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-10805: Spatially-varying ZOGY option #66

Merged
merged 1 commit into from
Aug 28, 2017
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 10 additions & 10 deletions python/lsst/ip/diffim/imageDecorrelation.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@
import lsst.log

from .imageMapReduce import (ImageMapReduceConfig, ImageMapReduceTask,
ImageMapperSubtask)
ImageMapper)

__all__ = ("DecorrelateALKernelTask", "DecorrelateALKernelConfig",
"DecorrelateALKernelMapperSubtask", "DecorrelateALKernelMapReduceConfig",
"DecorrelateALKernelMapper", "DecorrelateALKernelMapReduceConfig",
"DecorrelateALKernelSpatialConfig", "DecorrelateALKernelSpatialTask")


Expand Down Expand Up @@ -349,8 +349,8 @@ def _doConvolve(exposure, kernel):
return outExp, kern


class DecorrelateALKernelMapperSubtask(DecorrelateALKernelTask, ImageMapperSubtask):
"""Task to be used as an ImageMapperSubtask for performing
class DecorrelateALKernelMapper(DecorrelateALKernelTask, ImageMapper):
"""Task to be used as an ImageMapper for performing
A&L decorrelation on subimages on a grid across a A&L difference image.

This task subclasses DecorrelateALKernelTask in order to implement
Expand Down Expand Up @@ -411,7 +411,7 @@ def run(self, subExposure, expandedSubExposure, fullBBox,
Notes
-----
This `run` method accepts parameters identical to those of
`ImageMapperSubtask.run`, since it is called from the
`ImageMapper.run`, since it is called from the
`ImageMapperTask`. See that class for more information.
"""
templateExposure = template # input template
Expand Down Expand Up @@ -439,11 +439,11 @@ def run(self, subExposure, expandedSubExposure, fullBBox,

class DecorrelateALKernelMapReduceConfig(ImageMapReduceConfig):
"""Configuration parameters for the ImageMapReduceTask to direct it to use
DecorrelateALKernelMapperSubtask as its mapperSubtask for A&L decorrelation.
DecorrelateALKernelMapper as its mapper for A&L decorrelation.
"""
mapperSubtask = pexConfig.ConfigurableField(
doc='A&L decorrelation subtask to run on each sub-image',
target=DecorrelateALKernelMapperSubtask
mapper = pexConfig.ConfigurableField(
doc='A&L decorrelation task to run on each sub-image',
target=DecorrelateALKernelMapper
)


Expand Down Expand Up @@ -479,7 +479,7 @@ def setDefaults(self):
self.decorrelateMapReduceConfig.gridStepX = self.decorrelateMapReduceConfig.gridStepY = 19
self.decorrelateMapReduceConfig.cellSizeX = self.decorrelateMapReduceConfig.cellSizeY = 20
self.decorrelateMapReduceConfig.borderSizeX = self.decorrelateMapReduceConfig.borderSizeY = 6
self.decorrelateMapReduceConfig.reducerSubtask.reduceOperation = 'average'
self.decorrelateMapReduceConfig.reducer.reduceOperation = 'average'


class DecorrelateALKernelSpatialTask(pipeBase.Task):
Expand Down
110 changes: 55 additions & 55 deletions python/lsst/ip/diffim/imageMapReduce.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,76 +35,76 @@
import lsst.pipe.base as pipeBase

__all__ = ("ImageMapReduceTask", "ImageMapReduceConfig",
"ImageMapperSubtask", "ImageMapperSubtaskConfig",
"ImageReducerSubtask", "ImageReducerSubtaskConfig")
"ImageMapper", "ImageMapperConfig",
"ImageReducer", "ImageReducerConfig")


"""Tasks for processing an exposure via processing on
multiple sub-exposures and then collecting the results
to either re-stitch the sub-exposures back into a new
exposure, or return summary results for each sub-exposure.

This essentially provides a framework for arbitrary mapper-reducer
This provides a framework for arbitrary mapper-reducer
operations on an exposure by implementing simple operations in
subTasks. It currently is not parallelized, although it could be in
the future. It does enable operations such as spatially-mapped
processing on a grid across an image, processing regions surrounding
centroids (such as for PSF processing), etc.

It is implemented as primary Task, `ImageMapReduceTask` which contains
two subtasks, `ImageMapperSubtask` and `ImageReducerSubtask`.
two subtasks, `ImageMapper` and `ImageReducer`.
`ImageMapReduceTask` configures the centroids and sub-exposure
dimensions to be processed, and then calls the `run` methods of the
`ImageMapperSubtask` and `ImageReducerSubtask` on those sub-exposures.
`ImageMapper` and `ImageReducer` on those sub-exposures.
`ImageMapReduceTask` may be configured with a list of sub-exposure
centroids (`config.cellCentroidsX` and `config.cellCentroidsY`) and a
single pair of bounding boxes defining their dimensions, or a set of
parameters defining a regular grid of centroids (`config.gridStepX`
and `config.gridStepY`).

`ImageMapperSubtask` is an abstract class and must be subclassed with
`ImageMapper` is an abstract class and must be subclassed with
an implemented `run` method to provide the desired operation for
processing individual sub-exposures. It is called from
`ImageMapReduceTask.run`, and may return a new, processed sub-exposure
which is to be "stitched" back into a new resulting larger exposure
(depending on the configured `ImageMapReduceTask.mapperSubtask`);
(depending on the configured `ImageMapReduceTask.mapper`);
otherwise if it does not return an lsst.afw.image.Exposure, then the results are
passed back directly to the caller.

`ImageReducerSubtask` will either stitch the `mapperResults` list of
results generated by the `ImageMapperSubtask` together into a new
`ImageReducer` will either stitch the `mapperResults` list of
results generated by the `ImageMapper` together into a new
Exposure (by default) or pass it through to the
caller. `ImageReducerSubtask` has an implemented `run` method for
caller. `ImageReducer` has an implemented `run` method for
basic reducing operations (`reduceOperation`) such as `average` (which
will average all overlapping pixels from sub-exposures produced by the
`ImageMapperSubtask` into the new exposure). Another notable
`ImageMapper` into the new exposure). Another notable
implemented `reduceOperation` is 'none', in which case the
`mapperResults` list is simply returned directly.
"""

class ImageMapperSubtaskConfig(pexConfig.Config):
"""Configuration parameters for ImageMapperSubtask
class ImageMapperConfig(pexConfig.Config):
"""Configuration parameters for ImageMapper
"""
pass


