geogebra.kernel.AlgoFrequency.java Source code

Java tutorial

Introduction

Here is the source code for geogebra.kernel.AlgoFrequency.java

Source

/* 
GeoGebra - Dynamic Mathematics for Everyone
http://www.geogebra.org
    
This file is part of GeoGebra.
    
This program is free software; you can redistribute it and/or modify it 
under the terms of the GNU General Public License as published by 
the Free Software Foundation.
    
 */

package geogebra.kernel;

import java.util.ArrayList;
import java.util.Iterator;

import org.apache.commons.math.stat.Frequency;

public class AlgoFrequency extends AlgoElement {

    private static final long serialVersionUID = 1L;
    private GeoList dataList; //input
    private GeoList classList; //input
    private GeoBoolean isCumulative; //input
    private GeoBoolean useDensity; //input
    private GeoNumeric density; //input

    private GeoList frequency; //output   

    // for compute
    private GeoList value = new GeoList(cons);

    AlgoFrequency(Construction cons, String label, GeoBoolean isCumulative, GeoList classList, GeoList dataList) {
        this(cons, label, isCumulative, classList, dataList, null, null);
    }

    AlgoFrequency(Construction cons, GeoBoolean isCumulative, GeoList classList, GeoList dataList) {
        this(cons, isCumulative, classList, dataList, null, null);
    }

    AlgoFrequency(Construction cons, String label, GeoBoolean isCumulative, GeoList classList, GeoList dataList,
            GeoBoolean useDensity, GeoNumeric density) {
        this(cons, isCumulative, classList, dataList, useDensity, density);
        frequency.setLabel(label);
    }

    AlgoFrequency(Construction cons, GeoBoolean isCumulative, GeoList classList, GeoList dataList,
            GeoBoolean useDensity, GeoNumeric density) {
        super(cons);

        this.classList = classList;
        this.dataList = dataList;
        this.isCumulative = isCumulative;
        this.useDensity = useDensity;
        this.density = density;

        frequency = new GeoList(cons);
        setInputOutput();
        compute();

    }

    public String getClassName() {
        return "AlgoFrequency";
    }

    protected void setInputOutput() {

        ArrayList<GeoElement> tempList = new ArrayList<GeoElement>();

        if (isCumulative != null)
            tempList.add(isCumulative);

        if (classList != null)
            tempList.add(classList);

        tempList.add(dataList);

        if (useDensity != null)
            tempList.add(useDensity);

        if (density != null)
            tempList.add(density);

        input = new GeoElement[tempList.size()];
        input = tempList.toArray(input);

        setOutputLength(1);
        setOutput(0, frequency);
        setDependencies(); // done by AlgoElement
    }

    GeoList getResult() {
        return frequency;
    }

    public GeoList getValue() {
        return value;
    }

    protected final void compute() {

        // Validate input arguments
        //=======================================================

        if (!dataList.isDefined() || dataList.size() == 0) {
            frequency.setUndefined();
            return;
        }

        if (!(dataList.getElementType() == GeoElement.GEO_CLASS_TEXT
                || dataList.getElementType() == GeoElement.GEO_CLASS_NUMERIC)) {
            frequency.setUndefined();
            return;
        }

        if (classList != null) {
            if (classList.getElementType() != GeoElement.GEO_CLASS_NUMERIC || classList.size() < 2) {
                frequency.setUndefined();
                return;
            }
        }

        if (density != null) {
            if (density.getDouble() <= 0) {
                frequency.setUndefined();
                return;
            }
        }

        frequency.setDefined(true);
        frequency.clear();
        if (value != null)
            value.clear();

        double numMax = 0, numMin = 0;
        boolean doCumulative = isCumulative != null && isCumulative.getBoolean();

        // Load the data into f, an instance of Frequency class 
        //=======================================================

        Frequency f = new Frequency();
        for (int i = 0; i < dataList.size(); i++) {
            if (dataList.getElementType() == GeoElement.GEO_CLASS_TEXT)
                f.addValue(((GeoText) dataList.get(i)).toValueString());
            if (dataList.getElementType() == GeoElement.GEO_CLASS_NUMERIC)
                f.addValue(((GeoNumeric) dataList.get(i)).getDouble());
        }

        // If classList does not exist, 
        // get the unique value list and compute frequencies for this list  
        //=======================================================

        // handle string data
        if (dataList.getElementType() == GeoElement.GEO_CLASS_TEXT) {

            Iterator itr = f.valuesIterator();
            String strMax = (String) itr.next();
            String strMin = strMax;
            itr = f.valuesIterator();

            while (itr.hasNext()) {
                String s = (String) itr.next();
                if (s.compareTo(strMax) > 0)
                    strMax = s;
                if (s.compareTo(strMin) < 0)
                    strMin = s;
                GeoText text = new GeoText(cons);
                text.setTextString(s);
                value.add(text);
                if (classList == null)
                    if (doCumulative)
                        frequency.add(new GeoNumeric(cons, f.getCumFreq((Comparable) s)));
                    else
                        frequency.add(new GeoNumeric(cons, f.getCount((Comparable) s)));
            }
        }

        // handle numeric data
        else {
            Iterator itr = f.valuesIterator();
            numMax = (Double) itr.next();
            numMin = numMax;
            itr = f.valuesIterator();

            while (itr.hasNext()) {
                Double n = (Double) itr.next();
                if (n > numMax)
                    numMax = n.doubleValue();
                if (n < numMin)
                    numMin = n.doubleValue();
                value.add(new GeoNumeric(cons, n));

                if (classList == null)
                    if (doCumulative)
                        frequency.add(new GeoNumeric(cons, f.getCumFreq((Comparable) n)));
                    else
                        frequency.add(new GeoNumeric(cons, f.getCount((Comparable) n)));
            }
        }

        // If classList exists, compute frequencies using the classList
        //=======================================================

        if (classList != null) {

            double lowerClassBound = 0;
            double upperClassBound = 0;
            double classFreq = 0;

            //set density conditions
            boolean hasDensity = false;
            if (useDensity != null)
                hasDensity = useDensity.getBoolean();

            double densityValue = 1; // default density
            if (density != null) {
                densityValue = density.getDouble();
            }

            double cumulativeClassFreq = 0;
            double swap;
            int length = classList.size();
            for (int i = 1; i < length; i++) {

                lowerClassBound = ((GeoNumeric) classList.get(i - 1)).getDouble();
                upperClassBound = ((GeoNumeric) classList.get(i)).getDouble();
                boolean increasing = true;
                if (lowerClassBound > upperClassBound) {
                    swap = upperClassBound;
                    upperClassBound = lowerClassBound;
                    lowerClassBound = swap;
                    increasing = false;
                }
                classFreq = f.getCumFreq((Comparable) upperClassBound) - f.getCumFreq((Comparable) lowerClassBound)
                        + f.getCount((Comparable) lowerClassBound);
                if ((i != length - 1 && increasing) || (i != 1 && !increasing))
                    classFreq -= f.getCount((Comparable) upperClassBound);

                //   System.out.println(" =================================");
                //   System.out.println("class freq: " + classFreq + "   " + density);
                if (hasDensity) {
                    classFreq = densityValue * classFreq / (upperClassBound - lowerClassBound);
                }
                if (doCumulative)
                    cumulativeClassFreq += classFreq;
                //   System.out.println("class freq: " + classFreq);

                // add the frequency to the output GeoList
                frequency.add(new GeoNumeric(cons, doCumulative ? cumulativeClassFreq : classFreq));

            }

            // handle the last (highest) class frequency specially
            // it must also count values equal to the highest class bound  

        }
    }

}