lsst.afw  22.0.0-22-gf1d71818e+0d6c1a9e28
KernelImagesForRegion.cc
Go to the documentation of this file.
1 // -*- LSST-C++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
25 /*
26  * Definition of KernelImagesForRegion class declared in detail/ConvolveImage.h
27  */
28 #include <algorithm>
29 #include <cmath>
30 #include <iostream>
31 #include <sstream>
32 #include <vector>
33 
34 #include "boost/assign/list_of.hpp"
35 
36 #include "lsst/pex/exceptions.h"
37 #include "lsst/log/Log.h"
38 #include "lsst/geom.h"
41 
43 
44 namespace lsst {
45 namespace afw {
46 namespace math {
47 namespace detail {
48 
50  lsst::geom::Point2I const &xy0, bool doNormalize)
51  : _kernelPtr(kernelPtr), _bbox(bbox), _xy0(xy0), _doNormalize(doNormalize), _imagePtrList(4) {
52  if (!_kernelPtr) {
53  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "kernelPtr is null");
54  }
55  LOGL_DEBUG("TRACE5.afw.math.convolve.KernelImagesForRegion",
56  "KernelImagesForRegion(bbox(minimum=(%d, %d), extent=(%d, %d)), xy0=(%d, %d), doNormalize=%d, "
57  "images...)",
58  _bbox.getMinX(), _bbox.getMinY(), _bbox.getWidth(), _bbox.getHeight(), _xy0[0], _xy0[1],
59  _doNormalize);
60 }
61 
63  lsst::geom::Point2I const &xy0, bool doNormalize,
64  ImagePtr bottomLeftImagePtr, ImagePtr bottomRightImagePtr,
65  ImagePtr topLeftImagePtr, ImagePtr topRightImagePtr)
66  : _kernelPtr(kernelPtr), _bbox(bbox), _xy0(xy0), _doNormalize(doNormalize), _imagePtrList(4) {
67  if (!_kernelPtr) {
68  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "kernelPtr is null");
69  }
70  _insertImage(BOTTOM_LEFT, bottomLeftImagePtr);
71  _insertImage(BOTTOM_RIGHT, bottomRightImagePtr);
72  _insertImage(TOP_LEFT, topLeftImagePtr);
73  _insertImage(TOP_RIGHT, topRightImagePtr);
74  LOGL_DEBUG("TRACE5.afw.math.convolve.KernelImagesForRegion",
75  "KernelImagesForRegion(bbox(minimum=(%d, %d), extent=(%d, %d)), xy0=(%d, %d), doNormalize=%d, "
76  "images...)",
77  _bbox.getMinX(), _bbox.getMinY(), _bbox.getWidth(), _bbox.getHeight(), _xy0[0], _xy0[1],
78  _doNormalize);
79 }
80 
82  if (_imagePtrList[location]) {
83  return _imagePtrList[location];
84  }
85 
86  ImagePtr imagePtr(new Image(_kernelPtr->getDimensions()));
87  _imagePtrList[location] = imagePtr;
88  _computeImage(location);
89  return imagePtr;
90 }
91 
93  switch (location) {
94  case BOTTOM_LEFT:
95  return _bbox.getMin();
96  break; // paranoia
97  case BOTTOM_RIGHT:
98  return lsst::geom::Point2I(_bbox.getMaxX() + 1, _bbox.getMinY());
99  break; // paranoia
100  case TOP_LEFT:
101  return lsst::geom::Point2I(_bbox.getMinX(), _bbox.getMaxY() + 1);
102  break; // paranoia
103  case TOP_RIGHT:
104  return lsst::geom::Point2I(_bbox.getMaxX() + 1, _bbox.getMaxY() + 1);
105  break; // paranoia
106  default: {
108  os << "Bug: unhandled location = " << location;
110  }
111  }
112 }
113 
115  if (regionRow.isLastRow()) {
116  return false;
117  }
118 
119  bool hasData = regionRow.hasData();
120  int startY;
121  if (hasData) {
122  startY = regionRow.front()->getBBox().getMaxY() + 1;
123  } else {
124  startY = this->_bbox.getMinY();
125  }
126 
127  int yInd = regionRow.incrYInd();
128  int remHeight = 1 + this->_bbox.getMaxY() - startY;
129  int remYDiv = regionRow.getNY() - yInd;
130  int height = _computeNextSubregionLength(remHeight, remYDiv);
131 
132  if (hasData) {
133  // Move each region up one segment
134  bool isFirst = true;
135  for (RowOfKernelImagesForRegion::Iterator rgnIter = regionRow.begin(), rgnEnd = regionRow.end();
136  rgnIter != rgnEnd; ++rgnIter) {
137  (*rgnIter)->_moveUp(isFirst, height);
138  isFirst = false;
139  }
140 
141  } else {
142  ImagePtr blImagePtr = getImage(BOTTOM_LEFT);
143  ImagePtr brImagePtr;
144  ImagePtr tlImagePtr;
145  ImagePtr const trImageNullPtr;
146 
147  lsst::geom::Point2I blCorner = lsst::geom::Point2I(this->_bbox.getMinX(), startY);
148 
149  int remWidth = this->_bbox.getWidth();
150  int remXDiv = regionRow.getNX();
151  for (RowOfKernelImagesForRegion::Iterator rgnIter = regionRow.begin(), rgnEnd = regionRow.end();
152  rgnIter != rgnEnd; ++rgnIter) {
153  int width = _computeNextSubregionLength(remWidth, remXDiv);
154  --remXDiv;
155  remWidth -= width;
156 
158  _kernelPtr, lsst::geom::Box2I(blCorner, lsst::geom::Extent2I(width, height)), _xy0,
159  _doNormalize, blImagePtr, brImagePtr, tlImagePtr, trImageNullPtr));
160  *rgnIter = regionPtr;
161 
162  if (!tlImagePtr) {
163  regionPtr->getImage(TOP_LEFT);
164  }
165 
166  blCorner += lsst::geom::Extent2I(width, 0);
167  blImagePtr = regionPtr->getImage(BOTTOM_RIGHT);
168  tlImagePtr = regionPtr->getImage(TOP_RIGHT);
169  }
170  }
171  return true;
172 }
173 
174 void KernelImagesForRegion::_computeImage(Location location) const {
175  ImagePtr imagePtr = _imagePtrList[location];
176  if (!imagePtr) {
178  os << "Null imagePtr at location " << location;
180  }
181 
182  lsst::geom::Point2I pixelIndex = getPixelIndex(location);
183  _kernelPtr->computeImage(*imagePtr, _doNormalize, image::indexToPosition(pixelIndex.getX() + _xy0[0]),
184  image::indexToPosition(pixelIndex.getY() + _xy0[1]));
185 }
186 
187 std::vector<int> KernelImagesForRegion::_computeSubregionLengths(int length, int nDivisions) {
188  if ((nDivisions > length) || (nDivisions < 1)) {
190  os << "nDivisions = " << nDivisions << " not in range [1, " << length << " = length]";
192  }
193  std::vector<int> regionLengths;
194  int remLength = length;
195  for (int remNDiv = nDivisions; remNDiv > 0; --remNDiv) {
196  int subLength = _computeNextSubregionLength(remLength, remNDiv);
197  if (subLength < 1) {
199  os << "Bug! _computeSubregionLengths(length=" << length << ", nDivisions=" << nDivisions
200  << ") computed sublength = " << subLength << " < 0; remLength = " << remLength;
201  throw LSST_EXCEPT(pexExcept::RuntimeError, os.str());
202  }
203  regionLengths.push_back(subLength);
204  remLength -= subLength;
205  }
206  return regionLengths;
207 }
208 
209 void KernelImagesForRegion::_moveUp(bool isFirst, int newHeight) {
210  // move bbox up (this must be done before recomputing the top kernel images)
211  _bbox = lsst::geom::Box2I(lsst::geom::Point2I(_bbox.getMinX(), _bbox.getMaxY() + 1),
212  lsst::geom::Extent2I(_bbox.getWidth(), newHeight));
213 
214  // swap top and bottom image pointers
215  _imagePtrList[BOTTOM_RIGHT].swap(_imagePtrList[TOP_RIGHT]);
216  _imagePtrList[BOTTOM_LEFT].swap(_imagePtrList[TOP_LEFT]);
217 
218  // recompute top right, and if the first image also recompute top left
219  _computeImage(TOP_RIGHT);
220  if (isFirst) {
221  _computeImage(TOP_LEFT);
222  }
223 }
224 
225 int const KernelImagesForRegion::_MinInterpolationSize = 10;
226 
228  : _nx(nx), _ny(ny), _yInd(-1), _regionList(nx) {
229  if ((nx < 1) || (ny < 1)) {
231  os << "nx = " << nx << " and/or ny = " << ny << " < 1";
233  };
234 }
235 } // namespace detail
236 } // namespace math
237 } // namespace afw
238 } // namespace lsst
AmpInfoBoxKey bbox
Definition: Amplifier.cc:117
#define LSST_EXCEPT(type,...)
#define LOGL_DEBUG(logger, message...)
std::ostream * os
Definition: Schema.cc:557
lsst::geom::Extent2I const getDimensions() const
Return the Kernel's dimensions (width, height)
Definition: Kernel.h:213
double computeImage(lsst::afw::image::Image< Pixel > &image, bool doNormalize, double x=0.0, double y=0.0) const
Compute an image (pixellized representation of the kernel) in place.
Definition: Kernel.cc:85
Location
locations of various points in the region
Definition: Convolve.h:192
KernelImagesForRegion(KernelConstPtr kernelPtr, lsst::geom::Box2I const &bbox, lsst::geom::Point2I const &xy0, bool doNormalize)
Construct a KernelImagesForRegion.
bool computeNextRow(RowOfKernelImagesForRegion &regionRow) const
Compute next row of subregions.
lsst::geom::Point2I getPixelIndex(Location location) const
Compute pixel index of a given location, relative to the parent image (thus offset by bottom left cor...
ImagePtr getImage(Location location) const
Return the image and sum at the specified location.
lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > Image
Definition: Convolve.h:175
RowOfKernelImagesForRegion(int nx, int ny)
Construct a RowOfKernelImagesForRegion.
std::shared_ptr< KernelImagesForRegion > front()
Return the first region in the list.
Definition: Convolve.h:366
RegionList::const_iterator begin() const
Return the begin iterator for the list.
Definition: Convolve.h:350
RegionList::const_iterator end() const
Return the end iterator for the list.
Definition: Convolve.h:354
int getMinY() const noexcept
int getHeight() const noexcept
Point2I const getMin() const noexcept
int getMinX() const noexcept
int getWidth() const noexcept
int getMaxX() const noexcept
int getMaxY() const noexcept
def length(self)
double indexToPosition(double ind)
Convert image index to image position.
Definition: ImageUtils.h:55
Extent< int, 2 > Extent2I
Point< int, 2 > Point2I
A base class for image defects.
T push_back(T... args)