class ImageMapperSubtask(with_metaclass(abc.ABCMeta, pipeBase.Task)):
class ImageMapper(with_metaclass(abc.ABCMeta, pipeBase.Task)):
"""Abstract base class for any task that is to be
used as `ImageMapReduceConfig.mapperSubtask`.
used as `ImageMapReduceConfig.mapper`.

An `ImageMapperSubtask` is responsible for processing individual
An `ImageMapper` is responsible for processing individual
sub-exposures in its `run` method, which is called from
`ImageMapReduceTask.run`. `run` may return a processed new
sub-exposure which can be be "stitched" back into a new resulting
larger exposure (depending on the configured
`ImageReducerSubtask`); otherwise if it does not return an
`ImageReducer`); otherwise if it does not return an
lsst.afw.image.Exposure, then the
`ImageReducerSubtask.config.reducerSubtask.reduceOperation`
`ImageReducer.config.reducer.reduceOperation`
should be set to 'none' and the result will be propagated
as-is.
"""
ConfigClass = ImageMapperSubtaskConfig
_DefaultName = "ip_diffim_ImageMapperSubtask"
ConfigClass = ImageMapperConfig
_DefaultName = "ip_diffim_ImageMapper"

@abc.abstractmethod
def run(self, subExposure, expandedSubExposure, fullBBox, **kwargs):
Expand All @@ -120,9 +120,9 @@ def run(self, subExposure, expandedSubExposure, fullBBox, **kwargs):

This method may return a new, processed sub-exposure which can
be be "stitched" back into a new resulting larger exposure
(depending on the paired, configured `ImageReducerSubtask`);
(depending on the paired, configured `ImageReducer`);
otherwise if it does not return an lsst.afw.image.Exposure, then the
`ImageReducerSubtask.config.mapperSubtask.reduceOperation`
`ImageReducer.config.mapper.reduceOperation`
should be set to 'none' and the result will be propagated
as-is.

