32 #include "boost/format.hpp"
73 void setMetadataFromFoundValue(daf::base::PropertyList& metadata,
std::string const&
name,
75 if (!foundValue.
found) {
76 throw LSST_EXCEPT(pex::exceptions::LogicError,
"Bug! FitsChan card \"" +
name +
"\" not found");
78 if (comment.empty()) {
81 metadata.set(
name, foundValue.
value, comment);
95 excludeNames.
insert(moreNames.begin(), moreNames.end());
98 if (metadata.
exists(
"RADECSYS") && !metadata.
exists(
"RADESYS")) {
100 metadata.
remove(
"RADECSYS");
104 "Encoding=FITS-WCS, IWC=1, SipReplace=0, ReportLevel=3");
108 obj = channel.read();
113 auto frameSet = std::dynamic_pointer_cast<ast::FrameSet>(obj);
116 "metadata describes a " + obj->
getClassName() +
", not a FrameSet");
119 auto const finalNames = setFromVector(channel.getAllCardNames());
123 std::set_difference(initialNames.begin(), initialNames.end(), finalNames.begin(), finalNames.end(),
132 for (
auto const&
name : namesToStrip) {
154 auto const initialBaseIndex = rawFrameSet->getBase();
158 if (rawFrameSet->findFrame(
ast::Frame(2,
"Domain=GRID"))) {
159 gridIndex = rawFrameSet->getCurrent();
163 auto const baseFrame = rawFrameSet->getFrame(initialBaseIndex,
false);
164 auto const baseClassName = rawFrameSet->getClassName();
165 if (baseFrame->getClassName() !=
"Frame") {
167 "The base frame is of type " + baseFrame->getClassName() +
168 "instead of Frame; cannot read metadata as a SkyWcs");
170 if (baseFrame->getNAxes() != 2) {
173 " axes instead of 2; cannot read metadata as a SkyWcs");
175 if (baseFrame->getDomain() !=
"") {
177 "The base frame has domain \"" + baseFrame->getDomain() +
178 "\" instead of blank or GRID; cannot read metadata as a SkyWcs");
182 gridIndex = initialBaseIndex;
186 if (!rawFrameSet->findFrame(
ast::Frame(2,
"Domain=IWC"))) {
189 auto const iwcIndex = rawFrameSet->getCurrent();
190 auto const iwcFrame = rawFrameSet->getFrame(iwcIndex);
195 auto const stdSkyFrameTemplate =
ast::SkyFrame(
"System=ICRS");
202 if (!rawFrameSet->findFrame(stdSkyFrameTemplate)) {
204 "Could not find a SkyFrame; cannot read metadata as a SkyWcs");
206 auto initialSkyIndex = rawFrameSet->getCurrent();
212 rawFrameSet->setBase(initialSkyIndex);
213 auto stdSkyFrameSet = rawFrameSet->findFrame(stdSkyFrameTemplate);
214 if (!stdSkyFrameSet) {
216 "Bug: found a SkyFrame the first time, but not the second time");
223 rawFrameSet->addFrame(initialSkyIndex, *stdSkyFrameSet->getMapping()->simplified(),
225 auto const stdSkyIndex = rawFrameSet->getCurrent();
226 auto const stdSkyFrame = rawFrameSet->getFrame(stdSkyIndex,
false);
235 auto const gridToIwc = rawFrameSet->getMapping(gridIndex, iwcIndex)->simplified();
236 auto const pixelToIwc = pixelToGrid.then(*gridToIwc).simplified();
237 auto const iwcToStdSky = rawFrameSet->getMapping(iwcIndex, stdSkyIndex);
239 auto frameDict = std::make_shared<ast::FrameDict>(
ast::Frame(2,
"Domain=PIXELS"), *pixelToIwc, *iwcFrame);
240 frameDict->addFrame(
"IWC", *iwcToStdSky, *stdSkyFrame);
244 auto crpixPixels = pixelToGrid.applyInverse(crpixGrid);
245 auto crvalRad = frameDict->applyForward(crpixPixels);
246 auto skyFrame = std::dynamic_pointer_cast<ast::SkyFrame>(frameDict->getFrame(
"SKY",
false));
250 skyFrame->setSkyRefIs(
"Ignored");
251 skyFrame->setSkyRef(crvalRad);
257 int const numCards = fitsChan.
getNCard();
258 auto metadata = std::make_shared<daf::base::PropertyList>();
259 for (
int cardNum = 1; cardNum <= numCards; ++cardNum) {
265 case ast::CardType::FLOAT: {
266 auto foundValue = fitsChan.
getFitsF();
267 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
270 case ast::CardType::INT: {
271 auto foundValue = fitsChan.
getFitsI();
272 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
275 case ast::CardType::STRING: {
276 auto foundValue = fitsChan.
getFitsS();
277 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
280 case ast::CardType::LOGICAL: {
281 auto foundValue = fitsChan.
getFitsL();
282 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
286 if (cardComment.empty()) {
287 metadata->set(cardName,
nullptr);
289 metadata->set(cardName,
nullptr, cardComment);
293 case ast::CardType::CONTINUE: {
295 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
298 case ast::CardType::COMMENT:
301 case ast::CardType::COMPLEXF:
302 case ast::CardType::COMPLEXI: {
305 os <<
"Card " << cardNum <<
" with name \"" << cardName <<
"\" has type "
306 <<
static_cast<int>(cardType) <<
", which is not supported by PropertyList";
309 case ast::CardType::NOTYPE: {
312 os <<
"Bug! Card " << cardNum <<
" with name \"" << cardName
313 <<
"\" has type NOTYPE, which should not be possible";
338 for (
auto const &fullName : allParamNames) {
339 if (excludeNames.
count(fullName) == 0) {
340 std::size_t lastPeriod = fullName.rfind(
char(
'.'));
341 auto name = (lastPeriod == std::string::npos) ? fullName : fullName.substr(lastPeriod + 1);
344 if (
name.size() > 8) {
348 if (
type ==
typeid(
bool)) {
352 }
else if (
type ==
typeid(
int)) {
354 }
else if (
type ==
typeid(
double) ||
type ==
typeid(float)) {
356 if (
type ==
typeid(
double)) {
357 value = metadata.
get<
double>(
name);
359 value =
static_cast<double>(metadata.
get<
float>(
name));
363 fc.setFitsF(
name, value);
367 boost::format(
"Found NaN in metadata item '%s'") %
name);
372 if (str.
size() <= 68) {