From f3615f994eb9deeabf7900ff1d0f850584c678ef Mon Sep 17 00:00:00 2001
From: Daniel Gonzalez <dgonzale@pasteur.fr>
Date: Mon, 23 Mar 2020 17:59:32 +0100
Subject: [PATCH] Separated logic from plugin behavior

- Created FFTCalculator to expose statically FFT calculation from code
instead of creating a new plugin instance
---
 src/plugins/praveen/fft/FFT.java           | 151 +-----------------
 src/plugins/praveen/fft/FFTCalculator.java | 172 +++++++++++++++++++++
 2 files changed, 178 insertions(+), 145 deletions(-)
 create mode 100644 src/plugins/praveen/fft/FFTCalculator.java

diff --git a/src/plugins/praveen/fft/FFT.java b/src/plugins/praveen/fft/FFT.java
index 68f5b1d..384e94d 100644
--- a/src/plugins/praveen/fft/FFT.java
+++ b/src/plugins/praveen/fft/FFT.java
@@ -1,12 +1,6 @@
 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;
@@ -14,23 +8,11 @@ import plugins.adufour.ezplug.EzVarBoolean;
 import plugins.adufour.ezplug.EzVarEnum;
 import plugins.adufour.ezplug.EzVarSequence;
 import plugins.adufour.vars.lang.VarSequence;
+import plugins.praveen.fft.FFTCalculator.FFTDims;
+import plugins.praveen.fft.FFTCalculator.FFTOutputType;
 
 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);
@@ -69,18 +51,18 @@ public class FFT extends EzPlug implements Block {
 
 		if(ndims.getValue()==FFTDims.FFT_2D)
 		{		
-			fSequence = FFT_2D(sequence, swap.getValue(), outputType.getValue());
+			fSequence = FFTCalculator.FFT_2D(sequence, swap.getValue(), outputType.getValue());
 		}
 		else
 		{
 			if (sequence.getSizeZ() >= 2)
 			{
-				fSequence = FFT_3D(sequence, swap.getValue(), outputType.getValue());
+				fSequence = FFTCalculator.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());
+				fSequence = FFTCalculator.FFT_2D(sequence, swap.getValue(), outputType.getValue());
 			}
 		}
 		
@@ -91,128 +73,7 @@ public class FFT extends EzPlug implements Block {
 		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() {
diff --git a/src/plugins/praveen/fft/FFTCalculator.java b/src/plugins/praveen/fft/FFTCalculator.java
new file mode 100644
index 0000000..548d697
--- /dev/null
+++ b/src/plugins/praveen/fft/FFTCalculator.java
@@ -0,0 +1,172 @@
+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;
+
+public class FFTCalculator
+{
+    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;
+        }
+    }
+
+    public static 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;
+    }
+
+    public static 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;
+    }
+}
-- 
GitLab