Skip to content

Commit

Permalink
Update documentation and names for clarity.
Browse files Browse the repository at this point in the history
  • Loading branch information
czwa committed Apr 9, 2020
1 parent 9d151ed commit 8c03013
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 81 deletions.
16 changes: 4 additions & 12 deletions pipelines/VisualizeVisit.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
description: Visualize full visit/focal plane with binned and mosaic images.
tasks:
bin:
class: lsst.pipe.tasks.visualizeVisit.VisBinTask
config:
binning: 8
connections.inputExp: 'calexp'
connections.outputExp: 'calexpBin'
moz:
class: lsst.pipe.tasks.visualizeVisit.VisMosaicTask
config:
binning: 8
connections.inputExps: 'calexpBin'
connections.outputData: 'calexpFP'
binning:
class: lsst.pipe.tasks.visualizeVisit.VisualizeBinExpTask
mosaic:
class: lsst.pipe.tasks.visualizeVisit.VisualizeMosaicExpTask
145 changes: 76 additions & 69 deletions python/lsst/pipe/tasks/visualizeVisit.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
import lsst.afw.cameraGeom.utils as afwUtils


__all__ = ['VisBinConfig', 'VisBinTask', 'VisMosaicConfig', 'VisMosaicTask']
__all__ = ['VisualizeBinExpConfig', 'VisualizeBinExpTask', 'VisualizeMosaicExpConfig', 'VisualizeMosaicExpTask']


