4 #include "astrometry/solver.h"
5 #include "astrometry/index.h"
6 #include "astrometry/starkd.h"
7 #include "astrometry/fitsioutils.h"
8 #include "astrometry/fitstable.h"
17 #include "boost/format.hpp"
20 #include "lsst/base.h"
21 #include "lsst/pex/exceptions.h"
22 #include "lsst/afw/table/Source.h"
23 #include "lsst/afw/image/Calib.h"
24 #pragma clang diagnostic push
25 #pragma clang diagnostic ignored "-Wunused-variable"
26 #include "lsst/afw/geom/Angle.h"
27 #include "lsst/afw/geom/Point.h"
28 #pragma clang diagnostic pop
30 namespace afwTable = lsst::afw::table;
31 namespace afwGeom = lsst::afw::geom;
35 namespace extensions {
36 namespace astrometryNet {
46 char const *indexName)
48 float *col =
static_cast<float*
>(fitstable_read_column_inds(tag, colName, type, starinds, nstars));
50 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
51 str(boost::format(
"Unable to read data for %s from %s") % colName % indexName));
58 afwTable::SimpleCatalog
60 lsst::afw::coord::Coord
const &ctrCoord,
61 lsst::afw::geom::Angle
const &radius,
63 std::vector<MagColInfo>
const& magColInfoList,
64 char const* isStarCol,
73 size_t const nMag = magColInfoList.size();
75 for (
auto mc = magColInfoList.cbegin(); mc != magColInfoList.cend(); ++mc) {
76 if (mc->filterName.empty()) {
77 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
78 "Magnitude names cannot be empty strings.");
82 if (mc->magCol.empty()) {
83 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
84 "Magnitude column names cannot be empty strings.");
89 auto icrsCoord = ctrCoord.toIcrs();
90 double raDeg = icrsCoord.getLongitude().asDegrees();
91 double decDeg = icrsCoord.getLatitude().asDegrees();
93 radecdeg2xyzarr(raDeg, decDeg, xyz);
94 double r2 = deg2distsq(radius.asDegrees());
96 afwTable::Schema schema = afwTable::SimpleTable::makeMinimalSchema();
98 afw::table::PointKey<double>::addFields(schema,
"centroid",
99 "centroid on some exposure; invalid unless \"hasCentroid\" is true)",
"pixels");
100 auto hasCentroidKey = schema.addField<afwTable::Flag>(
"hasCentroid",
101 "true if centroid field has been set");
103 std::vector<afwTable::Key<double> > fluxKey;
104 std::vector<afwTable::Key<double> > fluxErrKey;
105 fluxKey.reserve(nMag);
106 fluxErrKey.reserve(nMag);
108 for (
auto mc = magColInfoList.cbegin(); mc != magColInfoList.cend(); ++mc) {
112 schema.addField<
double>(
113 mc->filterName +
"_flux",
114 mc->filterName +
" flux"));
116 fluxErrKey.push_back(
117 schema.addField<
double>(
118 mc->filterName +
"_fluxSigma",
119 mc->filterName +
" flux uncertainty (sigma)"));
123 afwTable::Key<afwTable::Flag> resolvedKey;
125 resolvedKey = schema.addField<afwTable::Flag>(
127 "set if the reference object is resolved");
129 afwTable::Key<afwTable::Flag> variableKey;
131 variableKey = schema.addField<afwTable::Flag>(
133 "set if the reference object is variable");
135 afwTable::Key<afwTable::Flag> photometricKey = schema.addField<afwTable::Flag>(
137 "set if the reference object can be used in photometric calibration");
139 afwTable::SimpleCatalog cat;
142 cat = afwTable::SimpleCatalog(afwTable::SimpleTable::make(schema, PTR(afwTable::IdFactory)()));
145 cat = afwTable::SimpleCatalog(afwTable::SimpleTable::make(schema));
149 std::set<std::int64_t> uids;
151 for (std::vector<index_t*>::iterator pind = inds.begin(); pind != inds.end(); ++pind) {
152 index_t* ind = (*pind);
154 double *radecs = NULL;
155 int *starinds = NULL;
157 startree_search_for(ind->starkd, xyz, r2, NULL, &radecs, &starinds, &nstars);
163 std::vector<float*> mag;
164 std::vector<float*> magErr;
166 magErr.reserve(nMag);
167 std::int64_t*
id = NULL;
168 bool* stargal = NULL;
170 if (idCol || nMag || isStarCol || isVarCol) {
171 fitstable_t* tag = startree_get_tagalong(ind->starkd);
172 tfits_type flt = fitscolumn_float_type();
173 tfits_type boo = fitscolumn_boolean_type();
174 tfits_type i64 = fitscolumn_i64_type();
177 std::string msg = boost::str(boost::format(
178 "astrometry_net_data index file %s does not contain a tag-along table, "
179 "so can't retrieve extra columns. idCol=%s, isStarCol=%s, isVarCol=%s") %
180 ind->indexname % idCol % isStarCol % isVarCol);
181 msg +=
", mag columns=[";
182 for (
unsigned int i=0; i<nMag; i++) {
186 msg +=
" name='" + magColInfoList[i].filterName +
187 "', mag='" + magColInfoList[i].magCol +
188 "', magErr='" + magColInfoList[i].magErrCol +
"'";
190 msg +=
" ]. You may need to edit the $ASTROMETRY_NET_DATA_DIR/andConfig.py file to set idColumn=None, etc.";
191 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, msg);
195 id =
static_cast<int64_t*
>(fitstable_read_column_inds(tag, idCol, i64, starinds, nstars));
197 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
198 str(boost::format(
"Unable to read data for %s from %s") % idCol % ind->indexname));
201 if (
id && uniqueIds) {
208 uids = std::set<std::int64_t>(id,
id+nstars);
211 for (
int i=0; i<nstars; i++) {
213 if (uids.insert(
id[i]).second) {
217 starinds[nkeep] = starinds[i];
218 radecs[nkeep*2+0] = radecs[i*2+0];
219 radecs[nkeep*2+1] = radecs[i*2+1];
239 for (
auto mc = magColInfoList.cbegin(); mc != magColInfoList.cend(); ++mc) {
240 char const* col = mc->magCol.c_str();
241 mag.push_back(read_column(tag, col, flt, starinds, nstars, ind->indexname));
243 char const* col = mc->magErrCol.c_str();
244 magErr.push_back(read_column(tag, col, flt, starinds, nstars, ind->indexname));
254 uint8_t* sg =
static_cast<uint8_t*
>(fitstable_read_column_inds(
255 tag, isStarCol, fitscolumn_u8_type(), starinds, nstars));
256 stargal =
static_cast<bool*
>(malloc(nstars));
258 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
259 str(boost::format(
"Unable to read data for %s from %s") % isStarCol % ind->indexname));
261 for (
int j=0; j<nstars; j++) {
262 stargal[j] = (sg[j] > 0);
267 var =
static_cast<bool*
>(fitstable_read_column_inds(tag, isVarCol, boo, starinds, nstars));
269 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
270 str(boost::format(
"Unable to read data for %s from %s") % isVarCol % ind->indexname));
275 for (
int i=0; i<nstars; i++) {
276 PTR(afwTable::SimpleRecord) src = cat.addNew();
281 lsst::afw::coord::IcrsCoord(
282 radecs[i * 2 + 0] * afwGeom::degrees,
283 radecs[i * 2 + 1] * afwGeom::degrees
291 src->set(hasCentroidKey,
false);
293 assert(fluxKey.size() == nMag);
295 assert(fluxErrKey.size() == magErr.size());
299 for (
auto mc = magColInfoList.cbegin(); mc != magColInfoList.cend(); ++mc, ++j) {
305 double flux = lsst::afw::image::fluxFromABMag(mag[j][i]);
307 src->set(fluxKey[j], flux);
310 double fluxErr = lsst::afw::image::fluxErrFromABMagErr(magErr[ej][i], mag[j][i]);
312 src->set(fluxErrKey[ej], fluxErr);
316 assert(ej == fluxErrKey.size());
318 bool photometric =
true;
320 src->set(resolvedKey, !stargal[i]);
321 photometric &= stargal[i];
324 src->set(variableKey, var[i]);
325 photometric &= (!var[i]);
327 src->set(photometricKey, photometric);
331 for (
size_t j=0; j<mag.size(); ++j) {
334 for (
size_t j=0; j<magErr.size(); ++j) {
lsst::afw::table::SimpleCatalog getCatalogImpl(std::vector< index_t * > inds, lsst::afw::coord::Coord const &ctrCoord, lsst::afw::geom::Angle const &radius, const char *idCol, std::vector< MagColInfo > const &magColInfoList, const char *starGalCol, const char *varCol, bool uniqueIds=true)
Implementation for index_t::getCatalog method.