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
SkyWcs.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2017 AURA/LSST.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <http://www.lsstcorp.org/LegalNotices/>.
21  */
22 
23 #include <algorithm>
24 #include <cmath>
25 #include <cstdint>
26 #include <exception>
27 #include <memory>
28 #include <ostream>
29 #include <sstream>
30 #include <vector>
31 
32 #include "astshim.h"
33 
34 #include "lsst/geom/Angle.h"
35 #include "lsst/geom/Point.h"
36 #include "lsst/geom/SpherePoint.h"
38 #include "lsst/afw/table.h"
43 #include "lsst/afw/geom/wcsUtils.h"
44 #include "lsst/afw/geom/SkyWcs.h"
46 #include "lsst/pex/exceptions.h"
47 #include "lsst/afw/table/io/Persistable.cc"
48 
49 namespace lsst {
50 namespace afw {
51 
54 
55 namespace geom {
56 namespace {
57 
58 int const SERIALIZATION_VERSION = 1;
59 
60 // TIGHT_FITS_TOL is used by getFitsMetadata to determine if a WCS can accurately be represented as a FITS
61 // WCS. It specifies the maximum departure from linearity (in pixels) allowed on either axis of the mapping
62 // from pixel coordinates to Intermediate World Coordinates over a range of 100 x 100 pixels
63 // (or the region specified by NAXIS[12], if provided, but we do not pass this to AST as of 2018-01-17).
64 // For more information,
65 // see FitsTol in the AST manual http://starlink.eao.hawaii.edu/devdocs/sun211.htx/sun211.html
66 double const TIGHT_FITS_TOL = 0.0001;
67 
68 class SkyWcsPersistenceHelper {
69 public:
70  table::Schema schema;
71  table::Key<table::Array<std::uint8_t>> wcs;
72 
73  static SkyWcsPersistenceHelper const& get() {
74  static SkyWcsPersistenceHelper instance;
75  return instance;
76  }
77 
78  // No copying
79  SkyWcsPersistenceHelper(const SkyWcsPersistenceHelper&) = delete;
80  SkyWcsPersistenceHelper& operator=(const SkyWcsPersistenceHelper&) = delete;
81 
82  // No moving
83  SkyWcsPersistenceHelper(SkyWcsPersistenceHelper&&) = delete;
84  SkyWcsPersistenceHelper& operator=(SkyWcsPersistenceHelper&&) = delete;
85 
86 private:
87  SkyWcsPersistenceHelper()
88  : schema(),
89  wcs(schema.addField<table::Array<std::uint8_t>>("wcs", "wcs string representation", "")) {
90  schema.getCitizen().markPersistent();
91  }
92 };
93 
94 class SkyWcsFactory : public table::io::PersistableFactory {
95 public:
96  explicit SkyWcsFactory(std::string const& name) : table::io::PersistableFactory(name) {}
97 
98  std::shared_ptr<table::io::Persistable> read(InputArchive const& archive,
99  CatalogVector const& catalogs) const override {
100  SkyWcsPersistenceHelper const& keys = SkyWcsPersistenceHelper::get();
101  LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
102  LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u);
103  LSST_ARCHIVE_ASSERT(catalogs.front().getSchema() == keys.schema);
104  table::BaseRecord const& record = catalogs.front().front();
105  std::string stringRep = formatters::bytesToString(record.get(keys.wcs));
106  return SkyWcs::readString(stringRep);
107  }
108 };
109 
110 std::string getSkyWcsPersistenceName() { return "SkyWcs"; }
111 
112 SkyWcsFactory registration(getSkyWcsPersistenceName());
113 
114 ast::FrameDict makeSkyWcsFrameDict(TransformPoint2ToPoint2 const& pixelsToFieldAngle,
115  lsst::geom::Angle const& orientation, bool flipX,
117  std::string const& projection = "TAN") {
118  auto const orientationAndFlipXMatrix = makeCdMatrix(1 * lsst::geom::degrees, orientation, flipX);
119  auto const initialWcs = makeSkyWcs(lsst::geom::Point2D(0, 0), crval, orientationAndFlipXMatrix, projection);
120  auto const initialFrameDict = initialWcs->getFrameDict();
121  auto const iwcToSkyMap = initialFrameDict->getMapping("IWC", "SKY");
122  auto const pixelFrame = initialFrameDict->getFrame("PIXELS");
123  auto const iwcFrame = initialFrameDict->getFrame("IWC");
124  auto const skyFrame = initialFrameDict->getFrame("SKY");
125  // Field angle is in radians and is aligned to focal plane x and y;
126  // IWC is basically the same thing, but in degrees and with rotation and flipX applied
127  ndarray::Array<double, 2, 2> fieldAngleToIwcNdArray = ndarray::allocate(2, 2);
128  asEigenMatrix(fieldAngleToIwcNdArray) = orientationAndFlipXMatrix * 180.0 / lsst::geom::PI;
129  auto const pixelsToFieldAngleMap = pixelsToFieldAngle.getMapping();
130  auto const fieldAngleToIwcMap = ast::MatrixMap(fieldAngleToIwcNdArray);
131  auto const pixelsToIwcMap = pixelsToFieldAngleMap->then(fieldAngleToIwcMap);
132  auto finalFrameDict = ast::FrameDict(*pixelFrame, pixelsToIwcMap, *iwcFrame);
133  finalFrameDict.addFrame("IWC", *iwcToSkyMap, *skyFrame);
134  return finalFrameDict;
135 }
136 
137 } // namespace
138 
140  bool flipX) {
141  Eigen::Matrix2d cdMatrix;
142  double orientRad = orientation.asRadians();
143  double scaleDeg = scale.asDegrees();
144  double xmult = flipX ? 1.0 : -1.0;
145  cdMatrix(0, 0) = std::cos(orientRad) * scaleDeg * xmult;
146  cdMatrix(0, 1) = std::sin(orientRad) * scaleDeg;
147  cdMatrix(1, 0) = -std::sin(orientRad) * scaleDeg * xmult;
148  cdMatrix(1, 1) = std::cos(orientRad) * scaleDeg;
149  return cdMatrix;
150 }
151 
153  auto const dstInverse = dst.getTransform()->inverted();
154  return src.getTransform()->then(*dstInverse);
155 }
156 
157 SkyWcs::SkyWcs(daf::base::PropertySet& metadata, bool strip)
158  : SkyWcs(detail::readLsstSkyWcs(metadata, strip)) {}
159 
160 SkyWcs::SkyWcs(ast::FrameDict const& frameDict) : SkyWcs(_checkFrameDict(frameDict)) {}
161 
162 bool SkyWcs::operator==(SkyWcs const& other) const { return writeString() == other.writeString(); }
163 
165  // Compute pixVec containing the pixel position and two nearby points
166  // (use a vector so all three points can be converted to sky in a single call)
167  double const side = 1.0;
169  pixel, pixel + lsst::geom::Extent2D(side, 0), pixel + lsst::geom::Extent2D(0, side),
170  };
171 
172  auto skyVec = pixelToSky(pixVec);
173 
174  // Work in 3-space to avoid RA wrapping and pole issues
175  auto skyLL = skyVec[0].getVector();
176  auto skyDx = skyVec[1].getVector() - skyLL;
177  auto skyDy = skyVec[2].getVector() - skyLL;
178 
179  // Compute pixel scale in radians = sqrt(pixel area in radians^2)
180  // pixel area in radians^2 = area of parallelogram with sides skyDx, skyDy = |skyDx cross skyDy|
181  // Use squared norm to avoid two square roots
182  double skyAreaSq = skyDx.cross(skyDy).getSquaredNorm();
183  return (std::pow(skyAreaSq, 0.25) / side) * lsst::geom::radians;
184 }
185 
187  // CRVAL is stored as the SkyRef property of the sky frame (the current frame of the SkyWcs)
189  getFrameDict()->getFrame(ast::FrameDict::CURRENT, false)); // false: do not copy
190  if (!skyFrame) {
191  throw LSST_EXCEPT(pex::exceptions::LogicError, "Current frame is not a SkyFrame");
192  }
193  auto const crvalRad = skyFrame->getSkyRef();
194  return lsst::geom::SpherePoint(crvalRad[0] * lsst::geom::radians, crvalRad[1] * lsst::geom::radians);
195 }
196 
197 Eigen::Matrix2d SkyWcs::getCdMatrix(lsst::geom::Point2D const& pixel) const {
198  auto const pixelToIwc = getFrameDict()->getMapping(ast::FrameSet::BASE, "IWC");
199  auto const pixelToIwcTransform = TransformPoint2ToPoint2(*pixelToIwc);
200  return pixelToIwcTransform.getJacobian(pixel);
201 }
202 
203 Eigen::Matrix2d SkyWcs::getCdMatrix() const { return getCdMatrix(getPixelOrigin()); }
204 
206  auto const crval = pixelToSky(pixel);
207  auto const cdMatrix = getCdMatrix(pixel);
208  auto metadata = makeSimpleWcsMetadata(pixel, crval, cdMatrix);
209  return std::make_shared<SkyWcs>(*metadata);
210 }
211 
213  auto newToOldPixel = TransformPoint2ToPoint2(ast::ShiftMap({-shift[0], -shift[1]}));
214  return makeModifiedWcs(newToOldPixel, *this, true);
215 }
216 
218  // Make a FrameSet that maps from GRID to SKY; GRID = the base frame (PIXELS or ACTUAL_PIXELS) + 1
219  auto const gridToPixel = ast::ShiftMap({-1.0, -1.0});
220  auto thisDict = getFrameDict();
221  auto const pixelToIwc = thisDict->getMapping(ast::FrameSet::BASE, "IWC");
222  auto const iwcToSky = thisDict->getMapping("IWC", "SKY");
223  auto const gridToSky = gridToPixel.then(*pixelToIwc).then(*iwcToSky);
224  ast::FrameSet frameSet(ast::Frame(2, "Domain=GRID"), gridToSky, *thisDict->getFrame("SKY", false));
225 
226  // Write frameSet to a FitsChan and extract the metadata
228  os << "Encoding=FITS-WCS, CDMatrix=1, FitsAxisOrder=<copy>, FitsTol=" << TIGHT_FITS_TOL;
229  ast::StringStream strStream;
230  ast::FitsChan fitsChan(strStream, os.str());
231  int const nObjectsWritten = fitsChan.write(frameSet);
232  if (nObjectsWritten == 0) {
233  if (precise) {
235  "Could not represent this SkyWcs using FITS-WCS metadata");
236  } else {
237  // An exact representation could not be written, so try to write a local TAN approximation;
238  // set precise true to avoid an infinite loop, should something go wrong
239  auto tanWcs = getTanWcs(getPixelOrigin());
240  return tanWcs->getFitsMetadata(true);
241  }
242  }
244 }
245 
247 
248 bool SkyWcs::isFits() const {
249  try {
250  getFitsMetadata(true);
251  } catch (const lsst::pex::exceptions::RuntimeError&) {
252  return false;
253  } catch (const std::runtime_error&) {
254  return false;
255  }
256  return true;
257 }
258 
260  lsst::geom::AngleUnit const& skyUnit) const {
261  return _linearizePixelToSky(skyToPixel(coord), coord, skyUnit);
262 }
264  lsst::geom::AngleUnit const& skyUnit) const {
265  return _linearizePixelToSky(pix, pixelToSky(pix), skyUnit);
266 }
267 
269  lsst::geom::AngleUnit const& skyUnit) const {
270  return _linearizeSkyToPixel(skyToPixel(coord), coord, skyUnit);
271 }
272 
274  lsst::geom::AngleUnit const& skyUnit) const {
275  return _linearizeSkyToPixel(pix, pixelToSky(pix), skyUnit);
276 }
277 
278 std::string SkyWcs::getShortClassName() { return "SkyWcs"; };
279 
280 bool SkyWcs::isFlipped() const {
281  double det = getCdMatrix().determinant();
282  if (det == 0) {
283  throw(LSST_EXCEPT(pex::exceptions::RuntimeError, "CD matrix is singular"));
284  }
285  return (det > 0);
286 }
287 
289  int version;
290  is >> version;
291  if (version != 1) {
292  throw LSST_EXCEPT(pex::exceptions::TypeError, "Unsupported version " + std::to_string(version));
293  }
294  std::string shortClassName;
295  is >> shortClassName;
296  if (shortClassName != SkyWcs::getShortClassName()) {
298  os << "Class name in stream " << shortClassName << " != " << SkyWcs::getShortClassName();
300  }
302  is >> hasFitsApproximation;
303  auto astStream = ast::Stream(&is, nullptr);
304  auto astObjectPtr = ast::Channel(astStream).read();
305  auto frameSet = std::dynamic_pointer_cast<ast::FrameSet>(astObjectPtr);
306  if (!frameSet) {
308  os << "The AST serialization was read as a " << astObjectPtr->getClassName()
309  << " instead of a FrameSet";
311  }
313  return std::make_shared<SkyWcs>(frameDict);
314 }
315 
317  std::istringstream is(str);
318  return SkyWcs::readStream(is);
319 }
320 
322  os << SERIALIZATION_VERSION << " " << SkyWcs::getShortClassName() << " " << hasFitsApproximation() << " ";
323  getFrameDict()->show(os, false); // false = do not write comments
324 }
325 
328  writeStream(os);
329  return os.str();
330 }
331 
332 std::string SkyWcs::getPersistenceName() const { return getSkyWcsPersistenceName(); }
333 
334 std::string SkyWcs::getPythonModule() const { return "lsst.afw.geom"; }
335 
336 void SkyWcs::write(OutputArchiveHandle& handle) const {
337  SkyWcsPersistenceHelper const& keys = SkyWcsPersistenceHelper::get();
338  table::BaseCatalog cat = handle.makeCatalog(keys.schema);
340  record->set(keys.wcs, formatters::stringToBytes(writeString()));
341  handle.saveCatalog(cat);
342 }
343 
345  : _frameDict(frameDict), _transform(), _pixelOrigin(), _pixelScaleAtOrigin(0 * lsst::geom::radians) {
346  _computeCache();
347 };
348 
349 std::shared_ptr<ast::FrameDict> SkyWcs::_checkFrameDict(ast::FrameDict const& frameDict) const {
350  // Check that each frame is present and has the right type and number of axes
351  std::vector<std::string> const domainNames = {"ACTUAL_PIXELS", "PIXELS", "IWC", "SKY"};
352  for (auto const& domainName : domainNames) {
353  if (frameDict.hasDomain(domainName)) {
354  auto const frame = frameDict.getFrame(domainName, false);
355  if (frame->getNAxes() != 2) {
357  "Frame " + domainName + " has " + std::to_string(frame->getNAxes()) +
358  " axes instead of 2");
359  }
360  auto desiredClassName = domainName == "SKY" ? "SkyFrame" : "Frame";
361  if (frame->getClassName() != desiredClassName) {
363  "Frame " + domainName + " is of type " + frame->getClassName() +
364  " instead of " + desiredClassName);
365  }
366  } else if (domainName != "ACTUAL_PIXELS") {
367  // This is a required frame
369  "No frame with domain " + domainName + " found");
370  }
371  }
372 
373  // The base frame must have domain "PIXELS" or "ACTUAL_PIXELS"
374  auto baseDomain = frameDict.getFrame(ast::FrameSet::BASE, false)->getDomain();
375  if (baseDomain != "ACTUAL_PIXELS" && baseDomain != "PIXELS") {
377  "Base frame has domain " + baseDomain + " instead of PIXELS or ACTUAL_PIXELS");
378  }
379 
380  // The current frame must have domain "SKY"
381  auto currentDomain = frameDict.getFrame(ast::FrameSet::CURRENT, false)->getDomain();
382  if (currentDomain != "SKY") {
384  "Current frame has domain " + currentDomain + " instead of SKY");
385  }
386 
387  return frameDict.copy();
388 }
389 
390 lsst::geom::AffineTransform SkyWcs::_linearizePixelToSky(lsst::geom::Point2D const& pix00,
391  lsst::geom::SpherePoint const& coord,
392  lsst::geom::AngleUnit const& skyUnit) const {
393  // Figure out the (0, 0), (0, 1), and (1, 0) ra/dec coordinates of the corners
394  // of a square drawn in pixel. It'd be better to center the square at sky00,
395  // but that would involve another conversion between sky and pixel coordinates
396  const double side = 1.0; // length of the square's sides in pixels
397  auto const sky00 = coord.getPosition(skyUnit);
398  auto const dsky10 = coord.getTangentPlaneOffset(pixelToSky(pix00 + lsst::geom::Extent2D(side, 0)));
399  auto const dsky01 = coord.getTangentPlaneOffset(pixelToSky(pix00 + lsst::geom::Extent2D(0, side)));
400 
401  Eigen::Matrix2d m;
402  m(0, 0) = dsky10.first.asAngularUnits(skyUnit) / side;
403  m(0, 1) = dsky01.first.asAngularUnits(skyUnit) / side;
404  m(1, 0) = dsky10.second.asAngularUnits(skyUnit) / side;
405  m(1, 1) = dsky01.second.asAngularUnits(skyUnit) / side;
406 
407  Eigen::Vector2d sky00v;
408  sky00v << sky00.getX(), sky00.getY();
409  Eigen::Vector2d pix00v;
410  pix00v << pix00.getX(), pix00.getY();
411  // return lsst::geom::AffineTransform(m, lsst::geom::Extent2D(sky00v - m * pix00v));
412  return lsst::geom::AffineTransform(m, (sky00v - m * pix00v));
413 }
414 
415 lsst::geom::AffineTransform SkyWcs::_linearizeSkyToPixel(lsst::geom::Point2D const& pix00,
416  lsst::geom::SpherePoint const& coord,
417  lsst::geom::AngleUnit const& skyUnit) const {
418  lsst::geom::AffineTransform inverse = _linearizePixelToSky(pix00, coord, skyUnit);
419  return inverse.inverted();
420 }
421 
422 std::shared_ptr<SkyWcs> makeFlippedWcs(SkyWcs const& wcs, bool flipLR, bool flipTB,
423  lsst::geom::Point2D const& center) {
424  double const dx = 1000; // any "reasonable" number of pixels will do
425  std::vector<double> inLL = {center[0] - dx, center[1] - dx};
426  std::vector<double> inUR = {center[0] + dx, center[1] + dx};
427  std::vector<double> outLL(inLL);
428  std::vector<double> outUR(inUR);
429  if (flipLR) {
430  outLL[0] = inUR[0];
431  outUR[0] = inLL[0];
432  }
433  if (flipTB) {
434  outLL[1] = inUR[1];
435  outUR[1] = inLL[1];
436  }
437  auto const flipPix = TransformPoint2ToPoint2(ast::WinMap(inLL, inUR, outLL, outUR));
438  return makeModifiedWcs(flipPix, wcs, true);
439 }
440 
442  bool modifyActualPixels) {
443  auto const pixelMapping = pixelTransform.getMapping();
444  auto oldFrameDict = wcs.getFrameDict();
445  bool const hasActualPixels = oldFrameDict->hasDomain("ACTUAL_PIXELS");
446  auto const pixelFrame = oldFrameDict->getFrame("PIXELS", false);
447  auto const iwcFrame = oldFrameDict->getFrame("IWC", false);
448  auto const skyFrame = oldFrameDict->getFrame("SKY", false);
449  auto const oldPixelToIwc = oldFrameDict->getMapping("PIXELS", "IWC");
450  auto const iwcToSky = oldFrameDict->getMapping("IWC", "SKY");
451 
452  std::shared_ptr<ast::FrameDict> newFrameDict;
453  std::shared_ptr<ast::Mapping> newPixelToIwc;
454  if (hasActualPixels) {
455  auto const actualPixelFrame = oldFrameDict->getFrame("ACTUAL_PIXELS", false);
456  auto const oldActualPixelToPixels = oldFrameDict->getMapping("ACTUAL_PIXELS", "PIXELS");
457  std::shared_ptr<ast::Mapping> newActualPixelsToPixels;
458  if (modifyActualPixels) {
459  newActualPixelsToPixels = pixelMapping->then(*oldActualPixelToPixels).simplified();
460  newPixelToIwc = oldPixelToIwc;
461  } else {
462  newActualPixelsToPixels = oldActualPixelToPixels;
463  newPixelToIwc = pixelMapping->then(*oldPixelToIwc).simplified();
464  }
465  newFrameDict =
466  std::make_shared<ast::FrameDict>(*actualPixelFrame, *newActualPixelsToPixels, *pixelFrame);
467  newFrameDict->addFrame("PIXELS", *newPixelToIwc, *iwcFrame);
468  } else {
469  newPixelToIwc = pixelMapping->then(*oldPixelToIwc).simplified();
470  newFrameDict = std::make_shared<ast::FrameDict>(*pixelFrame, *newPixelToIwc, *iwcFrame);
471  }
472  newFrameDict->addFrame("IWC", *iwcToSky, *skyFrame);
473  return std::make_shared<SkyWcs>(*newFrameDict);
474 }
475 
477  return std::make_shared<SkyWcs>(metadata, strip);
478 }
479 
481  Eigen::Matrix2d const& cdMatrix, std::string const& projection) {
482  auto metadata = makeSimpleWcsMetadata(crpix, crval, cdMatrix, projection);
483  return std::make_shared<SkyWcs>(*metadata);
484 }
485 
487  lsst::geom::Angle const& orientation, bool flipX,
488  lsst::geom::SpherePoint const& boresight, std::string const& projection) {
489  auto frameDict = makeSkyWcsFrameDict(pixelsToFieldAngle, orientation, flipX, boresight, projection);
490  return std::make_shared<SkyWcs>(frameDict);
491 }
492 
494  Eigen::Matrix2d const& cdMatrix, Eigen::MatrixXd const& sipA,
495  Eigen::MatrixXd const& sipB) {
496  auto metadata = makeTanSipMetadata(crpix, crval, cdMatrix, sipA, sipB);
497  return std::make_shared<SkyWcs>(*metadata);
498 }
499 
501  Eigen::Matrix2d const& cdMatrix, Eigen::MatrixXd const& sipA,
502  Eigen::MatrixXd const& sipB, Eigen::MatrixXd const& sipAp,
503  Eigen::MatrixXd const& sipBp) {
504  auto metadata = makeTanSipMetadata(crpix, crval, cdMatrix, sipA, sipB, sipAp, sipBp);
505  return std::make_shared<SkyWcs>(*metadata);
506 }
507 
509  bool simplify) {
510  auto iwcToSky = wcs.getFrameDict()->getMapping("IWC", "SKY");
511  return std::make_shared<TransformPoint2ToSpherePoint>(*iwcToSky, simplify);
512 }
513 
515  auto pixelToIwc = wcs.getFrameDict()->getMapping(ast::FrameSet::BASE, "IWC");
516  return std::make_shared<TransformPoint2ToPoint2>(*pixelToIwc, simplify);
517 }
518 
520  os << "SkyWcs";
521  return os;
522 };
523 
524 } // namespace geom
525 } // namespace afw
526 } // namespace lsst
table::Key< table::Array< std::uint8_t > > frameSet
std::pair< Angle, Angle > getTangentPlaneOffset(SpherePoint const &other) const
Get the offset from a tangent plane centered at this point to another point.
Definition: SpherePoint.cc:214
static std::shared_ptr< T > dynamicCast(std::shared_ptr< Persistable > const &ptr)
Dynamically cast a shared_ptr.
Definition: Persistable.cc:18
A 2-dimensional celestial WCS that transform pixels to ICRS RA/Dec, using the LSST standard for pixel...
Definition: SkyWcs.h:115
std::shared_ptr< SkyWcs > getTanWcs(lsst::geom::Point2D const &pixel) const
Get a local TAN WCS approximation to this WCS at the specified pixel position.
Definition: SkyWcs.cc:205
constexpr double asRadians() const noexcept
Return an Angle&#39;s value in radians.
Definition: Angle.h:166
MatrixMap is a form of Mapping which performs a general linear transformation.
Definition: MatrixMap.h:42
constexpr double asDegrees() const noexcept
Return an Angle&#39;s value in degrees.
Definition: Angle.h:169
lsst::geom::Point2D skyToPixel(lsst::geom::SpherePoint const &sky) const
Compute pixel position(s) from sky position(s)
Definition: SkyWcs.h:347
An object passed to Persistable::write to allow it to persist itself.
An affine coordinate transformation consisting of a linear transformation and an offset.
lsst::geom::SpherePoint pixelToSky(lsst::geom::Point2D const &pixel) const
Compute sky position(s) from pixel position(s)
Definition: SkyWcs.h:332
std::shared_ptr< const ast::Mapping > getMapping() const
Get the contained mapping.
Definition: Transform.h:135
bool isFits() const
Return true getFitsMetadata(true) will succeed, false if not.
Definition: SkyWcs.cc:248
table::PointKey< double > crpix
Definition: OldWcs.cc:131
Point2D getPosition(AngleUnit unit) const noexcept
Return longitude, latitude as a Point2D object.
Definition: SpherePoint.cc:129
def scale(algorithm, min, max=None, frame=None)
Definition: ds9.py:109
T to_string(T... args)
Channel provides input/output of AST objects.
Definition: Channel.h:60
std::ostream & operator<<(std::ostream &os, GenericEndpoint const &endpoint)
Print "GenericEndpoint(_n_)" to the ostream where _n_ is the number of axes, e.g. "GenericAxes(4)"...
Definition: Endpoint.cc:240
SeriesMap then(Mapping const &next) const
Return a series compound mapping this(first(input)) containing shallow copies of the original...
Definition: Mapping.cc:37
std::shared_ptr< SkyWcs > makeModifiedWcs(TransformPoint2ToPoint2 const &pixelTransform, SkyWcs const &wcs, bool modifyActualPixels)
Create a new SkyWcs whose pixels are transformed by pixelTransform, as described below.
Definition: SkyWcs.cc:441
std::string getPythonModule() const override
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
Definition: SkyWcs.cc:334
table::PointKey< double > crval
Definition: OldWcs.cc:130
std::shared_ptr< ast::FrameDict > readLsstSkyWcs(daf::base::PropertySet &metadata, bool strip=true)
Read an LSST celestial WCS FrameDict from a FITS header.
lsst::geom::SpherePoint getSkyOrigin() const
Get the sky origin, the celestial fiducial point.
Definition: SkyWcs.cc:186
static int constexpr CURRENT
index of current frame
Definition: FrameSet.h:105
std::string bytesToString(ndarray::Array< std::uint8_t const, 1, 1 > const &bytes)
Decode a std::string from a vector of uint8 returned by stringToBytes.
Definition: Utils.cc:173
STL class.
std::shared_ptr< const ast::FrameDict > getFrameDict() const
Get the contained FrameDict.
Definition: SkyWcs.cc:246
AngleUnit constexpr radians
constant with units of radians
Definition: Angle.h:108
A class representing an angle.
Definition: Angle.h:127
A specialized form of Channel which reads and writes FITS header cards.
Definition: FitsChan.h:201
table::Key< table::Array< std::uint8_t > > wcs
Definition: SkyWcs.cc:71
Transform< Point2Endpoint, Point2Endpoint > TransformPoint2ToPoint2
Definition: Transform.h:300
STL class.
T sin(T... args)
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
Definition: SkyWcs.cc:332
A WinMap is a linear Mapping which transforms a rectangular window in one coordinate system into a si...
Definition: WinMap.h:45
Eigen::Matrix2d getCdMatrix() const
Get the 2x2 CD matrix at the pixel origin.
Definition: SkyWcs.cc:203
std::shared_ptr< const TransformPoint2ToSpherePoint > getTransform() const
Get a TransformPoint2ToSpherePoint that transforms pixels to sky in the forward direction and sky to ...
Definition: SkyWcs.h:255
AngleUnit constexpr degrees
constant with units of degrees
Definition: Angle.h:109
SkyFrame is a specialised form of Frame which describes celestial longitude/latitude coordinate syste...
Definition: SkyFrame.h:66
A base class for image defects.
bool hasFitsApproximation() const
Does this SkyWcs have an approximate SkyWcs that can be represented as standard FITS WCS...
Definition: SkyWcs.h:362
std::shared_ptr< SkyWcs > makeFlippedWcs(SkyWcs const &wcs, bool flipLR, bool flipTB, lsst::geom::Point2D const &center)
Return a copy of a FITS-WCS with pixel positions flipped around a specified center.
Definition: SkyWcs.cc:422
Frame is used to represent a coordinate system.
Definition: Frame.h:157
std::shared_ptr< Frame > getFrame(std::string const &domain, bool copy=true) const
Variant of getFrame(int, bool) where the frame is specified by domain name.
Definition: FrameDict.h:151
std::shared_ptr< FrameDict > copy() const
Return a deep copy of this object.
Definition: FrameDict.h:123
static std::shared_ptr< SkyWcs > readStream(std::istream &is)
Deserialize a SkyWcs from an input stream.
Definition: SkyWcs.cc:288
lsst::geom::AffineTransform linearizePixelToSky(lsst::geom::SpherePoint const &coord, lsst::geom::AngleUnit const &skyUnit) const
Return the local linear approximation to pixelToSky at a point given in sky coordinates.
Definition: SkyWcs.cc:259
T str(T... args)
std::shared_ptr< daf::base::PropertyList > getPropertyListFromFitsChan(ast::FitsChan &fitsChan)
Copy values from an AST FitsChan into a PropertyList.
T cos(T... args)
T dynamic_pointer_cast(T... args)
static std::string getShortClassName()
Definition: SkyWcs.cc:278
std::shared_ptr< TransformPoint2ToPoint2 > getPixelToIntermediateWorldCoords(SkyWcs const &wcs, bool simplify=true)
Return a transform from pixel coordinates to intermediate world coordinates.
Definition: SkyWcs.cc:514
std::shared_ptr< SkyWcs > makeTanSipWcs(lsst::geom::Point2D const &crpix, lsst::geom::SpherePoint const &crval, Eigen::Matrix2d const &cdMatrix, Eigen::MatrixXd const &sipA, Eigen::MatrixXd const &sipB)
Construct a TAN-SIP SkyWcs with forward SIP distortion terms and an iterative inverse.
Definition: SkyWcs.cc:493
std::shared_ptr< TransformPoint2ToSpherePoint > getIntermediateWorldCoordsToSky(SkyWcs const &wcs, bool simplify=true)
Return a transform from intermediate world coordinates to sky.
Definition: SkyWcs.cc:508
Reports errors in the logical structure of the program.
Definition: Runtime.h:46
ShiftMap is a linear Mapping which shifts each axis by a specified constant value.
Definition: ShiftMap.h:40
std::shared_ptr< RecordT > src
Definition: Match.cc:48
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
std::shared_ptr< daf::base::PropertyList > makeTanSipMetadata(lsst::geom::Point2D const &crpix, lsst::geom::SpherePoint const &crval, Eigen::Matrix2d const &cdMatrix, Eigen::MatrixXd const &sipA, Eigen::MatrixXd const &sipB)
Make metadata for a TAN-SIP WCS without inverse matrices.
Definition: wcsUtils.cc:198
std::shared_ptr< SkyWcs > copyAtShiftedPixelOrigin(lsst::geom::Extent2D const &shift) const
Return a copy of this SkyWcs with the pixel origin shifted by the specified amount.
Definition: SkyWcs.cc:212
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
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
std::shared_ptr< daf::base::PropertyList > makeSimpleWcsMetadata(lsst::geom::Point2D const &crpix, lsst::geom::SpherePoint const &crval, Eigen::Matrix2d const &cdMatrix, std::string const &projection="TAN")
Make FITS metadata for a simple FITS WCS (one with no distortion).
Definition: wcsUtils.cc:172
STL class.
Point in an unspecified spherical coordinate system.
Definition: SpherePoint.h:57
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition: Persistable.h:48
static std::shared_ptr< SkyWcs > readString(std::string &str)
Deserialize a SkyWcs from a string, using the same format as readStream.
Definition: SkyWcs.cc:316
lsst::geom::Point2D getPixelOrigin() const
Get the pixel origin, in pixels, using the LSST convention.
Definition: SkyWcs.h:213
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Definition: SkyWcs.cc:336
T pow(T... args)
SkyWcs(SkyWcs const &)=default
Class for storing generic metadata.
Definition: PropertySet.h:68
std::string writeString() const
Serialize this SkyWcs to a string, using the same format as writeStream.
Definition: SkyWcs.cc:326
std::shared_ptr< SkyWcs > makeSkyWcs(daf::base::PropertySet &metadata, bool strip=false)
Construct a SkyWcs from FITS keywords.
Definition: SkyWcs.cc:476
std::shared_ptr< daf::base::PropertyList > getFitsMetadata(bool precise=false) const
Return the WCS as FITS WCS metadata.
Definition: SkyWcs.cc:217
Eigen::Matrix2d makeCdMatrix(lsst::geom::Angle const &scale, lsst::geom::Angle const &orientation=0 *lsst::geom::degrees, bool flipX=false)
Make a WCS CD matrix.
Definition: SkyWcs.cc:139
String-based source and sink for channels.
Definition: Stream.h:180
int m
Definition: SpanSet.cc:49
lsst::geom::SpherePoint SpherePoint
Definition: misc.h:35
table::PointKey< int > pixel
void writeStream(std::ostream &os) const
Serialize this SkyWcs to an output stream.
Definition: SkyWcs.cc:321
ItemVariant const * other
Definition: Schema.cc:56
static int constexpr BASE
index of base frame
Definition: FrameSet.h:104
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
table::Key< int > version
Definition: PhotoCalib.cc:272
bool isFlipped() const
Does the WCS follow the convention of North=Up, East=Left?
Definition: SkyWcs.cc:280
ndarray::Array< std::uint8_t, 1, 1 > stringToBytes(std::string const &str)
Encode a std::string as a vector of uint8.
Definition: Utils.cc:162
Extent< double, 2 > Extent2D
Definition: Extent.h:400
lsst::geom::AffineTransform linearizeSkyToPixel(lsst::geom::SpherePoint const &coord, lsst::geom::AngleUnit const &skyUnit) const
Return the local linear approximation to skyToPixel at a point given in sky coordinates.
Definition: SkyWcs.cc:268
table::Schema schema
Definition: SkyWcs.cc:70
Reports errors from accepting an object of an unexpected or inappropriate type.
Definition: Runtime.h:167
lsst::geom::Angle getPixelScale() const
Get the pixel scale at the pixel origin.
Definition: SkyWcs.h:206
A FrameSet whose frames can be referenced by domain name.
Definition: FrameDict.h:67
STL class.
bool operator==(SkyWcs const &other) const
Equality is based on the string representations being equal.
Definition: SkyWcs.cc:162
AffineTransform const inverted() const
Return the inverse transform.
std::shared_ptr< Object > read()
Read an object from a channel.
Definition: Channel.cc:50
A stream for ast::Channel.
Definition: Stream.h:41
A FrameSet consists of a set of one or more Frames (which describe coordinate systems), connected together by Mappings (which describe how the coordinate systems are inter-related).
Definition: FrameSet.h:99
double constexpr PI
The ratio of a circle&#39;s circumference to diameter.
Definition: Angle.h:39
bool strip
Definition: fits.cc:831
A class used to convert scalar POD types such as double to Angle.
Definition: Angle.h:70
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
bool hasDomain(std::string const &domain) const
Return True if a frame in this FrameDict has the specified domain.
Definition: FrameDict.h:201
Reports errors that are due to events beyond the control of the program.
Definition: Runtime.h:104
std::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
Definition: Catalog.h:472