package jsci.maths.wavelet;
import jsci.maths.*;
/*************************************
* A Wavelet (and more) matching pursuit class
* Uses adaptative Morse coding for better
* performance. The MatchingPursuit is used
* to obtain a Time-Frequency representation (TF)
* through a fast algorithm.
* @author Daniel Lemire
*************************************/
public class MatchingPursuit extends BasisFunctionLibrary implements Cloneable {
private int[] Record;
private double[] Coefs;
private double[][][] TF=new double[0][][];
public void add(MultiscaleFunction fprimary, MultiscaleFunction fdual) {
super.add(fprimary, fdual);
double[][][] TFback=TF;
TF=new double[getSize()][][];
System.arraycopy(TFback,0,TF,0,TFback.length);
TF[getSize()-1]=getTF(super.Fprimary[getSize()-1]);
}
public Object clone() {
MatchingPursuit c=(MatchingPursuit) super.clone();
if(this.Record!=null) {
c.Record=ArrayMath.copy(this.Record);
}
if(this.Coefs!=null) {
c.Coefs=ArrayMath.copy(this.Coefs);
}
if(this.TF!=null) {
TF=new double[this.TF.length][][];
System.arraycopy(TF,0,c.TF,0,TF.length);
}
return(c);
}
/*****************************
* Allows one to trace back the
* matches
******************************/
private void addToRecord (int K, double d) {
if(Record==null) {
Record=new int[1];
Record[0]=K;
Coefs=new double[1];
Coefs[0]=d;
} else {
int[] back=Record;
double[] backednorm=Coefs;
Record=new int[Record.length+1];
Coefs=new double[Record.length+1];
System.arraycopy(back,0,Record,0,Record.length-1);
System.arraycopy(backednorm,0,Coefs,0,Record.length-1);
//for(int k=0;kener1*tol) {
throw new IllegalArgumentException("Fail to match dictionnary element number "+k+" got a 'de facto' tolerance of "+(ener2/ener1));
}
}
}
/************************************
* Convert the an element to a
* time-frequency representation
* using Fourier as a basis multiply
* everything by a coefficient b.
*************************************/
private double[][] getTF(int pos, double b) {
double[][] ans=ArrayMath.copy(TF[pos]);
for(int k=0;k1)||(tol<0)) {
throw new IllegalArgumentException("The percentile should be between 0 and 1: "+tol);
}
int TimesAround=0;
double ener0=DFunction.norm();
double ts=ener0*tol;
int maxTimesAround=5*getSize();
double[][] ans=new double[0][0];
while(DFunction.norm()>ts) {
TimesAround++;
if(TimesAround>maxTimesAround) {
throw new MaximumIterationsExceededException("Impossible to match to the desired precision ("+tol+") with this dictionnary of size "+getSize()+" after "+TimesAround+" iterations. You might want to expand the dictionnary.");
}
if(ans.length!=0) {
ans=add(ans,match());
} else {
ans=match();
}
}
return(ans);
}
/******************************************
* Force the system to select the given
* element as the best match. It will return
* the TF representaiton. The TF representation
* may contain negative values and so,
* taking the absolute value of the
* result will often be useful.
*******************************************/
public double[][] forcedMatch(int pos) {
double coef=DiscreteHilbertSpace.integrate(DFunction,Fdual[pos]);
addToRecord(pos,coef);
DFunction=new DiscreteFunction(DiscreteHilbertSpace.add(DFunction,-coef,Fprimary[pos]));
return(getTF(pos,coef));
}
/*********************************
* Does the matching j times and
* return the TF representation.
* The TF representation
* may contain negative values and so,
* taking the absolute value of the
* result will often be useful.
* @param j number of iterations
* @exception IllegalArgumentException if j is not positive
**********************************/
public double[][] match(int j) {
if(j<=0) {
throw new IllegalArgumentException("Can't do "+j+" matching... Must be a positive number.");
}
double[][] ans=match();
for(int k=1;k
Ads help maintain this website.