8 #define PACKAGE_NAME "n/a" 11 #ifndef PACKAGE_VERSION 12 #define PACKAGE_VERSION "n/a" 16 #define REVISION "n/a" 29 class ofits :
public std::ostream
47 Key() : delim(false), offset(0), changed(true) { }
48 Key(
const std::string &s) : delim(false), fitsString(s), offset(0), changed(true) { }
53 const size_t first = str.find_first_not_of(
' ');
54 const size_t last = str.find_last_not_of(
' ');
57 if (std::string::npos==first || std::string::npos==last)
60 return str.substr(first, last-first+1);
69 throw std::runtime_error(
"Key name empty.");
77 std::ostringstream sout;
78 sout <<
"Key '" << key <<
"' exceeds 8 bytes.";
80 throw std::runtime_error(sout.str());
88 #if GCC_VERSION < 40603 89 for (std::string::const_iterator c=key.begin(); c<key.end(); c++)
91 for (std::string::const_iterator c=key.cbegin(); c<key.cend(); c++)
93 if ((*c<'A' || *c>
'Z') && (*c<'0' || *c>
'9') && *c!=
'-' && *c!=
'_')
95 std::ostringstream sout;
96 sout <<
"Invalid character '" << *c <<
"' found in key '" << key <<
"'";
98 throw std::runtime_error(sout.str());
110 comment =
Trim(comment);
112 #if GCC_VERSION < 40603 113 for (std::string::const_iterator c=key.begin(); c<key.end(); c++)
115 for (std::string::const_iterator c=key.cbegin(); c<key.cend(); c++)
119 std::ostringstream sout;
120 sout <<
"Invalid character '" << *c <<
"' [" << int(*c) <<
"] found in comment '" << comment <<
"'";
122 throw std::runtime_error(sout.str());
146 std::ostringstream sout;
147 sout <<
"Size " << sz <<
" of entry for key '" << key <<
"' exceeds 80 characters.";
149 throw std::runtime_error(sout.str());
164 std::ostringstream sout;
165 sout <<
"Size " << sz <<
" of entry for key '" << key <<
"' exceeds 80 characters... removed comment.";
171 std::ostringstream sout;
172 sout <<
"Size " << sz <<
" of entry for key '" << key <<
"' exceeds 80 characters even without comment.";
174 throw std::runtime_error(sout.str());
184 return 10+comment.size();
186 return 10 + (value.size()<20?20:value.size()) + 3 + comment.size();
191 if (!fitsString.empty())
194 std::ostringstream sout;
195 sout << std::left << std::setw(8) <<
key;
204 sout << (!value.empty() && value[0]==
'\''?std::left:std::right);
205 sout << std::setw(20) << value << std::left;
207 if (!comment.empty())
208 sout <<
" / " << comment;
215 void Out(std::ostream &fout)
221 str.insert(str.end(), 80-str.size(),
' ');
224 offset = fout.tellp();
232 checksum.
add(str.c_str(), 80);
253 for (
auto it=fKeys.begin(); it!=fKeys.end(); it++)
277 std::ostringstream sout;
278 sout <<
"No new header key can be defined, rows were already written to the file... ignoring new key '" <<
key <<
"'";
280 throw std::runtime_error(sout.str());
297 fKeys.emplace_back(entry);
321 Table() : offset(0), bytes_per_row(0), num_rows(0), num_cols(0)
331 std::vector<Table::Column>::const_iterator
findcol(
const std::string &name)
333 for (
auto it=fTable.
cols.cbegin(); it!=fTable.
cols.cend(); it++)
337 return fTable.
cols.cend();
348 :
std::ostream(), fFilebuf(), fCommentTrimming(false), fManualExtName(false)
354 :
std::ostream(), fFilebuf(), fCommentTrimming(false), fManualExtName(false)
360 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 361 ofits(
const std::string &fname)
382 return fFilebuf.is_open();
387 return fFilebuf.is_open();
390 virtual void open(
const char *filename,
bool addEXTNAMEKey=
true)
398 SetStr(
"XTENSION",
"BINTABLE",
"binary table extension");
399 SetInt(
"BITPIX", 8,
"8-bit bytes");
400 SetInt(
"NAXIS", 2,
"2-dimensional binary table");
401 SetInt(
"NAXIS1", 0,
"width of table in bytes");
402 SetInt(
"NAXIS2", 0,
"number of rows in table");
403 SetInt(
"PCOUNT", 0,
"size of special data area");
404 SetInt(
"GCOUNT", 1,
"one data group (required keyword)");
405 SetInt(
"TFIELDS", 0,
"number of fields in each row");
407 SetStr(
"EXTNAME",
"",
"name of extension table");
409 fManualExtName =
true;
410 SetStr(
"CHECKSUM",
"0000000000000000",
"Checksum for the whole HDU");
411 SetStr(
"DATASUM",
" 0",
"Checksum for the data block");
413 if (!fFilebuf.open(filename, ios_base::out|ios_base::trunc))
414 setstate(ios_base::failbit);
419 virtual void open(
const std::string &filename,
bool addEXTNAMEKey=
true)
421 open(filename.c_str(), addEXTNAMEKey);
426 fCommentTrimming = allow;
471 throw std::runtime_error(
"No header keys can be copied, rows were already written to the file... ignoring CopyKeys().");
473 gLog <<
___err___ <<
"ERROR - No header key can be copyied, rows were already written to the file... ignoring CopyKeys()." << std::endl;
478 const auto &keys = fin.
GetKeys();
481 for (
auto it=keys.cbegin(); it!=keys.cend(); it++)
483 const std::string &
key = it->first;
488 const auto &entry = it->second;
491 if (entry.fitsString[9]==
'=')
495 if (it2!=fKeys.end())
504 fKeys.emplace_back(entry.fitsString);
513 return Set(key,
true, val, comment);
528 for (uint
i=0;
i<s.length();
i++)
537 std::ostringstream sout;
545 std::ostringstream sout;
548 sout << std::setprecision(-p) << fixed;
550 sout << std::setprecision(p);
552 sout << std::setprecision(f>1e-100 && f<1e100 ? 15 : 14);
556 std::string
str = sout.str();
558 replace(str.begin(), str.end(),
'e',
'E');
560 if (str.find_first_of(
'E')==std::string::npos && str.find_first_of(
'.')==std::string::npos)
573 std::ostringstream sout;
574 sout << std::hex <<
"0x" <<
i;
580 return Set(
"COMMENT",
false,
"", comment);
585 return Set(
"HISTORY",
false,
"", comment);
591 while (fKeys.size()%36!=0)
592 fKeys.emplace_back();
596 virtual bool AddColumn(uint32_t cnt,
char typechar,
const std::string &name,
const std::string &unit,
const std::string &
comment=
"",
bool addHeaderKeys=
true)
600 std::ostringstream sout;
601 sout <<
"File not open... ignoring column '" << name <<
"'";
603 throw std::runtime_error(sout.str());
612 std::ostringstream sout;
613 sout <<
"Header already written, no new column can be defined... ignoring column '" << name <<
"'";
615 throw std::runtime_error(sout.str());
624 std::ostringstream sout;
625 sout <<
"A column with the name '" << name <<
"' already exists.";
627 throw std::runtime_error(sout.str());
634 typechar = toupper(typechar);
636 static const std::string allow(
"LABIJKEDQ");
637 #if GCC_VERSION < 40603 638 if (std::find(allow.begin(), allow.end(), typechar)==allow.end())
640 if (std::find(allow.cbegin(), allow.cend(), typechar)==allow.end())
643 std::ostringstream sout;
644 sout <<
"Column type '" << typechar <<
"' not supported.";
646 throw std::runtime_error(sout.str());
653 std::ostringstream
type;
664 #if GCC_VERSION < 40603 665 const std::string nc = std::to_string((
long long int)(fTable.
num_cols));
667 const std::string nc = std::to_string(fTable.
num_cols);
672 SetStr(
"TUNIT"+nc, unit,
"unit of "+name);
685 fTable.
cols.emplace_back(col);
695 virtual bool AddColumn(
const FITS::Compression&, uint32_t cnt,
char typechar,
const std::string& name,
const std::string& unit,
const std::string&
comment=
"",
bool addHeaderKeys=
true)
700 bool AddColumnShort(uint32_t cnt,
const std::string &name,
const std::string &unit=
"",
const std::string &
comment=
"")
702 bool AddColumnInt(uint32_t cnt,
const std::string &name,
const std::string &unit=
"",
const std::string &
comment=
"")
704 bool AddColumnLong(uint32_t cnt,
const std::string &name,
const std::string &unit=
"",
const std::string &
comment=
"")
706 bool AddColumnFloat(uint32_t cnt,
const std::string &name,
const std::string &unit=
"",
const std::string &
comment=
"")
710 bool AddColumnChar(uint32_t cnt,
const std::string &name,
const std::string &unit=
"",
const std::string &
comment=
"")
712 bool AddColumnByte(uint32_t cnt,
const std::string &name,
const std::string &unit=
"",
const std::string &
comment=
"")
714 bool AddColumnBool(uint32_t cnt,
const std::string &name,
const std::string &unit=
"",
const std::string &
comment=
"")
786 for (
auto it=fKeys.begin(); it!=fKeys.end(); it++)
804 const off_t pos = tellp();
813 h.
SetBool(
"SIMPLE",
true,
"file does conform to FITS standard");
814 h.
SetInt (
"BITPIX", 8,
"number of bits per data pixel");
815 h.
SetInt (
"NAXIS", 0,
"number of data axes");
816 h.
SetBool(
"EXTEND",
true,
"FITS dataset may contain extensions");
817 h.
SetStr (
"CHECKSUM",
"0000000000000000",
"Checksum for the whole HDU");
818 h.
SetStr (
"DATASUM",
" 0",
"Checksum for the data block");
819 h.
AddComment(
"FITS (Flexible Image Transport System) format is defined in 'Astronomy");
820 h.
AddComment(
"and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H");
827 const size_t offset = tellp();
849 throw std::runtime_error(
"File not empty anymore.");
851 gLog <<
___err___ <<
"ERROR - File not empty anymore." << std::endl;
875 void revcpy(
char *dest,
const char *src,
int num)
877 const char *pend = src + num*N;
878 for (
const char *ptr = src; ptr<pend; ptr+=N, dest+=N)
879 std::reverse_copy(ptr, ptr+N, dest);
884 virtual bool WriteRow(
const void *ptr,
size_t cnt,
bool byte_swap=
true)
890 std::ostringstream sout;
891 sout <<
"WriteRow - Size " << cnt <<
" does not match expected size " << fTable.
bytes_per_row;
893 throw std::runtime_error(sout.str());
905 auto ib = fOutputBuffer.begin();
906 auto ie = fOutputBuffer.rbegin();
918 memcpy(buffer, ptr, cnt);
921 for (
auto it=fTable.
cols.cbegin(); it!=fTable.
cols.cend(); it++)
923 const char *src =
reinterpret_cast<const char*
>(ptr) + it->offset;
924 char *dest = buffer + it->offset;
930 case 1: memcpy (dest, src, it->num*it->size);
break;
931 case 2: revcpy<2>(dest, src, it->num);
break;
932 case 4: revcpy<4>(dest, src, it->num);
break;
933 case 8: revcpy<8>(dest, src, it->num);
break;
939 fDataSum.
add(fOutputBuffer);
949 return WriteRow(vec.data(), vec.size()*
sizeof(N));
963 if (tellp()%(80*36)>0)
965 std::vector<char> filler(80*36-tellp()%(80*36));
966 write(filler.data(), filler.size());
972 std::ostringstream dataSumStr;
973 dataSumStr << fDataSum.
val();
974 SetStr(
"DATASUM", dataSumStr.str());
980 SetStr(
"CHECKSUM", (sum+fDataSum).
str());
996 if (!fFilebuf.close())
997 setstate(ios_base::failbit);
999 if ((chk+fDataSum).valid())
1002 std::ostringstream sout;
1003 sout <<
"Checksum (" << std::hex << chk.
val() <<
") invalid.";
1005 throw std::runtime_error(sout.str());
1014 std::string datasum;
1017 for (std::vector<Key>::const_iterator it=fKeys.cbegin(); it!= fKeys.cend(); it++)
1019 if (it->key ==
"CHECKSUM") checksum = it->value;
1020 if (it->key ==
"DATASUM") datasum = it->value;
1022 if (checksum[0] ==
'\'')
1023 checksum = checksum.substr(1,checksum.size()-2);
1024 if (datasum[0] ==
'\'')
1025 datasum = datasum.substr(1, datasum.size()-2);
1026 return std::make_pair(checksum, atoi(datasum.c_str()));
1031 SetStr(
"TELESCOP",
"FACT",
"Telescope that acquired this data");
1032 SetStr(
"CREATOR",
typeid(*this).name(),
"Class that wrote this file");
1033 SetFloat(
"EXTREL", 1.0,
"Release Number");
1034 SetStr(
"COMPILED", __DATE__
" " __TIME__,
"Compile time");
1035 SetStr(
"ORIGIN",
"FACT",
"Institution that wrote the file");
1036 SetStr(
"TIMESYS",
"UTC",
"Time system");
1037 SetStr(
"TIMEUNIT",
"d",
"Time given in days w.r.t. to MJDREF");
1038 SetInt(
"MJDREF", 40587,
"MJD to UNIX time (seconds since 1970/1/1)");
1043 const time_t t0 =
time(NULL);
1044 const struct tm *tmp1 = gmtime(&t0);
1046 std::string
str(19,
'\0');
1047 if (tmp1 && strftime(const_cast<char*>(str.data()), 20,
"%Y-%m-%dT%H:%M:%S", tmp1))
1048 SetStr(
"DATE", str,
"File creation date");
1057 using namespace std;
1059 ofits h2(
"delme.fits");
1061 h2.
SetInt(
"KEY1", 1,
"comment 1");
1062 h2.
AddColumnInt(2,
"testcol1",
"counts",
"My comment");
1065 h2.
SetInt(
"KEY2", 2,
"comment 2");
1084 for (
int i=0;
i<10;
i++)
1086 int j[3] = {
i+10,
i*10, i*100 };
1092 h2.
SetInt(
"KEY2", 2,
"comment 2xxx");
1097 cout <<
"---" << endl;
1099 fits f(
"delme.fits");
1101 throw std::runtime_error(
"xxx");
1103 cout <<
"Header is valid: " << f.
IsHeaderOk() << endl;
1107 cout <<
"File is valid: " << f.
IsFileOk() << endl;
1109 cout <<
"---" << endl;
bool SetInt(const std::string &key, int64_t i, const std::string &comment="")
bool AddColumnByte(const std::string &name, const std::string &unit="", const std::string &comment="")
bool SetHex(const std::string &key, uint64_t i, const std::string &comment="")
static bool IsReservedKeyWord(const std::string &key)
Checksum UpdateHeaderChecksum()
bool AddColumnLong(const FITS::Compression &comp, uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnLong(const FITS::Compression &comp, const std::string &name, const std::string &unit="", const std::string &comment="")
virtual void open(const std::string &filename, bool addEXTNAMEKey=true)
bool AddColumnShort(const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnDouble(const FITS::Compression &comp, const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnDouble(const FITS::Compression &comp, uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool WriteRow(const std::vector< N > &vec)
void revcpy(char *dest, const char *src, int num)
std::pair< std::string, int > GetChecksumData()
bool check(bool trim=false)
bool SetKeyComment(const std::string &key, const std::string &comment)
bool AddColumnByte(uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddHistory(const std::string &comment)
bool AddColumnByte(const FITS::Compression &comp, const std::string &name, const std::string &unit="", const std::string &comment="")
void Out(std::ostream &fout)
virtual uint32_t GetBytesPerRow() const
bool CopyKeys(const fits &fin, bool update=false)
virtual bool AddColumn(uint32_t cnt, char typechar, const std::string &name, const std::string &unit, const std::string &comment="", bool addHeaderKeys=true)
bool SetBool(const std::string &key, bool b, const std::string &comment="")
bool AddColumnChar(uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
int64_t first
Size of this column in the tile.
bool AddColumnFloat(const FITS::Compression &comp, uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddComment(const std::string &comment)
virtual bool WriteDrsOffsetsTable()
bool AddColumnInt(const FITS::Compression &comp, const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnInt(uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnChar(const FITS::Compression &comp, uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnShort(uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool GetNextRow(bool check=true)
bool AddColumnChar(const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnBool(const FITS::Compression &comp, uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
static uint32_t SizeFromType(char type)
const Table::Keys & GetKeys() const
std::vector< Column > cols
bool AddColumnFloat(uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
virtual void open(const char *filename, bool addEXTNAMEKey=true)
bool AddColumnLong(const std::string &name, const std::string &unit="", const std::string &comment="")
bool SetStr(const std::string &key, std::string s, const std::string &comment="")
bool AddColumnDouble(const std::string &name, const std::string &unit="", const std::string &comment="")
Key(const std::string &s)
virtual bool AddColumn(const FITS::Compression &, uint32_t cnt, char typechar, const std::string &name, const std::string &unit, const std::string &comment="", bool addHeaderKeys=true)
bool AddColumnBool(const std::string &name, const std::string &unit="", const std::string &comment="")
virtual bool WriteCatalog()
bool AddColumnFloat(const std::string &name, const std::string &unit="", const std::string &comment="")
bool SetRaw(const std::string &key, const std::string &val, const std::string &comment)
std::string str(bool complm=true) const
Warning because the service this data corrsponds to might have been last updated longer ago than Local time
std::vector< Table::Column >::const_iterator findcol(const std::string &name)
void AllowCommentsTrimming(bool allow)
std::vector< Key >::iterator findkey(const std::string &key)
bool AddColumnChar(const FITS::Compression &comp, const std::string &name, const std::string &unit="", const std::string &comment="")
virtual void FlushNumRows()
bool AddColumnInt(const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnByte(const FITS::Compression &comp, uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool Set(const std::string &key="", bool delim=false, const std::string &value="", const std::string &comment="")
bool AddColumnShort(const FITS::Compression &comp, const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnShort(const FITS::Compression &comp, uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
std::string Trim(const std::string &str)
bool AddColumnBool(uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool SetFloat(const std::string &key, double f, int p, const std::string &comment="")
std::vector< char > fOutputBuffer
virtual bool IsFileOk() const
bool AddColumnFloat(const FITS::Compression &comp, const std::string &name, const std::string &unit="", const std::string &comment="")
size_t GetNumRows() const
bool AddColumnInt(const FITS::Compression &comp, uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
virtual bool WriteTableHeader(const char *name="DATA")
static std::string CommentFromType(char type)
bool add(const char *buf, size_t len, bool big_endian=true)
Checksum WriteHeader(std::ostream &fout)
bool AddColumnLong(uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnDouble(uint32_t cnt, const std::string &name, const std::string &unit="", const std::string &comment="")
bool AddColumnBool(const FITS::Compression &comp, const std::string &name, const std::string &unit="", const std::string &comment="")
virtual bool WriteRow(const void *ptr, size_t cnt, bool byte_swap=true)
Checksum WriteFitsHeader()
bool AddEmpty(const std::string &key, const std::string &comment="")
bool SetFloat(const std::string &key, double f, const std::string &comment="")