class VisBinConnections(pipeBase.PipelineTaskConnections,
class VisualizeBinExpConnections(pipeBase.PipelineTaskConnections,
dimensions=("instrument", "detector")):
inputExp = cT.Input(
name="calexp",
Expand All @@ -54,14 +54,14 @@ class VisBinConnections(pipeBase.PipelineTaskConnections,
)


class VisBinConfig(pipeBase.PipelineTaskConfig,
pipelineConnections=VisBinConnections):
class VisualizeBinExpConfig(pipeBase.PipelineTaskConfig,
pipelineConnections=VisualizeBinExpConnections):
"""Configuration for focal plane visualization.
"""
binning = pexConfig.Field(
dtype=int,
default=8,
doc="Binning factor to apply.",
doc="Binning factor to apply to each input exposure.",
)
detectorKeyword = pexConfig.Field(
dtype=str,
Expand All @@ -70,12 +70,16 @@ class VisBinConfig(pipeBase.PipelineTaskConfig,
)


class VisBinTask(pipeBase.PipelineTask,
class VisualizeBinExpTask(pipeBase.PipelineTask,
pipeBase.CmdLineTask):
"""Task for focal plane visualization.
"""Bin the detectors of an exposure.
The outputs of this task should be passed to
VisualizeMosaicExpTask to be mosaicked into a full focal plane
visualization image.
"""
ConfigClass = VisBinConfig
_DefaultName = 'VisBin'
ConfigClass = VisualizeBinExpConfig
_DefaultName = 'VisualizeBinExp'

def run(self, inputExp, camera):
"""Bin input image, attach associated detector.
Expand Down Expand Up @@ -104,14 +108,17 @@ def run(self, inputExp, camera):
binned = afwMath.binImage(binned, self.config.binning)
outputExp = afwImage.makeExposure(binned)

if outputExp.getDetector() is None:
outputExp.setDetector(inputExp.getDetector())
outputExp.setInfo(inputExp.getInfo())
outputExp.setFilter(inputExp.getFilter())
outputExp.setMetadata(inputExp.getMetadata())
outputExp.setDetector(inputExp.getDetector())

return pipeBase.Struct(
outputExp=outputExp,
)


class VisMosaicConnections(pipeBase.PipelineTaskConnections,
class VisualizeMosaicExpConnections(pipeBase.PipelineTaskConnections,
dimensions=("instrument", )):
inputExps = cT.Input(
name="calexpBin",
Expand All @@ -128,30 +135,38 @@ class VisMosaicConnections(pipeBase.PipelineTaskConnections,
)

outputData = cT.Output(
name="calexpFP",
name="calexpFocalPlane",
doc="Output binned mosaicked frame.",
storageClass="ImageF",
dimensions=("instrument", ),
)


class VisMosaicConfig(pipeBase.PipelineTaskConfig,
pipelineConnections=VisMosaicConnections):
class VisualizeMosaicExpConfig(pipeBase.PipelineTaskConfig,
pipelineConnections=VisualizeMosaicExpConnections):
"""Configuration for focal plane visualization.
"""
binning = pexConfig.Field(
dtype=int,
default=8,
doc="Binning factor to apply.",
doc="Binning factor to apply to input exposures before mosaicking.",
)


class VisMosaicTask(pipeBase.PipelineTask,
class VisualizeMosaicExpTask(pipeBase.PipelineTask,
pipeBase.CmdLineTask):
"""Task to mosaic binned products.
Additional binning of the mosaic can also be performed by setting
the binning value greater than 1. The tradeoff between binning in
this task and in VisualizeBinningExpTask is that binning there
allows the work to be parallelized. However, binning entirely at
that level would result in a focal plane image that has inter-chip
gaps that are either too wide or too narrow to provide an accurate
visualization.
"""
ConfigClass = VisMosaicConfig
_DefaultName = 'VisMosaic'
ConfigClass = VisualizeMosaicExpConfig
_DefaultName = 'VisualizeMosaicExp'

def makeCameraImage(self, inputExps, camera, binning):
"""Make an image of an entire focal plane.
Expand All @@ -168,54 +183,6 @@ def makeCameraImage(self, inputExps, camera, binning):
Image mosaicked from the individual binned images for each
detector.
"""
class ImageSource:
"""Source of images for makeImageFromCamera"""
def __init__(self, exposures):
self.isTrimmed = True
self.exposures = exposures
self.background = np.nan

def getCcdImage(self, detector, imageFactory, binSize):
"""Provide image of CCD to makeImageFromCamera
Parameters
----------
detector : `int`
Detector ID to get image data for.
imageFactory : `lsst.afw.image.Image`
Type of image to construct.
binSize : `int`
Binsize to use to recompute dimensions.
Returns
-------
image : `lsst.afw.image.Image`
Appropriately rotated, binned, and transformed
image to be mosaicked.
detector : `lsst.afw.cameraGeom.Detector`
Camera detector that the returned image data
belongs to.
"""
detId = detector.getId()
if detId not in self.exposures:
dims = detector.getBBox().getDimensions()/binSize
image = imageFactory(*[int(xx) for xx in dims])
image.set(self.background)
else:
image = self.exposures[detector.getId()]
if hasattr(image, "getMaskedImage"):
image = image.getMaskedImage()
if hasattr(image, "getMask"):
mask = image.getMask()
isBad = mask.getArray() & mask.getPlaneBitMask("NO_DATA") > 0
image = image.clone()
image.getImage().getArray()[isBad] = self.background
if hasattr(image, "getImage"):
image = image.getImage()

image = afwMath.rotateImageBy90(image, detector.getOrientation().getNQuarter())
return image, detector

image = afwUtils.makeImageFromCamera(
camera,
imageSource=ImageSource(inputExps),
Expand All @@ -225,7 +192,7 @@ def getCcdImage(self, detector, imageFactory, binSize):
return image

def run(self, inputExps, camera):
"""Mosaic inputs.
"""Mosaic inputs together to create focal plane image.
Parameters
----------
Expand All @@ -242,9 +209,49 @@ def run(self, inputExps, camera):
``outputExp``
Binned version of input image. (`lsst.afw.image.Exposure`)
"""
expDict = dict((exp.getDetector().getId(), exp) for exp in inputExps)
expDict = {exp.getDetector().getId(): exp for exp in inputExps}
image = self.makeCameraImage(expDict, camera, self.config.binning)

return pipeBase.Struct(
outputData=image,
)

class ImageSource:
"""Source of images for makeImageFromCamera"""
def __init__(self, exposures):
self.exposures = exposures

def getCcdImage(self, detector, imageFactory, binSize):
"""Provide image of CCD to makeImageFromCamera
Parameters
----------
detector : `int`
Detector ID to get image data for.
imageFactory : `lsst.afw.image.Image`
Type of image to construct.
binSize : `int`
Binsize to use to recompute dimensions.
Returns
-------
image : `lsst.afw.image.Image`
Appropriately rotated, binned, and transformed
image to be mosaicked.
detector : `lsst.afw.cameraGeom.Detector`
Camera detector that the returned image data
belongs to.
"""
detId = detector.getId()
if detId not in self.exposures:
dims = detector.getBBox().getDimensions()/binSize
image = imageFactory(*[int(xx) for xx in dims])
image.set(np.nan)
else:
image = self.exposures[detector.getId()]
image = image.getImage()

# afwMath.rotateImageBy90 checks NQuarter values,
# so we don't need to here.
image = afwMath.rotateImageBy90(image, detector.getOrientation().getNQuarter())
return image, detector

0 comments on commit 8c03013

Please sign in to comment.