Commit 8da6e5978a7f3a4359ec11fcdf5a75c943ca76b8

Authored by knodlseder
1 parent 26ff1560

start implementation of file creation and saving

include/GFits.hpp
... ... @@ -46,6 +46,7 @@ public:
46 46 void close(void);
47 47 GFitsHDU* hdu(const std::string extname);
48 48 GFitsHDU* hdu(int extno);
  49 + void append(const GFitsHDU* hdu);
49 50  
50 51 private:
51 52 // Private methods
... ...
include/GFitsCfitsio.hpp
... ... @@ -31,7 +31,9 @@
31 31 /* __ Macros _____________________________________________________________ */
32 32 #define __ffgerr(A, B) ffgerr(A, B)
33 33 #define __ffopen(A, B, C, D) ffopen(A, B, C, D)
  34 +#define __ffinit(A, B, C) ffinit(A, B, C)
34 35 #define __ffclos(A, B) ffclos(A, B)
  36 +#define __ffdelt(A, B) ffdelt(A, B)
35 37 #define __ffthdu(A, B, C) ffthdu(A, B, C)
36 38 #define __ffmahd(A, B, C, D) ffmahd(A, B, C, D)
37 39 #define __ffghdt(A, B, C) ffghdt(A, B, C)
... ... @@ -62,7 +64,9 @@ typedef fitsfile __fitsfile;
62 64 /* __ Macros _____________________________________________________________ */
63 65 #define __ffgerr(A, B) __error(A, B)
64 66 #define __ffopen(A, B, C, D) __dummy()
  67 +#define __ffinit(A, B, C) __dummy()
65 68 #define __ffclos(A, B) __dummy()
  69 +#define __ffdelt(A, B) __dummy()
