예제 #1
0
DataModel::Origin* relocate(Seismology::LocatorInterface *locator, DataModel::Origin* origin) {
	if ( !locator )
		throw Core::GeneralException("No locator type set.");

	DataModel::Origin* newOrg = NULL;
	std::string errorMsg;

	try {
		newOrg = locator->relocate(origin);
		if ( newOrg )
			return newOrg;

		errorMsg = "The Relocation failed for some reason.";
	}
	catch ( Core::GeneralException& e ) {
		errorMsg = e.what();
	}

	// if no initial location is supported throw the error
	// after the first try
	if ( !locator->supports(Seismology::LocatorInterface::InitialLocation) )
		throw Core::GeneralException(errorMsg);

	Seismology::LocatorInterface::PickList picks;
	for ( size_t i = 0; i < origin->arrivalCount(); ++i ) {
		DataModel::Arrival* arrival = origin->arrival(i);
		try {
			if ( arrival->weight() < 0.5 ) continue;
		}
		catch ( ... ) {}

		DataModel::Pick* pick = locator->getPick(arrival);
		if ( !pick )
			throw Core::GeneralException("pick '" + arrival->pickID() + "' not found");

		picks.push_back(Seismology::LocatorInterface::WeightedPick(pick,1));
	}

	if ( picks.empty() )
		throw Core::GeneralException("No picks given to relocate");

	std::sort(picks.begin(), picks.end(), comparePick());
	DataModel::SensorLocation *sloc = locator->getSensorLocation(picks.front().first.get());
	if ( !sloc )
		throw Core::GeneralException("station '" + picks.front().first->waveformID().networkCode() +
		                             "." + picks.front().first->waveformID().stationCode() + "' not found");

	DataModel::OriginPtr tmp = DataModel::Origin::Create();
	*tmp = *origin;
	for ( size_t i = 0; i < origin->arrivalCount(); ++i ) {
		DataModel::ArrivalPtr ar = new DataModel::Arrival(*origin->arrival(i));
		tmp->add(ar.get());
	}

	tmp->setLatitude(sloc->latitude());
	tmp->setLongitude(sloc->longitude());
	tmp->setDepth(DataModel::RealQuantity(11.0));
	tmp->setTime(picks.front().first->time());

	newOrg = locator->relocate(tmp.get());

	if ( newOrg )
		return newOrg;

	throw Core::GeneralException(errorMsg);
}
예제 #2
0
		bool listNetworks() {
			// Disable object registration
			DataModel::PublicObject::SetRegistrationEnabled(false);

			vector<string> files;
			collectFiles(files);

			if ( files.empty() ) {
				cerr << "Nothing to merge, no files given" << endl;
				return false;
			}

			DataModel::InventoryPtr finalInventory = new DataModel::Inventory();
			Merge merger(finalInventory.get());

			_currentTask = &merger;

			for ( size_t i = 0; i < files.size(); ++i ) {
				if ( _exitRequested ) break;

				IO::XMLArchive ar;
				if ( !ar.open(files[i].c_str()) ) {
					cerr << "Could not open file (ignored): " << files[i] << endl;
					continue;
				}

				DataModel::InventoryPtr inv;
				cerr << "Parsing " << files[i] << " ... " << flush;
				ar >> inv;
				cerr << "done" << endl;
				if ( !inv ) {
					cerr << "No inventory found (ignored): " << files[i] << endl;
					continue;
				}

				_inventorySources[inv.get()] = files[i];

				// Pushing the inventory into the merger cleans it
				// completely. The ownership of all childs went to
				// the merger
				merger.push(inv.get());
			}

			_currentTask = NULL;

			if ( _exitRequested ) {
				cerr << "Exit requested: abort" << endl;
				return false;
			}

			cerr << "Merging inventory ... " << flush;
			merger.merge(false);
			cerr << "done" << endl;

			bool compact = commandline().hasOption("compact");
			int level = 2;
			if ( _level == "net" )
				level = 0;
			else if ( _level == "sta" )
				level = 1;
			else if ( _level == "cha" )
				level = 2;
			else if ( _level == "resp" )
				level = 3;

			std::vector<DataModel::Network*> nets;

			for ( size_t n = 0; n < finalInventory->networkCount(); ++n )
				nets.push_back(finalInventory->network(n));

			sort(nets.begin(), nets.end(), lessID<DataModel::Network>);

			for ( size_t n = 0; n < nets.size(); ++n ) {
				DataModel::Network *net = nets[n];
				if ( compact )
					cout << net->code() << "\t" << epochToStr(net) << endl;
				else {
					cout << "  network " << net->code();
					if ( !net->description().empty() ) {
						cout << setfill(' ') << setw(8-net->code().size()) << ' ';
						cout << " " << net->description();
					}
					cout << endl;
					cout << "    epoch " << epochToStr(net) << endl;
				}

				std::vector<DataModel::Station*> stas;

				if ( level > 0 ) {
					for ( size_t s = 0; s < net->stationCount(); ++s )
						stas.push_back(net->station(s));
				}

				sort(stas.begin(), stas.end(), lessID<DataModel::Station>);

				for ( size_t s = 0; s < stas.size(); ++s ) {
					DataModel::Station *sta = stas[s];
					if ( compact )
						cout << " " << sta->code() << "\t" << epochToStr(sta) << endl;
					else {
						cout << "    station " << sta->code();
						if ( !sta->description().empty() ) {
							cout << setfill(' ') << setw(6-sta->code().size()) << ' ';
							cout << " " << sta->description();
						}
						cout << endl;
						cout << "      epoch " << epochToStr(sta) << endl;
					}

					std::vector<DataModel::SensorLocation*> locs;

					if ( level > 1 ) {
						for ( size_t l = 0; l < sta->sensorLocationCount(); ++l )
							locs.push_back(sta->sensorLocation(l));
					}

					sort(locs.begin(), locs.end(), lessID<DataModel::SensorLocation>);

					for ( size_t l = 0; l < locs.size(); ++l ) {
						DataModel::SensorLocation *loc = locs[l];
						if ( compact ) {
							cout << "  ";
							if ( loc->code().empty() )
								cout << "__";
							else
								cout << loc->code();
							cout << "\t" << epochToStr(loc) << endl;
						}
						else {
							cout << "      location ";
							if ( loc->code().empty() )
								cout << "__";
							else
								cout << loc->code();
							cout << endl;

							cout << "        epoch " << epochToStr(loc) << endl;
						}

						std::vector<DataModel::Stream*> streams;

						for ( size_t s = 0; s < loc->streamCount(); ++s )
							streams.push_back(loc->stream(s));

						sort(streams.begin(), streams.end(), lessID<DataModel::Stream>);

						for ( size_t s = 0; s < streams.size(); ++s ) {
							DataModel::Stream *str = streams[s];
							if ( compact )
								cout << "   " << str->code() << "\t" << epochToStr(str) << endl;
							else {
								cout << "        channel ";
								cout << str->code() << endl;

								cout << "          epoch " << epochToStr(str) << endl;
							}

							if ( level >= 3 ) {
								const DataModel::Sensor *sens;
								const DataModel::Datalogger *dl;
								const DataModel::ResponsePAZ *paz;
								const DataModel::ResponsePolynomial *poly;
								const DataModel::ResponseFAP *fap;
								const DataModel::ResponseIIR *iir;

								try {
									int sr_num = str->sampleRateNumerator();
									int sr_den = str->sampleRateDenominator();
									cout << "          rate  " << sr_num << "/" << sr_den << " sps" << endl;
								}
								catch ( ... ) {}

								try {
									double gain = str->gain();
									cout << "          gain  " << gain << endl;
								}
								catch ( ... ) {}
								try {
									double freq = str->gainFrequency();
									cout << "          freq  " << freq << "Hz" << endl;
								}
								catch ( ... ) {}

								if ( !str->gainUnit().empty() )
									cout << "          unit  " << str->gainUnit() << endl;

								sens = merger.findSensor(str->sensor());
								if ( sens ) {
									cout << "          sens  " << sens->description() << endl;
									paz = merger.findPAZ(sens->response());
									if ( paz ) {
										cout << "          resp  PAZ" << endl;
										cout << tabular(paz, 16) << endl;
									}
									else {
										poly = merger.findPoly(sens->response());
										if ( poly ) {
											cout << "          resp  polynomial" << endl;
											cout << tabular(poly, 16) << endl;
										}
										else {
											fap = merger.findFAP(sens->response());
											if ( fap ) {
												cout << "          resp  fap" << endl;
												cout << tabular(fap, 16) << endl;
											}
											else {
												iir = merger.findIIR(sens->response());
												if ( iir ) {
													cout << "          resp  iir" << endl;
													cout << tabular(iir, 16) << endl;
												}
											}
										}
									}
								}

								dl = merger.findDatalogger(str->datalogger());
								if ( dl ) {
									if ( !dl->description().empty() )
										cout << "          dl    " << dl->description() << endl;
									else
										cout << "          dl    -" << endl;

									try {
										double gain = dl->gain();
										cout << "                gain         " << gain << endl;
									}
									catch ( ... ) {}

									try {
										DataModel::Decimation *deci = dl->decimation(DataModel::DecimationIndex(str->sampleRateNumerator(), str->sampleRateDenominator()));
										if ( deci ) {
											cout << "          dec   " << str->sampleRateNumerator() << "/" << str->sampleRateDenominator() << " sps" << endl;
											cout << tabular(&merger, deci, 16) << endl;
										}
									}
									catch ( ... ) {}
								}
							}
						}
					}
				}
			}

			return true;
		}
예제 #3
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());
}