package signalproc.algorithms;
import jfftw.Plan;
import org.trianacode.taskgraph.Unit;
import triana.types.*;
import triana.types.audio.MultipleAudio;
import triana.types.util.SigAnalWindows;
import triana.types.util.Str;
import triana.types.util.Triplet;
import java.util.ArrayList;
/**
* A FFT unit to perform a Fast Fourier Transform on the input data.
* <p/>
* If the input implements the Signal Interface, then signal parameters (sampling rate, etc) are used to produce a
* correctly normalized spectrum, ie an approximation to the continuous FT. If the input data are real, then the output
* are one-sided. The output is a ComplexSpectrum data type.
* <p/>
* If the input data implements Spectral, then an inverse FFT is performed. If the data are one-sided, the the output is
* a SampleSet. If the data are two-sided, then the output is a ComplexSampleSet. If the data are narrow-band, they are
* converted to full bandwidth (padding with zeroes) before the inverse transform is applied. In each case, the
* normalization is based on the data in the Spectral data set.
* <p/>
* If the input data does not implement the Spectral or Signal Interfaces, then it is assumed to require a direct
* (forward) FFT, and the output is a ComplexSpectrum data set with no normalization applied. This is the same as for an
* input SampleSet with sampling frequency = 1.
* <p/>
* If this automatic behavior is not desired, then use the Units DirectFFT and InverseFFT instead. These Units always
* perform the FFT in the indicated direction and apply no normalization, not even the 1/N. Their output is always a
* VectorType (real or complex as appropriate) and the data are always two-sided.
* <p/>
* If the input data are not uniformly sampled, then an error is generated and no output takes place.
* <p/>
* The FFT is performed using the FFTC algorithm.
*
* @author Ian Taylor
* @author B F Schutz
* @author Rob Davies
* @author Craig Robinson
* @version 2.11 09 March 2001
* @see FFTC
* @see Spectral
* @see Signal
* @see ComplexSpectrum
* @see Spectrum
* @see SampleSet
* @see ComplexSampleSet
*/
public class FFTW extends Unit {
String style = "Automatic";
String WindowFunction = "(none)";
boolean padding = false;
//added by Rob 30/06/03
//don't need for fftw
//String opt = "MaximumSpeed";
FFTC fft;
//variables added Rob 01/07/03
Plan createdPlan;
int planLength;
boolean planForward;
FFTWLibrary fftwlib;
String planType = "Estimate";
// private String wisdomFile = System.getProperty("user.getApplicationDataDir") + System.getProperty("file.separator") + "fftw.wisdom";
/**
* ********************************************* ** A Java FFT algorithm ***
* *********************************************
*/
public void process() throws Exception {
GraphType result = null;
GraphType input;
int points = 1;
int points0 = 1;
int kk, j;
int targetN = 1;
double sf = 0;
double sf0 = 0;
double maxFreq = 0.5;
double maxFreq0 = 0.5;
boolean applyNorm = true;
double norm = 1;
double norm0 = 1;
double resolution = 1;
double resolution0 = 1;
boolean direct = true;
boolean oneSide = true;
boolean conjugateSymmetric = false;
boolean conjugateAntisymmetric = false;
int conjugateAnswer = 0;
//added by Rob 30/06/03
//don't need for fftw
//boolean speed = opt.equals("MaximumSpeed");
double[] dataR = null;
double[] dataI = null;
double[] real = null;
double[] imag = null;
double[][] mdataR = null;
double[][] mdataI = null;
double[][] mreal = null;
double[][] mimag = null;
Class inClass = null;
Class[] inClasses = null;
int numberOfChannels = 1;
ArrayList dataList = null;
int[] chSize = null;
String acqTime = "";
int typeInt;
if (planType.equals("Estimate")) {
typeInt = jfftw.Plan.ESTIMATE | jfftw.Plan.USE_WISDOM;
} else {
typeInt = jfftw.Plan.MEASURE | jfftw.Plan.USE_WISDOM;
}
input = (GraphType) getInputAtNode(0);
if (input instanceof MultipleAudio) {
MultipleAudio au = (MultipleAudio) input;
double[] data = (double[]) au.getDataArrayRealAsDoubles(0);
input = new SampleSet(au.getAudioChannelFormat(0).getSamplingRate(), data);
}
boolean oneD = (input instanceof VectorType);
boolean twoD = (input instanceof MatrixType);
boolean multipleOneD = (input instanceof MultipleAudio);
boolean inputSignal = (input instanceof Signal);
if (inputSignal) {
acqTime = (new StringBuffer("FFT: Acquistion time of first sample of data from which output is built = "))
.append(((Signal) input).getAcquisitionTime()).toString();
}
/* Debugging output
println("Got input." );
System.out.print("It is of type ");
if ( input instanceof Signal ) println("Signal.");
else if (input instanceof Spectral ) println("Spectral. It contains parameter nFull = " + String.valueOf(((Spectral)input).getOriginalN(0) ) );
*/
if (padding) {
if (oneD) {
points = ((VectorType) input).size();
targetN = 1;
while (targetN < points) {
targetN *= 2;
}
if (targetN > points) {
((VectorType) input).extendWithZeros(targetN, false);
}
} else if (twoD) {
// padding not yet implemented for matrices
} else if (multipleOneD) {
// padding not yet implemented in MultipleAudio
}
}
// implement windowing only for one-dimensional transforms of single vectors
if (oneD && !WindowFunction.equals("(none)")) {
input = (VectorType) SigAnalWindows.applyWindowFunction((VectorType) input, WindowFunction, true);
}
// println("Got past window function.");
boolean inputComplex = input.isDependentComplex(0);
if (oneD) {
inClass = input.getDataArrayClass(0);
dataR = ((VectorType) input).getDataReal();
dataI = null;
if (inputComplex) {
dataI = ((VectorType) input).getDataImag();
}
//change by Rob 07/07/03
if (inputComplex) {
//may not be, maybe points = dataR.length + dataI.lentgh - 1;
//points = dataR.length + dataI.length - 2;
points = FFTWLibrary.mergeLength(dataR, dataI);
} else {
points = ((VectorType) input).size();
}
//end change by Rob
} else if (twoD) {
inClass = input.getDataArrayClass(0);
mdataR = ((MatrixType) input).getDataReal();
mdataI = null;
if (inputComplex) {
mdataI = ((MatrixType) input).getDataImag();
}
points = (((MatrixType) input).size())[1];
points0 = (((MatrixType) input).size())[0];
} else if (multipleOneD) {
numberOfChannels = input.getDependentVariables();
inClasses = new Class[numberOfChannels];
dataList = new ArrayList(numberOfChannels);
dataR = (double[]) ((MultipleAudio) input).getDataArrayReal(0);
dataI = null;
points = ((MultipleAudio) input).getChannelLength(0);
/* for ( int ch = 0; ch < numberOfChannels; ch++ ) {
inClasses[ ch ] = input.getDataArrayClass( ch );
dataList.add( ((MultipleAudio)input).getDataArrayReal( ch ) );
chSize[ ch ] = ((MultipleAudio)input).getChannelLength( ch );
} */
}
// println("Got size = " + String.valueOf( points ) );
if (style.equals("Direct")) {
applyNorm = false;
direct = true;
oneSide = false;
if (oneD) {
//added by Rob 30/06/03
if (!inputComplex) {
oneSide = true;
System.out.println("creating real plan");
createdPlan = fftwlib.realPlan(dataR.length, true, typeInt);
} else {
//todo : check if this dimension is correct!!!
createdPlan = fftwlib.complexPlan(dataR.length, true, typeInt);
}
//end of changes by Rob
sf = 1.0 / ((VectorType) input).getXTriplet().getStep();
}
if (twoD) {
//added Rob 01/07/03
//todo : check that these plans are created properly!!!
if (!inputComplex) {
createdPlan = fftwlib.realNdPlan(new int[]{mdataR.length}, true, typeInt);
} else {
createdPlan = fftwlib.complexNdPlan(new int[]{mdataR.length}, true, typeInt);
}
//end Rob
sf = 1.0 / ((MatrixType) input).getXorYTriplet(1).getStep();
sf0 = 1.0 / ((MatrixType) input).getXorYTriplet(0).getStep();
resolution0 = sf0 / points0;
maxFreq0 = sf0 / 2.0;
}
resolution = sf / points;
maxFreq = sf / 2.0;
} else if (style.equals("Direct/normalized(1/N)")) {
applyNorm = true;
direct = true;
norm = 1. / points;
oneSide = false;
if (oneD) {
//added by Rob 07/07/03
if (!inputComplex) {
oneSide = true;
System.out.println("creating real plan");
createdPlan = fftwlib.realPlan(dataR.length, true, typeInt);
} else {
//todo : check if this dimension is correct!!!
createdPlan = fftwlib.complexPlan(dataR.length, true, typeInt);
}
//end of changes by Rob
sf = 1.0 / ((VectorType) input).getXTriplet().getStep();
}
if (twoD) {
//added Rob 07/07/03
//todo : check that these plans are created properly!!!
if (!inputComplex) {
createdPlan = fftwlib.realNdPlan(new int[]{mdataR.length}, true, typeInt);
} else {
createdPlan = fftwlib.complexNdPlan(new int[]{mdataR.length}, true, typeInt);
}
//end Rob
sf = 1.0 / ((MatrixType) input).getXorYTriplet(1).getStep();
sf0 = 1.0 / ((MatrixType) input).getXorYTriplet(0).getStep();
resolution0 = sf0 / points0;
maxFreq0 = sf0 / 2.0;
norm0 = 1. / points0;
}
resolution = sf / points;
maxFreq = sf / 2.0;
} else if (style.equals("Inverse")) {
applyNorm = false;
direct = false;
oneSide = false;
if (oneD) {
//added by Rob 30/06/03
if ((inputComplex) && ((input instanceof Spectral))) {
if (!((Spectral) input).isTwoSided()) {
oneSide = true;
System.out.println("creating inverse fftw plan");
//todo : this isn't correct. The Need to sort out the length being passed!!!
//maybe dataR.length+dataI.length-1
int length = FFTWLibrary.mergeLength(dataR, dataI);
createdPlan = fftwlib.realPlan(length, direct, typeInt);
} else {
createdPlan = fftwlib.complexPlan(dataR.length, direct, typeInt);
}
} else {
createdPlan = fftwlib.complexPlan(dataR.length, direct, typeInt);
}
//end of changes by Rob
resolution = ((VectorType) input).getXTriplet().getStep();
}
if (twoD) {
resolution = ((MatrixType) input).getXorYTriplet(1).getStep();
resolution0 = ((MatrixType) input).getXorYTriplet(0).getStep();
sf0 = resolution0 * points0;
}
sf = resolution * points;
System.out.println("***resolution : " + resolution);
System.out.println("***points : " + points);
System.out.println("***sf : " + sf);
} else if (style.equals("Inverse/normalized(1/N)")) {
applyNorm = true;
direct = false;
norm = 1. / points;
oneSide = false;
if (oneD) {
//added by Rob 30/06/03
//changed 08/07/03
if ((inputComplex) && ((input instanceof Spectral))) {
if (!((Spectral) input).isTwoSided()) {
oneSide = true;
System.out.println("creating inverse fftw plan");
//maybe dataR.length+dataI.length-1
int length = FFTWLibrary.mergeLength(dataR, dataI);
createdPlan = fftwlib.realPlan(length, direct, typeInt);
} else {
createdPlan = fftwlib.complexPlan(dataR.length, direct, typeInt);
}
} else {
createdPlan = fftwlib.complexPlan(dataR.length, direct, typeInt);
}
//end of changes by Rob
resolution = ((VectorType) input).getXTriplet().getStep();
}
if (twoD) {
resolution = ((MatrixType) input).getXorYTriplet(1).getStep();
resolution0 = ((MatrixType) input).getXorYTriplet(0).getStep();
sf0 = resolution0 * points0;
norm0 = 1. / points0;
}
sf = resolution * points;
} else if (style.equals("Automatic")) {
if (input instanceof Signal) {
applyNorm = true;
sf = ((Signal) input).getSamplingRate();
maxFreq = sf / 2.0;
resolution = sf / points;
norm = 1. / sf;
// println("Signal object: norm = " + String.valueOf(norm) + ", resolution = " + String.valueOf(resolution) );
direct = true;
//changes buy Rob 01/07/03
//if ( speed ) oneSide = false;
//else oneSide = !inputComplex;
oneSide = !inputComplex;
//end changes by Rob
// println("About to test conjugate symmetry.");
//change by Rob 01/07/03
//if ( !speed ) {
//craigif ( !oneSide ) {
//end of Rob change
// conjugateAnswer = fft.testConjugateSymmetry( dataR, dataI );
// if ( conjugateAnswer == 1 ) conjugateSymmetric = true;
// else if (conjugateAnswer == -1 ) conjugateAntisymmetric = true;
// System.out.println("Result of test: " + String.valueOf(conjugateSymmetric) + " " + String.valueOf(conjugateAntisymmetric) );
//craig }
} else if (input instanceof Spectral) {
applyNorm = true;
if (oneD) {
oneSide = !((Spectral) input).isTwoSided();
} else {
oneSide = false;
}
resolution = ((Spectral) input).getFrequencyResolution(0);
if (twoD) {
resolution = ((Spectral) input).getFrequencyResolution(1);
resolution0 = ((Spectral) input).getFrequencyResolution(0);
}
// println("About to convert from dataR with first element = " + String.valueOf(dataR[0]) + ", original N = " + String.valueOf(((Spectral)input).getOriginalN( 0 )) );
/*Craig if ( oneSide || ((Spectral)input).isNarrow( 0 ) ) {
dataR = FlatArray.convertToFullSpectrum( dataR, ((Spectral)input).getOriginalN( 0 ), oneSide, true, ((Spectral)input).isNarrow( 0 ), (int)Math.round(((Spectral)input).getLowerFrequencyBound( 0 )/((Spectral)input).getFrequencyResolution( 0 )) );
println("Calling convertToFullSpectrum with arguments:");
println("nfull = " + String.valueOf(((Spectral)input).getOriginalN( 0 )));
println("oneside = " + String.valueOf( oneSide ) );
println("narrow = " + String.valueOf( ((Spectral)input).isNarrow( 0 ) ) );
println("low index = " + String.valueOf((int)Math.round(((Spectral)input).getLowerFrequencyBound( 0 )/((Spectral)input).getFrequencyResolution( 0 ))) );
int pd;
println("Real data full spectrum:");
for( pd = 0; pd < dataR.length; pd++ ) println(String.valueOf(dataR[pd]));
if ( inputComplex ) {
dataI = FlatArray.convertToFullSpectrum( dataI, ((Spectral)input).getOriginalN( 0 ), oneSide, false, ((Spectral)input).isNarrow( 0 ), (int)Math.round(((Spectral)input).getLowerFrequencyBound( 0 )/((Spectral)input).getFrequencyResolution( 0 )) );
println("Imaginary data full spectrum:");
for( pd = 0; pd < dataI.length; pd++ ) println(String.valueOf(dataI[pd]));
}
}Craig*/
norm = resolution;
// println("Spectral object: norm = " + String.valueOf(norm) + ", resolution = " + String.valueOf(resolution) );
points = ((Spectral) input).getOriginalN(1);
sf = resolution * points;
if (twoD) {
//points0 = ((Spectral)input).getOriginalN( 1 );
sf = resolution0 * points0;
norm0 = /*1.0 / points0*/ resolution0;
//Craig points0 = ((Spectral)input).getOriginalN( 0 );
sf0 = resolution0 * points0;
maxFreq0 = sf0 / 2.;
}
maxFreq = sf / 2.;
direct = false;
//change by Rob 01/07/03
//if ( !speed && oneD ) {
/*Craigif ( oneD ) {
//end change Rob
if ( oneSide ) conjugateSymmetric = true;
else {
conjugateAnswer = fft.testConjugateSymmetry( dataR, dataI );
if ( conjugateAnswer == 1 ) conjugateSymmetric = true;
else if (conjugateAnswer == -1 ) conjugateAntisymmetric = true;
}
// println("Result of test: " + String.valueOf(conjugateSymmetric) + " " + String.valueOf(conjugateAntisymmetric) );
}Craig*/
} else {
applyNorm = false; //Craig
if (oneD) {
// System.out.println("It gets here");
sf = 1.0; /// ((VectorType)input).getXTriplet().getStep();
//Craig applyNorm = false;
maxFreq = 0.5;
}
// println("Other object: norm = " + String.valueOf(norm) + ", resolution = " + String.valueOf(resolution) );
direct = true;
if (twoD) {
oneSide = false;
sf = 1.0;// / ((MatrixType)input).getXorYTriplet( 1 ).getStep();
sf0 = 1.0;// / ((MatrixType)input).getXorYTriplet( 0 ).getStep();
resolution0 = sf0 / points0;
maxFreq0 = 0.5;
//maxFreq0 = sf0 / 2.0; //Craig
} else {
//changes by Rob 01/07/03
//if ( speed ) oneSide = false;
//else oneSide = !inputComplex;
oneSide = !inputComplex;
// System.out.println("oneside = " + oneSide);
//if ( !speed ) {
//Craigif ( !oneSide ) {
//end changes by Rob
// conjugateAnswer = fft.testConjugateSymmetry( dataR, dataI );
// if ( conjugateAnswer == 1 ) conjugateSymmetric = true;
// else if (conjugateAnswer == -1 ) conjugateAntisymmetric = true;
// println("Result of test: " + String.valueOf(conjugateSymmetric) + " " + String.valueOf(conjugateAntisymmetric) );
//Craig}
}
resolution = sf / points;
//maxFreq = sf / 2.0; // Craig
}
if (direct == true) {
if (oneD) {
if (!inputComplex) {
createdPlan = fftwlib.realPlan(dataR.length, true, typeInt);
} else {
createdPlan = fftwlib.complexPlan(dataR.length, true, typeInt);
}
}
if (twoD) {
if (!inputComplex) {
createdPlan = fftwlib.realNdPlan(new int[]{mdataR.length}, true, typeInt);
} else {
createdPlan = fftwlib.complexNdPlan(new int[]{mdataR.length}, true, typeInt);
}
}
} else {
if (oneD) {
if (inputComplex) {
if (oneSide) {
int length = FFTWLibrary.mergeLength(dataR, dataI);
createdPlan = fftwlib.realPlan(length, false, typeInt);
} else {
createdPlan = fftwlib.complexPlan(dataR.length, false, typeInt);
}
} else {
createdPlan = fftwlib.complexPlan(dataR.length, false, typeInt);
}
}
if (twoD) {
if (!inputComplex) {
createdPlan = fftwlib.realNdPlan(new int[]{mdataR.length}, false, typeInt);
} else {
createdPlan = fftwlib.complexNdPlan(new int[]{mdataR.length}, false, typeInt);
}
}
}
}
ArrayList fourier;
if (oneD) {
real = dataR;
if (dataI != null) {
imag = dataI;
//complex transform
//fourier = fftwlib.complexTransform(real,imag);
if (createdPlan instanceof jfftw.real.Plan) {
System.out.println("reverse half_complex transform");
fourier = fftwlib.realTransform(FFTWLibrary.merge4(real, imag), direct);
//fourier = fftwlib.realTransform(FFTWLibrary.merge2(real,imag),direct);
} else {
// fourier = new ArrayList();
fourier = fftwlib.complexTransform(real, imag);
}
} else {
imag = new double[points];
if (createdPlan instanceof jfftw.real.Plan) {
System.out.println("fftw real transform");
fourier = fftwlib.realTransform(real, direct);
} else {
fourier = fftwlib.complexTransform(real, imag);
}
}
// println("Going into FFT_C.");
//fourier = fft.FFT_C( real, imag, direct, false );
real = (double[]) fourier.get(0);
imag = (double[]) fourier.get(1);
if (applyNorm) {
for (j = 0; j < real.length; j++) {
real[j] *= norm;
imag[j] *= norm;
}
}
} else if (twoD) {
mreal = mdataR;
if (mdataI != null) {
mimag = mdataI;
} else {
mimag = new double[points0][points];
}
int row, column;
for (row = 0; row < points0; row++) {
fourier = fft.FFT_C(mreal[row], mimag[row], direct, false);
mreal[row] = (double[]) fourier.get(0);
mimag[row] = (double[]) fourier.get(1);
}
if (applyNorm) {
norm *= norm0;
}
double[][] transposeReal = new double[points][points0];
double[][] transposeImag = new double[points][points0];
for (row = 0; row < points0; row++) {
for (column = 0; column < points; column++) {
transposeReal[column][row] = mreal[row][column];
transposeImag[column][row] = mimag[row][column];
}
}
for (column = 0; column < points; column++) {
fourier = fft.FFT_C(transposeReal[column], transposeImag[column], direct, false);
transposeReal[column] = (double[]) fourier.get(0);
transposeImag[column] = (double[]) fourier.get(1);
if (applyNorm) {
for (j = 0; j < points0; j++) {
transposeReal[column][j] *= norm;
transposeImag[column][j] *= norm;
}
}
}
for (row = 0; row < points0; row++) {
for (column = 0; column < points; column++) {
mreal[row][column] = transposeReal[column][row];
mimag[row][column] = transposeImag[column][row];
}
}
}
/* Debugging output
println("Exited from FFT_C with data real:");
for( kk = 0; kk < real.length; kk++) System.out.print(String.valueOf(real[kk]) + " " );
println(" ");
println("and imag:");
for( kk = 0; kk < imag.length; kk++) System.out.print(String.valueOf(imag[kk]) + " " );
println(" ");
*/
/*
* Begin output
*/
if ((style.equals("Direct")) || (style.equals("Direct/normalized(1/N)"))) {
if (oneD) {
//changes Rob 01/07/03
// System.out.println("It is direct");
//result = new ComplexSpectrum( true, false, real, imag, points, resolution, maxFreq );
System.out.println("oneSide : " + oneSide);
System.out.println("Points : " + points);
System.out.println("Points2 : " + real.length);
System.out.println("Resolution : " + resolution);
System.out.println("MaxFreq : " + maxFreq);
result = new ComplexSpectrum(!oneSide, false, real, imag, points, resolution, maxFreq);
//end Rob changes
} else if (twoD) {
double[] df = {resolution0, resolution};
result = new Spectrum2D(mreal, mimag, df);
}
} else if ((style.equals("Inverse")) || (style.equals("Inverse/normalized(1/N)"))) {
if (oneD) {
//changes Rob 01/07/03
//System.out.println("It is inverse");
if ((inputComplex) && (input instanceof Spectral && ((Spectral) input).isTwoSided())) {
result = new ComplexSampleSet(sf, real, imag);
} else {
System.out.println("***Output is Real*** : " + sf);
System.out.println(real.length);
result = new SampleSet(sf, real);
}
//end Rob changes
} else if (twoD) {
result = new MatrixType(new Triplet(points0, 0, 1. / sf0), new Triplet(points, 0, 1. / sf), mreal,
mimag);
}
} else if (style.equals("Automatic")) {
//System.out.println("It is automatic");
if (input instanceof Spectral) {
// System.out.println("Output route for input being Spectral:");
if (oneD) {
//change by Rob 01/07/03
//if ( !speed ) {
/*Craig change if ( !oneSide ) {
//end change Rob
if ( conjugateSymmetric ) {
System.out.println("conjugateSymmetric is true.");
result = new SampleSet( sf, real );
}
else {
System.out.println("conjugateSymmetric is false.");
if ( conjugateAntisymmetric ) {
System.out.println("conjugateAntisymmetric is true.");
FlatArray.initializeArray( real );
}
result = new ComplexSampleSet( sf, real, imag );
}
Craig change }*/
if ((inputComplex) && (((Spectral) input).isTwoSided())) {
/* else */
result = new ComplexSampleSet(sf, real, imag);
} else {
result = new SampleSet(sf, real);
} //end Craig change
} else if (twoD) {
result = new MatrixType(new Triplet(points0, 0, 1.0 / sf0), new Triplet(points, 0, 1. / sf), mreal,
mimag);
}
} else {
if (oneD) {
//change by Rob 01/07/03
//if ( !speed ) {
//Craig change if ( !oneSide ) {
//end change Rob
// System.out.println("Output route for input NOT being Spectral:");
/*Craigif ( conjugateSymmetric ) {
System.out.println("conjugateSymmetric is true.");
if ( oneSide ) real = FlatArray.convertToOneSided( real, points, false, true );
result = new Spectrum( !oneSide, false, real, points, resolution, maxFreq );
}
else {
System.out.println("conjugateSymmetric is false.");
if ( conjugateAntisymmetric ) {
System.out.println("conjugateAntisymmetric is true.");
if ( oneSide ) {
real = FlatArray.convertToOneSided( real, points, false, true );
imag = FlatArray.convertToOneSided( imag, points, false, true );
}
}
else {
System.out.println("Neither conjugateSymmetric not conjugateAntisymmetric is true.");
if ( oneSide ) {
real = FlatArray.convertToOneSided( real, points, false, true );
imag = FlatArray.convertToOneSided( imag, points, false, true );
}
}
}Craig*/
/* Debugging output
println("About to create ComplexSpectrum with data real:");
for( kk = 0; kk < real.length; kk++) System.out.print(String.valueOf(real[kk]) + " " );
println(" ");
println("and imag:");
for( kk = 0; kk < imag.length; kk++ ) System.out.print(String.valueOf(imag[kk]) + " " );
println(" ");
println("Number of points = " + String.valueOf(points));
*/
result = new ComplexSpectrum(!oneSide, false, real, imag, points, resolution, maxFreq);
//Craig change}
//Craig change else result = new ComplexSpectrum( true, false, real, imag, points, resolution, maxFreq );
} else if (twoD) {
double[] df = {resolution0, resolution};
result = new Spectrum2D(mreal, mimag, df);
}
}
}
//if ( inputSignal) result.addToLegend( acqTime );
output(result);
// System.out.println("It gets here");
// Wisdom.save(new File(wisdomFile));
}
/**
* Initialses information specific to FFT.
*/
public void init() {
super.init();
// setUseGUIBuilder(true);
setMinimumInputNodes(1);
setMaximumInputNodes(1);
setDefaultInputNodes(1);
setMinimumOutputNodes(1);
setDefaultOutputNodes(1);
// This is to ensure thfat we receive arrays containing double-precision numbers
// setRequireDoubleInputs(true);
// setCanProcessDoubleArrays(true);
fftwlib = new FFTWLibrary();
// try {
// Wisdom.load(new File(wisdomFile));
// }
// catch(IOException e) {}
String guilines = "";
guilines += "Operation of transform: $title style Choice Automatic Direct Direct/normalized(1/N) Inverse Inverse/normalized(1/N)\n";
guilines += "Plan - Estimate or Measure: $title planType Choice Estimate Measure\n";
guilines += "For 1D transform, apply this window to the data: $title WindowFunction Choice " + SigAnalWindows
.listOfWindows() + "\n";
guilines += "For 1D transform, pad input with zeros to a power of 2: $title padding Checkbox false\n";
setGUIBuilderV2Info(guilines);
}
/**
* return the GUI information for this unit. It uses the addGUILine function to add lines to the GUI interface. Such
* lines must in the specified GUI text format.
*/
// public void setGUIInformation() {
// addGUILine(
// "Operation of transform: $title style Choice Automatic Direct Direct/normalized(1/N) Inverse Inverse/normalized(1/N)");
// //addGUILine("For 1D transform, optimize for: $title opt Choice MaximumSpeed MinimumStorage");
// addGUILine("Plan - Estimate or Measure: $title planType Choice Estimate Measure");
// addGUILine("For 1D transform, apply this window to the data: $title WindowFunction Choice " + SigAnalWindows
// .listOfWindows());
// addGUILine("For 1D transform, pad input with zeros to a power of 2: $title padding Checkbox false");
// }
/**
* Called when the reset button is pressed within the MainTriana Window
*/
public void reset() {
super.reset();
}
/**
* Called when the stop button is pressed within the MainTriana Window
*/
public void stopping() {
super.stopping();
}
/**
* Called when the start button is pressed within the MainTriana Window
*/
// public void starting() {
// super.starting();
// }
//
// /**
// * Saves FFT's parameters.
// */
// public void saveParameters() {
// saveParameter("style", style);
// saveParameter("planType", planType);
// //saveParameter("opt", opt);
// saveParameter("WindowFunction", WindowFunction);
// saveParameter("padding", padding);
// }
/**
* Used to set each of FFT's parameters.
*/
public void parameterUpdate(String name, Object value) {
//updateGUIParameter(name, value);
if (name.equals("style")) {
style = (String) value;
}
if (name.equals("planType")) {
planType = (String) value;
}
/*if (name.equals("opt")) {
opt = value;
}*/
if (name.equals("WindowFunction")) {
WindowFunction = (String) value;
}
if (name.equals("padding")) {
padding = Str.strToBoolean((String) value);
}
}
/**
* @return a string containing the names of the types allowed to be input to FFT, each separated by a white space.
*/
// public String inputTypes() {
// return "MultipleAudio VectorType MatrixType";
// }
//
// /**
// * @return a string containing the names of the types output from FFT, each separated by a white space.
// */
// public String outputTypes() {
// return "ComplexSpectrum Spectrum ComplexSampleSet SampleSet Spectrum2D MatrixType";
// }
public String[] getInputTypes() {
return new String[]{"triana.types.audio.MultipleAudio", "triana.types.VectorType", "triana.types.MatrixType"};
}
public String[] getOutputTypes() {
return new String[]{"triana.types.ComplexSpectrum", "triana.types.Spectrum", "triana.types.ComplexSampleSet", "triana.types.SampleSet", "triana.types.Spectrum2D", "triana.types.MatrixType"};
}
/**
* This returns a <b>brief!</b> description of what the unit does. The text here is shown in a pop up window when
* the user puts the mouse over the unit icon for more than a second.
*/
public String getPopUpDescription() {
return "Performs a Fast Fourier Transform or its inverse using fftw.";
}
/**
* @return the location of the help file for this unit.
*/
public String getHelpFile() {
return "FFTW.html";
}
}