/*-
* #%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.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.io.IOFunctions;
import net.imglib2.RandomAccessible;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.RealRandomAccessible;
import net.imglib2.img.Img;
import net.imglib2.interpolation.InterpolatorFactory;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.real.FloatType;
import spim.Threads;
import spim.fiji.spimdata.SpimData2;
import spim.process.fusion.FusionHelper;
import spim.process.fusion.ImagePortion;
import spim.process.fusion.boundingbox.BoundingBoxGUI;
public class ProcessParalell extends ProcessFusion
{
public ProcessParalell(
final SpimData2 spimData,
final List< ViewId > viewIdsToProcess,
final BoundingBoxGUI bb,
final boolean useBlending,
final boolean useContentBased )
{
super( spimData, viewIdsToProcess, bb, useBlending, useContentBased );
}
/**
* 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 )
{
IOFunctions.println("(" + new Date(System.currentTimeMillis()) + "): Reserving memory for fused image.");
// get all views that are fused
final ArrayList< ViewDescription > inputData =
FusionHelper.assembleInputData( spimData, timepoint, channel, viewIdsToProcess );
// it can be that for a certain comination of timepoint/channel there is nothing to do
// (e.g. fuse timepoint 1 channel 1 and timepoint 2 channel 2)
if ( inputData.size() == 0 )
return null;
// 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 ArrayList< RandomAccessibleInterval< T > > imgs = new ArrayList< RandomAccessibleInterval< T > >();
for ( int i = 0; i < inputData.size(); ++i )
{
final ViewDescription vd = inputData.get( i );
IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Requesting Img from ImgLoader (tp=" + vd.getTimePointId() + ", setup=" + vd.getViewSetupId() + ")" );
imgs.add( getImage( type, spimData, vd, false ) );
}
// get all weighting methods
final ArrayList< ArrayList< RealRandomAccessible< FloatType > > > weights = new ArrayList< ArrayList< RealRandomAccessible< FloatType > > >();
for ( int i = 0; i < inputData.size(); ++i )
weights.add( getAllWeights( imgs.get( i ), inputData.get( i ), spimData.getSequenceDescription().getImgLoader() ) );
// 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< ProcessParalellPortion< T > > tasks = new ArrayList< ProcessParalellPortion< T > >();
if ( weights.get( 0 ).size() == 0 ) // no weights
{
for ( final ImagePortion portion : portions )
tasks.add( new ProcessParalellPortion< T >( portion, imgs, interpolatorFactory, getTransforms( inputData ), fusedImg, bb ) );
}
else if ( weights.get( 0 ).size() > 1 ) // many weights
{
for ( final ImagePortion portion : portions )
tasks.add( new ProcessParalellPortionWeights< T >( portion, imgs, weights, interpolatorFactory, getTransforms( inputData ), fusedImg, bb ) );
}
else // one weight
{
final ArrayList< RealRandomAccessible< FloatType > > singleWeight = new ArrayList< RealRandomAccessible< FloatType > >();
for ( int i = 0; i < inputData.size(); ++i )
singleWeight.add( weights.get( i ).get( 0 ) );
for ( final ImagePortion portion : portions )
tasks.add( new ProcessParalellPortionWeight< T >( portion, imgs, singleWeight, interpolatorFactory, getTransforms( 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();
return fusedImg;
}
}