Page MenuHomec4science

No OneTemporary

File Metadata

Created
Wed, Oct 2, 03:29
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/DeconvolutionLab2/DeconvolutionLab2.config b/DeconvolutionLab2/DeconvolutionLab2.config
index 4b8bc9e..2735ed7 100644
--- a/DeconvolutionLab2/DeconvolutionLab2.config
+++ b/DeconvolutionLab2/DeconvolutionLab2.config
@@ -1,72 +1,63 @@
#DeconvolutionLab2 [Beta 2]
#DeconvolutionLab2 [Beta 2]
-#Wed Feb 22 13:06:29 WET 2017
+#Thu Mar 02 18:44:42 CET 2017
Algorithm.I.gaussian.mean=0.0
Algorithm.I.gaussian.stdev=1.0
Algorithm.I.iterations=10
Algorithm.I.poisson=0.0
Algorithm.I.reg=0.1
Algorithm.I.scale=3
Algorithm.I.step=1.0
Algorithm.I.wavelets=Haar
-Algorithm.algorithm=Regularized Inverse Filter [RIF | LRIF]
-Border.apoxy=Uniform
+Algorithm.algorithm=Landweber [LW |\u00A0LLS]
+Border.apoxy=Hamming
Border.apoz=Uniform
-Border.extxy=0
+Border.extxy=1
Border.extz=0
Border.padxy=None
Border.padz=None
Computation.dim=XYZ
Computation.epsilon=1E-6
-Computation.fft=Academic
+Computation.fft=Fastest
Computation.normalization=1
Controller.constraint.enable=false
Controller.constraint.value=no
Controller.itmax.enable=true
Controller.reference.enable=false
Controller.reference.value=
Controller.residu.enable=false
Controller.residu.value=0.01
Controller.time.enable=false
Controller.time.value=3600
-DeconvolutionLab.DeconvolutionDialog.location.h=400
-DeconvolutionLab.DeconvolutionDialog.location.w=600
-DeconvolutionLab.DeconvolutionDialog.location.x=711
-DeconvolutionLab.DeconvolutionDialog.location.y=129
-DeconvolutionLab.MainDialog.location.h=381
-DeconvolutionLab.MainDialog.location.w=544
-DeconvolutionLab.MainDialog.location.x=35
-DeconvolutionLab.MainDialog.location.y=165
-Image.image.row0=Pos1-1.tif;file;/Users/dsage/Desktop/Maria Azevedo/Pos1-1.tif;
-Image.image.row1=DoG;synthetic;DoG 100.0 0.0 3.0 35.0 size 128 128 32 ;\u232B
-Image.image.row2=Cube;synthetic;Cube 100.0 0.0 10.0 1.0 size 128 128 32 ;\u232B
-Image.image.row3=IMG_0517.JPG;file;/Users/dsage/Desktop/IMG_0517.JPG;null
+DeconvolutionLab.MainDialog.location.h=597
+DeconvolutionLab.MainDialog.location.w=500
+DeconvolutionLab.MainDialog.location.x=250
+DeconvolutionLab.MainDialog.location.y=45
+Image.image.row0=Cell7.tif;file;/Users/dsage/Desktop/Maria Azevedo/Cell7.tif;null
+Image.image.row1=Cube;synthetic;Cube 100.0 0.0 10.0 1.0 size 128 128 32 ;\u232B
+Image.image.row2=DoG;synthetic;DoG 100.0 0.0 3.0 35.0 size 128 128 32 ;\u232B
+Image.image.row3=Cube;synthetic;Cube 100.0 0.0 10.0 1.0 size 128 128 32 ;\u232B
Image.image.row4=RandomLines;synthetic;RandomLines 100.0 0.0 300.0 size 512 512 32 ;\u232B
Image.image.row5=Cube;synthetic;Cube 100.0 0.0 10.0 1.0 size 128 128 32 ;\u232B
Image.image.row6=Applications;platform;Applications;\u232B
Image.image.row7=Applications;directory;/users/dsage/Applications;\u232B
Image.image.row8=Cube;synthetic;Cube 100.0 0.0 10.0 1.0 size 128 128 32 ;\u232B
Image.image.row9=lib;directory;/Users/dsage/git/deconvolution/DeconvolutionLab2/lib;\u232B
-Image.image.selected=Pos1-1.tif;file;/Users/dsage/Desktop/Maria Azevedo/Pos1-1.tif;
+Image.image.selected=Cell7.tif;file;/Users/dsage/Desktop/Maria Azevedo/Cell7.tif;null
Language.headless=Run (Headless)
Language.job=Job
Language.language=Command line
-Output.output.row0=stats;ST1;;;;\u2713;\u2713;\u232B
-Output.output.row1=ortho;OR1;;;;\u2713;\u2713;\u232B
-Output.output.selected=stats;ST1;;;;\u2713;\u2713;\u232B
+Output.output.row0=ortho;OR2;;;;\u2713;\u2713;\u232B
+Output.output.selected=ortho;OR2;;;;\u2713;\u2713;\u232B
PSF.psf.row0=AirySimulated;synthetic;AirySimulated 100.0 0.0 1.0 size 128 128 32 ;null
PSF.psf.row1=Chrome Apps.localized;directory;/users/dsage/applications/Chrome Apps.localized;\u232B
PSF.psf.row2=FI1.tif;file;/Users/dsage/git/deconvolution/DeconvolutionLab2/FI1.tif;\u232B
PSF.psf.selected=AirySimulated;synthetic;AirySimulated 100.0 0.0 1.0 size 128 128 32 ;null
Running.Directory=/Users/dsage/Applications
Running.Display=no
-Running.Monitor=no
+Running.Monitor=console table
Running.Multithreading=yes
Running.Path=specify
-Running.Stats=show save
+Running.Stats=show
Running.System=no
Running.Verbose=log
-System.Frame.location.h=80
-System.Frame.location.w=637
-System.Frame.location.x=30
-System.Frame.location.y=564
diff --git a/DeconvolutionLab2/src/DL2.java b/DeconvolutionLab2/src/DL2.java
index 700727b..8cd3758 100644
--- a/DeconvolutionLab2/src/DL2.java
+++ b/DeconvolutionLab2/src/DL2.java
@@ -1,237 +1,252 @@
-import java.io.File;
-
-import deconvolution.Deconvolution;
-import deconvolutionlab.Imaging;
-import deconvolutionlab.Lab;
-import deconvolutionlab.LabDialog;
-import ij.ImagePlus;
-import ij.WindowManager;
-import matlab.Converter;
-import signal.RealSignal;
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.io.File;
+
+import deconvolution.Deconvolution;
+import deconvolutionlab.Imaging;
+import deconvolutionlab.Lab;
+import deconvolutionlab.LabDialog;
+import ij.ImagePlus;
+import ij.WindowManager;
+import matlab.Converter;
+import signal.RealSignal;
+
/**
- * This class is dedicated to the Matlab interface for DeconvolutionLab2
+ * This class allows Matlab interface for DeconvolutionLab2
+ *
+ * A Matlab 3D variable in converted to a RealSignal and vice-versa.
+ *
* @author sage
*
*/
public class DL2 {
public static void lab() {
Lab.init(Imaging.Platform.MATLAB, System.getProperty("user.dir") + File.separator + "DeconvolutionLab2.config");
LabDialog dlg = new LabDialog();
Lab.setVisible(dlg, false);
}
public static void run(String command) {
new Deconvolution("Matlab", command).deconvolve();
}
public static void launch(String command) {
new Deconvolution("Matlab", command).launch();
}
public static Object get(String image) {
ImagePlus imp = WindowManager.getCurrentImage();
if (imp != null)
return Converter.get(imp);
return null;
}
public static Object run(Object arrayImage, Object arrayPSF, String algo) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -image platform input -psf platform psf -algorithm " + algo;
Deconvolution d = new Deconvolution("Matlab", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
public static void help() {
Lab.help();
}
public static void clear() {
int ids[] = WindowManager.getIDList();
for(int id : ids) {
ImagePlus imp = WindowManager.getImage(id);
if (imp != null)
imp.close();
}
}
public static Object DIV(Object arrayImage, Object arrayPSF) {
return DIV(arrayImage, arrayPSF, "");
}
public static Object DIV(Object arrayImage, Object arrayPSF, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -algorithm DIV " + options;
Deconvolution d = new Deconvolution("Matlab DIV", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
public static Object CONV(Object arrayImage, Object arrayPSF) {
return CONV(arrayImage, arrayPSF, "");
}
public static Object CONV(Object arrayImage, Object arrayPSF, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -algorithm CONV " + options;
Deconvolution d = new Deconvolution("Matlab CONV", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
public static Object NIF(Object arrayImage, Object arrayPSF) {
return NIF(arrayImage, arrayPSF, "");
}
public static Object NIF(Object arrayImage, Object arrayPSF, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -algorithm NIF " + options;
Deconvolution d = new Deconvolution("Matlab NIF", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
public static Object TRIF(Object arrayImage, Object arrayPSF, double regularizationFactor) {
return TRIF(arrayImage, arrayPSF, regularizationFactor, "");
}
public static Object TRIF(Object arrayImage, Object arrayPSF, double regularizationFactor, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -algorithm TRIF " + regularizationFactor + " " + options;
Deconvolution d = new Deconvolution("Matlab TRIF", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
public static Object RIF(Object arrayImage, Object arrayPSF, double regularizationFactor) {
return RIF(arrayImage, arrayPSF, regularizationFactor, "");
}
public static Object RIF(Object arrayImage, Object arrayPSF, double regularizationFactor, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -algorithm RIF " + regularizationFactor + " " + options;
Deconvolution d = new Deconvolution("Matlab RIF", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
public static Object RL(Object arrayImage, Object arrayPSF, double itmax) {
return RL(arrayImage, arrayPSF, itmax, "");
}
public static Object RL(Object arrayImage, Object arrayPSF, double itmax, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -algorithm RL " + itmax + " " + options;
Deconvolution d = new Deconvolution("Matlab RL", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
public static Object RLTV(Object arrayImage, Object arrayPSF, double itmax, double regularizationFactor) {
return RLTV(arrayImage, arrayPSF, itmax, regularizationFactor, "");
}
public static Object RLTV(Object arrayImage, Object arrayPSF, double itmax, double regularizationFactor, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -algorithm RLTV " + itmax + " " + regularizationFactor + " " + options;
Deconvolution d = new Deconvolution("Matlab RLTV", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
public static Object LW(Object arrayImage, Object arrayPSF, double itmax, double gamma) {
return LW(arrayImage, arrayPSF, itmax, gamma, "");
}
public static Object LW(Object arrayImage, Object arrayPSF, double itmax, double gamma, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -algorithm LW " + itmax + " " + gamma + " " + options;
Deconvolution d = new Deconvolution("Matlab LW", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
public static Object NNLS(Object arrayImage, Object arrayPSF, double itmax, double gamma) {
- return LW(arrayImage, arrayPSF, itmax, gamma, "");
+ return NNLS(arrayImage, arrayPSF, itmax, gamma, "");
}
public static Object NNLS(Object arrayImage, Object arrayPSF, double itmax, double gamma, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
- String command = " -algorithm LW+ " + itmax + " " + options;
+ String command = " -algorithm NNLS " + itmax + " " + options;
Deconvolution d = new Deconvolution("Matlab NNLS", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
+ public static Object BVLS(Object arrayImage, Object arrayPSF, double itmax, double gamma) {
+ return BVLS(arrayImage, arrayPSF, itmax, gamma, "");
+ }
+
+ public static Object BVLS(Object arrayImage, Object arrayPSF, double itmax, double gamma, String options) {
+ RealSignal image = Converter.createRealSignal(arrayImage);
+ RealSignal psf = Converter.createRealSignal(arrayPSF);
+ String command = " -algorithm BVLS " + itmax + " " + options;
+ Deconvolution d = new Deconvolution("Matlab BVLS", command);
+ RealSignal result = d.deconvolve(image, psf);
+ return Converter.createObject(result);
+ }
+
public static Object TM(Object arrayImage, Object arrayPSF, double itmax, double gamma, double lambda) {
return TM(arrayImage, arrayPSF, itmax, gamma, lambda, "");
}
public static Object TM(Object arrayImage, Object arrayPSF, double itmax, double gamma, double lambda, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -algorithm TM " + itmax + " " + gamma + " " + lambda + " " + options;
Deconvolution d = new Deconvolution("Matlab TM", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
public static Object ICTM(Object arrayImage, Object arrayPSF, double itmax, double gamma, double lambda) {
return ICTM(arrayImage, arrayPSF, itmax, gamma, lambda, "");
}
public static Object ICTM(Object arrayImage, Object arrayPSF, double itmax, double gamma, double lambda, String options) {
RealSignal image = Converter.createRealSignal(arrayImage);
RealSignal psf = Converter.createRealSignal(arrayPSF);
String command = " -algorithm ICTM " + itmax + " " + gamma + " " + lambda + " " + options;
Deconvolution d = new Deconvolution("Matlab ICTM", command);
RealSignal result = d.deconvolve(image, psf);
return Converter.createObject(result);
}
-
-
}
diff --git a/DeconvolutionLab2/src/DeconvolutionLab2_Lab.java b/DeconvolutionLab2/src/DeconvolutionLab2_Lab.java
index 62e260b..0b1b749 100644
--- a/DeconvolutionLab2/src/DeconvolutionLab2_Lab.java
+++ b/DeconvolutionLab2/src/DeconvolutionLab2_Lab.java
@@ -1,49 +1,48 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
import java.io.File;
-import deconvolutionlab.Config;
import deconvolutionlab.Imaging;
import deconvolutionlab.Lab;
import deconvolutionlab.LabDialog;
import ij.IJ;
import ij.plugin.PlugIn;
public class DeconvolutionLab2_Lab implements PlugIn {
@Override
public void run(String arg) {
Lab.init(Imaging.Platform.IMAGEJ, IJ.getDirectory("plugins") + File.separator + "DeconvolutionLab2.config");
LabDialog dlg = new LabDialog();
Lab.setVisible(dlg, false);
}
}
diff --git a/DeconvolutionLab2/src/DeconvolutionLab2_Run.java b/DeconvolutionLab2/src/DeconvolutionLab2_Run.java
index bd023f7..431fca0 100644
--- a/DeconvolutionLab2/src/DeconvolutionLab2_Run.java
+++ b/DeconvolutionLab2/src/DeconvolutionLab2_Run.java
@@ -1,55 +1,54 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
import java.io.File;
import deconvolution.Deconvolution;
-import deconvolutionlab.Config;
import deconvolutionlab.Imaging;
import deconvolutionlab.Lab;
import deconvolutionlab.LabDialog;
import ij.IJ;
import ij.Macro;
import ij.plugin.PlugIn;
public class DeconvolutionLab2_Run implements PlugIn {
@Override
public void run(String arg) {
Lab.init(Imaging.Platform.IMAGEJ, IJ.getDirectory("plugins") + File.separator + "DeconvolutionLab2.config");
if (Macro.getOptions() == null) {
LabDialog dlg = new LabDialog();
Lab.setVisible(dlg, false);
}
else
new Deconvolution("Run", Macro.getOptions()).deconvolve();
}
}
diff --git a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Bigradient.java b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Bigradient.java
index 9a0a65d..198952e 100644
--- a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Bigradient.java
+++ b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Bigradient.java
@@ -1,92 +1,123 @@
+/*
+ * DeconvolutionLab2
+ *
+ * Conditions of use: You are free to use this software for research or
+ * educational purposes. In addition, we expect you to include adequate
+ * citations and acknowledgments whenever you present or publish results that
+ * are based on it.
+ *
+ * Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
+ * Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
+ * R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
+ */
+
+/*
+ * Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
+ *
+ * This file is part of DeconvolutionLab2 (DL2).
+ *
+ * DL2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * DL2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
package course;
+
import java.io.File;
import javax.swing.filechooser.FileSystemView;
import deconvolution.Deconvolution;
import ij.plugin.PlugIn;
-
public class DeconvolutionLab2_Course_Bigradient implements PlugIn {
private String desktop = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + "Desktop";
private String root = desktop + File.separator + "Deconvolution" + File.separator;
private String res = root + "results" + File.separator + "bigradient" + File.separator;
private String data = root + "data" + File.separator + "bigradient" + File.separator;
public DeconvolutionLab2_Course_Bigradient() {
new File(res).mkdir();
System.setProperty("user.dir", res);
new File(res + "TRIF").mkdir();
new File(res + "RIF").mkdir();
new File(res + "LW").mkdir();
new File(res + "LW-ITER").mkdir();
new File(res + "LW+").mkdir();
new File(res + "LW+-ITER").mkdir();
new File(res + "RL").mkdir();
new File(res + "RL-ITER").mkdir();
new File(res + "RLTV").mkdir();
new File(res + "RLTV-ITER").mkdir();
new File(res + "FISTA").mkdir();
new File(res + "FISTA-ITER").mkdir();
String psf = " -psf file " + data + "psf.tif -reference " + data + "ref.tif ";
String noisy = " -image file convnoise.tif";
new Deconvolution("run", "-image file " + data + "ref.tif" + psf + " -algorithm SIM 0 1 1 -out stack convnoise -out stack conbnoise_8 rescaled byte noshow").deconvolve();
new Deconvolution("run", noisy + psf + " -algorithm NIF -out stack NIF").deconvolve();
new Deconvolution("run", noisy + psf + " -algorithm DIV -out stack DIV").deconvolve();
for(int i=0; i<=3; i++) {
double p = Math.pow(5, i-10);
String name = "RIF" + String.format("%02d", i);
new Deconvolution("run", noisy + psf + " -algorithm RIF " + p + out("RIF" + File.separator, name)).deconvolve();
}
for(int i=0; i<=3; i++) {
double p = Math.pow(5, i-10);
String name = "TRIF" + String.format("%02d", i);
new Deconvolution("run", noisy + psf + " -algorithm TRIF " + p + out("TRIF" + File.separator, name)).deconvolve();
}
String lw = " -algorithm LW 20 1 -out mip @2 LW-ITER/I -out stats @1 LW nosave";
new Deconvolution("run", noisy + psf + lw).deconvolve();
new File(res + "LW-ITER/I.tif").delete();
String lwp = " -algorithm LW+ 20 1 -out mip @2 LW+-ITER/I -out stats @1 LW+ nosave";
new Deconvolution("run", noisy + psf + lwp).deconvolve();
new File(res + "LW+-ITER/I.tif").delete();
String rl = " -algorithm RL 20 -out mip @2 RL-ITER/I -out stats @1 RL nosave";
new Deconvolution("run", noisy + psf + rl).deconvolve();
new File(res + "RL-ITER/I.tif").delete();
String rltv = " -algorithm RLTV 20 10 -out mip @2 RLTV-ITER/I -out stats @1 RLTV nosave";
new Deconvolution("run", noisy + psf + rltv).deconvolve();
new File(res + "RLTV-ITER/I.tif").delete();
String fista = " -algorithm FISTA 20 1 1 Spline3 3 -mip @2 FISTA-ITER/I -out stats @1 FISTA nosave";
new Deconvolution("run", noisy + psf + fista).deconvolve();
new File(res + "FISTA-ITER/I.tif").delete();
}
private static String out(String root, String name) {
return "out stats " + root + name +
" -out stack " + root + name + "_32 -out stack " + root + name + "_8 rescaled byte noshow";
}
public static void main(String arg[]) {
new DeconvolutionLab2_Course_Bigradient();
}
@Override
public void run(String arg) {
new DeconvolutionLab2_Course_Bigradient();
}
}
diff --git a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Border.java b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Border.java
index 8522104..e82fddb 100644
--- a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Border.java
+++ b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Border.java
@@ -1,108 +1,138 @@
+/*
+ * DeconvolutionLab2
+ *
+ * Conditions of use: You are free to use this software for research or
+ * educational purposes. In addition, we expect you to include adequate
+ * citations and acknowledgments whenever you present or publish results that
+ * are based on it.
+ *
+ * Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
+ * Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
+ * R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
+ */
+
+/*
+ * Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
+ *
+ * This file is part of DeconvolutionLab2 (DL2).
+ *
+ * DL2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * DL2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
package course;
-// Course Version 2
import ij.plugin.PlugIn;
import java.io.File;
import javax.swing.filechooser.FileSystemView;
import signal.RealSignal;
import signal.factory.Cube;
import signal.factory.Gaussian;
import deconvolution.Deconvolution;
import deconvolutionlab.Lab;
import deconvolutionlab.monitor.Monitors;
public class DeconvolutionLab2_Course_Border implements PlugIn {
private String desktop = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + "Desktop";
private String root = desktop + File.separator + "Deconvolution" + File.separator;
private String res = root + "results" + File.separator + "border" + File.separator;
public DeconvolutionLab2_Course_Border() {
Monitors monitors = Monitors.createDefaultMonitor();
new File(res).mkdir();
System.setProperty("user.dir", res);
int nx = 200;
int ny = 200;
int nz = 40;
RealSignal im = new Cube(22, .1).intensity(0, 100).center(0.25, 0.00, 0.05).generate(nx, ny, nz);
RealSignal i0 = new Cube(22, .1).intensity(0, 100).center(0.25, 0.05, 0.05).generate(nx, ny, nz);
RealSignal i1 = new Cube(22, .1).intensity(0, 100).center(0.25, 0.10, 0.05).generate(nx, ny, nz);
RealSignal i2 = new Cube(22, .1).intensity(0, 100).center(0.25, 0.15, 0.05).generate(nx, ny, nz);
im.max(i1.max(i2).max(i0));
RealSignal g = new Gaussian(10, 10, 10).intensity(0, 101).generate(nx, ny, nz);
Lab.save(monitors, im, res + "ref.tif");
Lab.save(monitors, g, res + "psf.tif");
String psf = " -psf file " + "psf.tif";
String ref = " -image file " + "ref.tif";
String cst = " -image synthetic constant 250 0 size 200 200 40";
String algo = " -algorithm CONV -out ortho REFo (64,32,16)";
new Deconvolution("run", ref + " -psf synthetic impulse " + algo).deconvolve();
algo = " -algorithm CONV -stack CONV -out ortho CONVo rescaled byte (64,32,16) -out mip CONVp rescaled byte";
new Deconvolution("run", ref + psf + algo).deconvolve();
algo = " -algorithm CONV -pad NO NO 200 200 -out ortho PADo200 rescaled byte (64,32,16) -out mip PADp200 rescaled byte";
new Deconvolution("run", ref + psf + algo).deconvolve();
algo = " -algorithm CONV -pad NO NO 100 100 -out ortho PADo100 rescaled byte (64,32,16) -out mip PADp100 rescaled byte";
new Deconvolution("run", ref + psf + algo).deconvolve();
algo = " -algorithm CONV -pad NO NO 40 40 -out ortho PADo40 rescaled byte (64,32,16) -out mip PADp40 rescaled byte";
new Deconvolution("run", ref + psf + algo).deconvolve();
algo = " -algorithm CONV -pad NO NO 20 20 -out ortho PADo20 rescaled byte (64,32,16) -out mip PADp20 rescaled byte";
new Deconvolution("run", ref + psf + algo).deconvolve();
algo = " -algorithm CONV -pad NO NO 10 10 -out ortho PADo10 rescaled byte (64,32,16) -out mip PADp10 rescaled byte";
new Deconvolution("run", ref + psf + algo).deconvolve();
algo = " -algorithm CONV -pad NO NO 5 5 -out ortho PADo2 rescaled byte (64,32,16) -out mip PADp2 rescaled byte";
new Deconvolution("run", ref + psf + algo).deconvolve();
algo = " -algorithm CONV -apo HANN HANN -out ortho HANNo rescaled byte (64,32,16) -out mip HANNp rescaled byte";
new Deconvolution("run", ref + psf + algo).deconvolve();
algo = " -algorithm CONV -apo TUKEY TUKEY -out ortho TUKEYo rescaled byte (64,32,16) -out mip TUKEYp rescaled byte";
new Deconvolution("run", ref + psf + algo).deconvolve();
algo = " -algorithm CONV --pad NO NO 8 8 apo HANN HANN -out ortho PAD8_HANNo rescaled byte (64,32,16) -out mip PAD8_HANNp rescaled byte";
new Deconvolution("run", ref + psf + algo).deconvolve();
algo = " -algorithm CONV -apo HANN HANN -out ortho HANN_CSTo rescaled byte -out mip HANN_CSTp rescaled byte";
new Deconvolution("run", cst + psf + algo).deconvolve();
algo = " -algorithm CONV -apo TUKEY TUKEY -out ortho TUKEY_CSTo rescaled byte -out mip TUKEY_CSTp rescaled byte";
new Deconvolution("run", cst + psf + algo).deconvolve();
algo = " -algorithm CONV -pad E2 E2 -out ortho PADpPower2FFTW rescaled byte (64,32,16) -out mip PADpPower2FFTW rescaled byte";
new Deconvolution("run", cst + psf + algo + " -fft FFTW2 ").deconvolve();
new Deconvolution("run", cst + psf + algo + " -fft Academic ").deconvolve();
new Deconvolution("run", cst + psf + algo + " -fft JTransforms ").deconvolve();
}
public static void main(String arg[]) {
new DeconvolutionLab2_Course_Border();
}
@Override
public void run(String arg) {
new DeconvolutionLab2_Course_Border();
}
}
\ No newline at end of file
diff --git a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Celegans.java b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Celegans.java
index 74caf94..3baeca7 100644
--- a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Celegans.java
+++ b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Celegans.java
@@ -1,91 +1,120 @@
-package course;
+/*
+ * DeconvolutionLab2
+ *
+ * Conditions of use: You are free to use this software for research or
+ * educational purposes. In addition, we expect you to include adequate
+ * citations and acknowledgments whenever you present or publish results that
+ * are based on it.
+ *
+ * Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
+ * Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
+ * R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
+ */
+
+/*
+ * Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
+ *
+ * This file is part of DeconvolutionLab2 (DL2).
+ *
+ * DL2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * DL2. If not, see <http://www.gnu.org/licenses/>.
+ */
-// Course Version 2
+package course;
import ij.ImagePlus;
import ij.io.FileSaver;
import ij.io.Opener;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import java.io.File;
import javax.swing.filechooser.FileSystemView;
import deconvolution.Deconvolution;
public class DeconvolutionLab2_Course_Celegans implements PlugIn {
private String desktop = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + "Desktop";
private String root = desktop + File.separator + "DeconvolutionLab2-Course" + File.separator;
private String res = root + "Results" + File.separator + "c-elegans" + File.separator;
private String data = root + "Data" + File.separator + "c-elegans" + File.separator;
public DeconvolutionLab2_Course_Celegans() {
new File(res).mkdir();
System.setProperty("user.dir", res);
run(" -algorithm RIF 0.000001 ", "RIF6_");
run(" -algorithm RIF 0.0000001 ", "RIF7_");
//run(" -algorithm RL 100 ", "RL_");
run(" -algorithm LW+ 200 1 ", "LW+_");
//run(" -algorithm I ", "IN_");
//run(" -algorithm RIF 0.001 ", "RIF3_");
//run(" -algorithm RIF 0.0001 ", "RIF4_");
//run(" -algorithm RIF 0.00001 ", "RIF5_");
//run(" -algorithm VC 100 ", "VC");
//run(" -algorithm RLTV 10 0.1 ", "RLTV");
//run(" -algorithm FISTA 50 1 0.1 ", "FISTA");
//run(" -algorithm ISTA 50 1 0.1 ", "ISTA");
}
private void run(String a, String name) {
String channels[] = new String[] { "CY3", "FITC", "DAPI"};
ImagePlus[] ort = new ImagePlus[3];
ImagePlus[] fig = new ImagePlus[3];
for (int i=0; i<3; i++) {
String channel = channels[i];
String psf = " -psf file " + data + "psf-CElegans-" + channel + ".tif";
String img = " -image file " + data + "CElegans-" + channel +".tif";
String param = " -fft JTransforms -disable display multithreading";
String algo = a + out(name + channel);
new Deconvolution("deconvolve", img + psf + algo + param).deconvolve();
ort[i] = new Opener().openImage( res + name + channel + "_ortho_8.tif");
fig[i] = new Opener().openImage( res + name + channel + "_figure_8.tif");
}
new FileSaver(color(ort)).saveAsTiff(res + name + "-ortho-rgb.tif");
new FileSaver(color(fig)).saveAsTiff(res + name + "-figure-rgb.tif");
}
private static String out(String name) {
return
" -out ortho " + name + "_ortho_8 rescaled byte (160,180,50) noshow" +
" -out mip " + name + "_mip_8 rescaled byte noshow" +
" -out figure " + name + "_figure_8 rescaled byte (160,180,50) ";
}
private static ImagePlus color(ImagePlus imp[]) {
int nx = imp[0].getWidth();
int ny = imp[0].getHeight();
ColorProcessor cp = new ColorProcessor(nx, ny);
byte r[] = (byte[])imp[0].getProcessor().getPixels();
byte g[] = (byte[])imp[1].getProcessor().getPixels();
byte b[] = (byte[])imp[2].getProcessor().getPixels();
cp.setRGB(r, g, b);
ImagePlus out = new ImagePlus( "rgb", cp);
out.show();
return out;
}
public static void main(String arg[]) {
new DeconvolutionLab2_Course_Celegans();
}
@Override
public void run(String arg) {
new DeconvolutionLab2_Course_Celegans();
}
}
\ No newline at end of file
diff --git a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Noise.java b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Noise.java
index d82785c..4672d13 100644
--- a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Noise.java
+++ b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Noise.java
@@ -1,67 +1,98 @@
+/*
+ * DeconvolutionLab2
+ *
+ * Conditions of use: You are free to use this software for research or
+ * educational purposes. In addition, we expect you to include adequate
+ * citations and acknowledgments whenever you present or publish results that
+ * are based on it.
+ *
+ * Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
+ * Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
+ * R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
+ */
+
+/*
+ * Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
+ *
+ * This file is part of DeconvolutionLab2 (DL2).
+ *
+ * DL2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * DL2. If not, see <http://www.gnu.org/licenses/>.
+ */
package course;
+
import java.io.File;
import javax.swing.filechooser.FileSystemView;
import deconvolution.Deconvolution;
import deconvolutionlab.Lab;
import deconvolutionlab.monitor.Monitors;
import ij.plugin.PlugIn;
import signal.RealSignal;
import signal.factory.Cube;
public class DeconvolutionLab2_Course_Noise implements PlugIn {
private String desktop = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + "Desktop";
private String root = desktop + File.separator + "Deconvolution" + File.separator;
private String res = root + "results" + File.separator + "noise" + File.separator;
public DeconvolutionLab2_Course_Noise() {
Monitors monitors = Monitors.createDefaultMonitor();
new File(res).mkdir();
System.setProperty("user.dir", res);
int nx = 560;
int ny = 120;
int nz = 1;
String size = " size " + nx + " " + ny + " " + nz;
RealSignal im = new Cube(50, 0.25).intensity(0, 100).center(0.2, 0.5, 0).generate(nx, ny, nz);
RealSignal i1 = new Cube(50, 0.25).intensity(0, 70).center(0.4, 0.5, 0).generate(nx, ny, nz);
RealSignal i2 = new Cube(50, 0.25).intensity(0, 40).center(0.6, 0.5, 0).generate(nx, ny, nz);
RealSignal i3 = new Cube(50, 0.25).intensity(0, 10).center(0.8, 0.5, 0).generate(nx, ny, nz);
im.plus(i1);
im.plus(i2);
im.plus(i3);
Lab.show(monitors, im, "im.tif");
Lab.save(monitors, im, res + "im.tif");
String psf = " -psf synthetic impulse 1 0 " + size;
String image = " -image file im.tif";
// Simulation
String name = "SIM m 0 s 50 p 0";
String out = " -stack " + name + " -out stack " + name + "-BYTE rescaled byte noshow";
new Deconvolution("noise", psf + image + " -algorithm " + name + out).run();
name = "SIM m 0 s 00 p 150";
out = " -stack " + name + " -out stack " + name + "-BYTE rescaled byte noshow";
new Deconvolution("noise", psf + image + " -algorithm " + name + out).run();
name = "SIM m 0 s 15 p 30";
out = " -stack " + name + " -out stack " + name + "-BYTE rescaled byte noshow";
new Deconvolution("noise", psf + image + " -algorithm " + name + out).run();
}
public static void main(String arg[]) {
new DeconvolutionLab2_Course_Noise();
}
@Override
public void run(String arg) {
new DeconvolutionLab2_Course_Noise();
}
}
diff --git a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Piecewise.java b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Piecewise.java
index bc5b2f5..5c1b8f5 100644
--- a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Piecewise.java
+++ b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Piecewise.java
@@ -1,85 +1,116 @@
+/*
+ * DeconvolutionLab2
+ *
+ * Conditions of use: You are free to use this software for research or
+ * educational purposes. In addition, we expect you to include adequate
+ * citations and acknowledgments whenever you present or publish results that
+ * are based on it.
+ *
+ * Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
+ * Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
+ * R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
+ */
+
+/*
+ * Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
+ *
+ * This file is part of DeconvolutionLab2 (DL2).
+ *
+ * DL2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * DL2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
package course;
import java.io.File;
import java.util.Random;
import javax.swing.filechooser.FileSystemView;
import deconvolution.Deconvolution;
import deconvolutionlab.Lab;
import deconvolutionlab.monitor.Monitors;
import ij.plugin.PlugIn;
import signal.RealSignal;
import signal.factory.Constant;
import signal.factory.Cube;
public class DeconvolutionLab2_Course_Piecewise implements PlugIn {
private String desktop = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + "Desktop";
private String root = desktop + File.separator + "Deconvolution" + File.separator;
private String res = root + "results" + File.separator + "piecewise" + File.separator;
public DeconvolutionLab2_Course_Piecewise() {
Monitors monitors = Monitors.createDefaultMonitor();
new File(res).mkdir();
System.setProperty("user.dir", res);
new File(res + "RIF").mkdir();
new File(res + "LW").mkdir();
new File(res + "LW+").mkdir();
new File(res + "RL").mkdir();
new File(res + "RLTV").mkdir();
new File(res + "ISTA").mkdir();
new File(res + "FISTA").mkdir();
int nx = 128;
int ny = 128;
int nz = 128;
int spacing = 16;
Random rand = new Random(1234);
RealSignal x = new Constant().intensity(0, 10).generate(nx, ny, nz);
for(int i = 0; i< 12; i++) {
double xc = (rand.nextDouble()*0.6 + 0.2);
double yc = (rand.nextDouble()*0.6 + 0.2);
double zc = (rand.nextDouble()*0.6 + 0.2);
double size = 15 + (rand.nextDouble()*30);
double ampl = (rand.nextDouble()+0.5)*10;
x.plus(new Cube(size, 0.1).intensity(0, ampl).center(xc, yc, zc).generate(nx, ny, nz));
}
Lab.show(monitors, x, "reference");
Lab.save(monitors, x, res + "ref.tif");
String algo = " ";
String ground = " -image file " + res + "ref.tif ";
//String psf = " -psf file ../../Data/resolution/psfgl.tif";
String psf = " -psf synthetic gaussian 100.0 0.0 1.2 1.2 3.6 size ";
// nx + " " + ny + " " + nz;
String signal = " -image file signal.tif -reference " + res + "ref.tif -disable monitor";
String paramout = " intact float (" + spacing + "," + spacing + "," + spacing + ")";
algo = " -algorithm CONV -out stats @3 PR nosave -out stack PR -out ortho PRo ";
new Deconvolution("run", ground + "-reference reference.tif -psf synthetic impulse 100 0 size 128 128 128 " + algo).deconvolve();
algo = " -algorithm SIM 0 1 1 -out stats @3 SIM nosave -out stack signal -out ortho SIGNALo ";
new Deconvolution("run", ground + psf + algo).deconvolve();
algo = " -algorithm NIF -out ortho NIF " + paramout;
new Deconvolution("run", signal + psf + algo).deconvolve();
algo = " -algorithm RLTV 15 0.01 -out stats @1 RLTV nosave -out ortho @1 RLTV/RLTV" + paramout;
new Deconvolution("run", signal + psf + algo).deconvolve();
}
public static void main(String arg[]) {
new DeconvolutionLab2_Course_Piecewise();
}
@Override
public void run(String arg) {
new DeconvolutionLab2_Course_Piecewise();
}
}
diff --git a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Resolution.java b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Resolution.java
index da209dd..2aaefc6 100644
--- a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Resolution.java
+++ b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_Resolution.java
@@ -1,76 +1,107 @@
+/*
+ * DeconvolutionLab2
+ *
+ * Conditions of use: You are free to use this software for research or
+ * educational purposes. In addition, we expect you to include adequate
+ * citations and acknowledgments whenever you present or publish results that
+ * are based on it.
+ *
+ * Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
+ * Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
+ * R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
+ */
+
+/*
+ * Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
+ *
+ * This file is part of DeconvolutionLab2 (DL2).
+ *
+ * DL2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * DL2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
package course;
import java.io.File;
import javax.swing.filechooser.FileSystemView;
import deconvolution.Deconvolution;
import deconvolutionlab.Lab;
import deconvolutionlab.monitor.Monitors;
import ij.plugin.PlugIn;
import signal.RealSignal;
import signal.factory.GridSpots;
public class DeconvolutionLab2_Course_Resolution implements PlugIn {
private String desktop = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + "Desktop";
private String root = desktop + File.separator + "Deconvolution" + File.separator;
private String res = root + "results" + File.separator + "resolution" + File.separator;
public DeconvolutionLab2_Course_Resolution() {
Monitors monitors = Monitors.createDefaultMonitor();
new File(res).mkdir();
System.setProperty("user.dir", res);
new File(res + "RIF").mkdir();
new File(res + "LW").mkdir();
new File(res + "LW+").mkdir();
new File(res + "RL").mkdir();
int nx = 128;
int ny = 128;
int nz = 128;
int spacing = 16;
RealSignal x = new GridSpots(3, 0.1, spacing).intensity(0, 255).generate(nx, ny, nz);
Lab.show(monitors, x, "reference");
Lab.save(monitors, x, res + "ref.tif");
String algo = " ";
String ground = " -image file " + res + "ref.tif ";
//String psf = " -psf file ../../Data/resolution/psfgl.tif";
String psf = " -psf synthetic gaussian 100.0 0.0 1.2 1.2 3.6 size " + nx + " " + ny + " " + nz;
String signal = " -image file signal.tif -reference " + res + "ref.tif -disable monitor";
String paramout = " intact float (" + spacing + "," + spacing + "," + spacing + ")";
algo = " -algorithm CONV -out stats @3 PR -out stack PR -out ortho PRo ";
new Deconvolution("run", ground + "-reference reference.tif -psf synthetic impulse 100 0 size 128 128 128 " + algo).deconvolve();
algo = " -algorithm SIM 0 1.5 0 -out stats @3 SIM -out stack signal -out ortho SIGNALo ";
new Deconvolution("run", ground + psf + algo).deconvolve();
algo = " -algorithm NIF -out ortho NIF " + paramout;
new Deconvolution("run", signal + psf + algo).deconvolve();
for(int i=0; i<=24; i++) {
double p = Math.pow(10, i-18);
algo = " -algorithm RIF " + p + " -out ortho @5 RIF/RIF" + i + paramout;
new Deconvolution("run", signal + psf + algo).deconvolve();
}
algo = " -algorithm LW+ 305 1 -out stats @3 LW+ nosave -out ortho @25 LW+/LW+" + paramout;
new Deconvolution("run", signal + psf + algo).deconvolve();
}
public static void main(String arg[]) {
new DeconvolutionLab2_Course_Resolution();
}
@Override
public void run(String arg) {
new DeconvolutionLab2_Course_Resolution();
}
}
\ No newline at end of file
diff --git a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_SpectralAnaylsis.java b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_SpectralAnaylsis.java
index 776bf70..a186c0e 100644
--- a/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_SpectralAnaylsis.java
+++ b/DeconvolutionLab2/src/course/DeconvolutionLab2_Course_SpectralAnaylsis.java
@@ -1,159 +1,190 @@
+/*
+ * DeconvolutionLab2
+ *
+ * Conditions of use: You are free to use this software for research or
+ * educational purposes. In addition, we expect you to include adequate
+ * citations and acknowledgments whenever you present or publish results that
+ * are based on it.
+ *
+ * Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
+ * Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
+ * R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
+ */
+
+/*
+ * Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
+ *
+ * This file is part of DeconvolutionLab2 (DL2).
+ *
+ * DL2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * DL2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
package course;
import java.io.File;
import javax.swing.filechooser.FileSystemView;
import deconvolution.Deconvolution;
import deconvolutionlab.Imaging;
import deconvolutionlab.Lab;
import deconvolutionlab.monitor.Monitors;
import fft.AbstractFFT;
import fft.FFT;
import ij.plugin.PlugIn;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
import signal.factory.DoG;
import signal.factory.Gaussian;
import signal.factory.complex.ComplexSignalFactory;
public class DeconvolutionLab2_Course_SpectralAnaylsis implements PlugIn {
private String desktop = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + "Desktop";
private String root = desktop + File.separator + "Deconvolution" + File.separator;
private String res = root + "results" + File.separator + "star" + File.separator;
private String data = root + "data" + File.separator + "star" + File.separator;
public DeconvolutionLab2_Course_SpectralAnaylsis() {
new File(res).mkdir();
System.setProperty("user.dir", res);
new File(res + "TRIF").mkdir();
new File(res + "TRIF-FILTER").mkdir();
new File(res + "RIF").mkdir();
new File(res + "RIF-FILTER").mkdir();
new File(res + "LW").mkdir();
new File(res + "LW-ITER").mkdir();
new File(res + "LW+").mkdir();
new File(res + "LW+-ITER").mkdir();
new File(res + "RL").mkdir();
new File(res + "RL-ITER").mkdir();
new File(res + "NOISELESS").mkdir();
new File(res + "PERTURBATION").mkdir();
new File(res + "SIMULATION").mkdir();
new File(res + "ICTM").mkdir();
new File(res + "ICTM-ITER").mkdir();
Monitors monitors = Monitors.createDefaultMonitor();
int nx = 256;
int ny = 256;
int nz = 1;
String size = " size " + nx + " " + ny + " " + nz;
double noise = 0.04;
double poisson = 0.01;
double wiener = Math.sqrt(noise * 2.0 / Math.PI);
System.out.println("Wiener value " + wiener);
AbstractFFT fft = FFT.createDefaultFFT(monitors, nx, ny, nz);
ComplexSignal L = ComplexSignalFactory.laplacian(nx, ny, nz);
RealSignal laplacian = fft.inverse(L).circular().rescale(monitors);
Lab.save(monitors, laplacian, res + "laplacian.tif", Imaging.Type.BYTE);
RealSignal h = new DoG(2, 3.6).generate(nx, ny, nz);
h.times(0.7f);
h.plus(new Gaussian(1.5, 1.5, 1.5).generate(nx, ny, nz));
Lab.save(monitors, h, res + "psf.tif");
h.plus(new Gaussian(0.5, 0.5, 0.5).generate(nx, ny, nz));
Lab.save(monitors, h, res + "psfPerturbated.tif");
String psf = " -psf file psf.tif -fft FFTW2";
String impulse = " -psf synthetic impulse 100.0 0.0 " + size;
String image = " -image file " + data + "ref.tif";
String constant = " -image constant 0 0 " + size;
// Simulation
String algo = " -algorithm CONV " + out("CONV");
new Deconvolution("run", psf + image + algo).deconvolve();
algo = " -algorithm CONV " + out("CONV-PERTURBATED");
new Deconvolution("run", psf + image + algo).deconvolve();
ComplexSignal H = fft.transform(h);
ComplexSignal H2 = Operations.multiply(H, H);
ComplexSignal LP = ComplexSignalFactory.laplacian(nx, ny, nz);
algo = " -algorithm SIM " + (6*noise) + " " + noise + " " + poisson + " " + out("SIM");
new Deconvolution("run", psf + image + algo).deconvolve();
algo = " -algorithm SIM " + (6*noise) + " " + noise + " " + poisson + " " + out("NOISE");
new Deconvolution("run", impulse + constant + algo).deconvolve();
// No Noise
String nonoise = " -image file CONV.tif -psf file psfPerturbated.tif";
new Deconvolution("run", nonoise + " -algorithm TRIF " + wiener + out("NOISELESS/WIF")).deconvolve();
new Deconvolution("run", nonoise + " -algorithm NIF -epsilon 1E0 " + out("NOISELESS/NIF0")).deconvolve();
new Deconvolution("run", nonoise + " -algorithm NIF -epsilon 1E-3 " + out("NOISELESS/NIF-1")).deconvolve();
new Deconvolution("run", nonoise + " -algorithm NIF -epsilon 1E-6 " + out("NOISELESS/NIF-6")).deconvolve();
new Deconvolution("run", nonoise + " -algorithm NIF -epsilon 1E-9 " + out("NOISELESS/NIF-9")).deconvolve();
new Deconvolution("run", nonoise + " -algorithm NIF -epsilon 1E-12 " + out("NOISELESS/NIF-12")).deconvolve();
new Deconvolution("run", nonoise + " -algorithm DIV " + out("NOISELESS/DIV")).deconvolve();
// Pertubatation
String pertubation = " -image file CONV.tif -psf file psfPerturbated.tif";
new Deconvolution("run", pertubation + " -algorithm TRIF " + wiener + out("PERTURBATION/WIF")).deconvolve();
new Deconvolution("run", pertubation + " -algorithm NIF " + out("PERTURBATION/NIF")).deconvolve();
new Deconvolution("run", pertubation + " -algorithm DIV " + out("PERTURBATION/DIV")).deconvolve();
// Noisy
String simulation = " -image file SIM.tif " + psf;
new Deconvolution("run", simulation + " -algorithm TRIF " + wiener + out("SIMULATION/WIF")).deconvolve();
new Deconvolution("run", simulation + " -algorithm NIF "+ out("SIMULATION/NIF")).deconvolve();
new Deconvolution("run", simulation + " -algorithm DIV" + out("SIMULATION/DIV")).deconvolve();
algo = " -algorithm LW+ 100 0.5 -out mip @1 LW+-ITER/I ";
new Deconvolution("run", simulation + algo + out("LW+/LW+")).deconvolve();
new File(res + "LW+-ITER/I.tif").delete();
for(int i=0; i<=20; i++) {
double p = Math.pow(5, i-12);
String name = "RIF/RIF" + String.format("%02d", i);
new Deconvolution("run", simulation + " -algorithm RIF " + p + out(name)).deconvolve();
RealSignal fa = fft.inverse(Operations.add(H2, Operations.multiply(p, LP, LP))).circular();
Lab.save(monitors, fa, res + "RIF-FILTER/RIF" + String.format("%02d", i) + ".tif");
}
for(int i=0; i<=20; i++) {
double p = Math.pow(5, i-12);
String name = "TRIF/TRIF" + String.format("%02d", i);
new Deconvolution("run", simulation + " -algorithm TRIF " + p + out(name)).deconvolve();
RealSignal fa = fft.inverse(Operations.add(H2, Operations.multiply(p, LP, LP))).circular();
Lab.save(monitors, fa, res + "TRIF-FILTER/RIF" + String.format("%02d", i) + ".tif");
}
algo = " -algorithm RL 100 -out mip @1 RL-ITER/I ";
new Deconvolution("run", simulation + algo + out("RL/RL")).deconvolve();
new File(res + "RL-ITER/I.tif").delete();
algo = " -algorithm ICTM 100 1.5 0.001 -out mip @1 ICTM-ITER/I ";
new Deconvolution("run", simulation + algo + out("ICTM/ICTM")).deconvolve();
new File(res + "ICTM-ITER/I.tif").delete();
}
private static String out(String name) {
return " -out stats " + name +
" -out stack " + name + " noshow -out ortho " + name + "-BYTE rescaled byte noshow";
}
public static void main(String arg[]) {
new DeconvolutionLab2_Course_SpectralAnaylsis();
}
@Override
public void run(String arg) {
new DeconvolutionLab2_Course_SpectralAnaylsis();
}
}
diff --git a/DeconvolutionLab2/src/course/DeconvolutionLab2_MemoryFootprint.java b/DeconvolutionLab2/src/course/DeconvolutionLab2_MemoryFootprint.java
new file mode 100644
index 0000000..2dd2c41
--- /dev/null
+++ b/DeconvolutionLab2/src/course/DeconvolutionLab2_MemoryFootprint.java
@@ -0,0 +1,103 @@
+/*
+ * DeconvolutionLab2
+ *
+ * Conditions of use: You are free to use this software for research or
+ * educational purposes. In addition, we expect you to include adequate
+ * citations and acknowledgments whenever you present or publish results that
+ * are based on it.
+ *
+ * Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
+ * Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
+ * R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
+ */
+
+/*
+ * Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
+ *
+ * This file is part of DeconvolutionLab2 (DL2).
+ *
+ * DL2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * DL2. If not, see <http://www.gnu.org/licenses/>.
+ */
+package course;
+
+import deconvolution.Deconvolution;
+import ij.plugin.PlugIn;
+import lab.component.CustomizedTable;
+import lab.tools.NumFormat;
+import signal.SignalCollector;
+
+public class DeconvolutionLab2_MemoryFootprint implements PlugIn {
+
+ public DeconvolutionLab2_MemoryFootprint() {
+
+ CustomizedTable table = new CustomizedTable(new String[] { "Name", "Algo", "Optimized", "Time", "Energy", "Peak Count", "Peak Bytes", "End Count", "End Byte", "Ratio" }, true);
+ table.show("Memory Footprint", 1100, 300);
+
+ run(table, "CONV");
+ run(table, "FISTA 10 1 1");
+ run(table, "ICTM 10 1 0.1");
+ run(table, "I");
+ run(table, "ISTA 10 1 1");
+ run(table, "LW 10 1");
+ run(table, "LLS 10 1");
+ run(table, "NLLS 10 1");
+ run(table, "NIF");
+ run(table, "DIV");
+ run(table, "RIF 1");
+ run(table, "RL 10");
+ run(table, "RLTV 10 1");
+ run(table, "SIM 1 1 1");
+ run(table, "BVLS 10 1");
+ run(table, "TM 10 1 0.1");
+ run(table, "TRIF 1");
+ run(table, "VC 10 1");
+ }
+
+ private void run(CustomizedTable table, String cmd) {
+ int nx = 64;
+ int ny = 32;
+ int nz = 12;
+ String size = " size " + nx + " " + ny + " " + nz;
+ String image = " -image synthetic Cross 110 0 1 1 80.0 " + size;
+ String psf = " -psf synthetic Double-Helix 100 0 3 10 10 " + size;
+
+ for (int i = 0; i <= 1; i++) {
+ SignalCollector.resetSignals();
+ SignalCollector.clear();
+ Deconvolution d = new Deconvolution("noise", " -algorithm " + cmd + psf + image + " -display no");
+ boolean optimized = i == 1;
+ d.getAlgo().setOptimizedMemoryFootprint(optimized);
+ String n = d.getAlgo().getName();
+ double chrono = System.nanoTime();
+ d.run();
+ String energy = "" + d.getOutput().getEnergy();
+ String time = NumFormat.time(System.nanoTime() - chrono);
+ int cp = SignalCollector.getCountPeakSignals();
+ int cs = SignalCollector.getCountSignals();
+ long bp = SignalCollector.getBytesPeakSignals();
+ long bs = SignalCollector.getBytesSignals();
+ double ratio = (bp + bs) / (nx * ny * nz * 4);
+ table.append(new String[] { n, cmd, "" + optimized, time, energy, "" + cp, NumFormat.bytes(bp), "" + cs, NumFormat.bytes(bs), NumFormat.nice(ratio) });
+ }
+ }
+
+ public static void main(String arg[]) {
+ new DeconvolutionLab2_MemoryFootprint();
+ }
+
+ @Override
+ public void run(String arg) {
+ new DeconvolutionLab2_MemoryFootprint();
+ }
+
+}
diff --git a/DeconvolutionLab2/src/deconvolution/Command.java b/DeconvolutionLab2/src/deconvolution/Command.java
index 5c0e7b7..9ae5393 100644
--- a/DeconvolutionLab2/src/deconvolution/Command.java
+++ b/DeconvolutionLab2/src/deconvolution/Command.java
@@ -1,469 +1,457 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution;
import java.util.ArrayList;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import deconvolution.algorithm.AbstractAlgorithm;
import deconvolution.algorithm.Algorithm;
import deconvolution.algorithm.Controller;
import deconvolutionlab.Output;
import deconvolutionlab.OutputCollection;
import deconvolutionlab.Output.View;
import deconvolutionlab.modules.AbstractModule;
import deconvolutionlab.modules.CommandModule;
import deconvolutionlab.monitor.Verbose;
import fft.AbstractFFT;
import fft.AbstractFFTLibrary;
import fft.FFT;
import lab.tools.NumFormat;
import signal.Constraint;
import signal.Operations;
import signal.apodization.AbstractApodization;
import signal.apodization.Apodization;
import signal.apodization.UniformApodization;
import signal.padding.AbstractPadding;
import signal.padding.NoPadding;
import signal.padding.Padding;
import wavelets.Wavelets;
public class Command {
public static String keywords[] = { "-image", "-psf", "-algorithm", "-path", "-disable", "-verbose", "-monitor", "-display", "-multithreading", "-system", "-stats", "-constraint", "-time", "-residu", "-reference", "-out", "-pad", "-apo", "-norm", "-fft", "-epsilon" };
private static AbstractModule modules[];
private static CommandModule command;
public static void active(AbstractModule[] m, CommandModule c) {
modules = m;
command = c;
}
public static String command() {
if (modules == null)
return "";
String cmd = "";
for (AbstractModule m : modules)
cmd += m.getCommand() + " ";
if (command != null)
command.setCommand(cmd);
return cmd;
}
public static void decode(String command, Deconvolution deconvolution) {
AbstractAlgorithm algo = Algorithm.getDefaultAlgorithm();
boolean flagSystem = true;
boolean flagDisplay = true;
boolean flagMultithreading = true;
- int monitor = 4;
- int stats = 4;
+ int monitor = 3;
+ int stats = 0;
Verbose verbose = Verbose.Log;
String path = System.getProperty("user.dir");
Controller controller = new Controller();
OutputCollection outs = new OutputCollection();
Padding pad = new Padding();
Apodization apo = new Apodization();
double norm = 1.0;
- AbstractFFTLibrary fft = FFT.getLibraryByName("Academic");
+ AbstractFFTLibrary fft = FFT.getFastestFFT();
ArrayList<Token> tokens = parse(command);
for (Token token : tokens) {
if (token.keyword.equalsIgnoreCase("-algorithm"))
algo = Command.decodeAlgorithm(token, controller);
if (token.keyword.equalsIgnoreCase("-path") && !token.parameters.equalsIgnoreCase("current"))
path = token.parameters;
if (token.keyword.equalsIgnoreCase("-monitor"))
monitor = decodeMonitor(token);
if (token.keyword.equalsIgnoreCase("-stats"))
stats = decodeStats(token);
if (token.keyword.equalsIgnoreCase("-system"))
flagSystem = decodeSystem(token);
if (token.keyword.equalsIgnoreCase("-display"))
flagDisplay = decodeDisplay(token);
if (token.keyword.equalsIgnoreCase("-multithreading"))
flagMultithreading = decodeMultithreading(token);
if (token.keyword.equalsIgnoreCase("-verbose"))
verbose = Verbose.getByName(token.parameters);
if (token.keyword.equalsIgnoreCase("-fft"))
fft = FFT.getLibraryByName(token.parameters);
if (token.keyword.equalsIgnoreCase("-pad"))
pad = decodePadding(token);
if (token.keyword.equalsIgnoreCase("-apo"))
apo = decodeApodization(token);
if (token.keyword.equalsIgnoreCase("-norm"))
norm = decodeNormalization(token);
if (token.keyword.equalsIgnoreCase("-constraint"))
decodeController(token, controller);
if (token.keyword.equalsIgnoreCase("-time"))
decodeController(token, controller);
if (token.keyword.equalsIgnoreCase("-residu"))
decodeController(token, controller);
if (token.keyword.equalsIgnoreCase("-reference"))
decodeController(token, controller);
if (token.keyword.equalsIgnoreCase("-epsilon"))
Operations.epsilon = NumFormat.parseNumber(token.parameters, 1e-6);
if (token.keyword.equals("-out")) {
Output out = decodeOut(token);
if (out != null)
outs.add(out);
}
}
deconvolution.setAlgorithm(algo, controller);
deconvolution.setPath(path);
deconvolution.setNormalization(norm);
deconvolution.setPadding(pad);
deconvolution.setApodization(apo);
deconvolution.setOutput(outs);
deconvolution.setVerbose(verbose);
deconvolution.setFFT(fft);
deconvolution.setMonitor(monitor);
deconvolution.setStats(stats);
deconvolution.setFlags(flagDisplay, flagMultithreading, flagSystem);
}
/**
* This methods first segments the command line, then create all the tokens
* of the command line
*
* @param command
* Command line
* @return the list of tokens extracted from the command line
*/
public static ArrayList<Token> parse(String command) {
ArrayList<CommandSegment> segments = new ArrayList<CommandSegment>();
for (String keyword : keywords)
segments.addAll(findSegment(command, keyword));
Collections.sort(segments);
ArrayList<Token> tokens = new ArrayList<Token>();
for (int i = 0; i < segments.size(); i++) {
String keyword = segments.get(i).keyword;
int begin = segments.get(i).index + keyword.length() + 1;
int end = (i < segments.size() - 1 ? segments.get(i + 1).index : command.length());
Token token = new Token(keyword, command, begin, end);
tokens.add(token);
}
return tokens;
}
public static Token extract(String command, String keyword) {
ArrayList<Token> tokens = parse(command);
for (Token token : tokens)
if (token.keyword.equalsIgnoreCase(keyword))
return token;
return (Token) null;
}
public static double[] parseNumeric(String line) {
ArrayList<String> num = new ArrayList<String>();
Pattern p = Pattern.compile("[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?");
Matcher m = p.matcher(line);
while (m.find()) {
num.add(m.group());
}
double number[] = new double[num.size()];
for (int i = 0; i < num.size(); i++)
number[i] = Double.parseDouble(num.get(i));
return number;
}
public static ArrayList<CommandSegment> findSegment(String command, String keyword) {
ArrayList<CommandSegment> segments = new ArrayList<CommandSegment>();
String regex = "(?<!\\w)" + keyword + "(?!\\w)";
if (command == null)
return segments;
Matcher matcher = Pattern.compile(regex).matcher(command);
while (matcher.find()) {
segments.add(new CommandSegment(keyword, matcher.start()));
}
return segments;
}
public static String extractOptions(String command) {
ArrayList<CommandSegment> segments = new ArrayList<CommandSegment>();
for (String keyword : keywords)
segments.addAll(findSegment(command, keyword));
Collections.sort(segments);
String options = "";
for (int i = 0; i < segments.size(); i++) {
String keyword = segments.get(i).keyword;
int begin = segments.get(i).index + keyword.length() + 1;
int end = (i < segments.size() - 1 ? segments.get(i + 1).index : command.length());
if (keyword != "-image" && keyword != "-psf" && keyword != "-algorithm")
options += keyword + " " + command.substring(begin, end);
}
return options;
}
public static AbstractAlgorithm decodeAlgorithm(Token token, Controller controller) {
String option = token.option;
AbstractAlgorithm algo = Algorithm.createAlgorithm(option);
algo.setShortname(option);
double params[] = parseNumeric(token.parameters);
if (params != null) {
algo.setParameters(params);
if (algo.isIterative() && params.length >= 1)
controller.setIterationMax((int)params[0]);
}
if (algo.isWaveletsBased()) {
for (String wavelet : Wavelets.getWaveletsAsArray()) {
int pos = token.parameters.toLowerCase().indexOf(wavelet.toLowerCase());
if (pos >= 0)
algo.setWavelets(wavelet);
}
}
return algo;
}
public static Output decodeOut(Token token) {
int freq = 0;
String line = token.parameters;
String parts[] = token.parameters.split(" ");
for (int i = 0; i < Math.min(2, parts.length); i++) {
if (parts[i].startsWith("@"))
freq = (int) NumFormat.parseNumber(parts[i], 0);
}
String p = token.parameters.toLowerCase();
Output out = null;
if (p.startsWith("stack"))
out = new Output(View.STACK, freq, line.substring("stack".length(), line.length()));
if (p.startsWith("series"))
out = new Output(View.SERIES, freq, line.substring("series".length(), line.length()));
if (p.startsWith("mip"))
out = new Output(View.MIP, freq, line.substring("mip".length(), line.length()));
if (p.startsWith("ortho"))
out = new Output(View.ORTHO, freq, line.substring("ortho".length(), line.length()));
if (p.startsWith("figure"))
out = new Output(View.FIGURE, freq, line.substring("figure".length(), line.length()));
if (p.startsWith("planar"))
out = new Output(View.PLANAR, freq, line.substring("planar".length(), line.length()));
return out;
}
public static void decodeController(Token token, Controller controller) {
String line = token.parameters;
if (token.parameters.startsWith("@")) {
String parts[] = token.parameters.split(" ");
if (parts.length >= 1) {
line = token.parameters.substring(parts[0].length(), token.parameters.length()).trim();
}
}
if (token.keyword.equals("-constraint"))
controller.setConstraint(Constraint.getByName(line.trim()));
else if (token.keyword.equals("-residu"))
controller.setResiduStop(NumFormat.parseNumber(line, -1));
else if (token.keyword.equals("-reference"))
controller.setReference(line);
else if (token.keyword.equals("-time"))
controller.setTimeStop(NumFormat.parseNumber(line, Double.MAX_VALUE));
}
public static double decodeNormalization(Token token) {
if (token.parameters.toLowerCase().endsWith("no"))
return 0;
else
return NumFormat.parseNumber(token.parameters, 1);
}
public static int decodeMonitor(Token token) {
String parts[] = token.parameters.toLowerCase().split(" ");
int m = 0;
for(String p : parts) {
if (p.startsWith("no"))
return 0;
if (p.equals("false"))
return 0;
if (p.equals("0"))
return 0;
if (p.equals("1"))
return 1;
if (p.equals("2"))
return 2;
if (p.equals("3"))
return 3;
if (p.equals("console"))
m += 1;
if (p.equals("table"))
m += 2;
}
return m;
}
public static int decodeStats(Token token) {
String parts[] = token.parameters.toLowerCase().split(" ");
int m = 0;
for(String p : parts) {
if (p.startsWith("no"))
return 0;
if (p.equals("false"))
return 0;
if (p.equals("0"))
return 0;
if (p.equals("1"))
return 1;
if (p.equals("2"))
return 2;
if (p.equals("3"))
return 3;
if (p.equals("show"))
m += 1;
if (p.equals("save"))
m += 2;
}
return m;
}
-
- public static boolean decodeMonitorConsole(Token token) {
- String p = token.parameters.toLowerCase();
- if (p.startsWith("no"))
- return false;
- if (p.equals("0"))
- return false;
- if (p.equals("false"))
- return false;
- return true;
- }
-
public static boolean decodeSystem(Token token) {
String p = token.parameters.toLowerCase();
if (p.startsWith("no"))
return false;
if (p.equals("0"))
return false;
if (p.equals("false"))
return false;
return true;
}
public static boolean decodeDisplay(Token token) {
String p = token.parameters.toLowerCase();
if (p.startsWith("no"))
return false;
if (p.equals("0"))
return false;
if (p.equals("false"))
return false;
return true;
}
public static boolean decodeMultithreading(Token token) {
String p = token.parameters.toLowerCase();
if (p.startsWith("no"))
return false;
if (p.equals("0"))
return false;
if (p.equals("false"))
return false;
if (p.startsWith("dis"))
return false;
return true;
}
public static Padding decodePadding(Token token) {
AbstractPadding padXY = new NoPadding();
AbstractPadding padZ = new NoPadding();
int extXY = 0;
int extZ = 0;
String param = token.parameters.trim();
String[] parts = param.split(" ");
if (parts.length > 0)
padXY = Padding.getByShortname(parts[0].trim());
if (parts.length > 1)
padZ = Padding.getByShortname(parts[1].trim());
double[] ext = NumFormat.parseNumbers(param);
if (ext.length > 0)
extXY = (int) Math.round(ext[0]);
if (ext.length > 1)
extZ = (int) Math.round(ext[1]);
return new Padding(padXY, padXY, padZ, extXY, extXY, extZ);
}
public static Apodization decodeApodization(Token token) {
AbstractApodization apoXY = new UniformApodization();
AbstractApodization apoZ = new UniformApodization();
String[] parts = token.parameters.trim().split(" ");
if (parts.length >= 1)
apoXY = Apodization.getByShortname(parts[0].trim());
if (parts.length >= 2)
apoZ = Apodization.getByShortname(parts[1].trim());
return new Apodization(apoXY, apoXY, apoZ);
}
public static String getPath() {
command();
ArrayList<Token> tokens = parse(command.getCommand());
String path = System.getProperty("user.dir");
for (Token token : tokens)
if (token.keyword.equalsIgnoreCase("-path") && !token.parameters.equalsIgnoreCase("current"))
path = token.parameters;
return path;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/Deconvolution.java b/DeconvolutionLab2/src/deconvolution/Deconvolution.java
index d64f611..48ce8b9 100644
--- a/DeconvolutionLab2/src/deconvolution/Deconvolution.java
+++ b/DeconvolutionLab2/src/deconvolution/Deconvolution.java
@@ -1,736 +1,550 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution;
import java.io.File;
import java.util.ArrayList;
import deconvolution.algorithm.AbstractAlgorithm;
import deconvolution.algorithm.Controller;
import deconvolutionlab.Constants;
import deconvolutionlab.Lab;
import deconvolutionlab.Output;
import deconvolutionlab.OutputCollection;
import deconvolutionlab.TableStats;
import deconvolutionlab.monitor.ConsoleMonitor;
import deconvolutionlab.monitor.Monitors;
import deconvolutionlab.monitor.StatusMonitor;
import deconvolutionlab.monitor.TableMonitor;
import deconvolutionlab.monitor.Verbose;
import deconvolutionlab.system.SystemInfo;
-import fft.AbstractFFT;
import fft.AbstractFFTLibrary;
import lab.tools.NumFormat;
import signal.RealSignal;
+import signal.SignalCollector;
import signal.apodization.Apodization;
-import signal.factory.SignalFactory;
import signal.padding.Padding;
public class Deconvolution implements Runnable {
public enum Finish {
DIE, ALIVE, KILL
};
- private AbstractAlgorithm algo = null;
+ public AbstractAlgorithm algo = null;
private String path;
- private double norm = 1.0;
- private Padding pad = new Padding();
- private Apodization apo = new Apodization();
+ public double norm = 1.0;
+ public Padding pad = new Padding();
+ public Apodization apo = new Apodization();
private OutputCollection outs;
private Verbose verbose = Verbose.Log;
private AbstractFFTLibrary fft;
private int flagMonitor = 3;
private int flagStats = 0;
private boolean flagDisplay = true;
private boolean flagMultithreading = true;
private boolean flagSystem = true;
- private Monitors monitors = new Monitors();
+ public Monitors monitors = new Monitors();
private String command = "";
private boolean live = false;
private Features report = new Features();
private String name = "";
private ArrayList<DeconvolutionListener> listeners = new ArrayList<DeconvolutionListener>();
- private boolean imageLoaded = false;
- private RealSignal image;
- private RealSignal psf;
+ public RealSignal image;
+ public RealSignal psf;
private RealSignal deconvolvedImage;
private Finish finish = Finish.DIE;
private DeconvolutionDialog dialog;
private TableStats tableStats;
- private TableMonitor tableMonitor;
-
+
public Deconvolution(String name, String command) {
this.name = name;
- tableStats = new TableStats(name, Constants.widthGUI, 240, path, (flagStats & 2) == 2);
- tableMonitor = new TableMonitor(name , Constants.widthGUI, 240);
this.finish = Finish.DIE;
setCommand(command);
+ tableStats = new TableStats(name, Constants.widthGUI, 240, path, (flagStats & 2) == 2);
}
public Deconvolution(String name, String command, Finish finish) {
this.name = name;
- tableStats = new TableStats(name, Constants.widthGUI, 240, path, (flagStats & 2) == 2);
- tableMonitor = new TableMonitor(name , Constants.widthGUI, 240);
this.finish = finish;
setCommand(command);
+ tableStats = new TableStats(name, Constants.widthGUI, 240, path, (flagStats & 2) == 2);
}
public void setCommand(String command) {
this.command = command;
Command.decode(command, this);
this.command = command;
if (name.equals("") && algo != null)
name = algo.getShortname();
- monitors = Monitors.createDefaultMonitor();
live = false;
}
- public void close() {
- if (dialog != null)
- dialog.dispose();
- finalize();
- }
-
- public void finalize() {
- algo = null;
- image = null;
- psf = null;
- monitors = null;
- System.gc();
- }
-
/**
* This method runs the deconvolution without graphical user interface.
*
* @param exit
* System.exit call is true
*/
public RealSignal deconvolve(RealSignal image, RealSignal psf) {
this.image = image;
this.psf = psf;
- imageLoaded = true;
runDeconvolve();
return deconvolvedImage;
}
public RealSignal deconvolve() {
this.image = null;
this.psf = null;
- imageLoaded = false;
runDeconvolve();
return deconvolvedImage;
}
/**
* This method runs the deconvolution without graphical user interface.
*
* @param exit
* System.exit call is true
*/
private void runDeconvolve() {
if ((flagMonitor & 2) == 2) {
+ TableMonitor tableMonitor = new TableMonitor(name , Constants.widthGUI, 240);
monitors.add(tableMonitor);
- tableMonitor.show();
+ Lab.setVisible(tableMonitor.getPanel(), "Monitor of " + name, 10, 10);
}
+ if ((flagMonitor & 1) == 1)
+ monitors.add(new ConsoleMonitor());
+
if ((flagStats & 1) == 1) {
- tableStats.show();
+ Lab.setVisible(tableStats.getPanel(), "Stats of " + name, 50, 50);
}
if (fft == null) {
run();
return;
}
if (!fft.isMultithreadable()) {
run();
return;
}
if (flagMultithreading) {
Thread thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
else {
run();
}
+
}
/**
* This method runs the deconvolution with a graphical user interface.
*
* @param job
* Name of the job of deconvolution
*/
public void launch() {
- dialog = new DeconvolutionDialog(DeconvolutionDialog.Module.ALL, this, tableMonitor, tableStats);
-
- Lab.setVisible(dialog, false);
monitors = new Monitors();
- monitors.add(new StatusMonitor(dialog.getProgressBar()));
-
+ TableMonitor tableMonitor = null;
if ((flagMonitor & 2) == 2) {
+ tableMonitor = new TableMonitor(name , Constants.widthGUI, 240);
monitors.add(tableMonitor);
}
+ if ((flagMonitor & 1) == 1)
+ monitors.add(new ConsoleMonitor());
+ if (flagStats == 0) {
+ tableStats = null;
+ }
- }
+ dialog = new DeconvolutionDialog(DeconvolutionDialog.Module.ALL, this, tableMonitor, tableStats);
+ monitors.add(new StatusMonitor(dialog.getProgressBar()));
- public Monitors createMonitors1() {
- Monitors monitors = new Monitors();
- return monitors;
+ Lab.setVisible(dialog, false);
}
@Override
public void run() {
double chrono = System.nanoTime();
- if ((flagMonitor & 1) == 1)
- monitors.add(new ConsoleMonitor());
-
if (flagSystem)
SystemInfo.activate();
for (DeconvolutionListener listener : listeners)
listener.started();
live = true;
if (monitors != null)
monitors.setVerbose(verbose);
report.add("Path", checkPath(path));
monitors.log("Path: " + checkPath(path));
-
- if (!imageLoaded)
+
+ if (image == null)
image = openImage();
if (image == null) {
monitors.error("Image: Not valid " + command);
report.add("Image", "Not valid");
if (finish == Finish.KILL)
System.exit(-101);
return;
}
report.add("Image", image.dimAsString());
monitors.log("Image: " + image.dimAsString());
- if (!imageLoaded)
- psf = openPSF();
+ psf = openPSF();
if (psf == null) {
monitors.error("PSF: not valid");
report.add("PSF", "Not valid");
if (finish == Finish.KILL)
System.exit(-102);
return;
}
report.add("PSF", psf.dimAsString());
monitors.log("PSF: " + psf.dimAsString());
if (algo == null) {
monitors.error("Algorithm: not valid");
if (finish == Finish.KILL)
System.exit(-103);
return;
}
Controller controller = algo.getController();
if (controller == null) {
monitors.error("Controller: not valid");
if (finish == Finish.KILL)
System.exit(-104);
return;
}
if (flagStats > 0)
controller.setTableStats(tableStats);
report.add("FFT", fft.getLibraryName());
if (outs != null) {
outs.setPath(path);
controller.setOutputs(outs);
}
monitors.log("Algorithm: " + algo.getName());
report.add("Algorithm", algo.getName());
algo.setController(controller);
deconvolvedImage = algo.run(monitors, image, psf, fft, pad, apo, norm, true);
live = false;
for (DeconvolutionListener listener : listeners)
listener.finish();
- report.add("End", algo.getName() + " in " + NumFormat.time(System.nanoTime() - chrono));
+ report.add("End", NumFormat.time(System.nanoTime() - chrono));
if (flagDisplay)
Lab.show(monitors, deconvolvedImage, "Result of " + algo.getShortname());
if (finish == Finish.KILL) {
System.out.println("End");
System.exit(0);
}
if (finish == Finish.DIE)
- finalize();
+ die();
}
+
+ public void close() {
+ if (dialog != null)
+ dialog.dispose();
+ SignalCollector.free(image);
+ SignalCollector.free(psf);
+ SignalCollector.free(deconvolvedImage);
+ algo = null;
+ image = null;
+ psf = null;
+ deconvolvedImage = null;
+ monitors = null;
+ System.gc();
+ }
+
+ public void die() {
+ SignalCollector.free(image);
+ SignalCollector.free(psf);
+ }
+
+
/**
* This methods make a recap of the deconvolution. Useful before starting
* the processing.
*
* @return list of messages to print
*/
public Features recap() {
Features features = new Features();
Token image = Command.extract(command, "-image");
features.add("Image", image == null ? "keyword -image not found" : image.parameters);
String normf = (norm < 0 ? " (no normalization)" : " (normalization to " + norm + ")");
Token psf = Command.extract(command, "-psf");
features.add("PSF", psf == null ? "keyword -psf not found" : psf.parameters + " norm:" + normf);
if (algo == null) {
features.add("Algorithm", "not valid>");
}
else {
Controller controller = algo.getController();
features.add("Algorithm", algo.toString());
features.add("Stopping Criteria", controller.getStoppingCriteriaAsString(algo));
features.add("Reference", controller.getReference());
features.add("Constraint", controller.getConstraintAsString());
features.add("Padding", pad.toString());
features.add("Apodization", apo.toString());
- features.add("FFT", algo.getFFT() == null ? "" : algo.getFFT().getName());
+ features.add("FFT", fft == null ? "null" : fft.getLibraryName());
}
features.add("Path", path);
String monitor = "";
if (flagMonitor == 0)
- monitor = " monitor: no ";
+ monitor = "no ";
if (flagMonitor == 1)
- monitor = " monitor: console (" + verbose.name().toLowerCase() + ")";
+ monitor = "console (" + verbose.name().toLowerCase() + ")";
if (flagMonitor == 2)
- monitor = " monitor: table (" + verbose.name().toLowerCase() + ")";
+ monitor = "table (" + verbose.name().toLowerCase() + ")";
if (flagMonitor == 3)
- monitor = " monitor: console table (" + verbose.name().toLowerCase() + ")";
+ monitor = "console table (" + verbose.name().toLowerCase() + ")";
String stats = "";
if (flagStats == 0)
- stats = " stats: no ";
+ stats = "no ";
if (flagStats == 1)
- stats = " stats: show ";
+ stats = "show ";
if (flagStats == 2)
- stats = " stats: save ";
+ stats = "save ";
if (flagStats == 3)
- stats = " stats: show save";
+ stats = "show save";
String running = "";
- running += " multithreading: " + (flagMultithreading ? "on " : "off ");
+ running += "multithreading: " + (flagMultithreading ? "on " : "off ");
running += " display: " + (flagDisplay ? "on " : "off ");
running += " system: " + (flagSystem ? "shown" : "hidden ");
features.add("Monitor", monitor);
features.add("Stats", stats);
features.add("Running", running);
if (outs == null)
features.add("Output", "not valid");
else
for (Output out : outs)
features.add("Output " + out.getName(), out.toString());
return features;
}
- public Features checkAlgo() {
- Features features = new Features();
- RealSignal image = openImage();
- if (image == null) {
- features.add("Image", "No valid input image");
- return features;
- }
- if (pad == null) {
- features.add("Padding", "No valid padding");
- return features;
- }
- if (apo == null) {
- features.add("Apodization", "No valid apodization");
- return features;
- }
- RealSignal psf = openPSF();
- if (psf == null) {
- features.add("Image", "No valid PSF");
- return features;
- }
- if (algo == null) {
- features.add("Algorithm", "No valid algorithm");
- return features;
- }
-
- Controller controller = algo.getController();
- if (controller == null) {
- features.add("Controller", "No valid controller");
- return features;
- }
-
- algo.setController(controller);
- double chrono = System.nanoTime();
- AbstractFFT f = fft.getDefaultFFT();
- RealSignal slice = image.getSlice(0);
- if (slice != null) {
- f.init(Monitors.createDefaultMonitor(), slice.nx, slice.ny, 1);
- f.transform(slice);
- int n = algo.isIterative() ? controller.getIterationMax() : 1;
- chrono = (System.nanoTime() - chrono) * 2 * slice.nz * n;
-
- features.add("Estimated Time", NumFormat.time(chrono) );
- }
- else
- features.add("Estimated Time", "Error" );
- features.add("Estimated Memory", controller.getMemoryAsString());
- features.add("Iterative", algo.isIterative() ? "" + controller.getIterationMax() : "Direct");
- return features;
- }
-
- public Features checkImage(RealSignal image) {
- Features features = new Features();
- if (image == null) {
- features.add("Image", "No valid input image");
- return features;
- }
- if (pad == null) {
- features.add("Padding", "No valid padding");
- return features;
- }
- if (apo == null) {
- features.add("Apodization", "No valid apodization");
- return features;
- }
-
- RealSignal signal = pad.pad(monitors, getApodization().apodize(monitors, image));
- float stats[] = signal.getStats();
- float stati[] = image.getStats();
- int sizi = image.nx * image.ny * image.nz;
- int sizs = signal.nx * signal.ny * signal.nz;
- float totali = stati[0] * sizi;
- float totals = stats[0] * sizs;
- features.add("<html><b>Orignal Image</b></html>", "");
- features.add("Size", image.dimAsString() + " " + NumFormat.bytes(sizi*4));
- features.add("Mean (stdev)", NumFormat.nice(stati[0]) + " (" + NumFormat.nice(stati[3]) + ")");
- features.add("Min ... Max", NumFormat.nice(stati[1]) + " ... " + NumFormat.nice(stati[2]));
- features.add("Energy (int)", NumFormat.nice(stati[5]) + " (" + NumFormat.nice(totali) + ")");
-
- features.add("<html><b>Working Image</b></html>", "");
- features.add("Size", signal.dimAsString() + " " + NumFormat.bytes(sizs*4));
- features.add("Mean (stdev)", NumFormat.nice(stats[0]) + " (" + NumFormat.nice(stats[3]) + ")");
- features.add("Min Max", NumFormat.nice(stats[1]) + " " + NumFormat.nice(stats[2]));
- features.add("Energy (int)", NumFormat.nice(stats[5]) + " (" + NumFormat.nice(totals) + ")");
- features.add("<html><b>Information</b></html>", "");
- features.add("Size Increase ", NumFormat.nice((double)(sizs-sizi)/sizi*100.0));
- features.add("Energy Lost", NumFormat.nice((stats[5]-stati[5])/stati[5]*100));
-
- return features;
- }
-
- public Features checkPSF(RealSignal psf) {
- Features features = new Features();
- if (!imageLoaded)
- image = openImage();
-
- if (image == null) {
- features.add("Image", "No valid input image");
- return features;
- }
- if (pad == null) {
- features.add("Padding", "No valid padding");
- return features;
- }
- if (apo == null) {
- features.add("Apodization", "No valid apodization");
- return features;
- }
-
- if (psf == null) {
- features.add("PSF", "No valid PSF");
- return features;
- }
-
- RealSignal h = psf.changeSizeAs(image);
- h.normalize(norm);
-
- float stats[] = h.getStats();
- float stati[] = psf.getStats();
- int sizi = psf.nx * psf.ny * psf.nz;
- int sizs = h.nx * h.ny * h.nz;
- float totali = stati[0] * sizi;
- float totals = stats[0] * sizs;
- features.add("<html><b>Orignal PSF</b></html>", "");
- features.add("Size", psf.dimAsString() + " " + NumFormat.bytes(sizi*4));
- features.add("Mean (stdev)", NumFormat.nice(stati[0]) + " (" + NumFormat.nice(stati[3]) + ")");
- features.add("Min ... Max", NumFormat.nice(stati[1]) + " ... " + NumFormat.nice(stati[2]));
- features.add("Energy (int)", NumFormat.nice(stati[5]) + " (" + NumFormat.nice(totali) + ")");
-
- features.add("<html><b>Working PSF</b></html>", "");
- features.add("Size", h.dimAsString() + " " + NumFormat.bytes(sizs*4));
- features.add("Mean (stdev)", NumFormat.nice(stats[0]) + " (" + NumFormat.nice(stats[3]) + ")");
- features.add("Min Max", NumFormat.nice(stats[1]) + " " + NumFormat.nice(stats[2]));
- features.add("Energy (int)", NumFormat.nice(stats[5]) + " (" + NumFormat.nice(totals) + ")");
- features.add("<html><b>Information</b></html>", "");
- features.add("Size Increase ", NumFormat.nice((double)(sizs-sizi)/sizi*100.0));
- features.add("Energy Lost", NumFormat.nice((stats[5]-stati[5])/stati[5]*100));
- return features;
- }
public Features checkOutput() {
Features features = new Features();
if (deconvolvedImage == null) {
features.add("Image", "No valid output image");
return features;
}
-
float stati[] = deconvolvedImage.getStats();
int sizi = deconvolvedImage.nx * deconvolvedImage.ny * deconvolvedImage.nz;
float totali = stati[0] * sizi;
features.add("<html><b>Deconvolved Image</b></html>", "");
- features.add("Size", image.dimAsString() + " " + NumFormat.bytes(sizi*4));
+ features.add("Size", deconvolvedImage.dimAsString() + " " + NumFormat.bytes(sizi*4));
features.add("Mean (stdev)", NumFormat.nice(stati[0]) + " (" + NumFormat.nice(stati[3]) + ")");
features.add("Min ... Max", NumFormat.nice(stati[1]) + " ... " + NumFormat.nice(stati[2]));
features.add("Energy (int)", NumFormat.nice(stati[5]) + " (" + NumFormat.nice(totali) + ")");
-
return features;
}
- public RealSignal getOutput() {
- return deconvolvedImage;
- }
-
- public Features getDeconvolutionReports() {
- return report;
- }
-
- public String getName() {
- return name;
- }
-
public boolean isLive() {
return live;
}
public void abort() {
live = false;
algo.getController().abort();
}
public String checkPath(String path) {
File dir = new File(path);
if (dir.exists()) {
if (dir.isDirectory()) {
if (dir.canWrite())
return path + " (writable)";
else
return path + " (non-writable)";
}
else {
return path + " (non-directory)";
}
}
else {
return path + " (not-valid)";
}
}
public RealSignal openImage() {
Token token = Command.extract(command, "-image");
if (token == null)
return null;
if (token.parameters.startsWith(">>>"))
return null;
- return getImage(monitors, token);
+ String arg = token.option.trim();
+ String cmd = token.parameters.substring(arg.length(), token.parameters.length()).trim();
+ image = Lab.createRealSignal(monitors, arg, cmd, path);
+ return image;
}
public RealSignal openPSF() {
Token token = Command.extract(command, "-psf");
if (token == null)
return null;
if (token.parameters.startsWith(">>>"))
return null;
- return getImage(monitors, token);
- }
-
- private RealSignal getImage(Monitors monitors, Token token) {
String arg = token.option.trim();
String cmd = token.parameters.substring(arg.length(), token.parameters.length()).trim();
-
- if (arg.equalsIgnoreCase("synthetic")) {
- String parts[] = cmd.split(" ");
- if (parts.length <= 0)
- return null;
- String shape = parts[0];
- for (String name : SignalFactory.getAllName()) {
- if (shape.equalsIgnoreCase(name.toLowerCase())) {
- double params[] = Command.parseNumeric(cmd);
- SignalFactory factory = SignalFactory.getFactoryByName(shape);
- if (factory == null)
- return null;
- double amplitude = params.length > 0 ? params[0] : 1;
- double background = params.length > 1 ? params[1] : 0;
- factory.intensity(background, amplitude);
- int np = factory.getParameters().length;
- double[] features = new double[np];
- for (int i = 0; i < Math.min(np, params.length); i++)
- features[i] = params[i + 2];
- factory.setParameters(features);
- int nx = params.length > np + 2 ? (int) Math.round(params[np + 2]) : 128;
- int ny = params.length > np + 3 ? (int) Math.round(params[np + 3]) : 128;
- int nz = params.length > np + 4 ? (int) Math.round(params[np + 4]) : 128;
- double cx = params.length > np + 5 ? params[np + 5] : 0.5;
- double cy = params.length > np + 6 ? params[np + 6] : 0.5;
- double cz = params.length > np + 7 ? params[np + 7] : 0.5;
- factory = factory.center(cx, cy, cz);
- RealSignal x = factory.generate(nx, ny, nz);
- return x;
- }
- }
- }
- if (arg.equalsIgnoreCase("file") || arg.equalsIgnoreCase("dir") || arg.equalsIgnoreCase("directory")) {
- RealSignal signal = null;
- File file = new File(path + File.separator + cmd);
- if (file != null) {
- if (file.isFile())
- signal = Lab.open(monitors, path + File.separator + cmd);
- if (file.isDirectory())
- signal = Lab.openDir(monitors, path + File.separator + cmd);
- }
- if (signal == null) {
- File local = new File(cmd);
- if (local != null) {
- if (local.isFile())
- signal = Lab.open(monitors, cmd);
- if (local.isDirectory())
- signal = Lab.openDir(monitors, cmd);
- }
- }
- return signal;
-
- }
-
- if (arg.equalsIgnoreCase("platform")) {
- return Lab.getImager().create(cmd);
- }
-
- return null;
+ psf = Lab.createRealSignal(monitors, arg, cmd, path);
+ return psf;
}
+
public void addDeconvolutionListener(DeconvolutionListener listener) {
listeners.add(listener);
}
public OutputCollection getOuts() {
return outs;
}
public void setAlgorithm(AbstractAlgorithm algo, Controller controller) {
this.algo = algo;
if (algo != null && controller != null) {
algo.setController(controller);
}
}
public AbstractAlgorithm getAlgo() {
return algo;
}
public void setPath(String path) {
this.path = path;
}
public String getPath() {
return path;
}
public void setNormalization(double norm) {
this.norm = norm;
}
public void setPadding(Padding pad) {
this.pad = pad;
}
public Padding getPadding() {
return pad;
}
+
+ public RealSignal getOutput() {
+ return deconvolvedImage;
+ }
+
+ public RealSignal getImage() {
+ return image;
+ }
+
+ public RealSignal getPSF() {
+ return psf;
+ }
+ public Features getDeconvolutionReports() {
+ return report;
+ }
+
+ public String getName() {
+ return name;
+ }
+
public void setApodization(Apodization apo) {
this.apo = apo;
}
public Apodization getApodization() {
return apo;
}
public void setOutput(OutputCollection outs) {
this.outs = outs;
}
public void setVerbose(Verbose verbose) {
this.verbose = verbose;
}
public void setFFT(AbstractFFTLibrary fft) {
this.fft = fft;
}
public void setMonitor(int flagMonitor) {
this.flagMonitor = flagMonitor;
}
public void setStats(int flagStats) {
this.flagStats = flagStats;
}
public void setFlags(boolean flagDisplay, boolean flagMultithreading, boolean flagSystem) {
this.flagDisplay = flagDisplay;
this.flagMultithreading = flagMultithreading;
this.flagSystem = flagSystem;
}
public String getCommand() {
return command;
}
+
+
}
diff --git a/DeconvolutionLab2/src/deconvolution/DeconvolutionDialog.java b/DeconvolutionLab2/src/deconvolution/DeconvolutionDialog.java
index 5e572ad..718fdd7 100644
--- a/DeconvolutionLab2/src/deconvolution/DeconvolutionDialog.java
+++ b/DeconvolutionLab2/src/deconvolution/DeconvolutionDialog.java
@@ -1,359 +1,379 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JToolBar;
import deconvolution.modules.AlgorithmDModule;
import deconvolution.modules.ImageDModule;
import deconvolution.modules.PSFDModule;
import deconvolution.modules.RecapDModule;
import deconvolution.modules.ReportDModule;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
import deconvolutionlab.Lab;
import deconvolutionlab.TableStats;
+import deconvolutionlab.monitor.StatusMonitor;
import deconvolutionlab.monitor.TableMonitor;
import lab.component.BorderToggledButton;
import lab.component.JPanelImage;
-public class DeconvolutionDialog extends JDialog implements ActionListener, Runnable, DeconvolutionListener {
+public class DeconvolutionDialog extends JDialog implements WindowListener, ActionListener, Runnable {
public enum State {
NOTDEFINED, READY, RUN, FINISH
};
-
+
public enum Module {
ALL, RECAP, IMAGE, PSF, ALGO
};
private JButton bnStart = new JButton("Run");
private JButton bnStop = new JButton("Stop");
private JButton bnReset = new JButton("Reset");
private JButton bnHelp = new JButton("Help");
private JButton bnQuit = new JButton("Quit");
private BorderToggledButton bnRecap = new BorderToggledButton("Recap");
private BorderToggledButton bnImage = new BorderToggledButton("Image");
private BorderToggledButton bnPSF = new BorderToggledButton("PSF");
private BorderToggledButton bnAlgo = new BorderToggledButton("Algorithm");
private BorderToggledButton bnReport = new BorderToggledButton("Report");
private BorderToggledButton bnMonitor = new BorderToggledButton("Monitor");
private BorderToggledButton bnStats = new BorderToggledButton("Stats");
- private String job = "";
private Thread thread = null;
private Deconvolution deconvolution;
- private State state = State.NOTDEFINED;
private JProgressBar progress = new JProgressBar();
public static Point location = new Point(0, 0);
private JPanel cards = new JPanel(new CardLayout());
private boolean flagMonitor = false;
private boolean flagStats = false;
- private ImageDModule image;
- private PSFDModule psf;
- private RecapDModule recap;
- private AlgorithmDModule algorithm;
- private ReportDModule report;
-
+ private ImageDModule image;
+ private PSFDModule psf;
+ private RecapDModule recap;
+ private AlgorithmDModule algorithm;
+ private ReportDModule report;
+
+ private TableStats tableStats;
+ private TableMonitor tableMonitor;
+
public DeconvolutionDialog(Module module, Deconvolution deconvolution, TableMonitor tableMonitor, TableStats tableStats) {
super(new JFrame(), deconvolution.getName());
this.deconvolution = deconvolution;
-
+ this.tableMonitor = tableMonitor;
+ this.tableStats = tableStats;
+
image = new ImageDModule(deconvolution);
psf = new PSFDModule(deconvolution);
recap = new RecapDModule(deconvolution);
algorithm = new AlgorithmDModule(deconvolution);
report = new ReportDModule(deconvolution);
-
+
// Panel status bar on bottom
progress.setAlignmentX(JLabel.CENTER_ALIGNMENT);
progress.setBorder(BorderFactory.createLoweredBevelBorder());
JToolBar statusBar = new JToolBar();
statusBar.setBorder(BorderFactory.createLoweredBevelBorder());
statusBar.setFloatable(false);
statusBar.setLayout(new BorderLayout());
statusBar.add(bnHelp, BorderLayout.WEST);
statusBar.add(progress, BorderLayout.CENTER);
statusBar.add(bnQuit, BorderLayout.EAST);
// Panel bottom
JPanel bottom = new JPanel();
bottom.setLayout(new BoxLayout(bottom, BoxLayout.PAGE_AXIS));
- bottom.add(statusBar);
// Panel buttons
if (module == Module.ALL) {
JPanelImage buttons = new JPanelImage("celegans.jpg");
buttons.setLayout(new FlowLayout());
buttons.setBorder(BorderFactory.createEtchedBorder());
buttons.add(bnReset);
buttons.add(bnStop);
buttons.add(bnStart);
bottom.add(buttons);
}
-
+ bottom.add(statusBar);
+
// Panel Image
cards.add(recap.getName(), recap.getPane());
cards.add(image.getName(), image.getPane());
cards.add(psf.getName(), psf.getPane());
cards.add(algorithm.getName(), algorithm.getPane());
cards.add(report.getName(), report.getPane());
if (tableMonitor != null)
cards.add("Monitor", tableMonitor.getPanel());
if (tableStats != null)
cards.add("Stats", tableStats.getPanel());
// Panel Main
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(cards, BorderLayout.CENTER);
panel.add(bottom, BorderLayout.SOUTH);
// Panel tool with all buttons
if (module == Module.ALL) {
JToolBar tool = new JToolBar();
tool.setFloatable(false);
tool.setLayout(new GridLayout(1, 6));
tool.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
tool.add(bnRecap);
tool.add(bnImage);
tool.add(bnPSF);
tool.add(bnAlgo);
- tool.add(bnMonitor);
- tool.add(bnStats);
+ if (tableMonitor != null)
+ tool.add(bnMonitor);
+ if (tableStats != null)
+ tool.add(bnStats);
tool.add(bnReport);
panel.add(tool, BorderLayout.NORTH);
}
add(panel);
bnReset.addActionListener(this);
bnQuit.addActionListener(this);
bnStart.addActionListener(this);
bnStop.addActionListener(this);
bnHelp.addActionListener(this);
bnImage.addActionListener(this);
bnPSF.addActionListener(this);
bnAlgo.addActionListener(this);
bnRecap.addActionListener(this);
- bnMonitor.addActionListener(this);
- bnStats.addActionListener(this);
+ if (tableMonitor != null)
+ bnMonitor.addActionListener(this);
+ if (tableStats != null)
+ bnStats.addActionListener(this);
bnReport.addActionListener(this);
- deconvolution.addDeconvolutionListener(this);
+ this.addWindowListener(this);
setMinimumSize(new Dimension(Constants.widthGUI, 400));
setPreferredSize(new Dimension(Constants.widthGUI, 400));
pack();
Config.registerFrame("DeconvolutionLab", "DeconvolutionDialog", this);
-
+
Rectangle rect = Config.getDialog("DeconvolutionLab.DeconvolutionDialog");
if (rect.x > 0 && rect.y > 0)
setLocation(rect.x, rect.y);
bnStop.setEnabled(false);
- if (module == Module.ALL)
+ if (module == Module.ALL) {
toggle(bnRecap);
- if (module == Module.IMAGE)
+ recap.update();
+ }
+ if (module == Module.IMAGE) {
toggle(bnImage);
- if (module == Module.PSF)
+ deconvolution.monitors.add(new StatusMonitor(getProgressBar()));
+ image.update();
+ }
+ if (module == Module.PSF) {
toggle(bnPSF);
- if (module == Module.ALGO)
+ deconvolution.monitors.add(new StatusMonitor(getProgressBar()));
+ psf.update();
+ }
+ if (module == Module.ALGO) {
toggle(bnAlgo);
- if (module == Module.RECAP)
- toggle(bnPSF);
- state = State.READY;
-
+ deconvolution.monitors.add(new StatusMonitor(getProgressBar()));
+ algorithm.update();
+ }
+ if (module == Module.RECAP) {
+ toggle(bnRecap);
+ recap.update();
+ }
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == bnStart) {
if (flagMonitor)
toggle(bnMonitor);
else if (flagStats)
toggle(bnStats);
-
+
if (thread == null) {
- job = bnStart.getText();
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
}
else if (e.getSource() == bnStop) {
toggle(bnReport);
- finish();
if (deconvolution != null)
deconvolution.abort();
}
else if (e.getSource() == bnImage) {
toggle(bnImage);
- if (thread == null) {
- job = bnImage.getText();
- thread = new Thread(this);
- thread.setPriority(Thread.MIN_PRIORITY);
- thread.start();
- }
+ image.update();
}
else if (e.getSource() == bnPSF) {
toggle(bnPSF);
- if (thread == null) {
- job = bnPSF.getText();
- thread = new Thread(this);
- thread.setPriority(Thread.MIN_PRIORITY);
- thread.start();
- }
+ psf.update();
}
else if (e.getSource() == bnAlgo) {
toggle(bnAlgo);
- if (thread == null) {
- job = bnAlgo.getText();
- thread = new Thread(this);
- thread.setPriority(Thread.MIN_PRIORITY);
- thread.start();
- }
+ algorithm.update();
}
else if (e.getSource() == bnRecap) {
toggle(bnRecap);
recap.update();
}
else if (e.getSource() == bnReport) {
toggle(bnReport);
report.update();
}
else if (e.getSource() == bnReset) {
toggle(bnRecap);
- state = State.READY;
+ if (tableMonitor != null)
+ tableMonitor.clear();
+ if (tableStats != null)
+ tableStats.clear();
+
bnStart.setEnabled(true);
}
else if (e.getSource() == bnQuit) {
- deconvolution.finalize();
+ deconvolution.close();
deconvolution = null;
dispose();
}
else if (e.getSource() == bnHelp)
Lab.help();
else if (e.getSource() == bnMonitor)
toggle(bnMonitor);
else if (e.getSource() == bnStats)
toggle(bnStats);
}
@Override
public void run() {
bnRecap.setEnabled(false);
bnImage.setEnabled(false);
bnPSF.setEnabled(false);
bnAlgo.setEnabled(false);
+ bnStart.setEnabled(false);
+ bnStop.setEnabled(true);
deconvolution.setCommand(recap.getCommand());
- if (job.equals(bnStart.getText())) {
- bnStart.setEnabled(false);
- bnStop.setEnabled(true);
- deconvolution.run();
- toggle(bnReport);
- bnStop.setEnabled(false);
- }
- else if (job.equals(bnImage.getText()))
- image.update();
- else if (job.equals(bnPSF.getText()))
- psf.update();
- else if (job.equals(bnAlgo.getText()))
- algorithm.update();
+ deconvolution.run();
+ toggle(bnReport);
+
+ bnStop.setEnabled(false);
+ report.update();
bnRecap.setEnabled(true);
bnAlgo.setEnabled(true);
bnPSF.setEnabled(true);
bnImage.setEnabled(true);
thread = null;
- toggle(bnReport);
- report.update();
- }
-
- @Override
- public void started() {
- state = State.RUN;
- }
-
- @Override
- public void finish() {
- state = State.FINISH;
- }
-
- public JProgressBar getProgressBar() {
- return progress;
}
public static void setLocationLaunch(Point l) {
location = l;
}
private void toggle(BorderToggledButton bn) {
((CardLayout) (cards.getLayout())).show(cards, bn.getText());
bnRecap.setSelected(false);
bnImage.setSelected(false);
bnPSF.setSelected(false);
bnAlgo.setSelected(false);
bnMonitor.setSelected(false);
bnStats.setSelected(false);
bnReport.setSelected(false);
bn.setSelected(true);
}
+ @Override
+ public void windowOpened(WindowEvent e) {
+ }
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ deconvolution.close();
+ deconvolution = null;
+ dispose();
+ }
+
+ @Override
+ public void windowClosed(WindowEvent e) {
+ }
+
+ @Override
+ public void windowIconified(WindowEvent e) {
+ }
+
+ @Override
+ public void windowDeiconified(WindowEvent e) {
+ }
+
+ @Override
+ public void windowActivated(WindowEvent e) {
+ }
+
+ @Override
+ public void windowDeactivated(WindowEvent e) {
+ }
+
+ public JProgressBar getProgressBar() {
+ return progress;
+ }
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithm.java b/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithm.java
index f80252b..33fe094 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithm.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithm.java
@@ -1,223 +1,240 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import deconvolutionlab.monitor.Monitors;
import fft.AbstractFFT;
import fft.AbstractFFTLibrary;
import fft.FFT;
import lab.tools.NumFormat;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
import signal.apodization.Apodization;
import signal.padding.Padding;
/**
* This class is the common part of every algorithm of deconvolution.
*
* @author Daniel Sage
*
*/
public abstract class AbstractAlgorithm implements Callable<RealSignal> {
+ /** y is the input signal of the deconvolution. */
protected RealSignal y = null;
+
+ /** h is the PSF signal for the deconvolution. */
protected RealSignal h = null;
+
+ /** The controller takes the control of the algorithm, in
+ * particular to do some operations at the starting,
+ * at every iteration and at the end. */
protected Controller controller = null;
+
+ /** This is the FFT used. */
protected AbstractFFT fft = null;
+
+ /** Shortname of the algorithm given by the user, useful in particular to deal with the synonym. */
protected String shortname = "I";
+ /** Optimized implementation in term of memory footprint */
+ protected boolean optimizedMemoryFootprint = true;
+
public AbstractAlgorithm() {
this.controller = new Controller();
}
public void setShortname(String shortname) {
this.shortname = shortname;
}
public String getShortname() {
return shortname;
}
+ public void setOptimizedMemoryFootprint(boolean optimizedMemoryFootprint) {
+ this.optimizedMemoryFootprint = optimizedMemoryFootprint;
+ }
+
public abstract String getName();
-
+ public abstract double getMemoryFootprintRatio();
+ public abstract int getComplexityNumberofFFT();
public abstract boolean isRegularized();
-
public abstract boolean isStepControllable();
-
public abstract boolean isIterative();
-
public abstract boolean isWaveletsBased();
-
public abstract void setParameters(double[] params);
-
public abstract double getRegularizationFactor();
-
public abstract double getStepFactor();
-
public abstract double[] getParameters();
-
public abstract double[] getDefaultParameters();
public RealSignal run(Monitors monitors,
RealSignal image, RealSignal psf,
AbstractFFTLibrary fftlib, Padding pad, Apodization apo, double norm, boolean threaded) {
-
+
if (image == null)
return null;
if (psf == null)
return null;
if (fftlib != null)
fft = FFT.createFFT(monitors, fftlib, image.nx, image.ny, image.nz);
else
fft = FFT.createDefaultFFT(monitors, image.nx, image.ny, image.nz);
-
controller.setFFT(fft);
-
- y = (pad == null ? image.duplicate() : pad.pad(monitors, apo.apodize(monitors, image)));
+
+ y = pad.pad(monitors, image);
+ y.setName("y");
+ apo.apodize(monitors, y);
monitors.log("Input: " + y.dimAsString());
- h = psf.changeSizeAs(y).normalize(norm);
- monitors.log("PSF: " + h.dimAsString());
-
- monitors.log("PSF: normalization " + (norm <= 0 ? "no" : norm));
+ h = psf.changeSizeAs(y);
+ h.setName("h");
+ h.normalize(norm);
+ monitors.log("PSF: " + h.dimAsString() + " normalized " + (norm <= 0 ? "no" : norm));
String iterations = (isIterative() ? controller.getIterationMax() + " iterations" : "direct");
monitors.log(getShortname() + " is starting (" + iterations + ")");
controller.setMonitors(monitors);
controller.start(y);
- h = Operations.circularShift(h);
+
+ h.circular();
if (fft == null)
fft = FFT.createDefaultFFT(monitors, y.nx, y.ny, y.nz);
else
fft.init(monitors, y.nx, y.ny, y.nz);
monitors.log(getShortname() + " data ready");
double params[] = getParameters();
if (params != null) {
if (params.length > 0) {
String s = " ";
for (double param : params)
s += "" + param + " ";
monitors.log(getShortname() + s);
}
}
RealSignal x = null;
+
try {
if (threaded == true) {
ExecutorService pool = Executors.newSingleThreadExecutor();
Future<RealSignal> future = pool.submit(this);
x = future.get();
}
else {
x = call();
}
}
catch (InterruptedException ex) {
ex.printStackTrace();
x = y.duplicate();
}
catch (ExecutionException ex) {
ex.printStackTrace();
x = y.duplicate();
}
catch (Exception e) {
e.printStackTrace();
x = y.duplicate();
}
-
+ x.setName("x");
controller.finish(x);
monitors.log(getName() + " is finished");
-
+ SignalCollector.free(y);
+ SignalCollector.free(h);
+
RealSignal result = pad.crop(monitors, x);
-
+ SignalCollector.free(x);
return result;
}
public AbstractFFT getFFT() {
return fft;
}
public void setFFT(AbstractFFT fft) {
this.fft = fft;
}
public Controller getController() {
return controller;
}
public void setController(Controller controller) {
this.controller = controller;
}
public int getIterations() {
return controller.getIterations();
}
public double getTime() {
return controller.getTimeNano();
}
public double getMemory() {
return controller.getMemory();
}
public void setWavelets(String waveletsName) {
}
@Override
public String toString() {
String s = "";
s += getName();
s += (isIterative() ? ", " + controller.getIterationMax() + " iterations" : " (direct)");
s += (isRegularized() ? ", &lambda=" + NumFormat.nice(getRegularizationFactor()) : "");
s += (isStepControllable() ? ", &gamma=" + NumFormat.nice(getStepFactor()) : "");
return s;
}
public String getParametersAsString() {
double p[] = getParameters();
String param = "";
for(int i=0; i<p.length; i++)
if (i==p.length-1)
param += p[i];
else
param += p[i] + ", ";
return param;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java b/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
index e61983e..9ec9346 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
@@ -1,144 +1,158 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.ArrayList;
public class Algorithm {
+ /** This is the static list of all available algorithms. */
private static ArrayList<AbstractAlgorithmPanel> list;
static {
list = new ArrayList<AbstractAlgorithmPanel>();
list.add(new RegularizedInverseFilterPanel());
list.add(new TikhonovRegularizationInverseFilterPanel());
list.add(new NaiveInverseFilterPanel());
list.add(new FISTAPanel());
list.add(new ISTAPanel());
list.add(new LandweberPanel());
list.add(new LandweberPositivityPanel());
list.add(new StarkParkerPanel());
list.add(new RichardsonLucyPanel());
list.add(new RichardsonLucyTVPanel());
list.add(new TikhonovMillerPanel());
list.add(new ICTMPanel());
list.add(new VanCittertPanel());
list.add(new IdentityPanel());
list.add(new ConvolutionPanel());
list.add(new SimulationPanel());
list.add(new NonStabilizedDivisionPanel());
}
public static ArrayList<AbstractAlgorithmPanel> getAvailableAlgorithms() {
return list;
}
public static AbstractAlgorithm getDefaultAlgorithm() {
return new Identity();
}
- public static AbstractAlgorithm createAlgorithm(String name) {
+ /**
+ * This static method return the algorithm specify by one of its shortname,
+ *
+ * @param shortname
+ * @return an algorithm
+ */
+ public static AbstractAlgorithm createAlgorithm(String shortname) {
AbstractAlgorithm algo = getDefaultAlgorithm();
- String n = name.trim().toLowerCase();
+ String n = shortname.trim().toLowerCase();
int i = 0;
if (list.get(i++).isNamed(n))
algo = new RegularizedInverseFilter(0.1);
else if (list.get(i++).isNamed(n))
algo = new TikhonovRegularizationInverseFilter(1.0);
else if (list.get(i++).isNamed(n))
algo = new NaiveInverseFilter();
else if (list.get(i++).isNamed(n))
algo = new FISTA(10, 1, 1, "Haar", 3);
else if (list.get(i++).isNamed(n))
algo = new ISTA(10, 1, 1, "Haar", 3);
else if (list.get(i++).isNamed(n))
algo = new Landweber(10, 1);
else if (list.get(i++).isNamed(n))
algo = new LandweberPositivity(10, 1);
else if (list.get(i++).isNamed(n))
algo = new StarkParker(10, 1);
else if (list.get(i++).isNamed(n))
algo = new RichardsonLucy(10);
else if (list.get(i++).isNamed(n))
algo = new RichardsonLucyTV(10, 1);
else if (list.get(i++).isNamed(n))
algo = new TikhonovMiller(10, 1, 0.1);
else if (list.get(i++).isNamed(n))
algo = new ICTM(10, 1, 0.1);
else if (list.get(i++).isNamed(n))
algo = new VanCittert(10, 1);
else if (list.get(i++).isNamed(n))
algo = new Identity();
else if (list.get(i++).isNamed(n))
algo = new Convolution();
else if (list.get(i++).isNamed(n))
algo = new Simulation(0, 1, 0);
else if (list.get(i++).isNamed(n))
algo = new NonStabilizedDivision();
else
algo = getDefaultAlgorithm();
if (algo != null)
- algo.setShortname(name);
+ algo.setShortname(shortname);
return algo;
}
- public static AbstractAlgorithmPanel getPanel(String name) {
+ /**
+ * This static method return the panel associated with
+ * the algorithm specify by one of its shortname,
+ *
+ * @param shortname
+ * @return an algorithm's panel
+ */
+ public static AbstractAlgorithmPanel getPanel(String shortname) {
for (AbstractAlgorithmPanel panel : getAvailableAlgorithms()) {
for(String sn : panel.getShortname())
- if (sn.equals(name.trim()))
+ if (sn.equals(shortname.trim()))
return panel;
- if (panel.getName().equals(name.trim()))
+ if (panel.getName().equals(shortname.trim()))
return panel;
}
return null;
}
public static ArrayList<String> getShortnames() {
ArrayList<String> list = new ArrayList<String>();
for (AbstractAlgorithmPanel algo : getAvailableAlgorithms()) {
for(String sn : algo.getShortname())
list.add(sn);
}
return list;
}
public static String getDocumentation(String name) {
for (AbstractAlgorithmPanel algo : getAvailableAlgorithms()) {
if (name.equals(algo.getName()))
return algo.getDocumentation();
}
return "Unknown Algorithm";
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java b/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java
index 26c1b75..67ee002 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java
@@ -1,335 +1,353 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.Timer;
import java.util.TimerTask;
import deconvolution.Deconvolution;
import deconvolutionlab.OutputCollection;
import deconvolutionlab.TableStats;
import deconvolutionlab.monitor.Monitors;
import deconvolutionlab.system.SystemUsage;
import fft.AbstractFFT;
import fft.FFT;
import lab.tools.NumFormat;
import signal.Assessment;
import signal.ComplexSignal;
import signal.Constraint;
import signal.RealSignal;
import signal.SignalCollector;
+/**
+ * This is an important class to manage all the common task
+ * of the algorithm.
+ * The method start() is called before at the starting of the
+ * algorithm.
+ * The method ends() is called at the end of every iterations
+ * for the iterative algorithm. It returns true if one the
+ * stopping criteria is true.
+ * The method finish() is called when the algorithm is completely
+ * terminated.
+ *
+ * @author sage
+ *
+ */
public class Controller {
private int iterationsMax = 100;
private double timeMax = 1000;
private double residuMin = -1;
private boolean doResidu = false;
private boolean doTime = false;
private boolean doReference = false;
private boolean doConstraint = false;
private boolean abort = false;
private double timeStarting = 0;
private double memoryStarting = 0;
private double residu = Double.MAX_VALUE;
private int iterations = 0;
private double memoryPeak = 0;
private double snr = 0;
private double psnr = 0;
private Constraint.Mode constraint = Constraint.Mode.NO;
private OutputCollection outs = null;
private String referenceName = "";
private RealSignal refImage;
private RealSignal prevImage;
private RealSignal x;
private Timer timer;
private AbstractFFT fft;
private TableStats tableStats;
private float[] statsInput;
private Monitors monitors = new Monitors();
public Controller() {
constraint = Constraint.Mode.NO;
doResidu = false;
doTime = false;
doReference = false;
doConstraint = false;
}
public void setTableStats(TableStats tableStats) {
this.tableStats = tableStats;
}
public void setMonitors(Monitors monitors) {
this.monitors = monitors;
}
public void setFFT(AbstractFFT fft) {
this.fft = fft;
}
public void abort() {
this.abort = true;
}
public int getIterationMax() {
return iterationsMax;
}
public void setIterationMax(int iterationsMax) {
this.iterationsMax = iterationsMax;
}
public void setTimeStop(double timeMax) {
this.doTime = true;
this.timeMax = timeMax * 1e9;
}
public void setResiduStop(double residuMin) {
this.doResidu = true;
this.residuMin = residuMin;
}
public void setReference(String referenceName) {
this.doReference = true;
this.referenceName = referenceName;
}
public void setConstraint(Constraint.Mode constraint) {
this.doConstraint = true;
this.constraint = constraint;
}
public void setOutputs(OutputCollection outs) {
this.outs = outs;
}
+ public boolean needSpatialComputation() {
+ return doConstraint || doResidu || doReference;
+ }
+
public void start(RealSignal x) {
this.x = x;
statsInput = x.getStats();
if (tableStats != null)
tableStats.nextStats(monitors, stats());
iterations = 0;
timer = new Timer();
timer.schedule(new Updater(), 0, 100);
timeStarting = System.nanoTime();
memoryStarting = SystemUsage.getHeapUsed();
if (doConstraint && x != null)
Constraint.setModel(x);
if (doReference) {
refImage = new Deconvolution("Reference", "-image file " + referenceName).openImage();
if (refImage == null)
monitors.error("Impossible to load the reference image " + referenceName);
else
monitors.log("Reference image loaded");
}
if (outs != null)
outs.executeStarting(monitors, x, this);
this.prevImage = x;
}
public boolean ends(ComplexSignal X) {
boolean out = outs == null ? false : outs.hasShow(iterations);
if (doConstraint || doResidu || doReference || out) {
if (fft == null)
fft = FFT.createDefaultFFT(monitors, X.nx, X.ny, X.nz);
x = fft.inverse(X, x);
return ends(x);
}
return ends((RealSignal) null);
}
public boolean ends(RealSignal x) {
this.x = x;
if (doConstraint || doResidu || doReference)
compute(iterations, x, doConstraint, doResidu, doReference);
if (outs != null)
outs.executeIterative(monitors, x, this, iterations);
iterations++;
double p = iterations * 100.0 / iterationsMax;
monitors.progress("Iterative " + iterations + "/" + iterationsMax, p);
double timeElapsed = getTimeNano();
boolean stopIter = (iterations >= iterationsMax);
boolean stopTime = doTime && (timeElapsed >= timeMax);
boolean stopResd = doResidu && (residu <= residuMin);
monitors.log("@" + iterations + " Time: " + NumFormat.seconds(timeElapsed));
if (tableStats != null)
tableStats.nextStats(monitors, stats());
String prefix = "Stopped>> by ";
if (abort)
monitors.log(prefix + "abort");
if (stopIter)
monitors.log(prefix + "iteration " + iterations + " > " + iterationsMax);
if (stopTime)
monitors.log(prefix + "time " + timeElapsed + " > " + timeMax);
if (stopResd)
monitors.log(prefix + "residu " + NumFormat.nice(residu) + " < " + NumFormat.nice(residuMin));
return abort | stopIter | stopTime | stopResd;
}
public void finish(RealSignal x) {
this.x = x;
boolean ref = doReference;
boolean con = doConstraint;
boolean res = doResidu;
if (con || res || ref)
compute(iterations, x, con, res, ref);
if (tableStats != null)
tableStats.lastStats(monitors, stats());
if (outs != null)
outs.executeFinal(monitors, x, this);
monitors.log("Time: " + NumFormat.seconds(getTimeNano()) + " Peak:" + getMemoryAsString());
if (timer != null)
timer.cancel();
}
private void compute(int iterations, RealSignal x, boolean con, boolean res, boolean ref) {
if (x == null)
return;
if (con && constraint != null)
new Constraint(monitors).apply(x, constraint);
if (ref && refImage != null) {
String s = "";
psnr = Assessment.psnr(x, refImage);
snr = Assessment.snr(x, refImage);
s += " PSNR: " + NumFormat.nice(psnr);
s += " SNR: " + NumFormat.nice(snr);
monitors.log("@" + iterations + " " + s);
}
residu = Double.MAX_VALUE;
if (res && prevImage != null) {
residu = Assessment.relativeResidu(x, prevImage);
prevImage = x.duplicate();
monitors.log("@" + iterations + " Residu: " + NumFormat.nice(residu));
}
}
public String[] stats() {
if (tableStats == null)
return null;
float params[] = null;
if (x != null)
params = x.getStats();
String[] row = new String[12];
row[0] = "" + iterations;
row[1] = (params == null ? "-" : "" + params[0]);
row[2] = (params == null ? "-" : "" + params[1]);
row[3] = (params == null ? "-" : "" + params[2]);
row[4] = (params == null ? "-" : "" + params[3]);
row[5] = (params == null ? "-" : "" + params[5]);
row[6] = NumFormat.seconds(getTimeNano());
row[7] = NumFormat.bytes(SystemUsage.getHeapUsed());
row[8] = SignalCollector.sumarize();
row[9] = doReference ? NumFormat.nice(psnr) : "n/a";
row[10] = doReference ? NumFormat.nice(snr) : "n/a";
row[11] = doResidu ? NumFormat.nice(residu) : "n/a";
return row;
}
public double getTimeNano() {
return (System.nanoTime() - timeStarting);
}
public Constraint.Mode getConstraint() {
return constraint;
}
public String getReference() {
return doReference ? referenceName : "no ground-truth";
}
public String getConstraintAsString() {
if (!doConstraint)
return "no";
if (constraint == null)
return "null";
return constraint.name().toLowerCase();
}
public String getStoppingCriteriaAsString(AbstractAlgorithm algo) {
- String stop = algo.isIterative() ? " iterations limit=" + getIterationMax() + ", " : "direct, ";
+ String stop = algo.isIterative() ? "iterations limit=" + getIterationMax() + ", " : "direct, ";
stop += doTime ? ", time limit=" + NumFormat.nice(timeMax * 1e-9) : " no time limit" + ", ";
stop += doResidu ? ", residu limit=" + NumFormat.nice(residuMin) : " no residu limit";
return stop;
}
public float[] getStatsInput() {
return statsInput;
}
public double getMemory() {
return memoryPeak - memoryStarting;
}
public String getMemoryAsString() {
return NumFormat.bytes(getMemory());
}
public int getIterations() {
return iterations;
}
private void update() {
memoryPeak = Math.max(memoryPeak, SystemUsage.getHeapUsed());
}
private class Updater extends TimerTask {
@Override
public void run() {
update();
}
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.java b/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.java
index f320e91..0970991 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.java
@@ -1,104 +1,118 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
public class Convolution extends AbstractAlgorithm implements Callable<RealSignal> {
public Convolution() {
super();
}
@Override
public RealSignal call() {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal X = Operations.multiply(H, Y);
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
return x;
}
@Override
public String getName() {
return "Convolution Noiseless [CONV]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3;
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 8.0;
+ }
+
@Override
public boolean isRegularized() {
return false;
}
@Override
public boolean isStepControllable() {
return false;
}
@Override
public boolean isIterative() {
return false;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
}
@Override
public double[] getParameters() {
return new double[] {};
}
@Override
public double[] getDefaultParameters() {
return new double[] {};
}
@Override
public double getRegularizationFactor() {
return 0.0;
}
@Override
public double getStepFactor() {
return 0;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/ConvolutionPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/ConvolutionPanel.java
index ce7fe4a..5213e96 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ConvolutionPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ConvolutionPanel.java
@@ -1,72 +1,72 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import javax.swing.JPanel;
import lab.component.GridPanel;
public class ConvolutionPanel extends AbstractAlgorithmPanel {
private Convolution algo = new Convolution();
@Override
public JPanel getPanelParameters() {
GridPanel pn = new GridPanel(false);
pn.place(1, 0, "<html><span \"nowrap\">No parameters</span></html>");
return pn;
}
@Override
public String getCommand() {
return "";
}
@Override
public String getName() {
return algo.getName();
}
@Override
public String[] getShortname() {
return new String[] {"CONV"};
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
- s += "<p>This algorithm is only used for simulation. It convolves the input image with the PSF.</p>";
+ s += "<p>This algorithm is only used for simulation. It make a pure convolution of the input image with the PSF in the Fourier domain.</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/FISTA.java b/DeconvolutionLab2/src/deconvolution/algorithm/FISTA.java
index ded7bd0..657f0c0 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/FISTA.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/FISTA.java
@@ -1,164 +1,183 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
import wavelets.AbstractWavelets;
import wavelets.Wavelets;
public class FISTA extends AbstractAlgorithm implements Callable<RealSignal> {
private double gamma = 1.0;
private double lambda = 0.1;
private String waveletsName = "Haar";
private int scale = 3;
public FISTA(int iter, double gamma, double lambda, String waveletsName, int scale) {
super();
controller.setIterationMax(iter);
this.gamma = gamma;
this.lambda = lambda;
this.waveletsName = waveletsName;
this.scale = scale;
}
@Override
public RealSignal call() throws Exception {
AbstractWavelets wavelets = Wavelets.getWaveletsByName(waveletsName);
wavelets.setScale(scale);
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal A = Operations.delta(gamma, H);
ComplexSignal G = Operations.multiplyConjugate(gamma, H, Y);
-
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
ComplexSignal Z = G.duplicate();
RealSignal x = fft.inverse(G);
RealSignal s = x.duplicate();
RealSignal z = x.duplicate();
RealSignal xprev = fft.inverse(G);
float pk1 = 1f;
float pk0 = 1f;
float threshold = (float) (lambda * gamma * 0.5);
RealSignal buffer = y.duplicate();
while (!controller.ends(x)) {
fft.transform(s, Z);
Z.times(A);
Z.plus(G);
fft.inverse(Z, z);
wavelets.shrinkage(threshold, z, x, buffer);
pk0 = pk1;
pk1 = (1f + (float) Math.sqrt(1f + 4f * pk0 * pk0)) * 0.5f;
update(xprev, x, (pk0 - 1f) / pk1, s);
}
+ SignalCollector.free(A);
+ SignalCollector.free(Z);
+ SignalCollector.free(G);
+ SignalCollector.free(s);
+ SignalCollector.free(z);
+ SignalCollector.free(xprev);
+ SignalCollector.free(buffer);
return x;
}
public void update(RealSignal xprev, RealSignal x, double w, RealSignal s) {
int nxy = x.nx * x.ny;
for (int k = 0; k < x.nz; k++)
for (int i = 0; i < nxy; i++) {
float vx = x.data[k][i];
s.data[k][i] = (float) (vx + w * (vx - xprev.data[k][i]));
xprev.data[k][i] = vx;
}
}
@Override
public String getName() {
return "Fast Iterative Shrinkage-Thresholding [FISTA]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 4 + 4 * controller.getIterationMax();
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 15.0;
+ }
+
@Override
public boolean isRegularized() {
return true;
}
@Override
public boolean isStepControllable() {
return true;
}
@Override
public boolean isIterative() {
return true;
}
@Override
public boolean isWaveletsBased() {
return true;
}
@Override
public void setWavelets(String waveletsName) {
this.waveletsName = waveletsName;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
controller.setIterationMax((int) Math.round(params[0]));
if (params.length > 1)
gamma = (float) params[1];
if (params.length > 2)
lambda = (float) params[2];
if (params.length > 3)
scale = (int) params[3];
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10, 1, 0.1 };
}
@Override
public double[] getParameters() {
return new double[] { controller.getIterationMax(), gamma, lambda };
}
@Override
public double getRegularizationFactor() {
return lambda;
}
@Override
public double getStepFactor() {
return gamma;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java b/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java
index 6c0d28f..cec5094 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java
@@ -1,130 +1,148 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Constraint;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
import signal.factory.complex.ComplexSignalFactory;
public class ICTM extends AbstractAlgorithm implements Callable<RealSignal> {
private double gamma = 1.0;
private double lambda = 1.0;
public ICTM(int iter, double gamma, double lambda) {
super();
controller.setIterationMax(iter);
controller.setConstraint(Constraint.Mode.NONNEGATIVE);
this.gamma = gamma;
this.lambda = lambda;
}
@Override
public RealSignal call() throws Exception {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal A = Operations.delta(gamma, H);
ComplexSignal L = ComplexSignalFactory.laplacian(Y.nx, Y.ny, Y.nz);
ComplexSignal L2 = Operations.multiplyConjugate(lambda * gamma, L, L);
+ SignalCollector.free(L);
A.minus(L2);
+ SignalCollector.free(L2);
ComplexSignal G = Operations.multiplyConjugate(gamma, H, Y);
+ SignalCollector.free(H);
+ SignalCollector.free(Y);
ComplexSignal X = G.duplicate();
controller.setConstraint(Constraint.Mode.NONNEGATIVE);
while (!controller.ends(X)) {
X.times(A);
X.plus(G);
}
+ SignalCollector.free(A);
+ SignalCollector.free(G);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
return x;
}
@Override
public String getName() {
return "Iterative Contraint Tikhonov-Miller [ICTM]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3 + controller.getIterationMax() * 2;
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 10.0;
+ }
+
@Override
public boolean isRegularized() {
return true;
}
@Override
public boolean isStepControllable() {
return true;
}
@Override
public boolean isIterative() {
return true;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
controller.setIterationMax((int) Math.round(params[0]));
if (params.length > 1)
gamma = (float) params[1];
if (params.length > 2)
lambda = (float) params[2];
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10, 1, 0.1 };
}
@Override
public double[] getParameters() {
return new double[] { controller.getIterationMax(), gamma, lambda };
}
@Override
public double getRegularizationFactor() {
return lambda;
}
@Override
public double getStepFactor() {
return gamma;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java b/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java
index f92c932..d37c909 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java
@@ -1,156 +1,174 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
import wavelets.AbstractWavelets;
import wavelets.Wavelets;
public class ISTA extends AbstractAlgorithm implements Callable<RealSignal> {
private double gamma = 1.0;
private double lambda = 1.0;
private String waveletsName = "Haar";
private int scale = 3;
public ISTA(int iter, double gamma, double lambda, String waveletsName, int scale) {
super();
controller.setIterationMax(iter);
this.gamma = gamma;
this.lambda = lambda;
this.waveletsName = waveletsName;
this.scale = scale;
}
@Override
public RealSignal call() throws Exception {
AbstractWavelets wavelets = Wavelets.getWaveletsByName(waveletsName);
wavelets.setScale(scale);
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal A = Operations.delta(gamma, H);
ComplexSignal G = Operations.multiplyConjugate(gamma, H, Y);
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
ComplexSignal Z = G.duplicate();
RealSignal x = fft.inverse(G);
RealSignal z = x.duplicate();
float threshold = (float)(lambda*gamma*0.5);
RealSignal buffer = y.duplicate();
while(!controller.ends(x)) {
fft.transform(x, Z);
Z.times(A);
Z.plus(G);
fft.inverse(Z, z);
wavelets.shrinkage(threshold, z, x, buffer);
}
+ SignalCollector.free(A);
+ SignalCollector.free(Z);
+ SignalCollector.free(G);
+ SignalCollector.free(z);
+ SignalCollector.free(buffer);
return x;
}
public void update(RealSignal xprev, RealSignal x, double w, RealSignal s) {
int nxy = x.nx * x.ny;
for(int k=0; k<x.nz; k++)
for(int i=0; i< nxy; i++) {
float vx = x.data[k][i];
s.data[k][i] = (float)(vx + w*(vx - xprev.data[k][i]));
xprev.data[k][i] = vx;
}
}
@Override
public String getName() {
return "Iterative Shrinkage-Thresholding [ISTA]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3 + 4 * controller.getIterationMax();
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 13.0;
+ }
+
@Override
public boolean isRegularized() {
return true;
}
@Override
public boolean isStepControllable() {
return true;
}
@Override
public boolean isIterative() {
return true;
}
@Override
public boolean isWaveletsBased() {
return true;
}
@Override
public void setWavelets(String waveletsName) {
this.waveletsName = waveletsName;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
controller.setIterationMax((int)Math.round(params[0]));
if (params.length > 1)
gamma = (float)params[1];
if (params.length > 2)
lambda = (float)params[2];
if (params.length > 3)
scale = (int)params[3];
}
@Override
public double[] getDefaultParameters() {
return new double[] {10, 1, 0.1};
}
@Override
public double[] getParameters() {
return new double[] {controller.getIterationMax(), gamma, lambda};
}
@Override
public double getRegularizationFactor() {
return lambda;
}
@Override
public double getStepFactor() {
return gamma;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java b/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java
index 7bbafb0..194d690 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java
@@ -1,99 +1,109 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.RealSignal;
public class Identity extends AbstractAlgorithm implements Callable<RealSignal> {
public Identity() {
super();
}
@Override
public RealSignal call() {
return y.duplicate();
}
@Override
public String getName() {
return "Identity (copy)";
}
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 5.0;
+ }
+
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 1;
+ }
+
@Override
public boolean isRegularized() {
return false;
}
@Override
public boolean isStepControllable() {
return false;
}
@Override
public boolean isIterative() {
return false;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
}
@Override
public double[] getParameters() {
return new double[] {};
}
@Override
public double[] getDefaultParameters() {
return new double[] {};
}
@Override
public double getRegularizationFactor() {
return 0.0;
}
@Override
public double getStepFactor() {
return 0;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java b/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java
index 2e3c64e..d353893 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java
@@ -1,125 +1,142 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
public class Landweber extends AbstractAlgorithm implements Callable<RealSignal> {
private double gamma = 1.0;
public Landweber(int iter, double gamma) {
super();
controller.setIterationMax(iter);
this.gamma = gamma;
}
@Override
// Landweber algorithm
// X(n+1) = X(n) + g*H*(Y-H*X(n))
// => X(n+1) = X(n) - g*H*H*X(n) + g*H*Y
// => X(n+1) = X(n) * (I-g*H*H) + g*H*Y
// => pre-compute: A = (I-g*H*H) and G = g*H*Y
// => Iteration : X(n+1) = X(n) * A + G with F(0) = G
public RealSignal call() {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal A = Operations.delta(gamma, H);
ComplexSignal G = Operations.multiplyConjugate(gamma, H, Y);
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
ComplexSignal X = G.duplicate();
+ X.setName("X");
while (!controller.ends(X)) {
X.times(A);
X.plus(G);
}
- RealSignal x = fft.inverse(X);
+ SignalCollector.free(A);
+ SignalCollector.free(G);
+ RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
return x;
}
@Override
public String getName() {
return "Landweber [LW | LLS]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3 + (controller.needSpatialComputation() ? 2 * controller.getIterationMax() : 0);
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 9.0;
+ }
+
@Override
public boolean isRegularized() {
return false;
}
@Override
public boolean isStepControllable() {
return true;
}
@Override
public boolean isIterative() {
return true;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
controller.setIterationMax((int) Math.round(params[0]));
if (params.length > 1)
gamma = (float) params[1];
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10, 1 };
}
@Override
public double[] getParameters() {
return new double[] { controller.getIterationMax(), gamma };
}
@Override
public double getRegularizationFactor() {
return 0.0;
}
@Override
public double getStepFactor() {
return gamma;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
index 0f7eed6..34cafe1 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
@@ -1,128 +1,144 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Constraint;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
public class LandweberPositivity extends AbstractAlgorithm implements Callable<RealSignal> {
private double gamma = 1.0;
public LandweberPositivity(int iter, double gamma) {
super();
controller.setIterationMax(iter);
controller.setConstraint(Constraint.Mode.NONNEGATIVE);
this.gamma = gamma;
}
@Override
// Landweber algorithm
// X(n+1) = X(n) + g*H*(Y-H*X(n))
// => X(n+1) = X(n) - g*H*H*X(n) + g*H*Y
// => X(n+1) = X(n) * (I-g*H*H) + g*H*Y
// => pre-compute: A = (I-g*H*H) and G = g*H*Y
// => Iteration : X(n+1) = X(n) * A + G with F(0) = G
public RealSignal call() {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal A = Operations.delta(gamma, H);
ComplexSignal G = Operations.multiplyConjugate(gamma, H, Y);
ComplexSignal X = G.duplicate();
controller.setConstraint(Constraint.Mode.NONNEGATIVE);
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
while (!controller.ends(X)) {
X.times(A);
X.plus(G);
}
+ SignalCollector.free(A);
+ SignalCollector.free(G);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
return x;
}
@Override
public String getName() {
return "Non-Negative Least-Square [NNLS | LW+]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3 + controller.getIterationMax() * 2;
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 10.0;
+ }
+
@Override
public boolean isRegularized() {
return false;
}
@Override
public boolean isStepControllable() {
return true;
}
@Override
public boolean isIterative() {
return true;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
controller.setIterationMax((int) Math.round(params[0]));
if (params.length > 1)
gamma = (float) params[1];
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10, 1 };
}
@Override
public double[] getParameters() {
return new double[] { controller.getIterationMax(), gamma };
}
@Override
public double getRegularizationFactor() {
return 0.0;
}
@Override
public double getStepFactor() {
return gamma;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java
index e9cc00b..403d09e 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java
@@ -1,109 +1,109 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import deconvolution.Command;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
import lab.component.GridPanel;
import lab.component.SpinnerRangeDouble;
import lab.component.SpinnerRangeInteger;
import lab.tools.NumFormat;
public class LandweberPositivityPanel extends AbstractAlgorithmPanel implements ChangeListener {
private SpinnerRangeInteger spnIter = new SpinnerRangeInteger(10, 1, 99999, 1);
private SpinnerRangeDouble spnStep = new SpinnerRangeDouble(1, 0, 2, 0.1);
private LandweberPositivity algo = new LandweberPositivity(10, 1);
@Override
public JPanel getPanelParameters() {
double[] params = algo.getDefaultParameters();
spnIter.setPreferredSize(Constants.dimParameters);
spnStep.setPreferredSize(Constants.dimParameters);
GridPanel pn = new GridPanel(false);
pn.place(1, 0, "<html><span \"nowrap\"><b>Iterations</b></span></html>");
pn.place(1, 1, "<html><span \"nowrap\"><i>N</i></span></html>");
pn.place(1, 2, spnIter);
pn.place(1, 3, "<html><span \"nowrap\">Step <i>&gamma;</i></span></html>");
pn.place(1, 4, spnStep);
pn.place(2, 0, "<html><span \"nowrap\"><b>Regularization</b></span></html>");
pn.place(2, 1, 4, 1, "<html><span \"nowrap\">No regularization</i></span></html>");
Config.register("Algorithm." + algo.getShortname(), "iterations", spnIter, params[0]);
Config.register("Algorithm." + algo.getShortname(), "step", spnStep, params[1]);
spnIter.addChangeListener(this);
spnStep.addChangeListener(this);
return pn;
}
@Override
public String getCommand() {
int iter = spnIter.get();
double gamma = spnStep.get();
return iter + " " + NumFormat.nice(gamma);
}
@Override
public void stateChanged(ChangeEvent e) {
Command.command();
}
@Override
public String getName() {
return algo.getName();
}
@Override
public String[] getShortname() {
- return new String[] {"NNLS", "LW+"};
+ return new String[] {"NLLS", "LW+"};
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
s += "<p>Iterative: " + algo.isIterative() + "</p>";
s += "<p>Step controllable: " + algo.isStepControllable() + "</p>";
s += "<p>Regularization: " + algo.isRegularized() + "</p>";
s += "<p>Wavelet-base: " + algo.isWaveletsBased() + "</p>";
s += "<p>Shortname: " + getShortname() + "</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java b/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java
index 9db63b0..f2bbf6d 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java
@@ -1,104 +1,118 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
public class NaiveInverseFilter extends AbstractAlgorithm implements Callable<RealSignal> {
public NaiveInverseFilter() {
super();
}
@Override
public RealSignal call() {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal X = Operations.divideStabilized(Y, H);
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
return x;
}
@Override
public String getName() {
return "Naive Inverse Filter [NIF | IF]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3;
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 8.0;
+ }
+
@Override
public boolean isRegularized() {
return false;
}
@Override
public boolean isStepControllable() {
return false;
}
@Override
public boolean isIterative() {
return false;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
}
@Override
public double[] getDefaultParameters() {
return new double[] {};
}
@Override
public double[] getParameters() {
return new double[] {};
}
@Override
public double getRegularizationFactor() {
return 0.0;
}
@Override
public double getStepFactor() {
return 0;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java b/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java
index 6e43a42..f89e80f 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java
@@ -1,104 +1,118 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
public class NonStabilizedDivision extends AbstractAlgorithm implements Callable<RealSignal> {
public NonStabilizedDivision() {
super();
}
@Override
public RealSignal call() {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal X = Operations.divideNotStabilized(Y, H);
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
return x;
}
@Override
public String getName() {
return "Non Stablized Division [DIV]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3;
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 8.0;
+ }
+
@Override
public boolean isRegularized() {
return false;
}
@Override
public boolean isStepControllable() {
return false;
}
@Override
public boolean isIterative() {
return false;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
}
@Override
public double[] getDefaultParameters() {
return new double[] {};
}
@Override
public double[] getParameters() {
return new double[] {};
}
@Override
public double getRegularizationFactor() {
return 0.0;
}
@Override
public double getStepFactor() {
return 0;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java b/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java
index 41782ed..d334dcd 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java
@@ -1,117 +1,185 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
import signal.factory.complex.ComplexSignalFactory;
public class RegularizedInverseFilter extends AbstractAlgorithm implements Callable<RealSignal> {
private double lambda = 0.001;
public RegularizedInverseFilter(double lambda) {
super();
this.lambda = lambda;
}
@Override
public RealSignal call() {
+ if (optimizedMemoryFootprint)
+ return runOptimizedMemoryFootprint();
+ else
+ return runTextBook();
+ }
+
+ public RealSignal runTextBook() {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal H2 = Operations.multiply(H, H);
ComplexSignal L = ComplexSignalFactory.laplacian(Y.nx, Y.ny, Y.nz);
ComplexSignal L2 = Operations.multiply(lambda, L, L);
ComplexSignal FA = Operations.add(H2, L2);
ComplexSignal FT = Operations.divideStabilized(H, FA);
ComplexSignal X = Operations.multiply(Y, FT);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(FT);
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
+ SignalCollector.free(FA);
+ SignalCollector.free(L);
+ SignalCollector.free(H2);
+ SignalCollector.free(L2);
+ SignalCollector.free(X);
return x;
}
+ public RealSignal runOptimizedMemoryFootprint() {
+ ComplexSignal Y = fft.transform(y);
+ ComplexSignal H = fft.transform(h);
+ ComplexSignal X = filter(Y, H);
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
+ RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
+ return x;
+ }
+
+ public ComplexSignal filter(ComplexSignal Y, ComplexSignal H) {
+ ComplexSignal X = ComplexSignalFactory.laplacian(Y.nx, Y.ny, Y.nz);
+ X.setName("X");
+ int nx = X.nx;
+ int ny = X.ny;
+ int nz = X.nz;
+ float la, lb, ha, hb, fa, fb, ta, tb, ya, yb;
+ int nxy = nx * ny * 2;
+ float w = (float) lambda;
+ float epsilon = (float) Operations.epsilon;
+ for (int k = 0; k < nz; k++)
+ for (int i = 0; i < nxy; i += 2) {
+ la = X.data[k][i];
+ lb = X.data[k][i + 1];
+ ha = H.data[k][i];
+ hb = H.data[k][i + 1];
+ fa = w * (la * la - lb * lb) + (ha * ha - hb * hb);
+ fb = w * (2f * la * lb) + (2f * ha * hb);
+ float mag = Math.max(epsilon, fa * fa + fb * fb);
+ ta = (ha * fa + hb * fb) / mag;
+ tb = (hb * fa - ha * fb) / mag;
+ ya = Y.data[k][i];
+ yb = Y.data[k][i + 1];
+ X.data[k][i] = ya * ta - yb * tb;
+ X.data[k][i + 1] = ya * tb + ta * yb;
+ }
+ // SignalCollector.free(L);
+ return X;
+ }
+
+
@Override
public String getName() {
return "Regularized Inverse Filter [RIF | LRIF]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3;
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 8.0;
+ }
+
@Override
public boolean isRegularized() {
return true;
}
@Override
public boolean isStepControllable() {
return false;
}
@Override
public boolean isIterative() {
return false;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
lambda = (float) params[0];
}
@Override
public double[] getDefaultParameters() {
return new double[] { 0.1 };
}
@Override
public double[] getParameters() {
return new double[] { lambda };
}
@Override
public double getRegularizationFactor() {
return lambda;
}
@Override
public double getStepFactor() {
return 0;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java
index 11fe33b..2c66b08 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java
@@ -1,121 +1,136 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
public class RichardsonLucy extends AbstractAlgorithm implements Callable<RealSignal> {
public RichardsonLucy(int iter) {
super();
controller.setIterationMax(iter);
}
// x(k+1) = x(k) *. Hconj * ( y /. H x(k))
@Override
public RealSignal call() {
ComplexSignal H = fft.transform(h);
ComplexSignal U = new ComplexSignal("RL-U", y.nx, y.ny, y.nz);
RealSignal x = y.duplicate();
RealSignal p = y.duplicate();
RealSignal u = y.duplicate();
while (!controller.ends(x)) {
fft.transform(x, U);
U.times(H);
fft.inverse(U, u);
Operations.divide(y, u, p);
fft.transform(p, U);
U.timesConjugate(H);
fft.inverse(U, u);
x.times(u);
}
+ SignalCollector.free(H);
+ SignalCollector.free(p);
+ SignalCollector.free(u);
+ SignalCollector.free(U);
return x;
}
@Override
public String getName() {
return "Richardson-Lucy [RL]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 1 + 5 * controller.getIterationMax();
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 9.0;
+ }
+
@Override
public boolean isRegularized() {
return false;
}
@Override
public boolean isStepControllable() {
return false;
}
@Override
public boolean isIterative() {
return true;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
controller.setIterationMax((int) Math.round(params[0]));
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10 };
}
@Override
public double[] getParameters() {
return new double[] { controller.getIterationMax() };
}
@Override
public double getRegularizationFactor() {
return 0.0;
}
@Override
public double getStepFactor() {
return 0;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyPanel.java
index 60beba8..489e331 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyPanel.java
@@ -1,92 +1,94 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import deconvolution.Command;
import deconvolutionlab.Config;
import lab.component.GridPanel;
import lab.component.SpinnerRangeInteger;
public class RichardsonLucyPanel extends AbstractAlgorithmPanel implements ChangeListener {
private SpinnerRangeInteger spnIter = new SpinnerRangeInteger(10, 1, 99999, 1);
private RichardsonLucy algo = new RichardsonLucy(10);
@Override
public JPanel getPanelParameters() {
double[] params = algo.getDefaultParameters();
GridPanel pn = new GridPanel(false);
pn.place(1, 0, "<html><span \"nowrap\"><b>Iterations</b></span></html>");
pn.place(1, 1, "<html><span \"nowrap\"><i>N</i></span></html>");
pn.place(1, 2, spnIter);
Config.register("Algorithm." + algo.getShortname(), "iterations", spnIter, params[0]);
spnIter.addChangeListener(this);
return pn;
}
@Override
public String getCommand() {
return "" + spnIter.get();
}
@Override
public void stateChanged(ChangeEvent e) {
Command.command();
}
@Override
public String getName() {
return algo.getName();
}
@Override
public String[] getShortname() {
return new String[] {"RL"};
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
- s += "<p>Iterative: " + algo.isIterative() + "</p>";
- s += "<p>Step controllable: " + algo.isStepControllable() + "</p>";
- s += "<p>Regularization: " + algo.isRegularized() + "</p>";
- s += "<p>Wavelet-base: " + algo.isWaveletsBased() + "</p>";
- s += "<p>Shortname: " + getShortname() + "</p>";
+ s += "<h2> Shortname: RL</h2>";
+
+ s += "<p>This is the well-known Richardson-Lucy algorithm.</p>";
+ s += "<p>It is an iterative with a slow convergence, it has only one parameter to tune: the maximum number of iterations</p>";
+ s += "<p>RL is well appropiate for dominant Poison noise.</p>";
+ s += "<p>It is a maximum likelihood estimator (MLE).</p>";
+ s += "<p>Warning: the input image should have only positive values</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTV.java b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTV.java
index b769aa3..0d7654d 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTV.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTV.java
@@ -1,214 +1,230 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
public class RichardsonLucyTV extends AbstractAlgorithm implements Callable<RealSignal> {
private double lambda = 0.1;
public RichardsonLucyTV(int iter, double lambda) {
super();
controller.setIterationMax(iter);
this.lambda = lambda;
}
// x(k+1) = x(k) *. Hconj * ( y /. H x(k))
@Override
public RealSignal call() {
ComplexSignal H = fft.transform(h);
ComplexSignal U = new ComplexSignal("RLTV-U",y.nx, y.ny, y.nz);
RealSignal x = y.duplicate();
RealSignal gx = y.duplicate();
RealSignal gy = y.duplicate();
RealSignal gz = y.duplicate();
RealSignal ggx = y.duplicate();
RealSignal ggy = y.duplicate();
RealSignal ggz = y.duplicate();
RealSignal u = gx; // resued memory
RealSignal p = gy; // resued memory
RealSignal tv = gz; // resued memory
while(!controller.ends(x)) {
gradientX(x, gx);
gradientY(x, gy);
gradientZ(x, gz);
normalize(gx, gy, gz);
gradientX(gx, ggx);
gradientY(gy, ggy);
gradientZ(gz, ggz);
compute((float)lambda, ggx, ggy, ggz, tv);
-
fft.transform(x, U);
U.times(H);
fft.inverse(U, u);
Operations.divide(y, u, p);
fft.transform(p, U);
U.timesConjugate(H);
fft.inverse(U, u);
x.times(u);
x.times(tv);
}
+ SignalCollector.free(H);
+ SignalCollector.free(U);
+ SignalCollector.free(ggx);
+ SignalCollector.free(ggy);
+ SignalCollector.free(ggz);
+ SignalCollector.free(tv);
+ SignalCollector.free(u);
+ SignalCollector.free(p);
return x;
}
private void compute(float lambda, RealSignal gx, RealSignal gy, RealSignal gz, RealSignal tv) {
int nxy = gx.nx * gy.ny;
for(int k=0; k<gx.nz; k++)
for(int i=0; i< nxy; i++) {
double dx = gx.data[k][i];
double dy = gy.data[k][i];
double dz = gz.data[k][i];
tv.data[k][i] = (float)(1.0 / ( (dx+dy+dz) * lambda + 1.0));
}
- //Log.info("Norm TV "+ Math.sqrt(norm));
}
public void gradientX(RealSignal signal, RealSignal output) {
int nx = signal.nx;
int ny = signal.ny;
int nz = signal.nz;
for(int k=0; k<nz; k++)
for(int j=0; j<ny; j++)
for(int i=0; i<nx-1; i++) {
int index = i + signal.nx*j;
output.data[k][index] = signal.data[k][index] - signal.data[k][index+1];
}
}
public void gradientY(RealSignal signal, RealSignal output) {
int nx = signal.nx;
int ny = signal.ny;
int nz = signal.nz;
for(int k=0; k<nz; k++)
for(int j=0; j<ny-1; j++)
for(int i=0; i<nx; i++) {
int index = i + signal.nx*j;
output.data[k][index] = signal.data[k][index] - signal.data[k][index+nx];
}
}
public void gradientZ(RealSignal signal, RealSignal output) {
int nx = signal.nx;
int ny = signal.ny;
int nz = signal.nz;
for(int k=0; k<nz-1; k++)
for(int j=0; j<ny; j++)
for(int i=0; i<nx; i++) {
int index = i + signal.nx*j;
output.data[k][index] = signal.data[k][index] - signal.data[k+1][index];
}
}
public void normalize(RealSignal x, RealSignal y, RealSignal z) {
int nx = x.nx;
int ny = y.ny;
int nz = z.nz;
float e = (float) Operations.epsilon;
for(int k=0; k<nz; k++)
for(int i=0; i<nx*ny; i++) {
double norm = Math.sqrt(x.data[k][i] * x.data[k][i] + y.data[k][i] * y.data[k][i] + z.data[k][i] * z.data[k][i]);
if (norm < e) {
x.data[k][i] = e;
y.data[k][i] = e;
z.data[k][i] = e;
}
else {
x.data[k][i] /= norm;
y.data[k][i] /= norm;
z.data[k][i] /= norm;
}
}
}
-
-
+
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 1 + 7 * controller.getIterationMax();
+ }
+
@Override
public String getName() {
return "Richardson-Lucy Total Variation [RLTV]";
}
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 13.0;
+ }
+
@Override
public boolean isRegularized() {
return true;
}
@Override
public boolean isStepControllable() {
return true;
}
@Override
public boolean isIterative() {
return true;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
controller.setIterationMax((int)Math.round(params[0]));
if (params.length > 1)
lambda = (float)params[1];
}
@Override
public double[] getDefaultParameters() {
return new double[] {10, 0.1};
}
@Override
public double[] getParameters() {
return new double[] {controller.getIterationMax(), lambda};
}
@Override
public double getRegularizationFactor() {
return lambda;
}
@Override
public double getStepFactor() {
return 0.0;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java b/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
index f589bab..e390b7b 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
@@ -1,145 +1,159 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import lab.tools.PsRandom;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
public class Simulation extends AbstractAlgorithm implements Callable<RealSignal> {
private static PsRandom rand = new PsRandom(1234);
private double mean = 0.0;
private double stdev = 10.0;
private double poisson = 0.0;
public Simulation(double mean, double stdev, double poisson) {
super();
this.mean = mean;
this.stdev = stdev;
this.poisson = poisson;
}
@Override
public RealSignal call() {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal X = Operations.multiply(H, Y);
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
gaussian(x, mean, stdev);
poisson(x, poisson);
return x;
}
public void gaussian(RealSignal x, double mean, double sd) {
for (int k = 0; k < x.nz; k++) {
float[] slice = x.getXY(k);
for (int j = 0; j < x.ny * x.nx; j++)
slice[j] += (float) rand.nextGaussian(mean, sd);
}
}
public void poisson(RealSignal x, double factor) {
if (factor < Operations.epsilon)
return;
double f = 1.0/(factor);
for (int k = 0; k < x.nz; k++) {
float[] slice = x.getXY(k);
for (int j = 0; j < x.ny * x.nx; j++)
if (slice[j] > Operations.epsilon) {
slice[j] = (float)(rand.nextPoissonian(f*(slice[j])) * factor);
}
}
}
@Override
public String getName() {
return "Simulation with noise [SIM]";
}
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3;
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 8.0;
+ }
+
@Override
public boolean isRegularized() {
return false;
}
@Override
public boolean isStepControllable() {
return false;
}
@Override
public boolean isIterative() {
return false;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
mean = params[0];
if (params.length > 1)
stdev = params[1];
if (params.length > 2)
poisson = params[2];
}
@Override
public double[] getDefaultParameters() {
return new double[] {0, 1, 0};
}
@Override
public double[] getParameters() {
return new double[] {mean, stdev, poisson};
}
@Override
public double getRegularizationFactor() {
return 0.0;
}
@Override
public double getStepFactor() {
return 0;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java b/DeconvolutionLab2/src/deconvolution/algorithm/StarkParker.java
similarity index 83%
copy from DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
copy to DeconvolutionLab2/src/deconvolution/algorithm/StarkParker.java
index 0f7eed6..5acfb8e 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/StarkParker.java
@@ -1,128 +1,143 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Constraint;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
-public class LandweberPositivity extends AbstractAlgorithm implements Callable<RealSignal> {
+public class StarkParker extends AbstractAlgorithm implements Callable<RealSignal> {
private double gamma = 1.0;
- public LandweberPositivity(int iter, double gamma) {
+ public StarkParker(int iter, double gamma) {
super();
controller.setIterationMax(iter);
- controller.setConstraint(Constraint.Mode.NONNEGATIVE);
this.gamma = gamma;
}
@Override
// Landweber algorithm
// X(n+1) = X(n) + g*H*(Y-H*X(n))
// => X(n+1) = X(n) - g*H*H*X(n) + g*H*Y
// => X(n+1) = X(n) * (I-g*H*H) + g*H*Y
// => pre-compute: A = (I-g*H*H) and G = g*H*Y
// => Iteration : X(n+1) = X(n) * A + G with F(0) = G
public RealSignal call() {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal A = Operations.delta(gamma, H);
ComplexSignal G = Operations.multiplyConjugate(gamma, H, Y);
+ SignalCollector.free(H);
+ SignalCollector.free(Y);
ComplexSignal X = G.duplicate();
- controller.setConstraint(Constraint.Mode.NONNEGATIVE);
+ controller.setConstraint(Constraint.Mode.CLIPPED);
while (!controller.ends(X)) {
X.times(A);
X.plus(G);
}
+ SignalCollector.free(A);
+ SignalCollector.free(G);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
return x;
}
@Override
public String getName() {
- return "Non-Negative Least-Square [NNLS | LW+]";
+ return "Bounded-Variable Least Squares [BVLS | SP]";
+ }
+
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3 + controller.getIterationMax() * 2;
+ }
+
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 9.0;
}
@Override
public boolean isRegularized() {
return false;
}
@Override
public boolean isStepControllable() {
return true;
}
@Override
public boolean isIterative() {
return true;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
controller.setIterationMax((int) Math.round(params[0]));
if (params.length > 1)
gamma = (float) params[1];
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10, 1 };
}
@Override
public double[] getParameters() {
return new double[] { controller.getIterationMax(), gamma };
}
@Override
public double getRegularizationFactor() {
return 0.0;
}
@Override
public double getStepFactor() {
return gamma;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/StarkParkerPanel.java
similarity index 84%
copy from DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java
copy to DeconvolutionLab2/src/deconvolution/algorithm/StarkParkerPanel.java
index e9cc00b..5206a7a 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/StarkParkerPanel.java
@@ -1,109 +1,110 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import deconvolution.Command;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
import lab.component.GridPanel;
import lab.component.SpinnerRangeDouble;
import lab.component.SpinnerRangeInteger;
import lab.tools.NumFormat;
-public class LandweberPositivityPanel extends AbstractAlgorithmPanel implements ChangeListener {
+public class StarkParkerPanel extends AbstractAlgorithmPanel implements ChangeListener {
private SpinnerRangeInteger spnIter = new SpinnerRangeInteger(10, 1, 99999, 1);
private SpinnerRangeDouble spnStep = new SpinnerRangeDouble(1, 0, 2, 0.1);
- private LandweberPositivity algo = new LandweberPositivity(10, 1);
+ private StarkParker algo = new StarkParker(10, 1);
@Override
public JPanel getPanelParameters() {
double[] params = algo.getDefaultParameters();
spnIter.setPreferredSize(Constants.dimParameters);
spnStep.setPreferredSize(Constants.dimParameters);
GridPanel pn = new GridPanel(false);
pn.place(1, 0, "<html><span \"nowrap\"><b>Iterations</b></span></html>");
pn.place(1, 1, "<html><span \"nowrap\"><i>N</i></span></html>");
pn.place(1, 2, spnIter);
pn.place(1, 3, "<html><span \"nowrap\">Step <i>&gamma;</i></span></html>");
pn.place(1, 4, spnStep);
pn.place(2, 0, "<html><span \"nowrap\"><b>Regularization</b></span></html>");
pn.place(2, 1, 4, 1, "<html><span \"nowrap\">No regularization</i></span></html>");
Config.register("Algorithm." + algo.getShortname(), "iterations", spnIter, params[0]);
Config.register("Algorithm." + algo.getShortname(), "step", spnStep, params[1]);
spnIter.addChangeListener(this);
spnStep.addChangeListener(this);
return pn;
}
@Override
public String getCommand() {
int iter = spnIter.get();
double gamma = spnStep.get();
return iter + " " + NumFormat.nice(gamma);
}
@Override
public void stateChanged(ChangeEvent e) {
Command.command();
}
@Override
public String getName() {
return algo.getName();
}
@Override
public String[] getShortname() {
- return new String[] {"NNLS", "LW+"};
+ return new String[] { "BVLS", "SP" };
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
- s += "<p>Iterative: " + algo.isIterative() + "</p>";
- s += "<p>Step controllable: " + algo.isStepControllable() + "</p>";
- s += "<p>Regularization: " + algo.isRegularized() + "</p>";
- s += "<p>Wavelet-base: " + algo.isWaveletsBased() + "</p>";
- s += "<p>Shortname: " + getShortname() + "</p>";
+ s += "<h1>Stark-Parker Algorithm</p>";
+ s += "<h2>Shortname: BVLS or SP</p>";
+ s += "<p>This algorithm also known as Stark-Parker algorithm is a least squares variant with a bounded-variable constraint.</p>";
+ s += "<p>In this implementation, the bounds are the bounds of the input image.</p>";
+ s += "<p></p>";
+ s += "<p>Reference: Stark and Parker, Computational Statistics <b>10</b>, 1995.</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMiller.java b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMiller.java
index 24b0fc4..a4dfc20 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMiller.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMiller.java
@@ -1,127 +1,146 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
import signal.factory.complex.ComplexSignalFactory;
public class TikhonovMiller extends AbstractAlgorithm implements Callable<RealSignal> {
private double gamma = 1.0;
private double lambda = 1.0;
public TikhonovMiller(int iter, double gamma, double lambda) {
super();
controller.setIterationMax(iter);
this.gamma = gamma;
this.lambda = lambda;
}
@Override
public RealSignal call() throws Exception {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal A = Operations.delta(gamma, H);
ComplexSignal L = ComplexSignalFactory.laplacian(Y.nx, Y.ny, Y.nz);
ComplexSignal L2 = Operations.multiplyConjugate(lambda*gamma, L, L);
+ SignalCollector.free(L);
A.minus(L2);
+ SignalCollector.free(L2);
ComplexSignal G = Operations.multiplyConjugate(gamma, H, Y);
+ SignalCollector.free(H);
+ SignalCollector.free(Y);
ComplexSignal X = G.duplicate();
while(!controller.ends(X)) {
X.times(A);
X.plus(G);
}
+ SignalCollector.free(A);
+ SignalCollector.free(G);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
+
return x;
}
-
+
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3 + (controller.needSpatialComputation() ? 2 * controller.getIterationMax() : 0);
+ }
+
@Override
public String getName() {
return "Tikhonov-Miller [TM]";
}
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 10.0;
+ }
+
@Override
public boolean isRegularized() {
return true;
}
@Override
public boolean isStepControllable() {
return true;
}
@Override
public boolean isIterative() {
return true;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
controller.setIterationMax((int)Math.round(params[0]));
if (params.length > 1)
gamma = (float)params[1];
if (params.length > 2)
lambda = (float)params[2];
}
@Override
public double[] getDefaultParameters() {
return new double[] {10, 1, 0.1};
}
@Override
public double[] getParameters() {
return new double[] {controller.getIterationMax(), gamma, lambda};
}
@Override
public double getRegularizationFactor() {
return lambda;
}
@Override
public double getStepFactor() {
return gamma;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilter.java b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilter.java
index 3e9f2c2..efce317 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilter.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilter.java
@@ -1,135 +1,178 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
+import signal.factory.complex.ComplexSignalFactory;
public class TikhonovRegularizationInverseFilter extends AbstractAlgorithm implements Callable<RealSignal> {
private double lambda = 0.1;
public TikhonovRegularizationInverseFilter(double lambda) {
super();
this.lambda = lambda;
}
@Override
public RealSignal call() {
+ if (optimizedMemoryFootprint)
+ return runOptimizedMemoryFootprint();
+ else
+ return runTextBook();
+ }
+
+ public RealSignal runTextBook() {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
- ComplexSignal X = compute(Y, H);
+ ComplexSignal H2 = Operations.multiply(H, H);
+ ComplexSignal I = ComplexSignalFactory.identity(Y.nx, Y.ny, Y.nz);
+ I.times((float)lambda);
+ ComplexSignal FA = Operations.add(H2, I);
+ ComplexSignal FT = Operations.divideStabilized(H, FA);
+ ComplexSignal X = Operations.multiply(Y, FT);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(FT);
+ SignalCollector.free(Y);
+ SignalCollector.free(H);
+ SignalCollector.free(FA);
+ SignalCollector.free(I);
+ SignalCollector.free(H2);
+ SignalCollector.free(X);
return x;
}
- private ComplexSignal compute(ComplexSignal Y, ComplexSignal H) {
+ public RealSignal runOptimizedMemoryFootprint() {
+ ComplexSignal Y = fft.transform(y);
+ ComplexSignal H = fft.transform(h);
+ ComplexSignal X = filter(Y, H);
+ SignalCollector.free(H);
+ SignalCollector.free(Y);
+ RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
+ return x;
+ }
+
+ private ComplexSignal filter(ComplexSignal Y, ComplexSignal H) {
int nx = H.nx;
int ny = H.ny;
int nz = H.nz;
int nxy = nx * ny*2;
- double ya, yb, ha, hb, fa, fb, mag, ta, tb;
- double epsilon2 = Operations.epsilon * Operations.epsilon;
- ComplexSignal result = new ComplexSignal("TM", nx, ny, nz);
+ float ya, yb, ha, hb, fa, fb, mag, ta, tb;
+ float epsilon2 = (float)(Operations.epsilon * Operations.epsilon);
+ ComplexSignal result = new ComplexSignal("TRIF", nx, ny, nz);
+ float l = (float)lambda;
for(int k=0; k<nz; k++)
for(int i=0; i< nxy; i+=2) {
ha = H.data[k][i];
hb = H.data[k][i+1];
ya = Y.data[k][i];
yb = Y.data[k][i+1];
- fa = ha*ha - hb*hb + lambda;
+ fa = ha*ha - hb*hb + l;
fb = 2f * ha * hb;
mag = fa*fa + fb*fb;
ta = (ha*fa + hb*fb) / (mag >= epsilon2 ? mag : epsilon2);
tb = (hb*fa - ha*fb) / (mag >= epsilon2 ? mag : epsilon2);
- result.data[k][i] = (float)(ya*ta - yb*tb);
- result.data[k][i+1] = (float)(ya*tb + ta*yb);
+ result.data[k][i] = ya*ta - yb*tb;
+ result.data[k][i+1] = ya*tb + ta*yb;
}
return result;
}
-
+
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3;
+ }
+
@Override
public String getName() {
return "Tikhonov Regularization [TRIF]";
}
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 8.0;
+ }
+
@Override
public boolean isRegularized() {
return true;
}
@Override
public boolean isStepControllable() {
return false;
}
@Override
public boolean isIterative() {
return false;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
lambda = (float)params[0];
}
@Override
public double[] getDefaultParameters() {
return new double[] {0.1};
}
@Override
public double[] getParameters() {
return new double[] {lambda};
}
@Override
public double getRegularizationFactor() {
return lambda;
}
@Override
public double getStepFactor() {
return 0.0;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java b/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java
index 030210f..0985224 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java
@@ -1,124 +1,140 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
+import signal.SignalCollector;
public class VanCittert extends AbstractAlgorithm implements Callable<RealSignal> {
private double gamma = 1.0;
public VanCittert(int iter, double gamma) {
super();
controller.setIterationMax(iter);
this.gamma = gamma;
}
@Override
// VAnCitter algorithm
// X(n+1) = X(n) + g*(Y-H*X(n))
// => X(n+1) = X(n) - g*H*X(n) + g*Y
// => X(n+1) = X(n) * (I-g*H) + g*Y
// => pre-compute: A = (I-g*H) and G = g*Y
// => Iteration : X(n+1) = X(n) * A + G with F(0) = G
public RealSignal call() {
ComplexSignal Y = fft.transform(y);
ComplexSignal H = fft.transform(h);
ComplexSignal A = Operations.delta1(gamma, H);
+ SignalCollector.free(H);
ComplexSignal G = Operations.multiply(gamma, Y);
+ SignalCollector.free(Y);
ComplexSignal X = G.duplicate();
while(!controller.ends(X)) {
X.times(A);
X.plus(G);
}
+ SignalCollector.free(G);
+ SignalCollector.free(A);
RealSignal x = fft.inverse(X);
+ SignalCollector.free(X);
return x;
}
-
+
+ @Override
+ public int getComplexityNumberofFFT() {
+ return 3 + (controller.needSpatialComputation() ? 2 * controller.getIterationMax() : 0);
+ }
+
@Override
public String getName() {
return "Van Cittert [VC]";
}
+ @Override
+ public double getMemoryFootprintRatio() {
+ return 8.0;
+ }
+
@Override
public boolean isRegularized() {
return false;
}
@Override
public boolean isStepControllable() {
return true;
}
@Override
public boolean isIterative() {
return true;
}
@Override
public boolean isWaveletsBased() {
return false;
}
@Override
public void setParameters(double[] params) {
if (params == null)
return;
if (params.length > 0)
controller.setIterationMax((int)Math.round(params[0]));
if (params.length > 1)
gamma = (float)params[1];
}
@Override
public double[] getDefaultParameters() {
return new double[] {10, 1};
}
@Override
public double[] getParameters() {
return new double[] {controller.getIterationMax(), gamma};
}
@Override
public double getRegularizationFactor() {
return 0.0;
}
@Override
public double getStepFactor() {
return gamma;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/modules/AbstractDModule.java b/DeconvolutionLab2/src/deconvolution/modules/AbstractDModule.java
index d8f7a7a..35eb768 100644
--- a/DeconvolutionLab2/src/deconvolution/modules/AbstractDModule.java
+++ b/DeconvolutionLab2/src/deconvolution/modules/AbstractDModule.java
@@ -1,32 +1,84 @@
package deconvolution.modules;
+import java.util.Timer;
+import java.util.TimerTask;
+
import javax.swing.JFrame;
import javax.swing.JSplitPane;
import deconvolution.Deconvolution;
import deconvolutionlab.Lab;
+import deconvolutionlab.monitor.Monitors;
public abstract class AbstractDModule {
protected Deconvolution deconvolution;
protected JSplitPane split;
+ private AsynchronousTimer signalTimer;
+ private Timer timer = new Timer();
+ private int count = 0;
+
+ private Monitors monitors;
+ private String message = "";
public AbstractDModule(Deconvolution deconvolution) {
this.deconvolution = deconvolution;
+ this.monitors = deconvolution.monitors;
}
public JSplitPane getPane() {
return split;
}
public void show(String name) {
JFrame frame = new JFrame(name);
update();
frame.getContentPane().add(split);
frame.pack();
Lab.setVisible(frame);
}
public abstract void update();
public abstract String getName();
+
+ public void stopAsynchronousTimer() {
+ if (monitors != null)
+ monitors.progress(message, 100);
+ if (signalTimer != null) {
+ signalTimer.cancel();
+ signalTimer = null;
+ }
+ }
+
+ public void startAsynchronousTimer(String message, long refreshTime) {
+ if (signalTimer != null) {
+ signalTimer.cancel();
+ signalTimer = null;
+ }
+ this.message = message;
+ signalTimer = new AsynchronousTimer(message);
+ timer.schedule(signalTimer, 0, refreshTime);
+ }
+
+ public void signal(String message) {
+ if (monitors != null)
+ monitors.progress(message, count+=2);
+ }
+
+ private class AsynchronousTimer extends TimerTask {
+ private String message;
+ public AsynchronousTimer(String message) {
+ this.message = message;
+ }
+ @Override
+ public void run() {
+ signal(message);
+ }
+ }
+
+ @Override
+ public void finalize() {
+ stopAsynchronousTimer();
+ }
+
}
diff --git a/DeconvolutionLab2/src/deconvolution/modules/AlgorithmDModule.java b/DeconvolutionLab2/src/deconvolution/modules/AlgorithmDModule.java
index 431e97e..a1bb3d0 100644
--- a/DeconvolutionLab2/src/deconvolution/modules/AlgorithmDModule.java
+++ b/DeconvolutionLab2/src/deconvolution/modules/AlgorithmDModule.java
@@ -1,46 +1,153 @@
package deconvolution.modules;
import javax.swing.JSplitPane;
import deconvolution.Deconvolution;
+import deconvolution.Features;
+import deconvolution.algorithm.AbstractAlgorithm;
import deconvolution.algorithm.AbstractAlgorithmPanel;
import deconvolution.algorithm.Algorithm;
+import deconvolution.algorithm.Controller;
+import deconvolutionlab.monitor.Monitors;
+import fft.AbstractFFT;
+import fft.FFT;
import lab.component.CustomizedTable;
import lab.component.HTMLPane;
+import lab.tools.NumFormat;
+import signal.ComplexSignal;
+import signal.RealSignal;
+import signal.SignalCollector;
-public class AlgorithmDModule extends AbstractDModule {
+public class AlgorithmDModule extends AbstractDModule implements Runnable {
private CustomizedTable table;
private HTMLPane doc;
public AlgorithmDModule(Deconvolution deconvolution) {
super(deconvolution);
doc = new HTMLPane(100, 1000);
table = new CustomizedTable(new String[] { "Features", "Values" }, false);
split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, table.getPane(200, 200), doc.getPane());
- update();
}
public void update() {
if (doc == null)
return;
if (table == null)
return;
- table.removeRows();
- for (String[] feature : deconvolution.checkAlgo())
- table.append(feature);
- doc.clear();
- String name = deconvolution.getAlgo().getShortname();
- AbstractAlgorithmPanel algo = Algorithm.getPanel(name);
- if (algo != null)
- doc.append(algo.getDocumentation());
+ table.removeRows();
+ table.append(new String[] { "PSF", "Waiting for loading ..." });
+ Thread thread = new Thread(this);
+ thread.setPriority(Thread.MIN_PRIORITY);
+ thread.start();
split.setDividerLocation(300);
}
@Override
public String getName() {
return "Algorithm";
}
+
+ @Override
+ public void run() {
+ Features features = new Features();
+
+ if (deconvolution.algo == null) {
+ features.add("Algorithm", "No valid algorithm");
+ return;
+ }
+ AbstractAlgorithm algo = deconvolution.algo;
+ doc.clear();
+ String name = algo.getShortname();
+ AbstractAlgorithmPanel algoPanel = Algorithm.getPanel(name);
+ if (algoPanel != null)
+ doc.append(algoPanel.getDocumentation());
+
+ if (deconvolution.image == null) {
+ startAsynchronousTimer("Open image", 200);
+ deconvolution.image = deconvolution.openImage();
+ stopAsynchronousTimer();
+ }
+
+ if (deconvolution.image == null) {
+ features.add("Image", "No valid input image");
+ return;
+ }
+ if (deconvolution.pad == null) {
+ features.add("Padding", "No valid padding");
+ return;
+ }
+ if (deconvolution.apo == null) {
+ features.add("Apodization", "No valid apodization");
+ return;
+ }
+
+ if (deconvolution.psf == null) {
+ startAsynchronousTimer("Open PSF", 200);
+ deconvolution.psf = deconvolution.openPSF();
+ stopAsynchronousTimer();
+ }
+
+ if (deconvolution.psf == null) {
+ features.add("Image", "No valid PSF");
+ return;
+ }
+
+ Controller controller = deconvolution.algo.getController();
+ if (controller == null) {
+ features.add("Controller", "No valid controller");
+ return;
+ }
+
+ startAsynchronousTimer("Run FFT", 200);
+ deconvolution.algo.setController(controller);
+ AbstractFFT f = FFT.getFastestFFT().getDefaultFFT();
+ double Q = Math.sqrt(2);
+ if (deconvolution.image != null) {
+ int mx = deconvolution.image.nx;
+ int my = deconvolution.image.ny;
+ int mz = deconvolution.image.nz;
+
+ while (mx * my * mz > Math.pow(2, 15)) {
+ mx = (int)(mx / Q);
+ my = (int)(my / Q);
+ mz = (int)(mz / Q);
+ }
+ double N = deconvolution.image.nx * deconvolution.image.ny * deconvolution.image.nz;
+ double M = mx * my * mz;
+ double ratio = 1;
+ if (M != 0)
+ ratio = (N * Math.log(N)) / (M * Math.log(M));
+
+ double chrono = System.nanoTime();
+ RealSignal x = new RealSignal("test", mx, my, mz);
+ ComplexSignal c = new ComplexSignal("test", mx, my, mz);
+ f.init(Monitors.createDefaultMonitor(), mx, my, mz);
+ f.transform(x, c);
+ SignalCollector.free(x);
+ SignalCollector.free(c);
+
+ chrono = (System.nanoTime() - chrono);
+ features.add("Tested on", mx + "x" + my + "x" + mz);
+ features.add("Estimated Time on small", NumFormat.time(chrono) );
+
+ chrono = chrono * ratio * algo.getComplexityNumberofFFT();
+
+ int n = algo.isIterative() ? controller.getIterationMax() : 1;
+ features.add("Estimated Time", NumFormat.time(chrono) );
+ features.add("Estimated Number of FFT / Transform", ""+algo.getComplexityNumberofFFT());
+ }
+ else
+ features.add("Estimated Time", "Error" );
+ double mem = (algo.getMemoryFootprintRatio() * deconvolution.image.nx * deconvolution.image.ny * deconvolution.image.nz * 4);
+ features.add("Estimated Memory", NumFormat.bytes(mem));
+ features.add("Iterative", algo.isIterative() ? "" + controller.getIterationMax() : "Direct");
+
+ table.removeRows();
+ for (String[] feature : features)
+ table.append(feature);
+ stopAsynchronousTimer();
+ }
}
\ No newline at end of file
diff --git a/DeconvolutionLab2/src/deconvolution/modules/ImageDModule.java b/DeconvolutionLab2/src/deconvolution/modules/ImageDModule.java
index bb6d2a8..1849b17 100644
--- a/DeconvolutionLab2/src/deconvolution/modules/ImageDModule.java
+++ b/DeconvolutionLab2/src/deconvolution/modules/ImageDModule.java
@@ -1,51 +1,109 @@
package deconvolution.modules;
import java.awt.Dimension;
-import java.awt.image.BufferedImage;
import javax.swing.JSplitPane;
import deconvolution.Deconvolution;
+import deconvolution.Features;
import lab.component.CustomizedTable;
import lab.component.JPanelImage;
+import lab.tools.NumFormat;
import signal.RealSignal;
+import signal.SignalCollector;
-public class ImageDModule extends AbstractDModule {
+public class ImageDModule extends AbstractDModule implements Runnable {
private JPanelImage pnImage;
private CustomizedTable table;
- private BufferedImage img;
public ImageDModule(Deconvolution deconvolution) {
super(deconvolution);
pnImage = new JPanelImage();
table = new CustomizedTable(new String[] { "Features", "Values" }, false);
pnImage.setPreferredSize(new Dimension(300, 300));
split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, table.getPane(300, 300), pnImage);
- update();
}
public void update() {
split.setDividerLocation(300);
if (pnImage == null)
return;
if (table == null)
return;
- RealSignal signal = deconvolution.openImage();
table.removeRows();
- if (signal == null) {
- table.append(new String[] {"ERROR", "No open image"});
- return;
- }
- img = signal.createPreviewMIPZ();
- pnImage.setImage(img);
- for (String[] feature : deconvolution.checkImage(signal))
- table.append(feature);
+ table.append(new String[] {"Image", "Waiting for loading ..."});
+ Thread thread = new Thread(this);
+ thread.setPriority(Thread.MIN_PRIORITY);
+ thread.start();
}
@Override
public String getName() {
return "Image";
}
+
+ @Override
+ public void run() {
+ Features features = new Features();
+
+ if (deconvolution.image == null) {
+ startAsynchronousTimer("Open image", 200);
+ deconvolution.image = deconvolution.openImage();
+ stopAsynchronousTimer();
+ }
+
+ if (deconvolution.image == null) {
+ features.add("Image", "No valid input image");
+ return;
+ }
+
+ if (deconvolution.pad == null) {
+ features.add("Padding", "No valid padding");
+ return;
+ }
+
+ if (deconvolution.apo == null) {
+ features.add("Apodization", "No valid apodization");
+ return;
+ }
+
+ startAsynchronousTimer("Preprocessing image", 200);
+
+ float stati[] = deconvolution.image.getStats();
+ int sizi = deconvolution.image.nx * deconvolution.image.ny * deconvolution.image.nz;
+ float totali = stati[0] * sizi;
+ features.add("<html><b>Orignal Image</b></html>", "");
+ features.add("Size", deconvolution.image.dimAsString() + " " + NumFormat.bytes(sizi*4));
+ features.add("Mean (stdev)", NumFormat.nice(stati[0]) + " (" + NumFormat.nice(stati[3]) + ")");
+ features.add("Min ... Max", NumFormat.nice(stati[1]) + " ... " + NumFormat.nice(stati[2]));
+ features.add("Energy (int)", NumFormat.nice(stati[5]) + " (" + NumFormat.nice(totali) + ")");
+ table.removeRows();
+ for (String[] feature : features)
+ table.append(feature);
+
+ RealSignal signal = deconvolution.pad.pad(deconvolution.monitors, deconvolution.image);
+ deconvolution.apo.apodize(deconvolution.monitors, signal);
+ float stats[] = signal.getStats();
+ int sizs = signal.nx * signal.ny * signal.nz;
+ float totals = stats[0] * sizs;
+
+ features.add("<html><b>Working Image</b></html>", "");
+ features.add("Size", signal.dimAsString() + " " + NumFormat.bytes(sizs*4));
+ features.add("Mean (stdev)", NumFormat.nice(stats[0]) + " (" + NumFormat.nice(stats[3]) + ")");
+ features.add("Min Max", NumFormat.nice(stats[1]) + " " + NumFormat.nice(stats[2]));
+ features.add("Energy (int)", NumFormat.nice(stats[5]) + " (" + NumFormat.nice(totals) + ")");
+ features.add("<html><b>Information</b></html>", "");
+ features.add("Size Increase ", NumFormat.nice((double)(sizs-sizi)/sizi*100.0));
+ features.add("Energy Lost", NumFormat.nice((stats[5]-stati[5])/stati[5]*100));
+ SignalCollector.free(signal);
+ table.removeRows();
+ for (String[] feature : features)
+ table.append(feature);
+
+ pnImage.setImage(deconvolution.image.preview());
+ stopAsynchronousTimer();
+
+ }
}
\ No newline at end of file
diff --git a/DeconvolutionLab2/src/deconvolution/modules/PSFDModule.java b/DeconvolutionLab2/src/deconvolution/modules/PSFDModule.java
index 1d4bb8d..437b23f 100644
--- a/DeconvolutionLab2/src/deconvolution/modules/PSFDModule.java
+++ b/DeconvolutionLab2/src/deconvolution/modules/PSFDModule.java
@@ -1,54 +1,122 @@
package deconvolution.modules;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import javax.swing.JSplitPane;
import deconvolution.Deconvolution;
+import deconvolution.Features;
import deconvolutionlab.Lab;
import deconvolutionlab.monitor.Monitors;
import lab.component.CustomizedTable;
import lab.component.JPanelImage;
+import lab.tools.NumFormat;
import signal.Constraint;
import signal.RealSignal;
+import signal.SignalCollector;
-public class PSFDModule extends AbstractDModule {
+public class PSFDModule extends AbstractDModule implements Runnable {
- private JPanelImage pnImage;
- private CustomizedTable table;
+ private JPanelImage pnImage;
+ private CustomizedTable table;
public PSFDModule(Deconvolution deconvolution) {
super(deconvolution);
pnImage = new JPanelImage();
table = new CustomizedTable(new String[] { "Features", "Values" }, false);
pnImage.setPreferredSize(new Dimension(300, 300));
split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, table.getPane(300, 300), pnImage);
- update();
}
-
+
public void update() {
split.setDividerLocation(300);
if (pnImage == null)
return;
if (table == null)
return;
- RealSignal signal = deconvolution.openPSF();
-
table.removeRows();
- if (signal == null) {
- table.append(new String[] {"ERROR", "No PSF image"});
- return;
- }
- BufferedImage img = signal.createPreviewMIPZ();
- pnImage.setImage(img);
- for (String[] feature : deconvolution.checkPSF(signal))
- table.append(feature);
+ table.append(new String[] { "PSF", "Waiting for loading ..." });
+ Thread thread = new Thread(this);
+ thread.setPriority(Thread.MIN_PRIORITY);
+ thread.start();
}
@Override
public String getName() {
return "PSF";
}
+ @Override
+ public void run() {
+ Features features = new Features();
+
+ if (deconvolution.image == null) {
+ startAsynchronousTimer("Open image", 200);
+ deconvolution.image = deconvolution.openImage();
+ stopAsynchronousTimer();
+ }
+
+ if (deconvolution.image == null) {
+ features.add("Image", "No valid input image");
+ return;
+ }
+
+ if (deconvolution.pad == null) {
+ features.add("Padding", "No valid padding");
+ return;
+ }
+
+ if (deconvolution.apo == null) {
+ features.add("Apodization", "No valid apodization");
+ return;
+ }
+
+ if (deconvolution.psf == null) {
+ startAsynchronousTimer("Open PSF", 200);
+ deconvolution.psf = deconvolution.openPSF();
+ stopAsynchronousTimer();
+ }
+
+ if (deconvolution.psf == null) {
+ features.add("PSF", "No valid PSF");
+ return;
+ }
+
+ startAsynchronousTimer("Preprocessing PSF", 200);
+
+ float stati[] = deconvolution.psf.getStats();
+ int sizi = deconvolution.psf.nx * deconvolution.psf.ny * deconvolution.psf.nz;
+ float totali = stati[0] * sizi;
+ features.add("<html><b>Orignal PSF</b></html>", "");
+ features.add("Size", deconvolution.psf.dimAsString() + " " + NumFormat.bytes(sizi * 4));
+ features.add("Mean (stdev)", NumFormat.nice(stati[0]) + " (" + NumFormat.nice(stati[3]) + ")");
+ features.add("Min ... Max", NumFormat.nice(stati[1]) + " ... " + NumFormat.nice(stati[2]));
+ features.add("Energy (int)", NumFormat.nice(stati[5]) + " (" + NumFormat.nice(totali) + ")");
+ table.removeRows();
+ for (String[] feature : features)
+ table.append(feature);
+
+ RealSignal h = deconvolution.psf.changeSizeAs(deconvolution.image);
+ h.normalize(deconvolution.norm);
+ float stats[] = h.getStats();
+ int sizs = h.nx * h.ny * h.nz;
+ float totals = stats[0] * sizs;
+ features.add("<html><b>Working PSF</b></html>", "");
+ features.add("Size", h.dimAsString() + " " + NumFormat.bytes(sizs * 4));
+ features.add("Mean (stdev)", NumFormat.nice(stats[0]) + " (" + NumFormat.nice(stats[3]) + ")");
+ features.add("Min Max", NumFormat.nice(stats[1]) + " " + NumFormat.nice(stats[2]));
+ features.add("Energy (int)", NumFormat.nice(stats[5]) + " (" + NumFormat.nice(totals) + ")");
+ features.add("<html><b>Information</b></html>", "");
+ features.add("Size Increase ", NumFormat.nice((double) (sizs - sizi) / sizi * 100.0));
+ features.add("Energy Lost", NumFormat.nice((stats[5] - stati[5]) / stati[5] * 100));
+ SignalCollector.free(h);
+ table.removeRows();
+ for (String[] feature : features)
+ table.append(feature);
+
+ pnImage.setImage(deconvolution.psf.preview());
+ stopAsynchronousTimer();
+ }
+
}
\ No newline at end of file
diff --git a/DeconvolutionLab2/src/deconvolution/modules/RecapDModule.java b/DeconvolutionLab2/src/deconvolution/modules/RecapDModule.java
index 2b88141..4ae3f77 100644
--- a/DeconvolutionLab2/src/deconvolution/modules/RecapDModule.java
+++ b/DeconvolutionLab2/src/deconvolution/modules/RecapDModule.java
@@ -1,75 +1,74 @@
package deconvolution.modules;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JSplitPane;
import javax.swing.text.BadLocationException;
import deconvolution.Deconvolution;
import lab.component.CustomizedTable;
import lab.component.HTMLPane;
public class RecapDModule extends AbstractDModule implements KeyListener {
private HTMLPane pnCommand;
private CustomizedTable table;
public RecapDModule(Deconvolution deconvolution) {
super(deconvolution);
// Panel command
pnCommand = new HTMLPane("Monaco", "#10FF10", "100020", 100, 100);
pnCommand.append("p", deconvolution.getCommand());
pnCommand.setEditable(true);
pnCommand.addKeyListener(this);
table = new CustomizedTable(new String[] { "Features", "Values" }, false);
split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, table.getPane(200, 200), pnCommand.getPane());
- update();
}
public void update() {
if (table == null)
return;
table.removeRows();
for (String[] feature : deconvolution.recap())
table.append(feature);
split.setDividerLocation(0.5);
split.repaint();
}
public String getCommand() {
return pnCommand.getText();
}
@Override
public String getName() {
return "Recap";
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
try {
int len = pnCommand.getDocument().getLength();
String command = pnCommand.getDocument().getText(0, len);
deconvolution.setCommand(command);
table.removeRows();
for (String[] feature : deconvolution.recap())
table.append(feature);
}
catch (BadLocationException e1) {
e1.printStackTrace();
}
}
}
\ No newline at end of file
diff --git a/DeconvolutionLab2/src/deconvolution/modules/ReportDModule.java b/DeconvolutionLab2/src/deconvolution/modules/ReportDModule.java
index 61c7a6c..59d9a73 100644
--- a/DeconvolutionLab2/src/deconvolution/modules/ReportDModule.java
+++ b/DeconvolutionLab2/src/deconvolution/modules/ReportDModule.java
@@ -1,55 +1,51 @@
package deconvolution.modules;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import javax.swing.JSplitPane;
import deconvolution.Deconvolution;
import lab.component.CustomizedTable;
import lab.component.JPanelImage;
import signal.RealSignal;
public class ReportDModule extends AbstractDModule {
private JPanelImage pnImage;
private CustomizedTable table;
- private BufferedImage img;
public ReportDModule(Deconvolution deconvolution) {
super(deconvolution);
pnImage = new JPanelImage();
table = new CustomizedTable(new String[] { "Output", "Values" }, false);
pnImage.setPreferredSize(new Dimension(300, 300));
split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, table.getPane(300, 300), pnImage);
- update();
}
public void update() {
split.setDividerLocation(300);
if (pnImage == null)
return;
if (table == null)
return;
table.removeRows();
for (String[] feature : deconvolution.getDeconvolutionReports())
table.append(feature);
- RealSignal signal = deconvolution.getOutput();
- if (signal == null) {
- table.append(new String[] {"ERROR", "No output image"});
+ RealSignal image = deconvolution.getOutput();
+ if (image == null) {
+ table.append(new String[] {"ERROR", "No open output"});
return;
}
- img = signal.createPreviewMIPZ();
- pnImage.setImage(img);
-
+ pnImage.setImage(image.preview());
for (String[] feature : deconvolution.checkOutput())
table.append(feature);
split.setDividerLocation(300);
}
@Override
public String getName() {
return "Report";
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/Lab.java b/DeconvolutionLab2/src/deconvolutionlab/Lab.java
index 9d7bacc..9f9f0cd 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/Lab.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/Lab.java
@@ -1,322 +1,381 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab;
import java.io.File;
import java.util.ArrayList;
+import java.util.Timer;
+import java.util.TimerTask;
import java.util.regex.Pattern;
import javax.swing.JDialog;
import javax.swing.JFrame;
+import javax.swing.JPanel;
import deconvolutionlab.Imaging.ContainerImage;
import deconvolutionlab.monitor.Monitors;
import fft.AbstractFFT;
import fft.AbstractFFTLibrary;
import fft.FFT;
import imagej.IJImager;
import lab.tools.NumFormat;
import lab.tools.WebBrowser;
import plugins.sage.deconvolutionlab.IcyImager;
import signal.ComplexComponent;
import signal.ComplexSignal;
import signal.RealSignal;
+import signal.factory.SignalFactory;
import signal.factory.Sphere;
public class Lab {
private static Imaging imaging;
private static ArrayList<JFrame> frames;
private static ArrayList<JDialog> dialogs;
static {
frames = new ArrayList<JFrame>();
dialogs = new ArrayList<JDialog>();
imaging = new IJImager();
Config.init(System.getProperty("user.dir") + File.separator + "DeconvolutionLab2.config");
}
public static Imaging.Platform getPlatform() {
return imaging.getPlatform();
}
public static void init(Imaging.Platform p) {
init(p, System.getProperty("user.dir") + File.separator + "DeconvolutionLab2.config");
}
public static void init(Imaging.Platform platform, String config) {
switch (platform) {
case IMAGEJ:
imaging = new IJImager();
break;
case ICY:
imaging = new IcyImager();
break;
default:
imaging = new IJImager();
break;
}
Config.init(System.getProperty("user.dir")+File.separator+"DeconvolutionLab2.config");
}
public static void help() {
WebBrowser.open(Constants.url);
}
public static void checkFFT(Monitors monitors) {
ArrayList<AbstractFFTLibrary> libraries = FFT.getInstalledLibraries();
for (int k = 1; k <= 3; k++)
for (AbstractFFTLibrary library : libraries) {
RealSignal y = new Sphere(3, 1).generate(40, 30, 20);
double chrono = System.nanoTime();
AbstractFFT fft = library.getDefaultFFT();
fft.init(monitors, y.nx, y.ny, y.nz);
RealSignal x = fft.inverse(fft.transform(y));
chrono = System.nanoTime() - chrono;
double residu = y.getEnergy() - x.getEnergy();
monitors.log(fft.getName() + " Test " + k);
monitors.log("\t residu of reconstruction: " + residu);
monitors.log("\t computation time (" + x.nx + "x" + x.ny + "x" + x.nz + ") " + NumFormat.time(chrono));
}
}
public static ContainerImage createContainer(Monitors monitors, String title) {
monitors.log("Create Live Real Signal " + title);
return imaging.createContainer(title);
}
public static void append(Monitors monitors, ContainerImage container, RealSignal signal, String title) {
imaging.append(container, signal, title, Imaging.Type.FLOAT);
monitors.log("Add Live Real Signal " + title);
}
public static void append(Monitors monitors, ContainerImage container, RealSignal signal, String title, Imaging.Type type) {
imaging.append(container, signal, title, type);
monitors.log("Add Live Real Signal " + title);
}
public static void show(Monitors monitors, ComplexSignal signal, String title) {
if (signal == null) {
monitors.error("Show " + title + " this image does not exist.");
return;
}
monitors.log("Show Real Signal " + title);
imaging.show(signal, title, ComplexComponent.MODULE);
}
public static void show(Monitors monitors, ComplexSignal signal, String title, ComplexComponent complex) {
if (signal == null) {
monitors.error("Show " + title + " this image does not exist.");
return;
}
monitors.log("Show Real Signal " + title);
imaging.show(signal, title, complex);
}
public static void show(Monitors monitors, RealSignal signal, String title) {
if (signal == null) {
monitors.error("Show " + title + " this image does not exist.");
return;
}
monitors.log("Show Real Signal " + title);
imaging.show(signal, title, Imaging.Type.FLOAT, signal.nz / 2);
}
public static void show(Monitors monitors, RealSignal signal, String title, Imaging.Type type) {
if (signal == null) {
monitors.error("Show " + title + " this image does not exist.");
return;
}
monitors.log("Show Real Signal " + title);
imaging.show(signal, title, type, signal.nz / 2);
}
public static void show(Monitors monitors, RealSignal signal, String title, Imaging.Type type, int z) {
if (signal == null) {
monitors.error("Show " + title + " this image does not exist.");
return;
}
monitors.log("Show Real Signal " + title);
imaging.show(signal, title, type, z);
}
public static void save(Monitors monitors, RealSignal signal, String filename) {
imaging.save(signal, filename, Imaging.Type.FLOAT);
monitors.log("Save Real Signal " + filename);
}
public static void save(Monitors monitors, RealSignal signal, String filename, Imaging.Type type) {
imaging.save(signal, filename, type);
monitors.log("Save Real Signal " + filename);
}
- public static RealSignal open(Monitors monitors, String filename) {
+ public static RealSignal createRealSignal(Monitors monitors, String arg, String cmd, String path) {
+
+ RealSignal signal = null;
+ if (arg.equalsIgnoreCase("synthetic")) {
+ signal = SignalFactory.createFromCommand(cmd);
+ }
+
+ if (arg.equalsIgnoreCase("platform")) {
+ signal = getImager().create(cmd);
+ }
+
+ if (arg.equalsIgnoreCase("file")) {
+ File file = new File(path + File.separator + cmd);
+ if (file != null) {
+ if (file.isFile())
+ signal = Lab.openFile(monitors, path + File.separator + cmd);
+ }
+ if (signal == null) {
+ File local = new File(cmd);
+ if (local != null) {
+ if (local.isFile())
+ signal = Lab.openFile(monitors, cmd);
+ }
+ }
+ }
+
+ if (arg.equalsIgnoreCase("dir") || arg.equalsIgnoreCase("directory")) {
+ File file = new File(path + File.separator + cmd);
+ if (file != null) {
+ if (file.isDirectory())
+ signal = Lab.openDir(monitors, path + File.separator + cmd);
+ }
+ if (signal == null) {
+ File local = new File(cmd);
+ if (local != null) {
+ if (local.isDirectory())
+ signal = Lab.openDir(monitors, cmd);
+ }
+ }
+ }
+ return signal;
+ }
+
+ public static RealSignal openFile(Monitors monitors, String filename) {
RealSignal signal = imaging.open(filename);
if (signal == null)
monitors.error("Unable to open " + filename);
else
monitors.log("Load " + filename);
return signal;
}
+
public static RealSignal openDir(Monitors monitors, String path) {
-
+
String parts[] = path.split(" pattern ");
String dirname = path;
String regex = "";
if (parts.length == 2) {
dirname = parts[0].trim();
regex = parts[1].trim();
}
-
File file = new File(dirname + File.separator);
-
if (!file.isDirectory()) {
monitors.error("Dir " + dirname + " is not a directory.");
return null;
}
String[] list = file.list();
ArrayList<RealSignal> slices = new ArrayList<RealSignal>();
int nx = 0;
int ny = 0;
Pattern pattern = Pattern.compile(regex);
for (String filename : list) {
if (pattern.matcher(filename).find()) {
RealSignal slice = imaging.open(dirname + File.separator + filename);
if (slice != null) {
slices.add(slice);
nx = Math.max(nx, slice.nx);
ny = Math.max(ny, slice.ny);
monitors.log("Image " + path + File.separator + filename + " is loaded.");
}
}
else {
monitors.error("Error in loading image " + path + File.separator + filename);
}
}
int nz = slices.size();
if (nz <= 0) {
monitors.error("Dir " + path + " do no contain valid images.");
return null;
}
RealSignal signal = new RealSignal(file.getName(), nx, ny, nz);
for (int z = 0; z < slices.size(); z++)
signal.setSlice(z, slices.get(z));
return signal;
}
public static void showOrthoview(Monitors monitors, RealSignal signal, String title, int hx, int hy, int hz) {
if (signal == null) {
monitors.error("Show Orthoview " + title + " this image does not exist.");
return;
}
imaging.show(signal.createOrthoview(hx, hy, hz), title, Imaging.Type.FLOAT, 0);
}
public static void showOrthoview(Monitors monitors, RealSignal signal, String title) {
if (signal == null) {
monitors.error("Show Orthoview " + title + " this image does not exist.");
return;
}
int hx = signal.nx / 2;
int hy = signal.ny / 2;
int hz = signal.nz / 2;
imaging.show(signal.createOrthoview(hx, hy, hz), title, Imaging.Type.FLOAT, 0);
}
public static void showMIP(Monitors monitors, RealSignal signal, String title) {
if (signal == null) {
monitors.error("Show MIP " + title + " this image does not exist.");
return;
}
imaging.show(signal.createMIP(), title, Imaging.Type.FLOAT, 0);
}
public static void showMontage(Monitors monitors, RealSignal signal, String title) {
if (signal == null) {
monitors.error("Show Montage " + title + " this image does not exist.");
return;
}
imaging.show(signal.createMontage(), title, Imaging.Type.FLOAT, 0);
}
public static RealSignal create(Monitors monitors, String name) {
RealSignal signal = imaging.create(name);
if (signal != null)
monitors.log("Created the real signal " + name + " " + signal.toString());
else
monitors.error("Impossible to create the real signal " + name);
return signal;
}
public static RealSignal create(Monitors monitors) {
RealSignal signal = imaging.create();
if (signal != null)
monitors.log("Created the real signal from the active window " + signal.toString());
else
monitors.error("Impossible to create the real signal from the active window");
return signal;
}
public static Imaging getImager() {
return imaging;
}
public static String getActiveImage() {
if (imaging.isSelectable())
return imaging.getSelectedImage();
return "";
}
public static void setVisible(JDialog dialog, boolean modal) {
if (dialog == null)
return;
dialogs.add(dialog);
imaging.setVisible(dialog, modal);
}
+ public static void setVisible(JPanel panel, String name, int x, int y) {
+ JFrame frame = new JFrame(name);
+ frame.getContentPane().add(panel);
+ frame.pack();
+ frame.setLocation(x, y);
+ frame.setVisible(true);
+ frames.add(frame);
+ }
+
public static void setVisible(JFrame frame) {
frames.add(frame);
frame.setVisible(true);
}
public static void close() {
for(JFrame frame : frames)
if (frame != null)
frame.dispose();
for(JDialog dialog : dialogs)
if (dialog != null)
dialog.dispose();
}
+
+
+
+
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/LabDialog.java b/DeconvolutionLab2/src/deconvolutionlab/LabDialog.java
index e2662b0..acac0b2 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/LabDialog.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/LabDialog.java
@@ -1,144 +1,145 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import deconvolution.DeconvolutionDialog;
import deconvolutionlab.system.SystemInfo;
public class LabDialog extends JDialog implements ComponentListener, ActionListener, WindowListener {
private LabPanel panel;
private JButton bnClose = new JButton("Close");
public LabDialog() {
super(new JFrame(), Constants.name);
Config.registerFrame("DeconvolutionLab", "MainDialog", this);
panel = new LabPanel(bnClose);
getContentPane().add(panel);
pack();
addWindowListener(this);
addComponentListener(this);
bnClose.addActionListener(this);
Rectangle rect = Config.getDialog("DeconvolutionLab.MainDialog");
if (rect.x > 0 && rect.y > 0)
setLocation(rect.x, rect.y);
if (rect.width > 0 && rect.height > 0)
setPreferredSize(new Dimension(rect.width, rect.height));
-
+ this.setMinimumSize(new Dimension(500, 400));
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == bnClose) {
Config.store();
SystemInfo.close();
panel.close();
dispose();
return;
}
}
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
panel.close();
Config.store();
dispose();
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
@Override
public void dispose() {
super.dispose();
if (Lab.getPlatform() == Imaging.Platform.STANDALONE)
System.exit(0);
}
@Override
public void componentResized(ComponentEvent e) {
panel.sizeModule();
}
@Override
public void componentMoved(ComponentEvent e) {
Point p = this.getLocation();
p.x += this.getWidth();
DeconvolutionDialog.setLocationLaunch(p);
}
@Override
public void componentShown(ComponentEvent e) {
panel.sizeModule();
+ pack();
}
@Override
public void componentHidden(ComponentEvent e) {
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/LabPanel.java b/DeconvolutionLab2/src/deconvolutionlab/LabPanel.java
index 0f76389..3668410 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/LabPanel.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/LabPanel.java
@@ -1,295 +1,294 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import deconvolution.Command;
import deconvolution.Deconvolution;
import deconvolution.DeconvolutionDialog;
import deconvolutionlab.dialog.BatchDialog;
import deconvolutionlab.modules.AboutModule;
import deconvolutionlab.modules.AbstractModule;
import deconvolutionlab.modules.AlgorithmModule;
import deconvolutionlab.modules.BatchModule;
import deconvolutionlab.modules.BorderModule;
import deconvolutionlab.modules.CommandModule;
import deconvolutionlab.modules.ConfigModule;
import deconvolutionlab.modules.ControllerModule;
import deconvolutionlab.modules.FFTModule;
import deconvolutionlab.modules.GroupedModulePanel;
import deconvolutionlab.modules.ImageModule;
import deconvolutionlab.modules.LanguageModule;
import deconvolutionlab.modules.LicenceModule;
import deconvolutionlab.modules.OutputModule;
import deconvolutionlab.modules.PSFModule;
import deconvolutionlab.modules.RunningModule;
import deconvolutionlab.system.SystemInfo;
import lab.component.JPanelImage;
public class LabPanel extends JPanel implements ActionListener, ChangeListener {
private JTabbedPane tab = new JTabbedPane();
private JButton bnHelp = new JButton("Help");
private JButton bnQuit = new JButton("Quit");
private JButton bnSystem = new JButton("System");
private JButton bnBatch = new JButton("Batch");
private JButton bnRun = new JButton("Run");
private JButton bnLaunch = new JButton("Launch");
private JButton bnClose;
private ImageModule image;
private PSFModule psf;
private AlgorithmModule algo;
private AboutModule about;
private LicenceModule licence;
private OutputModule output;
private FFTModule fourier;
private BorderModule border;
private ConfigModule config;
private BatchModule batch;
private LanguageModule language;
private CommandModule command;
private RunningModule running;
private ControllerModule controller;
private GroupedModulePanel panelDeconv;
private GroupedModulePanel panelAdvanc;
private GroupedModulePanel panelScript;
private GroupedModulePanel panelAbout;
private AbstractModule modules[];
public LabPanel(JButton bnClose) {
this.bnClose = bnClose;
image = new ImageModule(false);
psf = new PSFModule(false);
algo = new AlgorithmModule(true);
output = new OutputModule(true);
fourier = new FFTModule(false);
border = new BorderModule(false);
controller = new ControllerModule(false);
batch = new BatchModule(false);
language = new LanguageModule(false);
about = new AboutModule(true);
licence = new LicenceModule(false);
config = new ConfigModule(false);
command = new CommandModule();
running = new RunningModule(false);
modules = new AbstractModule[] { image, psf, algo, output, controller, border, fourier, batch, running };
Command.active(modules, command);
Command.command();
panelDeconv = new GroupedModulePanel(buildDeconvolutionPanel(), this);
panelAdvanc = new GroupedModulePanel(buildAdvancedPanel(), this);
panelScript = new GroupedModulePanel(buildProgrammingPanel(), this);
panelAbout = new GroupedModulePanel(buildAboutPanel(), this);
Border border = BorderFactory.createEmptyBorder(5, 5, 5, 5);
JPanelImage bottom = new JPanelImage("celegans.jpg");
bottom.setBorder(border);
bottom.setLayout(new GridLayout(1, 6));
bottom.setBorder(border);
bottom.add(bnHelp);
bottom.add(bnSystem);
bottom.add(bnClose);
bottom.add(bnBatch);
bottom.add(bnRun);
bottom.add(bnLaunch);
tab.add("Deconvolution", panelDeconv);
tab.add("Advanced", panelAdvanc);
tab.add("Scripting", panelScript);
tab.add("About", panelAbout);
tab.addChangeListener(this);
setLayout(new BorderLayout());
add(tab, BorderLayout.CENTER);
add(bottom, BorderLayout.SOUTH);
bnBatch.addActionListener(this);
bnRun.addActionListener(this);
bnLaunch.addActionListener(this);
bnClose.addActionListener(this);
bnQuit.addActionListener(this);
bnHelp.addActionListener(this);
bnSystem.addActionListener(this);
((GroupedModulePanel) tab.getSelectedComponent()).organize();
setMinimumSize(new Dimension(500, 500));
Config.load();
running.init();
//sizeModule();
Command.command();
running.update();
image.update();
psf.update();
output.update();
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == bnHelp)
Lab.help();
else if (e.getSource() == bnClose)
Config.store();
else if (e.getSource() == bnSystem)
SystemInfo.activate();
else if (e.getSource() == bnBatch) {
tab.setSelectedIndex(2);
batch.expand();
sizeModule();
BatchDialog dlg = new BatchDialog(batch);
Lab.setVisible(dlg, true);
}
else if (e.getSource() == bnLaunch) {
String job = language.getJobName() + " " + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
Deconvolution d = new Deconvolution(job, Command.command(), Deconvolution.Finish.ALIVE);
d.launch();
}
else if (e.getSource() == bnRun) {
String job = language.getJobName() + " " + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
Deconvolution d = new Deconvolution(job, Command.command());
d.deconvolve();
-// deconvolutions.add(d);
}
}
@Override
public void stateChanged(ChangeEvent e) {
((GroupedModulePanel) tab.getSelectedComponent()).organize();
Command.command();
}
private ArrayList<AbstractModule> buildDeconvolutionPanel() {
ArrayList<AbstractModule> list = new ArrayList<AbstractModule>();
list.add(image);
list.add(psf);
list.add(algo);
list.add(running);
return list;
}
private ArrayList<AbstractModule> buildAdvancedPanel() {
ArrayList<AbstractModule> list = new ArrayList<AbstractModule>();
list.add(output);
list.add(controller);
list.add(border);
list.add(fourier);
return list;
}
private ArrayList<AbstractModule> buildProgrammingPanel() {
ArrayList<AbstractModule> list = new ArrayList<AbstractModule>();
list.add(batch);
list.add(command);
list.add(language);
return list;
}
private ArrayList<AbstractModule> buildAboutPanel() {
ArrayList<AbstractModule> list = new ArrayList<AbstractModule>();
list.add(about);
list.add(licence);
list.add(config);
return list;
}
public void close() {
for (AbstractModule module : modules)
module.close();
bnLaunch.removeActionListener(this);
bnRun.removeActionListener(this);
bnBatch.removeActionListener(this);
bnClose.removeActionListener(this);
bnHelp.removeActionListener(this);
Lab.close();
}
public void sizeModule() {
if (tab.getSelectedIndex() == 0)
sizePanel(panelDeconv);
if (tab.getSelectedIndex() == 1)
sizePanel(panelAdvanc);
if (tab.getSelectedIndex() == 2)
sizePanel(panelScript);
if (tab.getSelectedIndex() == 3)
sizePanel(panelAbout);
}
private void sizePanel(GroupedModulePanel panel) {
Dimension dim = getSize();
- int hpc = 60;
+ int hpc = 70;
int npc = hpc * panel.getModules().size();
Dimension small = new Dimension(dim.width, hpc);
Dimension large = new Dimension(dim.width, dim.height - npc);
+ setMinimumSize(new Dimension(Constants.widthGUI, 4*hpc));
for (AbstractModule module : panel.getModules()) {
if (module.isExpanded()) {
module.setPreferredSize(large);
module.setMaximumSize(large);
module.setMinimumSize(small);
module.getExpandedPanel().setPreferredSize(large);
module.getExpandedPanel().setMaximumSize(large);
module.getExpandedPanel().setMinimumSize(small);
-
}
else {
module.setPreferredSize(small);
module.setMaximumSize(small);
module.setMinimumSize(small);
module.getCollapsedPanel().setPreferredSize(small);
module.getCollapsedPanel().setMaximumSize(small);
module.getCollapsedPanel().setMinimumSize(small);
}
}
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/TableStats.java b/DeconvolutionLab2/src/deconvolutionlab/TableStats.java
index b456ea7..368efff 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/TableStats.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/TableStats.java
@@ -1,90 +1,89 @@
package deconvolutionlab;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.io.File;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
+import javax.swing.table.DefaultTableModel;
import deconvolutionlab.monitor.Monitors;
import lab.component.CustomizedColumn;
import lab.component.CustomizedTable;
public class TableStats {
private JPanel panel;
private CustomizedTable table;
private String name;
private boolean save;
private String path;
public TableStats(String name, int width, int height, String path, boolean save) {
this.name = name;
this.save = save;
this.path = path;
ArrayList<CustomizedColumn> columns = new ArrayList<CustomizedColumn>();
columns.add(new CustomizedColumn("Iterations", String.class, 100, false));
columns.add(new CustomizedColumn("Mean", String.class, 100, false));
columns.add(new CustomizedColumn("Minimum", String.class, 100, false));
columns.add(new CustomizedColumn("Maximum", String.class, 100, false));
columns.add(new CustomizedColumn("Stdev", String.class, 100, false));
columns.add(new CustomizedColumn("Energy", String.class, 100, false));
columns.add(new CustomizedColumn("Time", String.class, 100, false));
columns.add(new CustomizedColumn("Memory", String.class, 100, false));
columns.add(new CustomizedColumn("Signal", String.class, 100, false));
columns.add(new CustomizedColumn("PSNR", String.class, 100, false));
columns.add(new CustomizedColumn("SNR", String.class, 100, false));
columns.add(new CustomizedColumn("Residu", String.class, 100, false));
table = new CustomizedTable(columns, true);
JScrollPane scroll = new JScrollPane(table);
scroll.setPreferredSize(new Dimension(width, height));
JPanel main = new JPanel(new BorderLayout());
main.add(scroll, BorderLayout.CENTER);
panel = new JPanel(new BorderLayout());
panel.add(main);
panel.setBorder(BorderFactory.createEtchedBorder());
}
public String getName() {
return name;
}
-
+
+ public void clear() {
+ DefaultTableModel model = (DefaultTableModel) table.getModel();
+ model.setRowCount(0);
+ }
+
public void nextStats(Monitors monitors, String[] stats) {
if (table == null)
return;
if (stats == null)
return;
table.append(stats);
monitors.log("Stats ");
}
public void lastStats(Monitors monitors, String[] stats) {
if (stats == null)
return;
if (table == null)
return;
if (save) {
String filename = path + File.separator + name + ".csv";
monitors.log("Stats save " + filename);
table.saveCSV(filename);
}
}
public JPanel getPanel() {
return panel;
}
- public void show() {
- JFrame frame = new JFrame(name);
- frame.getContentPane().add(panel);
- frame.pack();
- frame.setVisible(true);
- }
-
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/dialog/OutputDialog.java b/DeconvolutionLab2/src/deconvolutionlab/dialog/OutputDialog.java
index 66fb214..73475d5 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/dialog/OutputDialog.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/dialog/OutputDialog.java
@@ -1,238 +1,275 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.dialog;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
+import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import deconvolutionlab.Imaging;
-import deconvolutionlab.Lab;
import deconvolutionlab.Output;
import deconvolutionlab.Output.Dynamic;
import deconvolutionlab.Output.View;
import ij.gui.GUI;
import lab.component.GridPanel;
+import lab.component.HTMLPane;
import lab.component.SpinnerRangeInteger;
public class OutputDialog extends JDialog implements ActionListener, ChangeListener {
private JComboBox<String> cmbDynamic = new JComboBox<String>(new String[] { "intact", "rescaled", "normalized", "clipped" });
private JComboBox<String> cmbType = new JComboBox<String>(new String[] { "float", "short", "byte" });
private JCheckBox chkSave = new JCheckBox("Save output", true);
private JCheckBox chkShow = new JCheckBox("Show output", true);
private SpinnerRangeInteger snpSnapshot = new SpinnerRangeInteger(0, 0, 99999, 1);
private JComboBox<String> cmbSnapshot = new JComboBox<String>(new String[] { "Final Output", "Specify Iterations..." });
private SpinnerRangeInteger spnX = new SpinnerRangeInteger(128, 0, 99999, 1);
private SpinnerRangeInteger spnY = new SpinnerRangeInteger(128, 0, 99999, 1);
private SpinnerRangeInteger spnZ = new SpinnerRangeInteger(32, 0, 99999, 1);
private JTextField txtName = new JTextField("Noname", 18);
private JCheckBox chkCenter = new JCheckBox("Center of the volume", true);
private JButton bnOK = new JButton("OK");
private JButton bnCancel = new JButton("Cancel");
private boolean cancel = false;
private JLabel lblBit = new JLabel("32-bit");
private JLabel lblIter = new JLabel("iterations");
- private JLabel lblSnapshot = new JLabel("Snapshot");
+ private JLabel lblSnapshot = new JLabel("Iterations");
private Output out;
private View view;
private GridPanel pnOrtho;
-
+ private HTMLPane info = new HTMLPane(200, 200);
+
private static int count = 1;
public OutputDialog(View view) {
super(new JFrame(), "Create a new output");
this.view = view;
lblBit.setBorder(BorderFactory.createEtchedBorder());
lblIter.setBorder(BorderFactory.createEtchedBorder());
txtName.setText(view.name().substring(0, 2) + (count++));
- GridPanel pn = new GridPanel(view.name());
+ GridPanel pn = new GridPanel(true);
pn.place(0, 0, "Name");
- pn.place(0, 1, 2, 1, txtName);
+ pn.place(0, 1, txtName);
pn.place(1, 0, "Dynamic");
pn.place(1, 1, cmbDynamic);
pn.place(2, 0, "Type");
pn.place(2, 1, cmbType);
- pn.place(2, 2, lblBit);
+ pn.place(3, 1, lblBit);
if (view != View.SERIES && view != View.STACK) {
pn.place(4, 0, "Snapshot");
pn.place(4, 1, cmbSnapshot);
pn.place(5, 0, lblSnapshot);
pn.place(5, 1, snpSnapshot);
- pn.place(5, 2, lblIter);
+ pn.place(6, 1, lblIter);
}
- pn.place(6, 0, 3, 1, chkShow);
- pn.place(7, 0, 3, 1, chkSave);
+ pn.place(7, 1, 3, 1, chkShow);
+ pn.place(8, 1, 3, 1, chkSave);
GridPanel main = new GridPanel(false);
main.place(1, 0, 2, 1, pn);
-
+
if (view == View.ORTHO || view == View.FIGURE) {
- pn.place(8, 0, 3, 1, chkCenter);
+ pn.place(9, 1, 3, 1, chkCenter);
pnOrtho = new GridPanel("Keypoint");
pnOrtho.place(4, 0, "Position in X");
pnOrtho.place(4, 1, spnX);
pnOrtho.place(4, 2, "[pixel]");
pnOrtho.place(5, 0, "Position in Y");
pnOrtho.place(5, 1, spnY);
pnOrtho.place(5, 2, "[pixel]");
pnOrtho.place(6, 0, "Position in Z");
pnOrtho.place(6, 1, spnZ);
pnOrtho.place(5, 2, "[pixel]");
main.place(2, 0, 2, 1, pnOrtho);
}
+ pn.place(10, 0, 2, 1, info.getPane());
+
main.place(3, 0, bnCancel);
main.place(3, 1, bnOK);
+ info();
cmbSnapshot.addActionListener(this);
snpSnapshot.addChangeListener(this);
chkCenter.addActionListener(this);
cmbType.addActionListener(this);
bnOK.addActionListener(this);
bnCancel.addActionListener(this);
add(main);
update();
pack();
GUI.center(this);
setModal(true);
}
-
+
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == chkCenter) {
update();
}
else if (e.getSource() == cmbSnapshot) {
update();
}
else if (e.getSource() == cmbType) {
if (cmbType.getSelectedIndex() == 0)
lblBit.setText("32-bits");
if (cmbType.getSelectedIndex() == 1)
lblBit.setText("16-bits");
if (cmbType.getSelectedIndex() == 2)
lblBit.setText("8-bits");
}
else if (e.getSource() == bnCancel) {
dispose();
cancel = true;
return;
}
else if (e.getSource() == bnOK) {
int freq = snpSnapshot.get();
Dynamic dynamic = Output.Dynamic.values()[cmbDynamic.getSelectedIndex()];
Imaging.Type type = Imaging.Type.values()[cmbType.getSelectedIndex()];
boolean show = chkShow.isSelected();
boolean save = chkSave.isSelected();
String name = txtName.getText();
if (chkCenter.isSelected()) {
out = new Output(view, show, save, freq, name, dynamic, type, true);
}
else {
int px = spnX.get();
int py = spnY.get();
int pz = spnZ.get();
out = new Output(view, show, save, freq, name, dynamic, type, px, py, pz);
}
dispose();
cancel = false;
}
}
private void update() {
if (cmbSnapshot.getSelectedIndex() == 0) {
snpSnapshot.set(0);
lblSnapshot.setEnabled(false);
lblIter.setEnabled(false);
lblSnapshot.setEnabled(false);
}
else {
lblSnapshot.setEnabled(true);
lblIter.setEnabled(true);
lblSnapshot.setEnabled(true);
}
if (snpSnapshot.get() == 0)
lblIter.setText("at the end (default)");
else
lblIter.setText("every " + snpSnapshot.get() + " iterations");
if (snpSnapshot.get() == 0)
lblIter.setText("at the end (default)");
else
lblIter.setText("every " + snpSnapshot.get() + " iterations");
boolean b = !chkCenter.isSelected();
if (pnOrtho != null) {
pnOrtho.setEnabled(b);
for (Component c : pnOrtho.getComponents())
c.setEnabled(b);
}
pack();
}
@Override
public void stateChanged(ChangeEvent e) {
if (e.getSource() == snpSnapshot)
update();
}
public Output getOut() {
return out;
}
public boolean wasCancel() {
return cancel;
}
+
+ private void info() {
+ if (view == View.FIGURE) {
+ info.append("h1", "figure");
+ info.append("h2", "Create a view with 2 panels (XY) and (YZ) with a border.");
+ }
+ if (view == View.MIP) {
+ info.append("h1", "mip");
+ info.append("h2", "Create a view 3 orthogonal projections.");
+ }
+ if (view == View.ORTHO) {
+ info.append("h1", "ortho");
+ info.append("h2", "Create a view 3 orthogonal section centered on the keypoint.");
+ }
+ if (view == View.PLANAR) {
+ info.append("h1", "ortho");
+ info.append("h2", "Create a montage of all Z-slice in one large flatten plane.");
+ }
+ if (view == View.STACK) {
+ info.append("h1", "stack");
+ info.append("h2", "Create a z-stack of image.");
+ }
+ if (view == View.SERIES) {
+ info.append("h1", "series");
+ info.append("h2", "Create a series of z-slices.");
+ }
+
+ info.append("p", "<b>Name:</b> This string will be used as title of the window in <i>show</i> mode or a filename in <i>save</i> mode.");
+ info.append("p", "<b>Dynamic:</b> Select the dynamic range used for the display. The default value is <i>intact</i> which preserves the true values.");
+ info.append("p", "<b>Type:</b> Select the data type. The default value is <i>float</i> which preserves the true values without loosing precision.");
+ info.append("p", "<b>Snapshot:</b> The output is usually shown (or saved) at the end of the processing, optionally it is possible to specify to show (or save) every N iterations.");
+ }
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/dialog/OutputDialog.java b/DeconvolutionLab2/src/deconvolutionlab/dialog/OutputPanel.java
similarity index 76%
copy from DeconvolutionLab2/src/deconvolutionlab/dialog/OutputDialog.java
copy to DeconvolutionLab2/src/deconvolutionlab/dialog/OutputPanel.java
index 66fb214..8954d79 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/dialog/OutputDialog.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/dialog/OutputPanel.java
@@ -1,238 +1,269 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.dialog;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
-import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
+import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import deconvolutionlab.Imaging;
-import deconvolutionlab.Lab;
import deconvolutionlab.Output;
import deconvolutionlab.Output.Dynamic;
import deconvolutionlab.Output.View;
import ij.gui.GUI;
import lab.component.GridPanel;
+import lab.component.HTMLPane;
import lab.component.SpinnerRangeInteger;
-public class OutputDialog extends JDialog implements ActionListener, ChangeListener {
+public class OutputPanel extends JPanel implements ActionListener, ChangeListener {
private JComboBox<String> cmbDynamic = new JComboBox<String>(new String[] { "intact", "rescaled", "normalized", "clipped" });
private JComboBox<String> cmbType = new JComboBox<String>(new String[] { "float", "short", "byte" });
private JCheckBox chkSave = new JCheckBox("Save output", true);
private JCheckBox chkShow = new JCheckBox("Show output", true);
private SpinnerRangeInteger snpSnapshot = new SpinnerRangeInteger(0, 0, 99999, 1);
private JComboBox<String> cmbSnapshot = new JComboBox<String>(new String[] { "Final Output", "Specify Iterations..." });
private SpinnerRangeInteger spnX = new SpinnerRangeInteger(128, 0, 99999, 1);
private SpinnerRangeInteger spnY = new SpinnerRangeInteger(128, 0, 99999, 1);
private SpinnerRangeInteger spnZ = new SpinnerRangeInteger(32, 0, 99999, 1);
private JTextField txtName = new JTextField("Noname", 18);
private JCheckBox chkCenter = new JCheckBox("Center of the volume", true);
private JButton bnOK = new JButton("OK");
private JButton bnCancel = new JButton("Cancel");
private boolean cancel = false;
private JLabel lblBit = new JLabel("32-bit");
private JLabel lblIter = new JLabel("iterations");
- private JLabel lblSnapshot = new JLabel("Snapshot");
+ private JLabel lblSnapshot = new JLabel("Iterations");
private Output out;
private View view;
private GridPanel pnOrtho;
-
+ private HTMLPane info = new HTMLPane(200, 200);
+
private static int count = 1;
- public OutputDialog(View view) {
- super(new JFrame(), "Create a new output");
+ public OutputPanel(View view) {
this.view = view;
lblBit.setBorder(BorderFactory.createEtchedBorder());
lblIter.setBorder(BorderFactory.createEtchedBorder());
txtName.setText(view.name().substring(0, 2) + (count++));
- GridPanel pn = new GridPanel(view.name());
+ GridPanel pn = new GridPanel(true);
pn.place(0, 0, "Name");
- pn.place(0, 1, 2, 1, txtName);
+ pn.place(0, 1, txtName);
pn.place(1, 0, "Dynamic");
pn.place(1, 1, cmbDynamic);
pn.place(2, 0, "Type");
pn.place(2, 1, cmbType);
- pn.place(2, 2, lblBit);
+ pn.place(3, 1, lblBit);
if (view != View.SERIES && view != View.STACK) {
pn.place(4, 0, "Snapshot");
pn.place(4, 1, cmbSnapshot);
pn.place(5, 0, lblSnapshot);
pn.place(5, 1, snpSnapshot);
- pn.place(5, 2, lblIter);
+ pn.place(6, 1, lblIter);
}
- pn.place(6, 0, 3, 1, chkShow);
- pn.place(7, 0, 3, 1, chkSave);
+ pn.place(7, 1, 3, 1, chkShow);
+ pn.place(8, 1, 3, 1, chkSave);
GridPanel main = new GridPanel(false);
main.place(1, 0, 2, 1, pn);
if (view == View.ORTHO || view == View.FIGURE) {
- pn.place(8, 0, 3, 1, chkCenter);
+ pn.place(9, 1, 3, 1, chkCenter);
pnOrtho = new GridPanel("Keypoint");
pnOrtho.place(4, 0, "Position in X");
pnOrtho.place(4, 1, spnX);
pnOrtho.place(4, 2, "[pixel]");
pnOrtho.place(5, 0, "Position in Y");
pnOrtho.place(5, 1, spnY);
pnOrtho.place(5, 2, "[pixel]");
pnOrtho.place(6, 0, "Position in Z");
pnOrtho.place(6, 1, spnZ);
pnOrtho.place(5, 2, "[pixel]");
main.place(2, 0, 2, 1, pnOrtho);
}
+ pn.place(10, 0, 2, 1, info.getPane());
+
main.place(3, 0, bnCancel);
main.place(3, 1, bnOK);
+ info();
cmbSnapshot.addActionListener(this);
snpSnapshot.addChangeListener(this);
chkCenter.addActionListener(this);
cmbType.addActionListener(this);
bnOK.addActionListener(this);
bnCancel.addActionListener(this);
add(main);
update();
- pack();
- GUI.center(this);
- setModal(true);
+
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == chkCenter) {
update();
}
else if (e.getSource() == cmbSnapshot) {
update();
}
else if (e.getSource() == cmbType) {
if (cmbType.getSelectedIndex() == 0)
lblBit.setText("32-bits");
if (cmbType.getSelectedIndex() == 1)
lblBit.setText("16-bits");
if (cmbType.getSelectedIndex() == 2)
lblBit.setText("8-bits");
}
else if (e.getSource() == bnCancel) {
- dispose();
cancel = true;
return;
}
else if (e.getSource() == bnOK) {
int freq = snpSnapshot.get();
Dynamic dynamic = Output.Dynamic.values()[cmbDynamic.getSelectedIndex()];
Imaging.Type type = Imaging.Type.values()[cmbType.getSelectedIndex()];
boolean show = chkShow.isSelected();
boolean save = chkSave.isSelected();
String name = txtName.getText();
if (chkCenter.isSelected()) {
out = new Output(view, show, save, freq, name, dynamic, type, true);
}
else {
int px = spnX.get();
int py = spnY.get();
int pz = spnZ.get();
out = new Output(view, show, save, freq, name, dynamic, type, px, py, pz);
}
- dispose();
cancel = false;
}
}
private void update() {
if (cmbSnapshot.getSelectedIndex() == 0) {
snpSnapshot.set(0);
lblSnapshot.setEnabled(false);
lblIter.setEnabled(false);
lblSnapshot.setEnabled(false);
}
else {
lblSnapshot.setEnabled(true);
lblIter.setEnabled(true);
lblSnapshot.setEnabled(true);
}
if (snpSnapshot.get() == 0)
lblIter.setText("at the end (default)");
else
lblIter.setText("every " + snpSnapshot.get() + " iterations");
if (snpSnapshot.get() == 0)
lblIter.setText("at the end (default)");
else
lblIter.setText("every " + snpSnapshot.get() + " iterations");
boolean b = !chkCenter.isSelected();
if (pnOrtho != null) {
pnOrtho.setEnabled(b);
for (Component c : pnOrtho.getComponents())
c.setEnabled(b);
}
- pack();
+ //pack();
}
@Override
public void stateChanged(ChangeEvent e) {
if (e.getSource() == snpSnapshot)
update();
}
public Output getOut() {
return out;
}
public boolean wasCancel() {
return cancel;
}
+
+ private void info() {
+ if (view == View.FIGURE) {
+ info.append("h1", "figure");
+ info.append("h2", "Create a view with 2 panels (XY) and (YZ) with a border.");
+ }
+ if (view == View.MIP) {
+ info.append("h1", "mip");
+ info.append("h2", "Create a view 3 orthogonal projections.");
+ }
+ if (view == View.ORTHO) {
+ info.append("h1", "ortho");
+ info.append("h2", "Create a view 3 orthogonal section centered on the keypoint.");
+ }
+ if (view == View.PLANAR) {
+ info.append("h1", "ortho");
+ info.append("h2", "Create a montage of all Z-slice in one large flatten plane.");
+ }
+ if (view == View.STACK) {
+ info.append("h1", "stack");
+ info.append("h2", "Create a z-stack of image.");
+ }
+ if (view == View.SERIES) {
+ info.append("h1", "series");
+ info.append("h2", "Create a series of z-slices.");
+ }
+
+ info.append("p", "<b>Name:</b> This string will be used as title of the window in <i>show</i> mode or a filename in <i>save</i> mode.");
+ info.append("p", "<b>Dynamic:</b> Select the dynamic range used for the display. The default value is <i>intact</i> which preserves the true values.");
+ info.append("p", "<b>Type:</b> Select the data type. The default value is <i>float</i> which preserves the true values without loosing precision.");
+ info.append("p", "<b>Snapshot:</b> The output is usually shown (or saved) at the end of the processing, optionally it is possible to specify to show (or save) every N iterations.");
+ }
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/modules/BorderModule.java b/DeconvolutionLab2/src/deconvolutionlab/modules/BorderModule.java
index e72be64..f069217 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/modules/BorderModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/modules/BorderModule.java
@@ -1,247 +1,247 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.modules;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import deconvolution.Command;
import deconvolution.Deconvolution;
import deconvolution.Features;
import deconvolutionlab.Config;
import deconvolutionlab.monitor.Monitors;
import lab.component.GridPanel;
import lab.component.SpinnerRangeInteger;
import lab.tools.NumFormat;
import signal.RealSignal;
import signal.apodization.AbstractApodization;
import signal.apodization.Apodization;
import signal.apodization.UniformApodization;
import signal.padding.AbstractPadding;
import signal.padding.NoPadding;
import signal.padding.Padding;
public class BorderModule extends AbstractModule implements ActionListener, ChangeListener {
private JComboBox<String> cmbPadXY;
private JComboBox<String> cmbPadZ;
private JComboBox<String> cmbApoXY;
private JComboBox<String> cmbApoZ;
private SpinnerRangeInteger spnExtensionXY;
private SpinnerRangeInteger spnExtensionZ;
private JLabel lblPad;
private JLabel lblApo;
private boolean build = false;
public BorderModule(boolean expanded) {
super("Border", "", "Test", "Default", expanded);
}
@Override
public String getCommand() {
AbstractPadding pxy = Padding.getByName((String) cmbPadXY.getSelectedItem());
AbstractPadding paz = Padding.getByName((String) cmbPadZ.getSelectedItem());
AbstractApodization axy = Apodization.getByName((String) cmbApoXY.getSelectedItem());
AbstractApodization apz = Apodization.getByName((String) cmbApoZ.getSelectedItem());
boolean ext = spnExtensionXY.get() + spnExtensionZ.get() > 0;
String extXY = (ext ? "" + spnExtensionXY.get() : "") + " ";
String extZ = ext ? "" + spnExtensionZ.get() : "";
String cmd = "";
if (!(pxy instanceof NoPadding) || !(paz instanceof NoPadding) || spnExtensionXY.get() > 0 || spnExtensionZ.get() > 0)
cmd += " -pad " + pxy.getShortname() + " " + paz.getShortname() + " " + extXY + extZ;
if (!(axy instanceof UniformApodization) || !(apz instanceof UniformApodization))
cmd += " -apo " + axy.getShortname() + " " + apz.getShortname() + " ";
return cmd;
}
@Override
public JPanel buildExpandedPanel() {
lblPad = new JLabel("Information on padding size");
lblPad.setBorder(BorderFactory.createEtchedBorder());
lblApo = new JLabel("Information on apodization energy");
lblApo.setBorder(BorderFactory.createEtchedBorder());
cmbPadXY = new JComboBox<String>(Padding.getPaddingsAsArray());
cmbPadZ = new JComboBox<String>(Padding.getPaddingsAsArray());
cmbApoXY = new JComboBox<String>(Apodization.getApodizationsAsArray());
cmbApoZ = new JComboBox<String>(Apodization.getApodizationsAsArray());
spnExtensionXY = new SpinnerRangeInteger(0, 0, 99999, 1);
spnExtensionZ = new SpinnerRangeInteger(0, 0, 99999, 1);
GridPanel pnBorder = new GridPanel(false, 3);
pnBorder.place(0, 1, "Lateral (XY)");
pnBorder.place(0, 2, "Axial (Z)");
pnBorder.place(2, 0, "Apodization");
pnBorder.place(2, 1, cmbApoXY);
pnBorder.place(2, 2, cmbApoZ);
pnBorder.place(3, 0, "Padding Extension");
pnBorder.place(3, 1, spnExtensionXY);
pnBorder.place(3, 2, spnExtensionZ);
pnBorder.place(4, 0, "Padding Constraint");
pnBorder.place(4, 1, cmbPadXY);
pnBorder.place(4, 2, cmbPadZ);
pnBorder.place(5, 0, 3, 1, lblPad);
pnBorder.place(6, 0, 3, 1, lblApo);
JScrollPane scroll = new JScrollPane(pnBorder);
scroll.setBorder(BorderFactory.createEmptyBorder());
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEtchedBorder());
panel.add(scroll, BorderLayout.CENTER);
Config.register(getName(), "padxy", cmbPadXY, Padding.getDefault().getName());
Config.register(getName(), "padz", cmbPadZ, Padding.getDefault().getName());
Config.register(getName(), "apoxy", cmbApoXY, Apodization.getDefault().getName());
Config.register(getName(), "apoz", cmbApoZ, Apodization.getDefault().getName());
Config.register(getName(), "extxy", spnExtensionXY, "0");
Config.register(getName(), "extz", spnExtensionZ, "0");
spnExtensionXY.addChangeListener(this);
spnExtensionZ.addChangeListener(this);
cmbPadXY.addActionListener(this);
cmbPadZ.addActionListener(this);
cmbApoXY.addActionListener(this);
cmbApoZ.addActionListener(this);
getAction1Button().addActionListener(this);
getAction2Button().addActionListener(this);
build = true;
return panel;
}
private void update() {
setCommand(getCommand());
boolean ext = spnExtensionXY.get() + spnExtensionZ.get() > 0;
boolean pad = cmbPadXY.getSelectedIndex() + cmbPadZ.getSelectedIndex() > 0;
boolean apo = cmbApoXY.getSelectedIndex() + cmbApoZ.getSelectedIndex() > 0;
if (pad || apo || ext) {
setSynopsis("" + " " + (pad ? "Padding" : "") + " " + (ext ? "Extension" : "") + " " + (apo ? "Apodization" : ""));
}
else {
setSynopsis("Default options");
}
Command.command();
}
@Override
public void stateChanged(ChangeEvent e) {
update();
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (e.getSource() == getAction2Button()) {
cmbPadXY.removeActionListener(this);
cmbPadZ.removeActionListener(this);
cmbApoXY.removeActionListener(this);
cmbApoZ.removeActionListener(this);
cmbPadXY.setSelectedIndex(0);
cmbPadZ.setSelectedIndex(0);
cmbApoXY.setSelectedIndex(0);
cmbApoZ.setSelectedIndex(0);
spnExtensionXY.set(0);
spnExtensionZ.set(0);
cmbPadXY.addActionListener(this);
cmbPadZ.addActionListener(this);
cmbApoXY.addActionListener(this);
cmbApoZ.addActionListener(this);
update();
return;
}
if (e.getSource() == getAction1Button()) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
getAction1Button().setEnabled(false);
getAction2Button().setEnabled(false);
Deconvolution d = new Deconvolution("CheckImage", Command.command());
Apodization apo = d.getApodization();
if (apo == null) {
lblApo.setText("Error in Apodization");
return;
}
Padding pad = d.getPadding();
if (pad == null) {
lblPad.setText("Error in Padding");
return;
}
RealSignal x = d.openImage();
if (x == null) {
lblPad.setText("Error in input image");
lblApo.setText("Error in input image");
return;
}
Monitors m = Monitors.createDefaultMonitor();
- RealSignal y = pad.pad(m, apo.apodize(m, x));
-
+ RealSignal y = pad.pad(m, x);
+ apo.apodize(m, y);
lblPad.setText(x.dimAsString() + " > " + y.dimAsString());
lblApo.setText(NumFormat.nice(x.getStats()[5]) + " > " + NumFormat.nice(y.getStats()[5]));
getAction1Button().setEnabled(true);
getAction2Button().setEnabled(true);
}
});
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
return;
}
update();
}
@Override
public void close() {
cmbPadXY.removeActionListener(this);
cmbPadZ.removeActionListener(this);
cmbApoXY.removeActionListener(this);
cmbApoZ.removeActionListener(this);
getAction1Button().removeActionListener(this);
getAction2Button().removeActionListener(this);
spnExtensionXY.removeChangeListener(this);
spnExtensionZ.removeChangeListener(this);
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/modules/ImageModule.java b/DeconvolutionLab2/src/deconvolutionlab/modules/ImageModule.java
index b999140..ca7542d 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/modules/ImageModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/modules/ImageModule.java
@@ -1,353 +1,354 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.modules;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import deconvolution.Command;
import deconvolution.Deconvolution;
import deconvolution.DeconvolutionDialog;
import deconvolution.modules.ImageDModule;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
import deconvolutionlab.Imaging;
import deconvolutionlab.Lab;
import deconvolutionlab.dialog.PatternDialog;
import deconvolutionlab.dialog.SyntheticDialog;
import deconvolutionlab.monitor.Monitors;
import lab.component.CustomizedColumn;
import lab.component.CustomizedTable;
import lab.tools.Files;
import signal.RealSignal;
import signal.factory.SignalFactory;
public class ImageModule extends AbstractModule implements ActionListener, MouseListener {
private CustomizedTable table;
private JButton bnFile;
private JButton bnDirectory;
private JButton bnSynthetic;
private JButton bnPlatform;
public ImageModule(boolean expanded) {
super("Image", "-image", (Lab.getPlatform() == Imaging.Platform.IMAGEJ ? "Active" : ""), "Check", expanded);
}
@Override
public String getCommand() {
int row = table.getSelectedRow();
if (row < 0)
return "";
return "-image " + table.getCell(row, 1) + " " + table.getCell(row, 2);
}
@Override
public JPanel buildExpandedPanel() {
ArrayList<CustomizedColumn> columns = new ArrayList<CustomizedColumn>();
columns.add(new CustomizedColumn("Name", String.class, 100, false));
columns.add(new CustomizedColumn("Source", String.class, 100, false));
columns.add(new CustomizedColumn("Command", String.class, Constants.widthGUI - 200, true));
columns.add(new CustomizedColumn("", String.class, 30, "\u232B", "Delete this image source"));
table = new CustomizedTable(columns, true);
table.getColumnModel().getColumn(3).setMaxWidth(30);
table.getColumnModel().getColumn(3).setMinWidth(30);
table.addMouseListener(this);
bnFile = new JButton("\u2295 file");
bnDirectory = new JButton("\u2295 directory");
bnSynthetic = new JButton("\u2295 synthetic");
bnPlatform = new JButton("\u2295 platform");
JToolBar pn = new JToolBar("Controls Image");
pn.setBorder(BorderFactory.createEmptyBorder());
pn.setLayout(new GridLayout(1, 4));
pn.setFloatable(false);
pn.add(bnFile);
pn.add(bnDirectory);
pn.add(bnSynthetic);
if (Lab.getPlatform() == Imaging.Platform.IMAGEJ)
pn.add(bnPlatform);
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEtchedBorder());
panel.setLayout(new BorderLayout());
panel.add(pn, BorderLayout.SOUTH);
panel.add(table.getMinimumPane(100, 100), BorderLayout.CENTER);
table.setDropTarget(new LocalDropTarget());
getCollapsedPanel().setDropTarget(new LocalDropTarget());
bnFile.addActionListener(this);
bnDirectory.addActionListener(this);
bnSynthetic.addActionListener(this);
bnPlatform.addActionListener(this);
getAction1Button().addActionListener(this);
getAction2Button().addActionListener(this);
getAction2Button().setToolTipText("Click to have a preview, Shift-click or Ctrl-click to show the complete stack");
getAction1Button().setToolTipText("Select the active window");
Config.registerTable(getName(), "image", table);
return panel;
}
public void update() {
int row = table.getSelectedRow();
if (row >= 0) {
setCommand(getCommand());
setSynopsis(table.getCell(row, 0));
Command.command();
}
else {
setSynopsis("");
setCommand("Drag your image file, here");
}
getAction2Button().setEnabled(table.getRowCount() > 0);
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (e.getSource() == bnFile)
file(Command.getPath());
else if (e.getSource() == bnDirectory)
dir(Command.getPath());
else if (e.getSource() == bnSynthetic)
synthetic(false);
else if (e.getSource() == bnPlatform)
platform();
else if (e.getSource() == getAction1Button()) {
int row = -1;
for(int i=0; i<table.getRowCount(); i++) {
if (table.getCell(i, 0).equalsIgnoreCase("active"))
if (table.getCell(i, 1).equalsIgnoreCase("platform"))
if (table.getCell(i, 2).equalsIgnoreCase("active"))
row = i;
}
if (row < 0)
table.insert(new String[] { "active", "platform", "active", "\u232B" });
else
table.setRowSelectionInterval(row, row);
}
else if (e.getSource() == getAction2Button()) {
boolean s = (e.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_MASK;
boolean c = (e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK;
display(s | c);
}
update();
}
public void platform() {
String name = Lab.getActiveImage();
if (name != "")
table.insert(new String[] { name, "platform", name, "\u232B" });
}
private void file(String path) {
File file = Files.browseFile(path);
if (file == null)
return;
table.insert(new String[] { file.getName(), "file", file.getAbsolutePath(), "\u232B" });
}
private void dir(String path) {
File file = Files.browseDirectory(path);
if (file == null)
return;
PatternDialog dlg = new PatternDialog(file);
Lab.setVisible(dlg, true);
if (dlg.wasCancel())
return;
table.insert(new String[] { dlg.getDirName(), "directory", dlg.getCommand(), "\u232B" });
}
private void synthetic(boolean edit) {
ArrayList<SignalFactory> list = SignalFactory.getImages();
SyntheticDialog dlg = new SyntheticDialog(list);
if (edit) {
int row = table.getSelectedRow();
if (row >= 0) {
dlg.setParameters(table.getCell(row, 0), table.getCell(row, 1));
}
}
Lab.setVisible(dlg, true);
if (dlg.wasCancel())
return;
if (edit) {
int row = table.getSelectedRow();
if (row <= 0)
table.removeRow(row);
}
table.insert(new String[] { dlg.getShapeName(), "synthetic", dlg.getCommand(), "\u232B" });
}
private void edit() {
int row = table.getSelectedRow();
if (row < 0)
return;
String name = table.getCell(row, 0).trim();
for (SignalFactory factory : SignalFactory.getAll()) {
if (name.equals(factory.getName().trim()))
synthetic(true);
return;
}
String filename = table.getCell(row, 1).trim();
File file = new File(filename);
if (!file.exists())
return;
if (file.isFile())
file(table.getCell(row, 21));
else
dir(table.getCell(row, 1));
}
private void display(boolean stack) {
int row = table.getSelectedRow();
if (row < 0)
return;
Deconvolution deconvolution = new Deconvolution("Check Image", Command.command());
+ deconvolution.openImage();
if (stack) {
- RealSignal x = deconvolution.openImage();
+ RealSignal x = deconvolution.getImage();
if (x != null)
Lab.show(Monitors.createDefaultMonitor(), x, table.getCell(row, 0));
}
else {
DeconvolutionDialog d = new DeconvolutionDialog(DeconvolutionDialog.Module.IMAGE, deconvolution, null, null);
Lab.setVisible(d, false);
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() == table) {
int row = table.getSelectedRow();
if (row < 0)
return;
if (table.getSelectedColumn() == 3) {
table.removeRow(row);
if (table.getRowCount() > 0)
table.setRowSelectionInterval(0, 0);
}
update();
if (e.getClickCount() == 2) {
edit();
}
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void close() {
bnFile.removeActionListener(this);
bnDirectory.removeActionListener(this);
bnSynthetic.removeActionListener(this);
bnPlatform.removeActionListener(this);
}
public class LocalDropTarget extends DropTarget {
@Override
public void drop(DropTargetDropEvent e) {
e.acceptDrop(DnDConstants.ACTION_COPY);
e.getTransferable().getTransferDataFlavors();
Transferable transferable = e.getTransferable();
DataFlavor[] flavors = transferable.getTransferDataFlavors();
for (DataFlavor flavor : flavors) {
if (flavor.isFlavorJavaFileListType()) {
try {
List<File> files = (List<File>) transferable.getTransferData(flavor);
for (File file : files) {
if (file.isDirectory()) {
table.insert(new String[] { file.getName(), "directory", file.getAbsolutePath(), "" });
table.setRowSelectionInterval(0, 0);
update();
}
if (file.isFile()) {
table.insert(new String[] { file.getName(), "file", file.getAbsolutePath(), "" });
update();
}
}
}
catch (UnsupportedFlavorException ex) {
ex.printStackTrace();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
e.dropComplete(true);
super.drop(e);
}
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/modules/OutputModule.java b/DeconvolutionLab2/src/deconvolutionlab/modules/OutputModule.java
index 6754279..fcb13b3 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/modules/OutputModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/modules/OutputModule.java
@@ -1,235 +1,236 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.modules;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import deconvolution.Command;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
import deconvolutionlab.Lab;
import deconvolutionlab.Output;
import deconvolutionlab.Output.View;
import deconvolutionlab.dialog.OutputDialog;
import lab.component.CustomizedColumn;
import lab.component.CustomizedTable;
public class OutputModule extends AbstractModule implements ActionListener, MouseListener {
private CustomizedTable table;
private JButton bnStack;
private JButton bnSeries;
private JButton bnMIP;
private JButton bnOrtho;
private JButton bnPlanar;
private JButton bnFigure;
public OutputModule(boolean expanded) {
super("Output", "", "", "Default", expanded);
}
@Override
public String getCommand() {
String cmd = " ";
if (table == null)
return cmd;
for (int i = 0; i < table.getRowCount(); i++) {
String[] values = new String[table.getColumnCount()];
for(int c=0; c<table.getColumnCount(); c++)
values[c] = table.getCell(i, c) == null ? "" : table.getCell(i, c).trim();
cmd += " -out " + values[0] + " " + values[1] + " " + values[2] + " " + values[3] + " " + values[4];
if (values[5].equals(""))
cmd += " noshow";
if (values[6].equals(""))
cmd += " nosave";
}
return cmd;
}
public void update() {
setCommand(getCommand());
setSynopsis(table.getRowCount() + " output" + (table.getRowCount() > 1 ? "s" : ""));
Command.command();
getAction1Button().setEnabled(table.getRowCount() > 0);
}
@Override
public JPanel buildExpandedPanel() {
String[] dynamics = { "intact", "rescaled", "normalized", "clipped" };
String[] types = { "float", "short", "byte" };
ArrayList<CustomizedColumn> columns = new ArrayList<CustomizedColumn>();
columns.add(new CustomizedColumn("Mode", String.class, 80, false));
columns.add(new CustomizedColumn("Name", String.class, Constants.widthGUI, true));
columns.add(new CustomizedColumn("Dynamic", String.class, 100, dynamics, "Select the dynamic range"));
columns.add(new CustomizedColumn("Type", String.class, 100, types, "Select the type"));
columns.add(new CustomizedColumn("Keypoint", String.class, 120, false));
columns.add(new CustomizedColumn("Show", String.class, 50, false));
columns.add(new CustomizedColumn("Save", String.class, 50, false));
columns.add(new CustomizedColumn("Del", String.class, 30, "\u232B", "Delete this image source"));
table = new CustomizedTable(columns, true);
table.getColumnModel().getColumn(5).setMaxWidth(50);
table.getColumnModel().getColumn(6).setMaxWidth(50);
table.getColumnModel().getColumn(7).setMaxWidth(30);
table.getColumnModel().getColumn(0).setMaxWidth(100);
table.getColumnModel().getColumn(2).setMaxWidth(100);
table.getColumnModel().getColumn(3).setMaxWidth(100);
table.addMouseListener(this);
bnStack = new JButton("\u2295 stack");
bnSeries = new JButton("\u2295 series");
bnMIP = new JButton("\u2295 mip");
bnOrtho = new JButton("\u2295 ortho");
bnPlanar = new JButton("\u2295 planar");
bnFigure = new JButton("\u2295 figure");
JToolBar pn = new JToolBar("Controls Image");
pn.setBorder(BorderFactory.createEmptyBorder());
pn.setLayout(new GridLayout(1, 6));
pn.setFloatable(false);
pn.add(bnStack);
pn.add(bnSeries);
pn.add(bnMIP);
pn.add(bnOrtho);
pn.add(bnPlanar);
pn.add(bnFigure);
JToolBar tool = new JToolBar("Path");
tool.setBorder(BorderFactory.createEmptyBorder());
tool.setLayout(new BorderLayout());
tool.setFloatable(false);
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEtchedBorder());
panel.setLayout(new BorderLayout());
panel.add(tool, BorderLayout.NORTH);
panel.add(pn, BorderLayout.SOUTH);
panel.add(table.getMinimumPane(100, 100), BorderLayout.CENTER);
bnStack.addActionListener(this);
bnSeries.addActionListener(this);
bnMIP.addActionListener(this);
bnOrtho.addActionListener(this);
bnPlanar.addActionListener(this);
bnFigure.addActionListener(this);
getAction1Button().addActionListener(this);
Config.registerTable(getName(), "output", table);
return panel;
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
View view = null;
if (e.getSource() == bnStack)
view = View.STACK;
else if (e.getSource() == bnSeries)
view = View.SERIES;
else if (e.getSource() == bnMIP)
view = View.MIP;
else if (e.getSource() == bnOrtho)
view = View.ORTHO;
else if (e.getSource() == bnPlanar)
view = View.PLANAR;
else if (e.getSource() == bnFigure)
view = View.FIGURE;
if (view != null) {
OutputDialog dlg = new OutputDialog(view);
Lab.setVisible(dlg, true);
if (dlg.wasCancel())
return;
+
Output out = dlg.getOut();
- if (out == null)
- System.out.println("Out is null");
- else
+ if (out != null)
table.insert(out.getAsString());
+
+ //Lab.setVisible(new OutputPanel(view), "panel", 30, 30);
update();
}
if (e.getSource() == getAction1Button()) {
table.removeRows();
}
}
@Override
public void mouseClicked(MouseEvent e) {
int row = table.getSelectedRow();
if (table.getSelectedColumn() == 7) {
table.removeRow(row);
if (table.getRowCount() > 0)
table.setRowSelectionInterval(0, 0);
}
update();
Command.command();
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void close() {
bnStack.removeActionListener(this);
bnSeries.removeActionListener(this);
bnMIP.removeActionListener(this);
bnOrtho.removeActionListener(this);
bnPlanar.removeActionListener(this);
bnFigure.removeActionListener(this);
getAction1Button().removeActionListener(this);
getAction2Button().removeActionListener(this);
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/modules/PSFModule.java b/DeconvolutionLab2/src/deconvolutionlab/modules/PSFModule.java
index ec01136..df38533 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/modules/PSFModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/modules/PSFModule.java
@@ -1,340 +1,342 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.modules;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import deconvolution.Command;
import deconvolution.Deconvolution;
import deconvolution.DeconvolutionDialog;
import deconvolution.modules.PSFDModule;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
import deconvolutionlab.Imaging;
import deconvolutionlab.Lab;
import deconvolutionlab.dialog.PatternDialog;
import deconvolutionlab.dialog.SyntheticDialog;
import deconvolutionlab.monitor.Monitors;
import lab.component.CustomizedColumn;
import lab.component.CustomizedTable;
import lab.tools.Files;
import signal.RealSignal;
import signal.factory.SignalFactory;
public class PSFModule extends AbstractModule implements ActionListener, MouseListener {
private CustomizedTable table;
private JButton bnFile;
private JButton bnDirectory;
private JButton bnSynthetic;
private JButton bnPlatform;
public PSFModule(boolean expanded) {
super("PSF", "-psf", "", "Check", expanded);
}
@Override
public String getCommand() {
int row = table.getSelectedRow();
if (row < 0)
return "";
return "-psf " + table.getCell(row, 1) + " " + table.getCell(row, 2);
}
@Override
public JPanel buildExpandedPanel() {
ArrayList<CustomizedColumn> columns = new ArrayList<CustomizedColumn>();
columns.add(new CustomizedColumn("Name", String.class, 100, false));
columns.add(new CustomizedColumn("Source", String.class, 100, false));
columns.add(new CustomizedColumn("Command", String.class, Constants.widthGUI - 200, true));
columns.add(new CustomizedColumn("", String.class, 30, "\u232B", "Delete this PSF source"));
table = new CustomizedTable(columns, true);
table.getColumnModel().getColumn(3).setMaxWidth(30);
table.getColumnModel().getColumn(3).setMinWidth(30);
table.addMouseListener(this);
bnFile = new JButton("\u2295 file");
bnDirectory = new JButton("\u2295 directory");
bnSynthetic = new JButton("\u2295 synthetic");
bnPlatform = new JButton("\u2295 platform");
JToolBar pn = new JToolBar("Controls PSF");
pn.setBorder(BorderFactory.createEmptyBorder());
pn.setLayout(new GridLayout(1, 5));
pn.setFloatable(false);
pn.add(bnFile);
pn.add(bnDirectory);
pn.add(bnSynthetic);
- pn.add(bnPlatform);
+ if (Lab.getPlatform() == Imaging.Platform.IMAGEJ)
+ pn.add(bnPlatform);
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEtchedBorder());
panel.setLayout(new BorderLayout());
panel.add(pn, BorderLayout.SOUTH);
panel.add(table.getMinimumPane(100, 100), BorderLayout.CENTER);
table.setDropTarget(new LocalDropTarget());
getCollapsedPanel().setDropTarget(new LocalDropTarget());
bnFile.addActionListener(this);
bnDirectory.addActionListener(this);
bnSynthetic.addActionListener(this);
if (Lab.getPlatform() == Imaging.Platform.IMAGEJ)
bnPlatform.addActionListener(this);
getAction1Button().addActionListener(this);
getAction2Button().addActionListener(this);
getAction2Button().setToolTipText("Click to have a preview, Shift-click or Ctrl-click to show the complete stack");
getAction1Button().setToolTipText("Select the active window");
Config.registerTable(getName(), "psf", table);
return panel;
}
public void update() {
int row = table.getSelectedRow();
if (row >= 0) {
setCommand(getCommand());
setSynopsis(table.getCell(row, 0));
Command.command();
}
else {
setSynopsis("");
setCommand("Drag your image file, here");
}
getAction2Button().setEnabled(table.getRowCount() > 0);
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (e.getSource() == bnFile)
file(Command.getPath());
else if (e.getSource() == bnDirectory)
dir(Command.getPath());
else if (e.getSource() == bnSynthetic)
synthetic(false);
else if (e.getSource() == bnPlatform)
platform();
else if (e.getSource() == getAction1Button())
platform();
else if (e.getSource() == getAction2Button()) {
boolean s = (e.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_MASK;
boolean c = (e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK;
display(s | c);
}
update();
}
public void platform() {
String name = Lab.getActiveImage();
if (name != "")
table.insert(new String[] {name, "platform", name, "\u232B" });
}
private void file(String path) {
File file = Files.browseFile(path);
if (file == null)
return;
table.insert(new String[] { file.getName(), "file", file.getAbsolutePath(), "\u232B" });
}
private void dir(String path) {
File file = Files.browseDirectory(path);
if (file == null)
return;
PatternDialog dlg = new PatternDialog(file);
Lab.setVisible(dlg, true);
if (dlg.wasCancel())
return;
table.insert(new String[] { dlg.getDirName(), "directory", dlg.getCommand(), "\u232B" });
}
private void synthetic(boolean edit) {
ArrayList<SignalFactory> list = SignalFactory.getPSF();
SyntheticDialog dlg = new SyntheticDialog(list);
if (edit) {
int row = table.getSelectedRow();
if (row >= 0) {
dlg.setParameters(table.getCell(row, 0), table.getCell(row, 1));
}
}
Lab.setVisible(dlg, true);
if (dlg.wasCancel())
return;
if (edit) {
int row = table.getSelectedRow();
if (row <= 0)
table.removeRow(row);
}
table.insert(new String[] { dlg.getShapeName(), "synthetic", dlg.getCommand(), "" });
}
private void edit() {
int row = table.getSelectedRow();
if (row < 0)
return;
String name = table.getCell(row, 0).trim();
for(SignalFactory factory : SignalFactory.getAll()) {
if (name.equals(factory.getName().trim()))
synthetic(true);
return;
}
String filename = table.getCell(row, 1).trim();
File file = new File(filename);
if (!file.exists())
return;
if (file.isFile())
file(table.getCell(row, 21));
else
dir(table.getCell(row, 1));
}
private void display(boolean stack) {
int row = table.getSelectedRow();
if (row < 0)
return;
Deconvolution deconvolution = new Deconvolution("Check PSF", Command.command());
+ deconvolution.openPSF();
if (stack) {
- RealSignal x = deconvolution.openPSF();
+ RealSignal x = deconvolution.getPSF();
if (x != null)
Lab.show(Monitors.createDefaultMonitor(), x, table.getCell(row, 0));
}
else {
DeconvolutionDialog d = new DeconvolutionDialog(DeconvolutionDialog.Module.PSF, deconvolution, null, null);
Lab.setVisible(d, false);
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() == table) {
int row = table.getSelectedRow();
if (row < 0)
return;
if (table.getSelectedColumn() == 3) {
table.removeRow(row);
if (table.getRowCount() > 0)
table.setRowSelectionInterval(0, 0);
}
update();
if (e.getClickCount() == 2) {
edit();
}
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void close() {
bnFile.removeActionListener(this);
bnDirectory.removeActionListener(this);
bnSynthetic.removeActionListener(this);
bnPlatform.removeActionListener(this);
}
public class LocalDropTarget extends DropTarget {
@Override
public void drop(DropTargetDropEvent e) {
e.acceptDrop(DnDConstants.ACTION_COPY);
e.getTransferable().getTransferDataFlavors();
Transferable transferable = e.getTransferable();
DataFlavor[] flavors = transferable.getTransferDataFlavors();
for (DataFlavor flavor : flavors) {
if (flavor.isFlavorJavaFileListType()) {
try {
List<File> files = (List<File>) transferable.getTransferData(flavor);
for (File file : files) {
if (file.isDirectory()) {
table.insert(new String[] { file.getName(), "directory", file.getAbsolutePath(), "" });
table.setRowSelectionInterval(0, 0);
update();
}
if (file.isFile()) {
table.insert(new String[] { file.getName(), "file", file.getAbsolutePath(), "" });
update();
}
}
}
catch (UnsupportedFlavorException ex) {
ex.printStackTrace();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
e.dropComplete(true);
super.drop(e);
}
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/modules/RunningModule.java b/DeconvolutionLab2/src/deconvolutionlab/modules/RunningModule.java
index 4cc44c0..ead41ca 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/modules/RunningModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/modules/RunningModule.java
@@ -1,264 +1,264 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.modules;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import deconvolution.Command;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
import lab.component.CustomizedColumn;
import lab.component.CustomizedTable;
import lab.tools.Files;
public class RunningModule extends AbstractModule implements MouseListener {
private CustomizedTable table;
private String[] valuesMonitor;
private String[] valuesVerbose;
private String[] valuesSystem;
private String[] valuesMultithreading;
private String[] valuesDisplay;
private String[] valuesStats;
private String[] valuesPath;
private JTextField txtMonitor;
private JTextField txtVerbose;
private JTextField txtSystem;
private JTextField txtMultithreading;
private JTextField txtDisplay;
private JTextField txtStats;
private JTextField txtPath;
private JTextField txtDirectory;
public RunningModule(boolean expanded) {
super("Running", "", "Default", "Browse", expanded);
}
@Override
public String getCommand() {
String cmd = "";
String p = txtPath.getText();
if (!p.equalsIgnoreCase(valuesPath[0]))
cmd += " -path " + txtDirectory.getText().toLowerCase();
if (!txtMonitor.getText().equalsIgnoreCase(valuesMonitor[0]))
cmd += " -monitor " + txtMonitor.getText().toLowerCase();
if (!txtVerbose.getText().equalsIgnoreCase(valuesVerbose[0]))
cmd += " -verbose " + txtVerbose.getText().toLowerCase();
if (!txtSystem.getText().equalsIgnoreCase(valuesSystem[0]))
cmd += " -system " + txtSystem.getText().toLowerCase();
if (!txtDisplay.getText().equalsIgnoreCase(valuesDisplay[0]))
cmd += " -display " + txtDisplay.getText().toLowerCase();
if (!txtStats.getText().equalsIgnoreCase(valuesStats[0]))
cmd += " -stats " + txtStats.getText().toLowerCase();
if (!txtMultithreading.getText().equalsIgnoreCase(valuesMultithreading[0]))
cmd += " -multithreading " + txtMultithreading.getText().toLowerCase();
return cmd;
}
@Override
public JPanel buildExpandedPanel() {
valuesPath = new String[] { "current", "specify" };
valuesMonitor = new String[] { "console table", "console", "table", "no" };
valuesStats = new String[] { "no", "show", "save", "show save" };
- valuesVerbose = new String[] { "log", "quiet", "nute", "prolix" };
+ valuesVerbose = new String[] { "log", "quiet", "mute", "prolix" };
valuesSystem = new String[] { "yes", "no" };
valuesMultithreading = new String[] { "yes", "no" };
valuesDisplay = new String[] { "yes", "no" };
txtDirectory = new JTextField(System.getProperty("user.dir"));
txtPath = new JTextField(valuesPath[0]);
txtMonitor = new JTextField(valuesMonitor[0]);
txtStats = new JTextField(valuesStats[0]);
txtVerbose = new JTextField(valuesVerbose[0]);
txtSystem = new JTextField(valuesSystem[0]);
txtMultithreading = new JTextField(valuesMultithreading[0]);
txtDisplay = new JTextField(valuesDisplay[0]);
ArrayList<CustomizedColumn> columns = new ArrayList<CustomizedColumn>();
columns.add(new CustomizedColumn("Settings", String.class, 150, false));
columns.add(new CustomizedColumn("State", String.class, 100, false));
columns.add(new CustomizedColumn("Information", String.class, Constants.widthGUI - 250, true));
columns.add(new CustomizedColumn("", String.class, 100, "Change", "Change this setting"));
table = new CustomizedTable(columns, false);
table.getColumnModel().getColumn(3).setMaxWidth(140);
table.getColumnModel().getColumn(3).setMaxWidth(140);
JPanel panel = new JPanel(new BorderLayout());
panel.add(table.getPane(100, 100), BorderLayout.CENTER);
Config.register(getName(), "Path", txtPath, valuesPath[0]);
Config.register(getName(), "Monitor", txtMonitor, valuesMonitor[0]);
Config.register(getName(), "Stats", txtStats, valuesStats[0]);
Config.register(getName(), "Verbose", txtVerbose, valuesVerbose[0]);
Config.register(getName(), "System", txtSystem, valuesSystem[0]);
Config.register(getName(), "Multithreading", txtMultithreading, valuesMultithreading[0]);
Config.register(getName(), "Display", txtDisplay, valuesDisplay[0]);
Config.register(getName(), "Directory", txtDirectory, System.getProperty("user.dir"));
getAction1Button().addActionListener(this);
getAction2Button().addActionListener(this);
table.addMouseListener(this);
return panel;
}
public void init() {
table.append(new String[] { "Path", txtPath.getText(), txtDirectory.getText(), "Change" });
table.append(new String[] { "Monitor", txtMonitor.getText(), "Monitor in table and in console", "Change" });
table.append(new String[] { "Stats", txtStats.getText(), "Compute stats (slow down)", "Change" });
table.append(new String[] { "Verbose", txtVerbose.getText(), "Level of messages in monitor", "Change" });
table.append(new String[] { "System", txtSystem.getText(), "Open the system window", "Change" });
table.append(new String[] { "Multithreading", txtMultithreading.getText(), "Activation of the multithreading", "Change" });
table.append(new String[] { "Display", txtDisplay.getText(), "Display result at the end", "Change" });
update();
}
public void update() {
setCommand(getCommand());
setSynopsis(txtDirectory.getText());
Command.command();
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (e.getSource() == getAction1Button()) {
for (int row = 0; row < table.getRowCount(); row++) {
if (table.getCell(row, 0).equalsIgnoreCase("path")) {
setDefault(row, valuesPath, txtPath);
txtDirectory.setText(System.getProperty("user.dir"));
table.setCell(0, 2, System.getProperty("user.dir"));
}
if (table.getCell(row, 0).equalsIgnoreCase("monitor"))
setDefault(row, valuesMonitor, txtMonitor);
if (table.getCell(row, 0).equalsIgnoreCase("stats"))
setDefault(row, valuesStats, txtStats);
if (table.getCell(row, 0).equalsIgnoreCase("verbose"))
setDefault(row, valuesVerbose, txtVerbose);
if (table.getCell(row, 0).equalsIgnoreCase("system"))
setDefault(row, valuesSystem, txtSystem);
if (table.getCell(row, 0).equalsIgnoreCase("multithreading"))
setDefault(row, valuesMultithreading, txtMultithreading);
if (table.getCell(row, 0).equalsIgnoreCase("display"))
setDefault(row, valuesDisplay, txtDisplay);
}
}
if (e.getSource() == getAction2Button()) {
File f = Files.browseDirectory(txtPath.getText());
if (f != null) {
txtDirectory.setText(f.getAbsolutePath());
txtPath.setText(valuesPath[1]);
table.setCell(0, 1, txtPath.getText());
table.setCell(0, 2, txtDirectory.getText());
}
}
update();
}
@Override
public void close() {
}
@Override
public void mouseClicked(MouseEvent e) {
int row = table.getSelectedRow();
if (table.getSelectedColumn() == 3) {
if (table.getCell(row, 0).equalsIgnoreCase("path")) {
toggle(row, valuesPath, txtPath);
txtDirectory.setText(System.getProperty("user.dir"));
table.setCell(0, 2, System.getProperty("user.dir"));
}
if (table.getCell(row, 0).equalsIgnoreCase("monitor"))
toggle(row, valuesMonitor, txtMonitor);
if (table.getCell(row, 0).equalsIgnoreCase("stats"))
toggle(row, valuesStats, txtStats);
if (table.getCell(row, 0).equalsIgnoreCase("verbose"))
toggle(row, valuesVerbose, txtVerbose);
if (table.getCell(row, 0).equalsIgnoreCase("system"))
toggle(row, valuesSystem, txtSystem);
if (table.getCell(row, 0).equalsIgnoreCase("multithreading"))
toggle(row, valuesMultithreading, txtMultithreading);
if (table.getCell(row, 0).equalsIgnoreCase("display"))
toggle(row, valuesDisplay, txtDisplay);
}
update();
Command.command();
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
private void toggle(int row, String values[], JTextField txt) {
for (int i = 0; i < values.length; i++) {
if (table.getCell(row, 1).equalsIgnoreCase(values[i])) {
int k = i == values.length - 1 ? 0 : i + 1;
table.setCell(row, 1, values[k]);
txt.setText(values[k]);
return;
}
}
setDefault(row, values, txt);
}
private void setDefault(int row, String values[], JTextField txt) {
table.setCell(row, 1, values[0]);
txt.setText(values[0]);
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/monitor/Monitors.java b/DeconvolutionLab2/src/deconvolutionlab/monitor/Monitors.java
index ee74b69..0db6c4c 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/monitor/Monitors.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/monitor/Monitors.java
@@ -1,96 +1,100 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.monitor;
import java.util.ArrayList;
public class Monitors extends ArrayList<AbstractMonitor> {
private double start;
private Verbose verbose;
private double progress;
public Monitors() {
super();
start = System.nanoTime();
verbose = Verbose.Log;
progress = 0;
}
public void setVerbose(Verbose v) {
verbose = v;
}
public Verbose getVerbose() {
return verbose;
}
public static Monitors createDefaultMonitor() {
Monitors monitors = new Monitors();
monitors.add(new ConsoleMonitor());
return monitors;
}
public static Monitors create(AbstractMonitor monitor) {
Monitors monitors = new Monitors();
monitors.add(new ConsoleMonitor());
monitors.add(monitor);
return monitors;
}
public void detail(String msg) {
if (verbose.ordinal() >= Verbose.Prolix.ordinal())
sendMessage(new Message(Verbose.Prolix, msg, System.nanoTime() - start, 0));
}
public void progress(String msg, double p) {
- if (verbose.ordinal() >= Verbose.Log.ordinal()) {
- progress = Math.max(0, Math.min(100, p));
- sendMessage(new Message(Verbose.Log, msg, System.nanoTime() - start, progress));
- }
+ progress = Math.max(0, Math.min(100, p));
+ sendProgress(new Message(Verbose.Prolix, msg, System.nanoTime() - start, progress));
}
public void log(String msg) {
if (verbose.ordinal() >= Verbose.Log.ordinal())
sendMessage(new Message(Verbose.Log, msg, System.nanoTime() - start, progress));
}
public void error(String msg) {
if (verbose.ordinal() >= Verbose.Quiet.ordinal())
sendMessage(new Message(Verbose.Quiet, msg, System.nanoTime() - start, 0));
}
private void sendMessage(Message message) {
for (AbstractMonitor monitor : this)
- monitor.add(message);
+ monitor.add(message);
+ }
+
+ private void sendProgress(Message message) {
+ for (AbstractMonitor monitor : this)
+ if (monitor instanceof StatusMonitor)
+ monitor.add(message);
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/monitor/StatusMonitor.java b/DeconvolutionLab2/src/deconvolutionlab/monitor/StatusMonitor.java
index 6fbfe1a..54b66be 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/monitor/StatusMonitor.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/monitor/StatusMonitor.java
@@ -1,86 +1,86 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.monitor;
import java.awt.FontMetrics;
import javax.swing.JProgressBar;
import deconvolutionlab.Constants;
public class StatusMonitor implements AbstractMonitor {
private JProgressBar progress;
public StatusMonitor(JProgressBar progress) {
super();
this.progress = progress;
progress.setMinimum(0);
progress.setMaximum(100);
progress.setStringPainted(true);
}
@Override
public void clear() {
progress.setValue(0);
progress.setString(Constants.copyright);
}
@Override
public void add(Message message) {
int w = progress.getWidth();
if (w <= 0)
return;
String m = message.formatProgress();
FontMetrics fm = progress.getFontMetrics(progress.getFont());
int tw = fm.stringWidth(m);
if (tw > w) {
String ellipsis = "...";
int ew = fm.stringWidth(ellipsis);
while (tw + ew > w) {
tw = fm.stringWidth(m);
m = m.substring(0, m.length() - 1);
}
m += "...";
}
- double p = message.getProgress();
+ double p = message.getProgress() % 100;
progress.setString(m);
progress.setValue((int) Math.round(p));
}
@Override
public String getName() {
return "status";
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/monitor/TableMonitor.java b/DeconvolutionLab2/src/deconvolutionlab/monitor/TableMonitor.java
index 15ca443..a3f3fdd 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/monitor/TableMonitor.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/monitor/TableMonitor.java
@@ -1,156 +1,150 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.monitor;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import lab.component.CustomizedColumn;
import lab.component.CustomizedTable;
public class TableMonitor implements AbstractMonitor, ActionListener {
private CustomizedTable table;
private JButton bnClear = new JButton("Clear");
private HashMap<Long, Color> colors = new HashMap<Long, Color>();
private JPanel panel;
private String name;
public TableMonitor(String name, int width, int height) {
+ this.name = name;
ArrayList<CustomizedColumn> columns = new ArrayList<CustomizedColumn>();
columns.add(new CustomizedColumn("#", Long.class, 60, false));
columns.add(new CustomizedColumn("Time", String.class, 100, false));
columns.add(new CustomizedColumn("Memory", String.class, 100, false));
columns.add(new CustomizedColumn("Message", String.class, Math.max(60, width - 3 * 60), false));
table = new CustomizedTable(columns, true);
table.getColumnModel().getColumn(0).setMinWidth(60);
table.getColumnModel().getColumn(0).setMaxWidth(60);
table.getColumnModel().getColumn(1).setMaxWidth(100);
table.getColumnModel().getColumn(1).setMinWidth(100);
table.getColumnModel().getColumn(2).setMaxWidth(100);
table.getColumnModel().getColumn(2).setMinWidth(100);
RowRenderer renderer = new RowRenderer();
for (int i = 0; i < 4; i++)
table.getColumnModel().getColumn(i).setCellRenderer(renderer);
JScrollPane scroll = new JScrollPane(table);
scroll.setPreferredSize(new Dimension(width, height));
JPanel main = new JPanel(new BorderLayout());
main.add(scroll, BorderLayout.CENTER);
bnClear.addActionListener(this);
panel = new JPanel(new BorderLayout());
panel.add(main);
panel.setBorder(BorderFactory.createEtchedBorder());
}
public JPanel getPanel() {
return panel;
}
- public void show() {
- JFrame frame = new JFrame(name);
- frame.getContentPane().add(panel);
- frame.pack();
- frame.setVisible(true);
- }
-
@Override
public void clear() {
DefaultTableModel model = (DefaultTableModel) table.getModel();
model.setRowCount(0);
}
@Override
public void add(Message message) {
String msg[] = message.formatArray();
int n = msg.length;
Object[] row = new Object[n + 1];
row[0] = message.getID();
for (int i = 0; i < n; i++)
row[i + 1] = msg[i];
table.append(row);
Verbose level = message.getLevel();
Color c = new Color(0, 0, 0);
if (level == Verbose.Prolix)
c = new Color(255, 0, 0);
else if (level == Verbose.Quiet)
c = new Color(200, 200, 0);
colors.put(new Long(message.getID()), c);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == bnClear) {
DefaultTableModel model = (DefaultTableModel) table.getModel();
model.setRowCount(0);
}
}
@Override
public String getName() {
return name;
}
class RowRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
DefaultTableModel model = (DefaultTableModel) table.getModel();
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (row >= 0) {
Long id = (Long) model.getValueAt(row, 0);
Color color = colors.get(id);
c.setForeground(color);
}
return c;
}
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/monitor/Verbose.java b/DeconvolutionLab2/src/deconvolutionlab/monitor/Verbose.java
index c0ae0a1..93ccc0d 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/monitor/Verbose.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/monitor/Verbose.java
@@ -1,18 +1,20 @@
package deconvolutionlab.monitor;
public enum Verbose {
- Mute, Quiet, Log, Prolix;
+ Mute, Quiet, Log, Prolix, Progress;
public static Verbose getByName(String name) {
String n = name.toLowerCase().trim();
if (n.equals("log"))
return Log;
if (n.equals("prolix"))
return Log;
if (n.equals("quiet"))
return Quiet;
if (n.equals("mute"))
return Mute;
+ if (n.equals("progress"))
+ return Progress;
return Log;
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/system/AbstractMeter.java b/DeconvolutionLab2/src/deconvolutionlab/system/AbstractMeter.java
index 86b447e..2aeeb79 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/system/AbstractMeter.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/system/AbstractMeter.java
@@ -1,121 +1,119 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.system;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.util.HashMap;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import deconvolutionlab.Constants;
import lab.component.CustomizedTable;
public abstract class AbstractMeter extends JButton {
protected Color colorBackground = new Color(10, 10, 10, 30);
protected Color colorText = new Color(10, 10, 10);
protected Color colorHot = new Color(10, 10, 160, 30);
protected CustomizedTable table;
protected HashMap<String, Integer> features = new HashMap<String, Integer>();
protected boolean initialized = false;
protected String prefix = "\u25BA ";
protected boolean collapse = true;
public AbstractMeter() {
super("");
int w = (int)(Constants.widthGUI/3.2);
int h = 25;
setBorder(BorderFactory.createEtchedBorder());
setPreferredSize(new Dimension(w, h));
setMinimumSize(new Dimension(w, h));
table = new CustomizedTable(new String[] {"Tool", "Feature", "Value"}, false);
}
public boolean isExpanded() {
return !collapse;
}
public void collapse() {
collapse = true;
prefix = " \u25BA ";
}
public void expand() {
collapse = false;
prefix = " \u25BC ";
}
public JPanel getPanel(int width, int height) {
JPanel panel = new JPanel(new BorderLayout());
panel.add(table.getPane(width, height), BorderLayout.CENTER);
setDetail();
initialized = true;
return panel;
}
public abstract String getName();
public abstract void setDetail();
public void update() {
if (table == null)
- return;
-
+ return;
setDetail();
- System.out.println("SetDetail" + getName());
}
protected void add(int i, String row[]) {
if (initialized) {
int r = features.get(row[0]);
if (i>=0 && i<table.getRowCount())
table.setCell(r, 1, row[1]);
}
else {
table.append(row);
features.put(row[0], i);
}
}
protected String split(String name) {
String func = name.substring(3);
return func.replaceAll("(\\p{Ll})(\\p{Lu})", "$1 $2");
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/system/SystemInfo.java b/DeconvolutionLab2/src/deconvolutionlab/system/SystemInfo.java
index 8595898..abfeb6f 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/system/SystemInfo.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/system/SystemInfo.java
@@ -1,285 +1,287 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.system;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
+import deconvolutionlab.Lab;
import fft.FFTPanel;
import lab.component.PanelImage;
import lab.tools.NumFormat;
import signal.SignalCollector;
public class SystemInfo extends JDialog implements WindowListener, ActionListener, MouseListener {
private JPanel cards;
private String[] rates = new String[] { "1 s.", "0.5 s.", "0.2 s.", "0.1 s.", "10 s.", "5 s.", "2 s." };
private JButton bnRate = new JButton("1 s.");
private JButton bnClear = new JButton("Clear");
private Timer timer = new Timer();
private TimerTask updater = new Updater();
private MemoryMeter memory;
private ProcessorMeter processor;
private SignalMeter signal;
private FFTMeter fft;
private JavaMeter java;
private FileMeter file;
private int width = Constants.widthGUI;
private static SystemInfo instance;
private int rate = 0;
private ArrayList<AbstractMeter> meters = new ArrayList<AbstractMeter>();
public static void activate() {
if (instance == null) {
instance = new SystemInfo();
- instance.setVisible(true);
+ Lab.setVisible(instance, false);
Config.registerFrame("System", "Frame", instance);
return;
}
if (!instance.isVisible())
- instance.setVisible(true);
+ Lab.setVisible(instance, false);
instance.toFront();
}
public static void close() {
if (instance == null)
return;
if (instance.isVisible())
instance.dispose();
}
private SystemInfo() {
super(new JFrame(), "DeconvolutionLab2 System");
memory = new MemoryMeter();
processor = new ProcessorMeter();
signal = new SignalMeter();
fft = new FFTMeter();
java = new JavaMeter();
file = new FileMeter();
meters.add(memory);
meters.add(processor);
meters.add(signal);
meters.add(fft);
meters.add(java);
meters.add(file);
// Panel meters on top
JPanel meters = new JPanel(new GridLayout(2, 3));
meters.add(file);
meters.add(memory);
meters.add(processor);
meters.add(java);
meters.add(signal);
meters.add(fft);
bnClear.setToolTipText("Clear all the entries");
bnRate.setToolTipText("Choose the rate of refreshing the information");
JPanel pan = new JPanel(new GridLayout(2, 1));
pan.add(bnRate);
pan.add(bnClear);
restart();
// Panel Compact
PanelImage pnCompact = new PanelImage("celegans.jpg");
pnCompact.setPreferredSize(new Dimension(width, 20));
// Panel cards, compact is visible
cards = new JPanel(new CardLayout());
cards.add("collapse", pnCompact);
cards.add(signal.getName(), SignalCollector.getPanel(width, 200));
cards.add(memory.getName(), memory.getPanel(width, 200));
cards.add(processor.getName(), processor.getPanel(width, 200));
cards.add(fft.getName(), new FFTPanel(width, 200));
cards.add(java.getName(), java.getPanel(width, 200));
cards.add(file.getName(), file.getPanel(width, 200));
cards.setVisible(false);
JPanel top = new JPanel(new BorderLayout());
top.add(meters, BorderLayout.CENTER);
top.add(pan, BorderLayout.EAST);
JPanel panel = new JPanel(new BorderLayout());
panel.add(top, BorderLayout.NORTH);
panel.add(cards, BorderLayout.CENTER);
getContentPane().add(panel);
bnClear.addActionListener(this);
signal.addMouseListener(this);
memory.addMouseListener(this);
processor.addMouseListener(this);
java.addMouseListener(this);
file.addMouseListener(this);
fft.addMouseListener(this);
bnRate.addActionListener(this);
setMinimumSize(new Dimension(width, 70));
pack();
bnClear.setEnabled(signal.isExpanded());
Rectangle rect = Config.getDialog("System.Frame");
if (rect.x > 0 && rect.y > 0)
setLocation(rect.x, rect.y);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == bnRate) {
rate++;
if (rate >= rates.length)
rate = 0;
bnRate.setText(rates[rate]);
restart();
}
- if (e.getSource() == bnClear)
+ if (e.getSource() == bnClear) {
SignalCollector.clear();
+ }
pack();
}
public void update() {
for(AbstractMeter meter : meters)
meter.update();
}
public void restart() {
long refreshTime = (long) (NumFormat.parseNumber(bnRate.getText(), 1) * 1000);
if (updater != null) {
updater.cancel();
updater = null;
}
updater = new Updater();
timer.schedule(updater, 0, refreshTime);
}
private class Updater extends TimerTask {
@Override
public void run() {
update();
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() instanceof AbstractMeter) {
AbstractMeter meter = (AbstractMeter) e.getSource();
if (meter.isExpanded()) {
meter.collapse();
cards.setVisible(false);
}
else for(AbstractMeter m : meters) {
if (m.isExpanded())
m.collapse();
meter.expand();
cards.setVisible(true);
}
((CardLayout) (cards.getLayout())).show(cards, meter.getName());
pack();
}
bnClear.setEnabled(signal.isExpanded());
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
timer.cancel();
timer = null;
dispose();
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/system/SystemInfo.java b/DeconvolutionLab2/src/deconvolutionlab/system/SystemPanel.java
similarity index 82%
copy from DeconvolutionLab2/src/deconvolutionlab/system/SystemInfo.java
copy to DeconvolutionLab2/src/deconvolutionlab/system/SystemPanel.java
index 8595898..bc1fbe4 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/system/SystemInfo.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/system/SystemPanel.java
@@ -1,285 +1,246 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolutionlab.system;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
+import deconvolutionlab.Lab;
import fft.FFTPanel;
import lab.component.PanelImage;
import lab.tools.NumFormat;
import signal.SignalCollector;
-public class SystemInfo extends JDialog implements WindowListener, ActionListener, MouseListener {
+public class SystemPanel extends JPanel implements ActionListener, MouseListener {
private JPanel cards;
private String[] rates = new String[] { "1 s.", "0.5 s.", "0.2 s.", "0.1 s.", "10 s.", "5 s.", "2 s." };
private JButton bnRate = new JButton("1 s.");
private JButton bnClear = new JButton("Clear");
private Timer timer = new Timer();
private TimerTask updater = new Updater();
private MemoryMeter memory;
private ProcessorMeter processor;
private SignalMeter signal;
private FFTMeter fft;
private JavaMeter java;
private FileMeter file;
private int width = Constants.widthGUI;
- private static SystemInfo instance;
+ private static SystemPanel instance;
private int rate = 0;
+ private static JFrame frame;
private ArrayList<AbstractMeter> meters = new ArrayList<AbstractMeter>();
- public static void activate() {
+ public static SystemPanel getInstance(JFrame parent) {
if (instance == null) {
- instance = new SystemInfo();
- instance.setVisible(true);
- Config.registerFrame("System", "Frame", instance);
- return;
+ instance = new SystemPanel();
}
- if (!instance.isVisible())
- instance.setVisible(true);
- instance.toFront();
+ frame = parent;
+
+ return instance;
}
- public static void close() {
- if (instance == null)
- return;
- if (instance.isVisible())
- instance.dispose();
- }
-
- private SystemInfo() {
- super(new JFrame(), "DeconvolutionLab2 System");
+ private SystemPanel() {
memory = new MemoryMeter();
processor = new ProcessorMeter();
signal = new SignalMeter();
fft = new FFTMeter();
java = new JavaMeter();
file = new FileMeter();
meters.add(memory);
meters.add(processor);
meters.add(signal);
meters.add(fft);
meters.add(java);
meters.add(file);
// Panel meters on top
JPanel meters = new JPanel(new GridLayout(2, 3));
meters.add(file);
meters.add(memory);
meters.add(processor);
meters.add(java);
meters.add(signal);
meters.add(fft);
bnClear.setToolTipText("Clear all the entries");
bnRate.setToolTipText("Choose the rate of refreshing the information");
JPanel pan = new JPanel(new GridLayout(2, 1));
pan.add(bnRate);
pan.add(bnClear);
restart();
// Panel Compact
PanelImage pnCompact = new PanelImage("celegans.jpg");
pnCompact.setPreferredSize(new Dimension(width, 20));
// Panel cards, compact is visible
cards = new JPanel(new CardLayout());
cards.add("collapse", pnCompact);
cards.add(signal.getName(), SignalCollector.getPanel(width, 200));
cards.add(memory.getName(), memory.getPanel(width, 200));
cards.add(processor.getName(), processor.getPanel(width, 200));
cards.add(fft.getName(), new FFTPanel(width, 200));
cards.add(java.getName(), java.getPanel(width, 200));
cards.add(file.getName(), file.getPanel(width, 200));
cards.setVisible(false);
JPanel top = new JPanel(new BorderLayout());
top.add(meters, BorderLayout.CENTER);
top.add(pan, BorderLayout.EAST);
- JPanel panel = new JPanel(new BorderLayout());
- panel.add(top, BorderLayout.NORTH);
- panel.add(cards, BorderLayout.CENTER);
+ setLayout(new BorderLayout());
+ add(top, BorderLayout.NORTH);
+ add(cards, BorderLayout.CENTER);
- getContentPane().add(panel);
+
bnClear.addActionListener(this);
signal.addMouseListener(this);
memory.addMouseListener(this);
processor.addMouseListener(this);
java.addMouseListener(this);
file.addMouseListener(this);
fft.addMouseListener(this);
bnRate.addActionListener(this);
setMinimumSize(new Dimension(width, 70));
- pack();
+
bnClear.setEnabled(signal.isExpanded());
Rectangle rect = Config.getDialog("System.Frame");
if (rect.x > 0 && rect.y > 0)
setLocation(rect.x, rect.y);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == bnRate) {
rate++;
if (rate >= rates.length)
rate = 0;
bnRate.setText(rates[rate]);
restart();
}
- if (e.getSource() == bnClear)
+ if (e.getSource() == bnClear) {
SignalCollector.clear();
-
- pack();
+ }
}
public void update() {
for(AbstractMeter meter : meters)
meter.update();
}
public void restart() {
long refreshTime = (long) (NumFormat.parseNumber(bnRate.getText(), 1) * 1000);
if (updater != null) {
updater.cancel();
updater = null;
}
updater = new Updater();
timer.schedule(updater, 0, refreshTime);
}
private class Updater extends TimerTask {
@Override
public void run() {
update();
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() instanceof AbstractMeter) {
AbstractMeter meter = (AbstractMeter) e.getSource();
if (meter.isExpanded()) {
meter.collapse();
cards.setVisible(false);
}
else for(AbstractMeter m : meters) {
if (m.isExpanded())
m.collapse();
meter.expand();
cards.setVisible(true);
}
((CardLayout) (cards.getLayout())).show(cards, meter.getName());
- pack();
+
}
bnClear.setEnabled(signal.isExpanded());
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
- @Override
- public void windowOpened(WindowEvent e) {
- }
-
- @Override
- public void windowClosing(WindowEvent e) {
- timer.cancel();
- timer = null;
- dispose();
- }
-
- @Override
- public void windowClosed(WindowEvent e) {
- }
- @Override
- public void windowIconified(WindowEvent e) {
- }
-
- @Override
- public void windowDeiconified(WindowEvent e) {
- }
-
- @Override
- public void windowActivated(WindowEvent e) {
- }
-
- @Override
- public void windowDeactivated(WindowEvent e) {
- }
}
diff --git a/DeconvolutionLab2/src/fft/fftw/FFTWLibrary.java b/DeconvolutionLab2/src/fft/fftw/FFTWLibrary.java
index 2810e2b..a8e2eb8 100644
--- a/DeconvolutionLab2/src/fft/fftw/FFTWLibrary.java
+++ b/DeconvolutionLab2/src/fft/fftw/FFTWLibrary.java
@@ -1,207 +1,206 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package fft.fftw;
import java.io.File;
import java.security.CodeSource;
import deconvolutionlab.monitor.Monitors;
import fft.AbstractFFT;
import fft.AbstractFFTLibrary;
import jfftw.complex.nd.Plan;
public class FFTWLibrary extends AbstractFFTLibrary {
private String location;
public FFTWLibrary(Monitors monitors) {
String path = "";
boolean found = false;
if (!found) {
try {
CodeSource code = FFTWLibrary.class.getProtectionDomain().getCodeSource();
File file = new File(code.getLocation().toURI().getPath());
path = file.getParentFile().getPath() + File.separator + "FFTW" + File.separator;
found = existsWidsom(monitors, path);
location = path;
}
catch (Exception ex) {
monitors.log("FFTW Widsom not found in : " + path);
location = "Not found in " + path;
found = false;
}
}
if (!found) {
try {
CodeSource code = FFTWLibrary.class.getProtectionDomain().getCodeSource();
File file = new File(code.getLocation().toURI().getPath());
path = file.getParentFile().getPath() + File.separator;
found = existsWidsom(monitors, path);
location = path;
}
catch (Exception ex) {
monitors.log("FFTW Widsom not found in : " + path);
location = "Not found in " + path;
found = false;
}
}
if (!found) {
try {
path = System.getProperty("user.home") + File.separator + "FFTW" + File.separator;
found = existsWidsom(monitors, path);
location = path;
}
catch (Exception ex) {
monitors.log("FFTW Widsom not found in : " + path);
location = "Not found in " + path;
found = false;
}
}
if (!found) {
try {
path = System.getProperty("user.home") + File.separator;
found = existsWidsom(monitors, path);
location = path;
}
catch (Exception ex) {
monitors.log("FFTW Widsom not found in : " + path);
location = "Not found in " + path;
found = false;
}
}
if (!found)
return;
loadLibraries(monitors, path);
try {
new Plan(new int[] { 20, 20, 20 }, Plan.FORWARD, Plan.ESTIMATE | Plan.IN_PLACE | Plan.USE_WISDOM);
ffts.add(new FFTW3D());
installed = true;
}
catch (UnsatisfiedLinkError ex) {
ex.printStackTrace();
installed = false;
}
}
@Override
public String getLocation() {
return location;
}
@Override
public boolean isMultithreadable() {
return true;
}
@Override
public String getCredit() {
return "http://www.fftw.org (FFTW Version 2)";
}
@Override
public String getLibraryName() {
return "FFTW2";
}
@Override
public String getLicence() {
return "<h1>FFTW Version 2, " + "<p>http://www.fftw.org" + "<p>FFTW is free software; you can redistribute it and/or modify it " + "under the terms of the GNU General Public License as published by "
+ "the Free Software Foundation; either version 2 of the License, or " + "(at your option) any later version.";
}
private static void loadLibraries(Monitors monitors, String path) {
try {
String osname = System.getProperty("os.name");
if (osname.startsWith("Linux")) {
String osarch = System.getProperty("os.arch");
if (osarch.contains("64")) {
System.load(path + "libFFTWJNI64.so");
monitors.log("Loading library FFTW for " + osarch + " " + osname + " " + path + "libFFTWJNI64.so");
}
else {
System.load(path + "libFFTWJNI32.so");
monitors.log("Loading library FFTW for " + osarch + " " + osname + " " + path + "libFFTWJNI32.so");
}
}
else if (osname.startsWith("Windows")) {
String osarch = System.getProperty("os.arch");
if (osarch.contains("64")) {
System.load(path + "FFTWJNIWin64.dll");
monitors.log("Loading library FFTW for " + osarch + " " + osname + " " + path + "FFTWJNIWin64.dll");
}
else {
System.load(path + "FFTWJNIWin32.dll");
monitors.log("Loading library FFTW for " + osarch + " " + osname + " " + path + "FFTWJNIWin32.dll");
}
}
else if (osname.startsWith("Mac")) {
System.load(path + "libFFTWJNIMac.jnilib");
monitors.log("Loading library FFTW for " + osname + " " + path + "libFFTWJNIMac.jnilib");
}
else {
monitors.log("FFTW is not provided for the architecture : " + osname);
}
}
catch (Exception ex) {
monitors.log("FFTW not found in : " + path);
- System.out.println(">>" + ex.toString());
}
}
private static boolean existsWidsom(Monitors monitors, String path) {
boolean found = false;
if (new File(path + "Wisdom").exists()) {
monitors.log("FFTW found in : " + path);
found = true;
}
else {
monitors.log("FFTW Widsom not found in : " + path);
found = false;
}
return found;
}
@Override
public AbstractFFT getDefaultFFT() {
return new FFTW3D();
}
}
diff --git a/DeconvolutionLab2/src/plugins/sage/deconvolutionlab/IcyImager.java b/DeconvolutionLab2/src/plugins/sage/deconvolutionlab/IcyImager.java
index e441366..5b90d23 100644
--- a/DeconvolutionLab2/src/plugins/sage/deconvolutionlab/IcyImager.java
+++ b/DeconvolutionLab2/src/plugins/sage/deconvolutionlab/IcyImager.java
@@ -1,216 +1,273 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package plugins.sage.deconvolutionlab;
import java.io.File;
import java.util.ArrayList;
import javax.swing.JDialog;
+import javax.swing.JFrame;
import deconvolutionlab.Imaging;
+import deconvolutionlab.Lab;
import icy.file.Saver;
-import icy.gui.frame.IcyFrame;
+import icy.gui.frame.IcyFrameEvent;
+import icy.gui.frame.IcyFrameListener;
import icy.image.IcyBufferedImage;
import icy.imagej.ImageJUtil;
import icy.main.Icy;
import icy.sequence.Sequence;
import icy.type.DataType;
import icy.type.collection.array.Array1DUtil;
import ij.ImagePlus;
import ij.io.Opener;
import signal.ComplexComponent;
import signal.ComplexSignal;
import signal.RealSignal;
-public class IcyImager extends Imaging {
+public class IcyImager extends Imaging implements IcyFrameListener {
@Override
public Platform getPlatform() {
return Imaging.Platform.ICY;
}
@Override
public void setVisible(JDialog dialog, boolean modal) {
+
+ /*
IcyFrame icf = new IcyFrame();
+ icf.addFrameListener(this);
icf.setTitle(dialog.getTitle());
- dialog.setModal(modal);
- icf.add(dialog.getContentPane());
+ //dialog.setModal(modal);
+ icf.add(dialog.getContentPane());
+ //icf.add(panel);
icf.toFront();
icf.addToDesktopPane();
- icf.setVisible(true);
+ icf.setVisible(true);
+ */
+ //Lab.setVisible(dialog, true);
+
+ dialog.pack();
+ dialog.setLocation(30, 30);
+ dialog.setVisible(true);
+
}
public static RealSignal create(Sequence seq) {
int nx = seq.getSizeX();
int ny = seq.getSizeY();
int nz = seq.getSizeZ();
RealSignal signal = new RealSignal("icy-" + seq.getName(), nx, ny, nz);
for (int k = 0; k < nz; k++) {
float pixels[] = new float[nx * ny];
Array1DUtil.arrayToFloatArray(seq.getDataXY(0, k, 0), pixels, seq.isSignedDataType());
signal.setXY(k, pixels);
}
return signal;
}
@Override
public RealSignal create() {
return build(Icy.getMainInterface().getActiveSequence());
}
@Override
public RealSignal create(String name) {
ArrayList<Sequence> sequences = Icy.getMainInterface().getSequences(name);
for(Sequence sequence : sequences)
if (sequence.getName().equals(name))
return build(sequence);
return null;
}
@Override
public RealSignal open(String filename) {
- //File file = new File(filename);
- //return build(Loader.loadSequence(file, 0, false));
Opener opener = new Opener();
ImagePlus imp = opener.openImage(filename);
Sequence seq = ImageJUtil.convertToIcySequence(imp, null);
return build(seq);
}
@Override
public void show(ComplexSignal signal, String title, ComplexComponent complex) {
Sequence sequence = new Sequence();
for (int k = 0; k < signal.nz; k++) {
float[] plane = null;
switch(complex) {
case REAL: plane = signal.getRealXY(k); break;
case IMAGINARY: plane = signal.getImagXY(k); break;
case MODULE: plane = signal.getModuleXY(k); break;
default: plane = signal.getModuleXY_dB(k);
}
IcyBufferedImage image = new IcyBufferedImage(signal.nx, signal.ny, 1, DataType.FLOAT);
Array1DUtil.floatArrayToSafeArray(plane, image.getDataXY(0), image.isSignedDataType());
image.dataChanged();
sequence.setImage(0, k, image);
}
sequence.setName(title);
Icy.getMainInterface().addSequence(sequence);
}
@Override
public void save(RealSignal signal, String filename, Imaging.Type type) {
Sequence sequence = build(signal, type);
File file = new File(filename);
Saver.save(sequence, file, false, true);
}
private RealSignal build(Sequence seq) {
int nx = seq.getSizeX();
int ny = seq.getSizeY();
int nz = seq.getSizeZ();
RealSignal signal = new RealSignal("icy-" + seq.getName(), nx, ny, nz);
for (int k = 0; k < nz; k++) {
float pixels[] = new float[nx * ny];
Array1DUtil.arrayToFloatArray(seq.getDataXY(0, k, 0), pixels, seq.isSignedDataType());
signal.setXY(k, pixels);
}
return signal;
}
private Sequence build(RealSignal signal, Imaging.Type type) {
int nx = signal.nx;
int ny = signal.ny;
int nz = signal.nz;
Sequence sequence = new Sequence();
for (int z = 0; z < nz; z++) {
if (type == Imaging.Type.SHORT) {
short[] plane = Array1DUtil.arrayToShortArray(signal.data[z], false);
IcyBufferedImage image = new IcyBufferedImage(nx, ny, 1, DataType.USHORT);
Array1DUtil.shortArrayToArray(plane, image.getDataXY(0), image.isSignedDataType());
image.dataChanged();
sequence.setImage(0, z, image);
}
else if (type == Imaging.Type.BYTE) {
byte[] plane = Array1DUtil.arrayToByteArray(signal.data[z]);
IcyBufferedImage image = new IcyBufferedImage(nx, ny, 1, DataType.UBYTE);
Array1DUtil.byteArrayToArray(plane, image.getDataXY(0), image.isSignedDataType());
image.dataChanged();
sequence.setImage(0, z, image);
}
else {
IcyBufferedImage image = new IcyBufferedImage(nx, ny, 1, DataType.FLOAT);
Array1DUtil.floatArrayToSafeArray(signal.data[z], image.getDataXY(0), image.isSignedDataType());
image.dataChanged();
sequence.setImage(0, z, image);
}
}
return sequence;
}
@Override
public String getName() {
return "Icy";
}
@Override
public ContainerImage createContainer(String title) {
// TODO Auto-generated method stub
return null;
}
@Override
public void append(ContainerImage container, RealSignal signal, String title, Type type) {
// TODO Auto-generated method stub
}
@Override
public void show(RealSignal signal, String title, Type type, int z) {
Sequence sequence = build(signal, type);
sequence.setName(title);
Icy.getMainInterface().addSequence(sequence);
}
@Override
public String getSelectedImage() {
return null;
}
@Override
public boolean isSelectable() {
return false;
}
+ @Override
+ public void icyFrameOpened(IcyFrameEvent e) {
+ System.out.println("" + e);
+ }
+
+ @Override
+ public void icyFrameClosing(IcyFrameEvent e) {
+ System.out.println("" + e);
+ }
+
+ @Override
+ public void icyFrameClosed(IcyFrameEvent e) {
+ System.out.println("" + e);
+ }
+
+ @Override
+ public void icyFrameIconified(IcyFrameEvent e) {
+ System.out.println("" + e);
+ }
+
+ @Override
+ public void icyFrameDeiconified(IcyFrameEvent e) {
+ System.out.println("" + e);
+ }
+
+ @Override
+ public void icyFrameActivated(IcyFrameEvent e) {
+ System.out.println("" + e);
+ }
+
+ @Override
+ public void icyFrameDeactivated(IcyFrameEvent e) {
+ System.out.println("" + e);
+ }
+
+ @Override
+ public void icyFrameInternalized(IcyFrameEvent e) {
+ System.out.println("" + e);
+ }
+
+ @Override
+ public void icyFrameExternalized(IcyFrameEvent e) {
+ System.out.println("" + e);
+ }
+
}
diff --git a/DeconvolutionLab2/src/signal/ComplexSignal.java b/DeconvolutionLab2/src/signal/ComplexSignal.java
index b796774..361b9bf 100644
--- a/DeconvolutionLab2/src/signal/ComplexSignal.java
+++ b/DeconvolutionLab2/src/signal/ComplexSignal.java
@@ -1,633 +1,626 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package signal;
public class ComplexSignal extends Signal implements SignalListener {
public ComplexSignal(String name, int nx, int ny, int nz) {
super(name, nx, ny, nz);
int step = Math.max(1, nz/SignalCollector.NOTIFICATION_RATE);
this.data = new float[nz][];
notify(name, 0);
for(int k=0; k<nz; k++) {
data[k] = new float[nx * ny * 2];
if (k % step == 0)
notify(name, k*100.0/nz);
}
notify(name, 100);
- SignalCollector.alloc(name, nx, ny, ny, true);
+ SignalCollector.alloc(this);//name, nx, ny, ny, true);
}
@Override
public void notify(String name, double progress) {
SignalCollector.setProgress(progress);
}
-
- @Override
- public void finalize() {
- data = null;
- System.gc();
- SignalCollector.free(name, nx, ny, ny, true);
- }
public void set(RealSignal real) {
for(int k=0; k<nz; k++) {
float[] s = data[k];
float[] r = real.getXY(k);
for(int i=0; i<nx*ny; i++) {
s[2*i] = r[i];
}
}
}
public void set(RealSignal real, RealSignal imag) {
for(int k=0; k<nz; k++) {
float[] s = data[k];
float[] re = real.getXY(k);
float[] im = imag.getXY(k);
for(int i=0; i<nx*ny; i++) {
s[2*i] = re[i];
s[2*i+1] = im[i];
}
}
}
public void divide(ComplexSignal denominator) {
float a1, a2, b1, b2, mag;
float epsilon2 = (float)(Operations.epsilon*Operations.epsilon);
int nxy = nx * ny * 2;
for(int k=0; k<nz; k++)
for(int i=0; i< nxy; i+=2) {
a1 = data[k][i];
b1 = data[k][i+1];
a2 = denominator.data[k][i];
b2 = denominator.data[k][i+1];
mag = a2*a2 + b2*b2;
if (mag >= epsilon2) {
data[k][i] = (a1*a2 + b1*b2) / mag;
data[k][i+1] = (b1*a2 - a1*b2) / mag;
}
else {
data[k][i] = (a1*a2 + b1*b2) / epsilon2;
data[k][i+1] = (b1*a2 - a1*b2) / epsilon2;
}
}
}
public double[][][] getReal3DArrayAsDouble() {
double[][][] ar = new double[nx][ny][nz];
for(int k=0; k<nz; k++) {
float[] s = data[k];
for(int i=0; i<nx; i++)
for(int j=0; j<ny; j++) {
ar[i][j][k] = s[2*(i+j*nx)];
}
}
return ar;
}
public double[][][] getImag3DArrayAsDouble() {
double[][][] ar = new double[nx][ny][nz];
for(int k=0; k<nz; k++) {
float[] s = data[k];
for(int i=0; i<nx; i++)
for(int j=0; j<ny; j++) {
ar[i][j][k] = s[2*(i+j*nx)+1];
}
}
return ar;
}
public void set3DArrayAsDouble(double[][][] real, double imag[][][]) {
for(int k=0; k<nz; k++) {
float[] s = data[k];
for(int i=0; i<nx; i++)
for(int j=0; j<ny; j++) {
s[2*(i+j*nx)] = (float)real[i][j][k];
s[2*(i+j*nx)+1] = (float)imag[i][j][k];
}
}
}
public ComplexSignal times(float factor) {
int nxy = nx * ny * 2;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
data[k][i] *= factor;
return this;
}
public ComplexSignal plus(float real, float imag) {
int nxy = nx * ny * 2;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i+=2) {
data[k][i] += real;
data[k][i+1] += imag;
}
return this;
}
public ComplexSignal times(ComplexSignal factor) {
float a1, a2, b1, b2;
int nxy = nx * ny * 2;
for(int k=0; k<nz; k++)
for(int i=0; i< nxy; i+=2) {
a1 = data[k][i];
b1 = data[k][i+1];
a2 = factor.data[k][i];
b2 = factor.data[k][i+1];
data[k][i] = a1*a2 - b1*b2;
data[k][i+1] = a1*b2 + a2*b1;
}
return this;
}
// this <- Ht * this
public void timesConjugate(ComplexSignal H) {
float a1, a2, b1, b2;
int nxy = nx * ny * 2;
for(int k=0; k<nz; k++)
for(int i=0; i< nxy; i+=2) {
a1 = data[k][i];
b1 = data[k][i+1];
a2 = H.data[k][i];
b2 = -H.data[k][i+1];
data[k][i] = a1*a2 - b1*b2;
data[k][i+1] = a1*b2 + a2*b1;
}
}
public void plus(ComplexSignal term) {
int nxy = nx * ny * 2;
for(int k=0; k<nz; k++)
for(int i=0; i< nxy; i+=2) {
data[k][i] += term.data[k][i];
data[k][i+1] += term.data[k][i+1];
}
}
public void minus(ComplexSignal term) {
int nxy = nx * ny * 2;
for(int k=0; k<nz; k++)
for(int i=0; i< nxy; i+=2) {
data[k][i] -= term.data[k][i];
data[k][i+1] -= term.data[k][i+1];
}
}
public void conjugate() {
int nxy = nx * ny * 2;
for(int k=0; k<nz; k++)
for(int i=0; i< nxy; i+=2)
data[k][i+1] = -data[k][i+1];
}
public float[] getValue(int i, int j, int k) {
return new float[] {data[k][2*(j*nx+i)], data[k][2*(j*nx+i)+1]};
}
public void setValue(int i, int j, int k, float[] value) {
data[k][2*(j*nx+i)] = value[0];
data[k][2*(j*nx+i)+1] = value[1];
}
public float[] getInterleaveXYZ() {
int nxy = nx*ny*2;
float[] interleave = new float[nz*nxy];
for (int k = 0; k < nz; k++)
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = 2*(k*nx*ny + j*nx + i);
interleave[index] = data[k][(i+j*nx)*2];
interleave[index + 1] = data[k][(i+j*nx)*2+1];
}
return interleave;
}
public void setInterleaveXYZ(float[] interleave) {
int nxy = nx * ny * 2;
this.data = new float[nz][nxy];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++)
for (int k = 0; k < nz; k++) {
int index = 2*(k*nx*ny + j*nx + i);
data[k][(i+j*nx)*2] = interleave[index];
data[k][(i+j*nx)*2 + 1] = interleave[index+1];
}
}
public RealSignal getRealSignal() {
String n = "real(" + name + ")";
RealSignal real = new RealSignal(n, nx, ny, nz);
int nxy = nx * ny;
for (int k = 0; k < nz; k++) {
float[] r = real.getXY(k);
for (int i = 0; i < nxy; i++)
r[i] = data[k][2*i];
}
return real;
}
public RealSignal getImagSignal() {
String n = "imag(" + name + ")";
RealSignal real = new RealSignal(n, nx, ny, nz);
int nxy = nx * ny;
for (int k = 0; k < nz; k++) {
float[] r = real.getXY(k);
for (int i = 0; i < nxy; i++)
r[i] = data[k][2*i+1];
}
return real;
}
public RealSignal getModule() {
String n = "mod(" + name + ")";
RealSignal module = new RealSignal(n, nx, ny, nz);
for (int k = 0; k < nz; k++)
module.setXY(k, getModuleXY(k));
return module;
}
public float[] getModuleXY(int k) {
float[] m = new float[nx*ny];
for (int i = 0; i < nx * ny; i++)
m[i] = data[k][2*i]*data[k][2*i] + data[k][2*i+1]*data[k][2*i+1];
return m;
}
public float[] getModuleXY_dB(int k) {
float[] m = new float[nx*ny];
for (int i = 0; i < nx * ny; i++)
m[i] = (float)(10f*Math.log10(data[k][2*i]*data[k][2*i] + data[k][2*i+1]*data[k][2*i+1]));
return m;
}
public ComplexSignal duplicate() {
ComplexSignal out = new ComplexSignal("copy(" + name + ")", nx, ny, nz);
int nxy = nx * ny * 2;
for (int k = 0; k < nz; k++)
System.arraycopy(data[k], 0, out.data[k], 0, nxy);
return out;
}
public ComplexSignal replicate() {
return new ComplexSignal(">" + name, nx, ny, nz);
}
public float getEnergy() {
int nxy = nx * ny;
float energy = 0.f;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
energy += modulus(k, i);
return energy;
}
private float modulus(int k, int index) {
int i = index * 2;
return (float)Math.sqrt(data[k][i] * data[k][i] + data[k][i + 1] * data[k][i + 1]);
}
public float[] getRealXYZ() {
float[] real = new float[nx*ny*nz];
int nxy = nx * ny;
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = i + nx*j;
for (int k = 0; k < nz; k++)
real[k*nxy + index] = data[k][2*index];
}
return real;
}
public float[] getImagXYZ() {
float[] imag = new float[nx*ny*nz];
int nxy = nx * ny;
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = i + nx*j;
for (int k = 0; k < nz; k++)
imag[k*nxy + index] = data[k][2*index+1];
}
return imag;
}
public void setXYZ(float[] real, float[] imag) {
int nxy = nx * ny;
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = i + nx*j;
for (int k = 0; k < nz; k++) {
data[k][2*index] = real[k*nxy + index];
data[k][2*index+1] = imag[k*nxy + index];
}
}
}
public float[] getInterleaveZ(int i, int j) {
float line[] = new float[nz*2];
int index = 2 * (i + j * nx);
for (int k = 0; k < nz; k++) {
line[2*k] = data[k][index];
line[2*k+1] = data[k][index+1];
}
return line;
}
public float[] getRealZ(int i, int j) {
float line[] = new float[nz];
int index = 2 * (i + j * nx);
for (int k = 0; k < nz; k++)
line[k] = data[k][index];
return line;
}
public float[] getImagZ(int i, int j) {
float line[] = new float[nz];
int index = 2 * (i + j * nx) + 1;
for (int k = 0; k < nz; k++)
line[k] = data[k][index];
return line;
}
public float[] getRealY(int i, int k) {
float line[] = new float[ny];
for (int j = 0; j < ny; j++)
line[j] = data[k][2 * (i + j * nx)];
return line;
}
public float[] getImagY(int i, int k) {
float line[] = new float[ny];
for (int j = 0; j < ny; j++)
line[j] = data[k][2 * (i + j * nx) + 1];
return line;
}
public float[] getRealX(int j, int k) {
float line[] = new float[nx];
for (int i = 0; i < nx; i++)
line[i] = data[k][2 * (i + j * nx)];
return line;
}
public float[] getImagX(int j, int k) {
float line[] = new float[nx];
for (int i = 0; i < nx; i++)
line[i] = data[k][2 * (i + j * nx) + 1];
return line;
}
public float[] getInterleaveXY(int k) {
float slice[] = new float[nx*ny*2];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = 2*(i + j * nx);
slice[index] = data[k][index];
slice[index + 1] = data[k][index + 1];
}
return slice;
}
public float[] getInterleaveYX(int k) {
float slice[] = new float[nx*ny*2];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = 2*(j + i * ny);
slice[index] = data[k][index];
slice[index + 1] = data[k][index + 1];
}
return slice;
}
public float[] getRealXY(int k) {
float slice[] = new float[nx*ny];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = i + j * nx;
slice[index] = data[k][2*index];
}
return slice;
}
public float[] getImagXY(int k) {
float slice[] = new float[nx*ny];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++)
slice[i + j * nx] = data[k][2 * (i + j * nx)+1];
return slice;
}
public void setInterleaveZ(int i, int j, float line[]) {
int index = 2 * (i + j * nx);
for (int k = 0; k < nz; k++) {
data[k][index] = line[2*k];
data[k][index+1] = line[2*k+1];
}
}
public void setRealZ(int i, int j, float line[]) {
int index = 2 * (i + j * nx);
for (int k = 0; k < nz; k++)
data[k][index] = line[k];
}
public void setImagZ(int i, int j, float line[]) {
int index = 2 * (i + j * nx) + 1;
for (int k = 0; k < nz; k++)
data[k][index] = line[k];
}
public void setRealX(int j, int k, float line[]) {
for (int i = 0; i < nx; i++)
data[k][2 * (i + j * nx)] = line[i];
}
public void setImagX(int j, int k, float line[]) {
for (int i = 0; i < nx; i++)
data[k][2 * (i + j * nx) + 1] = line[i];
}
public void setRealY(int i, int k, float line[]) {
for (int j = 0; j < ny; j++)
data[k][2 * (i + j * nx)] = line[j];
}
public void setImagY(int i, int k, float line[]) {
for (int j = 0; j < ny; j++)
data[k][2 * (i + j * nx) + 1] = line[j];
}
public void setInterleaveXY(int k, float slice[]) {
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
data[k][2 * (i + j * nx)] = slice[2*(i + j * nx)];
data[k][2 * (i + j * nx) + 1] = slice[2*(i + j * nx) + 1];
}
}
public void setInterleaveYX(int k, float slice[]) {
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
data[k][2 * (i + j * nx)] = slice[2*(j + i * ny)];
data[k][2 * (i + j * nx) + 1] = slice[2*(j + i * ny) + 1];
}
}
public void setRealXY(int k, float slice[]) {
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++)
data[k][2 * (i + j * nx)] = slice[i + j * nx];
}
public void setImagXY(int k, float slice[]) {
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++)
data[k][2 * (i + j * nx)+1] = slice[i + j * nx];
}
public float[] getRealY(int i, int k, int imag) {
float line[] = new float[ny];
int off = 2 * i + imag;
for (int j = 0; j < ny; j++)
line[j] = data[k][2 * j * nx + off];
return line;
}
public void swap() {
int hx = nx / 2;
int hy = ny / 2;
int hz = nz / 2;
if (nx > 1) {
float rx[] = new float[nx];
float ix[] = new float[nx];
for (int j = 0; j < ny; j++)
for (int k = 0; k < nz; k++) {
float real[] = getRealX(j, k);
float imag[] = getImagX(j, k);
for (int i = 0; i < hx; i++) {
rx[i] = real[i + hx];
rx[i + hx] = real[i];
ix[i] = imag[i + hx];
ix[i + hx] = imag[i];
}
setRealX(j, k, rx);
setImagX(j, k, ix);
}
}
if (ny > 1) {
float ry[] = new float[ny];
float iy[] = new float[ny];
for (int i = 0; i < nx; i++)
for (int k = 0; k < nz; k++) {
float real[] = getRealY(i, k);
float imag[] = getImagY(i, k);
for (int j = 0; j < hy; j++) {
ry[j] = real[j + hy];
ry[j + hy] = real[j];
iy[j] = imag[j + hy];
iy[j + hy] = imag[j];
}
setRealY(i, k, ry);
setImagY(i, k, iy);
}
}
if (nz > 1) {
float rz[] = new float[nz];
float iz[] = new float[nz];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
float real[] = getRealZ(i, j);
float imag[] = getImagZ(i, j);
for (int k = 0; k < hz; k++) {
rz[k] = real[k + hz];
rz[k + hz] = real[k];
iz[k] = imag[k + hz];
iz[k + hz] = imag[k];
}
setRealZ(i, j, rz);
setImagZ(i, j, iz);
}
}
}
public void circularShift() {
for(int i=0; i<nx; i++)
for(int j=0; j<ny; j++) {
setImagZ(i, j, rotate(getImagZ(i, j)));
setRealZ(i, j, rotate(getRealZ(i, j)));
}
for(int i=0; i<nx; i++)
for(int k=0; k<nz; k++) {
setImagY(i, k, rotate(getImagY(i, k)));
setRealY(i, k, rotate(getRealY(i, k)));
}
for(int j=0; j<ny; j++)
for(int k=0; k<nz; k++) {
setImagX(j, k, rotate(getImagX(j, k)));
setRealX(j, k, rotate(getRealX(j, k)));
}
}
private float[] rotate(float[] buffer) {
int len = buffer.length;
if (len <= 1)
return buffer;
int count = 0;
int offset = 0;
int start = len / 2;
while (count < len) {
int index = offset;
float tmp = buffer[index];
int index2 = (start + index) % len;
while (index2 != offset) {
buffer[index] = buffer[index2];
count++;
index = index2;
index2 = (start + index) % len;
}
buffer[index] = tmp;
count++;
offset++;
}
return buffer;
}
@Override
public String toString() {
return "Complex Signal [" + nx + ", " + ny + ", " + nz + "]";
}
}
\ No newline at end of file
diff --git a/DeconvolutionLab2/src/signal/RealSignal.java b/DeconvolutionLab2/src/signal/RealSignal.java
index b49a5f1..cfa0428 100644
--- a/DeconvolutionLab2/src/signal/RealSignal.java
+++ b/DeconvolutionLab2/src/signal/RealSignal.java
@@ -1,658 +1,652 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package signal;
-import java.awt.Image;
import java.awt.image.BufferedImage;
-import deconvolutionlab.Lab;
import deconvolutionlab.monitor.Monitors;
public class RealSignal extends Signal implements SignalListener {
+ private BufferedImage preview;
+
public RealSignal(String name, int nx, int ny, int nz) {
super(name, nx, ny, nz);
this.data = new float[nz][];
int step = Math.max(1, nz / SignalCollector.NOTIFICATION_RATE);
notify(name, 0);
for (int k = 0; k < nz; k++) {
data[k] = new float[nx * ny];
if (k % step == 0)
notify(name, k * 100.0 / nz);
}
notify(name, 100);
- SignalCollector.alloc(name, nx, ny, ny, false);
- this.addSignalListener(this);
+ SignalCollector.alloc(this);//name, nx, ny, ny, false);
}
@Override
public void notify(String name, double progress) {
SignalCollector.setProgress(progress);
}
- @Override
- public void finalize() {
- data = null;
- System.gc();
- SignalCollector.free(name, nx, ny, ny, false);
- }
-
public void copy(RealSignal source) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = source.data[k][i];
}
}
public void setSignal(RealSignal signal) {
int sx = signal.nx;
int mx = Math.min(nx, signal.nx);
int my = Math.min(ny, signal.ny);
int mz = Math.min(nz, signal.nz);
for (int i = 0; i < mx; i++)
for (int j = 0; j < my; j++)
for (int k = 0; k < mz; k++)
data[k][i + nx * j] = signal.data[k][i + sx * j];
}
public void getSignal(RealSignal signal) {
int sx = signal.nx;
int mx = Math.min(nx, signal.nx);
int my = Math.min(ny, signal.ny);
int mz = Math.min(nz, signal.nz);
for (int i = 0; i < mx; i++)
for (int j = 0; j < my; j++)
for (int k = 0; k < mz; k++)
signal.data[k][i + sx * j] = data[k][i + nx * j];
}
/**
* Applies a soft threshold (in-place processing)
*
* @param inferiorLimit
* @param superiorLimit
* @return the instance of the calling object
*/
public RealSignal thresholdSoft(float inferiorLimit, float superiorLimit) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
if (data[k][i] <= inferiorLimit)
data[k][i] += inferiorLimit;
else if (data[k][i] >= superiorLimit)
data[k][i] -= superiorLimit;
else
data[k][i] = 0f;
}
return this;
}
/**
* Multiplies by a signal pixelwise (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal times(RealSignal factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] *= factor.data[k][i];
}
return this;
}
/**
* Multiplies by a scalar factor (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal times(float factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] *= factor;
}
return this;
}
/**
* Adds a signal pixelwise (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal plus(RealSignal factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] += factor.data[k][i];
}
return this;
}
/**
* Subtracts by a signal pixelwise (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal minus(RealSignal factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] -= factor.data[k][i];
}
return this;
}
/**
* Adds a scalar term (in-place processing)
*
* @param term
* @return the instance of the calling object
*/
public RealSignal plus(float term) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] += term;
}
return this;
}
/**
* Takes the maximum (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal max(RealSignal factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = Math.max(data[k][i], factor.data[k][i]);
}
return this;
}
/**
* Takes the minimum (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal min(RealSignal factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = Math.min(data[k][i], factor.data[k][i]);
}
return this;
}
public double[][][] get3DArrayAsDouble() {
double[][][] ar = new double[nx][ny][nz];
for (int k = 0; k < nz; k++) {
float[] s = data[k];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
ar[i][j][k] = s[i + j * nx];
}
}
return ar;
}
public void set3DArrayAsDouble(double[][][] real) {
for (int k = 0; k < nz; k++) {
float[] s = data[k];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
s[i + j * nx] = (float) real[i][j][k];
}
}
}
public RealSignal duplicate() {
RealSignal out = new RealSignal("copy(" + name + ")", nx, ny, nz);
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
System.arraycopy(data[k], 0, out.data[k], 0, nxy);
return out;
}
public float getEnergy() {
int nxy = nx * ny;
float energy = 0.f;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
energy += data[k][i];
return energy;
}
public float[] getStats() {
int nxy = nx * ny;
float min = Float.MAX_VALUE;
float max = -Float.MAX_VALUE;
double norm1 = 0.0;
double norm2 = 0.0;
double mean = 0.0;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
float v = data[k][i];
max = Math.max(max, v);
min = Math.min(min, v);
mean += v;
norm1 += (v > 0 ? v : -v);
norm2 += v * v;
}
mean = mean / (nz * nxy);
norm1 = norm1 / (nz * nxy);
norm2 = Math.sqrt(norm2 / (nz * nxy));
double stdev = 0.0;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
stdev += (data[k][i] - mean) * (data[k][i] - mean);
}
stdev = Math.sqrt(stdev / (nz * nxy));
return new float[] { (float) mean, min, max, (float) stdev, (float) norm1, (float) norm2 };
}
public float[] getExtrema() {
int nxy = nx * ny;
float min = Float.MAX_VALUE;
float max = -Float.MAX_VALUE;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
float v = data[k][i];
max = Math.max(max, v);
min = Math.min(min, v);
}
return new float[] { min, max };
}
public RealSignal normalize(double to) {
if (to == 0)
return this;
int nxy = nx * ny;
float sum = 0f;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
sum += data[k][i];
if (sum != 0f) {
double r = to / sum;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
data[k][i] *= r;
}
return this;
}
public void setSlice(int z, RealSignal slice) {
int mx = slice.nx;
int my = slice.ny;
for (int j = 0; j < Math.min(ny, my); j++)
for (int i = 0; i < Math.min(nx, mx); i++)
data[z][i + nx * j] = slice.data[0][i + mx * j];
}
public RealSignal getSlice(int z) {
RealSignal slice = new RealSignal(name + "_z=" + z, nx, ny, 1);
for (int j = 0; j < nx * ny; j++)
slice.data[0][j] = data[z][j];
return slice;
}
public void multiply(double factor) {
for (int k = 0; k < nz; k++)
for (int i = 0; i < nx * ny; i++)
data[k][i] *= factor;
}
public float[] getInterleaveXYZAtReal() {
float[] interleave = new float[2 * nz * nx * ny];
for (int k = 0; k < nz; k++)
for (int j = 0; j < ny; j++)
for (int i = 0; i < nx; i++)
interleave[2 * (k * nx * ny + j * nx + i)] = data[k][i + j * nx];
return interleave;
}
public void setInterleaveXYZAtReal(float[] interleave) {
for (int k = 0; k < nz; k++)
for (int j = 0; j < ny; j++)
for (int i = 0; i < nx; i++)
data[k][i + nx * j] = interleave[(k * nx * ny + j * nx + i) * 2];
}
public float[] getInterleaveXYAtReal(int k) {
float real[] = new float[nx * ny * 2];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = i + j * nx;
real[2 * index] = data[k][index];
}
return real;
}
public void setInterleaveXYAtReal(int k, float real[]) {
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = i + j * nx;
data[k][index] = real[2 * index];
}
}
public float[] getXYZ() {
int nxy = nx * ny;
float[] d = new float[nz * nx * ny];
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
d[k * nxy + i] = data[k][i];
return d;
}
public void setXYZ(float[] data) {
if (nx * ny * nz != data.length)
return;
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
this.data[k][i] = data[k * nxy + i];
}
public float[] getXY(int k) {
return data[k];
}
public void setXY(int k, float slice[]) {
data[k] = slice;
}
public float[] getX(int j, int k) {
float line[] = new float[nx];
for (int i = 0; i < nx; i++)
line[i] = data[k][i + j * nx];
return line;
}
public float[] getZ(int i, int j) {
float line[] = new float[nz];
int index = i + j * nx;
for (int k = 0; k < nz; k++)
line[k] = data[k][index];
return line;
}
public float[] getY(int i, int k) {
float line[] = new float[ny];
for (int j = 0; j < ny; j++)
line[j] = data[k][i + j * nx];
return line;
}
public void setX(int j, int k, float line[]) {
for (int i = 0; i < nx; i++)
data[k][i + j * nx] = line[i];
}
public void setY(int i, int k, float line[]) {
for (int j = 0; j < ny; j++)
data[k][i + j * nx] = line[j];
}
public void setZ(int i, int j, float line[]) {
int index = i + j * nx;
for (int k = 0; k < nz; k++)
data[k][index] = line[k];
}
public void clip(float min, float max) {
for (int k = 0; k < nz; k++)
for (int j = 0; j < ny * nx; j++)
if (data[k][j] < min)
data[k][j] = min;
else if (data[k][j] > max)
data[k][j] = max;
}
public void fill(float constant) {
for (int k = 0; k < nz; k++)
for (int j = 0; j < ny * nx; j++)
data[k][j] = constant;
}
public RealSignal changeSizeAs(RealSignal model) {
return size(model.nx, model.ny, model.nz);
}
public RealSignal size(int mx, int my, int mz) {
String n = "resize(" + name + ")";
int ox = (mx - nx) / 2;
int oy = (my - ny) / 2;
int oz = (mz - nz) / 2;
RealSignal signal = new RealSignal(n, mx, my, mz);
int vx = Math.min(nx, mx);
int vy = Math.min(ny, my);
int vz = Math.min(nz, mz);
for (int k = 0; k < vz; k++)
for (int j = 0; j < vy; j++)
for (int i = 0; i < vx; i++) {
int pi = ox >= 0 ? i + ox : i;
int qi = ox >= 0 ? i : i - ox;
int pj = oy >= 0 ? j + oy : j;
int qj = oy >= 0 ? j : j - oy;
int pk = oz >= 0 ? k + oz : k;
int qk = oz >= 0 ? k : k - oz;
signal.data[pk][pi + pj * mx] = data[qk][qi + qj * nx];
}
return signal;
}
- public BufferedImage createPreviewMIPZ() {
- RealSignal mip = createMIPZ();
- mip.rescale(Monitors.createDefaultMonitor());
- BufferedImage img = new BufferedImage(nx, ny, BufferedImage.TYPE_INT_ARGB);
- int alpha = (255 << 24);
- for (int i = 0; i < nx; i++)
- for (int j = 0; j < ny; j++) {
- int v = (int)mip.data[0][i + j * nx];
- img.setRGB(i, j, alpha | (v << 16) | (v << 8) | v);
- }
- return img;
- }
-
public RealSignal createOrthoview() {
return createOrthoview(nx / 2, ny / 2, nz / 2);
}
public RealSignal createOrthoview(int hx, int hy, int hz) {
String n = "ortho(" + name + ")";
int vx = nx + nz;
int vy = ny + nz;
RealSignal view = new RealSignal(n, vx, vy, 1);
hx = Math.min(nx - 1, Math.max(0, hx));
hy = Math.min(ny - 1, Math.max(0, hy));
hz = Math.min(nz - 1, Math.max(0, hz));
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++)
view.data[0][x + vx * y] = data[hz][x + nx * y];
for (int z = 0; z < nz; z++)
for (int y = 0; y < ny; y++)
view.data[0][nx + z + vx * y] = data[z][hx + nx * y];
for (int z = 0; z < nz; z++)
for (int x = 0; x < nx; x++)
view.data[0][x + vx * (ny + z)] = data[z][x + nx * hy];
return view;
}
public RealSignal createFigure(int hx, int hy, int hz) {
String n = "figure(" + name + ")";
int vx = nx + nz + 4;
int vy = ny + 2;
float max = this.getExtrema()[1];
RealSignal view = new RealSignal(n, vx, vy, 1);
for (int i = 0; i < vx * vy; i++)
view.data[0][i] = max;
hx = Math.min(nx - 1, Math.max(0, hx));
hy = Math.min(ny - 1, Math.max(0, hy));
hz = Math.min(nz - 1, Math.max(0, hz));
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++)
view.data[0][x + 1 + vx * (y + 1)] = data[hz][x + nx * y];
for (int z = 0; z < nz; z++)
for (int y = 0; y < ny; y++)
view.data[0][nx + 3 + z + vx * (y + 1)] = data[z][hx + nx * y];
return view;
}
public RealSignal createMIP() {
String n = "mip(" + name + ")";
int vx = nx + nz + 1;
int vy = ny + nz + 1;
RealSignal view = new RealSignal(n, vx, vy, 1);
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++)
for (int k = 0; k < nz; k++) {
int index = x + vx * y;
view.data[0][index] = Math.max(view.data[0][index], data[k][x + nx * y]);
}
for (int z = 0; z < nz; z++)
for (int y = 0; y < ny; y++)
for (int x = 0; x < nx; x++) {
int index = nx + 1 + z + vx * y;
view.data[0][index] = Math.max(view.data[0][index], data[z][x + nx * y]);
}
for (int z = 0; z < nz; z++)
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++) {
int index = x + vx * (ny + 1 + z);
view.data[0][index] = Math.max(view.data[0][index], data[z][x + nx * y]);
}
return view;
}
- public RealSignal createMIPZ() {
- String n = "mipz(" + name + ")";
- RealSignal view = new RealSignal(n, nx, ny, 1);
- for (int x = 0; x < nx; x++)
- for (int y = 0; y < ny; y++) {
- int index = x + nx * y;
- for (int k = 0; k < nz; k++) {
- view.data[0][index] = Math.max(view.data[0][index], data[k][x + nx * y]);
- }
- }
- return view;
- }
-
public RealSignal createMontage() {
String n = "planar(" + name + ")";
int nr = (int) Math.sqrt(nz);
int nc = (int) Math.ceil(nz / nr) + 1;
int w = nx * nr;
int h = ny * nc;
RealSignal view = new RealSignal(n, w, h, 1);
for (int k = 0; k < nz; k++) {
int col = k % nr;
int row = k / nr;
int offx = col * nx;
int offy = row * ny;
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++)
view.data[0][x + offx + w * (y + offy)] = data[k][x + nx * y];
}
return view;
}
public RealSignal circular() {
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++)
setZ(i, j, rotate(getZ(i, j)));
for (int i = 0; i < nx; i++)
for (int k = 0; k < nz; k++)
setY(i, k, rotate(getY(i, k)));
for (int j = 0; j < ny; j++)
for (int k = 0; k < nz; k++)
setX(j, k, rotate(getX(j, k)));
return this;
}
public RealSignal rescale(Monitors monitors) {
new Constraint(monitors).rescaled(this, 0, 255);
return this;
}
public float[] rotate(float[] buffer) {
int len = buffer.length;
if (len <= 1)
return buffer;
int count = 0;
int offset = 0;
int start = len / 2;
while (count < len) {
int index = offset;
float tmp = buffer[index];
int index2 = (start + index) % len;
while (index2 != offset) {
buffer[index] = buffer[index2];
count++;
index = index2;
index2 = (start + index) % len;
}
buffer[index] = tmp;
count++;
offset++;
}
return buffer;
}
@Override
public String toString() {
return "Real Signal [" + nx + ", " + ny + ", " + nz + "]";
}
+
+ public BufferedImage preview() {
+ if (preview != null)
+ return preview;
+ int nxy = nx*ny;
+ float[] pixels = new float[nx*ny];
+ for (int i = 0; i < nxy; i++)
+ for (int k = 0; k < nz; k++) {
+ pixels[i] = Math.max(pixels[i], data[k][i]);
+ }
+ float max = -Float.MAX_VALUE;
+ float min = Float.MAX_VALUE;
+ for (int i = 0; i < nxy; i++) {
+ if (pixels[i] > max)
+ max = pixels[i];
+ if (pixels[i] < min)
+ min = pixels[i];
+ }
+ float a = 255f / Math.max(max-min, (float)Operations.epsilon);
+ preview = new BufferedImage(nx, ny, BufferedImage.TYPE_INT_ARGB);
+ int alpha = (255 << 24);
+ for (int i = 0; i < nx; i++)
+ for (int j = 0; j < ny; j++) {
+ int v = (int)(a*(pixels[i+j*nx] - min));
+ preview.setRGB(i, j, alpha | (v << 16) | (v << 8) | v);
+ }
+ return preview;
+ }
}
diff --git a/DeconvolutionLab2/src/signal/Signal.java b/DeconvolutionLab2/src/signal/Signal.java
index 6aa8f68..fa0c232 100644
--- a/DeconvolutionLab2/src/signal/Signal.java
+++ b/DeconvolutionLab2/src/signal/Signal.java
@@ -1,66 +1,59 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package signal;
import java.util.ArrayList;
public class Signal {
public int nx = 0;
public int ny;
public int nz;
public float data[][];
public String name = "untitled";
- private ArrayList<SignalListener> listeners = new ArrayList<SignalListener>();
-
public Signal(String name, int nx, int ny, int nz) {
this.name = name;
this.nx = nx;
this.ny = ny;
this.nz = nz;
}
- public String dimAsString() {
- return nx + "x" + ny + "x" + nz + " ";
- }
-
- public void addSignalListener(SignalListener listener) {
- listeners.add(listener);
+ public void setName(String name) {
+ this.name = name;
}
- public void notify(String name, double progress) {
- for(SignalListener listener : listeners)
- listener.notify(name, progress);
+ public String dimAsString() {
+ return nx + "x" + ny + "x" + nz + " ";
}
}
diff --git a/DeconvolutionLab2/src/signal/SignalCollector.java b/DeconvolutionLab2/src/signal/SignalCollector.java
index 672e2fd..89393c4 100644
--- a/DeconvolutionLab2/src/signal/SignalCollector.java
+++ b/DeconvolutionLab2/src/signal/SignalCollector.java
@@ -1,109 +1,157 @@
package signal;
import java.util.ArrayList;
import javax.swing.JScrollPane;
import deconvolutionlab.system.SystemUsage;
import lab.component.CustomizedColumn;
import lab.component.CustomizedTable;
import lab.tools.NumFormat;
public class SignalCollector {
- private static long bytesReal = 0;
- private static int countReal = 0;
- private static long bytesComplex = 0;
- private static int countComplex = 0;
- private static double chrono = 0;
- private static CustomizedTable table;
- private static double progress = 0;
+ private static long bytesReal = 0;
+ private static int countReal = 0;
+ private static long bytesComplex = 0;
+ private static int countComplex = 0;
+ private static double chrono = 0;
+ private static CustomizedTable table;
+ private static double progress = 0;
- protected final static int NOTIFICATION_RATE = 25;
+ private static int countPeakComplex = 0;
+ private static int countPeakReal = 0;
+ private static long bytesPeakComplex = 0;
+ private static long bytesPeakReal = 0;
+
+ private static ArrayList<Signal> signals;
+ protected final static int NOTIFICATION_RATE = 25;
static {
bytesReal = 0;
countReal = 0;
bytesComplex = 0;
countComplex = 0;
+ signals = new ArrayList<Signal>();
chrono = System.nanoTime();
-
ArrayList<CustomizedColumn> columns = new ArrayList<CustomizedColumn>();
columns.add(new CustomizedColumn("Time", String.class, 100, false));
columns.add(new CustomizedColumn("Name", String.class, 600, false));
columns.add(new CustomizedColumn("Dimension", String.class, 60, false));
columns.add(new CustomizedColumn("Count", String.class, 100, false));
columns.add(new CustomizedColumn("Total", String.class, 100, false));
columns.add(new CustomizedColumn("Memory", String.class, 100, false));
table = new CustomizedTable(columns, true);
table.getColumnModel().getColumn(4).setMaxWidth(100);
table.getColumnModel().getColumn(4).setMinWidth(100);
}
-
+
public static JScrollPane getPanel(int w, int h) {
return table.getPane(w, h);
}
-
+
public static String sumarize() {
- String r = "Signals: " + NumFormat.bytes(bytesReal + bytesComplex);
+ String r = "Signals: " + NumFormat.bytes(bytesReal + bytesComplex);
return r;
}
-
+
public static void clear() {
+ for(Signal signal : signals) {
+ for (int z = 0; z < signal.nz; z++)
+ signal.data[z] = new float[1];
+ }
+ signals.clear();
table.removeRows();
}
-
+
public static double getProgress() {
return progress;
}
-
+
public static void setProgress(double p) {
progress = p;
}
-
- public static void marker(String name) {
- String t = NumFormat.time(System.nanoTime()-chrono);
- String m = NumFormat.bytes(SystemUsage.getHeapUsed());
- String row[] = {t, name, "", "", "", m};
+
+ public static void marker(String msg) {
+ String row[] = { "", msg, "", "", "", "" };
table.append(row);
}
-
- public static void alloc(String name, int nx, int ny, int nz, boolean complex) {
- long b = nx * ny * nz * 4 * (complex ? 2 : 1);
+
+ public static void alloc(Signal signal) {
+ if (signal == null) {
+ marker("error in allocating");
+ return;
+ }
+ signals.add(signal);
+ addTable(signal, 1);
+ }
+
+ public static void free(Signal signal) {
+ if (signal == null) {
+ marker("error in freeing");
+ return;
+ }
+ for (int z = 0; z < signal.nz; z++)
+ signal.data[z] = new float[1];
+
+ signals.remove(signal);
+ addTable(signal, -1);
+ signal = null;
+ }
+
+ public static void addTable(Signal signal, int sign) {
+ boolean complex = signal instanceof ComplexSignal;
+ int nx = signal.nx;
+ int ny = signal.ny;
+ int nz = signal.nz;
+ long b = sign * (nx * ny * nz * 4 * (complex ? 2 : 1));
+
if (complex) {
bytesComplex += b;
- countComplex++;
+ countComplex += sign;
}
else {
bytesReal += b;
- countReal++;
+ countReal += sign;
}
+
+ bytesPeakComplex = Math.max(bytesPeakComplex, bytesComplex);
+ bytesPeakReal = Math.max(bytesPeakReal, bytesReal);
+ countPeakComplex = Math.max(countPeakComplex, countComplex);
+ countPeakReal = Math.max(countPeakReal, countReal);
String m = NumFormat.bytes(SystemUsage.getHeapUsed());
- String t = NumFormat.time(System.nanoTime()-chrono);
+ String t = NumFormat.time(System.nanoTime() - chrono);
String dim = "" + nx + "x" + ny + "x" + nz;
String c = "" + (countReal + countComplex);
String a = NumFormat.bytes(bytesReal + bytesComplex);
- String row[] = {t, name, dim, c, a, m};
+ String row[] = { t, (sign > 0 ? "+" : "-") + signal.name, dim, c, a, m };
table.append(row);
}
- public static void free(String name, int nx, int ny, int nz, boolean complex) {
- long b = nx * ny * nz * 4 * (complex ? 2 : 1);
- if (complex) {
- bytesComplex -= b;
- countComplex--;
- }
- else {
- bytesReal -= b;
- countReal--;
- }
- String m = NumFormat.bytes(SystemUsage.getHeapUsed());
- String t = NumFormat.time(System.nanoTime()-chrono);
- String dim = "" + nx + "x" + ny + "x" + nz;
- String c = "" + (countReal + countComplex);
- String a = NumFormat.bytes(bytesReal + bytesComplex);
- String row[] = {t, name, dim, c, a, m};
- table.append(row);
+ public static int getCountSignals() {
+ return countComplex + countReal;
}
+ public static long getBytesSignals() {
+ return bytesComplex + bytesReal;
+ }
+
+ public static long getBytesPeakSignals() {
+ return bytesPeakComplex + bytesPeakReal;
+ }
+
+ public static int getCountPeakSignals() {
+ return countPeakComplex + countPeakReal;
+ }
+
+ public static void resetSignals() {
+ countPeakComplex = 0;
+ countPeakReal = 0;
+ bytesPeakComplex = 0;
+ bytesPeakReal = 0;
+ countComplex = 0;
+ countReal = 0;
+ bytesComplex = 0;
+ bytesReal = 0;
+ }
}
diff --git a/DeconvolutionLab2/src/signal/SignalListener.java b/DeconvolutionLab2/src/signal/SignalListener.java
index 3d1cdc5..6ff2d3c 100644
--- a/DeconvolutionLab2/src/signal/SignalListener.java
+++ b/DeconvolutionLab2/src/signal/SignalListener.java
@@ -1,6 +1,5 @@
package signal;
public interface SignalListener {
-
public void notify(String name, double progress);
}
diff --git a/DeconvolutionLab2/src/signal/apodization/Apodization.java b/DeconvolutionLab2/src/signal/apodization/Apodization.java
index 0af3223..1378a5e 100644
--- a/DeconvolutionLab2/src/signal/apodization/Apodization.java
+++ b/DeconvolutionLab2/src/signal/apodization/Apodization.java
@@ -1,169 +1,160 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package signal.apodization;
import java.util.ArrayList;
import deconvolutionlab.monitor.Monitors;
import signal.RealSignal;
import signal.factory.Constant;
public class Apodization {
private AbstractApodization apoX = getDefault();
private AbstractApodization apoY = getDefault();
private AbstractApodization apoZ = getDefault();
public Apodization() {
apoX = new UniformApodization();
apoY = new UniformApodization();
apoZ = new UniformApodization();
}
public Apodization(AbstractApodization apoX, AbstractApodization apoY, AbstractApodization apoZ) {
this.apoX = apoX;
this.apoY = apoY;
this.apoZ = apoZ;
}
public Apodization(String nameX, String nameY, String nameZ) {
for(AbstractApodization apo : getApodizations()) {
if (apo.getName().equals(nameX))
apoX = apo;
if (apo.getName().equals(nameY))
apoY = apo;
if (apo.getName().equals(nameZ))
apoZ = apo;
if (apo.getShortname().equals(nameX))
apoX = apo;
if (apo.getShortname().equals(nameY))
apoY = apo;
if (apo.getShortname().equals(nameZ))
apoZ = apo;
}
}
public static ArrayList<AbstractApodization> getApodizations() {
ArrayList<AbstractApodization> apos = new ArrayList<AbstractApodization>();
apos.add(new UniformApodization());
apos.add(new HammingApodization());
apos.add(new HannApodization());
apos.add(new RaisedCosineApodization(1));
apos.add(new TukeyApodization(0.5));
apos.add(new WelchApodization());
return apos;
}
public static ArrayList<String> getApodizationsName() {
ArrayList<AbstractApodization> apos = getApodizations();
ArrayList<String> names = new ArrayList<String>();
for(AbstractApodization apo : apos)
names.add(apo.getName());
return names;
}
public static String[] getApodizationsAsArray() {
ArrayList<AbstractApodization> apos = getApodizations();
String names[] = new String[apos.size()];
for(int i=0; i<apos.size(); i++)
names[i] = apos.get(i).getName();
return names;
}
public static AbstractApodization getByName(String name) {
ArrayList<AbstractApodization> apos = getApodizations();
for(AbstractApodization apo : apos)
if (name.equals(apo.getName()))
return apo;
return getDefault();
}
public static AbstractApodization getByShortname(String name) {
ArrayList<AbstractApodization> apos = getApodizations();
for(AbstractApodization apo : apos)
if (name.equals(apo.getShortname()))
return apo;
return getDefault();
}
public static AbstractApodization getDefault() {
return new UniformApodization();
}
-
- public double estimateLostEnergy(int size) {
- RealSignal in = new Constant().intensity(0, 1).generate(size, size, size);
- double ein = size * size * size;
- double eout = apodize(Monitors.createDefaultMonitor(), in).getEnergy();
- return 1.0 - (ein - eout) / ein;
- }
-
- public RealSignal apodize(Monitors monitors, RealSignal input) {
+
+ public void apodize(Monitors monitors, RealSignal signal) {
if (apoX instanceof UniformApodization &&
apoY instanceof UniformApodization &&
apoZ instanceof UniformApodization) {
- return input;
+ return;
}
if (monitors != null)
monitors.log("Apodization (" + apoX.getName() + ", " + apoY.getName() + ", " + apoZ.getName() + ")");
- String name = " apo( " + input.name + ")";
- RealSignal out = new RealSignal(name, input.nx, input.ny, input.nz);
- for(int i=0; i<input.nx; i++) {
- double cx = apoX.apodize(i, input.nx);
- for(int j=0; j<input.ny; j++) {
- double cy = apoY.apodize(j, input.ny);
- int index = i + input.nx*j;
- for(int k=0; k<input.nz; k++) {
- double cz = apoZ.apodize(k, input.nz);
- out.data[k][index] = (float)(cx * cy * cz * input.data[k][index]);
+ signal.setName("apo(" + signal.name + ")");
+ for(int i=0; i<signal.nx; i++) {
+ double cx = apoX.apodize(i, signal.nx);
+ for(int j=0; j<signal.ny; j++) {
+ double cy = apoY.apodize(j, signal.ny);
+ int index = i + signal.nx*j;
+ for(int k=0; k<signal.nz; k++) {
+ double cz = apoZ.apodize(k, signal.nz);
+ signal.data[k][index] = (float)(cx * cy * cz * signal.data[k][index]);
}
}
}
- return out;
}
@Override
public String toString() {
String s = "";
s += "lateral (XY)";
if (apoX instanceof UniformApodization)
s += " keep unchanged";
else
s+= " " + apoX.getName();
s += ", axial (Z)";
if (apoZ instanceof UniformApodization)
s += " keep unchanged";
else
s+= " " + apoZ.getName();
return s;
}
}
diff --git a/DeconvolutionLab2/src/signal/factory/SignalFactory.java b/DeconvolutionLab2/src/signal/factory/SignalFactory.java
index 9a1275e..ee1f9d3 100644
--- a/DeconvolutionLab2/src/signal/factory/SignalFactory.java
+++ b/DeconvolutionLab2/src/signal/factory/SignalFactory.java
@@ -1,210 +1,244 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package signal.factory;
import java.util.ArrayList;
import javax.swing.SwingWorker;
+import deconvolution.Command;
import signal.RealSignal;
public abstract class SignalFactory {
protected double fractXC = 0.5;
protected double fractYC = 0.5;
protected double fractZC = 0.5;
protected double background = 0.0;
protected double amplitude = 1.0;
protected double xc;
protected double yc;
protected double zc;
protected int nx;
protected int ny;
protected int nz;
public SignalFactory() {
}
public SignalFactory(double[] parameters) {
setParameters(parameters);
}
public static SignalFactory get(String name) {
ArrayList<SignalFactory> list = getAll();
for (SignalFactory factory : list) {
if (factory.getName().equals(name))
return factory;
}
return null;
}
+
+ public static RealSignal createFromCommand(String cmd) {
+ String parts[] = cmd.split(" ");
+ if (parts.length <= 0)
+ return null;
+ String shape = parts[0];
+ for (String name : SignalFactory.getAllName()) {
+ if (shape.equalsIgnoreCase(name.toLowerCase())) {
+ double params[] = Command.parseNumeric(cmd);
+ SignalFactory factory = SignalFactory.getFactoryByName(shape);
+ if (factory == null)
+ return null;
+ double amplitude = params.length > 0 ? params[0] : 1;
+ double background = params.length > 1 ? params[1] : 0;
+ factory.intensity(background, amplitude);
+ int np = factory.getParameters().length;
+ double[] features = new double[np];
+ for (int i = 0; i < Math.min(np, params.length); i++)
+ features[i] = params[i + 2];
+ factory.setParameters(features);
+ int nx = params.length > np + 2 ? (int) Math.round(params[np + 2]) : 128;
+ int ny = params.length > np + 3 ? (int) Math.round(params[np + 3]) : 128;
+ int nz = params.length > np + 4 ? (int) Math.round(params[np + 4]) : 128;
+ double cx = params.length > np + 5 ? params[np + 5] : 0.5;
+ double cy = params.length > np + 6 ? params[np + 6] : 0.5;
+ double cz = params.length > np + 7 ? params[np + 7] : 0.5;
+ factory = factory.center(cx, cy, cz);
+ return factory.generate(nx, ny, nz);
+ }
+ }
+ return null;
+
+ }
public static ArrayList<String> getAllName() {
ArrayList<String> list = new ArrayList<String>();
for (SignalFactory factory : getAll()) {
list.add(factory.getName());
}
return list;
}
public static ArrayList<SignalFactory> getAll() {
ArrayList<SignalFactory> list = new ArrayList<SignalFactory>();
list.add(new AirySimulated(1));
list.add(new Astigmatism(3, 0.2));
list.add(new Constant());
list.add(new Cross(1, 1, 30));
list.add(new Cube(10 ,1));
list.add(new Defocus(3, 10, 10));
list.add(new DoG(3, 4));
list.add(new DoubleHelix(3, 10, 10));
list.add(new Gaussian(3, 3, 3));
list.add(new GridSpots(3, 1, 10));
list.add(new Impulse());
//list.add(new MotionBlur(3, 30, 3));
list.add(new Ramp(1, 0, 0));
list.add(new RandomLines(3));
list.add(new Sinc(3, 3, 3));
list.add(new Sphere(10, 1));
list.add(new Torus(10));
return list;
}
public static ArrayList<SignalFactory> getImages() {
ArrayList<SignalFactory> list = new ArrayList<SignalFactory>();
list.add(new Cube(10, 1));
list.add(new Sphere(10, 1));
list.add(new GridSpots(3, 1, 10));
list.add(new Constant());
list.add(new Cross(1, 1, 30));
list.add(new DoG(3, 4));
list.add(new Gaussian(3, 3, 3));
list.add(new Impulse());
list.add(new Ramp(1, 0, 0));
list.add(new RandomLines(3));
list.add(new Torus(10));
return list;
}
public static ArrayList<SignalFactory> getPSF() {
ArrayList<SignalFactory> list = new ArrayList<SignalFactory>();
list.add(new AirySimulated(1));
list.add(new Astigmatism(3, 0.2));
list.add(new Cross(3, 1, 10));
list.add(new Cube(10, 1));
list.add(new Defocus(3, 10, 10));
list.add(new DoG(3, 4));
list.add(new DoubleHelix(3, 10, 10));
list.add(new Gaussian(3, 3, 3));
//list.add(new MotionBlur(3, 30, 3));
list.add(new Impulse());
list.add(new Sinc(3, 3, 3));
list.add(new Sphere(10, 1));
list.add(new RandomLines(3));
list.add(new Torus(10));
return list;
}
public static SignalFactory getFactoryByName(String name) {
ArrayList<SignalFactory> list = getAll();
for (SignalFactory factory : list)
if (name.toLowerCase().equals(factory.getName().toLowerCase())) {
return factory;
}
return null;
}
public SignalFactory center(double fractXC, double fractYC, double fractZC) {
this.fractXC = fractXC;
this.fractYC = fractYC;
this.fractZC = fractZC;
return this;
}
public SignalFactory intensity(double background, double amplitude) {
this.background = background;
this.amplitude = amplitude;
return this;
}
public String params() {
String name[] = getParametersName();
double params[] = getParameters();
if (params.length == 1)
return name[0] + "=" + params[0];
else if (params.length == 2)
return name[0] + "=" + params[0] + " " + name[1] + "=" + params[1];
else
return name[0] + "=" + params[0] + " " + name[1] + "=" + params[2] + " " + name[2] + "=" + params[2];
}
public RealSignal generate(int nx, int ny, int nz) {
this.nx = nx;
this.ny = ny;
this.nz = nz;
xc = fractXC * nx;
yc = fractYC * ny;
zc = fractZC * nz;
RealSignal signal = new RealSignal(getName(), nx, ny, nz);
fill(signal);
return signal;
}
public abstract String getName();
public abstract void setParameters(double[] parameters);
public abstract double[] getParameters();
public abstract String[] getParametersName();
public abstract void fill(RealSignal signal);
public class Worker extends SwingWorker<RealSignal, String> {
private RealSignal signal;
public boolean done=false;
public Worker(RealSignal signal) {
this.signal = signal;
done = false;
}
protected RealSignal doInBackground() throws Exception {
fill(signal);
done = true;
return signal;
}
protected void done() {
done = true;
}
}
}
diff --git a/DeconvolutionLab2/src/signal/padding/Padding.java b/DeconvolutionLab2/src/signal/padding/Padding.java
index 090a66c..57f2102 100644
--- a/DeconvolutionLab2/src/signal/padding/Padding.java
+++ b/DeconvolutionLab2/src/signal/padding/Padding.java
@@ -1,254 +1,253 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package signal.padding;
import java.util.ArrayList;
import deconvolutionlab.monitor.Monitors;
import signal.RealSignal;
+import signal.SignalCollector;
public class Padding {
private AbstractPadding padX = getDefault();
private AbstractPadding padY = getDefault();
private AbstractPadding padZ = getDefault();
private int minExtensionX = 0;
private int minExtensionY = 0;
private int minExtensionZ = 0;
private int nx = -1;
private int ny = -1;
private int nz = -1;
public Padding() {
padX = new NoPadding();
padY = new NoPadding();
padZ = new NoPadding();
this.minExtensionX = 0;
this.minExtensionY = 0;
this.minExtensionZ = 0;
}
public Padding(int minExtensionX, int minExtensionY, int minExtensionZ) {
padX = new NoPadding();
padY = new NoPadding();
padZ = new NoPadding();
this.minExtensionX = minExtensionX;
this.minExtensionY = minExtensionY;
this.minExtensionZ = minExtensionZ;
}
public Padding(AbstractPadding padX, AbstractPadding padY, AbstractPadding padZ, int minExtensionX, int minExtensionY, int minExtensionZ) {
this.padX = padX;
this.padY = padY;
this.padZ = padZ;
this.minExtensionX = minExtensionX;
this.minExtensionY = minExtensionY;
this.minExtensionZ = minExtensionZ;
}
public Padding(AbstractPadding pad, int extension) {
this.padX = pad;
this.padY = pad;
this.padZ = pad;
this.minExtensionX = extension;
this.minExtensionY = extension;
this.minExtensionZ = extension;
}
public Padding(String nameX, String nameY, String nameZ, int minExtensionX, int minExtensionY, int minExtensionZ) {
for(AbstractPadding pad : getPaddings()) {
if (pad.getName().equals(nameX))
padX = pad;
if (pad.getName().equals(nameY))
padY = pad;
if (pad.getName().equals(nameZ))
padZ = pad;
if (pad.getShortname().equals(nameX))
padX = pad;
if (pad.getShortname().equals(nameY))
padY = pad;
if (pad.getShortname().equals(nameZ))
padZ = pad;
this.minExtensionX = minExtensionX;
this.minExtensionY = minExtensionY;
this.minExtensionZ = minExtensionZ;
}
}
public static ArrayList<AbstractPadding> getPaddings() {
ArrayList<AbstractPadding> pads = new ArrayList<AbstractPadding>();
pads.add(new NoPadding());
pads.add(new Multiple2Padding());
pads.add(new Power2Padding());
pads.add(new Multiple23Padding());
pads.add(new Multiple235Padding());
return pads;
}
public static ArrayList<String> getPaddingsName() {
ArrayList<AbstractPadding> pads = getPaddings();
ArrayList<String> names = new ArrayList<String>();
for(AbstractPadding pad : pads)
names.add(pad.getName());
return names;
}
public static String[] getPaddingsAsArray() {
ArrayList<AbstractPadding> pads = getPaddings();
String names[] = new String[pads.size()];
for(int i=0; i<pads.size(); i++)
names[i] = pads.get(i).getName();
return names;
}
public static AbstractPadding getByName(String name) {
ArrayList<AbstractPadding> pads = getPaddings();
for(AbstractPadding pad : pads)
if (name.equals(pad.getName()))
return pad;
return getDefault();
}
public static AbstractPadding getByShortname(String name) {
ArrayList<AbstractPadding> pads = getPaddings();
for(AbstractPadding pad : pads)
if (name.equals(pad.getShortname()))
return pad;
return getDefault();
}
public static AbstractPadding getDefault() {
return new NoPadding();
}
public int[] pad(int nx, int ny, int nz) {
return new int[] { padX.padding(nx+minExtensionX), padY.padding(ny+minExtensionY), padZ.padding(nz+minExtensionZ)};
}
public RealSignal pad(Monitors monitors, RealSignal input) {
if (padX instanceof NoPadding && padY instanceof NoPadding &&
padZ instanceof NoPadding && (minExtensionX + minExtensionY + minExtensionZ == 0)) {
nx = ny = nz = -1;
return input.duplicate();
}
nx = input.nx;
ny = input.ny;
nz = input.nz;
int lx = padX.padding(nx+minExtensionX);
int ly = padY.padding(ny+minExtensionY);
int lz = padZ.padding(nz+minExtensionZ);
monitors.log("Padding to (" + lx + ", " + ly + ", " + lz + ")");
if (lx == nx)
if (ly == ny)
if (lz == nz)
return input.duplicate();
int ox = (lx - nx) / 2;
int oy = (ly - ny) / 2;
int oz = (lz - nz) / 2;
- String name = " pad( " + input.name + ")";
-
+ String name = "pad(" + input.name + ")";
RealSignal large = new RealSignal(name, lx, ly, lz);
-
for(int k=0; k<nz; k++) {
float in[] = input.data[k];
float lpix[] = large.data[k+oz];
for(int i=0; i<nx; i++)
for(int j=0; j<ny; j++)
lpix[(i+ox) + lx*(j+oy)] = in[i + nx*j];
}
return large;
}
public RealSignal crop(Monitors monitors, RealSignal large) {
if (nx == -1 || ny == -1 || nz == -1) {
- return large;
+ return large.duplicate();
}
int lx = large.nx;
int ly = large.ny;
int lz = large.nz;
int ox = (lx - nx) / 2;
int oy = (ly - ny) / 2;
int oz = (lz - nz) / 2;
if (lx == nx)
if (ly == ny)
if (lz == nz)
return large;
String name = " crop( " + large.name + ")";
RealSignal output = new RealSignal(name, nx, ny, nz);
monitors.log("Cropping to (" + nx + ", " + ny + ", " + nz + ")");
for(int k=0; k<nz; k++) {
float lpix[] = large.data[k+oz];
float out[] = output.data[k];
for(int i=0; i<nx; i++)
for(int j=0; j<ny; j++)
out[i + nx*j] = lpix[(i+ox) + lx*(j+oy)];
}
return output;
}
@Override
public String toString() {
String s = "";
s += "lateral (XY)";
if (padX instanceof NoPadding) {
if (minExtensionX == 0)
s += " no padding";
else
s += " extension of " + minExtensionX;
}
else {
s += " enforced to " + padX.getName();
}
s += ", axial (Z)";
if (padZ instanceof NoPadding) {
if (minExtensionZ == 0)
s += " no padding";
else
s += " extension of " + minExtensionZ;
}
else {
s += " enforced to " + padZ.getName();
}
return s;
}
}
diff --git a/DeconvolutionLab2/src/wavelets/AbstractWavelets.java b/DeconvolutionLab2/src/wavelets/AbstractWavelets.java
index 34bc83d..ef7c0e4 100644
--- a/DeconvolutionLab2/src/wavelets/AbstractWavelets.java
+++ b/DeconvolutionLab2/src/wavelets/AbstractWavelets.java
@@ -1,114 +1,121 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package wavelets;
import signal.RealSignal;
+import signal.SignalCollector;
public abstract class AbstractWavelets {
protected int scales;
public AbstractWavelets() {
this.scales = 3;
}
public AbstractWavelets(int scales) {
this.scales = scales;
}
public abstract void setScale(int scale);
- public abstract RealSignal analysis1(RealSignal in);
- public abstract RealSignal synthesis1(RealSignal in);
+ public abstract void analysis1(RealSignal in, RealSignal out);
+ public abstract void synthesis1(RealSignal in, RealSignal out);
public abstract String getName();
public abstract String getDocumentation();
public int getScales() {
return scales;
}
public void shrinkage(float threshold, RealSignal in, RealSignal out, RealSignal buffer) {
analysis(in, buffer);
buffer.thresholdSoft(-threshold, threshold);
synthesis(buffer, out);
}
public void analysis(RealSignal in, RealSignal out) {
String name = "w(" + in.name + ")";
if (out == null)
out = new RealSignal(name, in.nx, in.ny, in.nz);
int nxfine = in.nx;
int nyfine = in.ny;
int nzfine = in.nz;
int nx = nxfine;
int ny = nyfine;
int nz = nzfine;
for ( int i=0; i<scales; i++) {
RealSignal sub = new RealSignal("sub" + i, nx, ny, nz);
if (i==0)
in.getSignal(sub);
else
out.getSignal(sub);
- sub = analysis1(sub);
- out.setSignal(sub);
+ RealSignal subout = new RealSignal("subout" + i, nx, ny, nz);
+ analysis1(sub, subout);
+ out.setSignal(subout);
+ SignalCollector.free(sub);
+ SignalCollector.free(subout);
nx = Math.max(1, nx / 2);
ny = Math.max(1, ny / 2);
nz = Math.max(1, nz / 2);
}
}
public void synthesis(RealSignal in, RealSignal out) {
String name = "iw(" + in.name + ")";
if (out == null)
out = new RealSignal(name, in.nx, in.ny, in.nz);
int div = (int)Math.pow(2.0, (double)(scales-1));
int nxcoarse = Math.max(1, in.nx / div);
int nycoarse = Math.max(1, in.ny / div);
int nzcoarse = Math.max(1, in.nz / div);
int nx = nxcoarse;
int ny = nycoarse;
int nz = nzcoarse;
out.copy(in);
for ( int i=0; i<scales; i++) {
RealSignal sub = new RealSignal("sub" + i, nx, ny, nz);
out.getSignal(sub);
- sub = synthesis1(sub);
- out.setSignal(sub);
+ RealSignal subout = new RealSignal("subout" + i, nx, ny, nz);
+ synthesis1(sub, subout);
+ out.setSignal(subout);
+ SignalCollector.free(sub);
+ SignalCollector.free(subout);
nx = nx * 2;
ny = ny * 2;
if (nz > 1)
- nz = nz * 2;
+ nz = nz * 2;
}
}
}
diff --git a/DeconvolutionLab2/src/wavelets/haar/HaarWavelets.java b/DeconvolutionLab2/src/wavelets/haar/HaarWavelets.java
index 62c5232..8a43a4e 100644
--- a/DeconvolutionLab2/src/wavelets/haar/HaarWavelets.java
+++ b/DeconvolutionLab2/src/wavelets/haar/HaarWavelets.java
@@ -1,156 +1,150 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package wavelets.haar;
import signal.RealSignal;
import wavelets.AbstractWavelets;
public class HaarWavelets extends AbstractWavelets {
private double q = Math.sqrt(2);
public HaarWavelets(int scales) {
super(scales);
}
@Override
public void setScale(int scale) {
this.scales = scale;
}
@Override
public String getName() {
return "Haar";
}
@Override
public String getDocumentation() {
return "Haar Wavelets";
}
@Override
- public RealSignal analysis1(RealSignal in) {
- String name = "w(" + in.name + ")";
+ public void analysis1(RealSignal in, RealSignal out) {
int nx = in.nx;
int ny = in.ny;
int nz = in.nz;
- RealSignal out = new RealSignal(name, nx, ny, nz);
float ux[] = new float[nx];
float vx[] = new float[nx];
for (int z = 0; z < nz; z++)
for (int y = 0; y < ny; y++) {
ux = in.getX(y, z);
split(ux, vx);
out.setX(y, z, vx);
}
float uy[] = new float[ny];
float vy[] = new float[ny];
for (int z = 0; z < nz; z++)
for (int x = 0; x < nx; x++) {
uy = out.getY(x, z);
split(uy, vy);
out.setY(x, z, vy);
}
if (nz > 1) {
float uz[] = new float[nz];
float vz[] = new float[nz];
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++) {
uz = out.getZ(x, y);
split(uz, vz);
out.setZ(x, y, vz);
}
}
- return out;
}
@Override
- public RealSignal synthesis1(RealSignal in) {
- String name = "iw(" + in.name + ")";
+ public void synthesis1(RealSignal in, RealSignal out) {
int nx = in.nx;
int ny = in.ny;
int nz = in.nz;
- RealSignal out = new RealSignal(name, nx, ny, nz);
float ux[] = new float[nx];
float vx[] = new float[nx];
for (int z = 0; z < nz; z++)
for (int y = 0; y < ny; y++) {
ux = in.getX(y, z);
merge(ux, vx);
out.setX(y, z, vx);
}
float uy[] = new float[ny];
float vy[] = new float[ny];
for (int z = 0; z < nz; z++)
for (int x = 0; x < nx; x++) {
uy = out.getY(x, z);
merge(uy, vy);
out.setY(x, z, vy);
}
if (nz > 1) {
float uz[] = new float[nz];
float vz[] = new float[nz];
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++) {
uz = out.getZ(x, y);
merge(uz, vz);
out.setZ(x, y, vz);
}
}
- return out;
}
private void split(float vin[], float vout[]) {
int n2 = vin.length / 2;
int j;
for (int i = 0; i < n2; i++) {
j = 2 * i;
vout[i] = (float) ((vin[j] + vin[j + 1]) / q);
vout[i + n2] = (float) ((vin[j] - vin[j + 1]) / q);
}
}
private void merge(float vin[], float vout[]) {
int n2 = vin.length / 2;
for (int i = 0; i < n2; i++) {
vout[2 * i] = (float) ((vin[i] + vin[i + n2]) / q);
vout[2 * i + 1] = (float) ((vin[i] - vin[i + n2]) / q);
}
}
}
diff --git a/DeconvolutionLab2/src/wavelets/spline/Spline1Wavelets.java b/DeconvolutionLab2/src/wavelets/spline/Spline1Wavelets.java
index 8954197..e8a8915 100644
--- a/DeconvolutionLab2/src/wavelets/spline/Spline1Wavelets.java
+++ b/DeconvolutionLab2/src/wavelets/spline/Spline1Wavelets.java
@@ -1,71 +1,71 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package wavelets.spline;
import signal.RealSignal;
import wavelets.AbstractWavelets;
public class Spline1Wavelets extends AbstractWavelets {
private SplineWaveletsTool tool;
public Spline1Wavelets(int scale) {
super(scale);
this.tool = new SplineWaveletsTool(scale, 1);
}
@Override
public void setScale(int scale) {
this.scales = scale;
this.tool = new SplineWaveletsTool(scale, 1);
}
@Override
public String getName() {
return "Spline1";
}
@Override
public String getDocumentation() {
return "Spline Wavelets (order 1)";
}
@Override
- public RealSignal analysis1(RealSignal in) {
- return tool.analysis1(in);
+ public void analysis1(RealSignal in, RealSignal out) {
+ tool.analysis1(in, out);
}
@Override
- public RealSignal synthesis1(RealSignal in) {
- return tool.synthesis1(in);
+ public void synthesis1(RealSignal in, RealSignal out) {
+ tool.synthesis1(in, out);
}
}
diff --git a/DeconvolutionLab2/src/wavelets/spline/Spline3Wavelets.java b/DeconvolutionLab2/src/wavelets/spline/Spline3Wavelets.java
index e607009..86d73e0 100644
--- a/DeconvolutionLab2/src/wavelets/spline/Spline3Wavelets.java
+++ b/DeconvolutionLab2/src/wavelets/spline/Spline3Wavelets.java
@@ -1,71 +1,71 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package wavelets.spline;
import signal.RealSignal;
import wavelets.AbstractWavelets;
public class Spline3Wavelets extends AbstractWavelets {
private SplineWaveletsTool tool;
public Spline3Wavelets(int scale) {
super(scale);
this.tool = new SplineWaveletsTool(scale, 3);
}
@Override
public void setScale(int scale) {
this.scales = scale;
this.tool = new SplineWaveletsTool(scale, 1);
}
@Override
public String getName() {
return "Spline3";
}
@Override
public String getDocumentation() {
return "Spline Wavelets (order 3)";
}
@Override
- public RealSignal analysis1(RealSignal in) {
- return tool.analysis1(in);
+ public void analysis1(RealSignal in, RealSignal out) {
+ tool.analysis1(in, out);
}
@Override
- public RealSignal synthesis1(RealSignal in) {
- return tool.synthesis1(in);
+ public void synthesis1(RealSignal in, RealSignal out) {
+ tool.synthesis1(in, out);
}
}
diff --git a/DeconvolutionLab2/src/wavelets/spline/Spline5Wavelets.java b/DeconvolutionLab2/src/wavelets/spline/Spline5Wavelets.java
index 45d22f7..15520cb 100644
--- a/DeconvolutionLab2/src/wavelets/spline/Spline5Wavelets.java
+++ b/DeconvolutionLab2/src/wavelets/spline/Spline5Wavelets.java
@@ -1,71 +1,71 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package wavelets.spline;
import signal.RealSignal;
import wavelets.AbstractWavelets;
public class Spline5Wavelets extends AbstractWavelets {
private SplineWaveletsTool tool;
public Spline5Wavelets(int scale) {
super(scale);
this.tool = new SplineWaveletsTool(scale, 5);
}
@Override
public void setScale(int scale) {
this.scales = scale;
this.tool = new SplineWaveletsTool(scale, 1);
}
@Override
public String getName() {
return "Spline5";
}
@Override
public String getDocumentation() {
return "Spline Wavelets (order 5)";
}
@Override
- public RealSignal analysis1(RealSignal in) {
- return tool.analysis1(in);
+ public void analysis1(RealSignal in, RealSignal out) {
+ tool.analysis1(in, out);
}
@Override
- public RealSignal synthesis1(RealSignal in) {
- return tool.synthesis1(in);
+ public void synthesis1(RealSignal in, RealSignal out) {
+ tool.synthesis1(in, out);
}
}
diff --git a/DeconvolutionLab2/src/wavelets/spline/SplineWaveletsTool.java b/DeconvolutionLab2/src/wavelets/spline/SplineWaveletsTool.java
index b574ba1..8929bbd 100644
--- a/DeconvolutionLab2/src/wavelets/spline/SplineWaveletsTool.java
+++ b/DeconvolutionLab2/src/wavelets/spline/SplineWaveletsTool.java
@@ -1,265 +1,255 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package wavelets.spline;
import signal.RealSignal;
public class SplineWaveletsTool {
private SplineFilter filters;
public SplineWaveletsTool(int scale, int order) {
this.filters = new SplineFilter(order);
}
- public RealSignal analysis1(RealSignal in) {
- String name = "w(" + in.name + ")";
-
+ public void analysis1(RealSignal in, RealSignal out) {
int nx = in.nx;
int ny = in.ny;
int nz = in.nz;
- RealSignal out = new RealSignal(name, nx, ny, nz);
-
float ux[] = new float[nx];
float vx[] = new float[nx];
for (int z = 0; z < nz; z++)
for (int y = 0; y < ny; y++) {
ux = in.getX(y, z);
splitMirror(ux, vx, filters.h, filters.g);
out.setX(y, z, vx);
}
float uy[] = new float[ny];
float vy[] = new float[ny];
for (int z = 0; z < nz; z++)
for (int x = 0; x < nx; x++) {
uy = out.getY(x, z);
splitMirror(uy, vy, filters.h, filters.g);
out.setY(x, z, vy);
}
if (nz > 1) {
float uz[] = new float[nz];
float vz[] = new float[nz];
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++) {
uz = out.getZ(x, y);
splitMirror(uz, vz, filters.h, filters.g);
out.setZ(x, y, vz);
}
}
-
- return out;
}
- public RealSignal synthesis1(RealSignal in) {
- String name = "iw(" + in.name + ")";
+ public void synthesis1(RealSignal in, RealSignal out) {
int nx = in.nx;
int ny = in.ny;
int nz = in.nz;
- RealSignal out = new RealSignal(name, nx, ny, nz);
-
float ux[] = new float[nx];
float vx[] = new float[nx];
for (int z = 0; z < nz; z++)
for (int y = 0; y < ny; y++) {
ux = in.getX(y, z);
mergeMirror(ux, vx, filters.h, filters.g);
out.setX(y, z, vx);
}
float uy[] = new float[ny];
float vy[] = new float[ny];
for (int z = 0; z < nz; z++)
for (int x = 0; x < nx; x++) {
uy = out.getY(x, z);
mergeMirror(uy, vy, filters.h, filters.g);
out.setY(x, z, vy);
}
if (nz > 1) {
float uz[] = new float[nz];
float vz[] = new float[nz];
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++) {
uz = out.getZ(x, y);
mergeMirror(uz, vz, filters.h, filters.g);
out.setZ(x, y, vz);
}
}
- return out;
}
private void splitMirror(float vin[], float vout[], double h[], double g[]) {
int n = vin.length;
int n2 = n / 2;
int nh = h.length;
int ng = g.length;
double pix;
int j, k, j1, j2;
int period = 2 * n - 2; // period for mirror boundary conditions
for (int i = 0; i < n2; i++) {
j = i * 2;
pix = vin[j] * h[0];
for (k = 1; k < nh; k++) { // Low pass part
j1 = j - k;
if (j1 < 0) { // Mirror conditions
while (j1 < 0)
j1 += period; // Periodize
if (j1 >= n)
j1 = period - j1; // Symmetrize
}
j2 = j + k;
if (j2 >= n) { // Mirror conditions
while (j2 >= n)
j2 -= period; // Periodize
if (j2 < 0)
j2 = -j2; // Symmetrize
}
pix = pix + h[k] * (vin[j1] + vin[j2]);
}
vout[i] = (float) pix;
j = j + 1;
pix = vin[j] * g[0]; // High pass part
for (k = 1; k < ng; k++) {
j1 = j - k;
if (j1 < 0) { // Mirror conditions
while (j1 < 0)
j1 += period; // Periodize
if (j1 >= n)
j1 = period - j1; // Symmetrize
}
j2 = j + k;
if (j2 >= n) { // Mirror conditions
while (j2 >= n)
j2 -= period; // Periodize
if (j2 < 0)
j2 = -j2; // Symmetrize
}
pix = pix + g[k] * (vin[j1] + vin[j2]);
}
vout[i + n2] = (float) pix;
}
}
static private void mergeMirror(float vin[], float vout[], double h[], double g[]) {
int n = vin.length;
int n2 = n / 2;
int nh = h.length;
int ng = g.length;
double pix1, pix2;
int j, k, kk, i1, i2;
int k01 = (nh / 2) * 2 - 1;
int k02 = (ng / 2) * 2 - 1;
int period = 2 * n2 - 1; // period for mirror boundary conditions
for (int i = 0; i < n2; i++) {
j = 2 * i;
pix1 = h[0] * vin[i];
for (k = 2; k < nh; k += 2) {
i1 = i - (k / 2);
if (i1 < 0) {
i1 = (-i1) % period;
if (i1 >= n2)
i1 = period - i1;
}
i2 = i + (k / 2);
if (i2 > n2 - 1) {
i2 = i2 % period;
if (i2 >= n2)
i2 = period - i2;
}
pix1 = pix1 + h[k] * (vin[i1] + vin[i2]);
}
pix2 = 0.;
for (k = -k02; k < ng; k += 2) {
kk = Math.abs(k);
i1 = i + (k - 1) / 2;
if (i1 < 0) {
i1 = (-i1 - 1) % period;
if (i1 >= n2)
i1 = period - 1 - i1;
}
if (i1 >= n2) {
i1 = i1 % period;
if (i1 >= n2)
i1 = period - 1 - i1;
}
pix2 = pix2 + g[kk] * vin[i1 + n2];
}
vout[j] = (float) (pix1 + pix2);
j = j + 1;
pix1 = 0.;
for (k = -k01; k < nh; k += 2) {
kk = Math.abs(k);
i1 = i + (k + 1) / 2;
if (i1 < 0) {
i1 = (-i1) % period;
if (i1 >= n2)
i1 = period - i1;
}
if (i1 >= n2) {
i1 = (i1) % period;
if (i1 >= n2)
i1 = period - i1;
}
pix1 = pix1 + h[kk] * vin[i1];
}
pix2 = g[0] * vin[i + n2];
for (k = 2; k < ng; k += 2) {
i1 = i - (k / 2);
if (i1 < 0) {
i1 = (-i1 - 1) % period;
if (i1 >= n2)
i1 = period - 1 - i1;
}
i2 = i + (k / 2);
if (i2 > n2 - 1) {
i2 = i2 % period;
if (i2 >= n2)
i2 = period - 1 - i2;
}
pix2 = pix2 + g[k] * (vin[i1 + n2] + vin[i2 + n2]);
}
vout[j] = (float) (pix1 + pix2);
}
}
}

Event Timeline