/*******************************************************************************
 * Copyright (c) 2009 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.stem.analysis.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.impl.EObjectImpl;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.stem.analysis.Activator;
import org.eclipse.stem.analysis.AnalysisPackage;
import org.eclipse.stem.analysis.DiseaseType;
import org.eclipse.stem.analysis.ReferenceScenarioDataMap;
import org.eclipse.stem.analysis.States;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Reference Scenario Data Map</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * </p>
 *
 * @generated
 */
public class ReferenceScenarioDataMapImpl extends EObjectImpl implements ReferenceScenarioDataMap {
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	protected ReferenceScenarioDataMapImpl() {
		super();
		referenceScenarioDataMap = new HashMap<String, ReferenceScenarioDataInstance>();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return AnalysisPackage.Literals.REFERENCE_SCENARIO_DATA_MAP;
	}

	public static final String ITERATION_KEY = "iteration";//$NON-NLS-1$
	/**
	 * key for incidence data
	 */
	public static final String INCIDENCE_KEY = "Incidence";//$NON-NLS-1$
	public static final String TIME_KEY = "time";//$NON-NLS-1$
	private double maxIncidence = 0.0;
	private String maxIncidenceLocation;
	private static final double PPM = 1.0/1000000.0;
	
	/**
	 * We have generalize the possible keys 
	 * so there can be more than one of each type but they
	 * are still, for now, of type SEIR. I might be Iactive or Ilatent though
	 */
	public Set<String> S_KEY_SET = new HashSet<String>();
	public Set<String> E_KEY_SET = new HashSet<String>();
	public Set<String> I_KEY_SET = new HashSet<String>();
	public Set<String> R_KEY_SET = new HashSet<String>();
	public Set<String> INCIDENCE_KEY_SET = new HashSet<String>();
	
	
	/**
	 * A single Reference Scenario is stored in a map
	 * for each  key<String> = Region id
	 */
	Map<String, ReferenceScenarioDataInstance> referenceScenarioDataMap = null;
	
	/**
	 * Directory used
	 */
	
	private String refDir;
	
	/**
	 * Type of data (e.g. SIR)
	 */
	
	DiseaseType type;
	
	/**
	 * addInstance Add a new data instance (e.g. data from .csv file) to the map
	 * 
	 * @param key The key, e.g. city id
	 * @param data ReferenceScenarioDataInstance 
	 */
	public void addInstance(String key, ReferenceScenarioDataInstance data) {
		referenceScenarioDataMap.put(key, data);
	}
	
	/**
	 * 
	 */
	public void findMaxIncidence() {
		Iterator<String> iter = referenceScenarioDataMap.keySet().iterator();
		while((iter!=null)&&(iter.hasNext()) ) {
			String key = iter.next();
			ReferenceScenarioDataInstance data = referenceScenarioDataMap.get(key);
			double count = getTotalIncidence(data);
			if(count >= maxIncidence) {
				maxIncidence = count;
				maxIncidenceLocation = key;
			}
		}
	}
	
	/**
	 * Return the type of the data. Used to determine which parameter estimator(s)
	 * can be used.
	 * 
	 * @return ParameterEstimator.Type The type, e.g. SEIR 
	 */
	
	public DiseaseType getType() {
		if(referenceScenarioDataMap == null || referenceScenarioDataMap.size() == 0) {
			return null;
		}
		return this.type;
	}
	
	/**
	 * Set the type of the data
	 * 
	 * @param t New type 
	 */
	
	public void setType(DiseaseType t, Set<String> Skeys, Set<String> Ekeys, Set<String>Ikeys, Set<String> Rkeys, Set<String> IncKeys) {
		this.type = t;
		this.S_KEY_SET=Skeys;
		this.E_KEY_SET=Ekeys;
		this.I_KEY_SET=Ikeys;
		this.R_KEY_SET=Rkeys;
		this.INCIDENCE_KEY_SET=IncKeys;
	}
	
