GammaLib  2.1.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-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
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::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  ***************************************************************************/
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::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  ***************************************************************************/
387 void 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
396  if (nrows < 0 || nrows > m_length-row) {
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  ***************************************************************************/
476 void 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
504  m_type = __TLOGICAL;
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  ***************************************************************************/
622 std::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  ***************************************************************************/
701 void 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  ***************************************************************************/
777 void 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 }
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:1167
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:1070
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:489