GammaLib 2.0.0
Loading...
Searching...
No Matches
GCOMObservation.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GCOMObservation.cpp - COMPTEL Observation class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2012-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 GCOMObservation.cpp
23 * @brief COMPTEL observation class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <typeinfo>
33#include "GTools.hpp"
34#include "GMath.hpp"
35#include "GException.hpp"
36#include "GFits.hpp"
37#include "GFitsHDU.hpp"
38#include "GCaldb.hpp"
39#include "GSource.hpp"
40#include "GModels.hpp"
41#include "GModelSky.hpp"
43#include "GXmlElement.hpp"
44#include "GCOMObservation.hpp"
45#include "GCOMEventBin.hpp"
46#include "GCOMStatus.hpp"
47#include "GCOMSupport.hpp"
48
49/* __ Globals ____________________________________________________________ */
51const GObservationRegistry g_obs_com_registry(&g_obs_com_seed);
52
53/* __ Method name definitions ____________________________________________ */
54#define G_RESPONSE "GCOMObservation::response(GResponse&)"
55#define G_READ "GCOMObservation::read(GXmlElement&)"
56#define G_WRITE "GCOMObservation::write(GXmlElement&)"
57#define G_LOAD_DRB "GCOMObservation::load_drb(GFilename&)"
58#define G_LOAD_DRG "GCOMObservation::load_drg(GFilename&)"
59#define G_DRM "GCOMObservation::drm(GModels&)"
60#define G_COMPUTE_DRB "GCOMObservation::compute_drb(std::string&, GCOMDri&, "\
61 "int&, int&, int&, int&"
62#define G_COMPUTE_DRB_PHINOR "GCOMObservation::compute_drb_phinor(GCOMDri&)"
63#define G_COMPUTE_DRB_BGDLIXA "GCOMObservation::compute_drb_bgdlixa("\
64 "GCOMDri&, int&, int&, int&, int&)"
65#define G_COMPUTE_DRB_BGDLIXE "GCOMObservation::compute_drb_bgdlixe("\
66 "GCOMDri&, int&, int&, int&, int&)"
67
68/* __ Macros _____________________________________________________________ */
69
70/* __ Coding definitions _________________________________________________ */
71
72/* __ Debug definitions __________________________________________________ */
73
74
75/*==========================================================================
76 = =
77 = Constructors/destructors =
78 = =
79 ==========================================================================*/
80
81/***********************************************************************//**
82 * @brief Void constructor
83 *
84 * Creates an empty COMPTEL observation.
85 ***************************************************************************/
87{
88 // Initialise members
90
91 // Return
92 return;
93}
94
95
96/***********************************************************************//**
97 * @brief XML constructor
98 *
99 * @param[in] xml XML element.
100 *
101 * Constructs a COMPTEL observation from the information that is found in an
102 * XML element.
103 ***************************************************************************/
105{
106 // Initialise members
107 init_members();
108
109 // Read XML
110 read(xml);
111
112 // Return
113 return;
114}
115
116
117/***********************************************************************//**
118 * @brief Binned observation DRI constructor
119 *
120 * @param[in] dre Event cube.
121 * @param[in] drb Background cube.
122 * @param[in] drg Geometry cube.
123 * @param[in] drx Exposure map.
124 *
125 * Creates COMPTEL observation from DRI instances.
126 *
127 * The method fixes the deadtime correction factor deadc to 0.965.
128 ***************************************************************************/
130 const GCOMDri& drb,
131 const GCOMDri& drg,
132 const GCOMDri& drx) : GObservation()
133{
134 // Initialise members
135 init_members();
136
137 // Store DRIs
138 m_events = new GCOMEventCube(dre);
139 m_drb = drb;
140 m_drg = drg;
141 m_drx = drx;
142
143 // Set attributes
144 m_obs_id = 0;
145 m_ontime = m_events->gti().ontime();
146 m_deadc = 0.965;
148 m_ewidth = m_events->emax().MeV() - m_events->emin().MeV();
149 m_name = "unknown";
150 m_drename = "";
151 m_drbname = "";
152 m_drgname = "";
153 m_drxname = "";
154
155 // Return
156 return;
157}
158
159
160/***********************************************************************//**
161 * @brief Binned observation filename constructor
162 *
163 * @param[in] drename Event cube name.
164 * @param[in] drbname Background cube name.
165 * @param[in] drgname Geometry cube name.
166 * @param[in] drxname Exposure map name.
167 *
168 * Creates COMPTEL observation by loading the following FITS files:
169 *
170 * DRE - Events cube
171 * DRB - Background model cube
172 * DRG - Geometry factors cube
173 * DRX - Exposure map
174 *
175 * Each of the four files is mandatory.
176 ***************************************************************************/
178 const GFilename& drbname,
179 const GFilename& drgname,
180 const GFilename& drxname) : GObservation()
181{
182 // Initialise members
183 init_members();
184
185 // Load observation
187
188 // Return
189 return;
190}
191
192
193/***********************************************************************//**
194 * @brief Unbinned observation constructor
195 *
196 * @param[in] evpname Event list FITS file name.
197 * @param[in] timname Good Time Intervals FITS file name.
198 * @param[in] oadnames List of Orbit Aspect Data FITS file names.
199 * @param[in] bvcname Solar System Barycentre Data FITS file name.
200 *
201 * Creates a COMPTEL unbinned observation by loading the event list, Good
202 * Time Interval, Orbit Aspect Data and optionally the Solar System
203 * Barycentre Data from FITS files. Except of the Solar System Barycentre
204 * Data all files are mandatory. The Solar System Barycentre Data will only
205 * be loaded if the file name is not empty.
206 ***************************************************************************/
208 const GFilename& timname,
209 const std::vector<GFilename>& oadnames,
210 const GFilename& bvcname)
211{
212 // Initialise members
213 init_members();
214
215 // Load observation
216 load(evpname, timname, oadnames, bvcname);
217
218 // Return
219 return;
220}
221
222
223/***********************************************************************//**
224 * @brief Copy constructor
225 *
226 * @param[in] obs COMPTEL observation.
227 *
228 * Creates COMPTEL observation by copying an existing COMPTEL observation.
229 ***************************************************************************/
231{
232 // Initialise members
233 init_members();
234
235 // Copy members
236 copy_members(obs);
237
238 // Return
239 return;
240}
241
242
243/***********************************************************************//**
244 * @brief Destructor
245 ***************************************************************************/
247{
248 // Free members
249 free_members();
250
251 // Return
252 return;
253}
254
255
256/*==========================================================================
257 = =
258 = Operators =
259 = =
260 ==========================================================================*/
261
262/***********************************************************************//**
263 * @brief Assignment operator
264 *
265 * @param[in] obs COMPTEL observation.
266 * @return COMPTEL observation.
267 *
268 * Assign COMPTEL observation to this object.
269 ***************************************************************************/
271{
272 // Execute only if object is not identical
273 if (this != &obs) {
274
275 // Copy base class members
276 this->GObservation::operator=(obs);
277
278 // Free members
279 free_members();
280
281 // Initialise members
282 init_members();
283
284 // Copy members
285 copy_members(obs);
286
287 } // endif: object was not identical
288
289 // Return this object
290 return *this;
291}
292
293
294/*==========================================================================
295 = =
296 = Public methods =
297 = =
298 ==========================================================================*/
299
300/***********************************************************************//**
301 * @brief Clear COMPTEL observation
302 ***************************************************************************/
304{
305 // Free members
306 free_members();
308
309 // Initialise members
311 init_members();
312
313 // Return
314 return;
315}
316
317
318/***********************************************************************//**
319 * @brief Clone COMPTEL observation
320 *
321 * @return Pointer to deep copy of COMPTEL observation.
322 ***************************************************************************/
324{
325 return new GCOMObservation(*this);
326}
327
328
329/***********************************************************************//**
330 * @brief Set response function
331 *
332 * @param[in] rsp Response function.
333 *
334 * @exception GException::invalid_argument
335 * Specified response is not a COMPTEL response.
336 *
337 * Sets the response function for the observation.
338 ***************************************************************************/
340{
341 // Get pointer on COM response
342 const GCOMResponse* comrsp = dynamic_cast<const GCOMResponse*>(&rsp);
343 if (comrsp == NULL) {
344 std::string cls = std::string(typeid(&rsp).name());
345 std::string msg = "Response of type \""+cls+"\" is "
346 "not a COMPTEL response. Please specify a COMPTEL "
347 "response as argument.";
349 }
350
351 // Clone response function
352 m_response = *comrsp;
353
354 // Return
355 return;
356}
357
358
359/***********************************************************************//**
360 * @brief Set response function
361 *
362 * @param[in] caldb Calibration database.
363 * @param[in] rspname Name of COMPTEL response.
364 *
365 * Sets the response function by loading the response information from the
366 * calibration database.
367 ***************************************************************************/
368void GCOMObservation::response(const GCaldb& caldb, const std::string& rspname)
369{
370 // Clear COM response function
372
373 // Set calibration database
374 m_response.caldb(caldb);
375
376 // Load instrument response function
377 m_response.load(rspname);
378
379 // Return
380 return;
381}
382
383
384/***********************************************************************//**
385 * @brief Read observation from XML element
386 *
387 * @param[in] xml XML element.
388 *
389 * Reads information for a COMPTEL observation from an XML element. The
390 * method supports both an unbinned and a binned observation.
391 *
392 * For an unbinned observation the XML format is
393 *
394 * <observation name="Crab" id="000001" instrument="COM">
395 * <parameter name="EVP" file="m16992_evp.fits"/>
396 * <parameter name="TIM" file="m10695_tim.fits"/>
397 * <parameter name="OAD" file="m20039_oad.fits"/>
398 * <parameter name="OAD" file="m20041_oad.fits"/>
399 * <parameter name="BVC" file="s10150_bvc.fits"/>
400 * ...
401 * </observation>
402 *
403 * where the observation can contain an arbitrary number of OAD file
404 * parameters. The @p file attribute provide either absolute or relative
405 * file names. If a file name includes no access path it is assumed that
406 * the file resides in the same location as the XML file. The BVC file is
407 * optional and does not need to be specified.
408 *
409 * For a binned observation the XML format is
410 *
411 * <observation name="Crab" id="000001" instrument="COM">
412 * <parameter name="DRE" file="m50438_dre.fits"/>
413 * <parameter name="DRB" file="m34997_drg.fits"/>
414 * <parameter name="DRG" file="m34997_drg.fits"/>
415 * <parameter name="DRX" file="m32171_drx.fits"/>
416 * <parameter name="IAQ" value="UNH(1.0-3.0)MeV"/>
417 * </observation>
418 ***************************************************************************/
420{
421 // Clear observation
422 clear();
423
424 // Extract instrument name
425 m_instrument = xml.attribute("instrument");
426
427 // If the XML elements has a "EVP" attribute we have an unbinned
428 // observation
429 if (gammalib::xml_has_par(xml, "EVP")) {
430
431 // Get EVP and TIM file names
432 std::string evpname = gammalib::xml_get_attr(G_READ, xml, "EVP", "file");
433 std::string timname = gammalib::xml_get_attr(G_READ, xml, "TIM", "file");
434
435 // Expand EVP and TIM file names
436 evpname = gammalib::xml_file_expand(xml, evpname);
437 timname = gammalib::xml_file_expand(xml, timname);
438
439 // Get OAD file names
440 std::vector<GFilename> oadnames;
441 for (int i = 0; i < xml.elements("parameter"); ++i) {
442 const GXmlElement* element = xml.element("parameter", i);
443 if (element->attribute("name") == "OAD") {
444 std::string oadname = element->attribute("file");
445 oadname = gammalib::xml_file_expand(xml, oadname);
446 oadnames.push_back(GFilename(oadname));
447 }
448 }
449
450 // Get and expand optional BVC file name
451 std::string bvcname = "";
452 if (gammalib::xml_has_par(xml, "BVC")) {
453 bvcname = gammalib::xml_get_attr(G_READ, xml, "BVC", "file");
454 bvcname = gammalib::xml_file_expand(xml, bvcname);
455 }
456
457 // Load observation
458 load(evpname, timname, oadnames, bvcname);
459
460 } // endif: unbinned observation
461
462 // ... otherwise we have a binned observation
463 else {
464
465 // Get parameters
466 std::string drename = gammalib::xml_get_attr(G_READ, xml, "DRE", "file");
467 std::string drbname = gammalib::xml_get_attr(G_READ, xml, "DRB", "file");
468 std::string drgname = gammalib::xml_get_attr(G_READ, xml, "DRG", "file");
469 std::string drxname = gammalib::xml_get_attr(G_READ, xml, "DRX", "file");
470 std::string iaqname = gammalib::xml_get_attr(G_READ, xml, "IAQ", "value");
471
472 // Expand file names
477 std::string iaqname_expanded = gammalib::xml_file_expand(xml, iaqname);
478
479 // Load observation
481
482 // Load IAQ by trying first the expanded name as a FITS file and
483 // otherwise the unexpanded name
484 GFilename filename_expanded(iaqname_expanded);
485 if (filename_expanded.is_fits()) {
486 response(GCaldb("cgro", "comptel"), iaqname_expanded);
487 }
488 else {
489 response(GCaldb("cgro", "comptel"), iaqname);
490 }
491
492 // Get optional Phibar layer attributes
493 if (xml.has_attribute("phi_first")) {
494 m_phi_first = gammalib::toint(xml.attribute("phi_first"));
495 }
496 if (xml.has_attribute("phi_last")) {
497 m_phi_last = gammalib::toint(xml.attribute("phi_last"));
498 }
499
500 } // endelse: binned observation
501
502 // Return
503 return;
504}
505
506
507/***********************************************************************//**
508 * @brief Write observation into XML element
509 *
510 * @param[in] xml XML element.
511 *
512 * Writes information for a COMPTEL observation into an XML element. The
513 * method supports both an unbinned and a binned observation.
514 *
515 * For an unbinned observation the XML format is
516 *
517 * <observation name="Crab" id="000001" instrument="COM">
518 * <parameter name="EVP" file="m16992_evp.fits"/>
519 * <parameter name="TIM" file="m10695_tim.fits"/>
520 * <parameter name="OAD" file="m20039_oad.fits"/>
521 * <parameter name="OAD" file="m20041_oad.fits"/>
522 * <parameter name="BVC" file="s10150_bvc.fits"/>
523 * ...
524 * </observation>
525 *
526 * where the observation can contain an arbitrary number of OAD file
527 * parameters. The @p file attribute provide either absolute or relative
528 * file names. If a file name includes no access path it is assumed that
529 * the file resides in the same location as the XML file. The BVC file is
530 * optional and is only written if BVC information is contained in the
531 * observation.
532 *
533 * For a binned observation the XML format is
534 *
535 * <observation name="Crab" id="000001" instrument="COM">
536 * <parameter name="DRE" file="m50438_dre.fits"/>
537 * <parameter name="DRB" file="m34997_drg.fits"/>
538 * <parameter name="DRG" file="m34997_drg.fits"/>
539 * <parameter name="DRX" file="m32171_drx.fits"/>
540 * <parameter name="IAQ" value="UNH(1.0-3.0)MeV"/>
541 * </observation>
542 ***************************************************************************/
544{
545 // Allocate XML element pointer
546 GXmlElement* par;
547
548 // Handle unbinned observation
549 if (is_unbinned()) {
550
551 // Set EVP parameter
552 par = gammalib::xml_need_par(G_WRITE, xml, "EVP");
554
555 // Set TIM parameter
556 par = gammalib::xml_need_par(G_WRITE, xml, "TIM");
558
559 // Remove all existing OAD parameters
560 for (int i = 0; i < xml.elements("parameter"); ++i) {
561 GXmlElement* element = xml.element("parameter", i);
562 if (element->attribute("name") == "OAD") {
563 xml.remove(i);
564 }
565 }
566
567 // Set OAD parameters
568 for (int i = 0; i < m_oadnames.size(); ++i) {
569 par = static_cast<GXmlElement*>(xml.append(GXmlElement("parameter name=\"OAD\"")));
570 par->attribute("file", gammalib::xml_file_reduce(xml, m_oadnames[i]));
571 }
572
573 // Optionally set BVC parameters
574 if (!m_bvcs.is_empty()) {
575 par = gammalib::xml_need_par(G_WRITE, xml, "BVC");
577 }
578
579 } // endif: observation was unbinned
580
581 // ... otherwise handle a binned observation
582 else if (is_binned()) {
583
584 // Set DRE parameter
585 par = gammalib::xml_need_par(G_WRITE, xml, "DRE");
587
588 // Set DRB parameter
589 par = gammalib::xml_need_par(G_WRITE, xml, "DRB");
591
592 // Set DRG parameter
593 par = gammalib::xml_need_par(G_WRITE, xml, "DRG");
595
596 // Set DRX parameter
597 par = gammalib::xml_need_par(G_WRITE, xml, "DRX");
599
600 // Set IAQ parameter
601 par = gammalib::xml_need_par(G_WRITE, xml, "IAQ");
603
604 // If there is a first Phibar layer selection then write it into XML file
605 if (m_phi_first != -1) {
606 xml.attribute("phi_first", gammalib::str(m_phi_first));
607 }
608
609 // If there is a last Phibar layer selection then write it into XML file
610 if (m_phi_last != -1) {
611 xml.attribute("phi_last", gammalib::str(m_phi_last));
612 }
613
614 } // endif: observation was binned
615
616 // Return
617 return;
618}
619
620
621/***********************************************************************//**
622 * @brief Load data for a binned observation
623 *
624 * @param[in] drename Event cube name.
625 * @param[in] drbname Background cube name.
626 * @param[in] drgname Geometry cube name.
627 * @param[in] drxname Exposure map name.
628 *
629 * Load event cube from DRE file, background model from DRB file, geometry
630 * factors from DRG file and the exposure map from the DRX file. All files
631 * are mandatory.
632 ***************************************************************************/
634 const GFilename& drbname,
635 const GFilename& drgname,
636 const GFilename& drxname)
637{
638 // Load DRE
640
641 // Load DRB
643
644 // Load DRG
646
647 // Load DRX
649
650 // Return
651 return;
652}
653
654
655/***********************************************************************//**
656 * @brief Load data for an unbinned observation
657 *
658 * @param[in] evpname Event list FITS file name.
659 * @param[in] timname Good Time Intervals FITS file name.
660 * @param[in] oadnames List of Orbit Aspect Data FITS file names.
661 * @param[in] bvcname Solar System Barycentre Data FITS file name.
662 *
663 * Loads the event list, Good Time Interval, Orbit Aspect Data and optionally
664 * the Solar System Barycentre Data for an unbinned observation. Except of
665 * the Solar System Barycentre Data all files are mandatory. The Solar
666 * System Barycentre Data will only be loaded if the file name is not empty.
667 *
668 * The method fixes the deadtime correction factor deadc to 0.965.
669 ***************************************************************************/
671 const GFilename& timname,
672 const std::vector<GFilename>& oadnames,
673 const GFilename& bvcname)
674{
675 // Clear object
676 clear();
677
678 // Extract observation information from event list
679 GFits fits(evpname);
680 read_attributes(fits[1]);
681 fits.close();
682
683 // Allocate event list
684 GCOMEventList *evp = new GCOMEventList(evpname);
685 m_events = evp;
686
687 // Load TIM data
688 m_tim.load(timname);
689
690 // Extract ontime from TIM and compute livetime assuming the value of
691 // 0.965 from Rob van Dijk's thesis, page 62
692 m_ontime = m_tim.gti().ontime();
693 m_deadc = 0.965;
695
696 // Initialise intermediate vector for OADs
697 std::vector<GCOMOads> oads;
698
699 // Load OAD data
700 for (int i = 0; i < oadnames.size(); ++i) {
701
702 // Load OAD file
703 GCOMOads oad(oadnames[i]);
704
705 // Skip file if it is empty
706 if (oad.size() < 1) {
707 continue;
708 }
709
710 // Find index of where to insert OAD file
711 int index = 0;
712 for (; index < oads.size(); ++index) {
713 if (oad[0].tstop() < oads[index][oads[index].size()-1].tstart()) {
714 break;
715 }
716 }
717
718 // Inserts Orbit Aspect Data
719 if (index < oads.size()) {
720 oads.insert(oads.begin()+index, oad);
721 }
722 else {
723 oads.push_back(oad);
724 }
725
726 }
727
728 // Now put all OAD into a single container
729 for (int i = 0; i < oads.size(); ++i) {
730 m_oads.extend(oads[i]);
731 }
732
733 // Optionally load BVC data
734 if (bvcname != "") {
735 m_bvcs.load(bvcname);
736 }
737
738 // Store filenames
739 m_evpname = evpname;
740 m_timname = timname;
741 m_oadnames = oadnames;
742 m_bvcname = bvcname;
743
744 // Return
745 return;
746}
747
748
749/***********************************************************************//**
750 * @brief Compute DRM cube
751 *
752 * @param[in] models Model container.
753 * @return DRM cube (units of counts)
754 *
755 * @exception GException::invalid_value
756 * Observation does not contain an event cube.
757 *
758 * Computes a COMPTEL DRM cube from the information provided in a model
759 * container. The values of the DRM cube are in units of counts.
760 ***************************************************************************/
762{
763 // Get pointer on COMPTEL event cube
764 const GCOMEventCube* cube = dynamic_cast<const GCOMEventCube*>(m_events);
765 if (cube == NULL) {
766 std::string cls = std::string(typeid(m_events).name());
767 std::string msg = "Events of type \""+cls+"\" is not a COMPTEL event "
768 "cube. Please specify a COMPTEL event cube when "
769 "using this method.";
771 }
772
773 // Create DRM cube as copy of DRE cube
774 GCOMEventCube drm_cube = *cube;
775
776 // Get vector of model values
777 GVector values = models.eval(*this);
778
779 // Loop over all cube bins
780 for (int i = 0; i < drm_cube.size(); ++i) {
781
782 // Get pointer to cube bin
783 GCOMEventBin* bin = drm_cube[i];
784
785 // Compute model value for cube bin
786 double model = values[i] * bin->size();
787
788 // Store model value in cube bin
789 bin->counts(model);
790
791 } // endfor: looped over DRM cube bins
792
793 // Get a copy of the DRM
794 GCOMDri drm = drm_cube.dre();
795
796 // Return DRM
797 return drm;
798}
799
800
801/***********************************************************************//**
802 * @brief Compute DRB cube
803 *
804 * @param[in] method Background method (PHINOR, BGDLIXA or BGDLIXE).
805 * @param[in] drm DRM cube.
806 * @param[in] nrunav BGDLIXA: number of bins used for running average.
807 * @param[in] navgr BGDLIXA: number of bins used for averaging.
808 * @param[in] nincl BGDLIXA: number of Phibar layers to include.
809 * @param[in] nexcl BGDLIXA: number of Phibar layers to exclude.
810 *
811 * Computes a COMPTEL DRB cube using either the PHINOR or BGDLIXA method.
812 * See the protected methods compute_drb_phinor() and compute_drb_bgdlixa()
813 * for more information.
814 ***************************************************************************/
815void GCOMObservation::compute_drb(const std::string& method,
816 const GCOMDri& drm,
817 const int& nrunav,
818 const int& navgr,
819 const int& nincl,
820 const int& nexcl)
821{
822 // Branch to relevant method based on specified background method
823 if (method == "PHINOR") {
825 }
826 else if (method == "BGDLIXA") {
827 compute_drb_bgdlixa(drm, nrunav, navgr, nincl, nexcl);
828 }
829 else if (method == "BGDLIXE") {
830 compute_drb_bgdlixe(drm, nrunav, navgr, nincl, nexcl);
831 }
832 else {
833 std::string msg = "Unknown background method \""+method+"\". "
834 "Specify either \"PHINOR\", \"BGDLIXA\" or "
835 "\"BGDLIXE\".";
837 }
838
839 // Return
840 return;
841}
842
843
844/***********************************************************************//**
845 * @brief Print observation information
846 *
847 * @param[in] chatter Chattiness.
848 * @return String containing observation information.
849 ***************************************************************************/
850std::string GCOMObservation::print(const GChatter& chatter) const
851{
852 // Initialise result string
853 std::string result;
854
855 // Continue only if chatter is not silent
856 if (chatter != SILENT) {
857
858 // Append header
859 result.append("=== GCOMObservation ===");
860
861 // Append information
862 result.append("\n"+gammalib::parformat("Name")+name());
863 result.append("\n"+gammalib::parformat("Identifier")+id());
864 result.append("\n"+gammalib::parformat("Instrument")+instrument());
865 result.append("\n"+gammalib::parformat("Statistic")+statistic());
866 result.append("\n"+gammalib::parformat("Ontime"));
867 result.append(gammalib::str(ontime())+" sec");
868 result.append("\n"+gammalib::parformat("Livetime"));
869 result.append(gammalib::str(livetime())+" sec");
870 result.append("\n"+gammalib::parformat("Deadtime correction"));
871 result.append(gammalib::str(m_deadc));
872
873 // Append Phibar selection
874 int phi_first = (m_phi_first != -1) ? m_phi_first : 0;
875 int phi_last = (m_phi_last != -1) ? m_phi_last : m_drg.map().nmaps();
876 if ((m_phi_first != -1) || (m_phi_last != -1)) {
877 result.append("\n"+gammalib::parformat("Likelihood Phibar range"));
878 result.append(gammalib::str(phi_first));
879 result.append(" - ");
880 result.append(gammalib::str(phi_last));
881 }
882
883 // Append response (if available)
884 if (response()->rspname().length() > 0) {
885 result.append("\n"+response()->print(gammalib::reduce(chatter)));
886 }
887
888 // Append events
889 if (m_events != NULL) {
890 result.append("\n"+m_events->print(gammalib::reduce(chatter)));
891 }
892 else {
893 result.append("\n"+gammalib::parformat("Events")+"undefined");
894 }
895
896 // Append TIM (if available)
897 if (m_tim.gti().size() > 0) {
898 result.append("\n"+m_tim.print(gammalib::reduce(chatter)));
899 }
900 else {
901 result.append("\n"+gammalib::parformat("TIM")+"undefined");
902 }
903
904 // Append OADs (if available)
905 if (!m_oads.is_empty()) {
906 result.append("\n"+m_oads.print(gammalib::reduce(chatter)));
907 }
908 else {
909 result.append("\n"+gammalib::parformat("OADs")+"undefined");
910 }
911
912 // Append BVCs (if available)
913 if (!m_bvcs.is_empty()) {
914 result.append("\n"+m_bvcs.print(gammalib::reduce(chatter)));
915 }
916 else {
917 result.append("\n"+gammalib::parformat("BVCs")+"undefined");
918 }
919
920 // Append DRB, DRG and DRX
921 //result.append("\n"+m_drb.print(chatter));
922 //result.append("\n"+m_drg.print(chatter));
923 //result.append("\n"+m_drx.print(chatter));
924
925 } // endif: chatter was not silent
926
927 // Return result
928 return result;
929}
930
931
932/*==========================================================================
933 = =
934 = Private methods =
935 = =
936 ==========================================================================*/
937
938/***********************************************************************//**
939 * @brief Initialise class members
940 ***************************************************************************/
942{
943 // Initialise members
944 m_instrument = "COM";
946 m_obs_id = 0;
947 m_ontime = 0.0;
948 m_livetime = 0.0;
949 m_deadc = 0.0;
950
951 // Initialise members for binned observation
956 m_drb.clear();
957 m_drg.clear();
958 m_drx.clear();
959 m_ewidth = 0.0;
960 m_phi_first = -1;
961 m_phi_last = -1;
962
963 // Initialise members for unbinned observation
966 m_oadnames.clear();
968 m_tim.clear();
969 m_oads.clear();
970 m_bvcs.clear();
971
972 // Return
973 return;
974}
975
976
977/***********************************************************************//**
978 * @brief Copy class members
979 *
980 * @param[in] obs COMPTEL observation.
981 ***************************************************************************/
983{
984 // Copy members
987 m_obs_id = obs.m_obs_id;
988 m_ontime = obs.m_ontime;
990 m_deadc = obs.m_deadc;
991
992 // Copy members for binned observation
993 m_drename = obs.m_drename;
994 m_drbname = obs.m_drbname;
995 m_drgname = obs.m_drgname;
996 m_drxname = obs.m_drxname;
997 m_drb = obs.m_drb;
998 m_drg = obs.m_drg;
999 m_drx = obs.m_drx;
1000 m_ewidth = obs.m_ewidth;
1002 m_phi_last = obs.m_phi_last;
1003
1004 // Copy members for unbinned observation
1005 m_evpname = obs.m_evpname;
1006 m_timname = obs.m_timname;
1007 m_oadnames = obs.m_oadnames;
1008 m_bvcname = obs.m_bvcname;
1009 m_tim = obs.m_tim;
1010 m_oads = obs.m_oads;
1011 m_bvcs = obs.m_bvcs;
1012
1013 // Return
1014 return;
1015}
1016
1017
1018/***********************************************************************//**
1019 * @brief Delete class members
1020 ***************************************************************************/
1022{
1023 // Return
1024 return;
1025}
1026
1027
1028/***********************************************************************//**
1029 * @brief Load event cube data from DRE file
1030 *
1031 * @param[in] drename DRE filename.
1032 *
1033 * Loads the event cube from a DRE file.
1034 *
1035 * The ontime is extracted from the Good Time Intervals. The deadtime
1036 * correction factor deadc is fixed to 0.965. The livetime is computed by
1037 * multiplying the deadtime correction by the ontime, i.e.
1038 * LIVETIME = ONTIME * DEADC.
1039 ***************************************************************************/
1041{
1042 // Delete any existing event container (do not call clear() as we do not
1043 // want to delete the response function)
1044 if (m_events != NULL) delete m_events;
1045 m_events = NULL;
1046
1047 // Allocate event cube
1048 m_events = new GCOMEventCube;
1049
1050 // Open FITS file
1051 GFits fits(drename);
1052
1053 // Read event cube
1054 m_events->read(fits);
1055
1056 // Extract ontime
1057 m_ontime = m_events->gti().ontime();
1058
1059 // Set fixed deadtime fraction (see Rob van Dijk's thesis, page 62)
1060 m_deadc = 0.965;
1061
1062 // Compute livetime
1064
1065 // Compute energy width
1066 m_ewidth = m_events->emax().MeV() - m_events->emin().MeV();
1067
1068 // Read additional observation attributes from primary extension
1069 read_attributes(fits[0]);
1070
1071 // Close FITS file
1072 fits.close();
1073
1074 // Store event filename
1076
1077 // Return
1078 return;
1079}
1080
1081
1082/***********************************************************************//**
1083 * @brief Load background model from DRB file
1084 *
1085 * @param[in] drbname DRB filename.
1086 *
1087 * @exception GException::invalid_value
1088 * DRB data space incompatible with DRE data space.
1089 *
1090 * Load the background model from the primary image of the specified FITS
1091 * file. Since a DRB file is optional the method does nothing if the DRB
1092 * filename is empty.
1093 ***************************************************************************/
1095{
1096 // Continue only if filename is not empty
1097 if (!drbname.is_empty()) {
1098
1099 // Open FITS file
1100 GFits fits(drbname);
1101
1102 // Get image
1103 const GFitsImage& image = *fits.image("Primary");
1104
1105 // Read background model
1106 m_drb.read(image);
1107
1108 // Correct WCS projection (HEASARC data format kludge)
1109 gammalib::com_wcs_mer2car(const_cast<GSkyMap&>(m_drb.map()));
1110
1111 // Close FITS file
1112 fits.close();
1113
1114 // Check map dimensions
1115 if (!check_dri(m_drb)) {
1116 std::string msg = "DRB data cube \""+drbname+"\" incompatible with "
1117 "DRE data cube \""+m_drename+"\".";
1119 }
1120
1121 // Store DRB filename
1123
1124 } // endif: DRB filename was empty
1125
1126 // Return
1127 return;
1128}
1129
1130
1131/***********************************************************************//**
1132 * @brief Load geometry factors from DRG file
1133 *
1134 * @param[in] drgname DRG filename.
1135 *
1136 * @exception GException::invalid_value
1137 * DRG data space incompatible with DRE data space.
1138 *
1139 * Load the geometry factors from the primary image of the specified FITS
1140 * file.
1141 ***************************************************************************/
1143{
1144 // Open FITS file
1145 GFits fits(drgname);
1146
1147 // Get image
1148 const GFitsImage& image = *fits.image("Primary");
1149
1150 // Read geometry factors
1151 m_drg.read(image);
1152
1153 // Correct WCS projection (HEASARC data format kludge)
1154 gammalib::com_wcs_mer2car(const_cast<GSkyMap&>(m_drg.map()));
1155
1156 // Close FITS file
1157 fits.close();
1158
1159 // Check map dimensions
1160 if (!check_dri(m_drg)) {
1161 std::string msg = "DRG data cube \""+drgname+"\" incompatible with "
1162 "DRE data cube \""+m_drename+"\".";
1164 }
1165
1166 // Store DRG filename
1168
1169 // Return
1170 return;
1171}
1172
1173
1174/***********************************************************************//**
1175 * @brief Load exposure from DRX file
1176 *
1177 * @param[in] drxname DRX filename.
1178 *
1179 * Load the exposure map from the primary image of the specified FITS file.
1180 ***************************************************************************/
1182{
1183 // Open FITS file
1184 GFits fits(drxname);
1185
1186 // Get HDU
1187 const GFitsImage& image = *fits.image("Primary");
1188
1189 // Read exposure map
1190 m_drx.read(image);
1191
1192 // Correct WCS projection (HEASARC data format kludge)
1193 gammalib::com_wcs_mer2car(const_cast<GSkyMap&>(m_drx.map()));
1194
1195 // Close FITS file
1196 fits.close();
1197
1198 // Store DRX filename
1200
1201 // Return
1202 return;
1203}
1204
1205
1206/***********************************************************************//**
1207 * @brief Check if DRI is compatible with event cube
1208 *
1209 * @param[in] dri DRI.
1210 * @return True if DRI is compatible, false otherwise.
1211 *
1212 * Compares the dimension and the WCS definition of a DRI to that of the
1213 * event cube. If both are identical, true is returned, false otherwise.
1214 ***************************************************************************/
1216{
1217 // Get references to event cube map and DRI map
1218 const GSkyMap& ref = dynamic_cast<GCOMEventCube*>(m_events)->dre().map();
1219 const GSkyMap& map = dri.map();
1220
1221 // Compare dimensions
1222 bool same_dimension = ((map.nx() == ref.nx()) &&
1223 (map.ny() == ref.ny()) &&
1224 (map.nmaps() == ref.nmaps()));
1225
1226 // Compare projections
1227 bool same_projection = false;
1228 const GSkyProjection* proj_ref = ref.projection();
1229 const GSkyProjection* proj_map = map.projection();
1230 if ((proj_ref == NULL) && (proj_map == NULL)) {
1231 same_projection = true;
1232 }
1233 else if ((proj_ref != NULL) && (proj_map != NULL)) {
1234 same_projection = (*proj_map == *proj_ref);
1235 }
1236
1237 // Return
1238 return (same_dimension && same_projection);
1239}
1240
1241
1242/***********************************************************************//**
1243 * @brief Read observation attributes
1244 *
1245 * @param[in] hdu FITS HDU pointer
1246 *
1247 * Reads optional attributes are
1248 *
1249 * OBS_ID - Observation identifier
1250 * OBJECT - Object
1251 *
1252 * Nothing is done if the HDU pointer is NULL.
1253 ***************************************************************************/
1255{
1256 // Continue only if HDU is valid
1257 if (hdu != NULL) {
1258
1259 // Read observation information
1260 m_obs_id = (hdu->has_card("OBS_ID")) ? hdu->real("OBS_ID") : 0;
1261 m_name = (hdu->has_card("OBJECT")) ? hdu->string("OBJECT") : "unknown";
1262
1263 } // endif: HDU was valid
1264
1265 // Return
1266 return;
1267}
1268
1269
1270/***********************************************************************//**
1271 * @brief Write observation attributes
1272 *
1273 * @param[in] hdu FITS HDU pointer
1274 *
1275 * Nothing is done if the HDU pointer is NULL.
1276 *
1277 * @todo Implement method.
1278 ***************************************************************************/
1280{
1281 // Continue only if HDU is valid
1282 if (hdu != NULL) {
1283
1284 } // endif: HDU was valid
1285
1286 // Return
1287 return;
1288}
1289
1290
1291/***********************************************************************//**
1292 * @brief Compute DRB cube using PHINOR method
1293 *
1294 * @param[in] drm DRM cube.
1295 *
1296 * @exception GException::invalid_value
1297 * Observation does not contain an event cube
1298 * @exception GException::invalid_argument
1299 * DRM cube is incompatible with DRE
1300 ***************************************************************************/
1302{
1303 // Extract COMPTEL event cube
1304 const GCOMEventCube* cube = dynamic_cast<const GCOMEventCube*>(this->events());
1305 if (cube == NULL) {
1306 std::string msg = "Observation \""+this->name()+"\" ("+this->id()+") "
1307 "does not contain a COMPTEL event cube. Please "
1308 "specify a COMPTEL observation containing and event "
1309 "cube.";
1311 }
1312
1313 // Check DRM
1314 if (!check_dri(drm)) {
1315 std::string msg = "Specified DRM cube is incompatible with DRE. Please "
1316 "specify a DRM with a data-space definition that is "
1317 "identical to that of the DRE.";
1319 }
1320
1321 // Initialise DRB by cloning DRG
1322 m_drb = m_drg;
1323
1324 // Get DRI sky maps
1325 const GSkyMap& map_dre = cube->dre().map();
1326 const GSkyMap& map_drm = drm.map();
1327 GSkyMap map_drg = get_weighted_drg_map();
1328 GSkyMap& map_drb = const_cast<GSkyMap&>(m_drb.map());
1329
1330 // Get data space dimensions
1331 int npix = m_drg.map().npix();
1332 int nphibar = m_drg.nphibar();
1333
1334 // Phibar normalise DRB
1335 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1336 double sum_dre = 0.0;
1337 double sum_drm = 0.0;
1338 double sum_drg = 0.0;
1339 for (int ipix = 0; ipix < npix; ++ipix) {
1340 sum_dre += map_dre(ipix, iphibar);
1341 sum_drm += map_drm(ipix, iphibar);
1342 sum_drg += map_drg(ipix, iphibar);
1343 }
1344 if (sum_drg > 0.0) {
1345 double norm = (sum_dre - sum_drm) / sum_drg;
1346 for (int ipix = 0; ipix < npix; ++ipix) {
1347 map_drb(ipix, iphibar) = map_drg(ipix, iphibar) * norm;
1348 }
1349 }
1350 else {
1351 for (int ipix = 0; ipix < npix; ++ipix) {
1352 map_drb(ipix, iphibar) = 0.0;
1353 }
1354 }
1355 }
1356
1357 // Make sure that DRB is non-negative
1358 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1359 for (int ipix = 0; ipix < npix; ++ipix) {
1360 if (map_drb(ipix, iphibar) < 0.0) {
1361 map_drb(ipix, iphibar) = 0.0;
1362 }
1363 }
1364 }
1365
1366 // Return
1367 return;
1368}
1369
1370
1371/***********************************************************************//**
1372 * @brief Compute DRB cube using BGDLIXA method
1373 *
1374 * @param[in] drm DRM cube.
1375 * @param[in] nrunav Number of bins used for running average.
1376 * @param[in] navgr Number of bins used for averaging.
1377 * @param[in] nincl Number of Phibar layers to include.
1378 * @param[in] nexcl Number of Phibar layers to exclude.
1379 *
1380 * @exception GException::invalid_value
1381 * Observation does not contain an event cube
1382 * @exception GException::invalid_argument
1383 * DRM cube is incompatible with DRE
1384 *
1385 * Computes a DRB cube using the BGDLIXA method that is documented in Rob
1386 * van Dijk's PhD thesis. The revelant equations from the thesis that are
1387 * implemented here are 3.12, 3.12 and 3.14.
1388 ***************************************************************************/
1390 const int& nrunav,
1391 const int& navgr,
1392 const int& nincl,
1393 const int& nexcl)
1394{
1395 // Extract COMPTEL event cube
1396 const GCOMEventCube* cube = dynamic_cast<const GCOMEventCube*>(this->events());
1397 if (cube == NULL) {
1398 std::string msg = "Observation \""+this->name()+"\" ("+this->id()+") "
1399 "does not contain a COMPTEL event cube. Please "
1400 "specify a COMPTEL observation containing and event "
1401 "cube.";
1403 }
1404
1405 // Check DRM
1406 if (!check_dri(drm)) {
1407 std::string msg = "Specified DRM cube is incompatible with DRE. Please "
1408 "specify a DRM with a data-space definition that is "
1409 "identical to that of the DRE.";
1411 }
1412
1413 // Initialise DRB and scratch DRI by cloning DRG
1414 m_drb = m_drg;
1415 GCOMDri dri = m_drg;
1416
1417 // Get references to relevant sky maps
1418 const GSkyMap& map_dre = cube->dre().map();
1419 const GSkyMap& map_drm = drm.map();
1420 GSkyMap map_drg = get_weighted_drg_map();
1421 GSkyMap& map_drb = const_cast<GSkyMap&>(m_drb.map());
1422 GSkyMap& map_dri = const_cast<GSkyMap&>(dri.map());
1423
1424 // Get data space dimensions
1425 int nchi = m_drg.nchi();
1426 int npsi = m_drg.npsi();
1427 int nphibar = m_drg.nphibar();
1428 int npix = nchi * npsi;
1429
1430 // Precompute half running average lengths
1431 int navgr2 = int(navgr/2);
1432
1433 // Initialise DRB and scratch DRI
1434 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1435 for (int ipix = 0; ipix < npix; ++ipix) {
1436 map_drb(ipix, iphibar) = 0.0;
1437 map_dri(ipix, iphibar) = 0.0;
1438 }
1439 }
1440
1441 // Phibar normalise DRB (Equation 3.12 in Rob van Dijk's PhD thesis).
1442 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1443 double sum_dre = 0.0;
1444 double sum_drm = 0.0;
1445 double sum_drg = 0.0;
1446 for (int ipix = 0; ipix < npix; ++ipix) {
1447 sum_dre += map_dre(ipix, iphibar);
1448 sum_drm += map_drm(ipix, iphibar);
1449 sum_drg += map_drg(ipix, iphibar);
1450 }
1451 if (sum_drg > 0.0) {
1452 double norm = (sum_dre - sum_drm) / sum_drg;
1453 for (int ipix = 0; ipix < npix; ++ipix) {
1454 map_dri(ipix, iphibar) = map_drg(ipix, iphibar) * norm;
1455 }
1456 }
1457 }
1458
1459 // Do 3D running average of DRE and Phibar normalised DRG (Equation 3.13
1460 // in Rob van Dijk's PhD thesis). The result is a Phibar normalised DRG
1461 // that is normalised over the 3D region to the DRE. The 3D region is all
1462 // Phibar layers and [-nrunav,+nrunav] Chi/Psi pixels around the pixel of
1463 // consideration.
1464 if (nrunav >= 1) {
1465
1466 // Loop over Chi pixels
1467 for (int ichi = 0; ichi < nchi; ++ichi) {
1468
1469 // Compute running average window in Chi
1470 int kchi_min = ichi - nrunav;
1471 int kchi_max = ichi + nrunav;
1472 if (kchi_min < 0) {
1473 kchi_min = 0;
1474 }
1475 if (kchi_max >= nchi) {
1476 kchi_max = nchi - 1;
1477 }
1478
1479 // Loop over Psi pixels
1480 for (int ipsi = 0; ipsi < npsi; ++ipsi) {
1481
1482 // Compute running average window in Psi
1483 int kpsi_min = ipsi - nrunav;
1484 int kpsi_max = ipsi + nrunav;
1485 if (kpsi_min < 0) {
1486 kpsi_min = 0;
1487 }
1488 if (kpsi_max >= npsi) {
1489 kpsi_max = npsi - 1;
1490 }
1491
1492 // Initialise sums
1493 double sum_dre = 0.0;
1494 double sum_drm = 0.0;
1495 double sum_dri = 0.0;
1496
1497 // Compute running average
1498 for (int kchi = kchi_min; kchi <= kchi_max; ++kchi) {
1499 for (int kpsi = kpsi_min; kpsi <= kpsi_max; ++kpsi) {
1500 int kpix = kchi + kpsi * nchi;
1501 for (int kphibar = 0; kphibar < nphibar; ++kphibar) {
1502 if (map_drg(kpix, kphibar) != 0.0) {
1503 sum_dre += map_dre(kpix, kphibar);
1504 sum_drm += map_drm(kpix, kphibar);
1505 sum_dri += map_dri(kpix, kphibar);
1506 }
1507 }
1508 }
1509 }
1510
1511 // Renormalise scratch array
1512 if (sum_dri != 0.0) {
1513 int ipix = ichi + ipsi * nchi;
1514 double norm = (sum_dre - sum_drm) / sum_dri;
1515 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1516 map_dri(ipix, iphibar) *= norm;
1517 }
1518 }
1519
1520 } // endfor: looped over Phi
1521
1522 } // endfor: looped over Chi
1523
1524 } // endif: running averaging was requested
1525
1526 // First part of Equation (3.14) in Rob van Dijk's PhD thesis.
1527 // (DRB = B^0C_L / sum B^0C_L). The DRB is pre-computed by adjusting the
1528 // scratch DRI over nincl Phibar layers.
1529 int ksel1 = 0;
1530 int kex1 = 0;
1531 int kex2 = 0;
1532 int ksel2 = 0;
1533 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1534
1535 // Get Phibar index range for sums
1536 get_bgdlixa_phibar_indices(iphibar, nincl, nexcl,
1537 &ksel1, &kex1, &kex2, &ksel2);
1538
1539 // Loop over Chi/Psi pixels
1540 for (int ipix = 0; ipix < npix; ++ipix) {
1541
1542 // Initialise DRB value
1543 map_drb(ipix, iphibar) = 0.0;
1544
1545 // Continue only if scratch DRI is non-zero
1546 if (map_dri(ipix, iphibar) != 0.0) {
1547
1548 // Initialise sum
1549 double sum_dri = 0.0;
1550
1551 // Take sum over [ksel1, kex1]
1552 if (kex1 >= 0) {
1553 for (int kphibar = ksel1; kphibar <= kex1; ++kphibar) {
1554 sum_dri += map_dri(ipix, kphibar);
1555 }
1556 }
1557
1558 // Take sum over [kxe2, ksel2]
1559 if (kex2 < nphibar) {
1560 for (int kphibar = kex2; kphibar <= ksel2; ++kphibar) {
1561 sum_dri += map_dri(ipix, kphibar);
1562 }
1563 }
1564
1565 // If sum is not zero then set DRB
1566 if (sum_dri != 0.0) {
1567 map_drb(ipix, iphibar) = map_dri(ipix, iphibar) / sum_dri;
1568 }
1569
1570 } // endif: scratch DRI was non-zero
1571
1572 } // endfor: looped over Chi/Psi pixels
1573
1574 } // endfor: looped over Phibar
1575
1576 // Second part of Equation (3.14) in Rob van Dijk's PhD thesis that
1577 // corresponds to G * [E / G]^s that will be stored in scratch DRI.
1578 //
1579 // NOTES:
1580 // - we replaced DRE by DRE-DRM in the nominator of the running
1581 // average since and source component should of course be
1582 // subtracted
1583 // - we implemented an alternative running average computation where
1584 // the ratio between the DRE and DRG sums is taken. This avoids
1585 // the divergence of the ratio at the edge of the DRG.
1586 for (int ichi = 0; ichi < nchi; ++ichi) {
1587
1588 // Compute running average window in Chi
1589 int kchi_min = ichi - navgr2;
1590 int kchi_max = ichi + navgr2;
1591 if (kchi_min < 0) {
1592 kchi_min = 0;
1593 }
1594 if (kchi_max >= nchi) {
1595 kchi_max = nchi - 1;
1596 }
1597
1598 // Loop over Psi pixels
1599 for (int ipsi = 0; ipsi < npsi; ++ipsi) {
1600
1601 // Compute running average window in Psi
1602 int kpsi_min = ipsi - navgr2;
1603 int kpsi_max = ipsi + navgr2;
1604 if (kpsi_min < 0) {
1605 kpsi_min = 0;
1606 }
1607 if (kpsi_max >= npsi) {
1608 kpsi_max = npsi - 1;
1609 }
1610
1611 // Loop over Phibar layers
1612 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1613
1614 // Initialise sums
1615 double sum_dre = 0.0;
1616 double sum_drm = 0.0;
1617 double sum_drg = 0.0;
1618
1619 // Compute running average
1620 for (int kchi = kchi_min; kchi <= kchi_max; ++kchi) {
1621 for (int kpsi = kpsi_min; kpsi <= kpsi_max; ++kpsi) {
1622 int kpix = kchi + kpsi * nchi;
1623 sum_dre += map_dre(kpix, iphibar);
1624 sum_drm += map_drm(kpix, iphibar);
1625 sum_drg += map_drg(kpix, iphibar);
1626 }
1627 }
1628
1629 // Multiply average by DRG and store it in scratch DRI
1630 int ipix = ichi + ipsi * nchi;
1631 if (sum_drg > 0.0) {
1632 double norm = (sum_dre - sum_drm) / sum_drg;
1633 map_dri(ipix, iphibar) = map_drg(ipix, iphibar) * norm;
1634 }
1635 else {
1636 map_dri(ipix, iphibar) = 0.0;
1637 }
1638
1639 } // endfor: looped over Phibar layers
1640
1641 } // endfor: looped over Psi pixels
1642
1643 } // endfor: looped over Chi pixels
1644
1645 // Third part of Equation (3.14) in Rob van Dijk's PhD thesis that sums
1646 // G * [E / G]^s over a subset of Phibar layers (the first parenthesis)
1647 // and multplies with B^0C_L / sum B^0C_L
1648 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1649
1650 // Get Phibar index range for sums
1651 get_bgdlixa_phibar_indices(iphibar, nincl, nexcl,
1652 &ksel1, &kex1, &kex2, &ksel2);
1653
1654 // Loop over Chi/Psi pixels
1655 for (int ipix = 0; ipix < npix; ++ipix) {
1656
1657 // If DRB is not empty then correct it
1658 if (map_drb(ipix, iphibar) != 0.0) {
1659
1660 // Initialise DRI sum
1661 double sum_dri = 0.0;
1662
1663 // Take sum over [ksel1, kex1]
1664 if (kex1 >= 0) {
1665 for (int kphibar = ksel1; kphibar <= kex1; ++kphibar) {
1666 sum_dri += map_dri(ipix, kphibar);
1667 }
1668 }
1669
1670 // Take sum over [kxe2, ksel2]
1671 if (kex2 < nphibar) {
1672 for (int kphibar = kex2; kphibar <= ksel2; ++kphibar) {
1673 sum_dri += map_dri(ipix, kphibar);
1674 }
1675 }
1676
1677 // Correct DRB
1678 map_drb(ipix, iphibar) *= sum_dri;
1679
1680 } // endif: DRB was not empty
1681
1682 } // endfor: looped over Chi/Psi pixels
1683
1684 } // endfor: looped over Phibar
1685
1686 // Phibar normalise DRB
1687 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1688 double sum_dre = 0.0;
1689 double sum_drm = 0.0;
1690 double sum_drb = 0.0;
1691 for (int ipix = 0; ipix < npix; ++ipix) {
1692 sum_dre += map_dre(ipix, iphibar);
1693 sum_drm += map_drm(ipix, iphibar);
1694 sum_drb += map_drb(ipix, iphibar);
1695 }
1696 if (sum_drb > 0.0) {
1697 double norm = (sum_dre - sum_drm) / sum_drb;
1698 for (int ipix = 0; ipix < npix; ++ipix) {
1699 map_drb(ipix, iphibar) *= norm;
1700 }
1701 }
1702 else {
1703 for (int ipix = 0; ipix < npix; ++ipix) {
1704 map_drb(ipix, iphibar) = 0.0;
1705 }
1706 }
1707 }
1708
1709 // Make sure that DRB is non-negative
1710 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1711 for (int ipix = 0; ipix < npix; ++ipix) {
1712 if (map_drb(ipix, iphibar) < 0.0) {
1713 map_drb(ipix, iphibar) = 0.0;
1714 }
1715 }
1716 }
1717
1718 // Return
1719 return;
1720}
1721
1722
1723/***********************************************************************//**
1724 * @brief Compute DRB cube using BGDLIXE method
1725 *
1726 * @param[in] drm DRM cube.
1727 * @param[in] nrunav Number of bins used for running average.
1728 * @param[in] navgr Number of bins used for averaging.
1729 * @param[in] nincl Number of Phibar layers to include.
1730 * @param[in] nexcl Number of Phibar layers to exclude.
1731 *
1732 * @exception GException::invalid_value
1733 * Observation does not contain an event cube
1734 * @exception GException::invalid_argument
1735 * DRM cube is incompatible with DRE
1736 *
1737 * Computes a DRB cube using the BGDLIXE method. This method differs from
1738 * the BGDLIXA method in the last step.
1739 ***************************************************************************/
1741 const int& nrunav,
1742 const int& navgr,
1743 const int& nincl,
1744 const int& nexcl)
1745{
1746 // Extract COMPTEL event cube
1747 const GCOMEventCube* cube = dynamic_cast<const GCOMEventCube*>(this->events());
1748 if (cube == NULL) {
1749 std::string msg = "Observation \""+this->name()+"\" ("+this->id()+") "
1750 "does not contain a COMPTEL event cube. Please "
1751 "specify a COMPTEL observation containing and event "
1752 "cube.";
1754 }
1755
1756 // Check DRM
1757 if (!check_dri(drm)) {
1758 std::string msg = "Specified DRM cube is incompatible with DRE. Please "
1759 "specify a DRM with a data-space definition that is "
1760 "identical to that of the DRE.";
1762 }
1763
1764 // Initialise DRB and scratch DRI by cloning DRG
1765 m_drb = m_drg;
1766 GCOMDri dri = m_drg;
1767
1768 // Get references to relevant sky maps
1769 const GSkyMap& map_dre = cube->dre().map();
1770 const GSkyMap& map_drm = drm.map();
1771 GSkyMap map_drg = get_weighted_drg_map();
1772 GSkyMap& map_drb = const_cast<GSkyMap&>(m_drb.map());
1773 GSkyMap& map_dri = const_cast<GSkyMap&>(dri.map());
1774
1775 // Get data space dimensions
1776 int nchi = m_drg.nchi();
1777 int npsi = m_drg.npsi();
1778 int nphibar = m_drg.nphibar();
1779 int npix = nchi * npsi;
1780
1781 // Precompute half running average lengths
1782 int navgr2 = int(navgr/2);
1783
1784 // Initialise DRB and scratch DRI
1785 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1786 for (int ipix = 0; ipix < npix; ++ipix) {
1787 map_drb(ipix, iphibar) = 0.0;
1788 map_dri(ipix, iphibar) = 0.0;
1789 }
1790 }
1791
1792 // Phibar normalise DRG (Equation 3.12 in Rob van Dijk's PhD thesis).
1793 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1794 double sum_dre = 0.0;
1795 double sum_drm = 0.0;
1796 double sum_drg = 0.0;
1797 for (int ipix = 0; ipix < npix; ++ipix) {
1798 sum_dre += map_dre(ipix, iphibar);
1799 sum_drm += map_drm(ipix, iphibar);
1800 sum_drg += map_drg(ipix, iphibar);
1801 }
1802 if (sum_drg > 0.0) {
1803 double norm = (sum_dre - sum_drm) / sum_drg;
1804 for (int ipix = 0; ipix < npix; ++ipix) {
1805 map_dri(ipix, iphibar) = map_drg(ipix, iphibar) * norm;
1806 }
1807 }
1808 }
1809
1810 // Fit Phibar normalised DRG to DRE-DRM
1811 for (int ichi = 0; ichi < nchi; ++ichi) {
1812
1813 // Compute running average window in Chi
1814 int kchi_min = ichi - navgr2;
1815 int kchi_max = ichi + navgr2;
1816 if (kchi_min < 0) {
1817 kchi_min = 0;
1818 }
1819 if (kchi_max >= nchi) {
1820 kchi_max = nchi - 1;
1821 }
1822
1823 // Loop over Psi pixels
1824 for (int ipsi = 0; ipsi < npsi; ++ipsi) {
1825
1826 // Compute running average window in Psi
1827 int kpsi_min = ipsi - navgr2;
1828 int kpsi_max = ipsi + navgr2;
1829 if (kpsi_min < 0) {
1830 kpsi_min = 0;
1831 }
1832 if (kpsi_max >= npsi) {
1833 kpsi_max = npsi - 1;
1834 }
1835
1836 // Loop over Phibar layers
1837 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1838
1839 // Get Phibar index range for sums
1840 int ksel1 = 0;
1841 int kex1 = 0;
1842 int kex2 = 0;
1843 int ksel2 = 0;
1844 get_bgdlixa_phibar_indices(iphibar, nincl, nexcl,
1845 &ksel1, &kex1, &kex2, &ksel2);
1846
1847 // Initialise sums
1848 double sum_dre = 0.0;
1849 double sum_drm = 0.0;
1850 double sum_dri = 0.0;
1851
1852 // Compute running average
1853 for (int kchi = kchi_min; kchi <= kchi_max; ++kchi) {
1854 for (int kpsi = kpsi_min; kpsi <= kpsi_max; ++kpsi) {
1855
1856 // Get index
1857 int kpix = kchi + kpsi * nchi;
1858
1859 // Take sum over [ksel1, kex1]
1860 if (kex1 >= 0) {
1861 for (int kphibar = ksel1; kphibar <= kex1; ++kphibar) {
1862 sum_dre += map_dre(kpix, kphibar);
1863 sum_drm += map_drm(kpix, kphibar);
1864 sum_dri += map_dri(kpix, kphibar);
1865 }
1866 }
1867
1868 // Take sum over [kxe2, ksel2]
1869 if (kex2 < nphibar) {
1870 for (int kphibar = kex2; kphibar <= ksel2; ++kphibar) {
1871 sum_dre += map_dre(kpix, kphibar);
1872 sum_drm += map_drm(kpix, kphibar);
1873 sum_dri += map_dri(kpix, kphibar);
1874 }
1875 }
1876
1877 } // endfor: looped over kpsi
1878 } // endfor: looped over kchi
1879
1880 // Renormalize DRI locally to DRE-DRM
1881 int ipix = ichi + ipsi * nchi;
1882 if (sum_dri > 0.0) {
1883 double norm = (sum_dre - sum_drm) / sum_dri;
1884 map_drb(ipix, iphibar) = map_dri(ipix, iphibar) * norm;
1885 }
1886 else {
1887 map_drb(ipix, iphibar) = 0.0;
1888 }
1889
1890 } // endfor: looped over Phibar layers
1891
1892 } // endfor: looped over Psi pixels
1893
1894 } // endfor: looped over Chi pixels
1895
1896 // Phibar normalise DRB
1897 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1898 double sum_dre = 0.0;
1899 double sum_drm = 0.0;
1900 double sum_drb = 0.0;
1901 for (int ipix = 0; ipix < npix; ++ipix) {
1902 sum_dre += map_dre(ipix, iphibar);
1903 sum_drm += map_drm(ipix, iphibar);
1904 sum_drb += map_drb(ipix, iphibar);
1905 }
1906 if (sum_drb > 0.0) {
1907 double norm = (sum_dre - sum_drm) / sum_drb;
1908 for (int ipix = 0; ipix < npix; ++ipix) {
1909 map_drb(ipix, iphibar) *= norm;
1910 }
1911 }
1912 else {
1913 for (int ipix = 0; ipix < npix; ++ipix) {
1914 map_drb(ipix, iphibar) = 0.0;
1915 }
1916 }
1917 }
1918
1919 // Make sure that DRB is non-negative
1920 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1921 for (int ipix = 0; ipix < npix; ++ipix) {
1922 if (map_drb(ipix, iphibar) < 0.0) {
1923 map_drb(ipix, iphibar) = 0.0;
1924 }
1925 }
1926 }
1927
1928 // Return
1929 return;
1930}
1931
1932
1933/***********************************************************************//**
1934 * @brief Return weighted DRG map
1935 *
1936 * @return Weighted DRG map.
1937 *
1938 * Returns a DRG as sky map where each pixel of the map is multiplied by the
1939 * solidangle of the pixel.
1940 ***************************************************************************/
1942{
1943 // Initialise
1944 GSkyMap drg = m_drg.map();
1945
1946 // Get data space dimensions
1947 int npix = drg.npix();
1948 int nphibar = drg.nmaps();
1949
1950 // Weight map
1951 for (int ipix = 0; ipix < npix; ++ipix) {
1952 double omega = drg.solidangle(ipix);
1953 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1954 drg(ipix,iphibar) *= omega;
1955 }
1956 }
1957
1958 // Return weighted DRG map
1959 return drg;
1960}
1961
1962
1963/***********************************************************************//**
1964 * @brief Compute Phibar index range for BGDLIXA background method
1965 *
1966 * @param[in] iphibar Phibar layer index.
1967 * @param[in] nincl Number of Phibar layers to include.
1968 * @param[in] nexcl Number of Phibar layers to exclude.
1969 * @param[out] isel1 Start index for first sum.
1970 * @param[out] iex1 Stop index for first sum.
1971 * @param[out] iex2 Start index for second sum.
1972 * @param[out] isel2 Stop index for second sum.
1973 *
1974 * This method is a helper method for the BGDLIXA background method. It
1975 * computes the Phibar index range for the third step of the background
1976 * model computation. The third step corresponds to Equation (3.14) in Rob
1977 * van Dijk's PhD thesis.
1978 *
1979 * The Phibar sum will be taken over the index ranges [isel1, iex1] and
1980 * [ixe2, isel2].
1981 ***************************************************************************/
1983 const int& nincl,
1984 const int& nexcl,
1985 int* isel1,
1986 int* iex1,
1987 int* iex2,
1988 int* isel2) const
1989{
1990 // Get number of Phibar layers
1991 int nphibar = m_drg.nphibar();
1992 int imax = nphibar - 1;
1993
1994 // Precompute half running average lengths
1995 int nexcl2 = int(nexcl/2);
1996 int nincl2 = int(nincl/2);
1997
1998 // Compute Phibar index range without respecting boundaries
1999 *iex1 = iphibar - nexcl2 - 1;
2000 *iex2 = iphibar + nexcl2 + 1;
2001 *isel1 = iphibar - nincl2;
2002 *isel2 = iphibar + nincl2;
2003
2004 // If no Phibar layers are to be excluded then make sure that the
2005 // Phibar layer range is continuous
2006 if (nexcl == 0) {
2007 (*iex2)--;
2008 }
2009
2010 // Make sure that start index of first sum and stop index of second
2011 // some are within the validity range
2012 if (*isel1 < 0) {
2013 *isel1 = 0;
2014 }
2015 if (*isel2 > imax) {
2016 *isel2 = imax;
2017 }
2018
2019 // Make sure that the sums use always ncincl Phibar layers, also near
2020 // the edges
2021 if (*isel1 == 0) {
2022 *isel2 = nincl - 1;
2023 if (nincl > imax) {
2024 *isel2 = imax;
2025 }
2026
2027 }
2028 if (*isel2 == imax) {
2029 *isel1 = nphibar - nincl;
2030 if (*isel1 < 0) {
2031 *isel1 = 0;
2032 }
2033 }
2034
2035 // Return
2036 return;
2037}
2038
2039
2040/***********************************************************************//**
2041 * @brief Check whether bin should be used for likelihood analysis
2042 *
2043 * @param[in] index Event index.
2044 * @return True if event with specified @p index should be used.
2045 *
2046 * Implements the Phibar event selection.
2047 ***************************************************************************/
2049{
2050 // Initialise usage flag
2051 bool use = true;
2052
2053 // Compute Phibar layer
2054 int iphi = index / m_drg.map().npix();
2055
2056 // Test first Phibar layer selection
2057 if ((m_phi_first != -1) && (iphi < m_phi_first)) {
2058 use = false;
2059 }
2060 else {
2061 // Test last Phibar layer selection
2062 if ((m_phi_last != -1) && (iphi > m_phi_last)) {
2063 use = false;
2064 }
2065 }
2066
2067 // Return usage flag
2068 return use;
2069}
#define G_WRITE
#define G_READ
COMPTEL event bin class interface definition.
#define G_RESPONSE
const GCOMObservation g_obs_com_seed
#define G_COMPUTE_DRB
#define G_LOAD_DRB
#define G_COMPUTE_DRB_BGDLIXA
#define G_COMPUTE_DRB_PHINOR
#define G_COMPUTE_DRB_BGDLIXE
#define G_DRM
COMPTEL observation class interface definition.
COMPTEL instrument status class definition.
Implementation of support function used by COMPTEL classes.
Calibration database class interface definition.
Exception handler interface definition.
Abstract FITS extension base class definition.
FITS file class interface definition.
Mathematical function definitions.
Sky model class interface definition.
Constant spectral model class interface definition.
Model container class definition.
Observation registry class definition.
Source class definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
double norm(const GVector &vector)
Computes vector norm.
Definition GVector.cpp:864
XML element node class interface definition.
void clear(void)
Clear COMPTEL Solar System Barycentre Data container.
Definition GCOMBvcs.cpp:170
void load(const GFilename &filename)
Load COMPTEL Solar System Barycentre Data FITS file.
Definition GCOMBvcs.cpp:370
bool is_empty(void) const
Signals if there are no Solar System Barycentre Data in container.
Definition GCOMBvcs.hpp:163
std::string print(const GChatter &chatter=NORMAL) const
Print COMPTEL Solar System Barycentre Data container.
Definition GCOMBvcs.cpp:692
COMPTEL Data Space class.
Definition GCOMDri.hpp:61
virtual void clear(void)
Clear COMPTEL Data Space.
Definition GCOMDri.cpp:228
int nchi(void) const
Return number of Chi bins.
Definition GCOMDri.hpp:231
const GSkyMap & map(void) const
Return DRI sky map.
Definition GCOMDri.hpp:267
int npsi(void) const
Return number of Psi bins.
Definition GCOMDri.hpp:243
int nphibar(void) const
Return number of Phibar bins.
Definition GCOMDri.hpp:255
void read(const GFitsImage &image)
Read COMPTEL Data Space from DRI FITS image.
Definition GCOMDri.cpp:942
COMPTEL event bin class.
virtual double size(void) const
Return size of event bin.
virtual double counts(void) const
Return number of counts in event bin.
COMPTEL event bin container class.
virtual int size(void) const
Return number of bins in event cube.
const GCOMDri & dre(void) const
Return reference to DRE data.
COMPTEL event list class.
COMPTEL Orbit Aspect Data container class.
Definition GCOMOads.hpp:51
void extend(const GCOMOads &oads)
Append Orbit Aspect Data container.
Definition GCOMOads.cpp:329
std::string print(const GChatter &chatter=NORMAL) const
Print COMPTEL Orbit Aspect Data container.
Definition GCOMOads.cpp:496
void clear(void)
Clear COMPTEL Orbit Aspect Data container.
Definition GCOMOads.cpp:167
int size(void) const
Return number of Orbit Aspect Data in container.
Definition GCOMOads.hpp:141
bool is_empty(void) const
Signals if there are no Orbit Aspect Data in container.
Definition GCOMOads.hpp:156
GCOMOad & insert(const int &index, const GCOMOad &oad)
Insert Orbit Aspect Data into container.
Definition GCOMOads.cpp:268
Interface class for COMPTEL observations.
void free_members(void)
Delete class members.
GCOMDri drm(const GModels &models) const
Compute DRM cube.
void init_members(void)
Initialise class members.
const GFilename & drename(void) const
Return DRE filename.
GFilename m_drgname
DRG filename.
bool is_unbinned(void) const
Check whether observation is unbinned.
void compute_drb_phinor(const GCOMDri &drm)
Compute DRB cube using PHINOR method.
GFilename m_drxname
DRX filename.
void compute_drb_bgdlixa(const GCOMDri &drm, const int &nrunav=3, const int &navgr=3, const int &nincl=13, const int &nexcl=0)
Compute DRB cube using BGDLIXA method.
const GFilename & drgname(void) const
Return DRG filename.
const GFilename & drxname(void) const
Return DRX filename.
double m_ontime
Ontime (sec)
void get_bgdlixa_phibar_indices(const int &iphibar, const int &nincl, const int &nexcl, int *isel1, int *iex1, int *iex2, int *isel2) const
Compute Phibar index range for BGDLIXA background method.
bool check_dri(const GCOMDri &map) const
Check if DRI is compatible with event cube.
const GCOMDri & drb(void) const
Return background model.
virtual double ontime(void) const
Return ontime.
virtual GCOMObservation * clone(void) const
Clone COMPTEL observation.
GCOMBvcs m_bvcs
Solar System Barycentre Data.
void read_attributes(const GFitsHDU *hdu)
Read observation attributes.
const int & phi_first(void) const
Return index of first Phibar layer to be used for likelihood fitting.
const GCOMOads & oads(void) const
Return Orbit Aspect Data.
int m_phi_last
Last Phibar layer to use for likelihood.
GFilename m_drename
DRE filename.
void load_drg(const GFilename &drgname)
Load geometry factors from DRG file.
virtual std::string instrument(void) const
Return instrument.
double m_livetime
Livetime (sec)
virtual void read(const GXmlElement &xml)
Read observation from XML element.
GSkyMap get_weighted_drg_map(void) const
Return weighted DRG map.
virtual void clear(void)
Clear COMPTEL observation.
double m_obs_id
Observation ID.
virtual void write(GXmlElement &xml) const
Write observation into XML element.
GCOMOads m_oads
Orbit Aspect Data.
int m_phi_first
First Phibar layer to use for likelihood.
GCOMObservation(void)
Void constructor.
GCOMTim m_tim
COMPTEL Good Time Intervals.
GCOMDri m_drg
Geometry factors.
virtual const GCOMResponse * response(void) const
Return response function.
virtual std::string print(const GChatter &chatter=NORMAL) const
Print observation information.
void load(const GFilename &drename, const GFilename &drbname, const GFilename &drgname, const GFilename &drxname)
Load data for a binned observation.
GCOMDri m_drb
Background model.
bool is_binned(void) const
Check whether observation is binned.
void load_dre(const GFilename &drename)
Load event cube data from DRE file.
const int & phi_last(void) const
Return index of last Phibar layer to be used for likelihood fitting.
void write_attributes(GFitsHDU *hdu) const
Write observation attributes.
double m_ewidth
Energy width (MeV)
GFilename m_drbname
DRB filename.
GFilename m_evpname
EVP filename.
virtual bool use_event_for_likelihood(const int &index) const
Check whether bin should be used for likelihood analysis.
void compute_drb_bgdlixe(const GCOMDri &drm, const int &nrunav=3, const int &navgr=3, const int &nincl=13, const int &nexcl=0)
Compute DRB cube using BGDLIXE method.
const GCOMDri & drx(void) const
Return exposure.
double m_deadc
Deadtime correction.
const GCOMDri & drg(void) const
Return geometry factors.
virtual double livetime(void) const
Return livetime.
const GFilename & drbname(void) const
Return DRB filename.
void compute_drb(const std::string &method, const GCOMDri &drm, const int &nrunav=3, const int &navgr=3, const int &nincl=13, const int &nexcl=0)
Compute DRB cube.
GFilename m_timname
TIM filename.
GCOMResponse m_response
Response functions.
std::vector< GFilename > m_oadnames
OAD filenames.
virtual ~GCOMObservation(void)
Destructor.
std::string m_instrument
Instrument name.
GFilename m_bvcname
BVC filename.
void load_drx(const GFilename &drxname)
Load exposure from DRX file.
void copy_members(const GCOMObservation &obs)
Copy class members.
void load_drb(const GFilename &drbname)
Load background model from DRB file.
virtual GCOMObservation & operator=(const GCOMObservation &obs)
Assignment operator.
GCOMDri m_drx
Exposure map.
Interface for the COMPTEL instrument response function.
const std::string & rspname(void) const
Return response name.
void caldb(const GCaldb &caldb)
Set calibration database.
virtual void clear(void)
Clear instance.
void load(const std::string &rspname)
Load COMPTEL response.
const GGti & gti(void) const
Return Good Time Intervals.
Definition GCOMTim.hpp:144
virtual void clear(void)
Clear COMPTEL good time intervals.
Definition GCOMTim.cpp:185
virtual std::string print(const GChatter &chatter=NORMAL) const
Print COMPTEL Good Time Intervals.
Definition GCOMTim.cpp:408
void load(const GFilename &filename, const std::string &usage="YES", const std::string &mode="NORMAL")
Load COMPTEL Good Time Intervals from FITS file.
Definition GCOMTim.cpp:218
Calibration database class.
Definition GCaldb.hpp:66
double MeV(void) const
Return energy in MeV.
Definition GEnergy.cpp:321
void gti(const GGti &gti)
Set Good Time Intervals.
Definition GEvents.cpp:154
virtual void read(const GFits &file)=0
virtual std::string print(const GChatter &chatter=NORMAL) const =0
Print content of object.
const GEnergy & emax(void) const
Return maximum energy.
Definition GEvents.hpp:182
const GEnergy & emin(void) const
Return minimum energy.
Definition GEvents.hpp:170
Filename class.
Definition GFilename.hpp:62
bool is_fits(void) const
Checks whether file is a FITS file.
bool is_empty(void) const
Signal if filename is empty.
void clear(void)
Clear file name.
Abstract FITS extension base class.
Definition GFitsHDU.hpp:51
bool has_card(const int &cardno) const
Check existence of header card.
Definition GFitsHDU.hpp:233
double real(const std::string &keyname) const
Return card value as double precision.
Definition GFitsHDU.hpp:423
std::string string(const std::string &keyname) const
Return card value as string.
Definition GFitsHDU.hpp:410
Abstract FITS image base class.
FITS file class.
Definition GFits.hpp:63
GFitsImage * image(const int &extno)
Get pointer to image HDU.
Definition GFits.cpp:368
void close(void)
Close FITS file.
Definition GFits.cpp:1342
int size(void) const
Return number of Good Time Intervals.
Definition GGti.hpp:154
const double & ontime(void) const
Returns ontime.
Definition GGti.hpp:240
Model container class.
Definition GModels.hpp:152
double eval(const GEvent &event, const GObservation &obs, const bool &gradients=false) const
Evaluate sum of all models.
Definition GModels.cpp:911
Interface definition for the observation registry class.
Abstract observation base class.
const std::string & statistic(void) const
Return optimizer statistic.
virtual double model(const GModels &models, const GEvent &event, GVector *gradients=NULL) const
Return model value and (optionally) gradients.
const std::string & id(void) const
Return observation identifier.
const std::string & name(void) const
Return observation name.
virtual GEvents * events(void)
Return events.
void init_members(void)
Initialise class members.
virtual GObservation & operator=(const GObservation &obs)
Assignment operator.
GEvents * m_events
Pointer to event container.
void free_members(void)
Delete class members.
std::string m_name
Observation name.
Abstract instrument response base class.
Definition GResponse.hpp:77
Sky map class.
Definition GSkyMap.hpp:89
const int & nmaps(void) const
Returns number of maps.
Definition GSkyMap.hpp:389
const int & nx(void) const
Returns number of pixels in x coordinate.
Definition GSkyMap.hpp:361
const int & npix(void) const
Returns number of pixels.
Definition GSkyMap.hpp:345
const int & ny(void) const
Returns number of pixels in y coordinate.
Definition GSkyMap.hpp:377
const GSkyProjection * projection(void) const
Returns pointer to sky projection.
Definition GSkyMap.hpp:463
Abstract sky projection base class.
Vector class.
Definition GVector.hpp:46
XML element node class.
const GXmlAttribute * attribute(const int &index) const
Return attribute.
bool has_attribute(const std::string &name) const
Check if element has a given attribute.
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition GXmlNode.cpp:287
virtual void remove(const int &index)
Remove XML child node.
Definition GXmlNode.cpp:481
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition GXmlNode.cpp:640
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition GXmlNode.cpp:586
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 xml_get_attr(const std::string &origin, const GXmlElement &xml, const std::string &name, const std::string &attribute)
Return attribute value for a given parameter in XML element.
Definition GTools.cpp:1738
int toint(const std::string &arg)
Convert string into integer value.
Definition GTools.cpp:821
GXmlElement * xml_need_par(const std::string &origin, GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition GTools.cpp:1637
GFilename xml_file_reduce(const GXmlElement &xml, const std::string &filename)
Reduce file name provided for writing as XML attribute.
Definition GTools.cpp:1946
void com_wcs_mer2car(GSkyMap &map)
Changes Mercator's projection to cartesian projection.
GChatter reduce(const GChatter &chatter)
Reduce chattiness by one level.
Definition GTypemaps.hpp:65
bool xml_has_par(const GXmlElement &xml, const std::string &name)
Checks if parameter with given name in XML element exists.
Definition GTools.cpp:1596
GFilename xml_file_expand(const GXmlElement &xml, const std::string &filename)
Expand file name provided as XML attribute for loading.
Definition GTools.cpp:1889