	/**
	 * 
	 * @return
	 */
	public String[] getS_Keys() {
		String[] keys = new String[0];
		if(S_KEY_SET!=null) {
			keys = S_KEY_SET.toArray(new String[S_KEY_SET.size()]);
		}
		return keys;
	}
	
	/**
	 * 
	 * @return
	 */
	public String[] getE_Keys() {
		String[] keys = new String[0];
		if(E_KEY_SET!=null) {
			keys = E_KEY_SET.toArray(new String[E_KEY_SET.size()]);
		}
		return keys;
	}
	
	/**
	 * 
	 * @return
	 */
	public String[] getI_Keys() {
		String[] keys = new String[0];
		if(I_KEY_SET!=null) {
			keys = I_KEY_SET.toArray(new String[I_KEY_SET.size()]);
		}
		return keys;
	}
	
	/**
	 * 
	 * @return
	 */
	public String[] getR_Keys() {
		String[] keys = new String[0];
		if(R_KEY_SET!=null) {
			keys = R_KEY_SET.toArray(new String[R_KEY_SET.size()]);
		}
		return keys;
	}

	public String[] getInc_KEY_SET() {
		String[] keys = new String[0];
		if(INCIDENCE_KEY_SET!=null) {
			keys = INCIDENCE_KEY_SET.toArray(new String[INCIDENCE_KEY_SET.size()]);
		}
		return keys;
	}

	
	/**
	 * getNumLocations. Return the number of locations analyzed
	 * 
	 * @return int Number of locations
	 */
	
	public int getNumLocations() {
		return referenceScenarioDataMap.size();
	}
	
	/**
	 * getLocations. Return the locations
	 * 
	 * @return Set<String> Set of all locations
	 */
	
	public Set<String> getLocations() {
		return referenceScenarioDataMap.keySet();
	}
	
	
	/**
	 * The the total incidence (summing over all time for some location instance 
	 * @param instance
	 * @return the total Incidence count
	 */
	public double getTotalIncidence(ReferenceScenarioDataInstance instance) {
		double retValue = 0.0;
		if(instance.getData().containsKey(INCIDENCE_KEY)) {
			List<Double> incidence = instance.getData().get(INCIDENCE_KEY);
			for (int i = 0; i < incidence.size(); i ++) {
				retValue += incidence.get(i).doubleValue();
			}
		}
		return retValue;
	}
	
	/**
	 * containsLocation Return true if the map contains the specified location
	 * 
	 * @param loc
	 * @return boolean True if the location is found in the map
	 */
	public boolean containsLocation(String loc) {
		return referenceScenarioDataMap.containsKey(loc);
	}
	
	/**
	 * getLocation. Return the data for the given location
	 * @param loc 
	 * @return ReferenceScenarioDataInstance Location instance, or null if not found
	 */
	
	public ReferenceScenarioDataInstance getLocation(String loc) {
		return referenceScenarioDataMap.get(loc);
	}
	
	/**
	 * Aggregate or integrate all data for all locations in a scenario.
	 * 
	 * @param runnableContext Runnable context for progress indicator
	 * @return ReferenceScenarioDataInstance aggregated data instance, or null if not found
	 */
	
	public ReferenceScenarioDataInstance aggregateScenarioData(IRunnableContext runnableContext) {
		final ReferenceScenarioDataInstance aggregatedData = new ReferenceScenarioDataInstance(this);
		
		IRunnableWithProgress aggregateTask = new IRunnableWithProgress() {
            public void run(IProgressMonitor progress) {
            	progress.beginTask("Aggregating data...", referenceScenarioDataMap.size());   	//$NON-NLS-1$
            	Iterator<String> iter = referenceScenarioDataMap.keySet().iterator();
            	while((iter!=null)&&(iter.hasNext())) {
            		progress.worked(1);
            		if(progress.isCanceled()) throw new OperationCanceledException();
            		String loc = iter.next();
			
            		ReferenceScenarioDataInstance locationData = referenceScenarioDataMap.get(loc);
            		aggregatedData.integrateData(locationData.instance);
            	}// all locations
            	progress.done();
            }
		};
		
		try {
			runnableContext.run(true, true, aggregateTask);
		} catch(InterruptedException ie) {
			// ToDo
			return null;
		} catch(InvocationTargetException ite) {
			// ToDo
			return null;
		}
		return aggregatedData;
	}
	
