/
blockette062.py
122 lines (115 loc) · 6.15 KB
/
blockette062.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# -*- coding: utf-8 -*-
from obspy.xseed.blockette import Blockette
from obspy.xseed.fields import FixedString, Float, Integer, Loop
from obspy.xseed.utils import Blockette34Lookup, formatRESP
import sys
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 xrange(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