/* SegmentedSampleSource.java created 2008-01-26 * */ package org.signalml.domain.signal.space; import org.signalml.domain.signal.MultichannelSampleProcessor; import org.signalml.domain.signal.samplesource.MultichannelSampleSource; import org.signalml.domain.signal.samplesource.MultichannelSegmentedSampleSource; import org.signalml.exception.SanityCheckException; import org.signalml.plugin.export.signal.SignalSelection; import org.signalml.plugin.export.signal.SignalSelectionType; /** * This class represents the {@link MultichannelSampleSource source} of samples * for the {@link SignalSelection selected} part of the signal. * Contains the index of the first sample, selected channels and the length * of the segment. * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. */ public class SelectionSegmentedSampleSource extends MultichannelSampleProcessor implements MultichannelSegmentedSampleSource { /** * the index of the first selected sample */ private int firstSample; /** * the number of samples in the selection */ private int segmentLength; /** * the number of segments in this source: * <ul> * <li>if the {@link SignalSelection selection} is a page selection - the * number of pages in the selection</li> * <li>if the selection is a block selection - the number of blocks</li> * <li>if the selection is a channel selection - <code>1</code></li> * </ul> */ private int segmentCount; /** * the number of channels in this source */ private int channelCount; /** * an array mapping indexes in this source to the indexes of channels * in the actual source */ private int[] channelIndices; /** * the number of segments that can not be used (the required * segment is not in the signal). */ private int unusableSegmentCount; /** * the point in time (seconds) where the selection starts */ private double firstPosition; /** * Constructor. Creates a source without the selection * @param source the actual source of samples */ public SelectionSegmentedSampleSource(MultichannelSampleSource source) { super(source); } /** * Constructor. Creates the source of samples based on a given * {@link MultichannelSampleSource source} of the signal, * {@link ChannelSpace subset} of channels and * {@link SignalSelection selection}. * @param source the source for the whole signal * @param selection the selection of the part of the signal * @param channelSpace the subset of channels * @param pageSize the size of a page (in seconds) * @param blockSize the size of a block (in seconds) */ public SelectionSegmentedSampleSource(MultichannelSampleSource source, SignalSelection selection, SignalSpace signalSpace, float pageSize, float blockSize) { super(source); ChannelSpace channelSpace = signalSpace.getChannelSpace(); float samplingFrequency = source.getSamplingFrequency(); SignalSelectionType selectionType = selection.getType(); // determine channel count & indices if (channelSpace != null) { channelCount = channelSpace.size(); channelIndices = channelSpace.getSelectedChannels(); } else if (selectionType.isChannel() && selection.getChannel() != SignalSelection.CHANNEL_NULL) { channelCount = 1; channelIndices = new int[] { selection.getChannel() }; } else { // all channels channelCount = source.getChannelCount(); channelIndices = new int[channelCount]; for (int i=0; i<channelCount; i++) { channelIndices[i] = i; } } // determine segmentation firstPosition = selection.getPosition(); firstSample = (int)(firstPosition * samplingFrequency); if (selectionType.isChannel() || (selectionType.isPage() && !signalSpace.isWholeSignalCompletePagesOnly())) { segmentCount = 1; segmentLength = (int)(selection.getLength() * samplingFrequency); } else { float segmentSize; if (selectionType.isPage()) { segmentSize = pageSize; segmentLength = (int)(pageSize * samplingFrequency); } else if (selectionType.isBlock()) { segmentSize = blockSize; segmentLength = (int)(blockSize * samplingFrequency); } else { throw new SanityCheckException("Unsupported type [" + selectionType + "]"); } segmentCount = selection.getSegmentLength(segmentSize); if (segmentCount * segmentSize < selection.getLength()) { unusableSegmentCount = 1; } else { unusableSegmentCount = 0; } } } @Override public double getSegmentTime(int segment) { return firstPosition + (segmentLength*segment); } /** * Constructor. Creates the source of samples based on the given * {@link MultichannelSampleSource source} of all channels an the given * {@link SelectionSegmentedSampleSourceDescriptor descriptor}. * @param source the source of samples for all channels * @param descriptor the descriptor of this source */ public SelectionSegmentedSampleSource(MultichannelSampleSource source, SelectionSegmentedSampleSourceDescriptor descriptor) { this(source); firstSample = descriptor.getFirstSample(); segmentLength = descriptor.getSegmentLength(); segmentCount = descriptor.getSegmentCount(); channelCount = descriptor.getChannelCount(); channelIndices = descriptor.getChannelIndices(); unusableSegmentCount = descriptor.getUnusableSegmentCount(); } @Override public SegmentedSampleSourceDescriptor createDescriptor() { SelectionSegmentedSampleSourceDescriptor descriptor = new SelectionSegmentedSampleSourceDescriptor(); descriptor.setFirstSample(firstSample); descriptor.setSegmentLength(segmentLength); descriptor.setSegmentCount(segmentCount); descriptor.setChannelCount(channelCount); descriptor.setChannelIndices(channelIndices); descriptor.setUnusableSegmentCount(unusableSegmentCount); return descriptor; } @Override public void getSamples(int channel, double[] target, int signalOffset, int count, int arrayOffset) { source.getSamples(channelIndices[channel], target, firstSample+signalOffset, count, arrayOffset); } @Override public int getDocumentChannelIndex(int channel) { return source.getDocumentChannelIndex(channelIndices[channel]); } @Override public int getChannelCount() { return channelCount; } @Override public int getSegmentCount() { return segmentCount; } @Override public int getSegmentLengthInSamples() { return segmentLength; } @Override public int getSampleCount(int channel) { return (segmentCount * segmentLength); } @Override public String getLabel(int channel) { return source.getLabel(channelIndices[channel]); } @Override public int getUnusableSegmentCount() { return unusableSegmentCount; } @Override public void getSegmentSamples(int channel, double[] target, int segment) { source.getSamples(channelIndices[channel], target, firstSample+(segment*segmentLength), segmentLength, 0); } }