[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,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