mt-metadata 0.3.9__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/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 +25 -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 +8 -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 -178
- 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/station.py +17 -1
- mt_metadata/utils/mttime.py +22 -3
- mt_metadata/utils/validators.py +4 -2
- {mt_metadata-0.3.9.dist-info → mt_metadata-0.4.0.dist-info}/METADATA +39 -15
- {mt_metadata-0.3.9.dist-info → mt_metadata-0.4.0.dist-info}/RECORD +95 -55
- {mt_metadata-0.3.9.dist-info → mt_metadata-0.4.0.dist-info}/WHEEL +1 -1
- {mt_metadata-0.3.9.dist-info → mt_metadata-0.4.0.dist-info}/AUTHORS.rst +0 -0
- {mt_metadata-0.3.9.dist-info → mt_metadata-0.4.0.dist-info}/LICENSE +0 -0
- {mt_metadata-0.3.9.dist-info → mt_metadata-0.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module containing FrequencyBands class representing a collection of Frequency Band objects.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Literal, Optional, Generator, Union, List
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import numpy as np
|
|
7
|
+
import warnings
|
|
8
|
+
from loguru import logger
|
|
9
|
+
|
|
10
|
+
from . import Band
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FrequencyBands:
|
|
14
|
+
"""
|
|
15
|
+
Collection of Band objects, typically used at a single decimation level.
|
|
16
|
+
|
|
17
|
+
Attributes
|
|
18
|
+
----------
|
|
19
|
+
_band_edges : pd.DataFrame
|
|
20
|
+
DataFrame with columns ['lower_bound', 'upper_bound'] containing
|
|
21
|
+
frequency band boundaries
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
band_edges: Optional[Union[np.ndarray, pd.DataFrame]] = None,
|
|
27
|
+
):
|
|
28
|
+
"""
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
band_edges : np.ndarray or pd.DataFrame, optional
|
|
32
|
+
If numpy array: 2D array with columns [lower_bound, upper_bound]
|
|
33
|
+
If DataFrame: Must have columns ['lower_bound', 'upper_bound']
|
|
34
|
+
"""
|
|
35
|
+
if band_edges is not None:
|
|
36
|
+
self.band_edges = band_edges
|
|
37
|
+
else:
|
|
38
|
+
self._band_edges = pd.DataFrame(columns=['lower_bound', 'upper_bound'])
|
|
39
|
+
|
|
40
|
+
def __str__(self) -> str:
|
|
41
|
+
"""Returns a Description of frequency bands"""
|
|
42
|
+
intro = "Frequency Bands:"
|
|
43
|
+
return f"{intro} \n{self._band_edges}"
|
|
44
|
+
|
|
45
|
+
def __repr__(self):
|
|
46
|
+
return self.__str__()
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def band_edges(self) -> pd.DataFrame:
|
|
50
|
+
"""Get band edges as a DataFrame"""
|
|
51
|
+
return self._band_edges
|
|
52
|
+
|
|
53
|
+
@band_edges.setter
|
|
54
|
+
def band_edges(self, value: Union[np.ndarray, pd.DataFrame]) -> None:
|
|
55
|
+
"""
|
|
56
|
+
Set band edges from either numpy array or DataFrame
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
value : np.ndarray or pd.DataFrame
|
|
61
|
+
Band edge definitions
|
|
62
|
+
"""
|
|
63
|
+
if isinstance(value, np.ndarray):
|
|
64
|
+
if value.ndim != 2 or value.shape[1] != 2:
|
|
65
|
+
raise ValueError("band_edges array must be 2D with shape (n_bands, 2)")
|
|
66
|
+
self._band_edges = pd.DataFrame(
|
|
67
|
+
value,
|
|
68
|
+
columns=['lower_bound', 'upper_bound']
|
|
69
|
+
)
|
|
70
|
+
elif isinstance(value, pd.DataFrame):
|
|
71
|
+
required_cols = ['lower_bound', 'upper_bound']
|
|
72
|
+
if not all(col in value.columns for col in required_cols):
|
|
73
|
+
raise ValueError(
|
|
74
|
+
f"DataFrame must contain columns {required_cols}"
|
|
75
|
+
)
|
|
76
|
+
self._band_edges = value[required_cols].copy()
|
|
77
|
+
else:
|
|
78
|
+
raise TypeError(
|
|
79
|
+
"band_edges must be numpy array or DataFrame"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Reset index to ensure 0-based integer indexing
|
|
83
|
+
self._band_edges.reset_index(drop=True, inplace=True)
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def number_of_bands(self) -> int:
|
|
87
|
+
"""Number of frequency bands"""
|
|
88
|
+
return len(self._band_edges)
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def array(self) -> np.ndarray:
|
|
92
|
+
"""Get band edges as numpy array"""
|
|
93
|
+
return self._band_edges.values
|
|
94
|
+
|
|
95
|
+
def sort(self, by: str = "center_frequency", ascending: bool = True) -> None:
|
|
96
|
+
"""
|
|
97
|
+
Sort bands by specified criterion.
|
|
98
|
+
|
|
99
|
+
Parameters
|
|
100
|
+
----------
|
|
101
|
+
by : str
|
|
102
|
+
Criterion to sort by:
|
|
103
|
+
- "lower_bound": Sort by lower frequency bound
|
|
104
|
+
- "upper_bound": Sort by upper frequency bound
|
|
105
|
+
- "center_frequency": Sort by geometric center frequency (default)
|
|
106
|
+
ascending : bool
|
|
107
|
+
If True, sort in ascending order, else descending
|
|
108
|
+
"""
|
|
109
|
+
if by in ["lower_bound", "upper_bound"]:
|
|
110
|
+
self._band_edges.sort_values(by=by, ascending=ascending, inplace=True)
|
|
111
|
+
elif by == "center_frequency":
|
|
112
|
+
centers = self.band_centers()
|
|
113
|
+
self._band_edges = self._band_edges.iloc[
|
|
114
|
+
np.argsort(centers)[::(-1 if not ascending else 1)]
|
|
115
|
+
].reset_index(drop=True)
|
|
116
|
+
else:
|
|
117
|
+
raise ValueError(
|
|
118
|
+
f"Invalid sort criterion: {by}. Must be one of: "
|
|
119
|
+
"'lower_bound', 'upper_bound', 'center_frequency'"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def bands(
|
|
123
|
+
self,
|
|
124
|
+
direction: str = "increasing_frequency",
|
|
125
|
+
sortby: Optional[str] = None,
|
|
126
|
+
rtype: str = "list"
|
|
127
|
+
) -> Union[List[Band], Generator[Band, None, None]]:
|
|
128
|
+
"""
|
|
129
|
+
Generate Band objects in specified order.
|
|
130
|
+
|
|
131
|
+
Parameters
|
|
132
|
+
----------
|
|
133
|
+
direction : str
|
|
134
|
+
Order of iteration: "increasing_frequency" or "increasing_period"
|
|
135
|
+
sortby : str, optional
|
|
136
|
+
Sort bands before iteration:
|
|
137
|
+
- "lower_bound": Sort by lower frequency bound
|
|
138
|
+
- "upper_bound": Sort by upper frequency bound
|
|
139
|
+
- "center_frequency": Sort by geometric center frequency
|
|
140
|
+
If None, uses existing order
|
|
141
|
+
rtype : str
|
|
142
|
+
Return type: "list" or "generator". Default is "list" for easier reuse.
|
|
143
|
+
Use "generator" for memory efficiency when bands are only iterated once.
|
|
144
|
+
|
|
145
|
+
Returns
|
|
146
|
+
-------
|
|
147
|
+
Union[List[Band], Generator[Band, None, None]]
|
|
148
|
+
Band objects for each frequency band, either as a list or generator
|
|
149
|
+
depending on rtype parameter.
|
|
150
|
+
"""
|
|
151
|
+
if sortby is not None or direction == "increasing_period":
|
|
152
|
+
# Create a copy to avoid modifying original
|
|
153
|
+
temp_bands = FrequencyBands(self._band_edges.copy())
|
|
154
|
+
temp_bands.sort(
|
|
155
|
+
by=sortby or "center_frequency",
|
|
156
|
+
ascending=(direction == "increasing_frequency")
|
|
157
|
+
)
|
|
158
|
+
bands_to_iterate = temp_bands
|
|
159
|
+
else:
|
|
160
|
+
bands_to_iterate = self
|
|
161
|
+
|
|
162
|
+
# Create generator
|
|
163
|
+
def band_generator():
|
|
164
|
+
for idx in range(bands_to_iterate.number_of_bands):
|
|
165
|
+
yield bands_to_iterate.band(idx)
|
|
166
|
+
|
|
167
|
+
# Return as requested type
|
|
168
|
+
if rtype == "generator":
|
|
169
|
+
return band_generator()
|
|
170
|
+
elif rtype == "list":
|
|
171
|
+
return list(band_generator())
|
|
172
|
+
else:
|
|
173
|
+
raise ValueError("rtype must be either 'list' or 'generator'")
|
|
174
|
+
|
|
175
|
+
def band(self, i_band: int) -> Band:
|
|
176
|
+
"""
|
|
177
|
+
Get specific frequency band.
|
|
178
|
+
|
|
179
|
+
Parameters
|
|
180
|
+
----------
|
|
181
|
+
i_band : int
|
|
182
|
+
Index of band to return (zero-based)
|
|
183
|
+
|
|
184
|
+
Returns
|
|
185
|
+
-------
|
|
186
|
+
Band
|
|
187
|
+
Frequency band object
|
|
188
|
+
"""
|
|
189
|
+
row = self._band_edges.iloc[i_band]
|
|
190
|
+
return Band(
|
|
191
|
+
frequency_min=row['lower_bound'],
|
|
192
|
+
frequency_max=row['upper_bound']
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
def band_centers(self, frequency_or_period: str = "frequency") -> np.ndarray:
|
|
196
|
+
"""
|
|
197
|
+
Calculate center frequencies/periods for all bands.
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
frequency_or_period : str
|
|
202
|
+
Return values in "frequency" (Hz) or "period" (s)
|
|
203
|
+
|
|
204
|
+
Returns
|
|
205
|
+
-------
|
|
206
|
+
np.ndarray
|
|
207
|
+
Center frequencies/periods for each band
|
|
208
|
+
"""
|
|
209
|
+
band_centers = np.array([
|
|
210
|
+
self.band(i).center_frequency
|
|
211
|
+
for i in range(self.number_of_bands)
|
|
212
|
+
])
|
|
213
|
+
|
|
214
|
+
if frequency_or_period == "period":
|
|
215
|
+
band_centers = 1.0 / band_centers
|
|
216
|
+
|
|
217
|
+
return band_centers
|
|
218
|
+
|
|
219
|
+
def validate(self) -> None:
|
|
220
|
+
"""
|
|
221
|
+
Validate and potentially reorder bands based on center frequencies.
|
|
222
|
+
"""
|
|
223
|
+
band_centers = self.band_centers()
|
|
224
|
+
|
|
225
|
+
# Check if band centers are monotonically increasing
|
|
226
|
+
if not np.all(band_centers[1:] > band_centers[:-1]):
|
|
227
|
+
logger.warning(
|
|
228
|
+
"Band centers are not monotonic. Attempting to reorganize bands."
|
|
229
|
+
)
|
|
230
|
+
self.sort(by="center_frequency")
|
|
@@ -52,6 +52,7 @@ class Processing(Base):
|
|
|
52
52
|
"""
|
|
53
53
|
dictionary of decimations levels
|
|
54
54
|
|
|
55
|
+
TODO: replace this convoluted setter with the model used for DecimationLevel.bands setter.
|
|
55
56
|
:param value: dict of decimation levels
|
|
56
57
|
:type value: dict
|
|
57
58
|
|
|
@@ -75,7 +76,6 @@ class Processing(Base):
|
|
|
75
76
|
for obj in value:
|
|
76
77
|
if isinstance(value, DecimationLevel):
|
|
77
78
|
self._decimations.append(obj)
|
|
78
|
-
|
|
79
79
|
elif isinstance(obj, dict):
|
|
80
80
|
level = DecimationLevel()
|
|
81
81
|
level.from_dict(obj)
|
|
@@ -84,7 +84,7 @@ class Processing(Base):
|
|
|
84
84
|
raise TypeError(
|
|
85
85
|
f"List entry must be a DecimationLevel or dict object not {type(obj)}"
|
|
86
86
|
)
|
|
87
|
-
|
|
87
|
+
# TODO: Add some doc describing the role of this weird check for a long string
|
|
88
88
|
elif isinstance(value, str):
|
|
89
89
|
if len(value) > 4:
|
|
90
90
|
raise TypeError(f"Not sure what to do with {type(value)}")
|
|
@@ -216,7 +216,7 @@ class Processing(Base):
|
|
|
216
216
|
) # self.decimations_dict[key]
|
|
217
217
|
decimation_obj.decimation.factor = d
|
|
218
218
|
decimation_obj.decimation.sample_rate = sr
|
|
219
|
-
decimation_obj.window.num_samples = num_samples_window[i_level]
|
|
219
|
+
decimation_obj.stft.window.num_samples = num_samples_window[i_level]
|
|
220
220
|
frequencies = decimation_obj.fft_frequencies
|
|
221
221
|
|
|
222
222
|
for low, high in band_edges:
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""
|
|
3
|
+
Module for `aurora` Run metadata container with useful built-in methods.
|
|
4
|
+
|
|
3
5
|
Created on Thu Feb 17 14:15:20 2022
|
|
4
6
|
|
|
5
7
|
@author: jpeacock
|
|
8
|
+
|
|
6
9
|
"""
|
|
7
10
|
# =============================================================================
|
|
8
11
|
# Imports
|
|
@@ -12,6 +15,7 @@ from mt_metadata.base import get_schema, Base
|
|
|
12
15
|
from .standards import SCHEMA_FN_PATHS
|
|
13
16
|
from mt_metadata.timeseries import TimePeriod
|
|
14
17
|
from .channel import Channel
|
|
18
|
+
from typing import Union
|
|
15
19
|
|
|
16
20
|
# =============================================================================
|
|
17
21
|
attr_dict = get_schema("run", SCHEMA_FN_PATHS)
|
|
@@ -20,6 +24,10 @@ class Run(Base):
|
|
|
20
24
|
__doc__ = write_lines(attr_dict)
|
|
21
25
|
|
|
22
26
|
def __init__(self, **kwargs):
|
|
27
|
+
"""
|
|
28
|
+
Constructor.
|
|
29
|
+
|
|
30
|
+
"""
|
|
23
31
|
self._input = []
|
|
24
32
|
self._output = []
|
|
25
33
|
self._time_periods = []
|
|
@@ -27,16 +35,16 @@ class Run(Base):
|
|
|
27
35
|
super().__init__(attr_dict=attr_dict, **kwargs)
|
|
28
36
|
|
|
29
37
|
@property
|
|
30
|
-
def input_channel_names(self):
|
|
38
|
+
def input_channel_names(self) -> list:
|
|
31
39
|
"""list of channel names"""
|
|
32
40
|
return [ch.id for ch in self._input]
|
|
33
41
|
|
|
34
42
|
@property
|
|
35
|
-
def input_channels(self):
|
|
43
|
+
def input_channels(self) -> list:
|
|
36
44
|
return self._input
|
|
37
45
|
|
|
38
46
|
@input_channels.setter
|
|
39
|
-
def input_channels(self, values):
|
|
47
|
+
def input_channels(self, values: Union[list, str, Channel, dict]) -> None:
|
|
40
48
|
self._input = []
|
|
41
49
|
if not isinstance(values, list):
|
|
42
50
|
values = [values]
|
|
@@ -90,17 +98,34 @@ class Run(Base):
|
|
|
90
98
|
return self._time_periods
|
|
91
99
|
|
|
92
100
|
@time_periods.setter
|
|
93
|
-
def time_periods(self, values):
|
|
101
|
+
def time_periods(self, values: Union[list, dict, TimePeriod]) -> None:
|
|
102
|
+
"""
|
|
103
|
+
Sets self.time_periods
|
|
104
|
+
|
|
105
|
+
Parameters
|
|
106
|
+
----------
|
|
107
|
+
values: Union[list, dict, TimePeriod]
|
|
108
|
+
If it is a list, the elements of the list must be TimePerid or dictionary representations of TimePeriods
|
|
109
|
+
|
|
110
|
+
"""
|
|
94
111
|
self._time_periods = []
|
|
95
112
|
if not isinstance(values, list):
|
|
96
113
|
values = [values]
|
|
97
114
|
|
|
98
115
|
for item in values:
|
|
99
|
-
if
|
|
116
|
+
if isinstance(item, TimePeriod):
|
|
117
|
+
self._time_periods.append(item)
|
|
118
|
+
elif isinstance(item, dict):
|
|
119
|
+
try:
|
|
120
|
+
tp = TimePeriod()
|
|
121
|
+
tp.from_dict(item)
|
|
122
|
+
self._time_periods.append(tp)
|
|
123
|
+
except Exception as e:
|
|
124
|
+
msg = f"Could not unpack dict to TimePeriod, got exception {e}"
|
|
125
|
+
raise ValueError(msg)
|
|
126
|
+
else:
|
|
100
127
|
raise TypeError(f"not sure what to do with type {type(item)}")
|
|
101
128
|
|
|
102
|
-
self._time_periods.append(item)
|
|
103
|
-
|
|
104
129
|
@property
|
|
105
130
|
def channel_scale_factors(self):
|
|
106
131
|
"""
|
|
@@ -1,87 +1,21 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
"type": "string",
|
|
4
|
-
"required": true,
|
|
5
|
-
"style": "controlled vocabulary",
|
|
6
|
-
"units": null,
|
|
7
|
-
"description": "Name of anti alias filter to be applied",
|
|
8
|
-
"options": ["deafult", "other"],
|
|
9
|
-
"alias": [],
|
|
10
|
-
"example": "default",
|
|
11
|
-
"default": "default"
|
|
12
|
-
},
|
|
13
|
-
"recoloring": {
|
|
14
|
-
"type": "bool",
|
|
15
|
-
"required": true,
|
|
16
|
-
"style": "free form",
|
|
17
|
-
"units": null,
|
|
18
|
-
"description": "Whether the data are recolored [True] or not [False].",
|
|
19
|
-
"options": [],
|
|
20
|
-
"alias": [],
|
|
21
|
-
"example": true,
|
|
22
|
-
"default": true
|
|
23
|
-
},
|
|
24
|
-
"min_num_stft_windows": {
|
|
2
|
+
"bands": {
|
|
25
3
|
"type": "integer",
|
|
26
4
|
"required": true,
|
|
27
|
-
"style": "
|
|
5
|
+
"style": "name list",
|
|
28
6
|
"units": null,
|
|
29
|
-
"description": "
|
|
7
|
+
"description": "List of bands",
|
|
30
8
|
"options": [],
|
|
31
9
|
"alias": [],
|
|
32
|
-
"example":
|
|
33
|
-
"default":
|
|
34
|
-
},
|
|
35
|
-
"method": {
|
|
36
|
-
"type": "string",
|
|
37
|
-
"required": true,
|
|
38
|
-
"style": "controlled vocabulary",
|
|
39
|
-
"units": null,
|
|
40
|
-
"description": "Fourier transform method",
|
|
41
|
-
"options": ["fft", "wavelet", "other"],
|
|
42
|
-
"alias": [],
|
|
43
|
-
"example": "fft",
|
|
44
|
-
"default": "fft"
|
|
45
|
-
},
|
|
46
|
-
"prewhitening_type": {
|
|
47
|
-
"type": "string",
|
|
48
|
-
"required": true,
|
|
49
|
-
"style": "controlled vocabulary",
|
|
50
|
-
"units": null,
|
|
51
|
-
"description": "Prewhitening method to be applied",
|
|
52
|
-
"options": ["first difference", "other"],
|
|
53
|
-
"alias": [],
|
|
54
|
-
"example": "first difference",
|
|
55
|
-
"default": "first difference"
|
|
56
|
-
},
|
|
57
|
-
"extra_pre_fft_detrend_type": {
|
|
58
|
-
"type": "string",
|
|
59
|
-
"required": true,
|
|
60
|
-
"style": "controlled vocabulary",
|
|
61
|
-
"units": null,
|
|
62
|
-
"description": "Extra Pre FFT detrend method to be applied",
|
|
63
|
-
"options": ["linear", "other"],
|
|
64
|
-
"alias": [],
|
|
65
|
-
"example": "linear",
|
|
66
|
-
"default": "linear"
|
|
67
|
-
},
|
|
68
|
-
"pre_fft_detrend_type": {
|
|
69
|
-
"type": "string",
|
|
70
|
-
"required": true,
|
|
71
|
-
"style": "controlled vocabulary",
|
|
72
|
-
"units": null,
|
|
73
|
-
"description": "Pre FFT detrend method to be applied",
|
|
74
|
-
"options": ["linear", "other"],
|
|
75
|
-
"alias": [],
|
|
76
|
-
"example": "linear",
|
|
77
|
-
"default": "linear"
|
|
10
|
+
"example": "[]",
|
|
11
|
+
"default": null
|
|
78
12
|
},
|
|
79
|
-
|
|
13
|
+
"channel_weight_specs": {
|
|
80
14
|
"type": "integer",
|
|
81
15
|
"required": true,
|
|
82
16
|
"style": "name list",
|
|
83
17
|
"units": null,
|
|
84
|
-
"description": "List of
|
|
18
|
+
"description": "List of weighting schemes to use for TF processing for each output channel",
|
|
85
19
|
"options": [],
|
|
86
20
|
"alias": [],
|
|
87
21
|
"example": "[]",
|
|
@@ -4,6 +4,9 @@ Created on Thu Feb 24 13:58:07 2022
|
|
|
4
4
|
|
|
5
5
|
@author: jpeacock
|
|
6
6
|
"""
|
|
7
|
+
from loguru import logger
|
|
8
|
+
from typing import Union
|
|
9
|
+
|
|
7
10
|
import pandas as pd
|
|
8
11
|
|
|
9
12
|
# =============================================================================
|
|
@@ -49,15 +52,40 @@ class Stations(Base):
|
|
|
49
52
|
return return_list
|
|
50
53
|
|
|
51
54
|
@remote.setter
|
|
52
|
-
def remote(self, rr_station):
|
|
55
|
+
def remote(self, rr_station: Union[list, dict]):
|
|
56
|
+
"""
|
|
57
|
+
Method for unpacking rr_station info into mt_metadata object.
|
|
58
|
+
|
|
59
|
+
Developmnent Notes:
|
|
60
|
+
This function was raising an exception when trying to populate an aurora.Processing object
|
|
61
|
+
from a json.loads() dict.
|
|
62
|
+
TODO: add a description of input variable and use cases, ... it seems that we may not want
|
|
63
|
+
to support multiple rr stations yet.
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
rr_station
|
|
68
|
+
|
|
69
|
+
Returns
|
|
70
|
+
-------
|
|
71
|
+
|
|
72
|
+
"""
|
|
53
73
|
self._remote = []
|
|
54
74
|
if isinstance(rr_station, list):
|
|
55
75
|
for item in rr_station:
|
|
56
|
-
if
|
|
76
|
+
if isinstance(item, Station):
|
|
77
|
+
self._remote.append(item)
|
|
78
|
+
elif isinstance(item, dict):
|
|
79
|
+
try:
|
|
80
|
+
remote = Station()
|
|
81
|
+
remote.from_dict(item)
|
|
82
|
+
self._remote.append(remote)
|
|
83
|
+
except Exception as e:
|
|
84
|
+
raise ValueError("could not unpack dict to a Station object")
|
|
85
|
+
else:
|
|
57
86
|
raise TypeError(
|
|
58
87
|
f"list item must be Station object not {type(item)}"
|
|
59
88
|
)
|
|
60
|
-
self._remote.append(item)
|
|
61
89
|
|
|
62
90
|
elif isinstance(rr_station, dict):
|
|
63
91
|
remote = Station()
|
|
@@ -69,9 +97,10 @@ class Stations(Base):
|
|
|
69
97
|
rr_station.remote = True
|
|
70
98
|
self._remote.append(rr_station)
|
|
71
99
|
|
|
72
|
-
elif isinstance(rr_station, str):
|
|
100
|
+
elif isinstance(rr_station, str): # TODO: Add doc; what is this doing? This does not affect self._remote.
|
|
73
101
|
if len(rr_station) > 4:
|
|
74
102
|
raise ValueError(f"not sure to do with {type(rr_station)}")
|
|
103
|
+
# TODO: Add doc explaining what happens when rr_station is str of length 3.
|
|
75
104
|
|
|
76
105
|
else:
|
|
77
106
|
raise ValueError(f"not sure to do with {type(rr_station)}")
|