LSST Applications 30.0.7,g0e76e35be5+e8e946ae08,g19811a7679+138f7293ba,g199a45376c+5e234f8357,g1fd858c14a+2f48dbc4c4,g262e1987ae+fb36cac54d,g29ae962dfc+d9108a0941,g2c21b0017a+4f59a27f16,g31e44d4a5c+b0138be388,g33ac35c1f1+28b9f72785,g35bb328faa+b0138be388,g40c9b15c53+823ad735c1,g47891489e3+bcc48a0b46,g53246c7159+b0138be388,g64539dfbff+e8e946ae08,g67b6fd64d1+bcc48a0b46,g74acd417e5+422380537a,g76965917b2+a5ca99c4d9,g786e29fd12+796b79145d,g7aefaa3e3d+dc0c200193,g86b635cae8+734fe384f0,g87389fa792+d8b5378923,g89139ef638+bcc48a0b46,g8bbb235e95+3f4f7f9447,g8ea07a8fe4+78a4c88802,g9290983e33+ffdc83c6f7,g92c671f44c+e8e946ae08,gaa753fd333+03f406da14,gbf99507273+b0138be388,gc49b57b85e+8df26ee1f0,gca7fc764a6+bcc48a0b46,gd7ef33dd92+bcc48a0b46,gdab6d2f7ff+422380537a,ge1c02a5578+b0138be388,ge410e46f29+bcc48a0b46,ge80df9fc40+e6db5413d1,geaed405ab2+1de65a85c6,gf5dcc679e7+35a0ce2edd,gf5f1c85443+e8e946ae08
LSST Data Management Base Package
Loading...
Searching...
No Matches
wcsUtils.cc
Go to the documentation of this file.
1// -*- lsst-c++ -*-
2
3/*
4 * LSST Data Management System
5 * Copyright 2018 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 <cmath>
26#include <memory>
27#include <vector>
28
29#include "lsst/afw/table/fwd.h"
34
35namespace lsst {
36namespace afw {
37namespace table {
38namespace {
39
40// Get the schema from a record
41Schema getSchema(BaseRecord const &record) { return record.getSchema(); }
42
43// Get the schema from a shared pointer to a record
44Schema getSchema(std::shared_ptr<const BaseRecord> const record) { return record->getSchema(); }
45
46// Get a value from a record
47template <typename Key>
48inline typename Key::Value getValue(BaseRecord const &record, Key const &key) {
49 return record.get(key);
50}
51
52// Get a value from a shared pointer to a record
53template <typename Key>
54inline typename Key::Value getValue(std::shared_ptr<const BaseRecord> const record, Key const &key) {
55 return record->get(key);
56}
57
58// Set a value in a record
59template <typename Key>
60inline void setValue(SimpleRecord &record, Key const &key, typename Key::Value const &value) {
61 record.set(key, value);
62}
63
64// Set a value in a shared pointer to a record
65template <typename Key>
66inline void setValue(std::shared_ptr<SimpleRecord> record, Key const &key, typename Key::Value const &value) {
67 record->set(key, value);
68}
69
70} // namespace
71
72template <typename ReferenceCollection>
73void updateRefCentroids(geom::SkyWcs const &wcs, ReferenceCollection &refList) {
74 if (refList.empty()) {
75 return;
76 }
77 auto const schema = getSchema(refList[0]);
78 CoordKey const coordKey(schema["coord"]);
79 Point2DKey const centroidKey(schema["centroid"]);
80 Key<Flag> const hasCentroidKey(schema["hasCentroid"]);
82 skyList.reserve(refList.size());
83 for (auto const &record : refList) {
84 skyList.emplace_back(getValue(record, coordKey));
85 }
86 std::vector<lsst::geom::Point2D> const pixelList = wcs.skyToPixel(skyList);
87 auto pixelPos = pixelList.cbegin();
88 for (auto &refObj : refList) {
89 setValue(refObj, centroidKey, *pixelPos);
90 setValue(refObj, hasCentroidKey, true);
91 ++pixelPos;
92 }
93}
94
95template <typename t>
96Eigen::Matrix<t, 2, 2> calculateCoordCovariance(geom::SkyWcs const& wcs, lsst::geom::Point2D center,
97 Eigen::Matrix<t, 2, 2> err, double factor) {
98 if (!std::isfinite(center.getX()) || !std::isfinite(center.getY())) {
99 return Eigen::Matrix<t, 2, 2>::Constant(NAN);
100 }
101 // Get the derivative of the pixel-to-sky transformation, then use it to
102 // propagate the centroid uncertainty to coordinate uncertainty. Note that
103 // the calculation is done in arcseconds, then converted to radians in
104 // order to achieve higher precision.
105 const static double scale = 1.0 / 3600.0;
106 const static Eigen::Matrix2d cdMatrix{{scale, 0}, {0, scale}};
107
108 lsst::geom::SpherePoint skyCenter = wcs.pixelToSky(center);
109 auto localGnomonicWcs = geom::makeSkyWcs(center, skyCenter, cdMatrix);
110 auto measurementToLocalGnomonic = wcs.getTransform()->then(*localGnomonicWcs->getTransform()->inverted());
111
112 Eigen::Matrix2d localMatrix = measurementToLocalGnomonic->getJacobian(center);
113 Eigen::Matrix<t, 2, 2> d = localMatrix.cast<t>() * scale * factor;
114
115 Eigen::Matrix<t, 2, 2> skyCov = d * err * d.transpose();
116 // Because the transform from pixels to RA/Dec was done at a local
117 // gnomonic, the RA and Dec covariance are already commensurate, and
118 // multiplying the RA covariance by cos(Dec) is not necessary.
119 return skyCov;
120}
121
122template <typename SourceCollection>
123void updateSourceCoords(geom::SkyWcs const &wcs, SourceCollection &sourceList, bool include_covariance) {
124 if (sourceList.empty()) {
125 return;
126 }
127 auto const schema = getSchema(sourceList[0]);
128 Point2DKey const centroidKey(schema["slot_Centroid"]);
129 CovarianceMatrixKey<float, 2> const centroidErrKey(schema["slot_Centroid"], {"x", "y"});
130 CoordKey const coordKey(schema["coord"]);
132 pixelList.reserve(sourceList.size());
134 skyErrList.reserve(sourceList.size());
135
136 for (auto const &source : sourceList) {
137 lsst::geom::Point2D center = getValue(source, centroidKey);
138 pixelList.emplace_back(center);
139 if (include_covariance) {
140 auto err = getValue(source, centroidErrKey);
141 Eigen::Matrix2f skyCov = calculateCoordCovariance<float>(wcs, center, err);
142 skyErrList.emplace_back(skyCov);
143 }
144 }
145
146 std::vector<lsst::geom::SpherePoint> const skyList = wcs.pixelToSky(pixelList);
147 auto skyCoord = skyList.cbegin();
148 auto skyErr = skyErrList.cbegin();
149 for (auto &source : sourceList) {
150 setValue(source, coordKey, *skyCoord);
151 if (include_covariance) {
152 CoordKey::ErrorKey const coordErrKey = CoordKey::getErrorKey(schema);
153 setValue(source, coordErrKey, *skyErr);
154 }
155 ++skyCoord;
156 ++skyErr;
157 }
158}
159
161 geom::SkyWcs const& wcs, double x, double y, double xErr, double yErr, double xy_covariance) {
162 lsst::geom::Point2D center{x, y};
163
164 auto radec = wcs.pixelToSky(center);
165
166 Eigen::Matrix2d err;
167 err(0, 0) = xErr * xErr;
168 err(1, 1) = yErr * yErr;
169 err(0, 1) = xy_covariance;
170 err(1, 0) = xy_covariance;
171
172 Eigen::Matrix2d result = calculateCoordCovariance<double>(wcs, center, err, 1.0);
173
174 return {{radec.getRa().asDegrees(), radec.getDec().asDegrees()},
175 {sqrt(result(0, 0)), sqrt(result(1, 1)), result(0, 1)}};
176}
177
179template void updateRefCentroids(geom::SkyWcs const &, std::vector<std::shared_ptr<SimpleRecord>> &);
180template void updateRefCentroids(geom::SkyWcs const &, SimpleCatalog &);
181
182template void updateSourceCoords(geom::SkyWcs const &, std::vector<std::shared_ptr<SourceRecord>> &,
183 bool include_covariance);
184template void updateSourceCoords(geom::SkyWcs const &, SourceCatalog &, bool include_covariance);
185
186template Eigen::Matrix2f calculateCoordCovariance(geom::SkyWcs const& wcs, lsst::geom::Point2D center,
187 Eigen::Matrix2f err, double factor);
188template Eigen::Matrix2d calculateCoordCovariance(geom::SkyWcs const& wcs, lsst::geom::Point2D center,
189 Eigen::Matrix2d err, double factor);
191
192} // namespace table
193} // namespace afw
194} // namespace lsst
T cbegin(T... args)
Base class for all records.
Definition BaseRecord.h:31
A FunctorKey used to get or set celestial coordinates from a pair of lsst::geom::Angle keys.
Definition aggregates.h:292
CovarianceMatrixKey< float, 2 > ErrorKey
Definition aggregates.h:304
static ErrorKey getErrorKey(Schema const &schema)
A class used as a handle to a particular field in a table.
Definition Key.h:53
Defines the fields and offsets for a table.
Definition Schema.h:51
Record class that must contain a unique ID field and a celestial coordinate field.
Definition Simple.h:48
Point in an unspecified spherical coordinate system.
Definition SpherePoint.h:57
T emplace_back(T... args)
T get(T... args)
T isfinite(T... args)
SortedCatalogT< SimpleRecord > SimpleCatalog
Definition fwd.h:79
Eigen::Matrix< t, 2, 2 > calculateCoordCovariance(geom::SkyWcs const &wcs, lsst::geom::Point2D center, Eigen::Matrix< t, 2, 2 > err, double factor=lsst::geom::PI/180.0)
Calculate covariance for sky coordinates given a pixel centroid and errors.
Definition wcsUtils.cc:96
void updateRefCentroids(geom::SkyWcs const &wcs, ReferenceCollection &refList)
Update centroids in a collection of reference objects.
Definition wcsUtils.cc:73
void updateSourceCoords(geom::SkyWcs const &wcs, SourceCollection &sourceList, bool include_covariance=true)
Update sky coordinates in a collection of source objects.
Definition wcsUtils.cc:123
SortedCatalogT< SourceRecord > SourceCatalog
Definition fwd.h:85
std::pair< std::tuple< double, double >, std::tuple< double, double, double > > convertCentroid(geom::SkyWcs const &wcs, double x, double y, double xErr, double yErr, double xy_covariance=0)
Convert an x/y centroid with errors into RA/dec.
Definition wcsUtils.cc:160
PointKey< double > Point2DKey
Definition aggregates.h:120
Point< double, 2 > Point2D
Definition Point.h:324
T reserve(T... args)
T Value
the type returned by BaseRecord::get
Definition FieldBase.h:42