lsst.ip.isr  20.0.0-16-g111fe95+e3b38461e6
linearize.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2016 AURA/LSST.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 import abc
23 import numpy as np
24 
25 from astropy.table import Table
26 
27 from lsst.pipe.base import Struct
28 from lsst.geom import Box2I, Point2I, Extent2I
29 from .applyLookupTable import applyLookupTable
30 from .calibType import IsrCalib
31 
32 __all__ = ["Linearizer",
33  "LinearizeBase", "LinearizeLookupTable", "LinearizeSquared",
34  "LinearizeProportional", "LinearizePolynomial", "LinearizeNone"]
35 
36 
38  """Parameter set for linearization.
39 
40  These parameters are included in cameraGeom.Amplifier, but
41  should be accessible externally to allow for testing.
42 
43  Parameters
44  ----------
45  table : `numpy.array`, optional
46  Lookup table; a 2-dimensional array of floats:
47  - one row for each row index (value of coef[0] in the amplifier)
48  - one column for each image value
49  To avoid copying the table the last index should vary fastest
50  (numpy default "C" order)
51  detector : `lsst.afw.cameraGeom.Detector`, optional
52  Detector object. Passed to self.fromDetector() on init.
53  log : `lsst.log.Log`, optional
54  Logger to handle messages.
55  kwargs : `dict`, optional
56  Other keyword arguments to pass to the parent init.
57 
58  Raises
59  ------
60  RuntimeError :
61  Raised if the supplied table is not 2D, or if the table has fewer
62  columns than rows (indicating that the indices are swapped).
63 
64  Notes
65  -----
66  The linearizer attributes stored are:
67 
68  hasLinearity : `bool`
69  Whether a linearity correction is defined for this detector.
70  override : `bool`
71  Whether the detector parameters should be overridden.
72  ampNames : `list` [`str`]
73  List of amplifier names to correct.
74  linearityCoeffs : `dict` [`str`, `numpy.array`]
75  Coefficients to use in correction. Indexed by amplifier
76  names. The format of the array depends on the type of
77  correction to apply.
78  linearityType : `dict` [`str`, `str`]
79  Type of correction to use, indexed by amplifier names.
80  linearityBBox : `dict` [`str`, `lsst.geom.Box2I`]
81  Bounding box the correction is valid over, indexed by
82  amplifier names.
83  fitParams : `dict` [`str`, `numpy.array`], optional
84  Linearity fit parameters used to construct the correction
85  coefficients, indexed as above.
86  fitParamsErr : `dict` [`str`, `numpy.array`], optional
87  Uncertainty values of the linearity fit parameters used to
88  construct the correction coefficients, indexed as above.
89  fitChiSq : `dict` [`str`, `float`], optional
90  Chi-squared value of the linearity fit, indexed as above.
91  tableData : `numpy.array`, optional
92  Lookup table data for the linearity correction.
93  """
94  _OBSTYPE = "LINEARIZER"
95  _SCHEMA = 'Gen3 Linearizer'
96  _VERSION = 1.1
97 
98  def __init__(self, table=None, **kwargs):
99  self.hasLinearity = False
100  self.override = False
101 
102  self.ampNames = list()
103  self.linearityCoeffs = dict()
104  self.linearityType = dict()
105  self.linearityBBox = dict()
106 
107  self.fitParams = dict()
108  self.fitParamsErr = dict()
109  self.fitChiSq = dict()
110 
111  self.tableData = None
112  if table is not None:
113  if len(table.shape) != 2:
114  raise RuntimeError("table shape = %s; must have two dimensions" % (table.shape,))
115  if table.shape[1] < table.shape[0]:
116  raise RuntimeError("table shape = %s; indices are switched" % (table.shape,))
117  self.tableData = np.array(table, order="C")
118 
119  super().__init__(**kwargs)
120  self.requiredAttributes.update(['hasLinearity', 'override',
121  'ampNames',
122  'linearityCoeffs', 'linearityType', 'linearityBBox',
123  'fitParams', 'fitParamsErr', 'fitChiSq',
124  'tableData'])
125 
126  def updateMetadata(self, setDate=False, **kwargs):
127  """Update metadata keywords with new values.
128 
129  This calls the base class's method after ensuring the required
130  calibration keywords will be saved.
131 
132  Parameters
133  ----------
134  setDate : `bool`, optional
135  Update the CALIBDATE fields in the metadata to the current
136  time. Defaults to False.
137  kwargs :
138  Other keyword parameters to set in the metadata.
139  """
140  kwargs['HAS_LINEARITY'] = self.hasLinearity
141  kwargs['OVERRIDE'] = self.override
142  kwargs['HAS_TABLE'] = self.tableData is not None
143 
144  super().updateMetadata(setDate=setDate, **kwargs)
145 
146  def fromDetector(self, detector):
147  """Read linearity parameters from a detector.
148 
149  Parameters
150  ----------
151  detector : `lsst.afw.cameraGeom.detector`
152  Input detector with parameters to use.
153 
154  Returns
155  -------
156  calib : `lsst.ip.isr.Linearizer`
157  The calibration constructed from the detector.
158  """
159  self._detectorName = detector.getName()
160  self._detectorSerial = detector.getSerial()
161  self._detectorId = detector.getId()
162  self.hasLinearity = True
163 
164  # Do not translate Threshold, Maximum, Units.
165  for amp in detector.getAmplifiers():
166  ampName = amp.getName()
167  self.ampNames.append(ampName)
168  self.linearityType[ampName] = amp.getLinearityType()
169  self.linearityCoeffs[ampName] = amp.getLinearityCoeffs()
170  self.linearityBBox[ampName] = amp.getBBox()
171 
172  return self
173 
174  @classmethod
175  def fromDict(cls, dictionary):
176  """Construct a calibration from a dictionary of properties
177 
178  Parameters
179  ----------
180  dictionary : `dict`
181  Dictionary of properties
182 
183  Returns
184  -------
185  calib : `lsst.ip.isr.Linearity`
186  Constructed calibration.
187 
188  Raises
189  ------
190  RuntimeError
191  Raised if the supplied dictionary is for a different
192  calibration.
193  """
194 
195  calib = cls()
196 
197  if calib._OBSTYPE != dictionary['metadata']['OBSTYPE']:
198  raise RuntimeError(f"Incorrect linearity supplied. Expected {calib._OBSTYPE}, "
199  f"found {dictionary['metadata']['OBSTYPE']}")
200 
201  calib.setMetadata(dictionary['metadata'])
202 
203  calib.hasLinearity = dictionary.get('hasLinearity',
204  dictionary['metadata'].get('HAS_LINEARITY', False))
205  calib.override = dictionary.get('override', True)
206 
207  if calib.hasLinearity:
208  for ampName in dictionary['amplifiers']:
209  amp = dictionary['amplifiers'][ampName]
210  calib.ampNames.append(ampName)
211  calib.linearityCoeffs[ampName] = np.array(amp.get('linearityCoeffs', None), dtype=np.float64)
212  calib.linearityType[ampName] = amp.get('linearityType', 'None')
213  calib.linearityBBox[ampName] = amp.get('linearityBBox', None)
214 
215  calib.fitParams[ampName] = np.array(amp.get('fitParams', None), dtype=np.float64)
216  calib.fitParamsErr[ampName] = np.array(amp.get('fitParamsErr', None), dtype=np.float64)
217  calib.fitChiSq[ampName] = amp.get('fitChiSq', None)
218 
219  calib.tableData = dictionary.get('tableData', None)
220  if calib.tableData:
221  calib.tableData = np.array(calib.tableData)
222 
223  return calib
224 
225  def toDict(self):
226  """Return linearity parameters as a dict.
227 
228  Returns
229  -------
230  outDict : `dict`:
231  """
232  self.updateMetadata()
233 
234  outDict = {'metadata': self.getMetadata(),
235  'detectorName': self._detectorName,
236  'detectorSerial': self._detectorSerial,
237  'detectorId': self._detectorId,
238  'hasTable': self.tableData is not None,
239  'amplifiers': dict(),
240  }
241  for ampName in self.linearityType:
242  outDict['amplifiers'][ampName] = {'linearityType': self.linearityType[ampName],
243  'linearityCoeffs': self.linearityCoeffs[ampName].toList(),
244  'linearityBBox': self.linearityBBox[ampName],
245  'fitParams': self.fitParams[ampName].toList(),
246  'fitParamsErr': self.fitParamsErr[ampName].toList(),
247  'fitChiSq': self.fitChiSq[ampName]}
248  if self.tableData is not None:
249  outDict['tableData'] = self.tableData.tolist()
250 
251  return outDict
252 
253  @classmethod
254  def fromTable(cls, tableList):
255  """Read linearity from a FITS file.
256 
257  This method uses the `fromDict` method to create the
258  calibration, after constructing an appropriate dictionary from
259  the input tables.
260 
261  Parameters
262  ----------
263  tableList : `list` [`astropy.table.Table`]
264  afwTable read from input file name.
265 
266  Returns
267  -------
268  linearity : `~lsst.ip.isr.linearize.Linearizer``
269  Linearity parameters.
270 
271  Notes
272  -----
273  The method reads a FITS file with 1 or 2 extensions. The metadata is read from the header of
274  extension 1, which must exist. Then the table is loaded, and the ['AMPLIFIER_NAME', 'TYPE',
275  'COEFFS', 'BBOX_X0', 'BBOX_Y0', 'BBOX_DX', 'BBOX_DY'] columns are read and used to
276  set each dictionary by looping over rows.
277  Eextension 2 is then attempted to read in the try block (which only exists for lookup tables).
278  It has a column named 'LOOKUP_VALUES' that contains a vector of the lookup entries in each row.
279 
280  """
281  coeffTable = tableList[0]
282 
283  metadata = coeffTable.meta
284  inDict = dict()
285  inDict['metadata'] = metadata
286  inDict['hasLinearity'] = metadata['HAS_LINEARITY']
287  inDict['amplifiers'] = dict()
288 
289  for record in coeffTable:
290  ampName = record['AMPLIFIER_NAME']
291 
292  fitParams = record['FIT_PARAMS'] if 'FIT_PARAMS' in record else None
293  fitParamsErr = record['FIT_PARAMS_ERR'] if 'FIT_PARAMS_ERR' in record else None
294  fitChiSq = record['RED_CHI_SQ'] if 'RED_CHI_SQ' in record else None
295 
296  inDict['amplifiers'][ampName] = {
297  'linearityType': record['TYPE'],
298  'linearityCoeffs': record['COEFFS'],
299  'linearityBBox': Box2I(Point2I(record['BBOX_X0'], record['BBOX_Y0']),
300  Extent2I(record['BBOX_DX'], record['BBOX_DY'])),
301  'fitParams': fitParams,
302  'fitParamsErr': fitParamsErr,
303  'fitChiSq': fitChiSq,
304  }
305 
306  if len(tableList) > 1:
307  tableData = tableList[1]
308  inDict['tableData'] = [record['LOOKUP_VALUES'] for record in tableData]
309 
310  return cls().fromDict(inDict)
311 
312  def toTable(self):
313  """Construct a list of tables containing the information in this calibration
314 
315  The list of tables should create an identical calibration
316  after being passed to this class's fromTable method.
317 
318  Returns
319  -------
320  tableList : `list` [`astropy.table.Table`]
321  List of tables containing the linearity calibration
322  information.
323  """
324 
325  tableList = []
326  self.updateMetadata()
327  catalog = Table([{'AMPLIFIER_NAME': ampName,
328  'TYPE': self.linearityType[ampName],
329  'COEFFS': self.linearityCoeffs[ampName],
330  'BBOX_X0': self.linearityBBox[ampName].getMinX(),
331  'BBOX_Y0': self.linearityBBox[ampName].getMinY(),
332  'BBOX_DX': self.linearityBBox[ampName].getWidth(),
333  'BBOX_DY': self.linearityBBox[ampName].getHeight(),
334  'FIT_PARAMS': self.fitParams[ampName],
335  'FIT_PARAMS_ERR': self.fitParamsErr[ampName],
336  'RED_CHI_SQ': self.fitChiSq[ampName],
337  } for ampName in self.ampNames])
338 
339  tableList.append(catalog)
340 
341  if self.tableData:
342  catalog = Table([{'LOOKUP_VALUES': value} for value in self.tableData])
343  tableList.append(catalog)
344 
345  return(catalog)
346 
347  def getLinearityTypeByName(self, linearityTypeName):
348  """Determine the linearity class to use from the type name.
349 
350  Parameters
351  ----------
352  linearityTypeName : str
353  String name of the linearity type that is needed.
354 
355  Returns
356  -------
357  linearityType : `~lsst.ip.isr.linearize.LinearizeBase`
358  The appropriate linearity class to use. If no matching class
359  is found, `None` is returned.
360  """
361  for t in [LinearizeLookupTable,
362  LinearizeSquared,
363  LinearizePolynomial,
364  LinearizeProportional,
365  LinearizeNone]:
366  if t.LinearityType == linearityTypeName:
367  return t
368  return None
369 
370  def validate(self, detector=None, amplifier=None):
371  """Validate linearity for a detector/amplifier.
372 
373  Parameters
374  ----------
375  detector : `lsst.afw.cameraGeom.Detector`, optional
376  Detector to validate, along with its amplifiers.
377  amplifier : `lsst.afw.cameraGeom.Amplifier`, optional
378  Single amplifier to validate.
379 
380  Raises
381  ------
382  RuntimeError :
383  Raised if there is a mismatch in linearity parameters, and
384  the cameraGeom parameters are not being overridden.
385  """
386  amplifiersToCheck = []
387  if detector:
388  if self._detectorName != detector.getName():
389  raise RuntimeError("Detector names don't match: %s != %s" %
390  (self._detectorName, detector.getName()))
391  if int(self._detectorId) != int(detector.getId()):
392  raise RuntimeError("Detector IDs don't match: %s != %s" %
393  (int(self._detectorId), int(detector.getId())))
394  if self._detectorSerial != detector.getSerial():
395  raise RuntimeError("Detector serial numbers don't match: %s != %s" %
396  (self._detectorSerial, detector.getSerial()))
397  if len(detector.getAmplifiers()) != len(self.linearityCoeffs.keys()):
398  raise RuntimeError("Detector number of amps = %s does not match saved value %s" %
399  (len(detector.getAmplifiers()),
400  len(self.linearityCoeffs.keys())))
401  amplifiersToCheck.extend(detector.getAmplifiers())
402 
403  if amplifier:
404  amplifiersToCheck.extend(amplifier)
405 
406  for amp in amplifiersToCheck:
407  ampName = amp.getName()
408  if ampName not in self.linearityCoeffs.keys():
409  raise RuntimeError("Amplifier %s is not in linearity data" %
410  (ampName, ))
411  if amp.getLinearityType() != self.linearityType[ampName]:
412  if self.override:
413  self.log.warn("Overriding amplifier defined linearityType (%s) for %s",
414  self.linearityType[ampName], ampName)
415  else:
416  raise RuntimeError("Amplifier %s type %s does not match saved value %s" %
417  (ampName, amp.getLinearityType(), self.linearityType[ampName]))
418  if (amp.getLinearityCoeffs().shape != self.linearityCoeffs[ampName].shape or not
419  np.allclose(amp.getLinearityCoeffs(), self.linearityCoeffs[ampName], equal_nan=True)):
420  if self.override:
421  self.log.warn("Overriding amplifier defined linearityCoeffs (%s) for %s",
422  self.linearityCoeffs[ampName], ampName)
423  else:
424  raise RuntimeError("Amplifier %s coeffs %s does not match saved value %s" %
425  (ampName, amp.getLinearityCoeffs(), self.linearityCoeffs[ampName]))
426 
427  def applyLinearity(self, image, detector=None, log=None):
428  """Apply the linearity to an image.
429 
430  If the linearity parameters are populated, use those,
431  otherwise use the values from the detector.
432 
433  Parameters
434  ----------
435  image : `~lsst.afw.image.image`
436  Image to correct.
437  detector : `~lsst.afw.cameraGeom.detector`
438  Detector to use for linearity parameters if not already
439  populated.
440  log : `~lsst.log.Log`, optional
441  Log object to use for logging.
442  """
443  if log is None:
444  log = self.log
445  if detector and not self.hasLinearity:
446  self.fromDetector(detector)
447 
448  self.validate(detector)
449 
450  numAmps = 0
451  numLinearized = 0
452  numOutOfRange = 0
453  for ampName in self.linearityType.keys():
454  linearizer = self.getLinearityTypeByName(self.linearityType[ampName])
455  numAmps += 1
456  if linearizer is not None:
457  ampView = image.Factory(image, self.linearityBBox[ampName])
458  success, outOfRange = linearizer()(ampView, **{'coeffs': self.linearityCoeffs[ampName],
459  'table': self.tableData,
460  'log': self.log})
461  numOutOfRange += outOfRange
462  if success:
463  numLinearized += 1
464  elif log is not None:
465  log.warn("Amplifier %s did not linearize.",
466  ampName)
467  return Struct(
468  numAmps=numAmps,
469  numLinearized=numLinearized,
470  numOutOfRange=numOutOfRange
471  )
472 
473 
474 class LinearizeBase(metaclass=abc.ABCMeta):
475  """Abstract base class functor for correcting non-linearity.
476 
477  Subclasses must define __call__ and set class variable
478  LinearityType to a string that will be used for linearity type in
479  the cameraGeom.Amplifier.linearityType field.
480 
481  All linearity corrections should be defined in terms of an
482  additive correction, such that:
483 
484  corrected_value = uncorrected_value + f(uncorrected_value)
485  """
486  LinearityType = None # linearity type, a string used for AmpInfoCatalogs
487 
488  @abc.abstractmethod
489  def __call__(self, image, **kwargs):
490  """Correct non-linearity.
491 
492  Parameters
493  ----------
494  image : `lsst.afw.image.Image`
495  Image to be corrected
496  kwargs : `dict`
497  Dictionary of parameter keywords:
498  ``"coeffs"``
499  Coefficient vector (`list` or `numpy.array`).
500  ``"table"``
501  Lookup table data (`numpy.array`).
502  ``"log"``
503  Logger to handle messages (`lsst.log.Log`).
504 
505  Returns
506  -------
507  output : `bool`
508  If true, a correction was applied successfully.
509 
510  Raises
511  ------
512  RuntimeError:
513  Raised if the linearity type listed in the
514  detector does not match the class type.
515  """
516  pass
517 
518 
519 class LinearizeLookupTable(LinearizeBase):
520  """Correct non-linearity with a persisted lookup table.
521 
522  The lookup table consists of entries such that given
523  "coefficients" c0, c1:
524 
525  for each i,j of image:
526  rowInd = int(c0)
527  colInd = int(c1 + uncorrImage[i,j])
528  corrImage[i,j] = uncorrImage[i,j] + table[rowInd, colInd]
529 
530  - c0: row index; used to identify which row of the table to use
531  (typically one per amplifier, though one can have multiple
532  amplifiers use the same table)
533  - c1: column index offset; added to the uncorrected image value
534  before truncation; this supports tables that can handle
535  negative image values; also, if the c1 ends with .5 then
536  the nearest index is used instead of truncating to the
537  next smaller index
538  """
539  LinearityType = "LookupTable"
540 
541  def __call__(self, image, **kwargs):
542  """Correct for non-linearity.
543 
544  Parameters
545  ----------
546  image : `lsst.afw.image.Image`
547  Image to be corrected
548  kwargs : `dict`
549  Dictionary of parameter keywords:
550  ``"coeffs"``
551  Columnation vector (`list` or `numpy.array`).
552  ``"table"``
553  Lookup table data (`numpy.array`).
554  ``"log"``
555  Logger to handle messages (`lsst.log.Log`).
556 
557  Returns
558  -------
559  output : `bool`
560  If true, a correction was applied successfully.
561 
562  Raises
563  ------
564  RuntimeError:
565  Raised if the requested row index is out of the table
566  bounds.
567  """
568  numOutOfRange = 0
569 
570  rowInd, colIndOffset = kwargs['coeffs'][0:2]
571  table = kwargs['table']
572  log = kwargs['log']
573 
574  numTableRows = table.shape[0]
575  rowInd = int(rowInd)
576  if rowInd < 0 or rowInd > numTableRows:
577  raise RuntimeError("LinearizeLookupTable rowInd=%s not in range[0, %s)" %
578  (rowInd, numTableRows))
579  tableRow = table[rowInd, :]
580  numOutOfRange += applyLookupTable(image, tableRow, colIndOffset)
581 
582  if numOutOfRange > 0 and log is not None:
583  log.warn("%s pixels were out of range of the linearization table",
584  numOutOfRange)
585  if numOutOfRange < image.getArray().size:
586  return True, numOutOfRange
587  else:
588  return False, numOutOfRange
589 
590 
592  """Correct non-linearity with a polynomial mode.
593 
594  corrImage = uncorrImage + sum_i c_i uncorrImage^(2 + i)
595 
596  where c_i are the linearity coefficients for each amplifier.
597  Lower order coefficients are not included as they duplicate other
598  calibration parameters:
599  ``"k0"``
600  A coefficient multiplied by uncorrImage**0 is equivalent to
601  bias level. Irrelevant for correcting non-linearity.
602  ``"k1"``
603  A coefficient multiplied by uncorrImage**1 is proportional
604  to the gain. Not necessary for correcting non-linearity.
605  """
606  LinearityType = "Polynomial"
607 
608  def __call__(self, image, **kwargs):
609  """Correct non-linearity.
610 
611  Parameters
612  ----------
613  image : `lsst.afw.image.Image`
614  Image to be corrected
615  kwargs : `dict`
616  Dictionary of parameter keywords:
617  ``"coeffs"``
618  Coefficient vector (`list` or `numpy.array`).
619  If the order of the polynomial is n, this list
620  should have a length of n-1 ("k0" and "k1" are
621  not needed for the correction).
622  ``"log"``
623  Logger to handle messages (`lsst.log.Log`).
624 
625  Returns
626  -------
627  output : `bool`
628  If true, a correction was applied successfully.
629  """
630  if not np.any(np.isfinite(kwargs['coeffs'])):
631  return False, 0
632  if not np.any(kwargs['coeffs']):
633  return False, 0
634 
635  ampArray = image.getArray()
636  correction = np.zeros_like(ampArray)
637  for order, coeff in enumerate(kwargs['coeffs'], start=2):
638  correction += coeff * np.power(ampArray, order)
639  ampArray += correction
640 
641  return True, 0
642 
643 
645  """Correct non-linearity with a squared model.
646 
647  corrImage = uncorrImage + c0*uncorrImage^2
648 
649  where c0 is linearity coefficient 0 for each amplifier.
650  """
651  LinearityType = "Squared"
652 
653  def __call__(self, image, **kwargs):
654  """Correct for non-linearity.
655 
656  Parameters
657  ----------
658  image : `lsst.afw.image.Image`
659  Image to be corrected
660  kwargs : `dict`
661  Dictionary of parameter keywords:
662  ``"coeffs"``
663  Coefficient vector (`list` or `numpy.array`).
664  ``"log"``
665  Logger to handle messages (`lsst.log.Log`).
666 
667  Returns
668  -------
669  output : `bool`
670  If true, a correction was applied successfully.
671  """
672 
673  sqCoeff = kwargs['coeffs'][0]
674  if sqCoeff != 0:
675  ampArr = image.getArray()
676  ampArr *= (1 + sqCoeff*ampArr)
677  return True, 0
678  else:
679  return False, 0
680 
681 
683  """Do not correct non-linearity.
684  """
685  LinearityType = "Proportional"
686 
687  def __call__(self, image, **kwargs):
688  """Do not correct for non-linearity.
689 
690  Parameters
691  ----------
692  image : `lsst.afw.image.Image`
693  Image to be corrected
694  kwargs : `dict`
695  Dictionary of parameter keywords:
696  ``"coeffs"``
697  Coefficient vector (`list` or `numpy.array`).
698  ``"log"``
699  Logger to handle messages (`lsst.log.Log`).
700 
701  Returns
702  -------
703  output : `bool`
704  If true, a correction was applied successfully.
705  """
706  return True, 0
707 
708 
710  """Do not correct non-linearity.
711  """
712  LinearityType = "None"
713 
714  def __call__(self, image, **kwargs):
715  """Do not correct for non-linearity.
716 
717  Parameters
718  ----------
719  image : `lsst.afw.image.Image`
720  Image to be corrected
721  kwargs : `dict`
722  Dictionary of parameter keywords:
723  ``"coeffs"``
724  Coefficient vector (`list` or `numpy.array`).
725  ``"log"``
726  Logger to handle messages (`lsst.log.Log`).
727 
728  Returns
729  -------
730  output : `bool`
731  If true, a correction was applied successfully.
732  """
733  return True, 0
lsst::ip::isr.linearize.Linearizer.toTable
def toTable(self)
Definition: linearize.py:312
lsst::ip::isr.linearize.Linearizer.override
override
Definition: linearize.py:100
lsst::ip::isr.linearize.Linearizer
Definition: linearize.py:37
lsst::ip::isr.linearize.LinearizeBase.__call__
def __call__(self, image, **kwargs)
Definition: linearize.py:489
lsst::ip::isr.linearize.LinearizeBase
Definition: linearize.py:474
lsst::ip::isr.calibType.IsrCalib.fromDetector
def fromDetector(self, detector)
Definition: calibType.py:342
lsst::ip::isr.linearize.Linearizer.hasLinearity
hasLinearity
Definition: linearize.py:99
lsst::ip::isr.calibType.IsrCalib.validate
def validate(self, other=None)
Definition: calibType.py:440
lsst::ip::isr.linearize.LinearizeSquared.__call__
def __call__(self, image, **kwargs)
Definition: linearize.py:653
lsst::ip::isr.linearize.Linearizer.updateMetadata
def updateMetadata(self, setDate=False, **kwargs)
Definition: linearize.py:126
lsst::ip::isr.linearize.Linearizer.fitChiSq
fitChiSq
Definition: linearize.py:109
lsst::ip::isr.calibType.IsrCalib.log
log
Definition: calibType.py:81
lsst::ip::isr.linearize.Linearizer.fitParams
fitParams
Definition: linearize.py:107
lsst::ip::isr.linearize.Linearizer.fromDetector
def fromDetector(self, detector)
Definition: linearize.py:146
lsst::ip::isr.linearize.Linearizer.linearityBBox
linearityBBox
Definition: linearize.py:105
lsst::ip::isr.linearize.LinearizeNone.__call__
def __call__(self, image, **kwargs)
Definition: linearize.py:714
lsst::ip::isr.linearize.LinearizeLookupTable.__call__
def __call__(self, image, **kwargs)
Definition: linearize.py:541
lsst::ip::isr.linearize.LinearizePolynomial
Definition: linearize.py:591
lsst::ip::isr.calibType.IsrCalib._detectorSerial
_detectorSerial
Definition: calibType.py:68
lsst::ip::isr.calibType.IsrCalib.requiredAttributes
requiredAttributes
Definition: calibType.py:76
lsst::ip::isr.linearize.Linearizer.__init__
def __init__(self, table=None, **kwargs)
Definition: linearize.py:98
applyLookupTable
lsst::ip::isr.linearize.Linearizer.tableData
tableData
Definition: linearize.py:111
lsst::ip::isr.linearize.Linearizer.linearityType
linearityType
Definition: linearize.py:104
lsst::ip::isr.linearize.LinearizeNone
Definition: linearize.py:709
lsst::ip::isr.calibType.IsrCalib.getMetadata
def getMetadata(self)
Definition: calibType.py:113
lsst::ip::isr.linearize.Linearizer.toDict
def toDict(self)
Definition: linearize.py:225
lsst::ip::isr.linearize.Linearizer.validate
def validate(self, detector=None, amplifier=None)
Definition: linearize.py:370
lsst::ip::isr.linearize.LinearizeProportional
Definition: linearize.py:682
lsst::geom
lsst::ip::isr.linearize.Linearizer.fromTable
def fromTable(cls, tableList)
Definition: linearize.py:254
lsst::ip::isr.calibType.IsrCalib._detectorId
_detectorId
Definition: calibType.py:69
lsst::ip::isr.linearize.LinearizeProportional.__call__
def __call__(self, image, **kwargs)
Definition: linearize.py:687
Point< int, 2 >
lsst::ip::isr.linearize.LinearizeSquared
Definition: linearize.py:644
lsst::geom::Box2I
lsst::ip::isr.linearize.Linearizer.linearityCoeffs
linearityCoeffs
Definition: linearize.py:103
lsst::ip::isr.calibType.IsrCalib
Definition: calibType.py:36
lsst::ip::isr.linearize.Linearizer.getLinearityTypeByName
def getLinearityTypeByName(self, linearityTypeName)
Definition: linearize.py:347
lsst::ip::isr.linearize.Linearizer.ampNames
ampNames
Definition: linearize.py:102
lsst::ip::isr.linearize.Linearizer.fitParamsErr
fitParamsErr
Definition: linearize.py:108
lsst::ip::isr.calibType.IsrCalib._detectorName
_detectorName
Definition: calibType.py:67
lsst::pipe::base
lsst::ip::isr.linearize.Linearizer.applyLinearity
def applyLinearity(self, image, detector=None, log=None)
Definition: linearize.py:427
Extent< int, 2 >
lsst::ip::isr.calibType.IsrCalib.updateMetadata
def updateMetadata(self, camera=None, detector=None, filterName=None, setCalibId=False, setDate=False, **kwargs)
Definition: calibType.py:142
lsst::ip::isr.linearize.LinearizePolynomial.__call__
def __call__(self, image, **kwargs)
Definition: linearize.py:608
lsst::ip::isr.linearize.Linearizer.fromDict
def fromDict(cls, dictionary)
Definition: linearize.py:175