3#include "mspass/algorithms/TimeWindow.h"
4#include "mspass/algorithms/algorithms.h"
5#include "mspass/seismic/Ensemble.h"
6#include "mspass/seismic/PowerSpectrum.h"
7#include "mspass/seismic/Seismogram.h"
8#include "mspass/seismic/TimeSeries.h"
9#include "mspass/utility/Metadata.h"
10#include "mspass/utility/MsPASSError.h"
11#include "mspass/utility/VectorStatistics.h"
13namespace mspass::algorithms::amplitudes {
24enum class ScalingMethod {
30const std::string scale_factor_key(
"calib");
56template <
typename Tdata>
57double scale(Tdata &d,
const ScalingMethod method,
const double level,
59 if ((method == ScalingMethod::ClipPerc) && (level <= 0.0 || level > 1.0))
61 "scale function: illegal perf level specified for clip percentage "
62 "scale - must be between 0 and 1\nData unaltered - may cause "
63 "downstream problems",
64 mspass::utility::ErrorSeverity::Suspect);
70 if (d.is_defined(scale_factor_key)) {
71 newcalib = d.get_double(scale_factor_key);
78 ampwindow.
start = d.t0();
79 ampwindow.
end = d.endtime();
80 }
else if ((fabs(win.
start - d.t0()) / d.dt() > 0.5) ||
81 (fabs(win.
end - d.endtime()) / d.dt() > 0.5)) {
83 ss <<
"Window time range is inconsistent with input data range"
85 <<
"Input data starttime=" << d.t0()
86 <<
" and window start time=" << win.
start
87 <<
" Difference=" << d.t0() - win.
start << std::endl
88 <<
"Input data endtime=" << d.endtime()
89 <<
" and window end time=" << win.
end
90 <<
" Difference=" << d.endtime() - win.
end << std::endl
91 <<
"One or the other exceeds 1/sample interval=" << d.dt() << std::endl
92 <<
"Window for amplitude calculation changed to data range";
93 d.elog.log_error(
"scale", ss.str(),
94 mspass::utility::ErrorSeverity::Complaint);
95 ampwindow.
start = d.t0();
96 ampwindow.
end = d.endtime();
101 windowed_data = mspass::algorithms::WindowData(d, ampwindow);
102 double amplitude, dscale;
104 case ScalingMethod::Peak:
105 amplitude = PeakAmplitude(windowed_data);
107 case ScalingMethod::ClipPerc:
108 amplitude = PercAmplitude(windowed_data, level);
110 case ScalingMethod::MAD:
111 amplitude = MADAmplitude(windowed_data);
113 case ScalingMethod::RMS:
115 amplitude = RMSAmplitude(windowed_data);
118 if (amplitude > 0.0) {
119 dscale = level / amplitude;
122 d.put(scale_factor_key, newcalib);
124 std::stringstream ss;
125 ss <<
"Data array is all 0s and cannot be scaled";
126 d.elog.log_error(
"scale", ss.str(),
127 mspass::utility::ErrorSeverity::Complaint);
130 d.put(scale_factor_key, newcalib);
161template <
typename Tdata>
164 const ScalingMethod &method,
const double level,
166 if ((method == ScalingMethod::ClipPerc) && (level <= 0.0 || level > 1.0))
168 "scale_ensemble_members function: illegal perf level specified for "
169 "clip percentage scale - must be between 0 and 1\nData unaltered - may "
170 "cause downstream problems",
171 mspass::utility::ErrorSeverity::Suspect);
173 typename std::vector<Tdata>::iterator dptr;
174 std::vector<double> amps;
175 amps.reserve(d.
member.size());
176 for (dptr = d.
member.begin(); dptr != d.
member.end(); ++dptr) {
178 thisamp = scale(*dptr, method, level, win);
179 amps.push_back(thisamp);
206template <
typename Tdata>
208 const ScalingMethod &method,
const double level,
209 const bool use_mean) {
210 if ((method == ScalingMethod::ClipPerc) && (level <= 0.0 || level > 1.0))
212 "scale_ensemble function: illegal perf level specified for clip "
213 "percentage scale - must be between 0 and 1\nData unaltered - may "
214 "cause downstream problems",
215 mspass::utility::ErrorSeverity::Suspect);
219 typename std::vector<Tdata>::iterator dptr;
220 std::vector<double> amps;
221 amps.reserve(d.
member.size());
223 for (dptr = d.
member.begin(); dptr != d.
member.end(); ++dptr) {
228 case ScalingMethod::Peak:
229 amplitude = PeakAmplitude(*dptr);
231 case ScalingMethod::ClipPerc:
232 amplitude = PercAmplitude(*dptr, level);
234 case ScalingMethod::MAD:
235 amplitude = MADAmplitude(*dptr);
237 case ScalingMethod::RMS:
239 amplitude = RMSAmplitude(*dptr);
242 amps.push_back(log(amplitude));
249 avgamp = ampstats.mean();
251 avgamp = ampstats.median();
255 avgamp = exp(avgamp);
261 double dscale = level / avgamp;
263 for (dptr = d.
member.begin(); dptr != d.
member.end(); ++dptr) {
267 if (dptr->is_defined(scale_factor_key)) {
268 calib = dptr->get_double(scale_factor_key);
273 dptr->put(scale_factor_key, calib);
282template <
class T> std::vector<T> normalize(
const std::vector<T> &d) {
284 std::vector<T> result;
288 for (
size_t i = 0; i < N; ++i) {
289 d_nrm += (d[i] * d[i]);
290 result.push_back(d[i]);
293 for (
size_t i = 0; i < N; ++i)
339 return 20.0 * log10(ratio);
403 const double snr_threshold,
const double tbp,
404 const double fhs = -1.0,
405 const bool fix_high_edge_to_fhs =
false);
Defines a time window.
Definition TimeWindow.h:12
double start
Definition TimeWindow.h:17
double end
Definition TimeWindow.h:21
Holds parameters defining a passband computed from snr.
Definition amplitudes.h:306
double low_edge_f
Definition amplitudes.h:309
double bandwidth() const
Definition amplitudes.h:334
double bandwidth_fraction() const
Definition amplitudes.h:327
double high_edge_f
Definition amplitudes.h:311
double low_edge_snr
Definition amplitudes.h:313
double high_edge_snr
Definition amplitudes.h:315
Vector (three-component) seismogram data object.
Definition CoreSeismogram.h:39
Scalar time series data object.
Definition CoreTimeSeries.h:17
std::vector< Tdata > member
Container holding data objects.
Definition Ensemble.h:20
Definition PowerSpectrum.h:11
Base class for error object thrown by MsPASS library routines.
Definition MsPASSError.h:38
Generic object to compute common robust statistics from a vector container of data.
Definition VectorStatistics.h:16