4141import net .imglib2 .view .IntervalView ;
4242import net .imglib2 .view .Views ;
4343
44- import org .apache .commons .lang3 .tuple .ImmutableTriple ;
45- import org .apache .commons .lang3 .tuple .Triple ;
44+ import org .mastodon .mamut .util .ByteFormatter ;
45+ import org .mastodon .mamut .util .ImgSizeUtils ;
46+ import org .mastodon .mamut .detection .util .SpimImageProperties ;
4647import org .mastodon .mamut .model .ModelGraph ;
4748import org .mastodon .mamut .util .LabelImageUtils ;
4849import org .mastodon .tracking .detection .DetectionUtil ;
4950import org .mastodon .tracking .detection .DetectorKeys ;
5051import org .mastodon .tracking .mamut .detection .AbstractSpotDetectorOp ;
52+ import org .scijava .Context ;
53+ import org .scijava .plugin .Parameter ;
5154import org .slf4j .Logger ;
5255import org .slf4j .LoggerFactory ;
5356
@@ -69,6 +72,14 @@ public abstract class DeepLearningDetector extends AbstractSpotDetectorOp
6972
7073 private static final Logger logger = LoggerFactory .getLogger ( MethodHandles .lookup ().lookupClass () );
7174
75+ @ Parameter
76+ protected Context context ;
77+
78+ /**
79+ * Represents the maximum allowable size in bytes for datasets handle via the appose java-python bridge.
80+ */
81+ private static final int MAX_SIZE_IN_BYTES = Integer .MAX_VALUE - 1 ;
82+
7283 @ Override
7384 public void compute ( final List < SourceAndConverter < ? > > sources , final ModelGraph graph )
7485 {
@@ -80,14 +91,13 @@ public void compute( final List< SourceAndConverter< ? > > sources, final ModelG
8091 if ( !validateAndInitializeSettings () )
8192 return ;
8293
83- Triple < Integer , Integer , Integer > settings = extractSettings ( sources );
94+ SpimImageProperties settings = extractSettings ( sources );
8495 if ( settings == null )
8596 return ;
8697 // Now we are sure the settings are valid.
8798
88- int minTimepoint = settings .getLeft ();
89- int maxTimepoint = settings .getMiddle ();
90- int setup = settings .getRight ();
99+ int minTimepoint = settings .getMinTimepoint ();
100+ int maxTimepoint = settings .getMaxTimepoint ();
91101
92102 // Perform detection.
93103 statusService .showStatus ( "Detecting spots..." );
@@ -101,8 +111,8 @@ public void compute( final List< SourceAndConverter< ? > > sources, final ModelG
101111 if ( isCanceled () )
102112 break ; // Exit but don't fail.
103113
104- if ( DetectionUtil .isPresent ( sources , setup , timepoint ) )
105- detectAndAddSpots ( sources , graph , setup , timepoint );
114+ if ( DetectionUtil .isPresent ( sources , settings . getSetupId () , timepoint ) )
115+ detectAndAddSpots ( sources , graph , settings . getSetupId () , timepoint , settings . getResolutionLevel () );
106116 }
107117 }
108118 catch ( Exception e )
@@ -119,14 +129,16 @@ public void compute( final List< SourceAndConverter< ? > > sources, final ModelG
119129 ok = true ;
120130 }
121131
122- private Triple < Integer , Integer , Integer > extractSettings ( final List < SourceAndConverter < ? > > sources )
132+ private SpimImageProperties extractSettings ( final List < SourceAndConverter < ? > > sources )
123133 {
124134 // Extract settings.
125135 final int minTimepoint = ( int ) settings .get ( DetectorKeys .KEY_MIN_TIMEPOINT );
126136 final int maxTimepoint = ( int ) settings .get ( DetectorKeys .KEY_MAX_TIMEPOINT );
127137 final int setup = ( int ) settings .get ( DetectorKeys .KEY_SETUP_ID );
138+ final int level = ( int ) settings .get ( DeepLearningDetectorKeys .KEY_LEVEL );
128139
129- logger .info ( "Settings contain, minTimepoint: {}, maxTimepoint: {} and setup {}" , minTimepoint , maxTimepoint , setup );
140+ logger .info ( "Settings contain, minTimepoint: {}, maxTimepoint: {}, setup: {} and level: {}" , minTimepoint , maxTimepoint , setup ,
141+ level );
130142
131143 if ( setup < 0 || setup >= sources .size () )
132144 {
@@ -142,27 +154,58 @@ private Triple< Integer, Integer, Integer > extractSettings( final List< SourceA
142154 logger .error ( "Invalid time-point range: {}" , errorMessage );
143155 return null ;
144156 }
145- return new ImmutableTriple <>( minTimepoint , maxTimepoint , setup );
157+ int availableLevels = sources .get ( setup ).getSpimSource ().getNumMipmapLevels ();
158+ if ( level < 0 || level >= availableLevels )
159+ {
160+ errorMessage = "The parameter " + DeepLearningDetectorKeys .KEY_LEVEL
161+ + " is not in the range of available resolution levels ( 0 to " + ( availableLevels - 1 ) + "): " + level ;
162+ logger .error ( "Invalid level: {}." , errorMessage );
163+ return null ;
164+ }
165+ return new SpimImageProperties ( minTimepoint , maxTimepoint , setup , level );
146166 }
147167
148168 private void detectAndAddSpots ( final List < SourceAndConverter < ? > > sources , final ModelGraph graph , final int setup ,
149- final int timepoint )
169+ final int timepoint , final int level )
150170 {
151171 // First, get the source for the current channel (or setup) at the desired time-point. In BDV jargon, this is a source.
152172 final Source < ? > source = sources .get ( setup ).getSpimSource ();
153173
154- // level 0 is always the highest resolution.
155- final int level = 0 ;
156-
157174 // This is the 3D image of the current time-point and specified channel. It is always 3D. If the source is 2D, the 3rd dimension has a size of 1.
158175 RandomAccessibleInterval < ? > image = source .getSource ( timepoint , level );
159176
177+ long theoreticalImageSize = 0 ;
178+ try
179+ {
180+ theoreticalImageSize = ImgSizeUtils .getSizeInBytes ( image );
181+ }
182+ catch ( IllegalArgumentException e )
183+ {
184+ logger .info ( "Could not estimate image size." );
185+ }
186+ if ( theoreticalImageSize > MAX_SIZE_IN_BYTES )
187+ {
188+ String actualSize = ByteFormatter .humanReadableByteCount ( theoreticalImageSize );
189+ String maxSize = ByteFormatter .humanReadableByteCount ( MAX_SIZE_IN_BYTES );
190+ logger .warn ( "Size of image at timepoint {}, setup {} and level {} is {}, which is larger than the maximum size of {}." ,
191+ timepoint , setup , level , actualSize , maxSize );
192+ String message = "Size of image at timepoint " + timepoint + ", setup " + setup + " and level " + level + " is " + actualSize
193+ + ", which is larger than the supported maximum size of " + maxSize
194+ + " per timepoint. Consider using a different resolution level or process only a region of interest.\n " ;
195+ throw new InferenceException ( message );
196+ }
197+
160198 // Crop the image to the region of interest (ROI) if specified in the settings.
161199 final Interval roi = ( Interval ) settings .get ( DetectorKeys .KEY_ROI );
162200 if ( roi != null )
201+ {
202+ logger .info ( "Settings contained a roi: {}" , roi );
163203 image = Views .interval ( image , roi );
204+ }
164205
165- final Img < ? > segmentation = performSegmentation ( image , source .getVoxelDimensions ().dimensionsAsDoubleArray () );
206+ System .err .println (); // show the FIJI console
207+ final Img < ? > segmentation =
208+ performSegmentation ( Views .dropSingletonDimensions ( image ), source .getVoxelDimensions ().dimensionsAsDoubleArray () );
166209
167210 if ( segmentation != null )
168211 {
@@ -192,8 +235,11 @@ private boolean validateAndInitializeSettings()
192235 return true ;
193236 }
194237
195- protected double getAnisotropy ( double [] voxelSizes )
238+ protected double getAnisotropy ( double [] voxelSizes , boolean is3D )
196239 {
240+ if ( !is3D )
241+ return 1.0 ;
242+
197243 if ( voxelSizes == null || voxelSizes .length == 0 )
198244 {
199245 throw new IllegalArgumentException ( "Array must not be empty" );
@@ -241,6 +287,7 @@ public Map< String, Object > getDefaultSettings()
241287 defaultSettings .put ( DetectorKeys .KEY_MIN_TIMEPOINT , DetectorKeys .DEFAULT_MIN_TIMEPOINT );
242288 defaultSettings .put ( DetectorKeys .KEY_MAX_TIMEPOINT , DetectorKeys .DEFAULT_MAX_TIMEPOINT );
243289 defaultSettings .put ( DetectorKeys .KEY_ROI , null ); // No ROI by default.
290+ defaultSettings .put ( DeepLearningDetectorKeys .KEY_LEVEL , DeepLearningDetectorKeys .DEFAULT_LEVEL );
244291 addSpecificDefaultSettings ( defaultSettings );
245292 return defaultSettings ;
246293 }
0 commit comments