package org.signalml.app.worker.signal; import static org.signalml.app.util.i18n.SvarogI18n._; import java.util.ArrayList; import java.util.List; import org.signalml.app.model.tag.SlopeType; import org.signalml.app.model.tag.SynchronizeTagsWithTriggerParameters; import org.signalml.app.worker.SwingWorkerWithBusyDialog; import org.signalml.domain.signal.samplesource.MultichannelSampleSource; /** * This worker is responsible for finding a specific type of {@link SlopeType slopes} * throught the signal. * * @author Piotr Szachewicz */ public class FindSignalSlopesWorker extends SwingWorkerWithBusyDialog<Integer[], Void> { private static final int DEFAULT_BUFFER_SIZE = 1024; private int bufferSize = DEFAULT_BUFFER_SIZE; private SynchronizeTagsWithTriggerParameters parameters; private double threshold; private MultichannelSampleSource sampleSource; private int lengthThreshold; public FindSignalSlopesWorker(SynchronizeTagsWithTriggerParameters parameters) { super(null); this.parameters = parameters; this.threshold = parameters.getThresholdValue(); this.sampleSource = parameters.getSampleSource(); this.lengthThreshold = (int) (parameters.getLengthThresholdValue() * sampleSource.getSamplingFrequency()); getBusyDialog().setText(_("Finding trigger activating slopes.")); getBusyDialog().setCancellable(false); } public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize; } public int getBufferSize() { return bufferSize; } @Override protected Integer[] doInBackground() throws Exception { showBusyDialog(); List<TriggerPush> triggerPushes = new ArrayList<TriggerPush>(); int sampleCount = sampleSource.getSampleCount(0); int currentSample = 0; int triggerAsc = -1; int triggerDesc = -1; while(currentSample < sampleCount) { int currentBufferSize = bufferSize; if (currentSample + currentBufferSize > sampleCount) currentBufferSize = sampleCount - currentSample; double[] samples = new double[currentBufferSize]; sampleSource.getSamples(parameters.getTriggerChannel(), samples, currentSample, currentBufferSize, 0); int i = 0; for (; i < samples.length-1; i++) { double currentSampleValue = samples[i]; double nextSampleValue = samples[i+1]; if (isSlopeAscending(currentSampleValue, nextSampleValue)) triggerAsc = currentSample + i + 1; else if (isSlopeDescending(currentSampleValue, nextSampleValue)) { triggerDesc = currentSample + i + 1; TriggerPush triggerPush = null; if (triggerAsc == -1) { // if the first slope is descending triggerPush = new TriggerPush(0, triggerDesc); triggerPush.setStartedProperly(false); } else triggerPush = new TriggerPush(triggerAsc, triggerDesc); triggerPushes.add(triggerPush); triggerAsc = -1; triggerDesc = -1; } } currentSample += (bufferSize-1); } if (triggerAsc != -1 && triggerDesc == -1) { // if the last push does not end triggerDesc = sampleCount-1; TriggerPush triggerPush = new TriggerPush(triggerAsc, triggerDesc); triggerPush.setEndedProperly(false); triggerPushes.add(triggerPush); } List<Integer> slopePositions = convertTriggerPushesToSlopePositions(triggerPushes); return slopePositions.toArray(new Integer[0]); } protected boolean isSlopeAscending(double currentSample, double nextSample) { return (nextSample >= threshold && currentSample < threshold); } protected boolean isSlopeDescending(double currentSample, double nextSample) { return (nextSample < threshold && currentSample >= threshold); } protected List<Integer> convertTriggerPushesToSlopePositions(List<TriggerPush> triggerPushes) { List<Integer> slopePositions = new ArrayList<Integer>(); for (TriggerPush triggerPush: triggerPushes) { if (parameters.isLengthThresholdEnabled() && triggerPush.getLength() < lengthThreshold) continue; switch(parameters.getSlopeType()) { case ASCENDING: if (triggerPush.isStartedProperly()) slopePositions.add(triggerPush.getStartSample()); break; case BOTH: if (triggerPush.isStartedProperly()) slopePositions.add(triggerPush.getStartSample()); if (triggerPush.isEndedProperly()) slopePositions.add(triggerPush.getEndSample()); break; case DESCENDING: if (triggerPush.isEndedProperly()) slopePositions.add(triggerPush.getEndSample()); break; } } return slopePositions; } }