LSSTApplications  11.0-22-g33de520,13.0+153,14.0+52,14.0+57,14.0-1-g013352c+36,14.0-1-g13ef843+9,14.0-1-g4b114ac+14,14.0-1-g7257b6a+12,14.0-1-g8b7e855+51,14.0-13-g7a60b79+2,14.0-14-g87d16e8+10,14.0-14-gbf7a6f8a,14.0-17-g4f4ea82+5,14.0-2-g319577b+11,14.0-2-ga5af9b6+10,14.0-22-gc48c03f+3,14.0-3-g20413be+3,14.0-46-g76222d5f+3,14.0-47-g0a51fac97,14.0-5-g744ff5f+2,14.0-5-g86eb1bd+31,14.0-6-gd5b81a9+6,14.0-6-ge2c9487+42,14.0-8-g7f6dd6b+6,14.0-8-gb81b6e9+4,14.0-9-g11010eb,14.0-9-g330837b+5
LSSTDataManagementBasePackage
makeWcs.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
25 #include <memory>
26 #include "Eigen/Core"
27 #include "lsst/log/Log.h"
28 #include "lsst/afw/image/Wcs.h"
29 #include "lsst/afw/image/TanWcs.h"
30 
31 namespace except = lsst::pex::exceptions;
32 
33 namespace lsst {
34 namespace afw {
35 namespace image {
36 
38  //
39  // _metadata is not const (it is probably meant to be), but we don't want to modify it.
40  //
41  auto metadata = _metadata; // we'll make a copy and modify metadata if needs be
42  auto modifyable = false; // ... and set this variable to say that we did
43 
45  if (metadata->exists("CTYPE1") && metadata->exists("CTYPE2")) {
46  ctype1 = metadata->getAsString("CTYPE1");
47  ctype2 = metadata->getAsString("CTYPE2");
48  } else {
49  LOGL_DEBUG("makeWcs", "Unable to construct valid WCS due to missing CTYPE1 or CTYPE2");
50  return std::shared_ptr<Wcs>();
51  }
52  //
53  // SCAMP used to use PVi_j keys with a CTYPE of TAN to specify a "TPV" projection
54  // (cf. https://github.com/astropy/astropy/issues/299
55  // and the discussion from Dave Berry in https://jira.lsstcorp.org/browse/DM-2883)
56  //
57  // Follow Dave's AST and switch TAN to TPV
58  //
59  if (ctype1.substr(5, 3) == "TAN" && (metadata->exists("PV1_5") || metadata->exists("PV2_1"))) {
60  LOGL_INFO("makeWcs", "Interpreting %s/%s + PVi_j as TPV", ctype1.c_str(), ctype2.c_str());
61 
62  if (!modifyable) {
63  metadata = _metadata->deepCopy();
64  modifyable = true;
65  }
66 
67  ctype1.replace(5, 3, "TPV");
68  metadata->set<std::string>("CTYPE1", ctype1);
69 
70  ctype2.replace(5, 3, "TPV");
71  metadata->set<std::string>("CTYPE2", ctype2);
72  }
73 
74  std::shared_ptr<Wcs> wcs; // we can't use make_shared as ctor is private
75  if (ctype1.substr(5, 3) == "TAN") {
76  wcs = std::shared_ptr<Wcs>(new TanWcs(metadata));
77  } else if (ctype1.substr(5, 3) == "TPV") { // unfortunately we don't support TPV
78  if (!modifyable) {
79  metadata = _metadata->deepCopy();
80  modifyable = true;
81  }
82 
83  LOGL_WARN("makeWcs", "Stripping PVi_j keys from projection %s/%s", ctype1.c_str(), ctype2.c_str());
84 
85  metadata->set<std::string>("CTYPE1", "RA---TAN");
86  metadata->set<std::string>("CTYPE2", "DEC--TAN");
87  metadata->set<bool>("TPV_WCS", true);
88  // PV1_[1-4] are in principle legal, although Swarp reuses them as part of the TPV parameterisation.
89  // It turns out that leaving PV1_[1-4] in the header breaks wcslib 4.14's ability to read
90  // DECam headers (DM-3196) so we'll delete them all for now.
91  //
92  // John Swinbank points out the maximum value of j in TVi_j is 39;
93  // http://fits.gsfc.nasa.gov/registry/tpvwcs/tpv.html
94  for (int i = 0; i != 2; ++i) {
95  for (int j = 1; j <= 39; ++j) { // 39's the max in the TPV standard
96  char pvName[8];
97  sprintf(pvName, "PV%d_%d", i, j);
98  if (metadata->exists(pvName)) {
99  metadata->remove(pvName);
100  }
101  }
102  }
103 
104  wcs = std::shared_ptr<Wcs>(new TanWcs(metadata));
105  } else {
106  wcs = std::shared_ptr<Wcs>(new Wcs(metadata));
107  }
108 
109  // If keywords LTV[1,2] are present, the image on disk is already a subimage, so
110  // we should shift the wcs to allow for this.
111  std::string key = "LTV1";
112  if (metadata->exists(key)) {
113  wcs->shiftReferencePixel(-metadata->getAsDouble(key), 0);
114  }
115 
116  key = "LTV2";
117  if (metadata->exists(key)) {
118  wcs->shiftReferencePixel(0, -metadata->getAsDouble(key));
119  }
120 
121  if (stripMetadata) {
122  detail::stripWcsKeywords(_metadata, wcs);
123  }
124 
125  return wcs;
126 }
127 
128 std::shared_ptr<Wcs> makeWcs(coord::Coord const& crval, geom::Point2D const& crpix, double CD11, double CD12,
129  double CD21, double CD22) {
130  Eigen::Matrix2d CD;
131  CD << CD11, CD12, CD21, CD22;
132  geom::Point2D crvalTmp;
133  crvalTmp[0] = crval.toIcrs().getLongitude().asDegrees();
134  crvalTmp[1] = crval.toIcrs().getLatitude().asDegrees();
135  return std::shared_ptr<Wcs>(new TanWcs(crvalTmp, crpix, CD));
136 }
137 }
138 }
139 } // end lsst::afw::image
lsst::afw::geom::Angle getLongitude() const
The main access method for the longitudinal coordinate.
Definition: Coord.h:166
int stripWcsKeywords(std::shared_ptr< lsst::daf::base::PropertySet > const &metadata, std::shared_ptr< Wcs const > const &wcs)
Definition: Wcs.cc:1143
std::shared_ptr< Wcs > makeWcs(std::shared_ptr< lsst::daf::base::PropertySet > const &fitsMetadata, bool stripMetadata=false)
Create a Wcs object from a fits header.
Definition: makeWcs.cc:37
table::PointKey< double > crval
Definition: Wcs.cc:934
virtual IcrsCoord toIcrs() const
Convert ourself to ICRS: RA, Dec (basically J2000)
Definition: Coord.cc:572
tbl::Key< int > wcs
Implementation of the WCS standard for a any projection.
Definition: Wcs.h:104
table::Key< std::string > ctype2
Definition: Wcs.cc:938
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Definition: Log.h:513
lsst::afw::geom::Angle getLatitude() const
The main access method for the latitudinal coordinate.
Definition: Coord.h:173
STL class.
LSST DM logging module built on log4cxx.
#define LOGL_INFO(logger, message...)
Log a info-level message using a varargs/printf style interface.
Definition: Log.h:529
A base class for image defects.
Definition: cameraGeom.dox:3
Implementation of the WCS standard for the special case of the Gnomonic (tangent plane) projection...
Definition: TanWcs.h:68
T replace(T... args)
#define LOGL_WARN(logger, message...)
Log a warn-level message using a varargs/printf style interface.
Definition: Log.h:545
T c_str(T... args)
T substr(T... args)
constexpr double asDegrees() const noexcept
Return an Angle&#39;s value in degrees.
Definition: Angle.h:144
This is the base class for spherical coordinates.
Definition: Coord.h:63
daf::base::PropertySet & _metadata
Definition: fits_io_mpl.h:83
table::Key< std::string > ctype1
Definition: Wcs.cc:937
table::PointKey< double > crpix
Definition: Wcs.cc:935