/*
* Piecewise DTW distance metric
*/
package weka.core.elastic_distance_measures;
/**
*
* @author Chris Rimmer
*/
public class PiecewiseDTW extends BasicDTW {
private int frameSize;
private double[] reducedDimensionSeries1;
private double[] reducedDimensionSeries2;
/**
* Creates new Piecewise DTW distance metric
*
* @param frameSize size of frame to split the data
* @throws IllegalArgumentException frameSize must be a factor of number of attributes in data
*/
public PiecewiseDTW(int frameSize) throws IllegalArgumentException{
super();
setup(frameSize);
}
/**
* Creates new Piecewise DTW distance metric
*
* @param frameSize size of frame to split the data
* @param earlyAbandon set early abandon
* @throws IllegalArgumentException frameSize must be a factor of number of attributes in data
*/
public PiecewiseDTW(int frameSize, boolean earlyAbandon) throws IllegalArgumentException{
super(earlyAbandon);
setup(frameSize);
}
/**
* Setup distance metric
*
* @param frameSize size of frame to split the data
* @throws IllegalArgumentException frameSize must be a factor of number of attributes in data
*/
private void setup(int frameSize) throws IllegalArgumentException{
if(frameSize < 1){
throw new IllegalArgumentException("Frame Size must be 1 or greater");
}
this.frameSize = frameSize;
}
/**
* reduces the data dimensionally in equal sized frames and passes to superclass to calculate distance
*
* @param first array 1
* @param second array 2
* @param cutOffValue used for early abandon
* @return distance between instances
*/
@Override
public double distance(double[] first,double[] second, double cutOffValue){
//check can divide into equal parts
if(first.length % this.frameSize != 0){
throw new IllegalArgumentException("Frame size must be a factor of the number of attributes");
}
//setup arrays
int seriesLength = first.length/this.frameSize;
this.reducedDimensionSeries1 = new double[seriesLength];
this.reducedDimensionSeries2 = new double[seriesLength];
double series1Frame = 0;
double series2Frame = 0;
//reduces the dimensionality of the data
for(int i = 0, reducedPos = 0; i < first.length; i+=this.frameSize, reducedPos++){
series1Frame = 0;
series2Frame = 0;
for(int j = i; j < i+this.frameSize; j++){
series1Frame += first[j];
series2Frame += second[j];
}
this.reducedDimensionSeries1[reducedPos] = series1Frame/this.frameSize;
this.reducedDimensionSeries2[reducedPos] = series2Frame/this.frameSize;
}
return super.distance(reducedDimensionSeries1, reducedDimensionSeries2, cutOffValue);
}
/**
* Sets the frame size
*
* @param frameSize size of frame to split the data
* @throws IllegalArgumentException frameSize must be a factor of number of attributes in data
*/
public void setFrameSize(int frameSize) throws IllegalArgumentException{
setup(frameSize);
}
/**
* Gets the current frame size
*
* @return current frame size
*/
public int getFrameSize() {
return frameSize;
}
/**
* Gets dimensionally reduced series 1
*
* @return reduced series 1
*/
public double[] getReducedDimensionSeries1() {
return reducedDimensionSeries1;
}
/**
* Gets dimensionally reduced series 2
*
* @return reduced series 2
*/
public double[] getReducedDimensionSeries2() {
return reducedDimensionSeries2;
}
/**
* Prints the reduced dimensionality series arrays
*/
public void printReducedSeries(){
System.out.println("------------------ Reduced Series 1 ------------------");
for(int i = 0; i<this.reducedDimensionSeries1.length; i++){
System.out.print(" "+ reducedDimensionSeries1[i]+"\n");
}
System.out.println("------------------ End ------------------");
System.out.println("------------------ Reduced Series 2 ------------------");
for(int i = 0; i<this.reducedDimensionSeries2.length; i++){
System.out.print(" "+ reducedDimensionSeries2[i]+"\n");
}
System.out.println("------------------ End ------------------");
}
@Override
public String toString() {
return "PiecewiseDTW{ " + "frameSize=" + this.frameSize + ", earlyAbandon=" + this.isEarlyAbandon + " }";
}
}