	/**
	 * getReferenceDirectory. Return the reference directory used
	 * 
	 * @return String Reference directory
	 */
	
	public String getReferenceDirectory() {
		return this.refDir;
	}
	
	/**
	 * setReferenceDirectoy. Set the reference directory
	 * 
	 * @param dir The directory
	 */
	
	public void setReferenceDirectory(String d) {
		this.refDir = d;
	}
	
	/**
	 * 
	 * @return the max incidence at the most effected location 
	 */
	public double getMaxIncidence() {
		return maxIncidence;
	}

	/**
	 * 
	 * @return the location with the max incidence
	 */
	public String getMaxIncidenceLocation() {
		return maxIncidenceLocation;
	}
	
	
	/**
	 * ReferenceScenarioDataInstance. Contains data for one location  
	
	 */
	public class ReferenceScenarioDataInstance implements Cloneable {
		
		private double maxS = 0.0;
		private double maxE = 0.0;
		private double maxI = 0.0;
		private double maxR = 0.0;
			
		

		/**
		 * The region data map is keyed by property (S,E, I, R, incidence, etc) and contains Data (mostly Doubles but
		 * STEMTime is stored as a String) so all data is stored as String.
		 */
		
		public Map<String,List<String>> instance;
		
		

		protected ReferenceScenarioDataMapImpl dataMap;
		
		public ReferenceScenarioDataMapImpl getDataMap() {
			return dataMap;
		}

		/**
		 * Create a new instance
		 *  
		 * @param data Map of parameter (e.g. a state) and its values
		 * @param map DataMap the instance belongs to
		 */
		public ReferenceScenarioDataInstance(Map<String, List<String>> data, ReferenceScenarioDataMapImpl map) {
			this.instance = data;
			this.dataMap = map;
		}
		
		/**
		 * Create an empty instance of some type
		 *  
		 * @param dataMap map
		 */
		public ReferenceScenarioDataInstance(ReferenceScenarioDataMapImpl dataMap) {
			this.instance = new HashMap<String, List<String>>();
			this.dataMap = dataMap;
		}
		
		/**
		 * deep clone
		 * @see java.lang.Object#clone()
		 */
		@Override
		public  ReferenceScenarioDataInstance clone() {
			this.getData();
			ReferenceScenarioDataInstance newInstance = new ReferenceScenarioDataInstance(this.dataMap);
			Iterator<String> iter = this.instance.keySet().iterator();
			while(iter.hasNext()) {
				String key = iter.next();
				List<String> dataList = instance.get(key);
				List<String> newList = new ArrayList<String>();
			
				for (int i = 0; i < dataList.size(); i ++) {
					String val = dataList.get(i);
					newList.add(val);
				}
				newInstance.instance.put(key,newList);
			}
			newInstance.getData();
			return newInstance;
		}
		
