    001/*-
    002 * Copyright 2015, 2016 Diamond Light Source Ltd.
    003 *
    004 * All rights reserved. This program and the accompanying materials
    005 * are made available under the terms of the Eclipse Public License v1.0
    006 * which accompanies this distribution, and is available at
    007 * http://www.eclipse.org/legal/epl-v10.html
    008 */
    009
    010package org.eclipse.january.dataset;
    011
    012import org.eclipse.january.DatasetException;
    013
    014/**
    015 * A running mean class
    016 */
    017public class RunningAverage {
    018
    019        private DoubleDataset average;
    020        private DoubleDataset sqAveError;
    021        private int count = 1;
    022
    023        /**
    024         * @param dataset
    025         */
    026        public RunningAverage(IDataset dataset) {
    027                average = (DoubleDataset) (dataset.getElementClass().equals(Double.class) ? DatasetUtils.convertToDataset(dataset).clone()
    028                                : DatasetUtils.cast(dataset, Dataset.FLOAT64));
    029
    030                sqAveError = null;
    031                Dataset eb = average.getErrorBuffer();
    032                if (eb != null) {
    033                        sqAveError = eb.getDType() != Dataset.FLOAT64 ? (DoubleDataset) DatasetUtils.cast(eb, Dataset.FLOAT64) :
    034                                (DoubleDataset) eb;
    035                }
    036        }
    037
    038        /**
    039         * Update average
    040         * @param dataset
    041         */
    042        public void update(IDataset dataset) {
    043                count++;
    044                IndexIterator it = average.getIterator(true);
    045                int[] pos = it.getPos();
    046                double f = 1. / count;
    047                if (sqAveError == null) {
    048                        while (it.hasNext()) {
    049                                double m = average.getAbs(it.index);
    050                                double v = f * (dataset.getDouble(pos) - m);
    051                                average.setAbs(it.index, m + v);
    052                        }
    053                } else {
    054                        double fs = f * f;
    055                        double gs = 2 * count - 1;
    056                        if (dataset instanceof Dataset) {
    057                                final Dataset d = (Dataset) dataset;
    058                                final Dataset e = d.getErrorBuffer();
    059                                while (it.hasNext()) {
    060                                        double m = average.getAbs(it.index);
    061                                        double v = f * (d.getDouble(pos) - m);
    062                                        average.setAbs(it.index, m + v);
    063
    064                                        if (e != null) {
    065                                                m = sqAveError.getDouble(pos);
    066                                                v = fs * (e.getDouble(pos) - gs * m);
    067                                                sqAveError.setItem(m + v, pos);
    068                                        }
    069                                }
    070                        } else { // only linear error available
    071                                ILazyDataset le = dataset.getErrors();
    072                                IDataset e = null;
    073                                if (le instanceof IDataset) {
    074                                        e = (IDataset) le;
    075                                } else if (le != null) {
    076                                        try {
    077                                                e = le.getSlice();
    078                                        } catch (DatasetException e1) {
    079                                        }
    080                                }
    081                                while (it.hasNext()) {
    082                                        double m = average.getAbs(it.index);
    083                                        double v = f * (dataset.getDouble(pos) - m);
    084                                        average.setAbs(it.index, m + v);
    085
    086                                        if (e != null) {
    087                                                m = sqAveError.getDouble(pos);
    088                                                v = e.getDouble(pos);
    089                                                v = fs * (v * v - gs * m);
    090                                                sqAveError.setItem(m + v, pos);
    091                                        }
    092                                }
    093                        }
    094                }
    095        }
    096
    097        /**
    098         * @return count
    099         */
    100        public int getCount() {
    101                return count;
    102        }
    103
    104        /**
    105         * @return current average
    106         */
    107        public Dataset getCurrentAverage() {
    108                if (sqAveError != null) {
    109                        Dataset e = sqAveError.clone();
    110                        DatasetUtils.makeFinite(e);
    111                        average.setErrorBuffer(e);
    112                }
    113
    114                return average;
    115        }
    116}