Exemple #1
0
class Blockette050(Blockette):
    """
    Blockette 050: Station Identifier Blockette.

    Sample:
    0500097ANMO +34.946200-106.456700+1740.00006001Albuquerque, NewMexico, USA~
    0013210101989,241~~NIU
    """

    id = 50
    name = "Station Identifier"
    fields = [
        FixedString(3, "Station call letters", 5, 'UN'),
        Float(4, "Latitude", 10, mask='%+02.6f'),
        Float(5, "Longitude", 11, mask='%+03.6f'),
        Float(6, "Elevation", 7, mask='%+04.1f'),
        Integer(7, "Number of channels", 4),
        Integer(8, "Number of station comments", 3),
        VariableString(9, "Site name", 1, 60, 'UNLPS'),
        Integer(10, "Network identifier code", 3, xpath=33),
        Integer(11, "word order 32bit", 4),
        Integer(12, "word order 16bit", 2),
        VariableString(13, "Start effective date", 1, 22, 'T'),
        VariableString(14, "End effective date", 0, 22, 'T', optional=True,
                       xseed_version='1.0'),
        VariableString(14, "End effective date", 0, 22, 'T',
                       xseed_version='1.1'),
        FixedString(15, "Update flag", 1),
        FixedString(16, "Network Code", 2, 'ULN', version=2.3)
    ]
Exemple #2
0
class Blockette052(Blockette):
    """
    Blockette 052: Channel Identifier Blockette.

    Sample:
    0520119  BHE0000004~001002+34.946200-106.456700+1740.0100.0090.0+00.0000112
    2.000E+01 2.000E-030000CG~1991,042,20:48~~N
    """

    id = 52
    name = "Channel Identifier"
    fields = [
        FixedString(3, "Location identifier", 2, 'UN'),
        FixedString(4, "Channel identifier", 3, 'UN'),
        Integer(5, "Subchannel identifier", 4),
        Integer(6, "Instrument identifier", 3, xpath=33),
        VariableString(7, "Optional comment", 0, 30, 'UNLPS'),
        Integer(8, "Units of signal response", 3, xpath=34),
        Integer(9, "Units of calibration input", 3, xpath=34),
        Float(10, "Latitude", 10, mask='%+2.6f'),
        Float(11, "Longitude", 11, mask='%+3.6f'),
        Float(12, "Elevation", 7, mask='%+4.1f'),
        Float(13, "Local depth", 5, mask='%3.1f'),
        Float(14, "Azimuth", 5, mask='%3.1f'),
        Float(15, "Dip", 5, mask='%+2.1f'),
        Integer(16, "Data format identifier code", 4, xpath=30),
        # The typo is intentional for XSEED 1.0 compatibility.
        Integer(17,
                "Data record length",
                2,
                xseed_version='1.0',
                xml_tag="data_recored_length"),
        Integer(17, "Data record length", 2, xseed_version='1.1'),
        Float(18, "Sample rate", 10, mask='%1.4e'),
        Float(19, "Max clock drift", 10, mask='%1.4e'),
        Integer(20, "Number of comments", 4),
        VariableString(21, "Channel flags", 0, 26, 'U'),
        VariableString(22, "Start date", 1, 22, 'T'),
        VariableString(23,
                       "End date",
                       0,
                       22,
                       'T',
                       optional=True,
                       xseed_version='1.0'),
        VariableString(23, "End date", 0, 22, 'T', xseed_version='1.1'),
        FixedString(24, "Update flag", 1)
    ]
Exemple #3
0
class Blockette011(Blockette):
    """
    Blockette 011: Volume Station Header Index Blockette.

    This is the index to the Station Identifier Blockettes [50] that appear
    later in the volume. This blockette refers to each station described in
    the station header section.

    Sample:
    0110054004AAK  000003ANMO 000007ANTO 000010BJI  000012
    """

    id = 11
    name = "Volume Station Header Index"
    fields = [
        Integer(3, "Number of stations", 3),
        # REPEAT fields 4 — 5 for the Number of stations:
        Loop(
            "Station identifier",
            "Number of stations", [
                FixedString(4, "Station identifier code", 5),
                Integer(5, "Sequence number of station header", 6, ignore=True)
            ],
            repeat_title=True)
    ]
