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"
16 #include "boost/cstdint.hpp"
17 #include "boost/format.hpp"
24 #pragma clang diagnostic push
25 #pragma clang diagnostic ignored "-Wunused-variable"
28 #pragma clang diagnostic pop
30 namespace afwTable = lsst::afw::table;
31 namespace afwGeom = lsst::afw::geom;
45 char const *indexName)
47 float *
col =
static_cast<float*
>(fitstable_read_column_inds(tag, colName, type, starinds, nstars));
49 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
50 str(
boost::format(
"Unable to read data for %s from %s") % colName % indexName));
62 std::vector<MagColInfo>
const& magColInfoList,
63 char const* isStarCol,
72 size_t const nMag = magColInfoList.size();
74 for (
auto mc = magColInfoList.cbegin(); mc != magColInfoList.cend(); ++mc) {
75 if (mc->filterName.empty()) {
76 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
77 "Magnitude names cannot be empty strings.");
81 if (mc->magCol.empty()) {
82 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
83 "Magnitude column names cannot be empty strings.");
88 auto icrsCoord = ctrCoord.
toIcrs();
90 double decDeg = icrsCoord.getLatitude().asDegrees();
92 radecdeg2xyzarr(raDeg, decDeg, xyz);
93 double r2 = deg2distsq(radius.
asDegrees());
98 "centroid on some exposure; invalid unless \"hasCentroid\" is true)",
"pixels");
99 auto hasCentroidKey = schema.addField<afwTable::Flag>(
"hasCentroid",
100 "true if centroid field has been set");
102 std::vector<afwTable::Key<double> > fluxKey;
103 std::vector<afwTable::Key<double> > fluxErrKey;
104 fluxKey.reserve(nMag);
105 fluxErrKey.reserve(nMag);
107 for (
auto mc = magColInfoList.cbegin(); mc != magColInfoList.cend(); ++mc) {
111 schema.addField<
double>(
112 mc->filterName +
"_flux",
113 mc->filterName +
" flux"));
115 fluxErrKey.push_back(
116 schema.addField<
double>(
117 mc->filterName +
"_fluxSigma",
118 mc->filterName +
" flux uncertainty (sigma)"));
124 resolvedKey = schema.addField<afwTable::Flag>(
126 "set if the reference object is resolved");
130 variableKey = schema.addField<afwTable::Flag>(
132 "set if the reference object is variable");
136 "set if the reference object can be used in photometric calibration");
148 std::set<boost::int64_t> uids;
150 for (std::vector<index_t*>::iterator pind = inds.begin(); pind != inds.end(); ++pind) {
151 index_t* ind = (*pind);
153 double *radecs = NULL;
154 int *starinds = NULL;
156 startree_search_for(ind->starkd, xyz, r2, NULL, &radecs, &starinds, &nstars);
162 std::vector<float*> mag;
163 std::vector<float*> magErr;
165 magErr.reserve(nMag);
166 boost::int64_t*
id = NULL;
167 bool* stargal = NULL;
169 if (idCol || nMag || isStarCol || isVarCol) {
170 fitstable_t* tag = startree_get_tagalong(ind->starkd);
171 tfits_type flt = fitscolumn_float_type();
172 tfits_type boo = fitscolumn_boolean_type();
173 tfits_type i64 = fitscolumn_i64_type();
177 "astrometry_net_data index file %s does not contain a tag-along table, "
178 "so can't retrieve extra columns. idCol=%s, isStarCol=%s, isVarCol=%s") %
179 ind->indexname % idCol % isStarCol % isVarCol);
180 msg +=
", mag columns=[";
181 for (
unsigned int i=0; i<nMag; i++) {
185 msg +=
" name='" + magColInfoList[i].filterName +
186 "', mag='" + magColInfoList[i].magCol +
187 "', magErr='" + magColInfoList[i].magErrCol +
"'";
189 msg +=
" ]. You may need to edit the $ASTROMETRY_NET_DATA_DIR/andConfig.py file to set idColumn=None, etc.";
190 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, msg);
194 id =
static_cast<int64_t*
>(fitstable_read_column_inds(tag, idCol, i64, starinds, nstars));
196 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
197 str(
boost::format(
"Unable to read data for %s from %s") % idCol % ind->indexname));
200 if (
id && uniqueIds) {
207 uids = std::set<boost::int64_t>(
id,
id+nstars);
210 for (
int i=0; i<nstars; i++) {
212 if (uids.insert(
id[i]).second) {
216 starinds[nkeep] = starinds[i];
217 radecs[nkeep*2+0] = radecs[i*2+0];
218 radecs[nkeep*2+1] = radecs[i*2+1];
238 for (
auto mc = magColInfoList.cbegin(); mc != magColInfoList.cend(); ++mc) {
239 char const*
col = mc->magCol.c_str();
240 mag.push_back(read_column(tag, col, flt, starinds, nstars, ind->indexname));
242 char const* col = mc->magErrCol.c_str();
243 magErr.push_back(read_column(tag, col, flt, starinds, nstars, ind->indexname));
253 uint8_t* sg =
static_cast<uint8_t*
>(fitstable_read_column_inds(
254 tag, isStarCol, fitscolumn_u8_type(), starinds, nstars));
255 stargal =
static_cast<bool*
>(malloc(nstars));
257 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
258 str(
boost::format(
"Unable to read data for %s from %s") % isStarCol % ind->indexname));
260 for (
int j=0; j<nstars; j++) {
261 stargal[j] = (sg[j] > 0);
266 var =
static_cast<bool*
>(fitstable_read_column_inds(tag, isVarCol, boo, starinds, nstars));
268 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
269 str(
boost::format(
"Unable to read data for %s from %s") % isVarCol % ind->indexname));
274 for (
int i=0; i<nstars; i++) {
290 src->set(hasCentroidKey,
false);
292 assert(fluxKey.size() == nMag);
294 assert(fluxErrKey.size() == magErr.size());
298 for (
auto mc = magColInfoList.cbegin(); mc != magColInfoList.cend(); ++mc, ++j) {
306 src->set(fluxKey[j], flux);
311 src->set(fluxErrKey[ej], fluxErr);
315 assert(ej == fluxErrKey.size());
317 bool photometric =
true;
319 src->set(resolvedKey, !stargal[i]);
320 photometric &= stargal[i];
323 src->set(variableKey, var[i]);
324 photometric &= (!var[i]);
326 src->set(photometricKey, photometric);
330 for (
size_t j=0; j<mag.size(); ++j) {
333 for (
size_t j=0; j<magErr.size(); ++j) {
Defines the fields and offsets for a table.
A coordinate class intended to represent absolute positions.
static PointKey addFields(Schema &schema, std::string const &name, std::string const &doc, std::string const &unit)
static Schema makeMinimalSchema()
Return a minimal schema for Simple tables and records.
afw::table::Schema schema
Include files required for standard LSST Exception handling.
double fluxErrFromABMagErr(double magErr, double mag)
Compute flux error in Janskys from AB magnitude error and AB magnitude.
lsst::afw::geom::Angle getLongitude() const
The main access method for the longitudinal coordinate.
double fluxFromABMag(double mag)
Compute flux in Janskys from AB magnitude.
Custom catalog class for record/table subclasses that are guaranteed to have an ID, and should generally be sorted by that ID.
afwTable::SimpleCatalog getCatalogImpl(std::vector< index_t * > inds, lsst::afw::coord::Coord const &ctrCoord, lsst::afw::geom::Angle const &radius, char const *idCol, std::vector< MagColInfo > const &magColInfoList, char const *isStarCol, char const *isVarCol, bool uniqueIds)
A polymorphic functor base class for generating record IDs for a table.
#define LSST_EXCEPT(type,...)
A class used as a handle to a particular field in a table.
virtual IcrsCoord toIcrs() const
Convert ourself to ICRS: RA, Dec (basically J2000)
static boost::shared_ptr< SimpleTable > make(Schema const &schema, boost::shared_ptr< IdFactory > const &idFactory)
Construct a new table.
Record class that must contain a unique ID field and a celestial coordinate field.
SortedCatalogT< SimpleRecord > SimpleCatalog
A class to handle Icrs coordinates (inherits from Coord)