com.ori.outlierserver.model.DataUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.ori.outlierserver.model.DataUtil.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ori.outlierserver.model;

import com.ori.outlierserver.dto.Reading;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang.NullArgumentException;

/**
 *
 * @author Haim
 */
public class DataUtil {

    public static enum OUTLIER_TYPE {
        NONE, MINOR, MAJOR
    }

    public Classifier<Reading, OUTLIER_TYPE> getOutlierClassifierFromList(final List<Reading> list)
            throws Throwable {

        if (list == null) {
            throw new Exception("List cannot be null");
        }

        if (list.size() < 1) {
            throw new Exception("List cannot be empty");
        }

        final double[] fences = getOutlierBounderysFromLits(list);

        return new Classifier<Reading, OUTLIER_TYPE>() {
            @Override
            public OUTLIER_TYPE classify(final Reading object) throws Throwable {
                if (object == null) {
                    throw new NullArgumentException("Object cannot be null");
                }
                double median_value = object.getMedian_value();
                if (median_value < fences[0] || median_value > fences[3]) {
                    return OUTLIER_TYPE.MAJOR;
                }
                if (median_value >= fences[0] && median_value < fences[1]
                        || median_value >= fences[2] && median_value < fences[3]) {
                    return OUTLIER_TYPE.MINOR;
                }
                return OUTLIER_TYPE.NONE;
            }
        };
    }

    private double[] getOutlierBounderysFromLits(List<Reading> list) {
        if (list == null) {
            return null;
        }

        if (list.size() == 1) {
            double[] arrayForOne = new double[4];
            Arrays.fill(arrayForOne, list.get(0).getMedian_value());
            return arrayForOne;
        }

        List<Double> values = new ArrayList<>();
        list.stream().forEach((Reading r) -> {
            values.add(r.getMedian_value());
        });
        int theSize = values.size();
        if (theSize == 1) {
            return new double[] {};
        }
        Collections.sort(values);
        boolean isEven = theSize % 2 == 0;
        double medianValue = findMedianValue(values);
        List<Double> lowerHalf = new ArrayList<>();
        List<Double> upperHalf = new ArrayList<>();
        for (Double d : values) {
            if (d.compareTo(medianValue) == -1) {
                lowerHalf.add(d);
            }
        }
        for (Double d : values) {
            if (d.compareTo(medianValue) >= 0) {
                upperHalf.add(d);
            }
        }

        double medianLow = findMedianValue(lowerHalf);
        double medianHigh = findMedianValue(upperHalf);

        double minorFenceDelta = (medianHigh - medianLow) * 1.5;
        double majorFenceDelta = (medianHigh - medianLow) * 3;

        return new double[] { medianLow - majorFenceDelta, medianLow - minorFenceDelta,
                medianHigh + minorFenceDelta, medianHigh + majorFenceDelta };
    }

    /**
     * Helper method, assuming list is sorted
     *
     * @param list the list to look in
     * @return median value for this list
     */
    private double findMedianValue(List<Double> list) {
        int theSize = list.size();
        if (theSize == 1) {
            return list.get(0);
        }
        boolean isEven = theSize % 2 == 0;
        int midPoint = (theSize - (theSize % 2)) / 2;
        double medianValue = list.get(midPoint);
        if (isEven) {
            medianValue += list.get(midPoint - 1);
            medianValue /= 2;
        }
        return medianValue;
    }

}