GammaLib  2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GCOMOads.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GCOMOads.cpp - COMPTEL Orbit Aspect Data container class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2017-2021 by Juergen Knodlseder *
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 GCOMOads.hpp
23  * @brief COMPTEL Orbit Aspect Data container class implementation
24  * @author Juergen Knodlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include "GException.hpp"
32 #include "GMath.hpp"
33 #include "GFits.hpp"
34 #include "GFitsTable.hpp"
35 #include "GCOMTools.hpp"
36 #include "GCOMSupport.hpp"
37 #include "GCOMOads.hpp"
38 
39 /* __ Method name definitions ____________________________________________ */
40 #define G_AT "GCOMOads::at(int&)"
41 #define G_INSERT "GCOMOads::insert(int&, GCOMOad&)"
42 #define G_REMOVE "GCOMOads::remove(int&)"
43 #define G_READ "GCOMOads::read(GFitsTable&)"
44 
45 /* __ Macros _____________________________________________________________ */
46 
47 /* __ Coding definitions _________________________________________________ */
48 //#define G_GEORAD_WARNING
49 
50 /* __ Debug definitions __________________________________________________ */
51 
52 
53 /*==========================================================================
54  = =
55  = Constructors/destructors =
56  = =
57  ==========================================================================*/
58 
59 /***********************************************************************//**
60  * @brief Void constructor
61  *
62  * Constructs an empty Orbit Aspect Data container
63  ***************************************************************************/
65 {
66  // Initialise class members
67  init_members();
68 
69  // Return
70  return;
71 }
72 
73 
74 /***********************************************************************//**
75  * @brief Filename constructor
76  *
77  * @param[in] filename Orbit Aspect Data FITS file
78  *
79  * Constructs an Orbit Aspect Data container from an OAD FITS file.
80  ***************************************************************************/
81 GCOMOads::GCOMOads(const GFilename& filename)
82 {
83  // Initialise class members
84  init_members();
85 
86  // Load data
87  load(filename);
88 
89  // Return
90  return;
91 }
92 
93 
94 /***********************************************************************//**
95  * @brief Copy constructor
96  *
97  * @param[in] oads COMPTEL Orbit Aspect Data container.
98  ***************************************************************************/
100 {
101  // Initialise class members
102  init_members();
103 
104  // Copy members
105  copy_members(oads);
106 
107  // Return
108  return;
109 }
110 
111 
112 /***********************************************************************//**
113  * @brief Destructor
114  ***************************************************************************/
116 {
117  // Free members
118  free_members();
119 
120  // Return
121  return;
122 }
123 
124 
125 /*==========================================================================
126  = =
127  = Operators =
128  = =
129  ==========================================================================*/
130 
131 /***********************************************************************//**
132  * @brief Assignment operator
133  *
134  * @param[in] oads COMPTEL Orbit Aspect Data container.
135  * @return COMPTEL Orbit Aspect Data container.
136  ***************************************************************************/
138 {
139  // Execute only if object is not identical
140  if (this != &oads) {
141 
142  // Free members
143  free_members();
144 
145  // Initialise private members
146  init_members();
147 
148  // Copy members
149  copy_members(oads);
150 
151  } // endif: object was not identical
152 
153  // Return this object
154  return *this;
155 }
156 
157 
158 /*==========================================================================
159  = =
160  = Public methods =
161  = =
162  ==========================================================================*/
163 
164 /***********************************************************************//**
165  * @brief Clear COMPTEL Orbit Aspect Data container
166  ***************************************************************************/
167 void GCOMOads::clear(void)
168 {
169  // Free members
170  free_members();
171 
172  // Initialise private members
173  init_members();
174 
175  // Return
176  return;
177 }
178 
179 
180 /***********************************************************************//**
181  * @brief Clone COMPTEL Orbit Aspect Data container
182  *
183  * @return Pointer to deep copy of COMPTEL Orbit Aspect Data container.
184  ***************************************************************************/
186 {
187  return new GCOMOads(*this);
188 }
189 
190 
191 /***********************************************************************//**
192  * @brief Return reference to Orbit Aspect Data
193  *
194  * @param[in] index Orbit Aspect Data index [0,...,size()-1].
195  *
196  * @exception GException::out_of_range
197  * Orbit Aspect Data index is out of range.
198  *
199  * Returns a reference to the Orbit Aspect Data with the specified @p index.
200  ***************************************************************************/
201 GCOMOad& GCOMOads::at(const int& index)
202 {
203  // Raise exception if index is out of range
204  if (index < 0 || index >= size()) {
205  throw GException::out_of_range(G_AT, "Orbit Aspect Data index",
206  index, size());
207  }
208 
209  // Return reference
210  return m_oads[index];
211 }
212 
213 
214 /***********************************************************************//**
215  * @brief Return reference to Orbit Aspect Data (const version)
216  *
217  * @param[in] index Orbit Aspect Data index [0,...,size()-1].
218  *
219  * @exception GException::out_of_range
220  * Orbit Aspect Data index is out of range.
221  *
222  * Returns a reference to the Orbit Aspect Data with the specified @p index.
223  ***************************************************************************/
224 const GCOMOad& GCOMOads::at(const int& index) const
225 {
226  // Raise exception if index is out of range
227  if (index < 0 || index >= size()) {
228  throw GException::out_of_range(G_AT, "Orbit Aspect Data index",
229  index, size());
230  }
231 
232  // Return reference
233  return m_oads[index];
234 }
235 
236 
237 /***********************************************************************//**
238  * @brief Append Orbit Aspect Data to container
239  *
240  * @param[in] oad Orbit Aspect Data.
241  * @return Reference to appended Orbit Aspect Data.
242  *
243  * Appends Orbit Aspect Data to the container by making a deep copy of the
244  * Orbit Aspect Data.
245  ***************************************************************************/
247 {
248  // Append oad to list
249  m_oads.push_back(oad);
250 
251  // Return reference
252  return m_oads[size()-1];
253 }
254 
255 
256 /***********************************************************************//**
257  * @brief Insert Orbit Aspect Data into container
258  *
259  * @param[in] index Orbit Aspect Data index (0,...,size()-1).
260  * @param[in] oad Orbit Aspect Data.
261  *
262  * @exception GException::out_of_range
263  * Orbit Aspect Data index is out of range.
264  *
265  * Inserts an @p Orbit Aspect Data into the container before the Orbit
266  * Aspect Data with the specified @p index.
267  ***************************************************************************/
268 GCOMOad& GCOMOads::insert(const int& index, const GCOMOad& oad)
269 {
270  // Compile option: raise exception if index is out of range
271  #if defined(G_RANGE_CHECK)
272  if (is_empty()) {
273  if (index > 0) {
274  throw GException::out_of_range(G_INSERT, "Orbit Aspect Data index",
275  index, size());
276  }
277  }
278  else {
279  if (index < 0 || index >= size()) {
280  throw GException::out_of_range(G_INSERT, "Orbit Aspect Data index",
281  index, size());
282  }
283  }
284  #endif
285 
286  // Inserts Orbit Aspect Data
287  m_oads.insert(m_oads.begin()+index, oad);
288 
289  // Return reference
290  return m_oads[index];
291 }
292 
293 
294 /***********************************************************************//**
295  * @brief Remove Orbit Aspect Data from container
296  *
297  * @param[in] index Orbit Aspect Data index (0,...,size()-1).
298  *
299  * @exception GException::out_of_range
300  * Orbit Aspect Data index is out of range.
301  *
302  * Remove Orbit Aspect Data of specified @p index from container.
303  ***************************************************************************/
304 void GCOMOads::remove(const int& index)
305 {
306  // Compile option: raise exception if index is out of range
307  #if defined(G_RANGE_CHECK)
308  if (index < 0 || index >= size()) {
309  throw GException::out_of_range(G_REMOVE, "Orbit Aspect Data index",
310  index, size());
311  }
312  #endif
313 
314  // Erase Orbit Aspect Data from container
315  m_oads.erase(m_oads.begin() + index);
316 
317  // Return
318  return;
319 }
320 
321 
322 /***********************************************************************//**
323  * @brief Append Orbit Aspect Data container
324  *
325  * @param[in] oads COMPTEL Orbit Aspect Data container.
326  *
327  * Append COMPTEL Orbit Aspect Data container to the container.
328  ***************************************************************************/
329 void GCOMOads::extend(const GCOMOads& oads)
330 {
331  // Do nothing if COMPTEL Orbit Aspect Data container is empty
332  if (!oads.is_empty()) {
333 
334  // Get size. Note that we extract the size first to avoid an
335  // endless loop that arises when a container is appended to
336  // itself.
337  int num = oads.size();
338 
339  // Reserve enough space
340  reserve(size() + num);
341 
342  // Loop over all elements and append them to container
343  for (int i = 0; i < num; ++i) {
344  m_oads.push_back(oads[i]);
345  }
346 
347  } // endif: COMPTEL Orbit Aspect Data container was not empty
348 
349  // Return
350  return;
351 }
352 
353 
354 /***********************************************************************//**
355  * @brief Load COMPTEL Orbit Aspect Data FITS file
356  *
357  * @param[in] filename COMPTEL OAD FITS file name.
358  *
359  * Loads an COMPTEL Orbit Aspect Data FITS file in the container.
360  ***************************************************************************/
361 void GCOMOads::load(const GFilename& filename)
362 {
363  // Open FITS file
364  GFits fits(filename);
365 
366  // Get HDU (pointer is always valid)
367  const GFitsTable& hdu = *fits.table(1);
368 
369  // Read Orbit Aspect Data FITS table
370  read(hdu);
371 
372  // Close FITS file
373  fits.close();
374 
375  // Return
376  return;
377 }
378 
379 
380 /***********************************************************************//**
381  * @brief Read COMPTEL Orbit Aspect Data FITS table
382  *
383  * @param[in] table COMPTEL OAD FITS table.
384  *
385  * Reads COMPTEL Orbit Aspect Data FITS table into the container.
386  ***************************************************************************/
387 void GCOMOads::read(const GFitsTable& table)
388 {
389  // Earth radius in km including atmosphere (see EVP routine EVSCDJ Rev.7)
390  const double era = 6451.03;
391 
392  // Set Earth radius in km excluding atmosphere
393  const double erd = 6378.5;
394  const double erd_min = erd + 300.0; // Lower limit on orbit
395  const double erd_max = erd + 530.0; // Upper limit on orbit
396 
397  // Clear
398  clear();
399 
400  // Extract number of records in FITS file
401  int num = table.nrows();
402 
403  // If there are records then load them
404  if (num > 0) {
405 
406  // Reserve data
407  m_oads.reserve(num);
408 
409  // Get column pointers
410  const GFitsTableCol* ptr_tjd = table["TJD"]; // days
411  const GFitsTableCol* ptr_tics = table["TICS"]; // ticks
412  const GFitsTableCol* ptr_gcaz = table["GCAZ"]; // rad
413  const GFitsTableCol* ptr_gcel = table["GCEL"]; // rad
414  const GFitsTableCol* ptr_posx = table["POSX"]; // km
415  const GFitsTableCol* ptr_posy = table["POSY"]; // km
416  const GFitsTableCol* ptr_posz = table["POSZ"]; // km
417  const GFitsTableCol* ptr_zrasc = table["ZRASC"]; // rad
418  const GFitsTableCol* ptr_zdecl = table["ZDECL"]; // rad
419  const GFitsTableCol* ptr_xrasc = table["XRASC"]; // rad
420  const GFitsTableCol* ptr_xdecl = table["XDECL"]; // rad
421 
422  // Initialise Earth radius angle
423  double georad = 73.5;
424 
425  // Copy data from columns into records
426  for (int i = 0; i < num; ++i) {
427 
428  // Allocate OAD record
429  GCOMOad oad;
430 
431  // Get time of record
432  int tjd = ptr_tjd->integer(i);
433  int tics = ptr_tics->integer(i);
434 
435  // Store time information. The stop time is defined as the start
436  // time plus 131071 tics, since the length of one superpacket is
437  // 16.384 secs, i.e. 16.384 * 8000 = 131072 ticks
438  oad.tjd(tjd);
439  oad.tics(tics);
440  oad.tstart(gammalib::com_time(tjd, tics));
441  oad.tstop(gammalib::com_time(tjd, tics + 131071));
442 
443  // Set geocentre azimuth and zenith angle in deg
444  oad.gcaz(ptr_gcaz->real(i) * gammalib::rad2deg);
445  oad.gcel(ptr_gcel->real(i) * gammalib::rad2deg);
446 
447  // Set telescope Z- and X-axes
448  GSkyDir zaxis;
449  GSkyDir xaxis;
450  zaxis.radec(ptr_zrasc->real(i), ptr_zdecl->real(i));
451  xaxis.radec(ptr_xrasc->real(i), ptr_xdecl->real(i));
452  oad.zaxis(zaxis);
453  oad.xaxis(xaxis);
454 
455  // Set telescope position vector
456  oad.pos(GVector(ptr_posx->real(i), ptr_posy->real(i), ptr_posz->real(i)));
457 
458  // Compute apparent radius of Earth
459  double radius = std::sqrt(ptr_posx->real(i) * ptr_posx->real(i) +
460  ptr_posy->real(i) * ptr_posy->real(i) +
461  ptr_posz->real(i) * ptr_posz->real(i));
462  if ((radius > erd_min) && (radius < erd_max)) {
463  georad = std::asin(era/radius) * gammalib::rad2deg;
464  }
465  #if defined(G_GEORAD_WARNING)
466  else {
467  std::string msg = "Error in CGRO position. Distance from "
468  "geocentre is "+gammalib::str(radius)+ " km "
469  "while it should be in the interval ["+
470  gammalib::str(erd_min)+","+
471  gammalib::str(erd_max)+"] km. Use previous "
472  "spacecraft altitude.";
474  }
475  #endif
476  oad.georad(georad);
477 
478  // Append record
479  m_oads.push_back(oad);
480 
481  } // endfor: looped over OAD records
482 
483  } // endif: there were records to load
484 
485  // Return
486  return;
487 }
488 
489 
490 /***********************************************************************//**
491  * @brief Print COMPTEL Orbit Aspect Data container
492  *
493  * @param[in] chatter Chattiness.
494  * @return String containing COMPTEL Orbit Aspect Data container information.
495  ***************************************************************************/
496 std::string GCOMOads::print(const GChatter& chatter) const
497 {
498  // Initialise result string
499  std::string result;
500 
501  // Continue only if chatter is not silent
502  if (chatter != SILENT) {
503 
504  // Append header
505  result.append("=== GCOMOads ===");
506 
507  // Append container information
508  result.append("\n"+gammalib::parformat("Superpackets"));
509  result.append(gammalib::str(size()));
510  if (size() > 0) {
511 
512  // Append time range
513  result.append("\n"+gammalib::parformat("TJD range"));
514  result.append(gammalib::str(m_oads[0].tjd()));
515  result.append(":");
516  result.append(gammalib::str(m_oads[0].tics()));
517  result.append(" - ");
518  result.append(gammalib::str(m_oads[size()-1].tjd()));
519  result.append(":");
520  result.append(gammalib::str(m_oads[size()-1].tics()));
521  result.append("\n"+gammalib::parformat("MJD range"));
522  result.append(gammalib::str(m_oads[0].tstart().mjd()));
523  result.append(" - ");
524  result.append(gammalib::str(m_oads[size()-1].tstop().mjd()));
525  result.append(" days");
526  result.append("\n"+gammalib::parformat("UTC range"));
527  result.append(m_oads[0].tstart().utc());
528  result.append(" - ");
529  result.append(m_oads[size()-1].tstop().utc());
530 
531  // Append detailed information
532  GChatter reduced_chatter = gammalib::reduce(chatter);
533  if (reduced_chatter > SILENT) {
534 
535  // Append TJDs
536  int tjd = 0;
537  int num = 0;
538  for (int i = 0; i < size(); ++i) {
539  if (m_oads[i].tjd() != tjd) {
540  if (num > 0) {
541  std::string key = "TJD "+gammalib::str(tjd);
542  result.append("\n"+gammalib::parformat(key));
543  result.append(gammalib::str(num)+" superpackets");
544  }
545  tjd = m_oads[i].tjd();
546  num = 1;
547  }
548  else {
549  num++;
550  }
551  }
552  std::string key = "TJD "+gammalib::str(tjd);
553  result.append("\n"+gammalib::parformat(key));
554  result.append(gammalib::str(num)+" superpackets");
555 
556  } // endif: detailed information requested
557 
558  } // endif: there were records
559 
560  } // endif: chatter was not silent
561 
562  // Return result
563  return result;
564 }
565 
566 
567 /*==========================================================================
568  = =
569  = Private methods =
570  = =
571  ==========================================================================*/
572 
573 /***********************************************************************//**
574  * @brief Initialise class members
575  ***************************************************************************/
577 {
578  // Initialise members
579  m_oads.clear();
580 
581  // Return
582  return;
583 }
584 
585 
586 /***********************************************************************//**
587  * @brief Copy class members
588  *
589  * @param[in] oads COMPTEL Orbit Aspect Data container.
590  ***************************************************************************/
592 {
593  // Copy members
594  m_oads = oads.m_oads;
595 
596  // Return
597  return;
598 }
599 
600 
601 /***********************************************************************//**
602  * @brief Delete class members
603  ***************************************************************************/
605 {
606  // Return
607  return;
608 }
GCOMOads * clone(void) const
Clone COMPTEL Orbit Aspect Data container.
Definition: GCOMOads.cpp:185
GFitsTable * table(const int &extno)
Get pointer to table HDU.
Definition: GFits.cpp:482
std::vector< GCOMOad > m_oads
Orbit Aspect Data records.
Definition: GCOMOads.hpp:89
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition: GTools.cpp:1386
Definition of COMPTEL tools.
GCOMOad & insert(const int &index, const GCOMOad &oad)
Insert Orbit Aspect Data into container.
Definition: GCOMOads.cpp:268
#define G_REMOVE
Definition: GCOMOads.cpp:42
const float & gcel(void) const
Return Geocentre zenith angle.
Definition: GCOMOad.hpp:280
bool is_empty(void) const
Signals if there are no Orbit Aspect Data in container.
Definition: GCOMOads.hpp:156
const GSkyDir & xaxis(void) const
Return telescope X-axis.
Definition: GCOMOad.hpp:368
std::string print(const GChatter &chatter=NORMAL) const
Print COMPTEL Orbit Aspect Data container.
Definition: GCOMOads.cpp:496
const GTime & tstop(void) const
Return stop time of superpacket.
Definition: GCOMOad.hpp:164
int size(void) const
Return number of Orbit Aspect Data in container.
Definition: GCOMOads.hpp:141
FITS file class.
Definition: GFits.hpp:63
void clear(void)
Clear COMPTEL Orbit Aspect Data container.
Definition: GCOMOads.cpp:167
FITS file class interface definition.
GCOMOad & at(const int &index)
Return reference to Orbit Aspect Data.
Definition: GCOMOads.cpp:201
#define G_INSERT
Definition: GCOMOads.cpp:41
GTime com_time(const int &tjd, const int &tics)
Convert TJD and COMPTEL tics in GTime object.
Definition: GCOMTools.cpp:55
const float & georad(void) const
Return apparent radius of Earth.
Definition: GCOMOad.hpp:309
COMPTEL Orbit Aspect Data class.
Definition: GCOMOad.hpp:49
Implementation of support function used by COMPTEL classes.
const GTime & tstart(void) const
Return start time of superpacket.
Definition: GCOMOad.hpp:133
void read(const GFitsTable &table)
Read COMPTEL Orbit Aspect Data FITS table.
Definition: GCOMOads.cpp:387
void radec(const double &ra, const double &dec)
Set equatorial sky direction (radians)
Definition: GSkyDir.cpp:197
GVector sqrt(const GVector &vector)
Computes square root of vector elements.
Definition: GVector.cpp:1358
void load(const GFilename &filename)
Load COMPTEL Orbit Aspect Data FITS file.
Definition: GCOMOads.cpp:361
const GVector & pos(void) const
Return telescope position vector (km)
Definition: GCOMOad.hpp:398
#define G_AT
Definition: GCOMOads.cpp:40
const GSkyDir & zaxis(void) const
Return telescope Z-axis.
Definition: GCOMOad.hpp:338
Filename class.
Definition: GFilename.hpp:62
Abstract interface for FITS table column.
virtual ~GCOMOads(void)
Destructor.
Definition: GCOMOads.cpp:115
Abstract interface for FITS table.
Definition: GFitsTable.hpp:44
GChatter
Definition: GTypemaps.hpp:33
GCOMOad & append(const GCOMOad &oad)
Append Orbit Aspect Data to container.
Definition: GCOMOads.cpp:246
void extend(const GCOMOads &oads)
Append Orbit Aspect Data container.
Definition: GCOMOads.cpp:329
GVector asin(const GVector &vector)
Computes arcsin of vector elements.
Definition: GVector.cpp:1106
const int & nrows(void) const
Return number of rows in table.
Definition: GFitsTable.hpp:119
void init_members(void)
Initialise class members.
Definition: GCOMOads.cpp:576
void free_members(void)
Delete class members.
Definition: GCOMOads.cpp:604
#define G_READ
Definition: GCOMOads.cpp:43
virtual int integer(const int &row, const int &inx=0) const =0
virtual double real(const int &row, const int &inx=0) const =0
const int & tjd(void) const
Return Truncated Julian Days of Orbit Aspect Record.
Definition: GCOMOad.hpp:193
GCOMOads & operator=(const GCOMOads &oads)
Assignment operator.
Definition: GCOMOads.cpp:137
void reserve(const int &num)
Reserves space for Orbit Aspect Data in container.
Definition: GCOMOads.hpp:170
GChatter reduce(const GChatter &chatter)
Reduce chattiness by one level.
Definition: GTypemaps.hpp:65
Exception handler interface definition.
COMPTEL Orbit Aspect Data container class.
Definition: GCOMOads.hpp:51
GCOMOads(void)
Void constructor.
Definition: GCOMOads.cpp:64
void remove(const int &index)
Remove Orbit Aspect Data from container.
Definition: GCOMOads.cpp:304
Vector class.
Definition: GVector.hpp:46
const double rad2deg
Definition: GMath.hpp:44
const int & tics(void) const
Return tics of Orbit Aspect Record.
Definition: GCOMOad.hpp:222
void copy_members(const GCOMOads &oads)
Copy class members.
Definition: GCOMOads.cpp:591
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
Sky direction class.
Definition: GSkyDir.hpp:62
void close(void)
Close FITS file.
Definition: GFits.cpp:1342
COMPTEL Orbit Aspect Data container class definition.
Mathematical function definitions.
const float & gcaz(void) const
Return Geocentre azimuth angle.
Definition: GCOMOad.hpp:251
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489
FITS table abstract base class interface definition.