GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GFitsImage.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GFitsImage.cpp - Abstract FITS image base class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2008-2021 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 GFitsImage.cpp
23  * @brief Abstract FITS image base class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include "GException.hpp"
32 #include "GFitsCfitsio.hpp"
33 #include "GFits.hpp"
34 #include "GFitsImage.hpp"
35 #include "GTools.hpp"
36 
37 /* __ Method name definitions ____________________________________________ */
38 #define G_NAXES "GFitsImage::naxes(int)"
39 #define G_OPEN_IMAGE "GFitsImage::open(void*)"
40 #define G_LOAD_IMAGE "GFitsImage::load_image(int,void*,void*,int*)"
41 #define G_SAVE_IMAGE "GFitsImage::save_image(int,void*)"
42 #define G_OFFSET_1D "GFitsImage::offset(int&)"
43 #define G_OFFSET_2D "GFitsImage::offset(int&,int&)"
44 #define G_OFFSET_3D "GFitsImage::offset(int&,int&,int&)"
45 #define G_OFFSET_4D "GFitsImage::offset(int&,int&,int&,int&)"
46 
47 /* __ Macros _____________________________________________________________ */
48 
49 /* __ Coding definitions _________________________________________________ */
50 
51 /* __ Debug definitions __________________________________________________ */
52 
53 
54 /*==========================================================================
55  = =
56  = Constructors/destructors =
57  = =
58  ==========================================================================*/
59 
60 /***********************************************************************//**
61  * @brief Void constructor
62  *
63  * Construct instance of an empty image. No header cards are present in an
64  * empty image.
65  ***************************************************************************/
67 {
68  // Initialise class members for clean destruction
69  init_members();
70 
71  // Return
72  return;
73 }
74 
75 
76 /***********************************************************************//**
77  * @brief 1D image constructor
78  *
79  * @param[in] bitpix Number of Bits per pixel (negative is floating point).
80  * @param[in] nx Number of pixels.
81  *
82  * Construct 1D instance of GFitsImage by specifying the number of pixels.
83  * This method also adds the relevant header cards.
84  ***************************************************************************/
85 GFitsImage::GFitsImage(const int& bitpix, const int& nx) : GFitsHDU()
86 {
87  // Initialise class members for clean destruction
88  init_members();
89 
90  // Store number of Bits per pixel
91  m_bitpix = bitpix;
92 
93  // Set number of axes
94  m_naxis = 1;
95 
96  // Set image dimensions
97  m_naxes = new long[m_naxis];
98  m_naxes[0] = nx;
99  m_num_pixels = nx;
100 
101  // Initialise header
103 
104  // Return
105  return;
106 }
107 
108 
109 /***********************************************************************//**
110  * @brief 2D image constructor
111  *
112  * @param[in] bitpix Number of Bits per pixel (negative is floating point).
113  * @param[in] nx Number of pixels in first dimension.
114  * @param[in] ny Number of pixels in second dimension.
115  *
116  * Construct 2D instance of GFitsImage by specifying the number of pixels
117  * in each dimension. This method also adds the relevant header cards.
118  ***************************************************************************/
119 GFitsImage::GFitsImage(const int& bitpix, const int& nx, const int& ny) :
120  GFitsHDU()
121 {
122  // Initialise class members for clean destruction
123  init_members();
124 
125  // Store number of Bits per pixel
126  m_bitpix = bitpix;
127 
128  // Set number of axes
129  m_naxis = 2;
130 
131  // Set image dimensions
132  m_naxes = new long[m_naxis];
133  m_naxes[0] = nx;
134  m_naxes[1] = ny;
135  m_num_pixels = nx * ny;
136 
137  // Initialise header
139 
140  // Return
141  return;
142 }
143 
144 
145 /***********************************************************************//**
146  * @brief 3D image constructor
147  *
148  * @param[in] bitpix Number of Bits per pixel (negative is floating point).
149  * @param[in] nx Number of pixels in first dimension.
150  * @param[in] ny Number of pixels in second dimension.
151  * @param[in] nz Number of pixels in third dimension.
152  *
153  * Construct 3D instance of GFitsImage by specifying the number of pixels
154  * in each dimension. This method also adds the relevant header cards.
155  ***************************************************************************/
156 GFitsImage::GFitsImage(const int& bitpix, const int& nx, const int& ny,
157  const int& nz) : GFitsHDU()
158 {
159  // Initialise class members for clean destruction
160  init_members();
161 
162  // Store number of Bits per pixel
163  m_bitpix = bitpix;
164 
165  // Set number of axes
166  m_naxis = 3;
167 
168  // Set image dimensions
169  m_naxes = new long[m_naxis];
170  m_naxes[0] = nx;
171  m_naxes[1] = ny;
172  m_naxes[2] = nz;
173  m_num_pixels = nx * ny * nz;
174 
175  // Initialise header
177 
178  // Return
179  return;
180 }
181 
182 
183 /***********************************************************************//**
184  * @brief 4D image constructor
185  *
186  * @param[in] bitpix Number of Bits per pixel (negative is floating point).
187  * @param[in] nx Number of pixels in first dimension.
188  * @param[in] ny Number of pixels in second dimension.
189  * @param[in] nz Number of pixels in third dimension.
190  * @param[in] nt Number of pixels in forth dimension.
191  *
192  * Construct 4D instance of GFitsImage by specifying the number of pixels
193  * in each dimension. This method also adds the relevant header cards.
194  ***************************************************************************/
195 GFitsImage::GFitsImage(const int& bitpix, const int& nx, const int& ny,
196  const int& nz, const int& nt) : GFitsHDU()
197 {
198  // Initialise class members for clean destruction
199  init_members();
200 
201  // Store number of Bits per pixel
202  m_bitpix = bitpix;
203 
204  // Set number of axes
205  m_naxis = 4;
206 
207  // Set image dimensions
208  m_naxes = new long[m_naxis];
209  m_naxes[0] = nx;
210  m_naxes[1] = ny;
211  m_naxes[2] = nz;
212  m_naxes[3] = nt;
213  m_num_pixels = nx * ny * nz * nt;
214 
215  // Initialise header
217 
218  // Return
219  return;
220 }
221 
222 
223 /***********************************************************************//**
224  * @brief Constructor
225  *
226  * @param[in] bitpix Number of Bits per pixel (negative is floating point).
227  * @param[in] naxes Vector of number of pixels in each dimension.
228  *
229  * Construct instance of GFitsImage by specifying the image dimension and
230  * the number of pixels in each dimension. This method also adds the relevant
231  * header cards.
232  ***************************************************************************/
233 GFitsImage::GFitsImage(const int& bitpix, const std::vector<int>& naxes) : GFitsHDU()
234 {
235  // Initialise class members for clean destruction
236  init_members();
237 
238  // Store number of Bits per pixel
239  m_bitpix = bitpix;
240 
241  // Store number of axes
242  m_naxis = naxes.size();
243 
244  // Copy number of pixels in each dimension and calculate the total
245  // number of pixels
246  if (m_naxis > 0) {
247  m_naxes = new long[m_naxis];
248  m_num_pixels = 1;
249  for (int i = 0; i < m_naxis; ++i) {
250  m_naxes[i] = naxes[i];
251  m_num_pixels *= naxes[i];
252  }
253  }
254 
255  // Initialise header
257 
258  // Return
259  return;
260 }
261 
262 
263 /***********************************************************************//**
264  * @brief Copy constructor
265  *
266  * @param[in] image FITS image.
267  ***************************************************************************/
269 {
270  // Initialise class members for clean destruction
271  init_members();
272 
273  // Copy members
274  copy_members(image);
275 
276  // Return
277  return;
278 }
279 
280 
281 /***********************************************************************//**
282  * @brief Destructor
283  ***************************************************************************/
285 {
286  // Free members
287  free_members();
288 
289  // Return
290  return;
291 }
292 
293 
294 /*==========================================================================
295  = =
296  = Operators =
297  = =
298  ==========================================================================*/
299 
300 /***********************************************************************//**
301  * @brief Assignment operator
302  *
303  * @param[in] image FITS image.
304  * @return FITS image.
305  ***************************************************************************/
307 {
308  // Execute only if object is not identical
309  if (this != &image) {
310 
311  // Copy base class members
312  this->GFitsHDU::operator=(image);
313 
314  // Free members
315  free_members();
316 
317  // Initialise private members for clean destruction
318  init_members();
319 
320  // Copy members
321  copy_members(image);
322 
323  } // endif: object was not identical
324 
325  // Return this object
326  return *this;
327 }
328 
329 
330 /*==========================================================================
331  = =
332  = Public methods =
333  = =
334  ==========================================================================*/
335 
336 /***********************************************************************//**
337  * @brief Return dimension of an image axis
338  *
339  * @param[in] axis Image axis [0,...,naxis()-1].
340  *
341  * @exception GException::out_of_range
342  * Image axis not valid.
343  ***************************************************************************/
344 int GFitsImage::naxes(const int& axis) const
345 {
346  // Check if axis is within the range
347  #if defined(G_RANGE_CHECK)
348  if (axis < 0 || axis >= naxis()) {
349  throw GException::out_of_range(G_NAXES, "Image axis", axis, naxis());
350  }
351  #endif
352 
353  // Get axis dimension
354  int dim = m_naxes[axis];
355 
356  // Return axis dimension
357  return dim;
358 }
359 
360 
361 /***********************************************************************//**
362  * @brief Set nul value
363  *
364  * @param[in] value Nul value.
365  *
366  * @todo To correctly reflect the nul value in the data, the image should
367  * be reloaded. However, the image may have been changed, so in principle
368  * saving is needed. However, we may not want to store the image, hence saving
369  * is also not desired. We thus have to develop a method to update the
370  * image information for a new nul value in place ...
371  ***************************************************************************/
372 void GFitsImage::nulval(const void* value)
373 {
374  // Allocate nul value
375  alloc_nulval(value);
376 
377  // Update image
378  //TODO
379 
380  // Return
381  return;
382 }
383 
384 
385 /***********************************************************************//**
386  * @brief Print column information
387  *
388  * @param[in] chatter Chattiness.
389  * @return String containing column information.
390  *
391  * @todo Format and cfitsio information is mainly for debugging. This could
392  * be vanish in a more stable version of the code, or it could be compiled
393  * in conditionally using a debug option.
394  ***************************************************************************/
395 std::string GFitsImage::print(const GChatter& chatter) const
396 {
397  // Initialise result string
398  std::string result;
399 
400  // Continue only if chatter is not silent
401  if (chatter != SILENT) {
402 
403  // Append header
404  result.append("=== GFitsImage ===");
405 
406  // Append HDU information
407  result.append("\n"+print_hdu(chatter));
408 
409  // Append image dimensions
410  result.append("\n"+gammalib::parformat("Image type"));
411  result.append(typecode(type()));
412  result.append("\n"+gammalib::parformat("Number of dimensions"));
413  result.append(gammalib::str(naxis()));
414  result.append("\n"+gammalib::parformat("Number of image pixels"));
415  result.append(gammalib::str(npix()));
416  for (int i = 0; i < naxis(); ++i) {
417  result.append("\n"+gammalib::parformat("Number of bins in "+gammalib::str(i)));
418  result.append(gammalib::str(naxes(i)));
419  }
420 
421  // NORMAL: Append header information
422  if (chatter >= NORMAL) {
423  result.append(+"\n"+m_header.print(gammalib::reduce(chatter)));
424  }
425 
426  } // endif: chatter was not silent
427 
428  // Return result
429  return result;
430 }
431 
432 
433 /*==========================================================================
434  = =
435  = Protected methods =
436  = =
437  ==========================================================================*/
438 
439 /***********************************************************************//**
440  * @brief Initialise class members
441  ***************************************************************************/
443 {
444  // Initialise members
445  m_bitpix = 8;
446  m_naxis = 0;
447  m_naxes = NULL;
448  m_num_pixels = 0;
449  m_anynul = 0;
450 
451  // Return
452  return;
453 }
454 
455 
456 /***********************************************************************//**
457  * @brief Copy class members
458  *
459  * @param[in] image FITS image to copy
460  ***************************************************************************/
462 {
463  // Copy attributes
464  m_bitpix = image.m_bitpix;
465  m_naxis = image.m_naxis;
466  m_num_pixels = image.m_num_pixels;
467  m_anynul = image.m_anynul;
468 
469  // Copy axes
470  m_naxes = NULL;
471  if (image.m_naxes != NULL && m_naxis > 0) {
472  m_naxes = new long[m_naxis];
473  for (int i = 0; i < m_naxis; ++i) {
474  m_naxes[i] = image.m_naxes[i];
475  }
476  }
477 
478  // Return
479  return;
480 }
481 
482 
483 /***********************************************************************//**
484  * @brief Delete class members
485  ***************************************************************************/
487 {
488  // Free memory
489  if (m_naxes != NULL) delete [] m_naxes;
490 
491  // Mark memory as free
492  m_naxes = NULL;
493 
494  // Return
495  return;
496 }
497 
498 
499 /***********************************************************************//**
500  * @brief Open FITS image
501  *
502  * @param[in] vptr FITS file pointer
503  *
504  * Open FITS image in FITS file. Opening means connecting the FITS file
505  * pointer to the image and reading the image and axes dimensions.
506  ***************************************************************************/
507 void GFitsImage::data_open(void* vptr)
508 {
509  // Open image
510  open_image(vptr);
511 
512  // Return
513  return;
514 }
515 
516 
517 /***********************************************************************//**
518  * @brief Save FITS image
519  *
520  * Saves the image into the FITS file.
521  ***************************************************************************/
523 {
524  // Save image
525  save_image(type(), pixels());
526 
527  // Return
528  return;
529 }
530 
531 
532 /***********************************************************************//**
533  * @brief Close FITS image
534  *
535  * Closing a FITS image resets the object into its initial state. Closing
536  * does NOT save the image into the FITS file. Use the save method for this
537  * purpose.
538  *
539  * @todo Not sure that this is efficient at this level since the pixel array
540  * will not be deallocated!!!
541  ***************************************************************************/
543 {
544  // Free members
545  free_members();
546 
547  // Initialise members
548  init_members();
549 
550  // Return
551  return;
552 }
553 
554 
555 /***********************************************************************//**
556  * @brief Connect FITS image
557  *
558  * @param[in] vptr FITS file pointer
559  *
560  * Connects a FITS file pointer to an image. This method actually does
561  * nothing since any GFitsImage can directly access the FITS file pointer
562  * that is stored in the GFitsHDU base class.
563  ***************************************************************************/
564 void GFitsImage::data_connect(void* vptr)
565 {
566  // Return
567  return;
568 }
569 
570 
571 /***********************************************************************//**
572  * @brief Initialise image header
573  *
574  * Initialises the image header by setting the default header cards. This
575  * method requires the members m_bitpix, m_naxis, and m_naxes to be set
576  * previously.
577  ***************************************************************************/
579 {
580  // Set image header keywords
581  m_header.append(GFitsHeaderCard("XTENSION", "IMAGE ",
582  "IMAGE extension"));
584  "number of bits per data pixel"));
586  "number of data axes"));
587  for (int i = 0; i < naxis(); ++i) {
588  std::ostringstream s_key;
589  std::ostringstream s_comment;
590  s_key << "NAXIS" << (i+1);
591  s_comment << "length of data axis " << (i+1);
592  m_header.append(GFitsHeaderCard(s_key.str(), naxes(i),
593  s_comment.str()));
594  }
595  m_header.append(GFitsHeaderCard("PCOUNT", 0,
596  "required keyword; must = 0"));
597  m_header.append(GFitsHeaderCard("GCOUNT", 1,
598  "required keyword; must = 1"));
599 
600  // Return
601  return;
602 }
603 
604 
605 /***********************************************************************//**
606  * @brief Open Image
607  *
608  * @param[in] vptr FITS file void pointer.
609  *
610  * @exception GException::fits_error
611  * FITS error.
612  *
613  * Open FITS image in FITS file. Opening means connecting the FITS file
614  * pointer to the image and reading the image and axes dimensions.
615  ***************************************************************************/
616 void GFitsImage::open_image(void* vptr)
617 {
618  // Move to HDU
620 
621  // Save the FITS file pointer and the HDU number
622  FPTR_COPY(m_fitsfile, vptr);
623  m_hdunum = FPTR(vptr)->HDUposition;
624 
625  // Get the image dimensions
626  int status = 0;
627  status = __ffgidm(FPTR(m_fitsfile), &m_naxis, &status);
628  if (status != 0) {
629  throw GException::fits_error(G_OPEN_IMAGE, status);
630  }
631 
632  // Reset number of image pixels
633  m_num_pixels = 0;
634 
635  // Get the axes dimensions
636  if (m_naxis > 0) {
637 
638  // Allocate memory for axes dimensions
639  if (m_naxes != NULL) delete [] m_naxes;
640  m_naxes = new long[m_naxis];
641 
642  // Get the axes dimensions
643  status = __ffgisz(FPTR(m_fitsfile), m_naxis, m_naxes, &status);
644  if (status != 0) {
645  throw GException::fits_error(G_OPEN_IMAGE, status);
646  }
647 
648  // Calculate number of image pixels
649  m_num_pixels = 1;
650  for (int i = 0; i < m_naxis; ++i) {
651  m_num_pixels *= m_naxes[i];
652  }
653 
654  } // endif: there is an image
655 
656  // Return
657  return;
658 }
659 
660 
661 /***********************************************************************//**
662  * @brief Load FITS image
663  *
664  * @param[in] datatype Datatype of pixels to be saved.
665  * @param[in] pixels Pixel array to be saved.
666  * @param[in] nulval Pointer to pixel nul value.
667  * @param[out] anynul Number of nul values encountered during loading.
668  *
669  * @exception GException::fits_error
670  * FITS error.
671  *
672  * Load image pixels from FITS file.
673  ***************************************************************************/
674 void GFitsImage::load_image(int datatype, const void* pixels,
675  const void* nulval, int* anynul)
676 {
677  // Move to HDU
678  move_to_hdu();
679 
680  // Load the image pixels (if there are some ...)
681  if (m_naxis > 0) {
682  long* fpixel = new long[m_naxis];
683  long* lpixel = new long[m_naxis];
684  long* inc = new long[m_naxis];
685  for (int i = 0; i < m_naxis; ++i) {
686  fpixel[i] = 1;
687  lpixel[i] = m_naxes[i];
688  inc[i] = 1;
689  }
690  int status = 0;
691  status = __ffgsv(FPTR(m_fitsfile), datatype, fpixel, lpixel, inc,
692  (void*)nulval, (void*)pixels, anynul, &status);
693  delete [] fpixel;
694  delete [] lpixel;
695  delete [] inc;
696  if (status != 0) {
697  throw GException::fits_error(G_LOAD_IMAGE, status);
698  }
699  }
700 
701  // Return
702  return;
703 }
704 
705 
706 /***********************************************************************//**
707  * @brief Save FITS image
708  *
709  * @param[in] datatype Datatype of pixels to be saved
710  * @param[in] pixels Pixel array to be saved
711  *
712  * @exception GException::runtime_error
713  * No FITS file has been opened.
714  * @exception GException::fits_error
715  * FITS error.
716  *
717  * Save image pixels into FITS file. In case that the HDU does not exist it
718  * is created. In case that the pixel array is empty no data are saved; all
719  * image pixels will be empty in this case.
720  ***************************************************************************/
721 void GFitsImage::save_image(int datatype, const void* pixels)
722 {
723  // Throw an exception if FITS file is not open
724  if (FPTR(m_fitsfile)->Fptr == NULL) {
725  std::string msg = "FITS file not open. Please open the FITS file "
726  "before saving the image.";
728  }
729 
730  // Move to HDU. We use here an explicit cfitsio moveto function since we
731  // want to recover the error code ...
732  int status = 0;
733  int type = 0;
734  status = __ffmahd(FPTR(m_fitsfile), m_hdunum+1, &type, &status);
735 
736  // If move was successful but HDU type in file differs from HDU type
737  // of object then replace the HDU in the file
738  if (status == 0 && type != exttype()) {
739  status = __ffdhdu(FPTR(m_fitsfile), NULL, &status);
740  if (status != 0) {
741  throw GException::fits_error(G_SAVE_IMAGE, status);
742  }
743  status = __ffiimg(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
744  //status = __ffiimgll(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
745  if (status != 0) {
746  throw GException::fits_error(G_SAVE_IMAGE, status);
747  }
748  }
749 
750  // If HDU does not yet exist in file then create it now
751  if (status == 107) {
752  status = 0;
753  status = __ffcrim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
754  if (status != 0) {
755  throw GException::fits_error(G_SAVE_IMAGE, status);
756  }
757  }
758  else if (status != 0) {
759  throw GException::fits_error(G_SAVE_IMAGE, status);
760  }
761 
762  // If HDU seems to be empty then create it now. This is only needed for the
763  // primary HDU, since __ffmahd gives no error if the primary HDU is empty.
764  // By checking the number of keywords in the HDU we detect an empty HDU ...
765  int num = 0;
766  status = __ffghsp(FPTR(m_fitsfile), &num, NULL, &status);
767  if (status != 0) {
768  throw GException::fits_error(G_SAVE_IMAGE, status);
769  }
770  if (num == 0) {
771  status = __ffcrim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
772  if (status != 0) {
773  throw GException::fits_error(G_SAVE_IMAGE, status);
774  }
775  }
776 
777  // Make sure that the image on disk has the right size by resizing it
778  status = __ffrsim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
779  if (status != 0) {
780  throw GException::fits_error(G_SAVE_IMAGE, status);
781  }
782 
783  // Save the image pixels (if there are some ...)
784  if (m_naxis > 0 && pixels != NULL) {
785  long* fpixel = new long[m_naxis];
786  long* lpixel = new long[m_naxis];
787  for (int i = 0; i < m_naxis; ++i) {
788  fpixel[i] = 1;
789  lpixel[i] = m_naxes[i];
790  }
791  status = __ffpss(FPTR(m_fitsfile), datatype, fpixel, lpixel,
792  (void*)pixels, &status);
793  delete [] fpixel;
794  delete [] lpixel;
795  if (status != 0) {
796  throw GException::fits_error(G_SAVE_IMAGE, status);
797  }
798  }
799 
800  // Return
801  return;
802 }
803 
804 
805 /***********************************************************************//**
806  * @brief Fetch image pixels
807  *
808  * Fetch the image pixels. This function is in general called if pixel
809  * values should be read or written yet no pixel array is allocated. In case
810  * that pixels existed already before they will be deleted before fetching
811  * new ones.
812  * There are two possibilities to fetch the pixels:
813  * (1) In case that a FITS file is attached to the image, the pixel array
814  * will be loaded from the FITS file using the load_image() method.
815  * (2) In case that no FITS file is attached, a new pixel array will be
816  * allocated that is initalised to zero.
817  ***************************************************************************/
819 {
820  // Fetch only if there are pixels in image
821  if (m_num_pixels > 0) {
822 
823  // Allocate and initialise fresh memory
824  alloc_data();
825  init_data();
826 
827  // If a FITS file is attached then load pixels from FITS file.
828  if (FPTR(m_fitsfile)->Fptr != NULL) {
830  }
831 
832  } // endif: there were pixels available
833 
834  // Return
835  return;
836 }
837 
838 
839 /***********************************************************************//**
840  * @brief Return pixel offset
841  *
842  * @param[in] ix Pixel index [0,...,m_num_pixels-1].
843  *
844  * @exception GException::out_of_range
845  * Pixel index is outside valid range.
846  ***************************************************************************/
847 int GFitsImage::offset(const int& ix) const
848 {
849  // Check if axis is within the range
850  #if defined(G_RANGE_CHECK)
851  if (ix < 0 || ix >= m_num_pixels) {
852  throw GException::out_of_range(G_OFFSET_1D, "Pixel index", ix, m_num_pixels);
853  }
854  #endif
855 
856  // Return index
857  return ix;
858 }
859 
860 
861 /***********************************************************************//**
862  * @brief Return 2D pixel offset
863  *
864  * @param[in] ix Pixel index in first dimension (starting from 0).
865  * @param[in] iy Pixel index in second dimension (starting from 0).
866  *
867  * @exception GException::invalid_argument
868  * Pixel array has less than 2 dimensions.
869  * @exception GException::out_of_range
870  * Image axis not valid.
871  *
872  * Computes of offset in the pixel array of a 2D coordinate. This method is
873  * only applicable to pixels arrays that have at least 2 dimenions.
874  ***************************************************************************/
875 int GFitsImage::offset(const int& ix, const int& iy) const
876 {
877  // Operator is only valid for 2D images
878  if (m_naxis < 2) {
879  std::string msg = "2D pixel access operator used for image with "+
880  gammalib::str(m_naxis)+" dimensions. Please use "
881  "the correct pixel access operator.";
883  }
884 
885  // Check if axis is within the range
886  #if defined(G_RANGE_CHECK)
887  if (ix < 0 || ix >= m_naxes[0]) {
889  "Pixel index for first dimension",
890  ix, m_naxes[0]);
891  }
892  if (iy < 0 || iy >= m_naxes[1]) {
894  "Pixel index for second dimension",
895  iy, m_naxes[1]);
896  }
897  #endif
898 
899  // Return offset
900  return (ix + iy * m_naxes[0]);
901 }
902 
903 
904 /***********************************************************************//**
905  * @brief Return 3D pixel offset
906  *
907  * @param[in] ix Pixel index in first dimension (starting from 0).
908  * @param[in] iy Pixel index in second dimension (starting from 0).
909  * @param[in] iz Pixel index in third dimension (starting from 0).
910  *
911  * @exception GException::invalid_argument
912  * Pixel array has less than 3 dimensions.
913  * @exception GException::out_of_range
914  * Image axis not valid.
915  *
916  * Computes of offset in the pixel array of a 3D coordinate. This method is
917  * only applicable to pixels arrays that have at least 3 dimenions.
918  ***************************************************************************/
919 int GFitsImage::offset(const int& ix, const int& iy, const int& iz) const
920 {
921  // Operator is only valid for 3D images
922  if (m_naxis < 3) {
923  std::string msg = "3D pixel access operator used for image with "+
924  gammalib::str(m_naxis)+" dimensions. Please use "
925  "the correct pixel access operator.";
927  }
928 
929  // Check if axis is within the range
930  #if defined(G_RANGE_CHECK)
931  if (ix < 0 || ix >= m_naxes[0]) {
933  "Pixel index for first dimension",
934  ix, m_naxes[0]);
935  }
936  if (iy < 0 || iy >= m_naxes[1]) {
938  "Pixel index for second dimension",
939  iy, m_naxes[1]);
940  }
941  if (iz < 0 || iz >= m_naxes[2]) {
943  "Pixel index for third dimension",
944  iz, m_naxes[2]);
945  }
946  #endif
947 
948  // Return offset
949  return (ix + m_naxes[0] * (iy + iz * m_naxes[1]));
950 }
951 
952 
953 /***********************************************************************//**
954  * @brief Return 4D pixel offset
955  *
956  * @param[in] ix Pixel index in first dimension (starting from 0).
957  * @param[in] iy Pixel index in second dimension (starting from 0).
958  * @param[in] iz Pixel index in third dimension (starting from 0).
959  * @param[in] it Pixel index in forth dimension (starting from 0).
960  *
961  * @exception GException::invalid_argument
962  * Pixel array has less than 4 dimensions.
963  * @exception GException::out_of_range
964  * Image axis not valid.
965  *
966  * Computes of offset in the pixel array of a 4D coordinate. This method is
967  * only applicable to pixels arrays that have at least 4 dimenions.
968  ***************************************************************************/
969 int GFitsImage::offset(const int& ix, const int& iy, const int& iz,
970  const int& it) const
971 {
972  // Operator is only valid for 4D images
973  if (m_naxis < 4) {
974  std::string msg = "4D pixel access operator used for image with "+
975  gammalib::str(m_naxis)+" dimensions. Please use "
976  "the correct pixel access operator.";
978  }
979 
980  // Check if axis is within the range
981  #if defined(G_RANGE_CHECK)
982  if (ix < 0 || ix >= m_naxes[0]) {
984  "Pixel index for first dimension",
985  ix, m_naxes[0]);
986  }
987  if (iy < 0 || iy >= m_naxes[1]) {
989  "Pixel index for second dimension",
990  iy, m_naxes[1]);
991  }
992  if (iz < 0 || iz >= m_naxes[2]) {
994  "Pixel index for third dimension",
995  iz, m_naxes[2]);
996  }
997  if (it < 0 || it >= m_naxes[3]) {
999  "Pixel index for third dimension",
1000  it, m_naxes[3]);
1001  }
1002  #endif
1003 
1004  // Return offset
1005  return (ix + m_naxes[0] * (iy + m_naxes[1] * (iz + it * m_naxes[2])));
1006 }
const int & bitpix(void) const
Return number of Bits per pixel (negative=floating point)
Definition: GFitsImage.hpp:146
#define __ffghsp(A, B, C, D)
Abstract FITS image base class.
Definition: GFitsImage.hpp:43
#define __ffdhdu(A, B, C)
int offset(const int &ix) const
Return pixel offset.
Definition: GFitsImage.cpp:847
const int & naxis(void) const
Return dimension of image.
Definition: GFitsImage.hpp:156
#define G_SAVE_IMAGE
Definition: GFitsImage.cpp:41
#define FPTR(A)
void open_image(void *vptr)
Open Image.
Definition: GFitsImage.cpp:616
std::string print_hdu(const GChatter &chatter=NORMAL) const
Print basic HDU information.
Definition: GFitsHDU.cpp:373
#define __ffpss(A, B, C, D, E, F)
Abstract FITS extension base class.
Definition: GFitsHDU.hpp:51
void data_close(void)
Close FITS image.
Definition: GFitsImage.cpp:542
void move_to_hdu(void)
Move FITS file pointer to HDU.
Definition: GFitsHDU.cpp:222
void data_open(void *vptr)
Open FITS image.
Definition: GFitsImage.cpp:507
virtual void * ptr_nulval(void)=0
virtual void init_data(void)=0
void * m_fitsfile
FITS file pointer pointing on actual HDU.
Definition: GFitsHDU.hpp:133
#define __ffiimg(A, B, C, D, E)
Gammalib tools definition.
#define __ffcrim(A, B, C, D, E)
FITS file class interface definition.
virtual void alloc_nulval(const void *value)=0
virtual void alloc_data(void)=0
Abstract FITS image base class definition.
GFitsHDU & operator=(const GFitsHDU &hdu)
Assignment operator.
Definition: GFitsHDU.cpp:124
int m_num_pixels
Number of image pixels.
Definition: GFitsImage.hpp:115
void save_image(int datatype, const void *pixels)
Save FITS image.
Definition: GFitsImage.cpp:721
void data_save(void)
Save FITS image.
Definition: GFitsImage.cpp:522
#define G_OPEN_IMAGE
Definition: GFitsImage.cpp:39
Implements FITS header card interface.
#define G_NAXES
Definition: GFitsImage.cpp:38
#define __ffrsim(A, B, C, D, E)
void init_image_header(void)
Initialise image header.
Definition: GFitsImage.cpp:578
#define G_OFFSET_4D
Definition: GFitsImage.cpp:45
long * m_naxes
Number of pixels in each dimension.
Definition: GFitsImage.hpp:114
#define __ffmahd(A, B, C, D)
GFitsHeaderCard & append(const GFitsHeaderCard &card)
Append or update header card.
virtual void * pixels(void)=0
CFITSIO interface header.
virtual int type(void) const =0
void data_connect(void *vptr)
Connect FITS image.
Definition: GFitsImage.cpp:564
const void * nulval(void) const
Return nul value.
Definition: GFitsImage.hpp:176
GFitsImage(void)
Void constructor.
Definition: GFitsImage.cpp:66
#define G_OFFSET_3D
Definition: GFitsImage.cpp:44
#define __ffgsv(A, B, C, D, E, F, G, H, I)
std::string print(const GChatter &chatter=NORMAL) const
Print FITS header information.
GChatter
Definition: GTypemaps.hpp:33
#define __ffgisz(A, B, C, D)
int m_anynul
Number of NULLs encountered.
Definition: GFitsImage.hpp:116
void fetch_data(void)
Fetch image pixels.
Definition: GFitsImage.cpp:818
GFitsHeader m_header
HDU header.
Definition: GFitsHDU.hpp:136
void init_members(void)
Initialise class members.
Definition: GFitsImage.cpp:442
#define FPTR_COPY(A, B)
int m_naxis
Image dimension.
Definition: GFitsImage.hpp:113
#define G_OFFSET_2D
Definition: GFitsImage.cpp:43
int naxes(const int &axis) const
Return dimension of an image axis.
Definition: GFitsImage.cpp:344
std::string print(const GChatter &chatter=NORMAL) const
Print column information.
Definition: GFitsImage.cpp:395
#define G_LOAD_IMAGE
Definition: GFitsImage.cpp:40
std::string typecode(int type) const
Return typecode as string.
Definition: GFitsHDU.cpp:398
virtual ~GFitsImage(void)
Destructor.
Definition: GFitsImage.cpp:284
const int & npix(void) const
Return size of pixel array.
Definition: GFitsImage.hpp:136
#define G_OFFSET_1D
Definition: GFitsImage.cpp:42
GChatter reduce(const GChatter &chatter)
Reduce chattiness by one level.
Definition: GTypemaps.hpp:65
void copy_members(const GFitsImage &image)
Copy class members.
Definition: GFitsImage.cpp:461
int m_bitpix
Number of Bits/pixel.
Definition: GFitsImage.hpp:112
#define __ffgidm(A, B, C)
Exception handler interface definition.
void load_image(int datatype, const void *pixels, const void *nulval, int *anynul)
Load FITS image.
Definition: GFitsImage.cpp:674
GFitsImage & operator=(const GFitsImage &image)
Assignment operator.
Definition: GFitsImage.cpp:306
int fits_move_to_hdu(const std::string &caller, void *vptr, const int &hdunum=0)
Move to FITS extension.
Definition: GFits.cpp:1774
virtual void * ptr_data(void)=0
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
HDUType exttype(void) const
Return extension type.
Definition: GFitsImage.hpp:126
int m_hdunum
HDU number (starting from 0)
Definition: GFitsHDU.hpp:134
void free_members(void)
Delete class members.
Definition: GFitsImage.cpp:486
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489