[seiscomp, scanloc] Install, add .gitignore

This commit is contained in:
2025-10-09 15:07:02 +02:00
commit 20f5301bb1
2848 changed files with 1315858 additions and 0 deletions

View File

@ -0,0 +1,547 @@
/***************************************************************************
* 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/datamodel/pick.h>
#include <seiscomp/client.h>
#include <functional>
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
};
class SignalTime {
public:
SignalTime() = default;
SignalTime(int v);
SignalTime(double v);
SignalTime(const char *); // throws invalid_argument
SignalTime(const std::string &); // throws invalid_argument
SignalTime(const SignalTime &time);
/**
* @brief Sets the expression to a constant expression.
* @param v The new value for the signal time
* @return this
*/
SignalTime &operator=(double v);
SignalTime &operator=(const SignalTime &time);
/**
* @brief Adds an offset to the signal expression but not to
* the compiled value. This only modifies the expression
* by adding a constant offset.
* @param v The offset value for the signal time
* @return this
*/
SignalTime &operator+=(double v);
/**
* @brief Substracts an offset to the signal expression but not
* to the compiled value. This only modifies the
* expression by substracting a constant offset.
* @param v The offset value for the signal time
* @return this
*/
SignalTime &operator-=(double v);
operator double() const;
/**
* @brief Sets and compiles a statement
* @param error Optional error message if compilation failed.
* @return Success flag
*/
bool set(const std::string &text, std::string *error = nullptr);
std::string toString() const;
bool isValid() const { return _exp != nullptr; }
/**
* @brief Evaluates the expression.
* This method throws a StatusException if the evaluation fails.
* @param proc The source processor
* @param left If the time is the left time of a time window
*/
void evaluate(const AmplitudeProcessor *proc, bool left);
private:
Core::BaseObjectPtr _exp;
OPT(double) _value;
};
//! Configuration structure to store processing dependent
//! settings
struct Config {
// The noise and signal time window expressions. Those
// might depend on origin or travel time information
// and are only evaluated during setEnvironment.
SignalTime noiseBegin;
SignalTime noiseEnd;
SignalTime signalBegin;
SignalTime signalEnd;
std::string ttInterface;
std::string ttModel;
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;
// If true, compute amplitudes according to the recommendations of the
// IASPEI CoSOI Magnitude Working Group. Currently only affects mb.
bool iaspeiAmplitudes;
};
struct Locale : Config {
enum Check {
Source,
SourceReceiver,
SourceReceiverPath
};
std::string name;
const Geo::GeoFeature *feature;
Check check;
Core::BaseObjectPtr extra;
};
struct Environment {
Environment();
std::string networkCode;
std::string stationCode;
std::string locationCode;
std::string channelCode;
const DataModel::Origin *hypocenter{nullptr};
const DataModel::SensorLocation *receiver{nullptr};
const DataModel::Pick *pick{nullptr};
const Locale *locale{nullptr};
};
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;
};
using IDList = std::vector<std::string>;
using PublishFunc = std::function<void (const AmplitudeProcessor*,
const Result &)>;
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
AmplitudeProcessor();
AmplitudeProcessor(const std::string &type);
//! D'tor
~AmplitudeProcessor();
// ----------------------------------------------------------------------
// Configuration Interface
// ----------------------------------------------------------------------
public:
//! Set the start of the noise window relative to the trigger
void setNoiseStart(const SignalTime &start) { _config.noiseBegin = start; }
//! Set the end of the noise window relative to the trigger
void setNoiseEnd(const SignalTime &end) { _config.noiseEnd = end; }
//! Set the start of the signal window relative to the trigger
void setSignalStart(const SignalTime &start) { _config.signalBegin = start; }
//! Set the end of the signal window relative to the trigger
void setSignalEnd(const SignalTime &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 or null
* @param receiver The receiver or null
* @param pick The pick or null
*/
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;
static bool CreateAlias(const std::string &aliasType,
const std::string &sourceType);
static bool RemoveAlias(const std::string &aliasType);
static void RemoveAllAliases();
// ----------------------------------------------------------------------
// 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;
//! 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);
//! 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);
void checkEnvironmentalLimits();
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;
friend class AmplitudeProcessorAliasFactory;
};
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

View File

@ -0,0 +1,79 @@
/***************************************************************************
* 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_ML_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_ML_H
#include <seiscomp/processing/amplitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API AbstractAmplitudeProcessor_ML : public AmplitudeProcessor {
public:
AbstractAmplitudeProcessor_ML(const std::string &type);
public:
void initFilter(double fsamp) override;
int capabilities() const override;
IDList capabilityParameters(Capability cap) const override;
bool setParameter(Capability cap, const std::string &value) override;
bool setup(const Settings &settings) override;
protected:
void setDefaultConfiguration();
bool deconvolveData(Response *resp, DoubleArray &data, int numberOfIntegrations) override;
/**
* Computes the zero-to-peak amplitude on the simulated Wood-Anderson
* trace.
*/
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) override;
protected:
enum AmplitudeMeasureType {
AbsMax,
MinMax,
PeakTrough
};
AmplitudeMeasureType _amplitudeMeasureType;
std::string _preFilter;
bool _applyWA{true};
};
}
}
#endif

View File

@ -0,0 +1,109 @@
/***************************************************************************
* 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_MLc_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_MLc_H
#include <seiscomp/processing/amplitudes/ML.h>
namespace Seiscomp {
namespace Processing {
//! Wrapper class that allows access to protected methods for
//! the proxy (see below).
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_MLc : public AbstractAmplitudeProcessor_ML {
public:
AmplitudeProcessor_MLc();
friend class AmplitudeProcessor_MLc2h;
};
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_MLc2h : public AmplitudeProcessor {
public:
AmplitudeProcessor_MLc2h();
public:
int capabilities() const override;
IDList capabilityParameters(Capability cap) const override;
bool setParameter(Capability cap, const std::string &value) override;
void reset() override;
bool setup(const Settings &settings) override;
void setTrigger(const Core::Time &trigger) override;
void setEnvironment(const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Pick *pick) override;
void computeTimeWindow() override;
void close() const override;
bool feed(const Record *record) override;
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) override;
const AmplitudeProcessor *componentProcessor(Component comp) const override;
const DoubleArray *processedData(Component comp) const override;
void reprocess(OPT(double) searchBegin, OPT(double) searchEnd) override;
private:
void setDefaultConfiguration();
void newAmplitude(const AmplitudeProcessor *proc,
const AmplitudeProcessor::Result &res);
struct ComponentResult {
AmplitudeValue value;
AmplitudeTime time;
double snr;
};
enum CombinerProc {
TakeMax,
TakeMin,
TakeAverage,
TakeGeometricMean
};
mutable AmplitudeProcessor_MLc _ampE, _ampN;
CombinerProc _combiner{TakeMax};
OPT(ComponentResult) _results[2];
double _amplitudeScale{1.0};
};
}
}
#endif

View File

@ -0,0 +1,112 @@
/***************************************************************************
* 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_MLH_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_MLH_H
#include <seiscomp/processing/amplitudes/ML.h>
namespace Seiscomp {
namespace Processing {
//! Wrapper class that allows access to protected methods for
//! the proxy (see below).
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_MLh : public AbstractAmplitudeProcessor_ML {
public:
AmplitudeProcessor_MLh();
friend class AmplitudeProcessor_ML2h;
};
//! Proxy amplitude processor that holds two MLh processors to calculate
//! the amplitudes on both horizontals and then averages the result.
//! This class does not handle waveforms itself. It directs them to the
//! corresponding amplitude processors instead.
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_ML2h : public AmplitudeProcessor {
public:
AmplitudeProcessor_ML2h();
public:
int capabilities() const override;
IDList capabilityParameters(Capability cap) const override;
bool setParameter(Capability cap, const std::string &value) override;
bool setup(const Settings &settings) override;
void setTrigger(const Core::Time& trigger) override;
void setEnvironment(const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Pick *pick) override;
void computeTimeWindow() override;
void reset() override;
void close() const override;
bool feed(const Record *record) override;
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) override;
const AmplitudeProcessor *componentProcessor(Component comp) const override;
const DoubleArray *processedData(Component comp) const override;
void reprocess(OPT(double) searchBegin, OPT(double) searchEnd) override;
private:
void newAmplitude(const AmplitudeProcessor *proc,
const AmplitudeProcessor::Result &res);
private:
struct ComponentResult {
AmplitudeValue value;
AmplitudeTime time;
double snr;
};
enum CombinerProc {
TakeMin,
TakeMax,
TakeAverage,
TakeGeometricMean
};
mutable AmplitudeProcessor_MLh _ampE, _ampN;
CombinerProc _combiner;
OPT(ComponentResult) _results[2];
};
}
}
#endif

View File

@ -0,0 +1,50 @@
/***************************************************************************
* 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_MLv_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_MLv_H
#include <seiscomp/processing/amplitudes/ML.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_MLv : public AbstractAmplitudeProcessor_ML {
public:
AmplitudeProcessor_MLv();
public:
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) override;
};
}
}
#endif

View File

@ -0,0 +1,57 @@
/***************************************************************************
* 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_MJMA_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_MJMA_H
#include <seiscomp/processing/amplitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_Mjma : public AmplitudeProcessor {
public:
AmplitudeProcessor_Mjma();
AmplitudeProcessor_Mjma(const Core::Time& trigger);
public:
virtual void initFilter(double fsamp) override;
protected:
bool deconvolveData(Response *resp, DoubleArray &data, int numberOfIntegrations) override;
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) override;
};
}
}
#endif

View File

@ -0,0 +1,55 @@
/***************************************************************************
* 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_MS20_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_MS20_H
#include <seiscomp/processing/amplitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_ms20 : public AmplitudeProcessor {
public:
AmplitudeProcessor_ms20();
public:
void initFilter(double fsamp) override;
protected:
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) override;
};
}
}
#endif

View File

@ -0,0 +1,60 @@
/***************************************************************************
* 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_Mwp_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_Mwp_H
#include <seiscomp/processing/amplitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_Mwp : public AmplitudeProcessor {
public:
AmplitudeProcessor_Mwp();
public:
const DoubleArray *processedData(Component comp) const override;
protected:
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) override;
private:
void init();
private:
DoubleArray _processedData;
};
}
}
#endif

View File

@ -0,0 +1,173 @@
/***************************************************************************
* 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_IASPEI_H_INCLUDED
#define SEISCOMP_PROCESSING_IASPEI_H_INCLUDED
#include <vector>
namespace Seiscomp {
namespace Processing {
namespace IASPEI {
// IASPEI Amplitude Measurement Procedure
//
// From:
// Summary of Magnitude Working Group Recommendations on Standard Procedures
// for Determining Earthquake Magnitudes From Digital Data - 2013 March 27
//
// Amplitudes [...] to be measured as one-half the maximum deflection of the
// seismogram trace, peak-to-adjacent- trough or trough-to-adjacent-peak,
// where peak and trough are separated by one crossing of the zero-line: the
// measurement is sometimes described as "one-half peak-to-peak amplitude."
// None of the magnitude formulas presented in this article are intended to
// be used with the full peak-to-trough deflection as the amplitude. The
// periods are to be measured as twice the time-intervals separating the
// peak and adjacent-trough from which the amplitudes are measured.
struct AmplitudePeriodMeasurement
{
// Amplitudes
//
// Note that "peak" here refers to both maxima and minima and
// thus can also refer to a trough. So peak-to-peak is either
// peak-to-trough or trough-to-peak. Just to avoid confusion.
//
// - az2p Max. zero-to-peak amplitude found at index iz2p
// - ap2p1 first peak of the max. peak-to-peak amplitude pair
// - ap2p2 second peak
//
// Note that az2p is the larger of ap2p1 and ap2p2.
double az2p;
double ap2p1;
double ap2p2;
// Sample indices corresponding the above peaks
std::size_t iz2p;
std::size_t ip2p1;
std::size_t ip2p2;
// From the above numbers we can now derive:
//
// - Period in sampling intervals:
//
// (ip2p2 - ip2p1)*2
//
// To be divided by the sampling rate in order to get the period
// in seconds.
//
//
// - One half of the max. peak-to-peak amplitude in data units:
//
// (ap2p1 + ap2p2)/2
//
//
// - Time of measurement as offset from first sample of the middle
// of the two peaks:
//
// (ip2p1 + ip2p2)/2
//
// To be divided by the sampling rate in order to get the time
// in seconds.
};
// Compute amplitude and dominant period for the given data vector.
//
// The data may have an offset to be removed during the amplitude measurement.
// If dealing with demeaned data the offset should be zero.
//
// We only work on the time window between samples istart and iend.
//
// A reference to a struct AmplitudePeriodMeasurement is speciefied, where the
// result will be written to. See above for details.
bool measureAmplitudePeriod(
const std::vector<double> &data,
double offset,
std::size_t istart,
std::size_t iend,
AmplitudePeriodMeasurement &measurement
);
// Interface for raw pointer.
bool measureAmplitudePeriod(
std::size_t ndata,
const double *data,
double offset,
std::size_t istart,
std::size_t iend,
AmplitudePeriodMeasurement &measurement
);
/**
* @brief Finds a zero crossing within the data portion.
* @param n The number of samples
* @param data The data pointer
* @param offset An optional data offset which is removed from each sample checked.
* @param istart Index to start from
* @param iend Index before to end
* @return The zero crossing index or -1 if none was found.
*/
double findZeroCrossing(
std::size_t n,
const double *data,
double offset,
std::size_t istart,
std::size_t iend
);
/**
* @brief Finds a zero crossing within the data portion.
* @param data The data vector
* @param offset An optional data offset which is removed from each sample checked.
* @param istart Index to start from
* @param iend Index before to end
* @return The zero crossing index or -1 if none was found.
*/
double findZeroCrossing(
const std::vector<double> &data,
double offset,
std::size_t istart,
std::size_t iend
);
// Compute the WWSSN-SP displacement amplitude response needed for the
// mb amplitude correction.
//
// The response is based on the poles and zeros specified in the IASPEI
// Magnitude Working Group Recommendations.
double wwssnspAmplitudeResponse(double frequency_hz);
} // namespace IASPEI
} // namespace Processing
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,51 @@
/***************************************************************************
* 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_mBc_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_mBc_H
#include <seiscomp/processing/amplitudes/m_B.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_mBc : public AmplitudeProcessor_mB {
public:
AmplitudeProcessor_mBc();
protected:
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) override;
};
}
}
#endif

View File

@ -0,0 +1,85 @@
/***************************************************************************
* 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. *
***************************************************************************/
#include <vector>
class Measurement {
public:
Measurement(std::size_t nsamp);
virtual ~Measurement();
public:
// offset of the data samples
// must be measured prior to the measurement
void setOffset(double x) { offset = x; }
// Feed n broadband ground velocity values v.
// feed() calls update() automatically!
virtual void feed(std::size_t n, const double *v) = 0;
double progress() const { return nsamp>0 ? double(processed)/nsamp : 0; }
protected:
// an offset to be subtracted before the actual measurement
double offset;
// number of samples anticipated to contribute to measurement
std::size_t nsamp;
// number of samples already processed
std::size_t processed;
};
class Measurement_mBc : public Measurement {
public:
Measurement_mBc(std::size_t nsamp, double q=0.6);
public:
void feed(std::size_t n, const double *v) override;
public:
// Accessors to subevents. mBc specific and meant for debugging, e.g.
// for plotting the individual subevents contributing to the sum.
//
// "Subevents" are individual extrema that contribute to the sum.
std::size_t subeventCount() const;
std::size_t subeventIndex(std::size_t i) const;
double subeventValue(std::size_t i) const;
public:
double vcum; // cumulative velocity
double vmax; // zero-to-peak maximum velocity
std::size_t icum; // index at which vcum was observed ( = index of last subevent)
std::size_t imax; // index at which vmax was observed
private:
// Cutoff threshold, normally fixed to 0.6, don't change!
// See also Bormann & Saul (2009)
double _q;
std::vector<std::size_t> _subeventIndices;
std::vector<double> _subeventValues;
int _previous;
std::size_t _ipeak;
double _vpeak;
};