Expand All @@ -149,8 +149,8 @@ def run(self, subExposure, expandedSubExposure, fullBBox, **kwargs):
return pipeBase.Struct(subExposure=subExposure)


class ImageReducerSubtaskConfig(pexConfig.Config):
"""Configuration parameters for the ImageReducerSubtask
class ImageReducerConfig(pexConfig.Config):
"""Configuration parameters for the ImageReducer
"""
reduceOperation = pexConfig.ChoiceField(
dtype=str,
Expand All @@ -177,18 +177,18 @@ class ImageReducerSubtaskConfig(pexConfig.Config):
)


class ImageReducerSubtask(pipeBase.Task):
class ImageReducer(pipeBase.Task):
"""Base class for any 'reduce' task that is to be
used as `ImageMapReduceConfig.reducerSubtask`.
used as `ImageMapReduceConfig.reducer`.

Basic reduce operations are provided by the `run` method
of this class, to be selected by its config.
"""
ConfigClass = ImageReducerSubtaskConfig
_DefaultName = "ip_diffim_ImageReducerSubtask"
ConfigClass = ImageReducerConfig
_DefaultName = "ip_diffim_ImageReducer"

def run(self, mapperResults, exposure, **kwargs):
"""Reduce a list of items produced by `ImageMapperSubtask`.
"""Reduce a list of items produced by `ImageMapper`.

Either stitch the passed `mapperResults` list
together into a new Exposure (default) or pass it through
Expand All @@ -204,11 +204,11 @@ def run(self, mapperResults, exposure, **kwargs):
Parameters
----------
mapperResults : list
list of `pipeBase.Struct` returned by `ImageMapperSubtask.run`.
list of `pipeBase.Struct` returned by `ImageMapper.run`.
exposure : lsst.afw.image.Exposure
the original exposure which is cloned to use as the
basis for the resulting exposure (if
self.config.mapperSubtask.reduceOperation is not 'none')
self.config.mapper.reduceOperation is not 'none')
kwargs :
additional keyword arguments propagated from
`ImageMapReduceTask.run`.
Expand All @@ -229,7 +229,7 @@ def run(self, mapperResults, exposure, **kwargs):
------------
1. To be done: correct handling of masks (nearly there)
2. This logic currently makes *two* copies of the original exposure
(one here and one in `mapperSubtask.run()`). Possibly of concern
(one here and one in `mapper.run()`). Possibly of concern
for large images on memory-constrained systems.
"""
# No-op; simply pass mapperResults directly to ImageMapReduceTask.run
Expand Down Expand Up @@ -329,7 +329,7 @@ def _constructPsf(self, mapperResults, exposure):
Parameters
----------
mapperResults : list
list of `pipeBase.Struct` returned by `ImageMapperSubtask.run`.
list of `pipeBase.Struct` returned by `ImageMapper.run`.
For this to work, each element of `mapperResults` must contain
a `subExposure` element, from which the component Psfs are
extracted (thus the reducerTask cannot have
Expand Down Expand Up @@ -375,14 +375,14 @@ def _constructPsf(self, mapperResults, exposure):
class ImageMapReduceConfig(pexConfig.Config):
"""Configuration parameters for the ImageMapReduceTask
"""
mapperSubtask = pexConfig.ConfigurableField(
doc="Subtask to run on each subimage",
target=ImageMapperSubtask,
mapper = pexConfig.ConfigurableField(
doc="Task to run on each subimage",
target=ImageMapper,
)

reducerSubtask = pexConfig.ConfigurableField(
doc="Subtask to combine results of mapperSubTask",
target=ImageReducerSubtask,
reducer = pexConfig.ConfigurableField(
doc="Task to combine results of mapper task",
target=ImageReducer,
)

# Separate cellCentroidsX and cellCentroidsY since pexConfig.ListField accepts limited dtypes
Expand Down Expand Up @@ -527,17 +527,17 @@ def __init__(self, *args, **kwargs):
pipeBase.Task.__init__(self, *args, **kwargs)

self.boxes0 = self.boxes1 = None
self.makeSubtask("mapperSubtask")
self.makeSubtask("reducerSubtask")
self.makeSubtask("mapper")
self.makeSubtask("reducer")

@pipeBase.timeMethod
def run(self, exposure, **kwargs):
"""Perform a map-reduce operation on the given exposure.

Split the exposure into sub-expposures on a grid (parameters
given by `ImageMapReduceConfig`) and perform
`config.mapperSubtask.run()` on each. Reduce the resulting
sub-exposures by running `config.reducerSubtask.run()`.
`config.mapper.run()` on each. Reduce the resulting
sub-exposures by running `config.reducer.run()`.

Parameters
----------
Expand All @@ -549,21 +549,21 @@ def run(self, exposure, **kwargs):

Returns
-------
output of `reducerSubtask.run()`
output of `reducer.run()`

"""
self.log.info("Mapper sub-task: %s", self.mapperSubtask._DefaultName)
self.log.info("Mapper sub-task: %s", self.mapper._DefaultName)
mapperResults = self._runMapper(exposure, **kwargs)
self.log.info("Reducer sub-task: %s", self.reducerSubtask._DefaultName)
self.log.info("Reducer sub-task: %s", self.reducer._DefaultName)
result = self._reduceImage(mapperResults, exposure, **kwargs)
return result

def _runMapper(self, exposure, doClone=False, **kwargs):
"""Perform `mapperSubtask.run` on each sub-exposure
"""Perform `mapper.run` on each sub-exposure

Perform `mapperSubtask.run` on each sub-exposure across a
Perform `mapper.run` on each sub-exposure across a
grid on `exposure` generated by `_generateGrid`. Also pass to
`mapperSubtask.run` an 'expanded sub-exposure' containing the
`mapper.run` an 'expanded sub-exposure' containing the
same region as the sub-exposure but with an expanded bounding box.

Parameters
Expand All @@ -575,11 +575,11 @@ def _runMapper(self, exposure, doClone=False, **kwargs):
in that case, the sub-exps do not have to be considered as read-only
kwargs :
additional keyword arguments to be passed to
`mapperSubtask.run` and `self._generateGrid`, including `forceEvenSized`.
`mapper.run` and `self._generateGrid`, including `forceEvenSized`.

Returns
-------
a list of `pipeBase.Struct`s as returned by `mapperSubtask.run`.
a list of `pipeBase.Struct`s as returned by `mapper.run`.
"""
if self.boxes0 is None:
self._generateGrid(exposure, **kwargs) # possibly pass `forceEvenSized`
Expand All @@ -594,7 +594,7 @@ def _runMapper(self, exposure, doClone=False, **kwargs):
if doClone:
subExp = subExp.clone()
expandedSubExp = expandedSubExp.clone()
result = self.mapperSubtask.run(subExp, expandedSubExp, exposure.getBBox(), **kwargs)
result = self.mapper.run(subExp, expandedSubExp, exposure.getBBox(), **kwargs)
if self.config.returnSubImages:
toAdd = pipeBase.Struct(inputSubExposure=subExp,
inputExpandedSubExposure=expandedSubExp)
Expand All @@ -613,17 +613,17 @@ def _reduceImage(self, mapperResults, exposure, **kwargs):
----------
mapperResults : list
list of `pipeBase.Struct`, each of which was produced by
`config.mapperSubtask`
`config.mapper`
exposure : lsst.afw.image.Exposure
the original exposure
**kwargs :
additional keyword arguments

Returns
-------
Output of `reducerSubtask.run` which is a `pipeBase.Struct`.
Output of `reducer.run` which is a `pipeBase.Struct`.
"""
result = self.reducerSubtask.run(mapperResults, exposure, **kwargs)
result = self.reducer.run(mapperResults, exposure, **kwargs)
return result

def _generateGrid(self, exposure, forceEvenSized=False, **kwargs):
Expand Down
7 changes: 7 additions & 0 deletions python/lsst/ip/diffim/imagePsfMatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -788,3 +788,10 @@ def _validateWcs(self, templateExposure, scienceExposure):
(templateExposure.getDimensions() != scienceExposure.getDimensions())):
return False
return True


subtractAlgorithmRegistry = pexConfig.makeRegistry(
doc="A registry of subtraction algorithms for use as a subtask in imageDifference",
)

subtractAlgorithmRegistry.register('al', ImagePsfMatchTask)