		/**
		 * integrates data from another instance
		 * @param data
		 */
		public void integrateData(Map<String, List<String>> data) {
			// get the state variables SEIR... as keys
			for (Entry<String,List<String>> entry : data.entrySet()) {
				// get the key
				String state = entry.getKey();
				List<String> valueList = entry.getValue();
				if(valueList.size()>=1) {
					// get the current list
					List<String> aggregatedList = new ArrayList<String>();
					if(this.instance.containsKey(state)) {
						aggregatedList = this.instance.get(state);
					} else {
						// create it if it doesn't exist
						for(int i = 0; i < valueList.size(); i ++) {
							aggregatedList.add("0.0");//$NON-NLS-1$
						}
						this.instance.put(state,aggregatedList);
					}
					
					
					
					String first = valueList.get(0);
					// check if this is numeric data - it might just be a date
					boolean isData = true;
					try {
						@SuppressWarnings("unused")
						double val = (new Double(first)).doubleValue();
					} catch (NumberFormatException nfe) {
						isData = false;
					}
					for (int i = 0; i < valueList.size(); i ++) {
						String value = valueList.get(i);
						if(isData) {
							double val = (new Double(value)).doubleValue();
							double oldVal = (new Double(aggregatedList.get(i))).doubleValue();
							if(state.indexOf(ITERATION_KEY)==-1) {
								// add them up except for the iteration counter column
								oldVal += val;
							} else {
								oldVal = val;
							}
							aggregatedList.set(i,""+oldVal);//$NON-NLS-1$
							this.instance.put(state,aggregatedList);
						} else {
							// just copy the strings
							aggregatedList.set(i,value);
							this.instance.put(state,aggregatedList);
						}
					}
					
					
				}
				
				
			}
			
			
		}
		
		
		/**
		 * getData. Return data for the given parameter (e.g. state)
		 * 
		 * @param parm Parameter
		 * @return List<String> data
		 */
		
		public List<String> getData(String parm) {
			return instance.get(parm);
		}
		
		/**
		 * containsParameter. Return true if the data contains the given parameter (e.g. a state)
		 * 
		 * @param p Parameter to check
		 * @return boolean true if found, false otherwise
		 */
		
		public boolean containsParameter(String p) {
			return this.instance.containsKey(p);
		}
		
		/**
		 * get the all the data
		 * @return this instance map
		 */
		public Map<String, List<String>> getInstance() {
			return instance;
		}
		
		/**
		 * find the maximum values for every type of state
		 * grouping  states by type (SEIR)
		 */
		public void findMaxValues() {
			
					
					String[] S_keys = this.dataMap.getS_Keys();
					String[] E_keys = this.dataMap.getE_Keys();
					String[] I_keys = this.dataMap.getI_Keys();
					String[] R_keys = this.dataMap.getR_Keys();
					
					// S states
					if(this.dataMap.getS_Keys() != null) {
						for (int i =0; i < S_keys.length; i ++) {
							List<String> dataList = this.getData(S_keys[i]);
							if(dataList != null) {
								maxS = new Double(dataList.get(0)).doubleValue();
		            			for(int j = 0; j < dataList.size(); j ++) {
		            				double val = new Double(dataList.get(j)).doubleValue();
		            				if (val > maxS) {
		            					maxS = val;
		            				}
		            			}
							}
						}
					}
					
					// If E state
					if(this.dataMap.getE_Keys() != null) {
						for (int i =0; i < E_keys.length; i ++) {
							List<String> dataList = this.getData(E_keys[i]);
							if(dataList != null) {
								maxE = new Double(dataList.get(0)).doubleValue();
		            			for(int j = 0; j < dataList.size(); j ++) {
		            				double val = new Double(dataList.get(j)).doubleValue();
		            				if (val > maxE) {
		            					maxE = val;
		            				}
		            			}
							}
						}
					}

					
        			
        			// If have I state 
					if(this.dataMap.getI_Keys() != null) {
						for (int i =0; i < I_keys.length; i ++) {
							List<String> dataList = this.getData(I_keys[i]);
							if(dataList != null) {
								maxI = new Double(dataList.get(0)).doubleValue();
		            			for(int j = 0; j < dataList.size(); j ++) {
		            				double val = new Double(dataList.get(j)).doubleValue();
		            				if (val > maxI) {
		            					maxI = val;
		            				}
		            			}
							}
						}
					}
					

        			
        			// If have R state 
					if(this.dataMap.getR_Keys() != null) {
						for (int i =0; i < R_keys.length; i ++) {
							List<String> dataList = this.getData(R_keys[i]);
							if(dataList != null) {
								maxR = new Double(dataList.get(0)).doubleValue();
		            			for(int j = 0; j < dataList.size(); j ++) {
		            				double val = new Double(dataList.get(j)).doubleValue();
		            				if (val > maxR) {
		            					maxR = val;
		            				}
		            			}
							}
						}
					}
					
					   
        			
        			
		} // findMaxValues
		
		
		