Exemple #4
0
class Blockette061(Blockette):
    """
    Blockette 061: FIR Response Blockette.

    The FIR blockette is used to specify FIR (Finite Impulse Response) digital
    filter coefficients. It is an alternative to blockette [54] when
    specifying FIR filters. The blockette recognizes the various forms of
    filter symmetry and can exploit them to reduce the number of factors
    specified to the blockette. In July 2007, the FDSN adopted a convention
    that requires the coefficients to be listed in forward time order.
    As a reference, minimum-phase filters (which are asymmetric) should be
    written with the largest values near the beginning of the coefficient list.
    """

    id = 61
    name = "FIR Response"
    fields = [
        Integer(3, "Stage sequence number", 2),
        VariableString(4, "Response Name", 1, 25, 'UN_'),
        FixedString(5, "Symmetry Code", 1, 'U'),
        Integer(6, "Signal In Units", 3, xpath=34),
        Integer(7, "Signal Out Units", 3, xpath=34),
        Integer(8, "Number of Coefficients", 4),
        #REPEAT field 9 for the Number of Coefficients
        Loop("FIR Coefficient",
             "Number of Coefficients",
             [Float(9, "FIR Coefficient", 14, mask='%+1.7e')],
             flat=True),
    ]

    def getRESP(self, station, channel, abbreviations):
        """
        Returns RESP string.
        """
        out = RESP % (station, channel, self.stage_sequence_number,
                      self.symmetry_code,
                      LookupCode(abbreviations, 34, 'unit_name',
                                 'unit_lookup_code', self.signal_in_units),
                      LookupCode(abbreviations, 34, 'unit_description',
                                 'unit_lookup_code', self.signal_in_units),
                      LookupCode(abbreviations, 34, 'unit_name',
                                 'unit_lookup_code', self.signal_out_units),
                      LookupCode(abbreviations, 34, 'unit_description',
                                 'unit_lookup_code', self.signal_out_units),
                      self.number_of_coefficients)
        if self.number_of_coefficients > 1:
            out += '#\t\tNumerator coefficients:\n'
            out += '#\t\t  i, coefficient\n'
            for _i in range(self.number_of_coefficients):
                out += 'B061F09    %4s %13s\n' % \
                    (_i, formatRESP(self.FIR_coefficient[_i], 6))
        elif self.number_of_coefficients == 1:
            out += '#\t\tNumerator coefficients:\n'
            out += '#\t\t  i, coefficient\n'
            out += 'B061F09    %4s %13s\n' % \
                (0, formatRESP(self.FIR_coefficient, 6))
        out += '#\t\t\n'
        return out.encode()
Exemple #5
0
class Blockette031(Blockette):
    """
    Blockette 031: Comment Description Blockette.

    Station operators, data collection centers, and data management centers
    can add descriptive comments to data to indicate problems encountered or
    special situations.

    Sample:
    03100720750Stime correction does not include leap second, (-1000ms).~000
    """
    id = 31
    name = "Comment Description"
    fields = [
        Integer(3, "Comment code key", 4),
        FixedString(4, "Comment class code", 1),
        VariableString(5, "Description of comment", 1, 70, 'UNLPS'),
        Integer(6, "Units of comment level", 3, ignore=True)
    ]
