roman-snpit-snappl 0.11.2__tar.gz → 0.12.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 (90) hide show
  1. {roman_snpit_snappl-0.11.2/roman_snpit_snappl.egg-info → roman_snpit_snappl-0.12.0}/PKG-INFO +1 -1
  2. roman_snpit_snappl-0.12.0/changes/68.feature.rst +1 -0
  3. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0/roman_snpit_snappl.egg-info}/PKG-INFO +1 -1
  4. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/roman_snpit_snappl.egg-info/SOURCES.txt +1 -0
  5. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/_version.py +3 -3
  6. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/psf.py +178 -5
  7. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.cruft.json +0 -0
  8. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/CODEOWNERS +0 -0
  9. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +0 -0
  10. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md +0 -0
  11. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/ISSUE_TEMPLATE/PR_TEMPLATE.md +0 -0
  12. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/dependabot.yml +0 -0
  13. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/labeler.yml +0 -0
  14. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/workflows/changelog.yml +0 -0
  15. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/workflows/run_labeler.yml +0 -0
  16. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/workflows/run_snappl_tests.yml +0 -0
  17. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/workflows/sphinx-deploy.yml +0 -0
  18. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.github/workflows/sub_package_update.yml +0 -0
  19. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.gitignore +0 -0
  20. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/.pre-commit-config.yaml +0 -0
  21. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/CHANGES.rst +0 -0
  22. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/CITATION.cff +0 -0
  23. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/CODE_OF_CONDUCT.md +0 -0
  24. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/CONTRIBUTING.md +0 -0
  25. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/LICENSE +0 -0
  26. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/MANIFEST.in +0 -0
  27. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/README.rst +0 -0
  28. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/.gitkeep +0 -0
  29. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/10.snappl.rst +0 -0
  30. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/13.bugfix.rst +0 -0
  31. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/14.snappl.rst +0 -0
  32. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/15.feature.rst +0 -0
  33. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/16.feature.rst +0 -0
  34. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/18.feature.rst +0 -0
  35. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/20.bugfix.rst +0 -0
  36. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/23.snappl.rst +0 -0
  37. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/26.feature.rst +0 -0
  38. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/29.feature.rst +0 -0
  39. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/3.snappl.rst +0 -0
  40. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/31.feature.rst +0 -0
  41. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/35.snappl.rst +0 -0
  42. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/36.snappl.rst +0 -0
  43. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/37.snappl.rst +0 -0
  44. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/40.snappl.rst +0 -0
  45. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/41.snappl.rst +0 -0
  46. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/43.snappl.rst +0 -0
  47. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/47.feature.rst +0 -0
  48. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/49.docs.rst +0 -0
  49. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/5.snappl.rst +0 -0
  50. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/54.snappl.rst +0 -0
  51. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/57.snappl.rst +0 -0
  52. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/58.snappl.rst +0 -0
  53. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/61.bugfix.rst +0 -0
  54. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/62.snappl.rst +0 -0
  55. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/65.bugfix.rst +0 -0
  56. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/8.snappl.rst +0 -0
  57. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/changes/9.snappl.rst +0 -0
  58. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/codespell-ignore.txt +0 -0
  59. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/docs/Makefile +0 -0
  60. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/docs/_static/logo_black_filled.png +0 -0
  61. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/docs/api.rst +0 -0
  62. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/docs/changes.rst +0 -0
  63. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/docs/conf.py +0 -0
  64. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/docs/index.rst +0 -0
  65. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/docs/installation.rst +0 -0
  66. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/docs/make.bat +0 -0
  67. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/docs/usage.rst +0 -0
  68. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/experimentation/README.md +0 -0
  69. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/experimentation/play_with_photutils.py +0 -0
  70. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/licenses/.DS_Store +0 -0
  71. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/licenses/LICENSE.rst +0 -0
  72. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/licenses/README.rst +0 -0
  73. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/licenses/TEMPLATE_LICENSE.rst +0 -0
  74. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/pyproject.toml +0 -0
  75. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/roman_snpit_snappl.egg-info/dependency_links.txt +0 -0
  76. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/roman_snpit_snappl.egg-info/not-zip-safe +0 -0
  77. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/roman_snpit_snappl.egg-info/requires.txt +0 -0
  78. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/roman_snpit_snappl.egg-info/top_level.txt +0 -0
  79. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/setup.cfg +0 -0
  80. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/setup.py +0 -0
  81. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/__init__.py +0 -0
  82. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/_dev/__init__.py +0 -0
  83. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/_dev/scm_version.py +0 -0
  84. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/data/README.rst +0 -0
  85. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/diaobject.py +0 -0
  86. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/image.py +0 -0
  87. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/imagecollection.py +0 -0
  88. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/sed.py +0 -0
  89. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/snappl/wcs.py +0 -0
  90. {roman_snpit_snappl-0.11.2 → roman_snpit_snappl-0.12.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roman_snpit_snappl
3
- Version: 0.11.2
3
+ Version: 0.12.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
+ Add GaussianPSF
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roman_snpit_snappl
3
- Version: 0.11.2
3
+ Version: 0.12.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>
@@ -51,6 +51,7 @@ changes/58.snappl.rst
51
51
  changes/61.bugfix.rst
52
52
  changes/62.snappl.rst
53
53
  changes/65.bugfix.rst
54
+ changes/68.feature.rst
54
55
  changes/8.snappl.rst
55
56
  changes/9.snappl.rst
56
57
  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.11.2'
32
- __version_tuple__ = version_tuple = (0, 11, 2)
31
+ __version__ = version = '0.12.0'
32
+ __version_tuple__ = version_tuple = (0, 12, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g3db2133f7'
34
+ __commit_id__ = commit_id = 'g656ebd8f3'
@@ -9,6 +9,7 @@ import pathlib
9
9
 
10
10
  # common library imports
11
11
  import numpy as np
12
+ import scipy.integrate
12
13
  import yaml
13
14
 
14
15
  # astro library imports
@@ -111,6 +112,9 @@ class PSF:
111
112
  if psfclass == "ou24PSF":
112
113
  return ou24PSF( _called_from_get_psf_object=True, **kwargs )
113
114
 
115
+ if psfclass == "gaussian":
116
+ return GaussianPSF( _called_from_get_psf_object=True, **kwargs )
117
+
114
118
  raise ValueError( f"Unknown PSF class {psfclass}" )
115
119
 
116
120
 
@@ -308,15 +312,66 @@ class PSF:
308
312
 
309
313
  x0, y0: int, default None
310
314
  The pixel position on the image corresponding to the center
311
- pixel of the returned PSF. If either is None, they default
312
- to x0=floor(x+0.5) and y0=floor(y+0.5). (See above for why
313
- we don't use round().) The peak* of the PSF on the returned
314
- stamp will be at (x-x0,y-y0) relative to the center pixel of
315
- the returned stamp.
315
+ pixel of the returned stamp. If either is None, they
316
+ default to x0=floor(x+0.5) and y0=floor(y+0.5). (See above
317
+ for why we don't use round().) The peak* of the PSF on the
318
+ returned stamp will be at (x-x0,y-y0) relative to the center
319
+ pixel of the returned stamp.
316
320
 
317
321
  * "peak" assumes the PSF is radially symmetric. If it's
318
322
  not, by "peak" read "center" or "fiducial point".
319
323
 
324
+ Lots and lots of notes and examples to think through exactly
325
+ what this means:
326
+
327
+ Algebra:
328
+
329
+ Define xc = floor(x + 0.5), yc = floor(y + 0.5). This is
330
+ the "closest integral pixel position" on the original
331
+ image to where the PSF is being rendered. (It's slightly
332
+ different from the pixel position rounded to the nearest
333
+ integer; see above.)
334
+
335
+ Define fx = x - xc, fy = y - yc ; both are in the range
336
+ [-0.5, 0.5).
337
+
338
+ Define midpix = stamp_size // 2
339
+ (so, for instance midpix=3 for a 7×7 stamp)
340
+
341
+ Given how we've defined the x and y parmaeters to this
342
+ function, on the original image, the peak of the PSF is at
343
+ (x, y) = (xc + fx, yc + fy).
344
+
345
+ Pixel (midpix, midpix) on the stamp corresponds to (x0, y0)
346
+ on the original image (given the definition of the
347
+ parameters to this function).
348
+
349
+ If (x0, y0) = (xc, yc), then the "closest integral pixel
350
+ position" for the peak of the PSF on the stamp is (midpix,
351
+ midpix).
352
+
353
+ In general, the "closest integral pixel position" for the
354
+ peak of the PSF on the stamp is (midpix + xc - x0, midpix
355
+ + yc - y0). (If xc is 5 and x0 is 6, then the center of
356
+ the stamp is to the right of the peak pixel on the stamp,
357
+ so the peak pixel position is less than midpix.)
358
+
359
+ The peak position of the PSF on the stamp is
360
+ (midpix + xc - x0 + fx, midpix + yc - y0 + fy)
361
+ (which is the same as (midpix + x - x0, midpix + y - y0)).
362
+
363
+ If we define (xrel=0, yrel=0) to be the peak of the PSF, then
364
+ (xrel, yrel) = (0, 0) is (midpix + xc + fx - x0, midpix +
365
+ yc + fy - y0) on the stamp.
366
+
367
+ Therefore the center of the stamp, (midpix, midpix), is at
368
+ (xrel, yrel) = (x0 - xc - fx, y0 - yc - fy)
369
+
370
+ The center of the lower-left pixel of the stamp, (0, 0), is at
371
+ (xrel, yrel) = (x0 - xc - fx - midpix, y0 - yc -fy - midpix)
372
+
373
+ Examples:
374
+
320
375
  For example: if you call psfobj.get_stamp(111., 113.), and
321
376
  if the PSF object as a stamp_size of 5, then you will get
322
377
  back an image that looks something like::
@@ -1596,3 +1651,121 @@ class ou24PSF( ou24PSF_slow ):
1596
1651
  # self._data = stamp.array
1597
1652
 
1598
1653
  # return self._data
1654
+
1655
+
1656
+ class GaussianPSF( PSF ):
1657
+ """A Gaussian PSF that doesn't vary across the image, for testing purposes.
1658
+
1659
+ The gaussian rendered at (x, y) has flux density as a function of position (xp, yp):
1660
+
1661
+ xr = (xp - x) * cosθ + (yp - y) * sinθ
1662
+ yr = -(xp - x) * sinθ + (yp - y) * cosθ
1663
+ f(xp, yp) = 1 / (2π √(σ_x σ_y)) * exp( -xr²/(2 σ_x²) -yr²/(2 σ_y²) )
1664
+
1665
+ Pixel values are integrals of flux density over the square-shaped area of the pixel.
1666
+
1667
+ """
1668
+
1669
+ def __init__( self, sigmax=1., sigmay=1., theta=0., stamp_size=None, _parent_class=False, **kwargs ):
1670
+ """Create an object that renders a Gaussian PSF.
1671
+
1672
+ Parmeters are as passed to PSF.__init__() plus:
1673
+
1674
+ Parameters
1675
+ ----------
1676
+ sigmax : float, default 1.
1677
+ The σ_x value in pixels. (See class docstring.)
1678
+
1679
+ sigmay : float, default 1.
1680
+ The σ_y value in pixels. (See class docstring.)
1681
+
1682
+ theta : float, default 0.
1683
+ The rotation in degrees. (See class docstring.)
1684
+
1685
+ stamp_size : int, default None
1686
+ Must be an odd integer if given. If not given, stamp size will be 2*floor(5*FWHM)+1 (using
1687
+ the larger of σ_x, σ_y to determine FWHM).
1688
+ """
1689
+
1690
+ super().__init__( _parent_class=True, **kwargs )
1691
+ self._warn_unknown_kwargs( kwargs, _parent_class=_parent_class )
1692
+
1693
+ self.sigmax = sigmax
1694
+ self.sigmay = sigmay
1695
+ self.theta = theta * np.pi / 180.
1696
+ self._rotmat = np.array( [ [ np.cos(self.theta), np.sin(self.theta) ],
1697
+ [ -np.sin(self.theta), np.cos(self.theta) ] ] )
1698
+ self._norm = 1. / ( 2 * np.pi * sigmax * sigmay )
1699
+
1700
+ self._stamp_size = stamp_size
1701
+ if self._stamp_size is None:
1702
+ self._stamp_size = 2 * int( np.floor( 5. * max( sigmax, sigmay ) * 2. * np.sqrt(2 * np.log(2.)) ) ) + 1
1703
+
1704
+ self._stamp_cache = {}
1705
+
1706
+ @property
1707
+ def stamp_size( self ):
1708
+ return self._stamp_size
1709
+
1710
+
1711
+ def _gauss( self, yrel, xrel ):
1712
+ """Function.
1713
+
1714
+ Parmeters
1715
+ ---------
1716
+ yrel, xrel: float
1717
+ Effectively, yp-y and xp-y as described in the class description.
1718
+
1719
+ Returns
1720
+ -------
1721
+ f(xp, yp): float
1722
+
1723
+ """
1724
+ coords = np.vstack( (xrel, yrel) )
1725
+ rcoords = np.matmul( self._rotmat, coords )
1726
+ return self._norm * np.exp( - ( rcoords[0][0]**2 / (2. * self.sigmax**2) )
1727
+ - ( rcoords[1][0]**2 / (2. * self.sigmay**2) ) )
1728
+
1729
+
1730
+ def get_stamp( self, x=None, y=None, x0=None, y0=None, flux=1. ):
1731
+ midpix = int( np.floor( self.stamp_size / 2 ) )
1732
+ xc = int( np.floor(x + 0.5 ) )
1733
+ yc = int( np.floor(y + 0.5 ) )
1734
+ x0 = x0 if x0 is not None else xc
1735
+ y0 = y0 if y0 is not None else yc
1736
+ if not ( isinstance( x0, numbers.Integral ) and isinstance( y0, numbers.Integral ) ):
1737
+ raise TypeError( f"x0 and y0 must be integers, got x0 as {type(x0)} and y0 as {type(y0)}" )
1738
+ millix = int( (x - xc) * 1000. )
1739
+ milliy = int( (y - yc) * 1000. )
1740
+ offx = x0 - xc
1741
+ offy = y0 - yc
1742
+ dex = ( millix, milliy, offx, offy )
1743
+
1744
+ if dex in self._stamp_cache:
1745
+ # Because calculating these is slow, cache them.
1746
+ # It may be overkill to round the position to 0.001 before
1747
+ # caching; 0.01 may be good enough.
1748
+ stamp = np.copy( self._stamp_cache[ dex ] )
1749
+
1750
+ else:
1751
+ stamp = np.zeros( ( self.stamp_size, self.stamp_size ), dtype=np.float64 )
1752
+
1753
+ # There may be a clever way to do this without a for loop. Not sure
1754
+ # if scipy.integrate.dblquad takes arrays. Given that it documents
1755
+ # that it returns a single float, I think not. In any event, I suspect
1756
+ # the overhead from the for loop is not all that big compared to the
1757
+ # integration.
1758
+ for iy in range( 0, self.stamp_size ):
1759
+ # See docstring on PSF.get_stamp
1760
+ yrel = offy - milliy / 1000. - midpix + iy
1761
+ for ix in range( 0, self.stamp_size ):
1762
+ # See docstring on PSF.get_stamp
1763
+ xrel = offx - millix / 1000. - midpix + ix
1764
+ res = scipy.integrate.dblquad( self._gauss, xrel-0.5, xrel+0.5, yrel-0.5, yrel+0.5 )
1765
+ stamp[ iy, ix ] = res[0]
1766
+
1767
+ self._stamp_cache[ dex ] = np.copy( stamp )
1768
+
1769
+ stamp *= flux
1770
+
1771
+ return stamp