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