Exemple #6
0
class Blockette041(Blockette):
    """
    Blockette 041: FIR Dictionary Blockette.

    The FIR blockette is used to specify FIR (Finite Impulse Response)
    digital filter coefficients. It is an alternative to blockette [44] when
    specifying FIR filters. The blockette recognizes the various forms of
    filter symmetry and can exploit them to reduce the number of factors
    specified in the blockette. See Response (Coefficients) Blockette [54]
    for more information.
    """

    id = 41
    name = "FIR Dictionary"
    fields = [
        Integer(3, "Response Lookup Key", 4),
        VariableString(4, "Response Name", 1, 25, 'UN_'),
        FixedString(5, "Symmetry Code", 1, 'U'),
        Integer(6, "Signal In Units", 3, xpath=34),
        Integer(7, "Signal Out Units", 3, xpath=34),
        Integer(8, "Number of Factors", 4),
        #REPEAT field 9 for the Number of Factors
        Loop("FIR Coefficient",
             "Number of Factors",
             [Float(9, "FIR Coefficient", 14, mask='%+1.7e')],
             flat=True),
    ]

    def parseSEED(self, data, expected_length=0):
        """
        If number of FIR coefficients are larger than maximal blockette size of
        9999 chars a follow up blockette with the same blockette id and
        response lookup key is expected - this is checked here.
        """
        # convert to stream for test issues
        if isinstance(data, basestring):
            expected_length = len(data)
            data = StringIO(data)
        # get current lookup key
        pos = data.tell()
        data.read(7)
        global_lookup_key = int(data.read(4))
        data.seek(pos)
        # read first blockette
        temp = StringIO()
        temp.write(data.read(expected_length))
        # check next blockettes
        while True:
            # save position
            pos = data.tell()
            try:
                blockette_id = int(data.read(3))
            except ValueError:
                break
            if blockette_id != 41:
                # different blockette id -> break
                break
            blockette_length = int(data.read(4))
            lookup_key = int(data.read(4))
            if lookup_key != global_lookup_key:
                # different lookup key -> break
                break
            # ok follow up blockette found - skip some unneeded fields
            self.fields[1].read(data)
            self.fields[2].read(data)
            self.fields[3].read(data)
            self.fields[4].read(data)
            self.fields[5].read(data)
            # remaining length in current blockette
            length = pos - data.tell() + blockette_length
            # read follow up blockette and append it to temporary blockette
            temp.write(data.read(length))
        # reposition file pointer
        data.seek(pos)
        # parse new combined temporary blockette
        temp.seek(0)
        Blockette.parseSEED(self, temp, expected_length=temp.len)

    def parseXML(self, xml_doc, *args, **kwargs):
        if self.xseed_version == '1.0':
            xml_doc.find('fir_coefficient').tag = 'FIR_coefficient'
        Blockette.parseXML(self, xml_doc, *args, **kwargs)

    def getXML(self, *args, **kwargs):
        xml = Blockette.getXML(self, *args, **kwargs)
        if self.xseed_version == '1.0':
            xml.find('FIR_coefficient').tag = 'fir_coefficient'
        return xml

    def getRESP(self, station, channel, abbreviations):
        """
        Returns RESP string.
        """
        string = \
        '#\t\t+                     +--------------------------------+' + \
        '                      +\n' + \
        '#\t\t+                     |   FIR response,' + \
        '%6s ch %s   |                      +\n' % (station, channel) + \
        '#\t\t+                     +--------------------------------+' + \
        '                      +\n' + \
        '#\t\t\n' + \
        'B041F05     Symmetry type:                         %s\n' \
                % self.symmetry_code + \
        'B041F06     Response in units lookup:              %s - %s\n'\
            % (LookupCode(abbreviations, 34, 'unit_name', 'unit_lookup_code',
                         self.signal_in_units),
              LookupCode(abbreviations, 34, 'unit_description',
                    'unit_lookup_code', self.signal_in_units)) + \
        'B041F07     Response out units lookup:             %s - %s\n'\
            % (LookupCode(abbreviations, 34, 'unit_name', 'unit_lookup_code',
                         self.signal_out_units),
              LookupCode(abbreviations, 34, 'unit_description',
                    'unit_lookup_code', self.signal_out_units)) + \
        'B041F08     Number of numerators:                  %s\n' \
                % self.number_of_factors
        if self.number_of_factors > 1:
            string += '#\t\tNumerator coefficients:\n' + \
                       '#\t\t  i, coefficient\n'
            for _i in xrange(self.number_of_factors):
                string += 'B041F09    %4s %13s\n' \
                            % (_i, formatRESP(self.FIR_coefficient[_i], 6))
        elif self.number_of_factors == 1:
            string += '#\t\tNumerator coefficients:\n' + \
                       '#\t\t  i, coefficient\n'
            string += 'B041F09    %4s %13s\n' \
                            % (0, formatRESP(self.FIR_coefficient, 6))
        string += '#\t\t\n'
        return string
