package gdsc.colocalisation.cda.engine; import gdsc.colocalisation.cda.engine.CalculationResult; import gdsc.core.utils.Correlator; import gdsc.colocalisation.cda.TwinStackShifter; import ij.IJ; import ij.ImageStack; import java.util.List; import java.util.concurrent.BlockingQueue; /** * Performs the CDA algorithm */ public class CDAWorker implements Runnable { ImageStack imageStack1; ImageStack roiStack1; ImageStack imageStack2; ImageStack roiStack2; ImageStack confinedStack; double denom1; double denom2; List<CalculationResult> results; TwinStackShifter twinImageShifter; BlockingQueue<CDAJob> jobs; int totalSteps; Correlator c = new Correlator(); private volatile boolean finished = false; public CDAWorker(ImageStack imageStack1, ImageStack roiStack1, ImageStack imageStack2, ImageStack roiStack2, ImageStack confinedStack, double denom1, double denom2, List<CalculationResult> results, BlockingQueue<CDAJob> jobs, int totalSteps) { this.imageStack1 = imageStack1; this.roiStack1 = roiStack1; this.imageStack2 = imageStack2; this.roiStack2 = roiStack2; this.confinedStack = confinedStack; this.denom1 = denom1; this.denom2 = denom2; this.results = results; this.jobs = jobs; this.totalSteps = totalSteps; } /** * Perform the CDA shift and calculate the results */ public void run(int n, int x, int y) { final double distance = Math.sqrt(x * x + y * y); if (n % 2 == 0) IJ.showProgress(n, totalSteps); twinImageShifter.run(x, y); IntersectResult intersectResult = calculateResults(twinImageShifter.getResultStack(), twinImageShifter.getResultStack2(), imageStack2, roiStack2); final double m1 = (double) intersectResult.sum1 / denom1; final double m2 = (double) intersectResult.sum2 / denom2; //System.out.printf("d=%f, x=%d, y=%d, n=%d, r=%f, sx=%d, sy=%d\n", distance, x, y, c.getN(), intersectResult.r, // c.getSumX(), c.getSumY()); results.add(new CalculationResult(distance, m1, m2, intersectResult.r)); } private IntersectResult calculateResults(ImageStack stack1, ImageStack roi1, ImageStack stack2, ImageStack roi2) { c.clear(); for (int slice = stack1.getSize(); slice > 0; slice--) { final short[] i1 = (short[]) stack1.getPixels(slice); final short[] i2 = (short[]) stack2.getPixels(slice); final byte[] m1 = (byte[]) roi1.getPixels(slice); final byte[] m2 = (byte[]) roi2.getPixels(slice); int[] ii1 = new int[i1.length]; int[] ii2 = new int[i1.length]; int n = 0; for (int i = i1.length; i-- > 0;) { if ((m1[i] != 0) && (m2[i] != 0)) { // ImageJ stores unsigned values ii1[n] = i1[i] & 0xffff; ii2[n] = i2[i] & 0xffff; n++; } } c.add(ii1, ii2, n); } return new IntersectResult(c.getSumX(), c.getSumY(), c.getCorrelation()); } /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ public void run() { twinImageShifter = new TwinStackShifter(imageStack1, roiStack1, confinedStack); try { while (!finished) { CDAJob job = jobs.take(); if (job == null || job.n < 0 || finished) break; run(job.n, job.x, job.y); } } catch (InterruptedException e) { System.out.println(e.toString()); throw new RuntimeException(e); } finally { finished = true; //notifyAll(); } } /** * Signal that the worker should end */ public void finish() { finished = true; } /** * @return True if the worker has finished */ public boolean isFinished() { return finished; } /** * @return True if the worker is ready to run jobs */ public boolean isInitialised() { return twinImageShifter != null; } }