		/**
		 * getData. Return the map that of raw data (not filtered)
		 * @return  Map<String, List<Double>> Map with state, value list
		 */
		@SuppressWarnings("boxing")
		public Map<String, List<Double>> getData() {
			
			HashMap<String, List<Double>> data = new HashMap<String, List<Double>>();
			
			for(String state : instance.keySet()) {
				ArrayList<Double> list = new ArrayList<Double>();
				if(state.equalsIgnoreCase("time"))continue;//$NON-NLS-1$
				for(String sd : instance.get(state)) 
					list.add(Double.parseDouble(sd));
				data.put(state, list);
			}
			return data;
		}
		
		/**
		 * Return the totals of type Susceptible (there could be more than one, eg
		 * by age or immune compromised state)
		 * @return  
		 */
		@SuppressWarnings("boxing")
		public List<Double> getStotals() {
			String[] keys = this.getDataMap().getS_Keys();
			List<Double> data = new ArrayList<Double>();
			if(keys.length == 0) return data;
			List<String> strList = instance.get(keys[0]);
			
			if(strList !=null) {
				for(int j = 0; j < strList.size(); j ++) {
					data.add(j, new Double(strList.get(j)).doubleValue());
				}
			}
			if(keys.length >=2) {
				// if we have more than one I compartment we sum them up
				for(int i = 1; i < keys.length; i ++) {
					strList = instance.get(keys[i]);
					for(int j = 0; j < strList.size(); j ++) {
	    				double val = new Double(strList.get(j)).doubleValue();
	    				val += data.get(j).doubleValue();
	    				data.set(j,new Double(val));
					}
				}
			}
			return data;
		}// getStotals
		
		/**
		 * Return the totals of type E (there could be more than one, eg
		 * by age or immune compromised state)
		 * @return  
		 */
		@SuppressWarnings("boxing")
		public List<Double> getEtotals() {
			String[] keys = this.getDataMap().getE_Keys();
			List<Double> data = new ArrayList<Double>();
			if(keys.length == 0) return data; // empty
			List<String> strList = instance.get(keys[0]);
			if(strList !=null) {
				for(int j = 0; j < strList.size(); j ++) {
					data.add(j, new Double(strList.get(j)).doubleValue());
				}
			}
			if(keys.length >=2) {
				// if we have more than one I compartment we sum them up
				for(int i = 1; i < keys.length; i ++) {
					strList = instance.get(keys[i]);
					for(int j = 0; j < strList.size(); j ++) {
	    				double val = new Double(strList.get(j)).doubleValue();
	    				val += data.get(j).doubleValue();
	    				data.set(j,new Double(val));
					}
				}
			}
			return data;
		}// getEtotals
		
		/**
		 * Return the totals of type I (there could be more than one, eg
		 * by age or immune compromised state)
		 * @return  
		 */
		@SuppressWarnings("boxing")
		public List<Double> getItotals() {
			String[] keys = this.getDataMap().getI_Keys();
			List<Double> data = new ArrayList<Double>();
			if(keys.length == 0) return data;
			List<String> strList = instance.get(keys[0]);
			
			if(strList !=null) {
				for(int j = 0; j < strList.size(); j ++) {
					data.add(j, new Double(strList.get(j)).doubleValue());
				}
			}
			if(keys.length >=2) {
				// if we have more than one I compartment we sum them up
				for(int i = 1; i < keys.length; i ++) {
					strList = instance.get(keys[i]);
					for(int j = 0; j < strList.size(); j ++) {
	    				double val = new Double(strList.get(j)).doubleValue();
	    				val += data.get(j).doubleValue();
	    				data.set(j,new Double(val));
					}
				}
			}
			return data;
		}// getItotals
		
