lsst.afw  22.0.1-29-g184b6e44e+8b185d4e2d
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 (auto & rgnIter : regionRow) {
136  rgnIter->_moveUp(isFirst, height);
137  isFirst = false;
138  }
139 
140  } else {
141  ImagePtr blImagePtr = getImage(BOTTOM_LEFT);
142  ImagePtr brImagePtr;
143  ImagePtr tlImagePtr;
144  ImagePtr const trImageNullPtr;
145 
146  lsst::geom::Point2I blCorner = lsst::geom::Point2I(this->_bbox.getMinX(), startY);
147 
148  int remWidth = this->_bbox.getWidth();
149  int remXDiv = regionRow.getNX();
150  for (auto & rgnIter : regionRow) {
151  int width = _computeNextSubregionLength(remWidth, remXDiv);
152  --remXDiv;
153  remWidth -= width;
154 
156  _kernelPtr, lsst::geom::Box2I(blCorner, lsst::geom::Extent2I(width, height)), _xy0,
157  _doNormalize, blImagePtr, brImagePtr, tlImagePtr, trImageNullPtr));
158  rgnIter = regionPtr;
159 
160  if (!tlImagePtr) {
161  regionPtr->getImage(TOP_LEFT);
162  }
163 
164  blCorner += lsst::geom::Extent2I(width, 0);
165  blImagePtr = regionPtr->getImage(BOTTOM_RIGHT);
166  tlImagePtr = regionPtr->getImage(TOP_RIGHT);
167  }
168  }
169  return true;
170 }
171 
172 void KernelImagesForRegion::_computeImage(Location location) const {
173  ImagePtr imagePtr = _imagePtrList[location];
174  if (!imagePtr) {
176  os << "Null imagePtr at location " << location;
178  }
179 
180  lsst::geom::Point2I pixelIndex = getPixelIndex(location);
181  _kernelPtr->computeImage(*imagePtr, _doNormalize, image::indexToPosition(pixelIndex.getX() + _xy0[0]),
182  image::indexToPosition(pixelIndex.getY() + _xy0[1]));
183 }
184 
185 std::vector<int> KernelImagesForRegion::_computeSubregionLengths(int length, int nDivisions) {
186  if ((nDivisions > length) || (nDivisions < 1)) {
188  os << "nDivisions = " << nDivisions << " not in range [1, " << length << " = length]";
190  }
191  std::vector<int> regionLengths;
192  int remLength = length;
193  for (int remNDiv = nDivisions; remNDiv > 0; --remNDiv) {
194  int subLength = _computeNextSubregionLength(remLength, remNDiv);
195  if (subLength < 1) {
197  os << "Bug! _computeSubregionLengths(length=" << length << ", nDivisions=" << nDivisions
198  << ") computed sublength = " << subLength << " < 0; remLength = " << remLength;
199  throw LSST_EXCEPT(pexExcept::RuntimeError, os.str());
200  }
201  regionLengths.push_back(subLength);
202  remLength -= subLength;
203  }
204  return regionLengths;
205 }
206 
207 void KernelImagesForRegion::_moveUp(bool isFirst, int newHeight) {
208  // move bbox up (this must be done before recomputing the top kernel images)
209  _bbox = lsst::geom::Box2I(lsst::geom::Point2I(_bbox.getMinX(), _bbox.getMaxY() + 1),
210  lsst::geom::Extent2I(_bbox.getWidth(), newHeight));
211 
212  // swap top and bottom image pointers
213  _imagePtrList[BOTTOM_RIGHT].swap(_imagePtrList[TOP_RIGHT]);
214  _imagePtrList[BOTTOM_LEFT].swap(_imagePtrList[TOP_LEFT]);
215 
216  // recompute top right, and if the first image also recompute top left
217  _computeImage(TOP_RIGHT);
218  if (isFirst) {
219  _computeImage(TOP_LEFT);
220  }
221 }
222 
223 int const KernelImagesForRegion::_MinInterpolationSize = 10;
224 
226  : _nx(nx), _ny(ny), _yInd(-1), _regionList(nx) {
227  if ((nx < 1) || (ny < 1)) {
229  os << "nx = " << nx << " and/or ny = " << ny << " < 1";
231  };
232 }
233 } // namespace detail
234 } // namespace math
235 } // namespace afw
236 } // namespace lsst
AmpInfoBoxKey bbox
Definition: Amplifier.cc:117
#define LSST_EXCEPT(type,...)
#define LOGL_DEBUG(logger, message...)
std::ostream * os
Definition: Schema.cc:558
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
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)