Exemple #7
0
class Blockette043(Blockette):
    """
    Blockette 043: Response (Poles & Zeros) Dictionary Blockette.

    See Response (Poles & Zeros) Blockette [53] for more information.
    """

    id = 43
    name = "Response Poles and Zeros Dictionary"
    fields = [
        Integer(3, "Response Lookup Key", 4),
        VariableString(4, "Response Name", 1, 25, 'UN_'),
        FixedString(5, "Response type", 1, 'U'),
        Integer(6, "Stage signal input units", 3, xpath=34),
        Integer(7, "Stage signal output units", 3, xpath=34),
        Float(8, "A0 normalization factor", 12, mask='%+1.5e'),
        Float(9, "Normalization frequency", 12, mask='%+1.5e'),
        Integer(10, "Number of complex zeros", 3),
        # REPEAT fields 11 — 14 for the Number of complex zeros:
        Loop('Complex zero', "Number of complex zeros", [
            Float(11, "Real zero", 12, mask='%+1.5e'),
            Float(12, "Imaginary zero", 12, mask='%+1.5e'),
            Float(13, "Real zero error", 12, mask='%+1.5e'),
            Float(14, "Imaginary zero error", 12, mask='%+1.5e')
        ]),
        Integer(15, "Number of complex poles", 3),
        # REPEAT fields 16 — 19 for the Number of complex poles:
        Loop('Complex pole', "Number of complex poles", [
            Float(16, "Real pole", 12, mask='%+1.5e'),
            Float(16, "Imaginary pole", 12, mask='%+1.5e'),
            Float(18, "Real pole error", 12, mask='%+1.5e'),
            Float(19, "Imaginary pole error", 12, mask='%+1.5e')
        ])
    ]

    # Changes the name of the blockette because of an error in XSEED 1.0
    def getXML(self, *args, **kwargs):
        xml = Blockette.getXML(self, *args, **kwargs)
        if self.xseed_version == '1.0':
            xml.tag = 'response_poles_and_zeros'
        return xml

    def getRESP(self, station, channel, abbreviations):
        """
        Returns RESP string.
        """
        # Field five needs some extra parsing.
        field_five_dict = {
            'A': 'A [Laplace Transform (Rad/sec)]',
            'B': 'B [Analog (Hz)]',
            'C': 'C [Composite]',
            'D': 'D [Digital (Z-transform)]'
        }
        string = \
            '#\t\t+               ' + \
            '+-----------------------------------------' + \
            '---+                +\n' + \
            '#\t\t+               |   Response (Poles & Zeros),' + \
            '%6s ch %s   |                +\n' % (station, channel) + \
            '#\t\t+               ' + \
            '+-----------------------------------------' + \
            '---+                +\n' + \
            '#\t\t\n' + \
            'B043F05     Response type:                         %s\n' \
            % field_five_dict[self.response_type] + \
            'B043F06     Response in units lookup:              %s\n' \
            % Blockette34Lookup(abbreviations,
                                self.stage_signal_input_units) + \
            'B043F07     Response out units lookup:             %s\n' \
            % Blockette34Lookup(abbreviations,
                                self.stage_signal_output_units) + \
            'B043F08     A0 normalization factor:               %G\n'\
            % self.A0_normalization_factor + \
            'B043F09     Normalization frequency:               %G\n'\
            % self.normalization_frequency + \
            'B043F10     Number of zeroes:                      %s\n'\
            % self.number_of_complex_zeros + \
            'B043F15     Number of poles:                       %s\n'\
            % self.number_of_complex_poles + \
            '#\t\tComplex zeroes:\n' + \
            '#\t\t  i  real          imag          real_error    imag_error\n'
        if self.number_of_complex_zeros > 0:
            if self.number_of_complex_zeros != 1:
                # Loop over all zeros.
                for _i in range(self.number_of_complex_zeros):
                    string += 'B043F11-14 %4s %13s %13s %13s %13s\n' % (
                        _i, formatRESP(self.real_zero[_i], 6),
                        formatRESP(self.imaginary_zero[_i],
                                   6), formatRESP(self.real_zero_error[_i], 6),
                        formatRESP(self.imaginary_zero_error[_i], 6))
            else:
                string += 'B043F11-14 %4s %13s %13s %13s %13s\n' % (
                    0, formatRESP(self.real_zero,
                                  6), formatRESP(self.imaginary_zero, 6),
                    formatRESP(self.real_zero_error,
                               6), formatRESP(self.imaginary_zero_error, 6))
        string += '#\t\tComplex poles:\n' + \
            '#\t\t  i  real          imag          real_error    imag_error\n'
        if self.number_of_complex_poles > 0:
            if self.number_of_complex_poles != 1:
                # Loop over all poles.
                for _i in range(self.number_of_complex_poles):
                    string += 'B043F16-19 %4s %13s %13s %13s %13s\n' % (
                        _i, formatRESP(self.real_pole[_i], 6),
                        formatRESP(self.imaginary_pole[_i],
                                   6), formatRESP(self.real_pole_error[_i], 6),
                        formatRESP(self.imaginary_pole_error[_i], 6))
            else:
                string += 'B043F16-19 %4s %13s %13s %13s %13s\n' % (
                    0, formatRESP(self.real_pole,
                                  6), formatRESP(self.imaginary_pole, 6),
                    formatRESP(self.real_pole_error,
                               6), formatRESP(self.imaginary_pole_error, 6))
        string += '#\t\t\n'
        return string
