use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedureX in project GDSC-SMLM by aherbert.
the class PeakFit method getSingleFrame.
/**
* Gets the single frame containing all the results (if they are all in a single frame), else 0.
*
* @param results the results (must not be empty)
* @return the single frame (or zero)
*/
private static int getSingleFrame(MemoryPeakResults results) {
final FrameCounter counter = new FrameCounter(results.getFirstFrame());
// The counter will return true (stop execution) if a new frame
results.forEach((PeakResultProcedureX) peakResult -> counter.advance(peakResult.getFrame()));
if (counter.currentFrame() != counter.previousFrame()) {
return 0;
}
return counter.currentFrame();
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedureX in project GDSC-SMLM by aherbert.
the class PeakResultsReader method simplifyTwoAxis.
/**
* Simplify two axis Gaussian 2D data.
*
* @param results the results
* @param removeTheta the remove theta flag
*/
private void simplifyTwoAxis(MemoryPeakResults results, boolean removeTheta) {
final int[] indices = PsfHelper.getGaussian2DWxWyIndices(psf);
final int isx = indices[0];
final int isy = indices[1];
// Columns to remove
int remove = (removeTheta) ? 1 : 0;
// New PSF type
PSFType psfType;
// Determine if sy is redundant
if (results.forEach((PeakResultProcedureX) peakResult -> peakResult.getParameter(isx) != peakResult.getParameter(isy))) {
if (!removeTheta) {
// Already a TwoAxis Gaussian
return;
}
// Otherwise this was a TwoAxisAndTheta with 1 column to remove
// so it should be simplified
psfType = PSFType.TWO_AXIS_GAUSSIAN_2D;
} else {
// sy is redundant so remove another column
psfType = PSFType.ONE_AXIS_GAUSSIAN_2D;
remove++;
}
// Update the PSF
final PSF.Builder builder = psf.toBuilder();
builder.setPsfType(psfType);
psf = builder.build();
results.setPsf(psf);
// Update the results.
// We can directly manipulate the params array
final int newLength = results.getf(0).getNumberOfParameters() - remove;
if (deviations) {
results.forEach((PeakResultProcedure) peakResult -> {
peakResult.resizeParameters(newLength);
peakResult.resizeParameterDeviations(newLength);
});
} else {
results.forEach((PeakResultProcedure) peakResult -> peakResult.resizeParameters(newLength));
}
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedureX in project GDSC-SMLM by aherbert.
the class PeakResultsReader method readNStorm.
private MemoryPeakResults readNStorm() {
final MemoryPeakResults results = createResults();
results.setName(FileUtils.getName(filename));
try (FileInputStream fis = new FileInputStream(filename);
BufferedReader input = new BufferedReader(new UnicodeReader(fis, null))) {
final ProgressReporter reporter = createProgressReporter(fis);
String line;
int errors = 0;
// The single line header
final String header = input.readLine();
if (header == null) {
throw new IOException("NStorm header missing");
}
// NStorm files added more column fields for later formats.
// If the header contains 'Photons' then this can be used to determine the gain
boolean readPhotons = header.contains("\tPhotons\t");
while ((line = input.readLine()) != null) {
if (line.isEmpty()) {
continue;
}
final PeakResult result = createNStormResult(line, readPhotons);
if (result != null) {
results.add(result);
// Just read the photons from the first 100
if (readPhotons) {
readPhotons = results.size() < 100;
}
} else if (++errors >= 10) {
break;
}
reporter.showProgress();
}
} catch (final IOException ex) {
logError(ex);
}
// The following relationship holds when length == 1:
// intensity = height * 2 * pi * sd0 * sd1 / pixel_pitch^2
// => Pixel_pitch = sqrt(height * 2 * pi * sd0 * sd1 / intensity)
// Try and create a calibration
final Statistics pixelPitch = new Statistics();
results.forEach(new PeakResultProcedureX() {
static final double TWO_PI = 2 * Math.PI;
@Override
public boolean execute(PeakResult peakResult) {
if (peakResult.getFrame() == peakResult.getEndFrame()) {
final float height = peakResult.getOrigValue();
final float intensity = peakResult.getParameter(PeakResult.INTENSITY);
final float sd0 = peakResult.getParameter(INDEX_SX);
final float sd1 = peakResult.getParameter(INDEX_SY);
pixelPitch.add(Math.sqrt(height * TWO_PI * sd0 * sd1 / intensity));
// Stop when we have enough for a good guess
return (pixelPitch.getN() > 100);
}
return false;
}
});
// Determine the gain using the photons column
final Statistics gain = new Statistics();
results.forEach((PeakResultProcedureX) peakResult -> {
double photons = peakResult.getError();
if (photons != 0) {
peakResult.setError(0);
gain.add(peakResult.getIntensity() / photons);
return false;
}
return true;
});
// TODO - Support all the NSTORM formats: one-axis, two-axis, rotated, 3D.
// Is this information in the header?
// We could support setting the PSF as a Gaussian2D with one/two axis SD.
// This would mean updating all the result params if it is a one axis PSF.
// For now just record it as a 2 axis PSF.
// Create a calibration
calibration = new CalibrationWriter();
// NSTORM data is in counts when the Photons column is present.
// Q. Is it in counts when this column is not present?
calibration.setIntensityUnit(IntensityUnit.COUNT);
calibration.setDistanceUnit(DistanceUnit.NM);
if (pixelPitch.getN() > 0) {
final double nmPerPixel = pixelPitch.getMean();
calibration.setNmPerPixel(nmPerPixel);
}
if (gain.getN() > 0 && gain.getStandardError() < 1e-3) {
calibration.setCountPerPhoton(gain.getMean());
}
results.setCalibration(calibration.getCalibration());
return results;
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedureX in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewer method createSphereSizeFromDeviations.
@Nullable
private static Point3f[] createSphereSizeFromDeviations(MemoryPeakResults results) {
if (!results.hasDeviations()) {
IJ.error(TITLE, "The results have no deviations");
return null;
}
// Currently the rendering is in nm
final TypeConverter<DistanceUnit> dc = results.getDistanceConverter(DistanceUnit.NM);
final Point3f[] size = new Point3f[results.size()];
final boolean failed = results.forEach(new PeakResultProcedureX() {
int index;
@Override
public boolean execute(PeakResult peakResult) {
final float x = peakResult.getParameterDeviation(PeakResult.X);
final float y = peakResult.getParameterDeviation(PeakResult.Y);
float z = peakResult.getParameterDeviation(PeakResult.Z);
// This should be OK as 2D fitting should provide these.
if (x == 0 || y == 0) {
return true;
}
if (z == 0) {
// Mean variance
z = (float) Math.sqrt((x * x + y * y) / 2);
}
// z = (x + y) / 2; // Mean Std Dev
size[index++] = new Point3f(dc.convert(x), dc.convert(y), dc.convert(z));
return false;
}
});
return (failed) ? null : size;
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedureX in project GDSC-SMLM by aherbert.
the class ResultsManager method run.
@Override
public void run(String arg) {
extraOptions = ImageJUtils.isExtraOptions();
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
if ("load".equals(arg)) {
batchLoad();
return;
}
if ("save".equals(arg)) {
batchSave();
return;
}
if (StringUtils.startsWith(arg, "clear")) {
runClearMemory(arg);
return;
}
if (!showDialog()) {
return;
}
final MemoryPeakResults results = loadResults(settings.inputOption);
if (MemoryPeakResults.isEmpty(results)) {
IJ.error(TITLE, "No results could be loaded");
IJ.showStatus("");
return;
}
IJ.showStatus("Loaded " + TextUtils.pleural(results.size(), "result"));
boolean saved = false;
if (resultsSettings.getResultsInMemorySettings().getInMemory() && fileInput) {
if (!addResultsToMemory(results, settings.inputFilename)) {
IJ.showStatus("");
return;
}
saved = true;
}
if (resultsSettings.getResultsTableSettings().getResultsTableFormatValue() <= 0 && resultsSettings.getResultsImageSettings().getImageTypeValue() <= 0 && TextUtils.isNullOrEmpty(resultsSettings.getResultsFileSettings().getResultsFilename())) {
// No outputs. Error if results were not saved to memory
if (!saved) {
IJ.error(TITLE, "No output selected");
}
return;
}
final Rectangle bounds = results.getBounds(true);
final boolean showDeviations = resultsSettings.getShowDeviations() && canShowDeviations(results);
final boolean showEndFrame = canShowEndFrame(results);
final boolean showId = canShowId(results);
final boolean showCategory = canShowCategory(results);
// Display the configured output
final PeakResultsList outputList = new PeakResultsList();
outputList.copySettings(results);
final int tableFormat = resultsSettings.getResultsTableSettings().getResultsTableFormatValue();
if (tableFormat == ResultsTableFormat.IMAGEJ_VALUE) {
addImageJTableResults(outputList, resultsSettings.getResultsTableSettings(), showDeviations, showEndFrame, results.is3D(), showId, showCategory);
} else if (tableFormat == ResultsTableFormat.INTERACTIVE_VALUE) {
showInteractiveTable(results, resultsSettings.getResultsTableSettings());
}
addImageResults(outputList, resultsSettings.getResultsImageSettings(), bounds, (extraOptions) ? FLAG_EXTRA_OPTIONS : 0);
addFileResults(outputList, showDeviations, showEndFrame, showId, showCategory);
if (outputList.numberOfOutputs() == 0) {
// This occurs when only using the interactive table
IJ.showStatus("Processed " + TextUtils.pleural(results.size(), "result"));
return;
}
IJ.showStatus("Processing outputs ...");
// Reduce to single object for speed
final PeakResults output = (outputList.numberOfOutputs() == 1) ? outputList.toArray()[0] : outputList;
output.begin();
// Note: We could add a batch iterator to the MemoryPeakResults.
// However the speed increase will be marginal as the main time
// taken is in processing the outputs.
// Process in batches to provide progress
final Counter progress = new Counter();
final int totalProgress = results.size();
final int batchSize = Math.max(100, totalProgress / 10);
final FixedPeakResultList batch = new FixedPeakResultList(batchSize);
IJ.showProgress(0);
results.forEach((PeakResultProcedureX) result -> {
batch.add(result);
if (batch.size == batchSize) {
if (IJ.escapePressed()) {
batch.clear();
return true;
}
output.addAll(batch.results);
batch.clear();
IJ.showProgress(progress.incrementAndGet(batchSize), totalProgress);
}
return false;
});
// Will be empty if interrupted
if (batch.isNotEmpty()) {
output.addAll(batch.toArray());
}
IJ.showProgress(1);
output.end();
if (output.size() == results.size()) {
IJ.showStatus("Processed " + TextUtils.pleural(results.size(), "result"));
} else {
IJ.showStatus(String.format("A %d/%s", output.size(), TextUtils.pleural(results.size(), "result")));
}
}
Aggregations