LSSTApplications  16.0-10-g0ee56ad+5,16.0-11-ga33d1f2+5,16.0-12-g3ef5c14+3,16.0-12-g71e5ef5+18,16.0-12-gbdf3636+3,16.0-13-g118c103+3,16.0-13-g8f68b0a+3,16.0-15-gbf5c1cb+4,16.0-16-gfd17674+3,16.0-17-g7c01f5c+3,16.0-18-g0a50484+1,16.0-20-ga20f992+8,16.0-21-g0e05fd4+6,16.0-21-g15e2d33+4,16.0-22-g62d8060+4,16.0-22-g847a80f+4,16.0-25-gf00d9b8+1,16.0-28-g3990c221+4,16.0-3-gf928089+3,16.0-32-g88a4f23+5,16.0-34-gd7987ad+3,16.0-37-gc7333cb+2,16.0-4-g10fc685+2,16.0-4-g18f3627+26,16.0-4-g5f3a788+26,16.0-5-gaf5c3d7+4,16.0-5-gcc1f4bb+1,16.0-6-g3b92700+4,16.0-6-g4412fcd+3,16.0-6-g7235603+4,16.0-69-g2562ce1b+2,16.0-8-g14ebd58+4,16.0-8-g2df868b+1,16.0-8-g4cec79c+6,16.0-8-gadf6c7a+1,16.0-8-gfc7ad86,16.0-82-g59ec2a54a+1,16.0-9-g5400cdc+2,16.0-9-ge6233d7+5,master-g2880f2d8cf+3,v17.0.rc1
LSSTDataManagementBasePackage
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 
39 #include <memory>
40 #include "boost/pointer_cast.hpp"
41 #include "boost/regex.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"
50 #include "lsst/afw/image/Calib.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::setCtrX(1) 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  boost::cmatch matches;
164  static const boost::regex LanczosRE("lanczos(\\d+)");
165  if (name == "bilinear") {
166  return KernelPtr(new BilinearWarpingKernel());
167  } else if (boost::regex_match(name.c_str(), matches, LanczosRE)) {
168  std::string orderStr(matches[1].first, matches[1].second);
169  int order;
170  std::istringstream(orderStr) >> order;
171  return KernelPtr(new LanczosWarpingKernel(order));
172  } else if (name == "nearest") {
173  return KernelPtr(new NearestWarpingKernel());
174  } else {
175  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "unknown warping kernel name: \"" + name + "\"");
176  }
177 }
178 
180  if (_warpingKernelPtr->getCacheSize() != _cacheSize) {
181  _warpingKernelPtr->computeCache(_cacheSize);
182  }
183  return _warpingKernelPtr;
184 };
185 
187  std::shared_ptr<SeparableKernel> warpingKernelPtr(makeWarpingKernel(warpingKernelName));
188  setWarpingKernel(*warpingKernelPtr);
189 }
190 
192  if (_maskWarpingKernelPtr) {
193  _testWarpingKernels(warpingKernel, *_maskWarpingKernelPtr);
194  }
195  std::shared_ptr<SeparableKernel> warpingKernelPtr(
196  std::static_pointer_cast<SeparableKernel>(warpingKernel.clone()));
197  _warpingKernelPtr = warpingKernelPtr;
198 }
199 
201  if (_maskWarpingKernelPtr) { // lazily update kernel cache
202  if (_maskWarpingKernelPtr->getCacheSize() != _cacheSize) {
203  _maskWarpingKernelPtr->computeCache(_cacheSize);
204  }
205  }
206  return _maskWarpingKernelPtr;
207 }
208 
209 void WarpingControl::setMaskWarpingKernelName(std::string const &maskWarpingKernelName) {
210  if (!maskWarpingKernelName.empty()) {
211  std::shared_ptr<SeparableKernel> maskWarpingKernelPtr(makeWarpingKernel(maskWarpingKernelName));
212  setMaskWarpingKernel(*maskWarpingKernelPtr);
213  } else {
214  _maskWarpingKernelPtr.reset();
215  }
216 }
217 
219  _testWarpingKernels(*_warpingKernelPtr, maskWarpingKernel);
220  _maskWarpingKernelPtr = std::static_pointer_cast<SeparableKernel>(maskWarpingKernel.clone());
221 }
222 
223 void WarpingControl::_testWarpingKernels(SeparableKernel const &warpingKernel,
224  SeparableKernel const &maskWarpingKernel) const {
225  lsst::geom::Box2I kernelBBox =
227  warpingKernel.getDimensions());
228  lsst::geom::Box2I maskKernelBBox =
230  maskWarpingKernel.getDimensions());
231  if (!kernelBBox.contains(maskKernelBBox)) {
233  "warping kernel is smaller than mask warping kernel");
234  }
235 }
236 
237 template <typename DestExposureT, typename SrcExposureT>
238 int warpExposure(DestExposureT &destExposure, SrcExposureT const &srcExposure, WarpingControl const &control,
239  typename DestExposureT::MaskedImageT::SinglePixel padValue) {
240  if (!destExposure.hasWcs()) {
241  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "destExposure has no Wcs");
242  }
243  if (!srcExposure.hasWcs()) {
244  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "srcExposure has no Wcs");
245  }
246  typename DestExposureT::MaskedImageT mi = destExposure.getMaskedImage();
247  std::shared_ptr<image::Calib> calibCopy(new image::Calib(*srcExposure.getCalib()));
248  destExposure.setCalib(calibCopy);
249  destExposure.setFilter(srcExposure.getFilter());
250  destExposure.getInfo()->setVisitInfo(srcExposure.getInfo()->getVisitInfo());
251  return warpImage(mi, *destExposure.getWcs(), srcExposure.getMaskedImage(), *srcExposure.getWcs(), control,
252  padValue);
253 }
254 
255 namespace {
256 
257 inline lsst::geom::Point2D computeSrcPos(
258  int destCol,
259  int destRow,
260  lsst::geom::Point2D const &destXY0,
261  geom::SkyWcs const &destWcs,
262  geom::SkyWcs const &srcWcs)
263 {
264  lsst::geom::Point2D const destPix(image::indexToPosition(destCol + destXY0[0]),
265  image::indexToPosition(destRow + destXY0[1]));
266  return srcWcs.skyToPixel(destWcs.pixelToSky(destPix));
267 }
268 
269 inline double computeRelativeArea(
270  lsst::geom::Point2D const &srcPos,
271  lsst::geom::Point2D const
272  &leftSrcPos,
273  lsst::geom::Point2D const &upSrcPos)
274 {
275  lsst::geom::Extent2D dSrcA = srcPos - leftSrcPos;
276  lsst::geom::Extent2D dSrcB = srcPos - upSrcPos;
277 
278  return std::abs(dSrcA.getX() * dSrcB.getY() - dSrcA.getY() * dSrcB.getX());
279 }
280 
281 } // namespace
282 
283 template <typename DestImageT, typename SrcImageT>
284 int warpImage(DestImageT &destImage, geom::SkyWcs const &destWcs, SrcImageT const &srcImage,
285  geom::SkyWcs const &srcWcs, WarpingControl const &control,
286  typename DestImageT::SinglePixel padValue) {
287  auto srcToDest = geom::makeWcsPairTransform(srcWcs, destWcs);
288  return warpImage(destImage, srcImage, *srcToDest, control, padValue);
289 }
290 
291 template <typename DestImageT, typename SrcImageT>
292 int warpImage(DestImageT &destImage, SrcImageT const &srcImage,
293  geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control,
294  typename DestImageT::SinglePixel padValue) {
295  if (imagesOverlap(destImage, srcImage)) {
296  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "destImage overlaps srcImage; cannot warp");
297  }
298  if (destImage.getBBox(image::LOCAL).isEmpty()) {
299  return 0;
300  }
301  // if src image is too small then don't try to warp
302  std::shared_ptr<SeparableKernel> warpingKernelPtr = control.getWarpingKernel();
303  try {
304  warpingKernelPtr->shrinkBBox(srcImage.getBBox(image::LOCAL));
306  for (int y = 0, height = destImage.getHeight(); y < height; ++y) {
307  for (typename DestImageT::x_iterator destPtr = destImage.row_begin(y), end = destImage.row_end(y);
308  destPtr != end; ++destPtr) {
309  *destPtr = padValue;
310  }
311  }
312  return 0;
313  }
314  int interpLength = control.getInterpLength();
315 
316  std::shared_ptr<LanczosWarpingKernel const> const lanczosKernelPtr =
318 
319  int numGoodPixels = 0;
320 
321  // compute a transform from local destination pixels to parent source pixels
322  auto const parentDestToParentSrc = srcToDest.inverted();
323  std::vector<double> const localDestToParentDestVec = {static_cast<double>(destImage.getX0()),
324  static_cast<double>(destImage.getY0())};
325  auto const localDestToParentDest = geom::TransformPoint2ToPoint2(ast::ShiftMap(localDestToParentDestVec));
326  auto const localDestToParentSrc = localDestToParentDest.then(*parentDestToParentSrc);
327 
328  // Get the source MaskedImage and a pixel accessor to it.
329  int const srcWidth = srcImage.getWidth();
330  int const srcHeight = srcImage.getHeight();
331  LOGL_DEBUG("TRACE2.afw.math.warp", "source image width=%d; height=%d", srcWidth, srcHeight);
332 
333  int const destWidth = destImage.getWidth();
334  int const destHeight = destImage.getHeight();
335  LOGL_DEBUG("TRACE2.afw.math.warp", "remap image width=%d; height=%d", destWidth, destHeight);
336 
337  // Set each pixel of destExposure's MaskedImage
338  LOGL_DEBUG("TRACE3.afw.math.warp", "Remapping masked image");
339 
340  int const maxCol = destWidth - 1;
341  int const maxRow = destHeight - 1;
342 
343  detail::WarpAtOnePoint<DestImageT, SrcImageT> warpAtOnePoint(srcImage, control, padValue);
344 
345  if (interpLength > 0) {
346  // Use interpolation. Note that 1 produces the same result as no interpolation
347  // but uses this code branch, thus providing an easy way to compare the two branches.
348 
349  // Estimate for number of horizontal interpolation band edges, to reserve memory in vectors
350  int const numColEdges = 2 + ((destWidth - 1) / interpLength);
351 
352  // A list of edge column indices for interpolation bands;
353  // starts at -1, increments by interpLen (except the final interval), and ends at destWidth-1
354  std::vector<int> edgeColList;
355  edgeColList.reserve(numColEdges);
356 
357  // A list of 1/column width for horizontal interpolation bands; the first value is garbage.
358  // The inverse is used for speed because the values are always multiplied.
359  std::vector<double> invWidthList;
360  invWidthList.reserve(numColEdges);
361 
362  // Compute edgeColList and invWidthList
363  edgeColList.push_back(-1);
364  invWidthList.push_back(0.0);
365  for (int prevEndCol = -1; prevEndCol < maxCol; prevEndCol += interpLength) {
366  int endCol = prevEndCol + interpLength;
367  if (endCol > maxCol) {
368  endCol = maxCol;
369  }
370  edgeColList.push_back(endCol);
371  assert(endCol - prevEndCol > 0);
372  invWidthList.push_back(1.0 / static_cast<double>(endCol - prevEndCol));
373  }
374  assert(edgeColList.back() == maxCol);
375 
376  // A list of delta source positions along the edge columns of the horizontal interpolation bands
377  std::vector<lsst::geom::Extent2D> yDeltaSrcPosList(edgeColList.size());
378 
379  // A cache of pixel positions on the source corresponding to the previous or current row
380  // of the destination image.
381  // The first value is for column -1 because the previous source position is used to compute relative
382  // area To simplify the indexing, use an iterator that starts at begin+1, thus: srcPosView =
383  // srcPosList.begin() + 1 srcPosView[col-1] and lower indices are for this row srcPosView[col] and
384  // higher indices are for the previous row
385  std::vector<lsst::geom::Point2D> srcPosList(1 + destWidth);
386  std::vector<lsst::geom::Point2D>::iterator const srcPosView = srcPosList.begin() + 1;
387 
388  std::vector<lsst::geom::Point2D> endColPosList;
389  endColPosList.reserve(numColEdges);
390 
391  // Initialize srcPosList for row -1
392  for (int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
393  int const endCol = edgeColList[colBand];
394  endColPosList.emplace_back(lsst::geom::Point2D(endCol, -1));
395  }
396  auto rightSrcPosList = localDestToParentSrc->applyForward(endColPosList);
397  srcPosView[-1] = rightSrcPosList[0];
398  for (int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
399  int const prevEndCol = edgeColList[colBand - 1];
400  int const endCol = edgeColList[colBand];
401  lsst::geom::Point2D leftSrcPos = srcPosView[prevEndCol];
402 
403  lsst::geom::Extent2D xDeltaSrcPos =
404  (rightSrcPosList[colBand] - leftSrcPos) * invWidthList[colBand];
405 
406  for (int col = prevEndCol + 1; col <= endCol; ++col) {
407  srcPosView[col] = srcPosView[col - 1] + xDeltaSrcPos;
408  }
409  }
410 
411  int endRow = -1;
412  while (endRow < maxRow) {
413  // Next horizontal interpolation band
414 
415  int prevEndRow = endRow;
416  endRow = prevEndRow + interpLength;
417  if (endRow > maxRow) {
418  endRow = maxRow;
419  }
420  assert(endRow - prevEndRow > 0);
421  double interpInvHeight = 1.0 / static_cast<double>(endRow - prevEndRow);
422 
423  // Set yDeltaSrcPosList for this horizontal interpolation band
424  std::vector<lsst::geom::Point2D> destRowPosList;
425  destRowPosList.reserve(edgeColList.size());
426  for (int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
427  int endCol = edgeColList[colBand];
428  destRowPosList.emplace_back(lsst::geom::Point2D(endCol, endRow));
429  }
430  auto bottomSrcPosList = localDestToParentSrc->applyForward(destRowPosList);
431  for (int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
432  int endCol = edgeColList[colBand];
433  yDeltaSrcPosList[colBand] =
434  (bottomSrcPosList[colBand] - srcPosView[endCol]) * interpInvHeight;
435  }
436 
437  for (int row = prevEndRow + 1; row <= endRow; ++row) {
438  typename DestImageT::x_iterator destXIter = destImage.row_begin(row);
439  srcPosView[-1] += yDeltaSrcPosList[0];
440  for (int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
441  // Next vertical interpolation band
442 
443  int const prevEndCol = edgeColList[colBand - 1];
444  int const endCol = edgeColList[colBand];
445 
446  // Compute xDeltaSrcPos; remember that srcPosView contains
447  // positions for this row in prevEndCol and smaller indices,
448  // and positions for the previous row for larger indices (including endCol)
449  lsst::geom::Point2D leftSrcPos = srcPosView[prevEndCol];
450  lsst::geom::Point2D rightSrcPos = srcPosView[endCol] + yDeltaSrcPosList[colBand];
451  lsst::geom::Extent2D xDeltaSrcPos = (rightSrcPos - leftSrcPos) * invWidthList[colBand];
452 
453  for (int col = prevEndCol + 1; col <= endCol; ++col, ++destXIter) {
454  lsst::geom::Point2D leftSrcPos = srcPosView[col - 1];
455  lsst::geom::Point2D srcPos = leftSrcPos + xDeltaSrcPos;
456  double relativeArea = computeRelativeArea(srcPos, leftSrcPos, srcPosView[col]);
457 
458  srcPosView[col] = srcPos;
459 
460  if (warpAtOnePoint(
461  destXIter, srcPos, relativeArea,
463  ++numGoodPixels;
464  }
465  } // for col
466  } // for col band
467  } // for row
468  } // while next row band
469 
470  } else {
471  // No interpolation
472 
473  // prevSrcPosList = source positions from the previous row; these are used to compute pixel area;
474  // to begin, compute sources positions corresponding to destination row = -1
476  destPosList.reserve(1 + destWidth);
477  for (int col = -1; col < destWidth; ++col) {
478  destPosList.emplace_back(lsst::geom::Point2D(col, -1));
479  }
480  auto prevSrcPosList = localDestToParentSrc->applyForward(destPosList);
481 
482  for (int row = 0; row < destHeight; ++row) {
483  destPosList.clear();
484  for (int col = -1; col < destWidth; ++col) {
485  destPosList.emplace_back(lsst::geom::Point2D(col, row));
486  }
487  auto srcPosList = localDestToParentSrc->applyForward(destPosList);
488 
489  typename DestImageT::x_iterator destXIter = destImage.row_begin(row);
490  for (int col = 0; col < destWidth; ++col, ++destXIter) {
491  // column index = column + 1 because the first entry in srcPosList is for column -1
492  auto srcPos = srcPosList[col + 1];
493  double relativeArea =
494  computeRelativeArea(srcPos, prevSrcPosList[col], prevSrcPosList[col + 1]);
495 
496  if (warpAtOnePoint(destXIter, srcPos, relativeArea,
498  ++numGoodPixels;
499  }
500  } // for col
501  // move points from srcPosList to prevSrcPosList (we don't care about what ends up in srcPosList
502  // because it will be reallocated anyway)
503  swap(srcPosList, prevSrcPosList);
504  } // for row
505  } // if interp
506 
507  return numGoodPixels;
508 }
509 
510 template <typename DestImageT, typename SrcImageT>
511 int warpCenteredImage(DestImageT &destImage, SrcImageT const &srcImage,
512  lsst::geom::LinearTransform const &linearTransform,
513  lsst::geom::Point2D const &centerPosition, WarpingControl const &control,
514  typename DestImageT::SinglePixel padValue) {
515  // force src and dest to be the same size and xy0
516  if ((destImage.getWidth() != srcImage.getWidth()) || (destImage.getHeight() != srcImage.getHeight()) ||
517  (destImage.getXY0() != srcImage.getXY0())) {
518  std::ostringstream errStream;
519  errStream << "src and dest images must have same size and xy0.";
521  }
522 
523  // set the xy0 coords to 0,0 to make life easier
524  SrcImageT srcImageCopy(srcImage, true);
525  srcImageCopy.setXY0(0, 0);
526  destImage.setXY0(0, 0);
527  lsst::geom::Extent2D cLocal =
528  lsst::geom::Extent2D(centerPosition) - lsst::geom::Extent2D(srcImage.getXY0());
529 
530  // for the affine transform, the centerPosition will not only get sheared, but also
531  // moved slightly. So we'll include a translation to move it back by an amount
532  // centerPosition - translatedCenterPosition
533  lsst::geom::AffineTransform affTran(linearTransform, cLocal - linearTransform(cLocal));
535 
536 // now warp
537 #if 0
538  static float t = 0.0;
539  float t_before = 1.0*clock()/CLOCKS_PER_SEC;
540  int n = warpImage(destImage, srcImageCopy, affTran, control, padValue);
541  float t_after = 1.0*clock()/CLOCKS_PER_SEC;
542  float dt = t_after - t_before;
543  t += dt;
544  std::cout <<srcImage.getWidth()<<"x"<<srcImage.getHeight()<<": "<< dt <<" "<< t <<std::endl;
545 #else
546  int n = warpImage(destImage, srcImageCopy, *affineTransform22, control, padValue);
547 #endif
548 
549  // fix the origin and we're done.
550  destImage.setXY0(srcImage.getXY0());
551 
552  return n;
553 }
554 
555 //
556 // Explicit instantiations
557 //
559 // may need to omit default params for EXPOSURE -- original code did that and it worked
560 #define EXPOSURE(PIXTYPE) image::Exposure<PIXTYPE, image::MaskPixel, image::VariancePixel>
561 #define MASKEDIMAGE(PIXTYPE) image::MaskedImage<PIXTYPE, image::MaskPixel, image::VariancePixel>
562 #define IMAGE(PIXTYPE) image::Image<PIXTYPE>
563 #define NL /* */
564 
565 #define INSTANTIATE(DESTIMAGEPIXELT, SRCIMAGEPIXELT) \
566  template int warpCenteredImage( \
567  IMAGE(DESTIMAGEPIXELT) & destImage, IMAGE(SRCIMAGEPIXELT) const &srcImage, \
568  lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const &centerPosition, \
569  WarpingControl const &control, IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
570  NL template int warpCenteredImage( \
571  MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
572  lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const &centerPosition, \
573  WarpingControl const &control, MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
574  NL template int warpImage(IMAGE(DESTIMAGEPIXELT) & destImage, IMAGE(SRCIMAGEPIXELT) const &srcImage, \
575  geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control, \
576  IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
577  NL template int warpImage(MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, \
578  MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
579  geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control, \
580  MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
581  NL template int warpImage(IMAGE(DESTIMAGEPIXELT) & destImage, geom::SkyWcs const &destWcs, \
582  IMAGE(SRCIMAGEPIXELT) const &srcImage, geom::SkyWcs const &srcWcs, \
583  WarpingControl const &control, IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
584  NL template int warpImage(MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, geom::SkyWcs const &destWcs, \
585  MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, geom::SkyWcs const &srcWcs, \
586  WarpingControl const &control, \
587  MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
588  NL template int warpExposure(EXPOSURE(DESTIMAGEPIXELT) & destExposure, \
589  EXPOSURE(SRCIMAGEPIXELT) const &srcExposure, WarpingControl const &control, \
590  EXPOSURE(DESTIMAGEPIXELT)::MaskedImageT::SinglePixel padValue);
591 
592 INSTANTIATE(double, double)
593 INSTANTIATE(double, float)
594 INSTANTIATE(double, int)
595 INSTANTIATE(double, std::uint16_t)
596 INSTANTIATE(float, float)
597 INSTANTIATE(float, int)
599 INSTANTIATE(int, int)
602 } // namespace math
603 } // namespace afw
604 } // namespace lsst
int col
Definition: CR.cc:144
Angle abs(Angle const &a)
Definition: Angle.h:106
T empty(T... args)
A 2-dimensional celestial WCS that transform pixels to ICRS RA/Dec, using the LSST standard for pixel...
Definition: SkyWcs.h:115
std::string toString(std::string const &="") const override
Return string representation.
double indexToPosition(double ind)
Convert image index to image position.
Definition: ImageUtils.h:55
lsst::geom::Point2D skyToPixel(lsst::geom::SpherePoint const &sky) const
Compute pixel position(s) from sky position(s)
Definition: SkyWcs.h:347
An affine coordinate transformation consisting of a linear transformation and an offset.
T swap(T... args)
afw::table::Key< std::string > warpingKernelName
Definition: CoaddPsf.cc:341
lsst::geom::SpherePoint pixelToSky(lsst::geom::Point2D const &pixel) const
Compute sky position(s) from pixel position(s)
Definition: SkyWcs.h:332
Kernel::Pixel operator()(double x) const override
Solve bilinear equation.
std::shared_ptr< Transform< ToEndpoint, FromEndpoint > > inverted() const
The inverse of this Transform.
Definition: Transform.cc:111
T endl(T... args)
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:898
void setWarpingKernelName(std::string const &warpingKernelName)
set the warping kernel by name
int y
Definition: SpanSet.cc:49
A functor that computes one warped pixel.
Parameters to control convolution.
Definition: warpExposure.h:250
std::shared_ptr< SeparableKernel > getWarpingKernel() const
get the warping kernel
std::string prefix
Definition: SchemaMapper.cc:79
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Definition: Log.h:489
Describe an exposure&#39;s calibration.
Definition: Calib.h:95
std::shared_ptr< SeparableKernel > makeWarpingKernel(std::string name)
Return a warping kernel given its name.
void setMaskWarpingKernel(SeparableKernel const &maskWarpingKernel)
set the mask warping kernel
Transform< Point2Endpoint, Point2Endpoint > TransformPoint2ToPoint2
Definition: Transform.h:300
STL class.
LSST DM logging module built on log4cxx.
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
Kernel::Pixel operator()(double x) const override
Solve nearest neighbor equation.
T push_back(T... args)
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.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
int getOrder() const
get the order of the kernel
A base class for image defects.
int getInterpLength() const
get the interpolation length (pixels)
Definition: warpExposure.h:303
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
Definition: warpExposure.cc:97
void setMaskWarpingKernelName(std::string const &maskWarpingKernelName)
set or clear the mask warping kernel by name
void setWarpingKernel(SeparableKernel const &warpingKernel)
set the warping kernel
T str(T... args)
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:715
lsst::geom::Point2I getCtr() const
Return index of kernel&#39;s center.
Definition: Kernel.h:238
T static_pointer_cast(T... args)
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
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.
T clear(T... args)
ShiftMap is a linear Mapping which shifts each axis by a specified constant value.
Definition: ShiftMap.h:40
double x
Bilinear warping: fast; good for undersampled data.
Definition: warpExposure.h:99
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
int getWidth() const
Return the Kernel&#39;s width.
Definition: Kernel.h:228
lsst::geom::Extent2I const getDimensions() const
Return the Kernel&#39;s dimensions (width, height)
Definition: Kernel.h:216
void swap(Image< PixelT > &a, Image< PixelT > &b)
Definition: Image.cc:465
T size(T... args)
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:152
std::shared_ptr< SeparableKernel > getMaskWarpingKernel() const
get the mask warping kernel
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
T begin(T... args)
bool contains(Point2I const &point) const noexcept
Return true if the box contains the point.
Definition: Box.cc:113
T c_str(T... args)
Nearest neighbor warping: fast; good for undersampled data.
Definition: warpExposure.h:163
T back(T... args)
Reports invalid arguments.
Definition: Runtime.h:66
Lanczos warping: accurate but slow and can introduce ringing artifacts.
Definition: warpExposure.h:65
ImageT::image_category image_category
Definition: ImageBase.h:68
Extent< double, 2 > Extent2D
Definition: Extent.h:400
An integer coordinate rectangle.
Definition: Box.h:54
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.
std::string toString(std::string const &="") const override
Return string representation.
int end
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
A 2D linear coordinate transformation.
std::ostream * os
Definition: Schema.cc:746
Transform LSST spatial data, such as lsst::geom::Point2D and lsst::geom::SpherePoint, using an AST mapping.
Definition: Transform.h:67
#define INSTANTIATE(FROMSYS, TOSYS)
Definition: Detector.cc:312
std::shared_ptr< TransformPoint2ToPoint2 > makeTransform(lsst::geom::AffineTransform const &affine)
Wrap an lsst::geom::AffineTransform as a Transform.
T reserve(T... args)
int row
Definition: CR.cc:145
T emplace_back(T... args)