lsst.pipe.drivers  19.0.0-7-g039c0b5+5
skyCorrection.py
Go to the documentation of this file.
1 # This file is part of pipe_drivers.
2 #
3 # Developed for the LSST Data Management System.
4 # This product includes software developed by the LSST Project
5 # (https://www.lsst.org).
6 # See the COPYRIGHT file at the top-level directory of this distribution
7 # for details of code ownership.
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 import lsst.afw.math as afwMath
22 import lsst.afw.image as afwImage
23 import lsst.pipe.base as pipeBase
24 
25 from lsst.pipe.base import ArgumentParser, ConfigDatasetType
26 from lsst.pex.config import Config, Field, ConfigurableField, ConfigField
27 from lsst.ctrl.pool.pool import Pool
28 from lsst.ctrl.pool.parallel import BatchPoolTask
29 from lsst.pipe.drivers.background import (SkyMeasurementTask, FocalPlaneBackground,
30  FocalPlaneBackgroundConfig, MaskObjectsTask)
31 import lsst.pipe.drivers.visualizeVisit as visualizeVisit
33 
34 __all__ = ["SkyCorrectionConfig", "SkyCorrectionTask"]
35 
36 DEBUG = False # Debugging outputs?
37 
38 
39 def makeCameraImage(camera, exposures, filename=None, binning=8):
40  """Make and write an image of an entire focal plane
41 
42  Parameters
43  ----------
44  camera : `lsst.afw.cameraGeom.Camera`
45  Camera description.
46  exposures : `list` of `tuple` of `int` and `lsst.afw.image.Exposure`
47  List of detector ID and CCD exposures (binned by `binning`).
48  filename : `str`, optional
49  Output filename.
50  binning : `int`
51  Binning size that has been applied to images.
52  """
53  image = visualizeVisit.makeCameraImage(camera, dict(exp for exp in exposures if exp is not None), binning)
54  if filename is not None:
55  image.writeFits(filename)
56  return image
57 
58 
59 class SkyCorrectionConnections(pipeBase.PipelineTaskConnections, dimensions=("instrument", "visit")):
60  rawLinker = cT.Input(
61  doc="Raw data to provide exp-visit linkage to connect calExp inputs to camera/sky calibs.",
62  name="raw",
63  multiple=True,
64  deferLoad=True,
65  storageClass="ExposureU",
66  dimensions=["instrument", "exposure", "detector"],
67  )
68  calExpArray = cT.Input(
69  doc="Input exposures to process",
70  name="calexp",
71  multiple=True,
72  storageClass="ExposureF",
73  dimensions=["instrument", "visit", "detector"],
74  )
75  calBkgArray = cT.Input(
76  doc="Input background files to use",
77  multiple=True,
78  name="calexpBackground",
79  storageClass="Background",
80  dimensions=["instrument", "visit", "detector"],
81  )
82  camera = cT.PrerequisiteInput(
83  doc="Input camera to use.",
84  name="camera",
85  storageClass="Camera",
86  dimensions=["instrument", "calibration_label"],
87  )
88  skyCalibs = cT.PrerequisiteInput(
89  doc="Input sky calibrations to use.",
90  name="sky",
91  multiple=True,
92  storageClass="ExposureF",
93  dimensions=["instrument", "physical_filter", "detector", "calibration_label"],
94  )
95  calExpCamera = cT.Output(
96  doc="Output camera image.",
97  name='calexp_camera',
98  storageClass="ImageF",
99  dimensions=["instrument", "visit"],
100  )
101  skyCorr = cT.Output(
102  doc="Output sky corrected images.",
103  name='skyCorr',
104  multiple=True,
105  storageClass="Background",
106  dimensions=["instrument", "visit", "detector"],
107  )
108 
109 
110 class SkyCorrectionConfig(pipeBase.PipelineTaskConfig, pipelineConnections=SkyCorrectionConnections):
111  """Configuration for SkyCorrectionTask"""
112  bgModel = ConfigField(dtype=FocalPlaneBackgroundConfig, doc="Background model")
113  bgModel2 = ConfigField(dtype=FocalPlaneBackgroundConfig, doc="2nd Background model")
114  sky = ConfigurableField(target=SkyMeasurementTask, doc="Sky measurement")
115  maskObjects = ConfigurableField(target=MaskObjectsTask, doc="Mask Objects")
116  doMaskObjects = Field(dtype=bool, default=True, doc="Mask objects to find good sky?")
117  doBgModel = Field(dtype=bool, default=True, doc="Do background model subtraction?")
118  doBgModel2 = Field(dtype=bool, default=True, doc="Do cleanup background model subtraction?")
119  doSky = Field(dtype=bool, default=True, doc="Do sky frame subtraction?")
120  binning = Field(dtype=int, default=8, doc="Binning factor for constructing focal-plane images")
121  calexpType = Field(dtype=str, default="calexp",
122  doc="Should be set to fakes_calexp if you want to process calexps with fakes in.")
123 
124  def setDefaults(self):
125  Config.setDefaults(self)
126  self.bgModel2.doSmooth = True
127  self.bgModel2.minFrac = 0.5
128  self.bgModel2.xSize = 256
129  self.bgModel2.ySize = 256
130  self.bgModel2.smoothScale = 1.0
131 
132 
133 class SkyCorrectionTask(pipeBase.PipelineTask, BatchPoolTask):
134  """Correct sky over entire focal plane"""
135  ConfigClass = SkyCorrectionConfig
136  _DefaultName = "skyCorr"
137 
138  def runQuantum(self, butlerQC, inputRefs, outputRefs):
139  inputs = butlerQC.get(inputRefs)
140  inputs.pop("rawLinker", None)
141  outputs = self.run(**inputs)
142  butlerQC.put(outputs, outputRefs)
143 
144  def __init__(self, *args, **kwargs):
145  super().__init__(**kwargs)
146 
147  self.makeSubtask("sky")
148  self.makeSubtask("maskObjects")
149 
150  @classmethod
151  def _makeArgumentParser(cls, *args, **kwargs):
152  kwargs.pop("doBatch", False)
153  datasetType = ConfigDatasetType(name="calexpType")
154  parser = ArgumentParser(name="skyCorr", *args, **kwargs)
155  parser.add_id_argument("--id", datasetType=datasetType, level="visit",
156  help="data ID, e.g. --id visit=12345")
157  return parser
158 
159  @classmethod
160  def batchWallTime(cls, time, parsedCmd, numCores):
161  """Return walltime request for batch job
162 
163  Subclasses should override if the walltime should be calculated
164  differently (e.g., addition of some serial time).
165 
166  Parameters
167  ----------
168  time : `float`
169  Requested time per iteration.
170  parsedCmd : `argparse.Namespace`
171  Results of argument parsing.
172  numCores : `int`
173  Number of cores.
174  """
175  numTargets = len(cls.RunnerClass.getTargetList(parsedCmd))
176  return time*numTargets
177 
178  def runDataRef(self, expRef):
179  """Perform sky correction on an exposure
180 
181  We restore the original sky, and remove it again using multiple
182  algorithms. We optionally apply:
183 
184  1. A large-scale background model.
185  This step removes very-large-scale sky such as moonlight.
186  2. A sky frame.
187  3. A medium-scale background model.
188  This step removes residual sky (This is smooth on the focal plane).
189 
190  Only the master node executes this method. The data is held on
191  the slave nodes, which do all the hard work.
192 
193  Parameters
194  ----------
195  expRef : `lsst.daf.persistence.ButlerDataRef`
196  Data reference for exposure.
197 
198  See Also
199  --------
200  ~lsst.pipe.drivers.SkyCorrectionTask.run
201  """
202  if DEBUG:
203  extension = "-%(visit)d.fits" % expRef.dataId
204 
205  with self.logOperation("processing %s" % (expRef.dataId,)):
206  pool = Pool()
207  pool.cacheClear()
208  pool.storeSet(butler=expRef.getButler())
209  camera = expRef.get("camera")
210 
211  dataIdList = [ccdRef.dataId for ccdRef in expRef.subItems("ccd") if
212  ccdRef.datasetExists(self.config.calexpType)]
213 
214  exposures = pool.map(self.loadImage, dataIdList)
215  if DEBUG:
216  makeCameraImage(camera, exposures, "restored" + extension)
217  exposures = pool.mapToPrevious(self.collectOriginal, dataIdList)
218  makeCameraImage(camera, exposures, "original" + extension)
219  exposures = pool.mapToPrevious(self.collectMask, dataIdList)
220  makeCameraImage(camera, exposures, "mask" + extension)
221 
222  if self.config.doBgModel:
223  exposures = self.focalPlaneBackground(camera, pool, dataIdList, self.config.bgModel)
224 
225  if self.config.doSky:
226  measScales = pool.mapToPrevious(self.measureSkyFrame, dataIdList)
227  scale = self.sky.solveScales(measScales)
228  self.log.info("Sky frame scale: %s" % (scale,))
229 
230  exposures = pool.mapToPrevious(self.subtractSkyFrame, dataIdList, scale)
231  if DEBUG:
232  makeCameraImage(camera, exposures, "skysub" + extension)
233  calibs = pool.mapToPrevious(self.collectSky, dataIdList)
234  makeCameraImage(camera, calibs, "sky" + extension)
235 
236  if self.config.doBgModel2:
237  exposures = self.focalPlaneBackground(camera, pool, dataIdList, self.config.bgModel2)
238 
239  # Persist camera-level image of calexp
240  image = makeCameraImage(camera, exposures)
241  expRef.put(image, "calexp_camera")
242 
243  pool.mapToPrevious(self.write, dataIdList)
244 
245  def focalPlaneBackground(self, camera, pool, dataIdList, config):
246  """Perform full focal-plane background subtraction
247 
248  This method runs on the master node.
249 
250  Parameters
251  ----------
252  camera : `lsst.afw.cameraGeom.Camera`
253  Camera description.
254  pool : `lsst.ctrl.pool.Pool`
255  Process pool.
256  dataIdList : iterable of `dict`
257  List of data identifiers for the CCDs.
258  config : `lsst.pipe.drivers.background.FocalPlaneBackgroundConfig`
259  Configuration to use for background subtraction.
260 
261  Returns
262  -------
263  exposures : `list` of `lsst.afw.image.Image`
264  List of binned images, for creating focal plane image.
265  """
266  bgModel = FocalPlaneBackground.fromCamera(config, camera)
267  data = [pipeBase.Struct(dataId=dataId, bgModel=bgModel.clone()) for dataId in dataIdList]
268  bgModelList = pool.mapToPrevious(self.accumulateModel, data)
269  for ii, bg in enumerate(bgModelList):
270  self.log.info("Background %d: %d pixels", ii, bg._numbers.array.sum())
271  bgModel.merge(bg)
272  return pool.mapToPrevious(self.subtractModel, dataIdList, bgModel)
273 
274  def focalPlaneBackgroundRun(self, camera, cacheExposures, idList, config):
275  """Perform full focal-plane background subtraction
276 
277  This method runs on the master node.
278 
279  Parameters
280  ----------
281  camera : `lsst.afw.cameraGeom.Camera`
282  Camera description.
283  cacheExposures : `list` of `lsst.afw.image.Exposures`
284  List of loaded and processed input calExp.
285  idList : `list` of `int`
286  List of detector ids to iterate over.
287  config : `lsst.pipe.drivers.background.FocalPlaneBackgroundConfig`
288  Configuration to use for background subtraction.
289 
290  Returns
291  -------
292  exposures : `list` of `lsst.afw.image.Image`
293  List of binned images, for creating focal plane image.
294  newCacheBgList : `list` of `lsst.afwMath.backgroundList`
295  Background lists generated.
296  cacheBgModel : `FocalPlaneBackground`
297  Full focal plane background model.
298  """
299  bgModel = FocalPlaneBackground.fromCamera(config, camera)
300  data = [pipeBase.Struct(id=id, bgModel=bgModel.clone()) for id in idList]
301 
302  bgModelList = []
303  for nodeData, cacheExp in zip(data, cacheExposures):
304  nodeData.bgModel.addCcd(cacheExp)
305  bgModelList.append(nodeData.bgModel)
306 
307  for ii, bg in enumerate(bgModelList):
308  self.log.info("Background %d: %d pixels", ii, bg._numbers.getArray().sum())
309  bgModel.merge(bg)
310 
311  exposures = []
312  newCacheBgList = []
313  cacheBgModel = []
314  for cacheExp in cacheExposures:
315  nodeExp, nodeBgModel, nodeBgList = self.subtractModelRun(cacheExp, bgModel)
316  exposures.append(afwMath.binImage(nodeExp.getMaskedImage(), self.config.binning))
317  cacheBgModel.append(nodeBgModel)
318  newCacheBgList.append(nodeBgList)
319 
320  return exposures, newCacheBgList, cacheBgModel
321 
322  def run(self, calExpArray, calBkgArray, skyCalibs, camera):
323  """Duplicate runDataRef method without ctrl_pool for Gen3.
324 
325  Parameters
326  ----------
327  calExpArray : `list` of `lsst.afw.image.Exposure`
328  Array of detector input calExp images for the exposure to
329  process.
330  calBkgArray : `list` of `lsst.afw.math.BackgroundList`
331  Array of detector input background lists matching the
332  calExps to process.
333  skyCalibs : `list` of `lsst.afw.image.Exposure`
334  Array of SKY calibrations for the input detectors to be
335  processed.
336  camera : `lsst.afw.cameraGeom.Camera`
337  Camera matching the input data to process.
338 
339  Returns
340  -------
341  results : `pipeBase.Struct` containing
342  calExpCamera : `lsst.afw.image.Exposure`
343  Full camera image of the sky-corrected data.
344  skyCorr : `list` of `lsst.afw.math.BackgroundList`
345  Detector-level sky-corrected background lists.
346 
347  See Also
348  --------
349  ~lsst.pipe.drivers.SkyCorrectionTask.runDataRef()
350  """
351  # To allow SkyCorrectionTask to run in the Gen3 butler
352  # environment, a new run() method was added that performs the
353  # same operations in a serial environment (pipetask processing
354  # does not support MPI processing as of 2019-05-03). Methods
355  # used in runDataRef() are used as appropriate in run(), but
356  # some have been rewritten in serial form. Please ensure that
357  # any updates to runDataRef() or the methods it calls with
358  # pool.mapToPrevious() are duplicated in run() and its
359  # methods.
360  #
361  # Variable names here should match those in runDataRef() as
362  # closely as possible. Variables matching data stored in the
363  # pool cache have a prefix indicating this. Variables that
364  # would be local to an MPI processing client have a prefix
365  # "node".
366  idList = [exp.getDetector().getId() for exp in calExpArray]
367 
368  # Construct arrays that match the cache in self.runDataRef() after
369  # self.loadImage() is map/reduced.
370  cacheExposures = []
371  cacheBgList = []
372  exposures = []
373  for calExp, calBgModel in zip(calExpArray, calBkgArray):
374  nodeExp, nodeBgList = self.loadImageRun(calExp, calBgModel)
375  cacheExposures.append(nodeExp)
376  cacheBgList.append(nodeBgList)
377  exposures.append(afwMath.binImage(nodeExp.getMaskedImage(), self.config.binning))
378 
379  if self.config.doBgModel:
380  # Generate focal plane background, updating backgrounds in the "cache".
381  exposures, newCacheBgList, cacheBgModel = self.focalPlaneBackgroundRun(
382  camera, cacheExposures, idList, self.config.bgModel
383  )
384  for cacheBg, newBg in zip(cacheBgList, newCacheBgList):
385  cacheBg.append(newBg)
386 
387  if self.config.doSky:
388  # Measure the sky frame scale on all inputs. Results in
389  # values equal to self.measureSkyFrame() and
390  # self.sky.solveScales() in runDataRef().
391  cacheSky = []
392  measScales = []
393  for cacheExp, skyCalib in zip(cacheExposures, skyCalibs):
394  skyExp = self.sky.exposureToBackground(skyCalib)
395  cacheSky.append(skyExp)
396  scale = self.sky.measureScale(cacheExp.getMaskedImage(), skyExp)
397  measScales.append(scale)
398 
399  scale = self.sky.solveScales(measScales)
400  self.log.info("Sky frame scale: %s" % (scale, ))
401 
402  # Subtract sky frame, as in self.subtractSkyFrame(), with
403  # appropriate scale from the "cache".
404  exposures = []
405  newBgList = []
406  for cacheExp, nodeSky, nodeBgList in zip(cacheExposures, cacheSky, cacheBgList):
407  self.sky.subtractSkyFrame(cacheExp.getMaskedImage(), nodeSky, scale, nodeBgList)
408  exposures.append(afwMath.binImage(cacheExp.getMaskedImage(), self.config.binning))
409 
410  if self.config.doBgModel2:
411  # As above, generate a focal plane background model and
412  # update the cache models.
413  exposures, newBgList, cacheBgModel = self.focalPlaneBackgroundRun(
414  camera, cacheExposures, idList, self.config.bgModel2
415  )
416  for cacheBg, newBg in zip(cacheBgList, newBgList):
417  cacheBg.append(newBg)
418 
419  # Generate camera-level image of calexp and return it along
420  # with the list of sky corrected background models.
421  image = makeCameraImage(camera, zip(idList, exposures))
422 
423  return pipeBase.Struct(
424  calExpCamera=image,
425  skyCorr=cacheBgList,
426  )
427 
428  def loadImage(self, cache, dataId):
429  """Load original image and restore the sky
430 
431  This method runs on the slave nodes.
432 
433  Parameters
434  ----------
435  cache : `lsst.pipe.base.Struct`
436  Process pool cache.
437  dataId : `dict`
438  Data identifier.
439 
440  Returns
441  -------
442  exposure : `lsst.afw.image.Exposure`
443  Resultant exposure.
444  """
445  cache.dataId = dataId
446  cache.exposure = cache.butler.get(self.config.calexpType, dataId, immediate=True).clone()
447  bgOld = cache.butler.get("calexpBackground", dataId, immediate=True)
448  image = cache.exposure.getMaskedImage()
449 
450  # We're removing the old background, so change the sense of all its components
451  for bgData in bgOld:
452  statsImage = bgData[0].getStatsImage()
453  statsImage *= -1
454 
455  image -= bgOld.getImage()
456  cache.bgList = afwMath.BackgroundList()
457  for bgData in bgOld:
458  cache.bgList.append(bgData)
459 
460  if self.config.doMaskObjects:
461  self.maskObjects.findObjects(cache.exposure)
462 
463  return self.collect(cache)
464 
465  def loadImageRun(self, calExp, calExpBkg):
466  """Serial implementation of self.loadImage() for Gen3.
467 
468  Load and restore background to calExp and calExpBkg.
469 
470  Parameters
471  ----------
472  calExp : `lsst.afw.image.Exposure`
473  Detector level calExp image to process.
474  calExpBkg : `lsst.afw.math.BackgroundList`
475  Detector level background list associated with the calExp.
476 
477  Returns
478  -------
479  calExp : `lsst.afw.image.Exposure`
480  Background restored calExp.
481  bgList : `lsst.afw.math.BackgroundList`
482  New background list containing the restoration background.
483  """
484  image = calExp.getMaskedImage()
485 
486  for bgOld in calExpBkg:
487  statsImage = bgOld[0].getStatsImage()
488  statsImage *= -1
489 
490  image -= calExpBkg.getImage()
491  bgList = afwMath.BackgroundList()
492  for bgData in calExpBkg:
493  bgList.append(bgData)
494 
495  if self.config.doMaskObjects:
496  self.maskObjects.findObjects(calExp)
497 
498  return (calExp, bgList)
499 
500  def measureSkyFrame(self, cache, dataId):
501  """Measure scale for sky frame
502 
503  This method runs on the slave nodes.
504 
505  Parameters
506  ----------
507  cache : `lsst.pipe.base.Struct`
508  Process pool cache.
509  dataId : `dict`
510  Data identifier.
511 
512  Returns
513  -------
514  scale : `float`
515  Scale for sky frame.
516  """
517  assert cache.dataId == dataId
518  cache.sky = self.sky.getSkyData(cache.butler, dataId)
519  scale = self.sky.measureScale(cache.exposure.getMaskedImage(), cache.sky)
520  return scale
521 
522  def subtractSkyFrame(self, cache, dataId, scale):
523  """Subtract sky frame
524 
525  This method runs on the slave nodes.
526 
527  Parameters
528  ----------
529  cache : `lsst.pipe.base.Struct`
530  Process pool cache.
531  dataId : `dict`
532  Data identifier.
533  scale : `float`
534  Scale for sky frame.
535 
536  Returns
537  -------
538  exposure : `lsst.afw.image.Exposure`
539  Resultant exposure.
540  """
541  assert cache.dataId == dataId
542  self.sky.subtractSkyFrame(cache.exposure.getMaskedImage(), cache.sky, scale, cache.bgList)
543  return self.collect(cache)
544 
545  def accumulateModel(self, cache, data):
546  """Fit background model for CCD
547 
548  This method runs on the slave nodes.
549 
550  Parameters
551  ----------
552  cache : `lsst.pipe.base.Struct`
553  Process pool cache.
554  data : `lsst.pipe.base.Struct`
555  Data identifier, with `dataId` (data identifier) and `bgModel`
556  (background model) elements.
557 
558  Returns
559  -------
560  bgModel : `lsst.pipe.drivers.background.FocalPlaneBackground`
561  Background model.
562  """
563  assert cache.dataId == data.dataId
564  data.bgModel.addCcd(cache.exposure)
565  return data.bgModel
566 
567  def subtractModel(self, cache, dataId, bgModel):
568  """Subtract background model
569 
570  This method runs on the slave nodes.
571 
572  Parameters
573  ----------
574  cache : `lsst.pipe.base.Struct`
575  Process pool cache.
576  dataId : `dict`
577  Data identifier.
578  bgModel : `lsst.pipe.drivers.background.FocalPlaneBackround`
579  Background model.
580 
581  Returns
582  -------
583  exposure : `lsst.afw.image.Exposure`
584  Resultant exposure.
585  """
586  assert cache.dataId == dataId
587  exposure = cache.exposure
588  image = exposure.getMaskedImage()
589  detector = exposure.getDetector()
590  bbox = image.getBBox()
591  cache.bgModel = bgModel.toCcdBackground(detector, bbox)
592  image -= cache.bgModel.getImage()
593  cache.bgList.append(cache.bgModel[0])
594  return self.collect(cache)
595 
596  def subtractModelRun(self, exposure, bgModel):
597  """Serial implementation of self.subtractModel() for Gen3.
598 
599  Load and restore background to calExp and calExpBkg.
600 
601  Parameters
602  ----------
603  exposure : `lsst.afw.image.Exposure`
604  Exposure to subtract the background model from.
605  bgModel : `lsst.pipe.drivers.background.FocalPlaneBackground`
606  Full camera level background model.
607 
608  Returns
609  -------
610  exposure : `lsst.afw.image.Exposure`
611  Background subtracted input exposure.
612  bgModelCcd : `lsst.afw.math.BackgroundList`
613  Detector level realization of the full background model.
614  bgModelMaskedImage : `lsst.afw.image.MaskedImage`
615  Background model from the bgModelCcd realization.
616  """
617  image = exposure.getMaskedImage()
618  detector = exposure.getDetector()
619  bbox = image.getBBox()
620  bgModelCcd = bgModel.toCcdBackground(detector, bbox)
621  image -= bgModelCcd.getImage()
622 
623  return (exposure, bgModelCcd, bgModelCcd[0])
624 
625  def realiseModel(self, cache, dataId, bgModel):
626  """Generate an image of the background model for visualisation
627 
628  Useful for debugging.
629 
630  Parameters
631  ----------
632  cache : `lsst.pipe.base.Struct`
633  Process pool cache.
634  dataId : `dict`
635  Data identifier.
636  bgModel : `lsst.pipe.drivers.background.FocalPlaneBackround`
637  Background model.
638 
639  Returns
640  -------
641  detId : `int`
642  Detector identifier.
643  image : `lsst.afw.image.MaskedImage`
644  Binned background model image.
645  """
646  assert cache.dataId == dataId
647  exposure = cache.exposure
648  detector = exposure.getDetector()
649  bbox = exposure.getMaskedImage().getBBox()
650  image = bgModel.toCcdBackground(detector, bbox).getImage()
651  return self.collectBinnedImage(exposure, image)
652 
653  def collectBinnedImage(self, exposure, image):
654  """Return the binned image required for visualization
655 
656  This method just helps to cut down on boilerplate.
657 
658  Parameters
659  ----------
660  image : `lsst.afw.image.MaskedImage`
661  Image to go into visualisation.
662 
663  Returns
664  -------
665  detId : `int`
666  Detector identifier.
667  image : `lsst.afw.image.MaskedImage`
668  Binned image.
669  """
670  return (exposure.getDetector().getId(), afwMath.binImage(image, self.config.binning))
671 
672  def collect(self, cache):
673  """Collect exposure for potential visualisation
674 
675  This method runs on the slave nodes.
676 
677  Parameters
678  ----------
679  cache : `lsst.pipe.base.Struct`
680  Process pool cache.
681 
682  Returns
683  -------
684  detId : `int`
685  Detector identifier.
686  image : `lsst.afw.image.MaskedImage`
687  Binned image.
688  """
689  return self.collectBinnedImage(cache.exposure, cache.exposure.maskedImage)
690 
691  def collectOriginal(self, cache, dataId):
692  """Collect original image for visualisation
693 
694  This method runs on the slave nodes.
695 
696  Parameters
697  ----------
698  cache : `lsst.pipe.base.Struct`
699  Process pool cache.
700  dataId : `dict`
701  Data identifier.
702 
703  Returns
704  -------
705  detId : `int`
706  Detector identifier.
707  image : `lsst.afw.image.MaskedImage`
708  Binned image.
709  """
710  exposure = cache.butler.get("calexp", dataId, immediate=True)
711  return self.collectBinnedImage(exposure, exposure.maskedImage)
712 
713  def collectSky(self, cache, dataId):
714  """Collect original image for visualisation
715 
716  This method runs on the slave nodes.
717 
718  Parameters
719  ----------
720  cache : `lsst.pipe.base.Struct`
721  Process pool cache.
722  dataId : `dict`
723  Data identifier.
724 
725  Returns
726  -------
727  detId : `int`
728  Detector identifier.
729  image : `lsst.afw.image.MaskedImage`
730  Binned image.
731  """
732  return self.collectBinnedImage(cache.exposure, cache.sky.getImage())
733 
734  def collectMask(self, cache, dataId):
735  """Collect mask for visualisation
736 
737  This method runs on the slave nodes.
738 
739  Parameters
740  ----------
741  cache : `lsst.pipe.base.Struct`
742  Process pool cache.
743  dataId : `dict`
744  Data identifier.
745 
746  Returns
747  -------
748  detId : `int`
749  Detector identifier.
750  image : `lsst.afw.image.Image`
751  Binned image.
752  """
753  # Convert Mask to floating-point image, because that's what's required for focal plane construction
754  image = afwImage.ImageF(cache.exposure.maskedImage.getBBox())
755  image.array[:] = cache.exposure.maskedImage.mask.array
756  return self.collectBinnedImage(cache.exposure, image)
757 
758  def write(self, cache, dataId):
759  """Write resultant background list
760 
761  This method runs on the slave nodes.
762 
763  Parameters
764  ----------
765  cache : `lsst.pipe.base.Struct`
766  Process pool cache.
767  dataId : `dict`
768  Data identifier.
769  """
770  cache.butler.put(cache.bgList, "skyCorr", dataId)
771 
772  def _getMetadataName(self):
773  """There's no metadata to write out"""
774  return None
lsst::afw::image
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.runDataRef
def runDataRef(self, expRef)
Definition: skyCorrection.py:178
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.loadImageRun
def loadImageRun(self, calExp, calExpBkg)
Definition: skyCorrection.py:465
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.runQuantum
def runQuantum(self, butlerQC, inputRefs, outputRefs)
Definition: skyCorrection.py:138
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.subtractModelRun
def subtractModelRun(self, exposure, bgModel)
Definition: skyCorrection.py:596
lsst.pipe.drivers.background
Definition: background.py:1
lsst.pipe.drivers.skyCorrection.makeCameraImage
def makeCameraImage(camera, exposures, filename=None, binning=8)
Definition: skyCorrection.py:39
lsst.pipe.drivers.skyCorrection.SkyCorrectionConfig.setDefaults
def setDefaults(self)
Definition: skyCorrection.py:124
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.loadImage
def loadImage(self, cache, dataId)
Definition: skyCorrection.py:428
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.collectOriginal
def collectOriginal(self, cache, dataId)
Definition: skyCorrection.py:691
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.accumulateModel
def accumulateModel(self, cache, data)
Definition: skyCorrection.py:545
lsst::ctrl::pool::parallel
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.batchWallTime
def batchWallTime(cls, time, parsedCmd, numCores)
Definition: skyCorrection.py:160
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.collectBinnedImage
def collectBinnedImage(self, exposure, image)
Definition: skyCorrection.py:653
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.run
def run(self, calExpArray, calBkgArray, skyCalibs, camera)
Definition: skyCorrection.py:322
lsst.pipe.drivers.visualizeVisit
Definition: visualizeVisit.py:1
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.__init__
def __init__(self, *args, **kwargs)
Definition: skyCorrection.py:144
lsst::ctrl::pool::parallel::BatchCmdLineTask::logOperation
def logOperation(self, operation, catch=False, trace=True)
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.measureSkyFrame
def measureSkyFrame(self, cache, dataId)
Definition: skyCorrection.py:500
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.subtractSkyFrame
def subtractSkyFrame(self, cache, dataId, scale)
Definition: skyCorrection.py:522
lsst.pipe.drivers.skyCorrection.SkyCorrectionConfig.bgModel2
bgModel2
Definition: skyCorrection.py:113
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.focalPlaneBackgroundRun
def focalPlaneBackgroundRun(self, camera, cacheExposures, idList, config)
Definition: skyCorrection.py:274
lsst::ctrl::pool::pool
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.collectMask
def collectMask(self, cache, dataId)
Definition: skyCorrection.py:734
lsst::ctrl::pool::pool::Pool
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.collectSky
def collectSky(self, cache, dataId)
Definition: skyCorrection.py:713
lsst::ctrl::pool::parallel::BatchPoolTask
lsst::afw::math
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.subtractModel
def subtractModel(self, cache, dataId, bgModel)
Definition: skyCorrection.py:567
lsst.pipe.drivers.skyCorrection.SkyCorrectionConnections
Definition: skyCorrection.py:59
lsst.pipe::base
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.realiseModel
def realiseModel(self, cache, dataId, bgModel)
Definition: skyCorrection.py:625
lsst.pipe.drivers.skyCorrection.SkyCorrectionConfig
Definition: skyCorrection.py:110
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask
Definition: skyCorrection.py:133
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.focalPlaneBackground
def focalPlaneBackground(self, camera, pool, dataIdList, config)
Definition: skyCorrection.py:245
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.collect
def collect(self, cache)
Definition: skyCorrection.py:672
lsst.pipe.drivers.skyCorrection.SkyCorrectionTask.write
def write(self, cache, dataId)
Definition: skyCorrection.py:758
lsst.pipe::base::connectionTypes