package edu.sc.seis.sod.process.waveform;
import org.w3c.dom.Element;
import edu.iris.Fissures.IfNetwork.ChannelNotFound;
import edu.iris.Fissures.IfNetwork.Filter;
import edu.iris.Fissures.IfNetwork.FilterType;
import edu.iris.Fissures.IfNetwork.Instrumentation;
import edu.iris.Fissures.IfSeismogramDC.RequestFilter;
import edu.iris.Fissures.model.UnitImpl;
import edu.iris.Fissures.network.ChannelImpl;
import edu.iris.Fissures.seismogramDC.LocalSeismogramImpl;
import edu.sc.seis.fissuresUtil.bag.Transfer;
import edu.sc.seis.fissuresUtil.cache.CacheEvent;
import edu.sc.seis.fissuresUtil.cache.InstrumentationLoader;
import edu.sc.seis.fissuresUtil.display.configuration.DOMHelper;
import edu.sc.seis.fissuresUtil.sac.FissuresToSac;
import edu.sc.seis.fissuresUtil.sac.InvalidResponse;
import edu.sc.seis.seisFile.sac.SacPoleZero;
import edu.sc.seis.sod.ConfigurationException;
import edu.sc.seis.sod.CookieJar;
import edu.sc.seis.sod.Start;
import edu.sc.seis.sod.Threadable;
import edu.sc.seis.sod.source.SodSourceException;
import edu.sc.seis.sod.source.network.NetworkSource;
import edu.sc.seis.sod.status.Fail;
import edu.sc.seis.sod.status.StringTreeLeaf;
/**
* @author crotwell
* Created on Aug 1, 2005
*/
public class TransferResponse implements WaveformProcess, Threadable {
public TransferResponse(Element config) throws ConfigurationException {
lowCut = DOMHelper.extractFloat(config, "lowCut", DEFAULT_LOW_CUT);
lowPass = DOMHelper.extractFloat(config, "lowPass", DEFAULT_LOW_PASS);
highPass = DOMHelper.extractFloat(config, "highPass", DEFAULT_HIGH_PASS);
highCut = DOMHelper.extractFloat(config, "highCut", DEFAULT_HIGH_CUT);
}
public WaveformResult accept(CacheEvent event,
ChannelImpl channel,
RequestFilter[] original,
RequestFilter[] available,
LocalSeismogramImpl[] seismograms,
CookieJar cookieJar) throws Exception {
try {
LocalSeismogramImpl[] out = new LocalSeismogramImpl[seismograms.length];
NetworkSource na = Start.getNetworkArm().getNetworkSource();
if(seismograms.length > 0) {
SacPoleZero polezero = checkResponse(channel, na);
Transfer transfer = new Transfer();
for(int i = 0; i < seismograms.length; i++) {
out[i] = transfer.apply(seismograms[i], polezero, lowCut, lowPass, highPass, highCut);
} // end of for (int i=0; i<seismograms.length; i++)
return new WaveformResult(out, new StringTreeLeaf(this, true));
}
return new WaveformResult(true, seismograms, this);
} catch(InvalidResponse e) {
return new WaveformResult(seismograms, new Fail(this, e.getMessage()));
}
}
public static SacPoleZero checkResponse(ChannelImpl chan, NetworkSource na) throws InvalidResponse, SodSourceException {
try {
Instrumentation inst = na.getInstrumentation(chan);
if (inst == null) {
throw new InvalidResponse("Response is null");
}
InstrumentationLoader.checkResponse(inst.the_response);
UnitImpl inUnits = ((UnitImpl)inst.the_response.stages[0].input_units);
if ( ! (inUnits.isConvertableTo(UnitImpl.METER)
|| inUnits.isConvertableTo(UnitImpl.METER_PER_SECOND)
|| inUnits.isConvertableTo(UnitImpl.METER_PER_SECOND_PER_SECOND) )) {
throw new InvalidResponse("Response input units are not convertible to m, m/s or m/s/s, cannot apply correction."+inUnits);
}
Filter filter = inst.the_response.stages[0].filters[0];
if (filter.discriminator().value() != FilterType._POLEZERO) {
String filterType = " ("+filter.discriminator().value()+")";
if (filter.discriminator().value() == FilterType._COEFFICIENT) {
filterType = "Coefficient Response ("+filterType+")";
} else if (filter.discriminator().value() == FilterType._LIST) {
filterType = "List Response ("+filterType+")";
}
throw new InvalidResponse("Instrumentation is not a of pole-zero type: "+filterType);
}
try {
return FissuresToSac.getPoleZero(inst.the_response);
} catch (IllegalArgumentException e) {
throw new InvalidResponse(e.getMessage(), e);
}
} catch(ChannelNotFound e) {
// channel not found is thrown if there is no response for a
// channel at a time
throw new InvalidResponse("No instrumentation found", e);
}
}
public boolean isThreadSafe() {
return true;
}
float lowCut, lowPass, highPass, highCut;
public static final float DEFAULT_LOW_CUT = 0.005f;
public static final float DEFAULT_LOW_PASS = 0.01f;
public static final float DEFAULT_HIGH_PASS = 1e5f;
public static final float DEFAULT_HIGH_CUT = 1e6f;
}