Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 96 additions & 72 deletions apps/processing/scautopick/picker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,116 +518,140 @@ bool App::init() {

for ( StationConfig::const_iterator it = _stationConfig.begin();
it != _stationConfig.end(); ++it ) {

const string& cfgNet = it->first.first;
const string& cfgSta = it->first.second;
const string& cfgLoc = it->second.locationCode;
const string& cfgCha = it->second.channel;

auto addDataChannel =
[this, cfgNet, cfgSta, cfgLoc, &subscribeStreams](const string & cha, bool verbose=true) {
string streamID = cfgNet + "." + cfgSta + "." + cfgLoc + "." + cha;
if ( subscribeStreams.find(streamID) == subscribeStreams.end() ) {
if (verbose) {
SEISCOMP_DEBUG("Adding data channel %s", streamID.c_str());
}
recordStream()->addStream(cfgNet, cfgSta, cfgLoc, cha);
subscribeStreams.insert(streamID);
}
};

// Ignore wildcards
if ( it->first.first == "*" ) continue;
if ( it->first.second == "*" ) continue;
if ( cfgNet == "*" ) continue;
if ( cfgSta == "*" ) continue;

// Ignore undefined channels
if ( it->second.channel.empty() ) continue;
if ( cfgCha.empty() ) continue;

// Ignore disabled channels
if ( !it->second.enabled ) {
SEISCOMP_INFO("Detector on station %s.%s disabled by config",
it->first.first, it->first.second);
cfgNet, cfgSta);
continue;
}

DataModel::SensorLocation *loc =
Client::Inventory::Instance()->getSensorLocation(it->first.first, it->first.second, it->second.locationCode, now);
bool isFixedChannel = cfgCha.size() > 2;
string compZFallback; // to be determined below

if ( _config.playback && inv ) {
// Figure out all historic epochs for locations and channels and
// subscribe to all channels covering all epochs. This is only
// required in playback mode if historic data is fed into the picker
// and where the current time check does not apply.

set<string> zCompAcrossEpochs;
for ( size_t n = 0; n < inv->networkCount(); ++n ) {
DataModel::Network *net = inv->network(n);
if ( net->code() != cfgNet ) continue;

for ( size_t s = 0; s < net->stationCount(); ++s ) {
DataModel::Station *sta = net->station(s);
if ( sta->code() != cfgSta ) continue;

string channel = it->second.channel;
char compCode = 'Z';
bool isFixedChannel = channel.size() > 2;
for ( size_t l = 0; l < sta->sensorLocationCount(); ++l ) {
DataModel::SensorLocation *loc = sta->sensorLocation(l);
if ( loc->code() != cfgLoc ) continue;

Core::Time epoch;
for ( size_t c = 0; c < loc->streamCount(); ++c ) {
DataModel::Stream *cha = loc->stream(c);
if ( cfgCha.compare(0, 2, cha->code(), 0, 2) != 0 ) continue;

addDataChannel(cha->code());

// if the bindings do not provide a fixed channel, check the
// vertical component for the current epoch
if ( !isFixedChannel && cha->start() != epoch) {
epoch = cha->start();
DataModel::Stream *compZ =
DataModel::getVerticalComponent(loc, cfgCha.c_str(), epoch);
if ( compZ ) {
zCompAcrossEpochs.insert(compZ->code());
}
}
}
}
}
}

// Verify the consistency of vertical components across epochs and use
// that as fall back component
if ( zCompAcrossEpochs.size() == 1 ) {
compZFallback = *zCompAcrossEpochs.begin();
}
else if ( zCompAcrossEpochs.size() > 1 ) {
string streamID = cfgNet + "." + cfgSta + "." + cfgLoc + "." + cfgCha;
SEISCOMP_ERROR(
"Ambiguous vertical channel across epochs for %s. Please configure a "
"fixed component.", streamID.c_str());
}
}

DataModel::SensorLocation *loc =
Client::Inventory::Instance()->getSensorLocation(cfgNet, cfgSta, cfgLoc, now);

DataModel::ThreeComponents chan;

if ( loc )
DataModel::getThreeComponents(chan, loc, it->second.channel.substr(0,2).c_str(), now);
if ( loc ) {
DataModel::getThreeComponents(chan, loc, cfgCha.substr(0,2).c_str(), now);
}

DataModel::Stream *compZ = chan.comps[DataModel::ThreeComponents::Vertical];
DataModel::Stream *compN = chan.comps[DataModel::ThreeComponents::FirstHorizontal];
DataModel::Stream *compE = chan.comps[DataModel::ThreeComponents::SecondHorizontal];

string channel = cfgCha;

if ( !isFixedChannel ) {
if ( compZ )
if ( compZ ) {
channel = compZ->code();
else
channel += compCode;
} else if ( !compZFallback.empty() ) {
channel = compZFallback;
} else {
channel = channel + 'Z';
}
}

std::string streamID = it->first.first + "." + it->first.second + "." + it->second.locationCode + "." + channel;
std::string streamID = cfgNet + "." + cfgSta + "." + cfgLoc + "." + channel;

SEISCOMP_INFO("Adding detection channel %s", streamID);

_streamIDs.insert(streamID);
subscribeStreams.insert(streamID);

recordStream()->addStream(it->first.first, it->first.second, it->second.locationCode, channel);
addDataChannel(channel, false);

if ( compZ && acquireComps[0] ) {
streamID = it->first.first + "." + it->first.second + "." + it->second.locationCode + "." + compZ->code();
if ( subscribeStreams.find(streamID) == subscribeStreams.end() ) {
SEISCOMP_DEBUG("Adding data channel %s", streamID);
recordStream()->addStream(it->first.first, it->first.second, it->second.locationCode, compZ->code());
subscribeStreams.insert(streamID);
}
addDataChannel(compZ->code());
}

if ( compN && acquireComps[1] ) {
streamID = it->first.first + "." + it->first.second + "." + it->second.locationCode + "." + compN->code();
if ( subscribeStreams.find(streamID) == subscribeStreams.end() ) {
SEISCOMP_DEBUG("Adding data channel %s", streamID);
recordStream()->addStream(it->first.first, it->first.second, it->second.locationCode, compN->code());
subscribeStreams.insert(streamID);
}
addDataChannel(compN->code());
}

if ( compE && acquireComps[2] ) {
streamID = it->first.first + "." + it->first.second + "." + it->second.locationCode + "." + compE->code();
if ( subscribeStreams.find(streamID) == subscribeStreams.end() ) {
SEISCOMP_DEBUG("Adding data channel %s", streamID);
recordStream()->addStream(it->first.first, it->first.second, it->second.locationCode, compE->code());
subscribeStreams.insert(streamID);
}
}

if ( _config.playback && inv ) {
// Figure out all historic epochs for locations and channels and
// subscribe to all channels covering all epochs. This is only
// required in playback mode if historic data is fed into the picker
// and where the current time check does not apply.

for ( size_t n = 0; n < inv->networkCount(); ++n ) {
DataModel::Network *net = inv->network(n);
if ( net->code() != it->first.first ) continue;

for ( size_t s = 0; s < net->stationCount(); ++s ) {
DataModel::Station *sta = net->station(s);
if ( sta->code() != it->first.second ) continue;

for ( size_t l = 0; l < sta->sensorLocationCount(); ++l ) {
DataModel::SensorLocation *loc = sta->sensorLocation(l);
if ( loc->code() != it->second.locationCode ) continue;

for ( size_t c = 0; c < loc->streamCount(); ++c ) {
DataModel::Stream *cha = loc->stream(c);

if ( it->second.channel.compare(0, 2, cha->code(), 0, 2) == 0 ) {
streamID = it->first.first + "." + it->first.second + "." + it->second.locationCode + "." + cha->code();
if ( subscribeStreams.find(streamID) == subscribeStreams.end() ) {
SEISCOMP_DEBUG("Adding data channel %s", streamID.c_str());
recordStream()->addStream(it->first.first, it->first.second, it->second.locationCode, cha->code());
subscribeStreams.insert(streamID);
}
}
}
}
}
}
addDataChannel(compE->code());
}
}


if ( _streamIDs.empty() ) {
if ( _config.useAllStreams )
SEISCOMP_INFO("No stations added (empty module configuration?)");
Expand Down