Skip to content

Commit

Permalink
Merge branch 'tickets/DM-27103'
Browse files Browse the repository at this point in the history
  • Loading branch information
czwa committed Apr 29, 2021
2 parents fb99f82 + 04e6e5a commit 669e18e
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 42 deletions.
18 changes: 0 additions & 18 deletions python/lsst/ip/isr/brighterFatterKernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,24 +88,6 @@ def __init__(self, camera=None, level=None, **kwargs):
'badAmps', 'gain', 'noise', 'meanXcorrs', 'valid',
'ampKernels', 'detKernels'])

def __eq__(self, other):
"""Calibration equivalence
"""
if not isinstance(other, self.__class__):
return False

for attr in self._requiredAttributes:
attrSelf = getattr(self, attr)
attrOther = getattr(other, attr)
if isinstance(attrSelf, dict) and isinstance(attrOther, dict):
for ampName in attrSelf:
if not np.allclose(attrSelf[ampName], attrOther[ampName], equal_nan=True):
return False
else:
if attrSelf != attrOther:
return False
return True

def updateMetadata(self, setDate=False, **kwargs):
"""Update calibration metadata.
Expand Down
35 changes: 32 additions & 3 deletions python/lsst/ip/isr/calibType.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import os.path
import warnings
import yaml
import numpy as np

from astropy.table import Table
from astropy.io import fits

Expand Down Expand Up @@ -91,15 +93,42 @@ def __str__(self):
def __eq__(self, other):
"""Calibration equivalence.
Subclasses will need to check specific sub-properties. The
default is only to check common entries.
Running ``calib.log.setLevel(0)`` enables debug statements to
identify problematic fields.
"""
if not isinstance(other, self.__class__):
self.log.debug("Incorrect class type: %s %s", self.__class__, other.__class__)
return False

for attr in self._requiredAttributes:
if getattr(self, attr) != getattr(other, attr):
attrSelf = getattr(self, attr)
attrOther = getattr(other, attr)

if isinstance(attrSelf, dict):
# Dictionary of arrays.
if attrSelf.keys() != attrOther.keys():
self.log.debug("Dict Key Failure: %s %s %s", attr, attrSelf.keys(), attrOther.keys())
return False
for key in attrSelf:
if not np.allclose(attrSelf[key], attrOther[key], equal_nan=True):
self.log.debug("Array Failure: %s %s %s", key, attrSelf[key], attrOther[key])
return False
elif isinstance(attrSelf, np.ndarray):
# Bare array.
if not np.allclose(attrSelf, attrOther, equal_nan=True):
self.log.debug("Array Failure: %s %s %s", attr, attrSelf, attrOther)
return False
elif type(attrSelf) != type(attrOther):
if set([attrSelf, attrOther]) == set([None, ""]):
# Fits converts None to "", but None is not "".
continue
self.log.debug("Type Failure: %s %s %s %s %s", attr, type(attrSelf), type(attrOther),
attrSelf, attrOther)
return False
else:
if attrSelf != attrOther:
self.log.debug("Value Failure: %s %s %s", attr, attrSelf, attrOther)
return False

return True

Expand Down
11 changes: 8 additions & 3 deletions python/lsst/ip/isr/crosstalk.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ def fromDetector(self, detector, coeffVector=None):
"""
if detector.hasCrosstalk() or coeffVector:
self._detectorId = detector.getId()
self._detectorName = detector.getName()
self._detectorSerial = detector.getSerial()

Expand All @@ -168,7 +169,11 @@ def fromDetector(self, detector, coeffVector=None):
raise RuntimeError("Crosstalk coefficients do not match detector shape. "
f"{self.crosstalkShape} {self.nAmp}")

self.coeffErr = np.zeros(self.crosstalkShape)
self.coeffNum = np.zeros(self.crosstalkShape, dtype=int)
self.coeffValid = np.ones(self.crosstalkShape, dtype=bool)
self.interChip = {}

self.hasCrosstalk = True
self.updateMetadata()
return self
Expand Down Expand Up @@ -334,11 +339,11 @@ def fromTable(cls, tableList):
inDict['nAmp'] = metadata['NAMP']

inDict['coeffs'] = coeffTable['CT_COEFFS']
if 'CT_ERRORS' in coeffTable:
if 'CT_ERRORS' in coeffTable.columns:
inDict['coeffErr'] = coeffTable['CT_ERRORS']
if 'CT_COUNTS' in coeffTable:
if 'CT_COUNTS' in coeffTable.columns:
inDict['coeffNum'] = coeffTable['CT_COUNTS']
if 'CT_VALID' in coeffTable:
if 'CT_VALID' in coeffTable.columns:
inDict['coeffValid'] = coeffTable['CT_VALID']

if len(tableList) > 1:
Expand Down
18 changes: 0 additions & 18 deletions python/lsst/ip/isr/ptcDataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,24 +197,6 @@ def __init__(self, ampNames=[], ptcFitType=None, covMatrixSide=1, **kwargs):
'aMatrix', 'bMatrix', 'finalVars', 'finalModelVars', 'finalMeans',
'photoCharge'])

def __eq__(self, other):
"""Calibration equivalence
"""
if not isinstance(other, self.__class__):
return False

for attr in self._requiredAttributes:
attrSelf = getattr(self, attr)
attrOther = getattr(other, attr)
if isinstance(attrSelf, dict) and isinstance(attrOther, dict):
for ampName in attrSelf:
if not np.allclose(attrSelf[ampName], attrOther[ampName], equal_nan=True):
return False
else:
if attrSelf != attrOther:
return False
return True

def setAmpValues(self, ampName, inputExpIdPair=[(np.nan, np.nan)], expIdMask=[np.nan],
rawExpTime=[np.nan], rawMean=[np.nan], rawVar=[np.nan], photoCharge=[np.nan],
gain=np.nan, gainErr=np.nan, noise=np.nan, noiseErr=np.nan, ptcFitPars=[np.nan],
Expand Down
21 changes: 21 additions & 0 deletions tests/test_crosstalk.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,27 @@ def test_interChip(self):
isr.crosstalk.run(exposure, crosstalk=calib, crosstalkSources=ctSources)
self.checkSubtracted(exposure)

def test_crosstalkIO(self):
"""Test that crosstalk doesn't change on being converted to persistable formats."""

# Add the interchip crosstalk as in the previous test.
exposure = self.exposure

coeff = np.array(self.crosstalk).transpose()
calib = CrosstalkCalib().fromDetector(exposure.getDetector(), coeffVector=coeff)
# Now convert this into zero intra-chip, full inter-chip:
calib.interChip['detector 2'] = coeff

outPath = tempfile.mktemp() + '.yaml'
calib.writeText(outPath)
newCrosstalk = CrosstalkCalib().readText(outPath)
self.assertEqual(calib, newCrosstalk)

outPath = tempfile.mktemp() + '.fits'
calib.writeFits(outPath)
newCrosstalk = CrosstalkCalib().readFits(outPath)
self.assertEqual(calib, newCrosstalk)


class MemoryTester(lsst.utils.tests.MemoryTestCase):
pass
Expand Down

0 comments on commit 669e18e

Please sign in to comment.