Seiscomp::DataModel::Origin *Autoloc::convertToSC3(const Autoloc::Origin* origin, bool allPhases) { Seiscomp::DataModel::Origin *sc3origin = Seiscomp::DataModel::Origin::Create(); Seiscomp::DataModel::TimeQuantity sc3tq; Seiscomp::DataModel::RealQuantity sc3rq; sc3origin->setTime(Seiscomp::DataModel::TimeQuantity(Autoloc::sc3time(origin->time), origin->timeerr, Seiscomp::Core::None, Seiscomp::Core::None, Seiscomp::Core::None)); sc3origin->setLatitude(Seiscomp::DataModel::RealQuantity(origin->lat, origin->laterr, Seiscomp::Core::None, Seiscomp::Core::None, Seiscomp::Core::None)); sc3origin->setLongitude(Seiscomp::DataModel::RealQuantity(origin->lon, origin->lonerr, Seiscomp::Core::None, Seiscomp::Core::None, Seiscomp::Core::None)); sc3origin->setDepth(Seiscomp::DataModel::RealQuantity(origin->dep, origin->deperr, Seiscomp::Core::None, Seiscomp::Core::None, Seiscomp::Core::None)); sc3origin->setMethodID(origin->methodID); sc3origin->setEarthModelID(origin->earthModelID); sc3origin->setEvaluationMode(Seiscomp::DataModel::EvaluationMode(Seiscomp::DataModel::AUTOMATIC)); if ( origin->preliminary ) sc3origin->setEvaluationStatus(Seiscomp::DataModel::EvaluationStatus(Seiscomp::DataModel::PRELIMINARY)); switch ( origin->depthType ) { case Autoloc::Origin::DepthFree: sc3origin->setDepthType(Seiscomp::DataModel::OriginDepthType(Seiscomp::DataModel::FROM_LOCATION)); break; case Autoloc::Origin::DepthMinimum: break; case Autoloc::Origin::DepthDefault: break; case Autoloc::Origin::DepthManuallyFixed: sc3origin->setDepthType(Seiscomp::DataModel::OriginDepthType(Seiscomp::DataModel::OPERATOR_ASSIGNED)); break; default: break; } // This is a preliminary fix which prevents autoloc from producing // origins with fixed depth, as this caused some problems at BMG // where the fixed-depth checkbox was not unchecked and an incorrect // depth was retained. Need a better way, though. // sc3origin->setDepthType(Seiscomp::DataModel::OriginDepthType(Seiscomp::DataModel::FROM_LOCATION)); // Store SC3 Picks/Stations here so that they can be found // via SC3 PublicObject lookup std::vector<Seiscomp::DataModel::PublicObjectPtr> sc3objects; int arrivalCount = origin->arrivals.size(); for (int i=0; i<arrivalCount; i++) { const Autoloc::Arrival &arr = origin->arrivals[i]; // If not all (automatic) phases are requested, only include P and PKP if ( !allPhases && automatic(arr.pick.get()) && arr.phase != "P" && arr.phase != "PKP") { SEISCOMP_DEBUG_S("SKIPPING 1 "+arr.pick->id); continue; } // Don't include arrivals with huge residuals as (unless by // accident) these are excluded from the location anyway. /* if (arr.excluded && fabs(arr.residual) > 30.) { // FIXME: quick+dirty fix SEISCOMP_DEBUG_S("SKIPPING 1 "+arr.pick->id); continue; } */ const Seiscomp::DataModel::Phase phase(arr.phase); Seiscomp::DataModel::ArrivalPtr sc3arr = new Seiscomp::DataModel::Arrival(); sc3arr->setPickID( arr.pick->id); sc3arr->setDistance( arr.distance); sc3arr->setAzimuth( arr.azimuth); sc3arr->setTimeResidual( arr.residual); sc3arr->setWeight( arr.excluded ? 0 : 1); sc3arr->setPhase(phase); Seiscomp::DataModel::PickPtr sc3pick = Seiscomp::DataModel::Pick::Cast( Seiscomp::DataModel::PublicObject::Find(arr.pick->id)); if ( sc3pick == NULL ) { sc3pick = Seiscomp::DataModel::Pick::Create(arr.pick->id); const Autoloc::Station *sta = arr.pick->station(); Seiscomp::DataModel::WaveformStreamID wfid(sta->net, sta->code, "", "XYZ", ""); sc3pick->setWaveformID(wfid); sc3tq.setValue(Autoloc::sc3time(arr.pick->time)); sc3pick->setTime(sc3tq); sc3pick->setPhaseHint(phase); if (arr.pick->status == Autoloc::Pick::Manual) sc3pick->setEvaluationMode(Seiscomp::DataModel::EvaluationMode(Seiscomp::DataModel::MANUAL)); else sc3pick->setEvaluationMode(Seiscomp::DataModel::EvaluationMode(Seiscomp::DataModel::AUTOMATIC)); } sc3objects.push_back(sc3pick); sc3origin->add(sc3arr.get()); } Seiscomp::DataModel::OriginQuality oq; oq.setAssociatedPhaseCount(sc3origin->arrivalCount()); oq.setUsedPhaseCount(origin->definingPhaseCount()); oq.setAssociatedStationCount(origin->associatedStationCount()); oq.setUsedStationCount(origin->definingStationCount()); oq.setMedianDistance(origin->medianStationDistance()); oq.setStandardError(origin->rms()); double minDist, maxDist, aziGap; origin->geoProperties(minDist, maxDist, aziGap); oq.setMinimumDistance(minDist); oq.setMaximumDistance(maxDist); oq.setAzimuthalGap(aziGap); sc3origin->setQuality(oq); return sc3origin; }
Origin* Locator::_sc3relocate(const Origin *origin, double fixedDepth) { // convert origin to SC3, relocate, and convert the result back Seiscomp::DataModel::OriginPtr sc3origin = convertToSC3(origin); Seiscomp::DataModel::TimeQuantity sc3tq; Seiscomp::DataModel::RealQuantity sc3rq; /* if(fixedDepth>=0) { setFixedDepth(fixedDepth); } else if(_useFixedDepth==true) { setFixedDepth(origin->dep); } else releaseDepth(); */ // Store SC3 Picks/Stations here so that they can be found // by LocSAT via SC3 PublicObject lookup vector<Seiscomp::DataModel::PublicObjectPtr> sc3objects; int arrivalCount = origin->arrivals.size(); for (int i=0; i<arrivalCount; i++) { const Arrival &arr = origin->arrivals[i]; const Seiscomp::DataModel::Phase phase(arr.phase); Seiscomp::DataModel::PickPtr sc3pick = Seiscomp::DataModel::Pick::Cast( Seiscomp::DataModel::PublicObject::Find(arr.pick->id)); if ( sc3pick == NULL ) { sc3pick = Seiscomp::DataModel::Pick::Create(arr.pick->id); if ( sc3pick == NULL ) { SEISCOMP_ERROR_S("Locator::_sc3relocate(): Failed to create pick "+arr.pick->id+" - giving up"); return NULL; } const Station *sta = arr.pick->station(); Seiscomp::DataModel::WaveformStreamID wfid(sta->net, sta->code, "", "XYZ", ""); sc3pick->setWaveformID(wfid); sc3tq.setValue(sc3time(arr.pick->time)); sc3pick->setTime(sc3tq); sc3pick->setPhaseHint(phase); sc3pick->setEvaluationMode(Seiscomp::DataModel::EvaluationMode(Seiscomp::DataModel::AUTOMATIC)); } sc3objects.push_back(sc3pick); } // // try the actual relocation // Seiscomp::DataModel::OriginPtr sc3relo; try { // FIXME| It is strange: sometimes LocSAT requires a second // FIXME| invocation to produce a decent result. Reason TBD Seiscomp::DataModel::OriginPtr temp; temp = Seiscomp::LocSAT::relocate(sc3origin.get()); if (!temp) return NULL; sc3relo = Seiscomp::LocSAT::relocate(temp.get()); if (!sc3relo) return NULL; } catch(Seiscomp::Seismology::LocatorException) { return NULL; } catch(Seiscomp::Seismology::PickNotFoundException) { SEISCOMP_WARNING("Unsuccessful location due to PickNotFoundException"); return NULL; } // // Now get the relocated origin back from SC3 // TODO: put it into sc3adapters.cpp // HOWEVER: here a copy of the original origin is just updated // // A copy is made of the input origins, i.e. the Arrival attributes // don't get lost or have to be searched for in a complicated manner. // However, this relies on the order of the arrivals as returned by // LocSAT being the same as in the input. If not, this is absolutely // fatal. // Origin *relo = new Origin(*origin); if ( ! relo) return NULL; relo->lat = sc3relo->latitude().value(); try { relo->laterr = 0.5*(sc3relo->latitude().lowerUncertainty()+sc3relo->latitude().upperUncertainty()); } catch ( ... ) { relo->laterr = sc3relo->latitude().uncertainty(); } relo->lon = sc3relo->longitude().value(); try { relo->lonerr = 0.5*(sc3relo->longitude().lowerUncertainty()+sc3relo->longitude().upperUncertainty()); } catch ( ... ) { relo->lonerr = sc3relo->longitude().uncertainty(); } relo->dep = sc3relo->depth().value(); try { relo->deperr = 0.5*(sc3relo->depth().lowerUncertainty()+sc3relo->depth().upperUncertainty()); } catch ( ... ) { relo->deperr = sc3relo->depth().uncertainty(); } relo->time = double(sc3relo->time().value() - Seiscomp::Core::Time()); try { relo->timeerr = 0.5*(sc3relo->time().lowerUncertainty()+sc3relo->time().upperUncertainty()); } catch ( ... ) { relo->timeerr = sc3relo->time().uncertainty(); } relo->methodID = sc3relo->methodID(); relo->earthModelID = sc3relo->earthModelID(); for (int i=0; i<arrivalCount; i++) { Arrival &arr = relo->arrivals[i]; const string &pickID = sc3relo->arrival(i)->pickID(); if (arr.pick->id != pickID) { // If this should ever happen, let it bang loudly! SEISCOMP_ERROR("Locator: FATAL ERROR: Inconsistent arrival order"); exit(1); } arr.residual = sc3relo->arrival(i)->timeResidual(); arr.distance = sc3relo->arrival(i)->distance(); arr.azimuth = sc3relo->arrival(i)->azimuth(); if ( (arr.phase == "P" || arr.phase == "P1") && arr.distance > 115) arr.phase = "PKP"; // if (arr.residual == -999.) // arr.residual = 0; // FIXME preliminary cosmetics; // We do not copy the weight back, because it is still there in the original arrival // arr.weight = sc3relo->arrival(i)->weight(); /* if ( arr.residual > 800 && ( arr.phase=="P" || arr.phase=="Pdiff" ) && \ arr.distance > 104 && arr.distance < 112) { Seiscomp::TravelTime tt; if ( ! travelTimeP(arr.distance, origin->dep, tt)) continue; arr.residual = arr.pick->time - (origin->time + tt.time); } */ } return relo; }