lsst.afw  21.0.0-44-ge87b71154+532d44eec1
warpExposure.cc
Go to the documentation of this file.
1 // -*- LSST-C++ -*- // fixed format comment for emacs
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  * Support for warping an %image to a new Wcs.
26  */
27 
28 #include <cassert>
29 #include <cmath>
30 #include <cstdint>
31 #include <limits>
32 #include <memory>
33 #include <sstream>
34 #include <string>
35 #include <vector>
36 #include <utility>
37 #include <ctime>
38 #include <regex>
39 
40 #include <memory>
41 #include "boost/pointer_cast.hpp"
42 #include "astshim.h"
43 
44 #include "lsst/log/Log.h"
45 #include "lsst/pex/exceptions.h"
46 #include "lsst/geom.h"
48 #include "lsst/afw/geom.h"
49 #include "lsst/afw/math/Kernel.h"
52 
54 
55 using std::swap;
56 
57 namespace lsst {
58 namespace afw {
59 namespace math {
60 
61 //
62 // A helper function for the warping kernels which provides error-checking:
63 // the warping kernels are designed to work in two cases
64 // 0 < x < 1 and ctrX=(size-1)/2
65 // -1 < x < 0 and ctrX=(size+1)/2
66 // (and analogously for y). Note that to get the second case, Kernel::setCtr(1, y) must be
67 // called before calling Kernel::setKernelParameter(). [see afw::math::offsetImage() for
68 // an example]
69 //
70 // FIXME eventually the 3 warping kernels will inherit from a common base class WarpingKernel
71 // and this routine can be eliminated by putting the code in WarpingKernel::setKernelParameter()
72 //
73 static inline void checkWarpingKernelParameter(const SeparableKernel *p, unsigned int ind, double value) {
74  if (ind > 1) {
76  "bad ind argument in WarpingKernel::setKernelParameter()");
77  }
78  int ctr = p->getCtr()[ind];
79  int size = p->getDimensions()[ind];
80 
81  if (ctr == (size - 1) / 2) {
82  if (value < -1e-6 || value > 1 + 1e-6) {
84  "bad coordinate in WarpingKernel::setKernelParameter()");
85  }
86  } else if (ctr == (size + 1) / 2) {
87  if (value < -1 - 1e-6 || value > 1e-6) {
89  "bad coordinate in WarpingKernel::setKernelParameter()");
90  }
91  } else {
93  "bad ctr value in WarpingKernel::setKernelParameter()");
94  }
95 }
96 
99 }
100 
101 int LanczosWarpingKernel::getOrder() const { return this->getWidth() / 2; }
102 
103 void LanczosWarpingKernel::setKernelParameter(unsigned int ind, double value) const {
104  checkWarpingKernelParameter(this, ind, value);
106 }
107 
110 }
111 
113  //
114  // this->_params[0] = value of x where we want to interpolate the function
115  // x = integer value of x where we evaluate the function in the interpolation
116  //
117  // The following weird-looking expression has no if/else statements, is roundoff-tolerant,
118  // and works in the following two cases:
119  // 0 < this->_params[0] < 1, x \in {0,1}
120  // -1 < this->_params[0] < 0, x \in {-1,0}
121  //
122  // The checks in BilinearWarpingKernel::setKernelParameter() ensure that one of these
123  // conditions is satisfied
124  //
125  return 0.5 + (1.0 - (2.0 * fabs(this->_params[0]))) * (0.5 - fabs(x));
126 }
127 
128 void BilinearWarpingKernel::setKernelParameter(unsigned int ind, double value) const {
129  checkWarpingKernelParameter(this, ind, value);
131 }
132 
135  os << "_BilinearFunction1: ";
136  os << Function1<Kernel::Pixel>::toString(prefix);
137  return os.str();
138 }
139 
141  return std::make_shared<NearestWarpingKernel>();
142 }
143 
145  // this expression is faster than using conditionals, but offers no sanity checking
146  return static_cast<double>((fabs(this->_params[0]) < 0.5) == (fabs(x) < 0.5));
147 }
148 
149 void NearestWarpingKernel::setKernelParameter(unsigned int ind, double value) const {
150  checkWarpingKernelParameter(this, ind, value);
152 }
153 
156  os << "_NearestFunction1: ";
157  os << Function1<Kernel::Pixel>::toString(prefix);
158  return os.str();
159 }
160 
162  typedef std::shared_ptr<SeparableKernel> KernelPtr;
163  std::smatch matches;
164  static const std::regex LanczosRE("lanczos(\\d+)");
165  if (name == "bilinear") {
166  return KernelPtr(new BilinearWarpingKernel());
167  } else if (std::regex_match(name, matches, LanczosRE)) {
168  std::string orderStr(matches[1].first, matches[1].second);
169  int order = std::stoi(orderStr);
170  return KernelPtr(new LanczosWarpingKernel(order));
171  } else if (name == "nearest") {
172  return KernelPtr(new NearestWarpingKernel());
173  } else {
174  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "unknown warping kernel name: \"" + name + "\"");
175  }
176 }
177 
179  if (_warpingKernelPtr->getCacheSize() != _cacheSize) {
180  _warpingKernelPtr->computeCache(_cacheSize);
181  }
182  return _warpingKernelPtr;
183 };
184 
185 void WarpingControl::setWarpingKernelName(std::string const &warpingKernelName) {
186  std::shared_ptr<SeparableKernel> warpingKernelPtr(makeWarpingKernel(warpingKernelName));
187  setWarpingKernel(*warpingKernelPtr);
188 }
189 
191  if (_maskWarpingKernelPtr) {
192  _testWarpingKernels(warpingKernel, *_maskWarpingKernelPtr);
193  }
194  std::shared_ptr<SeparableKernel> warpingKernelPtr(
195  std::static_pointer_cast<SeparableKernel>(warpingKernel.clone()));
196  _warpingKernelPtr = warpingKernelPtr;
197 }
198 
200  if (_maskWarpingKernelPtr) { // lazily update kernel cache
201  if (_maskWarpingKernelPtr->getCacheSize() != _cacheSize) {
202  _maskWarpingKernelPtr->computeCache(_cacheSize);
203  }
204  }
205  return _maskWarpingKernelPtr;
206 }
207 
208 void WarpingControl::setMaskWarpingKernelName(std::string const &maskWarpingKernelName) {
209  if (!maskWarpingKernelName.empty()) {
210  std::shared_ptr<SeparableKernel> maskWarpingKernelPtr(makeWarpingKernel(maskWarpingKernelName));
211  setMaskWarpingKernel(*maskWarpingKernelPtr);
212  } else {
213  _maskWarpingKernelPtr.reset();
214  }
215 }
216 
218  _testWarpingKernels(*_warpingKernelPtr, maskWarpingKernel);
219  _maskWarpingKernelPtr = std::static_pointer_cast<SeparableKernel>(maskWarpingKernel.clone());
220 }
221 
222 void WarpingControl::_testWarpingKernels(SeparableKernel const &warpingKernel,
223  SeparableKernel const &maskWarpingKernel) const {
224  lsst::geom::Box2I kernelBBox =
226  warpingKernel.getDimensions());
227  lsst::geom::Box2I maskKernelBBox =
229  maskWarpingKernel.getDimensions());
230  if (!kernelBBox.contains(maskKernelBBox)) {
232  "warping kernel is smaller than mask warping kernel");
233  }
234 }
235 
236 template <typename DestExposureT, typename SrcExposureT>
237 int warpExposure(DestExposureT &destExposure, SrcExposureT const &srcExposure, WarpingControl const &control,
238  typename DestExposureT::MaskedImageT::SinglePixel padValue) {
239  if (!destExposure.hasWcs()) {
240  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "destExposure has no Wcs");
241  }
242  if (!srcExposure.hasWcs()) {
243  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "srcExposure has no Wcs");
244  }
245  typename DestExposureT::MaskedImageT mi = destExposure.getMaskedImage();
246  destExposure.setPhotoCalib(srcExposure.getPhotoCalib());
247  destExposure.setFilterLabel(srcExposure.getFilterLabel());
248  destExposure.getInfo()->setVisitInfo(srcExposure.getInfo()->getVisitInfo());
249  return warpImage(mi, *destExposure.getWcs(), srcExposure.getMaskedImage(), *srcExposure.getWcs(), control,
250  padValue);
251 }
252 
253 namespace {
254 
255 inline lsst::geom::Point2D computeSrcPos(
256  int destCol,
257  int destRow,
258  lsst::geom::Point2D const &destXY0,
259  geom::SkyWcs const &destWcs,
260  geom::SkyWcs const &srcWcs)
261 {
262  lsst::geom::Point2D const destPix(image::indexToPosition(destCol + destXY0[0]),
263  image::indexToPosition(destRow + destXY0[1]));
264  return srcWcs.skyToPixel(destWcs.pixelToSky(destPix));
265 }
266 
267 inline double computeRelativeArea(
268  lsst::geom::Point2D const &srcPos,
269  lsst::geom::Point2D const
270  &leftSrcPos,
271  lsst::geom::Point2D const &upSrcPos)
272 {
273  lsst::geom::Extent2D dSrcA = srcPos - leftSrcPos;
274  lsst::geom::Extent2D dSrcB = srcPos - upSrcPos;
275 
276  return std::abs(dSrcA.getX() * dSrcB.getY() - dSrcA.getY() * dSrcB.getX());
277 }
278 
279 } // namespace
280 
281 template <typename DestImageT, typename SrcImageT>
282 int warpImage(DestImageT &destImage, geom::SkyWcs const &destWcs, SrcImageT const &srcImage,
283  geom::SkyWcs const &srcWcs, WarpingControl const &control,
284  typename DestImageT::SinglePixel padValue) {
285  auto srcToDest = geom::makeWcsPairTransform(srcWcs, destWcs);
286  return warpImage(destImage, srcImage, *srcToDest, control, padValue);
287 }
288 
289 template <typename DestImageT, typename SrcImageT>
290 int warpImage(DestImageT &destImage, SrcImageT const &srcImage,
291  geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control,
292  typename DestImageT::SinglePixel padValue) {
293  if (imagesOverlap(destImage, srcImage)) {
294  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "destImage overlaps srcImage; cannot warp");
295  }
296  if (destImage.getBBox(image::LOCAL).isEmpty()) {
297  return 0;
298  }
299  // if src image is too small then don't try to warp
300  std::shared_ptr<SeparableKernel> warpingKernelPtr = control.getWarpingKernel();
301  try {
302  warpingKernelPtr->shrinkBBox(srcImage.getBBox(image::LOCAL));
304  for (int y = 0, height = destImage.getHeight(); y < height; ++y) {
305  for (typename DestImageT::x_iterator destPtr = destImage.row_begin(y), end = destImage.row_end(y);
306  destPtr != end; ++destPtr) {
307  *destPtr = padValue;
308  }
309  }
310  return 0;
311  }
312  int interpLength = control.getInterpLength();
313 
314  std::shared_ptr<LanczosWarpingKernel const> const lanczosKernelPtr =
315  std::dynamic_pointer_cast<LanczosWarpingKernel>(warpingKernelPtr);
316 
317  int numGoodPixels = 0;
318 
319  // compute a transform from local destination pixels to parent source pixels
320  auto const parentDestToParentSrc = srcToDest.inverted();
321  std::vector<double> const localDestToParentDestVec = {static_cast<double>(destImage.getX0()),
322  static_cast<double>(destImage.getY0())};
323  auto const localDestToParentDest = geom::TransformPoint2ToPoint2(ast::ShiftMap(localDestToParentDestVec));
324  auto const localDestToParentSrc = localDestToParentDest.then(*parentDestToParentSrc);
325 
326  // Get the source MaskedImage and a pixel accessor to it.
327  int const srcWidth = srcImage.getWidth();
328  int const srcHeight = srcImage.getHeight();
329  LOGL_DEBUG("TRACE2.afw.math.warp", "source image width=%d; height=%d", srcWidth, srcHeight);
330 
331  int const destWidth = destImage.getWidth();
332  int const destHeight = destImage.getHeight();
333  LOGL_DEBUG("TRACE2.afw.math.warp", "remap image width=%d; height=%d", destWidth, destHeight);
334 
335  // Set each pixel of destExposure's MaskedImage
336  LOGL_DEBUG("TRACE3.afw.math.warp", "Remapping masked image");
337 
338  int const maxCol = destWidth - 1;
339  int const maxRow = destHeight - 1;
340 
341  detail::WarpAtOnePoint<DestImageT, SrcImageT> warpAtOnePoint(srcImage, control, padValue);
342 
343  if (interpLength > 0) {
344  // Use interpolation. Note that 1 produces the same result as no interpolation
345  // but uses this code branch, thus providing an easy way to compare the two branches.
346 
347  // Estimate for number of horizontal interpolation band edges, to reserve memory in vectors
348  int const numColEdges = 2 + ((destWidth - 1) / interpLength);
349 
350  // A list of edge column indices for interpolation bands;
351  // starts at -1, increments by interpLen (except the final interval), and ends at destWidth-1
352  std::vector<int> edgeColList;
353  edgeColList.reserve(numColEdges);
354 
355  // A list of 1/column width for horizontal interpolation bands; the first value is garbage.
356  // The inverse is used for speed because the values are always multiplied.
357  std::vector<double> invWidthList;
358  invWidthList.reserve(numColEdges);
359 
360  // Compute edgeColList and invWidthList
361  edgeColList.push_back(-1);
362  invWidthList.push_back(0.0);
363  for (int prevEndCol = -1; prevEndCol < maxCol; prevEndCol += interpLength) {
364  int endCol = prevEndCol + interpLength;
365  if (endCol > maxCol) {
366  endCol = maxCol;
367  }
368  edgeColList.push_back(endCol);
369  assert(endCol - prevEndCol > 0);
370  invWidthList.push_back(1.0 / static_cast<double>(endCol - prevEndCol));
371  }
372  assert(edgeColList.back() == maxCol);
373 
374  // A list of delta source positions along the edge columns of the horizontal interpolation bands
375  std::vector<lsst::geom::Extent2D> yDeltaSrcPosList(edgeColList.size());
376 
377  // A cache of pixel positions on the source corresponding to the previous or current row
378  // of the destination image.
379  // The first value is for column -1 because the previous source position is used to compute relative
380  // area To simplify the indexing, use an iterator that starts at begin+1, thus: srcPosView =
381  // srcPosList.begin() + 1 srcPosView[col-1] and lower indices are for this row srcPosView[col] and
382  // higher indices are for the previous row
383  std::vector<lsst::geom::Point2D> srcPosList(1 + destWidth);
384  std::vector<lsst::geom::Point2D>::iterator const srcPosView = srcPosList.begin() + 1;
385 
386  std::vector<lsst::geom::Point2D> endColPosList;
387  endColPosList.reserve(numColEdges);
388 
389  // Initialize srcPosList for row -1
390  for (int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
391  int const endCol = edgeColList[colBand];
392  endColPosList.emplace_back(lsst::geom::Point2D(endCol, -1));
393  }
394  auto rightSrcPosList = localDestToParentSrc->applyForward(endColPosList);
395  srcPosView[-1] = rightSrcPosList[0];
396  for (int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
397  int const prevEndCol = edgeColList[colBand - 1];
398  int const endCol = edgeColList[colBand];
399  lsst::geom::Point2D leftSrcPos = srcPosView[prevEndCol];
400 
401  lsst::geom::Extent2D xDeltaSrcPos =
402  (rightSrcPosList[colBand] - leftSrcPos) * invWidthList[colBand];
403 
404  for (int col = prevEndCol + 1; col <= endCol; ++col) {
405  srcPosView[col] = srcPosView[col - 1] + xDeltaSrcPos;
406  }
407  }
408 
409  int endRow = -1;
410  while (endRow < maxRow) {
411  // Next horizontal interpolation band
412 
413  int prevEndRow = endRow;
414  endRow = prevEndRow + interpLength;
415  if (endRow > maxRow) {
416  endRow = maxRow;
417  }
418  assert(endRow - prevEndRow > 0);
419  double interpInvHeight = 1.0 / static_cast<double>(endRow - prevEndRow);
420 
421  // Set yDeltaSrcPosList for this horizontal interpolation band
422  std::vector<lsst::geom::Point2D> destRowPosList;
423  destRowPosList.reserve(edgeColList.size());
424  for (int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
425  int endCol = edgeColList[colBand];
426  destRowPosList.emplace_back(lsst::geom::Point2D(endCol, endRow));
427  }
428  auto bottomSrcPosList = localDestToParentSrc->applyForward(destRowPosList);
429  for (int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
430  int endCol = edgeColList[colBand];
431  yDeltaSrcPosList[colBand] =
432  (bottomSrcPosList[colBand] - srcPosView[endCol]) * interpInvHeight;
433  }
434 
435  for (int row = prevEndRow + 1; row <= endRow; ++row) {
436  typename DestImageT::x_iterator destXIter = destImage.row_begin(row);
437  srcPosView[-1] += yDeltaSrcPosList[0];
438  for (int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
439  // Next vertical interpolation band
440 
441  int const prevEndCol = edgeColList[colBand - 1];
442  int const endCol = edgeColList[colBand];
443 
444  // Compute xDeltaSrcPos; remember that srcPosView contains
445  // positions for this row in prevEndCol and smaller indices,
446  // and positions for the previous row for larger indices (including endCol)
447  lsst::geom::Point2D leftSrcPos = srcPosView[prevEndCol];
448  lsst::geom::Point2D rightSrcPos = srcPosView[endCol] + yDeltaSrcPosList[colBand];
449  lsst::geom::Extent2D xDeltaSrcPos = (rightSrcPos - leftSrcPos) * invWidthList[colBand];
450 
451  for (int col = prevEndCol + 1; col <= endCol; ++col, ++destXIter) {
452  lsst::geom::Point2D leftSrcPos = srcPosView[col - 1];
453  lsst::geom::Point2D srcPos = leftSrcPos + xDeltaSrcPos;
454  double relativeArea = computeRelativeArea(srcPos, leftSrcPos, srcPosView[col]);
455 
456  srcPosView[col] = srcPos;
457 
458  if (warpAtOnePoint(
459  destXIter, srcPos, relativeArea,
461  ++numGoodPixels;
462  }
463  } // for col
464  } // for col band
465  } // for row
466  } // while next row band
467 
468  } else {
469  // No interpolation
470 
471  // prevSrcPosList = source positions from the previous row; these are used to compute pixel area;
472  // to begin, compute sources positions corresponding to destination row = -1
474  destPosList.reserve(1 + destWidth);
475  for (int col = -1; col < destWidth; ++col) {
476  destPosList.emplace_back(lsst::geom::Point2D(col, -1));
477  }
478  auto prevSrcPosList = localDestToParentSrc->applyForward(destPosList);
479 
480  for (int row = 0; row < destHeight; ++row) {
481  destPosList.clear();
482  for (int col = -1; col < destWidth; ++col) {
483  destPosList.emplace_back(lsst::geom::Point2D(col, row));
484  }
485  auto srcPosList = localDestToParentSrc->applyForward(destPosList);
486 
487  typename DestImageT::x_iterator destXIter = destImage.row_begin(row);
488  for (int col = 0; col < destWidth; ++col, ++destXIter) {
489  // column index = column + 1 because the first entry in srcPosList is for column -1
490  auto srcPos = srcPosList[col + 1];
491  double relativeArea =
492  computeRelativeArea(srcPos, prevSrcPosList[col], prevSrcPosList[col + 1]);
493 
494  if (warpAtOnePoint(destXIter, srcPos, relativeArea,
496  ++numGoodPixels;
497  }
498  } // for col
499  // move points from srcPosList to prevSrcPosList (we don't care about what ends up in srcPosList
500  // because it will be reallocated anyway)
501  swap(srcPosList, prevSrcPosList);
502  } // for row
503  } // if interp
504 
505  return numGoodPixels;
506 }
507 
508 template <typename DestImageT, typename SrcImageT>
509 int warpCenteredImage(DestImageT &destImage, SrcImageT const &srcImage,
510  lsst::geom::LinearTransform const &linearTransform,
511  lsst::geom::Point2D const &centerPosition, WarpingControl const &control,
512  typename DestImageT::SinglePixel padValue) {
513  // force src and dest to be the same size and xy0
514  if ((destImage.getWidth() != srcImage.getWidth()) || (destImage.getHeight() != srcImage.getHeight()) ||
515  (destImage.getXY0() != srcImage.getXY0())) {
516  std::ostringstream errStream;
517  errStream << "src and dest images must have same size and xy0.";
519  }
520 
521  // set the xy0 coords to 0,0 to make life easier
522  SrcImageT srcImageCopy(srcImage, true);
523  srcImageCopy.setXY0(0, 0);
524  destImage.setXY0(0, 0);
525  lsst::geom::Extent2D cLocal =
526  lsst::geom::Extent2D(centerPosition) - lsst::geom::Extent2D(srcImage.getXY0());
527 
528  // for the affine transform, the centerPosition will not only get sheared, but also
529  // moved slightly. So we'll include a translation to move it back by an amount
530  // centerPosition - translatedCenterPosition
531  lsst::geom::AffineTransform affTran(linearTransform, cLocal - linearTransform(cLocal));
533 
534 // now warp
535 #if 0
536  static float t = 0.0;
537  float t_before = 1.0*clock()/CLOCKS_PER_SEC;
538  int n = warpImage(destImage, srcImageCopy, affTran, control, padValue);
539  float t_after = 1.0*clock()/CLOCKS_PER_SEC;
540  float dt = t_after - t_before;
541  t += dt;
542  std::cout <<srcImage.getWidth()<<"x"<<srcImage.getHeight()<<": "<< dt <<" "<< t <<std::endl;
543 #else
544  int n = warpImage(destImage, srcImageCopy, *affineTransform22, control, padValue);
545 #endif
546 
547  // fix the origin and we're done.
548  destImage.setXY0(srcImage.getXY0());
549 
550  return n;
551 }
552 
553 //
554 // Explicit instantiations
555 //
557 // may need to omit default params for EXPOSURE -- original code did that and it worked
558 #define EXPOSURE(PIXTYPE) image::Exposure<PIXTYPE, image::MaskPixel, image::VariancePixel>
559 #define MASKEDIMAGE(PIXTYPE) image::MaskedImage<PIXTYPE, image::MaskPixel, image::VariancePixel>
560 #define IMAGE(PIXTYPE) image::Image<PIXTYPE>
561 #define NL /* */
562 
563 #define INSTANTIATE(DESTIMAGEPIXELT, SRCIMAGEPIXELT) \
564  template int warpCenteredImage( \
565  IMAGE(DESTIMAGEPIXELT) & destImage, IMAGE(SRCIMAGEPIXELT) const &srcImage, \
566  lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const &centerPosition, \
567  WarpingControl const &control, IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
568  NL template int warpCenteredImage( \
569  MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
570  lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const &centerPosition, \
571  WarpingControl const &control, MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
572  NL template int warpImage(IMAGE(DESTIMAGEPIXELT) & destImage, IMAGE(SRCIMAGEPIXELT) const &srcImage, \
573  geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control, \
574  IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
575  NL template int warpImage(MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, \
576  MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
577  geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control, \
578  MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
579  NL template int warpImage(IMAGE(DESTIMAGEPIXELT) & destImage, geom::SkyWcs const &destWcs, \
580  IMAGE(SRCIMAGEPIXELT) const &srcImage, geom::SkyWcs const &srcWcs, \
581  WarpingControl const &control, IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
582  NL template int warpImage(MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, geom::SkyWcs const &destWcs, \
583  MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, geom::SkyWcs const &srcWcs, \
584  WarpingControl const &control, \
585  MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
586  NL template int warpExposure(EXPOSURE(DESTIMAGEPIXELT) & destExposure, \
587  EXPOSURE(SRCIMAGEPIXELT) const &srcExposure, WarpingControl const &control, \
588  EXPOSURE(DESTIMAGEPIXELT)::MaskedImageT::SinglePixel padValue);
589 
590 INSTANTIATE(double, double)
591 INSTANTIATE(double, float)
592 INSTANTIATE(double, int)
593 INSTANTIATE(double, std::uint16_t)
594 INSTANTIATE(float, float)
595 INSTANTIATE(float, int)
597 INSTANTIATE(int, int)
600 } // namespace math
601 } // namespace afw
602 } // namespace lsst
table::Key< std::string > name
Definition: Amplifier.cc:116
int end
double x
#define INSTANTIATE(FROMSYS, TOSYS)
Definition: Detector.cc:484
#define LSST_EXCEPT(type,...)
#define LOGL_DEBUG(logger, message...)
Implementation of the Photometric Calibration class.
std::ostream * os
Definition: Schema.cc:557
std::string prefix
Definition: SchemaMapper.cc:72
int y
Definition: SpanSet.cc:49
T back(T... args)
T begin(T... args)
A 2-dimensional celestial WCS that transform pixels to ICRS RA/Dec, using the LSST standard for pixel...
Definition: SkyWcs.h:117
lsst::geom::SpherePoint pixelToSky(lsst::geom::Point2D const &pixel) const
Compute sky position(s) from pixel position(s)
Definition: SkyWcs.h:334
lsst::geom::Point2D skyToPixel(lsst::geom::SpherePoint const &sky) const
Compute pixel position(s) from sky position(s)
Definition: SkyWcs.h:349
Transform LSST spatial data, such as lsst::geom::Point2D and lsst::geom::SpherePoint,...
Definition: Transform.h:68
std::shared_ptr< Transform< ToEndpoint, FromEndpoint > > inverted() const
The inverse of this Transform.
Definition: Transform.cc:111
std::string toString(std::string const &="") const override
Return string representation.
Kernel::Pixel operator()(double x) const override
Solve bilinear equation.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
std::vector< double > _params
Definition: Function.h:185
lsst::geom::Extent2I const getDimensions() const
Return the Kernel's dimensions (width, height)
Definition: Kernel.h:213
lsst::geom::Point2I getCtr() const
Return index of kernel's center.
Definition: Kernel.h:235
int getWidth() const
Return the Kernel's width.
Definition: Kernel.h:225
Lanczos warping: accurate but slow and can introduce ringing artifacts.
Definition: warpExposure.h:65
int getOrder() const
get the order of the kernel
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
Definition: warpExposure.cc:97
Kernel::Pixel operator()(double x) const override
Solve nearest neighbor equation.
std::string toString(std::string const &="") const override
Return string representation.
Nearest neighbor warping: fast; good for undersampled data.
Definition: warpExposure.h:163
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
Definition: Kernel.h:861
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
Parameters to control convolution.
Definition: warpExposure.h:250
void setWarpingKernel(SeparableKernel const &warpingKernel)
set the warping kernel
int getInterpLength() const
get the interpolation length (pixels)
Definition: warpExposure.h:303
void setWarpingKernelName(std::string const &warpingKernelName)
set the warping kernel by name
void setMaskWarpingKernelName(std::string const &maskWarpingKernelName)
set or clear the mask warping kernel by name
void setMaskWarpingKernel(SeparableKernel const &maskWarpingKernel)
set the mask warping kernel
std::shared_ptr< SeparableKernel > getWarpingKernel() const
get the warping kernel
std::shared_ptr< SeparableKernel > getMaskWarpingKernel() const
get the mask warping kernel
A functor that computes one warped pixel.
bool contains(Point2I const &point) const noexcept
T clear(T... args)
T emplace_back(T... args)
T empty(T... args)
T endl(T... args)
void swap(CameraSys &a, CameraSys &b)
Definition: CameraSys.h:157
std::shared_ptr< TransformPoint2ToPoint2 > makeTransform(lsst::geom::AffineTransform const &affine)
Wrap an lsst::geom::AffineTransform as a Transform.
std::shared_ptr< TransformPoint2ToPoint2 > makeWcsPairTransform(SkyWcs const &src, SkyWcs const &dst)
A Transform obtained by putting two SkyWcs objects "back to back".
Definition: SkyWcs.cc:151
Transform< Point2Endpoint, Point2Endpoint > TransformPoint2ToPoint2
Definition: Transform.h:300
double indexToPosition(double ind)
Convert image index to image position.
Definition: ImageUtils.h:55
bool imagesOverlap(ImageBase< T1 > const &image1, ImageBase< T2 > const &image2)
Return true if the pixels for two images or masks overlap in memory.
Definition: Image.cc:705
std::shared_ptr< SeparableKernel > makeWarpingKernel(std::string name)
Return a warping kernel given its name.
int warpCenteredImage(DestImageT &destImage, SrcImageT const &srcImage, lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const &centerPosition, WarpingControl const &control, typename DestImageT::SinglePixel padValue=lsst::afw::math::edgePixel< DestImageT >(typename lsst::afw::image::detail::image_traits< DestImageT >::image_category()))
Warp an image with a LinearTranform about a specified point.
int warpImage(DestImageT &destImage, geom::SkyWcs const &destWcs, SrcImageT const &srcImage, geom::SkyWcs const &srcWcs, WarpingControl const &control, typename DestImageT::SinglePixel padValue=lsst::afw::math::edgePixel< DestImageT >(typename lsst::afw::image::detail::image_traits< DestImageT >::image_category()))
Warp an Image or MaskedImage to a new Wcs.
int warpExposure(DestExposureT &destExposure, SrcExposureT const &srcExposure, WarpingControl const &control, typename DestExposureT::MaskedImageT::SinglePixel padValue=lsst::afw::math::edgePixel< typename DestExposureT::MaskedImageT >(typename lsst::afw::image::detail::image_traits< typename DestExposureT::MaskedImageT >::image_category()))
Warp (remap) one exposure to another.
Extent< double, 2 > Extent2D
A base class for image defects.
T push_back(T... args)
T regex_match(T... args)
T reserve(T... args)
T size(T... args)
T stoi(T... args)
T str(T... args)
ImageT::image_category image_category
Definition: ImageBase.h:67
T swap(T... args)