use of uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.ImagePSF in project GDSC-SMLM by aherbert.
the class CreateData method getImageHwhm.
/**
* Get the PSF half-width at half-maxima from the Image PSF.
*
* @return the PSF half-width at half-maxima
*/
private double getImageHwhm() {
final ImagePlus imp = WindowManager.getImage(settings.getPsfImageName());
if (imp == null) {
IJ.error(TITLE, "Unable to create the PSF model from image: " + settings.getPsfImageName());
return -1;
}
final ImagePSF psfSettings = ImagePsfHelper.fromString(imp.getProperty("Info").toString());
if (psfSettings == null) {
IJ.error(TITLE, "Unknown PSF settings for image: " + imp.getTitle());
return -1;
}
if (psfSettings.getFwhm() <= 0) {
IJ.error(TITLE, "Unknown PSF FWHM setting for image: " + imp.getTitle());
return -1;
}
if (psfSettings.getPixelSize() <= 0) {
IJ.error(TITLE, "Unknown PSF pixel size setting for image: " + imp.getTitle());
return -1;
}
// output image
return 0.5 * psfSettings.getFwhm() * psfSettings.getPixelSize() / settings.getPixelPitch();
}
use of uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.ImagePSF in project GDSC-SMLM by aherbert.
the class CubicSplineManager method loadFromFile.
private static CubicSplinePsf loadFromFile(String name, String filename) {
// Try to load from file
try (InputStream is = new BufferedInputStream(new FileInputStream(filename))) {
IJ.showStatus("Loading cubic spline: " + name);
final ImagePSF imagePsf = ImagePSF.parseDelimitedFrom(is);
final CubicSplineData function = CubicSplineData.read(is, SimpleImageJTrackProgress.getInstance());
return new CubicSplinePsf(imagePsf, function);
} catch (final Exception ex) {
ImageJUtils.log("Failed to load spline model %s from file: %s. %s", name, filename, ex.getMessage());
} finally {
IJ.showStatus("");
}
return null;
}
use of uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.ImagePSF in project GDSC-SMLM by aherbert.
the class CubicSplineManager method createCubicSpline.
/**
* Creates the cubic spline.
*
* @param imagePsf the image PSF details
* @param image the image
* @param singlePrecision Set to true to use single precision (float values) to store the cubic
* spline coefficients
* @return the cubic spline PSF
*/
public static CubicSplinePsf createCubicSpline(ImagePSFOrBuilder imagePsf, ImageStack image, final boolean singlePrecision) {
final int maxx = image.getWidth();
final int maxy = image.getHeight();
final int maxz = image.getSize();
final float[][] psf = new float[maxz][];
for (int z = 0; z < maxz; z++) {
psf[z] = ImageJImageConverter.getData(image.getPixels(z + 1), null);
}
// We reduce by a factor of 3
final int maxi = (maxx - 1) / 3;
final int maxj = (maxy - 1) / 3;
final int maxk = (maxz - 1) / 3;
final int size = maxi * maxj;
final CustomTricubicFunction[][] splines = new CustomTricubicFunction[maxk][size];
final int threadCount = Prefs.getThreads();
final Ticker ticker = ImageJUtils.createTicker((long) maxi * maxj * maxk, threadCount);
final ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
final LocalList<Future<?>> futures = new LocalList<>(maxk);
// spline node along each dimension, i.e. dimension length = n*3 + 1 with n the number of nodes.
for (int k = 0; k < maxk; k++) {
final int kk = k;
futures.add(threadPool.submit(() -> {
final CubicSplineCalculator calc = new CubicSplineCalculator();
final double[] value = new double[64];
final int zz = 3 * kk;
for (int j = 0, index = 0; j < maxj; j++) {
// 4x4 block origin in the XY data
int index0 = 3 * j * maxx;
for (int i = 0; i < maxi; i++, index++) {
ticker.tick();
int count = 0;
for (int z = 0; z < 4; z++) {
final float[] data = psf[zz + z];
for (int y = 0; y < 4; y++) {
for (int x = 0, ii = index0 + y * maxx; x < 4; x++) {
value[count++] = data[ii++];
}
}
}
splines[kk][index] = CustomTricubicFunctionUtils.create(calc.compute(value));
if (singlePrecision) {
splines[kk][index] = splines[kk][index].toSinglePrecision();
}
index0 += 3;
}
}
}));
}
ticker.stop();
threadPool.shutdown();
ConcurrencyUtils.waitForCompletionUnchecked(futures);
// Normalise
double maxSum = 0;
for (int k = 0; k < maxk; k++) {
double sum = 0;
for (int i = 0; i < size; i++) {
sum += splines[k][i].value000();
}
if (maxSum < sum) {
maxSum = sum;
}
}
if (maxSum == 0) {
throw new IllegalStateException("The cubic spline has no maximum signal");
}
final double scale = 1.0 / maxSum;
for (int k = 0; k < maxk; k++) {
for (int i = 0; i < size; i++) {
splines[k][i] = splines[k][i].scale(scale);
}
}
// Create on an integer scale
final CubicSplineData f = new CubicSplineData(maxi, maxj, splines);
// Create a new info with the PSF details
final ImagePSF.Builder b = ImagePSF.newBuilder();
b.setImageCount(imagePsf.getImageCount());
// Reducing the image has the effect of enlarging the pixel size
b.setPixelSize(imagePsf.getPixelSize() * 3.0);
b.setPixelDepth(imagePsf.getPixelDepth() * 3.0);
// The centre has to be moved as we reduced the image size by 3.
// In the ImagePSF the XY centre puts 0.5 at the centre of the pixel.
// The spline puts 0,0 at the centre of each pixel for convenience.
double cx = maxi / 2.0;
if (imagePsf.getXCentre() != 0) {
cx = (imagePsf.getXCentre() - 0.5) / 3;
}
double cy = maxj / 2.0;
if (imagePsf.getYCentre() != 0) {
cy = (imagePsf.getYCentre() - 0.5) / 3;
}
double cz = maxk / 2.0;
if (imagePsf.getZCentre() != 0) {
cz = imagePsf.getZCentre() / 3;
} else if (imagePsf.getCentreImage() != 0) {
cz = (imagePsf.getCentreImage() - 1) / 3.0;
}
b.setXCentre(cx);
b.setYCentre(cy);
b.setZCentre(cz);
return new CubicSplinePsf(b.build(), f);
}
use of uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.ImagePSF in project GDSC-SMLM by aherbert.
the class CreateData method createImagePsf.
/**
* Create a PSF model from the image that contains all the z-slices needed to draw the given
* localisations.
*
* @param localisationSets the localisation sets
* @return the image PSF model
*/
private ImagePsfModel createImagePsf(List<LocalisationModelSet> localisationSets) {
final ImagePlus imp = WindowManager.getImage(settings.getPsfImageName());
if (imp == null) {
IJ.error(TITLE, "Unable to create the PSF model from image: " + settings.getPsfImageName());
return null;
}
try {
final ImagePSF psfSettings = ImagePsfHelper.fromString(imp.getProperty("Info").toString());
if (psfSettings == null) {
throw new IllegalStateException("Unknown PSF settings for image: " + imp.getTitle());
}
// Check all the settings have values
if (psfSettings.getPixelSize() <= 0) {
throw new IllegalStateException("Missing nmPerPixel calibration settings for image: " + imp.getTitle());
}
if (psfSettings.getPixelDepth() <= 0) {
throw new IllegalStateException("Missing nmPerSlice calibration settings for image: " + imp.getTitle());
}
if (psfSettings.getCentreImage() <= 0) {
throw new IllegalStateException("Missing zCentre calibration settings for image: " + imp.getTitle());
}
if (psfSettings.getFwhm() <= 0) {
throw new IllegalStateException("Missing FWHM calibration settings for image: " + imp.getTitle());
}
// To save memory construct the Image PSF using only the slices that are within
// the depth of field of the simulation
double minZ = Double.POSITIVE_INFINITY;
double maxZ = Double.NEGATIVE_INFINITY;
for (final LocalisationModelSet l : localisationSets) {
for (final LocalisationModel m : l.getLocalisations()) {
final double z = m.getZ();
if (minZ > z) {
minZ = z;
}
if (maxZ < z) {
maxZ = z;
}
}
}
final int nSlices = imp.getStackSize();
// z-centre should be an index and not the ImageJ slice number so subtract 1
final int zCentre = psfSettings.getCentreImage() - 1;
// Calculate the start/end slices to cover the depth of field
// This logic must match the ImagePSFModel.
final double unitsPerSlice = psfSettings.getPixelDepth() / settings.getPixelPitch();
// We assume the PSF was imaged axially with increasing z-stage position (moving the stage
// closer to the objective). Thus higher z-coordinate are for higher slice numbers.
int lower = (int) Math.round(minZ / unitsPerSlice) + zCentre;
int upper = (int) Math.round(maxZ / unitsPerSlice) + zCentre;
// Add extra to the range so that gradients can be computed.
lower--;
upper++;
upper = (upper < 0) ? 0 : (upper >= nSlices) ? nSlices - 1 : upper;
lower = (lower < 0) ? 0 : (lower >= nSlices) ? nSlices - 1 : lower;
// Image PSF requires the z-centre for normalisation
if (!(lower <= zCentre && upper >= zCentre)) {
// Ensure we include the zCentre
lower = Math.min(lower, zCentre);
upper = Math.max(upper, zCentre);
}
final double noiseFraction = 1e-3;
final float[][] image = extractImageStack(imp, lower, upper);
final ImagePsfModel model = new ImagePsfModel(image, zCentre - lower, psfSettings.getPixelSize() / settings.getPixelPitch(), unitsPerSlice, noiseFraction);
// Add the calibrated centres. The map will not be null
final Map<Integer, Offset> map = psfSettings.getOffsetsMap();
if (!map.isEmpty()) {
final int sliceOffset = lower + 1;
for (final Entry<Integer, Offset> entry : map.entrySet()) {
model.setRelativeCentre(entry.getKey() - sliceOffset, entry.getValue().getCx(), entry.getValue().getCy());
}
} else {
// Use the CoM if present
final double cx = psfSettings.getXCentre();
final double cy = psfSettings.getYCentre();
if (cx != 0 || cy != 0) {
for (int slice = 0; slice < image.length; slice++) {
model.setCentre(slice, cx, cy);
}
}
}
// Initialise the HWHM table so that it can be cloned
model.initialiseHwhm();
return model;
} catch (final Exception ex) {
IJ.error(TITLE, "Unable to create the image PSF model:\n" + ex.getMessage());
return null;
}
}
use of uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.ImagePSF in project GDSC-SMLM by aherbert.
the class PsfDrift method createImageList.
private static List<String> createImageList(boolean requireFwhm) {
final List<String> titles = new LinkedList<>();
final int[] ids = WindowManager.getIDList();
if (ids != null) {
for (final int id : ids) {
final ImagePlus imp = WindowManager.getImage(id);
if (imp != null && // Image must be greyscale
(imp.getType() == ImagePlus.GRAY8 || imp.getType() == ImagePlus.GRAY16 || imp.getType() == ImagePlus.GRAY32) && // Image must be square and a stack of a single channel
(imp.getWidth() == imp.getHeight() && imp.getNChannels() == 1)) {
// Check if these are PSF images created by the SMLM plugins
final ImagePSF psfSettings = getPsfSettings(imp);
if (psfSettings != null) {
if (psfSettings.getCentreImage() <= 0) {
ImageJUtils.log(TITLE + ": Unknown PSF z-centre setting for image: " + imp.getTitle());
continue;
}
if (psfSettings.getPixelSize() <= 0) {
ImageJUtils.log(TITLE + ": Unknown PSF nm/pixel setting for image: " + imp.getTitle());
continue;
}
if (psfSettings.getPixelDepth() <= 0) {
ImageJUtils.log(TITLE + ": Unknown PSF nm/slice setting for image: " + imp.getTitle());
continue;
}
if (requireFwhm && psfSettings.getFwhm() <= 0) {
ImageJUtils.log(TITLE + ": Unknown PSF FWHM setting for image: " + imp.getTitle());
continue;
}
titles.add(imp.getTitle());
}
}
}
}
return titles;
}
Aggregations