LSSTApplications  11.0-13-gbb96280,12.1+18,12.1+7,12.1-1-g14f38d3+72,12.1-1-g16c0db7+5,12.1-1-g5961e7a+84,12.1-1-ge22e12b+23,12.1-11-g06625e2+4,12.1-11-g0d7f63b+4,12.1-19-gd507bfc,12.1-2-g7dda0ab+38,12.1-2-gc0bc6ab+81,12.1-21-g6ffe579+2,12.1-21-gbdb6c2a+4,12.1-24-g941c398+5,12.1-3-g57f6835+7,12.1-3-gf0736f3,12.1-37-g3ddd237,12.1-4-gf46015e+5,12.1-5-g06c326c+20,12.1-5-g648ee80+3,12.1-5-gc2189d7+4,12.1-6-ga608fc0+1,12.1-7-g3349e2a+5,12.1-7-gfd75620+9,12.1-9-g577b946+5,12.1-9-gc4df26a+10
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  */
32 #include <cassert>
33 #include <cmath>
34 #include <cstdint>
35 #include <limits>
36 #include <sstream>
37 #include <string>
38 #include <vector>
39 #include <utility>
40 #include <ctime>
41 
42 #include <memory>
43 #include "boost/pointer_cast.hpp"
44 #include "boost/regex.hpp"
45 
46 #include "lsst/log/Log.h"
47 #include "lsst/pex/exceptions.h"
49 #include "lsst/afw/geom.h"
50 #include "lsst/afw/math/Kernel.h"
51 #include "lsst/afw/coord/Coord.h"
52 #include "lsst/afw/image/Calib.h"
53 #include "lsst/afw/image/Wcs.h"
56 
57 namespace pexExcept = lsst::pex::exceptions;
58 namespace afwImage = lsst::afw::image;
59 namespace afwGeom = lsst::afw::geom;
60 namespace afwCoord = lsst::afw::coord;
61 namespace afwMath = lsst::afw::math;
62 
63 
64 //
65 // A helper function for the warping kernels which provides error-checking:
66 // the warping kernels are designed to work in two cases
67 // 0 < x < 1 and ctrX=(size-1)/2
68 // -1 < x < 0 and ctrX=(size+1)/2
69 // (and analogously for y). Note that to get the second case, Kernel::setCtrX(1) must be
70 // called before calling Kernel::setKernelParameter(). [see afw::math::offsetImage() for
71 // an example]
72 //
73 // FIXME eventually the 3 warping kernels will inherit from a common base class WarpingKernel
74 // and this routine can be eliminated by putting the code in WarpingKernel::setKernelParameter()
75 //
76 static inline void checkWarpingKernelParameter(const afwMath::SeparableKernel *p, unsigned int ind, double value)
77 {
78  if (ind > 1) {
79  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "bad ind argument in WarpingKernel::setKernelParameter()");
80  }
81  int ctr = p->getCtr()[ind];
82  int size = p->getDimensions()[ind];
83 
84  if (ctr == (size-1)/2) {
85  if (value < -1e-6 || value > 1+1e-6) {
86  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "bad coordinate in WarpingKernel::setKernelParameter()");
87  }
88  } else if (ctr == (size+1)/2) {
89  if (value < -1-1e-6 || value > 1e-6) {
90  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "bad coordinate in WarpingKernel::setKernelParameter()");
91  }
92  } else {
93  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "bad ctr value in WarpingKernel::setKernelParameter()");
94  }
95 }
96 
97 
98 PTR(afwMath::Kernel) afwMath::LanczosWarpingKernel::clone() const {
99  return PTR(afwMath::Kernel)(new afwMath::LanczosWarpingKernel(this->getOrder()));
100 }
101 
106  return this->getWidth() / 2;
107 }
108 
109 void afwMath::LanczosWarpingKernel::setKernelParameter(unsigned int ind, double value) const
110 {
111  checkWarpingKernelParameter(this, ind, value);
113 }
114 
115 PTR(afwMath::Kernel) afwMath::BilinearWarpingKernel::clone() const {
117 }
118 
126 afwMath::Kernel::Pixel afwMath::BilinearWarpingKernel::BilinearFunction1::operator() (double x) const
127 {
128  //
129  // this->_params[0] = value of x where we want to interpolate the function
130  // x = integer value of x where we evaluate the function in the interpolation
131  //
132  // The following weird-looking expression has no if/else statements, is roundoff-tolerant,
133  // and works in the following two cases:
134  // 0 < this->_params[0] < 1, x \in {0,1}
135  // -1 < this->_params[0] < 0, x \in {-1,0}
136  //
137  // The checks in BilinearWarpingKernel::setKernelParameter() ensure that one of these
138  // conditions is satisfied
139  //
140  return 0.5 + (1.0 - (2.0 * fabs(this->_params[0]))) * (0.5 - fabs(x));
141 }
142 
143 void afwMath::BilinearWarpingKernel::setKernelParameter(unsigned int ind, double value) const
144 {
145  checkWarpingKernelParameter(this, ind, value);
147 }
148 
152 std::string afwMath::BilinearWarpingKernel::BilinearFunction1::toString(std::string const& prefix) const {
153  std::ostringstream os;
154  os << "_BilinearFunction1: ";
155  os << Function1<Kernel::Pixel>::toString(prefix);
156  return os.str();
157 }
158 
159 PTR(afwMath::Kernel) afwMath::NearestWarpingKernel::clone() const {
161 }
162 
170 afwMath::Kernel::Pixel afwMath::NearestWarpingKernel::NearestFunction1::operator() (double x) const {
171  // this expression is faster than using conditionals, but offers no sanity checking
172  return static_cast<double>((fabs(this->_params[0]) < 0.5) == (fabs(x) < 0.5));
173 }
174 
175 void afwMath::NearestWarpingKernel::setKernelParameter(unsigned int ind, double value) const
176 {
177  checkWarpingKernelParameter(this, ind, value);
179 }
180 
184 std::string afwMath::NearestWarpingKernel::NearestFunction1::toString(std::string const& prefix) const {
185  std::ostringstream os;
186  os << "_NearestFunction1: ";
187  os << Function1<Kernel::Pixel>::toString(prefix);
188  return os.str();
189 }
190 
191 std::shared_ptr<afwMath::SeparableKernel> afwMath::makeWarpingKernel(std::string name) {
192  typedef std::shared_ptr<afwMath::SeparableKernel> KernelPtr;
193  boost::cmatch matches;
194  static const boost::regex LanczosRE("lanczos(\\d+)");
195  if (name == "bilinear") {
196  return KernelPtr(new BilinearWarpingKernel());
197  } else if (boost::regex_match(name.c_str(), matches, LanczosRE)) {
198  std::string orderStr(matches[1].first, matches[1].second);
199  int order;
200  std::istringstream(orderStr) >> order;
201  return KernelPtr(new LanczosWarpingKernel(order));
202  } else if (name == "nearest") {
203  return KernelPtr(new NearestWarpingKernel());
204  } else {
205  throw LSST_EXCEPT(pexExcept::InvalidParameterError,
206  "unknown warping kernel name: \"" + name + "\"");
207  }
208 }
209 
210 PTR(afwMath::SeparableKernel) afwMath::WarpingControl::getWarpingKernel() const {
211  if (_warpingKernelPtr->getCacheSize() != _cacheSize) {
212  _warpingKernelPtr->computeCache(_cacheSize);
213  }
214  return _warpingKernelPtr;
215 };
216 
218  std::string const &warpingKernelName
219 ) {
220  PTR(SeparableKernel) warpingKernelPtr(makeWarpingKernel(warpingKernelName));
221  setWarpingKernel(*warpingKernelPtr);
222 }
223 
225  SeparableKernel const &warpingKernel
226 ) {
227  if (_maskWarpingKernelPtr) {
228  _testWarpingKernels(warpingKernel, *_maskWarpingKernelPtr);
229  }
230  PTR(SeparableKernel) warpingKernelPtr(std::static_pointer_cast<SeparableKernel>(warpingKernel.clone()));
231  _warpingKernelPtr = warpingKernelPtr;
232 }
233 
234 
235 PTR(afwMath::SeparableKernel) afwMath::WarpingControl::getMaskWarpingKernel() const {
236  if (_maskWarpingKernelPtr) { // lazily update kernel cache
237  if (_maskWarpingKernelPtr->getCacheSize() != _cacheSize) {
238  _maskWarpingKernelPtr->computeCache(_cacheSize);
239  }
240  }
241  return _maskWarpingKernelPtr;
242 }
243 
245  std::string const &maskWarpingKernelName
246 ) {
247  if (!maskWarpingKernelName.empty()) {
248  PTR(SeparableKernel) maskWarpingKernelPtr(makeWarpingKernel(maskWarpingKernelName));
249  setMaskWarpingKernel(*maskWarpingKernelPtr);
250  } else {
251  _maskWarpingKernelPtr.reset();
252  }
253 }
254 
256  SeparableKernel const & maskWarpingKernel
257 ) {
258  _testWarpingKernels(*_warpingKernelPtr, maskWarpingKernel);
259  _maskWarpingKernelPtr = std::static_pointer_cast<SeparableKernel>(maskWarpingKernel.clone());
260 }
261 
262 
264  SeparableKernel const &warpingKernel,
265  SeparableKernel const &maskWarpingKernel
266 ) const {
269  warpingKernel.getDimensions()
270  );
272  lsst::afw::geom::Point2I(0, 0) - lsst::afw::geom::Extent2I(maskWarpingKernel.getCtr()),
273  maskWarpingKernel.getDimensions()
274  );
275  if (!kernelBBox.contains(maskKernelBBox)) {
276  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
277  "warping kernel is smaller than mask warping kernel");
278  }
279 }
280 
281 template<typename DestExposureT, typename SrcExposureT>
283  DestExposureT &destExposure,
284  SrcExposureT const &srcExposure,
285  afwMath::WarpingControl const &control,
286  typename DestExposureT::MaskedImageT::SinglePixel padValue
287  )
288 {
289  if (!destExposure.hasWcs()) {
290  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "destExposure has no Wcs");
291  }
292  if (!srcExposure.hasWcs()) {
293  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "srcExposure has no Wcs");
294  }
295  typename DestExposureT::MaskedImageT mi = destExposure.getMaskedImage();
296  std::shared_ptr<afwImage::Calib> calibCopy(new afwImage::Calib(*srcExposure.getCalib()));
297  destExposure.setCalib(calibCopy);
298  destExposure.setFilter(srcExposure.getFilter());
299  return warpImage(mi, *destExposure.getWcs(), srcExposure.getMaskedImage(), *srcExposure.getWcs(),
300  control, padValue);
301 }
302 
303 
304 /************************************************************************************************************/
305 namespace {
306 
307  inline afwGeom::Point2D computeSrcPos(
308  int destCol,
309  int destRow,
310  afwGeom::Point2D const &destXY0,
311  afwImage::Wcs const &destWcs,
312  afwImage::Wcs const &srcWcs)
313  {
314  double const col = afwImage::indexToPosition(destCol + destXY0[0]);
315  double const row = afwImage::indexToPosition(destRow + destXY0[1]);
316  afwGeom::Angle sky1, sky2;
317  destWcs.pixelToSky(col, row, sky1, sky2);
318  return srcWcs.skyToPixel(sky1, sky2);
319  }
320 
321 
322  inline double computeRelativeArea(
323  afwGeom::Point2D const &srcPos,
324  afwGeom::Point2D const &leftSrcPos,
325  afwGeom::Point2D const &upSrcPos)
326  {
327  afwGeom::Extent2D dSrcA = srcPos - leftSrcPos;
328  afwGeom::Extent2D dSrcB = srcPos - upSrcPos;
329 
330  return std::abs(dSrcA.getX()*dSrcB.getY() - dSrcA.getY()*dSrcB.getX());
331  }
332 
333  template<typename DestImageT, typename SrcImageT>
334  int doWarpImage(
335  DestImageT &destImage,
336  SrcImageT const &srcImage,
337  afwMath::detail::PositionFunctor const &computeSrcPos,
338  afwMath::WarpingControl const &control,
340  typename DestImageT::SinglePixel padValue
341  ) {
342  if (afwMath::details::isSameObject(destImage, srcImage)) {
343  throw LSST_EXCEPT(pexExcept::InvalidParameterError,
344  "destImage is srcImage; cannot warp in place");
345  }
346  if (destImage.getBBox(afwImage::LOCAL).isEmpty()) {
347  return 0;
348  }
349  // if src image is too small then don't try to warp
350  try {
351  PTR(afwMath::SeparableKernel) warpingKernelPtr = control.getWarpingKernel();
352  warpingKernelPtr->shrinkBBox(srcImage.getBBox(afwImage::LOCAL));
353  } catch(...) {
354  for (int y = 0, height = destImage.getHeight(); y < height; ++y) {
355  for (typename DestImageT::x_iterator destPtr = destImage.row_begin(y), end = destImage.row_end(y);
356  destPtr != end; ++destPtr) {
357  *destPtr = padValue;
358  }
359  }
360  return 0;
361  }
362  PTR(afwMath::SeparableKernel) warpingKernelPtr = control.getWarpingKernel();
363  int interpLength = control.getInterpLength();
364 
365  std::shared_ptr<afwMath::LanczosWarpingKernel const> const lanczosKernelPtr =
366  std::dynamic_pointer_cast<afwMath::LanczosWarpingKernel>(warpingKernelPtr);
367 
368 
369  int numGoodPixels = 0;
370 
371  // Get the source MaskedImage and a pixel accessor to it.
372  int const srcWidth = srcImage.getWidth();
373  int const srcHeight = srcImage.getHeight();
374  LOGL_DEBUG("TRACE2.afw.math.warp", "source image width=%d; height=%d", srcWidth, srcHeight);
375 
376  int const destWidth = destImage.getWidth();
377  int const destHeight = destImage.getHeight();
378 
379  LOGL_DEBUG("TRACE2.afw.math.warp", "remap image width=%d; height=%d", destWidth, destHeight);
380 
381  // Set each pixel of destExposure's MaskedImage
382  LOGL_DEBUG("TRACE3.afw.math.warp", "Remapping masked image");
383 
384  // A cache of pixel positions on the source corresponding to the previous or current row
385  // of the destination image.
386  // The first value is for column -1 because the previous source position is used to compute relative area
387  // To simplify the indexing, use an iterator that starts at begin+1, thus:
388  // srcPosView = _srcPosList.begin() + 1
389  // srcPosView[col-1] and lower indices are for this row
390  // srcPosView[col] and higher indices are for the previous row
391  std::vector<afwGeom::Point2D> _srcPosList(1 + destWidth);
392  std::vector<afwGeom::Point2D>::iterator const srcPosView = _srcPosList.begin() + 1;
393 
394  int const maxCol = destWidth - 1;
395  int const maxRow = destHeight - 1;
396 
397  afwMath::detail::WarpAtOnePoint<DestImageT, SrcImageT> warpAtOnePoint(srcImage, control, padValue);
398 
399  if (interpLength > 0) {
400  // Use interpolation. Note that 1 produces the same result as no interpolation
401  // but uses this code branch, thus providing an easy way to compare the two branches.
402 
403  // Estimate for number of horizontal interpolation band edges, to reserve memory in vectors
404  int const numColEdges = 2 + ((destWidth - 1) / interpLength);
405 
406  // A list of edge column indices for interpolation bands;
407  // starts at -1, increments by interpLen (except the final interval), and ends at destWidth-1
408  std::vector<int> edgeColList;
409  edgeColList.reserve(numColEdges);
410 
411  // A list of 1/column width for horizontal interpolation bands; the first value is garbage.
412  // The inverse is used for speed because the values is always multiplied.
413  std::vector<double> invWidthList;
414  invWidthList.reserve(numColEdges);
415 
416  // Compute edgeColList and invWidthList
417  edgeColList.push_back(-1);
418  invWidthList.push_back(0.0);
419  for (int prevEndCol = -1; prevEndCol < maxCol; prevEndCol += interpLength) {
420  int endCol = prevEndCol + interpLength;
421  if (endCol > maxCol) {
422  endCol = maxCol;
423  }
424  edgeColList.push_back(endCol);
425  assert(endCol - prevEndCol > 0);
426  invWidthList.push_back(1.0 / static_cast<double>(endCol - prevEndCol));
427  }
428  assert(edgeColList.back() == maxCol);
429 
430  // A list of delta source positions along the edge columns of the horizontal interpolation bands
431  std::vector<afwGeom::Extent2D> yDeltaSrcPosList(edgeColList.size());
432 
433  // Initialize _srcPosList for row -1
434  //srcPosView[-1] = computeSrcPos(-1, -1, destXY0, destWcs, srcWcs);
435  srcPosView[-1] = computeSrcPos(-1, -1);
436  for (int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
437  int const prevEndCol = edgeColList[colBand-1];
438  int const endCol = edgeColList[colBand];
439  afwGeom::Point2D leftSrcPos = srcPosView[prevEndCol];
440  afwGeom::Point2D rightSrcPos = computeSrcPos(endCol, -1);
441  afwGeom::Extent2D xDeltaSrcPos = (rightSrcPos - leftSrcPos) * invWidthList[colBand];
442 
443  for (int col = prevEndCol + 1; col <= endCol; ++col) {
444  srcPosView[col] = srcPosView[col-1] + xDeltaSrcPos;
445  }
446  }
447 
448  int endRow = -1;
449  while (endRow < maxRow) {
450  // Next horizontal interpolation band
451 
452  int prevEndRow = endRow;
453  endRow = prevEndRow + interpLength;
454  if (endRow > maxRow) {
455  endRow = maxRow;
456  }
457  assert(endRow - prevEndRow > 0);
458  double interpInvHeight = 1.0 / static_cast<double>(endRow - prevEndRow);
459 
460  // Set yDeltaSrcPosList for this horizontal interpolation band
461  for (int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
462  int endCol = edgeColList[colBand];
463  afwGeom::Point2D bottomSrcPos = computeSrcPos(endCol, endRow);
464  yDeltaSrcPosList[colBand] = (bottomSrcPos - srcPosView[endCol]) * interpInvHeight;
465  }
466 
467  for (int row = prevEndRow + 1; row <= endRow; ++row) {
468  typename DestImageT::x_iterator destXIter = destImage.row_begin(row);
469  srcPosView[-1] += yDeltaSrcPosList[0];
470  for (int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
472 
473  int const prevEndCol = edgeColList[colBand-1];
474  int const endCol = edgeColList[colBand];
475 
476  // Compute xDeltaSrcPos; remember that srcPosView contains
477  // positions for this row in prevEndCol and smaller indices,
478  // and positions for the previous row for larger indices (including endCol)
479  afwGeom::Point2D leftSrcPos = srcPosView[prevEndCol];
480  afwGeom::Point2D rightSrcPos = srcPosView[endCol] + yDeltaSrcPosList[colBand];
481  afwGeom::Extent2D xDeltaSrcPos = (rightSrcPos - leftSrcPos) * invWidthList[colBand];
482 
483  for (int col = prevEndCol + 1; col <= endCol; ++col, ++destXIter) {
484  afwGeom::Point2D leftSrcPos = srcPosView[col-1];
485  afwGeom::Point2D srcPos = leftSrcPos + xDeltaSrcPos;
486  double relativeArea = computeRelativeArea(srcPos, leftSrcPos, srcPosView[col]);
487 
488  srcPosView[col] = srcPos;
489 
490  if (warpAtOnePoint(destXIter, srcPos, relativeArea,
492  ++numGoodPixels;
493  }
494  } // for col
495  } // for col band
496  } // for row
497  } // while next row band
498 
499 
500  } else {
501  // No interpolation
502 
503  // initialize _srcPosList for row -1;
504  // the first value is not needed, but it's safer to compute it
505  std::vector<afwGeom::Point2D>::iterator srcPosView = _srcPosList.begin() + 1;
506  for (int col = -1; col < destWidth; ++col) {
507  srcPosView[col] = computeSrcPos(col, -1);
508  }
509 
510  for (int row = 0; row < destHeight; ++row) {
511  typename DestImageT::x_iterator destXIter = destImage.row_begin(row);
512 
513  srcPosView[-1] = computeSrcPos(-1, row);
514 
515  for (int col = 0; col < destWidth; ++col, ++destXIter) {
516  afwGeom::Point2D srcPos = computeSrcPos(col, row);
517  double relativeArea = computeRelativeArea(srcPos, srcPosView[col-1], srcPosView[col]);
518  srcPosView[col] = srcPos;
519 
520  if (warpAtOnePoint(destXIter, srcPos, relativeArea,
522  ++numGoodPixels;
523  }
524  } // for col
525  } // for row
526  } // if interp
527 
528  return numGoodPixels;
529  }
530 
531 } // namespace
532 
533 template<typename DestImageT, typename SrcImageT>
535  DestImageT &destImage,
536  lsst::afw::image::Wcs const &destWcs,
537  SrcImageT const &srcImage,
538  lsst::afw::image::Wcs const &srcWcs,
539  afwMath::WarpingControl const &control,
540  typename DestImageT::SinglePixel padValue
541 ) {
542  afwGeom::Point2D const destXY0(destImage.getXY0());
543  afwImage::XYTransformFromWcsPair xyTransform{destWcs.clone(), srcWcs.clone()};
544  afwMath::detail::XYTransformPositionFunctor const computeSrcPos{destXY0, xyTransform};
545  return doWarpImage(destImage, srcImage, computeSrcPos, control, padValue);
546 }
547 
548 
549 template<typename DestImageT, typename SrcImageT>
551  DestImageT &destImage,
552  SrcImageT const &srcImage,
553  afwGeom::XYTransform const &xyTransform,
554  afwMath::WarpingControl const &control,
555  typename DestImageT::SinglePixel padValue
556 ) {
557  afwGeom::Point2D const destXY0(destImage.getXY0());
558  afwMath::detail::XYTransformPositionFunctor const computeSrcPos(destXY0, xyTransform);
559  return doWarpImage(destImage, srcImage, computeSrcPos, control, padValue);
560 }
561 
562 
563 template<typename DestImageT, typename SrcImageT>
565  DestImageT &destImage,
566  SrcImageT const &srcImage,
567  afwGeom::LinearTransform const &linearTransform,
568  afwGeom::Point2D const &centerPosition,
569  afwMath::WarpingControl const &control,
570  typename DestImageT::SinglePixel padValue
571 ) {
572  // force src and dest to be the same size and xy0
573  if (
574  (destImage.getWidth() != srcImage.getWidth()) ||
575  (destImage.getHeight() != srcImage.getHeight()) ||
576  (destImage.getXY0() != srcImage.getXY0())
577  ) {
578  std::ostringstream errStream;
579  errStream << "src and dest images must have same size and xy0.";
580  throw LSST_EXCEPT(pexExcept::InvalidParameterError, errStream.str());
581  }
582 
583  // set the xy0 coords to 0,0 to make life easier
584  SrcImageT srcImageCopy(srcImage, true);
585  srcImageCopy.setXY0(0, 0);
586  destImage.setXY0(0, 0);
587  afwGeom::Extent2D cLocal = afwGeom::Extent2D(centerPosition) - afwGeom::Extent2D(srcImage.getXY0());
588 
589  // for the affine transform, the centerPosition will not only get sheared, but also
590  // moved slightly. So we'll include a translation to move it back by an amount
591  // centerPosition - translatedCenterPosition
592  afwGeom::AffineTransform affTran(linearTransform, cLocal - linearTransform(cLocal));
593  afwGeom::AffineXYTransform affXYTransform(affTran);
594 
595  // now warp
596 #if 0
597  static float t = 0.0;
598  float t_before = 1.0*clock()/CLOCKS_PER_SEC;
599  int n = warpImage(destImage, srcImageCopy, affTran, control, padValue);
600  float t_after = 1.0*clock()/CLOCKS_PER_SEC;
601  float dt = t_after - t_before;
602  t += dt;
603  std::cout <<srcImage.getWidth()<<"x"<<srcImage.getHeight()<<": "<< dt <<" "<< t <<std::endl;
604 #else
605  int n = warpImage(destImage, srcImageCopy, affXYTransform, control, padValue);
606 #endif
607 
608  // fix the origin and we're done.
609  destImage.setXY0(srcImage.getXY0());
610 
611  return n;
612 }
613 
614 
615 //
616 // Explicit instantiations
617 //
619 // may need to omit default params for EXPOSURE -- original code did that and it worked
620 #define EXPOSURE(PIXTYPE) afwImage::Exposure<PIXTYPE, afwImage::MaskPixel, afwImage::VariancePixel>
621 #define MASKEDIMAGE(PIXTYPE) afwImage::MaskedImage<PIXTYPE, afwImage::MaskPixel, afwImage::VariancePixel>
622 #define IMAGE(PIXTYPE) afwImage::Image<PIXTYPE>
623 #define NL /* */
624 
625 #define INSTANTIATE(DESTIMAGEPIXELT, SRCIMAGEPIXELT) \
626  template int afwMath::warpCenteredImage( \
627  IMAGE(DESTIMAGEPIXELT) &destImage, \
628  IMAGE(SRCIMAGEPIXELT) const &srcImage, \
629  afwGeom::LinearTransform const &linearTransform, \
630  afwGeom::Point2D const &centerPosition, \
631  afwMath::WarpingControl const &control, \
632  IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
633  template int afwMath::warpCenteredImage( \
634  MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \
635  MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
636  afwGeom::LinearTransform const &linearTransform, \
637  afwGeom::Point2D const &centerPosition, \
638  afwMath::WarpingControl const &control, \
639  MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
640  template int afwMath::warpImage( \
641  IMAGE(DESTIMAGEPIXELT) &destImage, \
642  IMAGE(SRCIMAGEPIXELT) const &srcImage, \
643  afwGeom::XYTransform const &xyTransform, \
644  afwMath::WarpingControl const &control, \
645  IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
646  template int afwMath::warpImage( \
647  MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \
648  MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
649  afwGeom::XYTransform const &xyTransform, \
650  afwMath::WarpingControl const &control, \
651  MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
652  template int afwMath::warpImage( \
653  IMAGE(DESTIMAGEPIXELT) &destImage, \
654  afwImage::Wcs const &destWcs, \
655  IMAGE(SRCIMAGEPIXELT) const &srcImage, \
656  afwImage::Wcs const &srcWcs, \
657  afwMath::WarpingControl const &control, \
658  IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
659  template int afwMath::warpImage( \
660  MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \
661  afwImage::Wcs const &destWcs, \
662  MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
663  afwImage::Wcs const &srcWcs, \
664  afwMath::WarpingControl const &control, \
665  MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
666  template int afwMath::warpExposure( \
667  EXPOSURE(DESTIMAGEPIXELT) &destExposure, \
668  EXPOSURE(SRCIMAGEPIXELT) const &srcExposure, \
669  afwMath::WarpingControl const &control,\
670  EXPOSURE(DESTIMAGEPIXELT)::MaskedImageT::SinglePixel padValue);
671 
672 
673 
674 
675 INSTANTIATE(double, double)
676 INSTANTIATE(double, float)
677 INSTANTIATE(double, int)
678 INSTANTIATE(double, std::uint16_t)
679 INSTANTIATE(float, float)
680 INSTANTIATE(float, int)
681 INSTANTIATE(float, std::uint16_t)
682 INSTANTIATE(int, int)
683 INSTANTIATE(std::uint16_t, std::uint16_t)
int y
virtual void setKernelParameter(unsigned int ind, double value) const
Set one kernel parameter.
An include file to include the header files for lsst::afw::geom.
virtual void setKernelParameter(unsigned int ind, double value) const
Set one kernel parameter.
Declare the Kernel class and subclasses.
boost::shared_ptr< SeparableKernel > makeWarpingKernel(std::string name)
Return a warping kernel given its name.
geom::Extent2I const getDimensions() const
Return the Kernel&#39;s dimensions (width, height)
Definition: Kernel.h:223
double indexToPosition(double ind)
Convert image index to image position.
Definition: ImageUtils.h:54
table::Key< std::string > name
Definition: ApCorrMap.cc:71
Include files required for standard LSST Exception handling.
Extent< double, 2 > Extent2D
Definition: Extent.h:361
geom::Point2D skyToPixel(geom::Angle sky1, geom::Angle sky2) const
Convert from sky coordinates (e.g.
Definition: Wcs.cc:796
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
Definition: Kernel.h:983
void setWarpingKernelName(std::string const &warpingKernelName)
set the warping kernel by name
XYTransformFromWcsPair: An XYTransform obtained by putting two Wcs objects &quot;back to back&quot;...
Definition: Wcs.h:449
Parameters to control convolution.
Definition: warpExposure.h:235
Implementation of the WCS standard for a any projection.
Definition: Wcs.h:107
virtual Ptr clone(void) const
Definition: Wcs.cc:566
int warpCenteredImage(DestImageT &destImage, SrcImageT const &srcImage, lsst::afw::geom::LinearTransform const &linearTransform, lsst::afw::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.
boost::shared_ptr< coord::Coord > pixelToSky(double pix1, double pix2) const
Convert from pixel position to sky coordinates (e.g.
Definition: Wcs.cc:886
#define INSTANTIATE(T)
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Definition: Log.h:513
Describe an exposure&#39;s calibration.
Definition: Calib.h:82
void setMaskWarpingKernel(SeparableKernel const &maskWarpingKernel)
set the mask warping kernel
An integer coordinate rectangle.
Definition: Box.h:53
int warpImage(DestImageT &destImage, lsst::afw::image::Wcs const &destWcs, SrcImageT const &srcImage, lsst::afw::image::Wcs 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.
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
int getOrder() const
get the order of the kernel
LSST DM logging module built on log4cxx.
int getWidth() const
Return the Kernel&#39;s width.
Definition: Kernel.h:237
A 2D linear coordinate transformation.
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.
metadata import lsst afw display as afwDisplay n
A class representing an Angle.
Definition: Angle.h:103
void ImageT ImageT int float saturatedPixelValue int const width
Definition: saturated.cc:44
An affine coordinate transformation consisting of a linear transformation and an offset.
bool contains(Point2I const &point) const
Return true if the box contains the point.
void setMaskWarpingKernelName(std::string const &maskWarpingKernelName)
set or clear the mask warping kernel by name
bool isSameObject(A const &, B const &)
Definition: warpExposure.h:489
void setWarpingKernel(SeparableKernel const &warpingKernel)
set the warping kernel
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
Definition: saturated.cc:47
double x
Classes to support calibration (e.g.
lsst::afw::geom::Point2I getCtr() const
Return index of kernel&#39;s center.
Definition: Kernel.h:251
Bilinear warping: fast; good for undersampled data.
Definition: warpExposure.h:99
void ImageT ImageT int float saturatedPixelValue int const height
Definition: saturated.cc:44
virtual void setKernelParameter(unsigned int ind, double value) const
Set one kernel parameter.
int row
Definition: CR.cc:158
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
Definition: Exception.h:46
tbl::Key< std::string > warpingKernelName
Definition: CoaddPsf.cc:353
#define PTR(...)
Definition: base.h:41
Support for warping an image to a new WCS.
Virtual base class for 2D transforms.
Definition: XYTransform.h:48
virtual void setKernelParameter(unsigned int ind, double value) const
Set one kernel parameter.
Nearest neighbor warping: fast; good for undersampled data.
Definition: warpExposure.h:155
void _testWarpingKernels(SeparableKernel const &warpingKernel, SeparableKernel const &maskWarpingKernel) const
Throw an exception if the two kernels are not compatible in shape.
Lanczos warping: accurate but slow and can introduce ringing artifacts.
Definition: warpExposure.h:70
Point< double, 2 > Point2D
Definition: Point.h:288
ImageT::image_category image_category
Definition: Image.h:78
image warping
virtual boost::shared_ptr< Kernel > clone() const
Return a pointer to a deep copy of this kernel.
Wrap an AffineTransform.
Definition: XYTransform.h:152
Kernels are used for convolution with MaskedImages and (eventually) Images.
Definition: Kernel.h:131
int col
Definition: CR.cc:157
Functions to handle coordinates.