package org.signalml.domain.signal.filter.export; import java.io.File; import java.io.IOException; import org.signalml.domain.montage.filter.TimeDomainSampleFilter; import org.signalml.domain.signal.SignalWriterMonitor; import org.signalml.domain.signal.filter.iir.ExportIIRSinglechannelSampleFilter; import org.signalml.domain.signal.filter.iir.helper.GrowSignalSampleSource; import org.signalml.domain.signal.filter.iir.helper.TrimSignalSampleSource; import org.signalml.domain.signal.raw.RawSignalSampleSource; import org.signalml.domain.signal.raw.RawSignalWriter; import org.signalml.domain.signal.raw.ReversedSampleSource; import org.signalml.domain.signal.samplesource.ChannelSelectorSampleSource; import org.signalml.domain.signal.samplesource.MultichannelSampleSource; import org.signalml.domain.signal.samplesource.SampleSource; import org.signalml.domain.signal.samplesource.SampleSourceEngine; import org.signalml.math.iirdesigner.BadFilterParametersException; import org.signalml.math.iirdesigner.FilterCoefficients; import org.signalml.math.iirdesigner.IIRDesigner; /** * This class is able to filter a {@link MultichannelSampleSource} with a single IIR filter. * * @author Piotr Szachewicz */ public class IIRMultichannelSingleFilterForExport extends AbstractMultichannelSingleFilterForExport implements SignalWriterMonitor { /** * Files that are used to store temporary filtering results. */ private File temporaryFile1 = new File("exportsub1.bin.tmp"); private File temporaryFile2 = new File("exportsub2.bin.tmp"); /** * A {@link RawSignalWriter} for writing the temporary results to files. */ private RawSignalWriter rawSignalWriter = new RawSignalWriter(); /** * The coefficients of the filter that will be used to filter the original sample source. */ private FilterCoefficients coefficients; /** * True if the filtering was done and the filtered samples could be * obtained through the getSamples method. */ private boolean filteringDone = false; /** * The number of temporary files that were written. */ private int temporaryFilesWritten = 0; /** * This object monitors the progress made while filtering the data. */ private SignalWriterMonitor signalWriterMonitor; private boolean[] filterExclusionArray; private boolean filtFiltEnabled; public IIRMultichannelSingleFilterForExport(MultichannelSampleSource inputSource, TimeDomainSampleFilter definition, boolean[] filterExclusionArray, boolean filtFiltEnabled, SignalWriterMonitor signalWriterMonitor) throws BadFilterParametersException, IOException { super(inputSource, definition, filterExclusionArray); this.signalWriterMonitor = signalWriterMonitor; this.filterExclusionArray = filterExclusionArray; this.filtFiltEnabled = filtFiltEnabled; prepareFilteredData(inputSource); } protected void prepareFilteredData(MultichannelSampleSource inputSource) throws BadFilterParametersException, IOException { int startIndex = 0; int endIndex = inputSource.getSampleCount(0); //step 1 - filtering rightwise filterEngines = new SampleSourceEngine[this.source.getChannelCount()]; for (int channelNumber = 0; channelNumber < source.getChannelCount(); channelNumber++) { ChannelSelectorSampleSource input = new ChannelSelectorSampleSource(source, channelNumber); GrowSignalSampleSource grownSampleSource = new GrowSignalSampleSource(input, getFilterCoefficients()); if (!filterExclusionArray[channelNumber]) { filterEngines[channelNumber] = new ExportIIRSinglechannelSampleFilter(grownSampleSource, getFilterCoefficients()); int paddingSize = this.getSampleCount(channelNumber) - inputSource.getSampleCount(channelNumber); startIndex = paddingSize/2; endIndex = this.getSampleCount(channelNumber) - paddingSize/2; } else { filterEngines[channelNumber] = grownSampleSource; } } if (!filtFiltEnabled) { for (int channelNumber = 0; channelNumber < filterEngines.length; channelNumber++) { if (filterEngines[channelNumber] != null) filterEngines[channelNumber] = new TrimSignalSampleSource(filterEngines[channelNumber], startIndex, endIndex); } } else { rawSignalWriter.writeSignal(temporaryFile1, this, MultichannelSampleFilterForExport.getSignalExportDescriptor(), this); temporaryFilesWritten++; //step 2 - filtering leftwise source = createFileSampleSource(temporaryFile1); filterEngines = new SampleSourceEngine[this.source.getChannelCount()]; for (int channelNumber = 0; channelNumber < source.getChannelCount(); channelNumber++) { if (!filterExclusionArray[channelNumber]) { ChannelSelectorSampleSource input = new ChannelSelectorSampleSource(source, channelNumber); ReversedSampleSource reversedSampleSource = new ReversedSampleSource(input); filterEngines[channelNumber] = new ExportIIRSinglechannelSampleFilter(reversedSampleSource, getFilterCoefficients()); } } rawSignalWriter.writeSignal(temporaryFile2, this, MultichannelSampleFilterForExport.getSignalExportDescriptor(), this); temporaryFilesWritten++; //step 3 - reverse samples source = createFileSampleSource(temporaryFile2); filterEngines = new SampleSourceEngine[this.source.getChannelCount()]; //all of them are null for (int channelNumber = 0; channelNumber < source.getChannelCount(); channelNumber++) { SampleSource input = new ChannelSelectorSampleSource(source, channelNumber); if (!filterExclusionArray[channelNumber]) { input = new ReversedSampleSource(input); } filterEngines[channelNumber] = new TrimSignalSampleSource(input, startIndex, endIndex); } } filteringDone = true; } protected MultichannelSampleSource createFileSampleSource(File file) throws IOException { RawSignalSampleSource rawSignalSampleSource = new RawSignalSampleSource(file, source.getChannelCount(), source.getSamplingFrequency(), MultichannelSampleFilterForExport.getSignalExportDescriptor().getSampleType(), MultichannelSampleFilterForExport.getSignalExportDescriptor().getByteOrder()); return rawSignalSampleSource; } protected FilterCoefficients getFilterCoefficients() throws BadFilterParametersException { if (coefficients == null) { coefficients = IIRDesigner.designDigitalFilter((TimeDomainSampleFilter) definition); } return coefficients; } @Override public void getSamples(int channel, double[] target, int signalOffset, int count, int arrayOffset) { super.getSamples(channel, target, signalOffset, count, arrayOffset); if (signalOffset + count == this.getSampleCount(channel) && filteringDone) { //after writing the last samples delete these files temporaryFile1.delete(); temporaryFile2.delete(); } } @Override protected void createEngine(int channelNumber, boolean[] filterExclusionArray) throws BadFilterParametersException { //do nothing } @Override public void setProcessedSampleCount(int sampleCount) { float realSampleCount = (float)(source.getSampleCount(0) * temporaryFilesWritten + sampleCount); realSampleCount = realSampleCount / 2; if (signalWriterMonitor != null) signalWriterMonitor.setProcessedSampleCount((int)realSampleCount); } @Override public void abort() { // TODO Auto-generated method stub } @Override public boolean isRequestingAbort() { return false; } }