/*- * #%L * Multiview stitching of large datasets. * %% * Copyright (C) 2016 - 2017 Big Stitcher 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 net.imglib2.algorithm.phasecorrelation; import java.util.List; import java.util.ArrayList; import java.util.Comparator; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import net.imglib2.Cursor; import net.imglib2.FinalInterval; import net.imglib2.Interval; import net.imglib2.Localizable; import net.imglib2.Point; import net.imglib2.RandomAccess; import net.imglib2.RandomAccessible; import net.imglib2.type.numeric.RealType; import net.imglib2.util.Pair; import net.imglib2.util.Util; import net.imglib2.util.ValuePair; import net.imglib2.view.Views; public class FourNeighborhoodExtrema { /** * merge the pre-sorted lists in lists, keep at most the maxN biggest values from any list in the result * @param lists lists to merge * @param maxN maximum size of output list * @param compare comparator * @param <T> list content type * @return merged list with size {@literal < maxN} */ public static <T> ArrayList<T> merge(List<List<T>> lists, final int maxN, Comparator<T> compare){ ArrayList<T> res = new ArrayList<T>(); int[] idxs = new int[lists.size()]; boolean[] hasMore = new boolean[lists.size()]; boolean allDone = true; for (int i = 0; i < lists.size(); i++){ hasMore[i] = lists.get(i).size() > 0; allDone &= !hasMore[i]; } while(!allDone && res.size() < maxN ){ int activeLists = 0; int maxList = 0; for (int i = 0; i<hasMore.length; i++){ if (hasMore[i]){ maxList=i; break; } } for (int i = 0; i< lists.size(); i++){ if(!hasMore[i]){ continue;} activeLists++; if (compare.compare(lists.get(i).get(idxs[i]),(lists.get(maxList).get(idxs[maxList]))) >= 0){ maxList = i; } } res.add(lists.get(maxList).get(idxs[maxList])); idxs[maxList]++; if (idxs[maxList] >= lists.get(maxList).size()){ hasMore[maxList] = false; activeLists--; } allDone = activeLists == 0; } return res; } /** * split the given Interval into nSplits intervals along the largest dimension * @param interval input interval * @param nSplits how may splits * @return list of intervals input was split into */ public static List<Interval> splitAlongLargestDimension(Interval interval, long nSplits){ List<Interval> res = new ArrayList<Interval>(); long[] min = new long[interval.numDimensions()]; long[] max = new long[interval.numDimensions()]; interval.min(min); interval.max(max); int splitDim = 0; for (int i = 0; i< interval.numDimensions(); i++){ if (interval.dimension(i) > interval.dimension(splitDim)) splitDim = i; } // there could be more splits than actual dimension entries nSplits = Math.min( nSplits, interval.dimension(splitDim) ); long chunkSize = interval.dimension(splitDim) / nSplits; long maxSplitDim = max[splitDim]; for (int i = 0; i<nSplits; i++){ if (i != 0){ min[splitDim] += chunkSize; } max[splitDim] = min[splitDim] + chunkSize - 1; if (i == nSplits -1){ max[splitDim] = maxSplitDim; } res.add(new FinalInterval(min, max)); } return res; } public static < T extends RealType< T > > ArrayList< Pair< Localizable, Double > > findMaxMT( final RandomAccessible< T > img, final Interval region, final int maxN , ExecutorService service){ int nTasks = Runtime.getRuntime().availableProcessors() * 4; List<Interval> intervals = splitAlongLargestDimension(region, nTasks); List<Future<ArrayList< Pair< Localizable, Double > >>> futures = new ArrayList<Future<ArrayList<Pair<Localizable,Double>>>>(); for (final Interval i : intervals){ futures.add(service.submit(new Callable<ArrayList< Pair< Localizable, Double > >>() { @Override public ArrayList<Pair<Localizable, Double>> call() throws Exception { return findMax(img, i, maxN); } })); } List<List< Pair< Localizable, Double > >> toMerge = new ArrayList<List<Pair<Localizable,Double>>>(); for (Future<ArrayList< Pair< Localizable, Double > >> f : futures){ try { toMerge.add(f.get()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } ArrayList< Pair< Localizable, Double > > res = merge(toMerge, maxN, new Comparator<Pair< Localizable, Double >>() { @Override public int compare(Pair<Localizable, Double> o1, Pair<Localizable, Double> o2) { return (int) Math.signum(o1.getB() - o2.getB()); } }); return res; } public static < T extends RealType< T > > ArrayList< Pair< Localizable, Double > > findMax( final RandomAccessible< T > img, final Interval region, final int maxN ) { final Cursor< T > c = Views.iterable( Views.interval( img, region ) ).localizingCursor(); final RandomAccess< T > r = img.randomAccess(); final int n = img.numDimensions(); final ArrayList< Pair< Localizable, Double > > list = new ArrayList< Pair< Localizable, Double > >(); for ( int i = 0; i < maxN; ++i ) list.add( new ValuePair< Localizable, Double >( null, -Double.MAX_VALUE ) ); A: while ( c.hasNext() ) { final double type = c.next().getRealDouble(); r.setPosition( c ); for ( int d = 0; d < n; ++d ) { r.fwd( d ); if ( type < r.get().getRealDouble() ) continue A; r.bck( d ); r.bck( d ); if ( type < r.get().getRealDouble() ) continue A; r.fwd( d ); } for ( int i = maxN - 1; i >= 0; --i ) { if ( type < list.get( i ).getB() ) { if ( i == maxN - 1 ) { continue A; } else { list.add( i + 1, new ValuePair< Localizable, Double >( new Point( c ), type ) ); list.remove( maxN ); continue A; } } } list.add( 0, new ValuePair< Localizable, Double >( new Point( c ), type ) ); list.remove( maxN ); } // remove all null elements for ( int i = maxN -1; i >= 0; --i ) if ( list.get( i ).getA() == null ) list.remove( i ); return list; } public static void main( String[] args ) { int maxN = 3; ArrayList< Double > list = new ArrayList< Double >(); list.add( 5.0 ); list.add( 2.0 ); list.add( 0.0 ); /* double type = 10; for ( int i = maxN - 1; i >= 0; --i ) { if ( type < list.get( i ) ) { if ( i == maxN - 1 ) { printList( list ); System.exit( 0 ); } else { list.add( i + 1, type ); list.remove( maxN ); printList( list ); System.exit( 0 ); } } } list.add( 0, type ); list.remove( maxN ); printList( list ); */ ArrayList< Double > list1 = new ArrayList< Double >(); list1.add( 5.0 ); list1.add( 2.0 ); list1.add( 0.0 ); ArrayList< Double > list2 = new ArrayList< Double >(); list2.add( 8.0 ); list2.add( 3.0 ); list2.add( 1.0 ); ArrayList<List<Double>> both = new ArrayList<List<Double>>(); both.add(list1); both.add(list2); ArrayList<Double> res = merge(both, 12, new Comparator<Double>() { @Override public int compare(Double o1, Double o2) { return Double.compare(o1, o2); } }); printList(res); Interval toSplit = new FinalInterval(new long[] {20, 40, 70}); List<Interval> splits = splitAlongLargestDimension(toSplit, 5); } public static void printList( ArrayList< Double > list ) { for ( double d : list ) System.out.println( d ); } }