GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GFitsTableULongCol.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GFitsTableULongCol.cpp - FITS table unsigned long integer 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 GFitsTableULongCol.cpp
23  * @brief FITS table unsigned long integer 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 "GFitsTableULongCol.hpp"
36 
37 /* __ Method name definitions ____________________________________________ */
38 #define G_INSERT "GFitsTableLongCol::insert(int&, int&)"
39 #define G_REMOVE "GFitsTableLongCol::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  ***************************************************************************/
75  const int& nrows,
76  const int& size) :
77  GFitsTableCol(name, nrows, size, 4)
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  ***************************************************************************/
131 {
132  // Execute only if object is not identical
133  if (this != &column) {
134 
135  // Copy base class members
136  this->GFitsTableCol::operator=(column);
137 
138  // Free members
139  free_members();
140 
141  // Initialise private members for clean destruction
142  init_members();
143 
144  // Copy members
145  copy_members(column);
146 
147  } // endif: object was not identical
148 
149  // Return this object
150  return *this;
151 }
152 
153 
154 /***********************************************************************//**
155  * @brief Column data access operator
156  *
157  * @param[in] row Row of column to access.
158  * @param[in] inx Vector index in column row to access.
159  *
160  * Provides access to data in a column.
161  ***************************************************************************/
162 unsigned long& GFitsTableULongCol::operator()(const int& row, const int& inx)
163 {
164  // If data are not available then load them now
165  if (m_data == NULL) fetch_data();
166 
167  // Return data bin
168  return m_data[offset(row, inx)];
169 }
170 
171 
172 /***********************************************************************//**
173  * @brief Column data access operator (const variant)
174  *
175  * @param[in] row Row of column to access.
176  * @param[in] inx Vector index in column row to access.
177  *
178  * Provides access to data in a column.
179  ***************************************************************************/
180 const unsigned long& GFitsTableULongCol::operator()(const int& row, const int& inx) const
181 {
182  // If data are not available then load them now
183  if (m_data == NULL) fetch_data();
184 
185  // Return data bin
186  return m_data[offset(row, inx)];
187 }
188 
189 
190 /*==========================================================================
191  = =
192  = Public methods =
193  = =
194  ==========================================================================*/
195 
196 /***********************************************************************//**
197  * @brief Clear instance
198  *
199  * This method properly resets the object to an initial state.
200  ***************************************************************************/
202 {
203  // Free class members (base and derived classes, derived class first)
204  free_members();
206 
207  // Initialise members
209  init_members();
210 
211  // Return
212  return;
213 }
214 
215 
216 /***********************************************************************//**
217  * @brief Clone column
218  ***************************************************************************/
220 {
221  return new GFitsTableULongCol(*this);
222 }
223 
224 
225 /***********************************************************************//**
226  * @brief Get string value
227  *
228  * @param[in] row Table row.
229  * @param[in] inx Table column vector index.
230  *
231  * Returns value of specified row and vector index as string.
232  ***************************************************************************/
233 std::string GFitsTableULongCol::string(const int& row, const int& inx) const
234 {
235  // If data are not available then load them now
236  if (m_data == NULL) fetch_data();
237 
238  // Return value
239  return (gammalib::str(m_data[offset(row,inx)]));
240 }
241 
242 
243 /***********************************************************************//**
244  * @brief Get double precision value
245  *
246  * @param[in] row Table row.
247  * @param[in] inx Table column vector index.
248  *
249  * Returns value of specified row and vector index as double precision.
250  ***************************************************************************/
251 double GFitsTableULongCol::real(const int& row, const int& inx) const
252 {
253  // If data are not available then load them now
254  if (m_data == NULL) fetch_data();
255 
256  // Convert unsigned long into double
257  double value = (double)m_data[offset(row,inx)];
258 
259  // Return value
260  return value;
261 }
262 
263 
264 /***********************************************************************//**
265  * @brief Get integer value
266  *
267  * @param[in] row Table row.
268  * @param[in] inx Table column vector index.
269  *
270  * Returns value of specified row and vector index as integer.
271  ***************************************************************************/
272 int GFitsTableULongCol::integer(const int& row, const int& inx) const
273 {
274  // If data are not available then load them now
275  if (m_data == NULL) fetch_data();
276 
277  // Convert unsigned long into int
278  int value = (int)m_data[offset(row,inx)];
279 
280  // Return value
281  return value;
282 }
283 
284 
285 /***********************************************************************//**
286  * @brief Insert rows in column
287  *
288  * @param[in] row Row after which rows should be inserted (0=first row).
289  * @param[in] nrows Number of rows to be inserted.
290  *
291  * @exception GException::out_of_range
292  * Specified row is invalid.
293  *
294  * Inserts rows into a FITS table. This implies that all columns will be
295  * loaded into memory.
296  ***************************************************************************/
297 void GFitsTableULongCol::insert(const int& row, const int& nrows)
298 {
299  // Make sure that row is valid
300  if (row < 0 || row > m_length) {
301  throw GException::out_of_range(G_INSERT, "FITS table row number",
302  row, m_length+1);
303  }
304 
305  // Continue only if there are rows to be inserted
306  if (nrows > 0) {
307 
308  // If we have no rows yet then simply set the length to the
309  // number of rows to be inserted
310  if (m_length == 0) {
311  m_length = nrows;
313  alloc_data();
314  init_data();
315  }
316 
317  // ... otherwise fetch data, allocate new data and copy over
318  // the existing items
319  else {
320 
321  // If data are not available then load them now
322  if (m_data == NULL) fetch_data();
323 
324  // Compute new column length
325  int length = m_length + nrows;
326 
327  // Calculate size of new memory
328  m_size = m_number * length;
329 
330  // Allocate new data to hold the column
331  unsigned long* new_data = new unsigned long[m_size];
332 
333  // Compute the number of elements before the insertion point,
334  // the number of elements that get inserted, and the total
335  // number of elements after the insertion point
336  int n_before = m_number * row;
337  int n_insert = m_number * nrows;
338  int n_after = m_number * (m_length - row);
339 
340  // Copy and initialise data
341  unsigned long* src = m_data;
342  unsigned long* dst = new_data;
343  for (int i = 0; i < n_before; ++i) {
344  *dst++ = *src++;
345  }
346  for (int i = 0; i < n_insert; ++i) {
347  *dst++ = 0;
348  }
349  for (int i = 0; i < n_after; ++i) {
350  *dst++ = *src++;
351  }
352 
353  // Free old data
354  if (m_data != NULL) delete [] m_data;
355 
356  // Set pointer to new data and store length
357  m_data = new_data;
358  m_length = length;
359 
360  } // endelse: there were already data
361 
362  } // endfor: there were rows to be inserted
363 
364  // Return
365  return;
366 }
367 
368 
369 /***********************************************************************//**
370  * @brief Remove rows from column
371  *
372  * @param[in] row Row after which rows should be removed (0=first row).
373  * @param[in] nrows Number of rows to be removed.
374  *
375  * @exception GException::out_of_range
376  * Specified row is invalid.
377  * Invalid number of rows specified.
378  *
379  * This method removes rows from a FITS table. This implies that the column
380  * will be loaded into memory.
381  ***************************************************************************/
382 void GFitsTableULongCol::remove(const int& row, const int& nrows)
383 {
384  // Make sure that row is valid
385  if (row < 0 || row >= m_length) {
386  throw GException::out_of_range(G_REMOVE, "FITS table row number",
387  row, m_length);
388  }
389 
390  // Make sure that we don't remove beyond the limit
391  if (nrows < 0 || nrows > m_length-row) {
392  throw GException::out_of_range(G_REMOVE, "Number of FITS table rows",
393  nrows, m_length-row+1);
394  }
395 
396  // Continue only if there are rows to be removed
397  if (nrows > 0) {
398 
399  // If data are not available then load them now
400  if (m_data == NULL) fetch_data();
401 
402  // Compute new column length
403  int length = m_length - nrows;
404 
405  // Calculate size of new memory
406  m_size = m_number * length;
407 
408  // If we have rows remaining then allocate new data to hold
409  // the column
410  if (m_size > 0) {
411 
412  // Allocate new data to hold the column
413  unsigned long* new_data = new unsigned long[m_size];
414 
415  // Compute the number of elements before the removal point,
416  // the number of elements that get removed, and the total
417  // number of elements after the removal point
418  int n_before = m_number * row;
419  int n_remove = m_number * nrows;
420  int n_after = m_number * (length - row);
421 
422  // Copy data
423  unsigned long* src = m_data;
424  unsigned long* dst = new_data;
425  for (int i = 0; i < n_before; ++i) {
426  *dst++ = *src++;
427  }
428  src += n_remove;
429  for (int i = 0; i < n_after; ++i) {
430  *dst++ = *src++;
431  }
432 
433  // Free old data
434  if (m_data != NULL) delete [] m_data;
435 
436  // Set pointer to new data and store length
437  m_data = new_data;
438  m_length = length;
439 
440  } // endif: there are still elements after removal
441 
442  // ... otherwise just remove all data
443  else {
444 
445  // Free old data
446  if (m_data != NULL) delete [] m_data;
447 
448  // Set pointer to new data and store length
449  m_data = NULL;
450  m_length = length;
451  }
452 
453  } // endfor: there were rows to be removed
454 
455  // Return
456  return;
457 }
458 
459 
460 /***********************************************************************//**
461  * @brief Set nul value
462  *
463  * @param[in] value Nul value.
464  *
465  * @todo To correctly reflect the nul value in the data, the column should
466  * be reloaded. However, the column may have been changed, so in principle
467  * saving is needed. However, we may not want to store the data, hence saving
468  * is also not desired. We thus have to develop a method to update the
469  * column information for a new nul value in place ...
470  ***************************************************************************/
471 void GFitsTableULongCol::nulval(const unsigned long* value)
472 {
473  // Allocate nul value
474  alloc_nulval(value);
475 
476  // Update column
477 // if (m_data != NULL) {
478 // save();
479 // load();
480 // }
481 
482  // Return
483  return;
484 }
485 
486 
487 /*==========================================================================
488  = =
489  = Private methods =
490  = =
491  ==========================================================================*/
492 
493 /***********************************************************************//**
494  * @brief Initialise class members
495  ***************************************************************************/
497 {
498  // Initialise members
499  m_type = __TULONG;
500  m_data = NULL;
501  m_nulval = NULL;
502 
503  // Return
504  return;
505 }
506 
507 
508 /***********************************************************************//**
509  * @brief Copy class members
510  *
511  * @param[in] column Column.
512  *
513  * Sets the content of the vector column by copying from another column.
514  * If the code is compiled with the small memory option, and if the source
515  * column has not yet been loaded, then we only load the column temporarily
516  * for copying purposes and release it again once copying is finished.
517  ***************************************************************************/
519 {
520  // Fetch data if necessary
521  bool not_loaded = (!column.is_loaded());
522  if (not_loaded) {
523  column.fetch_data();
524  }
525 
526  // Copy attributes
527  m_type = column.m_type;
528  m_size = column.m_size;
529  m_varlen = column.m_varlen;
530  m_rowstart = column.m_rowstart;
531 
532  // Copy column data
533  if (column.m_data != NULL && m_size > 0) {
534  alloc_data();
535  for (int i = 0; i < m_size; ++i) {
536  m_data[i] = column.m_data[i];
537  }
538  }
539 
540  // Copy NULL value
541  alloc_nulval(column.m_nulval);
542 
543  // Small memory option: release column if it was fetch above
544  #if defined(G_SMALL_MEMORY)
545  if (not_loaded) {
546  const_cast<GFitsTableULongCol*>(&column)->release_data();
547  }
548  #endif
549 
550  // Return
551  return;
552 }
553 
554 
555 /***********************************************************************//**
556  * @brief Delete class members
557  ***************************************************************************/
559 {
560  // Free memory
561  if (m_data != NULL) delete [] m_data;
562  if (m_nulval != NULL) delete m_nulval;
563 
564  // Mark memory as freed
565  m_data = NULL;
566  m_nulval = NULL;
567 
568  // Return
569  return;
570 }
571 
572 
573 /***********************************************************************//**
574  * @brief Returns format string of ASCII table
575  ***************************************************************************/
576 std::string GFitsTableULongCol::ascii_format(void) const
577 {
578  // Initialize format string
579  std::string format;
580 
581  // Set type code
582  format.append("I10");
583 
584  // Set width
585  //format.append(gammalib::str(m_width));
586 
587  // Return format
588  return format;
589 }
590 
591 
592 /***********************************************************************//**
593  * @brief Allocates column data
594  ***************************************************************************/
596 {
597  // Free any existing memory
598  if (m_data != NULL) delete [] m_data;
599 
600  // Mark pointer as free
601  m_data = NULL;
602 
603  // Allocate new data
604  if (m_size > 0) {
605  m_data = new unsigned long[m_size];
606  }
607 
608  // Return
609  return;
610 }
611 
612 
613 /***********************************************************************//**
614  * @brief Fetch column data
615  ***************************************************************************/
617 {
618  // Load column (circumvent const correctness)
619  const_cast<GFitsTableULongCol*>(this)->load_column();
620 
621  // Return
622  return;
623 }
624 
625 
626 /***********************************************************************//**
627  * @brief Resize column data
628  *
629  * @param[in] index Start index.
630  * @param[in] number Number of elements to add/remove.
631  *
632  * Adds or removes elements from specified index on. Adding is done if
633  * @p number is a positive number, removing if @p number is negative.
634  * Note that the method does not change the validity of the arguments.
635  * This needs to be done by the client.
636  ***************************************************************************/
637 void GFitsTableULongCol::resize_data(const int& index, const int& number)
638 {
639  // Continue only if number of elements is not zero
640  if (number != 0) {
641 
642  // If data are not available then load them now
643  if (m_data == NULL) fetch_data();
644 
645  // If elements should be removed then do not allocate new memory
646  // but just move elements forward and change the logical size of
647  // memory. Only if all elements should be removed the memory is
648  // released.
649  if (number < 0) {
650  int left = index - number;
651  unsigned long* dst = m_data + index;
652  unsigned long* src = m_data + left;
653  int num = m_size - left;
654  for (int i = 0; i < num; ++i) {
655  *dst++ = *src++;
656  }
657  m_size += number;
658  if (m_size < 1) {
659  release_data();
660  }
661  }
662 
663  // If elements should be added then allocate new memory, copy over
664  // the old data and initialise the new elements
665  else {
666  int left = m_size - index;
667  m_size += number;
668  unsigned long* new_data = new unsigned long[m_size];
669  unsigned long* dst = new_data;
670  unsigned long* src = m_data;
671  for (int i = 0; i < index; ++i) {
672  *dst++ = *src++;
673  }
674  for (int i = 0; i < number; ++i) {
675  *dst++ = 0;
676  }
677  for (int i = 0; i < left; ++i) {
678  *dst++ = *src++;
679  }
680  if (m_data != NULL) delete [] m_data;
681  m_data = new_data;
682  }
683 
684  } // endif: number was non-zero
685 
686  // Return
687  return;
688 }
689 
690 
691 /***********************************************************************//**
692  * @brief Release column data
693  ***************************************************************************/
695 {
696  // Free any existing memory
697  if (m_data != NULL) delete [] m_data;
698 
699  // Mark pointer as free and reset loaded vector size
700  m_data = NULL;
701  m_size = 0;
702 
703  // Return
704  return;
705 }
706 
707 
708 /***********************************************************************//**
709  * @brief Allocates nul value
710  *
711  * @param[in] value Nul value.
712  ***************************************************************************/
713 void GFitsTableULongCol::alloc_nulval(const unsigned long* value)
714 {
715  // Free any existing memory
716  if (m_nulval != NULL) delete m_nulval;
717 
718  // Mark pointer as free
719  m_nulval = NULL;
720 
721  // If we have valid value, allocate and set nul value
722  if (value != NULL) {
723  m_nulval = new unsigned long;
724  *m_nulval = *value;
725  }
726 
727  // Return
728  return;
729 }
730 
731 
732 /***********************************************************************//**
733  * @brief Initialise column data
734  ***************************************************************************/
736 {
737  // Initialise data if they exist
738  if (m_data != NULL) {
739  for (int i = 0; i < m_size; ++i) {
740  m_data[i] = 0;
741  }
742  }
743 
744  // Return
745  return;
746 }
virtual std::string ascii_format(void) const
Returns format string of ASCII table.
#define G_INSERT
virtual void clear(void)
Clear instance.
#define __TULONG
int m_type
Column type.
std::string number(const std::string &noun, const int &number)
Convert singular noun into number noun.
Definition: GTools.cpp:1167
void alloc_nulval(const unsigned long *value)
Allocates nul value.
FITS table unsigned long integer column class interface definition.
int m_number
Number of elements in column.
unsigned long * nulval(void)
Returns pointer to nul value.
void free_members(void)
Delete class members.
GFitsTableCol & operator=(const GFitsTableCol &column)
Assignment operator.
#define G_REMOVE
GFitsTableULongCol & operator=(const GFitsTableULongCol &column)
Assignment operator.
virtual std::string string(const int &row, const int &col=0) const
Get string value.
virtual double real(const int &row, const int &col=0) const
Get double precision value.
int m_varlen
Maximum number of elements in variable-length.
virtual bool is_loaded(void) const
Checks if column has been loaded.
Gammalib tools definition.
GFitsTableULongCol(void)
Constructor.
virtual void load_column(void)
Load table column from FITS file.
virtual GFitsTableULongCol * clone(void) const
Clone column.
const int & number(void) const
Returns number of elements in column.
unsigned long * m_nulval
NULL value.
void init_members(void)
Initialise class members.
virtual void init_data(void)
Initialise column data.
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
virtual void resize_data(const int &index, const int &number)
Resize column data.
FITS table unsigned long integer column.
virtual void fetch_data(void) const
Fetch column data.
virtual void remove(const int &row, const int &nrows)
Remove rows from column.
virtual void release_data(void)
Release column data.
void free_members(void)
Delete class members.
virtual void alloc_data(void)
Allocates column data.
int m_length
Length of column (number of rows)
virtual void insert(const int &row, const int &nrows)
Insert rows in column.
int m_size
Size of allocated data area (0 if not loaded)
void init_members(void)
Initialise class members.
virtual int offset(const int &row, const int &inx) const
Compute offset of column element in memory.
Exception handler interface definition.
unsigned long & operator()(const int &row, const int &inx=0)
Column data access operator.
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 ~GFitsTableULongCol(void)
Destructor.
unsigned long * m_data
Data vector.
void copy_members(const GFitsTableULongCol &column)
Copy class members.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489