31#include "boost/format.hpp"
68void setMetadataFromFoundValue(daf::base::PropertyList& metadata,
std::string const& name,
70 if (!foundValue.
found) {
71 throw LSST_EXCEPT(pex::exceptions::LogicError,
"Bug! FitsChan card \"" + name +
"\" not found");
73 if (comment.empty()) {
74 metadata.set(name, foundValue.
value);
76 metadata.set(name, foundValue.
value, comment);
90 excludeNames.
insert(moreNames.begin(), moreNames.end());
93 if (metadata.
exists(
"RADECSYS") && !metadata.
exists(
"RADESYS")) {
95 metadata.
remove(
"RADECSYS");
99 "Encoding=FITS-WCS, IWC=1, SipReplace=0, ReportLevel=3");
103 obj = channel.read();
108 auto frameSet = std::dynamic_pointer_cast<ast::FrameSet>(obj);
111 "metadata describes a " + obj->getClassName() +
", not a FrameSet");
114 auto const finalNames = setFromVector(channel.getAllCardNames());
118 std::set_difference(initialNames.begin(), initialNames.end(), finalNames.begin(), finalNames.end(),
127 for (
auto const& name : namesToStrip) {
142 excludeNames.
insert(moreNames.begin(), moreNames.end());
145 if (metadata.
exists(
"RADECSYS") && !metadata.
exists(
"RADESYS")) {
147 metadata.
remove(
"RADECSYS");
151 "Encoding=FITS-WCS, IWC=1, SipReplace=0, ReportLevel=3");
152 auto const initialNames = setFromVector(channel.getAllCardNames());
156 obj = channel.read();
161 auto const finalNames = setFromVector(channel.getAllCardNames());
165 std::set_difference(initialNames.begin(), initialNames.end(), finalNames.begin(), finalNames.end(),
174 for (
auto const& name : namesToStrip) {
194 auto const initialBaseIndex = rawFrameSet->getBase();
198 if (rawFrameSet->findFrame(
ast::Frame(2,
"Domain=GRID"))) {
199 gridIndex = rawFrameSet->getCurrent();
203 auto const baseFrame = rawFrameSet->getFrame(initialBaseIndex,
false);
204 auto const baseClassName = rawFrameSet->getClassName();
205 if (baseFrame->getClassName() !=
"Frame") {
207 "The base frame is of type " + baseFrame->getClassName() +
208 "instead of Frame; cannot read metadata as a SkyWcs");
210 if (baseFrame->getNAxes() != 2) {
213 " axes instead of 2; cannot read metadata as a SkyWcs");
215 if (baseFrame->getDomain() !=
"") {
217 "The base frame has domain \"" + baseFrame->getDomain() +
218 "\" instead of blank or GRID; cannot read metadata as a SkyWcs");
222 gridIndex = initialBaseIndex;
226 if (!rawFrameSet->findFrame(
ast::Frame(2,
"Domain=IWC"))) {
229 auto const iwcIndex = rawFrameSet->getCurrent();
230 auto const iwcFrame = rawFrameSet->getFrame(iwcIndex);
235 auto const stdSkyFrameTemplate =
ast::SkyFrame(
"System=ICRS");
242 if (!rawFrameSet->findFrame(stdSkyFrameTemplate)) {
244 "Could not find a SkyFrame; cannot read metadata as a SkyWcs");
246 auto initialSkyIndex = rawFrameSet->getCurrent();
252 rawFrameSet->setBase(initialSkyIndex);
253 auto stdSkyFrameSet = rawFrameSet->findFrame(stdSkyFrameTemplate);
254 if (!stdSkyFrameSet) {
256 "Bug: found a SkyFrame the first time, but not the second time");
263 rawFrameSet->addFrame(initialSkyIndex, *stdSkyFrameSet->getMapping()->simplified(),
265 auto const stdSkyIndex = rawFrameSet->getCurrent();
266 auto const stdSkyFrame = rawFrameSet->getFrame(stdSkyIndex,
false);
275 auto const gridToIwc = rawFrameSet->getMapping(gridIndex, iwcIndex)->simplified();
276 auto const pixelToIwc = pixelToGrid.then(*gridToIwc).simplified();
277 auto const iwcToStdSky = rawFrameSet->getMapping(iwcIndex, stdSkyIndex);
279 auto frameDict = std::make_shared<ast::FrameDict>(
ast::Frame(2,
"Domain=PIXELS"), *pixelToIwc, *iwcFrame);
280 frameDict->addFrame(
"IWC", *iwcToStdSky, *stdSkyFrame);
284 auto crpixPixels = pixelToGrid.applyInverse(crpixGrid);
285 auto crvalRad = frameDict->applyForward(crpixPixels);
286 auto skyFrame = std::dynamic_pointer_cast<ast::SkyFrame>(frameDict->getFrame(
"SKY",
false));
290 skyFrame->setSkyRefIs(
"Ignored");
291 skyFrame->setSkyRef(crvalRad);
297 int const numCards = fitsChan.
getNCard();
298 auto metadata = std::make_shared<daf::base::PropertyList>();
299 for (
int cardNum = 1; cardNum <= numCards; ++cardNum) {
306 auto foundValue = fitsChan.
getFitsF();
307 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
311 auto foundValue = fitsChan.
getFitsI();
312 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
316 auto foundValue = fitsChan.
getFitsS();
317 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
321 auto foundValue = fitsChan.
getFitsL();
322 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
326 if (cardComment.empty()) {
327 metadata->set(cardName,
nullptr);
329 metadata->set(cardName,
nullptr, cardComment);
335 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
345 os <<
"Card " << cardNum <<
" with name \"" << cardName <<
"\" has type "
346 <<
static_cast<int>(cardType) <<
", which is not supported by PropertyList";
352 os <<
"Bug! Card " << cardNum <<
" with name \"" << cardName
353 <<
"\" has type NOTYPE, which should not be possible";
378 for (
auto const &fullName : allParamNames) {
379 if (excludeNames.
count(fullName) == 0) {
380 std::size_t lastPeriod = fullName.rfind(
char(
'.'));
381 auto name = (lastPeriod == std::string::npos) ? fullName : fullName.substr(lastPeriod + 1);
384 if (name.size() > 8) {
388 if (type ==
typeid(
bool)) {
389 fc.setFitsL(name, metadata.
get<
bool>(name));
392 }
else if (type ==
typeid(
int)) {
393 fc.setFitsI(name, metadata.
get<
int>(name));
394 }
else if (type ==
typeid(
double) || type ==
typeid(
float)) {
396 if (type ==
typeid(
double)) {
397 value = metadata.
get<
double>(
name);
399 value =
static_cast<double>(metadata.
get<
float>(
name));
403 fc.setFitsF(name, value);
407 boost::format(
"Found NaN in metadata item '%s'") % name);
412 if (str.size() <= 68) {
table::Key< std::string > name
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
LSST DM logging module built on log4cxx.
#define LOGLS_WARN(logger, message)
Log a warn-level message using an iostream-based interface.
A specialized form of Channel which reads and writes FITS header cards.
std::string getCardComm() const
Get CardComm: the comment of the current card.
FoundValue< std::string > getFitsS(std::string const &name="", std::string defval="") const
Get the value of a string card.
void setCard(int ind)
Set Card: the index of the current card, where 1 is the first card.
FoundValue< bool > getFitsL(std::string const &name="", bool defval=false) const
Get the value of a bool card.
std::string getCardName() const
Get CardName: the keyword name of the current card.
FoundValue< int > getFitsI(std::string const &name="", int defval=0) const
Get the value of a int card.
CardType getCardType() const
Get CardType: data type of the current FITS card.
int getNCard() const
Get NCard: the number of cards.
FoundValue< double > getFitsF(std::string const &name="", double defval=0) const
Get the value of a double card.
FoundValue< std::string > getFitsCN(std::string const &name="", std::string defval="") const
Get the value of a CONTINUE card.
A value and associated validity flag.
T value
The found value; ignore if found is false.
bool found
Was the value found?
Frame is used to represent a coordinate system.
static int constexpr CURRENT
index of current frame
static int constexpr NOFRAME
an invalid frame index
ShiftMap is a linear Mapping which shifts each axis by a specified constant value.
SkyFrame is a specialised form of Frame which describes celestial longitude/latitude coordinate syste...
String-based source and sink for channels.
Class for storing ordered metadata with comments.
std::vector< std::string > getOrderedNames() const
Get the list of property names, in the order they were added.
Class for storing generic metadata.
std::string getAsString(std::string const &name) const
Get the last value for a string property name (possibly hierarchical).
virtual void remove(std::string const &name)
Remove all values for a property name (possibly hierarchical).
bool exists(std::string const &name) const
Determine if a name (possibly hierarchical) exists.
void set(std::string const &name, T const &value)
Replace all values for a property name (possibly hierarchical) with a new scalar value.
std::type_info const & typeOf(std::string const &name) const
Get the type of values for a property name (possibly hierarchical).
double getAsDouble(std::string const &name) const
Get the last value for any arithmetic property name (possibly hierarchical).
T get(std::string const &name) const
Get the last value for a property name (possibly hierarchical).
std::vector< std::string > paramNames(bool topLevelOnly=true) const
A variant of names that excludes the names of subproperties.
virtual char const * what(void) const noexcept
Return a character string summarizing this exception.
Reports errors in the logical structure of the program.
Reports attempts to access elements using an invalid key.
Reports errors from accepting an object of an unexpected or inappropriate type.
T make_move_iterator(T... args)
@ NOTYPE
card does not exist (card number invalid)
@ COMPLEXI
complex integer
@ COMPLEXF
complex floating point
@ COMMENT
card is a comment-style card with no "=" (COMMENT, HISTORY, ...)
std::shared_ptr< ast::FrameSet > readFitsWcs(daf::base::PropertySet &metadata, bool strip=true)
Read a FITS convention WCS FrameSet from FITS metadata.
ast::FitsChan getFitsChanFromPropertyList(daf::base::PropertySet &metadata, std::set< std::string > const &excludeNames={}, std::string options="")
Construct AST FitsChan from PropertyList.
void stripWcsMetadata(daf::base::PropertySet &metadata)
Strip all WCS metadata from a header.
std::shared_ptr< ast::FrameDict > readLsstSkyWcs(daf::base::PropertySet &metadata, bool strip=true)
Read an LSST celestial WCS FrameDict from a FITS header.
std::shared_ptr< daf::base::PropertyList > getPropertyListFromFitsChan(ast::FitsChan &fitsChan)
Copy values from an AST FitsChan into a PropertyList.
std::shared_ptr< daf::base::PropertyList > createTrivialWcsMetadata(std::string const &wcsName, lsst::geom::Point2I const &xy0)
lsst::geom::Point2I getImageXY0FromMetadata(daf::base::PropertySet &metadata, std::string const &wcsName, bool strip=false)
std::string const wcsNameForXY0
T set_difference(T... args)