Exemple #8
0
class Blockette044(Blockette):
    """
    Blockette 044: Response (Coefficients) Dictionary Blockette.

    See Response (Coefficients) Dictionary Blockette [54] for more information.
    """

    id = 44
    name = "Response Coefficients Dictionary"
    fields = [
        Integer(3, "Response Lookup Key", 4),
        VariableString(4, "Response Name", 1, 25, 'UN_'),
        FixedString(5, "Response type", 1, 'U'),
        Integer(6, "Signal input units", 3, xpath=34),
        Integer(7, "Signal output units", 3, xpath=34),
        Integer(8, "Number of numerators", 4),
        # REPEAT fields 9 - 10 for the Number of numerators:
        Loop('Numerators',
             "Number of numerators", [
                 Float(9, "Numerator coefficient", 12, mask='%+1.5e'),
                 Float(10, "Numerator error", 12, mask='%+1.5e')
             ],
             flat=True),
        Integer(11, "Number of denominators", 4),
        # REPEAT fields 12 — 13 for the Number of denominators:
        Loop('Denominators',
             "Number of denominators", [
                 Float(12, "Denominator coefficient", 12, mask='%+1.5e'),
                 Float(13, "Denominator error", 12, mask='%+1.5e')
             ],
             flat=True)
    ]

    # Changes the name of the blockette because of an error in XSEED 1.0
    def getXML(self, *args, **kwargs):
        xml = Blockette.getXML(self, *args, **kwargs)
        if self.xseed_version == '1.0':
            xml.tag = 'response_coefficients'
        return xml

    def getRESP(self, station, channel, abbreviations):
        """
        Returns RESP string.
        """
        string = \
            '#\t\t+               +----------------------------------------' +\
            '---+                 +\n' + \
            '#\t\t+               |   Response (Coefficients),' + \
            '%6s ch %s   |                 +\n' % (station, channel) + \
            '#\t\t+               +----------------------------------------' +\
            '---+                 +\n' + \
            '#\t\t\n' + \
            'B044F05     Response type:                         %s\n' \
            % self.response_type + \
            'B044F06     Response in units lookup:              %s\n'\
            % Blockette34Lookup(abbreviations, self.signal_input_units) + \
            'B044F07     Response out units lookup:             %s\n'\
            % Blockette34Lookup(abbreviations, self.signal_output_units) + \
            'B044F08     Number of numerators:                  %s\n' \
            % self.number_of_numerators + \
            'B044F11     Number of denominators:                %s\n' \
            % self.number_of_denominators + \
            '#\t\tNumerator coefficients:\n' + \
            '#\t\t  i, coefficient,  error\n'
        if self.number_of_numerators:
            string += \
                '#\t\tNumerator coefficients:\n' + \
                '#\t\t  i, coefficient,  error\n'
            if self.number_of_numerators > 1:
                # Loop over all zeros.
                for _i in range(self.number_of_numerators):
                    string += 'B044F09-10  %3s %13s %13s\n' % (
                        _i, formatRESP(self.numerator_coefficient[_i], 6),
                        formatRESP(self.numerator_error[_i], 6))
            else:
                string += 'B044F09-10  %3s %13s %13s\n' % (
                    0, formatRESP(self.numerator_coefficient,
                                  6), formatRESP(self.numerator_error, 6))
        if self.number_of_denominators:
            string += \
                '#\t\tDenominator coefficients:\n' + \
                '#\t\t i, coefficient, error\n'
            if self.number_of_denominators > 1:
                # Loop over all zeros.
                for _i in range(self.number_of_numerators):
                    string += 'B044F12-13  %3s %13s %13s\n' % (
                        _i, formatRESP(self.denominator_coefficient[_i], 6),
                        formatRESP(self.denominator_error[_i], 6))
            else:
                string += 'B044F12-13  %3s %13s %13s\n' % (
                    0, formatRESP(self.denominator_coefficient,
                                  6), formatRESP(self.denominator_error, 6))
        string += '#\t\t\n'
        return string
