Page MenuHomec4science

No OneTemporary

File Metadata

Created
Sun, Feb 16, 14:16
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/DeconvolutionLab2/src/deconvolution/Command.java b/DeconvolutionLab2/src/deconvolution/Command.java
index ba2839f..44aa624 100644
--- a/DeconvolutionLab2/src/deconvolution/Command.java
+++ b/DeconvolutionLab2/src/deconvolution/Command.java
@@ -1,432 +1,432 @@
/*
* 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 ij.IJ;
import java.util.ArrayList;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import bilib.tools.Files;
import bilib.tools.NumFormat;
-import deconvolution.algorithm.AbstractAlgorithm;
import deconvolution.algorithm.Algorithm;
+import deconvolution.algorithm.AlgorithmList;
import deconvolution.algorithm.Controller;
import deconvolutionlab.Constants;
import deconvolutionlab.module.AbstractModule;
import deconvolutionlab.module.CommandModule;
import deconvolutionlab.monitor.ConsoleMonitor;
import deconvolutionlab.monitor.Monitors;
import deconvolutionlab.monitor.TableMonitor;
import deconvolutionlab.monitor.Verbose;
import deconvolutionlab.output.Output;
import deconvolutionlab.output.Output.View;
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 Controller decodeController(String command) {
Controller controller = new Controller();
ArrayList<Token> tokens = parse(command);
for (Token token : tokens) {
if (token.keyword.equalsIgnoreCase("-path")) {
if (token.parameters.trim().equals("current"))
controller.setPath(Files.getWorkingDirectory());
else if (token.parameters.trim().equals("home"))
controller.setPath(Files.getHomeDirectory());
else if (token.parameters.trim().equals("desktop"))
controller.setPath(Files.getDesktopDirectory());
else
controller.setPath(token.parameters);
}
if (token.keyword.equalsIgnoreCase("-monitor"))
controller.setMonitors(decodeMonitors(token.parameters));
if (token.keyword.equalsIgnoreCase("-verbose"))
controller.setVerbose(Verbose.getByName(token.parameters));
if (token.keyword.equalsIgnoreCase("-system"))
controller.setSystem(decodeBoolean(token.parameters));
if (token.keyword.equalsIgnoreCase("-multithreading"))
controller.setMultithreading(decodeBoolean(token.parameters));
if (token.keyword.equalsIgnoreCase("-display"))
controller.setDisplayFinal(decodeBoolean(token.parameters));
if (token.keyword.equalsIgnoreCase("-stats"))
controller.setStats(decodeStats(token));
if (token.keyword.equalsIgnoreCase("-constraint"))
controller.setConstraint(decodeConstraint(token));
if (token.keyword.equalsIgnoreCase("-time"))
controller.setTimeLimit(decodeTimeLimit(token));
if (token.keyword.equalsIgnoreCase("-residu"))
controller.setResiduMin(decodeResidu(token));
if (token.keyword.equalsIgnoreCase("-reference"))
controller.setReferenceName(token.parameters);
if (token.keyword.equalsIgnoreCase("-pad"))
controller.setPadding(decodePadding(token));
if (token.keyword.equalsIgnoreCase("-apo"))
controller.setApodization(decodeApodization(token));
if (token.keyword.equalsIgnoreCase("-norm"))
controller.setNormalizationPSF(decodeNormalization(token));
if (token.keyword.equalsIgnoreCase("-epsilon"))
Operations.epsilon = NumFormat.parseNumber(token.parameters, 1e-6);
if (token.keyword.equalsIgnoreCase("-fft"))
controller.setFFT(FFT.getLibraryByName(token.parameters).getDefaultFFT());
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)
controller.addOutput(out);
}
}
return controller;
}
- public static AbstractAlgorithm decodeAlgorithm(String command) {
- AbstractAlgorithm algo = Algorithm.getDefaultAlgorithm();
+ public static Algorithm decodeAlgorithm(String command) {
+ Algorithm algo = AlgorithmList.getDefaultAlgorithm();
ArrayList<Token> tokens = parse(command);
for (Token token : tokens) {
if (token.keyword.equalsIgnoreCase("-algorithm"))
algo = Command.decodeAlgorithm(token);
}
return algo;
}
/**
* 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) {
+ public static Algorithm decodeAlgorithm(Token token) {
String option = token.option;
- AbstractAlgorithm algo = Algorithm.createAlgorithm(option);
+ Algorithm algo = AlgorithmList.createAlgorithm(option);
double params[] = parseNumeric(token.parameters);
if (params != null) {
algo.setParameters(params);
}
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 double decodeNormalization(Token token) {
if (token.parameters.toLowerCase().endsWith("no"))
return 0;
else
return NumFormat.parseNumber(token.parameters, 1);
}
public static Stats decodeStats(Token token) {
String parts[] = token.parameters.toLowerCase().split(" ");
int m = 0;
for (String p : parts) {
if (p.startsWith("no") || p.equals("false") || p.equals("0"))
return new Stats(Stats.Mode.NO);
if (p.equals("1"))
return new Stats(Stats.Mode.SHOW);
if (p.equals("2"))
return new Stats(Stats.Mode.SAVE);
if (p.equals("3"))
return new Stats(Stats.Mode.SHOWSAVE);
if (p.equals("show"))
m += 1;
if (p.equals("save"))
m += 2;
}
if (m==1)
return new Stats(Stats.Mode.SHOW);
if (m==2)
return new Stats(Stats.Mode.SAVE);
if (m==3)
return new Stats(Stats.Mode.SHOWSAVE);
return new Stats(Stats.Mode.NO);
}
public static Constraint.Mode decodeConstraint(Token token) {
String p = token.parameters.toLowerCase();
if (p.startsWith("non"))
return Constraint.Mode.NONNEGATIVE;
if (p.startsWith("no"))
return Constraint.Mode.NO;
if (p.startsWith("clip"))
return Constraint.Mode.CLIPPED;
if (p.equals("0"))
return Constraint.Mode.NO;
return Constraint.Mode.NO;
}
public static double decodeResidu(Token token) {
if (token.parameters.toLowerCase().endsWith("no"))
return -1;
else
return NumFormat.parseNumber(token.parameters, 1);
}
public static double decodeTimeLimit(Token token) {
if (token.parameters.toLowerCase().endsWith("no"))
return -1;
else
return NumFormat.parseNumber(token.parameters, 1);
}
public static Padding decodePadding(Token token) {
AbstractPadding padXY = new NoPadding();
AbstractPadding padZ = new NoPadding();
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);
int extXY = 0;
if (ext.length > 0)
extXY = (int) Math.round(ext[0]);
int extZ = 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;
}
public static Monitors decodeMonitors(String cmd) {
String parts[] = cmd.toLowerCase().split(" ");
Monitors monitors = new Monitors();
for (String p : parts) {
if (p.equals("0") || p.startsWith("no"))
monitors.clear();
if (p.equals("1") || p.startsWith("console"))
monitors.add(new ConsoleMonitor());
if (p.equals("2"))
monitors.add(new TableMonitor(Constants.widthGUI, 240));
if (p.equals("3")) {
monitors.add(new ConsoleMonitor());
monitors.add(new TableMonitor(Constants.widthGUI, 240));
}
if (p.equals("console"))
monitors.add(new ConsoleMonitor());
if (p.equals("table"))
monitors.add(new TableMonitor(Constants.widthGUI, 240));
}
return monitors;
}
public static boolean decodeBoolean(String cmd) {
String p = cmd.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;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/Deconvolution.java b/DeconvolutionLab2/src/deconvolution/Deconvolution.java
index 0e66cb9..d885c03 100644
--- a/DeconvolutionLab2/src/deconvolution/Deconvolution.java
+++ b/DeconvolutionLab2/src/deconvolution/Deconvolution.java
@@ -1,410 +1,410 @@
/*
* 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 ij.IJ;
import java.io.File;
import bilib.tools.NumFormat;
-import deconvolution.algorithm.AbstractAlgorithm;
+import deconvolution.algorithm.Algorithm;
import deconvolution.algorithm.Controller;
import deconvolutionlab.Lab;
import deconvolutionlab.monitor.AbstractMonitor;
import deconvolutionlab.monitor.Monitors;
import deconvolutionlab.monitor.StatusMonitor;
import deconvolutionlab.monitor.TableMonitor;
import deconvolutionlab.output.Output;
import signal.RealSignal;
import signal.SignalCollector;
/**
* This class is the main class to run deconvolution with or without user interface.
*
* All the parameters are given in the command line (String variable command).
*
* @author Daniel Sage
*
*/
public class Deconvolution implements Runnable {
public enum Finish {
DIE, ALIVE, KILL
};
- private AbstractAlgorithm algo = null;
+ private Algorithm algo = null;
private Controller controller = new Controller();
private String command = "";
private Features report = new Features();
private String name = "";
public RealSignal image;
public RealSignal psf;
private RealSignal deconvolvedImage;
private Finish finish = Finish.DIE;
private DeconvolutionDialog dialog;
private boolean embeddedStats = false;
public Deconvolution(String name, String command) {
this.name = name;
this.finish = Finish.DIE;
setCommand(command);
}
public Deconvolution(String name, String command, Finish finish) {
this.name = name;
this.finish = finish;
setCommand(command);
}
public void setCommand(String command) {
this.command = command;
controller = Command.decodeController(command);
algo = Command.decodeAlgorithm(command);
algo.setController(controller);
this.command = command;
if (name.equals("") && algo != null)
name = algo.getShortnames()[0];
}
public RealSignal deconvolve() {
return deconvolve(image, psf);
}
public RealSignal deconvolve(RealSignal image, RealSignal psf) {
this.image = image;
this.psf = psf;
for(AbstractMonitor monitor : controller.getMonitors())
if (monitor instanceof TableMonitor)
Lab.setVisible(((TableMonitor)monitor).getPanel(), "Monitor of " + name, 10, 10);
if (controller.getFFT() == null) {
run();
return deconvolvedImage;
}
if (!controller.getFFT().isMultithreadable()) {
run();
return deconvolvedImage;
}
if (controller.isMultithreading()) {
Thread thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
else {
run();
}
return deconvolvedImage;
}
/**
* This method runs the deconvolution with a graphical user interface.
*/
public void launch() {
embeddedStats = true;
dialog = new DeconvolutionDialog(DeconvolutionDialog.Module.ALL, this);
Lab.setVisible(dialog, false);
}
@Override
public void run() {
double chrono = System.nanoTime();
Monitors monitors = controller.getMonitors();
report.add("Path", controller.toStringPath());
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());
if (algo == null) {
monitors.error("Algorithm: not valid");
if (finish == Finish.KILL)
System.exit(-103);
return;
}
report.add("FFT", controller.getFFT().getName());
report.add("Algorithm", algo.getName());
if (embeddedStats) {
TableMonitor tableMonitor = null;
for(AbstractMonitor monitor : controller.getMonitors())
if (monitor instanceof TableMonitor)
tableMonitor = (TableMonitor)monitor;
if (controller.getStats().getMode() == Stats.Mode.SHOW || controller.getStats().getMode() == Stats.Mode.SHOWSAVE) {
controller.getStats().setEmbeddedInFrame(embeddedStats);
dialog.addStats(controller.getStats());
}
if (tableMonitor != null) {
dialog.addMonitor(tableMonitor);
}
}
algo.setController(controller);
deconvolvedImage = algo.run(image, psf);
report.add("End", NumFormat.time(System.nanoTime() - chrono));
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;
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);
double norm = controller.getNormalizationPSF();
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.getReferenceName());
features.add("Constraint", controller.getConstraintAsString());
features.add("Padding", controller.getPadding().toString());
features.add("Apodization", controller.getApodization().toString());
features.add("FFT", controller.getFFT() == null ? "null" : controller.getFFT().getName());
}
features.add("Path", controller.getPath());
String s = "[" + controller.getVerbose().name() + "] ";
for(AbstractMonitor monitor : controller.getMonitors())
s+= monitor.getName() + " ";
features.add("Monitor", s);
if (controller.getStats() != null)
features.add("Stats", controller.getStats().toStringStats());
features.add("Running", controller.toStringRunning());
for (Output out : controller.getOuts())
features.add("Output " + out.getName(), out.toString());
controller.getMonitors().log("Recap deconvolution parameters");
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 void abort() {
algo.getController().abort();
}
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 = createRealSignal(controller.getMonitors(), arg, cmd, controller.getPath());
controller.getMonitors().log("Open image " + arg + " " + cmd);
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 = createRealSignal(controller.getMonitors(), arg, cmd, controller.getPath());
controller.getMonitors().log("Open PSF " + arg + " " + cmd);
return psf;
}
private static RealSignal createRealSignal(Monitors monitors, String arg, String cmd, String path) {
RealSignal signal = null;
if (arg.equalsIgnoreCase("synthetic")) {
signal = Lab.createSynthetic(monitors, cmd);
}
if (arg.equalsIgnoreCase("platform")) {
signal = Lab.getImage(monitors, 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 void setAlgorithm(AbstractAlgorithm algo) {
+ public void setAlgorithm(Algorithm algo) {
this.algo = algo;
}
- public AbstractAlgorithm getAlgorithm() {
+ public Algorithm getAlgorithm() {
return algo;
}
public void setController(Controller controller) {
this.controller = controller;
}
public Controller getController() {
return controller;
}
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 Monitors getMonitors() {
return controller.getMonitors();
}
public String getCommand() {
return command;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithm.java b/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithm.java
deleted file mode 100644
index 76b202d..0000000
--- a/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithm.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * 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;
-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 signal.Constraint;
-import signal.RealSignal;
-import signal.SignalCollector;
-import signal.apodization.Apodization;
-import signal.padding.Padding;
-import bilib.tools.NumFormat;
-import deconvolution.Stats;
-import deconvolutionlab.Lab;
-import deconvolutionlab.monitor.Monitors;
-import deconvolutionlab.monitor.Verbose;
-import deconvolutionlab.output.Output;
-import deconvolutionlab.system.SystemInfo;
-import fft.AbstractFFT;
-import fft.FFT;
-
-/**
- * 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;
-
- /** h is the PSF signal for the deconvolution. */
- protected RealSignal h;
-
- protected boolean threaded;
-
- /** Optimized implementation in term of memory footprint */
- protected boolean optimizedMemoryFootprint;
-
- protected int iterMax = 0;
-
- protected AbstractFFT fft;
- protected Controller controller;
-
- public AbstractAlgorithm() {
- setController(new Controller());
- optimizedMemoryFootprint = true;
- threaded = true;
- fft = FFT.getFastestFFT().getDefaultFFT();
- }
-
- public AbstractAlgorithm(Controller controller) {
- this.controller = controller;
- optimizedMemoryFootprint = true;
- threaded = true;
- fft = FFT.getFastestFFT().getDefaultFFT();
- }
-
- 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 AbstractAlgorithm setParameters(double... params);
- public abstract double getRegularizationFactor();
- public abstract double getStepFactor();
- public abstract double[] getParameters();
-
- public abstract double[] getDefaultParameters();
-
- public RealSignal run(RealSignal image, RealSignal psf) {
-
- String sn = getShortnames()[0];
- String algoParam = sn + "(" + getParametersAsString() + ")";
- if (controller.isSystem())
- SystemInfo.activate();
-
- Padding pad = controller.getPadding();
- Apodization apo = controller.getApodization();
- double norm = controller.getNormalizationPSF();
-
- controller.setAlgoName(algoParam);
- fft = controller.getFFT();
- controller.setIterationsMax(iterMax);
-
- if (image == null)
- return null;
-
- if (psf == null)
- return null;
-
- // Prepare the controller and the outputs
-
- Monitors monitors = controller.getMonitors();
- monitors.setVerbose(controller.getVerbose());
- monitors.log("Path: " + controller.toStringPath());
- monitors.log("Algorithm: " + getName());
-
- // Prepare the signal and the PSF
- 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);
- monitors.log("PSF: " + h.dimAsString() + " normalized " + (norm <= 0 ? "no" : norm));
-
- String iterations = (isIterative() ? iterMax + " iterations" : "direct");
-
- controller.setIterationsMax(iterMax);
-
- monitors.log(sn + " is starting (" + iterations + ")");
- controller.setMonitors(monitors);
-
- controller.start(y);
- h.circular();
-
- // FFT
- fft.init(monitors, y.nx, y.ny, y.nz);
- controller.setFFT(fft);
-
- monitors.log(sn + " data ready");
- monitors.log(algoParam);
-
- 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();
- }
- SignalCollector.free(y);
- SignalCollector.free(h);
- x.setName("x");
- RealSignal result = pad.crop(monitors, x);
-
- controller.finish(result);
- monitors.log(getName() + " is finished");
-
- SignalCollector.free(x);
-
- if (controller.isDisplayFinal())
- Lab.show(monitors, result, "Final Display of " + sn);
-
- result.setName("Out of " + algoParam);
-
- monitors.log("End of " + sn + " in " + NumFormat.seconds(controller.getTimeNano()) + " and " + controller.getMemoryAsString());
-
- return result;
- }
-
- public AbstractAlgorithm noPopup() {
- return this.disableDisplayFinal().disableSystem();
- }
-
- public AbstractAlgorithm setController(Controller controller) {
- this.controller = controller;
- return this;
- }
-
- public Controller getController() {
- return controller;
- }
-
- public int getIterationsMax() {
- return iterMax;
- }
-
- public int getIterations() {
- return controller.getIterations();
- }
-
- public double getTime() {
- return controller.getTimeNano();
- }
-
- public double getMemory() {
- return controller.getMemory();
- }
-
- public double getResidu() {
- return controller.getResidu();
- }
-
- public double getSNR() {
- return controller.getSNR();
- }
-
- public double getPSNR() {
- return controller.getPSNR();
- }
-
- public void setWavelets(String waveletsName) {
- }
-
- @Override
- public String toString() {
- String s = "";
- s += getName();
- s += (isIterative() ? ", " + iterMax + " iterations" : " (direct)");
- s += (isRegularized() ? ", &lambda=" + NumFormat.nice(getRegularizationFactor()) : "");
- s += (isStepControllable() ? ", &gamma=" + NumFormat.nice(getStepFactor()) : "");
- return s;
- }
-
- public String getParametersAsString() {
- double p[] = getParameters();
- String param = "";
- for (int i = 0; i < p.length; i++)
- if (i == p.length - 1)
- param += NumFormat.nice(p[i]);
- else
- param += NumFormat.nice(p[i]) + ", ";
- return param;
- }
-
-
- public AbstractFFT getFFT() {
- return controller.getFFT();
- }
-
- public AbstractAlgorithm setFFT(AbstractFFT fft) {
- this.fft = fft;
- controller.setFFT(fft);
- return this;
- }
-
- public String getPath() {
- return controller.getPath();
- }
-
- public AbstractAlgorithm setPath(String path) {
- controller.setPath(path);
- return this;
- }
-
- public boolean isSystem() {
- return controller.isSystem();
- }
-
- public AbstractAlgorithm enableSystem() {
- controller.setSystem(true);
- return this;
- }
-
- public AbstractAlgorithm disableSystem() {
- controller.setSystem(false);
- return this;
- }
-
- public boolean isMultithreading() {
- return controller.isMultithreading();
- }
-
- public AbstractAlgorithm enableMultithreading() {
- controller.setMultithreading(true);
- return this;
- }
-
- public AbstractAlgorithm disableMultithreading() {
- controller.setMultithreading(false);
- return this;
- }
-
- public boolean isDisplayFinal() {
- return controller.isDisplayFinal();
- }
-
- public AbstractAlgorithm enableDisplayFinal() {
- controller.setDisplayFinal(true);
- return this;
- }
-
- public AbstractAlgorithm disableDisplayFinal() {
- controller.setDisplayFinal(false);
- return this;
- }
-
- public double getNormalizationPSF() {
- return controller.getNormalizationPSF();
- }
-
- public AbstractAlgorithm setNormalizationPSF(double normalizationPSF) {
- controller.setNormalizationPSF(normalizationPSF);
- return this;
- }
-
- public double getEpsilon() {
- return controller.getEpsilon();
- }
-
- public AbstractAlgorithm setEpsilon(double epsilon) {
- controller.setEpsilon(epsilon);
- return this;
- }
-
- public Padding getPadding() {
- return controller.getPadding();
- }
-
- public AbstractAlgorithm setPadding(Padding padding) {
- controller.setPadding(padding);
- return this;
- }
-
- public Apodization getApodization() {
- return controller.getApodization();
- }
-
- public AbstractAlgorithm setApodization(Apodization apodization) {
- controller.setApodization(apodization);
- return this;
- }
-
- public Monitors getMonitors() {
- return controller.getMonitors();
- }
-
- public AbstractAlgorithm setMonitors(Monitors monitors) {
- controller.setMonitors(monitors);
- return this;
- }
-
- public Verbose getVerbose() {
- return controller.getVerbose();
- }
-
- public AbstractAlgorithm setVerbose(Verbose verbose) {
- controller.setVerbose(verbose);
- return this;
- }
-
- public Constraint.Mode getConstraint() {
- return controller.getConstraint();
- }
-
- public AbstractAlgorithm setConstraint(Constraint.Mode constraint) {
- controller.setConstraint(constraint);
- return this;
- }
-
- public Stats getStats() {
- return controller.getStats();
- }
-
- public AbstractAlgorithm setStats(Stats stats) {
- controller.setStats(stats);
- return this;
- }
-
- public AbstractAlgorithm showStats() {
- controller.setStats(new Stats(Stats.Mode.SHOW));
- return this;
- }
-
- public AbstractAlgorithm saveStats(Stats stats) {
- controller.setStats(new Stats(Stats.Mode.SAVE));
- return this;
- }
-
- public AbstractAlgorithm setStats() {
- controller.setStats(new Stats(Stats.Mode.SHOWSAVE));
- return this;
- }
-
- public double getResiduMin() {
- return controller.getResiduMin();
- }
-
- public AbstractAlgorithm setResiduMin(double residuMin) {
- controller.setResiduMin(residuMin);
- return this;
- }
-
- public double getTimeLimit() {
- return controller.getTimeLimit();
- }
-
- public AbstractAlgorithm setTimeLimit(double timeLimit) {
- controller.setTimeLimit(timeLimit);
- return this;
- }
-
- public RealSignal getReference() {
- return controller.getReference();
- }
-
- public AbstractAlgorithm setReference(RealSignal ref) {
- controller.setReference(ref);
- return this;
- }
-
- public ArrayList<Output> getOuts() {
- return controller.getOuts();
- }
-
- public AbstractAlgorithm setOuts(ArrayList<Output> outs) {
- controller.setOuts(outs);
- return this;
- }
-
- public AbstractAlgorithm addOutput(Output out) {
- controller.addOutput(out);
- return this;
- }
-
- public String getParametersToString() {
- double params[] = getParameters();
- if (params != null) {
- if (params.length > 0) {
- String s = " ";
- for (double param : params)
- s += NumFormat.nice(param) + " ";
- return s;
- }
- }
- return "parameter-free";
- }
-}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java b/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
index 8bdcb9a..e7e5310 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
@@ -1,156 +1,479 @@
/*
* 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;
+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;
-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 TikhonovRegularizedInverseFilterPanel());
- 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;
+import signal.Constraint;
+import signal.RealSignal;
+import signal.SignalCollector;
+import signal.apodization.Apodization;
+import signal.padding.Padding;
+import bilib.tools.NumFormat;
+import deconvolution.Stats;
+import deconvolutionlab.Lab;
+import deconvolutionlab.monitor.Monitors;
+import deconvolutionlab.monitor.Verbose;
+import deconvolutionlab.output.Output;
+import deconvolutionlab.system.SystemInfo;
+import fft.AbstractFFT;
+import fft.FFT;
+
+/**
+ * This class is the common part of every algorithm of deconvolution.
+ *
+ * @author Daniel Sage
+ *
+ */
+public abstract class Algorithm implements Callable<RealSignal> {
+
+ /** y is the input signal of the deconvolution. */
+ protected RealSignal y;
+
+ /** h is the PSF signal for the deconvolution. */
+ protected RealSignal h;
+
+ protected boolean threaded;
+
+ /** Optimized implementation in term of memory footprint */
+ protected boolean optimizedMemoryFootprint;
+
+ protected int iterMax = 0;
+
+ protected AbstractFFT fft;
+ protected Controller controller;
+
+ public Algorithm() {
+ setController(new Controller());
+ optimizedMemoryFootprint = true;
+ threaded = true;
+ fft = FFT.getFastestFFT().getDefaultFFT();
}
- 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 TikhonovRegularizedInverseFilter(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();
+ public Algorithm(Controller controller) {
+ this.controller = controller;
+ optimizedMemoryFootprint = true;
+ threaded = true;
+ fft = FFT.getFastestFFT().getDefaultFFT();
+ }
+
+ 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 Algorithm setParameters(double... params);
+ public abstract double getRegularizationFactor();
+ public abstract double getStepFactor();
+ public abstract double[] getParameters();
+
+ public abstract double[] getDefaultParameters();
+
+ public RealSignal run(RealSignal image, RealSignal psf) {
+
+ String sn = getShortnames()[0];
+ String algoParam = sn + "(" + getParametersAsString() + ")";
+ if (controller.isSystem())
+ SystemInfo.activate();
+
+ Padding pad = controller.getPadding();
+ Apodization apo = controller.getApodization();
+ double norm = controller.getNormalizationPSF();
- 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.getShortnames())
- if (sn.equals(shortname.trim()))
- return panel;
- if (panel.getName().equals(shortname.trim()))
- return panel;
+ controller.setAlgoName(algoParam);
+ fft = controller.getFFT();
+ controller.setIterationsMax(iterMax);
+ if (image == null)
+ return null;
+
+ if (psf == null)
+ return null;
+
+ // Prepare the controller and the outputs
+
+ Monitors monitors = controller.getMonitors();
+ monitors.setVerbose(controller.getVerbose());
+ monitors.log("Path: " + controller.toStringPath());
+ monitors.log("Algorithm: " + getName());
+
+ // Prepare the signal and the PSF
+ 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);
+ monitors.log("PSF: " + h.dimAsString() + " normalized " + (norm <= 0 ? "no" : norm));
+
+ String iterations = (isIterative() ? iterMax + " iterations" : "direct");
+
+ controller.setIterationsMax(iterMax);
+
+ monitors.log(sn + " is starting (" + iterations + ")");
+ controller.setMonitors(monitors);
+
+ controller.start(y);
+ h.circular();
+
+ // FFT
+ fft.init(monitors, y.nx, y.ny, y.nz);
+ controller.setFFT(fft);
+
+ monitors.log(sn + " data ready");
+ monitors.log(algoParam);
+
+ 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();
}
- return null;
+ catch (Exception e) {
+ e.printStackTrace();
+ x = y.duplicate();
+ }
+ SignalCollector.free(y);
+ SignalCollector.free(h);
+ x.setName("x");
+ RealSignal result = pad.crop(monitors, x);
+
+ controller.finish(result);
+ monitors.log(getName() + " is finished");
+
+ SignalCollector.free(x);
+
+ if (controller.isDisplayFinal())
+ Lab.show(monitors, result, "Final Display of " + sn);
+
+ result.setName("Out of " + algoParam);
+
+ monitors.log("End of " + sn + " in " + NumFormat.seconds(controller.getTimeNano()) + " and " + controller.getMemoryAsString());
+
+ return result;
}
- public static ArrayList<String> getShortnames() {
- ArrayList<String> list = new ArrayList<String>();
- for (AbstractAlgorithmPanel algo : getAvailableAlgorithms()) {
- for(String sn : algo.getShortnames())
- list.add(sn);
- }
- return list;
+ public Algorithm noPopup() {
+ return this.disableDisplayFinal().disableSystem();
+ }
+
+ public Algorithm setController(Controller controller) {
+ this.controller = controller;
+ return this;
+ }
+
+ public Controller getController() {
+ return controller;
+ }
+
+ public int getIterationsMax() {
+ return iterMax;
+ }
+
+ public int getIterations() {
+ return controller.getIterations();
+ }
+
+ public double getTime() {
+ return controller.getTimeNano();
+ }
+
+ public double getMemory() {
+ return controller.getMemory();
+ }
+
+ public double getResidu() {
+ return controller.getResidu();
+ }
+
+ public double getSNR() {
+ return controller.getSNR();
+ }
+
+ public double getPSNR() {
+ return controller.getPSNR();
+ }
+
+ public void setWavelets(String waveletsName) {
+ }
+
+ @Override
+ public String toString() {
+ String s = "";
+ s += getName();
+ s += (isIterative() ? ", " + iterMax + " iterations" : " (direct)");
+ s += (isRegularized() ? ", &lambda=" + NumFormat.nice(getRegularizationFactor()) : "");
+ s += (isStepControllable() ? ", &gamma=" + NumFormat.nice(getStepFactor()) : "");
+ return s;
+ }
+
+ public String getParametersAsString() {
+ double p[] = getParameters();
+ String param = "";
+ for (int i = 0; i < p.length; i++)
+ if (i == p.length - 1)
+ param += NumFormat.nice(p[i]);
+ else
+ param += NumFormat.nice(p[i]) + ", ";
+ return param;
+ }
+
+
+ public AbstractFFT getFFT() {
+ return controller.getFFT();
+ }
+
+ public Algorithm setFFT(AbstractFFT fft) {
+ this.fft = fft;
+ controller.setFFT(fft);
+ return this;
+ }
+
+ public String getPath() {
+ return controller.getPath();
+ }
+
+ public Algorithm setPath(String path) {
+ controller.setPath(path);
+ return this;
}
- public static String getDocumentation(String name) {
- for (AbstractAlgorithmPanel algo : getAvailableAlgorithms()) {
- if (name.equals(algo.getName()))
- return algo.getDocumentation();
+ public boolean isSystem() {
+ return controller.isSystem();
+ }
+
+ public Algorithm enableSystem() {
+ controller.setSystem(true);
+ return this;
+ }
+
+ public Algorithm disableSystem() {
+ controller.setSystem(false);
+ return this;
+ }
+
+ public boolean isMultithreading() {
+ return controller.isMultithreading();
+ }
+
+ public Algorithm enableMultithreading() {
+ controller.setMultithreading(true);
+ return this;
+ }
+
+ public Algorithm disableMultithreading() {
+ controller.setMultithreading(false);
+ return this;
+ }
+
+ public boolean isDisplayFinal() {
+ return controller.isDisplayFinal();
+ }
+
+ public Algorithm enableDisplayFinal() {
+ controller.setDisplayFinal(true);
+ return this;
+ }
+
+ public Algorithm disableDisplayFinal() {
+ controller.setDisplayFinal(false);
+ return this;
+ }
+
+ public double getNormalizationPSF() {
+ return controller.getNormalizationPSF();
+ }
+
+ public Algorithm setNormalizationPSF(double normalizationPSF) {
+ controller.setNormalizationPSF(normalizationPSF);
+ return this;
+ }
+
+ public double getEpsilon() {
+ return controller.getEpsilon();
+ }
+
+ public Algorithm setEpsilon(double epsilon) {
+ controller.setEpsilon(epsilon);
+ return this;
+ }
+
+ public Padding getPadding() {
+ return controller.getPadding();
+ }
+
+ public Algorithm setPadding(Padding padding) {
+ controller.setPadding(padding);
+ return this;
+ }
+
+ public Apodization getApodization() {
+ return controller.getApodization();
+ }
+
+ public Algorithm setApodization(Apodization apodization) {
+ controller.setApodization(apodization);
+ return this;
+ }
+
+ public Monitors getMonitors() {
+ return controller.getMonitors();
+ }
+
+ public Algorithm setMonitors(Monitors monitors) {
+ controller.setMonitors(monitors);
+ return this;
+ }
+
+ public Verbose getVerbose() {
+ return controller.getVerbose();
+ }
+
+ public Algorithm setVerbose(Verbose verbose) {
+ controller.setVerbose(verbose);
+ return this;
+ }
+
+ public Constraint.Mode getConstraint() {
+ return controller.getConstraint();
+ }
+
+ public Algorithm setConstraint(Constraint.Mode constraint) {
+ controller.setConstraint(constraint);
+ return this;
+ }
+
+ public Stats getStats() {
+ return controller.getStats();
+ }
+
+ public Algorithm setStats(Stats stats) {
+ controller.setStats(stats);
+ return this;
+ }
+
+ public Algorithm showStats() {
+ controller.setStats(new Stats(Stats.Mode.SHOW));
+ return this;
+ }
+
+ public Algorithm saveStats(Stats stats) {
+ controller.setStats(new Stats(Stats.Mode.SAVE));
+ return this;
+ }
+
+ public Algorithm setStats() {
+ controller.setStats(new Stats(Stats.Mode.SHOWSAVE));
+ return this;
+ }
+
+ public double getResiduMin() {
+ return controller.getResiduMin();
+ }
+
+ public Algorithm setResiduMin(double residuMin) {
+ controller.setResiduMin(residuMin);
+ return this;
+ }
+
+ public double getTimeLimit() {
+ return controller.getTimeLimit();
+ }
+
+ public Algorithm setTimeLimit(double timeLimit) {
+ controller.setTimeLimit(timeLimit);
+ return this;
+ }
+
+ public RealSignal getReference() {
+ return controller.getReference();
+ }
+
+ public Algorithm setReference(RealSignal ref) {
+ controller.setReference(ref);
+ return this;
+ }
+
+ public ArrayList<Output> getOuts() {
+ return controller.getOuts();
+ }
+
+ public Algorithm setOuts(ArrayList<Output> outs) {
+ controller.setOuts(outs);
+ return this;
+ }
+
+ public Algorithm addOutput(Output out) {
+ controller.addOutput(out);
+ return this;
+ }
+
+ public String getParametersToString() {
+ double params[] = getParameters();
+ if (params != null) {
+ if (params.length > 0) {
+ String s = " ";
+ for (double param : params)
+ s += NumFormat.nice(param) + " ";
+ return s;
+ }
}
- return "Unknown Algorithm";
+ return "parameter-free";
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java b/DeconvolutionLab2/src/deconvolution/algorithm/AlgorithmList.java
similarity index 87%
copy from DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
copy to DeconvolutionLab2/src/deconvolution/algorithm/AlgorithmList.java
index 8bdcb9a..de558c4 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Algorithm.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/AlgorithmList.java
@@ -1,156 +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 {
+public class AlgorithmList {
/** This is the static list of all available algorithms. */
- private static ArrayList<AbstractAlgorithmPanel> list;
+ private static ArrayList<AlgorithmPanel> list;
static {
- list = new ArrayList<AbstractAlgorithmPanel>();
+ list = new ArrayList<AlgorithmPanel>();
list.add(new RegularizedInverseFilterPanel());
list.add(new TikhonovRegularizedInverseFilterPanel());
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() {
+ public static ArrayList<AlgorithmPanel> getAvailableAlgorithms() {
return list;
}
- public static AbstractAlgorithm getDefaultAlgorithm() {
+ public static Algorithm 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();
+ public static Algorithm createAlgorithm(String shortname) {
+ Algorithm 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 TikhonovRegularizedInverseFilter(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();
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()) {
+ public static AlgorithmPanel getPanel(String shortname) {
+ for (AlgorithmPanel panel : getAvailableAlgorithms()) {
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 (AlgorithmPanel algo : getAvailableAlgorithms()) {
for(String sn : algo.getShortnames())
list.add(sn);
}
return list;
}
public static String getDocumentation(String name) {
- for (AbstractAlgorithmPanel algo : getAvailableAlgorithms()) {
+ for (AlgorithmPanel algo : getAvailableAlgorithms()) {
if (name.equals(algo.getName()))
return algo.getDocumentation();
}
return "Unknown Algorithm";
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithmPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/AlgorithmPanel.java
similarity index 92%
rename from DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithmPanel.java
rename to DeconvolutionLab2/src/deconvolution/algorithm/AlgorithmPanel.java
index 15eafef..19aed66 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/AbstractAlgorithmPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/AlgorithmPanel.java
@@ -1,58 +1,64 @@
/*
* 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 {
+/**
+ * This is the abstract panel class associated the algorithm.
+ *
+ * @author Daniel Sage
+ *
+ */
+public abstract class AlgorithmPanel {
public abstract JPanel getPanelParameters();
public abstract String getCommand();
public abstract String getName();
public abstract String[] getShortnames();
public abstract String getDocumentation();
public boolean isNamed(String name) {
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/Controller.java b/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java
index 2e48691..6709698 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java
@@ -1,669 +1,676 @@
/*
* 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.io.File;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import signal.Assessment;
import signal.ComplexSignal;
import signal.Constraint;
import signal.RealSignal;
import signal.apodization.Apodization;
import signal.padding.Padding;
import bilib.tools.Files;
import bilib.tools.NumFormat;
import deconvolution.Deconvolution;
import deconvolution.Stats;
import deconvolutionlab.Constants;
import deconvolutionlab.monitor.AbstractMonitor;
import deconvolutionlab.monitor.ConsoleMonitor;
import deconvolutionlab.monitor.Monitors;
import deconvolutionlab.monitor.TableMonitor;
import deconvolutionlab.monitor.Verbose;
import deconvolutionlab.output.Output;
import deconvolutionlab.system.SystemUsage;
import fft.AbstractFFT;
import fft.FFT;
/**
* This is an important class to manage all the common task of the algorithm.
* The method start() is called before at the starting of the algorithm. The
* method ends() is called at the end of every iterations for the iterative
* algorithm. It returns true if one the stopping criteria is true. The method
* finish() is called when the algorithm is completely terminated.
*
+ * A timer is started to get the peak memory.
+ *
* @author Daniel Sage
*
*/
public class Controller {
private String path;
private boolean system;
private boolean multithreading;
private boolean displayFinal;
private double normalizationPSF;
private double epsilon;
private Padding padding;
private Apodization apodization;
private ArrayList<Output> outs;
private Stats stats;
private Constraint.Mode constraintMode;
private double residuMin;
private double timeLimit;
private String referenceName;
private Monitors monitors;
private Verbose verbose;
private AbstractFFT fft;
private int iterationsMax = 100;
private boolean doResidu = false;
private boolean doTime = false;
private boolean doReference = false;
private boolean doConstraint = false;
private boolean abort = false;
private double timeStarting = 0;
private double memoryStarting = 0;
private double residu = Double.MAX_VALUE;
private int iterations = 0;
private double memoryPeak = 0;
private double snr = 0;
private double psnr = 0;
private RealSignal refImage;
private RealSignal prevImage;
private RealSignal x;
private Timer timer;
private String algoName = "";
+ /**
+ * Constructor.
+ *
+ * One controller is always instantiated for every run of a algorithm.
+ */
public Controller() {
doResidu = false;
doTime = false;
doReference = false;
doConstraint = false;
timeStarting = System.nanoTime();
setPath(Files.getWorkingDirectory());
setSystem(true);
setMultithreading(true);
setDisplayFinal(true);
setFFT(FFT.getFastestFFT().getDefaultFFT());
setNormalizationPSF(1);
setEpsilon(1e-6);
setPadding(new Padding());
setApodization(new Apodization());
monitors = new Monitors();
monitors.add(new ConsoleMonitor());
monitors.add(new TableMonitor(Constants.widthGUI, 240));
setVerbose(Verbose.Log);
setStats(new Stats(Stats.Mode.NO));
setConstraint(Constraint.Mode.NO);
setResiduMin(-1);
setTimeLimit(-1);
setReference(null);
setOuts(new ArrayList<Output>());
}
public void setAlgoName(String algoName) {
this.algoName = algoName;
}
public void setFFT(AbstractFFT fft) {
this.fft = fft;
}
public void abort() {
this.abort = true;
}
public void setIterationsMax(int iterationsMax) {
this.iterationsMax = iterationsMax;
}
public boolean needSpatialComputation() {
return doConstraint || doResidu || doReference;
}
/**
* Call one time at the beginning of the algorithms
*
* @param x
* the input signal
*/
public void start(RealSignal x) {
this.x = x;
stats.show();
stats.addInput(x);
iterations = 0;
timer = new Timer();
timer.schedule(new Updater(), 0, 100);
timeStarting = System.nanoTime();
memoryStarting = SystemUsage.getHeapUsed();
if (doConstraint && x != null)
Constraint.setModel(x);
if (doReference) {
refImage = new Deconvolution("Reference", "-image file " + referenceName).openImage();
if (refImage == null)
monitors.error("Impossible to load the reference image " + referenceName);
else
monitors.log("Reference image loaded");
}
for (Output out : outs)
out.executeStarting(monitors, x, this);
this.prevImage = x;
}
public boolean ends(ComplexSignal X) {
boolean out = false;
for (Output output : outs)
out = out | output.is(iterations);
if (doConstraint || doResidu || doReference || out) {
if (fft == null)
fft = FFT.createDefaultFFT(monitors, X.nx, X.ny, X.nz);
x = fft.inverse(X, x);
return ends(x);
}
return ends((RealSignal) null);
}
public boolean ends(RealSignal x) {
this.x = x;
if (doConstraint || doResidu || doReference)
compute(iterations, x, doConstraint, doResidu, doReference);
for (Output out : outs)
out.executeIterative(monitors, x, this, iterations);
iterations++;
double p = iterations * 100.0 / iterationsMax;
monitors.progress("Iterative " + iterations + "/" + iterationsMax, p);
double timeElapsed = getTimeSecond();
boolean stopIter = (iterations >= iterationsMax);
boolean stopTime = doTime && (timeElapsed >= timeLimit);
boolean stopResd = doResidu && (residu <= residuMin);
monitors.log("@" + iterations + " Time: " + NumFormat.seconds(timeElapsed*1e9));
String pnsrText = doReference ? "" + psnr : "n/a";
String snrText = doReference ? "" + snr : "n/a";
String residuText = doResidu ? "" + residu : "n/a";
stats.add(x, iterations, NumFormat.seconds(getTimeNano()), pnsrText, snrText, residuText);
String prefix = "Stopped>> by ";
if (abort)
monitors.log(prefix + "abort");
if (stopIter)
monitors.log(prefix + "iteration " + iterations + " > " + iterationsMax);
if (stopTime)
monitors.log(prefix + "time " + timeElapsed + " > " + timeLimit);
if (stopResd)
monitors.log(prefix + "residu " + NumFormat.nice(residu) + " < " + NumFormat.nice(residuMin));
return abort | stopIter | stopTime | stopResd;
}
public void finish(RealSignal x) {
this.x = x;
boolean ref = doReference;
boolean con = doConstraint;
boolean res = doResidu;
if (con || res || ref)
compute(iterations, x, con, res, ref);
String pnsrText = doReference ? ""+psnr : "n/a";
String snrText = doReference ? ""+snr : "n/a";
String residuText = doResidu ? "" + residu : "n/a";
stats.addOutput(x, algoName, NumFormat.seconds(getTimeNano()), pnsrText, snrText, residuText);
stats.save(monitors, path);
for (Output out : outs)
out.executeFinal(monitors, x, this);
monitors.log("Time: " + NumFormat.seconds(getTimeNano()) + " Peak:" + getMemoryAsString());
if (timer != null)
timer.cancel();
}
private void compute(int iterations, RealSignal x, boolean con, boolean res, boolean ref) {
if (x == null)
return;
if (con && constraintMode != null)
new Constraint(monitors).apply(x, constraintMode);
if (ref && refImage != null) {
String s = "";
psnr = Assessment.psnr(x, refImage);
snr = Assessment.snr(x, refImage);
s += " PSNR: " + NumFormat.nice(psnr);
s += " SNR: " + NumFormat.nice(snr);
monitors.log("@" + iterations + " " + s);
}
residu = Double.MAX_VALUE;
if (res && prevImage != null) {
residu = Assessment.relativeResidu(x, prevImage);
prevImage = x.duplicate();
monitors.log("@" + iterations + " Residu: " + NumFormat.nice(residu));
}
}
public double getTimeNano() {
return (System.nanoTime() - timeStarting);
}
public double getTimeSecond() {
return (System.nanoTime() - timeStarting) * 1e-9;
}
public String getConstraintAsString() {
if (!doConstraint)
return "no";
if (constraintMode == null)
return "null";
return constraintMode.name().toLowerCase();
}
- public String getStoppingCriteriaAsString(AbstractAlgorithm algo) {
+ public String getStoppingCriteriaAsString(Algorithm algo) {
String stop = algo.isIterative() ? "iterations limit=" + algo.getIterationsMax() + ", " : "direct, ";
stop += doTime ? ", time limit=" + NumFormat.nice(timeLimit * 1e-9) : " no time limit" + ", ";
stop += doResidu ? ", residu limit=" + NumFormat.nice(residuMin) : " no residu limit";
return stop;
}
public double getMemory() {
return memoryPeak - memoryStarting;
}
public String getMemoryAsString() {
return NumFormat.bytes(getMemory());
}
public int getIterations() {
return iterations;
}
public double getSNR() {
return snr;
}
public double getPSNR() {
return psnr;
}
public double getResidu() {
return residu;
}
private void update() {
memoryPeak = Math.max(memoryPeak, SystemUsage.getHeapUsed());
}
public AbstractFFT getFFT() {
return fft;
}
/**
* @return the path
*/
public String getPath() {
return path;
}
/**
* @param path
* the path to set
*/
public void setPath(String path) {
this.path = path;
}
/**
* @return the system
*/
public boolean isSystem() {
return system;
}
/**
* @param system
* the system to set
*/
public void setSystem(boolean system) {
this.system = system;
}
/**
* @return the multithreading
*/
public boolean isMultithreading() {
return multithreading;
}
/**
* @param multithreading
* the multithreading to set
*/
public void setMultithreading(boolean multithreading) {
this.multithreading = multithreading;
}
/**
* @return the displayFinal
*/
public boolean isDisplayFinal() {
return displayFinal;
}
/**
* @param displayFinal
* the displayFinal to set
*/
public void setDisplayFinal(boolean displayFinal) {
this.displayFinal = displayFinal;
}
/**
* @return the normalizationPSF
*/
public double getNormalizationPSF() {
return normalizationPSF;
}
/**
* @param normalizationPSF
* the normalizationPSF to set
*/
public void setNormalizationPSF(double normalizationPSF) {
this.normalizationPSF = normalizationPSF;
}
/**
* @return the epsilon
*/
public double getEpsilon() {
return epsilon;
}
/**
* @param epsilon
* the epsilon to set
*/
public void setEpsilon(double epsilon) {
this.epsilon = epsilon;
}
/**
* @return the padding
*/
public Padding getPadding() {
return padding;
}
/**
* @param padding
* the padding to set
*/
public void setPadding(Padding padding) {
this.padding = padding;
}
/**
* @return the apodization
*/
public Apodization getApodization() {
return apodization;
}
/**
* @param apodization
* the apodization to set
*/
public void setApodization(Apodization apodization) {
this.apodization = apodization;
}
/**
* @return the monitors
*/
public Monitors getMonitors() {
if (monitors == null)
return Monitors.createDefaultMonitor();
return monitors;
}
/**
* @param monitors
* the monitors to set
*/
public void setMonitors(Monitors monitors) {
this.monitors = monitors;
}
/**
* @return the verbose
*/
public Verbose getVerbose() {
return verbose;
}
/**
* @param verbose
* the verbose to set
*/
public void setVerbose(Verbose verbose) {
this.verbose = verbose;
}
public Constraint.Mode getConstraint() {
return constraintMode;
}
public void setConstraint(Constraint.Mode constraintMode) {
doConstraint = constraintMode != Constraint.Mode.NO;
this.constraintMode = constraintMode;
}
/**
* @return the stats
*/
public Stats getStats() {
return stats;
}
/**
* @param stats
* the stats to set
*/
public void setStats(Stats stats) {
this.stats = stats;
}
/**
* @return the residuMin
*/
public double getResiduMin() {
return residuMin;
}
/**
* @param residuMin
* the residuMin to set
*/
public void setResiduMin(double residuMin) {
doResidu = residuMin > 0;
this.residuMin = residuMin;
}
/**
* @return the timeLimit
*/
public double getTimeLimit() {
return timeLimit;
}
/**
* @param timeLimit
* the timeLimit to set
*/
public void setTimeLimit(double timeLimit) {
doTime = timeLimit > 0;
this.timeLimit = timeLimit;
}
/**
* @return the reference
*/
public String getReferenceName() {
return referenceName;
}
/**
* @param reference
* the reference to set
*/
public void setReferenceName(String referenceName) {
doReference = false;
if (referenceName == null)
return;
if (referenceName.equals(""))
return;
doReference = true;
this.referenceName = referenceName;
}
/**
* @return the reference
*/
public RealSignal getReference() {
return refImage;
}
/**
* @param reference
* the reference to set
*/
public void setReference(RealSignal refImage) {
doReference = false;
if (refImage == null)
return;
doReference = true;
this.refImage = refImage;
}
/**
* @return the outs
*/
public ArrayList<Output> getOuts() {
return outs;
}
/**
* @param outs
* the outs to set
*/
public void setOuts(ArrayList<Output> outs) {
this.outs = outs;
}
public void addOutput(Output out) {
this.outs.add(out);
}
public String toStringMonitor() {
String s = "[" + verbose.name().toLowerCase() + "] ";
for (AbstractMonitor monitor : monitors) {
s += "" + monitor.getName() + " ";
}
return s;
}
public Stats.Mode getStatsMode() {
return stats.getMode();
}
public void setStatsMode(Stats.Mode mode) {
this.stats = new Stats(mode);
}
public String toStringRunning() {
String s = "";
s += "system " + (system ? "shown" : "hidden ");
s += ", multithreading " + (multithreading ? "on" : "off ");
s += ", display final " + (displayFinal ? "on " : "off ");
return s;
}
public String toStringPath() {
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)";
}
}
private class Updater extends TimerTask {
@Override
public void run() {
update();
}
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.java b/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.java
index 9aa4a72..5f4c2ed 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Convolution.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.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
import signal.SignalCollector;
-public class Convolution extends AbstractAlgorithm implements Callable<RealSignal> {
+public class Convolution extends Algorithm 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";
}
@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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
return this;
}
@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 58ca3f8..a2f4577 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ConvolutionPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ConvolutionPanel.java
@@ -1,73 +1,73 @@
/*
* 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 {
+public class ConvolutionPanel extends AlgorithmPanel {
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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">CONV</span>]</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 b7bd81a..1eab3a5 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/FISTA.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/FISTA.java
@@ -1,189 +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 wavelets.AbstractWavelets;
import wavelets.Wavelets;
-public class FISTA extends AbstractAlgorithm implements Callable<RealSignal> {
+public class FISTA extends Algorithm implements Callable<RealSignal> {
private double gamma = 1.0;
private double lambda = 0.1;
private String waveletsName = "Haar";
private int scale = 3;
public FISTA(int iterMax, double gamma, double lambda, String waveletsName, int scale) {
super();
this.iterMax = iterMax;
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";
}
@Override
public String[] getShortnames() {
return new String[] {"FISTA"};
}
@Override
public int getComplexityNumberofFFT() {
return 4 + 4 * iterMax;
}
@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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
iterMax = (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];
return this;
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10, 1, 0.1 };
}
@Override
public double[] getParameters() {
return new double[] { iterMax, 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 ea96406..9b32cc0 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/FISTAPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/FISTAPanel.java
@@ -1,168 +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 FISTAPanel extends AbstractAlgorithmPanel implements KeyListener, ActionListener, ChangeListener {
+public class FISTAPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">FISTA</span>]</h1>";
s += "<p>FISTA exploits the sparsity of the wavelet domain to better preserve ";
s += "image details and discontinuities. The associated cost function is: </p>";
s += "<p>C(<b>x</b>) = | <b>y</b> - <b>H</b><b>x</b> | + &lambda; |<b>W</b><b>x</b>|<sub>1</sub> </p>";
s += "<p>where <b>W</b> represents a wavelet transform. ";
s += "Due to the non-smoothness of the l<sub>1</sub> norm, ";
s += "the problem can be solved efficiently by fast iterative soft-thresholding </p>";
s += "<p>Reference: A. Beck, M. Teboulle, A fast iterative shrinkage-thresholding algorithm for linear inverse problems, SIAM J. Imag. Sci. 2, 2009. ";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java b/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java
index 9b6109f..053640d 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ICTM.java
@@ -1,154 +1,154 @@
/*
* 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> {
+public class ICTM extends Algorithm implements Callable<RealSignal> {
private double gamma = 1.0;
private double lambda = 1.0;
public ICTM(int iterMax, double gamma, double lambda) {
super();
this.iterMax = iterMax;
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";
}
@Override
public String[] getShortnames() {
return new String[] {"ICTM"};
}
@Override
public int getComplexityNumberofFFT() {
return 3 + iterMax * 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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
iterMax = (int) Math.round(params[0]);
if (params.length > 1)
gamma = (float) params[1];
if (params.length > 2)
lambda = (float) params[2];
return this;
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10, 1, 0.1 };
}
@Override
public double[] getParameters() {
return new double[] { iterMax, 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 724d85e..ce1fd4e 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ICTMPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ICTMPanel.java
@@ -1,142 +1,142 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.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 {
+public class ICTMPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">ICTM</span>]</h1>";
s += "<p>TM algorithm uses iterative gradient descent to minimize the regularized inverse filter cost.</p>";
s += "<p>The iterative scheme allows nonnegativity constraint at each iteration.</p>";
s += "<p>Reference: H. Van der Voort, K. Strasters, Restoration of confocal images for quantitative image analysis. J of Microscopy 178, 165-181, 1995</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java b/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java
index 6253d28..c521fd7 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ISTA.java
@@ -1,181 +1,181 @@
/*
* 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> {
+public class ISTA extends Algorithm implements Callable<RealSignal> {
private double gamma = 1.0;
private double lambda = 1.0;
private String waveletsName = "Haar";
private int scale = 3;
public ISTA(int iterMax, double gamma, double lambda, String waveletsName, int scale) {
super();
this.iterMax = iterMax;
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";
}
@Override
public String[] getShortnames() {
return new String[] {"ISTA"};
}
@Override
public int getComplexityNumberofFFT() {
return 3 + 4 * iterMax;
}
@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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
iterMax = (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];
return this;
}
@Override
public double[] getDefaultParameters() {
return new double[] {10, 1, 0.1};
}
@Override
public double[] getParameters() {
return new double[] {iterMax, 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 1383e3b..15d2ad8 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/ISTAPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/ISTAPanel.java
@@ -1,166 +1,166 @@
/*
* 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 {
+public class ISTAPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">ISTA</span>]</h1>";
s += "<p>ISTA exploits the sparsity of the wavelet domain to better preserve ";
s += "image details and discontinuities. The associated cost function is: </p>";
s += "<p>C(<b>x</b>) = | <b>y</b> - <b>H</b><b>x</b> | + &lambda; |<b>W</b><b>x</b>|<sub>1</sub> </p>";
s += "<p>where <b>W</b> represents a wavelet transform. ";
s += "<p>Reference: An EM algorithm for wavelet-based image restoration, MAT Figueiredo, RD Nowak, Image Processing, IEEE Transactions on 12 (8), 2003. ";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java b/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java
index d1c097e..5a51f63 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Identity.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Identity.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.util.concurrent.Callable;
import signal.RealSignal;
-public class Identity extends AbstractAlgorithm implements Callable<RealSignal> {
+public class Identity extends Algorithm 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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
return this;
}
@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 bb41c3b..0528811 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/IdentityPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/IdentityPanel.java
@@ -1,73 +1,73 @@
/*
* 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 {
+public class IdentityPanel extends AlgorithmPanel {
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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">I</span>]</h1>";
s += "<p>This algorithm does nothing. It returns a copy of the input image.</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java b/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java
index 63781ed..ecef712 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Landweber.java
@@ -1,148 +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.Operations;
import signal.RealSignal;
import signal.SignalCollector;
-public class Landweber extends AbstractAlgorithm implements Callable<RealSignal> {
+public class Landweber extends Algorithm implements Callable<RealSignal> {
private double gamma = 1.0;
public Landweber(int iterMax, double gamma) {
super();
this.iterMax = iterMax;
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";
}
@Override
public String[] getShortnames() {
return new String[] {"LW", "LLS"};
}
@Override
public int getComplexityNumberofFFT() {
return 3 + (controller.needSpatialComputation() ? 2 * iterMax : 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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
iterMax = (int) Math.round(params[0]);
if (params.length > 1)
gamma = (float) params[1];
return this;
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10, 1 };
}
@Override
public double[] getParameters() {
return new double[] { iterMax, 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 6b9f79d..043606c 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPanel.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 LandweberPanel extends AbstractAlgorithmPanel implements ChangeListener {
+public class LandweberPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">LW</span> | ";
s += " <span style=\"color:#FF3333;font-family:georgia\">LLS</span>]</h1>";
s += "<p>The Landweber algorithm known as Linear Least-Square (LLS) minimizes the same least-squares cost function than NIF.</p>";
s += "<p>The Landweber algorithm proceeds by an iterative gradient-descent approach which allows ";
s += " to impose a nonnegativity constraint at each iteration (see LW+ or NLLS algorithm).</p>";
s += "<p>Reference: L. Landweber, An iteration formula for fredholm integral equations of the first kind, Am. J. Math. 73, 1951. ";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
index 6e46302..ff31c16 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivity.java
@@ -1,150 +1,150 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Constraint;
import signal.Operations;
import signal.RealSignal;
import signal.SignalCollector;
-public class LandweberPositivity extends AbstractAlgorithm implements Callable<RealSignal> {
+public class LandweberPositivity extends Algorithm implements Callable<RealSignal> {
private double gamma = 1.0;
public LandweberPositivity(int iterMax, double gamma) {
super();
this.iterMax = iterMax;
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-Linear Least-Square";
}
@Override
public String[] getShortnames() {
return new String[] {"NNLS", "LW+"};
}
@Override
public int getComplexityNumberofFFT() {
return 3 + iterMax * 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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
iterMax = (int) Math.round(params[0]);
if (params.length > 1)
gamma = (float) params[1];
return this;
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10, 1 };
}
@Override
public double[] getParameters() {
return new double[] { iterMax, 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 bbbb263..b1f5ba9 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/LandweberPositivityPanel.java
@@ -1,108 +1,108 @@
/*
* 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 {
+public class LandweberPositivityPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">LW+</span> | ";
s += " <span style=\"color:#FF3333;font-family:georgia\">NNLS</span>]</h1>";
s += "<p>The Landweber+ algorithm known as Non-Negative Least-Square (NLLS) minimizes a least-squares cost function with a non-negative constraint.</p>";
s += "<p>Reference: L. Landweber, An iteration formula for fredholm integral equations of the first kind, Am. J. Math. 73, 1951. ";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java b/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java
index f2a3aab..83d8c0e 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilter.java
@@ -1,124 +1,124 @@
/*
* 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 class NaiveInverseFilter extends Algorithm 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";
}
@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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
return this;
}
@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 1813afc..956479a 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilterPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/NaiveInverseFilterPanel.java
@@ -1,76 +1,76 @@
/*
* 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 {
+public class NaiveInverseFilterPanel extends AlgorithmPanel {
private NaiveInverseFilter algo = new NaiveInverseFilter();
@Override
public JPanel getPanelParameters() {
GridPanel pn = new GridPanel(false);
pn.place(1, 0, "<html><span \"nowrap\">NIF is parameter-free</span></html>");
return pn;
}
@Override
public String getCommand() {
return "";
}
@Override
public String getName() {
return algo.getName();
}
@Override
public String[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">NIF</span> | ";
s += " <span style=\"color:#FF3333;font-family:georgia\">IF</span>] </h1>";
s += "<p>The simplest approach to deconvolution consists in minimizing a least-squares cost function. ";
s += "Unfortunately, the NIF tends to amplify measurement noise, resulting in spurious high-frequency oscillations. ";
s += "It corresponds to maximum-likelihood estimation in the presence of Gaussian noise. ";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java b/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java
index 5f30c5b..c3571ba 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivision.java
@@ -1,124 +1,124 @@
/*
* 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 class NonStabilizedDivision extends Algorithm 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";
}
@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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
return this;
}
@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 c191dfe..d368d90 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivisionPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/NonStabilizedDivisionPanel.java
@@ -1,73 +1,73 @@
/*
* 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 {
+public class NonStabilizedDivisionPanel extends AlgorithmPanel {
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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() ;
s += " [<span style=\"color:#FF3333;font-family:georgia\">DIV</span>]</h1>";
s += "<p>It makes a division in the Fourier domain. Not stabilization is applied.";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java b/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java
index 4d0909d..b0d82fa 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilter.java
@@ -1,186 +1,186 @@
/*
* 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> {
+public class RegularizedInverseFilter extends Algorithm 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 L = ComplexSignalFactory.laplacian(Y.nx, Y.ny, Y.nz);
L.setName("Laplacian");
float la, lb, ha, hb, fa, fb, ta, tb, ya, yb;
int nxy = Y.nx * Y.ny * 2;
float w = (float) lambda;
float epsilon = (float) Operations.epsilon;
for (int k = 0; k < Y.nz; k++)
for (int i = 0; i < nxy; i += 2) {
la = L.data[k][i];
lb = L.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];
L.data[k][i] = ya * ta - yb * tb;
L.data[k][i + 1] = ya * tb + ta * yb;
}
return L;
}
@Override
public String getName() {
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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
lambda = (float) params[0];
return this;
}
@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 f815035..3ccd275 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilterPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RegularizedInverseFilterPanel.java
@@ -1,124 +1,124 @@
/*
* 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 {
+public class RegularizedInverseFilterPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">RIF</span> | ";
s += " <span style=\"color:#FF3333;font-family:georgia\">LRIF</span>] </h1>";
s += "<p><i>Laplacian Regularized Inverse Filter</i></p>";
s += "<p>This algorithm is a direct inverse filter with a Laplacian regularization following this formalization: ";
s += "<b>x</b> = (<b>H</b><sup>T</sup><b>H</b> + &lambda; <b>L</b><sup>T</sup><b>L</b>)<sup>-1</sup> <b>H</b><sup>T</sup><b>y</b>";
s += "<p> where <b>H</b> is the PSF and <b>L</b> is the discretization of the Laplacian operator. ";
s += "This regularization tends to reduce high frequencies noisy and in the same time ";
s += "it tends to blur the image. It is controlled by the regularization factor &lambda;. ";
s += "</p>";
s += "<p>RIF or LRIF is very fast. It is non-iterative algorithm</p>";
s += "<p>When the filtering by <b>L</b><sup>T</sup><b>L</b> has a whitening effect on <b>x</b> ";
s += "and &lambda; is defined as the inverse of the noise variance, RIF amounts to Wiener filtering.</p>";
s += "<p>Reference: N. Wiener, Extrapolation, Interpolation, and Smoothing of Stationary Time Series, vol. 2, MIT press Cambridge, 1949.</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java
index 3271f12..24a593c 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucy.java
@@ -1,142 +1,142 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
import signal.SignalCollector;
-public class RichardsonLucy extends AbstractAlgorithm implements Callable<RealSignal> {
+public class RichardsonLucy extends Algorithm implements Callable<RealSignal> {
public RichardsonLucy(int iterMax) {
super();
this.iterMax = iterMax;
}
// 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";
}
@Override
public String[] getShortnames() {
return new String[] {"RL"};
}
@Override
public int getComplexityNumberofFFT() {
return 1 + 5 * iterMax;
}
@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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
iterMax = (int) Math.round(params[0]);
return this;
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10 };
}
@Override
public double[] getParameters() {
return new double[] { iterMax };
}
@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 13bc401..bfe02a3 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyPanel.java
@@ -1,96 +1,96 @@
/*
* 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 {
+public class RichardsonLucyPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName() + "";
s += " [<span style=\"color:#FF3333;font-family:georgia\">RL</span>]</h1>";
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 assumes that the noise follows a Poisson distribution.</p>";
s += "<p>It is a maximum likelihood estimator (MLE).</p>";
s += "<p>Warning: the input image should have only positive values</p>";
s += "<p>References:</p>";
s += "<p>W.H. Richardson, Bayesian-based iterative method of image restoration, J. Optical Soc. Am. 62, 1972.";
s += "<p>L.B. Lucy, An iterative technique for the rectification of observed distributions, Astrophys. J. 79 (6), 1974.";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTV.java b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTV.java
index 4440066..39eeea4 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTV.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/RichardsonLucyTV.java
@@ -1,236 +1,236 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package 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> {
+public class RichardsonLucyTV extends Algorithm implements Callable<RealSignal> {
private double lambda = 0.1;
public RichardsonLucyTV(int iterMax, double lambda) {
super();
this.iterMax = iterMax;
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 * iterMax;
}
@Override
public String getName() {
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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
iterMax = (int) Math.round(params[0]);
if (params.length > 1)
lambda = (float)params[1];
return this;
}
@Override
public double[] getDefaultParameters() {
return new double[] {10, 0.1};
}
@Override
public double[] getParameters() {
return new double[] {iterMax, 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 8d666b6..12751d5 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 {
+public class RichardsonLucyTVPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">RLTV</span>]</h1>";
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.</p>";
s += "<p>It has a weighted parameter &lambda; to control the effect of the total variation.</p>";
s += "<p></p>";
s += "<h3>Reference: N. Dey et al., Richardson–Lucy algorithm with total variation regularization for 3D confocal microscope deconvolution, Microsc. Res. Tech. 69, 2006. </p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java b/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
index 227ac5f..d0bb0c1 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
@@ -1,169 +1,169 @@
/*
* 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> {
+public class Simulation extends Algorithm 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++) {
double a = slice[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";
}
@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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
mean = params[0];
if (params.length > 1)
stdev = params[1];
if (params.length > 2)
poisson = params[2];
return this;
}
@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 579e371..90ed516 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/SimulationPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/SimulationPanel.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.JTextField;
import bilib.component.GridPanel;
import deconvolution.Command;
import deconvolutionlab.Config;
-public class SimulationPanel extends AbstractAlgorithmPanel implements KeyListener {
+public class SimulationPanel extends AlgorithmPanel 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.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 getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">SIM</span>]</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 3a283c6..47ad424 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/StarkParker.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/StarkParker.java
@@ -1,149 +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 StarkParker extends AbstractAlgorithm implements Callable<RealSignal> {
+public class StarkParker extends Algorithm implements Callable<RealSignal> {
private double gamma = 1.0;
public StarkParker(int iterMax, double gamma) {
super();
this.iterMax = iterMax;
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";
}
@Override
public String[] getShortnames() {
return new String[] {"BVLS", "SP"};
}
@Override
public int getComplexityNumberofFFT() {
return 3 + iterMax * 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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
iterMax = (int) Math.round(params[0]);
if (params.length > 1)
gamma = (float) params[1];
return this;
}
@Override
public double[] getDefaultParameters() {
return new double[] { 10, 1 };
}
@Override
public double[] getParameters() {
return new double[] { iterMax, 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 8ce334f..cb4ddb5 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/StarkParkerPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/StarkParkerPanel.java
@@ -1,109 +1,109 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import 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 {
+public class StarkParkerPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">BVLS</span> | ";
s += " <span style=\"color:#FF3333;font-family:georgia\">SP</span>]</h1>";
s += "<p>The Bounded-Variables Least-Square algorithm is known also as Spark-Parker (SP) algorithm. ";
s += "It minimizes a least-squares cost function with a clipped values constraint.</p>";
s += "<p>Reference: P. Stark, R. Parker, Bounded-variable least-squares: an algorithm and applications. Computational Statistics 10, 1995.";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMiller.java b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMiller.java
index 9f8f47e..1ea0b68 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMiller.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMiller.java
@@ -1,152 +1,152 @@
/*
* 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> {
+public class TikhonovMiller extends Algorithm implements Callable<RealSignal> {
private double gamma = 1.0;
private double lambda = 1.0;
public TikhonovMiller(int iterMax, double gamma, double lambda) {
super();
this.iterMax = iterMax;
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 * iterMax : 0);
}
@Override
public String getName() {
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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
iterMax = (int) Math.round(params[0]);
if (params.length > 1)
gamma = (float)params[1];
if (params.length > 2)
lambda = (float)params[2];
return this;
}
@Override
public double[] getDefaultParameters() {
return new double[] {10, 1, 0.1};
}
@Override
public double[] getParameters() {
return new double[] {iterMax, 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 3348628..6ee1e67 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMillerPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovMillerPanel.java
@@ -1,140 +1,140 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.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 {
+public class TikhonovMillerPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">TM</span>]</h1>";
s += "<p>TM algorithm uses iterative gradient descent to minimize the regularized inverse filter cost.</p>";
s += "<p>The iterative scheme allows nonnegativity constraint at each iteration (see ICTM).</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizedInverseFilter.java b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizedInverseFilter.java
index 559e853..372834e 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizedInverseFilter.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizedInverseFilter.java
@@ -1,184 +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 TikhonovRegularizedInverseFilter extends AbstractAlgorithm implements Callable<RealSignal> {
+public class TikhonovRegularizedInverseFilter extends Algorithm implements Callable<RealSignal> {
private double lambda = 0.1;
public TikhonovRegularizedInverseFilter(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 Inverse Filter";
}
@Override
public String[] getShortnames() {
return new String[] {"TRIF", "TR"};
}
@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 AbstractAlgorithm setParameters(double... params ) {
+ public Algorithm setParameters(double... params ) {
if (params == null)
return this;
if (params.length > 0)
lambda = (float)params[0];
return this;
}
@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/TikhonovRegularizedInverseFilterPanel.java b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizedInverseFilterPanel.java
index eba186a..e0801b8 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizedInverseFilterPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/TikhonovRegularizedInverseFilterPanel.java
@@ -1,131 +1,131 @@
/*
* 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 TikhonovRegularizedInverseFilterPanel extends AbstractAlgorithmPanel implements ActionListener, ChangeListener, KeyListener {
+public class TikhonovRegularizedInverseFilterPanel extends AlgorithmPanel implements ActionListener, ChangeListener, KeyListener {
private RegularizationPanel reg;
private TikhonovRegularizedInverseFilter algo = new TikhonovRegularizedInverseFilter(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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">TRIF</span> | ";
s += " <span style=\"color:#FF3333;font-family:georgia\">TR</span>] </h1>";
s += "<p>This algorithm is a direct inverse filter with a Tikhonov regularization following this formalization: ";
s += "<b>x</b> = (<b>H</b><sup>T</sup><b>H</b> + &lambda; <b>I</b>)<sup>-1</sup> <b>H</b><sup>T</sup><b>y</b>";
s += "<p> where <b>H</b> is the PSF and <b>I</b> is the identity operator. ";
s += "This regularization tends to reduce high frequencies noisy and in the same time ";
s += "it tends to blur the image. It is controlled by the regularization factor &lambda;. ";
s += "</p>";
s += "<p>TRIF or TR is very fast. It is non-iterative algorithm. </p>";
s += "<p>This formulation can also be interpreted as a maximum a posteriori model.";
s += "The regularization introduces prior information about the signal to guide the estimation.</p>";
s += "<p>Reference: A. Tikhonov, Solution of incorrectly formulated problems and the regularization method, Soviet Mathematics Dokl., vol. 5, 1963.</p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java b/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java
index 040e264..0f6df6a 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/VanCittert.java
@@ -1,146 +1,146 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.algorithm;
import java.util.concurrent.Callable;
import signal.ComplexSignal;
import signal.Operations;
import signal.RealSignal;
import signal.SignalCollector;
-public class VanCittert extends AbstractAlgorithm implements Callable<RealSignal> {
+public class VanCittert extends Algorithm implements Callable<RealSignal> {
private double gamma = 1.0;
public VanCittert(int iterMax, double gamma) {
super();
this.iterMax = iterMax;
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 * iterMax : 0);
}
@Override
public String getName() {
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 AbstractAlgorithm setParameters(double... params) {
+ public Algorithm setParameters(double... params) {
if (params == null)
return this;
if (params.length > 0)
iterMax = (int) Math.round(params[0]);
if (params.length > 1)
gamma = (float)params[1];
return this;
}
@Override
public double[] getDefaultParameters() {
return new double[] {10, 1};
}
@Override
public double[] getParameters() {
return new double[] {iterMax, 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 debc0c7..a60849c 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/VanCittertPanel.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/VanCittertPanel.java
@@ -1,104 +1,104 @@
/*
* 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 {
+public class VanCittertPanel extends AlgorithmPanel 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.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[] getShortnames() {
return algo.getShortnames();
}
@Override
public String getDocumentation() {
String s = "";
s += "<h1>" + getName();
s += " [<span style=\"color:#FF3333;font-family:georgia\">VC</span>]</h1>";
s += "<p>The simplest iterative algorithm for image deconvolution is the Van Cittert algorithm (1930)</p>";
s += "<p>The algorithm is sensitive to the presence of noise and tends to increase the noise </p>";
return s;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/capsule/AlgorithmCapsule.java b/DeconvolutionLab2/src/deconvolution/capsule/AlgorithmCapsule.java
index 699d490..84f0267 100644
--- a/DeconvolutionLab2/src/deconvolution/capsule/AlgorithmCapsule.java
+++ b/DeconvolutionLab2/src/deconvolution/capsule/AlgorithmCapsule.java
@@ -1,185 +1,185 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution.capsule;
import javax.swing.JSplitPane;
import com.esotericsoftware.minlog.Log;
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.AlgorithmPanel;
+import deconvolution.algorithm.AlgorithmList;
import deconvolutionlab.monitor.Monitors;
import fft.AbstractFFT;
import fft.FFT;
import signal.ComplexSignal;
import signal.RealSignal;
import signal.SignalCollector;
/**
* This class is a information module for the algorithm.
*
* @author Daniel Sage
*
*/
public class AlgorithmCapsule extends AbstractCapsule implements Runnable {
private CustomizedTable table;
private HTMLPane doc;
public AlgorithmCapsule(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());
}
@Override
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.getAlgorithm() == null) {
features.add("Algorithm", "No valid algorithm");
return;
}
- AbstractAlgorithm algo = deconvolution.getAlgorithm();
+ Algorithm algo = deconvolution.getAlgorithm();
doc.clear();
String name = algo.getShortnames()[0];
- AbstractAlgorithmPanel algoPanel = Algorithm.getPanel(name);
+ AlgorithmPanel algoPanel = AlgorithmList.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.getController().getPadding() == null) {
features.add("Padding", "No valid padding");
return;
}
if (deconvolution.getController().getApodization() == 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;
}
startAsynchronousTimer("Check Algorithm", 200);
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("Small dataset", mx + "x" + my + "x" + mz);
features.add("Elapsed time on small dataset", NumFormat.time(chrono) );
chrono = chrono * ratio * algo.getComplexityNumberofFFT();
features.add("Estimated time for input dataset", NumFormat.time(chrono) );
features.add("Estimated number of FFTs", "" + 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 required memory", NumFormat.bytes(mem));
features.add("Iterative", algo.isIterative() ? "" + algo.getIterationsMax() : "Direct");
table.removeRows();
for (String[] feature : features)
table.append(feature);
stopAsynchronousTimer();
}
}
\ No newline at end of file
diff --git a/DeconvolutionLab2/src/deconvolutionlab/module/AlgorithmModule.java b/DeconvolutionLab2/src/deconvolutionlab/module/AlgorithmModule.java
index 89638c6..b73da37 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/module/AlgorithmModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/module/AlgorithmModule.java
@@ -1,172 +1,172 @@
/*
* 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.module;
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.JLabel;
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 deconvolution.algorithm.AlgorithmPanel;
+import deconvolution.algorithm.AlgorithmList;
import deconvolutionlab.Config;
import deconvolutionlab.Lab;
public class AlgorithmModule extends AbstractModule implements ActionListener, ChangeListener {
private JComboBox<String> cmb;
private HTMLPane doc;
private JPanel cards;
private JLabel shortname;
public AlgorithmModule() {
super("Algorithm", "-algorithm", "", "Check");
- ArrayList<AbstractAlgorithmPanel> deconv = Algorithm.getAvailableAlgorithms();
- for (AbstractAlgorithmPanel panel : deconv)
+ ArrayList<AlgorithmPanel> deconv = AlgorithmList.getAvailableAlgorithms();
+ for (AlgorithmPanel panel : deconv)
cmb.addItem(panel.getName());
cmb.addActionListener(this);
}
@Override
public String getCommand() {
String name = (String) cmb.getSelectedItem();
- AbstractAlgorithmPanel algo = Algorithm.getPanel(name);
+ AlgorithmPanel algo = AlgorithmList.getPanel(name);
String cmd = "-algorithm " + algo.getShortnames()[0] + " " + algo.getCommand();
String synopsis = algo.getShortnames()[0] + " " + algo.getCommand();
setSynopsis(synopsis);
setCommand(cmd);
return cmd;
}
@Override
public JPanel buildExpandedPanel() {
shortname = new JLabel("-------");
Border bl1 = BorderFactory.createEtchedBorder();
Border bl2 = BorderFactory.createEmptyBorder(0, 10, 0, 10);
shortname.setBorder(BorderFactory.createCompoundBorder(bl1, bl2));
cmb = new JComboBox<String>();
cmb.setBorder(BorderFactory.createEtchedBorder());
JPanel pnc = new JPanel();
pnc.add(cmb);
doc = new HTMLPane(100, 1000);
cards = new JPanel(new CardLayout());
- ArrayList<AbstractAlgorithmPanel> panels = Algorithm.getAvailableAlgorithms();
+ ArrayList<AlgorithmPanel> panels = AlgorithmList.getAvailableAlgorithms();
- for (AbstractAlgorithmPanel panel : panels) {
+ for (AlgorithmPanel 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 top = new JPanel(new BorderLayout());
top.add(cmb, BorderLayout.CENTER);
top.add(shortname, BorderLayout.EAST);
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));
cards.setBorder(BorderFactory.createEtchedBorder());
control.add(top);
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());
+ Config.register(getName(), "algorithm", cmb, AlgorithmList.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);
+ AlgorithmPanel algo = AlgorithmList.getPanel(name);
doc.append(algo.getDocumentation());
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, name);
String s = "<html><b><p style =\"font-family:georgia\">";
for(int i=0; i<algo.getShortnames().length; i++)
s += (i==0 ? "" : " | ") + algo.getShortnames()[i] ;
shortname.setText(s + "</b></html>");
}
if (e.getSource() == getAction2Button()) {
Deconvolution deconvolution = new Deconvolution("Check Algorithm", Command.command());
DeconvolutionDialog d = new DeconvolutionDialog(DeconvolutionDialog.Module.ALGO, deconvolution);
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/module/ComputationModule.java b/DeconvolutionLab2/src/deconvolutionlab/module/ComputationModule.java
index 16e0d00..21be4d7 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/module/ComputationModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/module/ComputationModule.java
@@ -1,137 +1,137 @@
/*
* 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.module;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import bilib.component.GridPanel;
import deconvolution.Command;
-import deconvolution.algorithm.Algorithm;
+import deconvolution.algorithm.AlgorithmList;
import deconvolutionlab.Config;
import fft.FFT;
public class ComputationModule extends AbstractModule implements ActionListener, ChangeListener {
private JComboBox<String> cmbFFT;
private JComboBox<String> cmbEpsilon;
boolean init = false;
public ComputationModule() {
super("Computation", "", "Default", "");
}
@Override
public String getCommand() {
String cmd = "";
if (cmbFFT.getSelectedIndex() != 0)
cmd += " -fft " + FFT.getLibraryByName((String) cmbFFT.getSelectedItem()).getLibraryName();
if (cmbEpsilon.getSelectedIndex() != 6)
cmd += " -epsilon " + (String) cmbEpsilon.getSelectedItem();
return cmd;
}
@Override
public JPanel buildExpandedPanel() {
cmbFFT = new JComboBox<String>(FFT.getLibrariesAsArray());
cmbEpsilon = new JComboBox<String>(new String[] { "1E-0", "1E-1", "1E-2", "1E-3", "1E-4", "1E-5", "1E-6", "1E-7", "1E-8", "1E-9", "1E-10", "1E-11", "1E-12" });
cmbEpsilon.setSelectedItem("1E-6");
GridPanel pnNumeric = new GridPanel(false, 2);
pnNumeric.place(1, 0, "norm");
pnNumeric.place(3, 0, new JLabel("fft"));
pnNumeric.place(3, 1, cmbFFT);
pnNumeric.place(3, 2, new JLabel("FFT library (Fourier)"));
pnNumeric.place(9, 0, new JLabel("epsilon"));
pnNumeric.place(9, 1, cmbEpsilon);
pnNumeric.place(9, 2, new JLabel("<html>Machine Epsilon &epsilon;</html>"));
JScrollPane scroll = new JScrollPane(pnNumeric);
scroll.setBorder(BorderFactory.createEmptyBorder());
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEtchedBorder());
panel.add(scroll, BorderLayout.CENTER);
- Config.register(getName(), "fft", cmbFFT, Algorithm.getDefaultAlgorithm());
+ Config.register(getName(), "fft", cmbFFT, AlgorithmList.getDefaultAlgorithm());
Config.register(getName(), "epsilon", cmbEpsilon, "1E-6");
cmbFFT.addActionListener(this);
cmbEpsilon.addActionListener(this);
getAction1Button().addActionListener(this);
init = true;
return panel;
}
private void update() {
setCommand(getCommand());
if (init)
setSynopsis(" " + FFT.getLibraryByName((String) cmbFFT.getSelectedItem()).getLibraryName());
Command.command();
}
@Override
public void stateChanged(ChangeEvent e) {
update();
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (e.getSource() == getAction1Button()) {
cmbFFT.setSelectedIndex(0);
cmbEpsilon.setSelectedIndex(0);
}
update();
}
@Override
public void close() {
getAction1Button().removeActionListener(this);
cmbFFT.removeActionListener(this);
cmbEpsilon.removeActionListener(this);
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/module/LanguageModule.java b/DeconvolutionLab2/src/deconvolutionlab/module/LanguageModule.java
index 111c194..86115c1 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/module/LanguageModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/module/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.module;
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 deconvolution.algorithm.Algorithm;
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() {
super("Language", "", "", "");
}
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.getAlgorithm();
+ Algorithm algo = d.getAlgorithm();
if (algo == null)
return "ERROR";
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>";
}
}
diff --git a/DeconvolutionLab2/src/deconvolutionlab/module/ResourcesModule.java b/DeconvolutionLab2/src/deconvolutionlab/module/ResourcesModule.java
index f200bac..38bba70 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/module/ResourcesModule.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/module/ResourcesModule.java
@@ -1,163 +1,163 @@
/*
* 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.module;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import bilib.component.GridPanel;
import bilib.table.CustomizedColumn;
-import deconvolution.algorithm.Algorithm;
+import deconvolution.algorithm.AlgorithmList;
import deconvolutionlab.Config;
import deconvolutionlab.Constants;
import deconvolutionlab.system.SystemInfo;
import fft.AbstractFFTLibrary;
import fft.FFT;
public class ResourcesModule extends AbstractModule implements ActionListener {
private JComboBox<String> cmbFFT;
private JComboBox<String> cmbEpsilon;
private JComboBox<String> cmbMultithreading;
private JComboBox<String> cmbSystem;
public ResourcesModule() {
super("Resources", "", "System", "Default");
}
@Override
public String getCommand() {
String cmd = " ";
if (cmbFFT.getSelectedIndex() != 0)
cmd += " -fft " + FFT.getLibraryByName((String) cmbFFT.getSelectedItem()).getLibraryName();
if (cmbEpsilon.getSelectedIndex() != 6)
cmd += " -epsilon " + (String) cmbEpsilon.getSelectedItem();
if (cmbMultithreading.getSelectedIndex() != 0)
cmd += " -multithreading no";
if (cmbSystem.getSelectedIndex() != 0)
cmd += " -system no";
return cmd;
}
public void update() {
AbstractFFTLibrary library = FFT.getLibraryByName((String) cmbFFT.getSelectedItem());
setCommand(getCommand());
setSynopsis(library.getLibraryName());
}
@Override
public JPanel buildExpandedPanel() {
cmbFFT = new JComboBox<String>(FFT.getLibrariesAsArray());
cmbEpsilon = new JComboBox<String>(new String[] { "1E-0", "1E-1", "1E-2", "1E-3", "1E-4", "1E-5", "1E-6", "1E-7", "1E-8", "1E-9", "1E-10", "1E-11", "1E-12" });
cmbEpsilon.setSelectedItem("1E-6");
cmbMultithreading = new JComboBox<String>(new String[] { "yes", "no" });
cmbSystem = new JComboBox<String>(new String[] { "yes", "no" });
ArrayList<CustomizedColumn> columns = new ArrayList<CustomizedColumn>();
columns.add(new CustomizedColumn("FFT Library", String.class, 100, false));
columns.add(new CustomizedColumn("Installed", String.class, 40, false));
columns.add(new CustomizedColumn("Installation", String.class, Constants.widthGUI, false));
GridPanel pn = new GridPanel(false, 2);
pn.place(0, 0, new JLabel("fft"));
pn.place(0, 1, cmbFFT);
pn.place(0, 2, new JLabel("FFT Library"));
pn.place(1, 0, new JLabel("espilon"));
pn.place(1, 1, cmbEpsilon);
pn.place(1, 2, new JLabel("Machine epsilon"));
pn.place(2, 0, new JLabel("multithreading"));
pn.place(2, 1, cmbMultithreading);
pn.place(2, 2, new JLabel("Activate multithreading"));
pn.place(3, 0, new JLabel("system"));
pn.place(3, 1, cmbSystem);
pn.place(3, 2, new JLabel("Open system panel at each run"));
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEtchedBorder());
panel.setLayout(new BorderLayout());
panel.add(pn, BorderLayout.CENTER);
- Config.register(getName(), "fft", cmbFFT, Algorithm.getDefaultAlgorithm());
+ Config.register(getName(), "fft", cmbFFT, AlgorithmList.getDefaultAlgorithm());
Config.register(getName(), "epsilon", cmbEpsilon, "1E-6");
Config.register(getName(), "multithreading", cmbMultithreading, cmbMultithreading.getItemAt(0));
Config.register(getName(), "system", cmbSystem, cmbSystem.getItemAt(0));
cmbMultithreading.addActionListener(this);
cmbFFT.addActionListener(this);
cmbEpsilon.addActionListener(this);
cmbSystem.addActionListener(this);
getAction1Button().addActionListener(this);
getAction2Button().addActionListener(this);
update();
return panel;
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (e.getSource() == getAction2Button()) {
cmbFFT.setSelectedIndex(0);;
cmbEpsilon.setSelectedItem("1E-6");
cmbMultithreading.setSelectedIndex(0);
cmbSystem.setSelectedIndex(0);
}
else if (e.getSource() == getAction1Button()) {
SystemInfo.activate();
}
update();
}
@Override
public void close() {
cmbSystem.removeActionListener(this);
cmbFFT.removeActionListener(this);
cmbEpsilon.removeActionListener(this);
cmbMultithreading.removeActionListener(this);
getAction1Button().removeActionListener(this);
getAction2Button().removeActionListener(this);
}
}

Event Timeline