roman-snpit-snappl 0.9.1__tar.gz → 0.11.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of roman-snpit-snappl might be problematic. Click here for more details.

Files changed (87) hide show
  1. {roman_snpit_snappl-0.9.1/roman_snpit_snappl.egg-info → roman_snpit_snappl-0.11.0}/PKG-INFO +1 -1
  2. roman_snpit_snappl-0.11.0/changes/57.snappl.rst +1 -0
  3. roman_snpit_snappl-0.11.0/changes/58.snappl.rst +1 -0
  4. roman_snpit_snappl-0.11.0/changes/61.bugfix.rst +1 -0
  5. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0/roman_snpit_snappl.egg-info}/PKG-INFO +1 -1
  6. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/roman_snpit_snappl.egg-info/SOURCES.txt +3 -0
  7. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/_version.py +3 -3
  8. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/image.py +85 -46
  9. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/imagecollection.py +5 -2
  10. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.cruft.json +0 -0
  11. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/CODEOWNERS +0 -0
  12. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +0 -0
  13. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md +0 -0
  14. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/ISSUE_TEMPLATE/PR_TEMPLATE.md +0 -0
  15. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/dependabot.yml +0 -0
  16. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/labeler.yml +0 -0
  17. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/workflows/changelog.yml +0 -0
  18. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/workflows/run_labeler.yml +0 -0
  19. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/workflows/run_snappl_tests.yml +0 -0
  20. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/workflows/sphinx-deploy.yml +0 -0
  21. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.github/workflows/sub_package_update.yml +0 -0
  22. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.gitignore +0 -0
  23. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/.pre-commit-config.yaml +0 -0
  24. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/CHANGES.rst +0 -0
  25. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/CITATION.cff +0 -0
  26. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/CODE_OF_CONDUCT.md +0 -0
  27. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/CONTRIBUTING.md +0 -0
  28. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/LICENSE +0 -0
  29. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/MANIFEST.in +0 -0
  30. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/README.rst +0 -0
  31. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/.gitkeep +0 -0
  32. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/10.snappl.rst +0 -0
  33. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/13.bugfix.rst +0 -0
  34. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/14.snappl.rst +0 -0
  35. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/15.feature.rst +0 -0
  36. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/16.feature.rst +0 -0
  37. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/18.feature.rst +0 -0
  38. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/20.bugfix.rst +0 -0
  39. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/23.snappl.rst +0 -0
  40. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/26.feature.rst +0 -0
  41. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/29.feature.rst +0 -0
  42. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/3.snappl.rst +0 -0
  43. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/31.feature.rst +0 -0
  44. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/35.snappl.rst +0 -0
  45. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/36.snappl.rst +0 -0
  46. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/37.snappl.rst +0 -0
  47. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/40.snappl.rst +0 -0
  48. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/41.snappl.rst +0 -0
  49. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/43.snappl.rst +0 -0
  50. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/47.feature.rst +0 -0
  51. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/49.docs.rst +0 -0
  52. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/5.snappl.rst +0 -0
  53. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/54.snappl.rst +0 -0
  54. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/8.snappl.rst +0 -0
  55. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/changes/9.snappl.rst +0 -0
  56. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/codespell-ignore.txt +0 -0
  57. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/docs/Makefile +0 -0
  58. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/docs/_static/logo_black_filled.png +0 -0
  59. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/docs/api.rst +0 -0
  60. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/docs/changes.rst +0 -0
  61. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/docs/conf.py +0 -0
  62. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/docs/index.rst +0 -0
  63. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/docs/installation.rst +0 -0
  64. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/docs/make.bat +0 -0
  65. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/docs/usage.rst +0 -0
  66. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/experimentation/README.md +0 -0
  67. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/experimentation/play_with_photutils.py +0 -0
  68. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/licenses/.DS_Store +0 -0
  69. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/licenses/LICENSE.rst +0 -0
  70. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/licenses/README.rst +0 -0
  71. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/licenses/TEMPLATE_LICENSE.rst +0 -0
  72. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/pyproject.toml +0 -0
  73. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/roman_snpit_snappl.egg-info/dependency_links.txt +0 -0
  74. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/roman_snpit_snappl.egg-info/not-zip-safe +0 -0
  75. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/roman_snpit_snappl.egg-info/requires.txt +0 -0
  76. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/roman_snpit_snappl.egg-info/top_level.txt +0 -0
  77. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/setup.cfg +0 -0
  78. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/setup.py +0 -0
  79. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/__init__.py +0 -0
  80. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/_dev/__init__.py +0 -0
  81. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/_dev/scm_version.py +0 -0
  82. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/data/README.rst +0 -0
  83. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/diaobject.py +0 -0
  84. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/psf.py +0 -0
  85. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/sed.py +0 -0
  86. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/snappl/wcs.py +0 -0
  87. {roman_snpit_snappl-0.9.1 → roman_snpit_snappl-0.11.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roman_snpit_snappl
3
- Version: 0.9.1
3
+ Version: 0.11.0
4
4
  Summary: Photometry utilities for the Roman SNPIT
5
5
  Author: Roman Supernova Project Infrastructure Team
6
6
  Maintainer-email: Roman SN PIT <raknop@lbl.gov>
@@ -0,0 +1 @@
1
+ Small imagecollection bugfixes.
@@ -0,0 +1 @@
1
+ Allow for kwargs to be passed to get_ra_dec_cutout in snappl.image.Image
@@ -0,0 +1 @@
1
+ Fix mjd getter for OpenUniverse2024FITSImage
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roman_snpit_snappl
3
- Version: 0.9.1
3
+ Version: 0.11.0
4
4
  Summary: Photometry utilities for the Roman SNPIT
5
5
  Author: Roman Supernova Project Infrastructure Team
6
6
  Maintainer-email: Roman SN PIT <raknop@lbl.gov>
@@ -46,6 +46,9 @@ changes/47.feature.rst
46
46
  changes/49.docs.rst
47
47
  changes/5.snappl.rst
48
48
  changes/54.snappl.rst
49
+ changes/57.snappl.rst
50
+ changes/58.snappl.rst
51
+ changes/61.bugfix.rst
49
52
  changes/8.snappl.rst
50
53
  changes/9.snappl.rst
51
54
  docs/Makefile
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.9.1'
32
- __version_tuple__ = version_tuple = (0, 9, 1)
31
+ __version__ = version = '0.11.0'
32
+ __version_tuple__ = version_tuple = (0, 11, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g1b1e672b9'
34
+ __commit_id__ = commit_id = 'gb17d1c2bc'
@@ -104,6 +104,7 @@ class Image:
104
104
  self.path = pathlib.Path( path )
105
105
  self._pointing = pointing
106
106
  self._sca = sca
107
+ self._mjd = None
107
108
  self._wcs = None # a BaseWCS object (in wcs.py)
108
109
  self._is_cutout = False
109
110
  self._zeropoint = None
@@ -207,6 +208,12 @@ class Image:
207
208
  """MJD of the start of the image (defined how? TAI?)"""
208
209
  raise NotImplementedError( f"{self.__class__.__name__} needs to implement mjd" )
209
210
 
211
+ @mjd.setter
212
+ def mjd( self, val ):
213
+ # We need an MJD setter so that ImageCollection can set the MJD when fetching the images, much faster than
214
+ # reading the header each time!
215
+ self._mjd = val
216
+
210
217
  @property
211
218
  def position_angle( self ):
212
219
  """Position angle in degrees east of north (or what)?"""
@@ -282,13 +289,64 @@ class Image:
282
289
  """Set self._zeropoint; see "zeropoint" property above."""
283
290
  raise NotImplementedError( f"{self.__class__.__name__} needs to implement _get_zeropoint" )
284
291
 
285
- def get_cutout(self, ra, dec, size):
292
+ def get_ra_dec_cutout(self, ra, dec, xsize, ysize=None, mode="strict", fill_value=np.nan):
293
+ """Creates a new snappl image object that is a cutout of the original image, at a location in pixel-space.
294
+
295
+ Parameters
296
+ ----------
297
+ ra : float
298
+ RA coordinate of the center of the cutout, in degrees.
299
+ dec : float
300
+ DEC coordinate of the center of the cutout, in degrees.
301
+ xsize : int
302
+ Width of the cutout in pixels.
303
+ ysize : int
304
+ Height of the cutout in pixels. If None, set to xsize.
305
+ mode : str, default 'strict'
306
+ "strict" does not allow for partial overlap between the cutout and the original image,
307
+ "partial" will fill in non-overlapping pixels with fill_value. This is identical to the
308
+ mode parameter of astropy.nddata.Cutout2D.
309
+ fill_value : float, default np.nan
310
+ Fill value for pixels that are outside the original
311
+ image when mode='partial'. This is identical to the fill_value parameter
312
+ of astropy.nddata.Cutout2D.
313
+
314
+ Returns
315
+ -------
316
+ cutout : snappl.image.Image
317
+ A new snappl image object that is a cutout of the original image.
318
+ """
319
+ raise NotImplementedError( f"{self.__class__.__name__} needs to implement get_ra_dec_cutout" )
320
+
321
+ def get_cutout(self, ra, dec, xsize, ysize=None, mode='strict', fill_value=np.nan):
286
322
 
287
323
  """Make a cutout of the image at the given RA and DEC.
324
+ This implementation assumes that the image WCS is an AstropyWCS.
325
+
326
+ Parameters
327
+ ----------
328
+ x : int
329
+ x pixel coordinate of the center of the cutout.
330
+ y : int
331
+ y pixel coordinate of the center of the cutout.
332
+ xsize : int
333
+ Width of the cutout in pixels.
334
+ ysize : int
335
+ Height of the cutout in pixels. If None, set to xsize.
336
+ mode : str, default 'strict'
337
+ "strict" does not allow for partial overlap between the cutout and the original image,
338
+ "partial" will fill in non-overlapping pixels with fill_value. This is identical to the
339
+ mode parameter of astropy.nddata.Cutout2D.
340
+ fill_value : float, default np.nan
341
+ Fill value for pixels that are outside the original
342
+ image when mode='partial'. This is identical to the fill_value parameter
343
+ of astropy.nddata.Cutout2D.
288
344
 
289
345
  Returns
290
346
  -------
291
- snappl.image.Image
347
+ cutout : snappl.image.Image
348
+ A new snappl image object that is a cutout of the original image.
349
+
292
350
  """
293
351
  raise NotImplementedError( f"{self.__class__.__name__} needs to implement get_cutout" )
294
352
 
@@ -594,27 +652,10 @@ class FITSImage( Numpy2DImage ):
594
652
  else:
595
653
  raise RuntimeError("get_data called with which='flags', but flags are not set.")
596
654
 
597
- def get_cutout(self, x, y, xsize, ysize=None):
598
- """Creates a new snappl image object that is a cutout of the original image, at a location in pixel-space.
599
-
600
- This implementation (in FITSImage) assumes that the image WCS is an AstropyWCS.
601
-
602
- Parameters
603
- ----------
604
- x : int
605
- x pixel coordinate of the center of the cutout.
606
- y : int
607
- y pixel coordinate of the center of the cutout.
608
- xsize : int
609
- Width of the cutout in pixels.
610
- ysize : int
611
- Height of the cutout in pixels. If None, set to xsize.
612
-
613
- Returns
614
- -------
615
- cutout : snappl.image.Image
616
- A new snappl image object that is a cutout of the original image.
655
+ def get_cutout(self, x, y, xsize, ysize=None, mode='strict', fill_value=np.nan):
656
+ """See Image.get_cutout
617
657
 
658
+ The mode and fill_value parameters are passed directly to astropy.nddata.Cutout2D for FITSImage.
618
659
  """
619
660
  if not all( [ isinstance( x, (int, np.integer) ),
620
661
  isinstance( y, (int, np.integer) ),
@@ -638,9 +679,13 @@ class FITSImage( Numpy2DImage ):
638
679
  apwcs = None if wcs is None else wcs._wcs
639
680
 
640
681
  # Remember that numpy arrays are indexed [y, x] (at least if they're read with astropy.io.fits)
641
- astropy_cutout = Cutout2D(data, (x, y), size=(ysize, xsize), mode='strict', wcs=apwcs)
642
- astropy_noise = Cutout2D(noise, (x, y), size=(ysize, xsize), mode='strict', wcs=apwcs)
643
- astropy_flags = Cutout2D(flags, (x, y), size=(ysize, xsize), mode='strict', wcs=apwcs)
682
+
683
+ astropy_cutout = Cutout2D(data, (x, y), size=(ysize, xsize), wcs=apwcs, mode=mode, fill_value=fill_value)
684
+ astropy_noise = Cutout2D(noise, (x, y), size=(ysize, xsize), wcs=apwcs, mode=mode, fill_value=fill_value)
685
+ # Because flags are integer, we can't use the same fill_value as the default.
686
+ # Per the slack channel, it seemed 1 will be used for bad pixels.
687
+ # https://github.com/spacetelescope/roman_datamodels/blob/main/src/roman_datamodels/dqflags.py
688
+ astropy_flags = Cutout2D(flags, (x, y), size=(ysize, xsize), wcs=apwcs, mode=mode, fill_value=1)
644
689
 
645
690
  snappl_cutout = self.__class__(self.path)
646
691
  snappl_cutout._data = astropy_cutout.data
@@ -651,31 +696,17 @@ class FITSImage( Numpy2DImage ):
651
696
 
652
697
  return snappl_cutout
653
698
 
654
- def get_ra_dec_cutout(self, ra, dec, xsize, ysize=None):
655
- """Creates a new snappl image object that is a cutout of the original image, at a location in pixel-space.
699
+ def get_ra_dec_cutout(self, ra, dec, xsize, ysize=None, mode='strict', fill_value=np.nan):
700
+ """See Image.get_ra_dec_cutout
656
701
 
657
- Parameters
658
- ----------
659
- ra : float
660
- RA coordinate of the center of the cutout, in degrees.
661
- dec : float
662
- DEC coordinate of the center of the cutout, in degrees.
663
- xsize : int
664
- Width of the cutout in pixels.
665
- ysize : int
666
- Height of the cutout in pixels. If None, set to xsize.
667
-
668
- Returns
669
- -------
670
- cutout : snappl.image.Image
671
- A new snappl image object that is a cutout of the original image.
702
+ The mode and fill_value parameters are passed directly to astropy.nddata.Cutout2D for FITSImage.
672
703
  """
673
704
 
674
705
  wcs = self.get_wcs()
675
706
  x, y = wcs.world_to_pixel( ra, dec )
676
707
  x = int( np.floor( x + 0.5 ) )
677
708
  y = int( np.floor( y + 0.5 ) )
678
- return self.get_cutout( x, y, xsize, ysize )
709
+ return self.get_cutout( x, y, xsize, ysize, mode=mode, fill_value=fill_value )
679
710
 
680
711
 
681
712
  # ======================================================================
@@ -686,7 +717,7 @@ class FITSImage( Numpy2DImage ):
686
717
 
687
718
  class ManualFITSImage(FITSImage):
688
719
  def __init__(self, header, data=None, noise=None, flags=None,
689
- path = None, exposure = None, sca = None, *args, **kwargs):
720
+ path=None, exposure=None, sca=None, *args, **kwargs):
690
721
 
691
722
  self._data = data
692
723
  self._noise = noise
@@ -919,8 +950,16 @@ class OpenUniverse2024FITSImage( FITSImageOnDisk ):
919
950
  TODO : is this start-time, mid-time, or end-time?
920
951
 
921
952
  """
922
- header = self.get_fits_header()
923
- return float( header['MJD-OBS'] )
953
+ if self._mjd is None:
954
+ header = self.get_fits_header()
955
+ self._mjd = float( header['MJD-OBS'] )
956
+ return self._mjd
957
+
958
+ @mjd.setter
959
+ def mjd( self, val ):
960
+ # We need an MJD setter so that ImageCollection can set the MJD when fetching the images, much faster than
961
+ # reading the header each time!
962
+ self._mjd = val
924
963
 
925
964
  @property
926
965
  def exptime( self ):
@@ -240,12 +240,15 @@ class ImageCollectionOU2024:
240
240
  if exptime_max is not None:
241
241
  params['exptime_max'] = float(exptime_max)
242
242
 
243
- res = retry_post( "https://roman-desc-simdex.lbl.gov/findromanimages", json=params )
243
+ res = retry_post( "https://roman-desc-simdex.lbl.gov/findromanimages", json=params ).json()
244
244
 
245
245
  images = []
246
246
  for i in range( len(res['pointing']) ):
247
247
  path = self.get_image_path( res['pointing'][i], res['filter'][i], res['sca'][i] )
248
- images.append( OpenUniverse2024FITSImage( path, None, res['sca'][i] ) )
248
+ image = OpenUniverse2024FITSImage(path, None, res["sca"][i])
249
+ image.mjd = res['mjd'][i]
250
+ images.append( image )
251
+
249
252
 
250
253
  return images
251
254