Exemple #9
0
class Blockette054(Blockette):
    """
    Blockette 054: Response (Coefficients) Blockette.

    This blockette is usually used only for finite impulse response (FIR)
    filter stages. You can express Laplace transforms this way, but you should
    use the Response (Poles & Zeros) Blockettes [53] for this. You can express
    IIR filters this way, but you should use the Response (Poles & Zeros)
    Blockette [53] here, too, to avoid numerical stability problems. Usually,
    you will follow this blockette with a Decimation Blockette [57] and a
    Sensitivity/Gain Blockette [58] to complete the definition of the filter
    stage.

    This blockette is the only blockette that might overflow the maximum
    allowed value of 9,999 characters. If there are more coefficients than fit
    in one record, list as many as will fit in the first occurrence of this
    blockette (the counts of Number of numerators and Number of denominators
    would then be set to the number included, not the total number). In the
    next record, put the remaining number. Be sure to write and read these
    blockettes in sequence, and be sure that the first few fields of both
    records are identical. Reading (and writing) programs have to be able to
    work with both blockettes as one after reading (or before writing). In
    July 2007, the FDSN adopted a convention that requires the coefficients to
    be listed in forward time order. As a reference, minimum-phase filters
    (which are asymmetric) should be written with the largest values near the
    beginning of the coefficient list.
    """

    id = 54
    name = "Response Coefficients"
    fields = [
        FixedString(3, "Response type", 1, 'U'),
        Integer(4, "Stage sequence number", 2),
        Integer(5, "Signal input units", 3, xpath=34),
        Integer(6, "Signal output units", 3, xpath=34),
        Integer(7, "Number of numerators", 4),
        # REPEAT fields 8 — 9 for the Number of numerators:
        Loop('Numerators',
             "Number of numerators", [
                 Float(8, "Numerator coefficient", 12, mask='%+1.5e'),
                 Float(9, "Numerator error", 12, mask='%+1.5e')
             ],
             flat=True),
        Integer(10, "Number of denominators", 4),
        # REPEAT fields 11 — 12 for the Number of denominators:
        Loop('Denominators',
             "Number of denominators", [
                 Float(11, "Denominator coefficient", 12, mask='%+1.5e'),
                 Float(12, "Denominator error", 12, mask='%+1.5e')
             ],
             flat=True)
    ]

    def getRESP(self, station, channel, abbreviations):
        """
        Returns RESP string.
        """
        string = \
            '#\t\t+               +----------------------------------------' +\
            '---+                 +\n' + \
            '#\t\t+               |   Response (Coefficients),' + \
            '%6s ch %s   |                 +\n' % (station, channel) + \
            '#\t\t+               +----------------------------------------' +\
            '---+                 +\n' + \
            '#\t\t\n' + \
            'B054F03     Transfer function type:                %s\n' \
            % self.response_type + \
            'B054F04     Stage sequence number:                 %s\n' \
            % self.stage_sequence_number + \
            'B054F05     Response in units lookup:              %s\n'\
            % Blockette34Lookup(abbreviations, self.signal_input_units) +\
            'B054F06     Response out units lookup:             %s\n'\
            % Blockette34Lookup(abbreviations, self.signal_output_units) +\
            'B054F07     Number of numerators:                  %s\n' \
            % self.number_of_numerators + \
            'B054F10     Number of denominators:                %s\n' \
            % self.number_of_denominators
        if self.number_of_numerators:
            string += \
                '#\t\tNumerator coefficients:\n' + \
                '#\t\t  i, coefficient,  error\n'
            if self.number_of_numerators > 1:
                # Loop over all zeros.
                for _i in range(self.number_of_numerators):
                    string += 'B054F08-09  %3s %13s %13s\n' % (
                        _i, formatRESP(self.numerator_coefficient[_i], 6),
                        formatRESP(self.numerator_error[_i], 6))
            else:
                string += 'B054F08-09  %3s %13s %13s\n' % (
                    0, formatRESP(self.numerator_coefficient,
                                  6), formatRESP(self.numerator_error, 6))
        if self.number_of_denominators:
            string += \
                '#\t\tDenominator coefficients:\n' + \
                '#\t\t i, coefficient, error\n'
            if self.number_of_denominators > 1:
                # Loop over all zeros.
                for _i in range(self.number_of_numerators):
                    string += 'B054F11-12  %3s %13s %13s\n' % (
                        _i, formatRESP(self.denominator_coefficient[_i], 6),
                        formatRESP(self.denominator_error[_i], 6))
            else:
                string += 'B054F11-12  %3s %13s %13s\n' % (
                    0, formatRESP(self.denominator_coefficient,
                                  6), formatRESP(self.denominator_error, 6))
        string += '#\t\t\n'
        return string.encode()
