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) {
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) {
305 case ast::CardType::FLOAT: {
306 auto foundValue = fitsChan.
getFitsF();
307 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
310 case ast::CardType::INT: {
311 auto foundValue = fitsChan.
getFitsI();
312 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
315 case ast::CardType::STRING: {
316 auto foundValue = fitsChan.
getFitsS();
317 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
320 case ast::CardType::LOGICAL: {
321 auto foundValue = fitsChan.
getFitsL();
322 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
325 case ast::CardType::UNDEF: {
326 if (cardComment.empty()) {
327 metadata->set(cardName,
nullptr);
329 metadata->set(cardName,
nullptr, cardComment);
333 case ast::CardType::CONTINUE: {
335 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
338 case ast::CardType::COMMENT:
341 case ast::CardType::COMPLEXF:
342 case ast::CardType::COMPLEXI: {
345 os <<
"Card " << cardNum <<
" with name \"" << cardName <<
"\" has type "
346 <<
static_cast<int>(cardType) <<
", which is not supported by PropertyList";
349 case ast::CardType::NOTYPE: {
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)) {
392 }
else if (
type ==
typeid(
int)) {
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,...)
#define LOGLS_WARN(logger, message)
std::string getCardComm() const
FoundValue< std::string > getFitsS(std::string const &name="", std::string defval="") const
FoundValue< bool > getFitsL(std::string const &name="", bool defval=false) const
std::string getCardName() const
FoundValue< int > getFitsI(std::string const &name="", int defval=0) const
CardType getCardType() const
FoundValue< double > getFitsF(std::string const &name="", double defval=0) const
FoundValue< std::string > getFitsCN(std::string const &name="", std::string defval="") const
static int constexpr CURRENT
static int constexpr NOFRAME
std::vector< std::string > getOrderedNames() const
std::string getAsString(std::string const &name) const
virtual void remove(std::string const &name)
bool exists(std::string const &name) const
void set(std::string const &name, T const &value)
std::type_info const & typeOf(std::string const &name) const
double getAsDouble(std::string const &name) const
T get(std::string const &name) const
std::vector< std::string > paramNames(bool topLevelOnly=true) const
virtual char const * what(void) const noexcept
T make_move_iterator(T... args)
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)