Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F95673655
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Dec 18, 06:19
Size
64 KB
Mime Type
application/octet-stream
Expires
Fri, Dec 20, 06:19 (1 d, 20 h)
Engine
blob
Format
Raw Data
Handle
23040770
Attached To
R2075 deconvolution
View Options
diff --git a/DeconvolutionLab2/src/deconvolution/Stats.java b/DeconvolutionLab2/src/deconvolution/Stats.java
index 7d65cb7..408850b 100644
--- a/DeconvolutionLab2/src/deconvolution/Stats.java
+++ b/DeconvolutionLab2/src/deconvolution/Stats.java
@@ -1,174 +1,182 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package deconvolution;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.io.File;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import bilib.table.CustomizedColumn;
import bilib.table.CustomizedTable;
import bilib.tools.NumFormat;
import deconvolutionlab.Constants;
import deconvolutionlab.Lab;
import deconvolutionlab.monitor.Monitors;
import deconvolutionlab.system.SystemUsage;
import signal.RealSignal;
import signal.SignalCollector;
public class Stats {
public enum Mode {NO, SHOW, SAVE, SHOWSAVE};
private CustomizedTable table;
private float[] statsInput;
private Mode mode;
private boolean embedded = false;
+ private boolean shown = false;
public Stats(Mode mode) {
this.mode = mode;
ArrayList<CustomizedColumn> columns = new ArrayList<CustomizedColumn>();
- columns.add(new CustomizedColumn("Iterations", String.class, 100, false));
- columns.add(new CustomizedColumn("Mean", String.class, 100, false));
- columns.add(new CustomizedColumn("Minimum", String.class, 100, false));
- columns.add(new CustomizedColumn("Maximum", String.class, 100, false));
+ columns.add(new CustomizedColumn("Signal", String.class, 200, false));
+ columns.add(new CustomizedColumn("Mean", String.class, 130, false));
+ columns.add(new CustomizedColumn("Minimum", String.class, 130, false));
+ columns.add(new CustomizedColumn("Maximum", String.class, 130, false));
columns.add(new CustomizedColumn("Stdev", String.class, 100, false));
columns.add(new CustomizedColumn("Energy", String.class, 100, false));
columns.add(new CustomizedColumn("Time", String.class, 100, false));
columns.add(new CustomizedColumn("Memory", String.class, 100, false));
- columns.add(new CustomizedColumn("Signal", String.class, 100, false));
+ columns.add(new CustomizedColumn("Allocated Signal", String.class, 100, false));
columns.add(new CustomizedColumn("PSNR", String.class, 100, false));
columns.add(new CustomizedColumn("SNR", String.class, 100, false));
columns.add(new CustomizedColumn("Residu", String.class, 100, false));
table = new CustomizedTable(columns, true);
}
public void setEmbeddedInFrame(boolean embedded) {
this.embedded = embedded;
}
/**
* Show the stats table in a frame if it is not yet embedded in another frame.
*/
public void show() {
if (embedded)
return;
+ if (shown)
+ return;
if (mode == Mode.SHOW || mode == Mode.SHOWSAVE) {
JFrame frame = new JFrame("Stats");
frame.getContentPane().add(getPanel());
frame.pack();
Lab.setVisible(frame);
+ shown = true;
}
}
+ public boolean isShown() {
+ return shown;
+ }
+
public void save(Monitors monitors, String path) {
if (mode == Mode.SAVE || mode == Mode.SHOWSAVE) {
String filename = path + File.separator + "stats.csv";
monitors.log("Stats save " + filename);
table.saveCSV(filename);
}
}
public void addInput(RealSignal x) {
statsInput = x.getStats();
table.append(compute(x, "In: " + x.name, "", "", "", ""));
}
public void add(RealSignal x, int iterations) {
table.append(compute(x, ""+iterations, "", "", "", ""));
}
public void add(RealSignal x, int iterations, String time, String psnr, String snr, String residu) {
table.append(compute(x, ""+iterations, time, psnr, snr, residu));
}
public void addOutput(RealSignal x, String algo, String time, String psnr, String snr, String residu) {
table.append(compute(x, "Out: " + algo, time, psnr, snr, residu));
}
public String[] compute(RealSignal x, String iterations, String time, String psnr, String snr, String residu) {
float params[] = null;
if (x != null)
params = x.getStats();
String[] row = new String[12];
row[0] = iterations;
- row[1] = (params == null ? "-" : "" + params[0]);
- row[2] = (params == null ? "-" : "" + params[1]);
- row[3] = (params == null ? "-" : "" + params[2]);
- row[4] = (params == null ? "-" : "" + params[3]);
- row[5] = (params == null ? "-" : "" + params[5]);
+ row[1] = (params == null ? "-" : "" + NumFormat.nice(params[0]));
+ row[2] = (params == null ? "-" : "" + NumFormat.nice(params[1]));
+ row[3] = (params == null ? "-" : "" + NumFormat.nice(params[2]));
+ row[4] = (params == null ? "-" : "" + NumFormat.nice(params[3]));
+ row[5] = (params == null ? "-" : "" + NumFormat.nice(params[5]));
row[6] = time;
row[7] = NumFormat.bytes(SystemUsage.getHeapUsed());
row[8] = SignalCollector.sumarize();
row[9] = psnr;
row[10] = snr;
row[11] = residu;
return row;
}
public JPanel getPanel() {
JScrollPane scroll = new JScrollPane(table);
- scroll.setPreferredSize(new Dimension(Constants.widthGUI, 400));
+ scroll.setPreferredSize(new Dimension(Constants.widthGUI+200, 400));
JPanel panel = new JPanel(new BorderLayout());
panel = new JPanel(new BorderLayout());
panel.add(scroll);
panel.setBorder(BorderFactory.createEtchedBorder());
return panel;
}
public String toStringStats() {
if (mode == Mode.SHOW)
return "show";
if (mode == Mode.SAVE)
return "save";
if (mode == Mode.SHOWSAVE)
return "show and save";
return "no";
}
public Mode getMode() {
return mode;
}
public float[] getStatsInput() {
return statsInput;
}
}
diff --git a/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java b/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java
index 78b75ff..19b958c 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Controller.java
@@ -1,654 +1,650 @@
/*
* 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.
*
* @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 reference;
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 = "";
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("");
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 " + reference).openImage();
if (refImage == null)
monitors.error("Impossible to load the reference image " + reference);
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));
- addStats();
+ 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 ? NumFormat.nice(psnr) : "n/a";
- String snrText = doReference ? NumFormat.nice(snr) : "n/a";
- String residuText = doResidu ? NumFormat.nice(residu) : "n/a";
+ 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));
}
}
- private void addStats() {
- String pnsrText = doReference ? NumFormat.nice(psnr) : "n/a";
- String snrText = doReference ? NumFormat.nice(snr) : "n/a";
- String residuText = doResidu ? NumFormat.nice(residu) : "n/a";
- stats.add(x, iterations, NumFormat.seconds(getTimeNano()), pnsrText, snrText, residuText);
- }
-
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) {
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 getReference() {
return reference;
}
/**
* @param reference
* the reference to set
*/
public void setReference(String reference) {
doReference = false;
if (reference == null)
return;
if (reference.equals(""))
return;
doReference = true;
this.reference = reference;
}
/**
* @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/Simulation.java b/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
index 48f0d7f..227ac5f 100644
--- a/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
+++ b/DeconvolutionLab2/src/deconvolution/algorithm/Simulation.java
@@ -1,166 +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> {
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) {
+ 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++)
+ 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) {
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/deconvolutionlab/output/Output.java b/DeconvolutionLab2/src/deconvolutionlab/output/Output.java
index ae8d789..b7a269c 100644
--- a/DeconvolutionLab2/src/deconvolutionlab/output/Output.java
+++ b/DeconvolutionLab2/src/deconvolutionlab/output/Output.java
@@ -1,405 +1,406 @@
/*
* 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.output;
import java.io.File;
import bilib.tools.NumFormat;
import deconvolution.algorithm.Controller;
import deconvolutionlab.Imager;
import deconvolutionlab.Imager.ContainerImage;
import deconvolutionlab.Lab;
import deconvolutionlab.monitor.Monitors;
import signal.Constraint;
import signal.RealSignal;
public class Output {
public enum View {
STACK, SERIES, ORTHO, MIP, PLANAR, FIGURE
};
public enum Dynamic {
INTACT, RESCALED, NORMALIZED, CLIPPED
};
public enum Action {
SHOW, SAVE, SHOWSAVE;
}
private ContainerImage container = null;
private int ox = 0;
private int oy = 0;
private int oz = 0;
private boolean center = true;
private String name = "";
private boolean save = true;
private boolean show = true;
private View view = View.STACK;
private Imager.Type type = Imager.Type.FLOAT;
private Dynamic dynamic = Dynamic.INTACT;
private String customPath = "$";
private int frequency = 0;
public Output(View view, int frequency, String param) {
String[] tokens = param.trim().split(" ");
this.view = view;
this.frequency = frequency;
this.name = "";
this.center = true;
this.save = true;
this.show = true;
this.container = Lab.createContainer(Monitors.createDefaultMonitor(), "");
for (int i = 0; i < tokens.length; i++) {
boolean found = false;
String p = tokens[i].trim().toLowerCase();
if (p.startsWith("@")) {
found = true;
}
if (p.startsWith("noshow")) {
show = false;
found = true;
}
if (p.startsWith("nosave")) {
save = false;
found = true;
}
for (Dynamic d : Dynamic.values()) {
if (p.toLowerCase().equals(d.name().toLowerCase())) {
dynamic = d;
found = true;
}
}
for (View v : View.values()) {
if (p.toLowerCase().equals(v.name().toLowerCase())) {
view = v;
found = true;
}
}
for (Imager.Type t : Imager.Type.values()) {
if (p.toLowerCase().equals(t.name().toLowerCase())) {
type = t;
found = true;
}
}
if (p.startsWith("(") && p.endsWith(")")) {
double pos[] = NumFormat.parseNumbers(p);
if (pos.length > 0)
ox = (int) Math.round(pos[0]);
if (pos.length > 1)
oy = (int) Math.round(pos[1]);
if (pos.length > 2)
oz = (int) Math.round(pos[2]);
found = true;
center = false;
}
if (!found)
name += tokens[i] + " ";
name = name.trim();
}
}
public Output(View view, Action action, String name) {
this.name = name;
this.show = action == Action.SHOW || action == Action.SHOWSAVE;
this.save = action == Action.SAVE || action == Action.SHOWSAVE;
this.view = view;
this.type = Imager.Type.FLOAT;
this.dynamic = Dynamic.INTACT;
this.center = true;
this.frequency = 0;
}
public Output rescale() {
this.dynamic = Dynamic.RESCALED;
return this;
}
public Output clip() {
this.dynamic = Dynamic.CLIPPED;
return this;
}
public Output normalize() {
this.dynamic = Dynamic.NORMALIZED;
return this;
}
public Output toFloat() {
this.type = Imager.Type.FLOAT;
return this;
}
public Output toShort() {
this.type = Imager.Type.SHORT;
return this;
}
public Output toByte() {
this.type = Imager.Type.BYTE;
return this;
}
public Output frequency(int frequency) {
this.frequency = frequency;
return this;
}
public Output origin(int ox, int oy, int oz) {
this.ox = ox;
this.oy = oy;
this.oz = oz;
this.center = false;
return this;
}
public boolean is(int iterations) {
if (frequency == 0)
return false;
return iterations % frequency == 0;
}
public View getView() {
return view;
}
public String getName() {
return name;
}
public void setPath(String customPath) {
this.customPath = customPath;
}
public int extractFrequency(String param) {
String line = param.trim();
if (!line.startsWith("@"))
line = "@0 " + line;
String parts[] = line.split(" ");
if (parts.length >= 1) {
return (int) Math.round(NumFormat.parseNumber(parts[0], 0));
}
return 0;
}
public String[] getAsString() {
String t = (type == Imager.Type.FLOAT ? "" : type.name().toLowerCase());
String d = (dynamic == Dynamic.INTACT ? "" : dynamic.name().toLowerCase());
String o = "";
if (!center)
o = " (" + ox + "," + oy + "," + oz + ")";
String sa = save ? "\u2713" : "";
String sh = show ? "\u2713" : "";
String fr = frequency > 0 ? " @" + frequency : "";
return new String[] { view.name().toLowerCase() + fr, name, d, t, o, sh, sa, "\u232B" };
}
public void executeStarting(Monitors monitors, RealSignal signal, Controller controller) {
if (signal == null)
return;
execute(monitors, signal, controller, true, false, false, 0);
}
public void executeFinal(Monitors monitors, RealSignal signal, Controller controller) {
if (signal == null)
return;
execute(monitors, signal, controller, false, false, true, 0);
}
public void executeIterative(Monitors monitors, RealSignal signal, Controller controller, int iter) {
if (signal == null)
return;
execute(monitors, signal, controller, false, true, false, iter);
}
private void execute(Monitors monitors, RealSignal signal, Controller controller, boolean start, boolean live, boolean finish, int iter) {
String title = name;
if (live)
if (!is(iter))
return;
if (controller != null && live) {
if (controller.getIterations() > 0) {
title += "@" + controller.getIterations();
}
}
RealSignal x = null;
Constraint constraint = new Constraint(monitors);
switch (dynamic) {
case RESCALED:
x = signal.duplicate();
constraint.rescaled(x, 0, 255);
break;
case CLIPPED:
x = signal.duplicate();
float[] stats = controller.getStats().getStatsInput();
if (stats != null)
constraint.clipped(x, stats[1], stats[2]);
break;
case NORMALIZED:
x = signal.duplicate();
float[] stats1 = controller.getStats().getStatsInput();
if (stats1 != null)
constraint.normalized(x, stats1[0], stats1[3]);
break;
default:
x = signal;
}
String path = (customPath.equals("$") ? controller.getPath() : customPath) + File.separator;
String filename = path + title + ".tif";
switch (view) {
case STACK:
if (show && !live)
Lab.show(monitors, x, title, type, (center ? x.nz / 2 : oz));
if (save && !live)
Lab.save(monitors, x, filename, type);
break;
case SERIES:
for (int k = 0; k < x.nz; k++) {
RealSignal slice = x.getSlice(k);
String z = "-z" + String.format("%06d", k) ;
if (show && !live)
Lab.show(monitors, slice, title + z, type);
if (save && !live) {
String zfilename = path + title + z + ".tif";
Lab.save(monitors, slice, zfilename, type);
}
}
break;
case ORTHO:
if (!start)
orthoview(monitors, x, title, filename, live);
break;
case FIGURE:
if (!start)
figure(monitors, x, title, filename, live);
break;
case MIP:
if (!start)
mip(monitors, x, title, filename, live);
break;
case PLANAR:
if (!start)
planar(monitors, x, title, filename, live);
break;
default:
break;
}
}
private void mip(Monitors monitors, RealSignal signal, String title, String filename, boolean live) {
RealSignal plane = signal.createMIP();
if (show && live) {
Lab.append(monitors, container, plane, title, type);
}
if (show && !live)
Lab.show(monitors, plane, title, type);
if (save)
Lab.save(monitors, plane, filename, type);
}
private void orthoview(Monitors monitors, RealSignal signal, String title, String filename, boolean live) {
int cx = ox;
int cy = oy;
int cz = oz;
if (center) {
cx = signal.nx / 2;
cy = signal.ny / 2;
cz = signal.nz / 2;
}
RealSignal plane = signal.createOrthoview(cx, cy, cz);
if (show && live) {
if (container == null)
container = Lab.createContainer(monitors, title);
Lab.append(monitors, container, plane, title, type);
}
if (show && !live)
Lab.show(monitors, plane, title, type);
if (save)
Lab.save(monitors, plane, filename, type);
}
+
private void figure(Monitors monitors, RealSignal signal, String title, String filename, boolean live) {
int cx = ox;
int cy = oy;
int cz = oz;
if (center) {
cx = signal.nx / 2;
cy = signal.ny / 2;
cz = signal.nz / 2;
}
RealSignal plane = signal.createFigure(cx, cy, cz);
if (show && live) {
if (container == null)
container = Lab.createContainer(monitors, title);
Lab.append(monitors, container, plane, title, type);
}
if (show && !live)
Lab.show(monitors, plane, title, type);
if (save)
Lab.save(monitors, plane, filename, type);
}
private void planar(Monitors monitors, RealSignal signal, String title, String filename, boolean live) {
RealSignal plane = signal.createPlanar();
if (show && live) {
if (container == null)
container = Lab.createContainer(monitors, title);
Lab.append(monitors, container, plane, title, type);
}
if (show && !live)
Lab.show(monitors, plane, title, type);
if (save)
Lab.save(monitors, plane, filename, type);
}
@Override
public String toString() {
String t = type.name().toLowerCase();
String v = view.name().toLowerCase();
String d = dynamic.name().toLowerCase();
String f = frequency > 0 ? " every " + frequency + " iterations" : "";
String k = (center ? "" : " keypoint = (" + ox + "," + oy + "," + oz + ")");
return v + " " + name + " format = (" + d + ", " + t + ") " + k + f;
}
}
diff --git a/DeconvolutionLab2/src/signal/RealSignal.java b/DeconvolutionLab2/src/signal/RealSignal.java
index 64657a1..f8f1509 100644
--- a/DeconvolutionLab2/src/signal/RealSignal.java
+++ b/DeconvolutionLab2/src/signal/RealSignal.java
@@ -1,790 +1,792 @@
/*
* DeconvolutionLab2
*
* Conditions of use: You are free to use this software for research or
* educational purposes. In addition, we expect you to include adequate
* citations and acknowledgments whenever you present or publish results that
* are based on it.
*
* Reference: DeconvolutionLab2: An Open-Source Software for Deconvolution
* Microscopy D. Sage, L. Donati, F. Soulez, D. Fortun, G. Schmit, A. Seitz,
* R. Guiet, C. Vonesch, M Unser, Methods of Elsevier, 2017.
*/
/*
* Copyright 2010-2017 Biomedical Imaging Group at the EPFL.
*
* This file is part of DeconvolutionLab2 (DL2).
*
* DL2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* DL2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* DL2. If not, see <http://www.gnu.org/licenses/>.
*/
package signal;
import java.awt.image.BufferedImage;
import deconvolutionlab.monitor.Monitors;
public class RealSignal extends Signal implements SignalListener {
private BufferedImage preview;
public RealSignal(String name, int nx, int ny, int nz) {
super(name, nx, ny, nz);
this.data = new float[nz][];
int step = Math.max(1, nz / SignalCollector.NOTIFICATION_RATE);
notify(name, 0);
for (int k = 0; k < nz; k++) {
data[k] = new float[nx * ny];
if (k % step == 0)
notify(name, k * 100.0 / nz);
}
notify(name, 100);
SignalCollector.alloc(this);//name, nx, ny, ny, false);
}
@Override
public void notify(String name, double progress) {
SignalCollector.setProgress(progress);
}
public void copy(RealSignal source) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = source.data[k][i];
}
}
public void setSignal(RealSignal signal) {
int sx = signal.nx;
int mx = Math.min(nx, signal.nx);
int my = Math.min(ny, signal.ny);
int mz = Math.min(nz, signal.nz);
for (int i = 0; i < mx; i++)
for (int j = 0; j < my; j++)
for (int k = 0; k < mz; k++)
data[k][i + nx * j] = signal.data[k][i + sx * j];
}
public void getSignal(RealSignal signal) {
int sx = signal.nx;
int mx = Math.min(nx, signal.nx);
int my = Math.min(ny, signal.ny);
int mz = Math.min(nz, signal.nz);
for (int i = 0; i < mx; i++)
for (int j = 0; j < my; j++)
for (int k = 0; k < mz; k++)
signal.data[k][i + sx * j] = data[k][i + nx * j];
}
/**
* Applies a soft threshold (in-place processing)
*
* @param inferiorLimit
* @param superiorLimit
* @return the instance of the calling object
*/
public RealSignal thresholdSoft(float inferiorLimit, float superiorLimit) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
if (data[k][i] <= inferiorLimit)
data[k][i] += inferiorLimit;
else if (data[k][i] >= superiorLimit)
data[k][i] -= superiorLimit;
else
data[k][i] = 0f;
}
return this;
}
/**
* Multiplies by a signal pixelwise (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal times(RealSignal factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] *= factor.data[k][i];
}
return this;
}
/**
* Multiplies by a scalar factor (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal times(float factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] *= factor;
}
return this;
}
/**
* Adds a signal pixelwise (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal plus(RealSignal factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] += factor.data[k][i];
}
return this;
}
/**
* Subtracts by a signal pixelwise (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal minus(RealSignal factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] -= factor.data[k][i];
}
return this;
}
/**
* Adds a scalar term (in-place processing)
*
* @param term
* @return the instance of the calling object
*/
public RealSignal plus(float term) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] += term;
}
return this;
}
/**
* Subtracts a scalar term (in-place processing)
*
* @param term
* @return the instance of the calling object
*/
public RealSignal minus(float term) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] -= term;
}
return this;
}
/**
* Takes the maximum (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal max(RealSignal factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = Math.max(data[k][i], factor.data[k][i]);
}
return this;
}
/**
* Takes the minimum (in-place processing)
*
* @param factor
* @return the instance of the calling object
*/
public RealSignal min(RealSignal factor) {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = Math.min(data[k][i], factor.data[k][i]);
}
return this;
}
public double[][][] get3DArrayAsDouble() {
double[][][] ar = new double[nx][ny][nz];
for (int k = 0; k < nz; k++) {
float[] s = data[k];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
ar[i][j][k] = s[i + j * nx];
}
}
return ar;
}
public void set3DArrayAsDouble(double[][][] real) {
for (int k = 0; k < nz; k++) {
float[] s = data[k];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
s[i + j * nx] = (float) real[i][j][k];
}
}
}
public RealSignal duplicate() {
RealSignal out = new RealSignal("copy(" + name + ")", nx, ny, nz);
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
System.arraycopy(data[k], 0, out.data[k], 0, nxy);
return out;
}
public float getEnergy() {
int nxy = nx * ny;
float energy = 0.f;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
energy += data[k][i];
return energy;
}
public float[] getStats() {
int nxy = nx * ny;
float min = Float.MAX_VALUE;
float max = -Float.MAX_VALUE;
double norm1 = 0.0;
double norm2 = 0.0;
double mean = 0.0;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
float v = data[k][i];
max = Math.max(max, v);
min = Math.min(min, v);
mean += v;
norm1 += (v > 0 ? v : -v);
norm2 += v * v;
}
mean = mean / (nz * nxy);
norm1 = norm1 / (nz * nxy);
norm2 = Math.sqrt(norm2 / (nz * nxy));
double stdev = 0.0;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
stdev += (data[k][i] - mean) * (data[k][i] - mean);
}
stdev = Math.sqrt(stdev / (nz * nxy));
return new float[] { (float) mean, min, max, (float) stdev, (float) norm1, (float) norm2 };
}
public float[] getExtrema() {
int nxy = nx * ny;
float min = Float.MAX_VALUE;
float max = -Float.MAX_VALUE;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
float v = data[k][i];
max = Math.max(max, v);
min = Math.min(min, v);
}
return new float[] { min, max };
}
public RealSignal normalize(double to) {
if (to == 0)
return this;
int nxy = nx * ny;
float sum = 0f;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
sum += data[k][i];
if (sum != 0f) {
double r = to / sum;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
data[k][i] *= r;
}
return this;
}
public void setSlice(int z, RealSignal slice) {
int mx = slice.nx;
int my = slice.ny;
for (int j = 0; j < Math.min(ny, my); j++)
for (int i = 0; i < Math.min(nx, mx); i++)
data[z][i + nx * j] = slice.data[0][i + mx * j];
}
public RealSignal getSlice(int z) {
RealSignal slice = new RealSignal(name + "_z=" + z, nx, ny, 1);
for (int j = 0; j < nx * ny; j++)
slice.data[0][j] = data[z][j];
return slice;
}
public void multiply(double factor) {
for (int k = 0; k < nz; k++)
for (int i = 0; i < nx * ny; i++)
data[k][i] *= factor;
}
public float[] getInterleaveXYZAtReal() {
float[] interleave = new float[2 * nz * nx * ny];
for (int k = 0; k < nz; k++)
for (int j = 0; j < ny; j++)
for (int i = 0; i < nx; i++)
interleave[2 * (k * nx * ny + j * nx + i)] = data[k][i + j * nx];
return interleave;
}
public void setInterleaveXYZAtReal(float[] interleave) {
for (int k = 0; k < nz; k++)
for (int j = 0; j < ny; j++)
for (int i = 0; i < nx; i++)
data[k][i + nx * j] = interleave[(k * nx * ny + j * nx + i) * 2];
}
public float[] getInterleaveXYAtReal(int k) {
float real[] = new float[nx * ny * 2];
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = i + j * nx;
real[2 * index] = data[k][index];
}
return real;
}
public void setInterleaveXYAtReal(int k, float real[]) {
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int index = i + j * nx;
data[k][index] = real[2 * index];
}
}
public float[] getXYZ() {
int nxy = nx * ny;
float[] d = new float[nz * nx * ny];
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
d[k * nxy + i] = data[k][i];
return d;
}
public void setXYZ(float[] data) {
if (nx * ny * nz != data.length)
return;
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++)
this.data[k][i] = data[k * nxy + i];
}
public float[] getXY(int k) {
return data[k];
}
public void setXY(int k, float slice[]) {
data[k] = slice;
}
public float[] getX(int j, int k) {
float line[] = new float[nx];
for (int i = 0; i < nx; i++)
line[i] = data[k][i + j * nx];
return line;
}
public float[] getZ(int i, int j) {
float line[] = new float[nz];
int index = i + j * nx;
for (int k = 0; k < nz; k++)
line[k] = data[k][index];
return line;
}
public float[] getY(int i, int k) {
float line[] = new float[ny];
for (int j = 0; j < ny; j++)
line[j] = data[k][i + j * nx];
return line;
}
public void setX(int j, int k, float line[]) {
for (int i = 0; i < nx; i++)
data[k][i + j * nx] = line[i];
}
public void setY(int i, int k, float line[]) {
for (int j = 0; j < ny; j++)
data[k][i + j * nx] = line[j];
}
public void setZ(int i, int j, float line[]) {
int index = i + j * nx;
for (int k = 0; k < nz; k++)
data[k][index] = line[k];
}
public void clip(float min, float max) {
for (int k = 0; k < nz; k++)
for (int j = 0; j < ny * nx; j++)
if (data[k][j] < min)
data[k][j] = min;
else if (data[k][j] > max)
data[k][j] = max;
}
public void fill(float constant) {
for (int k = 0; k < nz; k++)
for (int j = 0; j < ny * nx; j++)
data[k][j] = constant;
}
/**
* Get a interpolated pixel value at specific position without specific
* boundary conditions.
*
* If the positions is not on the pixel grid, the method return a
* interpolated value of the pixel (linear interpolation). If the positions
* is outside of this signal, the method return 0.0.
*
* @param x
* position in the X axis
* @param y
* position in the Y axis
* @param z
* position in the Z axis
* @return an interpolated value
*/
public float getInterpolatedPixel(double x, double y, double z) {
if (x > nx - 1)
return 0.0f;
if (y > ny - 1)
return 0.0f;
if (z > nz - 1)
return 0.0f;
if (x < 0)
return 0.0f;
if (y < 0)
return 0.0f;
if (z < 0)
return 0.0f;
int i = (x >= 0.0 ? ((int) x) : ((int) x - 1));
int j = (y >= 0.0 ? ((int) y) : ((int) y - 1));
int k = (z >= 0.0 ? ((int) z) : ((int) z - 1));
boolean fi = (i == nx - 1);
boolean fj = (j == ny - 1);
boolean fk = (k == nz - 1);
int index = i + j * nx;
try {
double v3_000 = data[k][index];
double v3_100 = fi ? v3_000 : data[k][index + 1];
double v3_010 = fj ? v3_000 : data[k][index + nx];
double v3_110 = fi ? (fj ? v3_000 : v3_010) : data[k][index + 1 + nx];
double v3_001 = fk ? v3_000 : data[k + 1][index];
double v3_011 = fk ? (fj ? v3_000 : v3_010) : data[k + 1][index + 1];
double v3_101 = fk ? (fi ? v3_000 : v3_100) : data[k + 1][index + nx];
double v3_111 = fk ? (fj ? (fi ? v3_000 : v3_100) : v3_110) : data[k + 1][index + 1 + nx];
double dx3 = x - (double) i;
double dy3 = y - (double) j;
double dz3 = z - (double) k;
double z1 = (dx3 * (v3_110 * dy3 - v3_100 * (dy3 - 1.0)) - (dx3 - 1.0) * (v3_010 * dy3 - v3_000 * (dy3 - 1.0)));
double z2 = (dx3 * (v3_111 * dy3 - v3_101 * (dy3 - 1.0)) - (dx3 - 1.0) * (v3_011 * dy3 - v3_001 * (dy3 - 1.0)));
return (float)(z2 * dz3 - z1 * (dz3 - 1.0));
}
catch(Exception ex) {
return 0f;
}
}
public RealSignal changeSizeAs(RealSignal model) {
return size(model.nx, model.ny, model.nz);
}
public RealSignal size(int mx, int my, int mz) {
String n = "resize(" + name + ")";
int ox = (mx - nx) / 2;
int oy = (my - ny) / 2;
int oz = (mz - nz) / 2;
RealSignal signal = new RealSignal(n, mx, my, mz);
int vx = Math.min(nx, mx);
int vy = Math.min(ny, my);
int vz = Math.min(nz, mz);
for (int k = 0; k < vz; k++)
for (int j = 0; j < vy; j++)
for (int i = 0; i < vx; i++) {
int pi = ox >= 0 ? i + ox : i;
int qi = ox >= 0 ? i : i - ox;
int pj = oy >= 0 ? j + oy : j;
int qj = oy >= 0 ? j : j - oy;
int pk = oz >= 0 ? k + oz : k;
int qk = oz >= 0 ? k : k - oz;
signal.data[pk][pi + pj * mx] = data[qk][qi + qj * nx];
}
return signal;
}
public RealSignal createOrthoview() {
return createOrthoview(nx / 2, ny / 2, nz / 2);
}
public RealSignal createOrthoview(int hx, int hy, int hz) {
String n = "ortho(" + name + ")";
int vx = nx + nz;
int vy = ny + nz;
RealSignal view = new RealSignal(n, vx, vy, 1);
hx = Math.min(nx - 1, Math.max(0, hx));
hy = Math.min(ny - 1, Math.max(0, hy));
hz = Math.min(nz - 1, Math.max(0, hz));
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++)
view.data[0][x + vx * y] = data[hz][x + nx * y];
for (int z = 0; z < nz; z++)
for (int y = 0; y < ny; y++)
view.data[0][nx + z + vx * y] = data[z][hx + nx * y];
for (int z = 0; z < nz; z++)
for (int x = 0; x < nx; x++)
view.data[0][x + vx * (ny + z)] = data[z][x + nx * hy];
return view;
}
public RealSignal createFigure(int hx, int hy, int hz) {
String n = "figure(" + name + ")";
int vx = nx + nz + 4;
int vy = ny + 2;
float max = this.getExtrema()[1];
RealSignal view = new RealSignal(n, vx, vy, 1);
for (int i = 0; i < vx * vy; i++)
view.data[0][i] = max;
hx = Math.min(nx - 1, Math.max(0, hx));
hy = Math.min(ny - 1, Math.max(0, hy));
hz = Math.min(nz - 1, Math.max(0, hz));
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++)
view.data[0][x + 1 + vx * (y + 1)] = data[hz][x + nx * y];
for (int z = 0; z < nz; z++)
for (int y = 0; y < ny; y++)
view.data[0][nx + 3 + z + vx * (y + 1)] = data[z][hx + nx * y];
return view;
}
public RealSignal createMIP() {
String n = "mip(" + name + ")";
int vx = nx + nz;
int vy = ny + nz;
RealSignal view = new RealSignal(n, vx, vy, 1);
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++)
for (int k = 0; k < nz; k++) {
int index = x + vx * y;
view.data[0][index] = Math.max(view.data[0][index], data[k][x + nx * y]);
}
for (int z = 0; z < nz; z++)
for (int y = 0; y < ny; y++)
for (int x = 0; x < nx; x++) {
int index = nx + z + vx * y;
view.data[0][index] = Math.max(view.data[0][index], data[z][x + nx * y]);
}
for (int z = 0; z < nz; z++)
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++) {
int index = x + vx * (ny + z);
view.data[0][index] = Math.max(view.data[0][index], data[z][x + nx * y]);
}
return view;
}
public RealSignal createPlanar() {
String n = "planar(" + name + ")";
int nr = (int) Math.sqrt(nz);
- int nc = (int) Math.ceil(nz / nr) + 1;
+ int nc = (int) Math.ceil(nz / nr);
+ if (nc*nr < nz)
+ nc++;
int w = nx * nr;
int h = ny * nc;
RealSignal view = new RealSignal(n, w, h, 1);
for (int k = 0; k < nz; k++) {
int col = k % nr;
int row = k / nr;
int offx = col * nx;
int offy = row * ny;
for (int x = 0; x < nx; x++)
for (int y = 0; y < ny; y++)
view.data[0][x + offx + w * (y + offy)] = data[k][x + nx * y];
}
return view;
}
public RealSignal circular() {
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++)
setZ(i, j, rotate(getZ(i, j)));
for (int i = 0; i < nx; i++)
for (int k = 0; k < nz; k++)
setY(i, k, rotate(getY(i, k)));
for (int j = 0; j < ny; j++)
for (int k = 0; k < nz; k++)
setX(j, k, rotate(getX(j, k)));
return this;
}
public RealSignal rescale(Monitors monitors) {
new Constraint(monitors).rescaled(this, 0, 255);
return this;
}
public float[] rotate(float[] buffer) {
int len = buffer.length;
if (len <= 1)
return buffer;
int count = 0;
int offset = 0;
int start = len / 2;
while (count < len) {
int index = offset;
float tmp = buffer[index];
int index2 = (start + index) % len;
while (index2 != offset) {
buffer[index] = buffer[index2];
count++;
index = index2;
index2 = (start + index) % len;
}
buffer[index] = tmp;
count++;
offset++;
}
return buffer;
}
@Override
public String toString() {
return "Real Signal [" + nx + ", " + ny + ", " + nz + "]";
}
public BufferedImage preview() {
if (preview != null)
return preview;
int nxy = nx*ny;
float[] pixels = new float[nx*ny];
for (int i = 0; i < nxy; i++)
for (int k = 0; k < nz; k++) {
pixels[i] = Math.max(pixels[i], data[k][i]);
}
float max = -Float.MAX_VALUE;
float min = Float.MAX_VALUE;
for (int i = 0; i < nxy; i++) {
if (pixels[i] > max)
max = pixels[i];
if (pixels[i] < min)
min = pixels[i];
}
float a = 255f / Math.max(max-min, (float)Operations.epsilon);
preview = new BufferedImage(nx, ny, BufferedImage.TYPE_INT_ARGB);
int alpha = (255 << 24);
for (int i = 0; i < nx; i++)
for (int j = 0; j < ny; j++) {
int v = (int)(a*(pixels[i+j*nx] - min));
preview.setRGB(i, j, alpha | (v << 16) | (v << 8) | v);
}
return preview;
}
public RealSignal log10() {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = (float)Math.log10(data[k][i]);
}
return this;
}
public RealSignal log() {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = (float)Math.log(data[k][i]);
}
return this;
}
public RealSignal exp() {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = (float)Math.exp(data[k][i]);
}
return this;
}
public RealSignal abs() {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = (float)Math.abs(data[k][i]);
}
return this;
}
public RealSignal sqrt() {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = (float)Math.sqrt(data[k][i]);
}
return this;
}
public RealSignal sqr() {
int nxy = nx * ny;
for (int k = 0; k < nz; k++)
for (int i = 0; i < nxy; i++) {
data[k][i] = (float)(data[k][i]*data[k][i]);
}
return this;
}
public RealSignal rescale(double min, double max) {
int nxy = nx * ny;
float minf = (float)min;
float stats[] = getStats();
float a = ((float)max-minf) / (stats[2] - stats[1]);
for(int k=0; k<nz; k++)
for(int i=0; i<nxy; i++) {
data[k][i] = a*(data[k][i] - stats[1]) + minf;
}
return this;
}
}
diff --git a/DeconvolutionLab2/src/signal/SignalCollector.java b/DeconvolutionLab2/src/signal/SignalCollector.java
index f15ac42..8decc1d 100644
--- a/DeconvolutionLab2/src/signal/SignalCollector.java
+++ b/DeconvolutionLab2/src/signal/SignalCollector.java
@@ -1,157 +1,156 @@
package signal;
import java.util.ArrayList;
import javax.swing.JScrollPane;
import bilib.table.CustomizedColumn;
import bilib.table.CustomizedTable;
import bilib.tools.NumFormat;
import deconvolutionlab.system.SystemUsage;
public class SignalCollector {
private static long bytesReal = 0;
private static int countReal = 0;
private static long bytesComplex = 0;
private static int countComplex = 0;
private static double chrono = 0;
private static CustomizedTable table;
private static double progress = 0;
private static int countPeakComplex = 0;
private static int countPeakReal = 0;
private static long bytesPeakComplex = 0;
private static long bytesPeakReal = 0;
private static ArrayList<Signal> signals;
protected final static int NOTIFICATION_RATE = 25;
static {
bytesReal = 0;
countReal = 0;
bytesComplex = 0;
countComplex = 0;
signals = new ArrayList<Signal>();
chrono = System.nanoTime();
ArrayList<CustomizedColumn> columns = new ArrayList<CustomizedColumn>();
columns.add(new CustomizedColumn("Time", String.class, 100, false));
columns.add(new CustomizedColumn("Name", String.class, 600, false));
columns.add(new CustomizedColumn("Dimension", String.class, 60, false));
columns.add(new CustomizedColumn("Count", String.class, 100, false));
columns.add(new CustomizedColumn("Total", String.class, 100, false));
columns.add(new CustomizedColumn("Memory", String.class, 100, false));
table = new CustomizedTable(columns, true);
table.getColumnModel().getColumn(4).setMaxWidth(100);
table.getColumnModel().getColumn(4).setMinWidth(100);
}
public static JScrollPane getPanel(int w, int h) {
return table.getPane(w, h);
}
public static String sumarize() {
- String r = "Signals: " + NumFormat.bytes(bytesReal + bytesComplex);
- return r;
+ return "" + NumFormat.bytes(bytesReal + bytesComplex);
}
public static void clear() {
for(Signal signal : signals) {
for (int z = 0; z < signal.nz; z++)
signal.data[z] = new float[1];
}
signals.clear();
table.removeRows();
}
public static double getProgress() {
return progress;
}
public static void setProgress(double p) {
progress = p;
}
public static void marker(String msg) {
String row[] = { "", msg, "", "", "", "" };
table.append(row);
}
public static void alloc(Signal signal) {
if (signal == null) {
marker("error in allocating");
return;
}
signals.add(signal);
addTable(signal, 1);
}
public static void free(Signal signal) {
if (signal == null) {
marker("error in freeing");
return;
}
for (int z = 0; z < signal.nz; z++)
signal.data[z] = new float[1];
signals.remove(signal);
addTable(signal, -1);
signal = null;
}
public static void addTable(Signal signal, int sign) {
boolean complex = signal instanceof ComplexSignal;
int nx = signal.nx;
int ny = signal.ny;
int nz = signal.nz;
long b = sign * (nx * ny * nz * 4 * (complex ? 2 : 1));
if (complex) {
bytesComplex += b;
countComplex += sign;
}
else {
bytesReal += b;
countReal += sign;
}
bytesPeakComplex = Math.max(bytesPeakComplex, bytesComplex);
bytesPeakReal = Math.max(bytesPeakReal, bytesReal);
countPeakComplex = Math.max(countPeakComplex, countComplex);
countPeakReal = Math.max(countPeakReal, countReal);
String m = NumFormat.bytes(SystemUsage.getHeapUsed());
String t = NumFormat.time(System.nanoTime() - chrono);
String dim = "" + nx + "x" + ny + "x" + nz;
String c = "" + (countReal + countComplex);
String a = NumFormat.bytes(bytesReal + bytesComplex);
String row[] = { t, (sign > 0 ? "+" : "-") + signal.name, dim, c, a, m };
table.append(row);
}
public static int getCountSignals() {
return countComplex + countReal;
}
public static long getBytesSignals() {
return bytesComplex + bytesReal;
}
public static long getBytesPeakSignals() {
return bytesPeakComplex + bytesPeakReal;
}
public static int getCountPeakSignals() {
return countPeakComplex + countPeakReal;
}
public static void resetSignals() {
countPeakComplex = 0;
countPeakReal = 0;
bytesPeakComplex = 0;
bytesPeakReal = 0;
countComplex = 0;
countReal = 0;
bytesComplex = 0;
bytesReal = 0;
}
}
Event Timeline
Log In to Comment