Exemple #10
0
class Blockette062(Blockette):
    """
    Blockette 062: Response [Polynomial] Blockette.

    Use this blockette to characterize the response of a non-linear sensor.
    The polynomial response blockette describes the output of an Earth sensor
    in fundamentally a different manner than the other response blockettes.
    The functional describing the sensor for the polynomial response blockette
    will have Earth units while the independent variable of the function will
    be in volts. This is precisely opposite to the other response blockettes.
    While it is a simple matter to convert a linear response to either form,
    the non-linear response (which we can describe in the polynomial
    blockette) would require extensive curve fitting or polynomial inversion
    to convert from one function to the other. Most data users are interested
    in knowing the sensor output in Earth units, and the polynomial response
    blockette facilitates the access to Earth units for sensors with
    non-linear responses.
    """

    id = 62
    name = "Response Polynomial"
    fields = [
        FixedString(3, "Transfer Function Type", 1),
        Integer(4, "Stage Sequence Number", 2),
        Integer(5, "Stage Signal In Units", 3, xpath=34),
        Integer(6, "Stage Signal Out Units", 3, xpath=34),
        FixedString(7, "Polynomial Approximation Type", 1),
        FixedString(8, "Valid Frequency Units", 1),
        Float(9, "Lower Valid Frequency Bound", 12, mask='%+1.5e'),
        Float(10, "Upper Valid Frequency Bound", 12, mask='%+1.5e'),
        Float(11, "Lower Bound of Approximation", 12, mask='%+1.5e'),
        Float(12, "Upper Bound of Approximation", 12, mask='%+1.5e'),
        Float(13, "Maximum Absolute Error", 12, mask='%+1.5e'),
        Integer(14, "Number of Polynomial Coefficients", 3),
        # REPEAT fields 15 and 16 for each polynomial coefficient
        Loop("Polynomial Coefficients", "Number of Polynomial Coefficients", [
            Float(12, "Polynomial Coefficient", 12, mask='%+1.5e'),
            Float(12, "Polynomial Coefficient Error", 12, mask='%+1.5e'),
        ])
    ]

    # Changes the name of the blockette because of an error in XSEED 1.0
    def getXML(self, *args, **kwargs):
        xml = Blockette.getXML(self, *args, **kwargs)
        if self.xseed_version == '1.0':
            msg = 'The xsd-validation file for XML-SEED version 1.0 does ' + \
                'not support Blockette 62. It will be written but ' + \
                'please be aware that the file cannot be validated.\n' + \
                'If you want to validate your file please use XSEED ' + \
                'version 1.1.\n'
            sys.stdout.write(msg)
        return xml

    def getRESP(self, station, channel, abbreviations):
        """
        Returns RESP string.
        """
        # Field three needs some extra parsing.
        field_three_dict = {
            'A': 'A [Laplace Transform (Rad/sec)]',
            'B': 'B [Analog (Hz)]',
            'C': 'C [Composite]',
            'D': 'D [Digital (Z-transform)]',
            'P': 'P [Polynomial]'
        }
        # Frequency too!
        frequency_dict = {'A': 'A [rad/sec]', 'B': 'B [Hz]'}
        # Polynomial Approximation too.
        polynomial_dict = {'M': 'M [MacLaurin]'}
        string = \
            '#\t\t+              +-----------------------' + \
            '----------------+                      +\n' + \
            '#\t\t+              |   Polynomial response,' + \
            '%6s ch %s   |                      +\n' % (station, channel) + \
            '#\t\t+              +-----------------------' + \
            '----------------+                      +\n' + \
            '#\t\t\n' + \
            'B062F03     Transfer function type:                %s\n' \
            % field_three_dict[self.transfer_function_type] + \
            'B062F04     Stage sequence number:                 %s\n' \
            % self.stage_sequence_number + \
            'B062F05     Response in units lookup:              %s\n' \
            % Blockette34Lookup(abbreviations, self.stage_signal_in_units) + \
            'B062F06     Response out units lookup:             %s\n' \
            % Blockette34Lookup(abbreviations, self.stage_signal_out_units) + \
            'B062F07     Polynomial Approximation Type:         %s\n' \
            % polynomial_dict[self.polynomial_approximation_type] + \
            'B062F08     Valid Frequency Units:                 %s\n' \
            % frequency_dict[self.valid_frequency_units] + \
            'B062F09     Lower Valid Frequency Bound:           %G\n' \
            % self.lower_valid_frequency_bound + \
            'B062F10     Upper Valid Frequency Bound:           %G\n' \
            % self.upper_valid_frequency_bound + \
            'B062F11     Lower Bound of Approximation:          %G\n' \
            % self.lower_bound_of_approximation + \
            'B062F12     Upper Bound of Approximation:          %G\n' \
            % self.upper_bound_of_approximation + \
            'B062F13     Maximum Absolute Error:                %G\n' \
            % self.maximum_absolute_error + \
            'B062F14     Number of coefficients:                %d\n' \
            % self.number_of_polynomial_coefficients
        if self.number_of_polynomial_coefficients:
            string += '#\t\tPolynomial coefficients:\n' + \
                '#\t\t  i, coefficient,  error\n'
            if self.number_of_polynomial_coefficients > 1:
                for _i in range(self.number_of_polynomial_coefficients):
                    string += 'B062F15-16   %2s %13s %13s\n' \
                        % (_i, formatRESP(self.polynomial_coefficient[_i], 6),
                           formatRESP(self.polynomial_coefficient_error[_i],
                                      6))
            else:
                string += 'B062F15-16   %2s %13s %13s\n' \
                    % (0, formatRESP(self.polynomial_coefficient, 6),
                       formatRESP(self.polynomial_coefficient_error, 6))
        string += '#\t\t\n'
        return string
