Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-47919: Add configuration for cutting visits from the fit by PSF FWHM #133

Merged
merged 2 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions python/lsst/fgcmcal/fgcmBuildStarsBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from lsst.meas.algorithms.sourceSelector import sourceSelectorRegistry

from .fgcmLoadReferenceCatalog import FgcmLoadReferenceCatalogTask
from .utilities import computeReferencePixelScale

import fgcm

Expand Down Expand Up @@ -259,13 +260,15 @@ def fgcmMakeVisitCatalog(self, camera, groupedHandles):
visitCat['used'] = 0
visitCat['sources_read'] = False

defaultPixelScale = computeReferencePixelScale(camera)

# No matter what, fill the catalog. This will check if it was
# already read.
self._fillVisitCatalog(visitCat, groupedHandles)
self._fillVisitCatalog(visitCat, groupedHandles, defaultPixelScale)

return visitCat

def _fillVisitCatalog(self, visitCat, groupedHandles):
def _fillVisitCatalog(self, visitCat, groupedHandles, defaultPixelScale):
"""
Fill the visit catalog with visit metadata

Expand All @@ -275,6 +278,8 @@ def _fillVisitCatalog(self, visitCat, groupedHandles):
Visit catalog. See _makeFgcmVisitSchema() for schema definition.
groupedHandles : `dict` [`list` [`lsst.daf.butler.DeferredDatasetHandle`]]
Dataset handles, grouped by visit.
defaultPixelScale : `float`
Default pixel scale to use if not in visit summary (arcsecond/pixel).
"""

# Guarantee that these are sorted.
Expand All @@ -292,15 +297,24 @@ def _fillVisitCatalog(self, visitCat, groupedHandles):

visitInfo = summaryRow.getVisitInfo()
physicalFilter = summaryRow['physical_filter']
# Compute the median psf sigma if possible
goodSigma, = np.where(summary['psfSigma'] > 0)
# Compute the median psf sigma and fwhm if possible.
if 'pixelScale' in summary.schema:
# This is not available in the older test summaries
pixelScales = summary['pixelScale']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome that you are using the as-measured pixelScale...it could start to really matter for the full camera!

else:
pixelScales = np.full(len(summary['psfSigma']), defaultPixelScale)
psfSigmas = summary['psfSigma']
goodSigma, = np.where((np.nan_to_num(psfSigmas) > 0) & (np.nan_to_num(pixelScales) > 0))
if goodSigma.size > 2:
psfSigma = np.median(summary['psfSigma'][goodSigma])
psfSigma = np.median(psfSigmas[goodSigma])
psfFwhm = np.median(psfSigmas[goodSigma] * pixelScales[goodSigma]) * np.sqrt(8.*np.log(2.))
elif goodSigma.size > 0:
psfSigma = summary['psfSigma'][goodSigma[0]]
psfSigma = psfSigmas[goodSigma[0]]
psfFwhm = psfSigmas[goodSigma[0]] * pixelScales[goodSigma[0]] * np.sqrt(8.)*np.log(2.)
else:
self.log.warning("Could not find any good summary psfSigma for visit %d", visit)
psfSigma = 0.0
psfFwhm = 0.0
# Compute median background if possible
goodBackground, = np.where(np.nan_to_num(summary['skyBg']) > 0.0)
if goodBackground.size > 2:
Expand Down Expand Up @@ -332,6 +346,7 @@ def _fillVisitCatalog(self, visitCat, groupedHandles):
# Median delta aperture, to be measured from stars
rec['deltaAper'] = 0.0
rec['psfSigma'] = psfSigma
rec['psfFwhm'] = psfFwhm
rec['skyBackground'] = skyBackground
rec['used'] = 1

Expand Down Expand Up @@ -559,7 +574,8 @@ def _makeFgcmVisitSchema(self, nCcd):
schema.addField('mjd', type=np.float64, doc="MJD of visit")
schema.addField('exptime', type=np.float32, doc="Exposure time")
schema.addField('pmb', type=np.float32, doc="Pressure (millibar)")
schema.addField('psfSigma', type=np.float32, doc="PSF sigma (reference CCD)")
schema.addField('psfSigma', type=np.float32, doc="PSF sigma (median); pixels")
schema.addField('psfFwhm', type=np.float32, doc="PSF FWHM (median); arcseconds")
schema.addField('deltaAper', type=np.float32, doc="Delta-aperture")
schema.addField('skyBackground', type=np.float32, doc="Sky background (ADU) (reference CCD)")
# the following field is not used yet
Expand Down
9 changes: 9 additions & 0 deletions python/lsst/fgcmcal/fgcmFitCycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,15 @@ class FgcmFitCycleConfig(pipeBase.PipelineTaskConfig,
dtype=float,
default=-0.25,
)
expFwhmCutDict = pexConfig.DictField(
doc=("Per-band specification on maximum exposure FWHM (arcseconds) that will "
"be considered for the model fit. Exposures with median FWHM larger "
"than this threshold will get zeropoints based on matching to good "
"stars."),
keytype=str,
itemtype=float,
default={},
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lovin' the per-band dict ❤️

I don't understand the second sentence...

expGrayPhotometricCutDict = pexConfig.DictField(
doc=("Per-band specification on maximum (negative) achromatic exposure residual "
"('gray term') for a visit to be considered photometric. Must have one "
Expand Down
7 changes: 4 additions & 3 deletions python/lsst/fgcmcal/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def makeConfigDict(config, log, camera, maxIter,
'expField': FGCM_EXP_FIELD,
'ccdField': FGCM_CCD_FIELD,
'seeingField': 'DELTA_APER',
'fwhmField': 'PSFSIGMA',
'fwhmField': 'PSFFWHM',
'skyBrightnessField': 'SKYBACKGROUND',
'deepFlag': 'DEEPFLAG', # unused
'bands': list(config.bands),
Expand Down Expand Up @@ -183,6 +183,7 @@ def makeConfigDict(config, log, camera, maxIter,
'minStarPerExp': config.minStarPerExp,
'minExpPerNight': config.minExpPerNight,
'expGrayInitialCut': config.expGrayInitialCut,
'expFwhmCutDict': dict(config.expFwhmCutDict),
'expGrayPhotometricCutDict': dict(config.expGrayPhotometricCutDict),
'expGrayHighCutDict': dict(config.expGrayHighCutDict),
'expGrayRecoverCut': config.expGrayRecoverCut,
Expand Down Expand Up @@ -404,7 +405,7 @@ def translateVisitCatalog(visitCat):
fgcmExpInfo = np.zeros(len(visitCat), dtype=[('VISIT', 'i8'),
('MJD', 'f8'),
('EXPTIME', 'f8'),
('PSFSIGMA', 'f8'),
('PSFFWHM', 'f8'),
('DELTA_APER', 'f8'),
('SKYBACKGROUND', 'f8'),
('DEEPFLAG', 'i2'),
Expand All @@ -423,7 +424,7 @@ def translateVisitCatalog(visitCat):
fgcmExpInfo['TELDEC'][:] = visitCat['teldec']
fgcmExpInfo['TELROT'][:] = visitCat['telrot']
fgcmExpInfo['PMB'][:] = visitCat['pmb']
fgcmExpInfo['PSFSIGMA'][:] = visitCat['psfSigma']
fgcmExpInfo['PSFFWHM'][:] = visitCat['psfFwhm']
fgcmExpInfo['DELTA_APER'][:] = visitCat['deltaAper']
fgcmExpInfo['SKYBACKGROUND'][:] = visitCat['skyBackground']
# Note that we have to go through asAstropy() to get a string
Expand Down
Loading