Exemplo n.º 1
0
void CalculateAmplitudes::addProcessor(Processing::AmplitudeProcessor *proc,
                                       const DataModel::Pick *pick,
                                       int c) {
    static const char *names[3] = {"vertical", "first horizontal", "second horizontal"};
    char component;
    ThreeComponents tc;

    try {
        tc = Client::Inventory::Instance()->getThreeComponents(pick);
    }
    catch ( ... ) {}

    WaveformStreamID cwid = pick->waveformID();

    if ( tc.comps[ThreeComponents::Component(c)] == NULL )
        component = '\0';
    else {
        cwid.setChannelCode(tc.comps[ThreeComponents::Component(c)]->code());
        component = *cwid.channelCode().rbegin();
    }

    std::string streamID = waveformIDToStdString(cwid);

    int row = addProcessingRow(streamID, proc->type());

    if ( component == '\0' ) {
        setError(row, QString("no %1 component found").arg(names[c]));
        return;
    }

    StreamMap::iterator it = _streams.find(streamID);
    if ( it != _streams.end() )
        proc->streamConfig((WaveformProcessor::Component)c) = *it->second;
    else {
        Processing::StreamPtr stream = new Processing::Stream;
        stream->init(cwid.networkCode(),
                     cwid.stationCode(),
                     cwid.locationCode(),
                     cwid.channelCode(),
                     pick->time().value());
        _streams[streamID] = stream;

        proc->streamConfig((WaveformProcessor::Component)c) = *stream;
    }

    if ( proc->streamConfig((WaveformProcessor::Component)c).gain == 0.0 ) {
        setError(row, "no gain found");
        return;
    }

    if ( proc->status() != WaveformProcessor::WaitingForData ) {
        setError(row, QString("%1 (%2)").arg(proc->status().toString()).arg(proc->statusValue(), 0, 'f', 2));
        return;
    }
    else
        setError(row, proc->status().toString());

    _rows.insert(TableRowMap::value_type(proc, row));
}
Exemplo n.º 2
0
void CalculateAmplitudes::subscribeData(Processing::AmplitudeProcessor *proc,
                                        const DataModel::Pick *pick,
                                        int c) {
    if ( proc->streamConfig((WaveformProcessor::Component)c).code().empty() )
        return;

    if ( proc->streamConfig((WaveformProcessor::Component)c).gain == 0.0 )
        return;

    WaveformStreamID cwid = pick->waveformID();
    cwid.setChannelCode(proc->streamConfig((WaveformProcessor::Component)c).code());
    std::string streamID = waveformIDToStdString(cwid);

    pair<ProcessorMap::iterator, bool> handle = _processors.insert(ProcessorMap::value_type(streamID, ProcessorSlot()));
    if ( handle.second )
        _thread->addStream(cwid.networkCode(), cwid.stationCode(), cwid.locationCode(), cwid.channelCode());

    handle.first->second.push_back(proc);

    // Add processors timewindow to global acquisition timewindow
    _timeWindow = _timeWindow | proc->safetyTimeWindow();
}
Exemplo n.º 3
0
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
void Envelope::addProcessor(SensorLocation *loc, const WaveformStreamID &id,
                            const Core::Time &timestamp, const char *type,
                            const char *short_type) {
	DataModel::ThreeComponents tc;
	DataModel::WaveformStreamID tmp(id);
	try {
		DataModel::getThreeComponents(
			tc, loc, id.channelCode().c_str(), timestamp
		);
	}
	catch ( exception &e ) {
		SEISCOMP_ERROR("%s: cannot query three components: %s: "
		               "%s channels not used",
		               Private::toStreamID(tmp).c_str(),
		               e.what(), type);
	}

	for ( int i = 0; i < 3; ++i ) {
		if ( tc.comps[i] == NULL ) continue;
		tmp.setChannelCode(tc.comps[i]->code());
		if ( !_streamFirewall.isAllowed(Private::toStreamID(tmp)) ) continue;

		SEISCOMP_INFO("%s: +%s", Private::toStreamID(tmp).c_str(), short_type);
		recordStream()->addStream(tmp.networkCode(), tmp.stationCode(),
		                          tmp.locationCode(), tmp.channelCode());
		ProcessorPtr proc = new Processor(_config.baselineCorrectionBufferLength);
		switch ( i ) {
			case ThreeComponents::Vertical:
				proc->setUsedComponent(Processing::WaveformProcessor::Vertical);
				proc->setName("Z");
				break;
			case ThreeComponents::FirstHorizontal:
				proc->setUsedComponent(Processing::WaveformProcessor::FirstHorizontal);
				proc->setName("H1");
				break;
			case ThreeComponents::SecondHorizontal:
				proc->setUsedComponent(Processing::WaveformProcessor::SecondHorizontal);
				proc->setName("H2");
				break;
		}

		Processing::StreamPtr stream = new Processing::Stream;
		stream->init(tmp.networkCode(), tmp.stationCode(),
		             tmp.locationCode(), tmp.channelCode(),
		             timestamp);

		proc->streamConfig((Processing::WaveformProcessor::Component)proc->usedComponent()) = *stream;
		proc->setWaveformID(tmp);
		proc->setSaturationThreshold(_config.saturationThreshold);
		proc->useVSFilterImplementation(!_config.useSC3Filter);

		if ( proc->streamConfig((Processing::WaveformProcessor::Component)proc->usedComponent()).gain == 0.0 ) {
			SEISCOMP_WARNING("%s: -%s: gain not defined (= 0.0)",
			                 short_type, Private::toStreamID(tmp).c_str());
			continue;
		}

		proc->setPublishFunction(boost::bind(&Envelope::emitResult, this, _1, _2, _3, _4, _5, _6));
		_processors[Private::toStreamID(tmp)] = proc;
	}
}
Exemplo n.º 4
0
/*!
 \brief Process one event

 This is called by processEvents() when iterating over all events in the cache
 */
