Isis 3 Programmer Reference
FitsToJson.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "FitsToJson.h"
8
9#include <nlohmann/json.hpp>
10#include <QString>
11
12#include "IException.h"
13#include "IString.h"
14#include "PvlObject.h"
15#include "PvlGroup.h"
16#include "PvlToJSON.h"
17
18using json = nlohmann::json;
19
20namespace Isis {
21
30 json fitsToJson(std::ifstream &fileStream) {
31 PvlObject fitsPvl;
32 QList<PvlGroup *> *fitsImageLabels = new QList< PvlGroup * >;
33 QList<PvlGroup *> *extraFitsLabels = new QList< PvlGroup * >;
34 QList<int> *headerSizes = new QList < int >;
35 QList<int> *dataStarts = new QList < int >;
36
37 // Process each FITS label area, storing each in its own PvlGroup.
38 char readBuf[81];
39 IString line = "";
40 unsigned int place;
41
42 // Start at the beginning of the file for the main FITS label
43 fileStream.seekg(0, std::ios_base::beg);
44
45 // Reads each label line (80 chars)
46 while (fileStream.read(readBuf, 80) && fileStream.gcount() == 80) {
47
48 PvlGroup *fitsLabel = new PvlGroup("FitsLabels");
49
50 readBuf[80] = '\0';
51 line = readBuf;
52 place = 80;
53
54 // Process each fits label record (80 bytes) and place keyword, value pairs into PvlKeywords
55 // with any associated comments.
56 while (line.substr(0, 3) != "END") {
57
58 // Check for blank lines
59 if (line.substr(0, 1) != " " && line.substr(0, 1) != "/") {
60 // Name of keyword
61 PvlKeyword label(line.Token(" =").ToQt()); // Stop on spaces OR equal sign
62 if (QString::compare(label.name(), "OBJECT", Qt::CaseInsensitive) == 0) {
63 label.setName("TARGET");
64 label.addComment("NOTE: This keyword name was changed from 'OBJECT' in the original "
65 "fit header file.");
66 }
67 // Remove up to beginning of data
68 line.TrimHead(" =");
69 line.TrimTail(" ");
70 if (label.name() == "COMMENT" || label.name() == "HISTORY") {
71 label += line.ToQt();
72 }
73 else {
74 // Check for a quoted value
75 if (line.substr(0,1) == "'") {
76 line.TrimHead("'");
77 label += line.Token("'").TrimHead(" ").TrimTail(" ").ToQt();
78 line.TrimHead(" '");
79 }
80 else {
81 // Access any remaining data without the trailing comment if there is one
82 IString value = line.Token("/");
83 value.TrimTail(" ");
84 label += value.ToQt();
85 line.TrimHead(" ");
86 }
87 // If the line still has anything in it, treat it is as a comment.
88 if (line.size() > 0) {
89 line.TrimHead(" /");
90 label.addComment(line.ToQt());
91 if (line != line.Token("[")) {
92 label.setUnits(line.Token("[").Token("]").ToQt());
93 }
94 }
95 }
96 fitsLabel->addKeyword(label);
97 }
98
99 fileStream.read(readBuf, 80);
100 readBuf[80] = '\0';
101 line = readBuf;
102 place += 80;
103 }
104 fitsPvl.addGroup(*fitsLabel);
105 // Move the file pointer past the padding after the "END" (i.e., points to start of data)
106 std::streamoff jump;
107 jump = headerSizes->last() * 2880 - place;
108 fileStream.seekg(jump, std::ios_base::cur);
109
110 dataStarts->append(fileStream.tellg());
111
112 if (fitsLabel->hasKeyword("BITPIX") && fitsLabel->hasKeyword("NAXIS")) {
113
114 if((int)fitsLabel->findKeyword("NAXIS") > 0) {
115 int bytesPerPixel = 0;
116 bytesPerPixel = (int)((*fitsLabel)["BITPIX"]);
117 bytesPerPixel = std::abs(bytesPerPixel);
118 bytesPerPixel /= 8;
119
120 unsigned int axis1 = 1;
121 axis1 = toInt((*fitsLabel)["NAXIS1"]);
122
123 unsigned int axis2 = 1;
124 if (fitsLabel->hasKeyword("NAXIS2")) {
125 axis2 = toInt((*fitsLabel)["NAXIS2"]);
126 }
127
128 unsigned int axis3 = 1;
129 if (fitsLabel->hasKeyword("NAXIS3")) {
130 axis3 = toInt((*fitsLabel)["NAXIS3"]);
131 }
132
133 jump = (int)(ceil(bytesPerPixel * axis1 * axis2 * axis3 / 2880.0) * 2880.0);
134 fileStream.seekg(jump, std::ios_base::cur);
135 }
136 else {
137 // Note: this will allow us to read extra label sections that have 0 axes,
138 // but has image-related info (so BITPIX and NAXIS keywords exist). This
139 // includes informational labels, as seen at the beginning of hayabusa2
140 // images in this case, there is NO DATA, so no jump should be needed to
141 // get to the next section.
142 PvlGroup *extraLabelGroup = fitsImageLabels->last();
143 extraLabelGroup->setName("FitsExtras");
144 extraFitsLabels->append(extraLabelGroup);
145
146 fitsImageLabels->removeLast();
147 headerSizes->removeLast();
148 dataStarts->removeLast();
149
150 fitsPvl.addGroup(*extraLabelGroup);
151 }
152 }
153 else if (fitsImageLabels->size() > 1) {
154 fitsImageLabels->removeLast();
155 headerSizes->removeLast();
156 dataStarts->removeLast();
157 break;
158 }
159
160 else {
161 QString msg = QObject::tr("The FITS file does not contain a section header that appears "
162 "to describe an image.");
163 throw IException(IException::User, msg, _FILEINFO_);
164 }
165 }
166 return pvlObjectToJSON(fitsPvl);
167 }
168
169
177 json fitsToJson(FileName fitsFile) {
178 std::ifstream fileStream;
179 try {
180 fileStream.open(fitsFile.expanded().toLocal8Bit().constData(), std::ios::in | std::ios::binary);
181 }
182 catch (IException &e) {
183 QString msg = QString("Unable to open FITS formatted file [%1].")
184 .arg(fitsFile.toString());
185 throw IException(e, IException::User, msg, _FILEINFO_);
186 }
187
188 return fitsToJson(fileStream);
189 }
190
191}
File name manipulation and expansion.
Definition FileName.h:100
Isis exception class.
Definition IException.h:91
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
Adds specific functionality to C++ strings.
Definition IString.h:165
IString TrimTail(const std::string &chars)
Trims the input characters from the end of the object IString.
Definition IString.cpp:587
IString Token(const IString &separator)
Returns the first token in the IString.
Definition IString.cpp:897
QString ToQt() const
Retuns the object string as a QString.
Definition IString.cpp:869
IString TrimHead(const std::string &chars)
Trims The input characters from the beginning of the object IString.
Definition IString.cpp:558
void setName(const QString &name)
Set the name of the container.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
A single keyword-value pair.
Definition PvlKeyword.h:87
void setName(QString name)
Sets the keyword name.
QString name() const
Returns the keyword name.
Definition PvlKeyword.h:103
void setUnits(QString units)
Sets the unit of measure for all current values if any exist.
void addComment(QString comment)
Add a comment to the PvlKeyword.
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition IString.cpp:93
json fitsToJson(std::ifstream &fileStream)
Convert the contents of a stream to a JSON object.
json pvlObjectToJSON(PvlObject &object)
Convert the contents of a PvlObject to a JSON object.