KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JSci > maths > wavelet > BasisFunctionLibrary


1 package JSci.maths.wavelet;
2
3 import JSci.maths.*;
4
5 /*********************************************
6 * This class is meant to be used for
7 * Fast Wavelet Transform, Matching Pursuit
8 * and related signal processing algorithm.
9 * The basic idea is to automatically build
10 * and compress a library of "basis functions".
11 * Using Morse Coding this class delivers
12 * very fast code without sacrificing
13 * anything. The only fee is the one you pay
14 * to build the object, and it is a one time
15 * fee.
16 *
17 * Note : this class should be rewritten to
18 * use the java.util collections starting with
19 * jdk1.2.
20 *
21 * This class is not meant to be used directly
22 * but rather, you should build on it.
23 *
24 * It supports only 1D data.
25 **********************************************/

26 public class BasisFunctionLibrary implements Cloneable JavaDoc {
27   //threshold for morse coding
28
private double MorseThreshold=0.5;
29     protected DiscreteFunction[] Fprimary;
30     protected DiscreteFunction[] Fdual;
31     protected DiscreteFunction DFunction;
32
33   public Object JavaDoc clone() {
34     try {
35       BasisFunctionLibrary c=(BasisFunctionLibrary) super.clone();
36       c.MorseThreshold=this.MorseThreshold;
37       c.DFunction=(DiscreteFunction) this.DFunction.clone();
38       c.Fprimary=cloneArrayDiscreteFunction(this.Fprimary);
39       c.Fdual=cloneArrayDiscreteFunction(this.Fdual);
40       return(c);
41     } catch (CloneNotSupportedException JavaDoc cnse) {
42       throw new InternalError JavaDoc();
43     }
44   }
45
46   public void setMorseThreshold(double p) {
47     if((p<0)||(p>1)) {
48       throw new IllegalArgumentException JavaDoc("The threshold must be between 0 and 1 :"+p);
49     }
50     MorseThreshold=p;
51   }
52
53   public double getMorseThreshold() {
54     return(MorseThreshold);
55   }
56
57
58     public void includeFourier () {
59         for(int k=0;k<=Math.floor(DFunction.dimension()/2d);k++) {
60             add(new Cosine(DFunction.dimension(),k));
61         }
62
63         for(int k=1;k<Math.ceil(DFunction.dimension()/2d);k++) {
64             add(new Sine(DFunction.dimension(),k));
65         }
66
67     }
68
69     public void includeMasslessFourier () {
70         for(int k=1;k<=Math.floor(DFunction.dimension()/2d);k++) {
71             add(new Cosine(DFunction.dimension(),k));
72         }
73         for(int k=1;k<Math.ceil(DFunction.dimension()/2d);k++) {
74             add(new Sine(DFunction.dimension(),k));
75         }
76     }
77
78     public DiscreteFunction getPrimary (int k) {
79         return(Fprimary[k]);
80     }
81
82     public DiscreteFunction getDual(int k) {
83         return(Fdual[k]);
84     }
85
86   protected BasisFunctionLibrary() {
87   }
88
89   public BasisFunctionLibrary(DiscreteFunction f) {
90     setData(f);
91   }
92
93     /***********************************
94     * Allows the user to change the
95     * DiscreteFunction (see constructor).
96   * @exception IllegalArgumentException if you
97   * try to change the number of data values
98   * (dimension of the DiscreteFunction)
99     ************************************/

100     public void setData(DiscreteFunction f) {
101     if(DFunction!=null) {
102       if(f.dimension()!=DFunction.dimension()) {
103         throw new IllegalArgumentException JavaDoc("You cannot change the dimension of the data object. Please create a new object.");
104       }
105     }
106         DFunction= (DiscreteFunction) f.clone();
107     }
108
109   /********************************
110   * get a copy of the data object
111   * (no direct access)
112   *********************************/

113     public DiscreteFunction getData () {
114         return((DiscreteFunction) DFunction.clone());
115     }
116
117   /*************************************
118   * Clone an arry of DiscreteFunction.
119   * This method is needed to handle
120   * eventual null object.
121   **************************************/

122     protected static DiscreteFunction[] cloneArrayDiscreteFunction (MultiscaleFunction[] a) {
123         if(a!=null) {
124
125             DiscreteFunction[] b=new DiscreteFunction[a.length];
126             for(int k=0;k<a.length;k++) {
127                 if(a[k]!=null) {
128                     b[k]=(DiscreteFunction) a[k].clone();
129                 }
130             }
131             return(b);
132         } else {
133             return(null);
134         }
135     }
136
137   private DiscreteFunction toDiscreteFunction(MultiscaleFunction f) {
138     int j=0;
139     while(f.dimension(j)<DFunction.dimension()) {
140       j++;
141       if(j>20) {
142         throw new IllegalScalingException("Could not match the added object with internal data object in 20 iterations.");
143       }
144     }
145     if(f.dimension(j)!=DFunction.dimension()) {
146         throw new IllegalScalingException("Could not match the added object with internal data object.");
147     }
148     double[] eval=ArrayMath.scalarMultiply(1/Math.sqrt((double)Cascades.PowerOf2(j)),f.evaluate(j));
149     int nonzero=0;
150     for(int k=0;k<eval.length;k++) {
151       if(eval[k]!=0)
152         nonzero++;
153     }
154     if(nonzero>(MorseThreshold*(double) eval.length))
155       return(new DiscreteFunction(eval));
156     else {
157       return(new SparseDiscreteFunction(eval));
158
159     }
160   }
161
162     /**********************************************
163     * Add a clone of the given MultiscaleFunctions
164     * to the internal arrays of MultiscaleFunctions.
165     ***********************************************/

166     public void add(MultiscaleFunction fprimary, MultiscaleFunction fdual) {
167         if((fprimary==null)||(fdual==null)) {
168             throw new NullPointerException JavaDoc("You cannot add a null object to the internal arrays.");
169         }
170         if(Fprimary!=null) {
171             DiscreteFunction[] backup=Fprimary;
172             Fprimary=new DiscreteFunction[backup.length+1];
173       System.arraycopy(backup,0,Fprimary,0,backup.length);
174             Fprimary[backup.length]=toDiscreteFunction((MultiscaleFunction) fprimary.clone());
175         } else {
176             Fprimary=new DiscreteFunction[1];
177             Fprimary[0]=toDiscreteFunction((MultiscaleFunction) fprimary.clone());
178         }
179         if(Fdual!=null) {
180             DiscreteFunction[] backup=Fdual;
181             Fdual=new DiscreteFunction[backup.length+1];
182       System.arraycopy(backup,0,Fdual,0,backup.length);
183             Fdual[backup.length]=toDiscreteFunction((MultiscaleFunction) fdual.clone());
184         } else {
185             Fdual=new DiscreteFunction[1];
186             Fdual[0]=toDiscreteFunction((MultiscaleFunction) fdual.clone());
187         }
188     }
189
190     /********************************************
191     * Add the MultiscaleFunction to both the primary
192     * and dual internal arrays.
193     *********************************************/

194     public void add(MultiscaleFunction f) {
195         add(f,f);
196     }
197
198     /********************************************
199     * Add the array of MultiscaleFunction to both
200   * the primary and dual internal arrays.
201     *********************************************/

202     public void add(MultiscaleFunction[] f) {
203     for(int k=0;k<f.length;k++) {
204           add(f[k],f[k]);
205     }
206     }
207
208   /**************************************************
209   * Attempt to add every possible functions belonging
210   * to a multiresolution. Entirely automatic!
211   * Limited to dyadic multiresolutions.
212   ***************************************************/

213     public void add (Multiresolution mr) {
214         int n=DFunction.dimension();
215         try {
216             do {
217                 n=mr.previousDimension(n);
218                 for(int k=0;k<n;k++) {
219                     this.add(mr.primaryScaling(n,k),mr.dualScaling(n,k));
220                 }
221                 for(int k=0;k<n-mr.getFilterType();k++) {
222                     this.add(mr.primaryWavelet(n,k),mr.dualWavelet(n,k));
223                 }
224
225             } while (true);
226         } catch (IllegalScalingException e) {}
227
228     }
229
230     public double[] getResidues() {
231         double[] coef=getWeigths();
232         double[] ans=new double[coef.length];
233         for(int k=0;k<ans.length;k++) {
234             ans[k]=ArrayMath.norm(DiscreteHilbertSpace.add(DFunction,-coef[k],Fprimary[k]));
235         }
236         return(ans);
237     }
238
239     public double getResidue(int k) {
240         return(ArrayMath.norm(DiscreteHilbertSpace.add(DFunction,-getWeigth(k),Fprimary[k])));
241     }
242
243     public double[] getWeigths() {
244         double[] ans=new double[getSize()];
245         for(int k=0;k<getSize();k++) {
246             ans[k]=DiscreteHilbertSpace.integrate(DFunction,Fdual[k]);//normalisation[k];
247
}
248         return(ans);
249     }
250
251     public double getWeigth(int k) {
252         return(DiscreteHilbertSpace.integrate(DFunction,Fdual[k]));//normalisation[k];
253
}
254
255     public double norm() {
256         return(ArrayMath.norm(DFunction.evaluate(0)));
257     }
258
259
260
261
262     /**********************************
263     * We will now attempt to match
264     * each MultiscaleFunction to the length
265     * of the data.
266     ***********************************/

267     public int getSize() {
268         if(Fprimary==null) {
269             return(0);
270         }
271         return(Fprimary.length);
272     }
273
274     protected static double norm(double a, double b) {
275         return(Math.sqrt(a*a+b*b));
276     }
277
278     private double[][] scalarMultiply(double[][] v, double a) {
279         double[][] ans=new double[v.length][];
280         for(int k=0;k<v.length;k++) {
281             ans[k]=new double[v[k].length];
282             for(int l=0;l<v[k].length;l++) {
283                 ans[k][l]=a*v[k][l];
284             }
285         }
286         return(ans);
287     }
288     /*************************************
289     * Checks whether whether or not the
290     * biorthogonality is satisfied
291   * If so, the return array should
292   * <I>roughly</I> be
293   * filled with ones.
294     **************************************/

295     public double[] checkBiorthogonality() {
296         double[] ans=new double[getSize()];
297         for(int k=0;k<getSize();k++) {
298         ans[k]=DiscreteHilbertSpace.integrate(Fprimary[k],Fdual[k]);
299     }
300         return(ans);
301     }
302
303     protected static double[][] add(double[][] v, double[][] w) {
304         if(v.length!=w.length) {
305             throw new IllegalArgumentException JavaDoc("Incompatible types "+v.length+", "+w.length );
306         }
307         double[][] ans=new double[v.length][];
308         for(int k=0;k<v.length;k++) {
309             ans[k]=new double[v[k].length];
310             if(v[k].length!=w[k].length) {
311                 throw new IllegalArgumentException JavaDoc("Incompatible types "+v.length+", "+w.length+" : " +v[k].length+", "+w[k].length );
312             }
313             for(int l=0;l<v[k].length;l++) {
314                 ans[k][l]=v[k][l]+w[k][l];
315             }
316         }
317         return(ans);
318     }
319 }
320
321
Popular Tags