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); }
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; }
/*! \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()); }