package edu.sc.seis.sod.subsetter.eventStation;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import edu.iris.Fissures.IfEvent.Origin;
import edu.iris.Fissures.model.QuantityImpl;
import edu.iris.Fissures.model.UnitImpl;
import edu.iris.Fissures.network.StationImpl;
import edu.sc.seis.TauP.Arrival;
import edu.sc.seis.TauP.SeismicPhase;
import edu.sc.seis.TauP.TauModelException;
import edu.sc.seis.TauP.TauP_Time;
import edu.sc.seis.fissuresUtil.bag.DistAz;
import edu.sc.seis.fissuresUtil.cache.CacheEvent;
import edu.sc.seis.fissuresUtil.display.configuration.DOMHelper;
import edu.sc.seis.sod.ConfigurationException;
import edu.sc.seis.sod.CookieJar;
import edu.sc.seis.sod.SodUtil;
import edu.sc.seis.sod.status.Fail;
import edu.sc.seis.sod.status.Pass;
import edu.sc.seis.sod.status.StringTree;
public class PhaseWithoutInterference extends PhaseExists implements EventStationSubsetter {
public PhaseWithoutInterference(Element config) throws ConfigurationException, TauModelException {
super(config);
List<Element> phElements = SodUtil.getAllElements(config, "interferingPhase");
mainPhase = new SeismicPhase(phaseName,
modelName,
0.0);
beginOffset = SodUtil.loadTimeInterval(DOMHelper.extractElement(config, "beginOffset")).getValue(UnitImpl.SECOND);
endOffset = SodUtil.loadTimeInterval(DOMHelper.extractElement(config, "endOffset")).getValue(UnitImpl.SECOND);
for (Element element : phElements) {
List<String> newPhases = TauP_Time.getPhaseNames(SodUtil.getNestedText(element));
for (String s : newPhases) {
if ( ! s.equals(phaseName)) {
interferingPhaseNames.add(s);
} else {
logger.warn("Phase cannot interfer with itself: "+phaseName+", skipping...");
}
}
}
arrivalIndex = DOMHelper.extractInt(config, "arrivalIndex", 1);
// shift to zero based index, so positive index minus one, neg index stays same
if (arrivalIndex > 0) { arrivalIndex -= 1; }
}
@Override
public StringTree accept(CacheEvent event, StationImpl station, CookieJar cookieJar) throws Exception {
Origin origin = event.get_preferred_origin();
double depth = ((QuantityImpl)origin.getLocation().depth).getValue(UnitImpl.KILOMETER);
List<List<Arrival>> arrivals = calcArrivals(depth, new DistAz(station.getLocation(),
origin.getLocation()).getDelta());
List<Arrival> mainArrivals = arrivals.get(0);
double mainTime;
if ( arrivalIndex >= 0 && mainArrivals.size() > arrivalIndex) {
mainTime = mainArrivals.get(arrivalIndex).getTime();
} else if ( arrivalIndex < 0 && mainArrivals.size() > -1*arrivalIndex) {
mainTime = mainArrivals.get(mainArrivals.size()+arrivalIndex).getTime();
} else {
return new Fail(this, "No arrival for "+phaseName+" ("+(arrivalIndex<0?arrivalIndex:arrivalIndex+1)+")");
}
double windowBegin = mainTime + beginOffset;
double windowEnd = mainTime + endOffset;
List<List<Arrival>> interfereArrivals = arrivals.subList(1, arrivals.size());
for (List<Arrival> list : interfereArrivals) {
for (Arrival arrival : list) {
logger.debug("check: "+arrival.getName()+" "+windowBegin+" < "+arrival.getTime()+" < "+windowEnd);
if (arrival.getTime() >= windowBegin && arrival.getTime() <= windowEnd ) {
return new Fail(this, arrival.getName()+" ("+arrival.getTime()+" s) interferes with "+ mainPhase.getName()+" ("+mainTime+" s)");
}
if (onlyFirst) {
// only do first arrival in the list
break;
}
}
}
return new Pass(this);
}
/** calcs arrivals.
* @throws TauModelException */
protected synchronized List<List<Arrival>> calcArrivals(double depth, double degrees) throws TauModelException {
if (mainPhase.getTauModel().getSourceDepth() != depth) {
mainPhase = new SeismicPhase(phaseName,
modelName,
depth);
phases.clear();
for (String phaseName : interferingPhaseNames) {
phases.add(new SeismicPhase(phaseName,
modelName,
depth));
}
}
List<List<Arrival>> out = new ArrayList<List<Arrival>>();
out.add(mainPhase.calcTime(degrees));
for (SeismicPhase phase : phases) {
out.add(phase.calcTime(degrees));
}
return out;
}
boolean onlyFirst = true;
double beginOffset, endOffset;
SeismicPhase mainPhase;
int arrivalIndex = 0;
List<SeismicPhase> phases = new ArrayList<SeismicPhase>(); // main phase is index 0, interferring phases are 1 to end
List<String> interferingPhaseNames = new ArrayList<String>();
private static Logger logger = LoggerFactory.getLogger(PhaseWithoutInterference.class);
}