View File

@ -0,0 +1,56 @@
/***************************************************************************
* 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_mB_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_mB_H
#include <seiscomp/processing/amplitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_mB : public AmplitudeProcessor {
public:
AmplitudeProcessor_mB();
public:
void finalizeAmplitude(DataModel::Amplitude *amplitude) const override;
protected:
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) override;
};
}
}
#endif

View File

@ -0,0 +1,61 @@
/***************************************************************************
* 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_mb_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_mb_H
#include <seiscomp/processing/amplitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_mb : public AmplitudeProcessor {
DECLARE_SC_CLASS(AmplitudeProcessor_mb)
public:
AmplitudeProcessor_mb();
public:
void initFilter(double fsamp) override;
void finalizeAmplitude(DataModel::Amplitude *amplitude) const override;
protected:
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) override;
};
}
}
#endif

View File

@ -0,0 +1,52 @@
/***************************************************************************
* 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_MSBB_H
#define SEISCOMP_PROCESSING_AMPLITUDEPROCESSOR_MSBB_H
#include <seiscomp/processing/amplitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API AmplitudeProcessor_msbb : public AmplitudeProcessor {
public:
AmplitudeProcessor_msbb();
protected:
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) override;
};
}
}
#endif

View File

@ -0,0 +1,153 @@
/***************************************************************************
* 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_STREAMPROCESSOR_APPLICATION_H
#define SEISCOMP_PROCESSING_STREAMPROCESSOR_APPLICATION_H
#include <seiscomp/client/streamapplication.h>
#include <seiscomp/datamodel/waveformstreamid.h>
#include <seiscomp/processing/waveformprocessor.h>
#include <seiscomp/processing/timewindowprocessor.h>
#include <seiscomp/processing/streambuffer.h>
namespace Seiscomp {
namespace Processing {
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/** \brief Application class for stream processing commandline applications.
*/
class SC_SYSTEM_CLIENT_API Application : public Client::StreamApplication {
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
Application(int argc, char **argv);
//! D'tor
~Application();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
StreamBuffer& streamBuffer();
const StreamBuffer& streamBuffer() const;
void addProcessor(const std::string& networkCode,
const std::string& stationCode,
const std::string& locationCode,
const std::string& channelCode,
WaveformProcessor *wp);
void addProcessor(const DataModel::WaveformStreamID &wfid,
WaveformProcessor *wp);
void addProcessor(const std::string& networkCode,
const std::string& stationCode,
const std::string& locationCode,
const std::string& channelCode,
TimeWindowProcessor *twp);
void addProcessor(const DataModel::WaveformStreamID &wfid,
TimeWindowProcessor *twp);
void removeProcessors(const std::string& networkCode,
const std::string& stationCode,
const std::string& locationCode,
const std::string& channelCode);
void removeProcessors(const DataModel::WaveformStreamID &wfid);
void removeProcessor(WaveformProcessor *wp);
size_t processorCount() const;
// ----------------------------------------------------------------------
// Protected methods
// ----------------------------------------------------------------------
protected:
void addObject(const std::string& parentID, DataModel::Object* o) override;
void removeObject(const std::string& parentID, DataModel::Object* o) override;
void updateObject(const std::string& parentID, DataModel::Object* o) override;
void handleRecord(Record *rec) override;
void enableStation(const std::string& code, bool enabled);
void enableStream(const std::string& code, bool enabled);
virtual void handleNewStream(const Record *) {}
virtual void processorFinished(const Record *, WaveformProcessor *) {}
void done() override;
// ----------------------------------------------------------------------
// Private methods
// ----------------------------------------------------------------------
private:
void registerProcessor(const std::string& networkCode,
const std::string& stationCode,
const std::string& locationCode,
const std::string& channelCode,
WaveformProcessor *wp);
void registerProcessor(const DataModel::WaveformStreamID &wfid,
WaveformProcessor *twp);
void registerProcessor(const std::string& networkCode,
const std::string& stationCode,
const std::string& locationCode,
const std::string& channelCode,
TimeWindowProcessor *twp);
void registerProcessor(const DataModel::WaveformStreamID &wfid,
TimeWindowProcessor *twp);
// ----------------------------------------------------------------------
// Private members
// ----------------------------------------------------------------------
private:
typedef std::multimap<std::string, WaveformProcessorPtr> StationProcessors;
typedef std::multimap<std::string, WaveformProcessorPtr> ProcessorMap;
typedef DataModel::WaveformStreamID WID;
typedef std::pair<WID, WaveformProcessorPtr> WaveformProcessorItem;
typedef std::pair<WID, TimeWindowProcessorPtr> TimeWindowProcessorItem;
typedef std::list<WaveformProcessorItem> WaveformProcessorQueue;
typedef std::list<WaveformProcessorPtr> WaveformProcessorRemovalQueue;
typedef std::list<TimeWindowProcessorItem> TimeWindowProcessorQueue;
ProcessorMap _processors;
StationProcessors _stationProcessors;
StreamBuffer _waveformBuffer;
WaveformProcessorQueue _waveformProcessorQueue;
WaveformProcessorRemovalQueue _waveformProcessorRemovalQueue;
TimeWindowProcessorQueue _timeWindowProcessorQueue;
bool _registrationBlocked;
};
}
}
#endif

View File

