package etomica.data;

import etomica.Constants;

/**
 * Accumulator for calculating ratio between two sums
 */
public class AccumulatorRatioAverage extends AccumulatorAverage {
    
    public double[] getData() {
        int currentBlockCount = blockSize - blockCountDown;
        if(count+currentBlockCount == 0) {
            setNaN(data);
        } else {
            super.getData();
            int numBaseStats = super.numStats();
            data[(numBaseStats+0)*nDataMinus1+0] = 1; // average
            data[(numBaseStats+1)*nDataMinus1+0] = 0; // error
            data[(numBaseStats+2)*nDataMinus1+0] = 0; // std dev
            double errorRatio0 = average[0]/error[0];
            errorRatio0 *= errorRatio0;
            double stdevRatio0 = average[0]/standardDeviation[0];
            stdevRatio0 *= stdevRatio0;
            for(int i=0; i<nData; i++) {
                double errorRatio = Double.NaN;
                double stdevRatio = Double.NaN;
                if (average[0] != 0.0) {
                    errorRatio = error[i]/average[i];
                    errorRatio = Math.sqrt(errorRatio*errorRatio + errorRatio0) * average[i]/average[0];
                    stdevRatio = standardDeviation[i]/average[i];
                    stdevRatio = Math.sqrt(stdevRatio*stdevRatio + stdevRatio0) * average[i]/average[0];
                }
                data[(numBaseStats+0)*nDataMinus1+i] = sum[i]/sum[0];
                if (average[i] == 0.0) {
                    data[(numBaseStats+1)*nDataMinus1+i] = Double.NaN;
                }
                else {
                    data[(numBaseStats+1)*nDataMinus1+i] = 0;
                }
                data[(numBaseStats+1)*nDataMinus1+i] = average[i] = errorRatio;
                data[(numBaseStats+2)*nDataMinus1+i] = error[i] = stdevRatio;
            }
        }
        return data;
    }
    
    public int numStats() {
        return 3+super.numStats();
    }
     
    public static class Type extends AccumulatorAverage.Type {
        protected Type(String label, int index) {super(label,index);}       
        public Constants.TypedConstant[] choices() {return VIRIAL_CHOICES;}
    }
    //XXX such an ugly hack!!!!
    protected static final AccumulatorAverage.Type[] VIRIAL_CHOICES = 
        new AccumulatorAverage.Type[] {
            CHOICES[0], CHOICES[1], CHOICES[2], CHOICES[3], CHOICES[4],
            new Type("Ratio",5),
            new Type("Ratio error",6), new Type("Ratio standard deviation",7)};
    public static final AccumulatorAverage.Type RATIO = VIRIAL_CHOICES[5];
    public static final AccumulatorAverage.Type RATIO_ERROR = VIRIAL_CHOICES[6];
    public static final AccumulatorAverage.Type RATIO_STANDARD_DEVIATION = VIRIAL_CHOICES[7];

    protected void setNData(int nData) {
        ratioStandardDeviation = redimension(nData, ratioError);
        ratioError = redimension(nData, ratioError);
        super.setNData(nData);
    }
     
    //need separate fields because ratio values are calculated from the non-ratio values.
    protected double[] ratioStandardDeviation, ratioError;
}

@@ -662,24 +662,24 @@
 0 = 
-average%5B0%5D/error
+error%5B0%5D/average
 %5B0%5D;
@@ -756,19 +756,8 @@
 0 = 
-average%5B0%5D/
 stan
@@ -772,16 +772,27 @@
 ation%5B0%5D
+/average%5B0%5D
 ;%0A      
@@ -847,17 +847,17 @@
 r(int i=
-0
+1
 ; i%3CnDat
@@ -1390,30 +1390,24 @@
 ats+0)*nData
-Minus1
 +i%5D = sum%5Bi%5D
@@ -1435,287 +1435,63 @@
     
-if (average%5Bi%5D == 0.0) %7B%0A                    data%5B(numBaseStats+1)*nDataMinus1+i%5D = Double.NaN;%0A                %7D%0A                else %7B%0A                    data%5B(numBaseStats+1)*nDataMinus1+i%5D = 0;%0A                %7D%0A                data%5B(numBaseStats+1)*nDataMinus1+i%5D = average
+data%5B(numBaseStats+1)*nData+i%5D = ratioStandardDeviation
 %5Bi%5D 
@@ -1551,21 +1551,20 @@
 Data
-Minus1+i%5D = e
++i%5D = ratioE
 rror

fix error, standard deviation