66 70 #define __ffthdu(A, B, C) __dummy()
67 71 #define __ffmahd(A, B, C, D) __dummy()
68 72 #define __ffghdt(A, B, C) __dummy()
... ...
include/GFitsHDU.hpp
... ... @@ -29,6 +29,9 @@
29 29 ***************************************************************************/
30 30 class GFitsHDU {
31 31  
  32 + // Friend classes
  33 + friend class GFits;
  34 +
32 35 // I/O friends
33 36 friend ostream& operator<< (ostream& os, const GFitsHDU& hdu);
34 37  
... ... @@ -50,6 +53,7 @@ public:
50 53 GFitsHeader* header(void) const;
51 54 GFitsData* data(void) const;
52 55 GFitsTableCol* column(const std::string& colname) const;
  56 + void primary(void);
53 57  
54 58 private:
55 59 // Private methods
... ...
include/GFitsHeader.hpp
... ... @@ -41,14 +41,15 @@ public:
41 41 // Methods
42 42 void open(__fitsfile* fptr);
43 43 void close(void);
44   - GFitsHeaderCard* card(const std::string keyname);
45   - GFitsHeaderCard* card(const int cardno);
46   - std::string string(const std::string keyname);
47   - std::string string(const int cardno);
48   - double real(const std::string keyname);
49   - double real(const int cardno);
50   - int integer(const std::string keyname);
51   - int integer(const int cardno);
  44 + void update(const GFitsHeaderCard& card);
  45 + GFitsHeaderCard* card(const std::string& keyname);
  46 + GFitsHeaderCard* card(const int& cardno);
  47 + std::string string(const std::string& keyname);
  48 + std::string string(const int& cardno);
  49 + double real(const std::string& keyname);
  50 + double real(const int& cardno);
  51 + int integer(const std::string& keyname);
  52 + int integer(const int& cardno);
52 53 GFitsHeader* clone(void) const;
53 54  
54 55 private:
... ... @@ -68,12 +69,12 @@ private:
68 69 * Inline methods *
69 70 ***************************************************************************/
70 71 inline
71   -GFitsHeaderCard* GFitsHeader::card(const std::string keyname)
  72 +GFitsHeaderCard* GFitsHeader::card(const std::string& keyname)
72 73 {
73 74 return GFitsHeader::card_ptr(keyname);
74 75 }
75 76 inline
76   -GFitsHeaderCard* GFitsHeader::card(const int cardno)
  77 +GFitsHeaderCard* GFitsHeader::card(const int& cardno)
77 78 {
78 79 return (cardno >= 0 && cardno < m_num_cards) ? &(m_card[cardno]) : NULL;
79 80 }
... ...
include/GFitsHeaderCard.hpp
... ... @@ -31,6 +31,8 @@ class GFitsHeaderCard {
31 31 public:
32 32 // Constructors & Destructors
33 33 GFitsHeaderCard();
  34 + GFitsHeaderCard(const std::string& keyname, const std::string& value,
  35 + const std::string& comment);
34 36 GFitsHeaderCard(const GFitsHeaderCard& card);
35 37 ~GFitsHeaderCard();
36 38  
... ... @@ -38,18 +40,18 @@ public:
38 40 GFitsHeaderCard& operator= (const GFitsHeaderCard& card);
39 41  
40 42 // Methods
41   - std::string keyname(void);
42   - std::string value(void);
43   - int value_type(void);
  43 + std::string keyname(void) const;
  44 + std::string value(void) const;
  45 + int value_type(void) const;
  46 + std::string unit(void) const;
  47 + std::string comment(void) const;
44 48 std::string string(void);
45 49 double real(void);
46 50 int integer(void);
47   - std::string unit(void);
48   - std::string comment(void);
49   - void set_keyname(std::string& keyname);
50   - void set_value(std::string& value);
51   - void set_unit(std::string& unit);
52   - void set_comment(std::string& comment);
  51 + void set_keyname(const std::string& keyname);
  52 + void set_value(const std::string& value);
  53 + void set_unit(const std::string& unit);
  54 + void set_comment(const std::string& comment);
53 55 void read(__fitsfile* fptr, int keynum);
54 56 void read(__fitsfile* fptr, std::string keyname);
55 57 void write(__fitsfile* fptr);
... ... @@ -73,15 +75,15 @@ private:
73 75 /***************************************************************************
74 76 * Inline methods *
75 77 ***************************************************************************/
76   -inline std::string GFitsHeaderCard::keyname(void) { return m_keyname; }
77   -inline std::string GFitsHeaderCard::value(void) { return m_value; }
78   -inline int GFitsHeaderCard::value_type(void) { return m_value_type; }
79   -inline std::string GFitsHeaderCard::unit(void) { return m_unit; }
80   -inline std::string GFitsHeaderCard::comment(void) { return m_comment; }
81   -inline void GFitsHeaderCard::set_keyname(std::string& keyname) { m_keyname = keyname; }
82   -inline void GFitsHeaderCard::set_value(std::string& value) { m_value = value; }
83   -inline void GFitsHeaderCard::set_unit(std::string& unit) { m_unit = unit; }
84   -inline void GFitsHeaderCard::set_comment(std::string& comment) { m_comment = comment; }
  78 +inline std::string GFitsHeaderCard::keyname(void) const { return m_keyname; }
  79 +inline std::string GFitsHeaderCard::value(void) const { return m_value; }
  80 +inline int GFitsHeaderCard::value_type(void) const { return m_value_type; }
  81 +inline std::string GFitsHeaderCard::unit(void) const { return m_unit; }
  82 +inline std::string GFitsHeaderCard::comment(void) const { return m_comment; }
  83 +inline void GFitsHeaderCard::set_keyname(const std::string& keyname) { m_keyname = keyname; }
  84 +inline void GFitsHeaderCard::set_value(const std::string& value) { m_value = value; }
  85 +inline void GFitsHeaderCard::set_unit(const std::string& unit) { m_unit = unit; }
  86 +inline void GFitsHeaderCard::set_comment(const std::string& comment) { m_comment = comment; }
85 87  
86 88  
87 89 #endif /* GFITSHEADERCARD_HPP */
... ...
src/GException.cpp
... ... @@ -233,7 +233,8 @@ GException::fits_error::fits_error(string origin, int status)
233 233 GException::fits_open_error::fits_open_error(string origin, string filename, int status)
234 234 {
235 235 m_origin = origin;
236   - m_message = "Unable to open FITS file '" + filename + "'";
  236 + m_message = "Unable to open FITS file '" + filename + "'"
  237 + + " (status: " + str(status) + ")";
237 238 }
238 239  
239 240  
... ...
src/fits/GFits.cpp
... ... @@ -134,7 +134,15 @@ void GFits::open(const std::string filename)
134 134 // Open FITS file
135 135 int status = 0;
136 136 status = __ffopen(&m_fitsfile, filename.c_str(), 1, &status);
137   - if (status != 0)
  137 +
  138 + // If FITS file does not exist then create it now
  139 + if (status == 104) {
  140 + status = 0;
  141 + status = __ffinit(&m_fitsfile, filename.c_str(), &status);
  142 + if (status != 0)
  143 + throw GException::fits_open_error(G_OPEN, filename, status);
  144 + }
  145 + else if (status != 0)
138 146 throw GException::fits_open_error(G_OPEN, filename, status);
139 147  
140 148 // Store FITS file attributes
... ... @@ -147,7 +155,7 @@ void GFits::open(const std::string filename)
147 155  
148 156 // Allocate HDUs
149 157 if (m_hdu != NULL) delete [] m_hdu;
150   - m_hdu = new GFitsHDU[m_num_hdu];
  158 + if (m_num_hdu > 0) m_hdu = new GFitsHDU[m_num_hdu];
151 159  
152 160 // Open all HDUs
153 161 for (int i = 0; i < m_num_hdu; ++i)
... ... @@ -252,6 +260,62 @@ GFitsHDU* GFits::hdu(const std::string extname)
252 260 }
253 261  
254 262  
  263 +/***************************************************************************
  264 + * Append HDU to FITS file *
  265 + * ----------------------------------------------------------------------- *
  266 + ***************************************************************************/
  267 +void GFits::append(const GFitsHDU* hdu)
  268 +{
  269 + // Determine number of HDUs to add. If there are no HDUs so far and if
  270 + // the HDU to append is not an image then we have to add a primary
  271 + // image first. In this case we add 2 new HDUs.
  272 + int n_add = (m_num_hdu == 0 && hdu->m_type != 0) ? 2 : 1;
  273 +
  274 + // Create memory to hold HDUs
  275 + GFitsHDU* tmp = new GFitsHDU[m_num_hdu+n_add];
  276 + if (tmp != NULL) {
  277 +
  278 + // Copy over existing HDUs and remove old ones
  279 + if (m_hdu != NULL) {
  280 + for (int i = 0; i < m_num_hdu; ++i)
  281 + tmp[i] = m_hdu[i];
  282 + delete [] m_hdu;
  283 + }
  284 +
  285 + // Connect the new memory to the card pointer
  286 + m_hdu = tmp;
  287 +
  288 + // Add primary image if required
  289 + if (n_add == 2) {
  290 +
  291 + // Append empty primary image
  292 + //m_hdu[m_num_hdu] = TBD
  293 +
  294 + // Set FITS file pointer for new HDU
  295 + m_hdu[m_num_hdu].m_fitsfile = *m_fitsfile;
  296 + m_hdu[m_num_hdu].m_fitsfile.HDUposition = m_num_hdu;
  297 +
  298 + // Increment number of HDUs
  299 + m_num_hdu++;
  300 + }
  301 +
  302 + // Append new HDU to list
  303 + m_hdu[m_num_hdu] = *hdu;
  304 +
  305 + // Set FITS file pointer for new HDU
  306 + m_hdu[m_num_hdu].m_fitsfile = *m_fitsfile;
  307 + m_hdu[m_num_hdu].m_fitsfile.HDUposition = m_num_hdu;
  308 +
  309 + // Increment number of HDUs
  310 + m_num_hdu++;
  311 +
  312 + }
  313 +
  314 + // Return
  315 + return;
  316 +}
  317 +
  318 +
255 319 /*==========================================================================
256 320 = =
257 321 = GFits private methods =
... ... @@ -311,10 +375,20 @@ void GFits::free_members(void)
311 375 {
312 376 // If FITS file has been opened then close it now
313 377 if (m_fitsfile != NULL) {
314   - int status = 0;
315   - status = __ffclos(m_fitsfile, &status);
316   - if (status != 0)
317   - throw GException::fits_error(G_FREE_MEM, status);
  378 +
  379 + // If there are no HDUs then delete the file (don't worry about error)
  380 + if (m_num_hdu == 0) {
  381 + int status = 0;
  382 + __ffdelt(m_fitsfile, &status);
  383 + }
  384 +
  385 + // ... otherwise close the file
  386 + else {
  387 + int status = 0;
  388 + status = __ffclos(m_fitsfile, &status);
  389 + if (status != 0)
  390 + throw GException::fits_error(G_FREE_MEM, status);
  391 + }
318 392 }
319 393  
320 394 // Free memory
... ...
src/fits/GFitsAsciiTable.cpp
... ... @@ -233,8 +233,10 @@ void GFitsAsciiTable::copy_members(const GFitsAsciiTable&amp; table)
233 233 // Copy column definition
234 234 if (table.m_columns != NULL && m_cols > 0) {
235 235 m_columns = new GFitsTableCol*[m_cols];
236   - for (int i = 0; i < m_cols; ++i)
237   - m_columns[i] = table.m_columns[i]->clone();
  236 + for (int i = 0; i < m_cols; ++i) {
  237 + if (table.m_columns[i] != NULL)
  238 + m_columns[i] = table.m_columns[i]->clone();
  239 + }
238 240 }
239 241  
240 242 // Return
... ...
src/fits/GFitsBinTable.cpp
... ... @@ -308,8 +308,10 @@ void GFitsBinTable::copy_members(const GFitsBinTable&amp; table)
308 308 // Copy column definition
309 309 if (table.m_columns != NULL && m_cols > 0) {
310 310 m_columns = new GFitsTableCol*[m_cols];
311   - for (int i = 0; i < m_cols; ++i)
312   - m_columns[i] = table.m_columns[i]->clone();
  311 + for (int i = 0; i < m_cols; ++i) {
  312 + if (table.m_columns[i] != NULL)
  313 + m_columns[i] = table.m_columns[i]->clone();
  314 + }
313 315 }
314 316  
315 317 // Return
... ...
src/fits/GFitsHDU.cpp
... ... @@ -186,11 +186,17 @@ void GFitsHDU::open(__fitsfile* fptr, int hdunum)
186 186 /// NOT YET IMPLEMENTED !!!
187 187 void GFitsHDU::save(void)
188 188 {
  189 +cout << "entry" << endl;
189 190 // Move to HDU
190 191 int status = 0;
191 192 status = __ffmahd(&m_fitsfile, (m_fitsfile.HDUposition)+1, NULL, &status);
192   - if (status != 0)
193   - throw GException::fits_error(G_SAVE, status);
  193 + cout << status << endl;
  194 +
  195 + // If HDU does not exist then create it now
  196 +
  197 +
  198 + //if (status != 0)
  199 + // throw GException::fits_error(G_SAVE, status);
194 200  
195 201 // Save header
196 202 //...
... ... @@ -198,6 +204,7 @@ void GFitsHDU::save(void)
198 204 // Save data
199 205 //...
200 206  
  207 +cout << "exit" << endl;
201 208 // Return
202 209 return;
203 210 }
... ... @@ -233,6 +240,31 @@ GFitsTableCol* GFitsHDU::column(const std::string&amp; colname) const
233 240 }
234 241  
235 242  
  243 +/***************************************************************************
  244 + * Setup minimal primary HDU *
  245 + * ----------------------------------------------------------------------- *
  246 + ***************************************************************************/
  247 +void GFitsHDU::primary(void)
  248 +{
  249 + // Free any allocated header and data
  250 + free_members();
  251 +
  252 + // Allocate header
  253 + m_header = new GFitsHeader();
  254 +
  255 + // Add cards
  256 + m_header->update(GFitsHeaderCard("SIMPLE", "T", "/ file does conform to FITS standard"));
  257 + m_header->update(GFitsHeaderCard("BITPIX", "8", "/ number of bits per data pixel"));
  258 + m_header->update(GFitsHeaderCard("NAXIS", "0", "/ number of data axes"));
  259 + m_header->update(GFitsHeaderCard("EXTEND", "T", "/ FITS dataset may contain extensions"));
  260 + m_header->update(GFitsHeaderCard("BZERO", "-128", "/ Make values Signed"));
  261 + m_header->update(GFitsHeaderCard("BSCALE", "1", "/ Make values Signed"));
  262 +
  263 + // Return
  264 + return;
  265 +}
  266 +
  267 +
236 268 /*==========================================================================
237 269 = =
238 270 = GFitsHDU private methods =
... ... @@ -268,8 +300,8 @@ void GFitsHDU::copy_members(const GFitsHDU&amp; hdu)
268 300 m_fitsfile = hdu.m_fitsfile;
269 301 m_name = hdu.m_name;
270 302 m_type = hdu.m_type;
271   - m_header = hdu.m_header->clone();
272   - m_data = hdu.m_data->clone();
  303 + if (hdu.m_header != NULL) m_header = hdu.m_header->clone();
  304 + if (hdu.m_data != NULL) m_data = hdu.m_data->clone();
273 305  
274 306 // Return
275 307 return;
... ... @@ -326,20 +358,26 @@ ostream&amp; operator&lt;&lt; (ostream&amp; os, const GFitsHDU&amp; hdu)
326 358 os << "Unknown" << endl;
327 359 break;
328 360 }
329   - os << *hdu.m_header;
330   - switch (hdu.m_type) {
331   - case 0: // Image HDU
332   - os << *(GFitsImage*)hdu.m_data;
333   - break;
334   - case 1: // ASCII Table HDU
335   - os << *(GFitsAsciiTable*)hdu.m_data;
336   - break;
337   - case 2: // Binary Table HDU
338   - os << *(GFitsBinTable*)hdu.m_data;
339   - break;
340   - default:
341   - os << "Unknown";
342   - break;
  361 +
  362 + // Put FITS header in stream
  363 + if (hdu.m_header != NULL)
  364 + os << *hdu.m_header;
  365 +
  366 + // Put FITS data in stream
  367 + if (hdu.m_data != NULL) {
  368 + switch (hdu.m_type) {
  369 + case 0: // Image HDU
  370 + os << *(GFitsImage*)hdu.m_data;
  371 + break;
  372 + case 1: // ASCII Table HDU
  373 + os << *(GFitsAsciiTable*)hdu.m_data;
  374 + break;
  375 + case 2: // Binary Table HDU
  376 + os << *(GFitsBinTable*)hdu.m_data;
  377 + break;
  378 + default:
  379 + break;
  380 + }
343 381 }
344 382  
345 383 // Return output stream
... ...
src/fits/GFitsHeader.cpp
... ... @@ -167,11 +167,53 @@ void GFitsHeader::close(void)
167 167 }
168 168  
169 169  
  170 +/***********************************************************************//**
  171 + * @brief Update card in header *
  172 + * ----------------------------------------------------------------------- *
  173 + * This method updates one header card. Updating means replacing any *
  174 + * existing card with the specified one or appending a new card to the *
  175 + * list of existing cards. *
  176 + ***************************************************************************/
  177 +void GFitsHeader::update(const GFitsHeaderCard& card)
  178 +{
  179 + // If card exists then update existing values
  180 + GFitsHeaderCard* ptr = this->card(card.keyname());
  181 + if (ptr != NULL)
  182 + *ptr = card;
  183 +
  184 + // ... otherwise append a new card
  185 + else {
  186 +
  187 + // Create memory to hold cards
  188 + GFitsHeaderCard* tmp = new GFitsHeaderCard[m_num_cards+1];
  189 + if (tmp != NULL) {
  190 +
  191 + // Copy over existing cards and remove old ones
  192 + if (m_card != NULL) {
  193 + for (int i = 0; i < m_num_cards; ++i)
  194 + tmp[i] = m_card[i];
  195 + delete [] m_card;
  196 + }
  197 +
  198 + // Connect the new memory to the card pointer
  199 + m_card = tmp;
  200 +
  201 + // Append new card to list
  202 + m_card[m_num_cards] = card;
  203 +
  204 + } // endif: new memory was valid
  205 + } // endif: card appending was required
  206 +
  207 + // Return
  208 + return;
  209 +}
  210 +
  211 +
170 212 /***************************************************************************
171 213 * Get specified header card value as string *
172 214 * ----------------------------------------------------------------------- *
173 215 ***************************************************************************/
174   -std::string GFitsHeader::string(const std::string keyname)
  216 +std::string GFitsHeader::string(const std::string& keyname)
175 217 {
176 218 // Get card pointer
177 219 GFitsHeaderCard* ptr = GFitsHeader::card(keyname);
... ... @@ -188,7 +230,7 @@ std::string GFitsHeader::string(const std::string keyname)
188 230 * Get specified header card value as string *
189 231 * ----------------------------------------------------------------------- *
190 232 ***************************************************************************/
191   -std::string GFitsHeader::string(const int cardno)
  233 +std::string GFitsHeader::string(const int& cardno)
192 234 {
193 235 // Get card pointer
194 236 GFitsHeaderCard* ptr = GFitsHeader::card(cardno);
... ... @@ -205,7 +247,7 @@ std::string GFitsHeader::string(const int cardno)
205 247 * Get specified header card value as double *
206 248 * ----------------------------------------------------------------------- *
207 249 ***************************************************************************/
208   -double GFitsHeader::real(const std::string keyname)
  250 +double GFitsHeader::real(const std::string& keyname)
209 251 {
210 252 // Get card pointer
211 253 GFitsHeaderCard* ptr = GFitsHeader::card(keyname);
... ... @@ -222,7 +264,7 @@ double GFitsHeader::real(const std::string keyname)
222 264 * Get specified header card value as double *
223 265 * ----------------------------------------------------------------------- *
224 266 ***************************************************************************/
225   -double GFitsHeader::real(const int cardno)
  267 +double GFitsHeader::real(const int& cardno)
226 268 {
227 269 // Get card pointer
228 270 GFitsHeaderCard* ptr = GFitsHeader::card(cardno);
... ... @@ -239,7 +281,7 @@ double GFitsHeader::real(const int cardno)
239 281 * Get specified header card value as int *
240 282 * ----------------------------------------------------------------------- *
241 283 ***************************************************************************/
242   -int GFitsHeader::integer(const std::string keyname)
  284 +int GFitsHeader::integer(const std::string& keyname)
243 285 {
244 286 // Get card pointer
245 287 GFitsHeaderCard* ptr = GFitsHeader::card(keyname);
... ... @@ -256,7 +298,7 @@ int GFitsHeader::integer(const std::string keyname)
256 298 * Get specified header card value as int *
257 299 * ----------------------------------------------------------------------- *
258 300 ***************************************************************************/
259   -int GFitsHeader::integer(const int cardno)
  301 +int GFitsHeader::integer(const int& cardno)
260 302 {
261 303 // Get card pointer
262 304 GFitsHeaderCard* ptr = GFitsHeader::card(cardno);
... ...
src/fits/GFitsHeaderCard.cpp
... ... @@ -60,6 +60,21 @@ GFitsHeaderCard::GFitsHeaderCard()
60 60 // Return
61 61 return;
62 62 }
  63 +GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname,
  64 + const std::string& value,
  65 + const std::string& comment)
  66 +{
  67 + // Initialise class members for clean destruction
  68 + init_members();
  69 +
  70 + // Set members
  71 + this->set_keyname(keyname);
  72 + this->set_value(value);
  73 + this->set_comment(comment);
  74 +
  75 + // Return
  76 + return;
  77 +}
63 78  
64 79  
65 80 /***************************************************************************
... ...
test/test_GFits.cpp
... ... @@ -289,6 +289,31 @@ void test_columns(void)
289 289  
290 290  
291 291 /***************************************************************************
  292 + * Test: Creation *
  293 + ***************************************************************************/
  294 +void test_create(void)
  295 +{
  296 + std::cout << "Test GFits: Create FITS file: ";
  297 + try {
  298 + GFits fits;
  299 + fits.open("test.fits");
  300 + cout << endl << fits;
  301 + GFitsHDU image;
  302 + fits.append(&image);
  303 + fits.save();
  304 + }
  305 + catch (exception &e) {
  306 + std::cout << std::endl << "TEST ERROR: Unable to create FITS file." << std::endl;
  307 + std::cout << e.what() << std::endl;
  308 + throw;
  309 + }
  310 + std::cout << ". ok." << std::endl;
  311 +}
  312 +
  313 +
  314 +
  315 +
  316 +/***************************************************************************
292 317 * Main test function *
293 318 ***************************************************************************/
294 319 int main(void)
... ... @@ -300,8 +325,9 @@ int main(void)
300 325 std::cout << "***********************" << std::endl;
301 326  
302 327 // Execute the tests
303   - test_open();
304   - test_columns();
  328 + test_create();
  329 + //test_open();
  330 + //test_columns();
305 331  
306 332 // Return
307 333 return 0;
... ...