Skip to content

Commit

Permalink
Provide initial guess for bootstrap repeats
Browse files Browse the repository at this point in the history
Add debug mode to allow logging to be controlled.
  • Loading branch information
aherbert committed Sep 20, 2023
1 parent 9f6bef4 commit 27fb144
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
6 changes: 6 additions & 0 deletions docs/analysis_plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,9 @@ When the plugin runs a dialog is presented that allows multiple datasets to be s
* - Show QQ plot
- Display a quantile-quantile plot of the model against the data distribution. The quantile for the model is taken using the cumulative probability of the data as (k - 1/3) / (n + 1/3).

* - Debug
- If enabled extra information is logged to the ``ImageJ`` log window.

The analysis extracts the tracks and filters them to stationary molecules. A histogram of residence times is created and fit using the exponential model (see :numref:`Figure %s <fig_residence_time_analysis_histogram>`). Fit progress is recorded in the ``ImageJ`` log window. Bootstrapping is optionally used on the data to produce a 95% confidence interval for the fit parameters.

.. _fig_residence_time_analysis_histogram:
Expand Down Expand Up @@ -1846,6 +1849,9 @@ The following parameters can be set:
* - Show QQ plot
- Display a quantile-quantile plot of the model against the data distribution. The quantile for the model is taken using the cumulative probability of the data as (k - 1/3) / (n + 1/3).

* - Debug
- If enabled extra information is logged to the ``ImageJ`` log window.

The simulation allows experimenting with the exposure time and number of samples required to obtain satisfactory results for the populations of bound molecules.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.math3.optim.InitialGuess;
import org.apache.commons.numbers.rootfinder.BrentSolver;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.AliasMethodDiscreteSampler;
Expand Down Expand Up @@ -134,6 +135,7 @@ private static class Settings {
Seed bootstrapSeed;
int maxPopulations;
boolean showQQplot;
boolean debug;

Settings() {
// Set defaults
Expand Down Expand Up @@ -172,6 +174,7 @@ private static class Settings {
bootstrapSeed = source.bootstrapSeed;
showQQplot = source.showQQplot;
maxPopulations = source.maxPopulations;
debug = source.debug;
}

Settings copy() {
Expand Down Expand Up @@ -380,6 +383,7 @@ private boolean showDialog() {
gd.addNumericField("Boostrap_repeats", settings.bootstrapRepeats, 0);
gd.addHexField("Bootstrap_seed", settings.bootstrapSeed.toBytes());
gd.addCheckbox("Show_QQ_plot", settings.showQQplot);
gd.addCheckbox("Debug", settings.debug);

gd.showDialog();
if (gd.wasCanceled() || gd.invalidNumber()) {
Expand All @@ -397,6 +401,7 @@ private boolean showDialog() {
settings.bootstrapRepeats = (int) gd.getNextNumber();
settings.bootstrapSeed = Seed.from(gd.getNextHexBytes());
settings.showQQplot = gd.getNextBoolean();
settings.debug = gd.getNextBoolean();

return !gd.invalidNumber();
}
Expand Down Expand Up @@ -656,6 +661,7 @@ private boolean showSimulationDialog() {
gd.addNumericField("Boostrap_repeats", settings.bootstrapRepeats, 0);
gd.addHexField("Bootstrap_seed", settings.bootstrapSeed.toBytes());
gd.addCheckbox("Show_QQ_plot", settings.showQQplot);
gd.addCheckbox("Debug", settings.debug);

gd.showDialog();

Expand All @@ -675,6 +681,7 @@ private boolean showSimulationDialog() {
settings.bootstrapRepeats = (int) gd.getNextNumber();
settings.bootstrapSeed = Seed.from(gd.getNextHexBytes());
settings.showQQplot = gd.getNextBoolean();
settings.debug = gd.getNextBoolean();

return !gd.invalidNumber();
}
Expand Down Expand Up @@ -796,11 +803,12 @@ private void runAnalysis(String title, double exposureTime, int[] counts, boolea
// Bootstrap the data to create confidence intervals for model parameters.
// Do this in parallel. This could be made an option.
final long start = System.nanoTime();
final InitialGuess guess = createGuess(m);
final Ticker ticker = ImageJUtils.createTicker(bootstrapSamples.length,
Runtime.getRuntime().availableProcessors(), "Fitting Bootstrap samples");
final List<Model> models = Arrays.stream(bootstrapSamples).parallel().map(h -> {
final Pair<FitResult, Model> fit =
ResidenceTimeFitting.of(exposureTime / 1000, h, clipped).fit(m.getSize());
ResidenceTimeFitting.of(exposureTime / 1000, h, clipped).fit(m.getSize(), guess);
ticker.tick();
return fit;
}).filter(fitAccept).map(Pair::getRight).collect(Collectors.toList());
Expand Down Expand Up @@ -936,6 +944,24 @@ private static Predicate<Pair<FitResult, Model>> createFitAcceptPredicate(double
};
}

/**
* Creates the guess from the fitted model.
*
* @param m the model
* @return the initial guess
*/
private static InitialGuess createGuess(Model m) {
int size = m.getSize();
if (size == 1) {
return new InitialGuess(new double[] {m.getRate(0)});
} else if (size == 2) {
return new InitialGuess(new double[] {m.getRate(0), m.getRate(1), m.getFraction(0)});
}
// Assume size is 3
return new InitialGuess(new double[] {m.getRate(0), m.getRate(1), m.getRate(2),
m.getFraction(0), m.getFraction(1), m.getFraction(2)});
}

/**
* Appends the value to the StringBuilder. The text is prefixed with a tab character and values
* are delimited by commas.
Expand Down Expand Up @@ -987,8 +1013,8 @@ private static double getConfidenceInterval(List<Model> models, ToDoubleFunction
*
* @return the timing log level
*/
private static Level getTimingLogLevel() {
return IJ.debugMode ? Level.INFO : Level.FINE;
private Level getTimingLogLevel() {
return settings.debug ? Level.INFO : Level.FINE;
}

/**
Expand Down

0 comments on commit 27fb144

Please sign in to comment.