GammaLib 2.2.0.dev
Loading...
Searching...
No Matches
GFitsImage.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GFitsImage.cpp - Abstract FITS image base class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2008-2026 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
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 ***************************************************************************/
85GFitsImage::GFitsImage(const int& bitpix, const int& nx) : GFitsHDU()
86{
87 // Initialise class members for clean destruction
89
90 // Store number of Bits per pixel
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 ***************************************************************************/
119GFitsImage::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
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 ***************************************************************************/
156GFitsImage::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
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 ***************************************************************************/
195GFitsImage::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
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 ***************************************************************************/
233GFitsImage::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
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 ***************************************************************************/
344int 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 ***************************************************************************/
372void 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 ***************************************************************************/
395std::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 result.append("\n"+gammalib::parformat("Pixel scaling (BSCALE)"));
421 result.append(gammalib::str(m_bscale));
422 result.append("\n"+gammalib::parformat("Pixel offset (BZERO)"));
423 result.append(gammalib::str(m_bzero));
424
425 // NORMAL: Append header information
426 if (chatter >= NORMAL) {
427 result.append(+"\n"+m_header.print(gammalib::reduce(chatter)));
428 }
429
430 } // endif: chatter was not silent
431
432 // Return result
433 return result;
434}
435
436
437/*==========================================================================
438 = =
439 = Protected methods =
440 = =
441 ==========================================================================*/
442
443/***********************************************************************//**
444 * @brief Initialise class members
445 ***************************************************************************/
447{
448 // Initialise members
449 m_bitpix = 8;
450 m_naxis = 0;
451 m_naxes = NULL;
452 m_num_pixels = 0;
453 m_anynul = 0;
454 m_bscale = 1.0;
455 m_bzero = 0.0;
456
457 // Return
458 return;
459}
460
461
462/***********************************************************************//**
463 * @brief Copy class members
464 *
465 * @param[in] image FITS image to copy
466 ***************************************************************************/
468{
469 // Copy attributes
470 m_bitpix = image.m_bitpix;
471 m_naxis = image.m_naxis;
473 m_anynul = image.m_anynul;
474 m_bscale = image.m_bscale;
475 m_bzero = image.m_bzero;
476
477 // Copy axes
478 m_naxes = NULL;
479 if (image.m_naxes != NULL && m_naxis > 0) {
480 m_naxes = new long[m_naxis];
481 for (int i = 0; i < m_naxis; ++i) {
482 m_naxes[i] = image.m_naxes[i];
483 }
484 }
485
486 // Return
487 return;
488}
489
490
491/***********************************************************************//**
492 * @brief Delete class members
493 ***************************************************************************/
495{
496 // Free memory
497 if (m_naxes != NULL) delete [] m_naxes;
498
499 // Mark memory as free
500 m_naxes = NULL;
501
502 // Return
503 return;
504}
505
506
507/***********************************************************************//**
508 * @brief Open FITS image
509 *
510 * @param[in] vptr FITS file pointer
511 *
512 * Open FITS image in FITS file. Opening means connecting the FITS file
513 * pointer to the image and reading the image and axes dimensions.
514 ***************************************************************************/
515void GFitsImage::data_open(void* vptr)
516{
517 // Open image
518 open_image(vptr);
519
520 // Return
521 return;
522}
523
524
525/***********************************************************************//**
526 * @brief Save FITS image
527 *
528 * Saves the image into the FITS file.
529 ***************************************************************************/
531{
532 // Save image
533 save_image(type(), pixels());
534
535 // Return
536 return;
537}
538
539
540/***********************************************************************//**
541 * @brief Close FITS image
542 *
543 * Closing a FITS image resets the object into its initial state. Closing
544 * does NOT save the image into the FITS file. Use the save method for this
545 * purpose.
546 *
547 * @todo Not sure that this is efficient at this level since the pixel array
548 * will not be deallocated!!!
549 ***************************************************************************/
551{
552 // Free members
553 free_members();
554
555 // Initialise members
556 init_members();
557
558 // Return
559 return;
560}
561
562
563/***********************************************************************//**
564 * @brief Connect FITS image
565 *
566 * @param[in] vptr FITS file pointer
567 *
568 * Connects a FITS file pointer to an image. This method actually does
569 * nothing since any GFitsImage can directly access the FITS file pointer
570 * that is stored in the GFitsHDU base class.
571 ***************************************************************************/
573{
574 // Return
575 return;
576}
577
578
579/***********************************************************************//**
580 * @brief Initialise image header
581 *
582 * Initialises the image header by setting the default header cards. This
583 * method requires the members m_bitpix, m_naxis, and m_naxes to be set
584 * previously.
585 ***************************************************************************/
587{
588 // Set image header keywords
589 m_header.append(GFitsHeaderCard("XTENSION", "IMAGE ",
590 "IMAGE extension"));
592 "number of bits per data pixel"));
594 "number of data axes"));
595 for (int i = 0; i < naxis(); ++i) {
596 std::ostringstream s_key;
597 std::ostringstream s_comment;
598 s_key << "NAXIS" << (i+1);
599 s_comment << "length of data axis " << (i+1);
600 m_header.append(GFitsHeaderCard(s_key.str(), naxes(i),
601 s_comment.str()));
602 }
603 m_header.append(GFitsHeaderCard("PCOUNT", 0,
604 "required keyword; must = 0"));
605 m_header.append(GFitsHeaderCard("GCOUNT", 1,
606 "required keyword; must = 1"));
607
608 // Return
609 return;
610}
611
612
613/***********************************************************************//**
614 * @brief Open Image
615 *
616 * @param[in] vptr FITS file void pointer.
617 *
618 * @exception GException::fits_error
619 * FITS error.
620 *
621 * Open FITS image in FITS file. Opening means connecting the FITS file
622 * pointer to the image and reading the image and axes dimensions.
623 ***************************************************************************/
625{
626 // Move to HDU
628
629 // Save the FITS file pointer and the HDU number
630 FPTR_COPY(m_fitsfile, vptr);
631 m_hdunum = FPTR(vptr)->HDUposition;
632
633 // Get the image dimensions
634 int status = 0;
635 status = __ffgidm(FPTR(m_fitsfile), &m_naxis, &status);
636 if (status != 0) {
638 }
639
640 // Reset number of image pixels
641 m_num_pixels = 0;
642
643 // Get the axes dimensions
644 if (m_naxis > 0) {
645
646 // Allocate memory for axes dimensions
647 if (m_naxes != NULL) delete [] m_naxes;
648 m_naxes = new long[m_naxis];
649
650 // Get the axes dimensions
651 status = __ffgisz(FPTR(m_fitsfile), m_naxis, m_naxes, &status);
652 if (status != 0) {
654 }
655
656 // Calculate number of image pixels
657 m_num_pixels = 1;
658 for (int i = 0; i < m_naxis; ++i) {
659 m_num_pixels *= m_naxes[i];
660 }
661
662 } // endif: there is an image
663
664 // Return
665 return;
666}
667
668
669/***********************************************************************//**
670 * @brief Load FITS image
671 *
672 * @param[in] datatype Datatype of pixels to be saved.
673 * @param[in] pixels Pixel array to be saved.
674 * @param[in] nulval Pointer to pixel nul value.
675 * @param[out] anynul Number of nul values encountered during loading.
676 *
677 * @exception GException::fits_error
678 * FITS error.
679 *
680 * Load image pixels from FITS file. If FITS pixels values are scaled using
681 * BSCALE and BZERO, the scaling is not applied and the raw pixel values are
682 * stored in the image. An exception to this are unsigned integer images
683 * that need to be scale to fit into unsigned datatypes.
684 ***************************************************************************/
685void GFitsImage::load_image(int datatype,
686 const void* pixels,
687 const void* nulval,
688 int* anynul)
689{
690 // Move to HDU
691 move_to_hdu();
692
693 // Avoid scaling of values when reading the image, except for unsigned
694 // images that need to be scaled to avoid overflow errors. The image
695 // pixels are thus raw (unscaled) pixel values.
696 if ((this->bitpix() != 10) && (this->bitpix() != 20) && (this->bitpix() != 40)) {
697
698 // Switch off cfitsio internal scaling
699 int status = 0;
700 status = __ffpscl(FPTR(m_fitsfile), 1.0, 0.0, &status);
701 if (status != 0) {
703 }
704
705 // Read BSCALE and BZERO keywords if they exist
706 if (has_card("BZERO") && has_card("BSCALE")) {
707 m_bscale = this->real("BSCALE");
708 m_bzero = this->real("BZERO");
709 }
710
711 } // endif: image was not an unsigned integer image
712
713 // Load the image pixels (if there are some ...)
714 if (m_naxis > 0) {
715 long* fpixel = new long[m_naxis];
716 long* lpixel = new long[m_naxis];
717 long* inc = new long[m_naxis];
718 for (int i = 0; i < m_naxis; ++i) {
719 fpixel[i] = 1;
720 lpixel[i] = m_naxes[i];
721 inc[i] = 1;
722 }
723 int status = 0;
724 status = __ffgsv(FPTR(m_fitsfile), datatype, fpixel, lpixel, inc,
725 (void*)nulval, (void*)pixels, anynul, &status);
726 delete [] fpixel;
727 delete [] lpixel;
728 delete [] inc;
729 if (status != 0) {
731 }
732 }
733
734 // Return
735 return;
736}
737
738
739/***********************************************************************//**
740 * @brief Save FITS image
741 *
742 * @param[in] datatype Datatype of pixels to be saved
743 * @param[in] pixels Pixel array to be saved
744 *
745 * @exception GException::runtime_error
746 * No FITS file has been opened.
747 * @exception GException::fits_error
748 * FITS error.
749 *
750 * Save image pixels into FITS file. In case that the HDU does not exist it
751 * is created. In case that the pixel array is empty no data are saved; all
752 * image pixels will be empty in this case.
753 ***************************************************************************/
754void GFitsImage::save_image(int datatype, const void* pixels)
755{
756 // Throw an exception if FITS file is not open
757 if (FPTR(m_fitsfile)->Fptr == NULL) {
758 std::string msg = "FITS file not open. Please open the FITS file "
759 "before saving the image.";
761 }
762
763 // Move to HDU. We use here an explicit cfitsio moveto function since we
764 // want to recover the error code ...
765 int status = 0;
766 int type = 0;
767 status = __ffmahd(FPTR(m_fitsfile), m_hdunum+1, &type, &status);
768
769 // If move was successful but HDU type in file differs from HDU type
770 // of object then replace the HDU in the file
771 if (status == 0 && type != exttype()) {
772 status = __ffdhdu(FPTR(m_fitsfile), NULL, &status);
773 if (status != 0) {
775 }
776 status = __ffiimg(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
777 //status = __ffiimgll(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
778 if (status != 0) {
780 }
781 }
782
783 // If HDU does not yet exist in file then create it now
784 if (status == 107) {
785 status = 0;
786 status = __ffcrim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
787 if (status != 0) {
789 }
790 }
791 else if (status != 0) {
793 }
794
795 // If HDU seems to be empty then create it now. This is only needed for the
796 // primary HDU, since __ffmahd gives no error if the primary HDU is empty.
797 // By checking the number of keywords in the HDU we detect an empty HDU ...
798 int num = 0;
799 status = __ffghsp(FPTR(m_fitsfile), &num, NULL, &status);
800 if (status != 0) {
802 }
803 if (num == 0) {
804 status = __ffcrim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
805 if (status != 0) {
807 }
808 }
809
810 // Make sure that the image on disk has the right size by resizing it
811 status = __ffrsim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
812 if (status != 0) {
814 }
815
816 // Save the image pixels (if there are some ...)
817 if (m_naxis > 0 && pixels != NULL) {
818 long* fpixel = new long[m_naxis];
819 long* lpixel = new long[m_naxis];
820 for (int i = 0; i < m_naxis; ++i) {
821 fpixel[i] = 1;
822 lpixel[i] = m_naxes[i];
823 }
824 status = __ffpss(FPTR(m_fitsfile), datatype, fpixel, lpixel,
825 (void*)pixels, &status);
826 delete [] fpixel;
827 delete [] lpixel;
828 if (status != 0) {
830 }
831 }
832
833 // Return
834 return;
835}
836
837
838/***********************************************************************//**
839 * @brief Fetch image pixels
840 *
841 * Fetch the image pixels. This function is in general called if pixel
842 * values should be read or written yet no pixel array is allocated. In case
843 * that pixels existed already before they will be deleted before fetching
844 * new ones.
845 * There are two possibilities to fetch the pixels:
846 * (1) In case that a FITS file is attached to the image, the pixel array
847 * will be loaded from the FITS file using the load_image() method.
848 * (2) In case that no FITS file is attached, a new pixel array will be
849 * allocated that is initalised to zero.
850 ***************************************************************************/
852{
853 // Fetch only if there are pixels in image
854 if (m_num_pixels > 0) {
855
856 // Allocate and initialise fresh memory
857 alloc_data();
858 init_data();
859
860 // If a FITS file is attached then load pixels from FITS file.
861 if (FPTR(m_fitsfile)->Fptr != NULL) {
863 }
864
865 } // endif: there were pixels available
866
867 // Return
868 return;
869}
870
871
872/***********************************************************************//**
873 * @brief Return pixel offset
874 *
875 * @param[in] ix Pixel index [0,...,m_num_pixels-1].
876 *
877 * @exception GException::out_of_range
878 * Pixel index is outside valid range.
879 ***************************************************************************/
880int GFitsImage::offset(const int& ix) const
881{
882 // Check if axis is within the range
883 #if defined(G_RANGE_CHECK)
884 if (ix < 0 || ix >= m_num_pixels) {
885 throw GException::out_of_range(G_OFFSET_1D, "Pixel index", ix, m_num_pixels);
886 }
887 #endif
888
889 // Return index
890 return ix;
891}
892
893
894/***********************************************************************//**
895 * @brief Return 2D pixel offset
896 *
897 * @param[in] ix Pixel index in first dimension (starting from 0).
898 * @param[in] iy Pixel index in second dimension (starting from 0).
899 *
900 * @exception GException::invalid_argument
901 * Pixel array has less than 2 dimensions.
902 * @exception GException::out_of_range
903 * Image axis not valid.
904 *
905 * Computes of offset in the pixel array of a 2D coordinate. This method is
906 * only applicable to pixels arrays that have at least 2 dimenions.
907 ***************************************************************************/
908int GFitsImage::offset(const int& ix, const int& iy) const
909{
910 // Operator is only valid for 2D images
911 if (m_naxis < 2) {
912 std::string msg = "2D pixel access operator used for image with "+
913 gammalib::str(m_naxis)+" dimensions. Please use "
914 "the correct pixel access operator.";
916 }
917
918 // Check if axis is within the range
919 #if defined(G_RANGE_CHECK)
920 if (ix < 0 || ix >= m_naxes[0]) {
922 "Pixel index for first dimension",
923 ix, m_naxes[0]);
924 }
925 if (iy < 0 || iy >= m_naxes[1]) {
927 "Pixel index for second dimension",
928 iy, m_naxes[1]);
929 }
930 #endif
931
932 // Return offset
933 return (ix + iy * m_naxes[0]);
934}
935
936
937/***********************************************************************//**
938 * @brief Return 3D pixel offset
939 *
940 * @param[in] ix Pixel index in first dimension (starting from 0).
941 * @param[in] iy Pixel index in second dimension (starting from 0).
942 * @param[in] iz Pixel index in third dimension (starting from 0).
943 *
944 * @exception GException::invalid_argument
945 * Pixel array has less than 3 dimensions.
946 * @exception GException::out_of_range
947 * Image axis not valid.
948 *
949 * Computes of offset in the pixel array of a 3D coordinate. This method is
950 * only applicable to pixels arrays that have at least 3 dimenions.
951 ***************************************************************************/
952int GFitsImage::offset(const int& ix, const int& iy, const int& iz) const
953{
954 // Operator is only valid for 3D images
955 if (m_naxis < 3) {
956 std::string msg = "3D pixel access operator used for image with "+
957 gammalib::str(m_naxis)+" dimensions. Please use "
958 "the correct pixel access operator.";
960 }
961
962 // Check if axis is within the range
963 #if defined(G_RANGE_CHECK)
964 if (ix < 0 || ix >= m_naxes[0]) {
966 "Pixel index for first dimension",
967 ix, m_naxes[0]);
968 }
969 if (iy < 0 || iy >= m_naxes[1]) {
971 "Pixel index for second dimension",
972 iy, m_naxes[1]);
973 }
974 if (iz < 0 || iz >= m_naxes[2]) {
976 "Pixel index for third dimension",
977 iz, m_naxes[2]);
978 }
979 #endif
980
981 // Return offset
982 return (ix + m_naxes[0] * (iy + iz * m_naxes[1]));
983}
984
985
986/***********************************************************************//**
987 * @brief Return 4D pixel offset
988 *
989 * @param[in] ix Pixel index in first dimension (starting from 0).
990 * @param[in] iy Pixel index in second dimension (starting from 0).
991 * @param[in] iz Pixel index in third dimension (starting from 0).
992 * @param[in] it Pixel index in forth dimension (starting from 0).
993 *
994 * @exception GException::invalid_argument
995 * Pixel array has less than 4 dimensions.
996 * @exception GException::out_of_range
997 * Image axis not valid.
998 *
999 * Computes of offset in the pixel array of a 4D coordinate. This method is
1000 * only applicable to pixels arrays that have at least 4 dimenions.
1001 ***************************************************************************/
1002int GFitsImage::offset(const int& ix, const int& iy, const int& iz,
1003 const int& it) const
1004{
1005 // Operator is only valid for 4D images
1006 if (m_naxis < 4) {
1007 std::string msg = "4D pixel access operator used for image with "+
1008 gammalib::str(m_naxis)+" dimensions. Please use "
1009 "the correct pixel access operator.";
1011 }
1012
1013 // Check if axis is within the range
1014 #if defined(G_RANGE_CHECK)
1015 if (ix < 0 || ix >= m_naxes[0]) {
1017 "Pixel index for first dimension",
1018 ix, m_naxes[0]);
1019 }
1020 if (iy < 0 || iy >= m_naxes[1]) {
1022 "Pixel index for second dimension",
1023 iy, m_naxes[1]);
1024 }
1025 if (iz < 0 || iz >= m_naxes[2]) {
1027 "Pixel index for third dimension",
1028 iz, m_naxes[2]);
1029 }
1030 if (it < 0 || it >= m_naxes[3]) {
1032 "Pixel index for third dimension",
1033 it, m_naxes[3]);
1034 }
1035 #endif
1036
1037 // Return offset
1038 return (ix + m_naxes[0] * (iy + m_naxes[1] * (iz + it * m_naxes[2])));
1039}
Exception handler interface definition.
CFITSIO interface header.
#define __ffpscl(A, B, C, D)
#define __ffpss(A, B, C, D, E, F)
#define FPTR(A)
#define __ffrsim(A, B, C, D, E)
#define __ffiimg(A, B, C, D, E)
#define __ffgisz(A, B, C, D)
#define __ffghsp(A, B, C, D)
#define __ffmahd(A, B, C, D)
#define FPTR_COPY(A, B)
#define __ffgidm(A, B, C)
#define __ffdhdu(A, B, C)
#define __ffcrim(A, B, C, D, E)
#define __ffgsv(A, B, C, D, E, F, G, H, I)
#define G_LOAD_IMAGE
#define G_OFFSET_3D
#define G_SAVE_IMAGE
#define G_OFFSET_4D
#define G_NAXES
#define G_OFFSET_1D
#define G_OFFSET_2D
#define G_OPEN_IMAGE
Abstract FITS image base class definition.
FITS file class interface definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ NORMAL
Definition GTypemaps.hpp:36
@ SILENT
Definition GTypemaps.hpp:34
Abstract FITS extension base class.
Definition GFitsHDU.hpp:51
bool has_card(const int &cardno) const
Check existence of header card.
Definition GFitsHDU.hpp:233
GFitsHeader m_header
HDU header.
Definition GFitsHDU.hpp:136
GFitsHDU & operator=(const GFitsHDU &hdu)
Assignment operator.
Definition GFitsHDU.cpp:124
void * m_fitsfile
FITS file pointer pointing on actual HDU.
Definition GFitsHDU.hpp:133
int m_hdunum
HDU number (starting from 0)
Definition GFitsHDU.hpp:134
void move_to_hdu(void)
Move FITS file pointer to HDU.
Definition GFitsHDU.cpp:222
double real(const std::string &keyname) const
Return card value as double precision.
Definition GFitsHDU.hpp:423
std::string typecode(int type) const
Return typecode as string.
Definition GFitsHDU.cpp:398
std::string print_hdu(const GChatter &chatter=NORMAL) const
Print basic HDU information.
Definition GFitsHDU.cpp:373
Implements FITS header card interface.
GFitsHeaderCard & append(const GFitsHeaderCard &card)
Append or update header card.
std::string print(const GChatter &chatter=NORMAL) const
Print FITS header information.
Abstract FITS image base class.
void open_image(void *vptr)
Open Image.
virtual void init_data(void)=0
virtual void * ptr_nulval(void)=0
int m_naxis
Image dimension.
double m_bscale
Scaling for integer pixels.
int naxes(const int &axis) const
Return dimension of an image axis.
const int & bitpix(void) const
Return number of Bits per pixel (negative=floating point)
int offset(const int &ix) const
Return pixel offset.
void free_members(void)
Delete class members.
const int & npix(void) const
Return size of pixel array.
void load_image(int datatype, const void *pixels, const void *nulval, int *anynul)
Load FITS image.
void fetch_data(void)
Fetch image pixels.
long * m_naxes
Number of pixels in each dimension.
const int & naxis(void) const
Return dimension of image.
double m_bzero
Offset for integer pixels.
HDUType exttype(void) const
Return extension type.
virtual void alloc_nulval(const void *value)=0
void data_save(void)
Save FITS image.
void save_image(int datatype, const void *pixels)
Save FITS image.
int m_bitpix
Number of Bits/pixel.
void copy_members(const GFitsImage &image)
Copy class members.
int m_num_pixels
Number of image pixels.
void init_image_header(void)
Initialise image header.
std::string print(const GChatter &chatter=NORMAL) const
Print column information.
void data_open(void *vptr)
Open FITS image.
GFitsImage & operator=(const GFitsImage &image)
Assignment operator.
const int & anynul(void) const
Return number of nul values encountered during loading.
virtual void * ptr_data(void)=0
void data_connect(void *vptr)
Connect FITS image.
GFitsImage(void)
Void constructor.
virtual void alloc_data(void)=0
const void * nulval(void) const
Return nul value.
virtual void * pixels(void)=0
int m_anynul
Number of NULLs encountered.
virtual int type(void) const =0
void data_close(void)
Close FITS image.
virtual ~GFitsImage(void)
Destructor.
void init_members(void)
Initialise class members.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1136
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:508
int fits_move_to_hdu(const std::string &caller, void *vptr, const int &hdunum=0)
Move to FITS extension.
Definition GFits.cpp:1774
GChatter reduce(const GChatter &chatter)
Reduce chattiness by one level.
Definition GTypemaps.hpp:65