Пример #1
0
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;
}
Пример #2
0
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;
}