Package de.dfki.km.text20.services.evaluators.gaze.util

Source Code of de.dfki.km.text20.services.evaluators.gaze.util.FixationsUtil

/*
* FixationsUtil.java
*
* Copyright (c) 2010, Ralf Biedert, DFKI. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301  USA
*
*/
package de.dfki.km.text20.services.evaluators.gaze.util;

import static net.jcores.CoreKeeper.$;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import net.jcores.cores.CoreObject;
import net.jcores.interfaces.functions.F1;
import net.jcores.interfaces.functions.F2DeltaObjects;
import net.jcores.interfaces.functions.F2ReduceObjects;
import net.jcores.utils.Staple;
import de.dfki.km.text20.services.evaluators.gaze.listenertypes.fixation.Fixation;
import de.dfki.km.text20.services.trackingdevices.eyes.EyeTrackingEvent;

/**
* Methods regarding fixations.
*
* @author rb
*
*/
public class FixationsUtil {

    /** */
    private final List<Fixation> fixations;

    /** */
    private CoreObject<Fixation> $fixations;

    /**
     * @param fixations
     */
    public FixationsUtil(final List<Fixation> fixations) {
        this.fixations = fixations;
        this.$fixations = $(fixations);
    }

    /**
     * Calculates the average y point of all fixations.
     *
     * @return .
     */
    public int getAverageYPosition() {
        final Staple<Point> staple = this.$fixations.map(new F1<Fixation, Point>() {
            @Override
            public Point f(Fixation arg0) {
                return arg0.getCenter();
            }
        }).staple(new Point(0, 0), new F2ReduceObjects<Point>() {
            @Override
            public Point f(Point arg0, Point arg1) {
                arg0.x += arg1.x;
                arg0.y += arg1.y;
                return arg0;
            }
        });

        return staple.staple().y / staple.size();
    }