void VsMagnitude::process(VsEvent *evt, Event *event) {
    if ( evt->stations.empty() )
        return;
    Client::Inventory *inv = Client::Inventory::Instance();

    double stmag;
    double distdg, epicdist, azi1, azi2;
    WaveformStreamID wid;
    ReturnCode ret;
    Timeline::StationList unused;
    evt->allThresholdStationsCount = 0;
    vs.seteqlat(evt->lat);
    vs.seteqlon(evt->lon);

    vector<VsInput> inputs;

    SEISCOMP_LOG(_processingInfoChannel,
                 "Start logging for event: %s", event->publicID().c_str());
    SEISCOMP_LOG(_processingInfoChannel, "update number: %d", evt->update);

    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;
    }

    evt->staMags.clear();
    VsWindows::iterator it;
    for ( it = evt->stations.begin(); it != evt->stations.end(); ++it ) {
        Envelope venv, henv;
        Core::Time vtime, htime;
        string locationCode, channelCode;


        ret = _timeline.maxmimum(it->first, it->second.startTime(),
                                 it->second.endTime(), it->second.pickTime(), venv, vtime, henv,
                                 htime, locationCode, channelCode);

        if ( no_data == ret ) {
            SEISCOMP_WARNING("No data available for %s.%s.%s", it->first.first.c_str(),
                             it->first.second.c_str(),locationCode.c_str());
            unused.insert(it->first);
            continue;
        }

        DataModel::SensorLocation *loc;
        loc = inv->getSensorLocation(it->first.first, it->first.second,
                                     locationCode, it->second.pickTime());
        if ( loc == NULL ) {
            SEISCOMP_WARNING(
                "%s.%s.%s: sensor location not in inventory: ignoring", it->first.first.c_str(), it->first.second.c_str(), locationCode.c_str());
            continue;
        }

        Math::Geo::delazi(evt->lat, evt->lon, loc->latitude(), loc->longitude(),
                          &distdg, &azi1, &azi2);
        epicdist = Math::Geo::deg2km(distdg);

        // if data is clipped or not enough to use it for magnitude
        // computation add the station to the overall count and then continue
        if ( not_enough_data == ret || clipped_data == ret) {
            SEISCOMP_WARNING("Not enough data available for %s.%s.%s", it->first.first.c_str(),
                             it->first.second.c_str(),locationCode.c_str());
            unused.insert(it->first);
            continue;
        }

        // catch remaining errors
        if ( index_error == ret || undefined_problem == ret)
            continue;

        if ( _maxepicdist > 0 ) {
            if( epicdist > _maxepicdist )
                continue;
        }

        inputs.resize(inputs.size() + 1);
        VsInput &input = inputs.back();
        input.lat = (float) loc->latitude();
        input.lon = (float) loc->longitude();

        SoilClass soilClass;
        float ca = siteEffect(input.lat, input.lon,
                              std::max(venv.values[Acceleration], henv.values[Acceleration]),
                              Acceleration, soilClass);
        float cv = siteEffect(input.lat, input.lon,
                              std::max(venv.values[Velocity], henv.values[Velocity]),
                              Velocity, soilClass);
        float cd = siteEffect(input.lat, input.lon,
                              std::max(venv.values[Displacement], henv.values[Displacement]),
                              Displacement, soilClass);

        // Convert from m to cm and apply site effect correction
        input.ZA = (float) (venv.values[Acceleration] / ca) * 100;
        input.ZV = (float) (venv.values[Velocity] / cv) * 100;
        input.ZD = (float) (venv.values[Displacement] / cd) * 100;

        input.HA = (float) (henv.values[Acceleration] / ca) * 100;
        input.HV = (float) (henv.values[Velocity] / cv) * 100;
        input.HD = (float) (henv.values[Displacement] / cd) * 100;

        input.PSclass =
            vs.psclass(input.ZA, input.ZV, input.HA, input.HV) == 0 ?
            P_Wave : S_Wave;
        input.SOILclass = soilClass;

        input.mest = vs.mest(vs.ground_motion_ratio(input.ZA, input.ZD),
                             input.PSclass);

        // Record single station magnitudes
        Notifier::SetEnabled(true);
        _creationInfo.setCreationTime(_currentTime);
        _creationInfo.setModificationTime(Core::None);
        DataModel::StationMagnitudePtr staMag = DataModel::StationMagnitude::Create();
        staMag->setMagnitude(RealQuantity(input.mest));
        staMag->setType("MVS");
        staMag->setCreationInfo(_creationInfo);
        wid.setNetworkCode(it->first.first);
        wid.setStationCode(it->first.second);
        wid.setLocationCode(locationCode);
        wid.setChannelCode(channelCode);
        staMag->setWaveformID(wid);
        org->add(staMag.get());
        evt->staMags.push_back(staMag);
        Notifier::SetEnabled(false);

        // Logging
        string resultstr;
        ostringstream out;
        out.precision(2);
        out.setf(ios::fixed, ios::floatfield);
        out << "Sensor: " << it->first.first << "." << locationCode << ".";
        out << it->first.second << "." << channelCode << "; ";
        out << "Wavetype: " << std::string(input.PSclass.toString()) << "; ";
        out << "Soil class: " << std::string(input.SOILclass.toString())
            << "; ";
        out << "Magnitude: " << input.mest;
        resultstr = out.str();
        out.str("");
        SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());
        out.precision(2);
        out.setf(ios::fixed, ios::floatfield);
        out << "station lat: " << input.lat << "; station lon: " << input.lon;
        out << "; epicentral distance: " << epicdist << ";";
        resultstr = out.str();
        out.str("");
        SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());
        out.precision(2);
        out.setf(ios::scientific, ios::floatfield);
        out << "PGA(Z): " << input.ZA / 100. << "; PGV(Z): " << input.ZV / 100.;
        out << "; PGD(Z): " << input.ZD / 100.;
        resultstr = out.str();
        out.str("");
        SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());
        out << "PGA(H): " << input.HA / 100. << "; PGV(H): " << input.HV / 100.;
        out << "; PGD(H): " << input.HD / 100.;
        resultstr = out.str();
        SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());
    }

    if ( inputs.empty() ) {
        SEISCOMP_LOG(_processingInfoChannel,
                     "End logging for event: %s", event->publicID().c_str());
        return;
    }

    // Grid search
    float mag = 0.5f;
    float minL = -1.0f;
    float minMag = mag;

    while ( mag <= 9.0f ) {
        float L = 0.0f;

        for ( size_t i = 0; i < inputs.size(); ++i ) {
            const VsInput &input = inputs[i];

            // Likelihood
            vs.setmag(mag);
            L += vs.likelihood(input.ZA, input.ZV, input.ZD, input.HA, input.HV,
                               input.HD, input.PSclass, input.SOILclass, input.lat,
                               input.lon);
        }

        if ( minL < 0 || minL > L ) {
            minL = L;
            minMag = mag;
        }

        mag += 0.01f;
    }

    // calculate the median of all station magnitudes
    size_t size = inputs.size();
    double *mestarray = new double[size];

    for ( size_t i = 0; i < size; ++i ) {
        const VsInput &input = inputs[i];
        mestarray[i] = input.mest;
    }

    nth_element(mestarray, mestarray + size / 2, mestarray + size);
    stmag = mestarray[size / 2];
    delete[] mestarray;

    // TODO: Define errors
    evt->vsMagnitude = minMag;
    evt->vsStationCount = inputs.size();


    if ( _timeline.pollbuffer(evt->lat, evt->lon,evt->dthresh,evt->allThresholdStationsCount) != no_problem) {
        SEISCOMP_WARNING("Problems in the buffer polling function.");
        return;
    }


    // Use quality control functions to decide if the event is valid
    evt->isValid = false;
    double deltamag;
    double deltapick;
    if ( isEventValid(stmag, evt, evt->likelihood, deltamag, deltapick) ) {
        evt->isValid = true;
    }

    // logging
    string resultstr;
    ostringstream out;
    out.precision(2);
    out.setf(ios::fixed, ios::floatfield);
    out << "VS-mag: " << minMag << "; median single-station-mag: " << stmag;
    out << "; lat: " << evt->lat << "; lon: " << evt->lon;
    out << "; depth : " << evt->dep << " km";
    resultstr = out.str();
    out.str("");
    SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());

    out << "creation time: " << _currentTime.toString("%FT%T.%2fZ");
    out << "; origin time: " << evt->time.toString("%FT%T.%2fZ");
    Core::TimeSpan difftime = _currentTime - evt->time;
    Core::Time now = Core::Time::GMT();
    Core::TimeSpan difftime_oa = now - evt->originArrivalTime;
    Core::TimeSpan difftime_ct = now - evt->originCreationTime;
    out << "; t-diff: " << difftime.length();
    out.precision(3);
    out << "; time since origin arrival: " << difftime_oa.length();
    out << "; time since origin creation: " << difftime_ct.length();
    resultstr = out.str();
    out.str("");
    SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());

    out << "# picked stations: " << evt->pickedStationsCount; // all stations with picks
    out << "; # envelope streams: " << _timeline.StreamCount(); // all stations with envelope streams
    resultstr = out.str();
    out.str("");
    SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());

    // distance threshold for delta-pick quality criteria
    out.precision(2);
    out << "Distance threshold (dt): " << Math::Geo::deg2km(evt->dthresh)
        << " km";
    out << "; # picked stations < dt: " << evt->pickedThresholdStationsCount;
    out << "; # envelope streams < dt: " << evt->allThresholdStationsCount;
    resultstr = out.str();
    out.str("");
    SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());

    if (evt->pickedStationsCount > evt->vsStationCount) {
        out << "Stations not used for VS-mag: ";
        // find picked stations that don't contribute to the VS magnitude
        Timeline::StationList &sl = evt->pickedStations;
        for (Timeline::StationList::iterator it=sl.begin(); it!=sl.end(); ++it) {
            if ( evt->stations.find(*it) == evt->stations.end() || unused.find(*it) != unused.end()) {
                out << (*it).first << '.' << (*it).second << ' ';
            }
        }
        resultstr = out.str();
        out.str("");
        SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());
    }

    out.precision(3);
    out << "Magnitude check: " << deltamag << "; Arrivals check: " << deltapick;
    out << "; Azimuthal gap: " << evt->azGap;
    resultstr = out.str();
    out.str("");
    SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());

    out.precision(2);
    out << "likelihood: " << evt->likelihood;
    resultstr = out.str();
    out.str("");
    SEISCOMP_LOG(_processingInfoChannel, "%s", resultstr.c_str());

    SEISCOMP_LOG(_processingInfoChannel,
                 "End logging for event: %s", event->publicID().c_str());
}