77
88
99class FindResolutionForSlide :
10- """A class that computes read parameters for slides.
10+ """
11+ A class that computes read parameters for slides.
1112
1213 An instance of class FindResolutionForSlide is a callable that
1314 will add level, target_magnification, scan_magnification,
@@ -22,8 +23,8 @@ class FindResolutionForSlide:
2223 The path of the image file to be read.
2324
2425 target_magnification : float
25- The desired objective magnification for generated tiles. For
26- example, a value of 10 corresponds to about 1 micron per pixel
26+ The desired objective magnification for generated tiles. For
27+ example, a value of 10 corresponds to about 1 micron per pixel
2728 and a value of 20 corresponds to about 0.5 microns per pixel.
2829
2930 magnification_source : str in ["scan", "native", "exact"]
@@ -32,15 +33,15 @@ class FindResolutionForSlide:
3233 magnification.
3334
3435 "native" will produce tiles from the nearest available
35- magnification equal to or greater than target_magnification
36- (within a 2% tolerance). The "native" option is useful when
37- you want to handle resizing of tiles to target_magnification
36+ magnification equal to or greater than target_magnification
37+ (within a 2% tolerance). The "native" option is useful when
38+ you want to handle resizing of tiles to target_magnification
3839 on your own.
3940
4041 "exact" will produce tiles using "native" option and then
41- resize these tiles to match target_magnification. Resizing
42- is handled by PIL using the Lanczos antialiasing filter
43- since the resizing shrinks the tile by definition.
42+ resize these tiles to match target_magnification. Resizing is
43+ handled by PIL using the Lanczos antialiasing filter since the
44+ resizing shrinks the tile by definition.
4445
4546 For either "scan" or "native", the size of the read and
4647 returned tiles will be (tile_height * returned_magnification /
@@ -49,19 +50,24 @@ class FindResolutionForSlide:
4950 tiles will be (tile_height, tile_width).
5051
5152 This procedure sets values in the slide dictionary to capture
52- the scan, read, and returned magnification of the tiles. This is
53- helpful for example to resize results to the scan magnification
54- for visualization in HistomicsUI, or to resize between native
55- and target magnification when using "native". "scan_magnification"
56- is the highest magnification from the source file; "read_magnification"
57- is the magnification read from the source file; "returned_magnification"
58- is the magnification of the returned tiles which is same as
59- "read_magnification" in the case of "scan" or "native" or
60- "target_magnification" in the case of "exact".
53+ the scan, read, and returned magnification of the tiles. This
54+ is helpful for example to resize results to the scan
55+ magnification for visualization in HistomicsUI, or to resize
56+ between native and target magnification when using
57+ "native". "scan_magnification" is the highest magnification
58+ from the source file; "read_magnification" is the
59+ magnification read from the source file;
60+ "returned_magnification" is the magnification of the returned
61+ tiles which is same as "read_magnification" in the case of
62+ "scan" or "native" or "target_magnification" in the case of
63+ "exact".
6164 """
6265
6366 def __init__ (self , study , target_magnification , magnification_source ):
64- """Sanity check the supplied parameters and store them for later use."""
67+ """
68+ Sanity check the supplied parameters and store them for later
69+ use.
70+ """
6571 # Check values.
6672 if not ("version" in study and study ["version" ] == "version-1" ):
6773 raise ValueError ('study["version"] must exist and be equal to "version-1".' )
@@ -82,7 +88,7 @@ def __init__(self, study, target_magnification, magnification_source):
8288 )
8389
8490 # Save values.
85- self .target_magnification = target_magnification
91+ self .target_magnification = float ( target_magnification )
8692 self .magnification_source = magnification_source
8793
8894 def __call__ (self , slide ):
@@ -106,13 +112,11 @@ def __call__(self, slide):
106112 ts = large_image .open (filename )
107113
108114 # scan_magnification = highest available magnification from source
109- scan_magnification = np .float32 (
110- ts .getNativeMagnification ()["magnification" ]
111- )
115+ scan_magnification = float (ts .getNativeMagnification ()["magnification" ])
112116
113117 if self .magnification_source == "exact" :
114- # Use the tile-source level that large_image is
115- # willing to interpolate for us.
118+ # Use the tile-source level that large_image is willing to interpolate
119+ # for us.
116120 preferred_levels = [
117121 ts .getLevelForMagnification (
118122 self .target_magnification , rounding = False
@@ -130,7 +134,7 @@ def __call__(self, slide):
130134
131135 estimated_magnifications = np .array (
132136 [
133- ts .getMagnificationForLevel (level )["magnification" ]
137+ float ( ts .getMagnificationForLevel (level )["magnification" ])
134138 for level in preferred_levels
135139 ]
136140 )
@@ -139,16 +143,24 @@ def __call__(self, slide):
139143 (level , returned_magnification ) = self ._get_level_and_magnifications (
140144 self .target_magnification , estimated_magnifications
141145 )
142- # Rather than as the index into preferred_levels, change
143- # level to be the value that large_image uses
146+ # Rather than as the index into preferred_levels, change level to be the
147+ # value that large_image uses
144148 level = preferred_levels [level ]
145149
146- # If large_image is resampling a native level for us, it
147- # is starting with the preferred level that is the least
148- # one that is not smaller than the resampled level.
149- read_magnification = ts .getMagnificationForLevel (
150- min ([ts .getPreferredLevel (i ) for i in range (ts .levels ) if i >= level ])
151- )["magnification" ]
150+ # If large_image is resampling a native level for us, it is starting with
151+ # the preferred level that is the least one that is not smaller than the
152+ # resampled level.
153+ read_magnification = float (
154+ ts .getMagnificationForLevel (
155+ min (
156+ [
157+ ts .getPreferredLevel (i )
158+ for i in range (ts .levels )
159+ if i >= level
160+ ]
161+ )
162+ )["magnification" ]
163+ )
152164
153165 slide ["target_magnification" ] = self .target_magnification
154166 slide ["scan_magnification" ] = scan_magnification
@@ -157,12 +169,12 @@ def __call__(self, slide):
157169
158170 # We don't want to walk off the right or bottom of the slide so we are
159171 # conservative as to how many pixels large_image will return for us.
160- # 1) large_image starts with an image that is of read_mangification; we
161- # compute the dimensions for read_magnification with math.floor from the
162- # dimensions of scan_magnification (i.e., ts.sizeX and ts.sizeY) to be
163- # conservative.
172+ # 1) large_image starts with an image that is of
173+ # read_magnification; we compute the dimensions for read_magnification
174+ # with math.floor from the dimensions of scan_magnification (i.e.,
175+ # ts.sizeX and ts.sizeY) to be conservative.
164176 # 2) large_image or external software may resampled from the
165- # read_mangification to the target_magnification; we compute dimensions
177+ # read_magnification to the target_magnification; we compute dimensions
166178 # for the target_magnification with math.floor from the
167179 # read_magnification to be conservative.
168180 number_pixel_rows_for_slide = ts .sizeY
@@ -199,7 +211,7 @@ def __call__(self, slide):
199211 source_group = zarr .open (store , mode = "r" )
200212
201213 # scan_magnification = highest available magnification from source
202- scan_magnification = np . float32 (
214+ scan_magnification = float (
203215 source_group .attrs [os .PROPERTY_NAME_OBJECTIVE_POWER ]
204216 )
205217
@@ -217,8 +229,8 @@ def __call__(self, slide):
217229 (level , returned_magnification ) = self ._get_level_and_magnifications (
218230 self .target_magnification , estimated_magnifications
219231 )
220- # Rather than as the index into preferred_levels, change
221- # level to be the value that zarr uses
232+ # Rather than as the index into preferred_levels, change level to be the
233+ # value that zarr uses
222234 level = preferred_levels [level ]
223235
224236 slide ["target_magnification" ] = self .target_magnification
@@ -267,7 +279,9 @@ def __call__(self, slide):
267279 def _get_level_and_magnifications (
268280 self , target_magnification , estimated_magnifications
269281 ):
270- """A private subroutine that computes level and magnifications."""
282+ """
283+ A private subroutine that computes level and magnifications.
284+ """
271285 # calculate difference with magnification levels
272286
273287 magnification_tolerance = 0.02
@@ -291,7 +305,8 @@ def _get_level_and_magnifications(
291305
292306
293307class TilesByGridAndMask :
294- """Select tiles according to a regular grid. Optionally, restrict
308+ """
309+ Select tiles according to a regular grid. Optionally, restrict
295310 the list by a mask that is read from a file. Optionally, further
296311 select a random subset of them.
297312
@@ -302,7 +317,8 @@ class TilesByGridAndMask:
302317 Parameters for the constructor
303318 ------------------------------
304319 study : dictionary
305- The study dictionary from which to read parameters about the study.
320+ The study dictionary from which to read parameters about the
321+ study.
306322 randomly_select: int
307323 The number of tiles to be randomly selected from the list that
308324 would otherwise be written to the slide dictionary. A value
@@ -336,12 +352,15 @@ def __init__(
336352 self ,
337353 study ,
338354 randomly_select = - 1 , # Defaults to select all
339- number_pixel_overlap_rows_for_tile = 0 , # Defaults to no overlap between adjacent tiles
355+ number_pixel_overlap_rows_for_tile = 0 , # Defaults to no overlap
340356 number_pixel_overlap_columns_for_tile = 0 ,
341357 mask_filename = "" , # Defaults to no masking
342358 mask_threshold = 0.0 , # Defaults to any overlap with the mask
343359 ):
344- """Sanity check the supplied parameters and store them for later use."""
360+ """
361+ Sanity check the supplied parameters and store them for later
362+ use.
363+ """
345364 # Check values.
346365 if not ("version" in study and study ["version" ] == "version-1" ):
347366 raise ValueError ('study["version"] must exist and be equal to "version-1".' )
@@ -416,8 +435,10 @@ def __init__(
416435 self .mask_threshold = mask_threshold
417436
418437 def __call__ (self , slide ):
419- """Select tiles according to a regular grid. Optionally, restrict the list by a mask.
420- Optionally, select a random subset of them.
438+ """
439+ Select tiles according to a regular grid. Optionally,
440+ restrict the list by a mask. Optionally, select a random
441+ subset of them.
421442 """
422443 # Check values.
423444 if "number_pixel_rows_for_slide" not in slide :
@@ -561,20 +582,20 @@ def mask_rejects(self, top, left):
561582 bottom = top + self .number_pixel_rows_for_tile
562583 right = left + self .number_pixel_columns_for_tile
563584 mask_top = (
564- top / self .number_pixel_rows_for_slide * self .number_pixel_rows_for_mask
585+ top * self .number_pixel_rows_for_mask / self .number_pixel_rows_for_slide
565586 )
566587 mask_bottom = (
567- bottom / self .number_pixel_rows_for_slide * self .number_pixel_rows_for_mask
588+ bottom * self .number_pixel_rows_for_mask / self .number_pixel_rows_for_slide
568589 )
569590 mask_left = (
570591 left
571- / self .number_pixel_columns_for_slide
572592 * self .number_pixel_columns_for_mask
593+ / self .number_pixel_columns_for_slide
573594 )
574595 mask_right = (
575596 right
576- / self .number_pixel_columns_for_slide
577597 * self .number_pixel_columns_for_mask
598+ / self .number_pixel_columns_for_slide
578599 )
579600 cumulative_top_left = self .interpolate_cumulative (mask_top , mask_left )
580601 cumulative_top_right = self .interpolate_cumulative (mask_top , mask_right )
@@ -598,7 +619,8 @@ def mask_rejects(self, top, left):
598619
599620
600621class TilesByList :
601- """Select the tiles supplied by the user. Optionally, select a
622+ """
623+ Select the tiles supplied by the user. Optionally, select a
602624 random subset of them.
603625
604626 An instance of class TilesByList is a callable that will select
@@ -608,7 +630,8 @@ class TilesByList:
608630 Parameters for the constructor
609631 ------------------------------
610632 study : dictionary
611- The study dictionary from which to read parameters about the study.
633+ The study dictionary from which to read parameters about the
634+ study.
612635 randomly_select: int
613636 The number of tiles to be randomly selected from the list that
614637 would otherwise be written to the slide dictionary. A value
@@ -628,7 +651,10 @@ def __init__(
628651 randomly_select = - 1 , # Defaults to select all
629652 tiles_dictionary = {}, # {'AB234': {'tile_top': top0, 'tile_left': left0}, 'CD43': {'tile_top': top1, 'tile_left': left1}, ...}
630653 ):
631- """Sanity check the supplied parameters and store them for later use."""
654+ """
655+ Sanity check the supplied parameters and store them for later
656+ use.
657+ """
632658 # Check values
633659 if not ("version" in study and study ["version" ] == "version-1" ):
634660 raise ValueError ('study["version"] must exist and be equal to "version-1".' )
@@ -701,7 +727,10 @@ def __init__(
701727 ) # in case user changes it later
702728
703729 def __call__ (self , slide ):
704- """Select the tiles supplied by the user. Optionally, select a random subset of them."""
730+ """
731+ Select the tiles supplied by the user. Optionally, select a
732+ random subset of them.
733+ """
705734 tiles = slide ["tiles" ] = copy .deepcopy (
706735 self .tiles_dictionary
707736 ) # in case __call__ is called again.
@@ -715,7 +744,8 @@ def __call__(self, slide):
715744
716745
717746class TilesRandomly :
718- """Select a random subset of all possible tiles.
747+ """
748+ Select a random subset of all possible tiles.
719749
720750 An instance of class TilesRandomly is a callable that will select
721751 the coordinates of tiles to be taken from a slide. The selected
@@ -724,15 +754,19 @@ class TilesRandomly:
724754 Parameters for the constructor
725755 ------------------------------
726756 study : dictionary
727- The study dictionary from which to read parameters about the study.
757+ The study dictionary from which to read parameters about the
758+ study.
728759 randomly_select: int
729760 The number of tiles to be randomly selected from the slide.
730761 The value must be positive. A value of 1 is the default.
731762
732763 """
733764
734765 def __init__ (self , study , randomly_select = 1 ): # Defaults to select one
735- """Sanity check the supplied parameters and store them for later use."""
766+ """
767+ Sanity check the supplied parameters and store them for later
768+ use.
769+ """
736770 # Check values.
737771 if not ("version" in study and study ["version" ] == "version-1" ):
738772 raise ValueError ('study["version"] must exist and be equal to "version-1".' )
@@ -766,7 +800,9 @@ def __init__(self, study, randomly_select=1): # Defaults to select one
766800 self .randomly_select = randomly_select
767801
768802 def __call__ (self , slide ):
769- """Select a random subset of all possible tiles."""
803+ """
804+ Select a random subset of all possible tiles.
805+ """
770806 if "number_pixel_rows_for_slide" not in slide :
771807 raise ValueError (
772808 'slide["number_pixel_rows_for_slide"] must be already set.'
0 commit comments