use of gdsc.core.utils.StoredDataStatistics in project GDSC-SMLM by aherbert.
the class TraceMolecules method saveTraceData.
private void saveTraceData(Statistics[] stats) {
// Get the directory
IJ.showStatus("Saving trace data");
String directory = Utils.getDirectory("Trace_data_directory", settings.traceDataDirectory);
if (directory != null) {
settings.traceDataDirectory = directory;
SettingsManager.saveSettings(globalSettings);
for (int i = 0; i < NAMES.length; i++) saveTraceData((StoredDataStatistics) stats[i], NAMES[i], FILENAMES[i]);
}
IJ.showStatus("");
}
use of gdsc.core.utils.StoredDataStatistics in project GDSC-SMLM by aherbert.
the class CreateData method run.
/*
* (non-Javadoc)
*
* @see ij.plugin.PlugIn#run(java.lang.String)
*/
public void run(String arg) {
SMLMUsageTracker.recordPlugin(this.getClass(), arg);
extraOptions = Utils.isExtraOptions();
simpleMode = (arg != null && arg.contains("simple"));
benchmarkMode = (arg != null && arg.contains("benchmark"));
spotMode = (arg != null && arg.contains("spot"));
trackMode = (arg != null && arg.contains("track"));
if ("load".equals(arg)) {
loadBenchmarkData();
return;
}
// Each localisation is a simulated emission of light from a point in space and time
List<LocalisationModel> localisations = null;
// Each localisation set is a collection of localisations that represent all localisations
// with the same ID that are on in the same image time frame (Note: the simulation
// can create many localisations per fluorophore per time frame which is useful when
// modelling moving particles)
List<LocalisationModelSet> localisationSets = null;
// Each fluorophore contains the on and off times when light was emitted
List<? extends FluorophoreSequenceModel> fluorophores = null;
if (simpleMode || benchmarkMode || spotMode) {
if (!showSimpleDialog())
return;
resetMemory();
// 1 second frames
settings.exposureTime = 1000;
areaInUm = settings.size * settings.pixelPitch * settings.size * settings.pixelPitch / 1e6;
// Number of spots per frame
int n = 0;
int[] nextN = null;
SpatialDistribution dist;
if (benchmarkMode) {
// --------------------
// BENCHMARK SIMULATION
// --------------------
// Draw the same point on the image repeatedly
n = 1;
dist = createFixedDistribution();
reportAndSaveFittingLimits(dist);
} else if (spotMode) {
// ---------------
// SPOT SIMULATION
// ---------------
// The spot simulation draws 0 or 1 random point per frame.
// Ensure we have 50% of the frames with a spot.
nextN = new int[settings.particles * 2];
Arrays.fill(nextN, 0, settings.particles, 1);
Random rand = new Random();
rand.shuffle(nextN);
// Only put spots in the central part of the image
double border = settings.size / 4.0;
dist = createUniformDistribution(border);
} else {
// -----------------
// SIMPLE SIMULATION
// -----------------
// The simple simulation draws n random points per frame to achieve a specified density.
// No points will appear in multiple frames.
// Each point has a random number of photons sampled from a range.
// We can optionally use a mask. Create his first as it updates the areaInUm
dist = createDistribution();
// Randomly sample (i.e. not uniform density in all frames)
if (settings.samplePerFrame) {
final double mean = areaInUm * settings.density;
System.out.printf("Mean samples = %f\n", mean);
if (mean < 0.5) {
GenericDialog gd = new GenericDialog(TITLE);
gd.addMessage("The mean samples per frame is low: " + Utils.rounded(mean) + "\n \nContinue?");
gd.enableYesNoCancel();
gd.hideCancelButton();
gd.showDialog();
if (!gd.wasOKed())
return;
}
PoissonDistribution poisson = new PoissonDistribution(createRandomGenerator(), mean, PoissonDistribution.DEFAULT_EPSILON, PoissonDistribution.DEFAULT_MAX_ITERATIONS);
StoredDataStatistics samples = new StoredDataStatistics(settings.particles);
while (samples.getSum() < settings.particles) {
samples.add(poisson.sample());
}
nextN = new int[samples.getN()];
for (int i = 0; i < nextN.length; i++) nextN[i] = (int) samples.getValue(i);
} else {
// Use the density to get the number per frame
n = (int) FastMath.max(1, Math.round(areaInUm * settings.density));
}
}
RandomGenerator random = null;
localisations = new ArrayList<LocalisationModel>(settings.particles);
localisationSets = new ArrayList<LocalisationModelSet>(settings.particles);
final int minPhotons = (int) settings.photonsPerSecond;
final int range = (int) settings.photonsPerSecondMaximum - minPhotons + 1;
if (range > 1)
random = createRandomGenerator();
// Add frames at the specified density until the number of particles has been reached
int id = 0;
int t = 0;
while (id < settings.particles) {
// Allow the number per frame to be specified
if (nextN != null) {
if (t >= nextN.length)
break;
n = nextN[t];
}
// Simulate random positions in the frame for the specified density
t++;
for (int j = 0; j < n; j++) {
final double[] xyz = dist.next();
// Ignore within border. We do not want to draw things we cannot fit.
//if (!distBorder.isWithinXY(xyz))
// continue;
// Simulate random photons
final int intensity = minPhotons + ((random != null) ? random.nextInt(range) : 0);
LocalisationModel m = new LocalisationModel(id, t, xyz, intensity, LocalisationModel.CONTINUOUS);
localisations.add(m);
// Each localisation can be a separate localisation set
LocalisationModelSet set = new LocalisationModelSet(id, t);
set.add(m);
localisationSets.add(set);
id++;
}
}
} else {
if (!showDialog())
return;
resetMemory();
areaInUm = settings.size * settings.pixelPitch * settings.size * settings.pixelPitch / 1e6;
int totalSteps;
double correlation = 0;
ImageModel imageModel;
if (trackMode) {
// ----------------
// TRACK SIMULATION
// ----------------
// In track mode we create fixed lifetime fluorophores that do not overlap in time.
// This is the simplest simulation to test moving molecules.
settings.seconds = (int) Math.ceil(settings.particles * (settings.exposureTime + settings.tOn) / 1000);
totalSteps = 0;
final double simulationStepsPerFrame = (settings.stepsPerSecond * settings.exposureTime) / 1000.0;
imageModel = new FixedLifetimeImageModel(settings.stepsPerSecond * settings.tOn / 1000.0, simulationStepsPerFrame);
} else {
// ---------------
// FULL SIMULATION
// ---------------
// The full simulation draws n random points in space.
// The same molecule may appear in multiple frames, move and blink.
//
// Points are modelled as fluorophores that must be activated and then will
// blink and photo-bleach. The molecules may diffuse and this can be simulated
// with many steps per image frame. All steps from a frame are collected
// into a localisation set which can be drawn on the output image.
SpatialIllumination activationIllumination = createIllumination(settings.pulseRatio, settings.pulseInterval);
// Generate additional frames so that each frame has the set number of simulation steps
totalSteps = (int) Math.ceil(settings.seconds * settings.stepsPerSecond);
// Since we have an exponential decay of activations
// ensure half of the particles have activated by 30% of the frames.
double eAct = totalSteps * 0.3 * activationIllumination.getAveragePhotons();
// Q. Does tOn/tOff change depending on the illumination strength?
imageModel = new ActivationEnergyImageModel(eAct, activationIllumination, settings.stepsPerSecond * settings.tOn / 1000.0, settings.stepsPerSecond * settings.tOffShort / 1000.0, settings.stepsPerSecond * settings.tOffLong / 1000.0, settings.nBlinksShort, settings.nBlinksLong);
imageModel.setUseGeometricDistribution(settings.nBlinksGeometricDistribution);
// Only use the correlation if selected for the distribution
if (PHOTON_DISTRIBUTION[PHOTON_CORRELATED].equals(settings.photonDistribution))
correlation = settings.correlation;
}
imageModel.setRandomGenerator(createRandomGenerator());
imageModel.setPhotonBudgetPerFrame(true);
imageModel.setDiffusion2D(settings.diffuse2D);
imageModel.setRotation2D(settings.rotate2D);
IJ.showStatus("Creating molecules ...");
SpatialDistribution distribution = createDistribution();
List<CompoundMoleculeModel> compounds = createCompoundMolecules();
if (compounds == null)
return;
List<CompoundMoleculeModel> molecules = imageModel.createMolecules(compounds, settings.particles, distribution, settings.rotateInitialOrientation);
// Activate fluorophores
IJ.showStatus("Creating fluorophores ...");
// Note: molecules list will be converted to compounds containing fluorophores
fluorophores = imageModel.createFluorophores(molecules, totalSteps);
if (fluorophores.isEmpty()) {
IJ.error(TITLE, "No fluorophores created");
return;
}
IJ.showStatus("Creating localisations ...");
// TODO - Output a molecule Id for each fluorophore if using compound molecules. This allows analysis
// of the ratio of trimers, dimers, monomers, etc that could be detected.
totalSteps = checkTotalSteps(totalSteps, fluorophores);
if (totalSteps == 0)
return;
imageModel.setPhotonDistribution(createPhotonDistribution());
imageModel.setConfinementDistribution(createConfinementDistribution());
// This should be optimised
imageModel.setConfinementAttempts(10);
localisations = imageModel.createImage(molecules, settings.fixedFraction, totalSteps, (double) settings.photonsPerSecond / settings.stepsPerSecond, correlation, settings.rotateDuringSimulation);
// Re-adjust the fluorophores to the correct time
if (settings.stepsPerSecond != 1) {
final double scale = 1.0 / settings.stepsPerSecond;
for (FluorophoreSequenceModel f : fluorophores) f.adjustTime(scale);
}
// Integrate the frames
localisationSets = combineSimulationSteps(localisations);
localisationSets = filterToImageBounds(localisationSets);
}
datasetNumber++;
localisations = drawImage(localisationSets);
if (localisations == null || localisations.isEmpty()) {
IJ.error(TITLE, "No localisations created");
return;
}
fluorophores = removeFilteredFluorophores(fluorophores, localisations);
double signalPerFrame = showSummary(fluorophores, localisations);
if (!benchmarkMode) {
boolean fullSimulation = (!(simpleMode || spotMode));
saveSimulationParameters(localisations.size(), fullSimulation, signalPerFrame);
}
IJ.showStatus("Saving data ...");
//convertRelativeToAbsolute(molecules);
saveFluorophores(fluorophores);
saveImageResults(results);
saveLocalisations(localisations);
// The settings for the filenames may have changed
SettingsManager.saveSettings(globalSettings);
IJ.showStatus("Done");
}
use of gdsc.core.utils.StoredDataStatistics in project GDSC-SMLM by aherbert.
the class CreateData method showSummary.
private double showSummary(List<? extends FluorophoreSequenceModel> fluorophores, List<LocalisationModel> localisations) {
IJ.showStatus("Calculating statistics ...");
createSummaryTable();
Statistics[] stats = new Statistics[NAMES.length];
for (int i = 0; i < stats.length; i++) {
stats[i] = (settings.showHistograms || alwaysRemoveOutliers[i]) ? new StoredDataStatistics() : new Statistics();
}
// Find the largest timepoint
ImagePlus outputImp = WindowManager.getImage(benchmarkImageId);
int nFrames;
if (outputImp == null) {
sortLocalisationsByTime(localisations);
nFrames = localisations.get(localisations.size() - 1).getTime();
} else {
nFrames = outputImp.getStackSize();
}
int[] countHistogram = new int[nFrames + 1];
// Use the localisations that were drawn to create the sampled on/off times
rebuildNeighbours(localisations);
// Assume that there is at least one localisation
LocalisationModel first = localisations.get(0);
// The current localisation
int currentId = first.getId();
// The last time this localisation was on
int lastT = first.getTime();
// Number of blinks
int blinks = 0;
// On-time of current pulse
int currentT = 0;
double signal = 0;
final double centreOffset = settings.size * 0.5;
// Used to convert the sampled times in frames into seconds
final double framesPerSecond = 1000.0 / settings.exposureTime;
final double gain = (settings.getTotalGain() > 0) ? settings.getTotalGain() : 1;
for (LocalisationModel l : localisations) {
if (l.getData() == null)
System.out.println("No localisation data. This should not happen!");
final double noise = (l.getData() != null) ? l.getData()[1] : 1;
final double intensity = (l.getData() != null) ? l.getData()[4] : l.getIntensity();
final double intensityInPhotons = intensity / gain;
// Q. What if the noise is zero, i.e. no background photon / read noise?
// Just ignore it at current.
final double snr = intensity / noise;
stats[SIGNAL].add(intensityInPhotons);
stats[NOISE].add(noise / gain);
if (noise != 0)
stats[SNR].add(snr);
//if (l.isContinuous())
if (l.getNext() != null && l.getPrevious() != null) {
stats[SIGNAL_CONTINUOUS].add(intensityInPhotons);
if (noise != 0)
stats[SNR_CONTINUOUS].add(snr);
}
int id = l.getId();
// Check if this a new fluorophore
if (currentId != id) {
// Add previous fluorophore
stats[SAMPLED_BLINKS].add(blinks);
stats[SAMPLED_T_ON].add(currentT / framesPerSecond);
stats[TOTAL_SIGNAL].add(signal);
// Reset
blinks = 0;
currentT = 1;
currentId = id;
signal = intensityInPhotons;
} else {
signal += intensityInPhotons;
// Check if the current fluorophore pulse is broken (i.e. a blink)
if (l.getTime() - 1 > lastT) {
blinks++;
stats[SAMPLED_T_ON].add(currentT / framesPerSecond);
currentT = 1;
stats[SAMPLED_T_OFF].add(((l.getTime() - 1) - lastT) / framesPerSecond);
} else {
// Continuous on-time
currentT++;
}
}
lastT = l.getTime();
countHistogram[lastT]++;
stats[X].add((l.getX() - centreOffset) * settings.pixelPitch);
stats[Y].add((l.getY() - centreOffset) * settings.pixelPitch);
stats[Z].add(l.getZ() * settings.pixelPitch);
}
// Final fluorophore
stats[SAMPLED_BLINKS].add(blinks);
stats[SAMPLED_T_ON].add(currentT / framesPerSecond);
stats[TOTAL_SIGNAL].add(signal);
// Samples per frame
for (int t = 1; t < countHistogram.length; t++) stats[SAMPLES].add(countHistogram[t]);
if (fluorophores != null) {
for (FluorophoreSequenceModel f : fluorophores) {
stats[BLINKS].add(f.getNumberOfBlinks());
// On-time
for (double t : f.getOnTimes()) stats[T_ON].add(t);
// Off-time
for (double t : f.getOffTimes()) stats[T_OFF].add(t);
}
} else {
// show no blinks
stats[BLINKS].add(0);
stats[T_ON].add(1);
//stats[T_OFF].add(0);
}
if (results != null) {
final boolean emCCD = (settings.getEmGain() > 1);
// Convert depth-of-field to pixels
final double depth = settings.depthOfField / settings.pixelPitch;
for (PeakResult r : results.getResults()) {
final double precision = r.getPrecision(settings.pixelPitch, gain, emCCD);
stats[PRECISION].add(precision);
// The error stores the z-depth in pixels
if (Math.abs(r.error) < depth)
stats[PRECISION_IN_FOCUS].add(precision);
stats[WIDTH].add(r.getSD());
}
// Compute density per frame. Multithread for speed
if (settings.densityRadius > 0) {
IJ.showStatus("Calculating density ...");
ExecutorService threadPool = Executors.newFixedThreadPool(Prefs.getThreads());
List<Future<?>> futures = new LinkedList<Future<?>>();
final ArrayList<float[]> coords = new ArrayList<float[]>();
int t = results.getHead().getFrame();
final Statistics densityStats = stats[DENSITY];
final float radius = (float) (settings.densityRadius * getHWHM());
final Rectangle bounds = results.getBounds();
currentIndex = 0;
finalIndex = results.getTail().getFrame();
// Store the density for each result.
int[] allDensity = new int[results.size()];
int allIndex = 0;
for (PeakResult r : results.getResults()) {
if (t != r.getFrame()) {
allIndex += runDensityCalculation(threadPool, futures, coords, densityStats, radius, bounds, allDensity, allIndex);
}
coords.add(new float[] { r.getXPosition(), r.getYPosition() });
t = r.getFrame();
}
runDensityCalculation(threadPool, futures, coords, densityStats, radius, bounds, allDensity, allIndex);
Utils.waitForCompletion(futures);
threadPool.shutdownNow();
threadPool = null;
IJ.showProgress(1);
// Split results into singles (density = 0) and clustered (density > 0)
MemoryPeakResults singles = copyMemoryPeakResults("No Density");
MemoryPeakResults clustered = copyMemoryPeakResults("Density");
int i = 0;
for (PeakResult r : results.getResults()) {
// Store density in the original value field
r.origValue = allDensity[i];
if (allDensity[i++] == 0)
singles.add(r);
else
clustered.add(r);
}
}
}
StringBuilder sb = new StringBuilder();
sb.append(datasetNumber).append("\t");
sb.append((fluorophores == null) ? localisations.size() : fluorophores.size()).append("\t");
sb.append(stats[SAMPLED_BLINKS].getN() + (int) stats[SAMPLED_BLINKS].getSum()).append("\t");
sb.append(localisations.size()).append("\t");
sb.append(nFrames).append("\t");
sb.append(Utils.rounded(areaInUm)).append("\t");
sb.append(Utils.rounded(localisations.size() / (areaInUm * nFrames), 4)).append("\t");
sb.append(Utils.rounded(getHWHM(), 4)).append("\t");
double s = getPsfSD();
sb.append(Utils.rounded(s, 4)).append("\t");
s *= settings.pixelPitch;
final double sa = PSFCalculator.squarePixelAdjustment(s, settings.pixelPitch) / settings.pixelPitch;
sb.append(Utils.rounded(sa, 4)).append("\t");
// Width not valid for the Image PSF
int nStats = (imagePSF) ? stats.length - 1 : stats.length;
for (int i = 0; i < nStats; i++) {
double centre = (alwaysRemoveOutliers[i]) ? ((StoredDataStatistics) stats[i]).getStatistics().getPercentile(50) : stats[i].getMean();
sb.append(Utils.rounded(centre, 4)).append("\t");
}
if (java.awt.GraphicsEnvironment.isHeadless()) {
IJ.log(sb.toString());
return stats[SIGNAL].getMean();
} else {
summaryTable.append(sb.toString());
}
// Show histograms
if (settings.showHistograms) {
IJ.showStatus("Calculating histograms ...");
boolean[] chosenHistograms = getChoosenHistograms();
WindowOrganiser wo = new WindowOrganiser();
boolean requireRetile = false;
for (int i = 0; i < NAMES.length; i++) {
if (chosenHistograms[i]) {
wo.add(Utils.showHistogram(TITLE, (StoredDataStatistics) stats[i], NAMES[i], (integerDisplay[i]) ? 1 : 0, (settings.removeOutliers || alwaysRemoveOutliers[i]) ? 2 : 0, settings.histogramBins * ((integerDisplay[i]) ? 100 : 1)));
requireRetile = requireRetile || Utils.isNewWindow();
}
}
wo.tile();
}
IJ.showStatus("");
return stats[SIGNAL].getMean();
}
use of gdsc.core.utils.StoredDataStatistics in project GDSC-SMLM by aherbert.
the class ImageModel method createImage.
/**
* Simulate an image of fluorophores. The total amount of time a fluorophore is on (i.e. sum of tOn) is used to
* create the signal strength using the specified correlation.
* <p>
* A second set of fluorophores, independent of the first, are generated using
* {@link #createFluorophores(List, int)}. The correlated on-times will be created by combining the times using the
* provided correlation (r):
*
* <pre>
* // X1 : Fluorophore total on-times
* // X2 : Independently generated fluorophore total on-times
* // r : correlation
* a = sqrt(1 - r * r)
* newX = (r * X1 + a * X2) / (r + a)
* </pre>
*
* The signal is proportional to newly generated on-times (newX) with an average of the specified photon budget.
* <p>
* The photon budget can either be distributed evenly over the fluorophore lifetime or per frame (see
* {@link #isPhotonBudgetPerFrame()}). Each frame signal output will be subject to Poisson sampling.
* <p>
* If the input correlation is zero then the number of photons will be sampled from the configured photon
* distribution or, if this is null, will be uniform.
* <p>
* A random fraction of the fluorophores will move using a random walk with the diffusion coefficient defined in the
* compound.
*
* @param compoundFluorophores
* The compounds containing the fluorophores
* @param fixedFraction
* The fraction of molecules that are fixed
* @param maxFrames
* The maximum frame for the simulation
* @param photonBudget
* the average number of photons per frame/lifetime; see {@link #isPhotonBudgetPerFrame()}
* @param correlation
* The correlation between the number of photons and the total on-time of the fluorophore
* @param rotate
* Rotate the molecule per frame
* @return the localisations
*/
public List<LocalisationModel> createImage(List<CompoundMoleculeModel> compoundFluorophores, double fixedFraction, int maxFrames, double photonBudget, double correlation, boolean rotate) {
List<LocalisationModel> localisations = new ArrayList<LocalisationModel>();
// Extract the fluorophores in all the compounds
ArrayList<FluorophoreSequenceModel> fluorophores = new ArrayList<FluorophoreSequenceModel>(compoundFluorophores.size());
for (CompoundMoleculeModel c : compoundFluorophores) {
for (int i = c.getSize(); i-- > 0; ) if (c.getMolecule(i) instanceof FluorophoreSequenceModel) {
fluorophores.add((FluorophoreSequenceModel) c.getMolecule(i));
}
}
final int nMolecules = fluorophores.size();
// Check the correlation bounds.
// Correlation for photons per frame verses total on time should be negative.
// Correlation for total photons verses total on time should be positive.
double r;
if (photonBudgetPerFrame)
r = (correlation < -1) ? -1 : (correlation > 0) ? 0 : correlation;
else
r = (correlation < 0) ? 0 : (correlation > 1) ? 1 : correlation;
// Create a photon budget for each fluorophore
double[] photons = new double[nMolecules];
// Generate a second set of on times using the desired correlation
if (r != 0) {
// Observations on real data show:
// - there is a weak positive correlation between total photons and time
// - There is a weak negative correlation between photons per frame and total on-time
// How to generate a random correlation:
// http://www.uvm.edu/~dhowell/StatPages/More_Stuff/CorrGen.html
// http://stats.stackexchange.com/questions/13382/how-to-define-a-distribution-such-that-draws-from-it-correlate-with-a-draw-from
// Used for debugging the correlation
//StoredDataStatistics onTime = new StoredDataStatistics();
//StoredDataStatistics allPhotons = new StoredDataStatistics();
//PearsonsCorrelation c = new PearsonsCorrelation();
// Create a second set of fluorophores. This is used to generate the correlated photon data
List<FluorophoreSequenceModel> fluorophores2 = new ArrayList<FluorophoreSequenceModel>();
while (fluorophores2.size() < fluorophores.size()) {
FluorophoreSequenceModel f = createFluorophore(0, new double[] { 0, 0, 0 }, maxFrames);
if (f != null)
fluorophores2.add(f);
}
final double a = Math.sqrt(1 - r * r);
// Q - How to generate a negative correlation?
// Generate a positive correlation then invert the data and shift to the same range
boolean invert = (r < 0);
r = Math.abs(r);
StoredDataStatistics correlatedOnTime = new StoredDataStatistics();
for (int i = 0; i < nMolecules; i++) {
final double X = getTotalOnTime(fluorophores.get(i));
final double Z = getTotalOnTime(fluorophores2.get(i));
//onTime.add(X);
correlatedOnTime.add((r * X + a * Z) / (r + a));
}
if (invert) {
final double min = correlatedOnTime.getStatistics().getMin();
final double range = correlatedOnTime.getStatistics().getMax() - min;
StoredDataStatistics newCorrelatedOnTime = new StoredDataStatistics();
for (double d : correlatedOnTime.getValues()) {
newCorrelatedOnTime.add(range - d + min);
}
correlatedOnTime = newCorrelatedOnTime;
}
// Get the average on time from the correlated sample.
// Using the population value (tOn * (1+nBlinks)) over-estimates the on time.
final double averageTotalTOn = correlatedOnTime.getMean();
// Now create the localisations
double[] correlatedOnTimes = correlatedOnTime.getValues();
for (int i = 0; i < nMolecules; i++) {
// Generate photons using the correlated on time data
double p = photonBudget * correlatedOnTimes[i] / averageTotalTOn;
//final double X = getTotalOnTime(fluorophores.get(i));
//double p = (X > 0) ? photonBudget * correlatedOnTimes[i] / X : 0;
//double p = (X > 0) ? randomGenerator.nextGamma(photonBudget, correlatedOnTimes[i] / X) : 0;
//double p = randomGenerator.nextGamma(photonBudget, correlatedOnTimes[i] / X);
//allPhotons.add(p);
photons[i] = p;
}
//System.out.printf("t = %f, p = %f, R = %f\n", averageTotalTOn, allPhotons.getMean(),
// c.correlation(onTime.getValues(), allPhotons.getValues()));
} else {
// running again with a different shape parameter / photon budget.
if (photonDistribution != null) {
// Ensure the custom distribution is scaled to the correct photon budget
final double photonScale = photonBudget / photonDistribution.getNumericalMean();
// Generate photons sampling from the photon budget
for (int i = 0; i < nMolecules; i++) {
photons[i] = photonDistribution.sample() * photonScale;
}
} else {
// No distribution so use the same number for all
Arrays.fill(photons, photonBudget);
}
}
int photonIndex = 0;
for (CompoundMoleculeModel c : compoundFluorophores) {
final boolean fixed = (random.nextDouble() < fixedFraction);
photonIndex += createLocalisation(c, localisations, fixed, maxFrames, photons, photonIndex, !fixed && rotate);
}
sortByTime(localisations);
return localisations;
}
use of gdsc.core.utils.StoredDataStatistics in project GDSC-SMLM by aherbert.
the class TraceDiffusion method calculateDiffusionCoefficient.
/**
* Calculate the diffusion coefficient (D) of the molecule. This is done by using the mean-squared deviation
* between frames divided by the time interval (delta) between frames. This is divided by 4 to produce the diffusion
* coefficient from two-dimensional distance analysis.
* <p>
* See Uphoff, et al, 2013. Single-molecule DNA repair in live bacteria, PNAS 110, 8063-8068
*
* @param msdPerMoleculeAdjacent
* @return The D per molecule
*/
private StoredDataStatistics calculateDiffusionCoefficient(StoredDataStatistics msdPerMoleculeAdjacent) {
StoredDataStatistics dPerMolecule = new StoredDataStatistics();
final double diffusionCoefficientConversion = 1.0 / 4.0;
for (double msd : msdPerMoleculeAdjacent.getValues()) {
dPerMolecule.add(msd * diffusionCoefficientConversion);
}
return dPerMolecule;
}
Aggregations