diff --git a/src/main/java/com/github/thed2lab/analysis/SaccadeVelocity.java b/src/main/java/com/github/thed2lab/analysis/SaccadeVelocity.java index 3d3431b..fc1ec22 100644 --- a/src/main/java/com/github/thed2lab/analysis/SaccadeVelocity.java +++ b/src/main/java/com/github/thed2lab/analysis/SaccadeVelocity.java @@ -27,18 +27,24 @@ static public LinkedHashMap analyze(DataEntry data) { if (!prevID.equals(currID) && positionProfile.size() != 0) { positionProfiles.add(positionProfile); positionProfile = new ArrayList(); - prevID = currID; } Double x = Double.parseDouble(data.getValue(FIXATIONX_INDEX, i)); Double y = Double.parseDouble(data.getValue(FIXATIONY_INDEX, i)); Double t = Double.parseDouble(data.getValue(TIME_INDEX, i)); positionProfile.add(new Double[] {x, y, t}); + prevID = currID; } else if (positionProfile.size() != 0) { positionProfiles.add(positionProfile); positionProfile = new ArrayList(); } + } + + // add the last saccade profile if it isn't already added + // see issue #39 and #40 for explanation + if (positionProfile.size() > 0) { + positionProfiles.add(positionProfile); } for (int i = 0; i < positionProfiles.size(); i++) { @@ -56,7 +62,7 @@ static public LinkedHashMap analyze(DataEntry data) { } - /* + /** * Returns the peak velocity of a given saccade calculated using a two point central difference algorithm. * * @param saccadePoints A list of saccade data points, where each data point is a double array. diff --git a/src/test/java/com/github/thed2lab/analysis/SaccadeVelocityTest.java b/src/test/java/com/github/thed2lab/analysis/SaccadeVelocityTest.java new file mode 100644 index 0000000..cfc5777 --- /dev/null +++ b/src/test/java/com/github/thed2lab/analysis/SaccadeVelocityTest.java @@ -0,0 +1,85 @@ +package com.github.thed2lab.analysis; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +public class SaccadeVelocityTest { + + final double PRECISION = 0.000000001; // allowable floating point error + final static int SCREEN_WIDTH = 1920; + final static int SCREEN_HEIGHT = 1080; + + @Test + public void testGetPeakVelocity_emptyPoints_returnNaN() { + List emptyList = new ArrayList<>(); + boolean isNaN = Double.isNaN(SaccadeVelocity.getPeakVelocity(emptyList)); + assertTrue(isNaN); + } + + @Test + public void testGetPeakVelocity_onePoint_returnNaN() { + List onePoint = new ArrayList<>() {{ + add(new Double[]{1., 1., 0.001}); + }}; + boolean isNaN = Double.isNaN(SaccadeVelocity.getPeakVelocity(onePoint)); + assertTrue(isNaN); + } + + @Test + public void testGetPeakVelocity_aboveThreshold_return0() { + List saccadePoints = new ArrayList<>() {{ + add(new Double[]{0., 0., 0.}); + add(new Double[]{0., 10., 0.0001}); + }}; + // 2332.21914 > 700 => return 0 + boolean isZero = SaccadeVelocity.getPeakVelocity(saccadePoints) == 0; + assertTrue(isZero); + } + + @Test + public void testGetPeakVelocity_normalUseCase_returnVelocityValue() { + + } + + @Test + public void testSaccadeVelocityAnalyze_nonContinuousEndsWithSaccadeData() { + final String GAZE_PATH = "./src/test/resources/filtered_by_validity.csv"; + final double EXPECTED_AVG_PEAK = 169.15239533934; + final String KEY = "average_peak_saccade_velocity"; + DataEntry gazeData = DataFilter.applyScreenSize(FileHandler.buildDataEntry(new File(GAZE_PATH)), SCREEN_WIDTH, SCREEN_HEIGHT); + + Map actualMap = SaccadeVelocity.analyze(gazeData); + assertEquals(1, actualMap.size()); + assertEquals(EXPECTED_AVG_PEAK, Double.parseDouble(actualMap.get(KEY)), PRECISION); + + } + + @Test + public void testSaccadeVelocityAnalyze_nonContinuousEndsWithFixationData() { + final String GAZE_PATH = "./src/test/resources/filtered_by_validity.csv"; + final double EXPECTED_AVG_PEAK = 169.15239533934; + final String KEY = "average_peak_saccade_velocity"; + DataEntry gazeData = DataFilter.applyScreenSize(FileHandler.buildDataEntry(new File(GAZE_PATH)), SCREEN_WIDTH, SCREEN_HEIGHT); + gazeData.process(Arrays.asList( + "0","X-Plane","971","6.53005","5.88E+12","0.47815","0.45335", + "6.53005","0.14856","25","1","0.46056","0.45713","1","0.60729", + "0.47315","0"," ","0","","0.41066","0.36362","16.25439","1.08789", + "1","0.61855","0.37037","15.69818","1.08789","1","0","0","11", + "4.43149","1","4.03482","1","0","0","0","0","0","0","0","0","1", + "1","1","1","1","1","1","0","0","0","AOI_A","0","0","0" + )); + + Map actualMap = SaccadeVelocity.analyze(gazeData); + assertEquals(1, actualMap.size()); + assertEquals(EXPECTED_AVG_PEAK, Double.parseDouble(actualMap.get(KEY)), PRECISION); + + } +}