GammaLib  1.7.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GCaldb.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GCaldb.cpp - Calibration database class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2011-2016 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 GCaldb.cpp
23  * @brief Calibration database class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <unistd.h> // access() function
32 #include <cstdlib> // std::getenv() function
33 #include "GException.hpp"
34 #include "GTools.hpp"
35 #include "GCaldb.hpp"
36 
37 /* __ Method name definitions ____________________________________________ */
38 #define G_GET_ROOTDIR "GCaldb::rootdir()"
39 #define G_SET_ROOTDIR "GCaldb::rootdir(std::string&)"
40 #define G_PATH "GCaldb::path(std::string&, std::string&)"
41 #define G_CIFNAME "GCaldb::cifname(std::string&, std::string&)"
42 
43 /* __ Macros _____________________________________________________________ */
44 
45 /* __ Coding definitions _________________________________________________ */
46 
47 /* __ Debug definitions __________________________________________________ */
48 
49 
50 
51 /*==========================================================================
52  = =
53  = Constructors/destructors =
54  = =
55  ==========================================================================*/
56 
57 /***********************************************************************//**
58  * @brief Void constructor
59  *
60  * Creates void instance of a calibration database.
61  ***************************************************************************/
63 {
64  // Initialise class members
65  init_members();
66 
67  // Return
68  return;
69 }
70 
71 
72 /***********************************************************************//**
73  * @brief Copy constructor
74  *
75  * @param[in] caldb Calibration database.
76  ***************************************************************************/
77 GCaldb::GCaldb(const GCaldb& caldb)
78 {
79  // Initialise class members for clean destruction
80  init_members();
81 
82  // Copy members
83  copy_members(caldb);
84 
85  // Return
86  return;
87 }
88 
89 
90 /***********************************************************************//**
91  * @brief Initalisation constructor
92  *
93  * @param[in] pathname Calibration database root directory.
94  *
95  * This constructor sets the calibration database using the specified root
96  * directory. Unless the specified pathname is not empty, any existing CALDB
97  * environment variables will be ignored.
98  ***************************************************************************/
99 GCaldb::GCaldb(const std::string& pathname)
100 {
101  // Initialise members
102  init_members();
103 
104  // If pathname is not empty then use it as root pathname
105  if (pathname.length() > 0) {
106  rootdir(gammalib::expand_env(pathname));
107  }
108 
109  // Return
110  return;
111 }
112 
113 
114 /***********************************************************************//**
115  * @brief Calibration database constructor
116  *
117  * @param[in] mission Mission name (case insensitive).
118  * @param[in] instrument Instrument name (case insensitive).
119  *
120  * Constructs a calibration database instance by opening the calibration
121  * database for the specified @p mission and @p instrument. Opening consists
122  * of loading the Calibration Index File (CIF) in memory. Once opened,
123  * calibration information can be accessed.
124  *
125  * For more information about opening the database, refer to GCaldb::open.
126  ***************************************************************************/
127 GCaldb::GCaldb(const std::string& mission, const std::string& instrument)
128 {
129  // Initialise members
130  init_members();
131 
132  // Open database
133  open(mission, instrument);
134 
135  // Return
136  return;
137 }
138 
139 
140 /***********************************************************************//**
141  * @brief Destructor
142  ***************************************************************************/
144 {
145  // Free members
146  free_members();
147 
148  // Return
149  return;
150 }
151 
152 
153 /*==========================================================================
154  = =
155  = Operators =
156  = =
157  ==========================================================================*/
158 
159 /***********************************************************************//**
160  * @brief Assignment operator
161  *
162  * @param[in] caldb Calibration database.
163  ***************************************************************************/
165 {
166  // Execute only if object is not identical
167  if (this != &caldb) {
168 
169  // Free members
170  free_members();
171 
172  // Initialise private members
173  init_members();
174 
175  // Copy members
176  copy_members(caldb);
177 
178  } // endif: object was not identical
179 
180  // Return this object
181  return *this;
182 }
183 
184 
185 /*==========================================================================
186  = =
187  = Public methods =
188  = =
189  ==========================================================================*/
190 
191 /***********************************************************************//**
192  * @brief Clear calibration database
193  ***************************************************************************/
194 void GCaldb::clear(void)
195 {
196  // Free members
197  free_members();
198 
199  // Initialise private members
200  init_members();
201 
202  // Return
203  return;
204 }
205 
206 
207 /***********************************************************************//**
208  * @brief Clone calibration database
209  *
210  * Cloning provides a copy of the calibration database.
211  ***************************************************************************/
212 GCaldb* GCaldb::clone(void) const
213 {
214  // Clone this object
215  return (new GCaldb(*this));
216 }
217 
218 
219 /***********************************************************************//**
220  * @brief Returns number of entries in calibration database
221  *
222  * This method returns the number of entries that were found in an opened
223  * calibration database. An entry corresponds to one line in the Calibration
224  * Index File (CIF). If the index file is empty, or if no calibration
225  * database has been opened, the method returns 0.
226  ***************************************************************************/
227 int GCaldb::size(void) const
228 {
229  // Initialise size
230  int size = 0;
231 
232  // If CIF is open then determine number of entries
233  if (m_cif != NULL) {
234  size = m_cif->nrows();
235  }
236 
237  // Return size
238  return size;
239 }
240 
241 
242 /***********************************************************************//**
243  * @brief Return path to CALDB root directory
244  *
245  * @exception GException::directory_not_found
246  * Calibration directory not found.
247  * @exception GException::directory_not_accessible
248  * No read permission granted to calibration directory.
249  *
250  * The calibration directory path is given by one of the following
251  *
252  * $CALDB/data/<mission>
253  * $CALDB/data/<mission>/<instrument>
254  *
255  * where <mission> is the name of the mission and <instrument> is the
256  * optional instrument name (all lower case). The arguments provided to the
257  * method are transformed to lower case.
258  ***************************************************************************/
259 std::string GCaldb::rootdir(void) const
260 {
261  // Initialise root directory to optional root directory name
262  std::string rootdir = m_opt_rootdir;
263 
264  // If root directory is empty then get the directory name from the
265  // CALDB environment variable. Throw an exception if the environment
266  // variable has not been set
267  if (rootdir.empty()) {
268 
269  // Get root directory from CALDB environment variables
270  char* ptr1 = std::getenv("CALDB");
271 
272  // Throw an exception if non of the environment variables was set
273  if (ptr1 == NULL) {
275  "CALDB",
276  "Please set the CALDB environment"
277  " variable to a valid calibration database root directory.");
278  }
279 
280  // If CALDB was set then check whether the directory exists
281  if (ptr1 != NULL) {
282  if (access(ptr1, F_OK) == 0) {
283  rootdir = std::string(ptr1);
284  }
285  }
286 
287  } // endif: no optional root directory has been set
288 
289  // Return root directory
290  return rootdir;
291 }
292 
293 
294 /***********************************************************************//**
295  * @brief Set calibration database root directory
296  *
297  * @param[in] pathname Calibration database root directory.
298  *
299  * @exception GException::directory_not_found
300  * Calibration database root directory not found.
301  * @exception GException::directory_not_accessible
302  * No read permission granted for calibration database root
303  * directory.
304  *
305  * Sets the calibration database root directory to a specific path. The
306  * method verifies the existence of the root directory prior to setting.
307  ***************************************************************************/
308 void GCaldb::rootdir(const std::string& pathname)
309 {
310  // Expand pathname
311  std::string rootdir = gammalib::expand_env(pathname);
312 
313  // Verify that specified root directory exists
314  if (!gammalib::dir_exists(rootdir)) {
316  }
317 
318  // Verify that specified root directory allows read access
319  if (access(rootdir.c_str(), R_OK) != 0) {
321  "Requested read permission not granted.");
322  }
323 
324  // Set calibration database root directory
326 
327  // Return
328  return;
329 }
330 
331 
332 /***********************************************************************//**
333  * @brief Return path to calibration directory
334  *
335  * @param[in] mission Mission name (case insensitive).
336  * @param[in] instrument Instrument name (case insensitive; optional).
337  *
338  * @exception GException::directory_not_found
339  * Calibration directory not found.
340  * @exception GException::directory_not_accessible
341  * No read permission granted to calibration directory.
342  *
343  * The calibration directory path is given by one of the following
344  *
345  * $CALDB/data/<mission>
346  * $CALDB/data/<mission>/<instrument>
347  *
348  * where <mission> is the name of the mission and <instrument> is the
349  * optional instrument name (all lower case). The arguments provided to the
350  * method are transformed to lower case.
351  ***************************************************************************/
352 std::string GCaldb::path(const std::string& mission, const std::string& instrument)
353 {
354  // Verify that mission name is valid and directory is accessible
355  std::string path = rootdir() + "/data/" + gammalib::tolower(mission);
356  if (!gammalib::dir_exists(path)) {
358  "Requested mission \""+gammalib::toupper(mission)+"\" not found in"
359  " calibration database.");
360  }
361  if (access(path.c_str(), R_OK) != 0) {
363  "Requested read permission not granted for mission \""+
364  gammalib::toupper(mission)+"\".");
365  }
366 
367  // If an instrument has been specified, verify that instrument name is
368  // valid and directory is accessible
369  if (instrument.length() > 0) {
370 
371  // Add instrument to path
372  path += "/" + gammalib::tolower(instrument);
373 
374  // Verify path
375  if (!gammalib::dir_exists(path)) {
377  "Requested instrument \""+gammalib::toupper(instrument)+"\" on"
378  " mission \""+gammalib::toupper(mission)+"\" not found in"
379  " calibration database.");
380  }
381  if (access(path.c_str(), R_OK) != 0) {
383  "Requested read permission not granted for instrument \""+
384  gammalib::toupper(instrument)+"\" on mission \""+gammalib::toupper(mission)+
385  "\".");
386  }
387 
388  } // endif: instrument has been specified
389 
390  // Return path
391  return path;
392 }
393 
394 
395 /***********************************************************************//**
396  * @brief Return absolute CIF filename
397  *
398  * @param[in] mission Mission name (case insensitive).
399  * @param[in] instrument Instrument name (case insensitive; optional).
400  *
401  * @exception GException::file_error
402  * Calibration Index File not found.
403  *
404  * The calibration directory path is given by one of the following
405  *
406  * $CALDB/data/<mission>/caldb.indx
407  * $CALDB/data/<mission>/<instrument>/caldb.indx
408  *
409  * where <mission> is the name of the mission and <instrument> is the
410  * optional instrument name (all lower case). The arguments provided to the
411  * method are transformed to lower case.
412  ***************************************************************************/
413 std::string GCaldb::cifname(const std::string& mission, const std::string& instrument)
414 {
415  // Set calibration index filename
416  std::string cif = path(mission, instrument) + "/caldb.indx";
417 
418  // Check if file exists
419  GFilename filename(cif);
420  if (!filename.exists()) {
421  std::string msg = "Calibration Index File (CIF) \""+
422  cif+"\" not found.";
423  throw GException::file_error(G_CIFNAME, msg);
424  }
425 
426  // Return cif
427  return cif;
428 }
429 
430 
431 /***********************************************************************//**
432  * @brief Open calibration database
433  *
434  * @param[in] mission Mission name (case insensitive).
435  * @param[in] instrument Instrument name (case insensitive; optional).
436  *
437  * Opens the calibration database for a given mission and instrument. Opening
438  * consists of loading the Calibration Index File (CIF) in memory. Once
439  * opened, calibration information can be accessed.
440  ***************************************************************************/
441 void GCaldb::open(const std::string& mission, const std::string& instrument)
442 {
443  // Close any open database
444  close();
445 
446  // Set full CIF filename (this also validates the mission and
447  // instrument names)
448  m_cifname = cifname(mission, instrument);
449 
450  // Store mission and instrument
451  m_mission = mission;
453 
454  // Open CIF FITS file
456 
457  // Store pointer to first extension which holds the CIF table
458  m_cif = m_fits.table(1);
459 
460  // Return
461  return;
462 }
463 
464 
465 /***********************************************************************//**
466  * @brief Close calibration database
467  *
468  * Close any previously opened calibration database.
469  ***************************************************************************/
470 void GCaldb::close(void)
471 {
472  // Reset database parameters
473  m_mission.clear();
474  m_instrument.clear();
475  m_cifname.clear();
476 
477  // Close CIF FITS file
478  m_fits.close();
479 
480  // Reset CIF table pointer
481  m_cif = NULL;
482 
483  // Return
484  return;
485 }
486 
487 
488 /***********************************************************************//**
489  * @brief Return calibration file name based on selection parameters
490  *
491  * @param[in] detector Detector name (not used if empty).
492  * @param[in] filter Filter name (not used if empty).
493  * @param[in] codename Code name (not used if empty).
494  * @param[in] date Date in yyyy-mm-dd format (not used if empty).
495  * @param[in] time Time in hh:mm:ss format (not used if empty).
496  * @param[in] expr Boolean selection expression (not used if empty).
497  * @return Calibration filename (empty if not found).
498  *
499  * Returns a calibration file name based on selection parameters. If more
500  * files satisfy the specified selection parameters, the first file will
501  * be returned.
502  *
503  * @todo data should support "now" and probably be implemented using < condition.
504  * @todo time should support "now" and probably be implemented using < condition.
505  * @todo expr should support arbitrary Boolean expressions.
506  ***************************************************************************/
507 GFilename GCaldb::filename(const std::string& detector,
508  const std::string& filter,
509  const std::string& codename,
510  const std::string& date,
511  const std::string& time,
512  const std::string& expr)
513 {
514  // Initialise empty filename
516 
517  // Continue only if CIF is opened
518  if (m_cif != NULL) {
519 
520  // Loop over all CIF entries
521  for (int i = 0; i < size(); ++i) {
522 
523  // Initialise selection flags
524  bool match_detector = false;
525  bool match_filter = false;
526  bool match_codename = false;
527  bool match_date = false;
528  bool match_time = false;
529  bool match_expr = false;
530 
531  // Check for detector
532  if (detector.length() > 0) {
533  const GFitsTableCol* column = (*m_cif)["DETNAM"];
534  if (gammalib::toupper(detector) ==
535  gammalib::toupper(column->string(i))) {
536  match_detector = true;
537  }
538  }
539  else {
540  match_detector = true;
541  }
542 
543  // Check for filter
544  if (filter.length() > 0) {
545  const GFitsTableCol* column = (*m_cif)["FILTER"];
546  if (gammalib::toupper(filter) ==
547  gammalib::toupper(column->string(i))) {
548  match_filter = true;
549  }
550  }
551  else {
552  match_filter = true;
553  }
554 
555  // Check for code name
556  if (codename.length() > 0) {
557  const GFitsTableCol* column = (*m_cif)["CAL_CNAM"];
558  if (gammalib::toupper(codename) ==
559  gammalib::toupper(column->string(i))) {
560  match_codename = true;
561  }
562  }
563  else {
564  match_codename = true;
565  }
566 
567  // Check for date
568  if (date.length() > 0) {
569  const GFitsTableCol* column = (*m_cif)["CAL_VSD"];
570  if (gammalib::toupper(date) ==
571  gammalib::toupper(column->string(i))) {
572  match_date = true;
573  }
574  }
575  else {
576  match_date = true;
577  }
578 
579  // Check for time
580  if (time.length() > 0) {
581  const GFitsTableCol* column = (*m_cif)["CAL_VST"];
582  if (gammalib::toupper(time) ==
583  gammalib::toupper(column->string(i))) {
584  match_time = true;
585  }
586  }
587  else {
588  match_time = true;
589  }
590 
591  // Check for expression
592  if (expr.length() > 0) {
593  const GFitsTableCol* column = (*m_cif)["CAL_CBD"];
594  int num_columns = column->elements(i);
595  for (int k = 0; k < num_columns; ++k) {
596  if (gammalib::toupper(expr) ==
597  gammalib::toupper(column->string(i,k))) {
598  match_expr = true;
599  break;
600  }
601  }
602  }
603  else {
604  match_expr = true;
605  }
606 
607  // Select file if all selection match
608  if (match_detector && match_filter && match_codename &&
609  match_date && match_time && match_expr) {
610  const GFitsTableCol* cal_dir = (*m_cif)["CAL_DIR"];
611  const GFitsTableCol* cal_file = (*m_cif)["CAL_FILE"];
612  std::string path = rootdir();
613  if (path.empty()) {
614  filename = cal_dir->string(i) + "/" +
615  cal_file->string(i);
616  }
617  else {
618  filename = path + "/" +
619  cal_dir->string(i) + "/" +
620  cal_file->string(i);
621  }
622  break;
623  }
624 
625  } // endfor: looped over all CIF entries
626 
627  } // endif: CIF has been opened
628 
629  // Return filename
630  return filename;
631 }
632 
633 
634 /***********************************************************************//**
635  * @brief Print calibration database information
636  *
637  * @param[in] chatter Chattiness (defaults to NORMAL).
638  * @return String containing calibration database information.
639  ***************************************************************************/
640 std::string GCaldb::print(const GChatter& chatter) const
641 {
642  // Initialise result string
643  std::string result;
644 
645  // Continue only if chatter is not silent
646  if (chatter != SILENT) {
647 
648  // Append Header
649  result.append("=== GCaldb ===");
650 
651  // Append information
652  result.append("\n"+gammalib::parformat("Database root"));
653  try {
654  result.append(rootdir());
655  }
656  catch (std::exception& e) {
657  result.append("undefined");
658  }
659 
660  // Append information about opened database
661  if (m_cif != NULL) {
662  result.append("\n"+gammalib::parformat("Selected Mission"));
663  result.append(gammalib::toupper(m_mission));
664  result.append("\n"+gammalib::parformat("Selected Instrument"));
665  result.append(gammalib::toupper(m_instrument));
666  result.append("\n"+gammalib::parformat("Calibration Index File"));
667  result.append(m_cifname);
668  result.append("\n"+gammalib::parformat("Number of entries"));
669  result.append(gammalib::str(size()));
670  }
671 
672  } // endif: chatter was not silent
673 
674  // Return
675  return result;
676 }
677 
678 
679 /*==========================================================================
680  = =
681  = Private methods =
682  = =
683  ==========================================================================*/
684 
685 /***********************************************************************//**
686  * @brief Initialise class members
687  ***************************************************************************/
689 {
690  // Initialise members
691  m_opt_rootdir.clear();
692  m_mission.clear();
693  m_instrument.clear();
694  m_cifname.clear();
695  m_fits.clear();
696  m_cif = NULL;
697 
698  // Return
699  return;
700 }
701 
702 
703 /***********************************************************************//**
704  * @brief Copy class members
705  *
706  * @param[in] caldb Calibration database.
707  ***************************************************************************/
708 void GCaldb::copy_members(const GCaldb& caldb)
709 {
710  // Copy attributes
712  m_mission = caldb.m_mission;
713  m_instrument = caldb.m_instrument;
714  m_cifname = caldb.m_cifname;
715  m_fits = caldb.m_fits;
716 
717  // Set CIF table pointer. We do not copy over the pointer as the FITS
718  // file has been copied here.
719  if (caldb.m_cif != NULL) {
720  m_cif = m_fits.table(1);
721  }
722  else {
723  m_cif = NULL;
724  }
725 
726  // Return
727  return;
728 }
729 
730 
731 /***********************************************************************//**
732  * @brief Delete class members
733  ***************************************************************************/
735 {
736  // Close any open database
737  close();
738 
739  // Return
740  return;
741 }
742 
743 
GCaldb & operator=(const GCaldb &caldb)
Assignment operator.
Definition: GCaldb.cpp:164
GFitsTable * table(const int &extno)
Get pointer to table HDU.
Definition: GFits.cpp:472
int size(void) const
Returns number of entries in calibration database.
Definition: GCaldb.cpp:227
std::string path(const std::string &mission, const std::string &instrument="")
Return path to calibration directory.
Definition: GCaldb.cpp:352
std::string m_mission
Mission of opened database.
Definition: GCaldb.hpp:111
void free_members(void)
Delete class members.
Definition: GCaldb.cpp:734
void clear(void)
Clear FITS file.
Definition: GFits.cpp:195
const std::string & mission(void) const
Return mission.
Definition: GCaldb.hpp:137
GCaldb * clone(void) const
Clone calibration database.
Definition: GCaldb.cpp:212
void elements(const int &row, const int &elements)
Set number of column elements for specific row.
GFilename filename(const std::string &detector, const std::string &filter, const std::string &codename, const std::string &date, const std::string &time, const std::string &expr)
Return calibration file name based on selection parameters.
Definition: GCaldb.cpp:507
Gammalib tools definition.
GFits m_fits
CIF FITS file.
Definition: GCaldb.hpp:114
void init_members(void)
Initialise class members.
Definition: GCaldb.cpp:688
virtual ~GCaldb(void)
Destructor.
Definition: GCaldb.cpp:143
void copy_members(const GCaldb &caldb)
Copy class members.
Definition: GCaldb.cpp:708
std::string m_instrument
Instrument of opened database.
Definition: GCaldb.hpp:112
void close(void)
Close calibration database.
Definition: GCaldb.cpp:470
void open(const std::string &mission, const std::string &instrument="")
Open calibration database.
Definition: GCaldb.cpp:441
const std::string & instrument(void) const
Return instrument.
Definition: GCaldb.hpp:149
virtual std::string string(const int &row, const int &inx=0) const =0
std::string m_cifname
CIF filename of opened database.
Definition: GCaldb.hpp:113
Calibration database class.
Definition: GCaldb.hpp:66
GCaldb(void)
Void constructor.
Definition: GCaldb.cpp:62
Filename class.
Definition: GFilename.hpp:62
Abstract interface for FITS table column.
void open(const GFilename &filename, const bool &create=false)
Open or (optionally) create FITS file.
Definition: GFits.cpp:1023
bool exists(void) const
Checks whether file exists.
Definition: GFilename.cpp:223
GChatter
Definition: GTypemaps.hpp:33
bool dir_exists(const std::string &dirname)
Checks if directory exists.
Definition: GTools.cpp:1191
std::string m_opt_rootdir
Optional root directory.
Definition: GCaldb.hpp:110
#define G_CIFNAME
Definition: GCaldb.cpp:41
Calibration database class interface definition.
const int & nrows(void) const
Return number of rows in table.
Definition: GFitsTable.hpp:119
#define G_SET_ROOTDIR
Definition: GCaldb.cpp:39
GFitsTable * m_cif
Pointer to CIF table.
Definition: GCaldb.hpp:115
#define G_PATH
Definition: GCaldb.cpp:40
std::string cifname(const std::string &mission, const std::string &instrument="")
Return absolute CIF filename.
Definition: GCaldb.cpp:413
std::string print(const GChatter &chatter=NORMAL) const
Print calibration database information.
Definition: GCaldb.cpp:640
Exception handler interface definition.
std::string toupper(const std::string &s)
Convert string to upper case.
Definition: GTools.cpp:820
std::string tolower(const std::string &s)
Convert string to lower case.
Definition: GTools.cpp:834
std::string expand_env(const std::string &arg)
Expand environment variables in string.
Definition: GTools.cpp:207
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1022
#define G_GET_ROOTDIR
Definition: GCaldb.cpp:38
void close(void)
Close FITS file.
Definition: GFits.cpp:1314
void clear(void)
Clear calibration database.
Definition: GCaldb.cpp:194
std::string rootdir(void) const
Return path to CALDB root directory.
Definition: GCaldb.cpp:259
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:413