28 #include "boost/algorithm/string/trim.hpp" 42 #include "lsst/afw/table/io/Persistable.cc" 68 double getDouble(daf::base::PropertySet
const& metadata,
std::string const&
key) {
69 return metadata.exists(key) ? metadata.getAsDouble(key) :
nan;
92 bool setDouble(daf::base::PropertySet& metadata,
std::string const& key,
double value,
95 metadata.set(key, value);
111 return setDouble(metadata, key, angle.
asDegrees(), comment);
121 case RotType::UNKNOWN:
125 case RotType::HORIZON:
131 os <<
"Unknown RotType enum: " <<
static_cast<int>(
rotType);
141 if (rotTypeName ==
"UNKNOWN") {
142 return RotType::UNKNOWN;
143 }
else if (rotTypeName ==
"SKY") {
145 }
else if (rotTypeName ==
"HORIZON") {
146 return RotType::HORIZON;
147 }
else if (rotTypeName ==
"MOUNT") {
148 return RotType::MOUNT;
151 os <<
"Unknown RotType name: \"" << rotTypeName <<
"\"";
155 class VisitInfoSchema {
161 table::Key<std::int64_t>
tai;
163 table::Key<lsst::geom::Angle>
era;
179 static VisitInfoSchema
const&
get() {
180 static VisitInfoSchema instance;
185 VisitInfoSchema(
const VisitInfoSchema&) =
delete;
186 VisitInfoSchema& operator=(
const VisitInfoSchema&) =
delete;
189 VisitInfoSchema(VisitInfoSchema&&) =
delete;
190 VisitInfoSchema& operator=(VisitInfoSchema&&) =
delete;
196 exposureTime(schema.addField<
double>(
"exposuretime",
"exposure duration",
"s")),
197 darkTime(schema.addField<
double>(
"darktime",
"time from CCD flush to readout",
"s")),
199 "tai",
"TAI date and time at middle of exposure as nsec from unix epoch",
"nsec")),
200 ut1(schema.addField<
double>(
"ut1",
"UT1 date and time at middle of exposure",
"MJD")),
204 "sky position of boresight at middle of exposure")),
209 "refracted apparent topocentric position of boresight at middle of exposure",
"")),
211 "boresightazalt_alt",
212 "refracted apparent topocentric position of boresight at middle of exposure",
"")),
214 "boresightairmass",
"airmass at boresight, relative to zenith at sea level",
"")),
216 "boresightrotangle",
"rotation angle at boresight at middle of exposure",
"")),
217 rotType(schema.addField<
int>(
"rottype",
"rotation type; see VisitInfo.getRotType for details",
221 "latitude",
"latitude of telescope (+ is east of Greenwich)",
"")),
223 elevation(schema.addField<
double>(
"elevation",
"elevation of telescope",
"")),
225 airTemperature(schema.addField<
double>(
"airtemperature",
"air temperature",
"C")),
226 airPressure(schema.addField<
double>(
"airpressure",
"air pressure",
"Pascal")),
227 humidity(schema.addField<
double>(
"humidity",
"humidity (%)",
"")) {
228 schema.getCitizen().markPersistent();
232 class VisitInfoFactory :
public table::io::PersistableFactory {
235 CatalogVector
const& catalogs)
const override {
236 VisitInfoSchema
const&
keys = VisitInfoSchema::get();
240 table::BaseRecord
const& record = catalogs.front().front();
242 new VisitInfo(record.get(keys.exposureId), record.get(keys.exposureTime),
243 record.get(keys.darkTime),
::DateTime(record.get(keys.tai), ::DateTime::TAI),
244 record.
get(keys.ut1), record.get(keys.era), record.get(keys.boresightRaDec),
246 record.get(keys.boresightAzAlt_alt)),
247 record.get(keys.boresightAirmass), record.get(keys.boresightRotAngle),
248 static_cast<RotType>(record.get(keys.rotType)),
249 coord::Observatory(record.get(keys.longitude), record.get(keys.latitude),
250 record.get(keys.elevation)),
251 coord::Weather(record.get(keys.airTemperature), record.get(keys.airPressure),
252 record.get(keys.humidity))));
256 explicit VisitInfoFactory(
std::string const&
name) : table::io::PersistableFactory(name) {}
259 std::string getVisitInfoPersistenceName() {
return "VisitInfo"; }
261 VisitInfoFactory registration(getVisitInfoPersistenceName());
271 "EXPID",
"EXPTIME",
"DARKTIME",
"DATE-AVG",
"TIMESYS",
"TIME-MID",
"MJD-AVG-UT1",
272 "AVG-ERA",
"BORE-RA",
"BORE-DEC",
"BORE-AZ",
"BORE-ALT",
"BORE-AIRMASS",
"BORE-ROTANG",
273 "ROTTYPE",
"OBS-LONG",
"OBS-LAT",
"OBS-ELEV",
"AIRTEMP",
"AIRPRESS",
"HUMIDITY"};
274 for (
auto&& key : keyList) {
275 if (metadata.
exists(key)) {
287 setDouble(metadata,
"EXPTIME", visitInfo.
getExposureTime(),
"Exposure time (sec)");
288 setDouble(metadata,
"DARKTIME", visitInfo.
getDarkTime(),
"Time from CCD flush to readout (sec)");
291 "TAI date at middle of observation");
292 metadata.
set(
"TIMESYS",
"TAI");
294 setDouble(metadata,
"MJD-AVG-UT1", visitInfo.
getUt1(),
"UT1 MJD date at ctr of obs");
295 setAngle(metadata,
"AVG-ERA", visitInfo.
getEra(),
"Earth rot ang at ctr of obs (deg)");
297 setAngle(metadata,
"BORE-RA", boresightRaDec[0],
"ICRS RA (deg) at boresight");
298 setAngle(metadata,
"BORE-DEC", boresightRaDec[1],
"ICRS Dec (deg) at boresight");
300 setAngle(metadata,
"BORE-AZ", boresightAzAlt[0],
"Refr app topo az (deg) at bore");
301 setAngle(metadata,
"BORE-ALT", boresightAzAlt[1],
"Refr app topo alt (deg) at bore");
302 setDouble(metadata,
"BORE-AIRMASS", visitInfo.
getBoresightAirmass(),
"Airmass at boresight");
303 setAngle(metadata,
"BORE-ROTANG", visitInfo.
getBoresightRotAngle(),
"Rotation angle (deg) at boresight");
304 metadata.
set(
"ROTTYPE", rotTypeStrFromEnum(visitInfo.
getRotType()),
"Type of rotation angle");
306 setAngle(metadata,
"OBS-LONG",
observatory.getLongitude(),
"Telescope longitude (+E, deg)");
307 setAngle(metadata,
"OBS-LAT",
observatory.getLatitude(),
"Telescope latitude (deg)");
308 setDouble(metadata,
"OBS-ELEV",
observatory.getElevation(),
"Telescope elevation (m)");
310 setDouble(metadata,
"AIRTEMP", weather.getAirTemperature(),
"Outside air temperature (C)");
311 setDouble(metadata,
"AIRPRESS", weather.getAirPressure(),
"Outdoor air pressure (P)");
312 setDouble(metadata,
"HUMIDITY", weather.getHumidity(),
"Relative humidity (%)");
320 _darkTime(getDouble(metadata,
"DARKTIME")),
322 _ut1(getDouble(metadata,
"MJD-AVG-UT1")),
323 _era(getAngle(metadata,
"AVG-ERA")),
325 lsst::geom::
SpherePoint(getAngle(metadata,
"BORE-RA"), getAngle(metadata,
"BORE-DEC"))),
327 lsst::geom::
SpherePoint(getAngle(metadata,
"BORE-AZ"), getAngle(metadata,
"BORE-ALT"))),
328 _boresightAirmass(getDouble(metadata,
"BORE-AIRMASS")),
329 _boresightRotAngle(getAngle(metadata,
"BORE-ROTANG")),
331 _observatory(getAngle(metadata,
"OBS-LONG"), getAngle(metadata,
"OBS-LAT"),
332 getDouble(metadata,
"OBS-ELEV")),
333 _weather(getDouble(metadata,
"AIRTEMP"), getDouble(metadata,
"AIRPRESS"),
334 getDouble(metadata,
"HUMIDITY")) {
336 if (metadata.
exists(key)) {
341 if (metadata.
exists(key)) {
352 if (metadata.
exists(key)) {
353 if (metadata.
exists(
"TIMESYS")) {
354 auto timesysName = boost::algorithm::trim_right_copy(metadata.
getAsString(
"TIMESYS"));
355 if (timesysName !=
"TAI") {
360 os <<
"TIMESYS = \"" << timesysName
361 <<
"\"; VisitInfo requires TIMESYS to exist and to equal \"TAI\"";
366 "TIMESYS not found; VistitInfo requires TIMESYS to exist and to equal \"TAI\"");
373 if (metadata.
exists(key)) {
379 if (metadata.
exists(key)) {
380 _rotType = rotTypeEnumFromStr(metadata.
getAsString(key));
395 return utils::hashCombine(17, _exposureId, _exposureTime, _darkTime, _date, _ut1, _era, _boresightRaDec,
396 _boresightAzAlt, _boresightAirmass, _boresightRotAngle, _rotType, _observatory,
403 VisitInfoSchema
const&
keys = VisitInfoSchema::get();
409 record->set(keys.tai,
getDate().nsecs(::DateTime::TAI));
410 record->set(keys.ut1,
getUt1());
411 record->set(keys.era,
getEra());
414 record->set(keys.boresightAzAlt_az, boresightAzAlt[0]);
415 record->set(keys.boresightAzAlt_alt, boresightAzAlt[1]);
418 record->set(keys.rotType, static_cast<int>(
getRotType()));
420 record->set(keys.latitude,
observatory.getLatitude());
421 record->set(keys.longitude,
observatory.getLongitude());
422 record->set(keys.elevation,
observatory.getElevation());
424 record->set(keys.airTemperature,
weather.getAirTemperature());
425 record->set(keys.airPressure,
weather.getAirPressure());
426 record->set(keys.humidity,
weather.getHumidity());
439 double _parallactic_y, _parallactic_x,
result;
444 result = atan2(_parallactic_y, _parallactic_x);
452 os <<
"darkTime=" << visitInfo.
getDarkTime() <<
", ";
454 os <<
"UT1=" << visitInfo.
getUt1() <<
", ";
455 os <<
"ERA=" << visitInfo.
getEra() <<
", ";
460 os <<
"rotType=" <<
static_cast<int>(visitInfo.
getRotType()) <<
", ";
std::int64_t RecordId
Type used for unique IDs for records.
double getBoresightAirmass() const
get airmass at the boresight, relative to zenith at sea level (and at the middle of the exposure...
double getAsDouble(std::string const &name) const
Get the last value for any arithmetic property name (possibly hierarchical).
lsst::geom::SpherePoint getBoresightAzAlt() const
get refracted apparent topocentric Az/Alt position at the boresight (and at the middle of the exposur...
static std::shared_ptr< T > dynamicCast(std::shared_ptr< Persistable > const &ptr)
Dynamically cast a shared_ptr.
table::Key< lsst::geom::Angle > latitude
double get(DateSystem system=MJD, Timescale scale=TAI) const
Get date as a double in a specified representation, such as MJD.
Class for handling dates/times, including MJD, UTC, and TAI.
constexpr double asDegrees() const noexcept
Return an Angle's value in degrees.
lsst::geom::Angle getLocalEra() const
An object passed to Persistable::write to allow it to persist itself.
table::Key< double > airTemperature
Class for storing ordered metadata with comments.
table::CoordKey boresightRaDec
Information about a single exposure of an imaging camera.
lsst::geom::SpherePoint getBoresightRaDec() const
get ICRS RA/Dec position at the boresight (and at the middle of the exposure, if it varies with time)...
double getUt1() const
get UT1 (universal time) MJD date at middle of exposure
void set(std::string const &name, T const &value)
Replace all values for a property name (possibly hierarchical) with a new scalar value.
std::string toString(Timescale scale) const
Get date as an ISO8601-formatted string.
table::Key< double > boresightAirmass
double getDarkTime() const
get time from CCD flush to exposure readout, including shutter open time (despite the name); (sec) ...
virtual void remove(std::string const &name)
Remove all values for a property name (possibly hierarchical).
double sin(Angle const &a)
bool operator==(VisitInfo const &other) const
table::Key< lsst::geom::Angle > era
AngleUnit constexpr radians
constant with units of radians
table::Key< int > rotType
Rotation angle is unknown.
A class representing an angle.
double cos(Angle const &a)
table::Key< lsst::geom::Angle > boresightRotAngle
std::size_t hash_value() const noexcept
Return a hash of this object.
lsst::geom::Angle getLongitude() const noexcept
get telescope longitude (positive values are E of Greenwich)
table::Key< lsst::geom::Angle > boresightAzAlt_az
void setVisitInfoMetadata(daf::base::PropertyList &metadata, VisitInfo const &visitInfo)
Set FITS metadata from a VisitInfo.
std::ostream & operator<<(std::ostream &os, VisitInfo const &visitInfo)
AngleUnit constexpr degrees
constant with units of degrees
A base class for image defects.
table::Key< double > exposureTime
table::RecordId getExposureId() const
get exposure ID
int64_t getAsInt64(std::string const &name) const
Get the last value for a bool/char/short/int/int64_t property name (possibly hierarchical).
table::Key< lsst::geom::Angle > boresightAzAlt_alt
table::Key< double > humidity
double tan(Angle const &a)
table::Key< table::RecordId > exposureId
bool exists(std::string const &name) const
Determine if a name (possibly hierarchical) exists.
table::Key< double > elevation
double getExposureTime() const
get exposure duration (shutter open time); (sec)
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
table::Key< lsst::geom::Angle > longitude
RotType getRotType() const
get rotation type of boresightRotAngle
lsst::geom::Angle getEra() const
get earth rotation angle at middle of exposure
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
bool isValid() const
Is this date valid?
table::Key< double > airPressure
daf::base::DateTime getDate() const
get uniform date and time at middle of exposure
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Class for storing generic metadata.
static CoordKey addFields(afw::table::Schema &schema, std::string const &name, std::string const &doc)
Add a pair of _ra, _dec fields to a Schema, and return a CoordKey that points to them.
int stripVisitInfoKeywords(daf::base::PropertySet &metadata)
Remove VisitInfo-related keywords from the metadata.
lsst::geom::Angle getBoresightParAngle() const
Get parallactic angle at the boresight.
lsst::geom::SpherePoint SpherePoint
ItemVariant const * other
table::Key< std::int64_t > tai
lsst::geom::Angle getBoresightRotAngle() const
Get rotation angle at boresight at middle of exposure.
std::string getAsString(std::string const &name) const
Get the last value for a string property name (possibly hierarchical).
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
std::size_t hashCombine(std::size_t seed) noexcept
Combine hashes.
Reports errors from accepting an object of an unexpected or inappropriate type.
table::Key< double > darkTime
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
coord::Observatory getObservatory() const
get observatory longitude, latitude and elevation
coord::Weather getWeather() const
get basic weather information
lsst::geom::Angle getBoresightHourAngle() const
Reports errors that are due to events beyond the control of the program.
std::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.