roman-snpit-snappl 0.2.2__tar.gz → 0.2.4__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 (73) hide show
  1. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/workflows/run_snappl_tests.yml +1 -1
  2. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/MANIFEST.in +2 -1
  3. {roman_snpit_snappl-0.2.2/roman_snpit_snappl.egg-info → roman_snpit_snappl-0.2.4}/PKG-INFO +1 -1
  4. roman_snpit_snappl-0.2.4/changes/14.snappl.rst +1 -0
  5. roman_snpit_snappl-0.2.4/changes/9.snappl.rst +1 -0
  6. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/pyproject.toml +1 -1
  7. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4/roman_snpit_snappl.egg-info}/PKG-INFO +1 -1
  8. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/roman_snpit_snappl.egg-info/SOURCES.txt +3 -13
  9. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/snappl/__init__.py +1 -1
  10. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/snappl/_dev/__init__.py +2 -1
  11. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/snappl/_version.py +2 -2
  12. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/snappl/image.py +37 -53
  13. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/snappl/psf.py +8 -9
  14. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/snappl/wcs.py +10 -5
  15. roman_snpit_snappl-0.2.2/examples/config_example.py +0 -48
  16. roman_snpit_snappl-0.2.2/examples/config_example.yaml +0 -12
  17. roman_snpit_snappl-0.2.2/snappl/tests/__init__.py +0 -1
  18. roman_snpit_snappl-0.2.2/snappl/tests/conftest.py +0 -6
  19. roman_snpit_snappl-0.2.2/snappl/tests/docker-compose.yaml +0 -44
  20. roman_snpit_snappl-0.2.2/snappl/tests/image_test_data/Roman_TDS_simple_model_F184_662_11.fits.gz +0 -0
  21. roman_snpit_snappl-0.2.2/snappl/tests/image_test_data/test_cutout.npy +0 -0
  22. roman_snpit_snappl-0.2.2/snappl/tests/psf_test_data/testpsfarray.npz +0 -0
  23. roman_snpit_snappl-0.2.2/snappl/tests/test_opensim2024fitsimage.py +0 -41
  24. roman_snpit_snappl-0.2.2/snappl/tests/test_oversampled_image_psf.py +0 -25
  25. roman_snpit_snappl-0.2.2/snappl/tests/test_version_string.py +0 -3
  26. roman_snpit_snappl-0.2.2/snappl/tests/test_yaml_serialized_oversampled_image_psf.py +0 -46
  27. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.cruft.json +0 -0
  28. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/CODEOWNERS +0 -0
  29. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +0 -0
  30. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md +0 -0
  31. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/ISSUE_TEMPLATE/PR_TEMPLATE.md +0 -0
  32. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/dependabot.yml +0 -0
  33. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/labeler.yml +0 -0
  34. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/workflows/changelog.yml +0 -0
  35. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/workflows/run_labeler.yml +0 -0
  36. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/workflows/sphinx-deploy.yml +0 -0
  37. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.github/workflows/sub_package_update.yml +0 -0
  38. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.gitignore +0 -0
  39. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/.pre-commit-config.yaml +0 -0
  40. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/CHANGES.rst +0 -0
  41. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/CITATION.cff +0 -0
  42. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/CODE_OF_CONDUCT.md +0 -0
  43. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/CONTRIBUTING.md +0 -0
  44. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/LICENSE +0 -0
  45. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/README.rst +0 -0
  46. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/changes/.gitkeep +0 -0
  47. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/changes/10.snappl.rst +0 -0
  48. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/changes/13.bugfix.rst +0 -0
  49. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/changes/3.snappl.rst +0 -0
  50. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/changes/5.snappl.rst +0 -0
  51. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/changes/8.snappl.rst +0 -0
  52. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/codespell-ignore.txt +0 -0
  53. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/docs/Makefile +0 -0
  54. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/docs/_static/logo_black_filled.png +0 -0
  55. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/docs/changes.rst +0 -0
  56. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/docs/conf.py +0 -0
  57. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/docs/index.rst +0 -0
  58. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/docs/installation.rst +0 -0
  59. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/docs/make.bat +0 -0
  60. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/docs/usage.rst +0 -0
  61. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/licenses/.DS_Store +0 -0
  62. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/licenses/LICENSE.rst +0 -0
  63. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/licenses/README.rst +0 -0
  64. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/licenses/TEMPLATE_LICENSE.rst +0 -0
  65. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/roman_snpit_snappl.egg-info/dependency_links.txt +0 -0
  66. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/roman_snpit_snappl.egg-info/not-zip-safe +0 -0
  67. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/roman_snpit_snappl.egg-info/requires.txt +0 -0
  68. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/roman_snpit_snappl.egg-info/top_level.txt +0 -0
  69. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/setup.cfg +0 -0
  70. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/setup.py +0 -0
  71. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/snappl/_dev/scm_version.py +0 -0
  72. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/snappl/data/README.rst +0 -0
  73. {roman_snpit_snappl-0.2.2 → roman_snpit_snappl-0.2.4}/tox.ini +0 -0
