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