Exemple #11
0
class Blockette053(Blockette):
    """
    Blockette 053: Response (Poles & Zeros) Blockette.

    Sample::

        0530382B 1007008 7.87395E+00 5.00000E-02  3
         0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00
         0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00
        -1.27000E+01 0.00000E+00 0.00000E+00 0.00000E+00  4
        -1.96418E-03 1.96418E-03 0.00000E+00 0.00000E+00
        S-1.96418E-03-1.96418E-03 0.00000E+00 0.00000E+00
        53-6.23500E+00 7.81823E+00 0.00000E+00 0.00000E+00
        -6.23500E+00-7.81823E+00 0.00000E+00 0.00000E+00
    """

    id = 53
    name = "Response Poles and Zeros"
    fields = [
        FixedString(3, "Transfer function types", 1, 'U'),
        Integer(4, "Stage sequence number", 2),
        Integer(5, "Stage signal input units", 3, xpath=34),
        Integer(6, "Stage signal output units", 3, xpath=34),
        Float(7, "A0 normalization factor", 12, mask='%+1.5e'),
        Float(8, "Normalization frequency", 12, mask='%+1.5e'),
        Integer(9, "Number of complex zeros", 3),
        # REPEAT fields 10 — 13 for the Number of complex zeros:
        Loop('Complex zero', "Number of complex zeros", [
            Float(10, "Real zero", 12, mask='%+1.5e'),
            Float(11, "Imaginary zero", 12, mask='%+1.5e'),
            Float(12, "Real zero error", 12, mask='%+1.5e'),
            Float(13, "Imaginary zero error", 12, mask='%+1.5e')
        ]),
        Integer(14, "Number of complex poles", 3),
        # REPEAT fields 15 — 18 for the Number of complex poles:
        Loop('Complex pole', "Number of complex poles", [
            Float(15, "Real pole", 12, mask='%+1.5e'),
            Float(16, "Imaginary pole", 12, mask='%+1.5e'),
            Float(17, "Real pole error", 12, mask='%+1.5e'),
            Float(18, "Imaginary pole error", 12, mask='%+1.5e')
        ])
    ]

    def getRESP(self, station, channel, abbreviations):
        """
        Returns RESP string.
        """
        # Field three needs some extra parsing.
        field_three_dict = {
            'A': 'A [Laplace Transform (Rad/sec)]',
            'B': 'B [Analog (Hz)]',
            'C': 'C [Composite]',
            'D': 'D [Digital (Z-transform)]'
        }
        out = RESP % (
            station, channel, field_three_dict[self.transfer_function_types],
            self.stage_sequence_number,
            LookupCode(abbreviations, 34, 'unit_name', 'unit_lookup_code',
                       self.stage_signal_input_units),
            LookupCode(abbreviations, 34, 'unit_description',
                       'unit_lookup_code', self.stage_signal_input_units),
            LookupCode(abbreviations, 34, 'unit_name', 'unit_lookup_code',
                       self.stage_signal_output_units),
            LookupCode(abbreviations, 34, 'unit_description',
                       'unit_lookup_code', self.stage_signal_output_units),
            self.A0_normalization_factor, self.normalization_frequency,
            self.number_of_complex_zeros, self.number_of_complex_poles)
        if self.number_of_complex_zeros > 0:
            if self.number_of_complex_zeros != 1:
                # Loop over all zeros.
                for _i in range(self.number_of_complex_zeros):
                    out += 'B053F10-13 %4s %13s %13s %13s %13s\n' % (
                        _i, formatRESP(self.real_zero[_i], 6),
                        formatRESP(self.imaginary_zero[_i],
                                   6), formatRESP(self.real_zero_error[_i], 6),
                        formatRESP(self.imaginary_zero_error[_i], 6))
            else:
                out += 'B053F10-13 %4s %13s %13s %13s %13s\n' % (
                    0, formatRESP(self.real_zero,
                                  6), formatRESP(self.imaginary_zero, 6),
                    formatRESP(self.real_zero_error,
                               6), formatRESP(self.imaginary_zero_error, 6))
        out += '#\t\tComplex poles:\n'
        out += '#\t\t  i  real          imag          real_error    '
        out += 'imag_error\n'
        if self.number_of_complex_poles > 0:
            if self.number_of_complex_poles != 1:
                # Loop over all poles.
                for _i in range(self.number_of_complex_poles):
                    out += 'B053F15-18 %4s %13s %13s %13s %13s\n' % (
                        _i, formatRESP(self.real_pole[_i], 6),
                        formatRESP(self.imaginary_pole[_i],
                                   6), formatRESP(self.real_pole_error[_i], 6),
                        formatRESP(self.imaginary_pole_error[_i], 6))
            else:
                out += 'B053F15-18 %4s %13s %13s %13s %13s\n' % (
                    0, formatRESP(self.real_pole,
                                  6), formatRESP(self.imaginary_pole, 6),
                    formatRESP(self.real_pole_error,
                               6), formatRESP(self.imaginary_pole_error, 6))
        out += '#\t\t\n'
        return out.encode()