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,275 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module for a monotonic_weight_kernel.
|
|
3
|
+
|
|
4
|
+
TODO: Ensure the standards JSON defaults are set when not specified.
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .base import BaseWeightKernel
|
|
9
|
+
from .standards import SCHEMA_FN_PATHS
|
|
10
|
+
from mt_metadata.base.helpers import write_lines
|
|
11
|
+
from mt_metadata.base import get_schema, Base
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Separate schemas for each type (optional, but recommended for clarity)
|
|
18
|
+
TAPER_STYLES = ["rectangle", "hann", "hamming", "blackman"]
|
|
19
|
+
ACTIVATION_STYLES = ["sigmoid", "hard_sigmoid", "tanh", "hard_tanh"]
|
|
20
|
+
|
|
21
|
+
base_attr_dict = get_schema("monotonic_weight_kernel", SCHEMA_FN_PATHS)
|
|
22
|
+
taper_attr_dict = get_schema("taper_monotonic_weight_kernel", SCHEMA_FN_PATHS)
|
|
23
|
+
activation_attr_dict = get_schema("activation_monotonic_weight_kernel", SCHEMA_FN_PATHS)
|
|
24
|
+
|
|
25
|
+
class MonotonicWeightKernel(BaseWeightKernel):
|
|
26
|
+
"""
|
|
27
|
+
MonotonicWeightKernel
|
|
28
|
+
|
|
29
|
+
Base class for monotonic weight kernels.
|
|
30
|
+
Handles bounds, normalization, and direction.
|
|
31
|
+
|
|
32
|
+
A weighting kernel that applies a monotonic activation/taper function between defined
|
|
33
|
+
lower and upper bounds, based on a given threshold direction.
|
|
34
|
+
|
|
35
|
+
There are two main types of monotonic kernels: taper and activation. The taper function
|
|
36
|
+
is used to smoothly transition between the lower and upper bounds over some finite interval,
|
|
37
|
+
while the activation style offers options that asymptote to 0 or 1, such as sigmoid or tanh.
|
|
38
|
+
Thus the activation style supports +/- infinity bounds, while the taper style requires finite bounds.
|
|
39
|
+
|
|
40
|
+
"""
|
|
41
|
+
__doc__ = write_lines(base_attr_dict)
|
|
42
|
+
|
|
43
|
+
def __init__(self, attr_dict=base_attr_dict, **kwargs):
|
|
44
|
+
"""
|
|
45
|
+
Constructor.
|
|
46
|
+
"""
|
|
47
|
+
super().__init__(attr_dict=base_attr_dict, **kwargs)
|
|
48
|
+
self.weight_type = "monotonic"
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def _has_finite_transition_bounds(self) -> bool:
|
|
52
|
+
"""
|
|
53
|
+
Check if the transition bounds are finite.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
bool
|
|
58
|
+
True if both transition_lower_bound and transition_upper_bound are finite, False otherwise.
|
|
59
|
+
"""
|
|
60
|
+
lb = float(self.transition_lower_bound)
|
|
61
|
+
ub = float(self.transition_upper_bound)
|
|
62
|
+
return np.isfinite(lb) and np.isfinite(ub)
|
|
63
|
+
|
|
64
|
+
def _normalize(self, values):
|
|
65
|
+
"""
|
|
66
|
+
Normalize input values to the [0, 1] interval based on finite transition bounds.
|
|
67
|
+
|
|
68
|
+
Only supports finite lower and upper bounds. Subclasses should override this method
|
|
69
|
+
if they wish to support infinite bounds or custom normalization.
|
|
70
|
+
|
|
71
|
+
Parameters
|
|
72
|
+
----------
|
|
73
|
+
values : array-like
|
|
74
|
+
Input values to be normalized.
|
|
75
|
+
|
|
76
|
+
Returns
|
|
77
|
+
-------
|
|
78
|
+
np.ndarray
|
|
79
|
+
Normalized values in the range [0, 1].
|
|
80
|
+
|
|
81
|
+
Raises
|
|
82
|
+
------
|
|
83
|
+
ValueError
|
|
84
|
+
If either transition bound is infinite.
|
|
85
|
+
"""
|
|
86
|
+
if self._has_finite_transition_bounds:
|
|
87
|
+
lb = float(self.transition_lower_bound)
|
|
88
|
+
ub = float(self.transition_upper_bound)
|
|
89
|
+
values = np.asarray(values)
|
|
90
|
+
return (values - lb) / (ub - lb)
|
|
91
|
+
else:
|
|
92
|
+
raise ValueError("MonotonicWeightKernel only supports finite transition bounds. "
|
|
93
|
+
"Override _normalize in subclasses for infinite bounds.")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class TaperMonotonicWeightKernel(MonotonicWeightKernel):
|
|
98
|
+
"""
|
|
99
|
+
Handles taper/window styles: rectangle, hann, hamming, blackman.
|
|
100
|
+
"""
|
|
101
|
+
__doc__ = write_lines(taper_attr_dict)
|
|
102
|
+
|
|
103
|
+
def __init__(self, **kwargs):
|
|
104
|
+
super().__init__(attr_dict=taper_attr_dict, **kwargs)
|
|
105
|
+
self.weight_type = "taper_monotonic"
|
|
106
|
+
|
|
107
|
+
def _normalize(self, values):
|
|
108
|
+
"""
|
|
109
|
+
Normalize input values to the [0, 1] interval based on the transition bounds and threshold direction.
|
|
110
|
+
|
|
111
|
+
This function maps the input array `values` to a normalized scale between 0 and 1, according to the
|
|
112
|
+
transition_lower_bound and transition_upper_bound attributes. The normalization is performed differently
|
|
113
|
+
depending on the threshold direction:
|
|
114
|
+
|
|
115
|
+
- If threshold is 'low cut', values below the lower bound are mapped to 0, values above the upper bound are mapped to 1,
|
|
116
|
+
and values in between are linearly scaled.
|
|
117
|
+
- If threshold is 'high cut', the mapping is reversed: values below the lower bound are mapped to 1, values above the upper bound to 0,
|
|
118
|
+
and values in between are linearly scaled in the opposite direction.
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------
|
|
122
|
+
values : array-like
|
|
123
|
+
Input values to be normalized.
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
np.ndarray
|
|
128
|
+
Normalized values in the range [0, 1].
|
|
129
|
+
|
|
130
|
+
Raises
|
|
131
|
+
------
|
|
132
|
+
ValueError
|
|
133
|
+
If the threshold direction is not recognized.
|
|
134
|
+
"""
|
|
135
|
+
lb = float(self.transition_lower_bound)
|
|
136
|
+
ub = float(self.transition_upper_bound)
|
|
137
|
+
direction = self.threshold
|
|
138
|
+
transition_range = ub - lb
|
|
139
|
+
if direction == "low cut":
|
|
140
|
+
return np.clip((values - lb) / transition_range, 0, 1)
|
|
141
|
+
elif direction == "high cut":
|
|
142
|
+
return 1 - np.clip((values - lb) / transition_range, 0, 1)
|
|
143
|
+
else:
|
|
144
|
+
raise ValueError(f"Unknown threshold direction: {direction}")
|
|
145
|
+
|
|
146
|
+
def evaluate(self, values):
|
|
147
|
+
x = self._normalize(values)
|
|
148
|
+
taper = self.half_window_style
|
|
149
|
+
if taper == "rectangle":
|
|
150
|
+
if self.threshold == "low cut":
|
|
151
|
+
return np.where(values < self.transition_lower_bound, 0.0, 1.0)
|
|
152
|
+
else:
|
|
153
|
+
return np.where(values > self.transition_upper_bound, 0.0, 1.0)
|
|
154
|
+
elif taper == "hann":
|
|
155
|
+
return 0.5 * (1 - np.cos(np.pi * x))
|
|
156
|
+
elif taper == "hamming":
|
|
157
|
+
return 0.54 - 0.46 * np.cos(np.pi * x)
|
|
158
|
+
elif taper == "blackman":
|
|
159
|
+
return 0.42 - 0.5 * np.cos(np.pi * x) + 0.08 * np.cos(2 * np.pi * x)
|
|
160
|
+
else:
|
|
161
|
+
raise ValueError(f"Unsupported taper style: {taper}")
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class ActivationMonotonicWeightKernel(MonotonicWeightKernel):
|
|
165
|
+
"""
|
|
166
|
+
Handles activation styles: sigmoid, hard_sigmoid, tanh, hard_tanh.
|
|
167
|
+
|
|
168
|
+
TODO: Add more testing - this is an experimental class.
|
|
169
|
+
|
|
170
|
+
"""
|
|
171
|
+
__doc__ = write_lines(activation_attr_dict)
|
|
172
|
+
|
|
173
|
+
def __init__(self, steepness: float = 10, **kwargs):
|
|
174
|
+
kwargs.pop("attr_dict", None) # Remove if present
|
|
175
|
+
super().__init__(attr_dict=activation_attr_dict, **kwargs)
|
|
176
|
+
self.weight_type = "activation_monotonic"
|
|
177
|
+
self.steepness = steepness
|
|
178
|
+
|
|
179
|
+
def _normalize(self, values):
|
|
180
|
+
"""
|
|
181
|
+
Normalize input values to the [0, 1] interval for activation kernels, supporting infinite bounds and respecting threshold direction.
|
|
182
|
+
|
|
183
|
+
For finite bounds, applies linear normalization and reverses for 'high cut'.
|
|
184
|
+
For infinite bounds, subclasses should define behavior, but this implementation will map all values to 0.5.
|
|
185
|
+
"""
|
|
186
|
+
lb = float(self.transition_lower_bound)
|
|
187
|
+
ub = float(self.transition_upper_bound)
|
|
188
|
+
values = np.asarray(values)
|
|
189
|
+
direction = getattr(self, 'threshold', 'low cut')
|
|
190
|
+
# Both bounds finite
|
|
191
|
+
if np.isfinite(lb) and np.isfinite(ub):
|
|
192
|
+
x = (values - lb) / (ub - lb)
|
|
193
|
+
if direction == 'high cut':
|
|
194
|
+
x = 1 - x
|
|
195
|
+
return np.clip(x, 0, 1)
|
|
196
|
+
# Infinite bounds: fallback (could be extended for custom behavior)
|
|
197
|
+
msg = "ActivationMonotonicWeightKernel only supports finite transition bounds. "
|
|
198
|
+
self.logger.warning(msg + "Returning 0.5 for all values.")
|
|
199
|
+
return np.full_like(values, 0.5)
|
|
200
|
+
|
|
201
|
+
def evaluate(self, values):
|
|
202
|
+
|
|
203
|
+
x = self._normalize(values)
|
|
204
|
+
activation_style = self.activation_style
|
|
205
|
+
|
|
206
|
+
if activation_style == "sigmoid":
|
|
207
|
+
y = 1 / (1 + np.exp(-float(self.steepness) * (x - 0.5)))
|
|
208
|
+
elif activation_style == "hard_sigmoid":
|
|
209
|
+
y = np.clip(0.2 * (x - 0.5) + 0.5, 0, 1)
|
|
210
|
+
elif activation_style == "tanh":
|
|
211
|
+
y = 0.5 * (np.tanh(float(self.steepness) * (x - 0.5)) + 1)
|
|
212
|
+
elif activation_style == "hard_tanh":
|
|
213
|
+
y = np.clip(x, 0, 1)
|
|
214
|
+
else:
|
|
215
|
+
raise ValueError(f"Unsupported activation style: {activation_style}")
|
|
216
|
+
|
|
217
|
+
return y
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class ThresholdWeightKernel(TaperMonotonicWeightKernel):
|
|
221
|
+
"""
|
|
222
|
+
ThresholdWeightKernel
|
|
223
|
+
|
|
224
|
+
A special case of MonotonicWeightKernel where the transition region is a single value,
|
|
225
|
+
resulting in a hard threshold (step function). This kernel outputs 0 or 1 depending on
|
|
226
|
+
whether the input is above or below the threshold, according to the threshold_type.
|
|
227
|
+
|
|
228
|
+
Parameters
|
|
229
|
+
----------
|
|
230
|
+
threshold : float
|
|
231
|
+
The threshold value.
|
|
232
|
+
threshold_type : str, optional
|
|
233
|
+
"low cut" (default) or "high cut". Determines which side is downweighted.
|
|
234
|
+
**kwargs :
|
|
235
|
+
Additional keyword arguments passed to MonotonicWeightKernel.
|
|
236
|
+
"""
|
|
237
|
+
def __init__(self, threshold, threshold_type="low cut", **kwargs):
|
|
238
|
+
super().__init__(
|
|
239
|
+
transition_lower_bound=threshold,
|
|
240
|
+
transition_upper_bound=threshold,
|
|
241
|
+
half_window_style="rectangle",
|
|
242
|
+
threshold=threshold_type,
|
|
243
|
+
**kwargs
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
# TODO: Uncomment if needed for testing or future use
|
|
248
|
+
# def _normalize(self, values):
|
|
249
|
+
# """
|
|
250
|
+
# Normalize input values to the [0, 1] interval, supporting infinite bounds for activation and taper kernels.
|
|
251
|
+
# Handles all combinations of finite and infinite transition bounds:
|
|
252
|
+
# - Both bounds finite: linear normalization.
|
|
253
|
+
# - Lower bound -inf, upper bound finite: exponential normalization.
|
|
254
|
+
# - Lower bound finite, upper bound +inf: exponential normalization.
|
|
255
|
+
# - Both bounds infinite: all values map to 0.5.
|
|
256
|
+
# """
|
|
257
|
+
# lb = float(self.transition_lower_bound)
|
|
258
|
+
# ub = float(self.transition_upper_bound)
|
|
259
|
+
# values = np.asarray(values)
|
|
260
|
+
# # Both bounds finite
|
|
261
|
+
# if np.isfinite(lb) and np.isfinite(ub):
|
|
262
|
+
# return np.clip((values - lb) / (ub - lb), 0, 1)
|
|
263
|
+
# # Lower bound -inf, upper bound finite
|
|
264
|
+
# elif not np.isfinite(lb) and np.isfinite(ub):
|
|
265
|
+
# scale = np.std(values) if np.std(values) > 0 else 1.0
|
|
266
|
+
# x = 1 - np.exp(-(ub - values) / scale)
|
|
267
|
+
# return np.clip(x, 0, 1)
|
|
268
|
+
# # Lower bound finite, upper bound +inf
|
|
269
|
+
# elif np.isfinite(lb) and not np.isfinite(ub):
|
|
270
|
+
# scale = np.std(values) if np.std(values) > 0 else 1.0
|
|
271
|
+
# x = 1 - np.exp(-(values - lb) / scale)
|
|
272
|
+
# return np.clip(x, 0, 1)
|
|
273
|
+
# # Both bounds infinite
|
|
274
|
+
# else:
|
|
275
|
+
# return np.full_like(values, 0.5)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"threshold": {
|
|
3
|
+
"type": "string",
|
|
4
|
+
"required": true,
|
|
5
|
+
"style": "controlled vocabulary",
|
|
6
|
+
"units": null,
|
|
7
|
+
"description": "Which side of a threshold should be downweighted.",
|
|
8
|
+
"options": ["low cut", "high cut"],
|
|
9
|
+
"alias": [],
|
|
10
|
+
"example": "low cut",
|
|
11
|
+
"default":"low cut"
|
|
12
|
+
},
|
|
13
|
+
"activation_style": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"required": true,
|
|
16
|
+
"style": "controlled vocabulary",
|
|
17
|
+
"units": null,
|
|
18
|
+
"description": "Tapering/activation function to use between transition bounds.",
|
|
19
|
+
"options": [
|
|
20
|
+
"sigmoid", "hard_sigmoid", "tanh", "hard_tanh"
|
|
21
|
+
],
|
|
22
|
+
"alias": [],
|
|
23
|
+
"example": "tanh",
|
|
24
|
+
"default": "sigmoid"
|
|
25
|
+
},
|
|
26
|
+
"steepness": {
|
|
27
|
+
"type": "float",
|
|
28
|
+
"required": false,
|
|
29
|
+
"style": "number",
|
|
30
|
+
"units": null,
|
|
31
|
+
"options": [],
|
|
32
|
+
"alias": [],
|
|
33
|
+
"example": "10",
|
|
34
|
+
"default": 10,
|
|
35
|
+
"description": "Controls the sharpness of the activation transition."
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"weight_type": {
|
|
3
|
+
"type": "string",
|
|
4
|
+
"required": true,
|
|
5
|
+
"style": "controlled vocabulary",
|
|
6
|
+
"units": null,
|
|
7
|
+
"description": "Type of weighting kernel (e.g., monotonic, learned, spatial).",
|
|
8
|
+
"options": ["monotonic", "learned", "spatial", "custom"],
|
|
9
|
+
"alias": [],
|
|
10
|
+
"example": "monotonic",
|
|
11
|
+
"default": "monotonic"
|
|
12
|
+
},
|
|
13
|
+
"description": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"required": false,
|
|
16
|
+
"style": "free form",
|
|
17
|
+
"units": null,
|
|
18
|
+
"description": "Human-readable description of what this kernel is for.",
|
|
19
|
+
"options": [],
|
|
20
|
+
"alias": [],
|
|
21
|
+
"example": "This kernel smoothly transitions between 0 and 1 in a monotonic way",
|
|
22
|
+
"default": ""
|
|
23
|
+
},
|
|
24
|
+
"active": {
|
|
25
|
+
"type": "boolean",
|
|
26
|
+
"required": false,
|
|
27
|
+
"style": "free form",
|
|
28
|
+
"units": null,
|
|
29
|
+
"description": "If false, this kernel will be skipped during weighting.",
|
|
30
|
+
"options": [],
|
|
31
|
+
"alias": [],
|
|
32
|
+
"example": "false",
|
|
33
|
+
"default": true
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"combination_style": {
|
|
3
|
+
"type": "string",
|
|
4
|
+
"required": true,
|
|
5
|
+
"style": "controlled vocabulary",
|
|
6
|
+
"units": null,
|
|
7
|
+
"description": "How to combine multiple feature weights.",
|
|
8
|
+
"options": ["multiplication", "minimum", "maximum", "mean"],
|
|
9
|
+
"alias": [],
|
|
10
|
+
"example": "multiplication",
|
|
11
|
+
"default": "multiplication"
|
|
12
|
+
},
|
|
13
|
+
"output_channels": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"required": true,
|
|
16
|
+
"style": "name list",
|
|
17
|
+
"units": null,
|
|
18
|
+
"description": "list of tf ouput channels for which this weighting scheme will be applied",
|
|
19
|
+
"options": [],
|
|
20
|
+
"alias": [],
|
|
21
|
+
"example": "[ ex ey hz ]",
|
|
22
|
+
"default": []
|
|
23
|
+
},
|
|
24
|
+
"feature_weight_specs": {
|
|
25
|
+
"type": "integer",
|
|
26
|
+
"required": true,
|
|
27
|
+
"style": "number list",
|
|
28
|
+
"units": null,
|
|
29
|
+
"description": "List of feature weighting schemes to use for TF processing.",
|
|
30
|
+
"options": [],
|
|
31
|
+
"alias": [],
|
|
32
|
+
"example": "[]",
|
|
33
|
+
"default": null
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"composition_method": {
|
|
3
|
+
"type": "string",
|
|
4
|
+
"required": true,
|
|
5
|
+
"style": "controlled vocabulary",
|
|
6
|
+
"units": null,
|
|
7
|
+
"description": "How to combine sub-kernels.",
|
|
8
|
+
"options": ["sum", "product", "min", "max", "custom"],
|
|
9
|
+
"alias": [],
|
|
10
|
+
"example": "sum",
|
|
11
|
+
"default": "product"
|
|
12
|
+
},
|
|
13
|
+
"kernels": {
|
|
14
|
+
"type": "list",
|
|
15
|
+
"required": true,
|
|
16
|
+
"style": "object list",
|
|
17
|
+
"units": null,
|
|
18
|
+
"description": "List of weight kernel instances (referenced or inline).",
|
|
19
|
+
"options": [],
|
|
20
|
+
"alias": [],
|
|
21
|
+
"example":[],
|
|
22
|
+
"default": []
|
|
23
|
+
},
|
|
24
|
+
"normalize_output": {
|
|
25
|
+
"type": "boolean",
|
|
26
|
+
"required": false,
|
|
27
|
+
"style": "boolean",
|
|
28
|
+
"units": null,
|
|
29
|
+
"description": "Whether to rescale combined weight back to [0,1].",
|
|
30
|
+
"options": [],
|
|
31
|
+
"alias": [],
|
|
32
|
+
"example": false,
|
|
33
|
+
"default": true
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"feature_name": {
|
|
3
|
+
"type": "string",
|
|
4
|
+
"required": true,
|
|
5
|
+
"style": "controlled vocabulary",
|
|
6
|
+
"units": null,
|
|
7
|
+
"description": "The name of the feature to evaluate (e.g., coherence, impedance_ratio).",
|
|
8
|
+
"options": ["coherence", "multiple coherence"],
|
|
9
|
+
"alias": [],
|
|
10
|
+
"example": "coherence",
|
|
11
|
+
"default": ""
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"threshold": {
|
|
3
|
+
"type": "string",
|
|
4
|
+
"required": true,
|
|
5
|
+
"style": "controlled vocabulary",
|
|
6
|
+
"units": null,
|
|
7
|
+
"description": "Which side of a threshold should be downweighted.",
|
|
8
|
+
"options": ["low cut", "high cut"],
|
|
9
|
+
"alias": [],
|
|
10
|
+
"example": "low cut",
|
|
11
|
+
"default":"low cut"
|
|
12
|
+
},
|
|
13
|
+
"style": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"required": true,
|
|
16
|
+
"style": "controlled vocabulary",
|
|
17
|
+
"units": null,
|
|
18
|
+
"description": "Tapering/activation function to use between transition bounds.",
|
|
19
|
+
"options": [
|
|
20
|
+
"taper", "activation"
|
|
21
|
+
],
|
|
22
|
+
"alias": [],
|
|
23
|
+
"example": "activation",
|
|
24
|
+
"default": "taper"
|
|
25
|
+
},
|
|
26
|
+
"transition_lower_bound": {
|
|
27
|
+
"type": "float",
|
|
28
|
+
"required": true,
|
|
29
|
+
"style": "number",
|
|
30
|
+
"units": null,
|
|
31
|
+
"description": "Start of the taper region (weight begins to change).",
|
|
32
|
+
"options": [],
|
|
33
|
+
"alias": [],
|
|
34
|
+
"example": "-inf",
|
|
35
|
+
"default": -1e9
|
|
36
|
+
},
|
|
37
|
+
"transition_upper_bound": {
|
|
38
|
+
"type": "float",
|
|
39
|
+
"required": true,
|
|
40
|
+
"style": "number",
|
|
41
|
+
"units": null,
|
|
42
|
+
"description": "End of the taper region (weight finishes changing).",
|
|
43
|
+
"options": [],
|
|
44
|
+
"alias": [],
|
|
45
|
+
"example": "+inf",
|
|
46
|
+
"default": 1e9
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"half_window_style": {
|
|
3
|
+
"type": "string",
|
|
4
|
+
"required": true,
|
|
5
|
+
"style": "controlled vocabulary",
|
|
6
|
+
"units": null,
|
|
7
|
+
"description": "Tapering/activation function to use between transition bounds.",
|
|
8
|
+
"options": [
|
|
9
|
+
"hamming", "hann", "rectangle", "blackman"
|
|
10
|
+
],
|
|
11
|
+
"alias": [],
|
|
12
|
+
"example": "hann",
|
|
13
|
+
"default": "rectangle"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module with a compound kernel, mixing multiple monotonic kernels.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from .monotonic_weight_kernel import TaperMonotonicWeightKernel
|
|
7
|
+
from .base import BaseWeightKernel
|
|
8
|
+
from typing import Tuple
|
|
9
|
+
|
|
10
|
+
class TaperWeightKernel(BaseWeightKernel):
|
|
11
|
+
"""
|
|
12
|
+
A composite weight kernel that multiplies a low-cut and a high-cut monotonic taper kernel.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
low_cut : tuple[float, float]
|
|
17
|
+
(lower_bound, upper_bound) for the low-cut transition region.
|
|
18
|
+
high_cut : tuple[float, float]
|
|
19
|
+
(lower_bound, upper_bound) for the high-cut transition region.
|
|
20
|
+
style : str, optional
|
|
21
|
+
The taper style to use (default is 'hann').
|
|
22
|
+
**kwargs
|
|
23
|
+
Additional keyword arguments passed to BaseWeightKernel.
|
|
24
|
+
"""
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
low_cut: Tuple[float, float],
|
|
28
|
+
high_cut: Tuple[float, float],
|
|
29
|
+
style: str = "hann",
|
|
30
|
+
**kwargs
|
|
31
|
+
):
|
|
32
|
+
super().__init__(**kwargs)
|
|
33
|
+
self._low_kernel = TaperMonotonicWeightKernel(
|
|
34
|
+
threshold="low cut",
|
|
35
|
+
transition_lower_bound=low_cut[0],
|
|
36
|
+
transition_upper_bound=low_cut[1],
|
|
37
|
+
half_window_style=style
|
|
38
|
+
)
|
|
39
|
+
self._high_kernel = TaperMonotonicWeightKernel(
|
|
40
|
+
threshold="high cut",
|
|
41
|
+
transition_lower_bound=high_cut[0],
|
|
42
|
+
transition_upper_bound=high_cut[1],
|
|
43
|
+
half_window_style=style
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def evaluate(self, values: np.ndarray) -> np.ndarray:
|
|
47
|
+
"""
|
|
48
|
+
Evaluate the composite taper weight kernel on the input values.
|
|
49
|
+
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
values : np.ndarray
|
|
53
|
+
Input values to evaluate the kernel on.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
np.ndarray
|
|
58
|
+
The product of the low-cut and high-cut kernel evaluations.
|
|
59
|
+
"""
|
|
60
|
+
return self._low_kernel.evaluate(values) * self._high_kernel.evaluate(values)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module has some general helper functions that it isn't yet clear where they should live.
|
|
3
|
+
|
|
4
|
+
These may not be needed at all after the pydantic upgrade is fully integrated.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Dict, List, Union
|
|
8
|
+
from mt_metadata.base import Base
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
Here are some rather abstract functions for generalizing setters of lists,
|
|
13
|
+
whose elements are particular mt_metadata classes.
|
|
14
|
+
Example usage is decimation_level.bands
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def validate_setter_input(value: Union[Dict, Base], expected_class: Base) -> List:
|
|
19
|
+
"""
|
|
20
|
+
Takes a setter's input and makes it a list if it not.
|
|
21
|
+
Then asserts that every list element is of permissible type (dict or expected class)
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
value: Union[Dict, Base]
|
|
26
|
+
The input to the setter.
|
|
27
|
+
|
|
28
|
+
expected_class: Base
|
|
29
|
+
Some mt_metadata class that we want the setter work with
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
value: list
|
|
34
|
+
List of elements for the setter all of type expected_class or dict.
|
|
35
|
+
"""
|
|
36
|
+
# Handle singleton cases
|
|
37
|
+
if isinstance(value, (expected_class, dict)):
|
|
38
|
+
value = [value, ]
|
|
39
|
+
|
|
40
|
+
if not isinstance(value, list):
|
|
41
|
+
raise TypeError(f"Not sure what to do with {type(value)}")
|
|
42
|
+
|
|
43
|
+
return value
|
|
44
|
+
|
|
45
|
+
def cast_to_class_if_dict(obj: Union[Dict, Base], cls: Base ) -> Base:
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
obj: Union[Dict, Base]
|
|
51
|
+
Either an mt_metadata object or its dict representaiton
|
|
52
|
+
cls: Base
|
|
53
|
+
Some mt_metadata object that we want to get back
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
either the input or the input dict cast to an mt_metadata object.
|
|
58
|
+
"""
|
|
59
|
+
if not isinstance(obj, (cls, dict)):
|
|
60
|
+
raise TypeError(
|
|
61
|
+
f"List entry must be a {cls().__class__} object not {type(obj)}"
|
|
62
|
+
)
|
|
63
|
+
if isinstance(obj, dict):
|
|
64
|
+
mt_metadata_obj = cls()
|
|
65
|
+
mt_metadata_obj.from_dict(obj)
|
|
66
|
+
else:
|
|
67
|
+
mt_metadata_obj = obj
|
|
68
|
+
|
|
69
|
+
return mt_metadata_obj
|