package org.signalml.plugin.newartifact.logic.tag.creators; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import org.signalml.plugin.newartifact.data.NewArtifactType; import org.signalml.plugin.newartifact.data.tag.NewArtifactTagData; import org.signalml.plugin.newartifact.data.tag.NewArtifactTagResult; import org.signalml.plugin.newartifact.logic.stat.Stat; public class TechnicalTagCreator extends AbstractNewArtifactTagCreator implements INewArtifactTagCreator { private static final NewArtifactType CREATOR_TYPE = NewArtifactType.TECHNICAL; private static final double FACTOR = 0.3777D; private static final double TRESHOLDM_A = 10D; private static final double TRESHOLDM_B = 2D; private static final double TRESHOLDS_A = 6D; private static final double TRESHOLDS_B = 1D; private Stat stdDeviationAlgorithm; public TechnicalTagCreator() { super(); this.stdDeviationAlgorithm = new Stat(); } @Override protected String getTagName() { return "X"; } @Override protected String getTagDescription() { return "Aparaturowe."; } @Override protected int getTagStretch() { return 4; } @Override public NewArtifactTagResult tag(NewArtifactTagData data) { final double sensitivity = data.parameters .getSensitivity(TechnicalTagCreator.CREATOR_TYPE) / 100.0; final double tresholdM = TechnicalTagCreator.TRESHOLDM_A + sensitivity * (TechnicalTagCreator.TRESHOLDM_B - TechnicalTagCreator.TRESHOLDM_A); final double tresholdS = TechnicalTagCreator.TRESHOLDS_A + sensitivity * (TechnicalTagCreator.TRESHOLDS_B - TechnicalTagCreator.TRESHOLDS_A); boolean exclusions[] = this.getExclusionMatrix(data); double channelDataCopy[][] = new double[3][]; double median[] = new double[3]; double std[] = new double[3]; double tresholds[] = new double[] { tresholdM, tresholdM, tresholdS }; int eegChannels[] = data.eegChannels; int blockCount = data.source[0].length / 3; int tailLength = blockCount >> 2; List<Integer> tags = new LinkedList<Integer>(); for (int j = 0; j < eegChannels.length; ++j) { double channelData[] = data.source[eegChannels[j]]; for (int i = 0; i < channelData.length; i += 3) { channelData[i] = -channelData[i]; } for (int k = 0; k < 2; ++k) { double min = Double.POSITIVE_INFINITY; for (int i = k; i < channelData.length; i += 3) { if (min > channelData[i]) { min = channelData[i]; } } channelDataCopy[k] = shiftMin(channelData, k, 3, min); } channelDataCopy[2] = shiftMin(channelData, 2, 3, 0.0D); for (int k = 0; k < 3; ++k) { double sortedData[] = Arrays.copyOf(channelDataCopy[k], channelDataCopy[k].length); Arrays.sort(sortedData); median[k] = sortedData[blockCount >> 1]; std[k] = this.stdDeviationAlgorithm.standardDeviation(Arrays.copyOfRange(sortedData, tailLength - 1, blockCount - tailLength - 1)) / TechnicalTagCreator.FACTOR; } for (int i = 0; i < blockCount; ++i) { for (int k = 0; k < 3; ++k) { double value = exclusions[eegChannels[j]] ? 0.0 : channelDataCopy[k][i]; if (value > median[k] + std[k] * tresholds[k]) { tags.add(i); break; } } } } return this.constructResult(tags); } private double[] shiftMin(double channelData[], int start, int step, double min) { double channelCopy[] = new double[(channelData.length + step - 1) / step]; double positiveMin = Double.POSITIVE_INFINITY; for (int i = start; i < channelData.length; i += step) { if (channelData[i] >= min && positiveMin > channelData[i]) { positiveMin = channelData[i]; } } positiveMin -= min; for (int j = 0, i = start; i < channelData.length; i += step, ++j) { channelCopy[j] = Math.log(channelData[i] > min ? channelData[i] - min : positiveMin); } return channelCopy; } }