35
35
36
36
import java .util .ArrayList ;
37
37
import java .util .Arrays ;
38
+ import java .util .Collection ;
38
39
import java .util .List ;
39
40
import java .util .concurrent .Callable ;
40
41
import java .util .concurrent .ExecutionException ;
41
42
import java .util .concurrent .ExecutorService ;
42
43
import java .util .concurrent .Future ;
43
44
import java .util .stream .IntStream ;
44
45
import java .util .stream .LongStream ;
45
-
46
- import net .imglib2 .Cursor ;
47
- import net .imglib2 .FinalInterval ;
48
46
import net .imglib2 .Interval ;
49
47
import net .imglib2 .Localizable ;
50
48
import net .imglib2 .Point ;
49
+ import net .imglib2 .RandomAccess ;
51
50
import net .imglib2 .RandomAccessible ;
52
51
import net .imglib2 .RandomAccessibleInterval ;
53
52
import net .imglib2 .Sampler ;
54
53
import net .imglib2 .algorithm .neighborhood .Neighborhood ;
55
54
import net .imglib2 .algorithm .neighborhood .RectangleShape ;
56
55
import net .imglib2 .algorithm .neighborhood .Shape ;
56
+ import net .imglib2 .converter .readwrite .WriteConvertedRandomAccessible ;
57
+ import net .imglib2 .loops .LoopBuilder ;
58
+ import net .imglib2 .parallel .Parallelization ;
59
+ import net .imglib2 .parallel .TaskExecutor ;
60
+ import net .imglib2 .parallel .TaskExecutors ;
57
61
import net .imglib2 .util .ConstantUtils ;
58
- import net .imglib2 .util .Intervals ;
59
62
import net .imglib2 .util .ValuePair ;
60
63
import net .imglib2 .view .IntervalView ;
61
64
import net .imglib2 .view .Views ;
@@ -306,7 +309,7 @@ public static < P, T > List< P > findLocalExtrema(
306
309
* @param numTasks
307
310
* Number of tasks for parallel execution
308
311
* @param splitDim
309
- * Dimension along which input should be split for parallization
312
+ * ignored
310
313
* @return {@link List} of extrema
311
314
* @throws ExecutionException
312
315
* @throws InterruptedException
@@ -320,38 +323,8 @@ public static < P, T > List< P > findLocalExtrema(
320
323
final int numTasks ,
321
324
final int splitDim ) throws InterruptedException , ExecutionException
322
325
{
323
-
324
- final long [] min = Intervals .minAsLongArray ( interval );
325
- final long [] max = Intervals .maxAsLongArray ( interval );
326
-
327
- final long splitDimSize = interval .dimension ( splitDim );
328
- final long splitDimMax = max [ splitDim ];
329
- final long splitDimMin = min [ splitDim ];
330
- final long taskSize = Math .max ( splitDimSize / numTasks , 1 );
331
-
332
- final ArrayList < Callable < List < P > > > tasks = new ArrayList <>();
333
-
334
- for ( long start = splitDimMin , stop = splitDimMin + taskSize - 1 ; start <= splitDimMax ; start += taskSize , stop += taskSize )
335
- {
336
- final long s = start ;
337
- // need max here instead of dimension for constructor of
338
- // FinalInterval
339
- final long S = Math .min ( stop , splitDimMax );
340
- tasks .add ( () -> {
341
- final long [] localMin = min .clone ();
342
- final long [] localMax = max .clone ();
343
- localMin [ splitDim ] = s ;
344
- localMax [ splitDim ] = S ;
345
- return findLocalExtrema ( source , new FinalInterval ( localMin , localMax ), localNeighborhoodCheck , shape );
346
- } );
347
- }
348
-
349
- final ArrayList < P > extrema = new ArrayList <>();
350
- final List < Future < List < P > > > futures = service .invokeAll ( tasks );
351
- for ( final Future < List < P > > f : futures )
352
- extrema .addAll ( f .get () );
353
- return extrema ;
354
-
326
+ TaskExecutor taskExecutor = TaskExecutors .forExecutorServiceAndNumTasks ( service , numTasks );
327
+ return Parallelization .runWithExecutor ( taskExecutor , () -> findLocalExtrema ( source , interval , localNeighborhoodCheck , shape ) );
355
328
}
356
329
357
330
/**
@@ -470,22 +443,30 @@ public static < P, T > List< P > findLocalExtrema(
470
443
final LocalNeighborhoodCheck < P , T > localNeighborhoodCheck ,
471
444
final Shape shape )
472
445
{
446
+ WriteConvertedRandomAccessible < T , RandomAccess < T > > randomAccessible = new WriteConvertedRandomAccessible <>( source , sampler -> (RandomAccess < T >) sampler );
447
+ RandomAccessibleInterval < RandomAccess < T > > centers = Views .interval ( randomAccessible , interval );
448
+ RandomAccessibleInterval < Neighborhood < T > > neighborhoods = Views .interval ( shape .neighborhoodsRandomAccessible ( source ), interval );
449
+ List < List < P > > extremas = LoopBuilder .setImages ( centers , neighborhoods ).multiThreaded ().forEachChunk ( chunk -> {
450
+ List < P > extrema = new ArrayList <>();
451
+ chunk .forEachPixel ( ( center , neighborhood ) -> {
452
+ P p = localNeighborhoodCheck .check ( center , neighborhood );
453
+ if ( p != null )
454
+ extrema .add ( p );
455
+ } );
456
+ return extrema ;
457
+ } );
458
+ return concatenate ( extremas );
459
+ }
473
460
474
- final IntervalView < T > sourceInterval = Views .interval ( source , interval );
475
-
476
- final ArrayList < P > extrema = new ArrayList <>();
477
-
478
- final Cursor < T > center = Views .flatIterable ( sourceInterval ).cursor ();
479
- for ( final Neighborhood < T > neighborhood : shape .neighborhoods ( sourceInterval ) )
480
- {
481
- center .fwd ();
482
- final P p = localNeighborhoodCheck .check ( center , neighborhood );
483
- if ( p != null )
484
- extrema .add ( p );
485
- }
486
-
487
- return extrema ;
488
-
461
+ private static < P > List <P > concatenate ( List <List <P >> lists )
462
+ {
463
+ if (lists .size () == 1 )
464
+ return lists .get ( 0 );
465
+ int size = lists .stream ().mapToInt ( List ::size ).sum ();
466
+ List < P > result = new ArrayList <>( size );
467
+ for ( List < P > list : lists )
468
+ result .addAll ( list );
469
+ return result ;
489
470
}
490
471
491
472
/**
0 commit comments