You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
464 lines
16 KiB
C++
464 lines
16 KiB
C++
/***************************************************************************
|
|
* Copyright (C) gempa GmbH *
|
|
* All rights reserved. *
|
|
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
|
* *
|
|
* GNU Affero General Public License Usage *
|
|
* This file may be used under the terms of the GNU Affero *
|
|
* Public License version 3.0 as published by the Free Software Foundation *
|
|
* and appearing in the file LICENSE included in the packaging of this *
|
|
* file. Please review the following information to ensure the GNU Affero *
|
|
* Public License version 3.0 requirements will be met: *
|
|
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
|
* *
|
|
* Other Usage *
|
|
* Alternatively, this file may be used in accordance with the terms and *
|
|
* conditions contained in a signed written agreement between you and *
|
|
* gempa GmbH. *
|
|
***************************************************************************/
|
|
|
|
|
|
#ifndef SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_H
|
|
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_H
|
|
|
|
|
|
#include <seiscomp/core/interfacefactory.h>
|
|
#include <seiscomp/processing/timewindowprocessor.h>
|
|
#include <seiscomp/math/filter/seismometers.h>
|
|
#include <seiscomp/datamodel/origin.h>
|
|
#include <seiscomp/datamodel/sensorlocation.h>
|
|
#include <seiscomp/client.h>
|
|
#include <boost/function.hpp>
|
|
|
|
|
|
namespace Seiscomp {
|
|
|
|
namespace Geo {
|
|
|
|
class GeoFeature;
|
|
|
|
}
|
|
|
|
namespace Processing {
|
|
|
|
|
|
DEFINE_SMARTPOINTER(AmplitudeProcessor);
|
|
|
|
class SC_SYSTEM_CLIENT_API AmplitudeProcessor : public TimeWindowProcessor {
|
|
DECLARE_SC_CLASS(AmplitudeProcessor)
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Public types
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
//! Amplitude calculation capabilities
|
|
enum Capability {
|
|
//! No supported capabilities
|
|
NoCapability = 0x0000,
|
|
//! Supports different amplitude measure types
|
|
MeasureType = 0x0001,
|
|
//! Supports different amplitude combiner if
|
|
//! the amplitude is measured on different
|
|
//! components
|
|
Combiner = 0x0002,
|
|
CapQuantity
|
|
};
|
|
|
|
//! Configuration structure to store processing dependent
|
|
//! settings
|
|
struct Config {
|
|
double noiseBegin; /* default: -35 */
|
|
double noiseEnd; /* default: -5 */
|
|
double signalBegin; /* default: -5 */
|
|
double signalEnd; /* default: 30 */
|
|
double snrMin; /* default: 3 */
|
|
|
|
double minimumDistance; /* default: 0 */
|
|
double maximumDistance; /* default: 180 */
|
|
double minimumDepth; /* default: 0 */
|
|
double maximumDepth; /* default: 700 */
|
|
|
|
double respTaper;
|
|
double respMinFreq;
|
|
double respMaxFreq;
|
|
|
|
Math::SeismometerResponse::WoodAnderson::Config woodAndersonResponse;
|
|
};
|
|
|
|
struct Locale : Config {
|
|
enum Check {
|
|
Source,
|
|
SourceReceiver,
|
|
SourceReceiverPath
|
|
};
|
|
|
|
std::string name;
|
|
const Geo::GeoFeature *feature;
|
|
Check check;
|
|
Core::BaseObjectPtr extra;
|
|
};
|
|
|
|
struct Environment {
|
|
Environment();
|
|
|
|
const DataModel::Origin *hypocenter;
|
|
const DataModel::SensorLocation *receiver;
|
|
const DataModel::Pick *pick;
|
|
const Locale *locale;
|
|
};
|
|
|
|
struct AmplitudeIndex {
|
|
double index;
|
|
double begin;
|
|
double end;
|
|
};
|
|
|
|
struct AmplitudeTime {
|
|
AmplitudeTime() : begin(0), end(0) {}
|
|
AmplitudeTime(const Core::Time &ref)
|
|
: reference(ref), begin(0), end(0) {}
|
|
Core::Time reference;
|
|
double begin;
|
|
double end;
|
|
};
|
|
|
|
struct AmplitudeValue {
|
|
double value;
|
|
OPT(double) lowerUncertainty;
|
|
OPT(double) upperUncertainty;
|
|
};
|
|
|
|
struct Result {
|
|
StreamComponent component;
|
|
const Record *record;
|
|
AmplitudeValue amplitude;
|
|
AmplitudeTime time;
|
|
double period;
|
|
double snr;
|
|
};
|
|
|
|
typedef std::vector<std::string> IDList;
|
|
|
|
typedef boost::function<void (const AmplitudeProcessor*,
|
|
const Result &)> PublishFunc;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// X'truction
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
//! C'tor
|
|
AmplitudeProcessor();
|
|
AmplitudeProcessor(const std::string &type);
|
|
AmplitudeProcessor(const Core::Time &trigger);
|
|
AmplitudeProcessor(const Core::Time &trigger, const std::string &type);
|
|
|
|
//! D'tor
|
|
~AmplitudeProcessor();
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Configuration Interface
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
//! Set the start of the noise window relative to the trigger
|
|
void setNoiseStart(double start) { _config.noiseBegin = start; }
|
|
|
|
//! Set the end of the noise window relative to the trigger
|
|
void setNoiseEnd(double end) { _config.noiseEnd = end; }
|
|
|
|
//! Set the start of the signal window relative to the trigger
|
|
void setSignalStart(double start) { _config.signalBegin = start; }
|
|
|
|
//! Set the end of the signal window relative to the trigger
|
|
void setSignalEnd(double end) { _config.signalEnd = end; }
|
|
|
|
void setMinSNR(double snr) { _config.snrMin = snr; }
|
|
|
|
//! Sets the minimum distance to calculate amplitudes for
|
|
void setMinDist(double dist) { _config.minimumDistance = dist; }
|
|
|
|
//! Sets the maximum distance to calculate amplitudes for
|
|
void setMaxDist(double dist) { _config.maximumDistance = dist; }
|
|
|
|
//! Sets the minimum depth to calculate amplitudes for
|
|
void setMinDepth(double depth) { _config.minimumDepth = depth; }
|
|
|
|
//! Sets the maximum depth to calculate amplitudes for
|
|
void setMaxDepth(double depth) { _config.maximumDepth = depth; }
|
|
|
|
//! Sets a configuration
|
|
void setConfig(const Config &config) { _config = config; }
|
|
|
|
//! Returns the current configuration
|
|
const Config &config() const { return _config; }
|
|
|
|
/**
|
|
* @brief Sets the environment for the amplitude processor. Basically
|
|
* it is the hypocenter, the receiver and the pick made. The
|
|
* pick time must correspond to the trigger time set.
|
|
* This method was added with API 12.
|
|
* @param hypocenter The hypocenter
|
|
* @param receiver The receiver
|
|
* @param pick The pick
|
|
*/
|
|
virtual void setEnvironment(const DataModel::Origin *hypocenter,
|
|
const DataModel::SensorLocation *receiver,
|
|
const DataModel::Pick *pick);
|
|
|
|
const Environment &environment() const { return _environment; }
|
|
|
|
//! Sets whether amplitude updates are enabled or not
|
|
void setUpdateEnabled(bool);
|
|
bool isUpdateEnabled() const;
|
|
|
|
void setReferencingPickID(const std::string&);
|
|
const std::string& referencingPickID() const;
|
|
|
|
void setPick(const DataModel::Pick *pick);
|
|
const DataModel::Pick *pick() const;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Query interface
|
|
// This interface is important to be implemented for interactive
|
|
// analysis.
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
//! Returns a child processor for a specific component. The
|
|
//! returned pointer must not be deleted. The default
|
|
//! implementation returns 'this' if comp matched the usedComponent.
|
|
virtual const AmplitudeProcessor *componentProcessor(Component comp) const;
|
|
|
|
//! Returns the internally processed data which is used to
|
|
//! measure the amplitude.
|
|
//! The default implementation returns
|
|
//! TimeWindowProcessor::continuousData.
|
|
//! The returned pointer must not be managed by a smartpointer or
|
|
//! deleted. It points to a static member of this class.
|
|
virtual const DoubleArray *processedData(Component comp) const;
|
|
|
|
//! Returns the implementations capabilities
|
|
//! The default implementation returns NoCapability (0)
|
|
virtual int capabilities() const;
|
|
|
|
//! Queries for a capability.
|
|
bool supports(Capability capability) const;
|
|
|
|
//! Returns a list of tokens valid for a certain capability
|
|
//! The default implementation returns an empty list
|
|
virtual IDList capabilityParameters(Capability cap) const;
|
|
|
|
//! Sets a processing parameter. Value must be part of the
|
|
//! list returned by capabilityParameters(cap).
|
|
//! The default implementation returns always false.
|
|
virtual bool setParameter(Capability cap, const std::string &value);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Public Interface
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
virtual bool initLocale(Locale *locale, const Settings &settings);
|
|
|
|
//! Reprocesses the current data chunk and searches for amplitudes
|
|
//! only in the given optional time window relative to trigger time
|
|
//! (if supported by the implementation).
|
|
virtual void reprocess(OPT(double) searchBegin = Core::None,
|
|
OPT(double) searchEnd = Core::None);
|
|
|
|
//! Resets the amplitude processor and deletes all data
|
|
//! and noise amplitudes
|
|
virtual void reset() override;
|
|
|
|
//! This method has to be called when all configuration
|
|
//! settings have been set to calculate the timewindow
|
|
virtual void computeTimeWindow() override;
|
|
|
|
//! Sets up the amplitude processor. By default it reads whether
|
|
//! to use response information or not.
|
|
virtual bool setup(const Settings &settings) override;
|
|
|
|
//! Sets the trigger used to compute the timewindow to calculate
|
|
//! the amplitude
|
|
//! Once a trigger has been set all succeeding calls will fail.
|
|
virtual void setTrigger(const Core::Time& trigger);
|
|
|
|
Core::Time trigger() const;
|
|
|
|
/**
|
|
* @brief Allows to finalize an amplitude object as created by
|
|
* client code.
|
|
*
|
|
* This method will usually be called right before the amplitude will
|
|
* be stored or sent and inside the emit handler. It allows processors
|
|
* to set specific attributes or to add comments.
|
|
* The default implementation does nothing.
|
|
* @param amplitude The amplitude to be finalized
|
|
*/
|
|
virtual void finalizeAmplitude(DataModel::Amplitude *amplitude) const;
|
|
|
|
void setPublishFunction(const PublishFunc &func);
|
|
|
|
//! Returns the computed noise offset
|
|
OPT(double) noiseOffset() const;
|
|
|
|
//! Returns the computed noise amplitude
|
|
OPT(double) noiseAmplitude() const;
|
|
|
|
//! Returns the type of amplitude to be calculated
|
|
const std::string &type() const;
|
|
|
|
//! Returns the unit of amplitude to be calculated
|
|
const std::string& unit() const;
|
|
|
|
void setHint(ProcessingHint hint, double value) override;
|
|
|
|
//! Dumps the record data into an ascii file
|
|
void writeData() const;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Protected Interface
|
|
// ----------------------------------------------------------------------
|
|
protected:
|
|
//! Sets the unit of the computed amplitude.
|
|
void setUnit(const std::string &unit);
|
|
|
|
virtual void process(const Record *record);
|
|
|
|
virtual bool handleGap(Filter *filter, const Core::TimeSpan&,
|
|
double lastSample, double nextSample,
|
|
size_t missingSamples) override;
|
|
|
|
//! Method to prepare the available data just before the noise
|
|
//! and amplitude calculation takes place. This method can be
|
|
//! reimplemented to convert the data into velocity if the input
|
|
//! signal unit is e.g. meter per second squared.
|
|
virtual void prepareData(DoubleArray &data);
|
|
|
|
//! Deconvolve the data using the sensor response. The default
|
|
//! implementation simply calls:
|
|
//! resp->deconvolveFFT(data, _fsamp, 60.0, 0.00833333, 0, numberOfIntegrations)
|
|
//! which corresponds to a period lowpass (freq highpass) filter
|
|
//! of 120 seconds.
|
|
virtual bool deconvolveData(Response *resp, DoubleArray &data,
|
|
int numberOfIntegrations);
|
|
|
|
//! -----------------------------------------------------------------------
|
|
//! Computes the amplitude of data in the range[i1, i2].
|
|
//! -----------------------------------------------------------------------
|
|
//! Input:
|
|
//! -----------------------------------------------------------------------
|
|
//! - data: the waveform data
|
|
//! - offset: the computed noise offset
|
|
//! - i1: start index in data (trigger + config.signalBegin)
|
|
//! - i2: end index in data (trigger + config.signalEnd)
|
|
//! - si1: start index of the amplitude search window
|
|
//! - si2: end index of the amplitude search window
|
|
//! NOTE: si1 and si2 are guaranteed to be in range [i1,i2] if
|
|
//! the default AmplitudeProcessor::process method is called (especially
|
|
//! when reimplemented).
|
|
//! -----------------------------------------------------------------------
|
|
//! Output:
|
|
//! -----------------------------------------------------------------------
|
|
//! - dt: the picked data index (can be a subindex if required)
|
|
//! the dt.begin and dt.end are the begin/end of the timewindow
|
|
//! in samples relativ to the picked index. dt.begin and dt.end
|
|
//! do not need to be in order, they are ordered afterwards
|
|
//! automatically. The default values for begin/end are 0.
|
|
//! - amplitude: the picked amplitude value with optional uncertainties.
|
|
//! - period: the period in samples and not seconds (-1 if not calculated)
|
|
//! - snr: signal-to-noise ratio
|
|
//! -----------------------------------------------------------------------
|
|
virtual bool computeAmplitude(const DoubleArray &data,
|
|
size_t i1, size_t i2,
|
|
size_t si1, size_t si2,
|
|
double offset,
|
|
AmplitudeIndex *dt,
|
|
AmplitudeValue *amplitude,
|
|
double *period, double *snr) = 0;
|
|
|
|
//! Computes the noise of data in the range [i1,i2] and returns the offset and
|
|
//! the amplitude in 'offset' and 'amplitude'
|
|
//! The default implementation takes the median of the data as offset and
|
|
//! twice the rms regarding the offset as amplitude
|
|
virtual bool computeNoise(const DoubleArray &data, int i1, int i2, double *offset, double *amplitude);
|
|
|
|
//! Computes the timewindow length when a distance hint has been set.
|
|
//! The default implementation return _config.signalEnd
|
|
virtual double timeWindowLength(double distance) const;
|
|
|
|
//! This method gets called when an amplitude has to be published
|
|
void emitAmplitude(const Result &result);
|
|
|
|
private:
|
|
bool readLocale(Locale *locale,
|
|
const Settings &settings,
|
|
const std::string &configPrefix);
|
|
|
|
private:
|
|
void init();
|
|
bool initRegionalization(const Settings &settings);
|
|
void process(const Record *record, const DoubleArray &filteredData) override;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Protected Members
|
|
// ----------------------------------------------------------------------
|
|
protected:
|
|
Core::Time _trigger;
|
|
|
|
// User defined amplitude search window
|
|
OPT(double) _searchBegin, _searchEnd;
|
|
|
|
// pre-arrival offset and rms
|
|
OPT(double) _noiseOffset, _noiseAmplitude, _lastAmplitude;
|
|
|
|
double _snrMax, _snrRMS;
|
|
bool _enableUpdates;
|
|
bool _enableResponses;
|
|
|
|
// config
|
|
Config _config;
|
|
Environment _environment;
|
|
|
|
std::string _type;
|
|
std::string _unit;
|
|
|
|
std::string _pickID;
|
|
|
|
bool _responseApplied;
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Private Members
|
|
// ----------------------------------------------------------------------
|
|
private:
|
|
PublishFunc _func;
|
|
};
|
|
|
|
|
|
inline AmplitudeProcessor::Environment::Environment()
|
|
: hypocenter(nullptr), receiver(nullptr), pick(nullptr) {}
|
|
|
|
inline const DataModel::Pick *AmplitudeProcessor::pick() const {
|
|
return _environment.pick;
|
|
}
|
|
|
|
|
|
DEFINE_INTERFACE_FACTORY(AmplitudeProcessor);
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#define REGISTER_AMPLITUDEPROCESSOR_VAR(Class, Service) \
|
|
Seiscomp::Core::Generic::InterfaceFactory<Seiscomp::Processing::AmplitudeProcessor, Class> __##Class##InterfaceFactory__(Service)
|
|
|
|
#define REGISTER_AMPLITUDEPROCESSOR(Class, Service) \
|
|
static REGISTER_AMPLITUDEPROCESSOR_VAR(Class, Service)
|
|
|
|
|
|
#endif
|