GammaLib 2.0.0
Loading...
Searching...
No Matches
GFitsTableBoolCol.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GFitsTableBoolCol.cpp - FITS table boolean column class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2010-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 GFitsTableBoolCol.cpp
23 * @brief FITS table boolean column class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <string>
32#include "GException.hpp"
33#include "GTools.hpp"
34#include "GFitsCfitsio.hpp"
35#include "GFitsTableBoolCol.hpp"
36
37/* __ Method name definitions ____________________________________________ */
38#define G_INSERT "GFitsTableBoolCol::insert(int&, int&)"
39#define G_REMOVE "GFitsTableBoolCol::remove(int&, int&)"
40
41/* __ Macros _____________________________________________________________ */
42
43/* __ Coding definitions _________________________________________________ */
44
45/* __ Debug definitions __________________________________________________ */
46
47
48/*==========================================================================
49 = =
50 = Constructors/destructors =
51 = =
52 ==========================================================================*/
53
54/***********************************************************************//**
55 * @brief Constructor
56 ***************************************************************************/
58{
59 // Initialise class members for clean destruction
61
62 // Return
63 return;
64}
65
66
67/***********************************************************************//**
68 * @brief Constructor
69 *
70 * @param[in] name Name of column.
71 * @param[in] nrows Number of rows in column.
72 * @param[in] size Vector size of column.
73 ***************************************************************************/
75 const int& nrows,
76 const int& size) :
77 GFitsTableCol(name, nrows, size, 1)
78{
79 // Initialise class members for clean destruction
81
82 // Return
83 return;
84}
85
86
87/***********************************************************************//**
88 * @brief Copy constructor
89 *
90 * @param[in] column Table column.
91 ***************************************************************************/
93 GFitsTableCol(column)
94{
95 // Initialise class members for clean destruction
97
98 // Copy members
99 copy_members(column);
100
101 // Return
102 return;
103}
104
105
106/***********************************************************************//**
107 * @brief Destructor
108 ***************************************************************************/
110{
111 // Free members
112 free_members();
113
114 // Return
115 return;
116}
117
118
119/*==========================================================================
120 = =
121 = Operators =
122 = =
123 ==========================================================================*/
124
125/***********************************************************************//**
126 * @brief Assignment operator
127 *
128 * @param[in] column Table column.
129 * @return Table column.
130 ***************************************************************************/
132{
133 // Execute only if object is not identical
134 if (this != &column) {
135
136 // Copy base class members
137 this->GFitsTableCol::operator=(column);
138
139 // Free members
140 free_members();
141
142 // Initialise private members for clean destruction
143 init_members();
144
145 // Copy members
146 copy_members(column);
147
148 } // endif: object was not identical
149
150 // Return this object
151 return *this;
152}
153
154
155/***********************************************************************//**
156 * @brief Column data access operator
157 *
158 * @param[in] row Row of column to access.
159 * @param[in] inx Vector index in column row to access.
160 *
161 * Provides access to data in a column.
162 ***************************************************************************/
163bool& GFitsTableBoolCol::operator()(const int& row, const int& inx)
164{
165 // If data are not available then load them now
166 if (m_data == NULL) fetch_data();
167
168 // Return data bin
169 return m_data[offset(row, inx)];
170}
171
172
173/***********************************************************************//**
174 * @brief Column data access operator (const variant)
175 *
176 * @param[in] row Row of column to access.
177 * @param[in] inx Vector index in column row to access
178 *
179 * Provides access to data in a column.
180 ***************************************************************************/
181const bool& GFitsTableBoolCol::operator()(const int& row, const int& inx) const
182{
183 // If data are not available then load them now
184 if (m_data == NULL) fetch_data();
185
186 // Return data bin
187 return m_data[offset(row, inx)];
188}
189
190
191/*==========================================================================
192 = =
193 = Public methods =
194 = =
195 ==========================================================================*/
196
197/***********************************************************************//**
198 * @brief Clear instance
199 *
200 * This method properly resets the object to an initial state.
201 ***************************************************************************/
203{
204 // Free class members (base and derived classes, derived class first)
205 free_members();
207
208 // Initialise members
210 init_members();
211
212 // Return
213 return;
214}
215
216
217/***********************************************************************//**
218 * @brief Clone column
219 ***************************************************************************/
221{
222 return new GFitsTableBoolCol(*this);
223}
224
225
226/***********************************************************************//**
227 * @brief Get string value
228 *
229 * @param[in] row Table row.
230 * @param[in] inx Table column vector index.
231 *
232 * Returns value of specified row and vector index as string.
233 ***************************************************************************/
234std::string GFitsTableBoolCol::string(const int& row, const int& inx) const
235{
236 // If data are not available then load them now
237 if (m_data == NULL) fetch_data();
238
239 // Convert bool into string
240 std::string result = (m_data[offset(row,inx)]) ? "T" : "F";
241
242 // Return value
243 return result;
244}
245
246
247/***********************************************************************//**
248 * @brief Get double precision value
249 *
250 * @param[in] row Table row.
251 * @param[in] inx Table column vector index.
252 *
253 * Returns value of specified row and vector index as double precision.
254 ***************************************************************************/
255double GFitsTableBoolCol::real(const int& row, const int& inx) const
256{
257 // If data are not available then load them now
258 if (m_data == NULL) fetch_data();
259
260 // Convert bool into double
261 double value = (double)m_data[offset(row,inx)];
262
263 // Return value
264 return value;
265}
266
267
268/***********************************************************************//**
269 * @brief Get integer value
270 *
271 * @param[in] row Table row.
272 * @param[in] inx Table column vector index.
273 *
274 * Returns value of specified row and vector index as integer.
275 ***************************************************************************/
276int GFitsTableBoolCol::integer(const int& row, const int& inx) const
277{
278 // If data are not available then load them now
279 if (m_data == NULL) fetch_data();
280
281 // Convert bool into int
282 int value = (int)m_data[offset(row,inx)];
283
284 // Return value
285 return value;
286}
287
288
289/***********************************************************************//**
290 * @brief Insert rows in column
291 *
292 * @param[in] row Row after which rows should be inserted (0=first row).
293 * @param[in] nrows Number of rows to be inserted.
294 *
295 * @exception GException::out_of_range
296 * Specified row is invalid.
297 *
298 * Inserts rows into a FITS table. This implies that the column will be
299 * loaded into memory.
300 ***************************************************************************/
301void GFitsTableBoolCol::insert(const int& row, const int& nrows)
302{
303 // Make sure that row is valid
304 if (row < 0 || row > m_length) {
305 throw GException::out_of_range(G_INSERT, "FITS table row number",
306 row, m_length+1);
307 }
308
309 // Continue only if there are rows to be inserted
310 if (nrows > 0) {
311
312 // If we have no rows yet then simply set the length to the
313 // number of rows to be inserted
314 if (m_length == 0) {
315 m_length = nrows;
317 alloc_data();
318 init_data();
319 }
320
321 // ... otherwise fetch data, allocate new data and copy over
322 // the existing items
323 else {
324
325 // If data are not available then load them now
326 if (m_data == NULL) fetch_data();
327
328 // Compute new column length
329 int length = m_length + nrows;
330
331 // Calculate size of new memory
332 m_size = m_number * length;
333
334 // Allocate new data to hold the column
335 bool* new_data = new bool[m_size];
336
337 // Compute the number of elements before the insertion point,
338 // the number of elements that get inserted, and the total
339 // number of elements after the insertion point
340 int n_before = m_number * row;
341 int n_insert = m_number * nrows;
342 int n_after = m_number * (m_length - row);
343
344 // Copy and initialise data
345 bool* src = m_data;
346 bool* dst = new_data;
347 for (int i = 0; i < n_before; ++i) {
348 *dst++ = *src++;
349 }
350 for (int i = 0; i < n_insert; ++i) {
351 *dst++ = 0;
352 }
353 for (int i = 0; i < n_after; ++i) {
354 *dst++ = *src++;
355 }
356
357 // Free old data
358 if (m_data != NULL) delete [] m_data;
359
360 // Set pointer to new data and store length
361 m_data = new_data;
362 m_length = length;
363
364 } // endelse: there were already data
365
366 } // endfor: there were rows to be inserted
367
368 // Return
369 return;
370}
371
372
373/***********************************************************************//**
374 * @brief Remove rows from column
375 *
376 * @param[in] row Row after which rows should be removed (0=first row).
377 * @param[in] nrows Number of rows to be removed.
378 *
379 * @exception GException::fits_invalid_row
380 * Specified row is invalid.
381 * @exception GException::fits_invalid_nrows
382 * Invalid number of rows specified.
383 *
384 * This method removes rows from a FITS table. This implies that the column
385 * will be loaded into memory.
386 ***************************************************************************/
387void GFitsTableBoolCol::remove(const int& row, const int& nrows)
388{
389 // Make sure that row is valid
390 if (row < 0 || row >= m_length) {
391 throw GException::out_of_range(G_REMOVE, "FITS table row number",
392 row, m_length);
393 }
394
395 // Make sure that we don't remove beyond the limit
397 throw GException::out_of_range(G_REMOVE, "Number of FITS table rows",
398 nrows, m_length-row+1);
399 }
400
401 // Continue only if there are rows to be removed
402 if (nrows > 0) {
403
404 // If data are not available then load them now
405 if (m_data == NULL) fetch_data();
406
407 // Compute new column length
408 int length = m_length - nrows;
409
410 // Calculate size of new memory
411 m_size = m_number * length;
412
413 // If we have rows remaining then allocate new data to hold
414 // the column
415 if (m_size > 0) {
416
417 // Allocate new data to hold the column
418 bool* new_data = new bool[m_size];
419
420 // Compute the number of elements before the removal point,
421 // the number of elements that get removed, and the total
422 // number of elements after the removal point
423 int n_before = m_number * row;
424 int n_remove = m_number * nrows;
425 int n_after = m_number * (length - row);
426
427 // Copy data
428 bool* src = m_data;
429 bool* dst = new_data;
430 for (int i = 0; i < n_before; ++i) {
431 *dst++ = *src++;
432 }
433 src += n_remove;
434 for (int i = 0; i < n_after; ++i) {
435 *dst++ = *src++;
436 }
437
438 // Free old data
439 if (m_data != NULL) delete [] m_data;
440
441 // Set pointer to new data and store length
442 m_data = new_data;
443 m_length = length;
444
445 } // endif: there are still elements after removal
446
447 // ... otherwise just remove all data
448 else {
449
450 // Free old data
451 if (m_data != NULL) delete [] m_data;
452
453 // Set pointer to new data and store length
454 m_data = NULL;
455 m_length = length;
456 }
457
458 } // endfor: there were rows to be removed
459
460 // Return
461 return;
462}
463
464
465/***********************************************************************//**
466 * @brief Set nul value
467 *
468 * @param[in] value Nul value.
469 *
470 * @todo To correctly reflect the nul value in the data, the column should
471 * be reloaded. However, the column may have been changed, so in principle
472 * saving is needed. However, we may not want to store the data, hence saving
473 * is also not desired. We thus have to develop a method to update the
474 * column information for a new nul value in place ...
475 ***************************************************************************/
476void GFitsTableBoolCol::nulval(const bool* value)
477{
478 // Allocate nul value
479 alloc_nulval(value);
480
481 // Update column
482// if (m_data != NULL) {
483// save();
484// load();
485// }
486
487 // Return
488 return;
489}
490
491
492/*==========================================================================
493 = =
494 = Private methods =
495 = =
496 ==========================================================================*/
497
498/***********************************************************************//**
499 * @brief Initialise class members
500 ***************************************************************************/
502{
503 // Initialise members
505 m_data = NULL;
506 m_buffer = NULL;
507 m_nulval = NULL;
508
509 // Return
510 return;
511}
512
513
514/***********************************************************************//**
515 * @brief Copy class members
516 *
517 * @param[in] column Column.
518 *
519 * Sets the content of the vector column by copying from another column.
520 * If the code is compiled with the small memory option, and if the source
521 * column has not yet been loaded, then we only load the column temporarily
522 * for copying purposes and release it again once copying is finished.
523 ***************************************************************************/
525{
526 // Fetch data if necessary
527 bool not_loaded = (!column.is_loaded());
528 if (not_loaded) {
529 column.fetch_data();
530 }
531
532 // Copy attributes
533 m_type = column.m_type;
534 m_size = column.m_size;
535 m_varlen = column.m_varlen;
536 m_rowstart = column.m_rowstart;
537
538 // Copy column data
539 if (column.m_data != NULL && m_size > 0) {
540 if (m_data != NULL) delete [] m_data;
541 m_data = new bool[m_size];
542 for (int i = 0; i < m_size; ++i) {
543 m_data[i] = column.m_data[i];
544 }
545 }
546
547 // Copy NULL value
548 alloc_nulval(column.m_nulval);
549
550 // Small memory option: release column if it was fetch above
551 #if defined(G_SMALL_MEMORY)
552 if (not_loaded) {
553 const_cast<GFitsTableBoolCol*>(&column)->release_data();
554 }
555 #endif
556
557 // Return
558 return;
559}
560
561
562/***********************************************************************//**
563 * @brief Delete class members
564 ***************************************************************************/
566{
567 // Free memory
568 if (m_data != NULL) delete [] m_data;
569 if (m_nulval != NULL) delete m_nulval;
570
571 // Mark memory as freed
572 m_data = NULL;
573 m_nulval = NULL;
574
575 // Reset load flag
576 m_size = 0;
577
578 // Free buffer
579 free_buffer();
580
581 // Return
582 return;
583}
584
585
586/***********************************************************************//**
587 * @brief Save table column into FITS file
588 *
589 * The table column is only saved if it is linked to a FITS file and if the
590 * data are indeed present in the class instance. This avoids saving of data
591 * that have not been modified.
592 *
593 * Refer to GFitsTableCol::save_column() for more information.
594 ***************************************************************************/
596{
597 // Free buffer
598 free_buffer();
599
600 // Allocate buffer
601 alloc_buffer();
602
603 // Transfer string into buffer
604 for (int i = 0; i < m_size; ++i) {
605 m_buffer[i] = (char)m_data[i];
606 }
607
608 // Save column
609 save_column();
610
611 // Free buffer
612 free_buffer();
613
614 // Return
615 return;
616}
617
618
619/***********************************************************************//**
620 * @brief Returns format string of ASCII table
621 ***************************************************************************/
622std::string GFitsTableBoolCol::ascii_format(void) const
623{
624 // Initialize format string
625 std::string format;
626
627 // Set type code
628 format.append("L");
629
630 // Set width
631 format.append(gammalib::str(m_width));
632
633 // Return format
634 return format;
635}
636
637
638/***********************************************************************//**
639 * @brief Allocates column data
640 ***************************************************************************/
642{
643 // Free any existing memory
644 if (m_data != NULL) delete [] m_data;
645
646 // Mark pointer as free
647 m_data = NULL;
648
649 // Allocate new data
650 if (m_size > 0) {
651 m_data = new bool[m_size];
652 }
653
654 // Allocate also buffer
655 free_buffer();
656 alloc_buffer();
657
658 // Return
659 return;
660}
661
662
663/***********************************************************************//**
664 * @brief Fetch column data
665 *
666 * If a FITS file is attached to the column the data are loaded into memory
667 * from the FITS file. If no FITS file is attached, memory is allocated
668 * to hold the column data and all cells are set to 0.
669 *
670 * Refer to GFitsTableCol::load_column for more information.
671 ***************************************************************************/
673{
674 // Load column
675 const_cast<GFitsTableBoolCol*>(this)->load_column();
676
677 // Extract values from buffer
678 for (int i = 0; i < m_size; ++i) {
679 m_data[i] = (bool)m_buffer[i];
680 }
681
682 // Free buffer memory
683 free_buffer();
684
685 // Return
686 return;
687}
688
689
690/***********************************************************************//**
691 * @brief Resize column data
692 *
693 * @param[in] index Start index.
694 * @param[in] number Number of elements to add/remove.
695 *
696 * Adds or removes elements from specified index on. Adding is done if
697 * @p number is a positive number, removing if @p number is negative.
698 * Note that the method does not change the validity of the arguments.
699 * This needs to be done by the client.
700 ***************************************************************************/
701void GFitsTableBoolCol::resize_data(const int& index, const int& number)
702{
703 // Continue only if number of elements is not zero
704 if (number != 0) {
705
706 // If data are not available then load them now
707 if (m_data == NULL) fetch_data();
708
709 // If elements should be removed then do not allocate new memory
710 // but just move elements forward and change the logical size of
711 // memory. Only if all elements should be removed the memory is
712 // released.
713 if (number < 0) {
714 if (m_data != NULL) {
715 int left = index - number;
716 bool* dst = m_data + index;
717 bool* src = m_data + left;
718 int num = m_size - left;
719 for (int i = 0; i < num; ++i) {
720 *dst++ = *src++;
721 }
722 m_size += number;
723 if (m_size < 1) {
724 release_data();
725 }
726 }
727 }
728
729 // If elements should be added then allocate new memory, copy over
730 // the old data and initialise the new elements
731 else {
732 int left = m_size - index;
733 m_size += number;
734 bool* new_data = new bool[m_size];
735 bool* dst = new_data;
736 bool* src = m_data;
737 for (int i = 0; i < index; ++i) {
738 *dst++ = *src++;
739 }
740 for (int i = 0; i < number; ++i) {
741 *dst++ = false;
742 }
743 for (int i = 0; i < left; ++i) {
744 *dst++ = *src++;
745 }
746 if (m_data != NULL) delete [] m_data;
747 m_data = new_data;
748 }
749
750 } // endif: number was non-zero
751
752 // Return
753 return;
754}
755
756
757/***********************************************************************//**
758 * @brief Release column data
759 ***************************************************************************/
761{
762 // Free any existing memory
763 if (m_data != NULL) delete [] m_data;
764
765 // Mark pointer as free and reset loaded vector size
766 m_data = NULL;
767 m_size = 0;
768
769 // Return
770 return;
771}
772
773
774/***********************************************************************//**
775 * @brief Allocate null value
776 ***************************************************************************/
777void GFitsTableBoolCol::alloc_nulval(const bool* value)
778{
779 // Free any existing memory
780 if (m_nulval != NULL) delete m_nulval;
781
782 // Mark pointer as free
783 m_nulval = NULL;
784
785 // If we have valid value, allocate and set null value
786 if (value != NULL) {
787 m_nulval = new bool;
788 *m_nulval = *value;
789 }
790
791 // Return
792 return;
793}
794
795
796/***********************************************************************//**
797 * @brief Initialise column data
798 ***************************************************************************/
800{
801 // Initialise data if they exist
802 if (m_data != NULL) {
803 for (int i = 0; i < m_size; ++i) {
804 m_data[i] = false;
805 }
806 }
807
808 // Return
809 return;
810}
811
812
813/***********************************************************************//**
814 * @brief Allocate CFITSIO transfer buffer
815 *
816 * The CFITSIO transfer buffer allows transparent conversion from the CFITSIO
817 * storage format to a vector of bool values.
818 ***************************************************************************/
820{
821 // Allocate and initialise buffer memory
822 if (m_size > 0) {
823 m_buffer = new char[m_size];
824 for (int i = 0; i < m_size; ++i) {
825 m_buffer[i] = 0;
826 }
827 }
828
829 // Return
830 return;
831}
832
833
834/***********************************************************************//**
835 * @brief Free CFITSIO transfer buffer
836 *
837 * Release memory that has been allocated for the CFITSIO transfer buffer.
838 ***************************************************************************/
840{
841 // Free buffer
842 if (m_buffer != NULL) delete [] m_buffer;
843
844 // Mark buffer as free
845 m_buffer = NULL;
846
847 // Return
848 return;
849}
Exception handler interface definition.
CFITSIO interface header.
#define __TLOGICAL
#define G_INSERT
#define G_REMOVE
FITS table Boolean column class interface definition.
Gammalib tools definition.
FITS table Boolean column.
void copy_members(const GFitsTableBoolCol &column)
Copy class members.
virtual void init_data(void)
Initialise column data.
virtual std::string string(const int &row, const int &col=0) const
Get string value.
void free_members(void)
Delete class members.
void init_members(void)
Initialise class members.
virtual void clear(void)
Clear instance.
bool * m_data
Data area.
char * m_buffer
Data area for CFITSIO transfer.
virtual void save(void)
Save table column into FITS file.
virtual GFitsTableBoolCol * clone(void) const
Clone column.
virtual void remove(const int &row, const int &nrows)
Remove rows from column.
virtual void insert(const int &row, const int &nrows)
Insert rows in column.
virtual ~GFitsTableBoolCol(void)
Destructor.
GFitsTableBoolCol & operator=(const GFitsTableBoolCol &column)
Assignment operator.
bool * m_nulval
NULL value.
virtual void release_data(void)
Release column data.
bool & operator()(const int &row, const int &inx=0)
Column data access operator.
virtual void alloc_data(void)
Allocates column data.
bool * nulval(void)
Returns pointer to nul value.
GFitsTableBoolCol(void)
Constructor.
virtual void resize_data(const int &index, const int &number)
Resize column data.
void alloc_buffer(void) const
Allocate CFITSIO transfer buffer.
void alloc_nulval(const bool *value)
Allocate null value.
void free_buffer(void) const
Free CFITSIO transfer buffer.
virtual void fetch_data(void) const
Fetch column data.
virtual bool is_loaded(void) const
Checks if column has been loaded.
virtual int integer(const int &row, const int &col=0) const
Get integer value.
virtual std::string ascii_format(void) const
Returns format string of ASCII table.
virtual double real(const int &row, const int &col=0) const
Get double precision value.
Abstract interface for FITS table column.
int m_type
Column type.
int m_length
Length of column (number of rows)
const int & nrows(void) const
Returns number of rows in column.
std::vector< int > m_rowstart
Start index of each row.
int m_size
Size of allocated data area (0 if not loaded)
int m_width
Width in Bytes of single column element.
int m_varlen
Maximum number of elements in variable-length.
GFitsTableCol & operator=(const GFitsTableCol &column)
Assignment operator.
const int & number(void) const
Returns number of elements in column.
void free_members(void)
Delete class members.
virtual void save_column(void)
Save table column into FITS file.
virtual void load_column(void)
Load table column from FITS file.
void init_members(void)
Initialise class members.
virtual int offset(const int &row, const int &inx) const
Compute offset of column element in memory.
int m_number
Number of elements in column.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489