lsst.meas.extensions.psfex  15.0-2-g18f3f21+7
fieldImpl.cc
Go to the documentation of this file.
1 // -*- lsst-C++ -*-
2 #include <cstring>
3 #include "lsst/meas/extensions/psfex/Field.hh"
4 #undef PI
5 #include "lsst/afw/geom/SkyWcs.h"
6 
7 extern "C" {
8  #include "globals.h"
9 }
10 
11 namespace lsst { namespace meas { namespace extensions { namespace psfex {
12 
13 Field::Field(std::string const& ident) :
14  impl(NULL), _isInitialized(false)
15 {
16  QCALLOC(impl, fieldstruct, 1);
17  impl->next = 0;
18 
19  strcpy(impl->catname, ident.c_str());
20  impl->rcatname = impl->catname;
21 #if 0
22  strncpy(impl->rtcatname, impl->rcatname, sizeof(impl->rtcatname) - 1);
23  strncpy(impl->ident, "??", sizeof(impl->ident) - 1);
24 #elif 1
25  if (!(impl->rcatname = strrchr(impl->catname, '/'))) {
26  impl->rcatname = impl->catname;
27  } else {
28  ++impl->rcatname;
29  }
30 
31  strncpy(impl->rtcatname, impl->rcatname, sizeof(impl->rtcatname) - 1);
32  {
33  char *pstr=strrchr(impl->rtcatname, '.');
34  if (pstr) {
35  *pstr = '\0';
36  }
37  }
38 
39  strncpy(impl->ident, "??", sizeof(impl->ident) - 1);
40 #endif
41 
42  impl->ndet = 0;
43  impl->psf = NULL;
44  impl->wcs = NULL;
45 
46  _finalize();
47 }
48 
49 Field::~Field()
50 {
51  for (int i = 0; i != impl->next; ++i) {
52  free(impl->wcs[i]); // psfex's wcs isn't quite the same as ours ...
53  impl->wcs[i] = NULL; // ... so don't let psfex free it
54  }
55  field_end(impl);
56  impl = NULL;
57 }
58 
59 /************************************************************************************************************/
60 
61 void
62 Field::_finalize(bool force)
63 {
64  if (force || !_isInitialized) {
65  field_init_finalize(impl);
66  _isInitialized = true;
67  }
68 }
69 
70 /************************************************************************************************************/
71 
73 Field::getPsfs() const
74 {
75  if (_psfs.empty()) {
76  _psfs.reserve(impl->next);
77  for (int i = 0; i != impl->next; ++i) {
78  _psfs.push_back(Psf(impl->psf[i]));
79  }
80  }
81 
82  return _psfs;
83 }
84 
85 void
86 Field::addExt(lsst::afw::geom::SkyWcs const& wcs_,
87  int const naxis1, int const naxis2,
88  int const nobj)
89 {
90  QREALLOC(impl->psf, psfstruct *, impl->next + 1);
91  impl->psf[impl->next] = 0;
92  QREALLOC(impl->wcs, wcsstruct *, impl->next + 1);
93  impl->wcs[impl->next] = 0;
94  /*
95  * We're going to fake psfex's wcsstruct object. We only need enough of it for field_locate
96  */
97  QMALLOC(impl->wcs[impl->next], wcsstruct, 1);
98  wcsstruct *wcs = impl->wcs[impl->next];
99 
100  wcs->naxis = 2;
101  wcs->naxisn[0] = naxis1;
102  wcs->naxisn[1] = naxis2;
103 
104  auto const crval = wcs_.getSkyOrigin();
105  // crpix using the FITS standard = pixel origin using the LSST standard + 1
106  auto const crpix = wcs_.getPixelOrigin() + afw::geom::Extent2D(1, 1);
107  auto const cdMatrix = wcs_.getCdMatrix();
108  std::string const cunit("DEG");
109  auto metadata = wcs_.getFitsMetadata();
110  for (int i = 0; i != wcs->naxis; ++i) {
111  auto ifits = i + 1;
112  auto ctype = metadata->getAsString("CTYPE" + std::to_string(ifits));
113  strncpy(wcs->ctype[i], ctype.c_str(), ctype.size() + 1);
114  strncpy(wcs->cunit[i], cunit.c_str(), cunit.size() + 1);
115  wcs->crpix[i] = crpix[i];
116  wcs->crval[i] = crval[i].asDegrees();
117  wcs->cdelt[i] = 1.0; // scale is in the CD matrix (is this even needed?)
118  wcs->crder[i] = 0;
119  wcs->csyer[i] = 0;
120  }
121  for (int i = 0, k = 0; i < 2; ++i) {
122  for (int j = 0; j < 2; ++j, ++k) {
123  wcs->cd[k] = cdMatrix(i, j);
124  }
125  }
126  wcs->lng = 0;
127  wcs->lat = 1;
128  wcs->equinox = 2000;
129 
130  auto center = wcs_.pixelToSky(afw::geom::Point2D(0.5*naxis1, 0.5*naxis2));
131  wcs->wcsscalepos[0] = center.getLongitude().asDegrees();
132  wcs->wcsscalepos[1] = center.getLatitude().asDegrees();
133 
134  double maxradius = 0.0; // Maximum distance to wcsscalepos
135  for (int x = 0; x <= 1; ++x) {
136  for (int y = 0; y <= 1; ++y) {
137  afw::geom::Point2D point(x*naxis1, y*naxis2); // Corner
138  double const radius = center.separation(wcs_.pixelToSky(point)).asDegrees();
139  if (radius > maxradius) {
140  maxradius = radius;
141  }
142  }
143  }
144  wcs->wcsmaxradius = maxradius;
145 
146  impl->ndet += nobj;
147 
148  ++impl->next;
149 }
150 
151 }}}}
Eigen::Matrix2d getCdMatrix(Point2D const &pixel) const
Extent< double, 2 > Extent2D
Angle getLongitude() const noexcept
table::PointKey< double > crpix
T to_string(T... args)
table::PointKey< double > crval
T free(T... args)
STL class.
table::Key< table::Array< std::uint8_t > > wcs
T strncpy(T... args)
Point< double, 2 > Point2D
double x
T strrchr(T... args)
T strcpy(T... args)
Point2D getPixelOrigin() const
STL class.
SpherePoint pixelToSky(Point2D const &pixel) const
T c_str(T... args)
std::shared_ptr< daf::base::PropertyList > getFitsMetadata(bool precise=false) const
constexpr double asDegrees() const noexcept
SpherePoint getSkyOrigin() const
int y
T reserve(T... args)