mt-metadata 0.3.8__py2.py3-none-any.whl → 0.4.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mt-metadata might be problematic. Click here for more details.
- mt_metadata/__init__.py +1 -1
- mt_metadata/base/helpers.py +84 -9
- mt_metadata/base/metadata.py +137 -65
- mt_metadata/data/transfer_functions/test.edi +28 -28
- mt_metadata/features/__init__.py +14 -0
- mt_metadata/features/coherence.py +303 -0
- mt_metadata/features/cross_powers.py +29 -0
- mt_metadata/features/fc_coherence.py +81 -0
- mt_metadata/features/feature.py +72 -0
- mt_metadata/features/feature_decimation_channel.py +26 -0
- mt_metadata/features/feature_fc.py +24 -0
- mt_metadata/{transfer_functions/processing/aurora/decimation.py → features/feature_fc_run.py} +9 -4
- mt_metadata/features/feature_ts.py +24 -0
- mt_metadata/{transfer_functions/processing/aurora/window.py → features/feature_ts_run.py} +11 -18
- mt_metadata/features/standards/__init__.py +6 -0
- mt_metadata/features/standards/base_feature.json +46 -0
- mt_metadata/features/standards/coherence.json +57 -0
- mt_metadata/features/standards/fc_coherence.json +57 -0
- mt_metadata/features/standards/feature_decimation_channel.json +68 -0
- mt_metadata/features/standards/feature_fc_run.json +35 -0
- mt_metadata/features/standards/feature_ts_run.json +35 -0
- mt_metadata/features/standards/feature_weighting_window.json +46 -0
- mt_metadata/features/standards/weight_kernel.json +46 -0
- mt_metadata/features/standards/weights.json +101 -0
- mt_metadata/features/test_helpers/channel_weight_specs_example.json +156 -0
- mt_metadata/features/weights/__init__.py +0 -0
- mt_metadata/features/weights/base.py +44 -0
- mt_metadata/features/weights/channel_weight_spec.py +209 -0
- mt_metadata/features/weights/feature_weight_spec.py +194 -0
- mt_metadata/features/weights/monotonic_weight_kernel.py +275 -0
- mt_metadata/features/weights/standards/__init__.py +6 -0
- mt_metadata/features/weights/standards/activation_monotonic_weight_kernel.json +38 -0
- mt_metadata/features/weights/standards/base.json +36 -0
- mt_metadata/features/weights/standards/channel_weight_spec.json +35 -0
- mt_metadata/features/weights/standards/composite.json +36 -0
- mt_metadata/features/weights/standards/feature_weight_spec.json +13 -0
- mt_metadata/features/weights/standards/monotonic_weight_kernel.json +49 -0
- mt_metadata/features/weights/standards/taper_monotonic_weight_kernel.json +16 -0
- mt_metadata/features/weights/taper_weight_kernel.py +60 -0
- mt_metadata/helper_functions.py +69 -0
- mt_metadata/timeseries/filters/channel_response.py +77 -37
- mt_metadata/timeseries/filters/coefficient_filter.py +6 -5
- mt_metadata/timeseries/filters/filter_base.py +11 -15
- mt_metadata/timeseries/filters/fir_filter.py +8 -1
- mt_metadata/timeseries/filters/frequency_response_table_filter.py +26 -11
- mt_metadata/timeseries/filters/helper_functions.py +0 -2
- mt_metadata/timeseries/filters/obspy_stages.py +4 -1
- mt_metadata/timeseries/filters/pole_zero_filter.py +9 -5
- mt_metadata/timeseries/filters/time_delay_filter.py +8 -1
- mt_metadata/timeseries/location.py +20 -5
- mt_metadata/timeseries/person.py +14 -7
- mt_metadata/timeseries/standards/person.json +1 -1
- mt_metadata/timeseries/standards/run.json +2 -2
- mt_metadata/timeseries/station.py +4 -2
- mt_metadata/timeseries/stationxml/__init__.py +5 -0
- mt_metadata/timeseries/stationxml/xml_channel_mt_channel.py +38 -27
- mt_metadata/timeseries/stationxml/xml_inventory_mt_experiment.py +16 -47
- mt_metadata/timeseries/stationxml/xml_station_mt_station.py +25 -24
- mt_metadata/transfer_functions/__init__.py +3 -0
- mt_metadata/transfer_functions/core.py +16 -11
- mt_metadata/transfer_functions/io/emtfxml/metadata/location.py +5 -0
- mt_metadata/transfer_functions/io/emtfxml/metadata/provenance.py +14 -3
- mt_metadata/transfer_functions/io/tools.py +2 -0
- mt_metadata/transfer_functions/io/zonge/metadata/header.py +1 -1
- mt_metadata/transfer_functions/io/zonge/metadata/standards/header.json +1 -1
- mt_metadata/transfer_functions/io/zonge/metadata/standards/job.json +2 -2
- mt_metadata/transfer_functions/io/zonge/zonge.py +19 -23
- mt_metadata/transfer_functions/processing/__init__.py +2 -1
- mt_metadata/transfer_functions/processing/aurora/__init__.py +2 -4
- mt_metadata/transfer_functions/processing/aurora/band.py +46 -125
- mt_metadata/transfer_functions/processing/aurora/channel_nomenclature.py +27 -20
- mt_metadata/transfer_functions/processing/aurora/decimation_level.py +324 -152
- mt_metadata/transfer_functions/processing/aurora/frequency_bands.py +230 -0
- mt_metadata/transfer_functions/processing/aurora/processing.py +3 -3
- mt_metadata/transfer_functions/processing/aurora/run.py +32 -7
- mt_metadata/transfer_functions/processing/aurora/standards/decimation_level.json +7 -73
- mt_metadata/transfer_functions/processing/aurora/stations.py +33 -4
- mt_metadata/transfer_functions/processing/fourier_coefficients/decimation.py +176 -177
- mt_metadata/transfer_functions/processing/fourier_coefficients/fc.py +11 -9
- mt_metadata/transfer_functions/processing/fourier_coefficients/standards/decimation.json +1 -111
- mt_metadata/transfer_functions/processing/short_time_fourier_transform.py +64 -0
- mt_metadata/transfer_functions/processing/standards/__init__.py +6 -0
- mt_metadata/transfer_functions/processing/standards/short_time_fourier_transform.json +94 -0
- mt_metadata/transfer_functions/processing/{aurora/standards/decimation.json → standards/time_series_decimation.json} +17 -6
- mt_metadata/transfer_functions/processing/{aurora/standards → standards}/window.json +13 -2
- mt_metadata/transfer_functions/processing/time_series_decimation.py +50 -0
- mt_metadata/transfer_functions/processing/window.py +118 -0
- mt_metadata/transfer_functions/tf/standards/transfer_function.json +1 -1
- mt_metadata/transfer_functions/tf/station.py +17 -1
- mt_metadata/utils/mttime.py +22 -3
- mt_metadata/utils/validators.py +4 -2
- {mt_metadata-0.3.8.dist-info → mt_metadata-0.4.0.dist-info}/METADATA +39 -15
- {mt_metadata-0.3.8.dist-info → mt_metadata-0.4.0.dist-info}/RECORD +97 -57
- {mt_metadata-0.3.8.dist-info → mt_metadata-0.4.0.dist-info}/WHEEL +1 -1
- {mt_metadata-0.3.8.dist-info → mt_metadata-0.4.0.dist-info}/AUTHORS.rst +0 -0
- {mt_metadata-0.3.8.dist-info → mt_metadata-0.4.0.dist-info}/LICENSE +0 -0
- {mt_metadata-0.3.8.dist-info → mt_metadata-0.4.0.dist-info}/top_level.txt +0 -0
|
@@ -156,9 +156,7 @@ class ZongeMTAvg:
|
|
|
156
156
|
entry = dict(
|
|
157
157
|
[
|
|
158
158
|
(key.lower(), value)
|
|
159
|
-
for key, value in zip(
|
|
160
|
-
["comp"] + self.info_keys, values
|
|
161
|
-
)
|
|
159
|
+
for key, value in zip(["comp"] + self.info_keys, values)
|
|
162
160
|
]
|
|
163
161
|
)
|
|
164
162
|
data_list.append(entry)
|
|
@@ -247,9 +245,7 @@ class ZongeMTAvg:
|
|
|
247
245
|
|
|
248
246
|
z[f_index, ii, jj] = z_real + 1j * z_imag
|
|
249
247
|
|
|
250
|
-
z_err[f_index, ii, jj] = np.sqrt(
|
|
251
|
-
z_real_error**2 + z_imag_error**2
|
|
252
|
-
)
|
|
248
|
+
z_err[f_index, ii, jj] = np.sqrt(z_real_error**2 + z_imag_error**2)
|
|
253
249
|
|
|
254
250
|
return z, z_err
|
|
255
251
|
|
|
@@ -304,13 +300,13 @@ class ZongeMTAvg:
|
|
|
304
300
|
if self.header.start_time is not None:
|
|
305
301
|
rm.time_period.start = self.header.start_time
|
|
306
302
|
|
|
307
|
-
if "zxy" in self.components:
|
|
303
|
+
if "zxy" in self.components or "zxxr" in self.components:
|
|
308
304
|
rm.add_channel(self.ex_metadata)
|
|
309
305
|
rm.add_channel(self.ey_metadata)
|
|
310
306
|
rm.add_channel(self.hx_metadata)
|
|
311
307
|
rm.add_channel(self.hy_metadata)
|
|
312
308
|
|
|
313
|
-
if "tzx" in self.components:
|
|
309
|
+
if "tzx" in self.components or "rxxr" in self.components:
|
|
314
310
|
rm.add_channel(self.hz_metadata)
|
|
315
311
|
|
|
316
312
|
return rm
|
|
@@ -323,9 +319,9 @@ class ZongeMTAvg:
|
|
|
323
319
|
ch.measurement_azimuth = self.header._comp_dict["zxy"][
|
|
324
320
|
"ch"
|
|
325
321
|
].azimuth[0]
|
|
326
|
-
ch.translated_azimuth = self.header._comp_dict["zxy"][
|
|
327
|
-
|
|
328
|
-
]
|
|
322
|
+
ch.translated_azimuth = self.header._comp_dict["zxy"]["ch"].azimuth[
|
|
323
|
+
0
|
|
324
|
+
]
|
|
329
325
|
ch.measurement_tilt = self.header._comp_dict["zxy"]["ch"].incl[0]
|
|
330
326
|
ch.translated_tilt = self.header._comp_dict["zxy"]["ch"].incl[0]
|
|
331
327
|
ch.channel_id = self.header._comp_dict["zxy"]["ch"].number[0]
|
|
@@ -347,9 +343,9 @@ class ZongeMTAvg:
|
|
|
347
343
|
ch.measurement_azimuth = self.header._comp_dict["zyx"][
|
|
348
344
|
"ch"
|
|
349
345
|
].azimuth[0]
|
|
350
|
-
ch.translated_azimuth = self.header._comp_dict["zyx"][
|
|
351
|
-
|
|
352
|
-
]
|
|
346
|
+
ch.translated_azimuth = self.header._comp_dict["zyx"]["ch"].azimuth[
|
|
347
|
+
0
|
|
348
|
+
]
|
|
353
349
|
ch.measurement_tilt = self.header._comp_dict["zyx"]["ch"].incl[0]
|
|
354
350
|
ch.translated_tilt = self.header._comp_dict["zyx"]["ch"].incl[0]
|
|
355
351
|
ch.channel_id = self.header._comp_dict["zyx"]["ch"].number[0]
|
|
@@ -370,9 +366,9 @@ class ZongeMTAvg:
|
|
|
370
366
|
ch.measurement_azimuth = self.header._comp_dict["zyx"][
|
|
371
367
|
"ch"
|
|
372
368
|
].azimuth[1]
|
|
373
|
-
ch.translated_azimuth = self.header._comp_dict["zyx"][
|
|
374
|
-
|
|
375
|
-
]
|
|
369
|
+
ch.translated_azimuth = self.header._comp_dict["zyx"]["ch"].azimuth[
|
|
370
|
+
1
|
|
371
|
+
]
|
|
376
372
|
ch.measurement_tilt = self.header._comp_dict["zyx"]["ch"].incl[1]
|
|
377
373
|
ch.translated_tilt = self.header._comp_dict["zyx"]["ch"].incl[1]
|
|
378
374
|
ch.sensor.id = self.header._comp_dict["zyx"]["ch"].number[1]
|
|
@@ -394,9 +390,9 @@ class ZongeMTAvg:
|
|
|
394
390
|
ch.measurement_azimuth = self.header._comp_dict["zxy"][
|
|
395
391
|
"ch"
|
|
396
392
|
].azimuth[1]
|
|
397
|
-
ch.translated_azimuth = self.header._comp_dict["zxy"][
|
|
398
|
-
|
|
399
|
-
]
|
|
393
|
+
ch.translated_azimuth = self.header._comp_dict["zxy"]["ch"].azimuth[
|
|
394
|
+
1
|
|
395
|
+
]
|
|
400
396
|
ch.measurement_tilt = self.header._comp_dict["zxy"]["ch"].incl[1]
|
|
401
397
|
ch.translated_tilt = self.header._comp_dict["zxy"]["ch"].incl[1]
|
|
402
398
|
ch.sensor.id = self.header._comp_dict["zxy"]["ch"].number[1]
|
|
@@ -418,9 +414,9 @@ class ZongeMTAvg:
|
|
|
418
414
|
ch.measurement_azimuth = self.header._comp_dict["tzx"][
|
|
419
415
|
"ch"
|
|
420
416
|
].azimuth[1]
|
|
421
|
-
ch.translated_azimuth = self.header._comp_dict["tzx"][
|
|
422
|
-
|
|
423
|
-
]
|
|
417
|
+
ch.translated_azimuth = self.header._comp_dict["tzx"]["ch"].azimuth[
|
|
418
|
+
1
|
|
419
|
+
]
|
|
424
420
|
ch.measurement_tilt = self.header._comp_dict["tzx"]["ch"].incl[1]
|
|
425
421
|
ch.translated_tilt = self.header._comp_dict["tzx"]["ch"].incl[1]
|
|
426
422
|
ch.sensor.id = self.header._comp_dict["tzx"]["ch"].number[1]
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
from .time_series_decimation import TimeSeriesDecimation
|
|
2
|
+
from .window import Window
|
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
from .band import Band
|
|
2
2
|
from .channel import Channel
|
|
3
3
|
from .channel_nomenclature import ChannelNomenclature
|
|
4
|
-
from .window import Window
|
|
5
|
-
from .decimation import Decimation
|
|
6
4
|
from .decimation_level import DecimationLevel
|
|
7
5
|
from .estimator import Estimator
|
|
6
|
+
from .frequency_bands import FrequencyBands
|
|
8
7
|
from .processing import Processing
|
|
9
8
|
from .regression import Regression
|
|
10
9
|
from .run import Run
|
|
11
10
|
from .station import Station
|
|
12
11
|
from .stations import Stations
|
|
13
12
|
|
|
14
|
-
|
|
15
13
|
__all__ = [
|
|
16
14
|
"Band",
|
|
17
15
|
"Channel",
|
|
18
16
|
"ChannelNomenclature",
|
|
19
|
-
"Window",
|
|
20
17
|
"Decimation",
|
|
21
18
|
"DecimationLevel",
|
|
22
19
|
"Estimator",
|
|
20
|
+
"FrequencyBands",
|
|
23
21
|
"Processing",
|
|
24
22
|
"Regression",
|
|
25
23
|
"Run",
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
Created on Fri Feb 25 15:20:59 2022
|
|
4
4
|
|
|
5
5
|
@author: jpeacock
|
|
6
|
+
|
|
7
|
+
Development Notes:
|
|
8
|
+
To add better overlap and intersection checking, consider using piso
|
|
9
|
+
https://piso.readthedocs.io/en/latest/getting_started/index.html
|
|
6
10
|
"""
|
|
7
11
|
# =============================================================================
|
|
8
12
|
# Imports
|
|
@@ -12,6 +16,7 @@ import pandas as pd
|
|
|
12
16
|
from mt_metadata.base.helpers import write_lines
|
|
13
17
|
from mt_metadata.base import get_schema, Base
|
|
14
18
|
from .standards import SCHEMA_FN_PATHS
|
|
19
|
+
from typing import Optional
|
|
15
20
|
|
|
16
21
|
# =============================================================================
|
|
17
22
|
attr_dict = get_schema("band", SCHEMA_FN_PATHS)
|
|
@@ -22,28 +27,38 @@ class Band(Base):
|
|
|
22
27
|
__doc__ = write_lines(attr_dict)
|
|
23
28
|
|
|
24
29
|
def __init__(self, **kwargs):
|
|
30
|
+
"""
|
|
31
|
+
Constructor.
|
|
32
|
+
|
|
33
|
+
:param kwargs: TODO description here
|
|
34
|
+
"""
|
|
25
35
|
|
|
26
36
|
super().__init__(attr_dict=attr_dict, **kwargs)
|
|
27
37
|
self._name = None
|
|
28
38
|
|
|
29
39
|
@property
|
|
30
|
-
def lower_bound(self):
|
|
40
|
+
def lower_bound(self) -> float:
|
|
31
41
|
return self.frequency_min
|
|
32
42
|
|
|
33
43
|
@property
|
|
34
|
-
def upper_bound(self):
|
|
44
|
+
def upper_bound(self) -> float:
|
|
35
45
|
return self.frequency_max
|
|
36
46
|
|
|
37
47
|
@property
|
|
38
|
-
def
|
|
48
|
+
def width(self) -> float:
|
|
49
|
+
""" returns the width of the band (the bandwidth)."""
|
|
50
|
+
return self.upper_bound - self.lower_bound
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def lower_closed(self) -> bool:
|
|
39
54
|
return self.to_interval().closed_left
|
|
40
55
|
|
|
41
56
|
@property
|
|
42
|
-
def upper_closed(self):
|
|
57
|
+
def upper_closed(self) -> bool:
|
|
43
58
|
return self.to_interval().closed_right
|
|
44
59
|
|
|
45
60
|
@property
|
|
46
|
-
def name(self):
|
|
61
|
+
def name(self) -> str:
|
|
47
62
|
"""
|
|
48
63
|
:return: The name of the frequency band (currently defaults to fstring with 6 decimal places.
|
|
49
64
|
:rtype: str
|
|
@@ -57,7 +72,7 @@ class Band(Base):
|
|
|
57
72
|
def name(self, value):
|
|
58
73
|
self._name = value
|
|
59
74
|
|
|
60
|
-
def _indices_from_frequencies(self, frequencies):
|
|
75
|
+
def _indices_from_frequencies(self, frequencies: np.ndarray) -> np.ndarray:
|
|
61
76
|
"""
|
|
62
77
|
|
|
63
78
|
Parameters
|
|
@@ -84,7 +99,7 @@ class Band(Base):
|
|
|
84
99
|
indices = np.where(cond1 & cond2)[0]
|
|
85
100
|
return indices
|
|
86
101
|
|
|
87
|
-
def set_indices_from_frequencies(self, frequencies):
|
|
102
|
+
def set_indices_from_frequencies(self, frequencies: np.ndarray) -> None:
|
|
88
103
|
"""assumes min/max freqs are defined"""
|
|
89
104
|
indices = self._indices_from_frequencies(frequencies)
|
|
90
105
|
self.index_min = indices[0]
|
|
@@ -98,7 +113,7 @@ class Band(Base):
|
|
|
98
113
|
@property
|
|
99
114
|
def harmonic_indices(self):
|
|
100
115
|
"""
|
|
101
|
-
Assumes all
|
|
116
|
+
Assumes all harmoincs between min and max are present in the band
|
|
102
117
|
|
|
103
118
|
Returns
|
|
104
119
|
-------
|
|
@@ -106,7 +121,7 @@ class Band(Base):
|
|
|
106
121
|
"""
|
|
107
122
|
return np.arange(self.index_min, self.index_max + 1)
|
|
108
123
|
|
|
109
|
-
def in_band_harmonics(self, frequencies):
|
|
124
|
+
def in_band_harmonics(self, frequencies: np.ndarray):
|
|
110
125
|
"""
|
|
111
126
|
Parameters
|
|
112
127
|
----------
|
|
@@ -122,7 +137,7 @@ class Band(Base):
|
|
|
122
137
|
return harmonics
|
|
123
138
|
|
|
124
139
|
@property
|
|
125
|
-
def center_frequency(self):
|
|
140
|
+
def center_frequency(self) -> float:
|
|
126
141
|
"""
|
|
127
142
|
Returns
|
|
128
143
|
-------
|
|
@@ -135,131 +150,37 @@ class Band(Base):
|
|
|
135
150
|
return (self.lower_bound + self.upper_bound) / 2
|
|
136
151
|
|
|
137
152
|
@property
|
|
138
|
-
def center_period(self):
|
|
153
|
+
def center_period(self) -> float:
|
|
154
|
+
""" Returns the inverse of center frequency."""
|
|
139
155
|
return 1.0 / self.center_frequency
|
|
140
156
|
|
|
157
|
+
def overlaps(self, other) -> bool:
|
|
158
|
+
""" Check if this band overlaps with another"""
|
|
159
|
+
ivl = self.to_interval()
|
|
160
|
+
other_ivl = other.to_interval()
|
|
161
|
+
return ivl.overlaps(other_ivl)
|
|
141
162
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
frequency band and two columns, one for the left-hand (lower bound) of the
|
|
149
|
-
frequency band and one for the right-hand (upper bound).
|
|
150
|
-
|
|
151
|
-
Note there are some "clever" ways to define the bands using a 1-D array but this
|
|
152
|
-
assumes the bands to be adjacent, and there is no good reason to bake this
|
|
153
|
-
constriant in -- band edges is thus 2-D.
|
|
154
|
-
"""
|
|
155
|
-
|
|
156
|
-
def __init__(self, **kwargs):
|
|
157
|
-
"""
|
|
158
|
-
|
|
159
|
-
Parameters
|
|
160
|
-
----------
|
|
161
|
-
kwargs
|
|
162
|
-
band_edges: 2d numpy array
|
|
163
|
-
"""
|
|
164
|
-
self.band_edges = kwargs.get("band_edges", None)
|
|
163
|
+
def contains(self, other) -> bool:
|
|
164
|
+
""" Check if this band contains nother """
|
|
165
|
+
ivl = self.to_interval()
|
|
166
|
+
cond1 = ivl.__contains__(other.lower_bound)
|
|
167
|
+
cond2 = ivl.__contains__(other.upper_bound)
|
|
168
|
+
return cond1 & cond2
|
|
165
169
|
|
|
166
170
|
@property
|
|
167
|
-
def
|
|
168
|
-
return self.band_edges.shape[0]
|
|
169
|
-
|
|
170
|
-
def validate(self):
|
|
171
|
+
def fractional_bandwidth(self):
|
|
171
172
|
"""
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
See
|
|
174
|
+
- https://en.wikipedia.org/wiki/Bandwidth_(signal_processing)#Fractional_bandwidth
|
|
175
|
+
- https://en.wikipedia.org/wiki/Q_factor
|
|
175
176
|
|
|
176
|
-
"""
|
|
177
|
-
band_centers = self.band_centers()
|
|
178
|
-
|
|
179
|
-
# check band centers are monotonically increasing
|
|
180
|
-
monotone_condition = np.all(band_centers[1:] > band_centers[:-1])
|
|
181
|
-
if monotone_condition:
|
|
182
|
-
pass
|
|
183
|
-
else:
|
|
184
|
-
print(
|
|
185
|
-
"WARNING Band Centers are Not Monotonic. This probably means that "
|
|
186
|
-
"the bands are being defined in an adhoc way"
|
|
187
|
-
)
|
|
188
|
-
print("This condition untested 20210720")
|
|
189
|
-
print("Attempting to reorganize bands")
|
|
190
|
-
# use np.argsort to rorganize the bands
|
|
191
|
-
self.band_edges = self.band_edges[np.argsort(band_centers), :]
|
|
192
|
-
|
|
193
|
-
return
|
|
194
|
-
|
|
195
|
-
def bands(self, direction="increasing_frequency"):
|
|
196
|
-
"""
|
|
197
|
-
make this a generator for iteration over bands
|
|
198
177
|
Returns
|
|
199
178
|
-------
|
|
200
179
|
|
|
201
180
|
"""
|
|
202
|
-
|
|
203
|
-
if direction == "increasing_period":
|
|
204
|
-
band_indices = np.flip(band_indices)
|
|
205
|
-
return (self.band(i_band) for i_band in band_indices)
|
|
181
|
+
return self.width / self.center_frequency
|
|
206
182
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
----------
|
|
211
|
-
i_band: integer (zero-indexed)
|
|
212
|
-
Specifies the band to return
|
|
213
|
-
|
|
214
|
-
Returns
|
|
215
|
-
-------
|
|
216
|
-
frequency_band: Band()
|
|
217
|
-
Class that represents a frequency band
|
|
218
|
-
"""
|
|
219
|
-
|
|
220
|
-
frequency_band = Band(
|
|
221
|
-
frequency_min=self.band_edges[i_band, 0],
|
|
222
|
-
frequency_max=self.band_edges[i_band, 1],
|
|
223
|
-
)
|
|
224
|
-
return frequency_band
|
|
225
|
-
|
|
226
|
-
def band_centers(self, frequency_or_period="frequency"):
|
|
227
|
-
"""
|
|
228
|
-
Parameters
|
|
229
|
-
----------
|
|
230
|
-
frequency_or_period : str
|
|
231
|
-
One of ["frequency" , "period"]. Determines if the vector of band
|
|
232
|
-
centers is returned in "Hz" or "s"
|
|
233
|
-
|
|
234
|
-
Returns
|
|
235
|
-
-------
|
|
236
|
-
band_centers : numpy array
|
|
237
|
-
center frequencies of the bands in Hz or in s
|
|
238
|
-
"""
|
|
239
|
-
band_centers = np.full(self.number_of_bands, np.nan)
|
|
240
|
-
for i_band in range(self.number_of_bands):
|
|
241
|
-
frequency_band = self.band(i_band)
|
|
242
|
-
band_centers[i_band] = frequency_band.center_frequency
|
|
243
|
-
if frequency_or_period == "period":
|
|
244
|
-
band_centers = 1.0 / band_centers
|
|
245
|
-
return band_centers
|
|
246
|
-
|
|
247
|
-
def from_decimation_object(self, decimation_object):
|
|
248
|
-
"""
|
|
249
|
-
Define band_edges array from config object,
|
|
183
|
+
@property
|
|
184
|
+
def Q(self):
|
|
185
|
+
return 1./self.fractional_bandwidth
|
|
250
186
|
|
|
251
|
-
Parameters
|
|
252
|
-
----------
|
|
253
|
-
decimation_object: mt_metadata.transfer_functions.processing.aurora.Decimation
|
|
254
|
-
"""
|
|
255
|
-
# replace below with decimation_object.delta_frequency ?
|
|
256
|
-
df = (
|
|
257
|
-
decimation_object.decimation.sample_rate
|
|
258
|
-
/ decimation_object.window.num_samples
|
|
259
|
-
)
|
|
260
|
-
half_df = df / 2.0
|
|
261
|
-
# half_df /=100
|
|
262
|
-
lower_edges = (decimation_object.lower_bounds * df) - half_df
|
|
263
|
-
upper_edges = (decimation_object.upper_bounds * df) + half_df
|
|
264
|
-
band_edges = np.vstack((lower_edges, upper_edges)).T
|
|
265
|
-
self.band_edges = band_edges
|
|
@@ -8,15 +8,27 @@
|
|
|
8
8
|
# =============================================================================
|
|
9
9
|
from mt_metadata.base.helpers import write_lines
|
|
10
10
|
from mt_metadata.base import get_schema, Base
|
|
11
|
-
from .standards import SCHEMA_FN_PATHS
|
|
12
|
-
|
|
13
11
|
from mt_metadata.transfer_functions import CHANNEL_MAPS
|
|
12
|
+
from .standards import SCHEMA_FN_PATHS
|
|
14
13
|
|
|
14
|
+
from typing import Dict, Literal
|
|
15
15
|
# =============================================================================
|
|
16
16
|
attr_dict = get_schema("channel_nomenclature", SCHEMA_FN_PATHS)
|
|
17
17
|
|
|
18
|
+
# ====================== Nomenclature definitions for typehints and docstrings ============= #
|
|
19
|
+
|
|
20
|
+
SupportedNomenclature = Literal[
|
|
21
|
+
"default",
|
|
22
|
+
"lemi12",
|
|
23
|
+
"lemi34",
|
|
24
|
+
"musgraves",
|
|
25
|
+
"nims",
|
|
26
|
+
"phoenix123",
|
|
27
|
+
]
|
|
28
|
+
|
|
18
29
|
|
|
19
30
|
# =============================================================================
|
|
31
|
+
|
|
20
32
|
class ChannelNomenclature(Base):
|
|
21
33
|
__doc__ = write_lines(attr_dict)
|
|
22
34
|
|
|
@@ -64,25 +76,20 @@ class ChannelNomenclature(Base):
|
|
|
64
76
|
self._keyword = keyword
|
|
65
77
|
self.update()
|
|
66
78
|
|
|
67
|
-
def get_channel_map(self):
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
channel_map = CHANNEL_MAPS["phoenix123"]
|
|
78
|
-
elif self.keyword.upper() == "MUSGRAVES":
|
|
79
|
-
channel_map = CHANNEL_MAPS["musgraves"]
|
|
80
|
-
else:
|
|
81
|
-
msg = f"channel mt_system {self.keyword} unknown"
|
|
79
|
+
def get_channel_map(self) -> Dict[str,str]:
|
|
80
|
+
"""
|
|
81
|
+
Based on self.keyword return the mapping between conventional channel names and
|
|
82
|
+
the custom channel names in the particular nomenclature.
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
try:
|
|
86
|
+
return CHANNEL_MAPS[self.keyword.lower()]
|
|
87
|
+
except KeyError:
|
|
88
|
+
msg = f"channel mt_system {self.keyword} unknown)"
|
|
82
89
|
raise NotImplementedError(msg)
|
|
83
|
-
return channel_map
|
|
84
90
|
|
|
85
|
-
|
|
91
|
+
|
|
92
|
+
def update(self) -> None:
|
|
86
93
|
"""
|
|
87
94
|
Assign values to standard channel names "ex", "ey" etc based on channel_map dict
|
|
88
95
|
"""
|
|
@@ -93,7 +100,7 @@ class ChannelNomenclature(Base):
|
|
|
93
100
|
self.hy = channel_map["hy"]
|
|
94
101
|
self.hz = channel_map["hz"]
|
|
95
102
|
|
|
96
|
-
def unpack(self):
|
|
103
|
+
def unpack(self) -> tuple:
|
|
97
104
|
return self.ex, self.ey, self.hx, self.hy, self.hz
|
|
98
105
|
|
|
99
106
|
@property
|