GammaLib 2.0.0
Loading...
Searching...
No Matches
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"
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
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
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
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 ***************************************************************************/
163GFits::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 ***************************************************************************/
235std::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 ***************************************************************************/
257double 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 ***************************************************************************/
278int 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 ***************************************************************************/
303void 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 ***************************************************************************/
390void 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
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
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 ***************************************************************************/
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) {
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 ***************************************************************************/
648void 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) {
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}
Exception handler interface definition.
CFITSIO interface header.
#define __TCOMPLEX
#define G_INSERT
#define G_REMOVE
FITS table float complex column class interface definition.
Gammalib tools definition.
FITS table float complex column.
void copy_members(const GFitsTableCFloatCol &column)
Copy class members.
void alloc_nulval(const GFits::cfloat *value)
Allocates null value.
virtual void alloc_data(void)
Allocates column data.
virtual void insert(const int &row, const int &nrows)
Insert rows in column.
virtual std::string ascii_format(void) const
Returns format string of ASCII table.
virtual void init_data(void)
Initialise column data.
virtual int integer(const int &row, const int &col=0) const
Get integer value (real part)
virtual void release_data(void)
Release column data.
virtual GFitsTableCFloatCol * clone(void) const
Clone column.
GFits::cfloat & operator()(const int &row, const int &inx=0)
Column data access operator.
GFitsTableCFloatCol & operator=(const GFitsTableCFloatCol &column)
Assignment operator.
void free_members(void)
Delete class members.
void init_members(void)
Initialise class members.
virtual void clear(void)
Clear instance.
virtual void resize_data(const int &index, const int &number)
Resize column data.
virtual double real(const int &row, const int &col=0) const
Get double precision value (real part)
GFits::cfloat * m_nulval
NULL value.
virtual void remove(const int &row, const int &nrows)
Remove rows from column.
virtual void fetch_data(void) const
Fetch column data.
GFits::cfloat * nulval(void)
Returns pointer to nul value.
GFitsTableCFloatCol(void)
Constructor.
GFits::cfloat * m_data
Data vector.
virtual bool is_loaded(void) const
Checks if column has been loaded.
virtual std::string string(const int &row, const int &col=0) const
Get string value.
virtual ~GFitsTableCFloatCol(void)
Destructor.
Abstract interface for FITS table column.
int m_type
Column type.
int m_length
Length of column (number of rows)
const int & nrows(void) const
Returns number of rows in column.
std::vector< int > m_rowstart
Start index of each row.
int m_size
Size of allocated data area (0 if not loaded)
int m_width
Width in Bytes of single column element.
int m_varlen
Maximum number of elements in variable-length.
GFitsTableCol & operator=(const GFitsTableCol &column)
Assignment operator.
const int & number(void) const
Returns number of elements in column.
void free_members(void)
Delete class members.
virtual void load_column(void)
Load table column from FITS file.
void init_members(void)
Initialise class members.
virtual int offset(const int &row, const int &inx) const
Compute offset of column element in memory.
int m_number
Number of elements in column.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489