From 804f8aee184515373b3c0a202f483185e275f6bc Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez <dgonzale@pasteur.fr> Date: Mon, 23 Mar 2020 16:01:26 +0100 Subject: [PATCH] First code commit --- .classpath | 13 ++ .gitignore | 2 + .project | 17 ++ FFT.png | Bin 0 -> 32194 bytes FFT_icon.png | Bin 0 -> 6190 bytes export.jardesc | 19 ++ src/plugins/praveen/fft/AssignFunction2D.java | 8 + src/plugins/praveen/fft/AssignFunction3D.java | 8 + src/plugins/praveen/fft/AssignFunctions.java | 95 ++++++++ src/plugins/praveen/fft/ComplexFunctions.java | 37 +++ src/plugins/praveen/fft/FFT.java | 220 ++++++++++++++++++ 11 files changed, 419 insertions(+) create mode 100644 .classpath create mode 100644 .gitignore create mode 100644 .project create mode 100644 FFT.png create mode 100644 FFT_icon.png create mode 100644 export.jardesc create mode 100644 src/plugins/praveen/fft/AssignFunction2D.java create mode 100644 src/plugins/praveen/fft/AssignFunction3D.java create mode 100644 src/plugins/praveen/fft/AssignFunctions.java create mode 100644 src/plugins/praveen/fft/ComplexFunctions.java create mode 100644 src/plugins/praveen/fft/FFT.java diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..7219206 --- /dev/null +++ b/.classpath @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"> + <attributes> + <attribute name="module" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="var" path="ICY_JAR"/> + <classpathentry kind="var" path="ICY_PLUGINS/adufour/ezplug/EzPlug.jar"/> + <classpathentry kind="var" path="ICY_PLUGINS/adufour/blocks/Blocks.jar"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a1f4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/*.jar +/bin/ diff --git a/.project b/.project new file mode 100644 index 0000000..f69e79c --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>fft</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/FFT.png b/FFT.png new file mode 100644 index 0000000000000000000000000000000000000000..8f59f36b596c2521b5e3929b4ebab0aa69b49eeb GIT binary patch literal 32194 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 basqRH`XXyX3SL0TW(N#(OtdRCaZiMBT literal 0 HcmV?d00001 diff --git a/FFT_icon.png b/FFT_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5c94a39495b91786100b93192a3dacc4e41894c3 GIT binary patch literal 6190 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 Mp2_tx9W3Gh0YbV=s{jB1 literal 0 HcmV?d00001 diff --git a/export.jardesc b/export.jardesc new file mode 100644 index 0000000..0430195 --- /dev/null +++ b/export.jardesc @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?> +<jardesc> + <jar path="fft/fftPlugin.jar"/> + <options buildIfNeeded="true" compress="true" descriptionLocation="/fft/export.jardesc" exportErrors="false" exportWarnings="true" includeDirectoryEntries="true" overwrite="true" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/> + <storedRefactorings deprecationInfo="true" structuralOnly="false"/> + <selectedProjects/> + <manifest generateManifest="true" manifestLocation="/Jython/META-INF/MANIFEST.MF" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true"> + <sealing sealJar="false"> + <packagesToSeal/> + <packagesToUnSeal/> + </sealing> + </manifest> + <selectedElements exportClassFiles="true" exportJavaFiles="true" exportOutputFolder="false"> + <javaElement handleIdentifier="=fft/src"/> + <file path="/fft/export.jardesc"/> + <file path="/fft/.classpath"/> + <file path="/fft/.project"/> + </selectedElements> +</jardesc> diff --git a/src/plugins/praveen/fft/AssignFunction2D.java b/src/plugins/praveen/fft/AssignFunction2D.java new file mode 100644 index 0000000..2a49873 --- /dev/null +++ b/src/plugins/praveen/fft/AssignFunction2D.java @@ -0,0 +1,8 @@ +package plugins.praveen.fft; + +import cern.colt.function.tdouble.DoubleDoubleFunction; + +public interface AssignFunction2D { + void assign(double[] in, double[] out, int _w, int _h, + DoubleDoubleFunction Function); +} diff --git a/src/plugins/praveen/fft/AssignFunction3D.java b/src/plugins/praveen/fft/AssignFunction3D.java new file mode 100644 index 0000000..b5ab05d --- /dev/null +++ b/src/plugins/praveen/fft/AssignFunction3D.java @@ -0,0 +1,8 @@ +package plugins.praveen.fft; + +import cern.colt.function.tdouble.DoubleDoubleFunction; + +public interface AssignFunction3D { + void assign(double[] in, double[][][] out, int _w, int _h, int _z, int c, + DoubleDoubleFunction function); +} diff --git a/src/plugins/praveen/fft/AssignFunctions.java b/src/plugins/praveen/fft/AssignFunctions.java new file mode 100644 index 0000000..bd6a326 --- /dev/null +++ b/src/plugins/praveen/fft/AssignFunctions.java @@ -0,0 +1,95 @@ +package plugins.praveen.fft; + +import cern.colt.function.tdouble.DoubleDoubleFunction; + +public class AssignFunctions { + + //function that walks the 2D FFT from JTransforms and fills the sequence data array + //this is the version that does not swap the quadrants + public static class DirectAssign2D implements AssignFunction2D { + public void assign(double[] in, double[] out, int _w, int _h, + DoubleDoubleFunction function) { + for (int i = 0; i < in.length/2; i++) + { + double real = in[2*i]; + double imag = in[2*i + 1]; + + out[i] = function.apply(real, imag); + } + } + } + + //function that walks the 3D FFT from JTransforms and fills the sequence data array + //this is the version that does not swap the quadrants + public static class DirectAssign3D implements AssignFunction3D { + public void assign(double[] in, double[][][] out, int _w, int _h, int _z, int c, + DoubleDoubleFunction function) { + for(int z = 0; z < _z; z++) + { + for(int y = 0; y < _h; y++) + { + for(int x = 0; x < _w; x++) + { + double real = in[(x + (y * _w) + (z * _w * _h))*2 + 0]; + double imag = in[(x + (y * _w) + (z * _w * _h))*2 + 1]; + out[z][c][x + _w*y] = function.apply(real, imag); + } + } + } + } + } + + // function that walks the 2D FFT from JTransforms and fills the sequence data array + // this is the version that swaps the quadrants + public static class SwapAssign2D implements AssignFunction2D{ + public void assign(double[] in, double[] out, int _w, int _h, + DoubleDoubleFunction function) + { + int wc = (int) Math.ceil(_w/2); + int hc = (int) Math.ceil(_h/2); + + for(int y = 0; y < _h; y++) + { + for(int x = 0; x < _w; x++) + { + double real = in[(x + y*_w)*2 + 0]; + double imag = in[(x + y*_w)*2 + 1]; + + int sx = (x + wc)%_w; // swap quadrants ! + int sy = (y + hc)%_h; + + out[sx + _w*sy] = function.apply(real, imag); + } + } + } + } + + //function that walks the 3D FFT from JTransforms and fills the sequence data array + //this is the version that swaps the quadrants + public static class SwapAssign3D implements AssignFunction3D { + public void assign(double[] in, double[][][] out, int _w, int _h, int _z, int c, + DoubleDoubleFunction function) { + int wc = (int) Math.ceil(_w/2); + int hc = (int) Math.ceil(_h/2); + int zc = (int) Math.ceil(_z/2); + + for(int z = 0; z < _z; z++) + { + for(int y = 0; y < _h; y++) + { + for(int x = 0; x < _w; x++) + { + double real = in[(x + y * _w + z * _w * _h)*2 + 0]; + double imag = in[(x + y * _w + z * _w * _h)*2 + 1]; + + int sx = (x + wc)%_w; // swap quadrants ! + int sy = (y + hc)%_h; + int sz = (z + zc)%_z; + + out[sz][c][sx + _w*sy] = function.apply(real, imag); + } + } + } + } + } +} diff --git a/src/plugins/praveen/fft/ComplexFunctions.java b/src/plugins/praveen/fft/ComplexFunctions.java new file mode 100644 index 0000000..2e385e8 --- /dev/null +++ b/src/plugins/praveen/fft/ComplexFunctions.java @@ -0,0 +1,37 @@ +package plugins.praveen.fft; + +import cern.colt.function.tdouble.DoubleDoubleFunction; + +public class ComplexFunctions { + public static class Real implements DoubleDoubleFunction + { + public double apply(double real, double imag) + { + return real; + } + }; + + public static class Imag implements DoubleDoubleFunction + { + public double apply(double real, double imag) + { + return imag; + } + }; + + public static class Magnitude implements DoubleDoubleFunction + { + public double apply(double real, double imag) + { + return Math.sqrt(Math.pow(real, 2) + Math.pow(imag, 2)); + } + }; + + public static class Angle implements DoubleDoubleFunction + { + public double apply(double real, double imag) + { + return Math.atan2(imag, real); + } + }; +} diff --git a/src/plugins/praveen/fft/FFT.java b/src/plugins/praveen/fft/FFT.java new file mode 100644 index 0000000..68f5b1d --- /dev/null +++ b/src/plugins/praveen/fft/FFT.java @@ -0,0 +1,220 @@ +package plugins.praveen.fft; + +import cern.colt.function.tdouble.DoubleDoubleFunction; +import edu.emory.mathcs.jtransforms.fft.DoubleFFT_2D; +import edu.emory.mathcs.jtransforms.fft.DoubleFFT_3D; +import icy.image.IcyBufferedImage; +import icy.sequence.Sequence; +import icy.type.DataType; +import icy.type.collection.array.Array1DUtil; +import plugins.adufour.blocks.lang.Block; +import plugins.adufour.blocks.util.VarList; +import plugins.adufour.ezplug.EzPlug; +import plugins.adufour.ezplug.EzVarBoolean; +import plugins.adufour.ezplug.EzVarEnum; +import plugins.adufour.ezplug.EzVarSequence; +import plugins.adufour.vars.lang.VarSequence; + +public class FFT extends EzPlug implements Block { + + public static enum FFTDims { + FFT_2D("2D (xy)"), FFT_3D("3D (xyz)"); + private String stringValue; + FFTDims(String s) { stringValue = s; } + public String toString() { return stringValue; } + } + + public static enum FFTOutputType { + MAGNITUDE_PHASE("Magnitude/Phase Pair"), REAL_IMAG("Real/Imaginary Pair"); + private String stringValue; + FFTOutputType(String s) { stringValue = s; } + public String toString() { return stringValue; } + } + + EzVarSequence input = new EzVarSequence("Input"); + EzVarEnum<FFTDims> ndims = new EzVarEnum<FFTDims>("Type", FFTDims.values(), 0); + EzVarEnum<FFTOutputType> outputType = new EzVarEnum<FFTOutputType>("Output as", FFTOutputType.values(), 0); + EzVarBoolean swap = new EzVarBoolean("Swap Quadrants?", false); + + VarSequence fSequenceVar = new VarSequence("FFT sequence", null); + + @Override + protected void initialize() { + super.addEzComponent(input); + super.addEzComponent(ndims); + super.addEzComponent(outputType); + super.addEzComponent(swap); + super.setTimeDisplay(true); + } + + // declare ourself to Blocks + @Override + public void declareInput(VarList inputMap) { + inputMap.add(input.name, input.getVariable()); + inputMap.add(ndims.name, ndims.getVariable()); + inputMap.add(outputType.name, outputType.getVariable()); + inputMap.add(swap.name, swap.getVariable()); + } + + // declare ourself to Blocks + @Override + public void declareOutput(VarList outputMap) { + outputMap.add(fSequenceVar.getName(), fSequenceVar); + } + + @Override + protected void execute() { + Sequence sequence = input.getValue(); + Sequence fSequence = null; + + if(ndims.getValue()==FFTDims.FFT_2D) + { + fSequence = FFT_2D(sequence, swap.getValue(), outputType.getValue()); + } + else + { + if (sequence.getSizeZ() >= 2) + { + fSequence = FFT_3D(sequence, swap.getValue(), outputType.getValue()); + } + else + { + System.err.println("Sequence depth is 1, so computing 2D FFT instead of 3D."); + fSequence = FFT_2D(sequence, swap.getValue(), outputType.getValue()); + } + } + + if (!isHeadLess()) { + addSequence(fSequence); + } + + fSequenceVar.setValue(fSequence); + } + + private Sequence FFT_3D(Sequence sequence, boolean swap, FFTOutputType outputType) { + int _w = sequence.getSizeX(); + int _h = sequence.getSizeY(); + int _z = sequence.getSizeZ(); + + final DoubleFFT_3D fft = new DoubleFFT_3D(_z, _h, _w); + Sequence fSequence = new Sequence(); + fSequence.setName("Fourier Transform 3D"); + + // allocate the output sequence + for(int k = 0; k < _z; k++) + { + IcyBufferedImage fImage = new IcyBufferedImage(_w, _h, 2, DataType.DOUBLE); + fSequence.setImage(0, k, fImage); + } + + double[] fArray = new double[_w*_h*_z*2]; + // copy the data in fArray, with proper structure + for(int k = 0; k < _z; k++) + { + Array1DUtil.arrayToDoubleArray(sequence.getDataXY(0, k, 0), 0, fArray, k*_w*_h, _w*_h, sequence.isSignedDataType()); + } + + fft.realForwardFull(fArray); + + // direct reference to 3D byte array data [Z][C][XY] for specified t + double[][][] resultData = fSequence.getDataXYCZAsDouble(0); + + DoubleDoubleFunction channel0ApplyFunction = null; + DoubleDoubleFunction channel1ApplyFunction = null; + if(outputType == FFTOutputType.MAGNITUDE_PHASE) + { + channel0ApplyFunction = new ComplexFunctions.Magnitude(); + channel1ApplyFunction = new ComplexFunctions.Angle(); + fSequence.setChannelName(0, "Magnitude"); + fSequence.setChannelName(1, "Phase"); + } + else + { + channel0ApplyFunction = new ComplexFunctions.Real(); + channel1ApplyFunction = new ComplexFunctions.Imag(); + fSequence.setChannelName(0, "Real"); + fSequence.setChannelName(1, "Imaginary"); + } + + AssignFunction3D assignFunction = null; + if(!swap) // No Quadrant swapping. Leave as it is. + { + assignFunction = new AssignFunctions.DirectAssign3D(); + } + else + { + assignFunction = new AssignFunctions.SwapAssign3D(); // Swap Quadrants + } + + assignFunction.assign(fArray, resultData, _w, _h, _z, 0, channel0ApplyFunction); + assignFunction.assign(fArray, resultData, _w, _h, _z, 1, channel1ApplyFunction); + + fSequence.dataChanged(); + + return fSequence; + } + + private Sequence FFT_2D(Sequence sequence, boolean swap, FFTOutputType outputType) + { + Sequence fSequence = new Sequence(); + fSequence.setName("Fourier Transform 2D"); + int _w = sequence.getSizeX(); + int _h = sequence.getSizeY(); + int _z = sequence.getSizeZ(); + + final DoubleFFT_2D fft = new DoubleFFT_2D(_h, _w); + + DoubleDoubleFunction channel0Function = null; + DoubleDoubleFunction channel1Function = null; + if(outputType == FFTOutputType.MAGNITUDE_PHASE) + { + channel0Function = new ComplexFunctions.Magnitude(); + channel1Function = new ComplexFunctions.Angle(); + fSequence.setChannelName(0, "Magnitude"); + fSequence.setChannelName(1, "Phase"); + } + else // Real/Imaginary Pair + { + channel0Function = new ComplexFunctions.Real(); + channel1Function = new ComplexFunctions.Imag(); + fSequence.setChannelName(0, "Real"); + fSequence.setChannelName(1, "Imaginary"); + } + + AssignFunction2D assignFunction = null; + if(!swap) //No Quadrant swapping + { + assignFunction = new AssignFunctions.DirectAssign2D(); + } + else //Swap quadrants + { + assignFunction = new AssignFunctions.SwapAssign2D(); + } + + for(int k = 0; k < _z; k++) + { + double[] fArray = new double[_w*_h*2]; + Array1DUtil.arrayToDoubleArray(sequence.getDataXY(0, k, 0), 0, fArray, 0, _w*_h, sequence.isSignedDataType()); + + // Computes 2D forward DFT of real data leaving the result in fArray + // Because the result is stored in fArray, fArray must be of size rows*2*columns, + // with only the first rows*columns elements filled with real data. + fft.realForwardFull(fArray); + + IcyBufferedImage resultArray = new IcyBufferedImage(_w, _h, 2, DataType.DOUBLE); + double[][] resultData = resultArray.getDataXYCAsDouble(); + + assignFunction.assign(fArray, resultData[0], _w, _h, channel0Function); + assignFunction.assign(fArray, resultData[1], _w, _h, channel1Function); + + resultArray.dataChanged(); + fSequence.setImage(0, k, resultArray); + } + + return fSequence; + } + + @Override + public void clean() { + } +} \ No newline at end of file -- GitLab