mt-metadata 0.3.3__py2.py3-none-any.whl → 0.3.5__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 +12 -10
- mt_metadata/base/metadata.py +24 -13
- mt_metadata/data/transfer_functions/tf_zmm.zmm +1 -1
- mt_metadata/timeseries/channel.py +8 -3
- mt_metadata/timeseries/filters/__init__.py +2 -2
- mt_metadata/timeseries/filters/{channel_response_filter.py → channel_response.py} +62 -29
- mt_metadata/timeseries/filters/coefficient_filter.py +1 -3
- mt_metadata/timeseries/filters/filter_base.py +70 -37
- mt_metadata/timeseries/filters/filtered.py +32 -22
- mt_metadata/timeseries/filters/fir_filter.py +10 -11
- mt_metadata/timeseries/filters/frequency_response_table_filter.py +9 -8
- mt_metadata/timeseries/filters/helper_functions.py +112 -3
- mt_metadata/timeseries/filters/pole_zero_filter.py +9 -8
- mt_metadata/timeseries/filters/standards/filter_base.json +2 -2
- mt_metadata/timeseries/filters/time_delay_filter.py +9 -8
- mt_metadata/timeseries/stationxml/fdsn_tools.py +8 -7
- mt_metadata/timeseries/stationxml/xml_channel_mt_channel.py +1 -1
- mt_metadata/timeseries/stationxml/xml_inventory_mt_experiment.py +4 -1
- mt_metadata/timeseries/tools/from_many_mt_files.py +15 -3
- mt_metadata/transfer_functions/__init__.py +1 -1
- mt_metadata/transfer_functions/core.py +89 -49
- mt_metadata/transfer_functions/io/edi/edi.py +9 -5
- mt_metadata/transfer_functions/io/edi/metadata/define_measurement.py +7 -3
- mt_metadata/transfer_functions/io/emtfxml/emtfxml.py +1 -4
- mt_metadata/transfer_functions/io/jfiles/jfile.py +2 -1
- mt_metadata/transfer_functions/io/zfiles/zmm.py +108 -62
- mt_metadata/transfer_functions/io/zonge/zonge.py +2 -2
- mt_metadata/transfer_functions/processing/aurora/band.py +16 -0
- mt_metadata/transfer_functions/processing/aurora/channel_nomenclature.py +34 -31
- mt_metadata/transfer_functions/processing/aurora/processing.py +12 -5
- mt_metadata/transfer_functions/processing/aurora/stations.py +11 -2
- mt_metadata/transfer_functions/processing/fourier_coefficients/decimation.py +1 -1
- mt_metadata/transfer_functions/processing/fourier_coefficients/standards/decimation.json +1 -1
- mt_metadata/transfer_functions/processing/fourier_coefficients/standards/fc_channel.json +23 -1
- mt_metadata/transfer_functions/tf/transfer_function.py +93 -1
- {mt_metadata-0.3.3.dist-info → mt_metadata-0.3.5.dist-info}/METADATA +379 -379
- {mt_metadata-0.3.3.dist-info → mt_metadata-0.3.5.dist-info}/RECORD +41 -41
- {mt_metadata-0.3.3.dist-info → mt_metadata-0.3.5.dist-info}/WHEEL +1 -1
- {mt_metadata-0.3.3.dist-info → mt_metadata-0.3.5.dist-info}/AUTHORS.rst +0 -0
- {mt_metadata-0.3.3.dist-info → mt_metadata-0.3.5.dist-info}/LICENSE +0 -0
- {mt_metadata-0.3.3.dist-info → mt_metadata-0.3.5.dist-info}/top_level.txt +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""
|
|
3
3
|
Created on Wed Dec 23 21:30:36 2020
|
|
4
4
|
|
|
5
|
-
:copyright:
|
|
5
|
+
:copyright:
|
|
6
6
|
Jared Peacock (jpeacock@usgs.gov)
|
|
7
7
|
|
|
8
8
|
:license: MIT
|
|
@@ -62,13 +62,10 @@ class Filtered(Base):
|
|
|
62
62
|
|
|
63
63
|
check = self._check_consistency()
|
|
64
64
|
if not check:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
self._name, self._applied
|
|
70
|
-
)
|
|
71
|
-
)
|
|
65
|
+
msg = (f"Filter names and applied lists are not the same size. "
|
|
66
|
+
f"Be sure to check the inputs. "
|
|
67
|
+
f"names = {self._name}, applied = {self._applied}")
|
|
68
|
+
self.logger.warning(msg)
|
|
72
69
|
|
|
73
70
|
@property
|
|
74
71
|
def applied(self):
|
|
@@ -77,17 +74,21 @@ class Filtered(Base):
|
|
|
77
74
|
@applied.setter
|
|
78
75
|
def applied(self, applied):
|
|
79
76
|
if not hasattr(applied, "__iter__"):
|
|
80
|
-
if applied in [None, "none", "None", "NONE", "null"
|
|
77
|
+
if applied in [None, "none", "None", "NONE", "null"]:
|
|
78
|
+
self._applied = [True]
|
|
79
|
+
return
|
|
80
|
+
elif applied in [0, "0"]:
|
|
81
81
|
self._applied = [False]
|
|
82
82
|
return
|
|
83
|
+
|
|
84
|
+
#sets an empty list to one default value
|
|
83
85
|
if isinstance(applied, list) and len(applied) == 0:
|
|
84
|
-
self.applied = [
|
|
86
|
+
self.applied = [True]
|
|
85
87
|
return
|
|
86
88
|
|
|
87
89
|
if isinstance(applied, str):
|
|
88
90
|
if applied.find("[") >= 0:
|
|
89
91
|
applied = applied.replace("[", "").replace("]", "")
|
|
90
|
-
|
|
91
92
|
if applied.count(",") > 0:
|
|
92
93
|
applied_list = [
|
|
93
94
|
ss.strip().lower() for ss in applied.split(",")
|
|
@@ -96,13 +97,21 @@ class Filtered(Base):
|
|
|
96
97
|
applied_list = [ss.lower() for ss in applied.split()]
|
|
97
98
|
elif isinstance(applied, list):
|
|
98
99
|
applied_list = applied
|
|
100
|
+
# set integer strings to integers ["0","1"]--> [0, 1]
|
|
101
|
+
for i, elt in enumerate(applied_list):
|
|
102
|
+
if elt in ["0", "1",]:
|
|
103
|
+
applied_list[i] = int(applied_list[i])
|
|
104
|
+
# set integers to bools [0,1]--> [False, True]
|
|
105
|
+
for i, elt in enumerate(applied_list):
|
|
106
|
+
if elt in [0, 1,]:
|
|
107
|
+
applied_list[i] = bool(applied_list[i])
|
|
99
108
|
elif isinstance(applied, bool):
|
|
100
109
|
applied_list = [applied]
|
|
101
110
|
# the returned type from a hdf5 dataset is a numpy array.
|
|
102
111
|
elif isinstance(applied, np.ndarray):
|
|
103
112
|
applied_list = list(applied)
|
|
104
113
|
if applied_list == []:
|
|
105
|
-
applied_list = [
|
|
114
|
+
applied_list = [True]
|
|
106
115
|
else:
|
|
107
116
|
msg = "applied must be a string or list of strings not {0}"
|
|
108
117
|
self.logger.error(msg.format(applied))
|
|
@@ -111,8 +120,8 @@ class Filtered(Base):
|
|
|
111
120
|
bool_list = []
|
|
112
121
|
for app_bool in applied_list:
|
|
113
122
|
if app_bool is None:
|
|
114
|
-
bool_list.append(
|
|
115
|
-
|
|
123
|
+
bool_list.append(True)
|
|
124
|
+
elif isinstance(app_bool, str):
|
|
116
125
|
if app_bool.lower() in ["false", "0"]:
|
|
117
126
|
bool_list.append(False)
|
|
118
127
|
elif app_bool.lower() in ["true", "1"]:
|
|
@@ -131,13 +140,11 @@ class Filtered(Base):
|
|
|
131
140
|
# check for consistency
|
|
132
141
|
check = self._check_consistency()
|
|
133
142
|
if not check:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
)
|
|
140
|
-
)
|
|
143
|
+
msg = (f"Filter names and applied lists are not the same size. "
|
|
144
|
+
f"Be sure to check the inputs. "
|
|
145
|
+
f"names = {self._name}, applied = {self._applied}")
|
|
146
|
+
self.logger.warning(msg)
|
|
147
|
+
|
|
141
148
|
|
|
142
149
|
def _check_consistency(self):
|
|
143
150
|
# check for consistency
|
|
@@ -165,7 +172,10 @@ class Filtered(Base):
|
|
|
165
172
|
)
|
|
166
173
|
)
|
|
167
174
|
return False
|
|
168
|
-
|
|
175
|
+
else:
|
|
176
|
+
return True
|
|
177
|
+
elif self._name == [] and len(self._applied) > 0:
|
|
178
|
+
self.logger.debug("Name probably not yet initialized -- skipping consitency check")
|
|
169
179
|
return True
|
|
170
180
|
else:
|
|
171
181
|
return False
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import copy
|
|
2
1
|
import matplotlib.pyplot as plt
|
|
3
2
|
import numpy as np
|
|
4
3
|
from obspy.core.inventory.response import FIRResponseStage
|
|
@@ -6,7 +5,7 @@ import scipy.signal as signal
|
|
|
6
5
|
|
|
7
6
|
from mt_metadata.base import get_schema
|
|
8
7
|
from mt_metadata.timeseries.filters.filter_base import FilterBase
|
|
9
|
-
from mt_metadata.timeseries.filters.filter_base import
|
|
8
|
+
from mt_metadata.timeseries.filters.filter_base import get_base_obspy_mapping
|
|
10
9
|
from mt_metadata.timeseries.filters.standards import SCHEMA_FN_PATHS
|
|
11
10
|
|
|
12
11
|
# =============================================================================
|
|
@@ -15,14 +14,6 @@ attr_dict.add_dict(get_schema("fir_filter", SCHEMA_FN_PATHS))
|
|
|
15
14
|
# =============================================================================
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
obspy_mapping = copy.deepcopy(OBSPY_MAPPING)
|
|
19
|
-
# obspy_mapping["_zeros"] = "_zeros"
|
|
20
|
-
obspy_mapping["_symmetry"] = "symmetry"
|
|
21
|
-
obspy_mapping["_coefficients"] = "coefficients"
|
|
22
|
-
obspy_mapping["decimation_factor"] = "decimation_factor"
|
|
23
|
-
obspy_mapping["decimation_input_sample_rate"] = "decimation_input_sample_rate"
|
|
24
|
-
obspy_mapping["stage_gain_frequency"] = "gain_frequency"
|
|
25
|
-
|
|
26
17
|
|
|
27
18
|
class FIRFilter(FilterBase):
|
|
28
19
|
"""
|
|
@@ -39,7 +30,15 @@ class FIRFilter(FilterBase):
|
|
|
39
30
|
if not self.decimation_factor:
|
|
40
31
|
self.decimation_factor = 1.0
|
|
41
32
|
|
|
42
|
-
|
|
33
|
+
|
|
34
|
+
def make_obspy_mapping(self):
|
|
35
|
+
mapping = get_base_obspy_mapping()
|
|
36
|
+
mapping["_symmetry"] = "symmetry"
|
|
37
|
+
mapping["_coefficients"] = "coefficients"
|
|
38
|
+
mapping["decimation_factor"] = "decimation_factor"
|
|
39
|
+
mapping["decimation_input_sample_rate"] = "decimation_input_sample_rate"
|
|
40
|
+
mapping["stage_gain_frequency"] = "gain_frequency"
|
|
41
|
+
return mapping
|
|
43
42
|
|
|
44
43
|
@property
|
|
45
44
|
def output_sampling_rate(self):
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""
|
|
3
3
|
.. py:module:: frequency_response_table_filter
|
|
4
|
-
:synopsis: Deal with frequency look-up tables
|
|
4
|
+
:synopsis: Deal with frequency look-up tables
|
|
5
5
|
|
|
6
6
|
.. codeauthor:: Jared Peacock <jpeacock@usgs.gov>
|
|
7
7
|
.. codeauthor:: Karl Kappler
|
|
8
8
|
|
|
9
9
|
"""
|
|
10
|
-
import copy
|
|
11
10
|
import numpy as np
|
|
12
11
|
from scipy.interpolate import interp1d
|
|
13
12
|
|
|
@@ -18,7 +17,7 @@ from obspy.core.inventory.response import (
|
|
|
18
17
|
|
|
19
18
|
from mt_metadata.base import get_schema
|
|
20
19
|
from mt_metadata.timeseries.filters.filter_base import FilterBase
|
|
21
|
-
from mt_metadata.timeseries.filters.filter_base import
|
|
20
|
+
from mt_metadata.timeseries.filters.filter_base import get_base_obspy_mapping
|
|
22
21
|
from mt_metadata.timeseries.filters.standards import SCHEMA_FN_PATHS
|
|
23
22
|
|
|
24
23
|
|
|
@@ -30,10 +29,6 @@ attr_dict.add_dict(
|
|
|
30
29
|
|
|
31
30
|
# =============================================================================
|
|
32
31
|
|
|
33
|
-
obspy_mapping = copy.deepcopy(OBSPY_MAPPING)
|
|
34
|
-
obspy_mapping["amplitudes"] = "_empirical_amplitudes"
|
|
35
|
-
obspy_mapping["frequencies"] = "_empirical_frequencies"
|
|
36
|
-
obspy_mapping["phases"] = "_empirical_phases"
|
|
37
32
|
|
|
38
33
|
|
|
39
34
|
class FrequencyResponseTableFilter(FilterBase):
|
|
@@ -47,7 +42,13 @@ class FrequencyResponseTableFilter(FilterBase):
|
|
|
47
42
|
|
|
48
43
|
super(FilterBase, self).__init__(attr_dict=attr_dict, **kwargs)
|
|
49
44
|
self.type = "frequency response table"
|
|
50
|
-
|
|
45
|
+
|
|
46
|
+
def make_obspy_mapping(self):
|
|
47
|
+
mapping = get_base_obspy_mapping()
|
|
48
|
+
mapping["amplitudes"] = "_empirical_amplitudes"
|
|
49
|
+
mapping["frequencies"] = "_empirical_frequencies"
|
|
50
|
+
mapping["phases"] = "_empirical_phases"
|
|
51
|
+
return mapping
|
|
51
52
|
|
|
52
53
|
@property
|
|
53
54
|
def frequencies(self):
|
|
@@ -1,5 +1,110 @@
|
|
|
1
1
|
import obspy
|
|
2
2
|
|
|
3
|
+
from loguru import logger
|
|
4
|
+
from mt_metadata.timeseries.filters.coefficient_filter import CoefficientFilter
|
|
5
|
+
from mt_metadata.timeseries.filters.frequency_response_table_filter import (
|
|
6
|
+
FrequencyResponseTableFilter,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
def make_coefficient_filter(gain=1.0, name="generic coefficient filter", **kwargs):
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
gain: float
|
|
15
|
+
name: string
|
|
16
|
+
units_in : string
|
|
17
|
+
A supported unit or "unknown"
|
|
18
|
+
one of "digital counts", "millivolts", etc.
|
|
19
|
+
A complete list of units can be found in mt_metadata/mt_metadata/util/units.py
|
|
20
|
+
and is accessible as a table via:
|
|
21
|
+
from mt_metadata.utils.units import UNITS_DF
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
# in general, you need to add all required fields from the standards.json
|
|
28
|
+
default_units_in = "unknown"
|
|
29
|
+
default_units_out = "unknown"
|
|
30
|
+
|
|
31
|
+
cf = CoefficientFilter()
|
|
32
|
+
cf.gain = gain
|
|
33
|
+
cf.name = name
|
|
34
|
+
|
|
35
|
+
cf.units_in = kwargs.get("units_in", default_units_in)
|
|
36
|
+
cf.units_out = kwargs.get("units_out", default_units_out)
|
|
37
|
+
|
|
38
|
+
return cf
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def make_frequency_response_table_filter(file_path, case="bf4"):
|
|
42
|
+
"""
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
filepath: pathlib.Path or string
|
|
46
|
+
case : string, placeholder for handling different fap table formats.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
fap_filter: FrequencyResponseTableFilter
|
|
51
|
+
"""
|
|
52
|
+
fap_filter = FrequencyResponseTableFilter()
|
|
53
|
+
|
|
54
|
+
if case == "bf4":
|
|
55
|
+
import numpy as np
|
|
56
|
+
import pandas as pd
|
|
57
|
+
|
|
58
|
+
df = pd.read_csv(file_path) # , skiprows=1)
|
|
59
|
+
# Hz, V/nT, degrees
|
|
60
|
+
fap_filter.frequencies = df["Frequency [Hz]"].values
|
|
61
|
+
fap_filter.amplitudes = df["Amplitude [V/nT]"].values
|
|
62
|
+
fap_filter.phases = np.deg2rad(df["Phase [degrees]"].values)
|
|
63
|
+
fap_filter.units_in = "volts"
|
|
64
|
+
fap_filter.units_out = "nanotesla"
|
|
65
|
+
fap_filter.gain = 1.0
|
|
66
|
+
fap_filter.name = "bf4"
|
|
67
|
+
return fap_filter
|
|
68
|
+
else:
|
|
69
|
+
msg = f"Case {case} not supported for FAP Table"
|
|
70
|
+
logger.error(msg)
|
|
71
|
+
raise NotImplementedError(msg)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def make_volt_per_meter_to_millivolt_per_km_converter():
|
|
75
|
+
"""
|
|
76
|
+
This represents a filter that converts from mV/km to V/m.
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
|
|
81
|
+
"""
|
|
82
|
+
coeff_filter = make_coefficient_filter(
|
|
83
|
+
gain=1e-6,
|
|
84
|
+
units_in="millivolts per kilometer",
|
|
85
|
+
units_out="volts per meter",
|
|
86
|
+
name="MT to SI electric field conversion",
|
|
87
|
+
)
|
|
88
|
+
return coeff_filter
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def make_tesla_to_nanotesla_converter():
|
|
92
|
+
"""
|
|
93
|
+
This represents a filter that converts from nt to T.
|
|
94
|
+
|
|
95
|
+
Returns
|
|
96
|
+
-------
|
|
97
|
+
|
|
98
|
+
"""
|
|
99
|
+
coeff_filter = make_coefficient_filter(
|
|
100
|
+
gain=1e-9,
|
|
101
|
+
units_in="nanotesla",
|
|
102
|
+
units_out="tesla",
|
|
103
|
+
name="MT to SI magnetic field conversion",
|
|
104
|
+
)
|
|
105
|
+
return coeff_filter
|
|
106
|
+
|
|
107
|
+
|
|
3
108
|
|
|
4
109
|
def decimation_info_is_degenerate(obspy_stage):
|
|
5
110
|
"""
|
|
@@ -33,6 +138,10 @@ def decimation_info_is_pure_delay(stage):
|
|
|
33
138
|
return False
|
|
34
139
|
|
|
35
140
|
|
|
36
|
-
def stage_gain_is_degenerate():
|
|
37
|
-
|
|
38
|
-
|
|
141
|
+
# def stage_gain_is_degenerate():
|
|
142
|
+
# # if gain is 1.0 ignore it
|
|
143
|
+
# pass
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
MT2SI_ELECTRIC_FIELD_FILTER = make_volt_per_meter_to_millivolt_per_km_converter()
|
|
147
|
+
MT2SI_MAGNETIC_FIELD_FILTER = make_tesla_to_nanotesla_converter()
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""
|
|
3
3
|
.. py:module:: pole_zero_filter
|
|
4
|
-
:synopsis: Deal with Pole Zero Filters
|
|
4
|
+
:synopsis: Deal with Pole Zero Filters
|
|
5
5
|
|
|
6
6
|
.. codeauthor:: Jared Peacock <jpeacock@usgs.gov>
|
|
7
7
|
|
|
8
8
|
"""
|
|
9
|
-
import copy
|
|
10
9
|
import numpy as np
|
|
11
10
|
import obspy
|
|
12
11
|
import scipy.signal as signal
|
|
13
12
|
|
|
14
13
|
from mt_metadata.base import get_schema
|
|
15
14
|
from mt_metadata.timeseries.filters.filter_base import FilterBase
|
|
16
|
-
from mt_metadata.timeseries.filters.filter_base import
|
|
15
|
+
from mt_metadata.timeseries.filters.filter_base import get_base_obspy_mapping
|
|
17
16
|
from mt_metadata.timeseries.filters.standards import SCHEMA_FN_PATHS
|
|
18
17
|
|
|
19
18
|
# =============================================================================
|
|
@@ -21,10 +20,6 @@ attr_dict = get_schema("filter_base", SCHEMA_FN_PATHS)
|
|
|
21
20
|
attr_dict.add_dict(get_schema("pole_zero_filter", SCHEMA_FN_PATHS))
|
|
22
21
|
# =============================================================================
|
|
23
22
|
|
|
24
|
-
obspy_mapping = copy.deepcopy(OBSPY_MAPPING)
|
|
25
|
-
obspy_mapping["_zeros"] = "zeros"
|
|
26
|
-
obspy_mapping["_poles"] = "poles"
|
|
27
|
-
obspy_mapping["normalization_factor"] = "normalization_factor"
|
|
28
23
|
|
|
29
24
|
|
|
30
25
|
class PoleZeroFilter(FilterBase):
|
|
@@ -35,7 +30,13 @@ class PoleZeroFilter(FilterBase):
|
|
|
35
30
|
super(FilterBase, self).__init__(attr_dict=attr_dict, **kwargs)
|
|
36
31
|
self.type = "zpk"
|
|
37
32
|
|
|
38
|
-
|
|
33
|
+
|
|
34
|
+
def make_obspy_mapping(self):
|
|
35
|
+
mapping = get_base_obspy_mapping()
|
|
36
|
+
mapping["_zeros"] = "zeros"
|
|
37
|
+
mapping["_poles"] = "poles"
|
|
38
|
+
mapping["normalization_factor"] = "normalization_factor"
|
|
39
|
+
return mapping
|
|
39
40
|
|
|
40
41
|
@property
|
|
41
42
|
def poles(self):
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"example": "ambient air temperature",
|
|
23
23
|
"default": null
|
|
24
24
|
},
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
"type": {
|
|
27
27
|
"type": "string",
|
|
28
28
|
"required": true,
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"alias": [],
|
|
77
77
|
"example": "2020-01-01",
|
|
78
78
|
"default": "1980-01-01"
|
|
79
|
-
},
|
|
79
|
+
},
|
|
80
80
|
|
|
81
81
|
"gain": {
|
|
82
82
|
"type": "float",
|
|
@@ -8,17 +8,14 @@
|
|
|
8
8
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
import copy
|
|
12
11
|
import numpy as np
|
|
13
12
|
from obspy.core import inventory
|
|
14
13
|
|
|
15
14
|
from mt_metadata.base import get_schema
|
|
16
15
|
from mt_metadata.timeseries.filters.filter_base import FilterBase
|
|
17
|
-
from mt_metadata.timeseries.filters.filter_base import
|
|
16
|
+
from mt_metadata.timeseries.filters.filter_base import get_base_obspy_mapping
|
|
18
17
|
from mt_metadata.timeseries.filters.standards import SCHEMA_FN_PATHS
|
|
19
18
|
|
|
20
|
-
obspy_mapping = copy.deepcopy(OBSPY_MAPPING)
|
|
21
|
-
obspy_mapping["decimation_delay"] = "delay"
|
|
22
19
|
# =============================================================================
|
|
23
20
|
attr_dict = get_schema("filter_base", SCHEMA_FN_PATHS)
|
|
24
21
|
attr_dict.add_dict(get_schema("time_delay_filter", SCHEMA_FN_PATHS))
|
|
@@ -32,12 +29,16 @@ class TimeDelayFilter(FilterBase):
|
|
|
32
29
|
super(FilterBase, self).__init__(attr_dict=attr_dict, **kwargs)
|
|
33
30
|
|
|
34
31
|
self.type = "time delay"
|
|
35
|
-
|
|
32
|
+
|
|
33
|
+
def make_obspy_mapping(self):
|
|
34
|
+
mapping = get_base_obspy_mapping()
|
|
35
|
+
mapping["decimation_delay"] = "delay"
|
|
36
|
+
return mapping
|
|
36
37
|
|
|
37
38
|
def to_obspy(self, stage_number=1, sample_rate=1, normalization_frequency=0):
|
|
38
39
|
"""
|
|
39
40
|
Convert to an obspy stage
|
|
40
|
-
|
|
41
|
+
|
|
41
42
|
:param stage_number: sequential stage number, defaults to 1
|
|
42
43
|
:type stage_number: integer, optional
|
|
43
44
|
:param normalization_frequency: Normalization frequency, defaults to 1
|
|
@@ -45,8 +46,8 @@ class TimeDelayFilter(FilterBase):
|
|
|
45
46
|
:param sample_rate: sample rate, defaults to 1
|
|
46
47
|
:type sample_rate: float, optional
|
|
47
48
|
:return: Obspy stage filter
|
|
48
|
-
:rtype: :class:`obspy.core.inventory.CoefficientsTypeResponseStage`
|
|
49
|
-
|
|
49
|
+
:rtype: :class:`obspy.core.inventory.CoefficientsTypeResponseStage`
|
|
50
|
+
|
|
50
51
|
"""
|
|
51
52
|
|
|
52
53
|
stage = inventory.CoefficientsTypeResponseStage(
|
|
@@ -319,6 +319,11 @@ def read_channel_code(channel_code):
|
|
|
319
319
|
|
|
320
320
|
def create_mt_component(channel_code):
|
|
321
321
|
"""
|
|
322
|
+
:param channel_code: Three character string {Period}{Component}{Orientation}
|
|
323
|
+
:type channel_code: string
|
|
324
|
+
:return: DESCRIPTION
|
|
325
|
+
:rtype: TYPE
|
|
326
|
+
|
|
322
327
|
Create a component for an MT channel given the measurement and orientation
|
|
323
328
|
|
|
324
329
|
>>> create_mt_component("LQN")
|
|
@@ -327,13 +332,9 @@ def create_mt_component(channel_code):
|
|
|
327
332
|
"""
|
|
328
333
|
code_dict = read_channel_code(channel_code)
|
|
329
334
|
if code_dict["measurement"] == "tide":
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
)
|
|
333
|
-
logger.warning("It is more likely that the channel code 'T' appeared")
|
|
334
|
-
logger.warning(
|
|
335
|
-
"Some historial MT data (PKD, SAO) used 'T' as the code for feedback coil magnetometers"
|
|
336
|
-
)
|
|
335
|
+
msg = ("Channel code indicates tidal data -- Some historial MT data (PKD, "
|
|
336
|
+
"SAO) used 'T' as the code for feedback coil magnetometers")
|
|
337
|
+
logger.warning(msg)
|
|
337
338
|
code_dict = read_channel_code(channel_code.replace("T", "F"))
|
|
338
339
|
|
|
339
340
|
mt_component = mt_components_dict[code_dict["measurement"]]
|
|
@@ -108,7 +108,7 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
108
108
|
|
|
109
109
|
# fill channel filters
|
|
110
110
|
mt_channel.filter.name = list(mt_filters.keys())
|
|
111
|
-
mt_channel.filter.applied = [
|
|
111
|
+
mt_channel.filter.applied = [True] * len(list(mt_filters.keys()))
|
|
112
112
|
|
|
113
113
|
return mt_channel, mt_filters
|
|
114
114
|
|
|
@@ -170,7 +170,10 @@ class XMLInventoryMTExperiment:
|
|
|
170
170
|
xml_network = self.network_translator.mt_to_xml(mt_survey)
|
|
171
171
|
for mt_station in mt_survey.stations:
|
|
172
172
|
xml_station = self.station_translator.mt_to_xml(mt_station)
|
|
173
|
-
|
|
173
|
+
if mt_survey.country is not None:
|
|
174
|
+
xml_station.site.country = ",".join(
|
|
175
|
+
[str(country) for country in mt_survey.country]
|
|
176
|
+
)
|
|
174
177
|
for mt_run in mt_station.runs:
|
|
175
178
|
xml_station = self.add_run(
|
|
176
179
|
xml_station, mt_run, mt_survey.filters
|
|
@@ -12,7 +12,14 @@ from pathlib import Path
|
|
|
12
12
|
import pandas as pd
|
|
13
13
|
from xml.etree import cElementTree as et
|
|
14
14
|
|
|
15
|
-
from mt_metadata.timeseries import
|
|
15
|
+
from mt_metadata.timeseries import (
|
|
16
|
+
Experiment,
|
|
17
|
+
Survey,
|
|
18
|
+
Station,
|
|
19
|
+
Run,
|
|
20
|
+
Electric,
|
|
21
|
+
Magnetic,
|
|
22
|
+
)
|
|
16
23
|
|
|
17
24
|
from mt_metadata.timeseries.filters import (
|
|
18
25
|
PoleZeroFilter,
|
|
@@ -22,6 +29,7 @@ from mt_metadata.timeseries.filters import (
|
|
|
22
29
|
)
|
|
23
30
|
from mt_metadata.timeseries.stationxml import XMLInventoryMTExperiment
|
|
24
31
|
|
|
32
|
+
|
|
25
33
|
# =============================================================================
|
|
26
34
|
# Useful Class
|
|
27
35
|
# =============================================================================
|
|
@@ -182,7 +190,7 @@ class MT2StationXML(XMLInventoryMTExperiment):
|
|
|
182
190
|
channels_list = []
|
|
183
191
|
for ch in order:
|
|
184
192
|
for fn in rdf:
|
|
185
|
-
if ch in fn.name.lower():
|
|
193
|
+
if ch in fn.name[len(station) :].lower():
|
|
186
194
|
channels_list.append(fn)
|
|
187
195
|
break
|
|
188
196
|
|
|
@@ -196,7 +204,11 @@ class MT2StationXML(XMLInventoryMTExperiment):
|
|
|
196
204
|
:rtype: TYPE
|
|
197
205
|
|
|
198
206
|
"""
|
|
199
|
-
fn_dict = {
|
|
207
|
+
fn_dict = {
|
|
208
|
+
"survey": self.survey,
|
|
209
|
+
"filters": self.filters,
|
|
210
|
+
"stations": [],
|
|
211
|
+
}
|
|
200
212
|
if stations in [None, []]:
|
|
201
213
|
station_iterator = self.stations
|
|
202
214
|
else:
|