    /**
     * TODO: Calculate proper median w. null elements considered.
     *
     * Calculates the average y point of all fixations.
     *
     * @return .
     */
    public int getMedianYPosition() {
        return this.$fixations.map(new F1<Fixation, Point>() {
            @Override
            public Point f(Fixation arg0) {
                return arg0.getCenter();
            }
        }).compact().sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                return o1.y - o2.y;
            }
        }).get(0.5).y;
    }

    /**
     * Returns the average length of saccades.
     *
     * @return .
     */
    @SuppressWarnings("boxing")
    public int getAvgSaccadeLength() {
        final Staple<Double> staple = this.$fixations.map(new F1<Fixation, Point>() {
            @Override
            public Point f(Fixation arg0) {
                return arg0.getCenter();
            }
        }).delta(new F2DeltaObjects<Point, Double>() {
            @Override
            public Double f(Point arg0, Point arg1) {
                return arg0.distance(arg1);
            }
        }).staple(0.0, new F2ReduceObjects<Double>() {
            @Override
            public Double f(Double arg0, Double arg1) {
                return arg0 + arg1;
            }
        });

        return (int) (staple.staple() / staple.size());
    }

    /**
     * Returns all saccade lengths.
     * 
     * @return .
     */
    @SuppressWarnings("boxing")
    public double[] getAllSaccadeLengths() {
        CoreObject<Double> fill = this.$fixations.map(new F1<Fixation, Point>() {
            public Point f(Fixation arg0) {
                return arg0.getCenter();
            }
        }).delta(new F2DeltaObjects<Point, Double>() {
            @Override
            public Double f(Point arg0, Point arg1) {
                return arg0.distance(arg1);
            }
        });

        // And now the ugly part: unbox
        final double rval[] = new double[fill.size()];
        for (int i = 0; i < rval.length; i++) {
            rval[i] = fill.get(i, Double.NaN);
        }

        return rval;
    }

    /**
     * Returns all angles between the fixations
     *
     * @return .
     */
    @SuppressWarnings("boxing")
    public double[] getAllAngles() {
        CoreObject<Double> fill = this.$fixations.map(new F1<Fixation, Point>() {
            @Override
            public Point f(Fixation arg0) {
                return arg0.getCenter();
            }
        }).delta(new F2DeltaObjects<Point, Double>() {
            @Override
            public Double f(Point c1, Point c2) {
                return Math.atan2(c2.y - c1.y, c2.x - c1.x);
            }
        });

        // And now the ugly part: unbox
        final double rval[] = new double[fill.size()];
        for (int i = 0; i < rval.length; i++) {
            rval[i] = fill.get(i, Double.NaN);
        }

        return rval;
    }

    /**
     * Returns the avg. vertical deviation of fixations from the
     * whole's line center.
     *
     * @return .
     */
    @SuppressWarnings("boxing")
    public int getAvgVerticalDeviation() {
        final int avg = getAverageYPosition();

        final Staple<Integer> staple = this.$fixations.map(new F1<Fixation, Integer>() {
            @Override
            public Integer f(Fixation x) {
                return x.getCenter().y;
            }
        }).staple(0, new F2ReduceObjects<Integer>() {
            @Override
            public Integer f(Integer left, Integer right) {
                return left + Math.abs(right - avg);
            }
        });

        return staple.staple() / staple.size();
    }

    /**
     * Returns the fixation line's dimension
     *
     * @return .
     */
    public Dimension getDimension() {
        final Point min = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
        final Point max = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);

        for (final Fixation fixation : this.fixations) {
            final Point center = fixation.getCenter();

            if (center == null) continue;

            min.x = Math.min(min.x, center.x);
            min.y = Math.min(min.y, center.y);

            max.x = Math.max(max.x, center.x);
            max.y = Math.max(max.y, center.y);
        }

        return new Dimension(max.x - min.x, max.y - min.y);
    }

    /**
     * Calculates how long has been gazed into the specified area of screen.
     *
     * @param screenRectangle
     * @return .
     */
    public long getGazetimeFor(final Rectangle screenRectangle) {
        long rval = 0;

        for (final Fixation fixation : this.fixations) {
            final Point center = fixation.getCenter();

            if (center == null) continue;

            if (screenRectangle.contains(center)) {
                rval += new FixationUtil(fixation).getFixationDuration();
            }
        }

        return rval;
    }

    /**
     * Returns the last n fixations.
     * @param n
     * @return .
     */
    public List<Fixation> getLastFixations(final int n) {
        final int s = this.fixations.size();
        return new ArrayList<Fixation>(this.fixations.subList(s - n, s));
    }

    /**
     * Returns the minimal x and y values. They are NOT connected. The point is likely not
     * existent, it only holds that no values are smaller than x or y.
     *
     * @return .
     */
    public Point getMinCoordinates() {
        final Point min = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);

        for (final Fixation fixation : this.fixations) {
            final Point center = fixation.getCenter();
            if (center == null) continue;
            min.x = Math.min(min.x, center.x);
            min.y = Math.min(min.y, center.y);
        }

        return min;
    }

    /**
     * Returns the rectangle of this fixation line.
     *
     * @return .
     */
    public Rectangle getRectangle() {
        return new Rectangle(getMinCoordinates(), getDimension());
    }

    /**
     * First observation-point of this event.
     *
     * @return .
     */
    public long getStartTime() {
        final Fixation fixation = this.$fixations.compact().get(0);
        if (fixation == null || fixation.getTrackingEvents() == null) return 0;

        final EyeTrackingEvent trackingEvent = fixation.getTrackingEvents().get(0);
        if (trackingEvent == null) return 0;

        return trackingEvent.getEventTime();
    }

    /**
     * Last observation-point of this fixation line.
     *
     * @return .
     */
    public long getStopTime() {
        final Fixation fixation = this.$fixations.compact().get(-1);
        if (fixation == null || fixation.getTrackingEvents() == null) return 0;

        final EyeTrackingEvent trackingEvent = $(fixation.getTrackingEvents()).get(-1);
        if (trackingEvent == null) return 0;

        return trackingEvent.getEventTime();
    }
}
TOP

Related Classes of de.dfki.km.text20.services.evaluators.gaze.util.FixationsUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.