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()) {
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) {
149 auto const initialBaseIndex = rawFrameSet->getBase();
153 if (rawFrameSet->findFrame(
ast::Frame(2,
"Domain=GRID"))) {
154 gridIndex = rawFrameSet->getCurrent();
158 auto const baseFrame = rawFrameSet->getFrame(initialBaseIndex,
false);
159 auto const baseClassName = rawFrameSet->getClassName();
160 if (baseFrame->getClassName() !=
"Frame") {
162 "The base frame is of type " + baseFrame->getClassName() +
163 "instead of Frame; cannot read metadata as a SkyWcs");
165 if (baseFrame->getNAxes() != 2) {
168 " axes instead of 2; cannot read metadata as a SkyWcs");
170 if (baseFrame->getDomain() !=
"") {
172 "The base frame has domain \"" + baseFrame->getDomain() +
173 "\" instead of blank or GRID; cannot read metadata as a SkyWcs");
177 gridIndex = initialBaseIndex;
181 if (!rawFrameSet->findFrame(
ast::Frame(2,
"Domain=IWC"))) {
184 auto const iwcIndex = rawFrameSet->getCurrent();
185 auto const iwcFrame = rawFrameSet->getFrame(iwcIndex);
190 auto const stdSkyFrameTemplate =
ast::SkyFrame(
"System=ICRS");
197 if (!rawFrameSet->findFrame(stdSkyFrameTemplate)) {
199 "Could not find a SkyFrame; cannot read metadata as a SkyWcs");
201 auto initialSkyIndex = rawFrameSet->getCurrent();
207 rawFrameSet->setBase(initialSkyIndex);
208 auto stdSkyFrameSet = rawFrameSet->findFrame(stdSkyFrameTemplate);
209 if (!stdSkyFrameSet) {
211 "Bug: found a SkyFrame the first time, but not the second time");
218 rawFrameSet->addFrame(initialSkyIndex, *stdSkyFrameSet->getMapping()->simplified(),
220 auto const stdSkyIndex = rawFrameSet->getCurrent();
221 auto const stdSkyFrame = rawFrameSet->getFrame(stdSkyIndex,
false);
230 auto const gridToIwc = rawFrameSet->getMapping(gridIndex, iwcIndex)->simplified();
231 auto const pixelToIwc = pixelToGrid.then(*gridToIwc).simplified();
232 auto const iwcToStdSky = rawFrameSet->getMapping(iwcIndex, stdSkyIndex);
234 auto frameDict = std::make_shared<ast::FrameDict>(
ast::Frame(2,
"Domain=PIXELS"), *pixelToIwc, *iwcFrame);
235 frameDict->addFrame(
"IWC", *iwcToStdSky, *stdSkyFrame);
239 auto crpixPixels = pixelToGrid.applyInverse(crpixGrid);
240 auto crvalRad = frameDict->applyForward(crpixPixels);
241 auto skyFrame = std::dynamic_pointer_cast<ast::SkyFrame>(frameDict->getFrame(
"SKY",
false));
245 skyFrame->setSkyRefIs(
"Ignored");
246 skyFrame->setSkyRef(crvalRad);
252 int const numCards = fitsChan.
getNCard();
253 auto metadata = std::make_shared<daf::base::PropertyList>();
254 for (
int cardNum = 1; cardNum <= numCards; ++cardNum) {
261 auto foundValue = fitsChan.
getFitsF();
262 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
266 auto foundValue = fitsChan.
getFitsI();
267 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
271 auto foundValue = fitsChan.
getFitsS();
272 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
276 auto foundValue = fitsChan.
getFitsL();
277 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
281 if (cardComment.empty()) {
282 metadata->set(cardName,
nullptr);
284 metadata->set(cardName,
nullptr, cardComment);
290 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
300 os <<
"Card " << cardNum <<
" with name \"" << cardName <<
"\" has type "
301 <<
static_cast<int>(cardType) <<
", which is not supported by PropertyList";
307 os <<
"Bug! Card " << cardNum <<
" with name \"" << cardName
308 <<
"\" has type NOTYPE, which should not be possible";
333 for (
auto const &fullName : allParamNames) {
334 if (excludeNames.
count(fullName) == 0) {
335 std::size_t lastPeriod = fullName.rfind(
char(
'.'));
336 auto name = (lastPeriod == std::string::npos) ? fullName : fullName.substr(lastPeriod + 1);
339 if (
name.size() > 8) {
343 if (
type ==
typeid(
bool)) {
347 }
else if (
type ==
typeid(
int)) {
349 }
else if (
type ==
typeid(
double) ||
type ==
typeid(float)) {
351 if (
type ==
typeid(
double)) {
352 value = metadata.
get<
double>(
name);
354 value =
static_cast<double>(metadata.
get<
float>(
name));
358 fc.setFitsF(
name, value);
362 boost::format(
"Found NaN in metadata item '%s'") %
name);
367 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.
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)