@ -0,0 +1,130 @@
/***************************************************************************
* 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_DETECTOR_H
#define SEISCOMP_PROCESSING_DETECTOR_H
#include <seiscomp/processing/waveformprocessor.h>
#include <boost/function.hpp>
#include <seiscomp/client.h>
namespace Seiscomp {
namespace Processing {
DEFINE_SMARTPOINTER(Detector);
class SC_SYSTEM_CLIENT_API Detector : public WaveformProcessor {
DECLARE_SC_CLASS(Detector)
public:
typedef boost::function<void (const Detector*, const Record*, const Core::Time&)> PublishFunc;
public:
Detector(double initTime);
public:
void setPublishFunction(const PublishFunc& func);
void setOffset(const Core::TimeSpan& ofs);
Core::TimeSpan offset() const;
void setDeadTimeAfterPick(const Core::TimeSpan &dt);
Core::TimeSpan deadTimeAfterPick() const;
virtual const std::string &methodID() const = 0;
virtual void reset() override;
protected:
virtual bool emitPick(const Record* rec, const Core::Time& t);
private:
PublishFunc _func;
Core::Time _lastPick;
Core::TimeSpan _offset;
Core::TimeSpan _deadTimeAfterPick;
};
DEFINE_SMARTPOINTER(SimpleDetector);
class SC_SYSTEM_CLIENT_API SimpleDetector : public Detector {
DECLARE_SC_CLASS(SimpleDetector)
public:
SimpleDetector(double deadTime = 0.0);
SimpleDetector(double on, double off, double deadTime);
public:
void setDeadTime(double deadTime) { _initTime = deadTime; }
void setThresholds(double on, double off);
//! Reimplemented method to analyse the filtered datastream.
//! It just checks whether a sample in filteredData exceeds the
//! 'on' threshold and calls validateOn or goes below the 'off'
//! threshold and calls validateOff.
void process(const Record *record, const DoubleArray &filteredData) override;
void reset() override;
protected:
bool isOn() const { return _triggered; }
bool isOff() const { return !_triggered; }
//! This methods returns whether a pick has been emitted after
//! setting the triggering state to 'on' or not
//! This value is only valid after the trigger state has
//! switched from 'off' to 'on'.
bool emittedPick() const { return _pickEmitted; }
//! This method gets called whenever the 'on' threshold is reached.
//! A derived class can return false for some reason to disable
//! setting the trigger state to true.
//!
//! When false is returned the processing of the current record
//! will be finished immediatly.
virtual bool validateOn(const Record *record, size_t &i, const DoubleArray &filteredData);
//! This method gets called whenever a filtered sample falls below
//! the 'off' threshold. A derived class can return false to disable
//! setting the trigger state to false. When false is returned the
//! processing of the current record will be finished immediatly.
virtual bool validateOff(const Record *record, size_t i, const DoubleArray &filteredData);
virtual const std::string &methodID() const override;
private:
bool _triggered;
bool _pickEmitted;
double _thresholdOn;
double _thresholdOff;
};
}
}
#endif

View File

@ -0,0 +1,340 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_H
#include <seiscomp/core/baseobject.h>
#include <seiscomp/core/interfacefactory.h>
#include <seiscomp/core/enumeration.h>
#include <seiscomp/processing/processor.h>
#include <seiscomp/client.h>
namespace Seiscomp {
namespace DataModel {
class Amplitude;
class StationMagnitude;
class Origin;
class SensorLocation;
}
namespace Geo {
class GeoFeature;
}
namespace Processing {
DEFINE_SMARTPOINTER(MagnitudeProcessor);
class SC_SYSTEM_CLIENT_API MagnitudeProcessor : public Processor {
DECLARE_SC_CLASS(MagnitudeProcessor)
// ----------------------------------------------------------------------
// Public types
// ----------------------------------------------------------------------
public:
MAKEENUM(
Status,
EVALUES(
//! No error
OK,
//! Given amplitude is out of range
AmplitudeOutOfRange,
//! Given depth is out of range to continue processing
DepthOutOfRange,
//! Given distance is out of range to continue processing
DistanceOutOfRange,
//! Given period is out of range to continue processing
PeriodOutOfRange,
//! Given amplitude SNR is out of range to continue processing
SNROutOfRange,
//! Either the origin or the sensor location hasn't been set
//! in call to computeMagnitude
MetaDataRequired,
//! The epicentre is out of supported regions
EpicenterOutOfRegions,
//! The receiver is out of supported regions
ReceiverOutOfRegions,
//! The entire raypath does not lie entirely in the supported
//! regions
RayPathOutOfRegions,
//! The unit of the input amplitude was not understood
InvalidAmplitudeUnit,
//! The amplitude object was missing
MissingAmplitudeObject,
//! The estimation of the Mw magnitude is not supported
MwEstimationNotSupported,
//! The configuration is not complete
IncompleteConfiguration,
//! Unspecified error
Error
),
ENAMES(
"OK",
"amplitude out of range",
"depth out of range",
"distance out of range",
"period out of range",
"signal-to-noise ratio out of range",
"meta data required",
"epicenter out of regions",
"receiver out of regions",
"ray path out of regions",
"invalid amplitude unit",
"missing amplitude object",
"Mw estimation not supported",
"configuration incomplete",
"error"
)
);
struct Locale {
enum Check {
Source,
SourceReceiver,
SourceReceiverPath
};
OPT(double) minimumDistance;
OPT(double) maximumDistance;
OPT(double) minimumDepth;
OPT(double) maximumDepth;
double multiplier;
double offset;
std::string name;
const Geo::GeoFeature *feature;
Check check;
Core::BaseObjectPtr extra;
};
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
protected:
//! C'tor
MagnitudeProcessor(const std::string &type);
public:
//! D'tor
~MagnitudeProcessor();
// ----------------------------------------------------------------------
// Public Interface
// ----------------------------------------------------------------------
public:
//! Returns the type of magnitude to be calculated
const std::string &type() const;
//! Returns the type of the Mw estimation
//! The default implementation returns "Mw($type)"
virtual std::string typeMw() const;
/**
* Returns the amplitude type used as input for this magnitude
* processor.
* The default implementation returns type()
* @return
*/
virtual std::string amplitudeType() const;
virtual bool setup(const Settings &settings) override;
/**
* @brief Computes the magnitude from an amplitude. The method signature
* has changed with API version >= 11. Prior to that version,
* hypocenter, receiver and amplitude were not present.
* @param amplitudeValue The amplitude value without unit. The unit is
implicitly defined by the requested amplitude
* type.
* @param unit The unit of the amplitude.
* @param period The measured period of the amplitude in seconds.
* @param snr The measured SNR of the amplitude.
* @param delta The distance from the epicenter in degrees.
* @param depth The depth of the hypocenter in kilometers.
* @param hypocenter The optional origin which describes the hypocenter.
* @param receiver The sensor location meta-data of the receiver.
* @param amplitude The optional amplitude object from which the values
* were extracted.
* @param value The return value, the magnitude.
* @return The status of the computation.
*/
Status computeMagnitude(double amplitudeValue, const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *amplitude,
double &value);
/**
* @brief When computeMagnitude return an error the computed magnitude
* value might nevertheless contain a meaningful value. E.g. if
* the distance is out of range according to the defined rules,
* the computation for a lower distance might still result in
* valid values. This function indicates whether the returned
* value should be treated as valid magnitude or not, even if an
* error was returned. This function's return value must not be
* used when computeMagnitude returned OK. A valid return value
* is only provided in case the computation failed. To make it
* clear: this function can only be called after
* computeMagnitude and only if computeMagnitude(...) != OK.
* @return Whether the computed magnitude is a valid value or has to be
* ignored. The default implementation returns false.
*/
virtual bool treatAsValidMagnitude() const;
/**
* @brief Estimates the Mw magnitude from a given magnitude. The
* default implementation returns MwEstimationNotSupported.
* @param config Optional configuration
* @param magnitude Input magnitude value.
* @param estimation Resulting Mw estimation.
* @param stdError Resulting standard error.
* @return The status of the computation.
*/
virtual Status estimateMw(const Config::Config *config,
double magnitude, double &estimation,
double &stdError);
void setCorrectionCoefficients(double a, double b);
/**
* @brief Allows to finalize a magnitude object as created by
* client code.
*
* This method will usually be called right before the magnitude 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 magnitude The magnitude to be finalized
*/
virtual void finalizeMagnitude(DataModel::StationMagnitude *magnitude) const;
static bool CreateAlias(const std::string &aliasType,
const std::string &sourceType,
const std::string &sourceAmpType);
static bool RemoveAlias(const std::string &aliasType);
static void RemoveAllAliases();
protected:
/**
* @brief Computes the magnitude from an amplitude. The method signature
* has changed with API version >= 11. Prior to that version,
* hypocenter, receiver and amplitude were not present.
* @param amplitudeValue The amplitude value without unit. The unit is
implicitly defined by the requested amplitude
* type.
* @param unit The unit of the amplitude.
* @param period The measured period of the amplitude in seconds.
* @param snr The measured SNR of the amplitude.
* @param delta The distance from the epicenter in degrees.
* @param depth The depth of the hypocenter in kilometers.
* @param hypocenter The optional origin which describes the hypocenter.
* @param receiver The sensor location meta-data of the receiver.
* @param amplitude The optional amplitude object from which the values
* were extracted.
* @param value The return value, the magnitude.
* @return The status of the computation.
*/
virtual Status computeMagnitude(double amplitudeValue, const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *amplitude,
const Locale *locale,
double &value) = 0;
virtual bool initLocale(Locale *locale,
const Settings &settings,
const std::string &configPrefix);
bool initRegionalization(const Settings &settings);
/**
* @brief Converts an amplitude value in an input unit to a value in
* an output unit, e.g. mm/s -> nm/s.
* @param amplitude The input value which will be changed
* @param amplitudeUnit The unit associated with the input amplitude value
* @param desiredAmplitudeUnit The desired amplitude unit of the output
* value.
* @return Success or not
*/
bool convertAmplitude(double &amplitude,
const std::string &amplitudeUnit,
const std::string &desiredAmplitudeUnit) const;
private:
bool readLocale(Locale *locale,
const Settings &settings,
const std::string &configPrefix);
protected:
struct Correction {
typedef std::pair<double, double> A;
typedef std::map<std::string, A> Profiles;
Profiles::mapped_type &operator[](const Profiles::key_type &key) {
return profiles[key];
}
const A *apply(double &val, const std::string &profile) const;
Profiles profiles;
};
std::string _type;
std::string _amplitudeType;
std::string _networkCode;
std::string _stationCode;
Correction _corrections;
Correction::A _defaultCorrection;
friend class MagnitudeProcessorAliasFactory;
};
DEFINE_INTERFACE_FACTORY(MagnitudeProcessor);
}
}
#define REGISTER_MAGNITUDEPROCESSOR_VAR(Class, Service) \
Seiscomp::Core::Generic::InterfaceFactory<Seiscomp::Processing::MagnitudeProcessor, Class> __##Class##InterfaceFactory__(Service)
#define REGISTER_MAGNITUDEPROCESSOR(Class, Service) \
static REGISTER_MAGNITUDEPROCESSOR_VAR(Class, Service)
#endif

View File

@ -0,0 +1,70 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_ML_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_ML_H
#include <seiscomp/processing/magnitudeprocessor.h>
#include <seiscomp/processing/magnitudes/utils.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API MagnitudeProcessor_ML : public MagnitudeProcessor {
DECLARE_SC_CLASS(MagnitudeProcessor_ML);
public:
MagnitudeProcessor_ML();
public:
bool setup(const Settings &settings) override;
std::string amplitudeType() const override;
protected:
bool initLocale(Locale *locale, const Settings &settings,
const std::string &configPrefix) override;
Status computeMagnitude(double amplitude, const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *,
const Locale *,
double &value) override;
private:
LogA0 _logA0;
double _maxDistanceKm;
};
}
}
#endif

View File

@ -0,0 +1,81 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_MLc_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_MLc_H
#include <seiscomp/processing/magnitudeprocessor.h>
#include <seiscomp/processing/magnitudes/utils.h>
#include <seiscomp/math/geo.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API MagnitudeProcessor_MLc : public MagnitudeProcessor {
public:
MagnitudeProcessor_MLc();
public:
bool setup(const Settings &settings) override;
std::string amplitudeType() const override;
protected:
Status computeMagnitude(double amplitude, const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *,
const Locale *,
double &value) override;
protected:
bool initLocale(Locale *locale, const Settings &settings,
const std::string &configPrefix) override;
private:
double _minDistanceKm{-1.0};
double _maxDistanceKm{8.0 * KM_OF_DEGREE};
double _maxDepth{80.0};
std::string _distanceMode{"hypocentral"};
std::string _calibrationType{"parametric"};
// parameters for parametric magnitude calibration
double _c0{0.0};
double _c1{0.69};
double _c2{0.00095};
double _c3{1.11};
double _c4{0.0};
double _c5{1.0};
// parameters for non-parametric magnitude calibration
LogA0 _logA0;
};
}
}
#endif

View File

@ -0,0 +1,71 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_MLV_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_MLV_H
#include <seiscomp/processing/magnitudeprocessor.h>
#include <seiscomp/processing/magnitudes/utils.h>
#include <vector>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API MagnitudeProcessor_MLv : public MagnitudeProcessor {
DECLARE_SC_CLASS(MagnitudeProcessor_MLv);
public:
MagnitudeProcessor_MLv();
public:
bool setup(const Settings &settings) override;
protected:
bool initLocale(Locale *locale, const Settings &settings,
const std::string &configPrefix) override;
Status computeMagnitude(double amplitude,
const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *,
const Locale *,
double &value) override;
private:
LogA0 _logA0;
double _maxDistanceKm;
};
}
}
#endif

View File

@ -0,0 +1,52 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_MJMA_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_MJMA_H
#include <seiscomp/processing/magnitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API MagnitudeProcessor_Mjma : public MagnitudeProcessor {
public:
MagnitudeProcessor_Mjma();
protected:
Status computeMagnitude(double amplitude, const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *,
const Locale *,
double &value) override;
};
}
}
#endif

View File

@ -0,0 +1,63 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_MS20_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_MS20_H
#include <seiscomp/processing/magnitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API MagnitudeProcessor_ms20 : public MagnitudeProcessor {
DECLARE_SC_CLASS(MagnitudeProcessor_ms20);
public:
MagnitudeProcessor_ms20();
bool setup(const Settings &settings) override;
protected:
Status computeMagnitude(double amplitude, const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *,
const Locale *,
double &value) override;
private:
double lowPer;
double upPer;
double minDistanceDeg;
double maxDistanceDeg;
double maxDepthKm;
};
}
}
#endif

View File

@ -0,0 +1,56 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_M_B_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_M_B_H
#include <seiscomp//processing/magnitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API MagnitudeProcessor_Mwp : public MagnitudeProcessor {
DECLARE_SC_CLASS(MagnitudeProcessor_Mwp);
public:
MagnitudeProcessor_Mwp();
Status computeMagnitude(double amplitude, const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *,
const Locale *,
double &value) override;
Status estimateMw(const Config::Config *config, double magnitude,
double &estimation, double &stdError) override;
};
}
}
#endif

View File

@ -0,0 +1,48 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_M_B_C_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_M_B_C_H
#include <seiscomp//processing/magnitudes/m_B.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API MagnitudeProcessor_mBc : public MagnitudeProcessor_mB {
DECLARE_SC_CLASS(MagnitudeProcessor_mBc)
public:
MagnitudeProcessor_mBc();
Status estimateMw(const Config::Config *config,
double magnitude, double &Mw_estimate,
double &Mw_stdError) override;
};
}
}
#endif

View File

@ -0,0 +1,65 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_M_B_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_M_B_H
#include <seiscomp//processing/magnitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API MagnitudeProcessor_mB : public MagnitudeProcessor {
DECLARE_SC_CLASS(MagnitudeProcessor_mB)
public:
MagnitudeProcessor_mB();
MagnitudeProcessor_mB(const std::string& type);
bool setup(const Settings &settings) override;
Status computeMagnitude(double amplitude, const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *,
const Locale *,
double &value) override;
Status estimateMw(const Config::Config *config,
double magnitude, double &Mw_estimate,
double &Mw_stdError) override;
private:
double minDistanceDeg;
double maxDistanceDeg;
};
}
}
#endif

View File

@ -0,0 +1,60 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_MB_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_MB_H
#include <seiscomp/processing/magnitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API MagnitudeProcessor_mb : public MagnitudeProcessor {
DECLARE_SC_CLASS(MagnitudeProcessor_mb)
bool setup(const Settings &settings) override;
public:
MagnitudeProcessor_mb();
protected:
Status computeMagnitude(double amplitude, const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *,
const Locale *,
double &value) override;
private:
double minDistanceDeg;
double maxDistanceDeg;
};
}
}
#endif

View File

