Fix Bug in Compound Error function when reference data (eg Deaths) are
all zero
diff --git a/org.eclipse.stem/analysis/org.eclipse.stem.analysis/src/org/eclipse/stem/analysis/impl/CompoundErrorFunctionImpl.java b/org.eclipse.stem/analysis/org.eclipse.stem.analysis/src/org/eclipse/stem/analysis/impl/CompoundErrorFunctionImpl.java
index 9405234..b704fd7 100644
--- a/org.eclipse.stem/analysis/org.eclipse.stem.analysis/src/org/eclipse/stem/analysis/impl/CompoundErrorFunctionImpl.java
+++ b/org.eclipse.stem/analysis/org.eclipse.stem.analysis/src/org/eclipse/stem/analysis/impl/CompoundErrorFunctionImpl.java
@@ -575,16 +575,22 @@
return avgList;
}
- public double[] getSpecificErrors(Map<String,List<Double>>commonDailyIncidenceLocationsMapA,Map<String,List<Double>>commonDailyIncidenceLocationsMapB,BasicEList<Double> list) {
- double[]errors = new double[2];//contains error and verror
-
- double [] Xref = new double[time.length];
- double [] Xdata = new double[time.length];
-
- double finalerror = 0.0;
- double verror = 0.0;
- for(int i=0;i<time.length;++i)list.add(0.0);
+
+
+ /**
+ * calculate the individual error(s) contributing to the compound error function
+ * (a user defined combination of cumulative incidence, daily incidence, and deaths
+ *
+ */
+ public double[] getSpecificErrors(Map<String,List<Double>>commonDailyIncidenceLocationsMapA,Map<String,List<Double>>commonDailyIncidenceLocationsMapB,BasicEList<Double> list) {
+ double[] errors = new double[2];//contains error and verror
+ double[] Xref = new double[time.length];
+ double[] Xdata = new double[time.length];
+ double finalerror = 0.0;
+ double verror = 0.0;
+
+ for(int i=0;i<time.length;++i) list.add(0.0);
// Get the average population for each location
for(String loc:commonPopulationLocationsA.keySet()) {
@@ -592,16 +598,16 @@
double sum = 0;for(double d:ld)sum+=d;
sum /= (double)ld.size();
commonAvgPopulationLocationsA.put(loc, sum);
- }
-
+ }
+
// Get the average population for each location
for(String loc:commonPopulationLocationsB.keySet()) {
List<Double>ld = commonPopulationLocationsB.get(loc);
double sum = 0;for(double d:ld)sum+=d;
sum /= (double)ld.size();
commonAvgPopulationLocationsB.put(loc, sum);
- }
-
+ }
+
// Get the maximum value for the A series (reference)
for(String loc:commonPopulationLocationsA.keySet()) {
List<Double>ld = commonDailyIncidenceLocationsMapA.get(loc);
@@ -612,9 +618,7 @@
// Calculate the normalized root mean square error for each location, then
// divide by the number of locatins
-
double weighted_denom = 0.0;
-
if(!AGGREGATE_NRMSE) { // Use NRMSE per location first
for(String loc:commonDailyIncidenceLocationsMapA.keySet()) {
double maxRef = 0.0;
@@ -623,62 +627,56 @@
for(int icount =0; icount < time.length; icount ++) {
List<Double> dataAI = commonDailyIncidenceLocationsMapA.get(loc);
List<Double> dataBI = commonDailyIncidenceLocationsMapB.get(loc);
-
double iA = dataAI.get(icount).doubleValue();
double iB = dataBI.get(icount).doubleValue();
-
Xref[icount]=iA;
Xdata[icount]=iB;
}
-
double nominator = 0.0;
double timesteps = 0;
for(int icount =0; icount < time.length; icount ++) {
if(Xref[icount]>maxRef)maxRef = Xref[icount];
if(Xref[icount]<minRef)minRef = Xref[icount];
-
// If we use the threshold and both the reference and the model is less than
// the THRESHOLD*MAXref(loc) we don't measure the data point
-
if(USE_THRESHOLD && (Xref[icount]<=THRESHOLD*commonMaxLocationsA.get(loc) &&
Xdata[icount]<=THRESHOLD*commonMaxLocationsA.get(loc))) continue;
-
nominator = nominator + Math.pow(Xref[icount]-Xdata[icount], 2);
list.set(icount, list.get(icount)+Math.abs(Xref[icount]-Xdata[icount]));
++timesteps;
}
double error = Double.MAX_VALUE;
- if(timesteps > 0 && maxRef-minRef > 0.0) {
+ if(timesteps > 0) {
error = Math.sqrt(nominator/timesteps);
- error = error / (maxRef-minRef);
+ if(maxRef-minRef > 0.0) {
+ error = error / (maxRef-minRef);
+ }
+ else if(maxRef-minRef==0) {
+ error=Double.MIN_VALUE;// if all values in the reference data is 0
+ }
if(WEIGHTED_AVERAGE) finalerror += commonAvgPopulationLocationsA.get(loc) * error;
else finalerror += error;
if(WEIGHTED_AVERAGE) weighted_denom += commonAvgPopulationLocationsA.get(loc);
else weighted_denom += 1.0;
}
-
}
-
-
-
// Divide the error by the number of locations
finalerror /= weighted_denom;
+
} else { // Aggregate signal, then calculate NRMSE
for(int icount =0; icount < time.length; icount ++) {
for(String loc:commonDailyIncidenceLocationsMapA.keySet()) {
List<Double> dataAI = commonDailyIncidenceLocationsMapA.get(loc);
List<Double> dataBI = commonDailyIncidenceLocationsMapB.get(loc);
-
double iA = dataAI.get(icount).doubleValue();
double iB = dataBI.get(icount).doubleValue();
-
Xref[icount]+=iA;
Xdata[icount]+=iB;
}
}
- double maxRef = Double.MIN_VALUE;
- double minRef = Double.MAX_VALUE;
+ double maxRef = Double.MIN_VALUE;
+ double minRef = Double.MAX_VALUE;
double maxValidationRef = Double.MIN_VALUE;
double minValidationRef = Double.MAX_VALUE;
@@ -694,12 +692,10 @@
double nominator = 0.0, vnominator = 0.0;
double timesteps = 0.0, vtimesteps = 0.0;
for(int icount =0; icount < time.length; icount ++) {
-
// Calculate validation error then skip
if(icount >= validationYear*365.25 && icount <= (validationYear+1)*365.25) {
if(USE_THRESHOLD && (Xref[icount]<=THRESHOLD*maxValidationRef &&
Xdata[icount]<=THRESHOLD*maxValidationRef)) continue;
-
vnominator = vnominator + Math.pow(Xref[icount]-Xdata[icount], 2);
list.set(icount, new Double(0)); // Set to 0 for validation data points
++vtimesteps;
@@ -707,28 +703,35 @@
}
// If we use the threshold and both the reference and the model is less than
// the THRESHOLD*MAXref(loc) we don't measure the data point
-
if(USE_THRESHOLD && (Xref[icount]<=THRESHOLD*maxRef &&
Xdata[icount]<=THRESHOLD*maxRef)) continue;
-
nominator = nominator + Math.pow(Xref[icount]-Xdata[icount], 2);
list.set(icount, Math.abs(Xref[icount]-Xdata[icount]));
++timesteps;
}
-
double error = Double.MAX_VALUE;
- if(timesteps > 0 && maxRef-minRef > 0.0) {
- error = Math.sqrt(nominator/timesteps);
- finalerror = error / (maxRef-minRef);
+ if(timesteps > 0) {
+ if(maxRef-minRef > 0.0) {
+ error = Math.sqrt(nominator/timesteps);
+ finalerror = error / (maxRef-minRef);
+ }
+ else if(maxRef-minRef==0) {
+ error=Double.MIN_VALUE;// if all values in the reference data is 0
+ finalerror=Double.MIN_VALUE;// if all values in the reference data is 0
+ }
}
// Validation
error = Double.MAX_VALUE;
- if(vtimesteps > 0 && maxValidationRef-minValidationRef > 0.0) {
+ if(vtimesteps > 0) {
+ if(maxValidationRef-minValidationRef > 0.0) {
error = Math.sqrt(vnominator/vtimesteps);
verror = error / (maxValidationRef-minValidationRef);
+ }else if(maxValidationRef-minValidationRef==0) {
+ error=Double.MIN_VALUE;// if all values in the reference data is 0
+ verror=Double.MIN_VALUE;// if all values in the reference data is 0
+ }
}
} // else
-
errors[0]=finalerror;
errors[1]=verror;
return errors;