@@ -42,7 +42,7 @@ jobs:
42
42
 
43
43
  - name: pull latest SNPIT cpu image
44
44
  run: |
45
- docker pull rknop/roman-snpit-env:cpu
45
+ docker pull rknop/roman-snpit-env:cpu-dev
46
46
 
47
47
  - name: run test
48
48
  run: |
@@ -8,4 +8,5 @@ global-exclude *.pyc *.o
8
8
  prune snappl/_version.py
9
9
  include LICENSE
10
10
  include README.rst
11
- include pyproject.toml
11
+ include pyproject.toml
12
+ prune snappl/tests
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roman_snpit_snappl
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Photometry utilities for the Roman SNPIT
5
5
  Author: Roman Supernove Project Infrastructure Team
6
6
  Maintainer-email: Roman SN PIT <raknop@lbl.gov>
@@ -0,0 +1 @@
1
+ Remove tests from what gets packaged for distribution
@@ -0,0 +1 @@
1
+ Added ability to set data from outside of the Image object for sky mean subtraction.
@@ -167,7 +167,7 @@ select = [ 'F', 'E101', 'E111', 'E112', 'E113', 'E115', 'E117',
167
167
  # This can be .rst or .md, towncrier's default template works with both.
168
168
  filename = "CHANGES.rst"
169
169
  directory = "changes"
170
- package = "roman_snpit_snappl"
170
+ package = "snappl"
171
171
  package_dir = "snappl"
172
172
  title_format = "{version} ({project_date})"
173
173
  ignore = [".gitkeep"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roman_snpit_snappl
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Photometry utilities for the Roman SNPIT
5
5
  Author: Roman Supernove Project Infrastructure Team
6
6
  Maintainer-email: Roman SN PIT <raknop@lbl.gov>
@@ -26,9 +26,11 @@ tox.ini
26
26
  changes/.gitkeep
27
27
  changes/10.snappl.rst
28
28
  changes/13.bugfix.rst
29
+ changes/14.snappl.rst
29
30
  changes/3.snappl.rst
30
31
  changes/5.snappl.rst
31
32
  changes/8.snappl.rst
33
+ changes/9.snappl.rst
32
34
  docs/Makefile
33
35
  docs/changes.rst
34
36
  docs/conf.py
@@ -37,8 +39,6 @@ docs/installation.rst
37
39
  docs/make.bat
38
40
  docs/usage.rst
39
41
  docs/_static/logo_black_filled.png
40
- examples/config_example.py
41
- examples/config_example.yaml
42
42
  licenses/.DS_Store
43
43
  licenses/LICENSE.rst
44
44
  licenses/README.rst
@@ -56,14 +56,4 @@ snappl/psf.py
56
56
  snappl/wcs.py
57
57
  snappl/_dev/__init__.py
58
58
  snappl/_dev/scm_version.py
59
- snappl/data/README.rst
60
- snappl/tests/__init__.py
61
- snappl/tests/conftest.py
62
- snappl/tests/docker-compose.yaml
63
- snappl/tests/test_opensim2024fitsimage.py
64
- snappl/tests/test_oversampled_image_psf.py
65
- snappl/tests/test_version_string.py
66
- snappl/tests/test_yaml_serialized_oversampled_image_psf.py
67
- snappl/tests/image_test_data/Roman_TDS_simple_model_F184_662_11.fits.gz
68
- snappl/tests/image_test_data/test_cutout.npy
69
- snappl/tests/psf_test_data/testpsfarray.npz
59
+ snappl/data/README.rst
@@ -4,7 +4,7 @@ __all__ = []
4
4
 
5
5
 
6
6
  try:
7
- __version__ = version("snappl")
7
+ __version__ = version("roman_snpit_snappl")
8
8
  except PackageNotFoundError:
9
9
  # package is not installed
10
10
  pass
@@ -1,4 +1,5 @@
1
- """
1
+ """Dev files
2
+
2
3
  This package contains utilities that are only used when developing drms in a
3
4
  copy of the source repository.
4
5
  These files are not installed, and should not be assumed to exist at
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.2.2'
21
- __version_tuple__ = version_tuple = (0, 2, 2)
20
+ __version__ = version = '0.2.4'
21
+ __version_tuple__ = version_tuple = (0, 2, 4)
@@ -6,39 +6,22 @@ from astropy.nddata.utils import Cutout2D
6
6
  from snpit_utils.logger import SNLogger
7
7
 
8
8
  from astropy.wcs import WCS as AstropyWCS
9
- from astropy.coordinates import SkyCoord
10
- from astropy import units as u
9
+ # from astropy.coordinates import SkyCoord
10
+
11
+ import numpy as np
11
12
 
12
13
 
13
14
  class Exposure:
14
15
  pass
15
16
 
17
+
16
18
  class OpenUniverse2024Exposure:
17
19
  def __init__( self, pointing ):
18
20
  self.pointing = pointing
19
21
 
22
+
20
23
  class Image:
21
- """Cole did this (with software):
22
- ___
23
- / _ \___ __ _ ___ ____
24
- / , _/ _ \/ ' \/ _ `/ _ \
25
- /_/|_|\___/_/_/_/\_,_/_//_/
26
- ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣔⣴⣦⣔⣠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
27
- ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣭⣿⣟⣿⣿⣿⣅⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀
28
- ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣷⣾⣿⣿⣿⣿⣿⣿⣿⡶⠀⠀⠀⠀⠀⠀⠀⠀⠀
29
- ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣄⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠄⠀⠀⠀⠀⠀⠀⠀⠀
30
- ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣠⠤⢤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀
31
- ⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⢒⣿⣿⣿⣠⠋⠀⠀⠀⠀⠀⠀⣀⣀⠤⠶⠿⠿⠛⠿⠿⠿⢻⢿⣿⣿⣿⠿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
32
- ⠀⠀⠀⠀⠀⠀⠀⠀⡞⢀⣿⣿⣿⡟⠃⠀⠀⠀⣀⡰⠶⠛⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠀⠃⠘⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
33
- ⠀⠀⠀⠀⠀⠀⠀⠘⢧⣤⣈⣡⣤⠤⠴⠒⠊⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
34
-
35
-
36
- _____ __ ___ __________
37
- / __/ |/ / / _ \/ _/_ __/
38
- _\ \/ / / ___// / / /
39
- /___/_/|_/ /_/ /___/ /_/
40
-
41
- """
24
+ """Encapsulates a single 2d image."""
42
25
 
43
26
  data_array_list = [ 'all', 'data', 'noise', 'flags' ]
44
27
 
@@ -70,6 +53,10 @@ class Image:
70
53
  """The image data, a 2d numpy array."""
71
54
  raise NotImplementedError( f"{self.__class__.__name__} needs to implement data" )
72
55
 
56
+ @data.setter
57
+ def data( self, new_value ):
58
+ raise NotImplementedError( f"{self.__class__.__name__} needs to implement data setter" )
59
+
73
60
  @property
74
61
  def noise( self ):
75
62
  """The 1σ pixel noise, a 2d numpy array."""
@@ -162,27 +149,20 @@ class Image:
162
149
 
163
150
  @property
164
151
  def coord_center(self):
165
- '''
166
- Get the RA and DEC at the center of the image.
152
+ """Get the RA and DEC at the center of the image.
153
+
167
154
  Note: By fetching the center from the WCS and not the header,
168
155
  this means that this works for cutouts too.
169
156
 
170
157
  Returns:
171
158
  coord_center: array of floats, shape (2,) [RA, DEC] in degrees.
172
- '''
159
+ """
173
160
  raise NotImplementedError( f"{self.__class__.__name__} needs to implement coord_center" )
174
161
 
175
162
  def get_image_shape(self):
176
163
  """Get the shape of the image."""
177
164
  raise NotImplementedError( f"{self.__class__.__name__} needs to implement get_image_shape" )
178
165
 
179
- @property
180
- def band( self ):
181
- """Band (str)"""
182
- raise NotImplementedError( f"{self.__class__.__name__} needs to implement band" )
183
-
184
-
185
-
186
166
 
187
167
  # # THE REST OF THIS MAY GO AWAY
188
168
 
@@ -235,7 +215,8 @@ class Image:
235
215
  # psf_path = self.pipeline.temp_dir / f"psf_{self.image_name}"
236
216
  # get_imsim_psf( self.image_path, self.pipeline.ra, self.pipeline.dec, self.pipeline.band,
237
217
  # self.pointing, self.sca,
238
- # size=201, psf_path=psf_path, config_yaml_file=self.pipeline.galsim_config_file, include_photonOps=True )
218
+ # size=201, psf_path=psf_path, config_yaml_file=self.pipeline.galsim_config_file,
219
+ # include_photonOps=True )
239
220
  # return psf_path
240
221
 
241
222
  # def save_psf_path( self, psf_path ):
@@ -267,18 +248,27 @@ class OpenUniverse2024FITSImage( Image ):
267
248
  self._load_data()
268
249
  return self._data
269
250
 
251
+ @data.setter
252
+ def data(self, new_value):
253
+ if isinstance(new_value, np.ndarray) and np.issubdtype(new_value.dtype, np.floating):
254
+ self._data = new_value
255
+ else:
256
+ raise ValueError("Data must be a numpy array of floats.")
257
+
270
258
  def _load_data( self ):
271
259
  """Loads the data from disk."""
272
260
  raise NotImplementedError( "Do." )
273
261
 
274
262
  def get_data( self, which='all' ):
275
263
  if self._is_cutout:
276
- raise RuntimeError( "get_data called on a cutout image, this will return the ORIGINAL UNCUT image. Currently not supported.")
264
+ raise RuntimeError( "get_data called on a cutout image, this will return the ORIGINAL UNCUT image. "
265
+ "Currently not supported.")
277
266
  if which not in Image.data_array_list:
278
267
  raise ValueError( f"Unknown which {which}, must be all, data, noise, or flags" )
279
268
  SNLogger.info( f"Reading FITS file {self.inputs.path}" )
280
269
  with fits.open( self.inputs.path ) as hdul:
281
270
  self._wcs = AstropyWCS( hdul[1].header )
271
+
282
272
  if which == 'all':
283
273
  return [ hdul[1].data, hdul[2].data, hdul[3].data ]
284
274
  elif which == 'data':
@@ -303,6 +293,7 @@ class OpenUniverse2024FITSImage( Image ):
303
293
  self._header = hdul[1].header
304
294
  return self._header
305
295
 
296
+
306
297
  @property
307
298
  def image_shape(self):
308
299
  """Get the shape of the image."""
@@ -318,13 +309,14 @@ class OpenUniverse2024FITSImage( Image ):
318
309
 
319
310
  @property
320
311
  def coord_center(self):
321
- '''
312
+ """The RA and Dec at the cnter of the image (
322
313
  Get the RA and DEC at the center of the image.
323
314
  Works for cutouts too.
324
315
  Returns:
325
316
  coord_center: array of floats, shape (2,) [RA, DEC] in degrees.
326
- '''
317
+ """
327
318
  wcs = self.get_wcs()
319
+ # ...this next method isn't defined for our WCS objects. Something is broken.
328
320
  coord_center = wcs.wcs_pix2world(
329
321
  self.get_image_shape()[0] // 2,
330
322
  self.get_image_shape()[1] // 2,
@@ -333,19 +325,12 @@ class OpenUniverse2024FITSImage( Image ):
333
325
 
334
326
  @property
335
327
  def band(self):
336
- '''
337
- Return the band the image is taken in.
338
-
339
- Returns:
340
- band: str
341
- '''
328
+ """The band the image is taken in (str)."""
342
329
  header = self.get_header()
343
330
  return header['FILTER'].strip()
344
331
 
345
332
  def get_cutout(self, x, y, xsize, ysize=None):
346
- '''
347
- Creates a new snappl image object that is a cutout of the original
348
- image, at a location in pixel-space.
333
+ """Creates a new snappl image object that is a cutout of the original image, at a location in pixel-space.
349
334
 
350
335
  Parameters
351
336
  ----------
@@ -361,7 +346,8 @@ class OpenUniverse2024FITSImage( Image ):
361
346
  -------
362
347
  cutout : snappl.image.Image
363
348
  A new snappl image object that is a cutout of the original image.
364
- '''
349
+
350
+ """
365
351
  if ysize is None:
366
352
  ysize = xsize
367
353
  if xsize % 2 != 1 or ysize % 2 != 1:
@@ -369,7 +355,7 @@ class OpenUniverse2024FITSImage( Image ):
369
355
  pixel, you tried to pass a size of {xsize, ysize}.")
370
356
  loc = (x, y)
371
357
  SNLogger.debug(f'Cutting out at {x , y}')
372
- data, noise, flags = self.get_data('all')
358
+ data, noise, _flags = self.get_data('all')
373
359
  astropy_cutout = Cutout2D(data, loc, size=(ysize, xsize), # Astropy asks for this order. Beats me. -Cole
374
360
  mode='strict', wcs=self.get_wcs())
375
361
  astropy_noise = Cutout2D(noise, loc, size=(ysize, xsize),
@@ -384,9 +370,8 @@ class OpenUniverse2024FITSImage( Image ):
384
370
  return snappl_cutout
385
371
 
386
372
  def get_ra_dec_cutout(self, ra, dec, xsize, ysize=None):
387
- '''
388
- Creates a new snappl image object that is a cutout of the original
389
- image, at a location in pixel-space.
373
+ """Creates a new snappl image object that is a cutout of the original image, at a location in pixel-space.
374
+
390
375
  Parameters
391
376
  ----------
392
377
  ra : float
@@ -402,11 +387,10 @@ class OpenUniverse2024FITSImage( Image ):
402
387
  -------
403
388
  cutout : snappl.image.Image
404
389
  A new snappl image object that is a cutout of the original image.
405
- '''
390
+ """
406
391
 
407
392
  wcs = self.get_wcs()
408
393
  x, y = wcs.wcs_world2pix(ra, dec, 0) # <--- I DO NOT UNDERSTAND WHY THIS
409
394
  # NEEDS TO BE ZERO, BUT THAT MADE THIS NEW FUNCTION AGREE WITH THE
410
395
  # OUTPUT OF THE OLD FUNCTION. COLE IS CONFUSED!!!!!
411
396
  return self.get_cutout(x, y, xsize, ysize)
412
-
@@ -3,6 +3,7 @@ import base64
3
3
 
4
4
  import numpy as np
5
5
 
6
+
6
7
  class PSF:
7
8
  def __init__( self, *args, **kwargs ):
8
9
  # Will define a PSF with a nominal position
@@ -34,7 +35,7 @@ class PSF:
34
35
  """
35
36
  raise NotImplementedError( f"{self.__class__.__name__} needs to implement get_stamp" )
36
37
 
37
-
38
+
38
39
 
39
40
  class OversampledImagePSF( PSF ):
40
41
  @classmethod
@@ -62,7 +63,7 @@ class OversampledImagePSF( PSF ):
62
63
  """
63
64
  # TODO : implement enforce_odd
64
65
  # TODO : enforce square
65
-
66
+
66
67
  psf = cls()
67
68
  psf._data = data
68
69
  if normalize:
@@ -75,7 +76,7 @@ class OversampledImagePSF( PSF ):
75
76
  @property
76
77
  def x0( self ):
77
78
  return self._x0
78
-
79
+
79
80
  @property
80
81
  def y0( self ):
81
82
  return self._x0
@@ -92,7 +93,7 @@ class OversampledImagePSF( PSF ):
92
93
  def clip_size( self ):
93
94
  """The size of the PSF image clip at image resolution."""
94
95
  return int( np.floor( self._data.shape[0] / self._oversamp ) )
95
-
96
+
96
97
  def __init__( self, *args, **kwargs ):
97
98
  super().__init__( *args, **kwargs )
98
99
  self._data = None
@@ -103,7 +104,7 @@ class OversampledImagePSF( PSF ):
103
104
  def get_stamp( self, x=None, y=None, normalize=True ):
104
105
  x = float(x) if x is not None else self._x0
105
106
  y = float(y) if y is not None else self._y0
106
-
107
+
107
108
  # round() isn't the right thing to use here, because it will
108
109
  # behave differently when x - round(x) = 0.5 based on whether
109
110
  # floor(x) is even or odd. What we *want* is for the psf to
@@ -174,12 +175,10 @@ class OversampledImagePSF( PSF ):
174
175
  clip /= clip.sum()
175
176
 
176
177
  return clip
177
-
178
178
 
179
179
 
180
-
181
180
  class YamlSerialized_OversampledImagePSF( OversampledImagePSF ):
182
-
181
+
183
182
  def __init__( self, *args, **kwargs ):
184
183
  super().__init__( *args, **kwargs )
185
184
 
@@ -190,7 +189,7 @@ class YamlSerialized_OversampledImagePSF( OversampledImagePSF ):
190
189
  self._oversamp = y['oversamp']
191
190
  self._data = np.frombuffer( base64.b64decode( y['data'] ), dtype=y['dtype'] )
192
191
  self._data = self._data.reshape( ( y['shape0'], y['shape1'] ) )
193
-
192
+
194
193
  def write( self, filepath ):
195
194
  out = { 'x0': float( self._x0 ),
196
195
  'y0': float( self._y0 ),
@@ -1,5 +1,6 @@
1
1
  import astropy.wcs
2
2
 
3
+
3
4
  class BaseWCS:
4
5
  def __init__( self ):
5
6
  pass
@@ -7,18 +8,21 @@ class BaseWCS:
7
8
  def pixel_to_world( self, *args, **kwargs ):
8
9
  """TODO DOCUMENT THIS"""
9
10
  raise NotImplementedError( f"{self.__class__.__name__} needs to implement pixel_to_world" )
10
-
11
+
11
12
  def world_to_pixel( self, *args, **kwargs ):
12
13
  """TODO DOCUMENT THIS"""
13
14
  raise NotImplementedError( f"{self.__class__.__name__} needs to implement world_to_pixel" )
14
-
15
+
16
+
15
17
  class AstropyWCS(BaseWCS):
16
18
  def __init__( self ):
17
19
  self._wcs = None
18
-
20
+
19
21
  @classmethod
20
22
  def from_header( cls, header ):
21
- self._wcs = astropy.wcs.WCS( header )
23
+ wcs = AstropyWCS()
24
+ wcs._wcs = astropy.wcs.WCS( header )
25
+ return wcs
22
26
 
23
27
  def pixel_to_world( self, *args, **kwargs ):
24
28
  return self._wcs.pixel_to_world( *args, **kwargs )
@@ -27,6 +31,7 @@ class AstropyWCS(BaseWCS):
27
31
  return self._wcs.world_to_pixel( *args, **kwargs )
28
32
 
29
33
  ## More?
30
-
34
+
35
+
31
36
  class TotalDisasterASDFWCS(BaseWCS):
32
37
  pass
@@ -1,48 +0,0 @@
1
- # Run this example in this directory with
2
- # SNAPPL_CONFIG=config_example.yaml python config_example.py
3
- #
4
- # then try
5
- # SNAPPL_CONFIG=config_example.yaml python config_example.py --help
6
- #
7
- # then try
8
- # SNAPPL_CONFIG=config.example.yaml python config_example.py --swallow-african_or_european European
9
-
10
- import sys
11
- import pathlib
12
- import argparse
13
-
14
- # This is a little bit ugly, but so that this example will work "in place"
15
- # we make sure that the directory where config.py is found is in our
16
- # PYTHONPATH. Do NOT do this in your own code. Make sure that things
17
- # are installed right, and that the PYTHONPATH includes all the snappl
18
- # path
19
- sys.path.insert( 0, str( pathlib.Path(__file__).parent.parent ) )
20
- from snappl.config import Config
21
-
22
-
23
- def main():
24
- cfg = Config.get()
25
-
26
- parser = argparse.ArgumentParser( 'config_example.py', description='Demonstrate config' )
27
- parser.add_argument( '-g', '--gratuitous', default='not_given', help="Your own argument" )
28
- cfg.augment_argparse( parser )
29
- args = parser.parse_args()
30
- cfg.parse_args( args )
31
-
32
- print( f"Gratuitous is {args.gratuitous}" )
33
-
34
- # Examples of extracting config values
35
-
36
- print( f"cfg.value('cat') is {cfg.value('cat')}" )
37
- print( f"cfg.value('swallow.unladen.airspeed') is {cfg.value('swallow.unladen.airspeed')} "
38
- f"with units {cfg.value('swallow.unladen.airspeed_units')}" )
39
- birdtype = cfg.value( 'swallow.african_or_european' )
40
- qt = "'"
41
- print( f"cfg.value('swallow.african_or_european') is "
42
- f"{f'I don{qt}t know that!.... AAAAAAAA!' if birdtype is None else birdtype}" )
43
- print( f"cfg.value('list') is {cfg.value('list')}" )
44
-
45
-
46
- if __name__ == "__main__":
47
- main()
48
-
@@ -1,12 +0,0 @@
1
- cat: fluffy
2
-
3
- swallow:
4
- unladen:
5
- airspeed: 11
6
- airspeed_units: miles per hour
7
- african_or_european: null
8
-
9
- list:
10
- - a
11
- - b
12
- - c
@@ -1 +0,0 @@
1
- """This module contains package tests."""
@@ -1,6 +0,0 @@
1
- # this is a module level file
2
- import pytest # noqa: F401
3
-
4
- import tox # noqa: F401
5
- from tox.pytest import init_fixture # noqa: F401
6
-
@@ -1,44 +0,0 @@
1
- # This is a compose file that creates an environment in which you can
2
- # run tests. Either just do
3
- #
4
- # docker compose run runtests
5
- #
6
- # or, do
7
- #
8
- # docker compose up -d shell
9
- #
10
- # to get a shell session running the SNPIT cpu image. Connect to it
11
- # with
12
- #
13
- # docker compose exec -it shell /bin/bash
14
- #
15
- # You can now do things in there, including
16
- #
17
- # cd /snappl/snappl/tests
18
- # pytest -v
19
-
20
- services:
21
- shell:
22
- image: rknop/roman-snpit-env:cpu-dev
23
- entrypoint: [ "tail", "-f", "/etc/issue" ]
24
- working_dir: /snappl
25
- volumes:
26
- - type: bind
27
- source: ../..
28
- target: /snappl
29
-
30
- runtests:
31
- image: rknop/roman-snpit-env:cpu-dev
32
- working_dir: /snappl
33
- entrypoint:
34
- - /bin/sh
35
- - -c
36
- - |
37
- pip install --no-deps -e . &&
38
- cd snappl/tests &&
39
- pytest -v
40
- volumes:
41
- - type: bind
42
- source: ../..
43
- target: /snappl
44
-
@@ -1,41 +0,0 @@
1
- # TODO -- remove these next few lines!
2
- # This needs to be set up in an environment
3
- # where snappl is available. This will happen "soon"
4
- # Get Rob to fix all of this. For now, this is a hack
5
- # so you can work short term.
6
- import sys
7
- import pathlib
8
- sys.path.insert(0, str(pathlib.Path(__file__).parent/"extern/snappl"))
9
- # End of lines that will go away once we do this right. (<-- From Rob.)
10
-
11
- import numpy as np
12
- from snappl.image import OpenUniverse2024FITSImage
13
- import astropy
14
- import pytest
15
-
16
-
17
- def test_get_cutout():
18
- imagepath = str(pathlib.Path(__file__).parent/'image_test_data/Roman_TDS_simple_model_F184_662_11.fits.gz')
19
- image = OpenUniverse2024FITSImage(imagepath, None, 11)
20
- ra, dec = 7.5942407686430995, -44.180904726970695
21
- cutout = image.get_ra_dec_cutout(ra, dec, 5)
22
- comparison_cutout = np.load(str(pathlib.Path(__file__).parent/'image_test_data/test_cutout.npy'),
23
- allow_pickle=True)
24
- message = "The cutout does not match the comparison cutout"
25
- assert np.array_equal(cutout._data, comparison_cutout), message
26
- # I am directly comparing for equality here because these numbers should
27
- # never actually change, provided the underlying image is unaltered. -Cole
28
-
29
- # Now we intentionally try to get a no overlap error.
30
- with pytest.raises(astropy.nddata.utils.NoOverlapError) as excinfo:
31
- ra, dec = 7.6942407686430995, -44.280904726970695
32
- cutout = image.get_ra_dec_cutout(ra, dec, 5)
33
- message = f"This should have caused a NoOverlapError but was actually {str(excinfo.value)}"
34
- assert 'do not overlap' in str(excinfo.value), message
35
-
36
- # Now we intentionally try to get a partial overlap error.
37
- with pytest.raises(astropy.nddata.utils.PartialOverlapError) as excinfo:
38
- ra, dec = 7.69380043,-44.13231831
39
- cutout = image.get_ra_dec_cutout(ra, dec, 55)
40
- message = f"This should have caused a PartialOverlapError but was actually {str(excinfo.value)}"
41
- assert 'partial' in str(excinfo.value), message
@@ -1,25 +0,0 @@
1
- import yaml
2
- import random
3
- import pytest
4
-
5
- import numpy as np
6
- from astropy.io import fits
7
-
8
- from snappl.psf import OversampledImagePSF
9
-
10
- @pytest.fixture
11
- def testpsf():
12
- loaded = np.load('psf_test_data/testpsfarray.npz')
13
- arr = loaded['args']
14
- mypsf = OversampledImagePSF.create( arr, 3832., 255., oversample_factor=3. )
15
- return mypsf
16
-
17
- def test_create( testpsf ):
18
- assert testpsf._data.sum() == pytest.approx( 1., rel=1e-9 )
19
-
20
-
21
- @pytest.mark.skip( reason="Comment out the skip to write some files for visual inspection" )
22
- def test_interactive_write_stamp_to_fits_for_visual_inspection( testpsf ):
23
- fits.writeto( 'test_deleteme_orig.fits', testpsf._data, overwrite=True )
24
- fits.writeto( 'test_deleteme_resamp.fits', testpsf.get_stamp(), overwrite=True )
25
-
@@ -1,3 +0,0 @@
1
- def test_version_is_string():
2
- from snappl import __version__
3
- assert isinstance(__version__, str)
@@ -1,46 +0,0 @@
1
- import yaml
2
- import random
3
- import pathlib
4
- import pytest
5
-
6
- import numpy as np
7
-
8
- from snappl.psf import OversampledImagePSF, YamlSerialized_OversampledImagePSF
9
-
10
- @pytest.fixture
11
- def testpsf():
12
- loaded = np.load('psf_test_data/testpsfarray.npz')
13
- arr = loaded['args']
14
- mypsf = YamlSerialized_OversampledImagePSF.create( arr, 3832., 255., oversample_factor=3. )
15
- return mypsf
16
-
17
- def test_write( testpsf ):
18
- barf = pathlib.Path( ''.join( random.choices( 'abcdefghijklmnopqrstuvwxyz', k=10 ) ) )
19
- try:
20
- testpsf.write( barf )
21
-
22
- y = yaml.safe_load( open(barf) )
23
- assert isinstance( y, dict )
24
- assert y['x0'] == 3832.
25
- assert y['y0'] == 255.
26
- assert y['oversamp'] == 3.
27
- assert y['shape0'] == 77
28
- assert y['shape1'] == 77
29
- assert isinstance( y['data'], str )
30
- finally:
31
- barf.unlink( missing_ok=True )
32
-
33
- def test_read( testpsf ):
34
- barf = pathlib.Path( ''.join( random.choices( 'abcdefghijklmnopqrstuvwxyz', k=10 ) ) )
35
- try:
36
- testpsf.write( barf )
37
-
38
- bpsf = YamlSerialized_OversampledImagePSF()
39
- bpsf.read( barf )
40
- assert bpsf._x0 == 3832.
41
- assert bpsf._y0 == 255.
42
- assert bpsf._oversamp == 3.
43
- assert bpsf._data.shape == (77,77)
44
- assert bpsf._data.sum() == pytest.approx( 1., rel=1e-9 )
45
- finally:
46
- barf.unlink( missing_ok=True )