@ -0,0 +1,54 @@
/***************************************************************************
* 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_MAGNITUDEPROCESSOR_MSBB_H
#define SEISCOMP_PROCESSING_MAGNITUDEPROCESSOR_MSBB_H
#include <seiscomp/processing/magnitudeprocessor.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API MagnitudeProcessor_msbb : public MagnitudeProcessor {
DECLARE_SC_CLASS(MagnitudeProcessor_msbb);
public:
MagnitudeProcessor_msbb();
protected:
Status computeMagnitude(double amplitude, const std::string &unit,
double period, double snr,
double delta, double depth,
const DataModel::Origin *hypocenter,
const DataModel::SensorLocation *receiver,
const DataModel::Amplitude *,
const Locale *,
double &value) override;
};
}
}
#endif

View File

@ -0,0 +1,64 @@
/***************************************************************************
* 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_MAGNITUDES_UTILS_H
#define SEISCOMP_PROCESSING_MAGNITUDES_UTILS_H
#include <ostream>
#include <string>
#include <vector>
namespace Seiscomp {
namespace Processing {
template <typename T>
struct TableXY {
using Item = std::pair<double, T>;
using Items = std::vector<Item>;
bool empty() const;
bool set(const std::string &definition);
bool set(const std::vector<std::string> &definition);
// Throws out_of_range if x is out of range
T at(double x) const;
Items items;
};
using LogA0 = TableXY<double>;
template <typename T>
std::ostream &operator<<(std::ostream &os, const TableXY<T> &table);
}
}
#include "utils.ipp"
#endif

View File

@ -0,0 +1,75 @@
/***************************************************************************
* 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_OPERATOR_L2NORM_H
#define SEISCOMP_PROCESSING_OPERATOR_L2NORM_H
namespace Seiscomp {
namespace Processing {
namespace Operator {
template <typename T, int N>
class L2Norm {
// Process N traces in place of length n
void operator()(const Record *, T *data[N], int n, const Core::Time &stime, double sfreq) const;
// publishs a processed component
bool publish(int c) const;
void reset();
};
template <typename T>
struct L2Norm<T,2> {
void operator()(const Record *, T *data[2], int n, const Core::Time &stime, double sfreq) const {
for ( int i = 0; i < n; ++i )
data[0][i] = sqrt(data[0][i] * data[0][i] +
data[1][i] * data[1][i]);
}
bool publish(int c) const { return c == 0; }
void reset() {}
};
template <typename T>
struct L2Norm<T,3> {
void operator()(const Record *, T *data[3], int n, const Core::Time &stime, double sfreq) const {
for ( int i = 0; i < n; ++i )
data[0][i] = sqrt(data[0][i] * data[0][i] +
data[1][i] * data[1][i]);
}
bool publish(int c) const { return c == 0; }
void reset() {}
};
}
}
}
#endif

View File

@ -0,0 +1,281 @@
/***************************************************************************
* 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_OPERATOR_NCOMPS_H
#define SEISCOMP_PROCESSING_OPERATOR_NCOMPS_H
#include <seiscomp/processing/waveformoperator.h>
#include <seiscomp/core/genericrecord.h>
#include <seiscomp/core/recordsequence.h>
namespace Seiscomp {
namespace Processing {
/*
template <typename T, int N>
class Proc {
// Process N traces in place of length n
void operator()(const Record *, T *data[N], int n, const Core::Time &stime, double sfreq) const;
// Publish a processed component
bool publish(int c) const;
// Returns the component index of a given channel code
int compIndex(const std::string &code) const;
void reset();
};
*/
template <typename T, int N, class PROC, int BSIZE=-1>
class NCompsOperator : public WaveformOperator {
public:
NCompsOperator(const PROC &proc) : _proc(proc), _processing(false) {}
WaveformProcessor::Status feed(const Record *record);
void reset();
// Returns the RingBuffer of each component.
const Seiscomp::RingBuffer &buffer(int i) const {
return this->_states[i].buffer;
}
const PROC &proc() const {
return this->_proc;
}
protected:
WaveformProcessor::Status process(int comp, const Record *rec);
protected:
struct State {
State() : buffer(BSIZE) {}
RingBuffer buffer;
Core::Time endTime;
};
// Stores the N channel codes and the according record buffer
State _states[N];
PROC _proc;
bool _processing;
};
namespace Operator {
template <typename T, int N, template <typename,int> class PROC>
class CodeWrapper {};
template <typename T, template <typename,int> class PROC>
class CodeWrapper<T,2,PROC> {
public:
CodeWrapper(const std::string &code1, const std::string &code2,
const PROC<T,2> &proc) : _proc(proc) {}
void operator()(const Record *rec, T *data[2], int n, const Core::Time &stime, double sfreq) const { _proc(rec, data, n, stime, sfreq); }
bool publish(int c) const { return _proc.publish(c); }
int compIndex(const std::string &code) const { return -1; }
const std::string &translateChannelCode(int c, const std::string &code) { return code; }
void reset() {
_proc.reset();
}
private:
PROC<T,2> _proc;
std::string _code1;
std::string _code2;
};
template <typename T, template <typename,int> class PROC>
class CodeWrapper<T,3,PROC> {
public:
CodeWrapper(const std::string &code1, const std::string &code2,
const std::string &code3, const PROC<T,3> &proc)
: _proc(proc), _code1(code1), _code2(code2), _code3(code3) {}
void operator()(const Record *rec, T *data[3], int n, const Core::Time &stime, double sfreq) const { _proc(rec, data, n, stime, sfreq); }
bool publish(int c) const { return _proc.publish(c); }
int compIndex(const std::string &code) const {
if ( code == _code1 ) return 0;
else if ( code == _code2 ) return 1;
else if ( code == _code3 ) return 2;
return -1;
}
const std::string &translateChannelCode(int c, const std::string &code) { return code; }
void reset() {
_proc.reset();
}
private:
PROC<T,3> _proc;
std::string _code1;
std::string _code2;
std::string _code3;
};
template <typename T, int N, template <typename,int> class PROC>
class StreamConfigWrapper {
public:
StreamConfigWrapper(Stream configs[N], const PROC<T,N> &proc)
: _proc(proc), _configs(configs) {}
void operator()(const Record *rec, T *data[N], int n, const Core::Time &stime, double sfreq) const {
// Sensitivity correction before applying the operator
for ( int c = 0; c < N; ++c ) {
if ( _configs[c].gain == 0.0 ) continue;
double scale = 1.0 / _configs[c].gain;
T *trace = data[c];
for ( int i = 0; i < n; ++i, ++trace )
*trace *= scale;
}
// Call real operator
_proc(rec, data, n, stime, sfreq);
}
bool publish(int c) const { return _proc.publish(c); }
int compIndex(const std::string &code) const {
for ( int i = 0; i < N; ++i )
if ( code == _configs[i].code() ) return i;
return -1;
}
const std::string &translateChannelCode(int c, const std::string &code) { return code; }
const PROC<T,N> &proc() const {
return _proc;
}
void reset() {
_proc.reset();
}
private:
PROC<T,N> _proc;
const Stream *_configs;
};
template <typename T, int N>
class NoOpWrapper {
public:
NoOpWrapper(Stream configs[N]) : _configs(configs) { }
// Process N traces in place of length n
void operator()(const Record *, T *data[N], int n, const Core::Time &stime, double sfreq) const {}
// publishs a processed component
bool publish(int c) const { return c < N; }
// Returns the component index of a given channel code
int compIndex(const std::string &code) const {
for ( int i = 0; i < N; ++i )
if ( code == _configs[i].code() ) return i;
return -1;
}
void reset() {}
private:
const Stream *_configs;
};
template <typename T, int N, class PROC>
class FilterWrapper {
public:
FilterWrapper(Math::Filtering::InPlaceFilter<T> *filter,
const PROC &proc)
: _proc(proc), _baseFilter(filter) {
for ( int i = 0; i < N; ++i ) _filter[i] = nullptr;
}
~FilterWrapper() {
for ( int i = 0; i < N; ++i )
if ( _filter[i] ) delete _filter[i];
}
void operator()(const Record *rec, T *data[N], int n, const Core::Time &stime, double sfreq) const {
if ( _baseFilter ) {
for ( int i = 0; i < N; ++i ) {
if ( _filter[i] == nullptr ) {
_filter[i] = _baseFilter->clone();
_filter[i]->setSamplingFrequency(sfreq);
}
_filter[i]->apply(n, data[i]);
}
}
// Call real operator
_proc(rec, data, n, stime, sfreq);
}
bool publish(int c) const { return _proc.publish(c); }
int compIndex(const std::string &code) const {
return _proc.compIndex(code);
}
const std::string &translateChannelCode(int, const std::string &code) {
return code;
}
const PROC &proc() const {
return _proc;
}
void reset() {}
private:
PROC _proc;
Math::Filtering::InPlaceFilter<T> *_baseFilter;
mutable Math::Filtering::InPlaceFilter<T> *_filter[N];
};
}
}
}
#include <seiscomp/processing/operator/ncomps.ipp>
#endif

View File

