GammaLib 2.0.0
Loading...
Searching...
No Matches
GFitsTableCol.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GFitsTableCol.cpp - FITS table column abstract 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 GFitsTableCol.cpp
23 * @brief Abstract FITS table column class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <cstdlib>
32#include "GException.hpp"
33#include "GTools.hpp"
34#include "GFitsCfitsio.hpp"
35#include "GFitsTableCol.hpp"
36
37/* __ Method name definitions ____________________________________________ */
38#define G_ELEMENTS1 "GFitsTableCol::elements(int&, int&)"
39#define G_ELEMENTS2 "GFitsTableCol::elements(int&)"
40#define G_LOAD_COLUMN_FIXED "GFitsTableCol::load_column_fixed()"
41#define G_LOAD_COLUMN_VARIABLE "GFitsTableCol::load_column_variable()"
42#define G_SAVE_COLUMN_FIXED "GFitsTableCol::save_column_fixed()"
43#define G_SAVE_COLUMN_VARIABLE "GFitsTableCol::save_column_variable()"
44#define G_OFFSET "GFitsTableCol::offset(int&, int&)"
45
46/* __ Macros _____________________________________________________________ */
47
48/* __ Coding definitions _________________________________________________ */
49//#define G_PRINT_CONTENT //!< Print column content
50
51/* __ Debug definitions __________________________________________________ */
52//#define G_CALL_GRAPH //!< Dump call graph in console
53
54
55/*==========================================================================
56 = =
57 = Constructors/destructors =
58 = =
59 ==========================================================================*/
60
61/***********************************************************************//**
62 * @brief Void constructor
63 ***************************************************************************/
65{
66 // Initialise class members for clean destruction
68
69 // Return
70 return;
71}
72
73
74/***********************************************************************//**
75 * @brief Column constructor
76 *
77 * @param[in] name Name of column.
78 * @param[in] nrows Number of rows in column.
79 * @param[in] number Number of elements in column (negative for variable-length).
80 * @param[in] width Width of one column element.
81 *
82 * Construct column instance from @p name, @p nrows, @p number of elements
83 * and @p width (or size) of one element. If @p number is negative, a
84 * variable-length column will be allocated. The repeat value, which is
85 * required for binary tables, is computed internally by multiplying the
86 * @p number by the @p width.
87 ***************************************************************************/
88GFitsTableCol::GFitsTableCol(const std::string& name,
89 const int& nrows,
90 const int& number,
91 const int& width)
92{
93 // Initialise class members for clean destruction
95
96 // Store attributes
97 if (number >= 0) { // fixed-length column
98 m_name = name;
101 m_width = width;
102 m_variable = false;
103 }
104 else { // variable-length column
105 m_name = name;
106 m_length = nrows;
107 m_number = 1;
108 m_width = width;
109 m_variable = true;
110 m_rowstart.assign(nrows+1, 0);
111 }
112
113 // Calculate repeat value (only used for binary table!)
115
116 // Return
117 return;
118}
119
120
121/***********************************************************************//**
122 * @brief Copy constructor
123 *
124 * @param[in] column Column.
125 ***************************************************************************/
127{
128 // Initialise class members for clean destruction
129 init_members();
130
131 // Copy members
132 copy_members(column);
133
134 // Return
135 return;
136}
137
138
139/***********************************************************************//**
140 * @brief Destructor
141 ***************************************************************************/
143{
144 // Free members
145 free_members();
146
147 // Return
148 return;
149}
150
151
152/*==========================================================================
153 = =
154 = Operators =
155 = =
156 ==========================================================================*/
157
158/***********************************************************************//**
159 * @brief Assignment operator
160 *
161 * @param[in] column Column.
162 * @return Column.
163 ***************************************************************************/
165{
166 // Execute only if object is not identical
167 if (this != &column) {
168
169 // Free members
170 free_members();
171
172 // Initialise private members for clean destruction
173 init_members();
174
175 // Copy members
176 copy_members(column);
177
178 } // endif: object was not identical
179
180 // Return this object
181 return *this;
182}
183
184
185/*==========================================================================
186 = =
187 = Public methods =
188 = =
189 ==========================================================================*/
190
191/***********************************************************************//**
192 * @brief Set number of column elements for specific row
193 *
194 * @param[in] row Row number.
195 * @param[in] elements Number of elements in @p row.
196 *
197 * @exception GException::out_of_range
198 * Invalid row index specified.
199 * @exception GException::invalid_argument
200 * Invalid number of elements specified.
201 *
202 * Sets the number of elements in column for a specific @p row.
203 ***************************************************************************/
204void GFitsTableCol::elements(const int& row, const int& elements)
205{
206 // Check row value
207 if (row < 0 || row >= nrows()) {
208 throw GException::out_of_range(G_ELEMENTS1, "FITS table row number",
209 row, nrows());
210 }
211
212 // Check that elements is non-negative
213 if (elements < 0) {
214 std::string msg = "Number of elements " + gammalib::str(elements) +
215 " can not be negative. Please specify a"
216 " non-negative number of elements.";
218 }
219
220 // First handle the case of a variable-length column
221 if (is_variable()) {
222
223 // Determine number of elements to add or to remove
224 int difference = elements - (m_rowstart[row+1] - m_rowstart[row]);
225
226 // If difference is positive, then add elements at the end of
227 // the vector. This is done using resize_data() which will insert
228 // "difference" elements at the index specified as first argument
229 if (difference > 0) {
230 resize_data(m_rowstart[row+1], difference);
231 }
232
233 // ... else if difference is negative then remove elements from
234 // the end of the array. This is done using resize_data() which
235 // will remove "difference" element from the index on specified as
236 // first argument
237 else if (difference < 0) {
238 resize_data(m_rowstart[row+1]+difference, difference);
239 }
240
241 // Update row start indices
242 for (int i = row + 1; i <= nrows(); ++i) {
243 m_rowstart[i] += difference;
244 }
245
246 // Update maximum column length
247 m_varlen = 0;
248 for (int i = 0; i < nrows(); ++i) {
249 int len = m_rowstart[row+1] - m_rowstart[row];
250 if (len > m_varlen) {
251 m_varlen = len;
252 }
253 }
254
255 } // endif: we had a variable-length column
256
257 // Return
258 return;
259}
260
261
262/***********************************************************************//**
263 * @brief Returns number of elements in column for specific row
264 *
265 * @param[in] row Row index.
266 * @return Number of elements in column at @p row.
267 *
268 * @exception GException::out_of_range
269 * Row index out of valid range.
270 *
271 * Returns the number of elements in the column for a specific @p row. For a
272 * fixed-length column the returned number is independent of the row. For a
273 * variable-length column the returned number is then length of the column
274 * for the specified row.
275 ***************************************************************************/
276int GFitsTableCol::elements(const int& row) const
277{
278 // Check row value
279 if (row < 0 || row >= nrows()) {
280 throw GException::out_of_range(G_ELEMENTS2, "FITS table row number",
281 row, nrows());
282 }
283
284 // Get number of elements
285 int number = (m_variable) ? m_rowstart[row+1] - m_rowstart[row]
286 : m_number;
287
288 // Return number
289 return number;
290}
291
292
293/***********************************************************************//**
294 * @brief Returns TFORM code for binary table column
295 *
296 * Constructs the TFORM code for a binary table column, supporting
297 * fixed-length and variable-length column types.
298 ***************************************************************************/
299std::string GFitsTableCol::tform_binary(void) const
300{
301 // Set type code string
302 std::string typecode = "";
303 switch (std::abs(type())) {
304 case __TBIT:
305 typecode = "X";
306 break;
307 case __TBYTE:
308 typecode = "B";
309 break;
310 case __TLOGICAL:
311 typecode = "L";
312 break;
313 case __TSTRING:
314 // If there are substrings then add width of substring
315 typecode = "A";
316 if (repeat() > width()) {
317 typecode.append(gammalib::str(width()));
318 }
319 break;
320 case __TUSHORT:
321 typecode = "U";
322 break;
323 case __TSHORT:
324 typecode = "I";
325 break;
326 case __TULONG:
327 typecode = "V";
328 break;
329 case __TLONG:
330 typecode = "J";
331 break;
332 case __TUINT:
333 typecode = "V";
334 break;
335 case __TINT:
336 typecode = "J";
337 break;
338 case __TFLOAT:
339 typecode = "E";
340 break;
341 case __TLONGLONG:
342 typecode = "K";
343 break;
344 case __TDOUBLE:
345 typecode = "D";
346 break;
347 case __TCOMPLEX:
348 typecode = "C";
349 break;
350 case __TDBLCOMPLEX:
351 typecode = "M";
352 break;
353 default:
354 break;
355 }
356
357 // Build TFORM code
358 std::string tform;
359 if (std::abs(type()) == __TSTRING) {
360 tform.append(gammalib::str(repeat()));
361 }
362 else {
363 tform.append(gammalib::str(number()));
364 }
365 if (is_variable()) {
366 tform.append("P");
367 }
368 tform.append(typecode);
369 if (is_variable() && m_varlen > 0) {
370 tform.append("("+gammalib::str(m_varlen)+")");
371 }
372
373 // Return TFORM code
374 return tform;
375}
376
377
378/***********************************************************************//**
379 * @brief Print column information
380 *
381 * @param[in] chatter Chattiness.
382 * @return String containing column information.
383 *
384 * @todo Format and cfitsio information is mainly for debugging. This could
385 * vanish in a more stable version of the code, or it could be compiled-in
386 * conditionally using a debug option. Alternatively, a higher chatter level
387 * may be required to see this information.
388 ***************************************************************************/
389std::string GFitsTableCol::print(const GChatter& chatter) const
390{
391 // Initialise result string
392 std::string result;
393
394 // Continue only if chatter is not silent
395 if (chatter != SILENT) {
396
397 // Append formatted column name. Optionally add units
398 if (unit().length() > 0) {
399 result.append(gammalib::parformat(name()+" ("+unit()+")"));
400 }
401 else {
402 result.append(gammalib::parformat(name()));
403 }
404
405 // Append column number. This will be "-" if the column does not exist
406 // in the FITS file.
407 if (m_colnum > 0) {
408 result.append(gammalib::right(gammalib::str(m_colnum),4)+" ");
409 }
410 else {
411 result.append(gammalib::right("[-]",4)+" ");
412 }
413
414 // Append loading information
415 if (is_loaded()) {
416 result.append("[loaded] ");
417 }
418 else {
419 result.append("[not loaded] ");
420 }
421
422 // Append format information
423 result.append("["+tform_binary()+","+ascii_format()+"]");
424
425 // Append dimensions (if available)
426 if (!dim().empty()) {
427
428 // Build TDIM string
429 std::string value = "("+gammalib::str(dim()[0]);
430 for (int k = 1; k < dim().size(); ++k) {
431 value += ","+gammalib::str(dim()[k]);
432 }
433 value += ")";
434
435 // Append
436 result.append(" "+value);
437 }
438
439 // Append cfitsio information
440 if (is_variable()) {
441 result.append(" repeat=" + gammalib::str(repeat()));
442 result.append(" width=" + gammalib::str(width()));
443 result.append(" number=" + gammalib::str(number()));
444 result.append(" rows=" + gammalib::str(nrows()));
445 result.append(" size=" + gammalib::str(m_size));
446 result.append(" varlen=");
447 if (m_varlen > 0) {
448 result.append(gammalib::str(m_varlen));
449 }
450 else {
451 result.append("undetermined");
452 }
453 }
454 else {
455 result.append(" repeat=" + gammalib::str(repeat()));
456 result.append(" width=" + gammalib::str(width()));
457 result.append(" number=" + gammalib::str(number()));
458 result.append(" rows=" + gammalib::str(nrows()));
459 result.append(" size=" + gammalib::str(m_size));
460 }
461
462 // Append tscale information
463 if (tscale() != 1.0) {
464 result.append(" tscale=" + gammalib::str(tscale()));
465 }
466
467 } // endif: chatter was not silent
468
469 // Compile option: print content
470 #if defined(G_PRINT_CONTENT)
471 if (chatter != SILENT) {
472
473 // Fetch data if necessary
474 if (!is_loaded()) fetch_data();
475
476 // Loop over all rows
477 for (int row = 0; row < nrows(); ++row) {
478 result.append("\n");
479 if (is_variable()) {
480 result.append("start=");
481 result.append(gammalib::str(m_rowstart[row]));
482 result.append(":");
483 }
484 for (int inx = 0; inx < elements(row); ++inx) {
485 result.append(" "+string(row, inx));
486 }
487 }
488 if (is_variable()) {
489 result.append("\nend=");
490 result.append(gammalib::str(m_rowstart[nrows()]));
491 }
492 }
493 #endif
494
495 // Return result
496 return result;
497}
498
499
500/*==========================================================================
501 = =
502 = Protected methods =
503 = =
504 ==========================================================================*/
505
506/***********************************************************************//**
507 * @brief Save table column into FITS file
508 *
509 * Refer to GFitsTableCol::save_column() for more information.
510 ***************************************************************************/
512{
513 // Save column
514 save_column();
515
516 // Return
517 return;
518}
519
520
521/***********************************************************************//**
522 * @brief Load table column from FITS file
523 *
524 * Loads table column from FITS file by calling the load_column_variable()
525 * method for variable-length columns and load_column_fixed() for fixed-
526 * length columns.
527 *
528 * The method also makes sure that any scaled column will be read unscaled.
529 ***************************************************************************/
531{
532 // If the column is scaled then rest the scaling so that data are read
533 // unscaled. This is necessary to avoid that information is lost when
534 // rewriting the table. Note that a call to fftscl does not alter the
535 // keywords. Also note that this implies that scaling of integer columns
536 // has to be performed by hand.
537 if (m_tscale != 1.0) {
538 int status = 0;
539 status = __fftscl(FPTR(m_fitsfile), m_colnum, 1.0, 0.0, &status);
540 }
541
542 // Load variable-length or fixed-length column from FITS file
543 if (is_variable()) {
545 }
546 else {
548 }
549
550 // Return
551 return;
552}
553
554
555/***********************************************************************//**
556 * @brief Load fixed-length column from FITS file
557 *
558 * @exception GException::fits_hdu_not_found
559 * Specified HDU not found in FITS file.
560 * @exception GException::fits_error
561 * An error occured while loading column data from FITS file.
562 *
563 * If a FITS file is attached to the column the data are loaded into memory
564 * from the FITS file. If no FITS file is attached, memory is allocated
565 * to hold the column data and all cells are set to 0.
566 *
567 * The method makes use of the virtual methods
568 * GFitsTableCol::alloc_data,
569 * GFitsTableCol::init_data,
570 * GFitsTableCol::ptr_data, and
571 * GFitsTableCol::ptr_nulval.
572 * These methods are implemented by the derived column classes which
573 * implement a specific storage class (i.e. float, double, short, ...).
574 ***************************************************************************/
576{
577 // Calculate size of memory
579
580 // Load only if the column has a positive size
581 if (m_size > 0) {
582
583 // Allocate and initialise fresh memory
584 alloc_data();
585 init_data();
586
587 // If a FITS file is attached then try loading column data from the
588 // FITS file. This may fail in case that no data has yet been written
589 // to the FITS file. In that case we just skip loading and return
590 // the initalised column ...
591 if (FPTR(m_fitsfile)->Fptr != NULL) {
592
593 // Move to the HDU
594 int status = 0;
595 status = __ffmahd(FPTR(m_fitsfile),
596 (FPTR(m_fitsfile)->HDUposition)+1,
597 NULL, &status);
598
599 // If this failed because:
600 // - the primary HDU was not found (status 252)
601 // - we moved past the file (status 107)
602 // we assume that no data have yet been written to the file and
603 // we skip the loading.
604 if (status != 252 && status != 107) {
605
606 // Break on any other cfitsio error
607 if (status != 0) {
608 std::string msg = "FITS HDU number "+
609 gammalib::str((FPTR(m_fitsfile)->HDUposition)+1)+
610 " not found in FITS file.";
612 }
613
614 // Load data
616 1, 1, m_size, ptr_nulval(), ptr_data(),
617 &m_anynul, &status);
618 if (status != 0) {
620 "for column \""+m_name+"\".");
621 }
622
623 } // endif: no primary HDU found
624
625 } // endif: there was a FITS file attached
626
627 } // endif: column has a positive size
628
629 // Return
630 return;
631}
632
633
634/***********************************************************************//**
635 * @brief Load variable-length column from FITS file
636 *
637 * @exception GException::fits_error
638 * An error occured while loading column data from FITS file.
639 *
640 * If a FITS file is attached to the column the data are loaded into memory
641 * from the FITS file. If no FITS file is attached, memory is allocated
642 * to hold the column data and all cells are set to 0.
643 *
644 * The method makes use of the virtual methods
645 * GFitsTableCol::alloc_data,
646 * GFitsTableCol::init_data,
647 * GFitsTableCol::ptr_data, and
648 * GFitsTableCol::ptr_nulval.
649 * These methods are implemented by the derived column classes which
650 * implement a specific storage class (i.e. float, double, short, ...).
651 ***************************************************************************/
653{
654 // If a FITS file is attached then try loading column data from the
655 // FITS file. This may fail in case that no data has yet been written
656 // to the FITS file. In that case we just skip loading and return
657 // the initalised column ...
658 if (FPTR(m_fitsfile)->Fptr != NULL) {
659
660 // Move to the HDU
661 int status = 0;
662 status = __ffmahd(FPTR(m_fitsfile),
663 (FPTR(m_fitsfile)->HDUposition)+1,
664 NULL,
665 &status);
666
667 // If this failed because:
668 // - the primary HDU was not found (status 252)
669 // - we moved past the file (status 107)
670 // we assume that no data have yet been written to the file and
671 // we skip the loading.
672 if (status != 252 && status != 107) {
673
674 // Break on any other cfitsio error
675 if (status != 0) {
676 std::string msg = "FITS HDU number "+
677 gammalib::str((FPTR(m_fitsfile)->HDUposition)+1)+
678 " not found in FITS file.";
680 }
681
682 // Allocate rowstart array
683 m_rowstart.assign(m_length+1, 0);
684
685 // Determine the column length for each row by looping over
686 // all rows and derive the total memory requirement
687 m_size = 0;
688 m_varlen = 0;
689 m_rowstart[0] = 0;
690 for (int row = 0; row < m_length; ++row) {
691
692 // Initialise offset and repeat
693 long offset(0);
694 long repeat(0);
695
696 // Get variable-length of row in repeat
697 status = __ffgdes(FPTR(m_fitsfile),
698 m_colnum,
699 row+1,
700 &repeat,
701 &offset,
702 &status);
703 if (status != 0) {
704 std::string msg = "Unable to get descriptor of row "+
705 gammalib::str(row+1)+" of column '"+
706 name()+"' from FITS file.";
708 msg);
709 }
710
711 // Store start of next row
712 m_rowstart[row+1] = m_rowstart[row] + repeat;
713 m_size += repeat;
714 if (repeat > m_varlen) {
716 }
717
718 } // endfor: looped over all rows
719
720 // Allocate and initialise fresh memory
721 alloc_data();
722 init_data();
723
724 // Load data for each row
725 for (int row = 0; row < m_length; ++row) {
726
727 // Initialise anynul
728 int anynul(0);
729
730 // Load data
731 status = __ffgcv(FPTR(m_fitsfile),
732 std::abs(m_type),
733 m_colnum,
734 row+1,
735 1,
736 elements(row),
737 ptr_nulval(),
738 ptr_data(m_rowstart[row]),
739 &anynul,
740 &status);
741 if (status != 0) {
742 std::string msg = "Unable to load row "+gammalib::str(row+1)+""
743 " of column '"+name()+"' from FITS file.";
745 msg);
746 }
747
748 // Increment anynul
749 m_anynul += anynul;
750
751 } // endfor: looped over all rows
752
753 } // endif: no primary HDU found
754
755 } // endif: there was a FITS file attached
756
757 // Return
758 return;
759}
760
761
762/***********************************************************************//**
763 * @brief Save table column into FITS file
764 *
765 * Save table column into FITS file by calling the save_column_variable()
766 * method for variable-length columns and save_column_fixed() for fixed-
767 * length columns.
768 ***************************************************************************/
770{
771 // Save variable-length or fixed-length column into FITS file
772 if (is_variable()) {
774 }
775 else {
777 }
778
779 // Return
780 return;
781}
782
783
784/***********************************************************************//**
785 * @brief Save table column into FITS file
786 *
787 * @exception GException::fits_error
788 * Error occured during writing of the column data.
789 *
790 * The table column is only saved if it is linked to a FITS file and if the
791 * data are indeed present in the class instance. This avoids saving of data
792 * that have not been modified.
793 *
794 * The method make use of the virtual methods
795 * GFitsTableCol::ptr_data and
796 * GFitsTableCol::ptr_nulval.
797 * These methods are implemented by the derived column classes which
798 * implement a specific storage class (i.e. float, double, short, ...).
799 ***************************************************************************/
801{
802 // Continue only if a FITS file is connected and data have been loaded
803 if (FPTR(m_fitsfile)->Fptr != NULL && m_colnum > 0 && ptr_data() != NULL) {
804
805 // Move to the HDU
806 int status = 0;
807 status = __ffmahd(FPTR(m_fitsfile),
808 (FPTR(m_fitsfile)->HDUposition)+1, NULL,
809 &status);
810 if (status != 0) {
811 std::string msg = "FITS HDU number "+
812 gammalib::str((FPTR(m_fitsfile)->HDUposition)+1)+
813 " not found in FITS file.";
815 }
816
817 // Save the column data
818 status = __ffpcn(FPTR(m_fitsfile), m_type, m_colnum, 1, 1,
819 m_size, ptr_data(), ptr_nulval(), &status);
820 if (status != 0) {
821 std::string msg = "Unable to save column '"+name()+"' to"
822 " FITS file.";
824 }
825
826 } // endif: FITS file was connected
827
828 // Return
829 return;
830}
831
832
833/***********************************************************************//**
834 * @brief Save table column into FITS file
835 *
836 * @exception GException::fits_hdu_not_found
837 * Specified HDU not found in FITS file.
838 * @exception GException::fits_error
839 * Error occured during writing of the column data.
840 *
841 * The table column is only saved if it is linked to a FITS file and if the
842 * data are indeed present in the class instance. This avoids saving of data
843 * that have not been modified.
844 *
845 * The method make use of the virtual methods
846 * GFitsTableCol::ptr_data and
847 * GFitsTableCol::ptr_nulval.
848 * These methods are implemented by the derived column classes which
849 * implement a specific storage class (i.e. float, double, short, ...).
850 ***************************************************************************/
852{
853 // Continue only if a FITS file is connected and data have been loaded
854 if (FPTR(m_fitsfile)->Fptr != NULL && m_colnum > 0 && ptr_data() != NULL) {
855
856 // Move to the HDU
857 int status = 0;
858 status = __ffmahd(FPTR(m_fitsfile),
859 (FPTR(m_fitsfile)->HDUposition)+1, NULL,
860 &status);
861 if (status != 0) {
862 std::string msg = "FITS HDU number "+
863 gammalib::str((FPTR(m_fitsfile)->HDUposition)+1)+
864 " not found in FITS file.";
866 }
867
868 // Save the column data row-by-row
869 for (int row = 0; row < m_length; ++row) {
870
871 // Save row data
872 status = __ffpcn(FPTR(m_fitsfile),
873 std::abs(m_type),
874 m_colnum,
875 row+1,
876 1,
877 elements(row),
878 ptr_data(m_rowstart[row]),
879 ptr_nulval(),
880 &status);
881 if (status != 0) {
882 std::string msg = "Unable to save row "+gammalib::str(row+1)+""
883 " of column '"+name()+"' to FITS file.";
885 msg);
886 }
887
888 } // endfor: looped over rows
889
890 } // endif: FITS file was connected
891
892 // Return
893 return;
894}
895
896
897/***********************************************************************//**
898 * @brief Compute offset of column element in memory
899 *
900 * @param[in] row Row of column [0,...,m_length[.
901 * @param[in] inx Vector index in column row [0,...,elements(row)[.
902 *
903 * @exception GException::out_of_range
904 * Table row or vector index are out of valid range.
905 *
906 * Computes the offset of a column element in the storage array from the
907 * @p row number and the vector index. The method also supports both
908 * variable-length and fixed-length columns.
909 ***************************************************************************/
910int GFitsTableCol::offset(const int& row, const int& inx) const
911{
912 // Check row value
913 #if defined(G_RANGE_CHECK)
914 if (row < 0 || row >= m_length) {
915 throw GException::out_of_range(G_OFFSET, "Row", row, m_length);
916 }
917 #endif
918
919 // Check inx value
920 #if defined(G_RANGE_CHECK)
921 if (inx < 0 || inx >= elements(row)) {
922 throw GException::out_of_range(G_OFFSET, "Vector index", inx,
923 elements(row));
924 }
925 #endif
926
927 // Calculate pixel offset
928 int offset = (is_variable()) ? m_rowstart[row] + inx : row * m_number + inx;
929
930 // Return offset
931 return offset;
932}
933
934
935/*==========================================================================
936 = =
937 = Private methods =
938 = =
939 ==========================================================================*/
940
941/***********************************************************************//**
942 * @brief Initialise class members
943 ***************************************************************************/
945{
946 // Optionally print call graph
947 #if defined(G_CALL_GRAPH)
948 printf("GFitsTableCol::init_members\n");
949 #endif
950
951 // Allocate FITS file pointer
954 FPTR(m_fitsfile)->Fptr = NULL;
955
956 // Initialise members
957 m_name.clear();
958 m_unit.clear();
959 m_dim.clear();
960 m_rowstart.clear();
961 m_colnum = 0;
962 m_type = 0;
963 m_repeat = 0;
964 m_width = 0;
965 m_number = 0;
966 m_length = 0;
967 m_variable = false;
968 m_varlen = 0;
969 m_size = 0;
970 m_anynul = 0;
971 m_tscale = 1.0;
972
973 // Optionally print call graph
974 #if defined(G_CALL_GRAPH)
975 printf("exit GFitsTableCol::init_members\n");
976 #endif
977
978 // Return
979 return;
980}
981
982
983/***********************************************************************//**
984 * @brief Copy class members
985 *
986 * @param[in] column Column to be copied.
987 ***************************************************************************/
989{
990 // Copy attributes
991 m_name = column.m_name;
992 m_unit = column.m_unit;
993 m_dim = column.m_dim;
994 m_colnum = column.m_colnum;
995 m_type = column.m_type;
996 m_repeat = column.m_repeat;
997 m_width = column.m_width;
998 m_number = column.m_number;
999 m_length = column.m_length;
1000 m_variable = column.m_variable;
1001 m_varlen = column.m_varlen;
1002 m_rowstart = column.m_rowstart;
1003 m_size = column.m_size;
1004 m_anynul = column.m_anynul;
1005 m_tscale = column.m_tscale;
1007
1008 // Return
1009 return;
1010}
1011
1012
1013/***********************************************************************//**
1014 * @brief Delete class members
1015 ***************************************************************************/
1017{
1018 // Optionally print call graph
1019 #if defined(G_CALL_GRAPH)
1020 printf("GFitsTableCol::free_members\n");
1021 #endif
1022
1023 // Free memory
1024 if (m_fitsfile != NULL) delete FPTR(m_fitsfile);
1025
1026 // Mark memory as free
1027 m_fitsfile = NULL;
1028
1029 // Optionally print call graph
1030 #if defined(G_CALL_GRAPH)
1031 printf("exit GFitsTableCol::free_members\n");
1032 #endif
1033
1034 // Return
1035 return;
1036}
1037
1038
1039/***********************************************************************//**
1040 * @brief Connect table column to FITS file
1041 *
1042 * @param[in] vptr Column file void pointer.
1043 *
1044 * A table column is connected to a FITS file when the m_fitsfile holds a
1045 * FITS file pointer. In that way, the column knows to which file it belongs.
1046 ***************************************************************************/
1048{
1049 // Connect table column by copying the column file pointer
1050 FPTR_COPY(m_fitsfile, vptr);
1051
1052 // Return
1053 return;
1054}
Exception handler interface definition.
CFITSIO interface header.
#define __TLONG
#define __TLOGICAL
#define __TLONGLONG
#define __TSHORT
#define FPTR(A)
#define __TDBLCOMPLEX
#define __TBYTE
#define __TULONG
#define __ffgdes(A, B, C, D, E, F)
#define __ffmahd(A, B, C, D)
#define __fftscl(A, B, C, D, E)
#define FPTR_COPY(A, B)
#define __TSTRING
#define __TFLOAT
#define __ffgcv(A, B, C, D, E, F, G, H, I, J)
#define __TDOUBLE
#define __TINT
#define __TUSHORT
#define __TCOMPLEX
#define __ffpcn(A, B, C, D, E, F, G, H, I)
#define __TUINT
#define __TBIT
#define G_LOAD_COLUMN_FIXED
#define G_SAVE_COLUMN_VARIABLE
#define G_OFFSET
#define G_ELEMENTS2
#define G_SAVE_COLUMN_FIXED
#define G_ELEMENTS1
#define G_LOAD_COLUMN_VARIABLE
FITS table column abstract base class definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
Abstract interface for FITS table column.
void connect(void *vptr)
Connect table column to FITS file.
virtual void resize_data(const int &index, const int &number)=0
int m_type
Column type.
int m_length
Length of column (number of rows)
double m_tscale
Optional scaling factor (1 = no scaling)
int m_anynul
Number of NULLs encountered.
std::vector< int > m_dim
Column dimension.
void * m_fitsfile
FITS file pointer associated with column.
const int & nrows(void) const
Returns number of rows in column.
const int & repeat(void) const
Returns column repeat value (only used for binary tables)
const int & anynul(void) const
Return number of NULLs encountered.
std::vector< int > m_rowstart
Start index of each row.
const std::vector< int > & dim(void) const
Returns column dimension.
std::string m_name
Column name.
int m_repeat
Repeat value of column.
std::string print(const GChatter &chatter=NORMAL) const
Print column information.
int m_size
Size of allocated data area (0 if not loaded)
int m_width
Width in Bytes of single column element.
const bool & is_variable(void) const
Signals if column is of variable length.
int m_varlen
Maximum number of elements in variable-length.
void copy_members(const GFitsTableCol &column)
Copy class members.
virtual void save_column_fixed(void)
Save table column into FITS file.
GFitsTableCol & operator=(const GFitsTableCol &column)
Assignment operator.
const int & number(void) const
Returns number of elements in column.
virtual void * ptr_nulval(void)=0
const double & tscale(void) const
Return TSCALE value.
void free_members(void)
Delete class members.
virtual void * ptr_data(const int &index=0)=0
virtual void init_data(void)=0
virtual void save_column(void)
Save table column into FITS file.
const std::string & name(void) const
Returns column name.
int m_colnum
Column number (starting from 1). This parameter is used to signal if a table column corresponds to a ...
GFitsTableCol(void)
Void constructor.
const int & width(void) const
Return width in Bytes of one column element.
virtual void load_column(void)
Load table column from FITS file.
bool m_variable
Signals if column is variable length.
void init_members(void)
Initialise class members.
virtual int offset(const int &row, const int &inx) const
Compute offset of column element in memory.
const std::string & unit(void) const
Returns column unit.
virtual bool is_loaded(void) const =0
int m_number
Number of elements in column.
virtual void save_column_variable(void)
Save table column into FITS file.
virtual std::string ascii_format(void) const =0
virtual void fetch_data(void) const =0
void elements(const int &row, const int &elements)
Set number of column elements for specific row.
std::string tform_binary(void) const
Returns TFORM code for binary table column.
virtual void alloc_data(void)=0
virtual void save(void)
Save table column into FITS file.
std::string m_unit
Column unit.
virtual void load_column_fixed(void)
Load fixed-length column from FITS file.
const int & type(void) const
Returns CFITSIO column type.
virtual ~GFitsTableCol(void)
Destructor.
virtual void load_column_variable(void)
Load variable-length column from FITS file.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1143
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
std::string right(const std::string &s, const int &n, const char &c=' ')
Right justify string to achieve a length of n characters.
Definition GTools.cpp:1094