/*
 * PAA.java   Jul 14, 2004
 *
 * Copyright (c) 2004 Stan Salvador
 * stansalvador@hotmail.com
 */

package com.fastdtw.timeseries;

import java.util.List;

public class PAA implements TimeSeries {
    // PRIVATE DATA
    private int[] aggPtSize; // ArrayList of Integer
    private final int originalLength;
    private final TimeSeries base;

    public PAA(TimeSeries ts, int shrunkSize) {
        base = new TimeSeriesBase(validate(ts, shrunkSize));

        // Initialize private data.
        this.originalLength = ts.size();
        this.aggPtSize = new int[shrunkSize];

        // Initialize the new aggregate time series.
        this.setLabels(ts.getLabels());

        // Determine the size of each sampled point. (may be a fraction)
        final double reducedPtSize = (double) ts.size() / (double) shrunkSize;

        // Variables that keep track of the range of points being averaged into
        // a single point.
        int ptToReadFrom = 0;
        int ptToReadTo;

        // Keep averaging ranges of points into aggregate points until all of
        // the data is averaged.
        while (ptToReadFrom < ts.size()) {
            ptToReadTo = (int) Math.round(reducedPtSize * (this.size() + 1)) - 1; // determine
                                                                                  // end
                                                                                  // of
                                                                                  // current
                                                                                  // range
            final int ptsToRead = ptToReadTo - ptToReadFrom + 1;

            // Keep track of the sum of all the values being averaged to create
            // a single point.
            double timeSum = 0.0;
            final double[] measurementSums = new double[ts.numOfDimensions()];

            // Sum all of the values over the range ptToReadFrom...ptToReadFrom.
            for (int pt = ptToReadFrom; pt <= ptToReadTo; pt++) {
                final double[] currentPoint = ts.getMeasurementVector(pt);

                timeSum += ts.getTimeAtNthPoint(pt);

                for (int dim = 0; dim < ts.numOfDimensions(); dim++)
                    measurementSums[dim] += currentPoint[dim];
            } // end for loop

            // Determine the average value over the range
            // ptToReadFrom...ptToReadFrom.
            timeSum = timeSum / ptsToRead;
            for (int dim = 0; dim < ts.numOfDimensions(); dim++)
                measurementSums[dim] = measurementSums[dim] / ptsToRead; // find
                                                                         // the
                                                                         // average
                                                                         // of
                                                                         // each
                                                                         // measurement

            // Add the computed average value to the aggregate approximation.
            this.aggPtSize[base.size()] = ptsToRead;
            base.addLast(timeSum, new TimeSeriesPoint(measurementSums));

           ptToReadFrom = ptToReadTo + 1; // next window of points to average
                                           // startw where the last window ended
        } // end while loop
    } // end Constructor

    private static int validate(TimeSeries ts, int shrunkSize) {
        if (shrunkSize > ts.size())
            throw new RuntimeException(
                    "ERROR:  The size of an aggregate representation may not be largerr than the \n"
                            + "original time series (shrunkSize=" + shrunkSize + " , origSize="
                            + ts.size() + ").");

        if (shrunkSize <= 0)
            throw new RuntimeException(
                    "ERROR:  The size of an aggregate representation must be greater than zero and \n"
                            + "no larger than the original time series.");
        return shrunkSize;
    }

    public int originalSize() {
        return originalLength;
    }

    public int aggregatePtSize(int ptIndex) {
        return aggPtSize[ptIndex];
    }

    public String toString() {
        return "(" + this.originalLength + " point time series represented as " + this.size()
                + " points)\n" + super.toString();
    } // end toString()

    @Override
    public int size() {
        return base.size();
    }

    @Override
    public int numOfDimensions() {
        return base.numOfDimensions();
    }

    @Override
    public double getTimeAtNthPoint(int n) {
        return base.getTimeAtNthPoint(n);
    }

    @Override
    public List<String> getLabels() {
        return base.getLabels();
    }

    @Override
    public void setLabels(List<String> newLabels) {
        base.setLabels(newLabels);
    }

    @Override
    public double getMeasurement(int pointIndex, int valueIndex) {
        return getMeasurement(pointIndex, valueIndex);
    }

    @Override
    public double getMeasurement(int pointIndex, String valueLabel) {
        return base.getMeasurement(pointIndex, valueLabel);
    }

    @Override
    public double[] getMeasurementVector(int pointIndex) {
        return base.getMeasurementVector(pointIndex);
    }

    @Override
    public void addLast(double time, TimeSeriesPoint values) {
        base.addLast(time, values);
    }

} // end class PAA

@@ -137,16 +137,45 @@
 ies;%0D%0A%0D%0A
+import java.util.ArrayList;%0D%0A
 import j
@@ -190,16 +190,16 @@
 .List;%0D%0A
-
 %0D%0Apublic
@@ -447,62 +447,249 @@
     
-base = new TimeSeriesBase(validate(ts, shrunkSize));%0D%0A
+validate(ts, shrunkSize);%0D%0A        List%3CString%3E labels = new ArrayList%3CString%3E(ts.getLabels());%0D%0A        List%3CDouble%3E timeReadings = new ArrayList%3CDouble%3E();%0D%0A        List%3CTimeSeriesPoint%3E points = new ArrayList%3CTimeSeriesPoint%3E();%0D%0A        
 %0D%0A  
@@ -818,105 +818,8 @@
 %0D%0A%0D%0A
-        // Initialize the new aggregate time series.%0D%0A        this.setLabels(ts.getLabels());%0D%0A%0D%0A
     
@@ -1354,18 +1354,26 @@
 ize * (t
-h
 i
+meReading
 s.size()
@@ -3332,20 +3332,28 @@
 gPtSize%5B
-base
+timeReadings
 .size()%5D
@@ -3383,30 +3383,59 @@
     
-base.addLast(timeSum, 
+timeReadings.add(timeSum);%0D%0A            points.add(
 new 
@@ -3466,26 +3466,24 @@
 entSums));%0D%0A
-%0D%0A
            p
@@ -3668,28 +3668,76 @@
     
-%7D // end Constructor
+    base = new TimeSeriesBase(labels, timeReadings, points);%0D%0A    %7D 
 %0D%0A%0D%0A

use composition in PPA