@ -0,0 +1,352 @@
/***************************************************************************
* 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. *
***************************************************************************/
#include <seiscomp/core/datetime.h>
#include <seiscomp/core/typedarray.h>
#include <seiscomp/core/bitset.h>
namespace Seiscomp {
namespace Processing {
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
struct ScopedUnsetFlag {
ScopedUnsetFlag(bool &f) : flag(f) {}
~ScopedUnsetFlag() { flag = false; }
bool &flag;
};
template <typename T, int N, class PROC, int BSIZE>
WaveformProcessor::Status NCompsOperator<T,N,PROC,BSIZE>::process(int, const Record *rec) {
Core::Time minStartTime;
Core::Time maxStartTime;
Core::Time minEndTime;
WaveformProcessor::Status status;
status = WaveformProcessor::WaitingForData;
ScopedUnsetFlag unsetProcessingFlagOnReturn(_processing);
_processing = true;
for ( int i = 0; i < N; ++i ) {
// Not all traces available, nothing to do
if ( _states[i].endTime.valid() ) {
if ( _states[i].endTime > minStartTime )
minStartTime = _states[i].endTime;
}
if ( _states[i].buffer.empty() ) {
return status;
}
}
// Find common start time for all three components
RecordSequence::iterator it[N];
RecordSequence::iterator it_end[N];
int maxStartComponent;
int skips;
double samplingFrequency, timeTolerance;
// Initialize iterators for each component
for ( int i = 0; i < N; ++i )
it[i] = _states[i].buffer.begin();
// Store sampling frequency of first record of first component
// All records must match this sampling frequency
samplingFrequency = (*it[0])->samplingFrequency();
timeTolerance = 0.5 / samplingFrequency;
while ( true ) {
if ( minStartTime ) {
for ( int i = 0; i < N; ++i ) {
while ( it[i] != _states[i].buffer.end() ) {
if ( (*it[i])->endTime() <= minStartTime )
it[i] = _states[i].buffer.erase(it[i]);
else
break;
}
// End of stream?
if ( it[i] == _states[i].buffer.end() )
return status;
}
}
// Advance all other components to first record matching
// the first sampling frequency found
for ( int i = 0; i < N; ++i ) {
if ( ((*it[i])->samplingFrequency() != samplingFrequency) )
return WaveformProcessor::InvalidSamplingFreq;
}
// Find maximum start time of all three records
skips = 1;
while ( skips ) {
maxStartComponent = -1;
for ( int i = 0; i < N; ++i ) {
if ( !i || maxStartTime < (*it[i])->startTime() ) {
maxStartTime = (*it[i])->startTime();
maxStartComponent = i;
}
}
skips = 0;
// Check all other components against maxStartTime
for ( int i = 0; i < N; ++i ) {
if ( i == maxStartComponent ) continue;
while ( (*it[i])->endTime() <= maxStartTime ) {
if ( (*it[i])->samplingFrequency() != samplingFrequency )
return WaveformProcessor::InvalidSamplingFreq;
++it[i];
// End of sequence? Nothing can be done anymore
if ( it[i] == _states[i].buffer.end() )
return status;
// Increase skip counter
++skips;
}
}
}
// Advance all iterators to last non-gappy record
for ( int i = 0; i < N; ++i ) {
RecordSequence::iterator tmp = it[i];
it_end[i] = it[i];
++it_end[i];
while ( it_end[i] != _states[i].buffer.end() ) {
const Record *rec = it_end[i]->get();
// Skip records with wrong sampling frequency
if ( rec->samplingFrequency() != samplingFrequency )
return WaveformProcessor::InvalidSamplingFreq;
double diff = (double)(rec->startTime()-(*tmp)->endTime());
if ( fabs(diff) > timeTolerance ) break;
tmp = it_end[i];
++it_end[i];
}
it_end[i] = tmp;
}
// Find minimum end time of all three records
for ( int i = 0; i < N; ++i ) {
if ( !i || minEndTime > (*it_end[i])->endTime() )
minEndTime = (*it_end[i])->endTime();
}
typedef typename Core::SmartPointer< NumericArray<T> >::Impl DataArrayPtr;
DataArrayPtr data[N];
GenericRecordPtr comps[N];
int minLen = 0;
// Clip maxStartTime to minStartTime
if ( maxStartTime < minStartTime )
maxStartTime = minStartTime;
BitSetPtr clipMask;
// Align records
for ( int i = 0; i < N; ++i ) {
float tq = 0;
int tqCount = 0;
if ( _proc.publish(i) )
comps[i] = new GenericRecord((*it[i])->networkCode(),
(*it[i])->stationCode(),
(*it[i])->locationCode(),
_proc.translateChannelCode(i, (*it[i])->channelCode()),
maxStartTime, samplingFrequency);
data[i] = new NumericArray<T>;
RecordSequence::iterator seq_end = it_end[i];
++seq_end;
for ( RecordSequence::iterator rec_it = it[i]; rec_it != seq_end; ) {
const Array *rec_data = (*rec_it)->data();
if ( (*rec_it)->startTime() > minEndTime )
break;
++it[i];
const NumericArray<T> *srcData = NumericArray<T>::ConstCast(rec_data);
typename Core::SmartPointer< NumericArray<T> >::Impl tmp;
if ( srcData == nullptr ) {
tmp = (NumericArray<T>*)rec_data->copy(NumericArray<T>::ArrayType);
srcData = tmp.get();
}
int startIndex = 0;
int endIndex = srcData->size();
if ( (*rec_it)->startTime() < maxStartTime )
startIndex += (int)(double(maxStartTime-(*rec_it)->startTime())*(*rec_it)->samplingFrequency()+0.5);
if ( (*rec_it)->endTime() > minEndTime )
endIndex -= (int)(double((*rec_it)->endTime()-minEndTime)*(*rec_it)->samplingFrequency());
int len = endIndex-startIndex;
// Skip empty records
if ( len <= 0 ) {
++rec_it;
continue;
}
if ( (*rec_it)->timingQuality() >= 0 ) {
tq += (*rec_it)->timingQuality();
++tqCount;
}
// Combine the clip masks with OR if available
const BitSet *recClipMask = (*rec_it)->clipMask();
if ( (recClipMask != nullptr) && recClipMask->any() ) {
int ofs = data[i]->size();
int nBits = data[i]->size() + len;
if ( !clipMask )
clipMask = new BitSet(nBits);
else if ( (int)clipMask->size() < nBits )
clipMask->resize(nBits, false);
for ( int i = startIndex; i < len; ++i, ++ofs )
clipMask->set(ofs, clipMask->test(ofs) || recClipMask->test(i));
}
data[i]->append(len, srcData->typedData()+startIndex);
++rec_it;
}
if ( comps[i] && (tqCount > 0) )
comps[i]->setTimingQuality((int)(tq / tqCount));
minLen = i==0?data[i]->size():std::min(minLen, data[i]->size());
if ( comps[i] ) comps[i]->setData(data[i].get());
}
// Trim clip mask to sample array size
if ( clipMask ) {
if ( (int)clipMask->size() > minLen )
clipMask->resize(minLen);
// Destroy clip mask if no bit is set
if ( !clipMask->any() )
clipMask = nullptr;
}
T *data_samples[N];
for ( int i = 0; i < N; ++i ) {
NumericArray<T> *ar = data[i].get();
if ( ar->size() > minLen ) {
ar->resize(minLen);
if ( comps[i] ) comps[i]->dataUpdated();
}
data_samples[i] = data[i]->typedData();
Core::Time endTime = maxStartTime + Core::TimeSpan(data[i]->size() / rec->samplingFrequency());
// Set last transformed end time of component
if ( !_states[i].endTime.valid() ||
_states[i].endTime < endTime ) {
_states[i].endTime = endTime;
}
}
if ( minLen > 0 ) {
// Process finally
try {
_proc(rec, data_samples, minLen, maxStartTime, rec->samplingFrequency());
}
catch ( ... ) {
return WaveformProcessor::Error;
}
for ( int i = 0; i < N; ++i ) {
if ( comps[i] ) {
if ( clipMask )
comps[i]->setClipMask(clipMask.get());
store(comps[i].get());
}
}
}
status = WaveformProcessor::InProgress;
minStartTime = minEndTime;
}
return status;
}
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
template <typename T, int N, class PROC, int BSIZE>
WaveformProcessor::Status NCompsOperator<T,N,PROC,BSIZE>::feed(const Record *rec) {
if ( rec->data() == nullptr ) return WaveformProcessor::WaitingForData;
int i = _proc.compIndex(rec->channelCode());
if ( i >= 0 ) {
_states[i].buffer.feed(rec);
return process(i, rec);
}
return WaveformProcessor::WaitingForData;
}
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
template <typename T, int N, class PROC, int BSIZE>
void NCompsOperator<T,N,PROC,BSIZE>::reset() {
// No reset while in processing
if ( _processing ) return;
for ( int i = 0; i < N; ++i ) {
_states[i] = State();
}
_proc.reset();
}
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}
}

View File

@ -0,0 +1,53 @@
/***************************************************************************
* 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_OPERATOR_PIPE_H
#define SEISCOMP_PROCESSING_OPERATOR_PIPE_H
#include <seiscomp/processing/waveformoperator.h>
namespace Seiscomp {
namespace Processing {
//! A simple wrapper for WaveformOperator::connect. It additionally
//! manages the two connected operators.
class PipeOperator : public WaveformOperator {
public:
PipeOperator(WaveformOperator *op1, WaveformOperator *op2);
WaveformProcessor::Status feed(const Record *record);
void reset();
private:
WaveformOperatorPtr _op1;
WaveformOperatorPtr _op2;
};
}
}
#endif

View File

@ -0,0 +1,96 @@
/***************************************************************************
* 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_OPERATOR_TRANSFORMATION_H
#define SEISCOMP_PROCESSING_OPERATOR_TRANSFORMATION_H
#include <seiscomp/core/datetime.h>
#include <seiscomp/math/matrix3.h>
namespace Seiscomp {
namespace Processing {
namespace Operator {
template <typename T, int N>
struct Transformation {
Transformation(const Math::Matrix3<T> &m);
// Process N traces in place of length n
void operator()(const Record *, T *data[N], int n, const Core::Time &, double) const;
// publishs a processed component
bool publish(int c) const;
void reset();
};
template <typename T>
struct Transformation<T,2> {
Transformation(const Math::Matrix3<T> &m) : matrix(m) {}
bool publish(int c) const { return true; }
void reset() {}
void operator()(const Record *, T *data[2], int n, const Core::Time &, double) const {
for ( int i = 0; i < n; ++i ) {
Math::Vector3<T> v = matrix*Math::Vector3<T>(*data[0], *data[1], 0);
*data[0] = v.x;
*data[1] = v.y;
++data[0]; ++data[1];
}
}
Math::Matrix3<T> matrix;
};
template <typename T>
struct Transformation<T,3> {
Transformation(const Math::Matrix3<T> &m) : matrix(m) {}
bool publish(int c) const { return true; }
void reset() {}
void operator()(const Record *, T *data[3], int n, const Core::Time &, double) const {
for ( int i = 0; i < n; ++i ) {
Math::Vector3<T> v = matrix*Math::Vector3<T>(*data[0], *data[1], *data[2]);
*data[0] = v.x;
*data[1] = v.y;
*data[2] = v.z;
++data[0]; ++data[1]; ++data[2];
}
}
Math::Matrix3<T> matrix;
};
}
}
}
#endif

View File

@ -0,0 +1,242 @@
/***************************************************************************
* 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_PICKER_H
#define SEISCOMP_PROCESSING_PICKER_H
#include <seiscomp/core/interfacefactory.h>
#include <seiscomp/processing/timewindowprocessor.h>
#include <seiscomp/client.h>
#include <boost/function.hpp>
namespace Seiscomp {
namespace Processing {
DEFINE_SMARTPOINTER(Picker);
class SC_SYSTEM_CLIENT_API Picker : public TimeWindowProcessor {
DECLARE_SC_CLASS(Picker)
// ----------------------------------------------------------------------
// Public types
// ----------------------------------------------------------------------
public:
//! Configuration structure to store processing dependent
//! settings
struct Config {
double noiseBegin; // start of the noise window to initialize filters
double signalBegin; // default: -30, relative to _trigger
double signalEnd; // default: +10, relative to _trigger
double snrMin; // default: 3
};
enum Polarity {
POSITIVE,
NEGATIVE,
UNDECIDABLE
};
struct Result {
const Record *record;
double snr;
Core::Time time;
double timeLowerUncertainty;
double timeUpperUncertainty;
double timeWindowBegin;
double timeWindowEnd;
OPT(double) slowness;
OPT(double) backAzimuth;
OPT(Polarity) polarity;
};
typedef boost::function<void (const Picker*,
const Result &)> PublishFunc;
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
Picker();
Picker(const Core::Time& trigger);
//! D'tor
~Picker();
// ----------------------------------------------------------------------
// Configuration Interface
// ----------------------------------------------------------------------
public:
//! Returns the name of the method used by concrete implementations
virtual const std::string &methodID() const = 0;
//! Returns the filter used by concrete implementations
virtual const std::string &filterID() const = 0;
//! Set the start of the noise window relative to the trigger
void setNoiseStart(double start) { _config.noiseBegin = start; }
//! 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; }
//! Returns the current configuration
const Config &config() const { return _config; }
//! This method has to be called when all configuration
//! settings has been set to calculate the timewindow
void computeTimeWindow() override;
void reset() override;
// ----------------------------------------------------------------------
// Public Interface
// ----------------------------------------------------------------------
public:
//! Sets the trigger used to compute the timewindow to calculate
//! the amplitude
//! Once a trigger has been set all succeeding calls will fail.
void setTrigger(const Core::Time &trigger);
Core::Time trigger() const;
/**
* @brief Returns the currently set noise window
*
* This is being computed as trigger + noiseBegin and
* trigger + signalBegin
* @return The time window of the noise
*/
Core::TimeWindow noiseWindow() const;
/**
* @brief Returns the currently set signal window
*
* This is being computed as trigger + signalBegin and
* trigger + signalEnd
* @return The time window of the signal
*/
Core::TimeWindow signalWindow() const;
/**
* @brief Allows to finalize a pick object as created by client code.
*
* This method will usually be called right before the pick 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 pick The pick to be finalized
*/
virtual void finalizePick(DataModel::Pick *pick) const;
void setPublishFunction(const PublishFunc& func);
//! Dumps the record data into an ASCII file
void writeData();
// ----------------------------------------------------------------------
// Protected Interface
// ----------------------------------------------------------------------
protected:
//! Implement this method to compute a pick.
//! The default implementation returns false and does nothing.
//! The returned uncertainty measures are in samples.
//! Negative uncertainties are invalid and not recognized further.
virtual bool calculatePick(int n, const double *data,
int signalStartIdx, int signalEndIdx,
int &triggerIdx, int &lowerUncertainty,
int &upperUncertainty, double &snr,
OPT(Polarity) &polarity) = 0;
void process(const Record *record, const DoubleArray &filteredData) override;
bool handleGap(Filter *filter, const Core::TimeSpan& span,
double lastSample, double nextSample,
size_t missingSamples) override;
//! This method is called when a pick has to be published
void emitPick(const Result &result);
private:
void init();
// ----------------------------------------------------------------------
// Protected Members
// ----------------------------------------------------------------------
protected:
Core::Time _trigger;
// config
Config _config;
// ----------------------------------------------------------------------
// Private Members
// ----------------------------------------------------------------------
private:
PublishFunc _func;
};
DEFINE_INTERFACE_FACTORY(Picker);
inline Core::Time Picker::trigger() const {
return _trigger;
}
inline Core::TimeWindow Picker::noiseWindow() const {
return Core::TimeWindow(
_trigger + Core::TimeSpan(_config.noiseBegin),
_trigger + Core::TimeSpan(_config.signalBegin)
);
}
inline Core::TimeWindow Picker::signalWindow() const {
return Core::TimeWindow(
_trigger + Core::TimeSpan(_config.signalBegin),
_trigger + Core::TimeSpan(_config.signalEnd)
);
}
}
}
#define REGISTER_POSTPICKPROCESSOR_VAR(Class, Service) \
Seiscomp::Core::Generic::InterfaceFactory<Seiscomp::Processing::Picker, Class> __##Class##InterfaceFactory__(Service)
#define REGISTER_POSTPICKPROCESSOR(Class, Service) \
static REGISTER_POSTPICKPROCESSOR_VAR(Class, Service)
#endif

View File

