From 8da6e5978a7f3a4359ec11fcdf5a75c943ca76b8 Mon Sep 17 00:00:00 2001 From: knodlseder <> Date: Sat, 1 Mar 2008 19:02:06 +0000 Subject: [PATCH] start implementation of file creation and saving --- include/GFits.hpp | 1 + include/GFitsCfitsio.hpp | 4 ++++ include/GFitsHDU.hpp | 4 ++++ include/GFitsHeader.hpp | 21 +++++++++++---------- include/GFitsHeaderCard.hpp | 38 ++++++++++++++++++++------------------ src/GException.cpp | 3 ++- src/fits/GFits.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ src/fits/GFitsAsciiTable.cpp | 6 ++++-- src/fits/GFitsBinTable.cpp | 6 ++++-- src/fits/GFitsHDU.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------ src/fits/GFitsHeader.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++------ src/fits/GFitsHeaderCard.cpp | 15 +++++++++++++++ test/test_GFits.cpp | 30 ++++++++++++++++++++++++++++-- 13 files changed, 277 insertions(+), 65 deletions(-) diff --git a/include/GFits.hpp b/include/GFits.hpp index a059563..5e501f5 100644 --- a/include/GFits.hpp +++ b/include/GFits.hpp @@ -46,6 +46,7 @@ public: void close(void); GFitsHDU* hdu(const std::string extname); GFitsHDU* hdu(int extno); + void append(const GFitsHDU* hdu); private: // Private methods diff --git a/include/GFitsCfitsio.hpp b/include/GFitsCfitsio.hpp index 4708053..a219c61 100644 --- a/include/GFitsCfitsio.hpp +++ b/include/GFitsCfitsio.hpp @@ -31,7 +31,9 @@ /* __ Macros _____________________________________________________________ */ #define __ffgerr(A, B) ffgerr(A, B) #define __ffopen(A, B, C, D) ffopen(A, B, C, D) +#define __ffinit(A, B, C) ffinit(A, B, C) #define __ffclos(A, B) ffclos(A, B) +#define __ffdelt(A, B) ffdelt(A, B) #define __ffthdu(A, B, C) ffthdu(A, B, C) #define __ffmahd(A, B, C, D) ffmahd(A, B, C, D) #define __ffghdt(A, B, C) ffghdt(A, B, C) @@ -62,7 +64,9 @@ typedef fitsfile __fitsfile; /* __ Macros _____________________________________________________________ */ #define __ffgerr(A, B) __error(A, B) #define __ffopen(A, B, C, D) __dummy() +#define __ffinit(A, B, C) __dummy() #define __ffclos(A, B) __dummy() +#define __ffdelt(A, B) __dummy() #define __ffthdu(A, B, C) __dummy() #define __ffmahd(A, B, C, D) __dummy() #define __ffghdt(A, B, C) __dummy() diff --git a/include/GFitsHDU.hpp b/include/GFitsHDU.hpp index 7b6b767..7d3cb01 100644 --- a/include/GFitsHDU.hpp +++ b/include/GFitsHDU.hpp @@ -29,6 +29,9 @@ ***************************************************************************/ class GFitsHDU { + // Friend classes + friend class GFits; + // I/O friends friend ostream& operator<< (ostream& os, const GFitsHDU& hdu); @@ -50,6 +53,7 @@ public: GFitsHeader* header(void) const; GFitsData* data(void) const; GFitsTableCol* column(const std::string& colname) const; + void primary(void); private: // Private methods diff --git a/include/GFitsHeader.hpp b/include/GFitsHeader.hpp index d2ab72d..a07674e 100644 --- a/include/GFitsHeader.hpp +++ b/include/GFitsHeader.hpp @@ -41,14 +41,15 @@ public: // Methods void open(__fitsfile* fptr); void close(void); - GFitsHeaderCard* card(const std::string keyname); - GFitsHeaderCard* card(const int cardno); - std::string string(const std::string keyname); - std::string string(const int cardno); - double real(const std::string keyname); - double real(const int cardno); - int integer(const std::string keyname); - int integer(const int cardno); + void update(const GFitsHeaderCard& card); + GFitsHeaderCard* card(const std::string& keyname); + GFitsHeaderCard* card(const int& cardno); + std::string string(const std::string& keyname); + std::string string(const int& cardno); + double real(const std::string& keyname); + double real(const int& cardno); + int integer(const std::string& keyname); + int integer(const int& cardno); GFitsHeader* clone(void) const; private: @@ -68,12 +69,12 @@ private: * Inline methods * ***************************************************************************/ inline -GFitsHeaderCard* GFitsHeader::card(const std::string keyname) +GFitsHeaderCard* GFitsHeader::card(const std::string& keyname) { return GFitsHeader::card_ptr(keyname); } inline -GFitsHeaderCard* GFitsHeader::card(const int cardno) +GFitsHeaderCard* GFitsHeader::card(const int& cardno) { return (cardno >= 0 && cardno < m_num_cards) ? &(m_card[cardno]) : NULL; } diff --git a/include/GFitsHeaderCard.hpp b/include/GFitsHeaderCard.hpp index 6462c4c..1ad4e8b 100644 --- a/include/GFitsHeaderCard.hpp +++ b/include/GFitsHeaderCard.hpp @@ -31,6 +31,8 @@ class GFitsHeaderCard { public: // Constructors & Destructors GFitsHeaderCard(); + GFitsHeaderCard(const std::string& keyname, const std::string& value, + const std::string& comment); GFitsHeaderCard(const GFitsHeaderCard& card); ~GFitsHeaderCard(); @@ -38,18 +40,18 @@ public: GFitsHeaderCard& operator= (const GFitsHeaderCard& card); // Methods - std::string keyname(void); - std::string value(void); - int value_type(void); + std::string keyname(void) const; + std::string value(void) const; + int value_type(void) const; + std::string unit(void) const; + std::string comment(void) const; std::string string(void); double real(void); int integer(void); - std::string unit(void); - std::string comment(void); - void set_keyname(std::string& keyname); - void set_value(std::string& value); - void set_unit(std::string& unit); - void set_comment(std::string& comment); + void set_keyname(const std::string& keyname); + void set_value(const std::string& value); + void set_unit(const std::string& unit); + void set_comment(const std::string& comment); void read(__fitsfile* fptr, int keynum); void read(__fitsfile* fptr, std::string keyname); void write(__fitsfile* fptr); @@ -73,15 +75,15 @@ private: /*************************************************************************** * Inline methods * ***************************************************************************/ -inline std::string GFitsHeaderCard::keyname(void) { return m_keyname; } -inline std::string GFitsHeaderCard::value(void) { return m_value; } -inline int GFitsHeaderCard::value_type(void) { return m_value_type; } -inline std::string GFitsHeaderCard::unit(void) { return m_unit; } -inline std::string GFitsHeaderCard::comment(void) { return m_comment; } -inline void GFitsHeaderCard::set_keyname(std::string& keyname) { m_keyname = keyname; } -inline void GFitsHeaderCard::set_value(std::string& value) { m_value = value; } -inline void GFitsHeaderCard::set_unit(std::string& unit) { m_unit = unit; } -inline void GFitsHeaderCard::set_comment(std::string& comment) { m_comment = comment; } +inline std::string GFitsHeaderCard::keyname(void) const { return m_keyname; } +inline std::string GFitsHeaderCard::value(void) const { return m_value; } +inline int GFitsHeaderCard::value_type(void) const { return m_value_type; } +inline std::string GFitsHeaderCard::unit(void) const { return m_unit; } +inline std::string GFitsHeaderCard::comment(void) const { return m_comment; } +inline void GFitsHeaderCard::set_keyname(const std::string& keyname) { m_keyname = keyname; } +inline void GFitsHeaderCard::set_value(const std::string& value) { m_value = value; } +inline void GFitsHeaderCard::set_unit(const std::string& unit) { m_unit = unit; } +inline void GFitsHeaderCard::set_comment(const std::string& comment) { m_comment = comment; } #endif /* GFITSHEADERCARD_HPP */ diff --git a/src/GException.cpp b/src/GException.cpp index 398ea10..ac8d4c4 100644 --- a/src/GException.cpp +++ b/src/GException.cpp @@ -233,7 +233,8 @@ GException::fits_error::fits_error(string origin, int status) GException::fits_open_error::fits_open_error(string origin, string filename, int status) { m_origin = origin; - m_message = "Unable to open FITS file '" + filename + "'"; + m_message = "Unable to open FITS file '" + filename + "'" + + " (status: " + str(status) + ")"; } diff --git a/src/fits/GFits.cpp b/src/fits/GFits.cpp index f376f10..8f097eb 100644 --- a/src/fits/GFits.cpp +++ b/src/fits/GFits.cpp @@ -134,7 +134,15 @@ void GFits::open(const std::string filename) // Open FITS file int status = 0; status = __ffopen(&m_fitsfile, filename.c_str(), 1, &status); - if (status != 0) + + // If FITS file does not exist then create it now + if (status == 104) { + status = 0; + status = __ffinit(&m_fitsfile, filename.c_str(), &status); + if (status != 0) + throw GException::fits_open_error(G_OPEN, filename, status); + } + else if (status != 0) throw GException::fits_open_error(G_OPEN, filename, status); // Store FITS file attributes @@ -147,7 +155,7 @@ void GFits::open(const std::string filename) // Allocate HDUs if (m_hdu != NULL) delete [] m_hdu; - m_hdu = new GFitsHDU[m_num_hdu]; + if (m_num_hdu > 0) m_hdu = new GFitsHDU[m_num_hdu]; // Open all HDUs for (int i = 0; i < m_num_hdu; ++i) @@ -252,6 +260,62 @@ GFitsHDU* GFits::hdu(const std::string extname) } +/*************************************************************************** + * Append HDU to FITS file * + * ----------------------------------------------------------------------- * + ***************************************************************************/ +void GFits::append(const GFitsHDU* hdu) +{ + // Determine number of HDUs to add. If there are no HDUs so far and if + // the HDU to append is not an image then we have to add a primary + // image first. In this case we add 2 new HDUs. + int n_add = (m_num_hdu == 0 && hdu->m_type != 0) ? 2 : 1; + + // Create memory to hold HDUs + GFitsHDU* tmp = new GFitsHDU[m_num_hdu+n_add]; + if (tmp != NULL) { + + // Copy over existing HDUs and remove old ones + if (m_hdu != NULL) { + for (int i = 0; i < m_num_hdu; ++i) + tmp[i] = m_hdu[i]; + delete [] m_hdu; + } + + // Connect the new memory to the card pointer + m_hdu = tmp; + + // Add primary image if required + if (n_add == 2) { + + // Append empty primary image + //m_hdu[m_num_hdu] = TBD + + // Set FITS file pointer for new HDU + m_hdu[m_num_hdu].m_fitsfile = *m_fitsfile; + m_hdu[m_num_hdu].m_fitsfile.HDUposition = m_num_hdu; + + // Increment number of HDUs + m_num_hdu++; + } + + // Append new HDU to list + m_hdu[m_num_hdu] = *hdu; + + // Set FITS file pointer for new HDU + m_hdu[m_num_hdu].m_fitsfile = *m_fitsfile; + m_hdu[m_num_hdu].m_fitsfile.HDUposition = m_num_hdu; + + // Increment number of HDUs + m_num_hdu++; + + } + + // Return + return; +} + + /*========================================================================== = = = GFits private methods = @@ -311,10 +375,20 @@ void GFits::free_members(void) { // If FITS file has been opened then close it now if (m_fitsfile != NULL) { - int status = 0; - status = __ffclos(m_fitsfile, &status); - if (status != 0) - throw GException::fits_error(G_FREE_MEM, status); + + // If there are no HDUs then delete the file (don't worry about error) + if (m_num_hdu == 0) { + int status = 0; + __ffdelt(m_fitsfile, &status); + } + + // ... otherwise close the file + else { + int status = 0; + status = __ffclos(m_fitsfile, &status); + if (status != 0) + throw GException::fits_error(G_FREE_MEM, status); + } } // Free memory diff --git a/src/fits/GFitsAsciiTable.cpp b/src/fits/GFitsAsciiTable.cpp index 1d1e538..fdfba0a 100644 --- a/src/fits/GFitsAsciiTable.cpp +++ b/src/fits/GFitsAsciiTable.cpp @@ -233,8 +233,10 @@ void GFitsAsciiTable::copy_members(const GFitsAsciiTable& table) // Copy column definition if (table.m_columns != NULL && m_cols > 0) { m_columns = new GFitsTableCol*[m_cols]; - for (int i = 0; i < m_cols; ++i) - m_columns[i] = table.m_columns[i]->clone(); + for (int i = 0; i < m_cols; ++i) { + if (table.m_columns[i] != NULL) + m_columns[i] = table.m_columns[i]->clone(); + } } // Return diff --git a/src/fits/GFitsBinTable.cpp b/src/fits/GFitsBinTable.cpp index 24e51cc..752f562 100644 --- a/src/fits/GFitsBinTable.cpp +++ b/src/fits/GFitsBinTable.cpp @@ -308,8 +308,10 @@ void GFitsBinTable::copy_members(const GFitsBinTable& table) // Copy column definition if (table.m_columns != NULL && m_cols > 0) { m_columns = new GFitsTableCol*[m_cols]; - for (int i = 0; i < m_cols; ++i) - m_columns[i] = table.m_columns[i]->clone(); + for (int i = 0; i < m_cols; ++i) { + if (table.m_columns[i] != NULL) + m_columns[i] = table.m_columns[i]->clone(); + } } // Return diff --git a/src/fits/GFitsHDU.cpp b/src/fits/GFitsHDU.cpp index ddb4133..55b2e84 100644 --- a/src/fits/GFitsHDU.cpp +++ b/src/fits/GFitsHDU.cpp @@ -186,11 +186,17 @@ void GFitsHDU::open(__fitsfile* fptr, int hdunum) /// NOT YET IMPLEMENTED !!! void GFitsHDU::save(void) { +cout << "entry" << endl; // Move to HDU int status = 0; status = __ffmahd(&m_fitsfile, (m_fitsfile.HDUposition)+1, NULL, &status); - if (status != 0) - throw GException::fits_error(G_SAVE, status); + cout << status << endl; + + // If HDU does not exist then create it now + + + //if (status != 0) + // throw GException::fits_error(G_SAVE, status); // Save header //... @@ -198,6 +204,7 @@ void GFitsHDU::save(void) // Save data //... +cout << "exit" << endl; // Return return; } @@ -233,6 +240,31 @@ GFitsTableCol* GFitsHDU::column(const std::string& colname) const } +/*************************************************************************** + * Setup minimal primary HDU * + * ----------------------------------------------------------------------- * + ***************************************************************************/ +void GFitsHDU::primary(void) +{ + // Free any allocated header and data + free_members(); + + // Allocate header + m_header = new GFitsHeader(); + + // Add cards + m_header->update(GFitsHeaderCard("SIMPLE", "T", "/ file does conform to FITS standard")); + m_header->update(GFitsHeaderCard("BITPIX", "8", "/ number of bits per data pixel")); + m_header->update(GFitsHeaderCard("NAXIS", "0", "/ number of data axes")); + m_header->update(GFitsHeaderCard("EXTEND", "T", "/ FITS dataset may contain extensions")); + m_header->update(GFitsHeaderCard("BZERO", "-128", "/ Make values Signed")); + m_header->update(GFitsHeaderCard("BSCALE", "1", "/ Make values Signed")); + + // Return + return; +} + + /*========================================================================== = = = GFitsHDU private methods = @@ -268,8 +300,8 @@ void GFitsHDU::copy_members(const GFitsHDU& hdu) m_fitsfile = hdu.m_fitsfile; m_name = hdu.m_name; m_type = hdu.m_type; - m_header = hdu.m_header->clone(); - m_data = hdu.m_data->clone(); + if (hdu.m_header != NULL) m_header = hdu.m_header->clone(); + if (hdu.m_data != NULL) m_data = hdu.m_data->clone(); // Return return; @@ -326,20 +358,26 @@ ostream& operator<< (ostream& os, const GFitsHDU& hdu) os << "Unknown" << endl; break; } - os << *hdu.m_header; - switch (hdu.m_type) { - case 0: // Image HDU - os << *(GFitsImage*)hdu.m_data; - break; - case 1: // ASCII Table HDU - os << *(GFitsAsciiTable*)hdu.m_data; - break; - case 2: // Binary Table HDU - os << *(GFitsBinTable*)hdu.m_data; - break; - default: - os << "Unknown"; - break; + + // Put FITS header in stream + if (hdu.m_header != NULL) + os << *hdu.m_header; + + // Put FITS data in stream + if (hdu.m_data != NULL) { + switch (hdu.m_type) { + case 0: // Image HDU + os << *(GFitsImage*)hdu.m_data; + break; + case 1: // ASCII Table HDU + os << *(GFitsAsciiTable*)hdu.m_data; + break; + case 2: // Binary Table HDU + os << *(GFitsBinTable*)hdu.m_data; + break; + default: + break; + } } // Return output stream diff --git a/src/fits/GFitsHeader.cpp b/src/fits/GFitsHeader.cpp index 04aeb2d..d1bf008 100644 --- a/src/fits/GFitsHeader.cpp +++ b/src/fits/GFitsHeader.cpp @@ -167,11 +167,53 @@ void GFitsHeader::close(void) } +/***********************************************************************//** + * @brief Update card in header * + * ----------------------------------------------------------------------- * + * This method updates one header card. Updating means replacing any * + * existing card with the specified one or appending a new card to the * + * list of existing cards. * + ***************************************************************************/ +void GFitsHeader::update(const GFitsHeaderCard& card) +{ + // If card exists then update existing values + GFitsHeaderCard* ptr = this->card(card.keyname()); + if (ptr != NULL) + *ptr = card; + + // ... otherwise append a new card + else { + + // Create memory to hold cards + GFitsHeaderCard* tmp = new GFitsHeaderCard[m_num_cards+1]; + if (tmp != NULL) { + + // Copy over existing cards and remove old ones + if (m_card != NULL) { + for (int i = 0; i < m_num_cards; ++i) + tmp[i] = m_card[i]; + delete [] m_card; + } + + // Connect the new memory to the card pointer + m_card = tmp; + + // Append new card to list + m_card[m_num_cards] = card; + + } // endif: new memory was valid + } // endif: card appending was required + + // Return + return; +} + + /*************************************************************************** * Get specified header card value as string * * ----------------------------------------------------------------------- * ***************************************************************************/ -std::string GFitsHeader::string(const std::string keyname) +std::string GFitsHeader::string(const std::string& keyname) { // Get card pointer GFitsHeaderCard* ptr = GFitsHeader::card(keyname); @@ -188,7 +230,7 @@ std::string GFitsHeader::string(const std::string keyname) * Get specified header card value as string * * ----------------------------------------------------------------------- * ***************************************************************************/ -std::string GFitsHeader::string(const int cardno) +std::string GFitsHeader::string(const int& cardno) { // Get card pointer GFitsHeaderCard* ptr = GFitsHeader::card(cardno); @@ -205,7 +247,7 @@ std::string GFitsHeader::string(const int cardno) * Get specified header card value as double * * ----------------------------------------------------------------------- * ***************************************************************************/ -double GFitsHeader::real(const std::string keyname) +double GFitsHeader::real(const std::string& keyname) { // Get card pointer GFitsHeaderCard* ptr = GFitsHeader::card(keyname); @@ -222,7 +264,7 @@ double GFitsHeader::real(const std::string keyname) * Get specified header card value as double * * ----------------------------------------------------------------------- * ***************************************************************************/ -double GFitsHeader::real(const int cardno) +double GFitsHeader::real(const int& cardno) { // Get card pointer GFitsHeaderCard* ptr = GFitsHeader::card(cardno); @@ -239,7 +281,7 @@ double GFitsHeader::real(const int cardno) * Get specified header card value as int * * ----------------------------------------------------------------------- * ***************************************************************************/ -int GFitsHeader::integer(const std::string keyname) +int GFitsHeader::integer(const std::string& keyname) { // Get card pointer GFitsHeaderCard* ptr = GFitsHeader::card(keyname); @@ -256,7 +298,7 @@ int GFitsHeader::integer(const std::string keyname) * Get specified header card value as int * * ----------------------------------------------------------------------- * ***************************************************************************/ -int GFitsHeader::integer(const int cardno) +int GFitsHeader::integer(const int& cardno) { // Get card pointer GFitsHeaderCard* ptr = GFitsHeader::card(cardno); diff --git a/src/fits/GFitsHeaderCard.cpp b/src/fits/GFitsHeaderCard.cpp index 9446459..1a90b07 100644 --- a/src/fits/GFitsHeaderCard.cpp +++ b/src/fits/GFitsHeaderCard.cpp @@ -60,6 +60,21 @@ GFitsHeaderCard::GFitsHeaderCard() // Return return; } +GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname, + const std::string& value, + const std::string& comment) +{ + // Initialise class members for clean destruction + init_members(); + + // Set members + this->set_keyname(keyname); + this->set_value(value); + this->set_comment(comment); + + // Return + return; +} /*************************************************************************** diff --git a/test/test_GFits.cpp b/test/test_GFits.cpp index 86b8269..3bcd134 100644 --- a/test/test_GFits.cpp +++ b/test/test_GFits.cpp @@ -289,6 +289,31 @@ void test_columns(void) /*************************************************************************** + * Test: Creation * + ***************************************************************************/ +void test_create(void) +{ + std::cout << "Test GFits: Create FITS file: "; + try { + GFits fits; + fits.open("test.fits"); + cout << endl << fits; + GFitsHDU image; + fits.append(&image); + fits.save(); + } + catch (exception &e) { + std::cout << std::endl << "TEST ERROR: Unable to create FITS file." << std::endl; + std::cout << e.what() << std::endl; + throw; + } + std::cout << ". ok." << std::endl; +} + + + + +/*************************************************************************** * Main test function * ***************************************************************************/ int main(void) @@ -300,8 +325,9 @@ int main(void) std::cout << "***********************" << std::endl; // Execute the tests - test_open(); - test_columns(); + test_create(); + //test_open(); + //test_columns(); // Return return 0; -- libgit2 0.21.4