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
|
@@ -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
|
|
@@ -21,6 +21,7 @@ from . import (
|
|
|
21
21
|
Fdsn,
|
|
22
22
|
Orientation,
|
|
23
23
|
Person,
|
|
24
|
+
provenance,
|
|
24
25
|
Provenance,
|
|
25
26
|
Location,
|
|
26
27
|
TimePeriod,
|
|
@@ -46,8 +47,9 @@ attr_dict.add_dict(
|
|
|
46
47
|
keys=["name", "comments", "organization"],
|
|
47
48
|
)
|
|
48
49
|
attr_dict.add_dict(get_schema("orientation", SCHEMA_FN_PATHS), "orientation")
|
|
50
|
+
|
|
49
51
|
attr_dict.add_dict(
|
|
50
|
-
|
|
52
|
+
provenance.attr_dict,
|
|
51
53
|
"provenance",
|
|
52
54
|
)
|
|
53
55
|
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
Tools to translate StationXML to MT Metadata
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
try:
|
|
7
|
+
import obspy
|
|
8
|
+
except ImportError:
|
|
9
|
+
raise ImportError("StationXML requires obspy to be installed.")
|
|
10
|
+
|
|
6
11
|
from .xml_network_mt_survey import XMLNetworkMTSurvey
|
|
7
12
|
from .xml_equipment_mt_run import XMLEquipmentMTRun
|
|
8
13
|
from .xml_station_mt_station import XMLStationMTStation
|
|
@@ -42,7 +42,7 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
42
42
|
"induction coil",
|
|
43
43
|
"coil",
|
|
44
44
|
"dipole",
|
|
45
|
-
"electrode"
|
|
45
|
+
"electrode",
|
|
46
46
|
]
|
|
47
47
|
|
|
48
48
|
def __init__(self):
|
|
@@ -121,8 +121,10 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
121
121
|
# fill channel filters
|
|
122
122
|
mt_channel.filter.name = list(mt_filters.keys())
|
|
123
123
|
mt_channel.filter.applied = [True] * len(list(mt_filters.keys()))
|
|
124
|
-
if UTCDateTime(mt_channel.time_period.end) < UTCDateTime(
|
|
125
|
-
mt_channel.time_period.
|
|
124
|
+
if UTCDateTime(mt_channel.time_period.end) < UTCDateTime(
|
|
125
|
+
mt_channel.time_period.start
|
|
126
|
+
):
|
|
127
|
+
mt_channel.time_period.end = "2200-01-01T00:00:00+00:00"
|
|
126
128
|
return mt_channel, mt_filters
|
|
127
129
|
|
|
128
130
|
def mt_to_xml(self, mt_channel, filters_dict, hard_code=True):
|
|
@@ -190,12 +192,8 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
190
192
|
xml_channel.types = ["geophysical".upper()]
|
|
191
193
|
xml_channel.sensor = self._mt_to_sensor(mt_channel)
|
|
192
194
|
xml_channel.comments = self._make_xml_comments(mt_channel.comments)
|
|
193
|
-
xml_channel.restricted_status = release_dict[
|
|
194
|
-
|
|
195
|
-
]
|
|
196
|
-
xml_channel = self._mt_to_xml_response(
|
|
197
|
-
mt_channel, filters_dict, xml_channel
|
|
198
|
-
)
|
|
195
|
+
xml_channel.restricted_status = release_dict[xml_channel.restricted_status]
|
|
196
|
+
xml_channel = self._mt_to_xml_response(mt_channel, filters_dict, xml_channel)
|
|
199
197
|
|
|
200
198
|
for mt_key, xml_key in self.mt_translator.items():
|
|
201
199
|
if xml_key is None:
|
|
@@ -211,9 +209,7 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
211
209
|
xml_channel.dip = mt_channel.measurement_tilt % 360
|
|
212
210
|
|
|
213
211
|
else:
|
|
214
|
-
setattr(
|
|
215
|
-
xml_channel, xml_key, mt_channel.get_attr_from_name(mt_key)
|
|
216
|
-
)
|
|
212
|
+
setattr(xml_channel, xml_key, mt_channel.get_attr_from_name(mt_key))
|
|
217
213
|
|
|
218
214
|
return xml_channel
|
|
219
215
|
|
|
@@ -272,9 +268,7 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
272
268
|
mt_channel.negative.model = sensor.model
|
|
273
269
|
mt_channel.negative.type = "electrode"
|
|
274
270
|
|
|
275
|
-
mt_channel.dipole_length = self._parse_dipole_length(
|
|
276
|
-
sensor.description
|
|
277
|
-
)
|
|
271
|
+
mt_channel.dipole_length = self._parse_dipole_length(sensor.description)
|
|
278
272
|
|
|
279
273
|
return mt_channel
|
|
280
274
|
|
|
@@ -434,7 +428,10 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
434
428
|
:rtype: TYPE
|
|
435
429
|
|
|
436
430
|
"""
|
|
431
|
+
|
|
437
432
|
comments = []
|
|
433
|
+
if mt_comment is None:
|
|
434
|
+
return comments
|
|
438
435
|
clist = mt_comment.split("run_ids:")
|
|
439
436
|
for item in clist:
|
|
440
437
|
if ":" in item:
|
|
@@ -479,9 +476,7 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
479
476
|
def _get_mt_units(self, xml_channel, mt_channel):
|
|
480
477
|
""" """
|
|
481
478
|
name = xml_channel.response.response_stages[-1].output_units
|
|
482
|
-
description = xml_channel.response.response_stages[
|
|
483
|
-
-1
|
|
484
|
-
].output_units_description
|
|
479
|
+
description = xml_channel.response.response_stages[-1].output_units_description
|
|
485
480
|
if description and name:
|
|
486
481
|
if len(description) > len(name):
|
|
487
482
|
mt_channel.units = description
|
|
@@ -545,9 +540,9 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
545
540
|
return f_obj.name, False
|
|
546
541
|
|
|
547
542
|
try:
|
|
548
|
-
last = sorted(
|
|
549
|
-
|
|
550
|
-
|
|
543
|
+
last = sorted([k for k in existing_filters.keys() if mt_filter.type in k])[
|
|
544
|
+
-1
|
|
545
|
+
]
|
|
551
546
|
except IndexError:
|
|
552
547
|
return f"{mt_filter.type}_{0:02}", True
|
|
553
548
|
try:
|
|
@@ -582,7 +577,6 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
582
577
|
|
|
583
578
|
return xml_channel
|
|
584
579
|
|
|
585
|
-
|
|
586
580
|
def _deduce_sensor_type(self, sensor):
|
|
587
581
|
"""
|
|
588
582
|
|
|
@@ -592,6 +586,7 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
592
586
|
:return:
|
|
593
587
|
"""
|
|
594
588
|
original_sensor_type = sensor.type
|
|
589
|
+
original_sensor_description = sensor.description
|
|
595
590
|
# set sensor_type to be a string if it is None
|
|
596
591
|
if original_sensor_type is None:
|
|
597
592
|
sensor_type = "" # make a string
|
|
@@ -600,17 +595,33 @@ class XMLChannelMTChannel(BaseTranslator):
|
|
|
600
595
|
else:
|
|
601
596
|
sensor_type = copy.deepcopy(original_sensor_type)
|
|
602
597
|
|
|
598
|
+
if original_sensor_description is None:
|
|
599
|
+
sensor_description = "" # make a string
|
|
600
|
+
else:
|
|
601
|
+
sensor_description = copy.deepcopy(original_sensor_type)
|
|
602
|
+
|
|
603
603
|
if sensor_type.lower() in self.understood_sensor_types:
|
|
604
604
|
return sensor_type
|
|
605
605
|
else:
|
|
606
|
-
self.logger.warning(
|
|
606
|
+
self.logger.warning(
|
|
607
|
+
f" sensor {sensor} type {sensor.type} not in {self.understood_sensor_types}"
|
|
608
|
+
)
|
|
607
609
|
|
|
608
610
|
# Try handling Bartington FGM at Earthscope ... this is a place holder for handling non-standard cases
|
|
609
|
-
if
|
|
611
|
+
if sensor_type.lower() == "bartington":
|
|
610
612
|
sensor_type = "magnetometer"
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
613
|
+
if not sensor_type:
|
|
614
|
+
if sensor_description == "Bartington 3-Axis Fluxgate Sensor":
|
|
615
|
+
sensor_type = "magnetometer"
|
|
616
|
+
if sensor_description:
|
|
617
|
+
if ("bf-4" in sensor_description.lower()) & (
|
|
618
|
+
"schlumberger" in sensor_description.lower()
|
|
619
|
+
): # BSL-NCEDC
|
|
620
|
+
sensor_type = "magnetometer"
|
|
621
|
+
elif ("electric" in sensor_description.lower()) & (
|
|
622
|
+
"dipole" in sensor_description.lower()
|
|
623
|
+
): # BSL-NCEDC
|
|
624
|
+
sensor_type = "dipole"
|
|
614
625
|
|
|
615
626
|
# reset sensor_type to None it it was not handled
|
|
616
627
|
if not sensor_type:
|
|
@@ -85,9 +85,7 @@ class XMLInventoryMTExperiment:
|
|
|
85
85
|
run_channel = deepcopy(mt_channel)
|
|
86
86
|
mt_run = mt_station.get_run(run_id)
|
|
87
87
|
# need to set the start and end time to the run
|
|
88
|
-
run_channel.time_period.start =
|
|
89
|
-
mt_run.time_period.start
|
|
90
|
-
)
|
|
88
|
+
run_channel.time_period.start = mt_run.time_period.start
|
|
91
89
|
run_channel.time_period.end = mt_run.time_period.end
|
|
92
90
|
mt_run.add_channel(run_channel)
|
|
93
91
|
# if there are runs already try to match by start, end, sample_rate
|
|
@@ -105,16 +103,13 @@ class XMLInventoryMTExperiment:
|
|
|
105
103
|
mt_run.time_period.start
|
|
106
104
|
>= mt_channel.time_period.start
|
|
107
105
|
) and (
|
|
108
|
-
mt_run.time_period.end
|
|
109
|
-
<= mt_channel.time_period.end
|
|
106
|
+
mt_run.time_period.end <= mt_channel.time_period.end
|
|
110
107
|
):
|
|
111
108
|
mt_run.channels.append(mt_channel)
|
|
112
109
|
mt_run.sample_rate = mt_channel.sample_rate
|
|
113
110
|
# make a new run with generic information
|
|
114
111
|
else:
|
|
115
|
-
mt_run = metadata.Run(
|
|
116
|
-
id=f"{len(mt_station.runs)+1:03d}"
|
|
117
|
-
)
|
|
112
|
+
mt_run = metadata.Run(id=f"{len(mt_station.runs)+1:03d}")
|
|
118
113
|
mt_run.time_period.start = mt_channel.time_period.start
|
|
119
114
|
mt_run.time_period.end = mt_channel.time_period.end
|
|
120
115
|
mt_run.sample_rate = mt_channel.sample_rate
|
|
@@ -128,18 +123,14 @@ class XMLInventoryMTExperiment:
|
|
|
128
123
|
# need to check if the network/survey already exists, the files
|
|
129
124
|
# from make_mth5_from_iris have multiples of the same network
|
|
130
125
|
if mt_survey.id in mt_experiment.surveys.keys():
|
|
131
|
-
mt_experiment.surveys[mt_survey.id].stations.update(
|
|
132
|
-
mt_survey.stations
|
|
133
|
-
)
|
|
126
|
+
mt_experiment.surveys[mt_survey.id].stations.update(mt_survey.stations)
|
|
134
127
|
else:
|
|
135
128
|
mt_experiment.surveys.append(mt_survey)
|
|
136
129
|
if mt_fn:
|
|
137
130
|
mt_experiment.to_xml(fn=mt_fn)
|
|
138
131
|
return mt_experiment
|
|
139
132
|
|
|
140
|
-
def mt_to_xml(
|
|
141
|
-
self, mt_experiment, mt_fn=None, stationxml_fn=None, ns_dict=None
|
|
142
|
-
):
|
|
133
|
+
def mt_to_xml(self, mt_experiment, mt_fn=None, stationxml_fn=None, ns_dict=None):
|
|
143
134
|
"""
|
|
144
135
|
Convert from MT :class:`mt_metadata.timeseries.Experiment` to
|
|
145
136
|
:class:`obspy.core.inventory.Inventory`
|
|
@@ -176,9 +167,7 @@ class XMLInventoryMTExperiment:
|
|
|
176
167
|
)
|
|
177
168
|
# need to sort the runs by time
|
|
178
169
|
for mt_run in mt_station.runs:
|
|
179
|
-
xml_station = self.add_run(
|
|
180
|
-
xml_station, mt_run, mt_survey.filters
|
|
181
|
-
)
|
|
170
|
+
xml_station = self.add_run(xml_station, mt_run, mt_survey.filters)
|
|
182
171
|
xml_network.stations.append(xml_station)
|
|
183
172
|
xml_inventory.networks.append(xml_network)
|
|
184
173
|
if stationxml_fn:
|
|
@@ -204,19 +193,13 @@ class XMLInventoryMTExperiment:
|
|
|
204
193
|
"""
|
|
205
194
|
|
|
206
195
|
for mt_channel in mt_run.channels:
|
|
207
|
-
xml_channel = self.channel_translator.mt_to_xml(
|
|
208
|
-
|
|
209
|
-
)
|
|
210
|
-
existing_channels = xml_station.select(
|
|
211
|
-
channel=xml_channel.code
|
|
212
|
-
).channels
|
|
196
|
+
xml_channel = self.channel_translator.mt_to_xml(mt_channel, filters_dict)
|
|
197
|
+
existing_channels = xml_station.select(channel=xml_channel.code).channels
|
|
213
198
|
|
|
214
199
|
if existing_channels:
|
|
215
200
|
find = False
|
|
216
201
|
start_list = [c.start_date for c in existing_channels]
|
|
217
|
-
existing_channel = existing_channels[
|
|
218
|
-
start_list.index(max(start_list))
|
|
219
|
-
]
|
|
202
|
+
existing_channel = existing_channels[start_list.index(max(start_list))]
|
|
220
203
|
# should only compare the last channel
|
|
221
204
|
# for existing_channel in existing_channels:
|
|
222
205
|
run_list = [c.value for c in existing_channel.comments]
|
|
@@ -231,9 +214,7 @@ class XMLInventoryMTExperiment:
|
|
|
231
214
|
f"Matched {xml_channel.code}={existing_channel.code}"
|
|
232
215
|
)
|
|
233
216
|
if not mt_run.id in run_list:
|
|
234
|
-
self.logger.debug(
|
|
235
|
-
f"adding run id {mt_run.id} to {run_list}"
|
|
236
|
-
)
|
|
217
|
+
self.logger.debug(f"adding run id {mt_run.id} to {run_list}")
|
|
237
218
|
existing_channel.comments.append(
|
|
238
219
|
inventory.Comment(mt_run.id, subject="mt.run.id")
|
|
239
220
|
)
|
|
@@ -250,22 +231,16 @@ class XMLInventoryMTExperiment:
|
|
|
250
231
|
)
|
|
251
232
|
run_list = [c.value for c in xml_channel.comments]
|
|
252
233
|
if not mt_run.id in run_list:
|
|
253
|
-
self.logger.debug(
|
|
254
|
-
f"adding run id {mt_run.id} to {run_list}"
|
|
255
|
-
)
|
|
234
|
+
self.logger.debug(f"adding run id {mt_run.id} to {run_list}")
|
|
256
235
|
xml_channel.comments.append(
|
|
257
236
|
inventory.Comment(mt_run.id, subject="mt.run.id")
|
|
258
237
|
)
|
|
259
238
|
xml_station.channels.append(xml_channel)
|
|
260
239
|
else:
|
|
261
|
-
self.logger.debug(
|
|
262
|
-
f"no existing channels for {xml_channel.code}"
|
|
263
|
-
)
|
|
240
|
+
self.logger.debug(f"no existing channels for {xml_channel.code}")
|
|
264
241
|
run_list = [c.value for c in xml_channel.comments]
|
|
265
242
|
if not mt_run.id in run_list:
|
|
266
|
-
self.logger.debug(
|
|
267
|
-
f"adding run id {mt_run.id} to {run_list}"
|
|
268
|
-
)
|
|
243
|
+
self.logger.debug(f"adding run id {mt_run.id} to {run_list}")
|
|
269
244
|
xml_channel.comments.append(
|
|
270
245
|
inventory.Comment(mt_run.id, subject="mt.run.id")
|
|
271
246
|
)
|
|
@@ -294,20 +269,14 @@ class XMLInventoryMTExperiment:
|
|
|
294
269
|
)
|
|
295
270
|
return False
|
|
296
271
|
if xml_channel_01.sensor != xml_channel_02.sensor:
|
|
297
|
-
self.logger.debug(
|
|
298
|
-
f"{xml_channel_01.sensor} != {xml_channel_02.sensor}"
|
|
299
|
-
)
|
|
272
|
+
self.logger.debug(f"{xml_channel_01.sensor} != {xml_channel_02.sensor}")
|
|
300
273
|
return False
|
|
301
|
-
if round(xml_channel_01.latitude, 3) != round(
|
|
302
|
-
xml_channel_02.latitude, 3
|
|
303
|
-
):
|
|
274
|
+
if round(xml_channel_01.latitude, 3) != round(xml_channel_02.latitude, 3):
|
|
304
275
|
self.logger.debug(
|
|
305
276
|
f"{round(xml_channel_01.latitude, 3)} != {round(xml_channel_02.latitude, 3)}"
|
|
306
277
|
)
|
|
307
278
|
return False
|
|
308
|
-
if round(xml_channel_01.longitude, 3) != round(
|
|
309
|
-
xml_channel_02.longitude, 3
|
|
310
|
-
):
|
|
279
|
+
if round(xml_channel_01.longitude, 3) != round(xml_channel_02.longitude, 3):
|
|
311
280
|
self.logger.debug(
|
|
312
281
|
f"{round(xml_channel_01.longitude, 3)} != {round(xml_channel_02.longitude, 3)}"
|
|
313
282
|
)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""
|
|
3
3
|
Created on Thu Feb 18 12:49:13 2021
|
|
4
4
|
|
|
5
|
-
:copyright:
|
|
5
|
+
:copyright:
|
|
6
6
|
Jared Peacock (jpeacock@usgs.gov)
|
|
7
7
|
|
|
8
8
|
:license: MIT
|
|
@@ -142,9 +142,7 @@ class XMLStationMTStation(BaseTranslator):
|
|
|
142
142
|
mt_station.id = mt_station.fdsn.id
|
|
143
143
|
|
|
144
144
|
# read in equipment information
|
|
145
|
-
mt_station = self._equipments_to_runs(
|
|
146
|
-
xml_station.equipments, mt_station
|
|
147
|
-
)
|
|
145
|
+
mt_station = self._equipments_to_runs(xml_station.equipments, mt_station)
|
|
148
146
|
mt_station = self._add_run_comments(run_comments, mt_station)
|
|
149
147
|
|
|
150
148
|
return mt_station
|
|
@@ -175,37 +173,46 @@ class XMLStationMTStation(BaseTranslator):
|
|
|
175
173
|
mt_station.fdsn.id = mt_station.id
|
|
176
174
|
|
|
177
175
|
xml_station = inventory.Station(
|
|
178
|
-
code,
|
|
176
|
+
code.upper(),
|
|
179
177
|
mt_station.location.latitude,
|
|
180
178
|
mt_station.location.longitude,
|
|
181
179
|
mt_station.location.elevation,
|
|
182
180
|
)
|
|
183
181
|
|
|
184
182
|
for xml_key, mt_key in self.xml_translator.items():
|
|
185
|
-
|
|
186
|
-
|
|
183
|
+
# need to skip code because we just set it above and it needs to be upper.
|
|
184
|
+
|
|
187
185
|
if mt_key is None:
|
|
188
|
-
|
|
189
|
-
xml_key
|
|
186
|
+
self.logger.debug(
|
|
187
|
+
f"Cannot currently map mt_key.station to inventory.station.{xml_key}"
|
|
190
188
|
)
|
|
191
|
-
self.logger.debug(msg)
|
|
192
189
|
continue
|
|
193
190
|
|
|
194
|
-
if xml_key
|
|
191
|
+
if xml_key in ["code"]:
|
|
192
|
+
continue
|
|
193
|
+
elif xml_key in ["alternate_code"]:
|
|
194
|
+
xml_station.alternate_code = mt_station.id.upper()
|
|
195
|
+
|
|
196
|
+
elif xml_key == "operators":
|
|
195
197
|
if mt_station.acquired_by.name:
|
|
196
198
|
if mt_station.acquired_by.organization is None:
|
|
197
199
|
mt_station.acquired_by.organization = " "
|
|
198
200
|
operator = inventory.Operator(
|
|
199
201
|
agency=mt_station.acquired_by.organization
|
|
200
202
|
)
|
|
201
|
-
person = inventory.Person(
|
|
202
|
-
names=[mt_station.acquired_by.name]
|
|
203
|
-
)
|
|
203
|
+
person = inventory.Person(names=[mt_station.acquired_by.name])
|
|
204
204
|
operator.contacts = [person]
|
|
205
205
|
xml_station.operators = [operator]
|
|
206
206
|
|
|
207
207
|
elif xml_key == "site":
|
|
208
|
-
|
|
208
|
+
if mt_station.geographic_name is None:
|
|
209
|
+
xml_station.site.name = mt_station.id.upper()
|
|
210
|
+
self.logger.warning(
|
|
211
|
+
f"Station.geographic_name is None, using Station.id = {mt_station.id}."
|
|
212
|
+
"Check StationXML site.name."
|
|
213
|
+
)
|
|
214
|
+
else:
|
|
215
|
+
xml_station.site.name = mt_station.geographic_name
|
|
209
216
|
|
|
210
217
|
elif xml_key == "comments":
|
|
211
218
|
if mt_station.comments is not None:
|
|
@@ -216,9 +223,7 @@ class XMLStationMTStation(BaseTranslator):
|
|
|
216
223
|
xml_station.restricted_status
|
|
217
224
|
]
|
|
218
225
|
else:
|
|
219
|
-
setattr(
|
|
220
|
-
xml_station, xml_key, mt_station.get_attr_from_name(mt_key)
|
|
221
|
-
)
|
|
226
|
+
setattr(xml_station, xml_key, mt_station.get_attr_from_name(mt_key))
|
|
222
227
|
|
|
223
228
|
# add mt comments
|
|
224
229
|
xml_station.comments = self.make_mt_comments(mt_station, "mt.station")
|
|
@@ -281,9 +286,7 @@ class XMLStationMTStation(BaseTranslator):
|
|
|
281
286
|
if run_attr == "comments":
|
|
282
287
|
value = f"{ckey}: {cvalue}"
|
|
283
288
|
try:
|
|
284
|
-
station_obj.runs[
|
|
285
|
-
run_index
|
|
286
|
-
].comments += f", {value}"
|
|
289
|
+
station_obj.runs[run_index].comments += f", {value}"
|
|
287
290
|
except TypeError:
|
|
288
291
|
station_obj.runs[run_index].comments = value
|
|
289
292
|
else:
|
|
@@ -293,8 +296,6 @@ class XMLStationMTStation(BaseTranslator):
|
|
|
293
296
|
c_attr, cvalue
|
|
294
297
|
)
|
|
295
298
|
else:
|
|
296
|
-
station_obj.runs[run_index].set_attr_from_name(
|
|
297
|
-
ckey, cvalue
|
|
298
|
-
)
|
|
299
|
+
station_obj.runs[run_index].set_attr_from_name(ckey, cvalue)
|
|
299
300
|
|
|
300
301
|
return station_obj
|
|
@@ -9,6 +9,7 @@ STANDARD_OUTPUT_CHANNELS = [
|
|
|
9
9
|
"hz",
|
|
10
10
|
]
|
|
11
11
|
|
|
12
|
+
# channel nomenclature mappings
|
|
12
13
|
CHANNEL_MAPS = {
|
|
13
14
|
"default": {"hx": "hx", "hy": "hy", "hz": "hz", "ex": "ex", "ey": "ey"},
|
|
14
15
|
"lemi12": {"hx": "bx", "hy": "by", "hz": "bz", "ex": "e1", "ey": "e2"},
|
|
@@ -16,6 +17,8 @@ CHANNEL_MAPS = {
|
|
|
16
17
|
"phoenix123": {"hx": "h1", "hy": "h2", "hz": "h3", "ex": "e1", "ey": "e2"},
|
|
17
18
|
"musgraves": {"hx": "bx", "hy": "by", "hz": "bz", "ex": "ex", "ey": "ey"},
|
|
18
19
|
}
|
|
20
|
+
CHANNEL_MAPS["nims"] = CHANNEL_MAPS["default"] # Alias NIMS system to use same config as default
|
|
21
|
+
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
def get_allowed_channel_names(standard_names):
|
|
@@ -37,7 +37,7 @@ from mt_metadata.transfer_functions.io.zfiles.metadata import (
|
|
|
37
37
|
from mt_metadata.base.helpers import validate_name
|
|
38
38
|
from mt_metadata.utils.list_dict import ListDict
|
|
39
39
|
from mt_metadata import DEFAULT_CHANNEL_NOMENCLATURE
|
|
40
|
-
|
|
40
|
+
from typing import Optional
|
|
41
41
|
# =============================================================================
|
|
42
42
|
|
|
43
43
|
|
|
@@ -179,12 +179,12 @@ class TF:
|
|
|
179
179
|
|
|
180
180
|
return f"TF( {(', ').join(lines)} )"
|
|
181
181
|
|
|
182
|
-
def __eq__(self, other):
|
|
182
|
+
def __eq__(self, other, ignore_station_metadata_keys: Optional[list] = None):
|
|
183
183
|
is_equal = True
|
|
184
184
|
if not isinstance(other, TF):
|
|
185
185
|
self.logger.info(f"Comparing object is not TF, type {type(other)}")
|
|
186
186
|
is_equal = False
|
|
187
|
-
if self.station_metadata
|
|
187
|
+
if not self.station_metadata.__eq__(other.station_metadata, ignore_keys=ignore_station_metadata_keys):
|
|
188
188
|
self.logger.info("Station metadata is not equal")
|
|
189
189
|
is_equal = False
|
|
190
190
|
if self.survey_metadata != other.survey_metadata:
|
|
@@ -1871,9 +1871,13 @@ class TF:
|
|
|
1871
1871
|
edi_obj.t = self.tipper.data
|
|
1872
1872
|
edi_obj.t_err = self.tipper_error.data
|
|
1873
1873
|
edi_obj.frequency = 1.0 / self.period
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1874
|
+
|
|
1875
|
+
if isinstance(self._rotation_angle, (int, float)):
|
|
1876
|
+
edi_obj.rotation_angle = np.repeat(
|
|
1877
|
+
self._rotation_angle, self.period.size
|
|
1878
|
+
)
|
|
1879
|
+
else:
|
|
1880
|
+
edi_obj.rotation_angle = self._rotation_angle
|
|
1877
1881
|
|
|
1878
1882
|
# fill from survey metadata
|
|
1879
1883
|
edi_obj.survey_metadata = self.survey_metadata
|
|
@@ -1937,7 +1941,8 @@ class TF:
|
|
|
1937
1941
|
"residual_covariance": "residual_covariance",
|
|
1938
1942
|
"transfer_function_error": "tf_err",
|
|
1939
1943
|
"survey_metadata": "survey_metadata",
|
|
1940
|
-
"station_metadata": "station_metadata",
|
|
1944
|
+
# "station_metadata": "station_metadata",
|
|
1945
|
+
"_rotation_angle": "rotation_angle",
|
|
1941
1946
|
}
|
|
1942
1947
|
)
|
|
1943
1948
|
else:
|
|
@@ -1949,7 +1954,8 @@ class TF:
|
|
|
1949
1954
|
"tipper": "t",
|
|
1950
1955
|
"tipper_error": "t_err",
|
|
1951
1956
|
"survey_metadata": "survey_metadata",
|
|
1952
|
-
"station_metadata": "station_metadata",
|
|
1957
|
+
# "station_metadata": "station_metadata",
|
|
1958
|
+
"_rotation_angle": "rotation_angle",
|
|
1953
1959
|
}
|
|
1954
1960
|
)
|
|
1955
1961
|
for tf_key, edi_key in k_dict.items():
|
|
@@ -2046,7 +2052,7 @@ class TF:
|
|
|
2046
2052
|
f"Input must be a EMTFXML object not {type(emtfxml_obj)}"
|
|
2047
2053
|
)
|
|
2048
2054
|
self.survey_metadata = emtfxml_obj.survey_metadata
|
|
2049
|
-
self.station_metadata =
|
|
2055
|
+
self.station_metadata = self.survey_metadata.stations[0]
|
|
2050
2056
|
|
|
2051
2057
|
self.period = emtfxml_obj.data.period
|
|
2052
2058
|
self.impedance = emtfxml_obj.data.z
|
|
@@ -2108,7 +2114,7 @@ class TF:
|
|
|
2108
2114
|
"tipper": "t",
|
|
2109
2115
|
"tipper_error": "t_err",
|
|
2110
2116
|
"survey_metadata": "survey_metadata",
|
|
2111
|
-
"station_metadata": "station_metadata",
|
|
2117
|
+
# "station_metadata": "station_metadata",
|
|
2112
2118
|
}
|
|
2113
2119
|
)
|
|
2114
2120
|
|
|
@@ -2369,7 +2375,6 @@ class TF:
|
|
|
2369
2375
|
if not isinstance(avg_obj, ZongeMTAvg):
|
|
2370
2376
|
raise TypeError(f"Input must be a ZMM object not {type(avg_obj)}")
|
|
2371
2377
|
self.survey_metadata = avg_obj.survey_metadata
|
|
2372
|
-
self.station_metadata = avg_obj.station_metadata
|
|
2373
2378
|
|
|
2374
2379
|
self.period = 1.0 / avg_obj.frequency
|
|
2375
2380
|
self.impedance = avg_obj.z
|
|
@@ -24,6 +24,8 @@ from mt_metadata.transfer_functions.io.emtfxml.metadata import helpers
|
|
|
24
24
|
# =============================================================================
|
|
25
25
|
attr_dict = get_schema("location", SCHEMA_FN_PATHS)
|
|
26
26
|
attr_dict.add_dict(Declination()._attr_dict, "declination")
|
|
27
|
+
|
|
28
|
+
|
|
27
29
|
# =============================================================================
|
|
28
30
|
class Location(Base):
|
|
29
31
|
__doc__ = write_lines(attr_dict)
|
|
@@ -31,6 +33,9 @@ class Location(Base):
|
|
|
31
33
|
def __init__(self, **kwargs):
|
|
32
34
|
|
|
33
35
|
self.declination = Declination()
|
|
36
|
+
self._latitude = 0.0
|
|
37
|
+
self._longitude = 0.0
|
|
38
|
+
self._elevation = 0.0
|
|
34
39
|
|
|
35
40
|
super().__init__(attr_dict=attr_dict, **kwargs)
|
|
36
41
|
|
|
@@ -25,9 +25,20 @@ from mt_metadata import __version__
|
|
|
25
25
|
|
|
26
26
|
# =============================================================================
|
|
27
27
|
attr_dict = get_schema("provenance", SCHEMA_FN_PATHS)
|
|
28
|
-
person_dict = get_schema(
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
person_dict = get_schema(
|
|
29
|
+
"person",
|
|
30
|
+
SCHEMA_FN_PATHS,
|
|
31
|
+
)
|
|
32
|
+
attr_dict.add_dict(
|
|
33
|
+
person_dict,
|
|
34
|
+
"creator",
|
|
35
|
+
keys=["name", "comments", "url", "org", "org_url", "email"],
|
|
36
|
+
)
|
|
37
|
+
attr_dict.add_dict(
|
|
38
|
+
person_dict,
|
|
39
|
+
"submitter",
|
|
40
|
+
keys=["name", "comments", "url", "org", "org_url", "email"],
|
|
41
|
+
)
|
|
31
42
|
# =============================================================================
|
|
32
43
|
|
|
33
44
|
|
|
@@ -198,7 +198,9 @@ def get_nm_elev(latitude, longitude):
|
|
|
198
198
|
|
|
199
199
|
# read the xml response and convert to a float
|
|
200
200
|
try:
|
|
201
|
+
# unpack the response to a dictionary
|
|
201
202
|
info = json.loads(response.read())
|
|
203
|
+
|
|
202
204
|
except json.JSONDecodeError:
|
|
203
205
|
logger.error(
|
|
204
206
|
f"Input values (latitude={latitude}, longitude={longitude}) "
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"options": [],
|
|
9
9
|
"alias": [],
|
|
10
10
|
"example": "yellowstone",
|
|
11
|
-
|
|
11
|
+
"default": null
|
|
12
12
|
},
|
|
13
13
|
"for": {
|
|
14
14
|
"type": "string",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"options": [],
|
|
20
20
|
"alias": [],
|
|
21
21
|
"example": "NSF",
|
|
22
|
-
|
|
22
|
+
"default": null
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
}
|