GammaLib 2.0.0
Loading...
Searching...
No Matches
GRmf.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GRmf.cpp - XSPEC Redistribution Matrix File class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2013-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 GRmf.cpp
23 * @brief XSPEC Redistribution Matrix File 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 "GMath.hpp"
33#include "GRmf.hpp"
34#include "GException.hpp"
35#include "GFits.hpp"
36#include "GFitsTable.hpp"
37#include "GFitsBinTable.hpp"
40
41/* __ Method name definitions ____________________________________________ */
42#define G_OPERATOR_PLUS "GRmf::operator+=(GRmf&)"
43#define G_OPERATOR_MINUS "GRmf::operator-=(GRmf&)"
44#define G_AT "GRmf::at(int&, int&)"
45
46/* __ Macros _____________________________________________________________ */
47
48/* __ Coding definitions _________________________________________________ */
49
50/* __ Debug definitions __________________________________________________ */
51
52
53/*==========================================================================
54 = =
55 = Constructors/destructors =
56 = =
57 ==========================================================================*/
58
59/***********************************************************************//**
60 * @brief Void constructor
61 ***************************************************************************/
63{
64 // Initialise members
66
67 // Return
68 return;
69}
70
71
72/***********************************************************************//**
73 * @brief File constructor
74 *
75 * @param[in] filename File name.
76 ***************************************************************************/
77GRmf::GRmf(const GFilename& filename)
78{
79 // Initialise members
81
82 // Load RMF file
84
85 // Return
86 return;
87}
88
89
90/***********************************************************************//**
91 * @brief Energy boundary constructor
92 *
93 * @param[in] etrue True energy boundaries.
94 * @param[in] emeasured Measured energy boundaries.
95 ***************************************************************************/
96GRmf::GRmf(const GEbounds& etrue, const GEbounds& emeasured)
97{
98 // Initialise members
100
101 // Set energy boundaries
104
105 // Initialize matrix
107
108 // Return
109 return;
110}
111
112
113/***********************************************************************//**
114 * @brief Copy constructor
115 *
116 * @param[in] rmf Redistribution Matrix File.
117 ***************************************************************************/
118GRmf::GRmf(const GRmf& rmf)
119{
120 // Initialise members
121 init_members();
122
123 // Copy members
124 copy_members(rmf);
125
126 // Return
127 return;
128}
129
130
131/***********************************************************************//**
132 * @brief Destructor
133 ***************************************************************************/
135{
136 // Free members
137 free_members();
138
139 // Return
140 return;
141}
142
143
144/*==========================================================================
145 = =
146 = Operators =
147 = =
148 ==========================================================================*/
149
150/***********************************************************************//**
151 * @brief Assignment operator
152 *
153 * @param[in] rmf Redistribution Matrix File.
154 * @return Redistribution Matrix File.
155 ***************************************************************************/
157{
158 // Execute only if object is not identical
159 if (this != &rmf) {
160
161 // Free members
162 free_members();
163
164 // Initialise members
165 init_members();
166
167 // Copy members
168 copy_members(rmf);
169
170 } // endif: object was not identical
171
172 // Return
173 return *this;
174}
175
176
177/***********************************************************************//**
178 * @brief Add Redistribution Matrix File
179 *
180 * @param[in] rmf Redistribution Matrix File.
181 * @return Sum of Redistribution Matrix File.
182 *
183 * @exception GException::invalid_value
184 * Incompatible Redistribution Matrix Files.
185 *
186 * Adds the RMF values of an Redistribution Matrix File to the current
187 * values.
188 *
189 * The operator only works if the provide Redistribution Matrix File has the
190 * same energy binning than the current Redistribution Matrix File.
191 ***************************************************************************/
193{
194 // Throw an exception if the RMF are not compatible
195 if (this->etrue() != rmf.etrue()) {
196 std::string msg = "Incompatible true energy binning of "
197 "Redistribution Matrix File.";
199 }
200 if (this->emeasured() != rmf.emeasured()) {
201 std::string msg = "Incompatible measured energy binning of "
202 "Redistribution Matrix File.";
204 }
205
206 // Add RMF values
207 for (int itrue = 0; itrue < ntrue(); ++itrue) {
208 for (int imeasured = 0; imeasured < nmeasured(); ++imeasured) {
209 m_matrix(itrue, imeasured) += rmf.m_matrix(itrue, imeasured);
210 }
211 }
212
213 // Return
214 return *this;
215}
216
217
218/***********************************************************************//**
219 * @brief Subtract Redistribution Matrix File
220 *
221 * @param[in] rmf Redistribution Matrix File.
222 * @return Difference of Redistribution Matrix File.
223 *
224 * @exception GException::invalid_value
225 * Incompatible Redistribution Matrix Files.
226 *
227 * Subtracts the RMF values of an Redistribution Matrix File from the current
228 * values.
229 *
230 * The operator only works if the provide Redistribution Matrix File has the
231 * same energy binning than the current Redistribution Matrix File.
232 ***************************************************************************/
234{
235 // Throw an exception if the RMF are not compatible
236 if (this->etrue() != rmf.etrue()) {
237 std::string msg = "Incompatible true energy binning of "
238 "Redistribution Matrix File.";
240 }
241 if (this->emeasured() != rmf.emeasured()) {
242 std::string msg = "Incompatible measured energy binning of "
243 "Redistribution Matrix File.";
245 }
246
247 // Subtract RMF values
248 for (int itrue = 0; itrue < ntrue(); ++itrue) {
249 for (int imeasured = 0; imeasured < nmeasured(); ++imeasured) {
250 m_matrix(itrue, imeasured) -= rmf.m_matrix(itrue, imeasured);
251 }
252 }
253
254 // Return
255 return *this;
256}
257
258
259/***********************************************************************//**
260 * @brief Scale Redistribution Matrix File values
261 *
262 * @param[in] scale Scale factor.
263 * @return Scaled Redistribution Matrix File.
264 *
265 * Multiplies the values of the Redistribution Matrix File with a scale
266 * factor.
267 ***************************************************************************/
268GRmf& GRmf::operator*=(const double& scale)
269{
270 // Scale RMF values
271 for (int itrue = 0; itrue < ntrue(); ++itrue) {
272 for (int imeasured = 0; imeasured < nmeasured(); ++imeasured) {
273 m_matrix(itrue, imeasured) *= scale;
274 }
275 }
276
277 // Return
278 return *this;
279}
280
281
282/***********************************************************************//**
283 * @brief Divide Redistribution Matrix File values
284 *
285 * @param[in] scale Division factor.
286 * @return Divided Redistribution Matrix File.
287 *
288 * Divides the values of the Redistribution Matrix File by a division factor.
289 ***************************************************************************/
290GRmf& GRmf::operator/=(const double& scale)
291{
292 // Divide RMF values
293 for (int itrue = 0; itrue < ntrue(); ++itrue) {
294 for (int imeasured = 0; imeasured < nmeasured(); ++imeasured) {
295 m_matrix(itrue, imeasured) /= scale;
296 }
297 }
298
299 // Return
300 return *this;
301}
302
303
304/*==========================================================================
305 = =
306 = Public methods =
307 = =
308 ==========================================================================*/
309
310/***********************************************************************//**
311 * @brief Clear object.
312 *
313 * Reset object to a clean initial state.
314 ***************************************************************************/
315void GRmf::clear(void)
316{
317 // Free memory and initialise members
318 free_members();
319 init_members();
320
321 // Return
322 return;
323}
324
325
326/***********************************************************************//**
327 * @brief Clone object
328 *
329 * @return Redistribution Matrix File.
330 ***************************************************************************/
331GRmf* GRmf::clone(void) const
332{
333 // Clone object
334 return new GRmf(*this);
335}
336
337
338/***********************************************************************//**
339 * @brief Return content of redistribution matrix bin
340 *
341 * @param[in] itrue True energy index [0,...,ntrue()[.
342 * @param[in] imeasured Measured energy index [0,...,nmeasured()[.
343 *
344 * @exception GException::out_of_range
345 * True or measured energy index is out of range.
346 *
347 * Returns reference to content of redistribution matrix bin bin with true
348 * energy index @p itrue and measured energy index @p imeasured.
349 ***************************************************************************/
350double& GRmf::at(const int& itrue, const int& imeasured)
351{
352 // Throw exception if indices are out of range
353 if (itrue < 0 || itrue >= ntrue()) {
354 throw GException::out_of_range(G_AT, "True energy index",
355 itrue, ntrue());
356 }
357 // Throw exception if indices are out of range
358 if (imeasured < 0 || imeasured >= nmeasured()) {
359 throw GException::out_of_range(G_AT, "Measured energy index",
360 imeasured, nmeasured());
361 }
362
363 // Return reference
364 return (m_matrix(itrue, imeasured));
365}
366
367
368/***********************************************************************//**
369 * @brief Return content of redistribution matrix bin (const version)
370 *
371 * @param[in] itrue True energy index [0,...,ntrue()[.
372 * @param[in] imeasured Measured energy index [0,...,nmeasured()[.
373 *
374 * @exception GException::out_of_range
375 * True or measured energy index is out of range.
376 *
377 * Returns reference to content of redistribution matrix bin bin with true
378 * energy index @p itrue and measured energy index @p imeasured.
379 ***************************************************************************/
380const double& GRmf::at(const int& itrue, const int& imeasured) const
381{
382 // Throw exception if indices are out of range
383 if (itrue < 0 || itrue >= ntrue()) {
384 throw GException::out_of_range(G_AT, "True energy index",
385 itrue, ntrue());
386 }
387 // Throw exception if indices are out of range
388 if (imeasured < 0 || imeasured >= nmeasured()) {
389 throw GException::out_of_range(G_AT, "Measured energy index",
390 imeasured, nmeasured());
391 }
392
393 // Return reference
394 return (m_matrix(itrue, imeasured));
395}
396
397
398/***********************************************************************//**
399 * @brief Return true energy boundaries for specified measured energy
400 *
401 * @param[in] emeasured Measured energy.
402 * @return True energy boundaries for specified measured energy.
403 *
404 * Returns the true energy boundaries for the specified measured energy
405 * @p emeasured. If the RMF is not covering the specified measured energy,
406 * an empty energy boundary object is returned.
407 ***************************************************************************/
408GEbounds GRmf::etrue(const GEnergy& emeasured) const
409{
410 // Initialise empty energy boundaries
411 GEbounds ebounds;
412
413 // Determine matrix column that corresponds to specified measured energy
414 int column = m_ebds_measured.index(emeasured);
415
416 // If matrix column was found then determine the boundaries for this
417 // column
418 if (column != -1) {
419
420 // Determine first and last non-zero indices
421 int row_start = -1;
422 int row_stop = -1;
423 for (int row = 0; row < m_matrix.rows(); ++row) {
424 if (m_matrix(row, column) > 0.0) {
425 row_start = row;
426 break;
427 }
428 }
429 for (int row = m_matrix.rows()-1; row >= 0; --row) {
430 if (m_matrix(row, column) > 0.0) {
431 row_stop = row;
432 break;
433 }
434 }
435
436 // Set energy boundaries if valid indices have been found
437 if (row_start != -1 && row_stop != -1) {
438 ebounds = GEbounds(m_ebds_true.emin(row_start),
439 m_ebds_true.emax(row_stop));
440 }
441
442 } // endif: row containing true energy was found
443
444 // Return energy boundaries
445 return ebounds;
446}
447//m_matrix(itrue, imeasured) (row, column)
448
449
450/***********************************************************************//**
451 * @brief Return measured energy boundaries for specified true energy
452 *
453 * @param[in] etrue True energy.
454 * @return Measured energy boundaries for specified true energy.
455 *
456 * Returns the measured energy boundaries for the specified true energy
457 * @p etrue. If the RMF is not covering the specified true energy,
458 * an empty energy boundary object is returned.
459 ***************************************************************************/
461{
462 // Initialise empty energy boundaries
463 GEbounds ebounds;
464
465 // Determine matrix row that corresponds to specified true energy
466 int row = m_ebds_true.index(etrue);
467
468 // If matrix row was found then determine the boundaries for this
469 // row
470 if (row != -1) {
471
472 // Determine first and last non-zero indices
473 int column_start = -1;
474 int column_stop = -1;
475 for (int column = 0; column < m_matrix.columns(); ++column) {
476 if (m_matrix(row, column) > 0.0) {
477 column_start = column;
478 break;
479 }
480 }
481 for (int column = m_matrix.columns()-1; column >= 0; --column) {
482 if (m_matrix(row, column) > 0.0) {
483 column_stop = column;
484 break;
485 }
486 }
487
488 // Set energy boundaries if valid indices have been found
489 if (column_start != -1 && column_stop != -1) {
490 ebounds = GEbounds(m_ebds_measured.emin(column_start),
491 m_ebds_measured.emax(column_stop));
492 }
493
494 } // endif: row containing true energy was found
495
496 // Return energy boundaries
497 return ebounds;
498}
499
500
501/***********************************************************************//**
502 * @brief Load Redistribution Matrix File
503 *
504 * @param[in] filename File name.
505 *
506 * Loads the Redistribution Matrix File from the `MATRIX` extension of the
507 * FITS file and the reconstructed energy boundaries from the `EBOUNDS`
508 * extension.
509 ***************************************************************************/
510void GRmf::load(const GFilename& filename)
511{
512 // Clear matrix
513 clear();
514
515 // Open FITS file (without extension name as the user is not allowed
516 // to modify the extension names)
517 GFits fits(filename.url());
518
519 // Read data
520 read(fits);
521
522 // Close FITS file
523 fits.close();
524
525 // Store filename
527
528 // Return
529 return;
530}
531
532
533/***********************************************************************//**
534 * @brief Save Redistribution Matrix File
535 *
536 * @param[in] filename File name.
537 * @param[in] clobber Overwrite existing file?
538 * @param[in] unit Energy unit.
539 *
540 * Saves the Redistribution Matrix File into a FITS file. If a file with the
541 * given @p filename does not yet exist it will be created. If the file
542 * exists it can be overwritten if the @p clobber flag is set to `true`.
543 * Otherwise an exception is thrown.
544 *
545 * The method will save two binary FITS tables into the FITS file: a
546 * `MATRIX` extension that contains the Redistribution Matrix File elements,
547 * and an `EBOUNDS` extension that contains the measured energy boundaries
548 * for all matrix. The @p unit argument specifies the unit of the true
549 * energies that will be saved in the `MATRIX` extension.
550 ***************************************************************************/
551void GRmf::save(const GFilename& filename,
552 const bool& clobber,
553 const std::string& unit) const
554{
555 // Create FITS file
556 GFits fits;
557
558 // Write RMF into file
559 write(fits, unit);
560
561 // Save to file (without extension name since the requested extension
562 // may not yet exist in the file)
563 fits.saveto(filename.url(), clobber);
564
565 // Store filename
567
568 // Return
569 return;
570}
571
572
573/***********************************************************************//**
574 * @brief Read Redistribution Matrix File
575 *
576 * @param[in] fits File file.
577 *
578 * Reads the Redistribution Matrix File from the `MATRIX` extension of the
579 * FITS file and the reconstructed energy boundaries from the `EBOUNDS`
580 * extension.
581 ***************************************************************************/
582void GRmf::read(const GFits& fits)
583{
584 // Clear spectrum
585 clear();
586
587 // Get energy boundary table
588 const GFitsTable& ebounds = *fits.table(gammalib::extname_ebounds);
589
590 // Read measured energy boundaries
591 m_ebds_measured.read(ebounds);
592
593 // Get RMF table
594 const GFitsTable& rmf = *fits.table(gammalib::extname_rmf);
595
596 // Read RMF data
597 read(rmf);
598
599 // Return
600 return;
601}
602
603
604/***********************************************************************//**
605 * @brief Read Redistribution Matrix File
606 *
607 * @param[in] table RMF FITS table.
608 *
609 * Reads the Redistribution Matrix File from a FITS table. The true energy
610 * bins are expected in the `ENERG_LO` and `ENERG_HI` columns. Information
611 * for matrix compression are stored in the `N_GRP`, `F_CHAN` and `N_CHAN`
612 * columns, and the matrix elements are stored in the `MATRIX` column.
613 *
614 * The method automatically decompresses the Redistribution Matrix File and
615 * stores the matrix elements in a spare matrix.
616 *
617 * See
618 * http://heasarc.gsfc.nasa.gov/docs/heasarc/caldb/docs/memos/cal_gen_92_002/cal_gen_92_002.html#tth_sEc3
619 * for details about the Redistribution Matrix File file format.
620 ***************************************************************************/
621void GRmf::read(const GFitsTable& table)
622{
623 // Initialise members
625
626 // Get pointer to data columns
627 const GFitsTableCol* energy_lo = table["ENERG_LO"];
628 const GFitsTableCol* energy_hi = table["ENERG_HI"];
629 const GFitsTableCol* n_grp = table["N_GRP"];
630 const GFitsTableCol* f_chan = table["F_CHAN"];
631 const GFitsTableCol* n_chan = table["N_CHAN"];
632 const GFitsTableCol* matrix = table["MATRIX"];
633
634 // Set matrix rows and columns
635 int rows = energy_lo->nrows();
636 int columns = m_ebds_measured.size();
637
638 // Initialize matrix
639 m_matrix = GMatrixSparse(rows, columns);
640
641 // Initialize matrix maximum
642 double max = 0.0;
643
644 // Set true energy bins
645 for (int itrue = 0; itrue < rows; ++itrue) {
646
647 // Append energy bin
648 GEnergy emin(energy_lo->real(itrue), energy_lo->unit());
649 GEnergy emax(energy_hi->real(itrue), energy_hi->unit());
650 m_ebds_true.append(emin, emax);
651
652 // Loop over groups
653 int icolumn = 0;
654 int ngroups = n_grp->integer(itrue);
655 for (int igroup = 0; igroup < ngroups; ++igroup) {
656
657 // Get start column index and number of columns
658 int imeasured = f_chan->integer(itrue, igroup);
659 int nvalues = n_chan->integer(itrue, igroup);
660
661 // Get values
662 for (int i = 0; i < nvalues; ++i, ++imeasured, ++icolumn) {
663
664 // Set matrix value
665 m_matrix(itrue, imeasured) = matrix->real(itrue, icolumn);
666
667 // Update fmax
668 if (max < m_matrix(itrue, imeasured)) {
669 max = m_matrix(itrue, imeasured);
670 m_itruemax = itrue;
671 m_imeasmax = imeasured;
672 }
673
674 } // endfor: looped over measured energy bins
675
676 } // endfor: looped over groups
677
678 } // endfor: looped over true energy bins
679
680 // Store FITS header
681 m_header = table.header();
682
683 // Return
684 return;
685}
686
687
688/***********************************************************************//**
689 * @brief Write Redistribution Matrix File
690 *
691 * @param[in] fits FITS file.
692 * @param[in] unit Energy unit.
693 *
694 * Writes the Redistribution Matrix File into `MATRIX` and `EBOUNDS`
695 * extensions of the FITS file. Extensions with these names will be removed
696 * from the FITS file before writing.
697 *
698 * The true energy bins are written into the `ENERG_LO` and `ENERG_HI`
699 * columns. The units of the energies in these columns is specified by the
700 * @p unit argument. Information for matrix compression are stored in the
701 * `N_GRP`, `F_CHAN` and `N_CHAN` columns, and the matrix elements are
702 * written into the `MATRIX` column.
703 *
704 * The measured energy bins are written into the `EBOUNDS` extension.
705 *
706 * See
707 * http://heasarc.gsfc.nasa.gov/docs/heasarc/caldb/docs/memos/cal_gen_92_002/cal_gen_92_002.html#tth_sEc3
708 * for details about the Redistribution Matrix File file format.
709 ***************************************************************************/
710void GRmf::write(GFits& fits, const std::string& unit) const
711{
712 // Remove extensions if they exist already
715 }
718 }
719
720 // Set table length
721 int length = ntrue();
722
723 // Continue only if there are true energies
724 if (length > 0) {
725
726 // Compute maximum number of matrix elements
727 int maxcolumns = 1;
728 for (int i = 0; i < length; i++) {
729
730 // Search first non-zero element
731 int ifirst = 0;
732 for (; ifirst < nmeasured(); ++ifirst) {
733 if (m_matrix(i, ifirst) != 0.0) {
734 break;
735 }
736 }
737
738 // Search last non-zero element
739 int ilast = nmeasured() - 1;
740 for (; ilast >= 0; --ilast) {
741 if (m_matrix(i, ilast) != 0.0) {
742 break;
743 }
744 }
745
746 // Compute number of non-zero matrix elements
747 int num = ilast - ifirst + 1;
748
749 // Set maximum
750 if (num > maxcolumns) {
751 maxcolumns = num;
752 }
753
754 } // endfor: looped over true energies
755
756 // Create new binary table
757 GFitsBinTable hdu;
758
759 // Allocate columns
760 GFitsTableFloatCol energy_lo("ENERG_LO", length);
761 GFitsTableFloatCol energy_hi("ENERG_HI", length);
762 GFitsTableShortCol n_grp("N_GRP", length);
763 GFitsTableShortCol f_chan("F_CHAN", length);
764 GFitsTableShortCol n_chan("N_CHAN", length);
765 GFitsTableFloatCol matrix("MATRIX", length, maxcolumns);
766
767 // Fill columns
768 for (int itrue = 0; itrue < length; ++itrue) {
769
770 // Search first non-zero element
771 int ifirst = 0;
772 for (; ifirst < nmeasured(); ++ifirst) {
773 if (m_matrix(itrue, ifirst) != 0.0) {
774 break;
775 }
776 }
777
778 // Search last non-zero element
779 int ilast = nmeasured() - 1;
780 for (; ilast >= 0; --ilast) {
781 if (m_matrix(itrue, ilast) != 0.0) {
782 break;
783 }
784 }
785
786 // Compute number of non-zero matrix elements
787 int num = ilast - ifirst + 1;
788 if (num < 0) {
789 ifirst = 0;
790 num = 0;
791 }
792
793 // Set energy bin
794 energy_lo(itrue) = m_ebds_true.emin(itrue)(unit);
795 energy_hi(itrue) = m_ebds_true.emax(itrue)(unit);
796
797 // Set group information
798 n_grp(itrue) = 1;
799 f_chan(itrue) = ifirst;
800 n_chan(itrue) = num;
801
802 // Set matrix elements
803 for (int i = 0; i < num; ++i, ++ifirst) {
804 matrix(itrue, i) = m_matrix(itrue, ifirst);
805 }
806
807 } // endfor: looped over true energy bins
808
809 // Set column units
810 energy_lo.unit(unit);
811 energy_hi.unit(unit);
812
813 // Set table attributes
815
816 // Append columns to table
817 hdu.append(energy_lo);
818 hdu.append(energy_hi);
819 hdu.append(n_grp);
820 hdu.append(f_chan);
821 hdu.append(n_chan);
822 hdu.append(matrix);
823
824 // Write mandatory header keywords for RMF matrix
825 hdu.card("TELESCOP", "unknown", "Telescope");
826 hdu.card("INSTRUME", "unknown", "Instrument");
827 hdu.card("FILTER", "none", "Filter");
828 hdu.card("CHANTYPE", "PI", "Channel type");
829 hdu.card("DETCHANS", nmeasured(), "Total number of possible channels");
830 hdu.card("HDUCLASS", "OGIP", "Format conforms to OGIP standard");
831 hdu.card("HDUCLAS1", "RESPONSE", "Extension contains response data");
832 hdu.card("HDUCLAS2", "RSP_MATRIX", "Extension contains a RMF");
833 hdu.card("HDUVERS", "1.3.0", "Version of the file format");
834 hdu.card("TLMIN4", 0, "Minimum value allowed in column 4");
835
836 // Write additional header keywords (do not overwrite any existing
837 // keywords, except of "TELESCOP", "INSTRUME" and "FILTER")
838 for (int i = 0; i < m_header.size(); ++i) {
839 if ((!hdu.contains(m_header[i].keyname())) ||
840 (m_header[i].keyname() == "TELESCOP") ||
841 (m_header[i].keyname() == "INSTRUME") ||
842 (m_header[i].keyname() == "FILTER")) {
843 hdu.card(m_header[i]);
844 }
845 }
846
847 // Append HDU to FITS file
848 fits.append(hdu);
849
850 // Append measured energy boundaries
852
853 } // endif: there were data to write
854
855 // Return
856 return;
857}
858
859
860/***********************************************************************//**
861 * @brief Print Redistribution Matrix File
862 *
863 * @param[in] chatter Chattiness.
864 * @return String containing Redistribution Matrix File information.
865 ***************************************************************************/
866std::string GRmf::print(const GChatter& chatter) const
867{
868 // Initialise result string
869 std::string result;
870
871 // Continue only if chatter is not silent
872 if (chatter != SILENT) {
873
874 // Append header
875 result.append("=== GRmf ===");
876
877 // Append energy boundary information
878 result.append("\n"+gammalib::parformat("Number of true energy bins"));
879 result.append(gammalib::str(m_ebds_true.size()));
880 result.append("\n"+gammalib::parformat("Number of measured bins"));
881 result.append(gammalib::str(m_ebds_measured.size()));
882 result.append("\n"+gammalib::parformat("True energy range"));
883 result.append(m_ebds_true.emin().print());
884 result.append(" - ");
885 result.append(m_ebds_true.emax().print());
886 result.append("\n"+gammalib::parformat("Measured energy range"));
887 result.append(m_ebds_measured.emin().print());
888 result.append(" - ");
889 result.append(m_ebds_measured.emax().print());
890
891 } // endif: chatter was not silent
892
893 // Return result
894 return result;
895}
896
897
898/*==========================================================================
899 = =
900 = Private methods =
901 = =
902 ==========================================================================*/
903
904/***********************************************************************//**
905 * @brief Initialise class members
906 ***************************************************************************/
908{
909 // Initialise members
913 m_matrix.clear();
914 m_itruemax = 0;
915 m_imeasmax = 0;
916 m_header.clear();
917
918 // Return
919 return;
920}
921
922
923/***********************************************************************//**
924 * @brief Copy class members
925 *
926 * @param[in] rmf Redistribution Matrix File.
927 ***************************************************************************/
928void GRmf::copy_members(const GRmf& rmf)
929{
930 // Copy members
934 m_matrix = rmf.m_matrix;
937 m_header = rmf.m_header;
938
939 // Return
940 return;
941}
942
943
944/***********************************************************************//**
945 * @brief Delete class members
946 ***************************************************************************/
948{
949 // Return
950 return;
951}
#define G_AT
#define G_OPERATOR_PLUS
Definition GArf.cpp:42
#define G_OPERATOR_MINUS
Definition GArf.cpp:43
Exception handler interface definition.
FITS binary table class definition.
FITS table float column class interface definition.
FITS table short integer column class interface definition.
FITS table abstract base class interface definition.
FITS file class interface definition.
Mathematical function definitions.
XSPEC Redistribution Matrix File class definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
double max(const GVector &vector)
Computes maximum vector element.
Definition GVector.cpp:915
Energy boundaries container class.
Definition GEbounds.hpp:60
int index(const GEnergy &eng) const
Returns energy bin index for a given energy.
Definition GEbounds.cpp:948
const GEnergy & emax(void) const
Return maximum energy of all intervals.
Definition GEbounds.hpp:199
void read(const GFitsTable &table)
Read energy boundaries from FITS table.
Definition GEbounds.cpp:761
void append(const GEnergy &emin, const GEnergy &emax)
Append energy interval.
Definition GEbounds.cpp:301
int size(void) const
Return number of energy boundaries.
Definition GEbounds.hpp:163
void clear(void)
Clear energy boundaries.
Definition GEbounds.cpp:268
const GEnergy & emin(void) const
Return minimum energy of all intervals.
Definition GEbounds.hpp:187
void write(GFits &file, const std::string &extname=gammalib::extname_ebounds, const std::string &unit="keV") const
Write energy boundaries into FITS object.
Definition GEbounds.cpp:816
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
std::string print(const GChatter &chatter=NORMAL) const
Print energy.
Definition GEnergy.cpp:748
Filename class.
Definition GFilename.hpp:62
std::string url(void) const
Return Uniform Resource Locator (URL)
void clear(void)
Clear file name.
FITS binary table class.
const GFitsHeader & header(void) const
Return extension header.
Definition GFitsHDU.hpp:205
const std::string & extname(void) const
Return extension name.
Definition GFitsHDU.hpp:162
GFitsHeaderCard & card(const int &cardno)
Return header card.
Definition GFitsHDU.hpp:259
void clear(void)
Clear header.
int size(void) const
Return number of cards in header.
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
void unit(const std::string &unit)
Set column unit.
void nrows(const int &nrows)
Set number of rows in column.
FITS table float column.
FITS table short integer column.
Abstract interface for FITS table.
bool contains(const std::string &colname) const
Checks the presence of a column in table.
GFitsTableCol * append(const GFitsTableCol &column)
Append column to the table.
FITS file class.
Definition GFits.hpp:63
void saveto(const GFilename &filename, const bool &clobber=false)
Saves to specified FITS file.
Definition GFits.cpp:1293
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
GFitsTable * table(const int &extno)
Get pointer to table HDU.
Definition GFits.cpp:482
const int & rows(void) const
Return number of matrix rows.
const int & columns(void) const
Return number of matrix columns.
Sparse matrix class interface definition.
virtual void clear(void)
Clear matrix.
Redistribution Matrix File class.
Definition GRmf.hpp:55
void copy_members(const GRmf &rmf)
Copy class members.
Definition GRmf.cpp:928
const GMatrixSparse & matrix(void) const
Return redistribution matrix.
Definition GRmf.hpp:277
const GEbounds & etrue(void) const
Return true energy boundaries.
Definition GRmf.hpp:251
double & at(const int &itrue, const int &imeasured)
Return content of redistribution matrix bin.
Definition GRmf.cpp:350
GFilename m_filename
Filename of origin.
Definition GRmf.hpp:117
GEbounds m_ebds_true
True energy boundaries.
Definition GRmf.hpp:118
const GEbounds & emeasured(void) const
Return measured energy boundaries.
Definition GRmf.hpp:265
int m_itruemax
Index of true maximum.
Definition GRmf.hpp:122
std::string print(const GChatter &chatter=NORMAL) const
Print Redistribution Matrix File.
Definition GRmf.cpp:866
virtual ~GRmf(void)
Destructor.
Definition GRmf.cpp:134
const GFilename & filename(void) const
Return file name.
Definition GRmf.hpp:294
GRmf(void)
Void constructor.
Definition GRmf.cpp:62
void init_members(void)
Initialise class members.
Definition GRmf.cpp:907
void save(const GFilename &filename, const bool &clobber=false, const std::string &unit="keV") const
Save Redistribution Matrix File.
Definition GRmf.cpp:551
int nmeasured(void) const
Return number of measured energy bins in redistribution matrix.
Definition GRmf.hpp:207
void clear(void)
Clear object.
Definition GRmf.cpp:315
int ntrue(void) const
Return number of true energy bins in redistribution matrix.
Definition GRmf.hpp:193
GRmf & operator=(const GRmf &rmf)
Assignment operator.
Definition GRmf.cpp:156
GRmf * clone(void) const
Clone object.
Definition GRmf.cpp:331
GRmf & operator-=(const GRmf &rmf)
Subtract Redistribution Matrix File.
Definition GRmf.cpp:233
int m_imeasmax
Index of measured maximum.
Definition GRmf.hpp:121
GEbounds m_ebds_measured
Measured energy boundaries.
Definition GRmf.hpp:119
void write(GFits &fits, const std::string &unit="keV") const
Write Redistribution Matrix File.
Definition GRmf.cpp:710
void read(const GFits &fits)
Read Redistribution Matrix File.
Definition GRmf.cpp:582
void free_members(void)
Delete class members.
Definition GRmf.cpp:947
GFitsHeader m_header
FITS header cards.
Definition GRmf.hpp:123
GRmf & operator/=(const double &scale)
Divide Redistribution Matrix File values.
Definition GRmf.cpp:290
GRmf & operator*=(const double &scale)
Scale Redistribution Matrix File values.
Definition GRmf.cpp:268
GRmf & operator+=(const GRmf &rmf)
Add Redistribution Matrix File.
Definition GRmf.cpp:192
GMatrixSparse m_matrix
Sparse redistribution matrix.
Definition GRmf.hpp:120
void load(const GFilename &filename)
Load Redistribution Matrix File.
Definition GRmf.cpp:510
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1143
const std::string extname_rmf
Definition GRmf.hpp:44
const std::string extname_ebounds
Definition GEbounds.hpp:44
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489