package org.signalml.domain.signal.filter.export;
import java.io.File;
import java.io.IOException;
import org.signalml.app.model.signal.SignalExportDescriptor;
import org.signalml.domain.montage.Montage;
import org.signalml.domain.montage.filter.FFTSampleFilter;
import org.signalml.domain.montage.filter.SampleFilterDefinition;
import org.signalml.domain.montage.filter.TimeDomainSampleFilter;
import org.signalml.domain.signal.SignalWriterMonitor;
import org.signalml.domain.signal.filter.MultichannelSampleFilter;
import org.signalml.domain.signal.raw.RawSignalSampleSource;
import org.signalml.domain.signal.raw.RawSignalWriter;
import org.signalml.domain.signal.samplesource.MultichannelSampleSource;
import org.signalml.math.iirdesigner.BadFilterParametersException;
/**
* A multichannel filter which is able to filter the data more appropriately
* than the {@link MultichannelSampleFilter}. This should be used to export
* filtered signals to file.
*
* @author Piotr Szachewicz
*/
public class MultichannelSampleFilterForExport extends MultichannelSampleFilter implements SignalWriterMonitor {
/**
* Files storing the temporary results of the filtering.
*/
private File inputFile = new File("export2.bin.tmp");
private File outputFile = new File("export1.bin.tmp");
private RawSignalWriter rawSignalWriter = new RawSignalWriter();
/**
* This sample source stores the filtered samples after the filtering is done.
*/
private RawSignalSampleSource resultSampleSource;
/**
* Monitors the progress made by this filter while exporting.
*/
private SignalWriterMonitor signalWriterMonitor;
private int filteringState = 0;
private boolean isFiltFiltEnabled;
public MultichannelSampleFilterForExport(MultichannelSampleSource source, Montage montage) throws BadFilterParametersException, IOException { //assume its ASSEMBLED sampleSource
super(source);
this.currentMontage = montage;
this.isFiltFiltEnabled = montage.isFiltfiltEnabled();
}
MultichannelSampleFilterForExport(MultichannelSampleSource source, Montage montage, RawSignalWriter rawSignalWriter) throws BadFilterParametersException, IOException { //assume its ASSEMBLED sampleSource
super(source);
this.currentMontage = montage;
this.rawSignalWriter = rawSignalWriter;
this.isFiltFiltEnabled = montage.isFiltfiltEnabled();
}
public RawSignalWriter getRawSignalWriter() {
return rawSignalWriter;
}
public void setSignalWriterMonitor(SignalWriterMonitor signalWriterMonitor) {
this.signalWriterMonitor = signalWriterMonitor;
}
/**
* Prepares the filtered data so that {@link MultichannelSampleFilterForExport#resultSampleSource}
* is filled with the already filtered samples.
* @throws BadFilterParametersException
* @throws IOException
*/
public void prepareFilteredData() throws BadFilterParametersException, IOException {
MultichannelSampleSource inputSource = source;
for (int i = 0; i < currentMontage.getSampleFilterCount(); i++) {
if (!currentMontage.isFilterEnabled(i))
continue;
SampleFilterDefinition sampleFilter = currentMontage.getSampleFilterAt(i);
if (i > 0) {
//swapFiles
File tmp = inputFile;
inputFile = outputFile;
outputFile = tmp;
inputSource = createRawSignalSampleSource(inputFile, source);
}
AbstractMultichannelSingleFilterForExport filter;
if (sampleFilter instanceof FFTSampleFilter)
filter = new FFTMultichannelSingleFilterForExport(inputSource, (FFTSampleFilter) sampleFilter,
currentMontage.getFilteringExclusionArray(i));
else
filter = new IIRMultichannelSingleFilterForExport(inputSource, (TimeDomainSampleFilter) sampleFilter,
currentMontage.getFilteringExclusionArray(i), isFiltFiltEnabled,
this);
filteringState++;
//switch files
rawSignalWriter.writeSignal(outputFile, filter, getSignalExportDescriptor(), this);
filteringState++;
}
if (currentMontage.getSampleFilterCount() > 0) {
inputFile.delete();
resultSampleSource = createRawSignalSampleSource(outputFile, source);
}
}
protected static RawSignalSampleSource createRawSignalSampleSource(File file, MultichannelSampleSource source) throws IOException {
return new RawSignalSampleSource(file, source.getChannelCount(), source.getSamplingFrequency(), getSignalExportDescriptor().getSampleType(), getSignalExportDescriptor().getByteOrder());
}
protected static SignalExportDescriptor getSignalExportDescriptor() {
return new SignalExportDescriptor();
}
@Override
public void getSamples(int channel, double[] target, int signalOffset, int count, int arrayOffset) {
if (currentMontage.getSampleFilterCount() > 0) {
if (filteringState == 0) {
try {
prepareFilteredData();
} catch (BadFilterParametersException e) {
// TODO Auto-generated catch block
logger.error("", e);
} catch (IOException e) {
// TODO Auto-generated catch block
logger.error("", e);
}
}
resultSampleSource.getSamples(channel, target, signalOffset, count, arrayOffset);
} else {
source.getSamples(channel, target, signalOffset, count, arrayOffset);
}
if (signalOffset + count == this.getSampleCount(channel)) {
//after writing the last samples delete these files
inputFile.delete();
outputFile.delete();
}
}
@Override
public void setProcessedSampleCount(int sampleCount) {
float realSampleCount = (float)(source.getSampleCount(0) * filteringState + sampleCount);
realSampleCount = realSampleCount / (2 * currentMontage.getSampleFilterCount());
if (signalWriterMonitor != null )
signalWriterMonitor.setProcessedSampleCount((int)realSampleCount);
}
@Override
public void abort() {
// TODO Auto-generated method stub
}
@Override
public boolean isRequestingAbort() {
// TODO Auto-generated method stub
return false;
}
}