use of uk.ac.sussex.gdsc.smlm.function.cspline.CubicSplineData 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.function.cspline.CubicSplineData 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);
}
Aggregations