// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> bool AmpTool::run() { if ( !_originID.empty() ) { OriginPtr org = Origin::Cast(query()->getObject(Origin::TypeInfo(), _originID)); if ( !org ) { cerr << "Origin not found!" << endl; return false; } _fetchMissingAmplitudes = false; query()->loadArrivals(org.get()); process(org.get()); return true; } if ( !_strTimeWindowStartTime.empty() || !_strTimeWindowEndTime.empty() ) { if ( database() == NULL ) { cerr << "No database currently active for time window reprocessing" << endl; return false; } Core::Time startTime, endTime; if ( !_strTimeWindowStartTime.empty() && !startTime.fromString(_strTimeWindowStartTime.c_str(), "%F %T") ) { cerr << "Invalid start time: " << _strTimeWindowStartTime << endl; return false; } if ( !_strTimeWindowEndTime.empty() && !endTime.fromString(_strTimeWindowEndTime.c_str(), "%F %T") ) { cerr << "Invalid end time: " << _strTimeWindowEndTime << endl; return false; } std::string dbQuery; dbQuery += "select PPick." + _T("publicID") + ", Pick.* from Pick,PublicObject as PPick,Amplitude " "where Pick._oid=PPick._oid and Amplitude." + _T("pickID") + "=PPick." + _T("publicID"); if ( startTime.valid() ) dbQuery += " and Pick." + _T("time_value") + ">='" + startTime.toString("%F %T") + "'"; if ( endTime.valid() ) dbQuery += " and Pick." + _T("time_value") + "<'" + endTime.toString("%F %T") + "'"; dbQuery += " group by Amplitude." + _T("pickID"); if ( !commandline().hasOption("commit") ) _testMode = true; EventParametersPtr ep; if ( _testMode ) ep = new EventParameters; typedef list<PickPtr> PickList; PickList picks; cerr << "Collecting picks ... " << flush; DatabaseIterator db_it = query()->getObjectIterator(dbQuery, Pick::TypeInfo()); ObjectPtr obj; while ( obj = db_it.get() ) { Pick *pick = static_cast<Pick*>(obj.get()); try { pick->waveformID().networkCode(); pick->waveformID().stationCode(); pick->waveformID().locationCode(); pick->waveformID().channelCode(); pick->time().value(); } catch ( ... ) { continue; } ++db_it; picks.push_back(pick); if ( ep ) ep->add(pick); } db_it.close(); cerr << picks.size() << endl; _report << std::endl; _report << "Reprocessing report" << std::endl; _report << "-------------------" << std::endl; _report << " + Picks" << std::endl; int errors = 0; int ampsRecomputed = 0; int messagesSent = 0; int idx = 1; for ( PickList::iterator it = picks.begin(); it != picks.end(); ++it, ++idx ) { PickPtr pick = *it; SingleAmplitudeMap dbAmps; if ( isExitRequested() ) break; // Clear all processors _processors.clear(); // Clear all station time windows _stationRequests.clear(); _report << " + " << pick->publicID() << std::endl; cerr << "[" << idx << "]" << " " << (*it)->publicID() << endl; db_it = query()->getAmplitudesForPick((*it)->publicID()); while ( obj = db_it.get() ) { Amplitude *amp = static_cast<Amplitude*>(obj.get()); cerr << " [" << setw(10) << left << amp->type() << "] "; AmplitudeProcessorPtr proc = AmplitudeProcessorFactory::Create(amp->type().c_str()); if ( !proc ) { if ( _amplitudeTypes.find(amp->type()) == _amplitudeTypes.end() ) cerr << "No processor"; else { cerr << "No processor but enabled"; ++errors; } } else { cerr << "Fetch data"; dbAmps[amp->type()] = amp; proc->setTrigger(pick->time().value()); proc->setReferencingPickID(pick->publicID()); proc->setPublishFunction(boost::bind(&AmpTool::storeLocalAmplitude, this, _1, _2)); _report << " + Data" << std::endl; addProcessor(proc.get(), pick.get(), None, None); } cerr << endl; ++db_it; } db_it.close(); cerr << " --------------------------------" << endl; if ( _stationRequests.empty() ) continue; for ( RequestMap::iterator it = _stationRequests.begin(); it != _stationRequests.end(); ++it ) { StationRequest &req = it->second; for ( WaveformIDSet::iterator wit = req.streams.begin(); wit != req.streams.end(); ++wit ) { const WaveformStreamID &wsid = *wit; recordStream()->addStream(wsid.networkCode(), wsid.stationCode(), wsid.locationCode(), wsid.channelCode(), req.timeWindow.startTime(), req.timeWindow.endTime()); } _report << " + TimeWindow (" << it->first << "): " << req.timeWindow.startTime().toString("%F %T") << ", " << req.timeWindow.endTime().toString("%F %T") << std::endl; } _reprocessMap.clear(); readRecords(false); list<AmplitudePtr> updates; for ( AmplitudeMap::iterator it = dbAmps.begin(); it != dbAmps.end(); ++it ) { AmplitudePtr oldAmp = it->second; AmplitudePtr newAmp = _reprocessMap[oldAmp->type()]; cerr << " [" << setw(10) << left << oldAmp->type() << "] " << oldAmp->amplitude().value() << " "; if ( newAmp ) { if ( newAmp->amplitude().value() != oldAmp->amplitude().value() ) { *oldAmp = *newAmp; if ( ep ) ep->add(oldAmp.get()); else updates.push_back(oldAmp); cerr << "-> " << newAmp->amplitude().value(); } else cerr << " no changes"; ++ampsRecomputed; } else { cerr << "-"; ++errors; } cerr << endl; } if ( !updates.empty() ) { if ( !_testMode ) { NotifierMessagePtr nmsg = new NotifierMessage; for ( list<AmplitudePtr>::iterator it = updates.begin(); it != updates.end(); ++it ) { nmsg->attach(new Notifier("EventParameters", OP_UPDATE, it->get())); } connection()->send(nmsg.get()); ++messagesSent; if ( messagesSent % 100 == 0 ) sync(); } else { cerr << " --------------------------------" << endl; cerr << " Test mode, nothing sent" << endl; } } } if ( ep ) { IO::XMLArchive ar; ar.create("-"); ar.setFormattedOutput(true); ar << ep; ar.close(); } cerr << "----------------------------------" << endl; cerr << "Recomputed " << ampsRecomputed << " amplitudes" << endl; cerr << "Sent " << messagesSent << " messages" << endl; if ( errors ) cerr << errors << " errors occurred, check the processing log" << endl; return true; } if ( !_epFile.empty() ) { _fetchMissingAmplitudes = false; // Disable database setDatabase(NULL); _cache.setDatabaseArchive(NULL); IO::XMLArchive ar; if ( !ar.open(_epFile.c_str()) ) { SEISCOMP_ERROR("Failed to open %s", _epFile.c_str()); return false; } ar >> _ep; ar.close(); if ( !_ep ) { SEISCOMP_ERROR("No event parameters found in %s", _epFile.c_str()); return false; } if ( commandline().hasOption("reprocess") ) { for ( size_t i = 0; i < _ep->amplitudeCount(); ++i ) { AmplitudePtr amp = _ep->amplitude(i); feed(amp.get()); } } for ( size_t i = 0; i < _ep->originCount(); ++i ) { OriginPtr org = _ep->origin(i); SEISCOMP_INFO("Processing origin %s", org->publicID().c_str()); process(org.get()); } ar.create("-"); ar.setFormattedOutput(true); ar << _ep; ar.close(); _ep = NULL; 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(); }