		/**
		 * Return the totals of type I (there could be more than one, eg
		 * by age or immune compromised state)
		 * @return  
		 */
		@SuppressWarnings("boxing")
		public List<Double> getRtotals() {
			String[] keys = this.getDataMap().getR_Keys();
			List<Double> data = new ArrayList<Double>();
			if(keys.length == 0) return data;
			List<String> strList = instance.get(keys[0]);
			
			if(strList !=null) {
				for(int j = 0; j < strList.size(); j ++) {
					data.add(j, new Double(strList.get(j)).doubleValue());
				}
			}
			if(keys.length >=2) {
				// if we have more than one I compartment we sum them up
				for(int i = 1; i < keys.length; i ++) {
					strList = instance.get(keys[i]);
					for(int j = 0; j < strList.size(); j ++) {
	    				double val = new Double(strList.get(j)).doubleValue();
	    				val += data.get(j).doubleValue();
	    				data.set(j,new Double(val));
					}
				}
			}
			return data;
		}// getRtotals
		
		
		
		
		/**
		 * 
		 * @return maxS
		 */
		public double getMaxS() {
			return maxS;
		}

		/**
		 * 
		 * @return maxE
		 */
		public double getMaxE() {
			return maxE;
		}

		/**
		 * 
		 * @return maxI
		 */
		public double getMaxI() {
			return maxI;
		}

		/**
		 * 
		 * @return maxR
		 */
		public double getMaxR() {
			return maxR;
		}
		
		/**
		 * getSize. Return the number of data rows in the instance. Each array (value) is assumed same size
		 * 
		 * @return int The size of the 
		 */
		
		public int getSize() {
			if(this.instance.size() == 0) return 0;
			return this.instance.values().iterator().next().size();
		}
	}


	/**
	 * TODO implement this method
	 * This method insures that the output of a disease model (or the output of a population model) is sane!
	 * @return
	 */
	public boolean sane() {
		Activator.logInformation("TODO   ReferenceScenarioDataMapImpl.sane() must be fully implemented !!!"); //$NON-NLS-1$
		
		Iterator<String> locationIter = getLocations().iterator();
		while(locationIter!=null && locationIter.hasNext()) {
			String locationID = locationIter.next();
			ReferenceScenarioDataInstance instance = getLocation(locationID);
			// Get the data. Always have at least S and I
			List<String>popData = instance.getData(States.statesToFit[States.POPULATION]);
			if(popData == null) popData =  instance.getData("Population Count");//$NON-NLS-1$
			
			List<String>sData = instance.getData(States.statesToFit[States.SUSCEPTIBLE]);
			List<String>eData = null;
			List<String>iData = instance.getData(States.statesToFit[States.INFECTIOUS]);
			List<String>rData = null;
			List<String>ddData = instance.getData(States.statesToFit[States.DISEASE_DEATHS]);
			
			// If E state
			if(instance.dataMap.getType()== DiseaseType.SEIR)  {
				eData = instance.getData(States.statesToFit[States.EXPOSED]);
			}
			// If have R state (i.e., not an SI model
			if(instance.dataMap.getType()!= DiseaseType.SI)  {
				rData = instance.getData(States.statesToFit[States.RECOVERED]);
			}
			
			// check that three things are true at every time step.
			// 0. All existing lists have the same length
			// 1. No data label should ever go negative
			// 2. The sum of the disease states = the total population at that time.
			int length = popData.size();
			if((sData.size() != length)||(iData.size() != length)||(ddData.size() != length)) return false;
			if((eData != null)&&(eData.size() != length)) return false;
			if((rData != null)&&(rData.size() != length)) return false;
			
			for (int t = 0; t < length; t ++) {
				double sum = 0.0;
				double s = new Double(sData.get(t)).doubleValue();
				double i = new Double(iData.get(t)).doubleValue();
				double dd = new Double(ddData.get(t)).doubleValue();
				double r = 0.0;
				double e = 0.0;
				if(eData != null) e = new Double(eData.get(t)).doubleValue();
				if(rData != null) r = new Double(rData.get(t)).doubleValue();
				if((s < 0)||(i<0)||(e<0)||(r<0)||(dd<0)) {
					System.err.println("Negative value found at time = "+t+" s="+s+" e="+e+" i="+i+" r="+r+"dd= "+dd);
					return false; //1
				}
				sum = s+e+i+r;
				if(!closeEnough(sum,new Double(popData.get(t)).doubleValue())) {
					System.err.println("Sum not correct at time = "+t+" difference is "+(sum-new Double(popData.get(t)).doubleValue()));	
					return false; // 2
				}
				// or exact equality but we need to check across different processors
//				if(sum != new Double(popData.get(t)).doubleValue()) {
//					Activator.logInformation("Sum not exactly correct at time = "+t+" difference is "+(sum-new Double(popData.get(t)).doubleValue()));
					
//				}
			}
			
		}
		return true;
	}
	
