GammaLib  1.7.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GFitsTableBoolCol.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GFitsTableBoolCol.cpp - FITS table boolean column class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2010-2017 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
60  init_members();
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  ***************************************************************************/
74 GFitsTableBoolCol::GFitsTableBoolCol(const std::string& name,
75  const int& nrows,
76  const int& size) :
77  GFitsTableCol(name, nrows, size, 1)
78 {
79  // Initialise class members for clean destruction
80  init_members();
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
96  init_members();
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  ***************************************************************************/
163 bool& 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  ***************************************************************************/
181 const 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  ***************************************************************************/
234 std::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  ***************************************************************************/
255 double 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  ***************************************************************************/
276 int 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::fits_invalid_row
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  ***************************************************************************/
301 void 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::fits_invalid_row(G_INSERT, row, m_length);
306  }
307 
308  // Continue only if there are rows to be inserted
309  if (nrows > 0) {
310 
311  // If we have no rows yet then simply set the length to the
312  // number of rows to be inserted
313  if (m_length == 0) {
314  m_length = nrows;
316  alloc_data();
317  init_data();
318  }
319 
320  // ... otherwise fetch data, allocate new data and copy over
321  // the existing items
322  else {
323 
324  // If data are not available then load them now
325  if (m_data == NULL) fetch_data();
326 
327  // Compute new column length
328  int length = m_length + nrows;
329 
330  // Calculate size of new memory
331  m_size = m_number * length;
332 
333  // Allocate new data to hold the column
334  bool* new_data = new bool[m_size];
335 
336  // Compute the number of elements before the insertion point,
337  // the number of elements that get inserted, and the total
338  // number of elements after the insertion point
339  int n_before = m_number * row;
340  int n_insert = m_number * nrows;
341  int n_after = m_number * (m_length - row);
342 
343  // Copy and initialise data
344  bool* src = m_data;
345  bool* dst = new_data;
346  for (int i = 0; i < n_before; ++i) {
347  *dst++ = *src++;
348  }
349  for (int i = 0; i < n_insert; ++i) {
350  *dst++ = 0;
351  }
352  for (int i = 0; i < n_after; ++i) {
353  *dst++ = *src++;
354  }
355 
356  // Free old data
357  if (m_data != NULL) delete [] m_data;
358 
359  // Set pointer to new data and store length
360  m_data = new_data;
361  m_length = length;
362 
363  } // endelse: there were already data
364 
365  } // endfor: there were rows to be inserted
366 
367  // Return
368  return;
369 }
370 
371 
372 /***********************************************************************//**
373  * @brief Remove rows from column
374  *
375  * @param[in] row Row after which rows should be removed (0=first row).
376  * @param[in] nrows Number of rows to be removed.
377  *
378  * @exception GException::fits_invalid_row
379  * Specified row is invalid.
380  * @exception GException::fits_invalid_nrows
381  * Invalid number of rows specified.
382  *
383  * This method removes rows from a FITS table. This implies that the column
384  * will be loaded into memory.
385  ***************************************************************************/
386 void GFitsTableBoolCol::remove(const int& row, const int& nrows)
387 {
388  // Make sure that row is valid
389  if (row < 0 || row >= m_length) {
391  }
392 
393  // Make sure that we don't remove beyond the limit
394  if (nrows < 0 || nrows > m_length-row) {
396  }
397 
398  // Continue only if there are rows to be removed
399  if (nrows > 0) {
400 
401  // If data are not available then load them now
402  if (m_data == NULL) fetch_data();
403 
404  // Compute new column length
405  int length = m_length - nrows;
406 
407  // Calculate size of new memory
408  m_size = m_number * length;
409 
410  // If we have rows remaining then allocate new data to hold
411  // the column
412  if (m_size > 0) {
413 
414  // Allocate new data to hold the column
415  bool* new_data = new bool[m_size];
416 
417  // Compute the number of elements before the removal point,
418  // the number of elements that get removed, and the total
419  // number of elements after the removal point
420  int n_before = m_number * row;
421  int n_remove = m_number * nrows;
422  int n_after = m_number * (length - row);
423 
424  // Copy data
425  bool* src = m_data;
426  bool* dst = new_data;
427  for (int i = 0; i < n_before; ++i) {
428  *dst++ = *src++;
429  }
430  src += n_remove;
431  for (int i = 0; i < n_after; ++i) {
432  *dst++ = *src++;
433  }
434 
435  // Free old data
436  if (m_data != NULL) delete [] m_data;
437 
438  // Set pointer to new data and store length
439  m_data = new_data;
440  m_length = length;
441 
442  } // endif: there are still elements after removal
443 
444  // ... otherwise just remove all data
445  else {
446 
447  // Free old data
448  if (m_data != NULL) delete [] m_data;
449 
450  // Set pointer to new data and store length
451  m_data = NULL;
452  m_length = length;
453  }
454 
455  } // endfor: there were rows to be removed
456 
457  // Return
458  return;
459 }
460 
461 
462 /***********************************************************************//**
463  * @brief Set nul value
464  *
465  * @param[in] value Nul value.
466  *
467  * @todo To correctly reflect the nul value in the data, the column should
468  * be reloaded. However, the column may have been changed, so in principle
469  * saving is needed. However, we may not want to store the data, hence saving
470  * is also not desired. We thus have to develop a method to update the
471  * column information for a new nul value in place ...
472  ***************************************************************************/
473 void GFitsTableBoolCol::nulval(const bool* value)
474 {
475  // Allocate nul value
476  alloc_nulval(value);
477 
478  // Update column
479 // if (m_data != NULL) {
480 // save();
481 // load();
482 // }
483 
484  // Return
485  return;
486 }
487 
488 
489 /*==========================================================================
490  = =
491  = Private methods =
492  = =
493  ==========================================================================*/
494 
495 /***********************************************************************//**
496  * @brief Initialise class members
497  ***************************************************************************/
499 {
500  // Initialise members
501  m_type = __TLOGICAL;
502  m_data = NULL;
503  m_buffer = NULL;
504  m_nulval = NULL;
505 
506  // Return
507  return;
508 }
509 
510 
511 /***********************************************************************//**
512  * @brief Copy class members
513  *
514  * @param[in] column Column.
515  *
516  * Sets the content of the vector column by copying from another column.
517  * If the code is compiled with the small memory option, and if the source
518  * column has not yet been loaded, then we only load the column temporarily
519  * for copying purposes and release it again once copying is finished.
520  ***************************************************************************/
522 {
523  // Fetch data if necessary
524  bool not_loaded = (!column.is_loaded());
525  if (not_loaded) {
526  column.fetch_data();
527  }
528 
529  // Copy attributes
530  m_type = column.m_type;
531  m_size = column.m_size;
532  m_varlen = column.m_varlen;
533  m_rowstart = column.m_rowstart;
534 
535  // Copy column data
536  if (column.m_data != NULL && m_size > 0) {
537  if (m_data != NULL) delete [] m_data;
538  m_data = new bool[m_size];
539  for (int i = 0; i < m_size; ++i) {
540  m_data[i] = column.m_data[i];
541  }
542  }
543 
544  // Copy NULL value
545  alloc_nulval(column.m_nulval);
546 
547  // Small memory option: release column if it was fetch above
548  #if defined(G_SMALL_MEMORY)
549  if (not_loaded) {
550  const_cast<GFitsTableBoolCol*>(&column)->release_data();
551  }
552  #endif
553 
554  // Return
555  return;
556 }
557 
558 
559 /***********************************************************************//**
560  * @brief Delete class members
561  ***************************************************************************/
563 {
564  // Free memory
565  if (m_data != NULL) delete [] m_data;
566  if (m_nulval != NULL) delete m_nulval;
567 
568  // Mark memory as freed
569  m_data = NULL;
570  m_nulval = NULL;
571 
572  // Reset load flag
573  m_size = 0;
574 
575  // Free buffer
576  free_buffer();
577 
578  // Return
579  return;
580 }
581 
582 
583 /***********************************************************************//**
584  * @brief Save table column into FITS file
585  *
586  * The table column is only saved if it is linked to a FITS file and if the
587  * data are indeed present in the class instance. This avoids saving of data
588  * that have not been modified.
589  *
590  * Refer to GFitsTableCol::save_column() for more information.
591  ***************************************************************************/
593 {
594  // Free buffer
595  free_buffer();
596 
597  // Allocate buffer
598  alloc_buffer();
599 
600  // Transfer string into buffer
601  for (int i = 0; i < m_size; ++i) {
602  m_buffer[i] = (char)m_data[i];
603  }
604 
605  // Save column
606  save_column();
607 
608  // Free buffer
609  free_buffer();
610 
611  // Return
612  return;
613 }
614 
615 
616 /***********************************************************************//**
617  * @brief Returns format string of ASCII table
618  ***************************************************************************/
619 std::string GFitsTableBoolCol::ascii_format(void) const
620 {
621  // Initialize format string
622  std::string format;
623 
624  // Set type code
625  format.append("L");
626 
627  // Set width
628  format.append(gammalib::str(m_width));
629 
630  // Return format
631  return format;
632 }
633 
634 
635 /***********************************************************************//**
636  * @brief Allocates column data
637  ***************************************************************************/
639 {
640  // Free any existing memory
641  if (m_data != NULL) delete [] m_data;
642 
643  // Mark pointer as free
644  m_data = NULL;
645 
646  // Allocate new data
647  if (m_size > 0) {
648  m_data = new bool[m_size];
649  }
650 
651  // Allocate also buffer
652  free_buffer();
653  alloc_buffer();
654 
655  // Return
656  return;
657 }
658 
659 
660 /***********************************************************************//**
661  * @brief Fetch column data
662  *
663  * If a FITS file is attached to the column the data are loaded into memory
664  * from the FITS file. If no FITS file is attached, memory is allocated
665  * to hold the column data and all cells are set to 0.
666  *
667  * Refer to GFitsTableCol::load_column for more information.
668  ***************************************************************************/
670 {
671  // Load column
672  const_cast<GFitsTableBoolCol*>(this)->load_column();
673 
674  // Extract values from buffer
675  for (int i = 0; i < m_size; ++i) {
676  m_data[i] = (bool)m_buffer[i];
677  }
678 
679  // Free buffer memory
680  free_buffer();
681 
682  // Return
683  return;
684 }
685 
686 
687 /***********************************************************************//**
688  * @brief Resize column data
689  *
690  * @param[in] index Start index.
691  * @param[in] number Number of elements to add/remove.
692  *
693  * Adds or removes elements from specified index on. Adding is done if
694  * @p number is a positive number, removing if @p number is negative.
695  * Note that the method does not change the validity of the arguments.
696  * This needs to be done by the client.
697  ***************************************************************************/
698 void GFitsTableBoolCol::resize_data(const int& index, const int& number)
699 {
700  // Continue only if number of elements is not zero
701  if (number != 0) {
702 
703  // If data are not available then load them now
704  if (m_data == NULL) fetch_data();
705 
706  // If elements should be removed then do not allocate new memory
707  // but just move elements forward and change the logical size of
708  // memory. Only if all elements should be removed the memory is
709  // released.
710  if (number < 0) {
711  if (m_data != NULL) {
712  int left = index - number;
713  bool* dst = m_data + index;
714  bool* src = m_data + left;
715  int num = m_size - left;
716  for (int i = 0; i < num; ++i) {
717  *dst++ = *src++;
718  }
719  m_size += number;
720  if (m_size < 1) {
721  release_data();
722  }
723  }
724  }
725 
726  // If elements should be added then allocate new memory, copy over
727  // the old data and initialise the new elements
728  else {
729  int left = m_size - index;
730  m_size += number;
731  bool* new_data = new bool[m_size];
732  bool* dst = new_data;
733  bool* src = m_data;
734  for (int i = 0; i < index; ++i) {
735  *dst++ = *src++;
736  }
737  for (int i = 0; i < number; ++i) {
738  *dst++ = false;
739  }
740  for (int i = 0; i < left; ++i) {
741  *dst++ = *src++;
742  }
743  if (m_data != NULL) delete [] m_data;
744  m_data = new_data;
745  }
746 
747  } // endif: number was non-zero
748 
749  // Return
750  return;
751 }
752 
753 
754 /***********************************************************************//**
755  * @brief Release column data
756  ***************************************************************************/
758 {
759  // Free any existing memory
760  if (m_data != NULL) delete [] m_data;
761 
762  // Mark pointer as free and reset loaded vector size
763  m_data = NULL;
764  m_size = 0;
765 
766  // Return
767  return;
768 }
769 
770 
771 /***********************************************************************//**
772  * @brief Allocate null value
773  ***************************************************************************/
774 void GFitsTableBoolCol::alloc_nulval(const bool* value)
775 {
776  // Free any existing memory
777  if (m_nulval != NULL) delete m_nulval;
778 
779  // Mark pointer as free
780  m_nulval = NULL;
781 
782  // If we have valid value, allocate and set null value
783  if (value != NULL) {
784  m_nulval = new bool;
785  *m_nulval = *value;
786  }
787 
788  // Return
789  return;
790 }
791 
792 
793 /***********************************************************************//**
794  * @brief Initialise column data
795  ***************************************************************************/
797 {
798  // Initialise data if they exist
799  if (m_data != NULL) {
800  for (int i = 0; i < m_size; ++i) {
801  m_data[i] = false;
802  }
803  }
804 
805  // Return
806  return;
807 }
808 
809 
810 /***********************************************************************//**
811  * @brief Allocate CFITSIO transfer buffer
812  *
813  * The CFITSIO transfer buffer allows transparent conversion from the CFITSIO
814  * storage format to a vector of bool values.
815  ***************************************************************************/
817 {
818  // Allocate and initialise buffer memory
819  if (m_size > 0) {
820  m_buffer = new char[m_size];
821  for (int i = 0; i < m_size; ++i) {
822  m_buffer[i] = 0;
823  }
824  }
825 
826  // Return
827  return;
828 }
829 
830 
831 /***********************************************************************//**
832  * @brief Free CFITSIO transfer buffer
833  *
834  * Release memory that has been allocated for the CFITSIO transfer buffer.
835  ***************************************************************************/
837 {
838  // Free buffer
839  if (m_buffer != NULL) delete [] m_buffer;
840 
841  // Mark buffer as free
842  m_buffer = NULL;
843 
844  // Return
845  return;
846 }
FITS table Boolean column class interface definition.
virtual GFitsTableBoolCol * clone(void) const
Clone column.
int m_type
Column type.
#define __TLOGICAL
std::string number(const std::string &noun, const int &number)
Convert singular noun into number noun.
Definition: GTools.cpp:1046
void free_buffer(void) const
Free CFITSIO transfer buffer.
#define G_REMOVE
int m_number
Number of elements in column.
bool * m_data
Data area.
void free_members(void)
Delete class members.
GFitsTableCol & operator=(const GFitsTableCol &column)
Assignment operator.
virtual bool is_loaded(void) const
Checks if column has been loaded.
bool * nulval(void)
Returns pointer to nul value.
int m_varlen
Maximum number of elements in variable-length.
Gammalib tools definition.
GFitsTableBoolCol(void)
Constructor.
void alloc_buffer(void) const
Allocate CFITSIO transfer buffer.
virtual double real(const int &row, const int &col=0) const
Get double precision value.
virtual void load_column(void)
Load table column from FITS file.
GFitsTableBoolCol & operator=(const GFitsTableBoolCol &column)
Assignment operator.
#define G_INSERT
virtual void insert(const int &row, const int &nrows)
Insert rows in column.
virtual std::string ascii_format(void) const
Returns format string of ASCII table.
const int & number(void) const
Returns number of elements in column.
void init_members(void)
Initialise class members.
CFITSIO interface header.
Abstract interface for FITS table column.
std::vector< int > m_rowstart
Start index of each row.
std::string left(const std::string &s, const int &n, const char &c= ' ')
Left justify string to achieve a length of n characters.
Definition: GTools.cpp:949
FITS table Boolean column.
virtual void remove(const int &row, const int &nrows)
Remove rows from column.
bool * m_nulval
NULL value.
bool & operator()(const int &row, const int &inx=0)
Column data access operator.
virtual ~GFitsTableBoolCol(void)
Destructor.
void init_members(void)
Initialise class members.
virtual void release_data(void)
Release column data.
void alloc_nulval(const bool *value)
Allocate null value.
virtual void resize_data(const int &index, const int &number)
Resize column data.
char * m_buffer
Data area for CFITSIO transfer.
int m_length
Length of column (number of rows)
int m_size
Size of allocated data area (0 if not loaded)
virtual int offset(const int &row, const int &inx) const
Compute offset of column element in memory.
virtual void alloc_data(void)
Allocates column data.
Exception handler interface definition.
void copy_members(const GFitsTableBoolCol &column)
Copy class members.
virtual void save_column(void)
Save table column into FITS file.
const int & nrows(void) const
Returns number of rows in column.
virtual int integer(const int &row, const int &col=0) const
Get integer value.
virtual void fetch_data(void) const
Fetch column data.
virtual void save(void)
Save table column into FITS file.
virtual std::string string(const int &row, const int &col=0) const
Get string value.
virtual void init_data(void)
Initialise column data.
void free_members(void)
Delete class members.
virtual void clear(void)
Clear instance.
int m_width
Width in Bytes of single column element.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:413