36
36
37
37
import java .util .ArrayList ;
38
38
import java .util .Arrays ;
39
- import java .util .Collections ;
40
39
import java .util .List ;
41
- import java .util .concurrent .ExecutorService ;
42
- import java .util .concurrent .Executors ;
43
- import java .util .concurrent .TimeUnit ;
44
40
41
+ import net .imglib2 .FinalInterval ;
45
42
import net .imglib2 .Interval ;
46
43
import net .imglib2 .Localizable ;
47
44
import net .imglib2 .Point ;
48
45
import net .imglib2 .RandomAccess ;
49
46
import net .imglib2 .RandomAccessible ;
50
47
import net .imglib2 .RealPoint ;
51
48
import net .imglib2 .RealPositionable ;
49
+ import net .imglib2 .loops .IntervalChunks ;
50
+ import net .imglib2 .parallel .Parallelization ;
51
+ import net .imglib2 .parallel .TaskExecutor ;
52
52
import net .imglib2 .type .numeric .RealType ;
53
53
import net .imglib2 .util .Intervals ;
54
54
import Jama .LUDecomposition ;
59
59
* {@link #refinePeaks(List, RandomAccessible, Interval, boolean, int, boolean, float, boolean[], int)}
60
60
* method to do this, but this has a lot of parameters. Therefore, this class
61
61
* can also be instantiated to encapsulate the parameter settings.
62
- *
62
+ *
63
63
* <p>
64
64
* A List {@link RefinedPeak} for the given list of {@link Localizable} is
65
65
* computed by, for each peak, fitting a quadratic function to the image and
68
68
* repeated at the corresponding integer coordinates. This is repeated to
69
69
* convergence, for a maximum number of iterations, or until the integer
70
70
* coordinates move out of the valid image.
71
- *
71
+ *
72
72
* @author Stephan Preibisch
73
73
* @author Tobias Pietzsch
74
74
*/
@@ -93,8 +93,6 @@ public SubpixelLocalization( final int numDimensions )
93
93
// principally one can move in any dimension
94
94
allowedToMoveInDim = new boolean [ numDimensions ];
95
95
Arrays .fill ( allowedToMoveInDim , true );
96
-
97
- numThreads = Runtime .getRuntime ().availableProcessors ();
98
96
}
99
97
100
98
public void setAllowMaximaTolerance ( final boolean allowMaximaTolerance )
@@ -164,14 +162,14 @@ public boolean getReturnInvalidPeaks()
164
162
165
163
public int getNumThreads ()
166
164
{
167
- return numThreads ;
165
+ return numThreads == 0 ? Parallelization . getTaskExecutor (). getParallelism () : numThreads ;
168
166
}
169
167
170
168
/**
171
169
* Refine a set of peaks to subpixel coordinates. Calls
172
170
* {@link #refinePeaks(List, RandomAccessible, Interval, boolean, int, boolean, float, boolean[], int)}
173
171
* with the parameters set to this object.
174
- *
172
+ *
175
173
* @param peaks
176
174
* List of integer peaks.
177
175
* @param img
@@ -184,7 +182,13 @@ public int getNumThreads()
184
182
*/
185
183
public ArrayList < RefinedPeak < P > > process ( final List < P > peaks , final RandomAccessible < T > img , final Interval validInterval )
186
184
{
187
- return refinePeaks ( peaks , img , validInterval , returnInvalidPeaks , maxNumMoves , allowMaximaTolerance , maximaTolerance , allowedToMoveInDim , numThreads );
185
+ if ( numThreads != 0 )
186
+ return Parallelization .runWithNumThreads ( numThreads ,
187
+ () -> refinePeaks ( peaks , img , validInterval , returnInvalidPeaks , maxNumMoves ,
188
+ allowMaximaTolerance , maximaTolerance , allowedToMoveInDim ) );
189
+ else
190
+ return refinePeaks ( peaks , img , validInterval , returnInvalidPeaks , maxNumMoves ,
191
+ allowMaximaTolerance , maximaTolerance , allowedToMoveInDim );
188
192
}
189
193
190
194
/**
@@ -197,7 +201,7 @@ public ArrayList< RefinedPeak< P > > process( final List< P > peaks, final Rando
197
201
* fit is repeated at the corresponding integer coordinates. This is
198
202
* repeated to convergence, for a maximum number of iterations, or until the
199
203
* integer coordinates move out of the valid image.
200
- *
204
+ *
201
205
* @param peaks
202
206
* List of integer peaks.
203
207
* @param img
@@ -231,45 +235,9 @@ public static < T extends RealType< T >, P extends Localizable > ArrayList< Refi
231
235
final int maxNumMoves , final boolean allowMaximaTolerance , final float maximaTolerance , final boolean [] allowedToMoveInDim ,
232
236
final int numThreads )
233
237
{
234
- final int numPeaks = peaks .size ();
235
- final ArrayList < RefinedPeak < P > > allRefinedPeaks = new ArrayList < RefinedPeak < P > >( numPeaks );
236
-
237
- if ( numPeaks == 0 )
238
- return allRefinedPeaks ;
239
-
240
- final int numTasks = numThreads <= 1 ? 1 : ( int ) Math .min ( numPeaks , numThreads * 20 );
241
- final int taskSize = numPeaks / numTasks ;
242
-
243
- final ExecutorService ex = Executors .newFixedThreadPool ( numThreads );
244
- final List < RefinedPeak < P > > synchronizedAllRefinedPeaks = Collections .synchronizedList ( allRefinedPeaks );
245
- for ( int taskNum = 0 ; taskNum < numTasks ; ++taskNum )
246
- {
247
- final int fromIndex = taskNum * taskSize ;
248
- final int toIndex = ( taskNum == numTasks - 1 ) ? numPeaks : fromIndex + taskSize ;
249
- final Runnable r = new Runnable ()
250
- {
251
- @ Override
252
- public void run ()
253
- {
254
- final ArrayList < RefinedPeak < P > > refinedPeaks = refinePeaks (
255
- peaks .subList ( fromIndex , toIndex ),
256
- img , validInterval , returnInvalidPeaks , maxNumMoves , allowMaximaTolerance , maximaTolerance , allowedToMoveInDim );
257
- synchronizedAllRefinedPeaks .addAll ( refinedPeaks );
258
- }
259
- };
260
- ex .execute ( r );
261
- }
262
- ex .shutdown ();
263
- try
264
- {
265
- ex .awaitTermination ( 1000 , TimeUnit .DAYS );
266
- }
267
- catch ( final InterruptedException e )
268
- {
269
- e .printStackTrace ();
270
- }
271
-
272
- return allRefinedPeaks ;
238
+ return Parallelization .runWithNumThreads ( numThreads ,
239
+ () -> refinePeaks ( peaks , img , validInterval , returnInvalidPeaks , maxNumMoves , allowMaximaTolerance , maximaTolerance ,
240
+ allowedToMoveInDim ) );
273
241
}
274
242
275
243
/**
@@ -282,7 +250,7 @@ public void run()
282
250
* fit is repeated at the corresponding integer coordinates. This is
283
251
* repeated to convergence, for a maximum number of iterations, or until the
284
252
* integer coordinates move out of the valid image.
285
- *
253
+ *
286
254
* @param peaks
287
255
* List of integer peaks.
288
256
* @param img
@@ -313,7 +281,38 @@ public static < T extends RealType< T >, P extends Localizable > ArrayList< Refi
313
281
final List < P > peaks , final RandomAccessible < T > img , final Interval validInterval , final boolean returnInvalidPeaks ,
314
282
final int maxNumMoves , final boolean allowMaximaTolerance , final float maximaTolerance , final boolean [] allowedToMoveInDim )
315
283
{
316
- final ArrayList < RefinedPeak < P >> refinedPeaks = new ArrayList < RefinedPeak < P > >();
284
+ final int numPeaks = peaks .size ();
285
+
286
+ if ( numPeaks == 0 )
287
+ return new ArrayList <>();
288
+
289
+ TaskExecutor taskExecutor = Parallelization .getTaskExecutor ();
290
+
291
+ List < Interval > chunks = IntervalChunks .chunkInterval ( new FinalInterval ( numPeaks ), taskExecutor .suggestNumberOfTasks () );
292
+
293
+ List < ArrayList < RefinedPeak < P > > > result = taskExecutor .forEachApply ( chunks , chunk ->
294
+ refinePeaksChunk (
295
+ peaks .subList ( ( int ) chunk .min ( 0 ), ( int ) chunk .max ( 0 ) + 1 ),
296
+ img , validInterval , returnInvalidPeaks , maxNumMoves , allowMaximaTolerance ,
297
+ maximaTolerance , allowedToMoveInDim )
298
+ );
299
+
300
+ return concatenate ( result );
301
+ }
302
+
303
+ private static < P > ArrayList < P > concatenate ( List < ? extends List < ? extends P > > lists )
304
+ {
305
+ int size = lists .stream ().mapToInt ( List ::size ).sum ();
306
+ ArrayList < P > result = new ArrayList <>( size );
307
+ lists .forEach ( result ::addAll );
308
+ return result ;
309
+ }
310
+
311
+ public static < T extends RealType < T >, P extends Localizable > ArrayList < RefinedPeak < P > > refinePeaksChunk (
312
+ final List < P > peaks , final RandomAccessible < T > img , final Interval validInterval , final boolean returnInvalidPeaks ,
313
+ final int maxNumMoves , final boolean allowMaximaTolerance , final float maximaTolerance , final boolean [] allowedToMoveInDim )
314
+ {
315
+ final ArrayList < RefinedPeak < P > > refinedPeaks = new ArrayList < RefinedPeak < P > >();
317
316
318
317
final int n = img .numDimensions ();
319
318
@@ -420,7 +419,7 @@ else if ( returnInvalidPeaks )
420
419
/**
421
420
* Estimate subpixel {@code offset} of extremum of quadratic function
422
421
* fitted at {@code p}.
423
- *
422
+ *
424
423
* @param p
425
424
* integer position at which to fit quadratic.
426
425
* @param access
0 commit comments