@Override public boolean process() { final long startTime = System.currentTimeMillis(); final long imageSize = image.getNumPixels(); final AtomicInteger ai = new AtomicInteger(0); final Thread[] threads = SimpleMultiThreading.newThreads(getNumThreads()); final Vector<Chunk> threadChunks = SimpleMultiThreading.divideIntoChunks(imageSize, numThreads); final boolean isCompatible = image.getContainer().compareStorageContainerCompatibility(output.getContainer()); for (int ithread = 0; ithread < threads.length; ++ithread) threads[ithread] = new Thread( new Runnable() { public void run() { // Thread ID final int myNumber = ai.getAndIncrement(); // get chunk of pixels to process final Chunk myChunk = threadChunks.get(myNumber); // check if all container types are comparable so that we can use simple iterators // we assume transivity here if (isCompatible) { // we can simply use iterators computeSimple(myChunk.getStartPosition(), myChunk.getLoopSize()); } else { // we need a combination of Localizable and LocalizableByDim computeAdvanced(myChunk.getStartPosition(), myChunk.getLoopSize()); } } }); SimpleMultiThreading.startAndJoin(threads); processingTime = System.currentTimeMillis() - startTime; return true; }
/** * Execute the segmentation part. * * <p>This method looks for bright blobs: bright object of approximately spherical shape, whose * expected diameter is given in argument. The method used for segmentation depends on the {@link * SpotSegmenter} chosen, and set in {@link #settings}; * * <p>This gives us a collection of spots, which at this stage simply wrap a physical center * location. These spots are stored in a {@link SpotCollection} field, {@link #spots}, but * listeners of this model are <b>not</b> notified when the process is over. * * @see #getSpots() */ public void execSegmentation() { final Settings settings = model.getSettings(); final int segmentationChannel = settings.segmentationChannel; final Logger logger = model.getLogger(); final ImagePlus imp = settings.imp; if (null == imp) { logger.error("No image to operate on.\n"); return; } if (null == settings.segmenter) { logger.error("No segmenter selected.\n"); return; } if (null == settings.segmenterSettings) { logger.error("No segmenter settings set.\n"); return; } if (!settings .segmenterSettings .getClass() .equals(settings.segmenter.createDefaultSettings().getClass())) { logger.error( String.format( "Segmenter settings class does not match segmenter class: %s vs %s.\n", settings.segmenterSettings.getClass().getSimpleName(), settings.segmenter.createDefaultSettings().getClass().getSimpleName())); return; } final int numFrames = settings.tend - settings.tstart + 1; final SpotCollection spots = new SpotCollection(); final AtomicInteger spotFound = new AtomicInteger(0); final AtomicInteger progress = new AtomicInteger(0); final Thread[] threads; if (useMultithreading) { threads = SimpleMultiThreading.newThreads(); } else { threads = SimpleMultiThreading.newThreads(1); } // Prepare the thread array final AtomicInteger ai = new AtomicInteger(settings.tstart); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread( "TrackMate spot feature calculating thread " + (1 + ithread) + "/" + threads.length) { public void run() { for (int i = ai.getAndIncrement(); i <= settings.tend; i = ai.getAndIncrement()) { Image<? extends RealType<?>> img = TMUtils.getCroppedSingleFrameAsImage( imp, i, segmentationChannel, settings); // will be cropped according to settings List<Spot> s = execSingleFrameSegmentation(img, settings, i); // Add segmentation feature other than position for (Spot spot : s) { spot.putFeature(Spot.POSITION_T, i * settings.dt); } spots.put(i, s); spotFound.addAndGet(s.size()); logger.setProgress(progress.incrementAndGet() / (float) numFrames); } // Finished looping over frames } }; } logger.setStatus("Segmenting..."); logger.setProgress(0); SimpleMultiThreading.startAndJoin(threads); model.setSpots(spots, true); logger.log("Found " + spotFound.get() + " spots.\n"); logger.setProgress(1); logger.setStatus(""); return; }
/** * Fuse one slice/volume (one channel) * * @param output - same the type of the ImagePlus input * @param input - FloatType, because of Interpolation that needs to be done * @param transform - the transformation */ public static <T extends RealType<T>> void fuseChannel( final Image<T> output, final Image<FloatType> input, final float[] offset, final InvertibleCoordinateTransform transform, final InterpolatorFactory<FloatType> factory) { final int dims = output.getNumDimensions(); long imageSize = output.getDimension(0); for (int d = 1; d < output.getNumDimensions(); ++d) imageSize *= output.getDimension(d); // run multithreaded final AtomicInteger ai = new AtomicInteger(0); final Thread[] threads = SimpleMultiThreading.newThreads(); final Vector<Chunk> threadChunks = SimpleMultiThreading.divideIntoChunks(imageSize, threads.length); for (int ithread = 0; ithread < threads.length; ++ithread) threads[ithread] = new Thread( new Runnable() { public void run() { // Thread ID final int myNumber = ai.getAndIncrement(); // get chunk of pixels to process final Chunk myChunk = threadChunks.get(myNumber); final long startPos = myChunk.getStartPosition(); final long loopSize = myChunk.getLoopSize(); final LocalizableCursor<T> out = output.createLocalizableCursor(); final Interpolator<FloatType> in = input.createInterpolator(factory); final float[] tmp = new float[input.getNumDimensions()]; try { // move to the starting position of the current thread out.fwd(startPos); // do as many pixels as wanted by this thread for (long j = 0; j < loopSize; ++j) { out.fwd(); for (int d = 0; d < dims; ++d) tmp[d] = out.getPosition(d) + offset[d]; transform.applyInverseInPlace(tmp); in.setPosition(tmp); out.getType().setReal(in.getType().get()); } } catch (NoninvertibleModelException e) { IJ.log("Cannot invert model, qutting."); return; } } }); SimpleMultiThreading.startAndJoin(threads); /* final LocalizableCursor<T> out = output.createLocalizableCursor(); final Interpolator<FloatType> in = input.createInterpolator( factory ); final float[] tmp = new float[ input.getNumDimensions() ]; try { while ( out.hasNext() ) { out.fwd(); for ( int d = 0; d < dims; ++d ) tmp[ d ] = out.getPosition( d ) + offset[ d ]; transform.applyInverseInPlace( tmp ); in.setPosition( tmp ); out.getType().setReal( in.getType().get() ); } } catch (NoninvertibleModelException e) { IJ.log( "Cannot invert model, qutting." ); return; } */ }