@ -0,0 +1,77 @@
/***************************************************************************
* 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_ARAICPICKER_H
#define SEISCOMP_PROCESSING_ARAICPICKER_H
#include <seiscomp/processing/picker.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API ARAICPicker : public Picker {
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
ARAICPicker();
ARAICPicker(const Core::Time& trigger);
//! D'tor
~ARAICPicker();
// ----------------------------------------------------------------------
// Public Interface
// ----------------------------------------------------------------------
public:
bool setup(const Settings &settings) override;
const std::string &methodID() const override;
const std::string &filterID() const override;
// ----------------------------------------------------------------------
// Protected Interface
// ----------------------------------------------------------------------
protected:
bool calculatePick(int n, const double *data,
int signalStartIdx, int signalEndIdx,
int &triggerIdx, int &lowerUncertainty,
int &upperUncertainty, double &snr,
OPT(Polarity) &polarity) override;
// ----------------------------------------------------------------------
// Private Interface
// ----------------------------------------------------------------------
private:
std::string _filter;
bool _dumpTraces;
};
}
}
#endif

View File

@ -0,0 +1,82 @@
/***************************************************************************
* 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_BKPICKER_H
#define SEISCOMP_PROCESSING_BKPICKER_H
#include <seiscomp/processing/picker.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API BKPicker : public Picker {
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
BKPicker();
BKPicker(const Core::Time& trigger);
//! D'tor
~BKPicker();
// ----------------------------------------------------------------------
// Public Interface
// ----------------------------------------------------------------------
public:
virtual bool setup(const Settings &settings) override;
const std::string &methodID() const override;
const std::string &filterID() const override;
// ----------------------------------------------------------------------
// Protected Interface
// ----------------------------------------------------------------------
protected:
// filter settings
std::string filterType;
int filterPoles; // number of poles
double f1; // bandpass lower cutoff freq. in Hz
double f2; // bandpass upper cutoff freq. in Hz
std::string usedFilter;
// picker parameters
double thrshl1; // threshold to trigger for pick (c.f. paper), default 10
double thrshl2; // threshold for updating sigma (c.f. paper), default 20
int debugOutput;
void bk_wrapper(int n, double *data, int &kmin, double &snr, double samplespersec=120);
bool calculatePick(int n, const double *data,
int signalStartIdx, int signalEndIdx,
int &triggerIdx, int &lowerUncertainty,
int &upperUncertainty, double &snr,
OPT(Polarity) &polarity) override;
};
}
}
#endif

View File

@ -0,0 +1,74 @@
/***************************************************************************
* 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_GFZPICKER_H
#define SEISCOMP_PROCESSING_GFZPICKER_H
#include <seiscomp/processing/picker.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API GFZPicker : public Picker {
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
GFZPicker();
GFZPicker(const Core::Time& trigger);
//! D'tor
~GFZPicker();
// ----------------------------------------------------------------------
// Public Interface
// ----------------------------------------------------------------------
public:
bool setup(const Settings &settings) override;
const std::string &methodID() const override;
const std::string &filterID() const override;
// ----------------------------------------------------------------------
// Protected Interface
// ----------------------------------------------------------------------
protected:
bool calculatePick(int n, const double *data,
int signalStartIdx, int signalEndIdx,
int &triggerIdx, int &lowerUncertainty,
int &upperUncertainty, double &snr,
OPT(Polarity) &polarity) override;
private:
std::string _usedFilter;
};
}
}
#endif

View File

@ -0,0 +1,115 @@
/***************************************************************************
* 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_PROCESSOR_H
#define SEISCOMP_PROCESSING_PROCESSOR_H
#include <seiscomp/config/exceptions.h>
#include <seiscomp/utils/keyvalues.h>
#include <seiscomp/client.h>
namespace Seiscomp {
namespace Config {
class Config;
}
namespace Processing {
struct SC_SYSTEM_CLIENT_API Settings {
Settings(const std::string &module,
const std::string &network,
const std::string &station,
const std::string &location,
const std::string &stream,
const Config::Config *config,
const Util::KeyValues *keys);
//! Returns a parameter value for a station. The first
//! lookup is in the global application configuration
//! with name "key.module.network.station.parameter.
//! If it is not found it tries to lookup the value in
//! keyParameters. If no value is found an exception
//! is thrown otherwise the value is returned.
std::string getString(const std::string &parameter) const;
int getInt(const std::string &parameter) const;
double getDouble(const std::string &parameter) const;
bool getBool(const std::string &parameter) const;
//! Set the parameter value for a station. The first
//! lookup is in the global application configuration
//! with name "key.module.network.station.parameter.
//! If it is not found it tries to lookup the value in
//! keyParameters. If no value is found, false is returned,
//! true otherwise
bool getValue(std::string &value, const std::string &parameter) const;
bool getValue(int &value, const std::string &parameter) const;
bool getValue(double &value, const std::string &parameter) const;
bool getValue(bool &value, const std::string &parameter) const;
const std::string &module;
const std::string &networkCode;
const std::string &stationCode;
const std::string &locationCode;
const std::string &channelCode;
const Config::Config *localConfiguration;
const Util::KeyValues *keyParameters;
};
DEFINE_SMARTPOINTER(Processor);
class SC_SYSTEM_CLIENT_API Processor : public Core::BaseObject {
DECLARE_SC_CLASS(Processor)
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
Processor();
//! D'tor
virtual ~Processor();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
//! This method can be called to initialize the processor.
//! 'parameters' contains simple name-value pairs (strings).
//! The default implementation does nothing.
virtual bool setup(const Settings &settings);
};
}
}
#endif

View File

@ -0,0 +1,106 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* Author: Jan Becker *
* Email: jabe@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_REGIONS_H
#define SEISCOMP_PROCESSING_REGIONS_H
#include <seiscomp/config/config.h>
#include <seiscomp/geo/featureset.h>
namespace Seiscomp {
namespace Processing {
DEFINE_SMARTPOINTER(Regions);
class Regions : public Core::BaseObject {
public:
/**
* @brief Returns the feature which contains the given point
* @param lat The latitude of the reference point
* @param lon The longitude of the reference point
* @return The feature which contains the reference point or null
*/
Geo::GeoFeature *find(double lat, double lon) const;
/**
* @brief Checks whether a given path is contained in
* the region set.
* @param lat0 The latitude of the starting point
* @param lon0 The longitude of the starting point
* @param lat1 The latitude of the end point
* @param lon1 The longitude of the end point
* @param anyFeature If true then the path is allowed to be contained
* in multiple features. If false then the path must
* be contained in a single feature.
* @param samplingDistance The distance of the path sampling. The default
* is 10 km which means that a point each 10 km
* along the path will be checked for containment.
* The lower this value the more precise the
* output but the more expensive in terms of
* CPU cycles. If a value lower than zero or
* equal to zero is passed then only the
* starting point and end point will be checked.
* @return The feature of the starting point or null
*/
Geo::GeoFeature *find(double lat0, double lon0,
double lat1, double lon1,
bool anyFeature = true,
double samplingDistance = 10) const;
/**
* @brief Checks whether a path is contained completely in a given
* feature.
* @param feature The feature to test again.
* @param lat0 The latitude of the starting point
* @param lon0 The longitude of the starting point
* @param lat1 The latitude of the end point
* @param lon1 The longitude of the end point
* @param samplingDistance The distance of the path sampling. The default
* is 10 km which means that a point each 10 km
* along the path will be checked for containment.
* The lower this value the more precise the
* output but the more expensive in terms of
* CPU cycles. If a value lower than zero or
* equal to zero is passed then only the
* starting point and end point will be checked.
* @return true if contained, false otherwise
*/
static bool contains(const Geo::GeoFeature *feature,
double lat0, double lon0,
double lat1, double lon1,
double samplingDistance = 10);
static const Regions *load(const std::string& filename);
public:
Geo::GeoFeatureSet featureSet;
};
}
}
#endif

View File

@ -0,0 +1,200 @@
/***************************************************************************
* 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_RESPONSE_H
#define SEISCOMP_PROCESSING_RESPONSE_H
#include <seiscomp/core/baseobject.h>
#include <seiscomp/core/typedarray.h>
#include <seiscomp/math/restitution/transferfunction.h>
#include <seiscomp/math/filter/seismometers.h>
#include <seiscomp/client.h>
#include <vector>
namespace Seiscomp {
namespace Processing {
DEFINE_SMARTPOINTER(Response);
class SC_SYSTEM_CLIENT_API Response : public Core::BaseObject {
DECLARE_CASTS(Response)
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
// C'tor
Response();
// D'tor
virtual ~Response();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
//! Deconvolves data in the frequency domain.
//! This method incorporates the gain. If no transfer function
//! can be retrieved false is returned.
bool deconvolveFFT(int n, float *inout, double fsamp,
double cutoff,
double min_freq, double max_freq,
int numberOfIntegrations = 0);
bool deconvolveFFT(int n, double *inout, double fsamp,
double cutoff,
double min_freq, double max_freq,
int numberOfIntegrations = 0);
bool deconvolveFFT(FloatArray &inout, double fsamp,
double cutoff,
double min_freq, double max_freq,
int numberOfIntegrations = 0);
bool deconvolveFFT(DoubleArray &inout, double fsamp,
double cutoff,
double min_freq, double max_freq,
int numberOfIntegrations = 0);
//! Returns a transfer function that can be used to deconvolve the
//! data. The transfer function does not incorporate the gain.
//! @param numberOfIntegrations How often to integrate. In case of
//! 'poles and zeros' this will push n
//! additional zeros to 'zeros'.
virtual Math::Restitution::FFT::TransferFunction *
getTransferFunction(int numberOfIntegrations = 0);
};
DEFINE_SMARTPOINTER(ResponsePAZ);
class SC_SYSTEM_CLIENT_API ResponsePAZ : public Response {
DECLARE_CASTS(ResponsePAZ)
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
typedef std::vector<Math::Complex> ComplexArray;
typedef ComplexArray Poles;
typedef ComplexArray Zeros;
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
// C'tor
ResponsePAZ();
// D'tor
virtual ~ResponsePAZ();
// ----------------------------------------------------------------------
// Public attributes
// ----------------------------------------------------------------------
public:
void setNormalizationFactor(const OPT(double)& normalizationFactor);
double normalizationFactor() const;
void setNormalizationFrequency(const OPT(double)& normalizationFrequency);
double normalizationFrequency() const;
void setPoles(const Poles& poles);
const Poles& poles() const;
void setZeros(const Zeros& zeros);
const Zeros& zeros() const;
void convertFromHz();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
Math::Restitution::FFT::TransferFunction *
getTransferFunction(int numberOfIntegrations = 0) override;
// ----------------------------------------------------------------------
// Private interface
// ----------------------------------------------------------------------
private:
OPT(double) _normalizationFactor;
OPT(double) _normalizationFrequency;
Poles _poles;
Zeros _zeros;
};
DEFINE_SMARTPOINTER(ResponseFAP);
class SC_SYSTEM_CLIENT_API ResponseFAP : public Response {
DECLARE_CASTS(ResponseFAP)
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
// C'tor
ResponseFAP();
// D'tor
virtual ~ResponseFAP();
// ----------------------------------------------------------------------
// Public attributes
// ----------------------------------------------------------------------
public:
void setFAPs(const Math::SeismometerResponse::FAPs& faps);
const Math::SeismometerResponse::FAPs& faps() const;
void convertFromHz();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
Math::Restitution::FFT::TransferFunction *
getTransferFunction(int numberOfIntegrations = 0) override;
// ----------------------------------------------------------------------
// Private interface
// ----------------------------------------------------------------------
private:
Math::SeismometerResponse::FAPs _faps;
};
}
}
#endif

View File

@ -0,0 +1,222 @@
/***************************************************************************
* 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_SECONDARYPICKER_H
#define SEISCOMP_PROCESSING_SECONDARYPICKER_H
#include <seiscomp/core/interfacefactory.h>
#include <seiscomp/processing/timewindowprocessor.h>
#include <boost/function.hpp>
namespace Seiscomp {
namespace Processing {
DEFINE_SMARTPOINTER(SecondaryPicker);
class SC_SYSTEM_CLIENT_API SecondaryPicker : public TimeWindowProcessor {
DECLARE_SC_CLASS(SecondaryPicker)
// ----------------------------------------------------------------------
// Public types
// ----------------------------------------------------------------------
public:
//! Configuration structure to store processing dependent
//! settings
struct Config {
double noiseBegin; // start of the noise window to initialize filters
double signalBegin; // start time relative to P pick
double signalEnd; // end time relative to P pick
};
struct Result {
const Record *record;
double snr;
Core::Time time;
double timeLowerUncertainty;
double timeUpperUncertainty;
std::string phaseCode;
std::string filterID;
OPT(double) slowness;
OPT(double) backAzimuth;
};
struct Trigger {
Trigger()
: onsetLowerUncertainty(-1), onsetUpperUncertainty(-1), snr(-1) {}
Core::Time onset;
double onsetLowerUncertainty;
double onsetUpperUncertainty;
OPT(double) slowness;
OPT(double) backAzimuth;
double snr;
};
typedef boost::function<void (const SecondaryPicker*,
const Result &)> PublishFunc;
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
SecondaryPicker();
//! D'tor
~SecondaryPicker();
// ----------------------------------------------------------------------
// Configuration Interface
// ----------------------------------------------------------------------
public:
//! Returns the methodID of the method used to determine
//! the secondary pick.
virtual const std::string &methodID() const = 0;
//! Returns the filter used by concrete implementations
virtual const std::string &filterID() const = 0;
//! Set the start of the noise window relative to the trigger
void setNoiseStart(double start) { _config.noiseBegin = start; }
//! 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; }
//! Returns the current configuration
const Config &config() const { return _config; }
//! This method has to be called when all configuration
//! settings has been set to calculate the timewindow.
void computeTimeWindow() override;
void reset() override;
// ----------------------------------------------------------------------
// Public Interface
// ----------------------------------------------------------------------
public:
//! Sets the trigger used to compute the timewindow to calculate
//! the amplitude.
//! Once a trigger has been set all succeeding calls will fail.
void setTrigger(const Trigger& trigger);
const Trigger &trigger() const { return _trigger; }
/**
* @brief Returns the currently set noise window
*
* This is being computed as trigger + noiseBegin and
* trigger + signalBegin
* @return The time window of the noise
*/
Core::TimeWindow noiseWindow() const;
/**
* @brief Returns the currently set signal window
*
* This is being computed as trigger + signalBegin and
* trigger + signalEnd
* @return The time window of the signal
*/
Core::TimeWindow signalWindow() const;
void setPublishFunction(const PublishFunc& func);
void setReferencingPickID(const std::string&);
const std::string& referencingPickID() const;
// ----------------------------------------------------------------------
// Protected Interface
// ----------------------------------------------------------------------
protected:
//! Zero gap tolerance!
//! The default implementation does not tolerate gaps and does not
//! handle them.
bool handleGap(Filter *filter, const Core::TimeSpan& span,
double lastSample, double nextSample,
size_t missingSamples) override;
//! This method is called when a pick has to be published
void emitPick(const Result &result);
// ----------------------------------------------------------------------
// Protected Members
// ----------------------------------------------------------------------
protected:
Trigger _trigger;
// config
Config _config;
// ----------------------------------------------------------------------
// Private Members
// ----------------------------------------------------------------------
private:
PublishFunc _func;
std::string _pickID;
};
DEFINE_INTERFACE_FACTORY(SecondaryPicker);
inline Core::TimeWindow SecondaryPicker::noiseWindow() const {
return Core::TimeWindow(
_trigger.onset + Core::TimeSpan(_config.noiseBegin),
_trigger.onset + Core::TimeSpan(_config.signalBegin)
);
}
inline Core::TimeWindow SecondaryPicker::signalWindow() const {
return Core::TimeWindow(
_trigger.onset + Core::TimeSpan(_config.signalBegin),
_trigger.onset + Core::TimeSpan(_config.signalEnd)
);
}
}
}
#define REGISTER_SECONDARYPICKPROCESSOR_VAR(Class, Service) \
Seiscomp::Core::Generic::InterfaceFactory<Seiscomp::Processing::SecondaryPicker, Class> __##Class##InterfaceFactory__(Service)
#define REGISTER_SECONDARYPICKPROCESSOR(Class, Service) \
static REGISTER_SECONDARYPICKPROCESSOR_VAR(Class, Service)
#endif

