blob: 05a07ac2d00dbf2d64ee8da182fab4afb7a51a6b [file] [log] [blame]
/**
*
*/
package org.eclipse.stem.util.analysis;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.stem.analysis.impl.ReferenceScenarioDataMapImpl.ReferenceScenarioDataInstance;
/*******************************************************************************
* Copyright (c) 2007, 2008 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
*******************************************************************************/
/**
* This class is designed to take a pair of time series each involving multiple epidemic waves. It uses one
* series as a reference an then phase shifts the peaks within the second data series so that the epidemics
* are "synchronized". This is necessary in order to accurately fit model parameters of many locations without imposing a
* transportation model. As the epidemic "moves", peaks occur at different times. Synchronizing allows us to estimate the epidemic
* parameters without a transportation model. This class is used when the fitting is done by adding synchronized data over all locations.
* This is not necessary if we can fit each location independantly, but is necessary when the amount of data is scarce (eg for real
* epidemic incidence data).
*/
public class PhaseSynchronizer {
ReferenceScenarioDataInstance reference;
ReferenceScenarioDataInstance data;
/**
* this phase shift maximizes the correlation between the two vectors
*/
int phaseShift;
/**
* by default we will try to find max correlation for a shift of +/- 30 days
* if the vectors are shorter than this we reduce the window
*/
int defaultShiftWindow = 30;
/**
* This class is designed to take a pair of ReferenceScenarioDataInstance(s) each involving multiple epidemic waves. It uses one
* series as a reference an then phase shifts the peaks within the second incidence data series so that the epidemics
* are "synchronized". This is necessary in order to accurately fit model parameters of many locations without imposing a
* transportation model. As the epidemic "moves", peaks occur at different times. Synchronizing allows us to estimate the epidemic
* parameters without a transportation model. This class is used when the fitting is done by adding synchronized data over all locations.
* This is not necessary if we can fit each location independently, but is necessary when the amount of data is scarce (eg for real
* epidemic incidence data).
* @param refInstance
*
*/
public PhaseSynchronizer(ReferenceScenarioDataInstance refInstance) {
reference = refInstance;
this.getPeakPositions(reference, "Incidence");
}
/**
* Finds index of peaks, returns as list
* @param instance
* @param key
* @parameter key (must be I, E, or incidence - they have peaks)
* @return list of peak positions
*/
public List<Integer> getPeakPositions(ReferenceScenarioDataInstance instance, String key) {
List<Double> vector = instance.getData().get(key);
List<Integer> peaks = new ArrayList<Integer>();
for (int i = 0; i < vector.size(); i ++) {
double value = vector.get(i).doubleValue();
double next = 0.0;
double last = 0.0;
if (i<(vector.size()-1)) next = vector.get(i+1).doubleValue();
if (i>0) last = vector.get(i-1).doubleValue();
if((value > next)&&(value>last)) {
peaks.add(new Integer(i));
// DEBUG
//System.out.println("found peak at i="+i+", value="+value);
}
}
return peaks;
}
/**
* Rotates the vector (List) by Shift - wrapping values from beginning to end or vice versa as necessary
* This should work for quasi periodic time series
* @param shift
* @param vector
* @return shifted vector
*/
public List<Double> getShiftedVector(int shift, List<Double> vector){
List shifted = new ArrayList<Double>();
int max = vector.size();
for (int i = 0; i < max; i ++) {
int j = i - shift;
if (j >= max) {
j = j - max;
}
if (j < 0) {
j = max+j;
}
shifted.add(i,vector.get(j));
}
return shifted;
}
}