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;
}
示例#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();
}