Page MenuHomec4science

No OneTemporary

File Metadata

Created
Fri, Nov 22, 06:13
diff --git a/DeconvolutionLab2/src/course/DeconvolutionLab2_JavaCoding.java b/DeconvolutionLab2/src/course/DeconvolutionLab2_JavaCoding.java
index bdb1d9b..2a46496 100644
--- a/DeconvolutionLab2/src/course/DeconvolutionLab2_JavaCoding.java
+++ b/DeconvolutionLab2/src/course/DeconvolutionLab2_JavaCoding.java
@@ -1,78 +1,68 @@
/*
* 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.algorithm.Convolution;
+import deconvolution.algorithm.Simulation;
import deconvolutionlab.Lab;
import deconvolutionlab.monitor.Monitors;
import ij.plugin.PlugIn;
import signal.RealSignal;
public class DeconvolutionLab2_JavaCoding 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;
+ private String desktop = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + "Desktop" + File.separator;
public DeconvolutionLab2_JavaCoding() {
-
+ String path = desktop + "Deconvolution" + File.separator + "data" + File.separator + "bars" + File.separator;
Monitors monitors = new Monitors();
+ RealSignal image = Lab.openFile(monitors, path + "bars.tif");
+ RealSignal psf = Lab.openFile(monitors, path + "psf.tif");
- RealSignal image = Lab.openFile(filename);
-
- Convolution convolution = new Convolution();
-
-
- RealSignal a = convolution.run(monitors, image, psf, fftlib, pad, apo, norm, threaded);
-
- }
-
- 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";
+ Simulation convolution = new Simulation(100, 100, 10);
+ RealSignal a = convolution.run(image, psf);
+ Lab.showMIP(monitors, a, "a");
}
public static void main(String arg[]) {
new DeconvolutionLab2_JavaCoding();
}
@Override
public void run(String arg) {
new DeconvolutionLab2_JavaCoding();
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/Command.java b/DeconvolutionLab2/src/deconvolution/Command.java
index 04b0d54..fbf999e 100644
--- a/DeconvolutionLab2/src/deconvolution/Command.java
+++ b/DeconvolutionLab2/src/deconvolution/Command.java
@@ -1,457 +1,456 @@
/*
* 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 bilib.tools.NumFormat;
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 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 = 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.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 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 20a4e98..283126e 100644
--- a/DeconvolutionLab2/src/deconvolution/Deconvolution.java
+++ b/DeconvolutionLab2/src/deconvolution/Deconvolution.java
@@ -1,550 +1,553 @@
/*
* 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 bilib.tools.NumFormat;
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.AbstractFFTLibrary;
import signal.RealSignal;
import signal.SignalCollector;
import signal.apodization.Apodization;
import signal.padding.Padding;
public class Deconvolution implements Runnable {
public enum Finish {
DIE, ALIVE, KILL
};
public AbstractAlgorithm algo = null;
private String path;
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;
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>();
public RealSignal image;
public RealSignal psf;
private RealSignal deconvolvedImage;
private Finish finish = Finish.DIE;
private DeconvolutionDialog dialog;
private TableStats tableStats;
public Deconvolution(String name, String command) {
this.name = name;
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;
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();
+ name = algo.getShortnames()[0];
live = false;
}
/**
* 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;
runDeconvolve();
return deconvolvedImage;
}
public RealSignal deconvolve() {
this.image = null;
this.psf = null;
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);
Lab.setVisible(tableMonitor.getPanel(), "Monitor of " + name, 10, 10);
}
if ((flagMonitor & 1) == 1)
monitors.add(new ConsoleMonitor());
if ((flagStats & 1) == 1) {
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() {
monitors = new Monitors();
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()));
Lab.setVisible(dialog, false);
}
@Override
public void run() {
double chrono = System.nanoTime();
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 (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());
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);
+ algo.setFFT(fft);
+ algo.setMonitors(monitors);
+
+ deconvolvedImage = algo.run(image, psf, pad, apo, norm);
live = false;
for (DeconvolutionListener listener : listeners)
listener.finish();
report.add("End", NumFormat.time(System.nanoTime() - chrono));
if (flagDisplay)
- Lab.show(monitors, deconvolvedImage, "Result of " + algo.getShortname());
+ Lab.show(monitors, deconvolvedImage, "Result of " + algo.getShortnames()[0]);
if (finish == Finish.KILL) {
System.out.println("End");
System.exit(0);
}
if (finish == Finish.DIE)
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", fft == null ? "null" : fft.getLibraryName());
}
features.add("Path", path);
String monitor = "";
if (flagMonitor == 0)
monitor = "no ";
if (flagMonitor == 1)
monitor = "console (" + verbose.name().toLowerCase() + ")";
if (flagMonitor == 2)
monitor = "table (" + verbose.name().toLowerCase() + ")";
if (flagMonitor == 3)
monitor = "console table (" + verbose.name().toLowerCase() + ")";
String stats = "";
if (flagStats == 0)
stats = "no ";
if (flagStats == 1)
stats = "show ";
if (flagStats == 2)
stats = "save ";
if (flagStats == 3)
stats = "show save";
String running = "";
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 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", 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 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;
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;
String arg = token.option.trim();
String cmd = token.parameters.substring(arg.length(), token.parameters.length()).trim();
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/algorithm/AbstractAlgorithm.java b/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithm.java
index becc3da..bdfa307 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithm.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithm.java
@@ -1,240 +1,268 @@
/*
* 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 bilib.tools.NumFormat;
import deconvolutionlab.monitor.Monitors;
import fft.AbstractFFT;
import fft.AbstractFFTLibrary;
import fft.FFT;
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;
-
+ /** y is the input signal of the deconvolution. */
+ protected RealSignal y;
+
+ /** h is the PSF signal for the deconvolution. */
+ protected RealSignal h;
+
+ /**
+ * 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;
+
/** This is the FFT used. */
- protected AbstractFFT fft = null;
+ protected AbstractFFT fft ;
- /** Shortname of the algorithm given by the user, useful in particular to deal with the synonym. */
- protected String shortname = "I";
+ protected Monitors monitors;
+ protected AbstractFFTLibrary fftlib;
+ protected boolean threaded;
/** Optimized implementation in term of memory footprint */
- protected boolean optimizedMemoryFootprint = true;
+ protected boolean optimizedMemoryFootprint;
public AbstractAlgorithm() {
this.controller = new Controller();
- }
-
- public void setShortname(String shortname) {
- this.shortname = shortname;
- }
-
- public String getShortname() {
- return shortname;
+ monitors = Monitors.createDefaultMonitor();
+ fftlib = FFT.getFastestFFT();
+ optimizedMemoryFootprint = true;
+ threaded = true;
}
public void setOptimizedMemoryFootprint(boolean optimizedMemoryFootprint) {
this.optimizedMemoryFootprint = optimizedMemoryFootprint;
}
-
+
public abstract String getName();
+ public abstract String[] getShortnames();
+
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) {
+ public RealSignal run(RealSignal image, RealSignal psf) {
+ return run(image, psf, new Padding(), new Apodization(), 1);
+ }
+
+ public RealSignal run(RealSignal image, RealSignal psf, Padding pad, Apodization apo) {
+ return run(image, psf, pad, apo, 1);
+ }
+
+ public RealSignal run(RealSignal image, RealSignal psf, Padding pad, Apodization apo, double norm) {
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.pad(monitors, image);
y.setName("y");
apo.apodize(monitors, y);
monitors.log("Input: " + y.dimAsString());
-
+
h = psf.changeSizeAs(y);
h.setName("h");
- h.normalize(norm);
+ 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 + ")");
+ monitors.log(getShortnames()[0] + " is starting (" + iterations + ")");
controller.setMonitors(monitors);
controller.start(y);
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");
+ monitors.log(getShortnames()[0] + " data ready");
double params[] = getParameters();
if (params != null) {
if (params.length > 0) {
String s = " ";
for (double param : params)
s += "" + param + " ";
- monitors.log(getShortname() + s);
+ monitors.log(getShortnames()[0] + 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 Monitors getMonitors() {
+ return monitors;
+ }
+
+ public void setMonitors(Monitors monitors) {
+ this.monitors = monitors;
+ }
+
public AbstractFFT getFFT() {
return fft;
}
public void setFFT(AbstractFFT fft) {
this.fft = fft;
}
+ public void setFFT(AbstractFFTLibrary fftlib) {
+ this.fftlib = fftlib;
+ }
+
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)
+ 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/AbstractAlgorithmPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithmPanel.java
index 491076f..15eafef 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithmPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithmPanel.java
@@ -1,58 +1,58 @@
/*
* 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;
public abstract class AbstractAlgorithmPanel {
public abstract JPanel getPanelParameters();
public abstract String getCommand();
public abstract String getName();
- public abstract String[] getShortname();
+ public abstract String[] getShortnames();
public abstract String getDocumentation();
public boolean isNamed(String name) {
- for(String sn : getShortname()) {
+ for(String sn : getShortnames()) {
if (name.equals(sn.toLowerCase()))
return true;
if (name.equals(getName().toLowerCase()))
return true;
}
return false;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java b/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
index 9ec9346..ff39c53 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
@@ -1,158 +1,156 @@
/*
* 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();
}
/**
* 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 = 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(shortname);
return algo;
}
/**
* 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())
+ for(String sn : panel.getShortnames())
if (sn.equals(shortname.trim()))
return panel;
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())
+ for(String sn : algo.getShortnames())
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/Convolution.java b/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.java
index 0970991..b4e49cf 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.java
@@ -1,118 +1,122 @@
/*
* 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]";
+ return "Convolution Noiseless";
+ }
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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 4a93291..0679d91 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 bilib.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"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
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 657f0c0..2947d54 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/FISTA.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/FISTA.java
@@ -1,183 +1,188 @@
/*
* 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 String[] getShortnames() {
+ return new String[] {"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/FISTAPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/FISTAPanel.java
index a96e210..a94a846 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/FISTAPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/FISTAPanel.java
@@ -1,167 +1,167 @@
/*
* 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.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import bilib.component.GridPanel;
import bilib.component.SpinnerRangeDouble;
import bilib.component.SpinnerRangeInteger;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolution.RegularizationPanel;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
import wavelets.AbstractWavelets;
import wavelets.Wavelets;
public class FISTAPanel extends AbstractAlgorithmPanel implements KeyListener, ActionListener, ChangeListener {
private SpinnerRangeInteger spnIter = new SpinnerRangeInteger(10, 1, 99999, 1, "###");
private SpinnerRangeDouble spnStep = new SpinnerRangeDouble(1, 0, 2, 0.1, "#.#");
private RegularizationPanel reg;
private JComboBox<String> cmbWav = new JComboBox<String>(Wavelets.getWaveletsAsArray());
private JComboBox<String> cmbScale = new JComboBox<String>(new String[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12" });
private FISTA algo = new FISTA(10, 1, 0.1, "Haar", 3);
@Override
public JPanel getPanelParameters() {
AbstractWavelets wavdef = Wavelets.getDefaultWavelets();
double[] params = algo.getDefaultParameters();
reg = new RegularizationPanel(params[2]);
spnIter.setPreferredSize(Constants.dimParameters);
spnStep.setPreferredSize(Constants.dimParameters);
cmbWav.setPreferredSize(Constants.dimParameters);
cmbScale.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, 5, 1, reg);
pn.place(5, 0, "<html><span \"nowrap\"><b>Wavelets</b></span></html>");
pn.place(5, 2, cmbWav);
pn.place(5, 3, "<html>Scale</html>");
pn.place(5, 4, cmbScale);
- Config.register("Algorithm." + algo.getShortname(), "iterations", spnIter, params[0]);
- Config.register("Algorithm." + algo.getShortname(), "step", spnStep, params[1]);
- Config.register("Algorithm." + algo.getShortname(), "wavelets", cmbWav, wavdef.getName());
- Config.register("Algorithm." + algo.getShortname(), "scale", cmbScale, wavdef.getScales());
- Config.register("Algorithm." + algo.getShortname(), "reg", reg.getText(), "0.1");
+ Config.register("Algorithm." + algo.getShortnames()[0], "iterations", spnIter, params[0]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "step", spnStep, params[1]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "wavelets", cmbWav, wavdef.getName());
+ Config.register("Algorithm." + algo.getShortnames()[0], "scale", cmbScale, wavdef.getScales());
+ Config.register("Algorithm." + algo.getShortnames()[0], "reg", reg.getText(), "0.1");
reg.getText().addKeyListener(this);
reg.getSlider().addChangeListener(this);
spnIter.addChangeListener(this);
spnStep.addChangeListener(this);
cmbWav.addActionListener(this);
cmbScale.addActionListener(this);
return pn;
}
@Override
public String getCommand() {
int iter = spnIter.get();
double gamma = spnStep.get();
double lambda = reg.getValue();
String waveletsName = (String) cmbWav.getSelectedItem();
int scale = Integer.parseInt((String) cmbScale.getSelectedItem());
return iter + " " + NumFormat.nice(gamma) + " " + NumFormat.nice(lambda) + " " + waveletsName + " " + scale;
}
@Override
public void actionPerformed(ActionEvent e) {
Command.command();
}
@Override
public void stateChanged(ChangeEvent e) {
reg.getText().removeKeyListener(this);
reg.updateFromSlider();
Command.command();
reg.getText().addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
reg.getSlider().removeChangeListener(this);
reg.updateFromText();
Command.command();
reg.getSlider().addChangeListener(this);
}
@Override
public String getName() {
return algo.getName();
}
@Override
- public String[] getShortname() {
- return new String[] {"FISTA"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
s += "<h2>Shortname: FISTA</h2>";
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></p>";
s += "<h3>Reference: Beck and Teboulle, SIAM <b>2</b> 2009</h3>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java b/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java
index cec5094..1f051ab 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java
@@ -1,148 +1,153 @@
/*
* 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]";
+ return "Iterative Contraint Tikhonov-Miller";
+ }
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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/ICTMPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/ICTMPanel.java
index 8952d5e..01c1f54 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ICTMPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ICTMPanel.java
@@ -1,144 +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.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import bilib.component.GridPanel;
import bilib.component.SpinnerRangeDouble;
import bilib.component.SpinnerRangeInteger;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolution.RegularizationPanel;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
public class ICTMPanel extends AbstractAlgorithmPanel implements KeyListener, ActionListener, ChangeListener {
private SpinnerRangeInteger spnIter = new SpinnerRangeInteger(10, 1, 99999, 1, "###");
private SpinnerRangeDouble spnStep = new SpinnerRangeDouble(1, 0, 2, 0.1, "#.#");
private RegularizationPanel reg;
private ICTM algo = new ICTM(10, 0.1, 1);
@Override
public JPanel getPanelParameters() {
double[] params = algo.getDefaultParameters();
spnIter.setPreferredSize(Constants.dimParameters);
spnStep.setPreferredSize(Constants.dimParameters);
reg = new RegularizationPanel(params[2]);
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, 5, 1, reg);
- Config.register("Algorithm." + algo.getShortname(), "iterations", spnIter, params[0]);
- Config.register("Algorithm." + algo.getShortname(), "step", spnStep, params[1]);
- Config.register("Algorithm." + algo.getShortname(), "reg", reg.getText(), "0.1");
+ Config.register("Algorithm." + algo.getShortnames()[0], "iterations", spnIter, params[0]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "step", spnStep, params[1]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "reg", reg.getText(), "0.1");
reg.getText().addKeyListener(this);
reg.getSlider().addChangeListener(this);
spnIter.addChangeListener(this);
spnStep.addChangeListener(this);
return pn;
}
@Override
public String getCommand() {
double gamma = spnStep.get();
double lambda = reg.getValue();
return spnIter.get() + " " + NumFormat.nice(gamma) + " " + NumFormat.nice(lambda);
}
@Override
public void actionPerformed(ActionEvent e) {
Command.command();
}
@Override
public void stateChanged(ChangeEvent e) {
reg.getText().removeKeyListener(this);
reg.updateFromSlider();
Command.command();
reg.getText().addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
reg.getSlider().removeChangeListener(this);
reg.updateFromText();
Command.command();
reg.getSlider().addChangeListener(this);
}
@Override
public String getName() {
return algo.getName();
}
@Override
- public String[] getShortname() {
- return new String[] {"ICTM"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
-
@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>";
+ String shortname = "<p>Shortname: ";
+ for(String name : getShortnames())
+ shortname += name + " ";
+ s += shortname + "</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java b/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java
index d37c909..12217dc 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java
@@ -1,174 +1,180 @@
/*
* 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 String[] getShortnames() {
+ return new String[] {"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/ISTAPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/ISTAPanel.java
index 6d52d27..8b6d089 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ISTAPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ISTAPanel.java
@@ -1,165 +1,168 @@
/*
* 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.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import bilib.component.GridPanel;
import bilib.component.SpinnerRangeDouble;
import bilib.component.SpinnerRangeInteger;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolution.RegularizationPanel;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
import wavelets.AbstractWavelets;
import wavelets.Wavelets;
public class ISTAPanel extends AbstractAlgorithmPanel implements KeyListener, ActionListener, ChangeListener {
private SpinnerRangeInteger spnIter = new SpinnerRangeInteger(10, 1, 99999, 1);
private SpinnerRangeDouble spnStep = new SpinnerRangeDouble(1, 0, 2, 0.1);
private RegularizationPanel reg;
private JComboBox<String> cmbWav = new JComboBox<String>(Wavelets.getWaveletsAsArray());
private JComboBox<String> cmbScale = new JComboBox<String>(new String[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12" });
private ISTA algo = new ISTA(0, 1, 0.1, "Haar", 3);
@Override
public JPanel getPanelParameters() {
AbstractWavelets wavdef = Wavelets.getDefaultWavelets();
double[] params = algo.getDefaultParameters();
reg = new RegularizationPanel(params[2]);
spnIter.setPreferredSize(Constants.dimParameters);
spnStep.setPreferredSize(Constants.dimParameters);
cmbWav.setPreferredSize(Constants.dimParameters);
cmbScale.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, 5, 1, reg);
pn.place(5, 0, "<html><span \"nowrap\"><b>Wavelets</b></span></html>");
pn.place(5, 2, cmbWav);
pn.place(5, 3, "<html>Scale</html>");
pn.place(5, 4, cmbScale);
- Config.register("Algorithm." + algo.getShortname(), "iterations", spnIter, params[0]);
- Config.register("Algorithm." + algo.getShortname(), "step", spnStep, params[1]);
- Config.register("Algorithm." + algo.getShortname(), "wavelets", cmbWav, wavdef.getName());
- Config.register("Algorithm." + algo.getShortname(), "scale", cmbScale, wavdef.getScales());
- Config.register("Algorithm." + algo.getShortname(), "reg", reg.getText(), "0.1");
+ Config.register("Algorithm." + algo.getShortnames()[0], "iterations", spnIter, params[0]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "step", spnStep, params[1]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "wavelets", cmbWav, wavdef.getName());
+ Config.register("Algorithm." + algo.getShortnames()[0], "scale", cmbScale, wavdef.getScales());
+ Config.register("Algorithm." + algo.getShortnames()[0], "reg", reg.getText(), "0.1");
reg.getText().addKeyListener(this);
reg.getSlider().addChangeListener(this);
spnIter.addChangeListener(this);
spnStep.addChangeListener(this);
cmbWav.addActionListener(this);
cmbScale.addActionListener(this);
return pn;
}
@Override
public String getCommand() {
int iter = spnIter.get();
double gamma = spnStep.get();
double lambda = reg.getValue();
String waveletsName = (String) cmbWav.getSelectedItem();
int scale = Integer.parseInt((String) cmbScale.getSelectedItem());
return iter + " " + NumFormat.nice(gamma) + " " + NumFormat.nice(lambda) + " " + waveletsName + " " + scale;
}
@Override
public void actionPerformed(ActionEvent e) {
Command.command();
}
@Override
public void stateChanged(ChangeEvent e) {
reg.getText().removeKeyListener(this);
reg.updateFromSlider();
Command.command();
reg.getText().addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
reg.getSlider().removeChangeListener(this);
reg.updateFromText();
Command.command();
reg.getSlider().addChangeListener(this);
}
@Override
public String getName() {
return algo.getName();
}
@Override
- public String[] getShortname() {
- return new String[] {"ISTA"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@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>";
+ String shortname = "<p>Shortname: ";
+ for(String name : getShortnames())
+ shortname += name + " ";
+ s += shortname + "</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java b/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java
index 194d690..e2fc317 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java
@@ -1,109 +1,114 @@
/*
* 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 String[] getShortnames() {
+ return new String[] {"I"};
+ }
+
@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/IdentityPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/IdentityPanel.java
index e6836c8..dbcc779 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/IdentityPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/IdentityPanel.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 bilib.component.GridPanel;
public class IdentityPanel extends AbstractAlgorithmPanel {
private Identity algo = new Identity();
@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[] {"I", "ID"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
s += "<p>This algorithm does nothing. It returns the input image.</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java b/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java
index d353893..9592e83 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java
@@ -1,142 +1,147 @@
/*
* 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);
}
SignalCollector.free(A);
SignalCollector.free(G);
RealSignal x = fft.inverse(X);
SignalCollector.free(X);
return x;
}
@Override
public String getName() {
- return "Landweber [LW | LLS]";
+ return "Landweber";
+ }
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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/LandweberPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPanel.java
index 865687a..50bf183 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPanel.java
@@ -1,109 +1,112 @@
/*
* 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 bilib.component.GridPanel;
import bilib.component.SpinnerRangeDouble;
import bilib.component.SpinnerRangeInteger;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
public class LandweberPanel extends AbstractAlgorithmPanel implements ChangeListener {
private SpinnerRangeInteger spnIter = new SpinnerRangeInteger(10, 1, 99999, 1);
private SpinnerRangeDouble spnStep = new SpinnerRangeDouble(1, 0, 2, 0.1);
private Landweber algo = new Landweber(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]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "iterations", spnIter, params[0]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "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[] {"LW", "LLS"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@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>";
+ String shortname = "<p>Shortname: ";
+ for(String name : getShortnames())
+ shortname += name + " ";
+ s += shortname + "</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
index 34cafe1..1110ba6 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
@@ -1,144 +1,149 @@
/*
* 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+]";
+ return "Non-Negative Least-Square";
+ }
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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 8ca1655..49c6d3c 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java
@@ -1,109 +1,112 @@
/*
* 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 bilib.component.GridPanel;
import bilib.component.SpinnerRangeDouble;
import bilib.component.SpinnerRangeInteger;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
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]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "iterations", spnIter, params[0]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "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[] {"NLLS", "LW+"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@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>";
+ String shortname = "<p>Shortname: ";
+ for(String name : getShortnames())
+ shortname += name + " ";
+ s += shortname + "</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java b/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java
index f2bbf6d..53314be 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java
@@ -1,118 +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 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]";
+ return "Naive Inverse Filter";
+ }
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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/NaiveInverseFilterPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilterPanel.java
index 7fa81fc..d79e65f 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilterPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilterPanel.java
@@ -1,75 +1,75 @@
/*
* 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 bilib.component.GridPanel;
public class NaiveInverseFilterPanel extends AbstractAlgorithmPanel {
private NaiveInverseFilter algo = new NaiveInverseFilter();
@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[] {"NIF", "IF"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
s += "<h3>Shortname: NIF or IF</p>";
s += "<p>This is the classical inverse filter.</p>";
s += "<p>This algorithm only performs a stabilized division in the Fourier domain.</p>";
s += "<p>The stabilization is controlled by the machine epsilon parameter &Epsilon; set by default at 1E-6.</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java b/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java
index f89e80f..bf806d6 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java
@@ -1,118 +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 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 String[] getShortnames() {
+ return new String[] {"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/NonStabilizedDivisionPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivisionPanel.java
index 39ed17a..e3484bf 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivisionPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivisionPanel.java
@@ -1,76 +1,79 @@
/*
* 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 bilib.component.GridPanel;
public class NonStabilizedDivisionPanel extends AbstractAlgorithmPanel {
private NonStabilizedDivision algo = new NonStabilizedDivision();
@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[] {"DIV"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@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>";
+ String shortname = "<p>Shortname: ";
+ for(String name : getShortnames())
+ shortname += name + " ";
+ s += shortname + "</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java b/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java
index d334dcd..a74440a 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java
@@ -1,185 +1,189 @@
/*
* 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]";
+ return "Regularized Inverse Filter";
+ }
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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/RegularizedInverseFilterPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilterPanel.java
index d1c3ec2..0de764e 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilterPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilterPanel.java
@@ -1,115 +1,115 @@
/*
* 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.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import bilib.component.GridPanel;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolution.RegularizationPanel;
import deconvolutionlab.Config;
public class RegularizedInverseFilterPanel extends AbstractAlgorithmPanel implements KeyListener, ChangeListener {
private RegularizationPanel reg;
private RegularizedInverseFilter algo = new RegularizedInverseFilter(0.1);
@Override
public JPanel getPanelParameters() {
double[] params = algo.getDefaultParameters();
reg = new RegularizationPanel(params[0]);
GridPanel pn = new GridPanel(false);
pn.place(0, 0, reg);
- Config.register("Algorithm." + algo.getShortname(), "reg", reg.getText(), "0.1");
+ Config.register("Algorithm." + algo.getShortnames()[0], "reg", reg.getText(), "0.1");
reg.getText().addKeyListener(this);
reg.getSlider().addChangeListener(this);
return pn;
}
@Override
public String getCommand() {
return NumFormat.nice(reg.getValue());
}
@Override
public void stateChanged(ChangeEvent e) {
reg.getText().removeKeyListener(this);
reg.updateFromSlider();
Command.command();
reg.getText().addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
reg.getSlider().removeChangeListener(this);
reg.updateFromText();
Command.command();
reg.getSlider().addChangeListener(this);
}
@Override
public String getName() {
return algo.getName();
}
@Override
- public String[] getShortname() {
- return new String[] {"RIF", "LRIF"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
s += "<h2>Shortname RIF or LRIF</h2>";
s += "<p>Laplacian Regularized Inverse Filter</p>";
s += "<p>This is a inverse filter with a Laplacian regularization that tends to have an effect on high frequency</p>";
s += "<p>It is very fast, non-iterative algorithm</p>";
s += "<p>The regularization blurs the noise and the image. It is controlled by &lambda;</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java
index 2c66b08..3d149e8 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java
@@ -1,136 +1,141 @@
/*
* 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]";
+ return "Richardson-Lucy";
+ }
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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 47d0a6c..dc2ce21 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyPanel.java
@@ -1,94 +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 bilib.component.GridPanel;
import bilib.component.SpinnerRangeInteger;
import deconvolution.Command;
import deconvolutionlab.Config;
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]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "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"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
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 0d7654d..479af1c 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTV.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTV.java
@@ -1,230 +1,235 @@
/*
* 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));
}
}
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]";
+ return "Richardson-Lucy Total Variation";
}
-
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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/RichardsonLucyTVPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTVPanel.java
index 11982b3..5fb9be6 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTVPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTVPanel.java
@@ -1,130 +1,130 @@
/*
* 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.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import bilib.component.GridPanel;
import bilib.component.SpinnerRangeInteger;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolution.RegularizationPanel;
import deconvolutionlab.Config;
public class RichardsonLucyTVPanel extends AbstractAlgorithmPanel implements KeyListener, ActionListener, ChangeListener {
private SpinnerRangeInteger spnIter = new SpinnerRangeInteger(10, 1, 99999, 1);
private RegularizationPanel reg;
private RichardsonLucyTV algo = new RichardsonLucyTV(10, 0.1);
@Override
public JPanel getPanelParameters() {
double[] params = algo.getDefaultParameters();
reg = new RegularizationPanel(params[1]);
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(2, 0, 3, 1, reg);
- Config.register("Algorithm." + algo.getShortname(), "reg", reg.getText(), "0.1");
+ Config.register("Algorithm." + algo.getShortnames()[0], "reg", reg.getText(), "0.1");
reg.getText().addKeyListener(this);
reg.getSlider().addChangeListener(this);
spnIter.addChangeListener(this);
return pn;
}
@Override
public String getCommand() {
double lambda = reg.getValue();
return spnIter.get() + " " + NumFormat.nice(lambda);
}
@Override
public void stateChanged(ChangeEvent e) {
reg.getText().removeKeyListener(this);
reg.updateFromSlider();
Command.command();
reg.getText().addKeyListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
Command.command();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
reg.getSlider().removeChangeListener(this);
reg.updateFromText();
Command.command();
reg.getSlider().addChangeListener(this);
}
@Override
public String getName() {
return algo.getName();
}
@Override
- public String[] getShortname() {
- return new String[] {"RLTV"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
s += "<h2> Shortname: RLTV</h2>";
s += "<p>This algorithm is a combinaison of the Richardson–Lucy algorithm with a regularization constraint based on Total Variation, which tends to reduce unstable oscillations while preserving object edges.</p>";
s += "<p>It is a iterative algorithm, relative slow to compute the Total Variation at every iteration.s</p>";
s += "<p>It has a weighted parameter &lamdba; to control the effect of the total variation.</p>";
s += "<p></p>";
- s += "<h3>Reference: Dey et al., Microscopy Research and Technics, 2006 " + getShortname() + "</p>";
+ s += "<h3>Reference: Dey et al., Microscopy Research and Technics, 2006.</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java b/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
index 4faaaf2..912e708 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
@@ -1,159 +1,165 @@
/*
* 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 bilib.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]";
+ return "Simulation with noise";
}
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"SIM", "SIMU"};
+ }
+
@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/SimulationPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/SimulationPanel.java
index d0bf53b..8f721c1 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/SimulationPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/SimulationPanel.java
@@ -1,114 +1,114 @@
/*
* 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.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.JTextField;
import bilib.component.GridPanel;
import deconvolution.Command;
import deconvolutionlab.Config;
public class SimulationPanel extends AbstractAlgorithmPanel implements KeyListener {
private JTextField txtMean;
private JTextField txtStdev;
private JTextField txtPoisson;
private Simulation algo = new Simulation(0, 0, 0);
@Override
public JPanel getPanelParameters() {
double[] params = algo.getDefaultParameters();
txtMean = new JTextField("" + params[0], 5);
txtStdev = new JTextField("" + params[1], 5);
txtPoisson = new JTextField("" + params[2], 5);
GridPanel pn = new GridPanel(false);
pn.place(1, 0, "<html>Gaussian (Mean)</html>");
pn.place(1, 2, txtMean);
pn.place(2, 0, "<html>Gaussian (Stdev)</html>");
pn.place(2, 2, txtStdev);
pn.place(3, 0, "<html>Poisson</html>");
pn.place(3, 2, txtPoisson);
txtMean.addKeyListener(this);
txtStdev.addKeyListener(this);
txtPoisson.addKeyListener(this);
- Config.register("Algorithm." + algo.getShortname(), "gaussian.mean", txtMean, params[0]);
- Config.register("Algorithm." + algo.getShortname(), "gaussian.stdev", txtStdev, params[1]);
- Config.register("Algorithm." + algo.getShortname(), "poisson", txtPoisson, params[2]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "gaussian.mean", txtMean, params[0]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "gaussian.stdev", txtStdev, params[1]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "poisson", txtPoisson, params[2]);
return pn;
}
@Override
public String getCommand() {
return txtMean.getText() + " " + txtStdev.getText() + " " + txtPoisson.getText();
}
@Override
public void keyTyped(KeyEvent e) {
Command.command();
}
@Override
public void keyPressed(KeyEvent e) {
Command.command();
}
@Override
public void keyReleased(KeyEvent e) {
Command.command();
}
@Override
public String getName() {
return algo.getName();
}
- @Override
- public String[] getShortname() {
- return new String[] {"SIM", "SIMU"};
- }
-
@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 and adds some noise.</p>";
s += "<p>The noise has a Gaussian distribution (mean, stdev) and a Poisson distribution (poisson).</p>";
return s;
}
+ @Override
+ public String[] getShortnames() {
+ return algo.getShortnames();
+ }
+
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/StarkParker.java b/DeconvolutionLab2/src/deconvolution/algorithm/StarkParker.java
index 5acfb8e..794d5c2 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/StarkParker.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/StarkParker.java
@@ -1,143 +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;
public class StarkParker extends AbstractAlgorithm implements Callable<RealSignal> {
private double gamma = 1.0;
public StarkParker(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(H);
SignalCollector.free(Y);
ComplexSignal X = G.duplicate();
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 "Bounded-Variable Least Squares [BVLS | SP]";
+ return "Bounded-Variable Least Squares";
+ }
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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/StarkParkerPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/StarkParkerPanel.java
index d36bd80..6009cc6 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/StarkParkerPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/StarkParkerPanel.java
@@ -1,110 +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 bilib.component.GridPanel;
import bilib.component.SpinnerRangeDouble;
import bilib.component.SpinnerRangeInteger;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
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 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]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "iterations", spnIter, params[0]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "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[] { "BVLS", "SP" };
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
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 a4dfc20..350c3e2 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMiller.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMiller.java
@@ -1,146 +1,151 @@
/*
* 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]";
+ return "Tikhonov-Miller";
+ }
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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/TikhonovMillerPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMillerPanel.java
index e41b095..8b5ef79 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMillerPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMillerPanel.java
@@ -1,142 +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.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import bilib.component.GridPanel;
import bilib.component.SpinnerRangeDouble;
import bilib.component.SpinnerRangeInteger;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolution.RegularizationPanel;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
public class TikhonovMillerPanel extends AbstractAlgorithmPanel implements KeyListener, ActionListener, ChangeListener {
private SpinnerRangeInteger spnIter = new SpinnerRangeInteger(10, 1, 99999, 1, "###");
private SpinnerRangeDouble spnStep = new SpinnerRangeDouble(1, 0, 2, 0.1, "#.#");
private RegularizationPanel reg;
private TikhonovMiller algo = new TikhonovMiller(10, 1, 0.1);
@Override
public JPanel getPanelParameters() {
double[] params = algo.getDefaultParameters();
spnIter.setPreferredSize(Constants.dimParameters);
spnStep.setPreferredSize(Constants.dimParameters);
reg = new RegularizationPanel(params[2]);
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, 5, 1, reg);
- Config.register("Algorithm." + algo.getShortname(), "iterations", spnIter, params[0]);
- Config.register("Algorithm." + algo.getShortname(), "step", spnStep, params[1]);
- Config.register("Algorithm." + algo.getShortname(), "reg", reg.getText(), "0.1");
+ Config.register("Algorithm." + algo.getShortnames()[0], "iterations", spnIter, params[0]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "step", spnStep, params[1]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "reg", reg.getText(), "0.1");
reg.getText().addKeyListener(this);
reg.getSlider().addChangeListener(this);
spnIter.addChangeListener(this);
spnStep.addChangeListener(this);
return pn;
}
@Override
public String getCommand() {
double gamma = spnStep.get();
double lambda = reg.getValue();
return spnIter.get() + " " + NumFormat.nice(gamma) + " " + NumFormat.nice(lambda);
}
@Override
public void actionPerformed(ActionEvent e) {
Command.command();
}
@Override
public void stateChanged(ChangeEvent e) {
reg.getText().removeKeyListener(this);
reg.updateFromSlider();
Command.command();
reg.getText().addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
reg.getSlider().removeChangeListener(this);
reg.updateFromText();
Command.command();
reg.getSlider().addChangeListener(this);
}
@Override
public String getName() {
return algo.getName();
}
@Override
- public String[] getShortname() {
- return new String[] {"TM"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@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>";
+ String shortname = "<p>Shortname: ";
+ for(String name : getShortnames())
+ shortname += name + " ";
+ s += shortname + "</p>";
+
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilter.java b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilter.java
index efce317..09cca2c 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilter.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilter.java
@@ -1,178 +1,184 @@
/*
* 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 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;
}
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;
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 + 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] = 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]";
+ return "Tikhonov Regularization";
}
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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/TikhonovRegularizationInverseFilterPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilterPanel.java
index 55feebe..1f1ac0a 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilterPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizationInverseFilterPanel.java
@@ -1,123 +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 deconvolution.algorithm;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import bilib.component.GridPanel;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolution.RegularizationPanel;
import deconvolutionlab.Config;
public class TikhonovRegularizationInverseFilterPanel extends AbstractAlgorithmPanel implements ActionListener, ChangeListener, KeyListener {
private RegularizationPanel reg;
private TikhonovRegularizationInverseFilter algo = new TikhonovRegularizationInverseFilter(0.1);
@Override
public JPanel getPanelParameters() {
double[] params = algo.getDefaultParameters();
reg = new RegularizationPanel(params[0]);
GridPanel pn = new GridPanel(false);
pn.place(0, 0, reg);
- Config.register("Algorithm." + algo.getShortname(), "reg", reg.getText(), "0.1");
+ Config.register("Algorithm." + algo.getShortnames()[0], "reg", reg.getText(), "0.1");
reg.getText().addKeyListener(this);
reg.getSlider().addChangeListener(this);
return pn;
}
@Override
public String getCommand() {
return NumFormat.nice(reg.getValue());
}
@Override
public void stateChanged(ChangeEvent e) {
reg.getText().removeKeyListener(this);
reg.updateFromSlider();
Command.command();
reg.getText().addKeyListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
Command.command();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
reg.getSlider().removeChangeListener(this);
reg.updateFromText();
Command.command();
reg.getSlider().addChangeListener(this);
}
@Override
public String getName() {
return algo.getName();
}
@Override
- public String[] getShortname() {
- return new String[] {"TRIF"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "</h1>";
s += "<h2>Shortname TRIF</h2>";
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>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java b/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java
index 0985224..11c33fa 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java
@@ -1,140 +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 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]";
+ return "Van Cittert";
+ }
+
+ @Override
+ public String[] getShortnames() {
+ return new String[] {"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/algorithm/VanCittertPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/VanCittertPanel.java
index 499ebb5..fd2551c 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/VanCittertPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/VanCittertPanel.java
@@ -1,106 +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 bilib.component.GridPanel;
import bilib.component.SpinnerRangeDouble;
import bilib.component.SpinnerRangeInteger;
import bilib.tools.NumFormat;
import deconvolution.Command;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
public class VanCittertPanel extends AbstractAlgorithmPanel implements ChangeListener {
private SpinnerRangeInteger spnIter = new SpinnerRangeInteger(10, 1, 99999, 1);
private SpinnerRangeDouble spnStep = new SpinnerRangeDouble(1, 0, 2, 0.1);
private VanCittert algo = new VanCittert(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);
- Config.register("Algorithm." + algo.getShortname(), "iterations", spnIter, params[0]);
- Config.register("Algorithm." + algo.getShortname(), "step", spnStep, params[1]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "iterations", spnIter, params[0]);
+ Config.register("Algorithm." + algo.getShortnames()[0], "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[] {"VC"};
+ public String[] getShortnames() {
+ return algo.getShortnames();
}
@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>";
+ String shortname = "<p>Shortname: ";
+ for(String name : getShortnames())
+ shortname += name + " ";
+ s += shortname + "</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/modules/AlgorithmDModule.java b/DeconvolutionLab2/src/deconvolution/modules/AlgorithmDModule.java
index 7983173..0415057 100644
--- a/DeconvolutionLab2/src/deconvolution/modules/AlgorithmDModule.java
+++ b/DeconvolutionLab2/src/deconvolution/modules/AlgorithmDModule.java
@@ -1,153 +1,153 @@
package deconvolution.modules;
import javax.swing.JSplitPane;
import bilib.component.HTMLPane;
import bilib.table.CustomizedTable;
import bilib.tools.NumFormat;
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 signal.ComplexSignal;
import signal.RealSignal;
import signal.SignalCollector;
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());
}
public void update() {
if (doc == null)
return;
if (table == null)
return;
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();
+ String name = algo.getShortnames()[0];
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/deconvolutionlab/Lab.java b/DeconvolutionLab2/src/deconvolutionlab/Lab.java
index e1ce296..dd28e3f 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/Lab.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/Lab.java
@@ -1,379 +1,378 @@
/*
* 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.regex.Pattern;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import bilib.tools.NumFormat;
import bilib.tools.WebBrowser;
import deconvolutionlab.Imaging.ContainerImage;
import deconvolutionlab.monitor.Monitors;
import fft.AbstractFFT;
import fft.AbstractFFTLibrary;
import fft.FFT;
import imagej.IJImager;
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 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/modules/AlgorithmModule.java b/DeconvolutionLab2/src/deconvolutionlab/modules/AlgorithmModule.java
index c61d1ba..0750aed 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/modules/AlgorithmModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/modules/AlgorithmModule.java
@@ -1,153 +1,153 @@
/*
* 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.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import bilib.component.HTMLPane;
import deconvolution.Command;
import deconvolution.Deconvolution;
import deconvolution.DeconvolutionDialog;
import deconvolution.algorithm.AbstractAlgorithmPanel;
import deconvolution.algorithm.Algorithm;
import deconvolutionlab.Config;
import deconvolutionlab.Lab;
public class AlgorithmModule extends AbstractModule implements ActionListener, ChangeListener {
private JComboBox<String> cmb;
private HTMLPane doc;
private JPanel cards;
public AlgorithmModule(boolean expanded) {
super("Algorithm", "-algorithm", "", "Check", expanded);
ArrayList<AbstractAlgorithmPanel> deconv = Algorithm.getAvailableAlgorithms();
for (AbstractAlgorithmPanel panel : deconv)
cmb.addItem(panel.getName());
cmb.addActionListener(this);
}
@Override
public String getCommand() {
String name = (String) cmb.getSelectedItem();
AbstractAlgorithmPanel algo = Algorithm.getPanel(name);
- String cmd = "-algorithm " + algo.getShortname()[0] + " " + algo.getCommand();
+ String cmd = "-algorithm " + algo.getShortnames()[0] + " " + algo.getCommand();
String synopsis = name;
setSynopsis(synopsis);
setCommand(cmd);
return cmd;
}
@Override
public JPanel buildExpandedPanel() {
cmb = new JComboBox<String>();
JPanel pnc = new JPanel();
pnc.add(cmb);
doc = new HTMLPane(100, 1000);
cards = new JPanel(new CardLayout());
ArrayList<AbstractAlgorithmPanel> panels = Algorithm.getAvailableAlgorithms();
for (AbstractAlgorithmPanel panel : panels) {
JScrollPane scroll = new JScrollPane(panel.getPanelParameters());
scroll.setBorder(BorderFactory.createEmptyBorder());
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
cards.add(panel.getName(), scroll);
}
cmb.setMaximumRowCount(panels.size());
JPanel control = new JPanel();
control.setLayout(new BoxLayout(control, BoxLayout.PAGE_AXIS));
Border b1 = BorderFactory.createEtchedBorder();
Border b2 = BorderFactory.createEmptyBorder(10, 10, 10, 10);
control.setBorder(BorderFactory.createCompoundBorder(b1, b2));
control.add(cmb);
control.add(cards);
doc.append("h1", "Documentation");
JPanel panel = new JPanel(new BorderLayout());
panel.add(control, BorderLayout.NORTH);
panel.add(doc.getPane(), BorderLayout.CENTER);
// cmb.addActionListener(this);
getAction2Button().setToolTipText("Human readable of the command line");
getAction2Button().addActionListener(this);
Config.register(getName(), "algorithm", cmb, Algorithm.getDefaultAlgorithm());
panel.setBorder(BorderFactory.createEtchedBorder());
return panel;
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (e.getSource() == cmb) {
doc.clear();
String name = (String) cmb.getSelectedItem();
AbstractAlgorithmPanel algo = Algorithm.getPanel(name);
doc.append(algo.getDocumentation());
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, name);
}
if (e.getSource() == getAction2Button()) {
Deconvolution deconvolution = new Deconvolution("Check Algorithm", Command.command());
DeconvolutionDialog d = new DeconvolutionDialog(DeconvolutionDialog.Module.ALGO, deconvolution, null, null);
Lab.setVisible(d, false);
}
setSynopsis((String) cmb.getSelectedItem());
setCommand(getCommand());
Command.command();
}
@Override
public void stateChanged(ChangeEvent e) {
setSynopsis((String) cmb.getSelectedItem());
setCommand(getCommand());
Command.command();
}
@Override
public void close() {
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/modules/LanguageModule.java b/DeconvolutionLab2/src/deconvolutionlab/modules/LanguageModule.java
index 21ebb6f..b6eca9e 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/modules/LanguageModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/modules/LanguageModule.java
@@ -1,251 +1,251 @@
/*
* 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 java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JTextField;
import bilib.component.HTMLPane;
import deconvolution.Command;
import deconvolution.Deconvolution;
import deconvolution.Token;
import deconvolution.algorithm.AbstractAlgorithm;
import deconvolutionlab.Config;
public class LanguageModule extends AbstractModule implements ActionListener {
private HTMLPane language;
private JComboBox<String> cmb;
private JComboBox<String> gui;
private JTextField txt;
public LanguageModule(boolean expanded) {
super("Language", "", "", "", expanded);
}
public String getJobName() {
if (txt != null)
return txt.getText();
return "";
}
@Override
public JPanel buildExpandedPanel() {
language = new HTMLPane("Monaco", 100, 100);
cmb = new JComboBox<String>(new String[] { "Command line", "ImageJ Macro", "Java", "Matlab" });
gui = new JComboBox<String>(new String[] { "Run (Headless)", "Launch (with control panel)" });
txt = new JTextField("Job", 8);
JPanel pn = new JPanel(new BorderLayout());
pn.add(cmb, BorderLayout.WEST);
pn.add(txt, BorderLayout.CENTER);
pn.add(gui, BorderLayout.EAST);
JPanel panel = new JPanel(new BorderLayout());
panel.add(pn, BorderLayout.NORTH);
panel.add(language.getPane(), BorderLayout.CENTER);
cmb.addActionListener(this);
gui.addActionListener(this);
Config.register(getName(), "language", cmb, cmb.getItemAt(0));
Config.register(getName(), "headless", gui, gui.getItemAt(0));
Config.register(getName(), "job", txt, "Job");
language.clear();
return panel;
}
@Override
public void expand() {
super.expand();
update();
}
public void update() {
if (cmb.getSelectedIndex() == 0) {
language.clear();
String run = gui.getSelectedIndex() == 0 ? " Run " : " Launch ";
language.append("p", "java -jar DeconvolutionLab_2.jar " + run + Command.command());
language.append("p", "");
language.append("p", "java -cp JTransforms.jar:DeconvolutionLab_2.jar DeconvolutionLab2 "+ run + Command.command());
}
else if (cmb.getSelectedIndex() == 1) {
language.clear();
language.append("p", imagej(gui.getSelectedIndex() == 0));
}
else if (cmb.getSelectedIndex() == 2) {
language.clear();
language.append("p", java(gui.getSelectedIndex() == 0));
}
else if (cmb.getSelectedIndex() == 3) {
language.clear();
language.append("p", matlab());
}
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (e.getSource() == cmb)
update();
if (e.getSource() == gui)
update();
}
@Override
public void close() {
}
@Override
public void setCommand(String command) {
update();
}
@Override
public String getCommand() {
return "";
}
private String matlab() {
String job = txt.getText();
String script = "";
String cmd = Command.command();
Deconvolution d = new Deconvolution("Matlab", cmd);
String options = Command.extractOptions(cmd);
AbstractAlgorithm algo = d.getAlgo();
if (algo == null)
return "ERROR";
- String s = algo.getShortname();
+ String s = algo.getShortnames()[0];
String param = algo.getParametersAsString();
script += p("% this function returns the deconvolved image as an 3D matrix");
script += p("% image is a 3D matrix containing the image");
script += p("% psf is a 3D matrix containing the PSF");
script += p("function result = " + job + "(image, psf)");
script += p1("% Install first DeconvolutionLab_2.jar into the java directory of Matlab");
script += p1("javaaddpath([matlabroot filesep 'java' filesep 'DeconvolutionLab_2.jar'])");
script += p1("% Run the deconvolution\n");
script += p1("result = DL2." + s + "(image, psf, " + param +" , '" + options +"');");
script += p("end");
return script;
}
private String imagej(boolean headless) {
String job = txt.getText();
String macro = p("// Job: " + job + " ");
macro += p("// Macro generated by DeconvolutionLab2 ");
macro += p("// " + new SimpleDateFormat("dd/MM/yy HH:m:s").format(new Date()) + " ");
String param = p("parameters = \"\" ");
ArrayList<Token> tokens = Command.parse(Command.command());
String image = "image = \" NOT DEFINED \" ";
String psf = "psf = \" NOT DEFINED \" ";
String algo = "algo = \" NOT DEFINED \" ";
for (Token token : tokens) {
if (token.keyword.equals("-image"))
image = p("image = \" -image " + token.parameters.trim() + "\" ");
else if (token.keyword.equals("-psf"))
psf = p("psf = \" -psf " + token.parameters.trim() + "\" ");
else if (token.keyword.equals("-algorithm"))
algo = p("algorithm = \" -algorithm " + token.parameters.trim() + "\" ");
else
param += p("parameters += \" " + token.keyword + " " + token.parameters.trim() + "\"");
}
String option = macro + image + psf + algo + param;
String cmd = "";
if (headless)
cmd = p("run(\"DeconvolutionLab2 Run\", image + psf + algorithm + parameters)");
else
cmd = p("run(\"DeconvolutionLab2 Launch\", image + psf + algorithm + parameters)");
return option + cmd;
}
private String java(boolean headless) {
String job = txt.getText();
String code = "";
code += p("import deconvolution.Deconvolution;");
code += p("import ij.plugin.PlugIn;");
code += p("");
code += p("public class DeconvolutionLab2_" + job + " implements PlugIn {");
code += p1("public DeconvolutionLab2_" + job + "() {");
String param = p2("String parameters = \"\";");
ArrayList<Token> tokens = Command.parse(Command.command());
String image = p2("String image = \" NOT DEFINED \";");
String psf = p2("String psf = \" NOT DEFINED \";");
String algo = p2("String algo = \" NOT DEFINED \";");
for (Token token : tokens) {
if (token.keyword.equals("-image"))
image = p2("String image = \" -image " + token.parameters.trim() + "\";");
else if (token.keyword.equals("-psf"))
psf = p2("String psf = \" -psf " + token.parameters.trim() + "\";");
else if (token.keyword.equals("-algorithm"))
algo = p2("String algorithm = \" -algorithm " + token.parameters.trim() + "\";");
else
param += p2("parameters += \" " + token.keyword + " " + token.parameters.trim() + "\";");
}
code += image + psf + algo + param;
code += p2("new Deconvolution(image + psf + algorithm + parameters)");
code += p1("}");
code += p1("");
code += p1("@Override");
code += p1("public void run(String arg0) {");
code += p2(" new DeconvolutionLab2_" + job + "();");
code += p1("}");
code += p("}");
return code;
}
private String p(String content) {
return "<p>" + content + "</p>";
}
private String p1(String content) {
return "<p style=\"padding-left:10px\">" + content + "</p>";
}
private String p2(String content) {
return "<p style=\"padding-left:20px\">" + content + "</p>";
}
}

Event Timeline