bool CalculateAmplitudes::process() { //_ui.btnOK->setEnabled(false); _processors.clear(); _ui.table->setRowCount(0); Core::TimeWindow acTimeWindow; if ( !_origin || (_recomputeAmplitudes && !_thread) ) return false; if ( _amplitudeTypes.empty() ) return false; _timeWindow = Core::TimeWindow(); /* TypeSet wantedAmpTypes; wantedAmpTypes.insert("MLv"); wantedAmpTypes.insert("mb"); wantedAmpTypes.insert("mB"); wantedAmpTypes.insert("Mwp"); try { vector<string> amps = SCApp->configGetStrings("amplitudes"); wantedAmpTypes.clear(); wantedAmpTypes.insert(amps.begin(), amps.end()); } catch (...) {} */ QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); if ( _thread ) _thread->connect(); typedef pair<PickCPtr, double> PickStreamEntry; // Typedef a pickmap that maps a streamcode to a pick typedef map<string, PickStreamEntry> PickStreamMap; // This map is needed to find the earliest P pick of // a certain stream PickStreamMap pickStreamMap; for ( size_t i = 0; i < _origin->arrivalCount(); ++i ) { Arrival *ar = _origin->arrival(i); double weight = 1.; try { weight = ar->weight(); } catch (Seiscomp::Core::ValueException) {} if ( Util::getShortPhaseName(ar->phase().code()) != 'P' || weight < 0.5 ) { continue; } Pick *pick = Pick::Find(ar->pickID()); if ( !pick ) { // cerr << " - Skipping arrival " << i << " -> no pick found" << endl; continue; } double dist = -1; try { dist = ar->distance(); } catch ( Core::ValueError &e ) { try { Client::StationLocation loc; double azi1, azi2; loc = Client::Inventory::Instance()->stationLocation(pick->waveformID().networkCode(), pick->waveformID().stationCode(), pick->time().value()); Math::Geo::delazi(loc.latitude, loc.longitude, _origin->latitude(), _origin->longitude(), &dist, &azi1, &azi2); } catch ( Core::GeneralException &e ) {} } DataModel::WaveformStreamID wfid = pick->waveformID(); // Strip the component code because every AmplitudeProcessor // will use its own component to pick the amplitude on wfid.setChannelCode(wfid.channelCode().substr(0,2)); string streamID = waveformIDToStdString(wfid); PickStreamEntry &e = pickStreamMap[streamID]; // When there is already a pick registered for this stream which has // been picked earlier, ignore the current pick if ( e.first && e.first->time().value() < pick->time().value() ) continue; e.first = pick; e.second = dist; } for ( PickStreamMap::iterator it = pickStreamMap.begin(); it != pickStreamMap.end(); ++it ) { PickCPtr pick = it->second.first; double dist = it->second.second; _ui.comboFilterType->clear(); _ui.comboFilterType->addItem("- Any -"); for ( TypeSet::iterator ita = _amplitudeTypes.begin(); ita != _amplitudeTypes.end(); ++ita ) _ui.comboFilterType->addItem(ita->c_str()); if ( _recomputeAmplitudes ) { for ( TypeSet::iterator ita = _amplitudeTypes.begin(); ita != _amplitudeTypes.end(); ++ita ) addProcessor(*ita, pick.get(), dist); } else { string streamID = waveformIDToStdString(pick->waveformID()); TypeSet usedTypes; if ( !_amplitudes.empty() ) { iterator_range itp; itp = _amplitudes.equal_range(pick->publicID()); for ( iterator it = itp.first; it != itp.second; ) { AmplitudePtr amp = it->second.first; // The amplitude type is not one of the wanted types if ( _amplitudeTypes.find(amp->type()) == _amplitudeTypes.end() ) { ++it; continue; } // Already has an amplitude of this type processed if ( usedTypes.find(amp->type()) != usedTypes.end() ) { ++it; continue; } usedTypes.insert(amp->type()); int row = addProcessingRow(waveformIDToStdString(amp->waveformID()), amp->type()); setMessage(row, "read from cache"); setValue(row, amp->amplitude().value()); ++it; } } bool foundAmplitudes = false; if ( _externalAmplitudeCache ) { iterator_range itp; itp = _externalAmplitudeCache->equal_range(pick->publicID()); for ( iterator ita = itp.first; ita != itp.second; ++ita ) { AmplitudePtr amp = ita->second.first; // The amplitude type is not one of the wanted types if ( _amplitudeTypes.find(amp->type()) == _amplitudeTypes.end() ) continue; // Already has an amplitude of this type processed if ( usedTypes.find(amp->type()) != usedTypes.end() ) { checkPriority(ita->second); continue; } usedTypes.insert(amp->type()); int row = addProcessingRow(waveformIDToStdString(amp->waveformID()), amp->type()); setMessage(row, "read from cache"); setValue(row, amp->amplitude().value()); _amplitudes.insert(PickAmplitudeMap::value_type(ita->first, ita->second)); } } if ( _query && !foundAmplitudes ) { DatabaseIterator it = _query->getAmplitudesForPick(pick->publicID()); for ( ; *it; ++it ) { AmplitudePtr amp = Amplitude::Cast(*it); if ( !amp ) continue; foundAmplitudes = true; // The amplitude type is not one of the wanted types if ( _amplitudeTypes.find(amp->type()) == _amplitudeTypes.end() ) continue; // Already has an amplitude of this type processed if ( usedTypes.find(amp->type()) != usedTypes.end() ) { checkPriority(AmplitudeEntry(amp, false)); continue; } usedTypes.insert(amp->type()); int row = addProcessingRow(waveformIDToStdString(amp->waveformID()), amp->type()); setMessage(row, "read from database"); setValue(row, amp->amplitude().value()); _amplitudes.insert(PickAmplitudeMap::value_type(pick->publicID(), AmplitudeEntry(amp, false))); } } if ( !foundAmplitudes ) { EventParameters *ep = EventParameters::Cast(PublicObject::Find("EventParameters")); if ( ep ) { for ( size_t i = 0; i < ep->amplitudeCount(); ++i ) { Amplitude *amp = ep->amplitude(i); if ( amp->pickID() != pick->publicID() ) continue; // The amplitude type is not one of the wanted types if ( _amplitudeTypes.find(amp->type()) == _amplitudeTypes.end() ) continue; // Already has an amplitude of this type processed if ( usedTypes.find(amp->type()) != usedTypes.end() ) { checkPriority(AmplitudeEntry(amp, false)); continue; } usedTypes.insert(amp->type()); int row = addProcessingRow(waveformIDToStdString(amp->waveformID()), amp->type()); setMessage(row, "read from memory"); setValue(row, amp->amplitude().value()); _amplitudes.insert(PickAmplitudeMap::value_type(pick->publicID(), AmplitudeEntry(amp, false))); } } } TypeSet remainingTypes; set_difference(_amplitudeTypes.begin(), _amplitudeTypes.end(), usedTypes.begin(), usedTypes.end(), inserter(remainingTypes, remainingTypes.begin())); for ( TypeSet::iterator ita = remainingTypes.begin(); ita != remainingTypes.end(); ++ita ) { if ( _thread ) addProcessor(*ita, pick.get(), dist); else { int row = addProcessingRow(streamID, *ita); setError(row, "missing"); } } } } _ui.table->resizeColumnsToContents(); _ui.table->resizeRowsToContents(); if ( _thread && _timeWindow ) { _thread->setTimeWindow(_timeWindow); _thread->start(); } //else // _ui.btnOK->setEnabled(true); QApplication::restoreOverrideCursor(); return true; }
/*! \brief Extract information from event object. \param event Seiscomp3 type Event */ void VsMagnitude::handleEvent(Event *event) { _cache.feed(event); double dmax = 0; // dmax distance of the furthest picked station from the epicenter double davg = 0; // average distance of all picked stations from the epicenter double dsum = 0; // sum of distances double dthresh; /// get the preferred origin of the event OriginPtr org = _cache.get<Origin>(event->preferredOriginID()); if ( !org ) { SEISCOMP_WARNING("Object %s not found in cache\nIs the cache size big enough?\n" "Have you subscribed to all necessary message groups?", event->preferredOriginID().c_str()); return; } /// search for the corresponding VsEvent in the cache VsEventPtr vsevent; VsEvents::iterator it = _events.find(event->publicID()); if ( it == _events.end() ) { /// if not found, create a new VsEvent vsevent = new VsEvent; if ( _expirationTimeReference == "ct" ) { vsevent->expirationTime = _currentTime + Core::TimeSpan(_eventExpirationTime, 0); } else if ( _expirationTimeReference == "ot" ) { vsevent->expirationTime = org->time().value() + Core::TimeSpan(_eventExpirationTime, 0); if ( !(_currentTime < vsevent->expirationTime) ) return; } // set time to track how long it takes to estimate the magnitude // and how long it took for the origin to arrive vsevent->originArrivalTime = Core::Time::GMT(); vsevent->originCreationTime = org->creationInfo().creationTime(); // check whether event has been published already EventIDBuffer::iterator cev = _publishedEvents.find(event->publicID()); if ( cev != _publishedEvents.end() ) { SEISCOMP_DEBUG("Event %s has already been published", event->publicID().c_str()); return; } vsevent->update = -1; vsevent->maxAzGap = _maxazgap; /// ...and attach it to the cache (_events) _events[event->publicID()] = vsevent; } /// if found, use the existing one else vsevent = it->second; /// Populate the vsevent with data from the preferred origin of the sc3 event vsevent->lat = org->latitude().value(); vsevent->lon = org->longitude().value(); vsevent->dep = org->depth().value(); vsevent->time = org->time().value(); if ( _expirationTimeReference == "ot" ) vsevent->expirationTime = org->time().value() + Core::TimeSpan(_eventExpirationTime, 0); /// Generate some statistics for later use in delta-pick quality measure Timeline::StationList pickedThresholdStations; // all picked stations at a limited distance from the epicenter vsevent->pickedStations.clear(); SEISCOMP_DEBUG("Number of arrivals in origin %s: %d", org->publicID().c_str(), (int)org->arrivalCount()); vsevent->stations.clear(); for ( size_t i = 0; i < org->arrivalCount(); ++i ) { Arrival *arr = org->arrival(i); PickPtr pick = _cache.get<Pick>(arr->pickID()); if ( !pick ) { SEISCOMP_DEBUG("cache.get<Pick>(\"%s\") failed to return pick", arr->pickID().c_str()); continue; } Timeline::StationID id(pick->waveformID().networkCode(), pick->waveformID().stationCode()); // if the station is not yet in the pickedStations set if ( vsevent->pickedStations.find(id) == vsevent->pickedStations.end() ) { double dist = arr->distance(); if ( dist > dmax ) dmax = dist; vsevent->pickedStations.insert(id); dsum += dist; } // if Station already used, continue if ( vsevent->stations.find(id) != vsevent->stations.end() ) continue; VsTimeWindow &tw = vsevent->stations[id]; tw.setStartTime(pick->time().value() - Core::TimeSpan(_twstarttime, 0)); tw.setEndTime(pick->time().value() + Core::TimeSpan(_twendtime, 0)); tw.setPickTime(pick->time().value()); // Todo: make sure that at least three seconds of data after the pick // are available } // count the number of arrivals with epicentral distance (in degrees) // less than the threshold for use in deltaPick() vsevent->pickedStationsCount = vsevent->pickedStations.size(); davg = dsum / (double) vsevent->pickedStationsCount; // calculate threshold dthresh = 0.5 * (dmax + davg); for ( size_t i = 0; i < org->arrivalCount(); i++ ) { Arrival *arr = org->arrival(i); PickPtr pick = _cache.get<Pick>(arr->pickID()); if ( !pick ) { SEISCOMP_DEBUG("cache.get<Pick>(\"%s\") failed to return pick", arr->pickID().c_str()); continue; } Timeline::StationID id(pick->waveformID().networkCode(), pick->waveformID().stationCode()); if ( pick && arr->distance() < dthresh ) { // if the pickedThresholdStations.insert(id); } } vsevent->pickedThresholdStationsCount = pickedThresholdStations.size(); vsevent->dthresh = dthresh; SEISCOMP_DEBUG("dmax; %f, davg: %f, dthresh: %f", dmax, davg, dthresh); // Get azimuthal gap vsevent->azGap = org->quality().azimuthalGap(); }