GammaLib  1.7.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GFitsTableCDoubleCol.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GFitsTableCDoubleCol.cpp - FITS table double precision complex column *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2010-2017 by Juergen Knoedlseder *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 /**
22  * @file GFitsTableCDoubleCol.cpp
23  * @brief FITS table double 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 "GFitsTableCDoubleCol.hpp"
36 
37 /* __ Method name definitions ____________________________________________ */
38 #define G_INSERT "GFitsTableCDoubleCol::insert(int&, int&)"
39 #define G_REMOVE "GFitsTableCDoubleCol::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::cdouble& GFitsTableCDoubleCol::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 GFitsTableCDoubleCol(*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 GFitsTableCDoubleCol::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 GFitsTableCDoubleCol::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 GFitsTableCDoubleCol::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::fits_invalid_row
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 GFitsTableCDoubleCol::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::fits_invalid_row(G_INSERT, row, m_length);
308  }
309 
310  // Continue only if there are rows to be inserted
311  if (nrows > 0) {
312 
313  // If we have no rows yet then simply set the length to the
314  // number of rows to be inserted
315  if (m_length == 0) {
316  m_length = nrows;
318  alloc_data();
319  init_data();
320  }
321 
322  // ... otherwise fetch data, allocate new data and copy over
323  // the existing items
324  else {
325 
326  // If data are not available then load them now
327  if (m_data == NULL) fetch_data();
328 
329  // Compute new column length
330  int length = m_length + nrows;
331 
332  // Calculate size of new memory
333  m_size = m_number * length;
334 
335  // Allocate new data to hold the column
336  GFits::cdouble* new_data = new GFits::cdouble[m_size];
337 
338  // Compute the number of elements before the insertion point,
339  // the number of elements that get inserted, and the total
340  // number of elements after the insertion point
341  int n_before = m_number * row;
342  int n_insert = m_number * nrows;
343  int n_after = m_number * (m_length - row);
344 
345  // Copy and initialise data
346  GFits::cdouble* src = m_data;
347  GFits::cdouble* dst = new_data;
348  for (int i = 0; i < n_before; ++i) {
349  *dst++ = *src++;
350  }
351  for (int i = 0; i < n_insert; ++i) {
352  dst->re = 0.0;
353  dst->im = 0.0;
354  dst++;
355  }
356  for (int i = 0; i < n_after; ++i) {
357  *dst++ = *src++;
358  }
359 
360  // Free old data
361  if (m_data != NULL) delete [] m_data;
362 
363  // Set pointer to new data and store length
364  m_data = new_data;
365  m_length = length;
366 
367  } // endelse: there were already data
368 
369  } // endfor: there were rows to be inserted
370 
371  // Return
372  return;
373 }
374 
375 
376 /***********************************************************************//**
377  * @brief Remove rows from column
378  *
379  * @param[in] row Row after which rows should be removed (0=first row).
380  * @param[in] nrows Number of rows to be removed.
381  *
382  * @exception GException::fits_invalid_row
383  * Specified row is invalid.
384  * @exception GException::fits_invalid_nrows
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 GFitsTableCDoubleCol::remove(const int& row, const int& nrows)
391 {
392  // Make sure that row is valid
393  if (row < 0 || row >= m_length) {
395  }
396 
397  // Make sure that we don't remove beyond the limit
398  if (nrows < 0 || nrows > m_length-row) {
400  }
401 
402  // Continue only if there are rows to be removed
403  if (nrows > 0) {
404 
405  // If data are not available then load them now
406  if (m_data == NULL) fetch_data();
407 
408  // Compute new column length
409  int length = m_length - nrows;
410 
411  // Calculate size of new memory
412  m_size = m_number * length;
413 
414  // If we have rows remaining then allocate new data to hold
415  // the column
416  if (m_size > 0) {
417 
418  // Allocate new data to hold the column
419  GFits::cdouble* new_data = new GFits::cdouble[m_size];
420 
421  // Compute the number of elements before the removal point,
422  // the number of elements that get removed, and the total
423  // number of elements after the removal point
424  int n_before = m_number * row;
425  int n_remove = m_number * nrows;
426  int n_after = m_number * (length - row);
427 
428  // Copy data
429  GFits::cdouble* src = m_data;
430  GFits::cdouble* dst = new_data;
431  for (int i = 0; i < n_before; ++i) {
432  *dst++ = *src++;
433  }
434  src += n_remove;
435  for (int i = 0; i < n_after; ++i) {
436  *dst++ = *src++;
437  }
438 
439  // Free old data
440  if (m_data != NULL) delete [] m_data;
441 
442  // Set pointer to new data and store length
443  m_data = new_data;
444  m_length = length;
445 
446  } // endif: there are still elements after removal
447 
448  // ... otherwise just remove all data
449  else {
450 
451  // Free old data
452  if (m_data != NULL) delete [] m_data;
453 
454  // Set pointer to new data and store length
455  m_data = NULL;
456  m_length = length;
457  }
458 
459  } // endfor: there were rows to be removed
460 
461  // Return
462  return;
463 }
464 
465 
466 /***********************************************************************//**
467  * @brief Set nul value
468  *
469  * @param[in] value Nul value.
470  *
471  * @todo To correctly reflect the nul value in the data, the column should
472  * be reloaded. However, the column may have been changed, so in principle
473  * saving is needed. However, we may not want to store the data, hence saving
474  * is also not desired. We thus have to develop a method to update the
475  * column information for a new nul value in place ...
476  ***************************************************************************/
478 {
479  // Allocate nul value
480  alloc_nulval(value);
481 
482  // Update column
483 // if (m_data != NULL) {
484 // save();
485 // load();
486 // }
487 
488  // Return
489  return;
490 }
491 
492 
493 /*==========================================================================
494  = =
495  = Private methods =
496  = =
497  ==========================================================================*/
498 
499 /***********************************************************************//**
500  * @brief Initialise class members
501  ***************************************************************************/
503 {
504  // Initialise members
506  m_data = NULL;
507  m_nulval = NULL;
508 
509  // Return
510  return;
511 }
512 
513 
514 /***********************************************************************//**
515  * @brief Copy class members
516  *
517  * @param[in] column Table 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  alloc_data();
541  for (int i = 0; i < m_size; ++i) {
542  m_data[i] = column.m_data[i];
543  }
544  }
545 
546  // Copy NULL value
547  alloc_nulval(column.m_nulval);
548 
549  // Small memory option: release column if it was fetch above
550  #if defined(G_SMALL_MEMORY)
551  if (not_loaded) {
552  const_cast<GFitsTableCDoubleCol*>(&column)->release_data();
553  }
554  #endif
555 
556  // Return
557  return;
558 }
559 
560 
561 /***********************************************************************//**
562  * @brief Delete class members
563  ***************************************************************************/
565 {
566  // Free memory
567  if (m_data != NULL) delete [] m_data;
568  if (m_nulval != NULL) delete m_nulval;
569 
570  // Mark memory as freed
571  m_data = NULL;
572  m_nulval = NULL;
573 
574  // Reset load flag
575  m_size = 0;
576 
577  // Return
578  return;
579 }
580 
581 
582 /***********************************************************************//**
583  * @brief Returns format string of ASCII table
584  ***************************************************************************/
585 std::string GFitsTableCDoubleCol::ascii_format(void) const
586 {
587  // Initialize format string
588  std::string format;
589 
590  // Set type code
591  format.append("M");
592 
593  // Set width
594  format.append(gammalib::str(m_width));
595 
596  // Return format
597  return format;
598 }
599 
600 
601 /***********************************************************************//**
602  * @brief Allocates column data
603  ***************************************************************************/
605 {
606  // Free any existing memory
607  if (m_data != NULL) delete [] m_data;
608 
609  // Mark pointer as free
610  m_data = NULL;
611 
612  // Allocate new data
613  if (m_size > 0) {
615  }
616 
617  // Return
618  return;
619 }
620 
621 
622 /***********************************************************************//**
623  * @brief Fetch column data
624  ***************************************************************************/
626 {
627  // Load column (circumvent const correctness)
628  const_cast<GFitsTableCDoubleCol*>(this)->load_column();
629 
630  // Return
631  return;
632 }
633 
634 
635 /***********************************************************************//**
636  * @brief Resize column data
637  *
638  * @param[in] index Start index.
639  * @param[in] number Number of elements to add/remove.
640  *
641  * Adds or removes elements from specified index on. Adding is done if
642  * @p number is a positive number, removing if @p number is negative.
643  * Note that the method does not change the validity of the arguments.
644  * This needs to be done by the client.
645  ***************************************************************************/
646 void GFitsTableCDoubleCol::resize_data(const int& index, const int& number)
647 {
648  // Continue only if number of elements is not zero
649  if (number != 0) {
650 
651  // If data are not available then load them now
652  if (m_data == NULL) fetch_data();
653 
654  // If elements should be removed then do not allocate new memory
655  // but just move elements forward and change the logical size of
656  // memory. Only if all elements should be removed the memory is
657  // released.
658  if (number < 0) {
659  int left = index - number;
660  GFits::cdouble* dst = m_data + index;
661  GFits::cdouble* src = m_data + left;
662  int num = m_size - left;
663  for (int i = 0; i < num; ++i) {
664  *dst++ = *src++;
665  }
666  m_size += number;
667  if (m_size < 1) {
668  release_data();
669  }
670  }
671 
672  // If elements should be added then allocate new memory, copy over
673  // the old data and initialise the new elements
674  else {
675  int left = m_size - index;
676  m_size += number;
677  GFits::cdouble* new_data = new GFits::cdouble[m_size];
678  GFits::cdouble* dst = new_data;
679  GFits::cdouble* src = m_data;
680  for (int i = 0; i < index; ++i) {
681  *dst++ = *src++;
682  }
683  for (int i = 0; i < number; ++i) {
684  dst->re = 0.0;
685  dst->im = 0.0;
686  dst++;
687  }
688  for (int i = 0; i < left; ++i) {
689  *dst++ = *src++;
690  }
691  if (m_data != NULL) delete [] m_data;
692  m_data = new_data;
693  }
694 
695  } // endif: number was non-zero
696 
697  // Return
698  return;
699 }
700 
701 
702 /***********************************************************************//**
703  * @brief Release column data
704  ***************************************************************************/
706 {
707  // Free any existing memory
708  if (m_data != NULL) delete [] m_data;
709 
710  // Mark pointer as free and reset loaded vector size
711  m_data = NULL;
712  m_size = 0;
713 
714  // Return
715  return;
716 }
717 
718 
719 /***********************************************************************//**
720  * @brief Allocates null value
721  ***************************************************************************/
723 {
724  // Free any existing memory
725  if (m_nulval != NULL) delete m_nulval;
726 
727  // Mark pointer as free
728  m_nulval = NULL;
729 
730  // If we have valid value, allocate and set nul value
731  if (value != NULL) {
732  m_nulval = new GFits::cdouble;
733  *m_nulval = *value;
734  }
735 
736  // Return
737  return;
738 }
739 
740 
741 /***********************************************************************//**
742  * @brief Initialise column data
743  ***************************************************************************/
745 {
746  // Initialise data if they exist
747  if (m_data != NULL) {
748  for (int i = 0; i < m_size; ++i) {
749  m_data[i].re = 0.0;
750  m_data[i].im = 0.0;
751  }
752  }
753 
754  // Return
755  return;
756 }
virtual void insert(const int &row, const int &nrows)
Insert rows in column.
virtual std::string string(const int &row, const int &col=0) const
Get string value.
int m_type
Column type.
std::string number(const std::string &noun, const int &number)
Convert singular noun into number noun.
Definition: GTools.cpp:1046
int m_number
Number of elements in column.
void free_members(void)
Delete class members.
GFitsTableCol & operator=(const GFitsTableCol &column)
Assignment operator.
FITS table double complex column.
int m_varlen
Maximum number of elements in variable-length.
GFitsTableCDoubleCol(void)
Constructor.
Gammalib tools definition.
virtual void resize_data(const int &index, const int &number)
Resize column data.
virtual int integer(const int &row, const int &col=0) const
Get integer value (real part)
#define __TDBLCOMPLEX
#define G_INSERT
virtual void load_column(void)
Load table column from FITS file.
GFits::cdouble * m_nulval
NULL value.
const int & number(void) const
Returns number of elements in column.
virtual void fetch_data(void) const
Fetch column data.
void init_members(void)
Initialise class members.
CFITSIO interface header.
Abstract interface for FITS table column.
GFits::cdouble & operator()(const int &row, const int &inx=0)
Column data access operator.
std::vector< int > m_rowstart
Start index of each row.
std::string left(const std::string &s, const int &n, const char &c= ' ')
Left justify string to achieve a length of n characters.
Definition: GTools.cpp:949
virtual std::string ascii_format(void) const
Returns format string of ASCII table.
virtual void remove(const int &row, const int &nrows)
Remove rows from column.
virtual GFitsTableCDoubleCol * clone(void) const
Clone column.
GFitsTableCDoubleCol & operator=(const GFitsTableCDoubleCol &column)
Assignment operator.
virtual void alloc_data(void)
Allocates column data.
FITS table double complex column class interface definition.
GFits::cdouble * m_data
Data vector.
virtual double real(const int &row, const int &col=0) const
Get double precision value (real part)
int m_length
Length of column (number of rows)
virtual ~GFitsTableCDoubleCol(void)
Destructor.
GFits::cdouble * nulval(void)
Returns pointer to nul value.
int m_size
Size of allocated data area (0 if not loaded)
virtual bool is_loaded(void) const
Checks if column has been loaded.
virtual int offset(const int &row, const int &inx) const
Compute offset of column element in memory.
void free_members(void)
Delete class members.
Exception handler interface definition.
virtual void init_data(void)
Initialise column data.
virtual void release_data(void)
Release column data.
void copy_members(const GFitsTableCDoubleCol &column)
Copy class members.
virtual void clear(void)
Clear instance.
void alloc_nulval(const GFits::cdouble *value)
Allocates null value.
const int & nrows(void) const
Returns number of rows in column.
void init_members(void)
Initialise class members.
#define G_REMOVE
int m_width
Width in Bytes of single column element.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:413