/*- * #%L * Fiji distribution of ImageJ for the life sciences. * %% * Copyright (C) 2007 - 2017 Fiji developers. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-2.0.html>. * #L% */ package spim.process.fusion.weightedavg; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Vector; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import mpicbg.spim.data.sequence.Channel; import mpicbg.spim.data.sequence.TimePoint; import mpicbg.spim.data.sequence.ViewDescription; import mpicbg.spim.data.sequence.ViewId; import mpicbg.spim.data.sequence.ViewSetup; import mpicbg.spim.io.IOFunctions; import net.imglib2.RandomAccessible; import net.imglib2.RandomAccessibleInterval; import net.imglib2.img.Img; import net.imglib2.interpolation.InterpolatorFactory; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; import spim.Threads; import spim.fiji.spimdata.SpimData2; import spim.process.fusion.FusionHelper; import spim.process.fusion.ImagePortion; import spim.process.fusion.boundingbox.BoundingBoxGUI; import spim.process.fusion.export.FixedNameImgTitler; import spim.process.fusion.export.ImgExport; import spim.process.fusion.export.ImgExportTitle; /** * Fused individual images for each input stack, uses the exporter directly * * @author Stephan Preibisch (stephan.preibisch@gmx.de) * */ public class ProcessIndependent extends ProcessFusion { final ImgExport export; final Map< ViewSetup, ViewSetup > newViewsetups; final FixedNameImgTitler titler; public ProcessIndependent( final SpimData2 spimData, final List< ViewId > viewIdsToProcess, final BoundingBoxGUI bb, final ImgExport export, final Map< ViewSetup, ViewSetup > newViewsetups ) { super( spimData, viewIdsToProcess, bb, false, false ); this.export = export; this.newViewsetups = newViewsetups; this.titler = new FixedNameImgTitler( "" ); if ( this.export instanceof ImgExportTitle ) ( (ImgExportTitle)this.export).setImgTitler( titler ); } /** * Fuses one stack, i.e. all angles/illuminations for one timepoint and channel * * @param type * @param interpolatorFactory * @param timepoint * @param channel * @return */ @Override public < T extends RealType< T > & NativeType< T > > Img< T > fuseStack( final T type, final InterpolatorFactory< T, RandomAccessible< T > > interpolatorFactory, final TimePoint timepoint, final Channel channel ) { // get all views that are fused final ArrayList< ViewDescription > allInputData = FusionHelper.assembleInputData( spimData, timepoint, channel, viewIdsToProcess ); // we will need to run some batches until all is fused for ( int i = 0; i < allInputData.size(); ++i ) { IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Fusing view " + i + " of " + (allInputData.size()-1) ); IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Reserving memory for fused image."); // try creating the output (type needs to be there to define T) final Img< T > fusedImg = bb.getImgFactory( type ).create( bb.getDimensions(), type ); if ( fusedImg == null ) { IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): WeightedAverageFusion: Cannot create output image." ); return null; } final ViewDescription inputData = allInputData.get( i ); // same as in the paralell fusion now more or less IOFunctions.println("(" + new Date(System.currentTimeMillis()) + "): Requesting Img from ImgLoader (tp=" + inputData.getTimePointId() + ", setup=" + inputData.getViewSetupId() + ")" ); final RandomAccessibleInterval< T > img = getImage( type, spimData, inputData, false ); // split up into many parts for multithreading final Vector< ImagePortion > portions = FusionHelper.divideIntoPortions( fusedImg.size(), Threads.numThreads() * 4 ); // set up executor service final ExecutorService taskExecutor = Executors.newFixedThreadPool( Threads.numThreads() ); final ArrayList< ProcessIndependentPortion< T > > tasks = new ArrayList< ProcessIndependentPortion< T > >(); for ( final ImagePortion portion : portions ) tasks.add( new ProcessIndependentPortion< T >( portion, img, interpolatorFactory, getTransform( inputData ), fusedImg, bb ) ); IOFunctions.println("(" + new Date(System.currentTimeMillis()) + "): Starting fusion process."); try { // invokeAll() returns when all tasks are complete taskExecutor.invokeAll( tasks ); } catch ( final InterruptedException e ) { IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Failed to compute fusion: " + e ); e.printStackTrace(); return null; } taskExecutor.shutdown(); titler.setTitle( "TP" + inputData.getTimePointId() + "_Channel" + inputData.getViewSetup().getChannel().getName() + "_Illum" + inputData.getViewSetup().getIllumination().getName() + "_Angle" + inputData.getViewSetup().getAngle().getName() ); export.exportImage( fusedImg, bb, timepoint, newViewsetups.get( inputData.getViewSetup() ) ); } return null; } protected int numBatches( final int numViews, final int sequentialViews ) { return numViews / sequentialViews + Math.min( numViews % sequentialViews, 1 ); } }