001: import java.awt.Color;
002: import java.awt.Frame;
003: import java.awt.GridLayout;
004: import java.awt.Label;
005: import java.awt.Panel;
006: import java.awt.event.WindowAdapter;
007: import java.awt.event.WindowEvent;
008: import java.io.BufferedReader;
009: import java.io.FileReader;
010: import java.io.FileWriter;
011: import java.io.PrintWriter;
012: import java.util.StringTokenizer;
013:
014: import JSci.awt.DefaultGraph2DModel;
015: import JSci.maths.wavelet.FWTCoef;
016: import JSci.maths.wavelet.Signal;
017: import JSci.maths.wavelet.daubechies2.Daubechies2;
018: import JSci.maths.wavelet.daubechies3.Daubechies3;
019: import JSci.maths.wavelet.daubechies4.Daubechies4;
020: import JSci.maths.wavelet.daubechies5.Daubechies5;
021: import JSci.maths.wavelet.daubechies6.Daubechies6;
022: import JSci.maths.wavelet.daubechies7.Daubechies7;
023: import JSci.maths.wavelet.daubechies8.Daubechies8;
024: import JSci.swing.JGraphLayout;
025: import JSci.swing.JLineGraph;
026:
027: /**
028: * Example class for denoising a signal.
029: * <p>
030: * In this case an astronomical spectrum of a faint galaxy stored in
031: * the file "galaxy.txt" is used. The denoised spectrum is written to
032: * file "galaxy_denoise.txt" and both spectra are plotted in a graph.
033: *
034: * @authors Peter W. Draper (p.w.draper@durham.ac.uk).
035: */
036: public class Denoise extends Frame {
037: public static void main(String[] args) {
038: Denoise denoise = new Denoise();
039: }
040:
041: protected Denoise() {
042: super ("Denoise graphs");
043: addWindowListener(new WindowAdapter() {
044: public void windowClosing(WindowEvent evt) {
045: dispose();
046: System.exit(0);
047: }
048: });
049: setLayout(new GridLayout(3, 1));
050: setSize(400, 800);
051:
052: if (readData()) {
053: doCalcs();
054: doDisplay();
055: writeData();
056: }
057: }
058:
059: // Choose a filter to use.
060: //private Daubechies8 filter = new Daubechies8();
061: private Daubechies2 filter = new Daubechies2();
062: //private Daubechies6 filter = new Daubechies6();
063: //private Daubechies7 filter = new Daubechies7();
064: //private Daubechies4 filter = new Daubechies4();
065:
066: /** Data read from input file, plus padding */
067: private double[] noisy = null;
068:
069: /** Data after it has been denoised */
070: private double[] clean = null;
071:
072: /** Offset into data array where real values start */
073: private int offset = 0;
074:
075: /** Number of lines read from input file */
076: private int nlines = 0;
077:
078: /** Power of 2 used to create data areas */
079: private int maxlevel = 1;
080:
081: /** Name of input file */
082: public static final String INFILE = "galaxy.txt";
083:
084: /** Name of output file */
085: public static final String OUTFILE = "galaxy_denoise.txt";
086:
087: /** Denoise threshold (0-1). */
088: public static double threshold = 0.5;
089:
090: /**
091: * Read in the "noisy" data.
092: */
093: private boolean readData() {
094: int filtertype = filter.getFilterType();
095:
096: // Read the data from the text file. This just uses the first
097: // word from each line.
098: try {
099: BufferedReader r = new BufferedReader(
100: new FileReader(INFILE));
101: String raw = null;
102:
103: // Count lines.
104: while ((raw = r.readLine()) != null) {
105: nlines++;
106: }
107: r.close();
108:
109: // Need a power of 2 for data size, plus padding for
110: // dyadic multiresolution scaling functions.
111: maxlevel = 1;
112: while (nlines > Math.pow(2.0, (double) maxlevel)) {
113: maxlevel++;
114: }
115: int count = (int) Math.pow(2.0, (double) maxlevel)
116: + filtertype;
117:
118: // Now really read data. If buffered place near centre.
119: r = new BufferedReader(new FileReader(INFILE));
120: noisy = new double[count];
121: offset = count = (count - nlines) / 2;
122: StringTokenizer st = null;
123: while ((raw = r.readLine()) != null) {
124: st = new StringTokenizer(raw);
125: noisy[count++] = Float.parseFloat(st.nextToken());
126: }
127: r.close();
128:
129: // Fill any buffered regions with end values.
130: double value = noisy[offset];
131: for (int i = 0; i < offset; i++) {
132: noisy[i] = value;
133: }
134: value = noisy[offset + nlines - 1];
135: for (int i = offset + nlines; i < noisy.length; i++) {
136: noisy[i] = value;
137: }
138: } catch (Exception e) {
139: e.printStackTrace();
140: return false;
141: }
142: return true;
143: }
144:
145: /**
146: * Determine the wavelet coefficient and generate a denoised
147: * signal by setting some of the coefficients to zero and
148: * re-generating.
149: */
150: private void doCalcs() {
151: // Choose a maximum level and use that. Note 20 is max
152: // possible, and we need to leave space for filtertype
153: // padding (-4).
154: int level = Math.min(maxlevel - 4, 20);
155:
156: // Make the Signal and filter it.
157: Signal signal = new Signal(noisy);
158: signal.setFilter(filter);
159: FWTCoef signalCoeffs = signal.fwt(level);
160:
161: // Zero any coefficients that are less than some fraction of
162: // the total sum.
163: signalCoeffs.denoise(threshold);
164:
165: // Rebuild the signal with the new set of coefficients.
166: double[] rebuild = signalCoeffs.rebuildSignal(filter).evaluate(
167: 0);
168:
169: // Trim padding away from all data.
170: double[] trimmed = new double[nlines];
171: System.arraycopy(noisy, offset, trimmed, 0, nlines);
172: noisy = trimmed;
173: clean = new double[nlines];
174: System.arraycopy(rebuild, offset, clean, 0, nlines);
175: }
176:
177: /**
178: * Write the denoised data to an output file.
179: */
180: private void writeData() {
181: try {
182: PrintWriter r = new PrintWriter(new FileWriter(OUTFILE));
183: for (int i = 0; i < clean.length; i++) {
184: r.println(clean[i]);
185: }
186: r.close();
187: } catch (Exception e) {
188: e.printStackTrace();
189: }
190: }
191:
192: /**
193: * Draw a graph showing the original data and the denoised version
194: * for comparison.
195: */
196: private void doDisplay() {
197: DefaultGraph2DModel model1 = new DefaultGraph2DModel();
198: model1.setXAxis(0.0f, (float) noisy.length, noisy.length);
199: model1.addSeries(noisy);
200: model1.addSeries(clean);
201: model1.setSeriesVisible(1, true);
202:
203: Panel panel1 = new Panel();
204: panel1.setLayout(new JGraphLayout());
205: Label title = new Label("Overlay graph", Label.CENTER);
206: panel1.add(title, "Title");
207: JLineGraph graph1 = new JLineGraph(model1);
208: graph1.setColor(0, Color.red);
209: graph1.setColor(1, Color.blue);
210: panel1.add(graph1, "Graph");
211: add(panel1);
212:
213: DefaultGraph2DModel model2 = new DefaultGraph2DModel();
214: model2.setXAxis(0.0f, (float) noisy.length, noisy.length);
215: model2.addSeries(noisy);
216:
217: Panel panel2 = new Panel();
218: panel2.setLayout(new JGraphLayout());
219: title = new Label("Raw data", Label.CENTER);
220: panel2.add(title, "Title");
221: JLineGraph graph2 = new JLineGraph(model2);
222: graph2.setColor(0, Color.red);
223: panel2.add(graph2, "Graph");
224: add(panel2);
225:
226: DefaultGraph2DModel model3 = new DefaultGraph2DModel();
227: model3.setXAxis(0.0f, (float) clean.length, clean.length);
228: model3.addSeries(clean);
229:
230: Panel panel3 = new Panel();
231: panel3.setLayout(new JGraphLayout());
232: title = new Label("Denoised data", Label.CENTER);
233: panel3.add(title, "Title");
234: JLineGraph graph3 = new JLineGraph(model3);
235: graph3.setColor(0, Color.blue);
236: panel3.add(graph3, "Graph");
237: add(panel3);
238:
239: setVisible(true);
240: }
241: }
|