GammaLib 2.1.0.dev
Loading...
Searching...
No Matches
GResponseVectorCache.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GResponseVectorCache.cpp - Response vector cache class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2020-2022 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 GResponseVectorCache.cpp
23 * @brief Response vector cache class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GTools.hpp"
32#include "GVector.hpp"
33#include "GFilename.hpp"
34#include "GFits.hpp"
35#include "GFitsTable.hpp"
36#include "GFitsBinTable.hpp"
38#include "GFitsTableLongCol.hpp"
41
42/* __ Method name definitions ____________________________________________ */
43
44/* __ Macros _____________________________________________________________ */
45
46/* __ Coding definitions _________________________________________________ */
47
48/* __ Debug definitions __________________________________________________ */
49//#define G_DEBUG_VECTOR_CACHE //!< Debug vector cache
50
51
52/*==========================================================================
53 = =
54 = Constructors/destructors =
55 = =
56 ==========================================================================*/
57
58/***********************************************************************//**
59 * @brief Void constructor
60 ***************************************************************************/
62{
63 // Initialise class members
65
66 // Return
67 return;
68}
69
70
71/***********************************************************************//**
72 * @brief Copy constructor
73 *
74 * @param[in] cache Response vector cache.
75 ***************************************************************************/
77{
78 // Initialise class members
80
81 // Copy members
82 copy_members(cache);
83
84 // Return
85 return;
86}
87
88
89/***********************************************************************//**
90 * @brief Destructor
91 ***************************************************************************/
93{
94 // Free members
96
97 // Return
98 return;
99}
100
101
102/*==========================================================================
103 = =
104 = Operators =
105 = =
106 ==========================================================================*/
107
108/***********************************************************************//**
109 * @brief Assignment operator
110 *
111 * @param[in] cache Response vector cache.
112 * @return Response vector cache.
113 ***************************************************************************/
115{
116 // Execute only if object is not identical
117 if (this != &cache) {
118
119 // Free members
120 free_members();
121
122 // Initialise private members
123 init_members();
124
125 // Copy members
126 copy_members(cache);
127
128 } // endif: object was not identical
129
130 // Return this object
131 return *this;
132}
133
134
135/*==========================================================================
136 = =
137 = Public methods =
138 = =
139 ==========================================================================*/
140
141/***********************************************************************//**
142 * @brief Clear response vector cache
143 ***************************************************************************/
145{
146 // Free members
147 free_members();
148
149 // Initialise private members
150 init_members();
151
152 // Return
153 return;
154}
155
156
157/***********************************************************************//**
158 * @brief Clone response cache
159 *
160 * @return Pointer to deep copy of response cache.
161 ***************************************************************************/
163{
164 return new GResponseVectorCache(*this);
165}
166
167
168/***********************************************************************//**
169 * @brief Set cache value
170 *
171 * @param[in] cache_id Cache identifier.
172 * @param[in] vector Cache vector.
173 *
174 * Set cache vector for a given @p cache_id.
175 ***************************************************************************/
176void GResponseVectorCache::set(const std::string& cache_id,
177 const GVector& vector)
178{
179 // Debug vector cache
180 #if defined(G_DEBUG_VECTOR_CACHE)
181 std::cout << "GResponseVectorCache::set(";
182 std::cout << cache_id << "," << vector.size() << "):";
183 #endif
184
185 // Initialise pointers to values and indices
186 double* values = NULL;
187 int* indices = NULL;
188
189 // Find cache index
190 int index = find_cache(cache_id);
191
192 // Determine size of vector cache
193 int entries = vector.non_zeros();
194
195 // Debug vector cache
196 #if defined(G_DEBUG_VECTOR_CACHE)
197 if (index != -1) {
198 std::cout << " entry found at index " << index;
199 std::cout << " with " << m_cache_entries[index] << " elements.";
200 std::cout << " Require " << entries << " elements.";
201 std::cout << std::endl;
202 }
203 else {
204 std::cout << " no entry found.";
205 std::cout << " Require " << entries << " elements.";
206 std::cout << std::endl;
207 }
208 #endif
209
210 // If cache identifier does not yet exist then create new cache entry
211 // and allocate memory to hold cache values and indices
212 if (index == -1) {
213 if (entries > 0) {
214 values = new double[entries];
215 indices = new int[entries];
216 }
217 m_cache_ids.push_back(cache_id);
218 m_cache_entries.push_back(entries);
219 m_cache_values.push_back(values);
220 m_cache_indices.push_back(indices);
221 }
222
223 // ... otherwise update cache existing entry by allocating new memory
224 // to hold cache values and indices in case that the number of entries
225 // have changed
226 else {
227 if (m_cache_entries[index] != entries) {
228 if (entries > 0) {
229 values = new double[entries];
230 indices = new int[entries];
231 }
232 if (m_cache_values[index] != NULL) delete [] m_cache_values[index];
233 if (m_cache_indices[index] != NULL) delete [] m_cache_indices[index];
234 m_cache_entries[index] = entries;
235 m_cache_values[index] = values;
236 m_cache_indices[index] = indices;
237 }
238 else {
239 values = m_cache_values[index];
240 indices = m_cache_indices[index];
241 }
242 }
243
244 // Set cache vector
245 for (int i = 0; i < vector.size(); ++i) {
246 if (vector[i] != 0.0) {
247 *values++ = vector[i];
248 *indices++ = i;
249 }
250 }
251
252 // Return
253 return;
254}
255
256
257/***********************************************************************//**
258 * @brief Remove cache
259 *
260 * @param[in] cache_id Cache identifier.
261 *
262 * Remove cache for a given @p cache_id.
263 ***************************************************************************/
264void GResponseVectorCache::remove(const std::string& cache_id)
265{
266 // Find cache index
267 int index = find_cache(cache_id);
268
269 // If cache index is valid then remove corresponding cache
270 if (index != -1) {
271
272 // Free memory
273 if (m_cache_values[index] != NULL) delete [] m_cache_values[index];
274 if (m_cache_indices[index] != NULL) delete [] m_cache_indices[index];
275
276 // Erase entry
277 m_cache_ids.erase(m_cache_ids.begin() + index);
278 m_cache_entries.erase(m_cache_entries.begin() + index);
279 m_cache_values.erase(m_cache_values.begin() + index);
280 m_cache_indices.erase(m_cache_indices.begin() + index);
281
282 } // endif: cache index was valid
283
284 // Return
285 return;
286}
287
288
289/***********************************************************************//**
290 * @brief Check if cache contains a value for specific parameters
291 *
292 * @param[in] cache_id Cache identifier.
293 * @param[in,out] vector Pointer to cached vector (only if found).
294 * @return True if cached value was found, otherwise false.
295 *
296 * Check if the cache contains a value for a given @p name, reconstructed
297 * energy @p ereco, and true energy @p etrue.
298 *
299 * If the @p value pointer argument is not NULL, the method will return the
300 * cached value through this argument in case that the value exists.
301 ***************************************************************************/
302bool GResponseVectorCache::contains(const std::string& cache_id,
303 GVector* vector) const
304{
305 // Debug vector cache
306 #if defined(G_DEBUG_VECTOR_CACHE)
307 std::cout << "GResponseVectorCache::contains(" << cache_id;
308 if (vector == NULL) {
309 std::cout << ", NULL):";
310 }
311 else {
312 std::cout << "," << vector->size() << "):";
313 }
314 #endif
315
316 // Find cache index
317 int index = find_cache(cache_id);
318
319 // Set contains flag
320 bool contains = (index != -1);
321
322 // Debug vector cache
323 #if defined(G_DEBUG_VECTOR_CACHE)
324 if (contains) {
325 std::cout << " entry found at index " << index;
326 std::cout << " with " << m_cache_entries[index] << " elements.";
327 std::cout << std::endl;
328 }
329 else {
330 std::cout << " no entry found." << std::endl;
331 }
332 #endif
333
334 // If cache contains the identifier and a pointer to a vector was
335 // provided then fill the vector
336 if (contains && vector != NULL) {
337
338 // Get pointer to values and indices
339 double* values = m_cache_values[index];
340 int* indices = m_cache_indices[index];
341
342 // Fill vector
343 for (int i = 0; i < m_cache_entries[index]; ++i, ++values, ++indices) {
344 (*vector)[*indices] = *values;
345 }
346
347 } // endif: filled vector
348
349 // Return containment flag
350 return contains;
351}
352
353
354/***********************************************************************//**
355 * @brief Load response vector cache from FITS file
356 *
357 * @param[in] filename FITS file name.
358 *
359 * Loads the response vector cache from a FITS file. All binary tables in
360 * the FITS file are assumed to be response vector cache entries.
361 ***************************************************************************/
363{
364 // Free members
365 free_members();
366
367 // Initialise attributes
368 init_members();
369
370 // Open FITS file
371 GFits fits(filename);
372
373 // Loop over all extensions
374 for (int i = 0; i < fits.size(); ++i) {
375
376 // Handle only binary table extensions
377 if (fits[i]->exttype() == GFitsHDU::HT_BIN_TABLE) {
378 read(*fits.table(i));
379 }
380
381 } // endfor: looped over all extensions
382
383 // Close FITS file
384 fits.close();
385
386 // Return
387 return;
388}
389
390
391/***********************************************************************//**
392 * @brief Save the response vector cache into FITS file
393 *
394 * @param[in] filename FITS file name.
395 * @param[in] clobber Overwrite an response vector cache file?
396 *
397 * Saves the response vector cache into a FITS file. If a file with the given
398 * @p filename does not yet exist it will be created, otherwise the method
399 * opens the existing file. The response vector cache can only be appended
400 * to an existing file if the @p clobber flag is set to "true" (otherwise
401 * an exception is thrown).
402 *
403 * The method will append all cache entries as binary FITS tables to the
404 * FITS file. The table extension names are defined by the cache
405 * identifiers. All cache entries with identifiers exceeding 80 characters
406 * will be skipped to avoid truncation of cache identifiers.
407 ***************************************************************************/
409 const bool& clobber) const
410{
411 // Open or create FITS file (without extension name)
412 GFits fits(filename.url(), true);
413
414 // Loop over the cache entries
415 for (int i = 0; i < size(); ++i) {
416
417 // Set extension name
418 std::string extname = m_cache_ids[i];
419
420 // Skip entries with too long identifiers
421 if (extname.length() > 80) {
422 continue;
423 }
424
425 // Get number of cache entries
426 int entries = m_cache_entries[i];
427
428 // Create response vector cache columns
429 GFitsTableDoubleCol col_values("VALUES", entries);
430 GFitsTableLongCol col_indices("INDICES", entries);
431
432 // Write cache values and indices in columns
433 double* values = m_cache_values[i];
434 int* indices = m_cache_indices[i];
435 for (int k = 0; k < entries; ++k, ++values, ++indices) {
436 col_values(k) = *values;
437 col_indices(k) = *indices;
438 }
439
440 // Create binary table
441 GFitsBinTable table(entries);
442 table.append(col_values);
443 table.append(col_indices);
444 table.extname(extname);
445
446 // Write mandatory keywords
447 table.card("HDUCLASS", "OGIP", "Format conforms to OGIP standard");
448 table.card("HDUCLAS1", "RESPONSE", "Extension contains response data");
449 table.card("HDUCLAS2", "VECTOR_CACHE", "Extension contains a response vector cache");
450 table.card("HDUVERS", "1.0.0", "Version of the file format");
451
452 // If the FITS object contains already an extension with the same
453 // name then remove now this extension
454 if (fits.contains(extname)) {
455 fits.remove(extname);
456 }
457
458 // Append response vector cache to FITS file
459 fits.append(table);
460
461
462 } // endfor: looped over cache entries
463
464 // Save to file
465 fits.save(clobber);
466
467 // Return
468 return;
469}
470
471
472/***********************************************************************//**
473 * @brief Read response vector cache from FITS table
474 *
475 * @param[in] table FITS table.
476 *
477 * Reads response vector cache from a FITS table. There is one cache entry
478 * in a FITS table, with the table extension name specifying the cache
479 * identifier. Only tables containing the "HDUCLAS2" keyword set to
480 * "VECTOR_CACHE" will be considered by the method, all other tables will
481 * be simply skipped.
482 ***************************************************************************/
484{
485 // Continue only if table contains a response vector cache
486 if (table.has_card("HDUCLAS2") && table.string("HDUCLAS2") == "VECTOR_CACHE") {
487
488 // Get number of rows in FITS table
489 int entries = table.nrows();
490
491 // Continue only if there are rows in the FITS table
492 if (entries > 0) {
493
494 // Set cache ID from extension name
495 std::string cache_id = table.extname();
496
497 // Get column pointers
498 const GFitsTableCol* col_values = table["VALUES"];
499 const GFitsTableCol* col_indices = table["INDICES"];
500
501 // Allocate memory for values and indices
502 double* values = new double[entries];
503 int* indices = new int[entries];
504
505 // Put information and pointers into cache
506 m_cache_ids.push_back(cache_id);
507 m_cache_entries.push_back(entries);
508 m_cache_values.push_back(values);
509 m_cache_indices.push_back(indices);
510
511 // Extact values and indices
512 for (int i = 0; i < entries; ++i) {
513 *values++ = col_values->real(i);
514 *indices++ = col_indices->integer(i);
515 }
516
517 } // endif: there were entries in table
518
519 } // endif: table contained a response vector cache
520
521 // Return
522 return;
523}
524
525
526/***********************************************************************//**
527 * @brief Print response cache
528 *
529 * @param[in] chatter Chattiness.
530 * @return String containing response cache information.
531 ***************************************************************************/
532std::string GResponseVectorCache::print(const GChatter& chatter) const
533{
534 // Initialise result string
535 std::string result;
536
537 // Continue only if chatter is not silent
538 if (chatter != SILENT) {
539
540 // Append header
541 result.append("=== GResponseVectorCache ===");
542
543 // Append total cache size
544 result.append("\n"+gammalib::parformat("Number of cached vectors"));
545 result.append(gammalib::str(size()));
546
547 // Append cache information
548 for (int i = 0; i < size(); ++i) {
549 result.append("\n"+gammalib::parformat("Identifier"));
550 result.append(m_cache_ids[i]);
551 result.append(" ("+gammalib::str(m_cache_entries[i])+" values");
552 }
553
554 } // endif: chatter was not silent
555
556 // Return result
557 return result;
558}
559
560
561/*==========================================================================
562 = =
563 = Private methods =
564 = =
565 ==========================================================================*/
566
567/***********************************************************************//**
568 * @brief Initialise class members
569 ***************************************************************************/
571{
572 // Initialise members
573 m_cache_ids.clear();
574 m_cache_entries.clear();
575 m_cache_values.clear();
576 m_cache_indices.clear();
577
578 // Return
579 return;
580}
581
582
583/***********************************************************************//**
584 * @brief Copy class members
585 *
586 * @param[in] cache Response cache.
587 ***************************************************************************/
589{
590 // Copy members
591 m_cache_ids = cache.m_cache_ids;
593
594 // Copy values and indices
595 for (int i = 0; i < size(); ++i) {
596 double* values = NULL;
597 int* indices = NULL;
598 if (m_cache_entries[i] > 0) {
599 values = new double[m_cache_entries[i]];
600 indices = new int[m_cache_entries[i]];
601 for (int k = 0; k < m_cache_entries[i]; ++k) {
602 values[k] = cache.m_cache_values[i][k];
603 indices[k] = cache.m_cache_indices[i][k];
604 }
605 }
606 m_cache_values.push_back(values);
607 m_cache_indices.push_back(indices);
608 }
609
610 // Return
611 return;
612}
613
614
615/***********************************************************************//**
616 * @brief Delete class members
617 ***************************************************************************/
619{
620 // Loop over entries
621 for (int i = 0; i < size(); ++i) {
622 if (m_cache_values[i] != NULL) delete [] m_cache_values[i];
623 if (m_cache_indices[i] != NULL) delete [] m_cache_indices[i];
624 m_cache_values[i] = NULL;
625 m_cache_indices[i] = NULL;
626 }
627
628 // Return
629 return;
630}
631
632
633/***********************************************************************//**
634 * @brief Find cache
635 *
636 * @param[in] cache_id Cache identifier.
637 * @return Cache index (-1 if no cache was found)
638 *
639 * Find cache for a given @p cache_id. If no cache was found the method
640 * returns -1.
641 ***************************************************************************/
642int GResponseVectorCache::find_cache(const std::string& cache_id) const
643{
644 // Initialise cache index
645 int index = -1;
646
647 // Loop over cache
648 for (int i = 0; i < m_cache_ids.size(); ++i) {
649 if (m_cache_ids[i] == cache_id) {
650 index = i;
651 break;
652 }
653 }
654
655 // Return index
656 return index;
657}
658
659
Filename class interface definition.
FITS binary table class definition.
FITS table double column class interface definition.
FITS table long integer column class interface definition.
FITS table string column class interface definition.
FITS table abstract base class interface definition.
FITS file class interface definition.
Response vector cache class definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
Vector class interface definition.
Filename class.
Definition GFilename.hpp:62
std::string url(void) const
Return Uniform Resource Locator (URL)
FITS binary table class.
bool has_card(const int &cardno) const
Check existence of header card.
Definition GFitsHDU.hpp:233
const std::string & extname(void) const
Return extension name.
Definition GFitsHDU.hpp:162
@ HT_BIN_TABLE
Definition GFitsHDU.hpp:69
std::string string(const std::string &keyname) const
Return card value as string.
Definition GFitsHDU.hpp:410
GFitsHeaderCard & card(const int &cardno)
Return header card.
Definition GFitsHDU.hpp:259
Abstract interface for FITS table column.
virtual int integer(const int &row, const int &inx=0) const =0
virtual double real(const int &row, const int &inx=0) const =0
FITS table double column.
FITS table long integer column.
Abstract interface for FITS table.
GFitsTableCol * append(const GFitsTableCol &column)
Append column to the table.
const int & nrows(void) const
Return number of rows in table.
FITS file class.
Definition GFits.hpp:63
int size(void) const
Return number of HDUs in FITS file.
Definition GFits.hpp:237
bool contains(const int &extno) const
Check if HDU exists in FITS file.
Definition GFits.hpp:282
GFitsHDU * append(const GFitsHDU &hdu)
Append HDU to FITS file.
Definition GFits.cpp:678
void close(void)
Close FITS file.
Definition GFits.cpp:1342
void remove(const int &extno)
Remove HDU from FITS file.
Definition GFits.cpp:862
void save(const bool &clobber=false)
Saves FITS file.
Definition GFits.cpp:1178
GFitsTable * table(const int &extno)
Get pointer to table HDU.
Definition GFits.cpp:482
Response vector cache class.
std::string print(const GChatter &chatter=NORMAL) const
Print response cache.
bool contains(const std::string &cache_id, GVector *irfs=NULL) const
Check if cache contains a value for specific parameters.
void read(const GFitsTable &table)
Read response vector cache from FITS table.
void free_members(void)
Delete class members.
int size(void) const
Returns size of vector chache.
std::vector< int > m_cache_entries
virtual ~GResponseVectorCache(void)
Destructor.
std::vector< int * > m_cache_indices
GResponseVectorCache(void)
Void constructor.
void save(const GFilename &filename, const bool &clobber=false) const
Save the response vector cache into FITS file.
std::vector< double * > m_cache_values
void remove(const std::string &cache_id)
Remove cache.
void copy_members(const GResponseVectorCache &cache)
Copy class members.
void init_members(void)
Initialise class members.
void clear(void)
Clear response vector cache.
int find_cache(const std::string &cache_id) const
Find cache.
std::vector< std::string > m_cache_ids
void load(const GFilename &filename)
Load response vector cache from FITS file.
void set(const std::string &cache_id, const GVector &vector)
Set cache value.
GResponseVectorCache * clone(void) const
Clone response cache.
GResponseVectorCache & operator=(const GResponseVectorCache &cache)
Assignment operator.
Vector class.
Definition GVector.hpp:46
const int & size(void) const
Return size of vector.
Definition GVector.hpp:180
int non_zeros(void) const
Returns number of non-zero elements in vector.
Definition GVector.cpp:627
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1162
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:508