	/**
	 * Are two values within 1ppm ?
	 * @param dbl1
	 * @param dbl2
	 * @return
	 */
	boolean closeEnough(double d1, double d2) {
		boolean retVal = true;
		if(d1 == 0.0) return (Math.abs(d2) < PPM);
		if(d2 == 0.0) return (Math.abs(d1) < PPM);
		double diff = (Math.abs(2.0*(d1-d2)/(d1+d2)));
		if(diff > PPM) retVal = false;
		return retVal;
	}
	
	/**
	 * Is this map consistent with another map?
	 * This is like "equal" but allows for small differences when comparing double(s)
	 * @param other
	 * @return
	 */
	public boolean consistentWith(ReferenceScenarioDataMapImpl other) {
		Activator.logInformation("TODO   ReferenceScenarioDataMapImpl.consistentWith(ReferenceScenarioDataMap other) must be fully implemented !!!");//$NON-NLS-1$
		
		// Make sure that both maps contain the same locations
		if(getLocations().size() !=  other.getLocations().size())
		{
			Activator.logInformation("Error mismatched number of locations in log files for "+other.getReferenceDirectory()+" vs "+getReferenceDirectory());
			return false;
		}
		for(String loc:getLocations())
			if(other.getLocation(loc) == null) {
				Activator.logInformation("Location missing in data map "+other.getReferenceDirectory());
				return false;
			}
		
		// Now check each location and each state
		for(String loc:getLocations()) {
			ReferenceScenarioDataInstance otherInst = other.getLocation(loc);
			ReferenceScenarioDataInstance thisInst = getLocation(loc);
			
			for(String state:thisInst.getInstance().keySet()) {
				List<String>thisData = thisInst.getInstance().get(state);
				List<String>otherData = otherInst.getInstance().get(state);
				if(thisData.size() != otherData.size()) {
					System.err.println("Error the list of data values does not have the same length for location "+loc+" folder "+getReferenceDirectory());
					return false;
				}
				
				for(int i=0;i<thisData.size();++i) {
					double thisD = Double.parseDouble(thisData.get(i));
					double otherD = Double.parseDouble(otherData.get(i));
					
					if(!closeEnough(thisD, otherD)) {
						System.err.println("Error mismatched result for state "+state+" location "+loc+" "+thisD+" not same as "+otherD+" timestep "+i+" folder "+getReferenceDirectory()+" vs "+other.getReferenceDirectory());
						return false;
					}
				}
					
			}
		}
			
		return true;
	}
	

} //ReferenceScenarioDataMapImpl
