001: package JSci.tests;
002:
003: import java.util.Map;
004: import java.util.HashMap;
005: import junit.framework.*;
006: import JSci.maths.*;
007:
008: /**
009: * Testcase for Fourier methods.
010: * @author Mark Hale
011: */
012: public class FourierTest extends TestCase {
013: private static final int N = 128;
014: private double[] signal;
015:
016: public static void main(String arg[]) {
017: junit.textui.TestRunner.run(suite());
018: }
019:
020: public static Test suite() {
021: double[][] signals = new double[][] { gaussian(N, 1.0, 8.0),
022: topHat(N, 1.0), constant(N, 1.0), square(N, 1.0),
023: triangle(N, 1.0), sine(N, 1.0, 16) };
024: TestSuite suite = new TestSuite(FourierTest.class.toString());
025: for (int i = 0; i < signals.length; i++) {
026: Map properties = new HashMap();
027: properties.put("test.signal", signals[i]);
028: suite.addTest(new TestProperties(new TestSuite(
029: FourierTest.class), properties));
030: }
031: return suite;
032: }
033:
034: public FourierTest(String name) {
035: super (name);
036: }
037:
038: protected void setUp() throws Exception {
039: JSci.GlobalSettings.ZERO_TOL = 1.0e-10;
040: signal = (double[]) TestProperties.getProperties().get(
041: "test.signal");
042: super .setUp();
043: }
044:
045: /** Tests invFFT(f) = (FFT(f*))* */
046: public void testInverseTransform() {
047: Complex[] inverse = FourierMath.inverseTransform(signal);
048: Complex[] transform = FourierMath.transform(signal);
049: for (int i = 0; i < N; i++) {
050: Complex result = transform[i].conjugate().divide(N);
051: assertEquals("Real", inverse[i].real(), result.real(),
052: JSci.GlobalSettings.ZERO_TOL);
053: assertEquals("Imag", inverse[i].imag(), result.imag(),
054: JSci.GlobalSettings.ZERO_TOL);
055: }
056: }
057:
058: public void testTransform() {
059: Complex[] transform = FourierMath.transform(signal);
060: Complex[] result = FourierMath.inverseTransform(transform);
061: for (int i = 0; i < N; i++) {
062: assertEquals("Real", signal[i], result[i].real(),
063: JSci.GlobalSettings.ZERO_TOL);
064: assertEquals("Imag", 0.0, result[i].imag(),
065: JSci.GlobalSettings.ZERO_TOL);
066: }
067: }
068:
069: public void testParsevalTheorem() {
070: Complex[] transform = FourierMath.transform(signal);
071: assertEquals(N * ArrayMath.sumSquares(signal), ArrayMath
072: .sumModSqrs(transform), JSci.GlobalSettings.ZERO_TOL);
073: }
074:
075: // A selection of test signals
076:
077: /**
078: * Under transform should give something like exp(-x^2).
079: * Real spectrum.
080: */
081: public static double[] gaussian(int n, double amplitude, double k) {
082: double data[] = new double[n];
083: double x;
084: for (int i = 0; i < n; i++) {
085: x = (i - n / 2) / k;
086: data[i] = amplitude * Math.exp(-x * x);
087: }
088: return data;
089: }
090:
091: /**
092: * Under transform should give something like cos(x)/x.
093: * Real spectrum.
094: */
095: public static double[] topHat(int n, double amplitude) {
096: double data[] = new double[n];
097: int i = 0;
098: for (; i < n / 4; i++)
099: data[i] = 0.0;
100: for (; i < 3 * n / 4; i++)
101: data[i] = amplitude;
102: for (; i < n; i++)
103: data[i] = 0.0;
104: return data;
105: }
106:
107: /**
108: * Under transform should give a delta-function at origin.
109: * Real spectrum.
110: */
111: public static double[] constant(int n, double amplitude) {
112: double data[] = new double[n];
113: for (int i = 0; i < n; i++)
114: data[i] = amplitude;
115: return data;
116: }
117:
118: /**
119: * Under transform should give something like i*sin(x)/x.
120: * Complex spectrum.
121: */
122: public static double[] square(int n, double amplitude) {
123: double data[] = new double[n];
124: int i = 0;
125: for (; i < n / 2; i++)
126: data[i] = -amplitude;
127: for (; i < n; i++)
128: data[i] = amplitude;
129: return data;
130: }
131:
132: /**
133: * Under transform should give something like i*sin(x)/x^2.
134: * Complex spectrum.
135: */
136: public static double[] triangle(int n, double amplitude) {
137: double data[] = new double[n];
138: double gradient = amplitude * 4.0 / n;
139: int i = 0;
140: for (; i < n / 4; i++)
141: data[i] = -gradient * i;
142: for (; i < 3 * n / 4; i++)
143: data[i] = -2.0 * amplitude + gradient * i;
144: for (; i < n; i++)
145: data[i] = 4.0 * amplitude - gradient * i;
146: return data;
147: }
148:
149: /**
150: * Under transform should give two delta-functions at +/- frequency.
151: * Complex spectrum.
152: */
153: public static double[] sine(int n, double amplitude, int cycles) {
154: double data[] = new double[n];
155: double w = NumericalConstants.TWO_PI * cycles / n;
156: for (int i = 0; i < n; i++)
157: data[i] = amplitude * Math.sin((i - n / 2) * w);
158: return data;
159: }
160: }
|