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