View File

@ -0,0 +1,110 @@
/***************************************************************************
* 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_PICKER_S_AIC_H
#define SEISCOMP_PROCESSING_PICKER_S_AIC_H
#include <seiscomp/processing/secondarypicker.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API SAICPicker : public SecondaryPicker {
// ----------------------------------------------------------------------
// Public types
// ----------------------------------------------------------------------
public:
struct AICConfig {
double threshold;
double minSNR;
double margin;
double timeCorr;
std::string filter;
std::string detecFilter;
};
struct State {
State();
bool aicValid;
double aicStart;
double aicEnd;
Core::Time detection;
Core::Time pick;
double snr;
};
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
SAICPicker(const std::string& methodID, StreamComponent c);
//! D'tor
~SAICPicker();
// ----------------------------------------------------------------------
// Public Interface
// ----------------------------------------------------------------------
public:
void setSaveIntermediate(bool);
const std::string &methodID() const override;
const std::string &filterID() const override;
bool setAicConfig(const AICConfig &config);
//! Returns the current configuration
const AICConfig &aicConfig() const { return _aicConfig; }
const State &state() const { return _state; }
const Result &result() const { return _result; }
//! Returns detection data from noiseBegin if setSaveIntermediate
//! has been enabled before processing started.
const DoubleArray &processedData() const { return _detectionTrace; }
protected:
virtual WaveformOperator* createFilterOperator(Filter* compFilter) = 0;
bool applyConfig();
void fill(size_t n, double *samples) override;
void process(const Record *rec, const DoubleArray &filteredData) override;
private:
bool _initialized;
AICConfig _aicConfig;
State _state;
Result _result;
Filter *_compFilter;
bool _saveIntermediate;
DoubleArray _detectionTrace;
const std::string _methodID;
};
}
}
#endif

View File

@ -0,0 +1,67 @@
/***************************************************************************
* 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_PICKER_S_L2_H
#define SEISCOMP_PROCESSING_PICKER_S_L2_H
#include "S_aic.h"
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API SL2Picker : public SAICPicker {
public:
using L2Config = SAICPicker::AICConfig;
public:
//! C'tor
SL2Picker();
//! D'tor
~SL2Picker();
public:
bool setup(const Settings &settings) override;
bool setL2Config(const AICConfig &config);
//! Returns the current configuration
const L2Config &l2Config() const;
protected:
WaveformOperator* createFilterOperator(Filter* compFilter) override;
};
inline bool SL2Picker::setL2Config(const AICConfig &config) {
return setAicConfig(config);
}
inline const SL2Picker::L2Config &SL2Picker::l2Config() const {
return aicConfig();
}
}
}
#endif

View File

@ -0,0 +1,49 @@
/***************************************************************************
* 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_PICKER_S_V_H
#define SEISCOMP_PROCESSING_PICKER_S_V_H
#include "S_aic.h"
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API SVPicker : public SAICPicker {
public:
//! C'tor
SVPicker();
//! D'tor
~SVPicker();
bool setup(const Settings &settings) override;
protected:
WaveformOperator* createFilterOperator(Filter* compFilter) override;
};
}
}
#endif

View File

@ -0,0 +1,89 @@
/***************************************************************************
* 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_SENSOR_H
#define SEISCOMP_PROCESSING_SENSOR_H
#include <seiscomp/core/baseobject.h>
#include <seiscomp/processing/response.h>
#include <seiscomp/client.h>
namespace Seiscomp {
namespace Processing {
DEFINE_SMARTPOINTER(Sensor);
class SC_SYSTEM_CLIENT_API Sensor : public Core::BaseObject {
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
Sensor();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
void setModel(const std::string& model);
const std::string& model() const;
void setManufacturer(const std::string& manufacturer);
const std::string& manufacturer() const;
void setType(const std::string& type);
const std::string& type() const;
void setUnit(const std::string& unit);
const std::string& unit() const;
void setLowFrequency(const OPT(double)& lowFrequency);
double lowFrequency() const;
void setHighFrequency(const OPT(double)& highFrequency);
double highFrequency() const;
Response *response() const;
void setResponse(Response *response);
// ----------------------------------------------------------------------
// Members
// ----------------------------------------------------------------------
private:
ResponsePtr _response;
std::string _model;
std::string _manufacturer;
std::string _type;
std::string _unit;
OPT(double) _lowFrequency;
OPT(double) _highFrequency;
};
}
}
#endif

View File

@ -0,0 +1,105 @@
/***************************************************************************
* 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_STREAM_H
#define SEISCOMP_PROCESSING_STREAM_H
#include <seiscomp/core/baseobject.h>
#include <seiscomp/core/timewindow.h>
#include <seiscomp/processing/sensor.h>
namespace Seiscomp {
namespace DataModel {
class Stream;
}
namespace Processing {
DEFINE_SMARTPOINTER(Stream);
class SC_SYSTEM_CLIENT_API Stream : public Core::BaseObject {
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
Stream();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
//! Initialized the stream meta data from the inventory
//! if available
void init(const std::string &networkCode,
const std::string &stationCode,
const std::string &locationCode,
const std::string &channelCode,
const Core::Time &time);
void init(const DataModel::Stream *stream);
void setCode(const std::string &code);
const std::string &code() const;
Sensor *sensor() const;
void setSensor(Sensor *sensor);
//! Applies the gain the data.
void applyGain(int n, double *inout);
void applyGain(DoubleArray &inout);
//! Removes the gain the data.
void removeGain(int n, double *inout);
void removeGain(DoubleArray &inout);
public:
Core::TimeWindow epoch;
double gain;
OPT(double) gainFrequency;
std::string gainUnit;
double azimuth;
double dip;
// ----------------------------------------------------------------------
// Members
// ----------------------------------------------------------------------
private:
// Sensor information
SensorPtr _sensor;
// Stream code
std::string _code;
};
}
}
#endif

View File

@ -0,0 +1,136 @@
/***************************************************************************
* 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_STREAMBUFFER_H
#define SEISCOMP_PROCESSING_STREAMBUFFER_H
#include <string>
#include <list>
#include <seiscomp/core/recordsequence.h>
#include <seiscomp/client.h>
namespace Seiscomp {
namespace Processing {
class SC_SYSTEM_CLIENT_API StreamBuffer {
// ----------------------------------------------------------------------
// Public Types
// ----------------------------------------------------------------------
public:
struct SC_SYSTEM_CLIENT_API WaveformID {
WaveformID(const std::string &net, const std::string &sta,
const std::string &loc, const std::string &cha)
: networkCode(net), stationCode(sta)
, locationCode(loc), channelCode(cha)
{}
WaveformID(const Record *rec)
: networkCode(rec->networkCode())
, stationCode(rec->stationCode())
, locationCode(rec->locationCode())
, channelCode(rec->channelCode())
{}
bool operator<(const WaveformID& other) const {
if ( networkCode < other.networkCode ) return true;
if ( networkCode > other.networkCode ) return false;
if ( stationCode < other.stationCode ) return true;
if ( stationCode > other.stationCode ) return false;
if ( locationCode < other.locationCode ) return true;
if ( locationCode > other.locationCode ) return false;
return channelCode < other.channelCode;
}
std::string networkCode;
std::string stationCode;
std::string locationCode;
std::string channelCode;
};
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! Creates streambuffer with no type yet
//! use setTimeWindow or setTimeSpan before using it
StreamBuffer();
//! Creates a timewindow buffer
StreamBuffer(const Core::TimeWindow &timeWindow);
//! Creates a ringbuffer
StreamBuffer(const Core::TimeSpan &timeSpan);
~StreamBuffer();
// ----------------------------------------------------------------------
// Interface
// ----------------------------------------------------------------------
public:
void setTimeWindow(const Core::TimeWindow &timeWindow);
void setTimeSpan(const Core::TimeSpan &timeSpan);
RecordSequence *sequence(const WaveformID &wid) const;
RecordSequence *feed(const Record *rec);
bool addedNewStream() const;
void printStreams(std::ostream &os = std::cout) const;
std::list<std::string> getStreams() const;
//! Clears the streambuffer and removes all cached records
void clear();
// ----------------------------------------------------------------------
// Members
// ----------------------------------------------------------------------
private:
enum Mode {
TIME_WINDOW,
RING_BUFFER
};
using SequenceMap = std::map<WaveformID, RecordSequence*>;
Mode _mode;
Seiscomp::Core::Time _timeStart;
Seiscomp::Core::TimeSpan _timeSpan;
SequenceMap _sequences;
bool _newStreamAdded;
};
}
}
#endif

View File

@ -0,0 +1,102 @@
/***************************************************************************
* 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_TIMEWINDOWPROCESSOR
#define SEISCOMP_PROCESSING_TIMEWINDOWPROCESSOR
#include <seiscomp/core/recordsequence.h>
#include <seiscomp/processing/waveformprocessor.h>
namespace Seiscomp {
namespace Processing {
DEFINE_SMARTPOINTER(TimeWindowProcessor);
class SC_SYSTEM_CLIENT_API TimeWindowProcessor : public WaveformProcessor {
DECLARE_SC_CLASS(TimeWindowProcessor)
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
TimeWindowProcessor();
//! D'tor
~TimeWindowProcessor();
// ----------------------------------------------------------------------
// Public Interface
// ----------------------------------------------------------------------
public:
void reset() override;
//! Sets the time window for the data to be fed
void setTimeWindow(const Core::TimeWindow &tw);
const Core::TimeWindow &timeWindow() const;
//! Returns the time window including the safety
//! margin.
const Core::TimeWindow &safetyTimeWindow() const;
//! Sets the timewindow margin added to the timewindow
//! when feeding the data into the processor. The default
//! margin are 60 seconds.
void setMargin(const Core::TimeSpan&);
const Core::TimeSpan &margin() const;
//! Derived classes should implement this method to
//! compute their needed timewindow
virtual void computeTimeWindow() {}
//! Returns the continuous data for the requested timewindow
const DoubleArray &continuousData() const;
// ----------------------------------------------------------------------
// Protected Interface
// ----------------------------------------------------------------------
protected:
void fill(size_t n, double *samples) override;
bool store(const Record *rec) override;
// ----------------------------------------------------------------------
// Members
// ----------------------------------------------------------------------
protected:
DoubleArray _data;
private:
Core::TimeWindow _timeWindow;
Core::TimeWindow _safetyTimeWindow;
Core::TimeSpan _safetyMargin;
};
}
}
#endif

View File

@ -0,0 +1,85 @@
/***************************************************************************
* 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_WAVEFORMPIPE_H
#define SEISCOMP_PROCESSING_WAVEFORMPIPE_H
#include <seiscomp/core/baseobject.h>
#include <seiscomp/core/record.h>
#include <seiscomp/processing/waveformprocessor.h>
#include <boost/function.hpp>
namespace Seiscomp {
namespace Processing {
DEFINE_SMARTPOINTER(WaveformOperator);
//! WaveformPipe declares an interface to modify/manipulate/combine
//! records. It can be used to rotate 3 components or to combine
//! two horizontal components into a single component.
class SC_SYSTEM_CLIENT_API WaveformOperator : public Core::BaseObject {
public:
typedef boost::function<bool (const Record *)> StoreFunc;
WaveformOperator();
virtual ~WaveformOperator();
public:
//! Sets the storage function called when a new records is
//! available.
void setStoreFunc(const StoreFunc &func);
//! Connects the output of op1 with input of op2. Calls setStoreFunc
//! on op1.
static void connect(WaveformOperator *op1, WaveformOperator *op2);
//! Feeds a record. In case a status value larger that Terminated
//! (which indicates an error) is returned, it is populated
//! into the WaveformProcessor's status.
virtual WaveformProcessor::Status feed(const Record *record) = 0;
//! Resets the operator.
virtual void reset() = 0;
protected:
bool store(const Record *rec) {
if ( _func ) return _func(rec);
return false;
}
private:
StoreFunc _func;
};
}
}
#endif

View File

@ -0,0 +1,421 @@
/***************************************************************************
* 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_WAVEFORMPROCESSOR_H
#define SEISCOMP_PROCESSING_WAVEFORMPROCESSOR_H
#include <seiscomp/core/record.h>
#include <seiscomp/core/recordsequence.h>
#include <seiscomp/core/typedarray.h>
#include <seiscomp/core/enumeration.h>
#include <seiscomp/math/filter.h>
#include <seiscomp/processing/processor.h>
#include <seiscomp/processing/stream.h>
namespace Seiscomp {
namespace Processing {
DEFINE_SMARTPOINTER(WaveformOperator);
DEFINE_SMARTPOINTER(WaveformProcessor);
class SC_SYSTEM_CLIENT_API WaveformProcessor : public Processor {
DECLARE_SC_CLASS(WaveformProcessor)
// ----------------------------------------------------------------------
// Public types
// ----------------------------------------------------------------------
public:
enum Component {
VerticalComponent = 0, /* usually Z */
FirstHorizontalComponent = 1, /* usually N */
SecondHorizontalComponent = 2 /* usually E */
};
enum StreamComponent {
Vertical = 0, /* usually Z */
FirstHorizontal = 1, /* usually N */
SecondHorizontal = 2, /* usually E */
Horizontal, /* usually N + E */
Any /* all available components */
};
typedef Math::Filtering::InPlaceFilter<double> Filter;
MAKEENUM(
SignalUnit,
EVALUES(
//! Displacement
Meter,
//! Velocity
MeterPerSecond,
//! Acceleration
MeterPerSecondSquared
),
// SEED names: see SEEDManual, ch.5 / 34, p.47
ENAMES(
"M",
"M/S",
"M/S**2"
)
);
MAKEENUM(
Status,
EVALUES(
//! No associated value
WaitingForData,
//! Associated value is progress in [0,100]
InProgress,
//! Associated value is 100
Finished,
//! Associated value is the last status
Terminated,
//! Associated value is the failed snr value
LowSNR,
//! No associated value yet
QCError,
//! Data is clipped
DataClipped,
//! Error during deconvolution
DeconvolutionFailed,
//! Distance hint is out of range to continue processing
DistanceOutOfRange,
//! Depth hint is out of range to continue processing
DepthOutOfRange,
//! Unit is not supported, e.g. m/s <> m/s**2
IncompatibleUnit,
//! Orientation missing
MissingOrientation,
//! Gain missing
MissingGain,
//! Response missing
MissingResponse,
//! Sampling frequency does not match. Either records of
//! one trace have different sampling frequencies or
//! the sampling frequencies of different channels do not match.
InvalidSamplingFreq,
//! No associated value yet (error code?)
Error,
// -- The following enumerations were added with API 12 ---
//! No distance hint set
MissingDistance,
//! No depth hint set
MissingDepth,
//! No time hint set
MissingTime,
//! No hypocenter (Origin) given
MissingHypocenter,
//! No receiver (SensorLocation) given
MissingReceiver,
//! No pick (Pick) given
MissingPick,
//! Metadata is incomplete, e.g. a particualr stream attribute
//! is not set or empty
IncompleteMetadata,
//! The epicentre is out of supported regions
EpicenterOutOfRegions,
//! The receiver is out of supported regions
ReceiverOutOfRegions,
//! The entire raypath does not lie entirely in the supported
//! regions
RayPathOutOfRegions,
//! Travel time table lookup failed
TravelTimeEstimateFailed,
//! Arrival has not been found
ArrivalNotFound,
//! Configuration error
ConfigurationError
),
ENAMES(
"waiting for data",
"in progress",
"finished",
"terminated",
"low SNR",
"QC error",
"data clipped",
"deconvolution failed",
"distance out of range",
"depth out of range",
"incompatible unit",
"missing orientation",
"missing gain",
"missing response",
"invalid sampling frequency",
"error",
"missing distance hint",
"missing depth hint",
"missing time hint",
"missing hypocenter",
"missing receiver",
"missing pick",
"incomplete metadata",
"epicenter out of regions",
"receiver out of regions",
"ray path out of regions",
"travel time estimate failed",
"arrival not found",
"configuration error"
)
);
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
WaveformProcessor(const Core::TimeSpan &initTime=0.0,
const Core::TimeSpan &gapThreshold=0.1);
//! D'tor
virtual ~WaveformProcessor();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
//! Call this method in derived classes to make sure
//! the filters samplingFrequency will be set correctly
//! The feed method filters the data according to the
//! set filter and calls process.
//! NOTE: This method does not distinguish between different
//! channelcodes. Its just feeds what it gets into the
//! data array. If multiple channels need to be combined
//! this method must be reimplemented.
virtual bool feed(const Record *record);
//! Convenience function to feed a whole record sequence into
//! a WaveformProcessor.
//! feed(const Record *) is used to feed a single record
//! @return The number of records successfully fed
int feedSequence(const RecordSequence *sequence);
//! Sets a userdata pointer that is managed by the processor
//! (stored inside a SmartPointer).
void setUserData(Core::BaseObject *obj) const;
//! Returns the set userdata object. This object must not be
//! deleted by the caller. It is managed by the processor and
//! dereferenced (and deleted) automatically. But the
//! caller may hold a SmartPointer to that object.
Core::BaseObject *userData() const;
//! Sets up the waveform processor. By default it reads whether
//! to check for data saturation or not
virtual bool setup(const Settings &settings) override;
//! Initialize the filter for the given sampling frequency
virtual void initFilter(double fsamp);
//! Sets the filter to apply
virtual void setFilter(Filter *filter);
//! Sets a operator for all fed records. An operator sits between
//! feed and store.
void setOperator(WaveformOperator *pipe);
WaveformOperator *getOperator() const;
//! The gain is input unit -> sensor unit
Stream &streamConfig(Component c);
const Stream &streamConfig(Component c) const;
//! Sets the component to use to calculate the amplitude for
void setUsedComponent(StreamComponent c) { _usedComponent = c; }
//! Returns the used component
StreamComponent usedComponent() const { return _usedComponent; }
//! Sets the maximal gap length in seconds for that
//! missing samples are handled or tolerated. Default: no tolerance
void setGapTolerance(const Core::TimeSpan &length);
const Core::TimeSpan &gapTolerance() const;
//! Enables/disables the linear interpolation of missing samples
//! inside a set gap tolerance
void setGapInterpolationEnabled(bool enable);
bool isGapInterpolationEnabled() const;
//! Enables saturation check of absolute values of incoming samples and
//! sets the status to DataClipped if checked positive. The data
//! is checked in the fill method. If derived classes reimplement
//! this method without calling this implementation, the check is
//! not performed.
void setSaturationCheckEnabled(bool enable);
//! Sets the saturation threshold. The default is -1
void setSaturationThreshold(double t);
//! Returns whether saturation check is enabled
bool isSaturationCheckEnabled() const;
//! Returns the saturation threshold that is applied if saturation
//! check is enabled.
double saturationThreshold() const { return _saturationThreshold; }
/**
* @brief Resets the processing state
*
* This method resets the current processing states back to as if
* wouldn't have received any data yet. It not *not* meant to reset
* the processors configuration to its defaults. This method is going
* to be called when e.g. gaps are detected.
*/
virtual void reset();
//! Returns the data's sampling frequency
double samplingFrequency() const;
void setEnabled(bool e);
bool isEnabled() const { return _enabled; }
//! Returns the timewindow of already processed data
Core::TimeWindow dataTimeWindow() const;
//! Returns the last fed record
const Record *lastRecord() const;
//! Returns the current status of the processor
Status status() const;
//! Returns the value associated with the status
double statusValue() const;
//! Terminates the processor ignoring its current state
void terminate();
//! Default implementation returns if the status if greater
//! than InProgress.
virtual bool isFinished() const;
//! Closes the processor meaning that no more records
//! are going to be fed in. The processing has been finished.
virtual void close() const;
// ----------------------------------------------------------------------
// Protected interface
// ----------------------------------------------------------------------
protected:
//! Callback methods to react on changes of the
//! enable state
virtual void disabled() {}
virtual void enabled() {}
//! Virtual method that must be used in derived classes to analyse
//! a datastream.
//! It gives the raw record and the filtered data array as parameter.
virtual void process(const Record *record,
const DoubleArray &filteredData) = 0;
//! Handles gaps. Returns whether the gap has been handled or not.
virtual bool handleGap(Filter *filter, const Core::TimeSpan&,
double lastSample, double nextSample,
size_t missingSamples);
virtual void fill(size_t n, double *samples);
virtual bool store(const Record *rec);
void setStatus(Status status, double value);
bool parseSaturationThreshold(const Settings &settings,
const std::string &optionName);
void setupStream(double fsamp);
// ----------------------------------------------------------------------
// Members
// ----------------------------------------------------------------------
protected:
//! Describes the current state of a component (e.g. Z or N)
struct StreamState {
StreamState();
~StreamState();
//! Value of the last sample
double lastSample;
//! Number of samples required to finish initialization
size_t neededSamples;
//! Number of samples already received
size_t receivedSamples;
//! Initialization state
bool initialized;
//! The last received record on this component
RecordCPtr lastRecord;
//! The complete processed data time window so far
Core::TimeWindow dataTimeWindow;
//! The sampling frequency of the component
double fsamp;
//! The filter (if used)
Filter *filter;
};
bool _enabled;
Core::TimeSpan _initTime;
//! threshold to recognize a gap
Core::TimeSpan _gapThreshold;
//! gap length to tolerate
Core::TimeSpan _gapTolerance;
//! default: false
bool _enableSaturationCheck;
double _saturationThreshold;
//! default: false
bool _enableGapInterpolation;
StreamState _stream;
//! default: vertical
StreamComponent _usedComponent;
Stream _streamConfig[3];
private:
Status _status;
double _statusValue;
WaveformOperatorPtr _operator;
mutable Core::BaseObjectPtr _userData;
};
inline WaveformOperator *WaveformProcessor::getOperator() const {
return _operator.get();
}
}
}
#endif