GammaLib 2.0.0
Loading...
Searching...
No Matches
GCaldb.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GCaldb.cpp - Calibration database class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2011-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 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
66
67 // Return
68 return;
69}
70
71
72/***********************************************************************//**
73 * @brief Copy constructor
74 *
75 * @param[in] caldb Calibration database.
76 ***************************************************************************/
78{
79 // Initialise class members for clean destruction
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 ***************************************************************************/
99GCaldb::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 ***************************************************************************/
127GCaldb::GCaldb(const std::string& mission, const std::string& instrument)
128{
129 // Initialise members
130 init_members();
131
132 // Open database
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 ***************************************************************************/
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 ***************************************************************************/
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 ***************************************************************************/
227int 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::invalid_value
246 * CALDB environment variable not set
247 *
248 * The calibration directory path is given by one of the following
249 *
250 * $CALDB/data/<mission>
251 * $CALDB/data/<mission>/<instrument>
252 *
253 * where <mission> is the name of the mission and <instrument> is the
254 * optional instrument name (all lower case). The arguments provided to the
255 * method are transformed to lower case.
256 ***************************************************************************/
257std::string GCaldb::rootdir(void) const
258{
259 // Initialise root directory to optional root directory name
260 std::string rootdir = m_opt_rootdir;
261
262 // If root directory is empty then get the directory name from the
263 // CALDB environment variable. Throw an exception if the environment
264 // variable has not been set
265 if (rootdir.empty()) {
266
267 // Get root directory from CALDB environment variables
268 char* ptr1 = std::getenv("CALDB");
269
270 // Throw an exception if non of the environment variables was set
271 if (ptr1 == NULL) {
272 std::string msg = "CALDB environment value not found. Please set "
273 "the CALDB environment variable to a valid "
274 "calibration database root directory.";
276 }
277
278 // If CALDB was set then check whether the directory exists
279 if (ptr1 != NULL) {
280 if (access(ptr1, F_OK) == 0) {
281 rootdir = std::string(ptr1);
282 }
283 }
284
285 } // endif: no optional root directory has been set
286
287 // Return root directory
288 return rootdir;
289}
290
291
292/***********************************************************************//**
293 * @brief Set calibration database root directory
294 *
295 * @param[in] pathname Calibration database root directory.
296 *
297 * @exception GException::invalid_argument
298 * Calibration database root directory not found.
299 * @exception GException::invalid_value
300 * No read permission granted for calibration database root
301 * directory.
302 *
303 * Sets the calibration database root directory to a specific path. The
304 * method verifies the existence of the root directory prior to setting.
305 ***************************************************************************/
306void GCaldb::rootdir(const std::string& pathname)
307{
308 // Expand pathname
309 std::string rootdir = gammalib::expand_env(pathname);
310
311 // Verify that specified root directory exists
313 std::string msg = "Calibration database root directory \""+
314 rootdir+"\" not found. Please specify a valid "
315 "root directory name.";
317 }
318
319 // Verify that specified root directory allows read access
320 if (access(rootdir.c_str(), R_OK) != 0) {
321 std::string msg = "Calibration database root directory \""+
322 rootdir+"\" is not accessible for read access. "
323 "Please provide read access to the calibration "
324 "database root directory.";
326 }
327
328 // Set calibration database root directory
330
331 // Return
332 return;
333}
334
335
336/***********************************************************************//**
337 * @brief Return path to calibration directory
338 *
339 * @param[in] mission Mission name (case insensitive).
340 * @param[in] instrument Instrument name (case insensitive; optional).
341 *
342 * @exception GException::invalid_argument
343 * Calibration directory not found.
344 * @exception GException::invalid_value
345 * No read permission granted to calibration directory.
346 *
347 * The calibration directory path is given by one of the following
348 *
349 * $CALDB/data/<mission>
350 * $CALDB/data/<mission>/<instrument>
351 *
352 * where <mission> is the name of the mission and <instrument> is the
353 * optional instrument name (all lower case). The arguments provided to the
354 * method are transformed to lower case.
355 ***************************************************************************/
356std::string GCaldb::path(const std::string& mission, const std::string& instrument)
357{
358 // Verify that mission name is valid and directory is accessible
359 std::string path = rootdir() + "/data/" + gammalib::tolower(mission);
361 std::string msg = "Requested mission \""+gammalib::toupper(mission)+
362 "\" not found in calibration database. Please "
363 "specify an available mission or add mission to "
364 "calibration database.";
366 }
367 if (access(path.c_str(), R_OK) != 0) {
368 std::string msg = "Calibration database directory \""+path+"\" for "
369 " mission \""+gammalib::toupper(mission)+"\" is "
370 "not accessible for read access. Please provide "
371 "read access to the calibration database "
372 "directory.";
374 }
375
376 // If an instrument has been specified, verify that instrument name is
377 // valid and directory is accessible
378 if (instrument.length() > 0) {
379
380 // Add instrument to path
382
383 // Verify path
385 std::string msg = "Requested instrument \""+
387 "\" on mission \""+
388 gammalib::toupper(mission)+"\" not found in "
389 "calibration database. Please specify an "
390 "available instrument or add instrument to "
391 "calibration database.";
393 }
394 if (access(path.c_str(), R_OK) != 0) {
395 std::string msg = "Calibration database directory \""+path+"\" for "
396 "instrument \""+gammalib::toupper(instrument)+
397 "\" on mission \""+
398 gammalib::toupper(mission)+"\" is not "
399 "accessible for read access. Please provide "
400 "read access to the calibration database "
401 "directory.";
403 }
404
405 } // endif: instrument has been specified
406
407 // Return path
408 return path;
409}
410
411
412/***********************************************************************//**
413 * @brief Return absolute CIF filename
414 *
415 * @param[in] mission Mission name (case insensitive).
416 * @param[in] instrument Instrument name (case insensitive; optional).
417 *
418 * @exception GException::file_error
419 * Calibration Index File not found.
420 *
421 * The calibration directory path is given by one of the following
422 *
423 * $CALDB/data/<mission>/caldb.indx
424 * $CALDB/data/<mission>/<instrument>/caldb.indx
425 *
426 * where <mission> is the name of the mission and <instrument> is the
427 * optional instrument name (all lower case). The arguments provided to the
428 * method are transformed to lower case.
429 ***************************************************************************/
430std::string GCaldb::cifname(const std::string& mission, const std::string& instrument)
431{
432 // Set calibration index filename
433 std::string cif = path(mission, instrument) + "/caldb.indx";
434
435 // Check if file exists
436 GFilename filename(cif);
437 if (!filename.exists()) {
438 std::string msg = "Calibration Index File (CIF) \""+
439 cif+"\" not found.";
441 }
442
443 // Return cif
444 return cif;
445}
446
447
448/***********************************************************************//**
449 * @brief Open calibration database
450 *
451 * @param[in] mission Mission name (case insensitive).
452 * @param[in] instrument Instrument name (case insensitive; optional).
453 *
454 * Opens the calibration database for a given mission and instrument. Opening
455 * consists of loading the Calibration Index File (CIF) in memory. Once
456 * opened, calibration information can be accessed.
457 ***************************************************************************/
458void GCaldb::open(const std::string& mission, const std::string& instrument)
459{
460 // Close any open database
461 close();
462
463 // Set full CIF filename (this also validates the mission and
464 // instrument names)
466
467 // Store mission and instrument
470
471 // Open CIF FITS file
473
474 // Store pointer to first extension which holds the CIF table
475 m_cif = m_fits.table(1);
476
477 // Return
478 return;
479}
480
481
482/***********************************************************************//**
483 * @brief Close calibration database
484 *
485 * Close any previously opened calibration database.
486 ***************************************************************************/
488{
489 // Reset database parameters
490 m_mission.clear();
491 m_instrument.clear();
492 m_cifname.clear();
493
494 // Close CIF FITS file
495 m_fits.close();
496
497 // Reset CIF table pointer
498 m_cif = NULL;
499
500 // Return
501 return;
502}
503
504
505/***********************************************************************//**
506 * @brief Return calibration file name based on selection parameters
507 *
508 * @param[in] detector Detector name (not used if empty).
509 * @param[in] filter Filter name (not used if empty).
510 * @param[in] codename Code name (not used if empty).
511 * @param[in] date Date in yyyy-mm-dd format (not used if empty).
512 * @param[in] time Time in hh:mm:ss format (not used if empty).
513 * @param[in] expr Boolean selection expression (not used if empty).
514 * @return Calibration filename (empty if not found).
515 *
516 * Returns a calibration file name based on selection parameters. If more
517 * files satisfy the specified selection parameters, the first file will
518 * be returned.
519 *
520 * @todo data should support "now" and probably be implemented using < condition.
521 * @todo time should support "now" and probably be implemented using < condition.
522 * @todo expr should support arbitrary Boolean expressions.
523 ***************************************************************************/
524GFilename GCaldb::filename(const std::string& detector,
525 const std::string& filter,
526 const std::string& codename,
527 const std::string& date,
528 const std::string& time,
529 const std::string& expr)
530{
531 // Initialise empty filename
533
534 // Continue only if CIF is opened
535 if (m_cif != NULL) {
536
537 // Loop over all CIF entries
538 for (int i = 0; i < size(); ++i) {
539
540 // Initialise selection flags
541 bool match_detector = false;
542 bool match_filter = false;
543 bool match_codename = false;
544 bool match_date = false;
545 bool match_time = false;
546 bool match_expr = false;
547
548 // Check for detector
549 if (detector.length() > 0) {
550 const GFitsTableCol* column = (*m_cif)["DETNAM"];
551 if (gammalib::toupper(detector) ==
552 gammalib::toupper(column->string(i))) {
553 match_detector = true;
554 }
555 }
556 else {
557 match_detector = true;
558 }
559
560 // Check for filter
561 if (filter.length() > 0) {
562 const GFitsTableCol* column = (*m_cif)["FILTER"];
563 if (gammalib::toupper(filter) ==
564 gammalib::toupper(column->string(i))) {
565 match_filter = true;
566 }
567 }
568 else {
569 match_filter = true;
570 }
571
572 // Check for code name
573 if (codename.length() > 0) {
574 const GFitsTableCol* column = (*m_cif)["CAL_CNAM"];
575 if (gammalib::toupper(codename) ==
576 gammalib::toupper(column->string(i))) {
577 match_codename = true;
578 }
579 }
580 else {
581 match_codename = true;
582 }
583
584 // Check for date
585 if (date.length() > 0) {
586 const GFitsTableCol* column = (*m_cif)["CAL_VSD"];
587 if (gammalib::toupper(date) ==
588 gammalib::toupper(column->string(i))) {
589 match_date = true;
590 }
591 }
592 else {
593 match_date = true;
594 }
595
596 // Check for time
597 if (time.length() > 0) {
598 const GFitsTableCol* column = (*m_cif)["CAL_VST"];
599 if (gammalib::toupper(time) ==
600 gammalib::toupper(column->string(i))) {
601 match_time = true;
602 }
603 }
604 else {
605 match_time = true;
606 }
607
608 // Check for expression
609 if (expr.length() > 0) {
610 const GFitsTableCol* column = (*m_cif)["CAL_CBD"];
611 int num_columns = column->elements(i);
612 for (int k = 0; k < num_columns; ++k) {
613 if (gammalib::toupper(expr) ==
614 gammalib::toupper(column->string(i,k))) {
615 match_expr = true;
616 break;
617 }
618 }
619 }
620 else {
621 match_expr = true;
622 }
623
624 // Select file if all selection match
625 if (match_detector && match_filter && match_codename &&
626 match_date && match_time && match_expr) {
627 const GFitsTableCol* cal_dir = (*m_cif)["CAL_DIR"];
628 const GFitsTableCol* cal_file = (*m_cif)["CAL_FILE"];
629 std::string path = rootdir();
630 if (path.empty()) {
631 filename = cal_dir->string(i) + "/" +
632 cal_file->string(i);
633 }
634 else {
635 filename = path + "/" +
636 cal_dir->string(i) + "/" +
637 cal_file->string(i);
638 }
639 break;
640 }
641
642 } // endfor: looped over all CIF entries
643
644 } // endif: CIF has been opened
645
646 // Return filename
647 return filename;
648}
649
650
651/***********************************************************************//**
652 * @brief Print calibration database information
653 *
654 * @param[in] chatter Chattiness (defaults to NORMAL).
655 * @return String containing calibration database information.
656 ***************************************************************************/
657std::string GCaldb::print(const GChatter& chatter) const
658{
659 // Initialise result string
660 std::string result;
661
662 // Continue only if chatter is not silent
663 if (chatter != SILENT) {
664
665 // Append Header
666 result.append("=== GCaldb ===");
667
668 // Append information
669 result.append("\n"+gammalib::parformat("Database root"));
670 try {
671 result.append(rootdir());
672 }
673 catch (std::exception& e) {
674 result.append("undefined");
675 }
676
677 // Append information about opened database
678 if (m_cif != NULL) {
679 result.append("\n"+gammalib::parformat("Selected Mission"));
680 result.append(gammalib::toupper(m_mission));
681 result.append("\n"+gammalib::parformat("Selected Instrument"));
682 result.append(gammalib::toupper(m_instrument));
683 result.append("\n"+gammalib::parformat("Calibration Index File"));
684 result.append(m_cifname);
685 result.append("\n"+gammalib::parformat("Number of entries"));
686 result.append(gammalib::str(size()));
687 }
688
689 } // endif: chatter was not silent
690
691 // Return
692 return result;
693}
694
695
696/*==========================================================================
697 = =
698 = Private methods =
699 = =
700 ==========================================================================*/
701
702/***********************************************************************//**
703 * @brief Initialise class members
704 ***************************************************************************/
706{
707 // Initialise members
708 m_opt_rootdir.clear();
709 m_mission.clear();
710 m_instrument.clear();
711 m_cifname.clear();
712 m_fits.clear();
713 m_cif = NULL;
714
715 // Return
716 return;
717}
718
719
720/***********************************************************************//**
721 * @brief Copy class members
722 *
723 * @param[in] caldb Calibration database.
724 ***************************************************************************/
725void GCaldb::copy_members(const GCaldb& caldb)
726{
727 // Copy attributes
729 m_mission = caldb.m_mission;
731 m_cifname = caldb.m_cifname;
732 m_fits = caldb.m_fits;
733
734 // Set CIF table pointer. We do not copy over the pointer as the FITS
735 // file has been copied here.
736 if (caldb.m_cif != NULL) {
737 m_cif = m_fits.table(1);
738 }
739 else {
740 m_cif = NULL;
741 }
742
743 // Return
744 return;
745}
746
747
748/***********************************************************************//**
749 * @brief Delete class members
750 ***************************************************************************/
752{
753 // Close any open database
754 close();
755
756 // Return
757 return;
758}
759
760
#define G_GET_ROOTDIR
Definition GCaldb.cpp:38
#define G_SET_ROOTDIR
Definition GCaldb.cpp:39
#define G_PATH
Definition GCaldb.cpp:40
#define G_CIFNAME
Definition GCaldb.cpp:41
Calibration database class interface definition.
Exception handler interface definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
Calibration database class.
Definition GCaldb.hpp:66
GCaldb * clone(void) const
Clone calibration database.
Definition GCaldb.cpp:212
GFits m_fits
CIF FITS file.
Definition GCaldb.hpp:114
void init_members(void)
Initialise class members.
Definition GCaldb.cpp:705
std::string cifname(const std::string &mission, const std::string &instrument="")
Return absolute CIF filename.
Definition GCaldb.cpp:430
std::string path(const std::string &mission, const std::string &instrument="")
Return path to calibration directory.
Definition GCaldb.cpp:356
std::string rootdir(void) const
Return path to CALDB root directory.
Definition GCaldb.cpp:257
GFitsTable * m_cif
Pointer to CIF table.
Definition GCaldb.hpp:115
const std::string & mission(void) const
Return mission.
Definition GCaldb.hpp:137
GCaldb & operator=(const GCaldb &caldb)
Assignment operator.
Definition GCaldb.cpp:164
void open(const std::string &mission, const std::string &instrument="")
Open calibration database.
Definition GCaldb.cpp:458
void copy_members(const GCaldb &caldb)
Copy class members.
Definition GCaldb.cpp:725
virtual ~GCaldb(void)
Destructor.
Definition GCaldb.cpp:143
int size(void) const
Returns number of entries in calibration database.
Definition GCaldb.cpp:227
void free_members(void)
Delete class members.
Definition GCaldb.cpp:751
std::string m_cifname
CIF filename of opened database.
Definition GCaldb.hpp:113
const std::string & instrument(void) const
Return instrument.
Definition GCaldb.hpp:149
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:524
std::string m_instrument
Instrument of opened database.
Definition GCaldb.hpp:112
GCaldb(void)
Void constructor.
Definition GCaldb.cpp:62
void clear(void)
Clear calibration database.
Definition GCaldb.cpp:194
void close(void)
Close calibration database.
Definition GCaldb.cpp:487
std::string print(const GChatter &chatter=NORMAL) const
Print calibration database information.
Definition GCaldb.cpp:657
std::string m_opt_rootdir
Optional root directory.
Definition GCaldb.hpp:110
std::string m_mission
Mission of opened database.
Definition GCaldb.hpp:111
Filename class.
Definition GFilename.hpp:62
bool exists(void) const
Checks whether file exists.
Abstract interface for FITS table column.
virtual std::string string(const int &row, const int &inx=0) const =0
void elements(const int &row, const int &elements)
Set number of column elements for specific row.
const int & nrows(void) const
Return number of rows in table.
void open(const GFilename &filename, const bool &create=false)
Open or (optionally) create FITS file.
Definition GFits.cpp:1041
void close(void)
Close FITS file.
Definition GFits.cpp:1342
void clear(void)
Clear FITS file.
Definition GFits.cpp:195
GFitsTable * table(const int &extno)
Get pointer to table HDU.
Definition GFits.cpp:482
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1143
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
std::string tolower(const std::string &s)
Convert string to lower case.
Definition GTools.cpp:955
std::string expand_env(const std::string &arg)
Expand environment variables in string.
Definition GTools.cpp:214
bool dir_exists(const std::string &dirname)
Checks if directory exists.
Definition GTools.cpp:1312
std::string toupper(const std::string &s)
Convert string to upper case.
Definition GTools.cpp:941