Ejemplo n.º 1
0
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
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;
	}
Ejemplo n.º 2
0
/*!
 \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();
}