11import logging
22import os
3+ import warnings
34from abc import ABC , abstractmethod
45from glob import glob
56from pathlib import Path
@@ -20,7 +21,12 @@ class MicrographSource(ABC):
2021 def __init__ (self , micrograph_count , micrograph_size , dtype , pixel_size = None ):
2122 """ """
2223 self .micrograph_count = int (micrograph_count )
23- self .micrograph_size = int (micrograph_size )
24+ # Expand single integer to 2-tuple
25+ if isinstance (micrograph_size , int ):
26+ micrograph_size = (micrograph_size ,) * 2
27+ if len (micrograph_size ) != 2 :
28+ raise ValueError ("`micrograph_size` should be a integer or 2-tuple" )
29+ self .micrograph_size = tuple (micrograph_size )
2430 self .dtype = np .dtype (dtype )
2531 if pixel_size is not None :
2632 pixel_size = float (pixel_size )
@@ -34,7 +40,7 @@ def __repr__(self):
3440
3541 :return: Returns a string description of instance.
3642 """
37- return f"{ self .__class__ .__name__ } with { self .micrograph_count } { self .dtype .name } micrographs of size { self .micrograph_size } x { self . micrograph_size } "
43+ return f"{ self .__class__ .__name__ } with { self .micrograph_count } { self .dtype .name } micrographs of size { self .micrograph_size } "
3844
3945 def __len__ (self ):
4046 """
@@ -142,14 +148,14 @@ def __init__(self, micrographs, dtype=None, pixel_size=None):
142148 if micrographs .ndim == 2 :
143149 micrographs = micrographs [None , :, :]
144150
145- if micrographs .ndim != 3 or ( micrographs . shape [ - 2 ] != micrographs . shape [ - 1 ]) :
151+ if micrographs .ndim != 3 :
146152 raise NotImplementedError (
147- f"Incompatible `micrographs` shape { micrographs .shape } , expects (count, L, L) "
153+ f"Incompatible `micrographs` shape { micrographs .shape } , expects 2D or 3D array. "
148154 )
149155
150156 super ().__init__ (
151157 micrograph_count = micrographs .shape [0 ],
152- micrograph_size = micrographs .shape [- 1 ],
158+ micrograph_size = micrographs .shape [- 2 : ],
153159 dtype = dtype or micrographs .dtype ,
154160 pixel_size = pixel_size ,
155161 )
@@ -201,15 +207,15 @@ def __init__(self, micrographs_path, dtype=None, pixel_size=None):
201207
202208 # Load the first micrograph to infer shape/type
203209 # Size will be checked during on-the-fly loading of subsequent micrographs.
204- micrograph0 = Image .load (self .micrograph_files [0 ])
205- if micrograph0 . pixel_size is not None and micrograph0 . pixel_size != pixel_size :
206- raise ValueError (
207- f"Mismatched pixel size. { micrograph0 . pixel_size } angstroms defined in { self .micrograph_files [0 ]} , but provided { pixel_size } angstroms."
208- )
210+ micrograph0 , _pixel_size = Image ._load_raw (self .micrograph_files [0 ])
211+ # Compare with user provided pixel size
212+ if pixel_size is not None and _pixel_size != pixel_size :
213+ msg = f"Mismatched pixel size. { _pixel_size } angstroms defined in { self .micrograph_files [0 ]} , but provided { pixel_size } angstroms."
214+ warnings . warn ( msg , UserWarning , stacklevel = 2 )
209215
210216 super ().__init__ (
211217 micrograph_count = len (self .micrograph_files ),
212- micrograph_size = micrograph0 .resolution ,
218+ micrograph_size = micrograph0 .shape [ - 2 :] ,
213219 dtype = dtype or micrograph0 .dtype ,
214220 pixel_size = pixel_size ,
215221 )
@@ -265,28 +271,27 @@ def _images(self, indices):
265271 # Initialize empty result
266272 n_micrographs = len (indices )
267273 micrographs = np .empty (
268- (n_micrographs , self . micrograph_size , self .micrograph_size ),
274+ (n_micrographs , * self .micrograph_size ),
269275 dtype = self .dtype ,
270276 )
271277 for i , ind in enumerate (indices ):
272278 # Load the micrograph image from file
273- micrograph = Image .load (self .micrograph_files [ind ])
279+ micrograph , _pixel_size = Image ._load_raw (self .micrograph_files [ind ])
280+
274281 # Assert size
275- if micrograph .resolution != self .micrograph_size :
282+ if micrograph .shape != self .micrograph_size :
276283 raise NotImplementedError (
277284 f"Micrograph { ind } has inconsistent shape { micrograph .shape } ,"
278- f" expected { ( self .micrograph_size , self . micrograph_size ) } ."
285+ f" expected { self .micrograph_size } ."
279286 )
287+
288+ # Continually compare with initial pixel_size
289+ if _pixel_size is not None and _pixel_size != self .pixel_size :
290+ msg = f"Mismatched pixel size. { micrograph .pixel_size } angstroms defined in { self .micrograph_files [ind ]} , but provided { self .pixel_size } angstroms."
291+ warnings .warn (msg , UserWarning , stacklevel = 2 )
292+
280293 # Assign to array, implicitly performs casting to dtype
281- micrographs [i ] = micrograph .asnumpy ()
282- # Assert pixel_size
283- if (
284- micrograph .pixel_size is not None
285- and micrograph .pixel_size != self .pixel_size
286- ):
287- raise ValueError (
288- f"Mismatched pixel size. { micrograph .pixel_size } angstroms defined in { self .micrograph_files [ind ]} , but provided { self .pixel_size } angstroms."
289- )
294+ micrographs [i ] = micrograph
290295
291296 return Image (micrographs , pixel_size = self .pixel_size )
292297
@@ -313,7 +318,7 @@ def __init__(
313318
314319 :param volume: `Volume` instance to be used in `Simulation`.
315320 An `(L,L,L)` `Volume` will generate `(L,L)` particle images.
316- :param micrograph_size: Size of micrograph in pixels, defaults to 4096.
321+ :param micrograph_size: Size of micrograph in pixels as integer or 2-tuple. Defaults to 4096.
317322 :param micrograph_count: Number of micrographs to generate (integer). Defaults to 1.
318323 :param particles_per_micrograph: The amount of particles generated for each micrograph. Defaults to 10.
319324 :param particle_amplitudes: Optional, amplitudes to pass to `Simulation`.
@@ -354,7 +359,7 @@ def __init__(
354359
355360 self .noise_adder = noise_adder
356361
357- if self .particle_box_size > micrograph_size :
362+ if self .particle_box_size > max ( self . micrograph_size ) :
358363 raise ValueError (
359364 "The micrograph size must be larger or equal to the `particle_box_size`."
360365 )
@@ -415,7 +420,7 @@ def __init__(
415420 else :
416421 if (
417422 boundary < (- self .particle_box_size // 2 )
418- or boundary > self .micrograph_size // 2
423+ or boundary > max ( self .micrograph_size ) // 2
419424 ):
420425 raise ValueError ("Illegal boundary value." )
421426 self .boundary = boundary
@@ -505,8 +510,8 @@ def _set_mask(self):
505510 """
506511 self ._mask = np .full (
507512 (
508- int (self .micrograph_size + 2 * self .pad ),
509- int (self .micrograph_size + 2 * self .pad ),
513+ int (self .micrograph_size [ 0 ] + 2 * self .pad ),
514+ int (self .micrograph_size [ 1 ] + 2 * self .pad ),
510515 ),
511516 False ,
512517 dtype = bool ,
@@ -547,7 +552,7 @@ def _clean_images(self, indices):
547552 # Initialize empty micrograph
548553 n_micrographs = len (indices )
549554 clean_micrograph = np .zeros (
550- (n_micrographs , self . micrograph_size , self .micrograph_size ),
555+ (n_micrographs , * self .micrograph_size ),
551556 dtype = self .dtype ,
552557 )
553558 # Pad the micrograph
@@ -579,8 +584,8 @@ def _clean_images(self, indices):
579584 )
580585 clean_micrograph = clean_micrograph [
581586 :,
582- self .pad : self .micrograph_size + self .pad ,
583- self .pad : self .micrograph_size + self .pad ,
587+ self .pad : self .micrograph_size [ 0 ] + self .pad ,
588+ self .pad : self .micrograph_size [ 1 ] + self .pad ,
584589 ]
585590 return Image (clean_micrograph , pixel_size = self .pixel_size )
586591
0 commit comments