GammaLib  1.7.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GFits.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GFits.cpp - FITS file access class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2008-2018 by Juergen Knoedlseder *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 /**
22  * @file GFits.cpp
23  * @brief FITS file access class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <cstdio>
32 #include "GException.hpp"
33 #include "GTools.hpp"
34 #include "GFitsCfitsio.hpp"
35 #include "GFits.hpp"
36 #include "GFitsImageByte.hpp"
37 #include "GFitsImageSByte.hpp"
38 #include "GFitsImageUShort.hpp"
39 #include "GFitsImageShort.hpp"
40 #include "GFitsImageULong.hpp"
41 #include "GFitsImageLong.hpp"
42 #include "GFitsImageLongLong.hpp"
43 #include "GFitsImageFloat.hpp"
44 #include "GFitsImageDouble.hpp"
45 #include "GFitsAsciiTable.hpp"
46 #include "GFitsBinTable.hpp"
47 #include "GVOClient.hpp"
48 #include "GVOTable.hpp"
49 
50 /* __ Method name definitions ____________________________________________ */
51 #define G_AT1 "GFits::at(int&)"
52 #define G_AT2 "GFits::at(std::string&)"
53 #define G_IMAGE1 "GFits::image(int&)"
54 #define G_IMAGE2 "GFits::image(std::string&)"
55 #define G_TABLE1 "GFits::table(int&)"
56 #define G_TABLE2 "GFits::table(std::string&)"
57 #define G_SET1 "GFits::set(int&, GFitsHDU&)"
58 #define G_SET2 "GFits::set(std::string&, GFitsHDU&)"
59 #define G_INSERT1 "GFits::insert(const int& extno, GFitsHDU& hdu)"
60 #define G_INSERT2 "GFits::insert(std::string&, GFitsHDU& hdu)"
61 #define G_REMOVE1 "GFits::remove(int&)"
62 #define G_REMOVE2 "GFits::remove(std::string&)"
63 #define G_OPEN "GFits::open(GFilename&, bool&)"
64 #define G_SAVE "GFits::save(bool&)"
65 #define G_SAVETO "GFits::saveto(GFilename&, bool&)"
66 #define G_PUBLISH "GFits::publish(std::string&, std::string&)"
67 #define G_FREE_MEM "GFits::free_members()"
68 #define G_NEW_IMAGE "GFits::new_image()"
69 
70 /* __ Macros _____________________________________________________________ */
71 
72 /* __ Coding definitions _________________________________________________ */
73 #define G_DELETE_EMPTY_FITS_FILES //!< Do not write empty FITS files
74 
75 /* __ Debug definitions __________________________________________________ */
76 //#define G_DEBUG //!< Debug methods
77 
78 
79 /*==========================================================================
80  = =
81  = Constructors/destructors =
82  = =
83  ==========================================================================*/
84 
85 /***********************************************************************//**
86  * @brief Void constructor
87  *
88  * Constructs empty FITS file.
89  ***************************************************************************/
91 {
92  // Initialise class members
93  init_members();
94 
95  // Return
96  return;
97 }
98 
99 
100 /***********************************************************************//**
101  * @brief FITS file constructor
102  *
103  * @param[in] filename FITS file name.
104  * @param[in] create Create file if it does not exist? (default: false)
105  *
106  * Construct an object by opening a FITS file. If the file does not exist it
107  * will be created if @p create is set to true.
108  ***************************************************************************/
109 GFits::GFits(const GFilename& filename, const bool& create)
110 {
111  // Initialise class members
112  init_members();
113 
114  // Open specified FITS file
115  open(filename, create);
116 
117  // Return
118  return;
119 }
120 
121 
122 /***********************************************************************//**
123  * @brief Copy constructor
124  *
125  * @param[in] fits FITS file.
126  ***************************************************************************/
127 GFits::GFits(const GFits& fits)
128 {
129  // Initialise class members
130  init_members();
131 
132  // Copy members
133  copy_members(fits);
134 
135  // Return
136  return;
137 }
138 
139 
140 /***********************************************************************//**
141  * @brief Destructor
142  ***************************************************************************/
144 {
145  // Free members
146  free_members();
147 
148  // Return
149  return;
150 }
151 
152 
153 /*==========================================================================
154  = =
155  = Operators =
156  = =
157  ==========================================================================*/
158 
159 /***********************************************************************//**
160  * @brief Assignment operator
161  *
162  * @param[in] fits FITS file.
163  * @return FITS file.
164  ***************************************************************************/
166 {
167  // Execute only if object is not identical
168  if (this != &fits) {
169 
170  // Free members
171  free_members();
172 
173  // Initialise private members for clean destruction
174  init_members();
175 
176  // Copy members
177  copy_members(fits);
178 
179  } // endif: object was not identical
180 
181  // Return this object
182  return *this;
183 }
184 
185 
186 /*==========================================================================
187  = =
188  = Public methods =
189  = =
190  ==========================================================================*/
191 
192 /***********************************************************************//**
193  * @brief Clear FITS file
194  ***************************************************************************/
195 void GFits::clear(void)
196 {
197  // Close file and free all members
198  free_members();
199 
200  // Initialise members
201  init_members();
202 
203  // Return
204  return;
205 }
206 
207 
208 /***********************************************************************//**
209  * @brief Clone FITS file
210  *
211  * @return Pointer to deep copy of FITS file.
212  ***************************************************************************/
213 GFits* GFits::clone(void) const
214 {
215  return new GFits(*this);
216 }
217 
218 
219 /***********************************************************************//**
220  * @brief Get pointer to HDU
221  *
222  * @param[in] extno Extension number [0,...,size()-1].
223  * @return Pointer to HDU.
224  *
225  * @exception GException::out_of_range
226  * Extension number is out of range.
227  * @exception GException::fits_hdu_not_found
228  * No HDU found for specified extension number.
229  *
230  * Returns a pointer to the HDU with the specified extension number @p extno.
231  * An exception is thrown if the HDU is not valid (i.e. NULL).
232  ***************************************************************************/
233 GFitsHDU* GFits::at(const int& extno)
234 {
235  // Compile option: raise an exception if index is out of range
236  #if defined(G_RANGE_CHECK)
237  if (extno < 0 || extno >= size()) {
238  throw GException::out_of_range(G_AT1, "Extension number", extno, size());
239  }
240  #endif
241 
242  // Get HDU pointer
243  GFitsHDU* ptr = m_hdu[extno];
244 
245  // Throw an error if HDU has not been found
246  if (ptr == NULL) {
247  std::string extname = "extno="+gammalib::str(extno);
248  throw GException::fits_hdu_not_found(G_AT1, extname);
249  }
250 
251  // Return pointer
252  return ptr;
253 }
254 
255 
256 /***********************************************************************//**
257  * @brief Get pointer to HDU (const version)
258  *
259  * @param[in] extno Extension number [0,...,size()-1].
260  * @return Pointer to HDU.
261  *
262  * @exception GException::out_of_range
263  * Extension number is out of range.
264  * @exception GException::fits_hdu_not_found
265  * No HDU found for specified extension number.
266  *
267  * Returns a pointer to the HDU with the specified extension number @p extno.
268  * An exception is thrown if the HDU is not valid (i.e. NULL).
269  ***************************************************************************/
270 const GFitsHDU* GFits::at(const int& extno) const
271 {
272  // Compile option: raise an exception if index is out of range
273  #if defined(G_RANGE_CHECK)
274  if (extno < 0 || extno >= size()) {
275  throw GException::out_of_range(G_AT1, "Extension number", extno, size());
276  }
277  #endif
278 
279  // Get HDU pointer
280  GFitsHDU* ptr = m_hdu[extno];
281 
282  // Throw an error if HDU has not been found
283  if (ptr == NULL) {
284  std::string extname = "extno="+gammalib::str(extno);
285  throw GException::fits_hdu_not_found(G_AT1, extname);
286  }
287 
288  // Return pointer
289  return ptr;
290 }
291 
292 
293 /***********************************************************************//**
294  * @brief Get pointer to HDU
295  *
296  * @param[in] extname Name of HDU extension.
297  * @return Pointer to HDU.
298  *
299  * @exception GException::fits_hdu_not_found
300  * No HDU with specified name has been found.
301  *
302  * Returns a pointer to the HDU with the specified @p extname. An exception
303  * is thrown if the HDU is not valid (i.e. NULL).
304  ***************************************************************************/
305 GFitsHDU* GFits::at(const std::string& extname)
306 {
307  // Get extenion number
308  int extno = this->extno(extname);
309  if (extno == -1) {
310  throw GException::fits_hdu_not_found(G_AT2, extname);
311  }
312 
313  // Get HDU pointer
314  GFitsHDU* ptr = m_hdu[extno];
315 
316  // Return pointer
317  return ptr;
318 }
319 
320 
321 /***********************************************************************//**
322  * @brief Get pointer to HDU (const version)
323  *
324  * @param[in] extname Name of HDU extension.
325  * @return Pointer to HDU.
326  *
327  * @exception GException::fits_hdu_not_found
328  * No HDU with specified name has been found.
329  *
330  * Returns a pointer to the HDU with the specified @p extname. An exception
331  * is thrown if the HDU is not valid (i.e. NULL).
332  ***************************************************************************/
333 const GFitsHDU* GFits::at(const std::string& extname) const
334 {
335  // Get extenion number
336  int extno = this->extno(extname);
337  if (extno == -1) {
338  throw GException::fits_hdu_not_found(G_AT2, extname);
339  }
340 
341  // Get HDU pointer
342  GFitsHDU* ptr = m_hdu[extno];
343 
344  // Return pointer
345  return ptr;
346 }
347 
348 
349 /***********************************************************************//**
350  * @brief Get pointer to image HDU
351  *
352  * @param[in] extno Extension number [0,...,size()-1].
353  * @return Pointer to FITS image.
354  *
355  * @exception GException::fits_hdu_not_image
356  * Requested HDU is not an image.
357  *
358  * Returns a pointer to the image HDU with extension number extno.
359  ***************************************************************************/
360 GFitsImage* GFits::image(const int& extno)
361 {
362  // Get HDU pointer
363  GFitsImage* ptr = dynamic_cast<GFitsImage*>(at(extno));
364 
365  // Throw an error if HDU is not an image
366  if (ptr == NULL) {
368  "(extno="+gammalib::str(extno)+")",
369  at(extno)->exttype());
370  }
371 
372  // Return pointer
373  return ptr;
374 }
375 
376 
377 /***********************************************************************//**
378  * @brief Get pointer to image HDU (const version)
379  *
380  * @param[in] extno Extension number [0,...,size()-1].
381  * @return Pointer to FITS image.
382  *
383  * @exception GException::fits_hdu_not_image
384  * Requested HDU is not an image.
385  *
386  * Returns a pointer to the image HDU with extension number extno.
387  ***************************************************************************/
388 const GFitsImage* GFits::image(const int& extno) const
389 {
390  // Get HDU pointer
391  const GFitsImage* ptr = dynamic_cast<const GFitsImage*>(at(extno));
392 
393  // Throw an error if HDU is not an image
394  if (ptr == NULL) {
396  "(extno="+gammalib::str(extno)+")",
397  at(extno)->exttype());
398  }
399 
400  // Return pointer
401  return ptr;
402 }
403 
404 
405 /***********************************************************************//**
406  * @brief Get pointer to image HDU
407  *
408  * @param[in] extname Name of HDU extension.
409  * @return Pointer to FITS image.
410  *
411  * @exception GException::fits_hdu_not_image
412  * Requested HDU is not an image.
413  *
414  * Returns a pointer to the image HDU with extension name extname.
415  ***************************************************************************/
416 GFitsImage* GFits::image(const std::string& extname)
417 {
418  // Get HDU pointer
419  GFitsImage* ptr = dynamic_cast<GFitsImage*>(at(extname));
420 
421  // Throw an error if HDU is not an image
422  if (ptr == NULL) {
424  extname,
425  at(extname)->exttype());
426  }
427 
428  // Return pointer
429  return ptr;
430 }
431 
432 
433 /***********************************************************************//**
434  * @brief Get pointer to image HDU (const version)
435  *
436  * @param[in] extname Name of HDU extension.
437  * @return Pointer to FITS image.
438  *
439  * @exception GException::fits_hdu_not_image
440  * Requested HDU is not an image.
441  *
442  * Returns a pointer to the image HDU with extension name extname.
443  ***************************************************************************/
444 const GFitsImage* GFits::image(const std::string& extname) const
445 {
446  // Get HDU pointer
447  const GFitsImage* ptr = dynamic_cast<const GFitsImage*>(at(extname));
448 
449  // Throw an error if HDU is not an image
450  if (ptr == NULL) {
452  extname,
453  at(extname)->exttype());
454  }
455 
456  // Return pointer
457  return ptr;
458 }
459 
460 
461 /***********************************************************************//**
462  * @brief Get pointer to table HDU
463  *
464  * @param[in] extno Extension number [0,...,size()-1].
465  * @return Pointer to FITS table.
466  *
467  * @exception GException::fits_hdu_not_table
468  * Requested HDU is not a table.
469  *
470  * Returns a pointer to the table HDU with extension number extno.
471  ***************************************************************************/
472 GFitsTable* GFits::table(const int& extno)
473 {
474  // Get HDU pointer
475  GFitsTable* ptr = dynamic_cast<GFitsTable*>(at(extno));
476 
477  // Throw an error if HDU is not an image
478  if (ptr == NULL) {
480  "(extno="+gammalib::str(extno)+")",
481  at(extno)->exttype());
482  }
483 
484  // Return pointer
485  return ptr;
486 }
487 
488 
489 /***********************************************************************//**
490  * @brief Get pointer to table HDU (const version)
491  *
492  * @param[in] extno Extension number [0,...,size()-1].
493  * @return Pointer to FITS table.
494  *
495  * @exception GException::fits_hdu_not_table
496  * Requested HDU is not a table.
497  *
498  * Returns a pointer to the table HDU with extension number extno.
499  ***************************************************************************/
500 const GFitsTable* GFits::table(const int& extno) const
501 {
502  // Get HDU pointer
503  const GFitsTable* ptr = dynamic_cast<const GFitsTable*>(at(extno));
504 
505  // Throw an error if HDU is not an image
506  if (ptr == NULL) {
508  "(extno="+gammalib::str(extno)+")",
509  at(extno)->exttype());
510  }
511 
512  // Return pointer
513  return ptr;
514 }
515 
516 
517 /***********************************************************************//**
518  * @brief Get pointer to table HDU
519  *
520  * @param[in] extname Name of HDU extension.
521  * @return Pointer to FITS table.
522  *
523  * @exception GException::fits_hdu_not_table
524  * Requested HDU is not a table.
525  *
526  * Returns a pointer to the table HDU with extension name extname.
527  ***************************************************************************/
528 GFitsTable* GFits::table(const std::string& extname)
529 {
530  // Get HDU pointer
531  GFitsTable* ptr = dynamic_cast<GFitsTable*>(at(extname));
532 
533  // Throw an error if HDU is not an image
534  if (ptr == NULL) {
536  extname,
537  at(extname)->exttype());
538  }
539 
540  // Return pointer
541  return ptr;
542 }
543 
544 
545 /***********************************************************************//**
546  * @brief Get pointer to table HDU
547  *
548  * @param[in] extname Name of HDU extension.
549  * @return Pointer to FITS table.
550  *
551  * @exception GException::fits_hdu_not_table
552  * Requested HDU is not a table.
553  *
554  * Returns a pointer to the table HDU with extension name extname.
555  ***************************************************************************/
556 const GFitsTable* GFits::table(const std::string& extname) const
557 {
558  // Get HDU pointer
559  const GFitsTable* ptr = dynamic_cast<const GFitsTable*>(at(extname));
560 
561  // Throw an error if HDU is not an image
562  if (ptr == NULL) {
564  extname,
565  at(extname)->exttype());
566  }
567 
568  // Return pointer
569  return ptr;
570 }
571 
572 
573 /***********************************************************************//**
574  * @brief Set HDU for the specified extension number
575  *
576  * @param[in] extno Extension number [0,...,size()-1].
577  * @param[in] hdu HDU.
578  * @return Pointer to cloned HDU.
579  *
580  * @exception GException::out_of_range
581  * Extension number out of range.
582  * @exception GException::invalid_argument
583  * Attempt to insert non-image HDU in first slot.
584  ***************************************************************************/
585 GFitsHDU* GFits::set(const int& extno, const GFitsHDU& hdu)
586 {
587  // Compile option: raise exception if index is out of range
588  #if defined(G_RANGE_CHECK)
589  if (extno < 0 || extno >= size()) {
590  throw GException::out_of_range(G_SET1, "Extension number", extno, size());
591  }
592  #endif
593 
594  // Throw an exception if a non-image extension should be set in the
595  // first slot
596  if (extno == 0 && hdu.exttype() != GFitsHDU::HT_IMAGE) {
597  std::string msg = "Attempt to set a table extension as the first"
598  " extension of a FITS file.\n"
599  "The first extension of a FITS file must be an"
600  " image, hence use the next slot to set a"
601  " table.";
603  }
604 
605  // Free existing HDU only if it differs from current HDU. This prevents
606  // unintential deallocation of the argument
607  if ((m_hdu[extno] != NULL) && (m_hdu[extno] != &hdu)) {
608  delete m_hdu[extno];
609  }
610 
611  // Assign new HDU by cloning
612  m_hdu[extno] = hdu.clone();
613 
614  // If FITS file exists then connect cloned HDU to FITS file
615  if (m_fitsfile != NULL) {
616  __fitsfile fptr = *(FPTR(m_fitsfile));
617  fptr.HDUposition = extno;
618  m_hdu[extno]->connect(&fptr);
619  }
620  else {
621  m_hdu[extno]->extno(extno);
622  }
623 
624  // Return pointer to HDU
625  return (m_hdu[extno]);
626 }
627 
628 
629 /***********************************************************************//**
630  * @brief Set HDU for the specified extension name
631  *
632  * @param[in] extname Name of HDU extension.
633  * @param[in] hdu HDU.
634  * @return Pointer to cloned HDU.
635  *
636  * @exception GException::invalid_argument
637  * Extension name not found.
638  ***************************************************************************/
639 GFitsHDU* GFits::set(const std::string& extname, const GFitsHDU& hdu)
640 {
641  // Get extenion number
642  int extno = this->extno(extname);
643  if (extno == -1) {
644  std::string msg = "No extension with name \""+extname+"\" found in "
645  "FITS file. Please specify a valid extension name.";
647  }
648 
649  // Set HDU and return pointer
650  return (set(extno, hdu));
651 }
652 
653 
654 /***********************************************************************//**
655  * @brief Append HDU to FITS file
656  *
657  * @param[in] hdu HDU.
658  * @return Pointer to appended HDU.
659  *
660  * Append HDU to the next free position in a FITS file. In case that no HDU
661  * exists so far in the FITS file and if the HDU to append is NOT an image,
662  * an empty primary image will be inserted as first HDU in the FITS file.
663  * This guarantees the compatibility with the FITS standard.
664  ***************************************************************************/
666 {
667  // Debug header
668  #if defined(G_DEBUG)
669  std::cout << "GFits::append(";
670  switch (hdu.exttype()) {
671  case GFitsHDU::HT_IMAGE:
672  std::cout << "GFitsImage";
673  break;
675  std::cout << "GFitsAsciiTable";
676  break;
678  std::cout << "GFitsBinTable";
679  break;
680  default:
681  std::cout << "<unknown header type>";
682  break;
683  }
684  std::cout << ") (size=" << size() << "): entry" << std::endl;
685  #endif
686 
687  // Determine next free HDU number
688  int n_hdu = size();
689 
690  // Add primary image if required
691  if (n_hdu == 0 && hdu.exttype() != GFitsHDU::HT_IMAGE) {
692 
693  // Allocate primary image
694  GFitsHDU* primary = new_primary();
695 
696  // If FITS file exists then connect primary image to FITS file
697  if (m_fitsfile != NULL) {
698  __fitsfile fptr = *(FPTR(m_fitsfile));
699  fptr.HDUposition = n_hdu;
700  primary->connect(&fptr);
701  }
702 
703  // Debug information
704  #if defined(G_DEBUG)
705  std::cout << "GFits::append: append primary image to HDU.";
706  std::cout << std::endl;
707  #endif
708 
709  // Push back primary image
710  m_hdu.push_back(primary);
711 
712  // Increment HDU number
713  n_hdu++;
714  }
715 
716  // Clone FITS HDU
717  GFitsHDU* ptr = hdu.clone();
718 
719  // Append HDU if it's valid
720  if (ptr != NULL) {
721 
722  // If FITS file exists then connect cloned HDU to FITS file
723  if (m_fitsfile != NULL) {
724  __fitsfile fptr = *(FPTR(m_fitsfile));
725  fptr.HDUposition = n_hdu;
726  ptr->connect(&fptr);
727  }
728  else {
729  ptr->extno(n_hdu);
730  }
731 
732  // Debug information
733  #if defined(G_DEBUG)
734  std::cout << "GFits::append: append HDU (extno=" << n_hdu << ")";
735  std::cout << std::endl;
736  #endif
737 
738  // Push back HDU
739  m_hdu.push_back(ptr);
740 
741  // Debug trailer
742  #if defined(G_DEBUG)
743  std::cout << "GFits::append: exit" << std::endl;
744  #endif
745 
746  } // endif: HDU was valid
747 
748  // Return
749  return ptr;
750 }
751 
752 
753 /***********************************************************************//**
754  * @brief Set HDU for the specified extension number
755  *
756  * @param[in] extno Extension number [0,...,size()-1].
757  * @param[in] hdu HDU.
758  * @return Pointer to cloned HDU.
759  *
760  * @exception GException::out_of_range
761  * Extension number out of range.
762  * @exception GException::invalid_argument
763  * Attempt to insert non-image HDU in first slot.
764  ***************************************************************************/
765 GFitsHDU* GFits::insert(const int& extno, const GFitsHDU& hdu)
766 {
767  // Compile option: raise exception if extension number is out of range
768  #if defined(G_RANGE_CHECK)
769  if (extno < 0 || extno >= size()) {
770  throw GException::out_of_range(G_INSERT1, "Extension number", extno, size());
771  }
772  #endif
773 
774  // Throw an exception if a non-image extension should be inserted in the
775  // first slot
776  if (extno == 0 && hdu.exttype() != GFitsHDU::HT_IMAGE) {
777  std::string msg = "Attempt to insert a table extension as the first "
778  "extension of a FITS file. The first extension of "
779  "a FITS file must be an image, hence use the next "
780  "slot to insert a table.";
782  }
783 
784  // Create deep copy of HDU
785  GFitsHDU* ptr = hdu.clone();
786 
787  // Inserts deep copy of HDU
788  m_hdu.insert(m_hdu.begin() + extno, ptr);
789 
790  // If FITS file exists then connect cloned HDU to FITS file
791  if (m_fitsfile != NULL) {
792  __fitsfile fptr = *(FPTR(m_fitsfile));
793  fptr.HDUposition = extno;
794  ptr->connect(&fptr);
795  }
796  else {
797  ptr->extno(extno);
798  }
799 
800  // Update extno for all subsequent HDUs
801  for (int i = extno + 1; i < size(); ++i) {
802  m_hdu[i]->extno(i);
803  }
804 
805  // Return pointer to HDU
806  return ptr;
807 }
808 
809 
810 /***********************************************************************//**
811  * @brief Insert HDU into FITS file
812  *
813  * @param[in] extname Extension name.
814  * @param[in] hdu Extension.
815  * @return Pointer to deep copy of extension @p hdu.
816  *
817  * @exception GException::invalid_argument
818  * Extension name not found.
819  *
820  * Inserts an extension @p hdu into the FITS file before the extension with
821  * the specified @p extname.
822  ***************************************************************************/
823 GFitsHDU* GFits::insert(const std::string& extname, const GFitsHDU& hdu)
824 {
825  // Get extenion number
826  int extno = this->extno(extname);
827  if (extno == -1) {
828  std::string msg = "No extension with name \""+extname+"\" found in "
829  "FITS file. Please specify a valid extension name.";
831  }
832 
833  // Insert HDU and return pointer
834  return (insert(extno, hdu));
835 }
836 
837 
838 /***********************************************************************//**
839  * @brief Remove HDU from FITS file
840  *
841  * @param[in] extno Extension number [0,...,size()-1].
842  *
843  * @exception GException::out_of_range
844  * Specified @p extno is out of range.
845  *
846  * @todo Handle HDU update in FITS file.
847  ***************************************************************************/
848 void GFits::remove(const int& extno)
849 {
850  // Compile option: raise an exception if index is out of range
851  #if defined(G_RANGE_CHECK)
852  if (extno < 0 || extno >= size()) {
853  throw GException::out_of_range(G_REMOVE1, "Extension number", extno, size());
854  }
855  #endif
856 
857  // Throw an exception if removal would lead to a non-image extension
858  // in the first slot
859  if (extno == 0 && size() > 1 && m_hdu[1]->exttype() != GFitsHDU::HT_IMAGE) {
860  std::string msg = "Attempt to remove primary image from a FITS file "
861  "with a table extension as second extension. The "
862  "removal of the primary image would result in "
863  "having a table as the first extension of the FITS "
864  "file, which is not a valid FITS file.";
866  }
867 
868  // Delete HDU
869  if (m_hdu[extno] != NULL) delete m_hdu[extno];
870 
871  // Erase HDU from FITS file
872  m_hdu.erase(m_hdu.begin() + extno);
873 
874  // Update extno for all subsequent HDUs
875  for (int i = extno; i < size(); ++i) {
876  m_hdu[i]->extno(i);
877  }
878 
879  // Return
880  return;
881 }
882 
883 
884 /***********************************************************************//**
885  * @brief Remove HDU from FITS file
886  *
887  * @param[in] extname Name of HDU extension.
888  *
889  * @exception GException::invalid_argument
890  * Specified @p extname not found in FITS file.
891  ***************************************************************************/
892 void GFits::remove(const std::string& extname)
893 {
894  // Get extenion number
895  int extno = this->extno(extname);
896  if (extno == -1) {
897  std::string msg = "No extension with name \""+extname+"\" found in "
898  "FITS file. Please specify a valid extension name.";
900  }
901 
902  // Remove extension
903  remove(extno);
904 
905  // Return
906  return;
907 }
908 
909 
910 /***********************************************************************//**
911  * @brief Append FITS file
912  *
913  * @param[in] fits FITS file.
914  *
915  * Append all extension of @p fits file to FITS file.
916  *
917  * @todo Handle HDU update in FITS file.
918  ***************************************************************************/
919 void GFits::extend(const GFits& fits)
920 {
921  // Do nothing if FITS file is empty
922  if (!fits.is_empty()) {
923 
924  // Get size. Note that we extract the size first to avoid an
925  // endless loop that arises when a container is appended to
926  // itself.
927  int num = fits.size();
928 
929  // Reserve enough space
930  reserve(size() + num);
931 
932  // Loop over all HDUs and append pointers to deep copies
933  for (int i = 0; i < num; ++i) {
934 
935  // Clone HDU
936  GFitsHDU* ptr = m_hdu[i]->clone();
937 
938  // Push back HDU on stack
939  m_hdu.push_back(ptr);
940 
941  // Retrieve extno
942  int extno = m_hdu.size()-1;
943 
944  // If FITS file exists then connect cloned HDU to FITS file
945  if (m_fitsfile != NULL) {
946  __fitsfile fptr = *(FPTR(m_fitsfile));
947  fptr.HDUposition = extno;
948  ptr->connect(&fptr);
949  }
950  else {
951  ptr->extno(extno);
952  }
953 
954  } // endfor: looped over all HDUs
955 
956  } // endif: FITS file was not empty
957 
958  // Return
959  return;
960 }
961 
962 
963 /***********************************************************************//**
964  * @brief Return extension number for specified extension name
965  *
966  * @param[in] extname Name of HDU extension.
967  * @return Extension number (-1 of not found).
968  *
969  * Returns the extension number for a specified extension name @p extname. If
970  * the extension name if "PRIMARY" an extension number of 0 is returned.
971  * If the extension is not found, -1 is returned.
972  ***************************************************************************/
973 int GFits::extno(const std::string& extname) const
974 {
975  // Initialise extension number
976  int extno = -1;
977 
978  // Return primary HDU if requested ...
979  if (gammalib::toupper(extname) == "PRIMARY") {
980  if (size() > 0) {
981  extno = 0;
982  }
983  }
984 
985  // ... otherwise search for specified extension
986  else {
987  for (int i = 0; i < size(); ++i) {
988  if (m_hdu[i]->extname() == extname) {
989  extno = i;
990  break;
991  }
992  }
993  }
994 
995  // Return extno
996  return extno;
997 }
998 
999 
1000 /***********************************************************************//**
1001  * @brief Open or (optionally) create FITS file
1002  *
1003  * @param[in] filename Name of FITS file to be opened.
1004  * @param[in] create Create FITS file if it does not exist (default: false)
1005  *
1006  * @exception GException::invalid_argument
1007  * Class instance contains already an opened FITS file.
1008  * Close file before opening a new one using GFits::close().
1009  * @exception GException::fits_open_error
1010  * Unable to open the specified file.
1011  * @exception GException::fits_hdu_not_found
1012  * Requested HDU not found.
1013  * @exception GException::fits_error
1014  * Unable to determine number of HDUs in the FITS file.
1015  *
1016  * This method opens all HDUs that are found in the specified FITS file.
1017  * If the file does not exist, and if create=true, a new FITS file is created.
1018  * For each HDU, a GFitsHDU object is associated to the GFits object.
1019  * The HDUs can then be accessed using the hdu(const std::string&) or
1020  * hdu(int extno) method.
1021  * Any environment variable present in the filename will be expanded.
1022  ***************************************************************************/
1023 void GFits::open(const GFilename& filename, const bool& create)
1024 {
1025  // Don't allow opening if a file is already open
1026  if (m_fitsfile != NULL) {
1027  std::string msg;
1028  if (m_filename == filename) {
1029  msg = "FITS file \""+m_filename+"\" has already been "
1030  "opened, cannot open it again.";
1031  }
1032  else {
1033  msg = "A FITS file \""+m_filename+"\" has already "
1034  "been opened, cannot open another FITS file \""+
1035  filename+"\" before closing the existing one.";
1036  }
1038  }
1039 
1040  // Remove any HDUs
1041  m_hdu.clear();
1042 
1043  // Initialise FITS file as readwrite and non created
1044  m_readwrite = true;
1045  m_created = false;
1046 
1047  // Try opening FITS file with readwrite access
1048  int status = 0;
1049  status = __ffopen(FHANDLE(m_fitsfile), std::string(filename).c_str(), 1, &status);
1050 
1051  // If failed then try opening as readonly.
1052  //
1053  // Possible error codes are:
1054  // 104: FILE_NOT_OPENED (could not open the named file)
1055  // 107: END_OF_FILE (tried to move past end of file, occurs if extname is invalid)
1056  // 112: READONLY_FILE (cannot write to readonly file)
1057  if (status == 104 || status == 107 || status == 112) {
1058  status = 0;
1059  status = __ffopen(FHANDLE(m_fitsfile), std::string(filename).c_str(), 0, &status);
1060  m_readwrite = false;
1061  }
1062 
1063  // If failed and if we are allowed to create a new FITS file then create
1064  // FITS file now. We pass the URL as filename since we want to create a
1065  // fresh file without any extension. We also remove any file before in
1066  // case that file exists but is not a FITS file.
1067  //
1068  // Possible error codes are:
1069  // 104: FILE_NOT_OPENED (could not open the named file)
1070  // 107: END_OF_FILE (tried to move past end of file, occurs if extname is invalid)
1071  if (create && (status == 104 || status == 107)) {
1072  filename.remove();
1073  status = 0;
1074  status = __ffinit(FHANDLE(m_fitsfile), filename.url().c_str(), &status);
1075  m_readwrite = true;
1076  m_created = true;
1077  }
1078 
1079  // Throw special exception if status=202 (keyword not found). This error
1080  // may occur if the file is opened with an expression
1081  if (status == 202) {
1082  throw GException::fits_open_error(G_OPEN, filename, status,
1083  "Keyword not found when opening file.");
1084  }
1085 
1086  // Throw any other error
1087  else if (status != 0) {
1088  throw GException::fits_open_error(G_OPEN, filename, status);
1089  }
1090 
1091  // Store FITS file name as GFilename object
1092  m_filename = filename;
1093 
1094  // Determine number of HDUs
1095  int num_hdu = 0;
1096  status = __ffthdu(FPTR(m_fitsfile), &num_hdu, &status);
1097  if (status != 0) {
1098  throw GException::fits_error(G_OPEN, status);
1099  }
1100 
1101  // Open and append all HDUs
1102  for (int i = 0; i < num_hdu; ++i) {
1103 
1104  // Move to HDU and get HDU type
1105  int type = gammalib::fits_move_to_hdu(G_OPEN, m_fitsfile, i+1);
1106 
1107  // Perform type dependent HDU allocation
1108  GFitsHDU* hdu = NULL;
1109  switch (type) {
1110  case GFitsHDU::HT_IMAGE:
1111  hdu = new_image();
1112  break;
1114  hdu = new GFitsAsciiTable;
1115  break;
1117  hdu = new GFitsBinTable;
1118  break;
1119  default:
1120  std::string msg = "Unknown HDU type \""+gammalib::str(type)+"\"";
1122  break;
1123  }
1124 
1125  // Open HDU
1126  hdu->open(FPTR(m_fitsfile), i);
1127 
1128  // Append HDU
1129  m_hdu.push_back(hdu);
1130 
1131  } // endfor: looped over all HDUs
1132 
1133  // Return
1134  return;
1135 }
1136 
1137 
1138 /***********************************************************************//**
1139  * @brief Saves FITS file
1140  *
1141  * @param[in] clobber Overwrite existing FITS file? (default: false).
1142  *
1143  * @exception GException::fits_file_exist
1144  * Attemting to overwrite an existing file without having specified
1145  * clobber=true.
1146  * @exception GException::fits_file_not_open
1147  * FITS file needs to be opened before saving.
1148  *
1149  * Saves all HDUs of an open FITS file to disk. After saving, the FITS file
1150  * remains open. Invoke the close() method if explicit closing is needed.
1151  * Note that de-allocation of the GFits object also closes the FITS file.
1152  *
1153  * In the special case that no first HDU exists an empty primary image is
1154  * created.
1155  ***************************************************************************/
1156 void GFits::save(const bool& clobber)
1157 {
1158  // Debug header
1159  #if defined(G_DEBUG)
1160  std::cout << "GFits::save (size=" << size() << "): entry" << std::endl;
1161  #endif
1162 
1163  // Initialise cfitsio status
1164  int status = 0;
1165 
1166  // If we attempt to save an existing file without overwriting permission
1167  // then throw an error
1168  if (!m_created && !clobber) {
1170  }
1171 
1172  // If no FITS file has been opened then throw an error
1173  if (m_fitsfile == NULL) {
1175  "Either open FITS file before saving or use saveto() method.");
1176  }
1177 
1178  // We have to make sure that all data are online before we can save them.
1179  // This needs to be done before the data are deleted from disk. We do
1180  // this by cloning all HDUs, as cloning will force all data to get online.
1181  for (int i = 0; i < size(); ++i) {
1182  GFitsHDU* hdu = m_hdu[i]->clone();
1183  delete m_hdu[i];
1184  m_hdu[i] = hdu;
1185  }
1186 
1187  // Determine number of HDUs in current FITS file on disk
1188  int num_hdu = 0;
1189  status = __ffthdu(FPTR(m_fitsfile), &num_hdu, &status);
1190  if (status != 0) {
1191  throw GException::fits_error(G_SAVE, status);
1192  }
1193 
1194  // Debug
1195  #if defined(G_DEBUG)
1196  std::cout << "GFits::save: currently " << num_hdu << " in file";
1197  std::cout << std::endl;
1198  #endif
1199 
1200  // Delete all HDUs (except of the primary HDU) since we will write them
1201  // all freshly
1202  for (int i = num_hdu-1; i >= 0; --i) {
1203  status = __ffdhdu(FPTR(m_fitsfile), NULL, &status);
1204  if (status != 0) {
1205  throw GException::fits_error(G_SAVE, status);
1206  }
1207  }
1208 
1209  // Debug
1210  #if defined(G_DEBUG)
1211  std::cout << "GFits::save: deleted HDUs" << std::endl;
1212  #endif
1213 
1214  // If no HDUs exist in the FITS object then write an empty primary image
1215  if (size() == 0) {
1216  status = __ffmahd(FPTR(m_fitsfile), 1, NULL, &status);
1217  status = __ffcrim(FPTR(m_fitsfile), 8, 0, NULL, &status);
1218  if (status != 0) {
1219  throw GException::fits_error(G_SAVE, status);
1220  }
1221  }
1222 
1223  // ... otherwise save all HDUs
1224  else {
1225  for (int i = 0; i < size(); ++i) {
1226  m_hdu[i]->extno(i);
1227  m_hdu[i]->save();
1228  }
1229  }
1230 
1231  // Debug
1232  #if defined(G_DEBUG)
1233  std::cout << "GFits::save: saved HDUs" << std::endl;
1234  #endif
1235 
1236  // Flush file to disk
1237  status = __ffflus(FPTR(m_fitsfile), &status);
1238  if (status != 0) {
1239  throw GException::fits_error(G_SAVE, status);
1240  }
1241 
1242  // Signal that file needs not to be created anymore
1243  m_created = false;
1244 
1245  // Debug trailer
1246  #if defined(G_DEBUG)
1247  std::cout << "GFits::save: exit" << std::endl;
1248  #endif
1249 
1250  // Return
1251  return;
1252 }
1253 
1254 
1255 /***********************************************************************//**
1256  * @brief Saves to specified FITS file
1257  *
1258  * @param[in] filename Filename.
1259  * @param[in] clobber Overwrite existing FITS file? (default: false)
1260  *
1261  * @exception GException::fits_file_exist
1262  * Specified file exists already. Overwriting requires
1263  * clobber=true.
1264  *
1265  * Saves the FITS object into a specific file.
1266  ***************************************************************************/
1267 void GFits::saveto(const GFilename& filename, const bool& clobber)
1268 {
1269  // Debug header
1270  #if defined(G_DEBUG)
1271  std::cout << "GFits::saveto(\"" << filename << "\", " << clobber << ")"
1272  << " (size=" << size() << "): entry" << std::endl;
1273  #endif
1274 
1275  // If overwriting has been specified then remove the file. Otherwise,
1276  // throw an exception if the file exists.
1277  if (clobber) {
1278  filename.remove();
1279  }
1280  else if (filename.exists()) {
1281  throw GException::fits_file_exist(G_SAVETO, filename);
1282  }
1283 
1284  // Create or open FITS file
1285  GFits fits(filename, true);
1286 
1287  // Append all headers
1288  for (int i = 0; i < size(); ++i) {
1289  fits.append(*m_hdu[i]);
1290  }
1291 
1292  // Save FITS file
1293  fits.save();
1294 
1295  // Close FITS file
1296  fits.close();
1297 
1298  // Debug trailer
1299  #if defined(G_DEBUG)
1300  std::cout << "GFits::saveto: exit" << std::endl;
1301  #endif
1302 
1303  // Return
1304  return;
1305 }
1306 
1307 
1308 /***********************************************************************//**
1309  * @brief Close FITS file
1310  *
1311  * Closing detaches a FITS file from the GFits object and returns a clean
1312  * empty object.
1313  ***************************************************************************/
1314 void GFits::close(void)
1315 {
1316  // Close file and free all members
1317  free_members();
1318 
1319  // Initialise members
1320  init_members();
1321 
1322  // Return
1323  return;
1324 }
1325 
1326 
1327 /***********************************************************************//**
1328  * @brief Publish FITS HDU on VO Hub
1329  *
1330  * @param[in] extno Extension number.
1331  * @param[in] name Optional name of published ressource.
1332  *
1333  * Publishes FITS HDU with specified @p extno.
1334  ***************************************************************************/
1335 void GFits::publish(const int& extno, const std::string& name) const
1336 {
1337  // If HDU is an image then publish it as a FITS image
1338  if (this->at(extno)->exttype() == GFitsHDU::HT_IMAGE) {
1339 
1340  // Get HDU as an image
1341  const GFitsImage* image = this->image(extno);
1342 
1343  // Save extension name
1344  std::string extname = image->extname();
1345 
1346  // Optionally set extension name
1347  if (!name.empty()) {
1348  const_cast<GFitsImage*>(image)->extname(name);
1349  }
1350 
1351  // Create VO Client
1352  GVOClient client;
1353 
1354  // Publish image using VO client
1355  client.publish(*image);
1356 
1357  // Restore extension name
1358  const_cast<GFitsImage*>(image)->extname(extname);
1359 
1360  } // endif: HDU was an image
1361 
1362  // ... otherwise publish the HDU as a VO table
1363  else {
1364 
1365  // Get HDU as a table
1366  const GFitsTable* table = this->table(extno);
1367 
1368  // Save extension name
1369  std::string extname = table->extname();
1370 
1371  // Optionally set extension name
1372  if (!name.empty()) {
1373  const_cast<GFitsTable*>(table)->extname(name);
1374  }
1375 
1376  // Create VO Client
1377  GVOClient client;
1378 
1379  // Generate VO table FITS table
1380  GVOTable votable(*table);
1381 
1382  // Publish VO table using VO client
1383  client.publish(votable);
1384 
1385  // Restore extension name
1386  const_cast<GFitsTable*>(table)->extname(extname);
1387 
1388  } // endelse: published HDU as VO table
1389 
1390  // Return
1391  return;
1392 }
1393 
1394 
1395 /***********************************************************************//**
1396  * @brief Publish FITS HDU on VO Hub
1397  *
1398  * @param[in] extname Extension name.
1399  * @param[in] name Optional name of published ressource.
1400  *
1401  * Publishes FITS HDU with specified @p extname.
1402  ***************************************************************************/
1403 void GFits::publish(const std::string& extname, const std::string& name) const
1404 {
1405  // Get extenion number
1406  int extno = this->extno(extname);
1407  if (extno == -1) {
1408  std::string msg = "Extension \""+extname+"\" not found in FITS file. "
1409  "Please specify a valid extension name.";
1411  }
1412 
1413  // Publish FITS HDU
1414  publish(extno, name);
1415 
1416  // Return
1417  return;
1418 }
1419 
1420 
1421 /***********************************************************************//**
1422  * @brief Print FITS information
1423  *
1424  * @param[in] chatter Chattiness.
1425  * @return String containing FITS information.
1426  ***************************************************************************/
1427 std::string GFits::print(const GChatter& chatter) const
1428 {
1429  // Initialise result string
1430  std::string result;
1431 
1432  // Continue only if chatter is not silent
1433  if (chatter != SILENT) {
1434 
1435  // Append header
1436  result.append("=== GFits ===");
1437 
1438  // Append file information
1439  result.append("\n"+gammalib::parformat("Filename"));
1440  result.append(m_filename);
1441  result.append("\n"+gammalib::parformat("History"));
1442  if (m_created) {
1443  result.append("new file");
1444  }
1445  else {
1446  result.append("existing file");
1447  }
1448  result.append("\n"+gammalib::parformat("Mode"));
1449  if (m_readwrite) {
1450  result.append("read/write");
1451  }
1452  else {
1453  result.append("read only");
1454  }
1455  result.append("\n"+gammalib::parformat("Number of HDUs"));
1456  result.append(gammalib::str(size()));
1457 
1458  // NORMAL: Append HDUs
1459  if (chatter >= NORMAL) {
1460  for (int i = 0; i < size(); ++i) {
1461  result.append("\n");
1462  result.append(m_hdu[i]->print(gammalib::reduce(chatter)));
1463  }
1464  }
1465 
1466  } // endif: chatter was not silent
1467 
1468  // Return result
1469  return result;
1470 }
1471 
1472 
1473 /*==========================================================================
1474  = =
1475  = Private methods =
1476  = =
1477  ==========================================================================*/
1478 
1479 /***********************************************************************//**
1480  * @brief Initialise class members
1481  ***************************************************************************/
1483 {
1484  // Initialise GFits members
1485  m_hdu.clear();
1486  m_filename.clear();
1487  m_fitsfile = NULL;
1488  m_readwrite = true;
1489  m_created = true;
1490 
1491  // Return
1492  return;
1493 }
1494 
1495 
1496 /***********************************************************************//**
1497  * @brief Copy class members
1498  *
1499  * @param fits Object to be copied
1500  *
1501  * The method does not copy the FITS file name and FITS file pointer.
1502  * This prevents that several copies of the FITS file pointer exist in
1503  * different instances of GFits, which would lead to confusion since one
1504  * instance could close the file while for another it still would be
1505  * opened. The rule ONE INSTANCE - ONE FILE applies.
1506  ***************************************************************************/
1507 void GFits::copy_members(const GFits& fits)
1508 {
1509  // Reset FITS file attributes
1510  m_filename.clear();
1511  m_fitsfile = NULL;
1512  m_readwrite = true;
1513  m_created = true;
1514 
1515  // Clone HDUs
1516  m_hdu.clear();
1517  for (int i = 0; i < fits.m_hdu.size(); ++i) {
1518  m_hdu.push_back((fits.m_hdu[i]->clone()));
1519  }
1520 
1521  // Return
1522  return;
1523 }
1524 
1525 
1526 /***********************************************************************//**
1527  * @brief Delete class members
1528  *
1529  * Closes the FITS file if it had been opened and deallocate all HDUs.
1530  *
1531  * If the G_DELETE_EMPTY_FITS_FILES option is defined, files without HDUs
1532  * or corrupted files will be deleted. This prevents leaving corrupted files
1533  * on disk (yet, corrupted files may be generated by another application,
1534  * thus this is not 100% safe; better make the code solid against reading
1535  * corrupted FITS files).
1536  ***************************************************************************/
1538 {
1539  // If FITS file has been opened then close it now
1540  if (m_fitsfile != NULL) {
1541 
1542  // If file has been created but not yet saved then delete the file
1543  // now. We do not worry about the status in this case.
1544  if (m_created) {
1545  int status = 0;
1546  __ffdelt(FPTR(m_fitsfile), &status);
1547  }
1548 
1549  // Compile option: If there are no HDUs then delete the file (don't
1550  // worry about error)
1551  #if defined(G_DELETE_EMPTY_FITS_FILES)
1552  else if (size() == 0) {
1553  int status = 0;
1554  __ffdelt(FPTR(m_fitsfile), &status);
1555  }
1556  #endif
1557 
1558  // ... otherwise close the file
1559  else {
1560  int status = 0;
1561  status = __ffclos(FPTR(m_fitsfile), &status);
1562  if (status == 252) {
1563  int new_status = 0;
1564  __ffdelt(FPTR(m_fitsfile), &new_status);
1565  if (new_status != 0) {
1566  throw GException::fits_error(G_FREE_MEM, new_status);
1567  }
1568  }
1569  else if (status != 0) {
1570  throw GException::fits_error(G_FREE_MEM, status);
1571  }
1572 
1573  } // endelse: there was an open FITS file
1574 
1575  // Set FITS file pointer to NULL
1576  m_fitsfile = NULL;
1577 
1578  } // endif: FITS file had been opened
1579 
1580  // Free HDUs
1581  for (int i = 0; i < m_hdu.size(); ++i) {
1582  if (m_hdu[i] != NULL) {
1583  delete m_hdu[i];
1584  m_hdu[i] = NULL;
1585  }
1586  }
1587 
1588  // Clear HDUs
1589  m_hdu.clear();
1590 
1591  // Return
1592  return;
1593 }
1594 
1595 
1596 /***********************************************************************//**
1597  * @brief Allocate new FITS image and return memory pointer
1598  *
1599  * Depending on the number of bits per pixel, a FITS image is allocated
1600  * and the pointer is returned. The following FITS image classes are
1601  * handled:
1602  * GFitsImageByte (bitpix=8)
1603  * GFitsImageShort (bitpix=16)
1604  * GFitsImageLong (bitpix=32)
1605  * GFitsImageLongLong (bitpix=64)
1606  * GFitsImageFloat (bitpix=-32)
1607  * GFitsImageDouble (bitpix=-64)
1608  * The information about the number of bits per pixels is extracted from
1609  * the actual HDU.
1610  *
1611  * @todo Additional code is needed to detect unsigned integer images. This
1612  * code may be insprired by the code used for table columns as the unsigned
1613  * information is stored in the BZERO keyword.
1614  ***************************************************************************/
1616 {
1617  // Initialise return value
1618  GFitsImage* image = NULL;
1619 
1620  // Get number of bits per pixel
1621  int status = 0;
1622  int bitpix = -64;
1623  status = __ffgiet(FPTR(m_fitsfile), &bitpix, &status);
1624  if (status != 0) {
1625  throw GException::fits_error(G_NEW_IMAGE, status);
1626  }
1627 
1628  // Check for unsigned image
1629  char keyname[10];
1630  long long bzero;
1631  long long bscale;
1632  std::sprintf(keyname, "BZERO");
1633  if (__ffgky(FPTR(m_fitsfile), __TLONGLONG, keyname, &bzero, NULL, &status) != 0) {
1634  bzero = 0;
1635  }
1636  std::sprintf(keyname, "BSCALE");
1637  if (__ffgky(FPTR(m_fitsfile), __TLONGLONG, keyname, &bscale, NULL, &status) != 0) {
1638  bscale = 0;
1639  }
1640  if (bitpix == 8 && bzero == -128 && bscale == 1) {
1641  bitpix = 10;
1642  }
1643  else if (bitpix == 16 && bzero == 32768u && bscale == 1) {
1644  bitpix = 20;
1645  }
1646  else if (bitpix == 32 && bzero == 2147483648u && bscale == 1) {
1647  bitpix = 40;
1648  }
1649 
1650  // Allocate bitpix dependent image
1651  switch (bitpix) {
1652  case 8:
1653  image = new GFitsImageByte;
1654  break;
1655  case 10:
1656  image = new GFitsImageSByte;
1657  break;
1658  case 16:
1659  image = new GFitsImageShort;
1660  break;
1661  case 20:
1662  image = new GFitsImageUShort;
1663  break;
1664  case 32:
1665  image = new GFitsImageLong;
1666  break;
1667  case 40:
1668  image = new GFitsImageULong;
1669  break;
1670  case 64:
1671  image = new GFitsImageLongLong;
1672  break;
1673  case -32:
1674  image = new GFitsImageFloat;
1675  break;
1676  case -64:
1677  image = new GFitsImageDouble;
1678  break;
1679  default:
1681  break;
1682  }
1683 
1684  // Return image pointer
1685  return image;
1686 }
1687 
1688 
1689 /***********************************************************************//**
1690  * @brief Return minimal primary HDU
1691  *
1692  * Creates a primary HDU in memory and open it using the GFitsHDU::open()
1693  * method.
1694  ***************************************************************************/
1696 {
1697  // Allocate an empty image
1699 
1700  // Create primary image in memory
1701  int status = 0;
1702  __fitsfile* fptr;
1703  status = __ffinit(&fptr, "mem://", &status);
1704  status = __ffcrim(fptr, 8, 0, NULL, &status);
1705 
1706  // Open HDU
1707  image->open(fptr,0);
1708 
1709  // Close FITS file in memory
1710  status = __ffclos(fptr, &status);
1711  if (status == 252) {
1712  status = 0;
1713  status = __ffdelt(fptr, &status);
1714  }
1715 
1716  // Initialise FITS file pointer
1717  FPTR(image->m_fitsfile)->HDUposition = 0;
1718  FPTR(image->m_fitsfile)->Fptr = NULL;
1719 
1720  // Return image
1721  return image;
1722 }
1723 
1724 
1725 /*==========================================================================
1726  = =
1727  = FITS utility functions =
1728  = =
1729  ==========================================================================*/
1730 
1731 /***********************************************************************//**
1732  * @brief Move to FITS extension
1733  *
1734  * @param[in] caller Name of caller.
1735  * @param[in] vptr FITS file void pointer.
1736  * @param[in] hdunum HDU number (optional)
1737  *
1738  * @exception GException::fits_error
1739  * cfitsio error occured.
1740  *
1741  * If @p hdunum is >0, moves the FITS file void pointer to the HDU
1742  * specified by @p hdunum. Otherwise, the FITS file void pointer is moved
1743  * to the HDU specified by the @p HDUposition attribute of the void pointer.
1744  ***************************************************************************/
1745 int gammalib::fits_move_to_hdu(const std::string& caller, void* vptr,
1746  const int& hdunum)
1747 {
1748  // Initialise status and HDU type
1749  int status = 0;
1750  int type = 0;
1751 
1752  // Set HDU position
1753  int position = (hdunum > 0) ? hdunum : (FPTR(vptr)->HDUposition)+1;
1754 
1755  // Move to HDU
1756  status = __ffmahd(FPTR(vptr), position, &type, &status);
1757 
1758  // Throw exception in case of an error
1759  if (status != 0) {
1760  std::string msg = "Unable to move FITS file pointer to extension "
1761  "number "+gammalib::str(position-1)+".";
1762  throw GException::fits_error(caller, status, msg);
1763  }
1764 
1765  // Return HDU type
1766  return type;
1767 }
Long long integer FITS image class definition.
std::vector< GFitsHDU * > m_hdu
Pointers to HDUs.
Definition: GFits.hpp:143
GFitsImage * new_image(void)
Allocate new FITS image and return memory pointer.
Definition: GFits.cpp:1615
GFitsHDU * at(const int &extno)
Get pointer to HDU.
Definition: GFits.cpp:233
VO client class.
Definition: GVOClient.hpp:59
Double precision FITS image class definition.
Abstract FITS image base class.
Definition: GFitsImage.hpp:43
#define __ffdhdu(A, B, C)
GFitsTable * table(const int &extno)
Get pointer to table HDU.
Definition: GFits.cpp:472
GFits(void)
Void constructor.
Definition: GFits.cpp:90
#define G_INSERT1
Definition: GFits.cpp:59
#define G_OPEN
Definition: GFits.cpp:63
#define FPTR(A)
void clear(void)
Clear FITS file.
Definition: GFits.cpp:195
Signed Byte FITS image class definition.
void publish(const GFitsHDU &hdu)
Publish FITS HDU.
Definition: GVOClient.cpp:372
void open(void *vptr, int hdunum)
Open HDU.
Definition: GFitsHDU.cpp:285
Single precision FITS image class definition.
Abstract FITS extension base class.
Definition: GFitsHDU.hpp:51
Signed Byte FITS image class.
void connect(void *fptr)
Connect HDU to FITS file.
Definition: GFitsHDU.cpp:192
#define __ffflus(A, B)
#define G_INSERT2
Definition: GFits.cpp:60
const GFilename & filename(void) const
Return FITS filename.
Definition: GFits.hpp:313
Unsigned long image FITS class.
virtual HDUType exttype(void) const =0
GFilename m_filename
FITS file name.
Definition: GFits.hpp:144
#define __ffinit(A, B, C)
#define G_PUBLISH
Definition: GFits.cpp:66
void * m_fitsfile
FITS file pointer pointing on actual HDU.
Definition: GFitsHDU.hpp:133
#define FHANDLE(A)
Unsigned short FITS image class definition.
Gammalib tools definition.
#define __ffcrim(A, B, C, D, E)
#define __ffthdu(A, B, C)
FITS file class.
Definition: GFits.hpp:63
FITS file class interface definition.
Long integer FITS image class definition.
#define __ffclos(A, B)
const int & extno(void) const
Return extension number.
Definition: GFitsHDU.hpp:176
GFits & operator=(const GFits &fits)
Assignment operator.
Definition: GFits.cpp:165
Long long integer FITS image class.
VO client class interface definition.
void saveto(const GFilename &filename, const bool &clobber=false)
Saves to specified FITS file.
Definition: GFits.cpp:1267
Unsigned long image FITS class definition.
GFitsImage * new_primary(void)
Return minimal primary HDU.
Definition: GFits.cpp:1695
void save(const bool &clobber=false)
Saves FITS file.
Definition: GFits.cpp:1156
#define __ffmahd(A, B, C, D)
void remove(const int &extno)
Remove HDU from FITS file.
Definition: GFits.cpp:848
Double precision FITS image class.
GFits * clone(void) const
Clone FITS file.
Definition: GFits.cpp:213
#define G_TABLE1
Definition: GFits.cpp:55
CFITSIO interface header.
Filename class.
Definition: GFilename.hpp:62
void open(const GFilename &filename, const bool &create=false)
Open or (optionally) create FITS file.
Definition: GFits.cpp:1023
void publish(const int &extno, const std::string &name="") const
Publish FITS HDU on VO Hub.
Definition: GFits.cpp:1335
void free_members(void)
Delete class members.
Definition: GFits.cpp:1537
#define __ffopen(A, B, C, D)
bool exists(void) const
Checks whether file exists.
Definition: GFilename.cpp:223
Abstract interface for FITS table.
Definition: GFitsTable.hpp:44
virtual GFitsHDU * clone(void) const =0
Clones object.
#define G_NEW_IMAGE
Definition: GFits.cpp:68
#define __ffgky(A, B, C, D, E, F)
GChatter
Definition: GTypemaps.hpp:33
#define G_SAVE
Definition: GFits.cpp:64
#define __ffdelt(A, B)
Short integer FITS image class.
FITS ASCII table class.
#define G_REMOVE1
Definition: GFits.cpp:61
Single precision FITS image class.
Unsigned short FITS image class.
void remove(void) const
Remove file from disk.
Definition: GFilename.cpp:345
const std::string & extname(void) const
Return extension name.
Definition: GFitsHDU.hpp:162
Short integer FITS image class definition.
#define G_REMOVE2
Definition: GFits.cpp:62
FITS Byte image class definition.
#define G_AT2
Definition: GFits.cpp:52
Long integer FITS image class.
GFitsImage * image(const int &extno)
Get pointer to image HDU.
Definition: GFits.cpp:360
#define G_IMAGE1
Definition: GFits.cpp:53
void reserve(const int &num)
Reserves space for HDUs in FITS file.
Definition: GFits.hpp:265
std::string url(void) const
Return Uniform Resource Locator (URL)
Definition: GFilename.hpp:189
void init_members(void)
Initialise class members.
Definition: GFits.cpp:1482
#define __TLONGLONG
void clear(void)
Clear file name.
Definition: GFilename.cpp:188
bool is_empty(void) const
Signals if there are no HDUs in FITS file.
Definition: GFits.hpp:251
#define G_SAVETO
Definition: GFits.cpp:65
#define G_TABLE2
Definition: GFits.cpp:56
FITS binary table class.
int size(void) const
Return number of HDUs in FITS file.
Definition: GFits.hpp:237
GChatter reduce(const GChatter &chatter)
Reduce chattiness by one level.
Definition: GTypemaps.hpp:65
FITS Byte image class.
GFitsHDU * insert(const int &extno, const GFitsHDU &hdu)
Set HDU for the specified extension number.
Definition: GFits.cpp:765
virtual ~GFits(void)
Destructor.
Definition: GFits.cpp:143
bool m_created
FITS file has been created (true/false)
Definition: GFits.hpp:147
Exception handler interface definition.
bool m_readwrite
FITS file is readwrite (true/false)
Definition: GFits.hpp:146
GFitsHDU * append(const GFitsHDU &hdu)
Append HDU to FITS file.
Definition: GFits.cpp:665
std::string toupper(const std::string &s)
Convert string to upper case.
Definition: GTools.cpp:831
VO table class definition.
FITS binary table class definition.
void copy_members(const GFits &fits)
Copy class members.
Definition: GFits.cpp:1507
#define G_AT1
Definition: GFits.cpp:51
int fits_move_to_hdu(const std::string &caller, void *vptr, const int &hdunum=0)
Move to FITS extension.
Definition: GFits.cpp:1745
#define G_FREE_MEM
Definition: GFits.cpp:67
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1033
#define G_SET2
Definition: GFits.cpp:58
VOTable class.
Definition: GVOTable.hpp:55
GFitsHDU * set(const int &extno, const GFitsHDU &hdu)
Set HDU for the specified extension number.
Definition: GFits.cpp:585
FITS ASCII table class definition.
std::string print(const GChatter &chatter=NORMAL) const
Print FITS information.
Definition: GFits.cpp:1427
#define G_SET1
Definition: GFits.cpp:57
void close(void)
Close FITS file.
Definition: GFits.cpp:1314
int extno(const std::string &extname) const
Return extension number for specified extension name.
Definition: GFits.cpp:973
void * m_fitsfile
FITS file pointer.
Definition: GFits.hpp:145
#define G_IMAGE2
Definition: GFits.cpp:54
#define __ffgiet(A, B, C)
void extend(const GFits &fits)
Append FITS file.
Definition: GFits.cpp:919
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:415