org.orbisgis.sos.LeqStats.java Source code

Java tutorial

Introduction

Here is the source code for org.orbisgis.sos.LeqStats.java

Source

/*
 * This file is part of the NoiseCapture application and OnoMap system.
 *
 * The 'OnoMaP' system is led by Lab-STICC and Ifsttar and generates noise maps via
 * citizen-contributed noise data.
 *
 * This application is co-funded by the ENERGIC-OD Project (European Network for
 * Redistributing Geospatial Information to user Communities - Open Data). ENERGIC-OD
 * (http://www.energic-od.eu/) is partially funded under the ICT Policy Support Programme (ICT
 * PSP) as part of the Competitiveness and Innovation Framework Programme by the European
 * Community. The application work is also supported by the French geographic portal GEOPAL of the
 * Pays de la Loire region (http://www.geopal.org).
 *
 * Copyright (C) IFSTTAR - LAE and Lab-STICC  CNRS UMR 6285 Equipe DECIDE Vannes
 *
 * NoiseCapture is a 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; either version 3 of
 * the License, or(at your option) any later version. NoiseCapture 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 General Public License for
 * more details.You should have received a copy of the GNU General Public License along with this
 * program; if not, write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301  USA or see For more information,  write to Ifsttar,
 * 14-20 Boulevard Newton Cite Descartes, Champs sur Marne F-77447 Marne la Vallee Cedex 2 FRANCE
 *  or write to scientific.computing@ifsttar.fr
 */

package org.orbisgis.sos;

import org.apache.commons.math3.stat.descriptive.rank.Percentile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Compute descriptive statistics on leq
 */
public class LeqStats {
    private double rmsSum = 0;
    private int rmsSumCount = 0;
    private double leqMin = Double.MAX_VALUE;
    private double leqMax = Double.MIN_VALUE;
    // Sorted map of leq classes
    private Map<Integer, AtomicInteger> leqClass = new TreeMap<>();
    private static final double classStep = 0.1;

    public LeqStats() {
    }

    public LeqStats(LeqStats copyFrom) {
        leqMin = copyFrom.leqMin;
        leqMax = copyFrom.leqMax;
        rmsSum = copyFrom.rmsSum;
        rmsSumCount = copyFrom.rmsSumCount;
        leqClass = new TreeMap<>(copyFrom.leqClass);
    }

    public void addLeq(double leq) {
        leqMin = Math.min(leqMin, leq);
        leqMax = Math.max(leqMax, leq);
        rmsSum += Math.pow(10., leq / 10.);
        int key = (int) (leq / classStep);
        AtomicInteger leqCounter = leqClass.get(key);
        if (leqCounter == null) {
            leqCounter = new AtomicInteger(0);
            leqClass.put(key, leqCounter);
        }
        leqCounter.addAndGet(1);
        rmsSumCount++;
    }

    /**
     * Compute Leq stats using specified range.double[][] classRanges = ;
     * @param laOccurrencesRanges Min-Max range ex: new double[][]{{Double.MIN_VALUE, 45}, {45, 55}, {55, 65}, {65, 75},{75, Double.MAX_VALUE}}
     * @return LeqOccurrences instance
     */
    public LeqOccurrences computeLeqOccurrences(double[][] laOccurrencesRanges) {
        // Compute invert sum of class occurrences
        List<Double> classList = new ArrayList<>(leqClass.size());
        List<Integer> classValue = new ArrayList<>(leqClass.size());
        long sum = 0;
        double[] values = new double[rmsSumCount];
        int valCounter = 0;
        for (Map.Entry<Integer, AtomicInteger> entry : leqClass.entrySet()) {
            double leq = entry.getKey() * classStep;
            classList.add(leq);
            classValue.add(0, entry.getValue().get());
            sum += entry.getValue().get();
            for (int classValCount = 0; classValCount < entry.getValue().get(); classValCount++) {
                values[valCounter++] = leq;
            }
        }
        List<Double> sumClassValuePerc = new ArrayList<>(classValue.size());
        double invSum = 0.;
        for (int classVal : classValue) {
            invSum += classVal / (double) sum;
            sumClassValuePerc.add(0, invSum);
        }
        Percentile percentile = new Percentile();
        percentile.setData(values);
        // Fetch level at each lae
        double la10 = percentile.evaluate(100 - 10);
        double la50 = percentile.evaluate(50);
        double la90 = percentile.evaluate(100 - 90);

        // Sum percentage between provided laOccurrancesRanges
        List<Double> laOccurrencesRangesValue = new ArrayList<>();
        if (laOccurrencesRanges != null) {
            for (double[] range : laOccurrencesRanges) {
                double min = range[0];
                double max = range[1];
                double sumClass = 0;
                for (int idClass = 0; idClass < sumClassValuePerc.size(); idClass++) {
                    if (classList.get(idClass) >= min) {
                        if (classList.get(idClass) < max) {
                            sumClass += classValue.get(sumClassValuePerc.size() - 1 - idClass) / (double) sum;
                        } else {
                            break;
                        }
                    }
                }
                laOccurrencesRangesValue.add(sumClass);
            }
        }

        return new LeqOccurrences(la10, la50, la90, laOccurrencesRangesValue);
    }

    public double getLeqMin() {
        return leqMin;
    }

    public double getLeqMax() {
        return leqMax;
    }

    public double getLeqMean() {
        if (rmsSumCount > 0) {
            return 10 * Math.log10(rmsSum / rmsSumCount);
        } else {
            return 0;
        }
    }

    public static class LeqOccurrences {
        private final double la10;
        private final double la50;
        private final double la90;
        private final List<Double> userDefinedOccurrences;

        public LeqOccurrences(double la10, double la50, double la90, List<Double> userDefinedOccurrences) {
            this.la10 = la10;
            this.la50 = la50;
            this.la90 = la90;
            this.userDefinedOccurrences = userDefinedOccurrences;
        }

        public double getLa10() {
            return la10;
        }

        public double getLa50() {
            return la50;
        }

        public double getLa90() {
            return la90;
        }

        public List<Double> getUserDefinedOccurrences() {
            return userDefinedOccurrences;
        }
    }
}