use of gdsc.smlm.results.Calibration in project GDSC-SMLM by aherbert.
the class BlinkEstimatorTest method estimateBlinking.
private TIntHashSet estimateBlinking(double nBlinks, double tOn, double tOff, int particles, double fixedFraction, boolean timeAtLowerBound, boolean doAssert) {
SpatialIllumination activationIllumination = new UniformIllumination(100);
int totalSteps = 100;
double eAct = totalSteps * 0.3 * activationIllumination.getAveragePhotons();
ImageModel imageModel = new ActivationEnergyImageModel(eAct, activationIllumination, tOn, 0, tOff, 0, nBlinks);
imageModel.setRandomGenerator(rand);
double[] max = new double[] { 256, 256, 32 };
double[] min = new double[3];
SpatialDistribution distribution = new UniformDistribution(min, max, rand.nextInt());
List<CompoundMoleculeModel> compounds = new ArrayList<CompoundMoleculeModel>(1);
CompoundMoleculeModel c = new CompoundMoleculeModel(1, 0, 0, 0, Arrays.asList(new MoleculeModel(0, 0, 0, 0)));
c.setDiffusionRate(diffusionRate);
c.setDiffusionType(DiffusionType.RANDOM_WALK);
compounds.add(c);
List<CompoundMoleculeModel> molecules = imageModel.createMolecules(compounds, particles, distribution, false);
// Activate fluorophores
List<? extends FluorophoreSequenceModel> fluorophores = imageModel.createFluorophores(molecules, totalSteps);
totalSteps = checkTotalSteps(totalSteps, fluorophores);
List<LocalisationModel> localisations = imageModel.createImage(molecules, fixedFraction, totalSteps, photons, 0.5, false);
// // Remove localisations to simulate missed counts.
// List<LocalisationModel> newLocalisations = new ArrayList<LocalisationModel>(localisations.size());
// boolean[] id = new boolean[fluorophores.size() + 1];
// Statistics photonStats = new Statistics();
// for (LocalisationModel l : localisations)
// {
// photonStats.add(l.getIntensity());
// // Remove by intensity threshold and optionally at random.
// if (l.getIntensity() < minPhotons || rand.nextDouble() < pDelete)
// continue;
// newLocalisations.add(l);
// id[l.getId()] = true;
// }
// localisations = newLocalisations;
// System.out.printf("Photons = %f\n", photonStats.getMean());
//
// List<FluorophoreSequenceModel> newFluorophores = new ArrayList<FluorophoreSequenceModel>(fluorophores.size());
// for (FluorophoreSequenceModel f : fluorophores)
// {
// if (id[f.getId()])
// newFluorophores.add(f);
// }
// fluorophores = newFluorophores;
MemoryPeakResults results = new MemoryPeakResults();
results.setCalibration(new Calibration(pixelPitch, 1, msPerFrame));
for (LocalisationModel l : localisations) {
// Remove by intensity threshold and optionally at random.
if (l.getIntensity() < minPhotons || rand.nextDouble() < pDelete)
continue;
float[] params = new float[7];
params[Gaussian2DFunction.X_POSITION] = (float) l.getX();
params[Gaussian2DFunction.Y_POSITION] = (float) l.getY();
params[Gaussian2DFunction.X_SD] = params[Gaussian2DFunction.Y_SD] = psfWidth;
params[Gaussian2DFunction.SIGNAL] = (float) (l.getIntensity());
results.addf(l.getTime(), 0, 0, 0, 0, 0, params, null);
}
// Add random localisations
for (int i = (int) (localisations.size() * pAdd); i-- > 0; ) {
float[] params = new float[7];
params[Gaussian2DFunction.X_POSITION] = (float) (rand.nextDouble() * max[0]);
params[Gaussian2DFunction.Y_POSITION] = (float) (rand.nextDouble() * max[1]);
params[Gaussian2DFunction.X_SD] = params[Gaussian2DFunction.Y_SD] = psfWidth;
// Intensity doesn't matter at the moment for tracing
params[Gaussian2DFunction.SIGNAL] = (float) (photons);
results.addf(1 + rand.nextInt(totalSteps), 0, 0, 0, 0, 0, params, null);
}
// Get actual simulated stats ...
Statistics statsNBlinks = new Statistics();
Statistics statsTOn = new Statistics();
Statistics statsTOff = new Statistics();
Statistics statsSampledNBlinks = new Statistics();
Statistics statsSampledTOn = new Statistics();
StoredDataStatistics statsSampledTOff = new StoredDataStatistics();
for (FluorophoreSequenceModel f : fluorophores) {
statsNBlinks.add(f.getNumberOfBlinks());
statsTOn.add(f.getOnTimes());
statsTOff.add(f.getOffTimes());
int[] on = f.getSampledOnTimes();
statsSampledNBlinks.add(on.length);
statsSampledTOn.add(on);
statsSampledTOff.add(f.getSampledOffTimes());
}
System.out.printf("N = %d (%d), N-blinks = %f, tOn = %f, tOff = %f, Fixed = %f\n", fluorophores.size(), localisations.size(), nBlinks, tOn, tOff, fixedFraction);
System.out.printf("Actual N-blinks = %f (%f), tOn = %f (%f), tOff = %f (%f), 95%% = %f, max = %f\n", statsNBlinks.getMean(), statsSampledNBlinks.getMean(), statsTOn.getMean(), statsSampledTOn.getMean(), statsTOff.getMean(), statsSampledTOff.getMean(), statsSampledTOff.getStatistics().getPercentile(95), statsSampledTOff.getStatistics().getMax());
System.out.printf("-=-=--=-\n");
BlinkEstimator be = new BlinkEstimator();
be.maxDarkTime = (int) (tOff * 10);
be.msPerFrame = msPerFrame;
be.relativeDistance = false;
double d = ImageModel.getRandomMoveDistance(diffusionRate);
be.searchDistance = (fixedFraction < 1) ? Math.sqrt(2 * d * d) * 3 : 0;
be.timeAtLowerBound = timeAtLowerBound;
be.showPlots = false;
//Assert.assertTrue("Max dark time must exceed the dark time of the data (otherwise no plateau)",
// be.maxDarkTime > statsSampledTOff.getStatistics().getMax());
int nMolecules = fluorophores.size();
if (usePopulationStatistics) {
nBlinks = statsNBlinks.getMean();
tOff = statsTOff.getMean();
} else {
nBlinks = statsSampledNBlinks.getMean();
tOff = statsSampledTOff.getMean();
}
// See if any fitting regime gets a correct answer
TIntHashSet ok = new TIntHashSet();
for (int nFittedPoints = MIN_FITTED_POINTS; nFittedPoints <= MAX_FITTED_POINTS; nFittedPoints++) {
be.nFittedPoints = nFittedPoints;
be.computeBlinkingRate(results, true);
double moleculesError = DoubleEquality.relativeError(nMolecules, be.getNMolecules());
double blinksError = DoubleEquality.relativeError(nBlinks, be.getNBlinks());
double offError = DoubleEquality.relativeError(tOff * msPerFrame, be.getTOff());
System.out.printf("Error %d: N = %f, blinks = %f, tOff = %f : %f\n", nFittedPoints, moleculesError, blinksError, offError, (moleculesError + blinksError + offError) / 3);
if (moleculesError < relativeError && blinksError < relativeError && offError < relativeError) {
ok.add(nFittedPoints);
System.out.printf("-=-=--=-\n");
System.out.printf("*** Correct at %d fitted points ***\n", nFittedPoints);
if (doAssert)
break;
}
//if (!be.isIncreaseNFittedPoints())
// break;
}
System.out.printf("-=-=--=-\n");
if (doAssert)
Assert.assertFalse(ok.isEmpty());
//Assert.assertEquals("Invalid t-off", tOff * msPerFrame, be.getTOff(), tOff * msPerFrame * relativeError);
return ok;
}
use of gdsc.smlm.results.Calibration in project GDSC-SMLM by aherbert.
the class DiffusionRateTest method aggregateIntoFrames.
private void aggregateIntoFrames(ArrayList<Point> points, boolean addError, double precisionInPixels, RandomGenerator[] random) {
if (myAggregateSteps < 1)
return;
MemoryPeakResults results = new MemoryPeakResults(points.size() / myAggregateSteps);
Calibration cal = new Calibration(settings.pixelPitch, 1, myAggregateSteps * 1000.0 / settings.stepsPerSecond);
results.setCalibration(cal);
results.setName(TITLE + " Aggregated");
MemoryPeakResults.addResults(results);
lastSimulatedDataset[1] = results.getName();
int id = 0;
int peak = 1;
int n = 0;
double cx = 0, cy = 0;
// Get the mean square distance
double sum = 0;
int count = 0;
PeakResult last = null;
for (Point result : points) {
final boolean newId = result.id != id;
if (n >= myAggregateSteps || newId) {
if (n != 0) {
final float[] params = new float[7];
double[] xyz = new double[] { cx / n, cy / n };
if (addError)
xyz = addError(xyz, precisionInPixels, random);
params[Gaussian2DFunction.X_POSITION] = (float) xyz[0];
params[Gaussian2DFunction.Y_POSITION] = (float) xyz[1];
params[Gaussian2DFunction.SIGNAL] = n;
params[Gaussian2DFunction.X_SD] = params[Gaussian2DFunction.Y_SD] = 1;
final float noise = 0.1f;
PeakResult r = new ExtendedPeakResult(peak, (int) params[Gaussian2DFunction.X_POSITION], (int) params[Gaussian2DFunction.Y_POSITION], n, 0, noise, params, null, peak, id);
results.add(r);
if (last != null) {
sum += last.distance2(r);
count++;
}
last = r;
n = 0;
cx = cy = 0;
peak++;
}
if (newId) {
// Increment the frame so that tracing analysis can distinguish traces
peak++;
last = null;
id = result.id;
}
}
n++;
cx += result.x;
cy += result.y;
}
// Final peak
if (n != 0) {
final float[] params = new float[7];
double[] xyz = new double[] { cx / n, cy / n };
if (addError)
xyz = addError(xyz, precisionInPixels, random);
params[Gaussian2DFunction.X_POSITION] = (float) xyz[0];
params[Gaussian2DFunction.Y_POSITION] = (float) xyz[1];
params[Gaussian2DFunction.SIGNAL] = n;
params[Gaussian2DFunction.X_SD] = params[Gaussian2DFunction.Y_SD] = 1;
final float noise = 0.1f;
PeakResult r = new ExtendedPeakResult(peak, (int) params[Gaussian2DFunction.X_POSITION], (int) params[Gaussian2DFunction.Y_POSITION], n, 0, noise, params, null, peak, id);
results.add(r);
if (last != null) {
sum += last.distance2(r);
count++;
}
}
// MSD in pixels^2 / frame
double msd = sum / count;
// Convert to um^2/second
Utils.log("Aggregated data D=%s um^2/s, Precision=%s nm, N=%d, step=%s s, mean=%s um^2, MSD = %s um^2/s", Utils.rounded(settings.diffusionRate), Utils.rounded(myPrecision), count, Utils.rounded(results.getCalibration().getExposureTime() / 1000), Utils.rounded(msd / conversionFactor), Utils.rounded((msd / conversionFactor) / (results.getCalibration().getExposureTime() / 1000)));
msdAnalysis(points);
}
use of gdsc.smlm.results.Calibration in project GDSC-SMLM by aherbert.
the class BenchmarkFit method showDialog.
private boolean showDialog() {
GenericDialog gd = new GenericDialog(TITLE);
gd.addHelp(About.HELP_URL);
final double sa = getSa();
gd.addMessage(String.format("Fits the benchmark image created by CreateData plugin.\nPSF width = %s, adjusted = %s", Utils.rounded(benchmarkParameters.s / benchmarkParameters.a), Utils.rounded(sa)));
// For each new benchmark width, reset the PSF width to the square pixel adjustment
if (lastS != benchmarkParameters.s) {
lastS = benchmarkParameters.s;
psfWidth = sa;
}
final String filename = SettingsManager.getSettingsFilename();
GlobalSettings settings = SettingsManager.loadSettings(filename);
fitConfig = settings.getFitEngineConfiguration().getFitConfiguration();
fitConfig.setNmPerPixel(benchmarkParameters.a);
gd.addSlider("Region_size", 2, 20, regionSize);
gd.addNumericField("PSF_width", psfWidth, 3);
String[] solverNames = SettingsManager.getNames((Object[]) FitSolver.values());
gd.addChoice("Fit_solver", solverNames, solverNames[fitConfig.getFitSolver().ordinal()]);
String[] functionNames = SettingsManager.getNames((Object[]) FitFunction.values());
gd.addChoice("Fit_function", functionNames, functionNames[fitConfig.getFitFunction().ordinal()]);
gd.addCheckbox("Offset_fit", offsetFitting);
gd.addNumericField("Start_offset", startOffset, 3);
gd.addCheckbox("Include_CoM_fit", comFitting);
gd.addCheckbox("Background_fitting", backgroundFitting);
gd.addMessage("Signal fitting can be disabled for " + FitFunction.FIXED.toString() + " function");
gd.addCheckbox("Signal_fitting", signalFitting);
gd.addCheckbox("Show_histograms", showHistograms);
gd.addCheckbox("Save_raw_data", saveRawData);
gd.showDialog();
if (gd.wasCanceled())
return false;
regionSize = (int) Math.abs(gd.getNextNumber());
psfWidth = Math.abs(gd.getNextNumber());
fitConfig.setFitSolver(gd.getNextChoiceIndex());
fitConfig.setFitFunction(gd.getNextChoiceIndex());
offsetFitting = gd.getNextBoolean();
startOffset = Math.abs(gd.getNextNumber());
comFitting = gd.getNextBoolean();
backgroundFitting = gd.getNextBoolean();
signalFitting = gd.getNextBoolean();
showHistograms = gd.getNextBoolean();
saveRawData = gd.getNextBoolean();
if (!comFitting && !offsetFitting) {
IJ.error(TITLE, "No initial fitting positions");
return false;
}
if (regionSize < 1)
regionSize = 1;
if (gd.invalidNumber())
return false;
// Initialise the correct calibration
Calibration calibration = settings.getCalibration();
calibration.setNmPerPixel(benchmarkParameters.a);
calibration.setGain(benchmarkParameters.gain);
calibration.setAmplification(benchmarkParameters.amplification);
calibration.setBias(benchmarkParameters.bias);
calibration.setEmCCD(benchmarkParameters.emCCD);
calibration.setReadNoise(benchmarkParameters.readNoise);
calibration.setExposureTime(1000);
if (!PeakFit.configureFitSolver(settings, filename, false))
return false;
if (showHistograms) {
gd = new GenericDialog(TITLE);
gd.addMessage("Select the histograms to display");
gd.addNumericField("Histogram_bins", histogramBins, 0);
double[] convert = getConversionFactors();
for (int i = 0; i < displayHistograms.length; i++) if (convert[i] != 0)
gd.addCheckbox(NAMES[i].replace(' ', '_'), displayHistograms[i]);
gd.showDialog();
if (gd.wasCanceled())
return false;
histogramBins = (int) Math.abs(gd.getNextNumber());
for (int i = 0; i < displayHistograms.length; i++) if (convert[i] != 0)
displayHistograms[i] = gd.getNextBoolean();
}
return true;
}
use of gdsc.smlm.results.Calibration in project GDSC-SMLM by aherbert.
the class SpotInspector method run.
/*
* (non-Javadoc)
*
* @see ij.plugin.PlugIn#run(java.lang.String)
*/
public void run(String arg) {
SMLMUsageTracker.recordPlugin(this.getClass(), arg);
if (MemoryPeakResults.isMemoryEmpty()) {
IJ.error(TITLE, "No localisations in memory");
return;
}
if (!showDialog())
return;
// Load the results
results = ResultsManager.loadInputResults(inputOption, false);
if (results == null || results.size() == 0) {
IJ.error(TITLE, "No results could be loaded");
IJ.showStatus("");
return;
}
// Check if the original image is open
ImageSource source = results.getSource();
if (source == null) {
IJ.error(TITLE, "Unknown original source image");
return;
}
source = source.getOriginal();
if (!source.open()) {
IJ.error(TITLE, "Cannot open original source image: " + source.toString());
return;
}
final float stdDevMax = getStandardDeviation(results);
if (stdDevMax < 0) {
// TODO - Add dialog to get the initial peak width
IJ.error(TITLE, "Fitting configuration (for initial peak width) is not available");
return;
}
// Rank spots
rankedResults = new ArrayList<PeakResultRank>(results.size());
final double a = results.getNmPerPixel();
final double gain = results.getGain();
final boolean emCCD = results.isEMCCD();
for (PeakResult r : results.getResults()) {
float[] score = getScore(r, a, gain, emCCD, stdDevMax);
rankedResults.add(new PeakResultRank(r, score[0], score[1]));
}
Collections.sort(rankedResults);
// Prepare results table. Get bias if necessary
if (showCalibratedValues) {
// Get a bias if required
Calibration calibration = results.getCalibration();
if (calibration.getBias() == 0) {
ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addMessage("Calibrated results requires a camera bias");
gd.addNumericField("Camera_bias (ADUs)", calibration.getBias(), 2);
gd.showDialog();
if (!gd.wasCanceled()) {
calibration.setBias(Math.abs(gd.getNextNumber()));
}
}
}
IJTablePeakResults table = new IJTablePeakResults(false, results.getName(), true);
table.copySettings(results);
table.setTableTitle(TITLE);
table.setAddCounter(true);
table.setShowCalibratedValues(showCalibratedValues);
table.begin();
// Add a mouse listener to jump to the frame for the clicked line
textPanel = table.getResultsWindow().getTextPanel();
// We must ignore old instances of this class from the mouse listeners
id = ++currentId;
textPanel.addMouseListener(this);
// Add results to the table
int n = 0;
for (PeakResultRank rank : rankedResults) {
rank.rank = n++;
PeakResult r = rank.peakResult;
table.add(r.getFrame(), r.origX, r.origY, r.origValue, r.error, r.noise, r.params, r.paramsStdDev);
}
table.end();
if (plotScore || plotHistogram) {
// Get values for the plots
float[] xValues = null, yValues = null;
double yMin, yMax;
int spotNumber = 0;
xValues = new float[rankedResults.size()];
yValues = new float[xValues.length];
for (PeakResultRank rank : rankedResults) {
xValues[spotNumber] = spotNumber + 1;
yValues[spotNumber++] = recoverScore(rank.score);
}
// Set the min and max y-values using 1.5 x IQR
DescriptiveStatistics stats = new DescriptiveStatistics();
for (float v : yValues) stats.addValue(v);
if (removeOutliers) {
double lower = stats.getPercentile(25);
double upper = stats.getPercentile(75);
double iqr = upper - lower;
yMin = FastMath.max(lower - iqr, stats.getMin());
yMax = FastMath.min(upper + iqr, stats.getMax());
IJ.log(String.format("Data range: %f - %f. Plotting 1.5x IQR: %f - %f", stats.getMin(), stats.getMax(), yMin, yMax));
} else {
yMin = stats.getMin();
yMax = stats.getMax();
IJ.log(String.format("Data range: %f - %f", yMin, yMax));
}
plotScore(xValues, yValues, yMin, yMax);
plotHistogram(yValues, yMin, yMax);
}
// Extract spots into a stack
final int w = source.getWidth();
final int h = source.getHeight();
final int size = 2 * radius + 1;
ImageStack spots = new ImageStack(size, size, rankedResults.size());
// To assist the extraction of data from the image source, process them in time order to allow
// frame caching. Then set the appropriate slice in the result stack
Collections.sort(rankedResults, new Comparator<PeakResultRank>() {
public int compare(PeakResultRank o1, PeakResultRank o2) {
if (o1.peakResult.getFrame() < o2.peakResult.getFrame())
return -1;
if (o1.peakResult.getFrame() > o2.peakResult.getFrame())
return 1;
return 0;
}
});
for (PeakResultRank rank : rankedResults) {
PeakResult r = rank.peakResult;
// Extract image
// Note that the coordinates are relative to the middle of the pixel (0.5 offset)
// so do not round but simply convert to int
final int x = (int) (r.params[Gaussian2DFunction.X_POSITION]);
final int y = (int) (r.params[Gaussian2DFunction.Y_POSITION]);
// Extract a region but crop to the image bounds
int minX = x - radius;
int minY = y - radius;
int maxX = FastMath.min(x + radius + 1, w);
int maxY = FastMath.min(y + radius + 1, h);
int padX = 0, padY = 0;
if (minX < 0) {
padX = -minX;
minX = 0;
}
if (minY < 0) {
padY = -minY;
minY = 0;
}
int sizeX = maxX - minX;
int sizeY = maxY - minY;
float[] data = source.get(r.getFrame(), new Rectangle(minX, minY, sizeX, sizeY));
// Prevent errors with missing data
if (data == null)
data = new float[sizeX * sizeY];
ImageProcessor spotIp = new FloatProcessor(sizeX, sizeY, data, null);
// Pad if necessary, i.e. the crop is too small for the stack
if (padX > 0 || padY > 0 || sizeX < size || sizeY < size) {
ImageProcessor spotIp2 = spotIp.createProcessor(size, size);
spotIp2.insert(spotIp, padX, padY);
spotIp = spotIp2;
}
int slice = rank.rank + 1;
spots.setPixels(spotIp.getPixels(), slice);
spots.setSliceLabel(Utils.rounded(rank.originalScore), slice);
}
source.close();
ImagePlus imp = Utils.display(TITLE, spots);
imp.setRoi((PointRoi) null);
// Make bigger
for (int i = 10; i-- > 0; ) imp.getWindow().getCanvas().zoomIn(imp.getWidth() / 2, imp.getHeight() / 2);
}
Aggregations