GammaLib 2.1.0.dev
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-2024 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_DRW "GCOMObservation::load_drw(GFilename&)"
59#define G_LOAD_DRG "GCOMObservation::load_drg(GFilename&)"
60#define G_CONVOLVE "GCOMObservation::convolve(GModels&)"
61#define G_DRM "GCOMObservation::drm(GModels&)"
62#define G_COMPUTE_DRB "GCOMObservation::compute_drb(std::string&, GCOMDri&, "\
63 "int&, int&, int&, int&"
64#define G_COMPUTE_DRB_PHINOR "GCOMObservation::compute_drb_phinor(GCOMDri&)"
65#define G_COMPUTE_DRB_BGDLIXA "GCOMObservation::compute_drb_bgdlixa("\
66 "GCOMDri&, int&, int&, int&, int&)"
67#define G_COMPUTE_DRB_BGDLIXE "GCOMObservation::compute_drb_bgdlixe("\
68 "GCOMDri&, int&, int&, int&, int&)"
69#define G_COMPUTE_DRB_BGDLIXF "GCOMObservation::compute_drb_bgdlixf("\
70 "GCOMDri&, int&, int&, int&, int&)"
71
72/* __ Macros _____________________________________________________________ */
73
74/* __ Coding definitions _________________________________________________ */
75
76/* __ Debug definitions __________________________________________________ */
77
78
79/*==========================================================================
80 = =
81 = Constructors/destructors =
82 = =
83 ==========================================================================*/
84
85/***********************************************************************//**
86 * @brief Void constructor
87 *
88 * Creates an empty COMPTEL observation.
89 ***************************************************************************/
91{
92 // Initialise members
94
95 // Return
96 return;
97}
98
99
100/***********************************************************************//**
101 * @brief XML constructor
102 *
103 * @param[in] xml XML element.
104 *
105 * Constructs a COMPTEL observation from the information that is found in an
106 * XML element.
107 ***************************************************************************/
109{
110 // Initialise members
111 init_members();
112
113 // Read XML
114 read(xml);
115
116 // Return
117 return;
118}
119
120
121/***********************************************************************//**
122 * @brief Binned observation DRI constructor
123 *
124 * @param[in] dre Event cube.
125 * @param[in] drb Background cube.
126 * @param[in] drg Geometry cube.
127 * @param[in] drx Exposure map.
128 *
129 * Creates COMPTEL observation from DRI instances.
130 *
131 * The method fixes the deadtime correction factor deadc to 0.965.
132 ***************************************************************************/
134 const GCOMDri& drb,
135 const GCOMDri& drg,
136 const GCOMDri& drx) : GObservation()
137{
138 // Initialise members
139 init_members();
140
141 // Store DRIs
142 m_events = new GCOMEventCube(dre);
143 m_drb = drb;
144 m_drg = drg;
145 m_drx = drx;
146
147 // Set attributes
148 m_obs_id = 0;
149 m_ontime = m_events->gti().ontime();
150 m_deadc = 0.965;
152 m_ewidth = m_events->emax().MeV() - m_events->emin().MeV();
153 m_name = "unknown";
154 m_drename = "";
155 m_drbname = "";
156 m_drwname = "";
157 m_drgname = "";
158 m_drxname = "";
159
160 // Return
161 return;
162}
163
164
165/***********************************************************************//**
166 * @brief Binned observation DRI constructor
167 *
168 * @param[in] dre Event cube.
169 * @param[in] drb Background cube.
170 * @param[in] drw Weighting cube.
171 * @param[in] drg Geometry cube.
172 * @param[in] drx Exposure map.
173 *
174 * Creates COMPTEL observation from DRI instances.
175 *
176 * The method fixes the deadtime correction factor deadc to 0.965.
177 ***************************************************************************/
179 const GCOMDri& drb,
180 const GCOMDri& drw,
181 const GCOMDri& drg,
182 const GCOMDri& drx) : GObservation()
183{
184 // Initialise members
185 init_members();
186
187 // Store DRIs
188 m_events = new GCOMEventCube(dre);
189 m_drb = drb;
190 m_drw = drw;
191 m_drg = drg;
192 m_drx = drx;
193
194 // Set attributes
195 m_obs_id = 0;
196 m_ontime = m_events->gti().ontime();
197 m_deadc = 0.965;
199 m_ewidth = m_events->emax().MeV() - m_events->emin().MeV();
200 m_name = "unknown";
201 m_drename = "";
202 m_drbname = "";
203 m_drwname = "";
204 m_drgname = "";
205 m_drxname = "";
206
207 // Return
208 return;
209}
210
211
212/***********************************************************************//**
213 * @brief Binned observation filename constructor
214 *
215 * @param[in] drename Event cube name.
216 * @param[in] drbname Background cube name.
217 * @param[in] drwname Weighting cube name.
218 * @param[in] drgname Geometry cube name.
219 * @param[in] drxname Exposure map name.
220 *
221 * Creates COMPTEL observation by loading the following FITS files:
222 *
223 * DRE - Events cube
224 * DRB - Background model cube
225 * DRW - Weighting cube
226 * DRG - Geometry factors cube
227 * DRX - Exposure map
228 *
229 * Each of the four files is mandatory.
230 ***************************************************************************/
232 const GFilename& drbname,
233 const GFilename& drwname,
234 const GFilename& drgname,
235 const GFilename& drxname) : GObservation()
236{
237 // Initialise members
238 init_members();
239
240 // Load observation
242
243 // Return
244 return;
245}
246
247
248/***********************************************************************//**
249 * @brief Unbinned observation constructor
250 *
251 * @param[in] evpname Event list FITS file name.
252 * @param[in] timname Good Time Intervals FITS file name.
253 * @param[in] oadnames List of Orbit Aspect Data FITS file names.
254 * @param[in] hkdnames List of Housekeeping Data FITS file names.
255 * @param[in] bvcname Solar System Barycentre Data FITS file name.
256 *
257 * Creates a COMPTEL unbinned observation by loading the event list, Good
258 * Time Interval, Orbit Aspect Data and optionally the Solar System
259 * Barycentre Data from FITS files.
260 *
261 * Except of the Housekeeping Data and the Solar System Barycentre Data all
262 * files are mandatory. The Housekeeping Data and the Solar System Barycentre
263 * Data will only be loaded if the file names are not empty.
264 *
265 * See load() method for more information.
266 ***************************************************************************/
268 const GFilename& timname,
269 const std::vector<GFilename>& oadnames,
270 const std::vector<GFilename>& hkdnames,
271 const GFilename& bvcname)
272{
273 // Initialise members
274 init_members();
275
276 // Load observation
277 load(evpname, timname, oadnames, hkdnames, bvcname);
278
279 // Return
280 return;
281}
282
283
284/***********************************************************************//**
285 * @brief Copy constructor
286 *
287 * @param[in] obs COMPTEL observation.
288 *
289 * Creates COMPTEL observation by copying an existing COMPTEL observation.
290 ***************************************************************************/
292{
293 // Initialise members
294 init_members();
295
296 // Copy members
297 copy_members(obs);
298
299 // Return
300 return;
301}
302
303
304/***********************************************************************//**
305 * @brief Destructor
306 ***************************************************************************/
308{
309 // Free members
310 free_members();
311
312 // Return
313 return;
314}
315
316
317/*==========================================================================
318 = =
319 = Operators =
320 = =
321 ==========================================================================*/
322
323/***********************************************************************//**
324 * @brief Assignment operator
325 *
326 * @param[in] obs COMPTEL observation.
327 * @return COMPTEL observation.
328 *
329 * Assign COMPTEL observation to this object.
330 ***************************************************************************/
332{
333 // Execute only if object is not identical
334 if (this != &obs) {
335
336 // Copy base class members
337 this->GObservation::operator=(obs);
338
339 // Free members
340 free_members();
341
342 // Initialise members
343 init_members();
344
345 // Copy members
346 copy_members(obs);
347
348 } // endif: object was not identical
349
350 // Return this object
351 return *this;
352}
353
354
355/*==========================================================================
356 = =
357 = Public methods =
358 = =
359 ==========================================================================*/
360
361/***********************************************************************//**
362 * @brief Clear COMPTEL observation
363 ***************************************************************************/
365{
366 // Free members
367 free_members();
369
370 // Initialise members
372 init_members();
373
374 // Return
375 return;
376}
377
378
379/***********************************************************************//**
380 * @brief Clone COMPTEL observation
381 *
382 * @return Pointer to deep copy of COMPTEL observation.
383 ***************************************************************************/
385{
386 return new GCOMObservation(*this);
387}
388
389
390/***********************************************************************//**
391 * @brief Set response function
392 *
393 * @param[in] rsp Response function.
394 *
395 * @exception GException::invalid_argument
396 * Specified response is not a COMPTEL response.
397 *
398 * Sets the response function for the observation.
399 ***************************************************************************/
401{
402 // Get pointer on COM response
403 const GCOMResponse* comrsp = dynamic_cast<const GCOMResponse*>(&rsp);
404 if (comrsp == NULL) {
405 std::string cls = std::string(typeid(&rsp).name());
406 std::string msg = "Response of type \""+cls+"\" is "
407 "not a COMPTEL response. Please specify a COMPTEL "
408 "response as argument.";
410 }
411
412 // Clone response function
413 m_response = *comrsp;
414
415 // Return
416 return;
417}
418
419
420/***********************************************************************//**
421 * @brief Set response function
422 *
423 * @param[in] caldb Calibration database.
424 * @param[in] rspname Name of COMPTEL response.
425 *
426 * Sets the response function by loading the response information from the
427 * calibration database.
428 ***************************************************************************/
429void GCOMObservation::response(const GCaldb& caldb, const std::string& rspname)
430{
431 // Clear COM response function
433
434 // Set calibration database
435 m_response.caldb(caldb);
436
437 // Load instrument response function
439
440 // Return
441 return;
442}
443
444
445/***********************************************************************//**
446 * @brief Return total number of predicted counts for one model
447 *
448 * @param[in] model Gamma-ray source model.
449 * @return Total number of predicted counts in model.
450 *
451 * Returns the total number of predicted counts in a given model component.
452 ***************************************************************************/
453double GCOMObservation::npred(const GModel& model) const
454{
455 // Initialise Npred
456 double npred = 0.0;
457
458 // Setup model container
459 GModels models;
460 models.append(model);
461
462 // Compute model vector
463 GVector model_vector = this->model(models, NULL);
464
465 // Get number of events
466 int nevents = model_vector.size();
467
468 // Iterate over all bins
469 for (int i = 0; i < nevents; ++i) {
470
471 // Skip events that should not be used
472 if (!use_event_for_likelihood(i)) {
473 continue;
474 }
475
476 // Get event pointer
477 const GEventBin* bin =
478 (*(static_cast<GEventCube*>(const_cast<GEvents*>(events()))))[i];
479
480 // Get model value
481 double model_value = model_vector[i] * bin->size();
482
483 // Update Npred
484 npred += model_value;
485
486 } // endfor: looped over all bins
487
488 // Return Npred
489 return npred;
490}
491
492
493/***********************************************************************//**
494 * @brief Read observation from XML element
495 *
496 * @param[in] xml XML element.
497 *
498 * Reads information for a COMPTEL observation from an XML element. The
499 * method supports both an unbinned and a binned observation.
500 *
501 * For an unbinned observation the XML format is
502 *
503 * <observation name="Crab" id="000001" instrument="COM">
504 * <parameter name="EVP" file="m16992_evp.fits"/>
505 * <parameter name="TIM" file="m10695_tim.fits"/>
506 * <parameter name="OAD" file="m20039_oad.fits"/>
507 * <parameter name="OAD" file="m20041_oad.fits"/>
508 * <parameter name="HKD" file="m20035_hkd.fits"/>
509 * <parameter name="HKD" file="m20037_hkd.fits"/>
510 * <parameter name="BVC" file="s10150_bvc.fits"/>
511 * ...
512 * </observation>
513 *
514 * where the observation can contain an arbitrary number of OAD file
515 * parameters. The @p file attribute provide either absolute or relative
516 * file names. If a file name includes no access path it is assumed that
517 * the file resides in the same location as the XML file. The HKD and BVC
518 * files are optional and do not need to be specified.
519 *
520 * For a binned observation the XML format is
521 *
522 * <observation name="Crab" id="000001" instrument="COM">
523 * <parameter name="DRE" file="m50438_dre.fits"/>
524 * <parameter name="DRB" file="m34997_drg.fits"/>
525 * <parameter name="DRW" file="m34997_drw.fits"/>
526 * <parameter name="DRG" file="m34997_drg.fits"/>
527 * <parameter name="DRX" file="m32171_drx.fits"/>
528 * <parameter name="IAQ" value="UNH(1.0-3.0)MeV"/>
529 * </observation>
530 *
531 * Note that the DRW parameter is optional.
532 ***************************************************************************/
534{
535 // Clear observation
536 clear();
537
538 // If the XML elements has a "EVP" attribute we have an unbinned
539 // observation
540 if (gammalib::xml_has_par(xml, "EVP")) {
541
542 // Get EVP and TIM file names
543 std::string evpname = gammalib::xml_get_attr(G_READ, xml, "EVP", "file");
544 std::string timname = gammalib::xml_get_attr(G_READ, xml, "TIM", "file");
545
546 // Expand EVP and TIM file names
547 evpname = gammalib::xml_file_expand(xml, evpname);
548 timname = gammalib::xml_file_expand(xml, timname);
549
550 // Get OAD file names
551 std::vector<GFilename> oadnames;
552 for (int i = 0; i < xml.elements("parameter"); ++i) {
553 const GXmlElement* element = xml.element("parameter", i);
554 if (element->attribute("name") == "OAD") {
555 std::string oadname = element->attribute("file");
556 oadname = gammalib::xml_file_expand(xml, oadname);
557 oadnames.push_back(GFilename(oadname));
558 }
559 }
560
561 // Get and expand optional HKD file names
562 std::vector<GFilename> hkdnames;
563 for (int i = 0; i < xml.elements("parameter"); ++i) {
564 const GXmlElement* element = xml.element("parameter", i);
565 if (element->attribute("name") == "HKD") {
566 std::string hkdname = element->attribute("file");
567 hkdname = gammalib::xml_file_expand(xml, hkdname);
568 hkdnames.push_back(GFilename(hkdname));
569 }
570 }
571
572 // Get and expand optional BVC file name
573 std::string bvcname = "";
574 if (gammalib::xml_has_par(xml, "BVC")) {
575 bvcname = gammalib::xml_get_attr(G_READ, xml, "BVC", "file");
576 bvcname = gammalib::xml_file_expand(xml, bvcname);
577 }
578
579 // Load observation
580 load(evpname, timname, oadnames, hkdnames, bvcname);
581
582 } // endif: unbinned observation
583
584 // ... otherwise we have a binned observation
585 else {
586
587 // Get parameters
588 std::string drename = gammalib::xml_get_attr(G_READ, xml, "DRE", "file");
589 std::string drbname = gammalib::xml_get_attr(G_READ, xml, "DRB", "file");
590 std::string drgname = gammalib::xml_get_attr(G_READ, xml, "DRG", "file");
591 std::string drxname = gammalib::xml_get_attr(G_READ, xml, "DRX", "file");
592 std::string iaqname = gammalib::xml_get_attr(G_READ, xml, "IAQ", "value");
593
594 // Optionally get DRW
595 std::string drwname = (gammalib::xml_has_par(xml, "DRW")) ?
596 gammalib::xml_get_attr(G_READ, xml, "DRW", "file") :
597 "";
598
599 // Expand file names
605 std::string iaqname_expanded = gammalib::xml_file_expand(xml, iaqname);
606
607 // Load observation
609
610 // Load IAQ by trying first the expanded name as a FITS file and
611 // otherwise the unexpanded name
612 GFilename filename_expanded(iaqname_expanded);
613 if (filename_expanded.is_fits()) {
614 response(GCaldb("cgro", "comptel"), iaqname_expanded);
615 }
616 else {
617 response(GCaldb("cgro", "comptel"), iaqname);
618 }
619
620 // Get optional Phibar layer attributes
621 if (xml.has_attribute("phi_first")) {
622 m_phi_first = gammalib::toint(xml.attribute("phi_first"));
623 }
624 if (xml.has_attribute("phi_last")) {
625 m_phi_last = gammalib::toint(xml.attribute("phi_last"));
626 }
627
628 // Optionally load response cache
629 if (gammalib::xml_has_par(xml, "RSP")) {
630
631 // Get and expand filename
632 m_rspname = gammalib::xml_get_attr(G_READ, xml, "RSP", "file");
634
635 // If file exists then load it
636 if (m_rspname.exists()) {
638 }
639
640 } // endif: optionally loaded response cache
641
642 } // endelse: binned observation
643
644 // Extract attributes
645 m_name = xml.attribute("name");
646 m_id = xml.attribute("id");
647 m_instrument = xml.attribute("instrument");
648
649 // Return
650 return;
651}
652
653
654/***********************************************************************//**
655 * @brief Write observation into XML element
656 *
657 * @param[in] xml XML element.
658 *
659 * Writes information for a COMPTEL observation into an XML element. The
660 * method supports both an unbinned and a binned observation.
661 *
662 * For an unbinned observation the XML format is
663 *
664 * <observation name="Crab" id="000001" instrument="COM">
665 * <parameter name="EVP" file="m16992_evp.fits"/>
666 * <parameter name="TIM" file="m10695_tim.fits"/>
667 * <parameter name="OAD" file="m20039_oad.fits"/>
668 * <parameter name="OAD" file="m20041_oad.fits"/>
669 * <parameter name="HKD" file="m20035_hkd.fits"/>
670 * <parameter name="HKD" file="m20037_hkd.fits"/>
671 * <parameter name="BVC" file="s10150_bvc.fits"/>
672 * ...
673 * </observation>
674 *
675 * where the observation can contain an arbitrary number of OAD file
676 * parameters. The @p file attribute provide either absolute or relative
677 * file names. If a file name includes no access path it is assumed that
678 * the file resides in the same location as the XML file. The HKD and BVC
679 * files are optional and are only written if HKD and BVC information is
680 * contained in the observation.
681 *
682 * For a binned observation the XML format is
683 *
684 * <observation name="Crab" id="000001" instrument="COM">
685 * <parameter name="DRE" file="m50438_dre.fits"/>
686 * <parameter name="DRB" file="m34997_drg.fits"/>
687 * <parameter name="DRW" file="m34997_drw.fits"/>
688 * <parameter name="DRG" file="m34997_drg.fits"/>
689 * <parameter name="DRX" file="m32171_drx.fits"/>
690 * <parameter name="IAQ" value="UNH(1.0-3.0)MeV"/>
691 * </observation>
692 *
693 * Note that the DRW parameter is optional.
694 ***************************************************************************/
696{
697 // Allocate XML element pointer
698 GXmlElement* par;
699
700 // Handle unbinned observation
701 if (is_unbinned()) {
702
703 // Set EVP parameter
704 par = gammalib::xml_need_par(G_WRITE, xml, "EVP");
706
707 // Set TIM parameter
708 par = gammalib::xml_need_par(G_WRITE, xml, "TIM");
710
711 // Remove all existing OAD parameters
712 for (int i = 0; i < xml.elements("parameter"); ++i) {
713 GXmlElement* element = xml.element("parameter", i);
714 if (element->attribute("name") == "OAD") {
715 xml.remove(i);
716 }
717 }
718
719 // Set OAD parameters
720 for (int i = 0; i < m_oadnames.size(); ++i) {
721 par = static_cast<GXmlElement*>(xml.append(GXmlElement("parameter name=\"OAD\"")));
722 par->attribute("file", gammalib::xml_file_reduce(xml, m_oadnames[i]));
723 }
724
725 // Optionally set HKD parameters
726 for (int i = 0; i < m_hkdnames.size(); ++i) {
727 par = static_cast<GXmlElement*>(xml.append(GXmlElement("parameter name=\"HKD\"")));
728 par->attribute("file", gammalib::xml_file_reduce(xml, m_hkdnames[i]));
729 }
730
731 // Optionally set BVC parameters
732 if (!m_bvcs.is_empty()) {
733 par = gammalib::xml_need_par(G_WRITE, xml, "BVC");
735 }
736
737 } // endif: observation was unbinned
738
739 // ... otherwise handle a binned observation
740 else if (is_binned()) {
741
742 // Set DRE parameter
743 par = gammalib::xml_need_par(G_WRITE, xml, "DRE");
745
746 // Set DRB parameter
747 par = gammalib::xml_need_par(G_WRITE, xml, "DRB");
749
750 // Set DRW parameter
751 if (m_drwname != "") {
752 par = gammalib::xml_need_par(G_WRITE, xml, "DRW");
754 }
755
756 // Set DRG parameter
757 par = gammalib::xml_need_par(G_WRITE, xml, "DRG");
759
760 // Set DRX parameter
761 par = gammalib::xml_need_par(G_WRITE, xml, "DRX");
763
764 // Set IAQ parameter
765 par = gammalib::xml_need_par(G_WRITE, xml, "IAQ");
767
768 // If there is a first Phibar layer selection then write it into XML file
769 if (m_phi_first != -1) {
770 xml.attribute("phi_first", gammalib::str(m_phi_first));
771 }
772
773 // If there is a last Phibar layer selection then write it into XML file
774 if (m_phi_last != -1) {
775 xml.attribute("phi_last", gammalib::str(m_phi_last));
776 }
777
778 // Optionally set response cache parameter
779 if (!m_rspname.is_empty()) {
780
781 // Set cache parameter
782 par = gammalib::xml_need_par(G_WRITE, xml, "RSP");
784
785 // If response cache file does not yet exist then save it now
786 // Note that this code assumes that the cache will never change
787 // once it has been computed. In case that the cache may have
788 // changed, a different file name needs to be choosen
789 if (!m_rspname.exists()) {
791 }
792
793 }
794
795 } // endif: observation was binned
796
797 // Return
798 return;
799}
800
801
802/***********************************************************************//**
803 * @brief Load data for a binned observation
804 *
805 * @param[in] drename Event cube name.
806 * @param[in] drbname Background cube name.
807 * @param[in] drwname Weighting cube name.
808 * @param[in] drgname Geometry cube name.
809 * @param[in] drxname Exposure map name.
810 *
811 * Load event cube from DRE file, background model from DRB file, weigthing
812 * cube from DRW file, geometry factors from DRG file and the exposure map
813 * from the DRX file. All files are mandatory.
814 ***************************************************************************/
816 const GFilename& drbname,
817 const GFilename& drwname,
818 const GFilename& drgname,
819 const GFilename& drxname)
820{
821 // Load DRE
823
824 // Load DRB
826
827 // Load DRW
829
830 // Load DRG
832
833 // Load DRX
835
836 // Return
837 return;
838}
839
840
841/***********************************************************************//**
842 * @brief Load data for an unbinned observation
843 *
844 * @param[in] evpname Event list FITS file name.
845 * @param[in] timname Good Time Intervals FITS file name.
846 * @param[in] oadnames List of Orbit Aspect Data FITS file names.
847 * @param[in] hkdnames List of Housekeeping Data FITS file names.
848 * @param[in] bvcname Solar System Barycentre Data FITS file name.
849 *
850 * Loads the event list, Good Time Interval, Orbit Aspect Data and optionally
851 * Housekeeping data and Solar System Barycentre Data for an unbinned
852 * observation.
853 *
854 * Except of the Housekeeping Data and the Solar System Barycentre Data all
855 * files are mandatory. The Housekeeping Data and the Solar System Barycentre
856 * Data will only be loaded if the file names are not empty.
857 *
858 * The method fixes the deadtime correction factor deadc to 0.965.
859 ***************************************************************************/
861 const GFilename& timname,
862 const std::vector<GFilename>& oadnames,
863 const std::vector<GFilename>& hkdnames,
864 const GFilename& bvcname)
865{
866 // Clear object
867 clear();
868
869 // Extract observation information from event list
870 GFits fits(evpname);
871 read_attributes(fits[1]);
872 fits.close();
873
874 // Allocate event list
875 GCOMEventList *evp = new GCOMEventList(evpname);
876 m_events = evp;
877
878 // Load TIM data
879 m_tim.load(timname);
880
881 // Extract ontime from TIM and compute livetime assuming the value of
882 // 0.965 from Rob van Dijk's thesis, page 62
883 m_ontime = m_tim.gti().ontime();
884 m_deadc = 0.965;
886
887 // Initialise intermediate vector for OADs
888 std::vector<GCOMOads> oads;
889
890 // Load OAD data
891 for (int i = 0; i < oadnames.size(); ++i) {
892
893 // Load OAD file
894 GCOMOads oad(oadnames[i]);
895
896 // Skip file if it is empty
897 if (oad.size() < 1) {
898 continue;
899 }
900
901 // Find index of where to insert OAD file
902 int index = 0;
903 for (; index < oads.size(); ++index) {
904 if (oad[0].tstop() < oads[index][oads[index].size()-1].tstart()) {
905 break;
906 }
907 }
908
909 // Inserts Orbit Aspect Data
910 if (index < oads.size()) {
911 oads.insert(oads.begin()+index, oad);
912 }
913 else {
914 oads.push_back(oad);
915 }
916
917 }
918
919 // Now put all OAD into a single container
920 for (int i = 0; i < oads.size(); ++i) {
921 m_oads.extend(oads[i]);
922 }
923
924 // Optionally load HKD data
925 for (int i = 0; i < hkdnames.size(); ++i) {
926
927 // Load HKD file
928 GCOMHkds hdks(hkdnames[i]);
929
930 // Skip file if it is empty
931 if (hdks.size() < 1) {
932 continue;
933 }
934
935 // Extend housekeeping data
936 m_hkds.extend(hdks);
937
938 }
939
940 // Optionally load BVC data
941 if (bvcname != "") {
942 m_bvcs.load(bvcname);
943 }
944
945 // Store filenames
946 m_evpname = evpname;
947 m_timname = timname;
948 m_oadnames = oadnames;
949 m_hkdnames = hkdnames;
950 m_bvcname = bvcname;
951
952 // Return
953 return;
954}
955
956
957/***********************************************************************//**
958 * @brief Compute DRM cube
959 *
960 * @param[in] models Model container.
961 * @return DRM cube (units of counts)
962 *
963 * @exception GException::invalid_value
964 * Observation does not contain an event cube.
965 *
966 * Computes a COMPTEL DRM cube from the information provided in a model
967 * container. The values of the DRM cube are in units of counts.
968 ***************************************************************************/
970{
971 // Get pointer on COMPTEL event cube
972 const GCOMEventCube* cube = dynamic_cast<const GCOMEventCube*>(m_events);
973 if (cube == NULL) {
974 std::string cls = std::string(typeid(m_events).name());
975 std::string msg = "Events of type \""+cls+"\" is not a COMPTEL event "
976 "cube. Please specify a COMPTEL event cube when "
977 "using this method.";
979 }
980
981 // Create DRM event cube as copy of DRE cube
982 GCOMEventCube drm_cube = *cube;
983
984 // Get vector of model values
985 GVector values = models.eval(*this);
986
987 // Loop over all cube bins
988 for (int i = 0; i < drm_cube.size(); ++i) {
989
990 // Get pointer to cube bin
991 GCOMEventBin* bin = drm_cube[i];
992
993 // Compute model value for cube bin
994 double model = values[i] * bin->size();
995
996 // Store model value in cube bin
997 bin->counts(model);
998
999 } // endfor: looped over DRM cube bins
1000
1001 // Extract DRM
1002 GCOMDri drm = drm_cube.dre();
1003
1004 // Return DRM
1005 return drm;
1006}
1007
1008
1009/***********************************************************************//**
1010 * @brief Compute DRB cube
1011 *
1012 * @param[in] method Background method (PHINOR, BGDLIXA, BGDLIXE or BGDLIXF).
1013 * @param[in] drm DRM cube.
1014 * @param[in] nrunav BGDLIXn: number of bins used for running average.
1015 * @param[in] navgr BGDLIXn: number of bins used for averaging.
1016 * @param[in] nincl BGDLIXn: number of Phibar layers to include.
1017 * @param[in] nexcl BGDLIXn: number of Phibar layers to exclude.
1018 *
1019 * Computes a COMPTEL DRB cube using either the PHINOR or BGDLIX method.
1020 * There are three variants of the BGFLIX method (BGDLIXA, BGDLIXE and
1021 * BGDLIXF). See the protected methods
1022 * compute_drb_phinor(),
1023 * compute_drb_bgdlixa(),
1024 * compute_drb_bgdlixe(), and
1025 * compute_drb_bgdlixf()
1026 * for more information.
1027 ***************************************************************************/
1028void GCOMObservation::compute_drb(const std::string& method,
1029 const GCOMDri& drm,
1030 const int& nrunav,
1031 const int& navgr,
1032 const int& nincl,
1033 const int& nexcl)
1034{
1035 // Branch to relevant method based on specified background method
1036 if (method == "PHINOR") {
1038 }
1039 else if (method == "BGDLIXA") {
1040 compute_drb_bgdlixa(drm, nrunav, navgr, nincl, nexcl);
1041 }
1042 else if (method == "BGDLIXE") {
1043 compute_drb_bgdlixe(drm, nrunav, navgr, nincl, nexcl);
1044 }
1045 else if (method == "BGDLIXF") {
1046 compute_drb_bgdlixf(drm, nrunav, navgr, nincl, nexcl);
1047 }
1048 else {
1049 std::string msg = "Unknown background method \""+method+"\". "
1050 "Specify either \"PHINOR\", \"BGDLIXA\" or "
1051 "\"BGDLIXE\".";
1053 }
1054
1055 // Return
1056 return;
1057}
1058
1059
1060/***********************************************************************//**
1061 * @brief Return gradient step size for a given model parameter
1062 *
1063 * @param[in] par Model parameter
1064 * @return Gradient step size
1065 *
1066 * Returns the step size that is used for numerical gradient computation
1067 * for a given model parameter @p par.
1068 *
1069 * Following a detailed analysis
1070 * (see https://gitlab.in2p3.fr/gammalib/gammalib/-/issues/14)
1071 * the step size is set to 0.002 for all parameters except of position
1072 * angles (PA) which will have a step size of 0.02. At these step sizes
1073 * numerical computation of parameter gradients is no longer perturbed by
1074 * numerical noise.
1075 ***************************************************************************/
1077{
1078 // Set step size
1079 //double step = (par.name() == "PA") ? 0.0002 : 0.0002;
1080 double step = 0.01;
1081
1082 // Return step size
1083 return step;
1084}
1085
1086
1087/***********************************************************************//**
1088 * @brief Print observation information
1089 *
1090 * @param[in] chatter Chattiness.
1091 * @return String containing observation information.
1092 ***************************************************************************/
1093std::string GCOMObservation::print(const GChatter& chatter) const
1094{
1095 // Initialise result string
1096 std::string result;
1097
1098 // Continue only if chatter is not silent
1099 if (chatter != SILENT) {
1100
1101 // Append header
1102 result.append("=== GCOMObservation ===");
1103
1104 // Append information
1105 result.append("\n"+gammalib::parformat("Name")+name());
1106 result.append("\n"+gammalib::parformat("Identifier")+id());
1107 result.append("\n"+gammalib::parformat("Instrument")+instrument());
1108 result.append("\n"+gammalib::parformat("Statistic")+statistic());
1109 result.append("\n"+gammalib::parformat("Ontime"));
1110 result.append(gammalib::str(ontime())+" sec");
1111 result.append("\n"+gammalib::parformat("Livetime"));
1112 result.append(gammalib::str(livetime())+" sec");
1113 result.append("\n"+gammalib::parformat("Deadtime correction"));
1114 result.append(gammalib::str(m_deadc));
1115
1116 // Append Phibar selection
1117 int phi_first = (m_phi_first != -1) ? m_phi_first : 0;
1118 int phi_last = (m_phi_last != -1) ? m_phi_last : m_drg.map().nmaps();
1119 if ((m_phi_first != -1) || (m_phi_last != -1)) {
1120 result.append("\n"+gammalib::parformat("Likelihood Phibar range"));
1121 result.append(gammalib::str(phi_first));
1122 result.append(" - ");
1123 result.append(gammalib::str(phi_last));
1124 }
1125
1126 // Append response (if available)
1127 if (response()->rspname().length() > 0) {
1128 result.append("\n"+response()->print(gammalib::reduce(chatter)));
1129 if (!m_rspname.is_empty()) {
1130 result.append("\n"+gammalib::parformat("Response cache file"));
1131 result.append(m_rspname);
1132 }
1133 }
1134
1135 // Append events
1136 if (m_events != NULL) {
1137 result.append("\n"+m_events->print(gammalib::reduce(chatter)));
1138 }
1139 else {
1140 result.append("\n"+gammalib::parformat("Events")+"undefined");
1141 }
1142
1143 // Append TIM (if available)
1144 if (m_tim.gti().size() > 0) {
1145 result.append("\n"+m_tim.print(gammalib::reduce(chatter)));
1146 }
1147 else {
1148 result.append("\n"+gammalib::parformat("TIM")+"undefined");
1149 }
1150
1151 // Append OADs (if available)
1152 if (!m_oads.is_empty()) {
1153 result.append("\n"+m_oads.print(gammalib::reduce(chatter)));
1154 }
1155 else {
1156 result.append("\n"+gammalib::parformat("OADs")+"undefined");
1157 }
1158
1159 // Append HKDs (if available)
1160 if (!m_hkds.is_empty()) {
1161 result.append("\n"+m_hkds.print(gammalib::reduce(chatter)));
1162 }
1163 else {
1164 result.append("\n"+gammalib::parformat("HKDs")+"undefined");
1165 }
1166
1167 // Append BVCs (if available)
1168 if (!m_bvcs.is_empty()) {
1169 result.append("\n"+m_bvcs.print(gammalib::reduce(chatter)));
1170 }
1171 else {
1172 result.append("\n"+gammalib::parformat("BVCs")+"undefined");
1173 }
1174
1175 } // endif: chatter was not silent
1176
1177 // Return result
1178 return result;
1179}
1180
1181
1182/*==========================================================================
1183 = =
1184 = Private methods =
1185 = =
1186 ==========================================================================*/
1187
1188/***********************************************************************//**
1189 * @brief Initialise class members
1190 ***************************************************************************/
1192{
1193 // Initialise members
1194 m_instrument = "COM";
1195 m_response.clear();
1196 m_obs_id = 0;
1197 m_ontime = 0.0;
1198 m_livetime = 0.0;
1199 m_deadc = 0.0;
1200
1201 // Initialise members for binned observation
1202 m_drename.clear();
1203 m_drbname.clear();
1204 m_drwname.clear();
1205 m_drgname.clear();
1206 m_drxname.clear();
1207 m_rspname.clear();
1208 m_drb.clear();
1209 m_drw.clear();
1210 m_drg.clear();
1211 m_drx.clear();
1212 m_ewidth = 0.0;
1213 m_phi_first = -1;
1214 m_phi_last = -1;
1215
1216 // Initialise members for unbinned observation
1217 m_evpname.clear();
1218 m_timname.clear();
1219 m_oadnames.clear();
1220 m_hkdnames.clear();
1221 m_bvcname.clear();
1222 m_tim.clear();
1223 m_oads.clear();
1224 m_hkds.clear();
1225 m_bvcs.clear();
1226
1227 // Return
1228 return;
1229}
1230
1231
1232/***********************************************************************//**
1233 * @brief Copy class members
1234 *
1235 * @param[in] obs COMPTEL observation.
1236 ***************************************************************************/
1238{
1239 // Copy members
1241 m_response = obs.m_response;
1242 m_obs_id = obs.m_obs_id;
1243 m_ontime = obs.m_ontime;
1244 m_livetime = obs.m_livetime;
1245 m_deadc = obs.m_deadc;
1246
1247 // Copy members for binned observation
1248 m_drename = obs.m_drename;
1249 m_drbname = obs.m_drbname;
1250 m_drwname = obs.m_drwname;
1251 m_drgname = obs.m_drgname;
1252 m_drxname = obs.m_drxname;
1253 m_rspname = obs.m_rspname;
1254 m_drb = obs.m_drb;
1255 m_drw = obs.m_drw;
1256 m_drg = obs.m_drg;
1257 m_drx = obs.m_drx;
1258 m_ewidth = obs.m_ewidth;
1260 m_phi_last = obs.m_phi_last;
1261
1262 // Copy members for unbinned observation
1263 m_evpname = obs.m_evpname;
1264 m_timname = obs.m_timname;
1265 m_oadnames = obs.m_oadnames;
1266 m_hkdnames = obs.m_hkdnames;
1267 m_bvcname = obs.m_bvcname;
1268 m_tim = obs.m_tim;
1269 m_oads = obs.m_oads;
1270 m_hkds = obs.m_hkds;
1271 m_bvcs = obs.m_bvcs;
1272
1273 // Return
1274 return;
1275}
1276
1277
1278/***********************************************************************//**
1279 * @brief Delete class members
1280 ***************************************************************************/
1282{
1283 // Return
1284 return;
1285}
1286
1287
1288/***********************************************************************//**
1289 * @brief Load event cube data from DRE file
1290 *
1291 * @param[in] drename DRE filename.
1292 *
1293 * Loads the event cube from a DRE file.
1294 *
1295 * The ontime is extracted from the Good Time Intervals. The deadtime
1296 * correction factor deadc is fixed to 0.965. The livetime is computed by
1297 * multiplying the deadtime correction by the ontime, i.e.
1298 * LIVETIME = ONTIME * DEADC.
1299 ***************************************************************************/
1301{
1302 // Delete any existing event container (do not call clear() as we do not
1303 // want to delete the response function)
1304 if (m_events != NULL) delete m_events;
1305 m_events = NULL;
1306
1307 // Allocate event cube
1308 m_events = new GCOMEventCube;
1309
1310 // Open FITS file
1311 GFits fits(drename);
1312
1313 // Read event cube
1314 m_events->read(fits);
1315
1316 // Extract ontime
1317 m_ontime = m_events->gti().ontime();
1318
1319 // Set fixed deadtime fraction (see Rob van Dijk's thesis, page 62)
1320 m_deadc = 0.965;
1321
1322 // Compute livetime
1324
1325 // Compute energy width
1326 m_ewidth = m_events->emax().MeV() - m_events->emin().MeV();
1327
1328 // Read additional observation attributes from primary extension
1329 read_attributes(fits[0]);
1330
1331 // Close FITS file
1332 fits.close();
1333
1334 // Store event filename
1336
1337 // Return
1338 return;
1339}
1340
1341
1342/***********************************************************************//**
1343 * @brief Load background model from DRB file
1344 *
1345 * @param[in] drbname DRB filename.
1346 *
1347 * @exception GException::invalid_value
1348 * DRB data space incompatible with DRE data space.
1349 *
1350 * Load the background model from the primary image of the specified FITS
1351 * file. Since a DRB file is optional the method does nothing if the DRB
1352 * filename is empty.
1353 ***************************************************************************/
1355{
1356 // Continue only if filename is not empty
1357 if (!drbname.is_empty()) {
1358
1359 // Open FITS file
1360 GFits fits(drbname);
1361
1362 // Get image
1363 const GFitsImage& image = *fits.image("Primary");
1364
1365 // Read background model
1366 m_drb.read(image);
1367
1368 // Correct WCS projection (HEASARC data format kludge)
1369 gammalib::com_wcs_mer2car(const_cast<GSkyMap&>(m_drb.map()));
1370
1371 // Close FITS file
1372 fits.close();
1373
1374 // Check map dimensions
1375 if (!check_dri(m_drb)) {
1376 std::string msg = "DRB data cube \""+drbname+"\" incompatible with "
1377 "DRE data cube \""+m_drename+"\".";
1379 }
1380
1381 // Store DRB filename
1383
1384 } // endif: DRB filename was empty
1385
1386 // Return
1387 return;
1388}
1389
1390
1391/***********************************************************************//**
1392 * @brief Load weighting cube from DRW file
1393 *
1394 * @param[in] drwname DRW filename.
1395 *
1396 * @exception GException::invalid_value
1397 * DRW data space incompatible with DRE data space.
1398 *
1399 * Load the weighting cube from the primary image of the specified FITS file.
1400 ***************************************************************************/
1402{
1403 // Continue only if filename is not empty
1404 if (!drwname.is_empty()) {
1405
1406 // Open FITS file
1407 GFits fits(drwname);
1408
1409 // Get image
1410 const GFitsImage& image = *fits.image("Primary");
1411
1412 // Read weighting cube
1413 m_drw.read(image);
1414
1415 // Close FITS file
1416 fits.close();
1417
1418 // Check map dimensions
1419 if (!check_dri(m_drw)) {
1420 std::string msg = "DRW data cube \""+drwname+"\" incompatible with "
1421 "DRE data cube \""+m_drename+"\".";
1423 }
1424
1425 // Store DRW filename
1427
1428 } // endif: DRW filename was empty
1429
1430 // Return
1431 return;
1432}
1433
1434
1435/***********************************************************************//**
1436 * @brief Load geometry factors from DRG file
1437 *
1438 * @param[in] drgname DRG filename.
1439 *
1440 * @exception GException::invalid_value
1441 * DRG data space incompatible with DRE data space.
1442 *
1443 * Load the geometry factors from the primary image of the specified FITS
1444 * file.
1445 ***************************************************************************/
1447{
1448 // Open FITS file
1449 GFits fits(drgname);
1450
1451 // Get image
1452 const GFitsImage& image = *fits.image("Primary");
1453
1454 // Read geometry factors
1455 m_drg.read(image);
1456
1457 // Correct WCS projection (HEASARC data format kludge)
1458 gammalib::com_wcs_mer2car(const_cast<GSkyMap&>(m_drg.map()));
1459
1460 // Close FITS file
1461 fits.close();
1462
1463 // Check map dimensions
1464 if (!check_dri(m_drg)) {
1465 std::string msg = "DRG data cube \""+drgname+"\" incompatible with "
1466 "DRE data cube \""+m_drename+"\".";
1468 }
1469
1470 // Store DRG filename
1472
1473 // Return
1474 return;
1475}
1476
1477
1478/***********************************************************************//**
1479 * @brief Load exposure from DRX file
1480 *
1481 * @param[in] drxname DRX filename.
1482 *
1483 * Load the exposure map from the primary image of the specified FITS file.
1484 ***************************************************************************/
1486{
1487 // Open FITS file
1488 GFits fits(drxname);
1489
1490 // Get HDU
1491 const GFitsImage& image = *fits.image("Primary");
1492
1493 // Read exposure map
1494 m_drx.read(image);
1495
1496 // Correct WCS projection (HEASARC data format kludge)
1497 gammalib::com_wcs_mer2car(const_cast<GSkyMap&>(m_drx.map()));
1498
1499 // Close FITS file
1500 fits.close();
1501
1502 // Store DRX filename
1504
1505 // Return
1506 return;
1507}
1508
1509
1510/***********************************************************************//**
1511 * @brief Check if DRI is compatible with event cube
1512 *
1513 * @param[in] dri DRI.
1514 * @return True if DRI is compatible, false otherwise.
1515 *
1516 * Compares the dimension and the WCS definition of a DRI to that of the
1517 * event cube. If both are identical, true is returned, false otherwise.
1518 ***************************************************************************/
1520{
1521 // Get references to event cube map and DRI map
1522 const GSkyMap& ref = dynamic_cast<GCOMEventCube*>(m_events)->dre().map();
1523 const GSkyMap& map = dri.map();
1524
1525 // Compare dimensions
1526 bool same_dimension = ((map.nx() == ref.nx()) &&
1527 (map.ny() == ref.ny()) &&
1528 (map.nmaps() == ref.nmaps()));
1529
1530 // Compare projections
1531 bool same_projection = false;
1532 const GSkyProjection* proj_ref = ref.projection();
1533 const GSkyProjection* proj_map = map.projection();
1534 if ((proj_ref == NULL) && (proj_map == NULL)) {
1535 same_projection = true;
1536 }
1537 else if ((proj_ref != NULL) && (proj_map != NULL)) {
1538 same_projection = (*proj_map == *proj_ref);
1539 }
1540
1541 // Return
1542 return (same_dimension && same_projection);
1543}
1544
1545
1546/***********************************************************************//**
1547 * @brief Read observation attributes
1548 *
1549 * @param[in] hdu FITS HDU pointer
1550 *
1551 * Reads optional attributes are
1552 *
1553 * OBS_ID - Observation identifier
1554 * OBJECT - Object
1555 *
1556 * Nothing is done if the HDU pointer is NULL.
1557 ***************************************************************************/
1559{
1560 // Continue only if HDU is valid
1561 if (hdu != NULL) {
1562
1563 // Read observation information
1564 m_obs_id = (hdu->has_card("OBS_ID")) ? hdu->real("OBS_ID") : 0;
1565 m_name = (hdu->has_card("OBJECT")) ? hdu->string("OBJECT") : "unknown";
1566
1567 } // endif: HDU was valid
1568
1569 // Return
1570 return;
1571}
1572
1573
1574/***********************************************************************//**
1575 * @brief Write observation attributes
1576 *
1577 * @param[in] hdu FITS HDU pointer
1578 *
1579 * Nothing is done if the HDU pointer is NULL.
1580 *
1581 * @todo Implement method.
1582 ***************************************************************************/
1584{
1585 // Continue only if HDU is valid
1586 if (hdu != NULL) {
1587
1588 } // endif: HDU was valid
1589
1590 // Return
1591 return;
1592}
1593
1594
1595/***********************************************************************//**
1596 * @brief Compute DRB cube using PHINOR method
1597 *
1598 * @param[in] drm DRM cube.
1599 *
1600 * @exception GException::invalid_value
1601 * Observation does not contain an event cube
1602 * @exception GException::invalid_argument
1603 * DRM cube is incompatible with DRE
1604 ***************************************************************************/
1606{
1607 // Extract COMPTEL event cube
1608 const GCOMEventCube* cube = dynamic_cast<const GCOMEventCube*>(this->events());
1609 if (cube == NULL) {
1610 std::string msg = "Observation \""+this->name()+"\" ("+this->id()+") "
1611 "does not contain a COMPTEL event cube. Please "
1612 "specify a COMPTEL observation containing and event "
1613 "cube.";
1615 }
1616
1617 // Check DRM
1618 if (!check_dri(drm)) {
1619 std::string msg = "Specified DRM cube is incompatible with DRE. Please "
1620 "specify a DRM with a data-space definition that is "
1621 "identical to that of the DRE.";
1623 }
1624
1625 // Initialise DRB by cloning DRG
1626 m_drb = m_drg;
1627
1628 // Get DRI sky maps
1629 const GSkyMap& map_dre = cube->dre().map();
1630 const GSkyMap& map_drm = drm.map();
1631 GSkyMap map_drg = get_weighted_drg_map();
1632 GSkyMap& map_drb = const_cast<GSkyMap&>(m_drb.map());
1633
1634 // Get data space dimensions
1635 int npix = m_drg.map().npix();
1636 int nphibar = m_drg.nphibar();
1637
1638 // Phibar normalise DRB
1639 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1640 double sum_dre = 0.0;
1641 double sum_drm = 0.0;
1642 double sum_drg = 0.0;
1643 for (int ipix = 0; ipix < npix; ++ipix) {
1644 sum_dre += map_dre(ipix, iphibar);
1645 sum_drm += map_drm(ipix, iphibar);
1646 sum_drg += map_drg(ipix, iphibar);
1647 }
1648 if (sum_drg > 0.0) {
1649 double norm = (sum_dre - sum_drm) / sum_drg;
1650 for (int ipix = 0; ipix < npix; ++ipix) {
1651 map_drb(ipix, iphibar) = map_drg(ipix, iphibar) * norm;
1652 }
1653 }
1654 else {
1655 for (int ipix = 0; ipix < npix; ++ipix) {
1656 map_drb(ipix, iphibar) = 0.0;
1657 }
1658 }
1659 }
1660
1661 // Make sure that DRB is non-negative
1662 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1663 for (int ipix = 0; ipix < npix; ++ipix) {
1664 if (map_drb(ipix, iphibar) < 0.0) {
1665 map_drb(ipix, iphibar) = 0.0;
1666 }
1667 }
1668 }
1669
1670 // Return
1671 return;
1672}
1673
1674
1675/***********************************************************************//**
1676 * @brief Compute DRB cube using BGDLIXA method
1677 *
1678 * @param[in] drm DRM cube.
1679 * @param[in] nrunav Number of bins used for running average.
1680 * @param[in] navgr Number of bins used for averaging.
1681 * @param[in] nincl Number of Phibar layers to include.
1682 * @param[in] nexcl Number of Phibar layers to exclude.
1683 *
1684 * @exception GException::invalid_value
1685 * Observation does not contain an event cube
1686 * @exception GException::invalid_argument
1687 * DRM cube is incompatible with DRE
1688 *
1689 * Computes a DRB cube using the BGDLIXA method that is documented in Rob
1690 * van Dijk's PhD thesis. The revelant equations from the thesis that are
1691 * implemented here are 3.12, 3.12 and 3.14.
1692 ***************************************************************************/
1694 const int& nrunav,
1695 const int& navgr,
1696 const int& nincl,
1697 const int& nexcl)
1698{
1699 // Extract COMPTEL event cube
1700 const GCOMEventCube* cube = dynamic_cast<const GCOMEventCube*>(this->events());
1701 if (cube == NULL) {
1702 std::string msg = "Observation \""+this->name()+"\" ("+this->id()+") "
1703 "does not contain a COMPTEL event cube. Please "
1704 "specify a COMPTEL observation containing and event "
1705 "cube.";
1707 }
1708
1709 // Check DRM
1710 if (!check_dri(drm)) {
1711 std::string msg = "Specified DRM cube is incompatible with DRE. Please "
1712 "specify a DRM with a data-space definition that is "
1713 "identical to that of the DRE.";
1715 }
1716
1717 // Initialise DRB and scratch DRI by cloning DRG
1718 m_drb = m_drg;
1719 GCOMDri dri = m_drg;
1720
1721 // Get references to relevant sky maps
1722 const GSkyMap& map_dre = cube->dre().map();
1723 const GSkyMap& map_drm = drm.map();
1724 GSkyMap map_drg = get_weighted_drg_map();
1725 GSkyMap& map_drb = const_cast<GSkyMap&>(m_drb.map());
1726 GSkyMap& map_dri = const_cast<GSkyMap&>(dri.map());
1727
1728 // Get data space dimensions
1729 int nchi = m_drg.nchi();
1730 int npsi = m_drg.npsi();
1731 int nphibar = m_drg.nphibar();
1732 int npix = nchi * npsi;
1733
1734 // Precompute half running average lengths
1735 int navgr2 = int(navgr/2);
1736
1737 // Initialise DRB and scratch DRI
1738 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1739 for (int ipix = 0; ipix < npix; ++ipix) {
1740 map_drb(ipix, iphibar) = 0.0;
1741 map_dri(ipix, iphibar) = 0.0;
1742 }
1743 }
1744
1745 // Phibar normalise DRB (Equation 3.12 in Rob van Dijk's PhD thesis).
1746 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1747 double sum_dre = 0.0;
1748 double sum_drm = 0.0;
1749 double sum_drg = 0.0;
1750 for (int ipix = 0; ipix < npix; ++ipix) {
1751 sum_dre += map_dre(ipix, iphibar);
1752 sum_drm += map_drm(ipix, iphibar);
1753 sum_drg += map_drg(ipix, iphibar);
1754 }
1755 if (sum_drg > 0.0) {
1756 double norm = (sum_dre - sum_drm) / sum_drg;
1757 for (int ipix = 0; ipix < npix; ++ipix) {
1758 map_dri(ipix, iphibar) = map_drg(ipix, iphibar) * norm;
1759 }
1760 }
1761 }
1762
1763 // Do 3D running average of DRE and Phibar normalised DRG (Equation 3.13
1764 // in Rob van Dijk's PhD thesis). The result is a Phibar normalised DRG
1765 // that is normalised over the 3D region to the DRE. The 3D region is all
1766 // Phibar layers and [-nrunav,+nrunav] Chi/Psi pixels around the pixel of
1767 // consideration.
1768 if (nrunav >= 1) {
1769
1770 // Loop over Chi pixels
1771 for (int ichi = 0; ichi < nchi; ++ichi) {
1772
1773 // Compute running average window in Chi
1774 int kchi_min = ichi - nrunav;
1775 int kchi_max = ichi + nrunav;
1776 if (kchi_min < 0) {
1777 kchi_min = 0;
1778 }
1779 if (kchi_max >= nchi) {
1780 kchi_max = nchi - 1;
1781 }
1782
1783 // Loop over Psi pixels
1784 for (int ipsi = 0; ipsi < npsi; ++ipsi) {
1785
1786 // Compute running average window in Psi
1787 int kpsi_min = ipsi - nrunav;
1788 int kpsi_max = ipsi + nrunav;
1789 if (kpsi_min < 0) {
1790 kpsi_min = 0;
1791 }
1792 if (kpsi_max >= npsi) {
1793 kpsi_max = npsi - 1;
1794 }
1795
1796 // Initialise sums
1797 double sum_dre = 0.0;
1798 double sum_drm = 0.0;
1799 double sum_dri = 0.0;
1800
1801 // Compute running average
1802 for (int kchi = kchi_min; kchi <= kchi_max; ++kchi) {
1803 for (int kpsi = kpsi_min; kpsi <= kpsi_max; ++kpsi) {
1804 int kpix = kchi + kpsi * nchi;
1805 for (int kphibar = 0; kphibar < nphibar; ++kphibar) {
1806 if (map_drg(kpix, kphibar) != 0.0) {
1807 sum_dre += map_dre(kpix, kphibar);
1808 sum_drm += map_drm(kpix, kphibar);
1809 sum_dri += map_dri(kpix, kphibar);
1810 }
1811 }
1812 }
1813 }
1814
1815 // Renormalise scratch array
1816 if (sum_dri != 0.0) {
1817 int ipix = ichi + ipsi * nchi;
1818 double norm = (sum_dre - sum_drm) / sum_dri;
1819 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1820 map_dri(ipix, iphibar) *= norm;
1821 }
1822 }
1823
1824 } // endfor: looped over Phi
1825
1826 } // endfor: looped over Chi
1827
1828 } // endif: running averaging was requested
1829
1830 // First part of Equation (3.14) in Rob van Dijk's PhD thesis.
1831 // (DRB = B^0C_L / sum B^0C_L). The DRB is pre-computed by adjusting the
1832 // scratch DRI over nincl Phibar layers.
1833 int ksel1 = 0;
1834 int kex1 = 0;
1835 int kex2 = 0;
1836 int ksel2 = 0;
1837 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1838
1839 // Get Phibar index range for sums
1840 get_bgdlixa_phibar_indices(iphibar, nincl, nexcl,
1841 &ksel1, &kex1, &kex2, &ksel2);
1842
1843 // Loop over Chi/Psi pixels
1844 for (int ipix = 0; ipix < npix; ++ipix) {
1845
1846 // Initialise DRB value
1847 map_drb(ipix, iphibar) = 0.0;
1848
1849 // Continue only if scratch DRI is non-zero
1850 if (map_dri(ipix, iphibar) != 0.0) {
1851
1852 // Initialise sum
1853 double sum_dri = 0.0;
1854
1855 // Take sum over [ksel1, kex1]
1856 if (kex1 >= 0) {
1857 for (int kphibar = ksel1; kphibar <= kex1; ++kphibar) {
1858 sum_dri += map_dri(ipix, kphibar);
1859 }
1860 }
1861
1862 // Take sum over [kxe2, ksel2]
1863 if (kex2 < nphibar) {
1864 for (int kphibar = kex2; kphibar <= ksel2; ++kphibar) {
1865 sum_dri += map_dri(ipix, kphibar);
1866 }
1867 }
1868
1869 // If sum is not zero then set DRB
1870 if (sum_dri != 0.0) {
1871 map_drb(ipix, iphibar) = map_dri(ipix, iphibar) / sum_dri;
1872 }
1873
1874 } // endif: scratch DRI was non-zero
1875
1876 } // endfor: looped over Chi/Psi pixels
1877
1878 } // endfor: looped over Phibar
1879
1880 // Second part of Equation (3.14) in Rob van Dijk's PhD thesis that
1881 // corresponds to G * [E / G]^s that will be stored in scratch DRI.
1882 //
1883 // NOTES:
1884 // - we replaced DRE by DRE-DRM in the nominator of the running
1885 // average since and source component should of course be
1886 // subtracted
1887 // - we implemented an alternative running average computation where
1888 // the ratio between the DRE and DRG sums is taken. This avoids
1889 // the divergence of the ratio at the edge of the DRG.
1890 for (int ichi = 0; ichi < nchi; ++ichi) {
1891
1892 // Compute running average window in Chi
1893 int kchi_min = ichi - navgr2;
1894 int kchi_max = ichi + navgr2;
1895 if (kchi_min < 0) {
1896 kchi_min = 0;
1897 }
1898 if (kchi_max >= nchi) {
1899 kchi_max = nchi - 1;
1900 }
1901
1902 // Loop over Psi pixels
1903 for (int ipsi = 0; ipsi < npsi; ++ipsi) {
1904
1905 // Compute running average window in Psi
1906 int kpsi_min = ipsi - navgr2;
1907 int kpsi_max = ipsi + navgr2;
1908 if (kpsi_min < 0) {
1909 kpsi_min = 0;
1910 }
1911 if (kpsi_max >= npsi) {
1912 kpsi_max = npsi - 1;
1913 }
1914
1915 // Loop over Phibar layers
1916 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1917
1918 // Initialise sums
1919 double sum_dre = 0.0;
1920 double sum_drm = 0.0;
1921 double sum_drg = 0.0;
1922
1923 // Compute running average
1924 for (int kchi = kchi_min; kchi <= kchi_max; ++kchi) {
1925 for (int kpsi = kpsi_min; kpsi <= kpsi_max; ++kpsi) {
1926 int kpix = kchi + kpsi * nchi;
1927 sum_dre += map_dre(kpix, iphibar);
1928 sum_drm += map_drm(kpix, iphibar);
1929 sum_drg += map_drg(kpix, iphibar);
1930 }
1931 }
1932
1933 // Multiply average by DRG and store it in scratch DRI
1934 int ipix = ichi + ipsi * nchi;
1935 if (sum_drg > 0.0) {
1936 double norm = (sum_dre - sum_drm) / sum_drg;
1937 map_dri(ipix, iphibar) = map_drg(ipix, iphibar) * norm;
1938 }
1939 else {
1940 map_dri(ipix, iphibar) = 0.0;
1941 }
1942
1943 } // endfor: looped over Phibar layers
1944
1945 } // endfor: looped over Psi pixels
1946
1947 } // endfor: looped over Chi pixels
1948
1949 // Third part of Equation (3.14) in Rob van Dijk's PhD thesis that sums
1950 // G * [E / G]^s over a subset of Phibar layers (the first parenthesis)
1951 // and multplies with B^0C_L / sum B^0C_L
1952 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1953
1954 // Get Phibar index range for sums
1955 get_bgdlixa_phibar_indices(iphibar, nincl, nexcl,
1956 &ksel1, &kex1, &kex2, &ksel2);
1957
1958 // Loop over Chi/Psi pixels
1959 for (int ipix = 0; ipix < npix; ++ipix) {
1960
1961 // If DRB is not empty then correct it
1962 if (map_drb(ipix, iphibar) != 0.0) {
1963
1964 // Initialise DRI sum
1965 double sum_dri = 0.0;
1966
1967 // Take sum over [ksel1, kex1]
1968 if (kex1 >= 0) {
1969 for (int kphibar = ksel1; kphibar <= kex1; ++kphibar) {
1970 sum_dri += map_dri(ipix, kphibar);
1971 }
1972 }
1973
1974 // Take sum over [kxe2, ksel2]
1975 if (kex2 < nphibar) {
1976 for (int kphibar = kex2; kphibar <= ksel2; ++kphibar) {
1977 sum_dri += map_dri(ipix, kphibar);
1978 }
1979 }
1980
1981 // Correct DRB
1982 map_drb(ipix, iphibar) *= sum_dri;
1983
1984 } // endif: DRB was not empty
1985
1986 } // endfor: looped over Chi/Psi pixels
1987
1988 } // endfor: looped over Phibar
1989
1990 // Phibar normalise DRB
1991 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
1992 double sum_dre = 0.0;
1993 double sum_drm = 0.0;
1994 double sum_drb = 0.0;
1995 for (int ipix = 0; ipix < npix; ++ipix) {
1996 sum_dre += map_dre(ipix, iphibar);
1997 sum_drm += map_drm(ipix, iphibar);
1998 sum_drb += map_drb(ipix, iphibar);
1999 }
2000 if (sum_drb > 0.0) {
2001 double norm = (sum_dre - sum_drm) / sum_drb;
2002 for (int ipix = 0; ipix < npix; ++ipix) {
2003 map_drb(ipix, iphibar) *= norm;
2004 }
2005 }
2006 else {
2007 for (int ipix = 0; ipix < npix; ++ipix) {
2008 map_drb(ipix, iphibar) = 0.0;
2009 }
2010 }
2011 }
2012
2013 // Make sure that DRB is non-negative
2014 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2015 for (int ipix = 0; ipix < npix; ++ipix) {
2016 if (map_drb(ipix, iphibar) < 0.0) {
2017 map_drb(ipix, iphibar) = 0.0;
2018 }
2019 }
2020 }
2021
2022 // Return
2023 return;
2024}
2025
2026
2027/***********************************************************************//**
2028 * @brief Compute DRB cube using BGDLIXE method
2029 *
2030 * @param[in] drm DRM cube.
2031 * @param[in] nrunav Number of bins used for running average.
2032 * @param[in] navgr Number of bins used for averaging.
2033 * @param[in] nincl Number of Phibar layers to include.
2034 * @param[in] nexcl Number of Phibar layers to exclude.
2035 *
2036 * @exception GException::invalid_value
2037 * Observation does not contain an event cube
2038 * @exception GException::invalid_argument
2039 * DRM cube is incompatible with DRE
2040 *
2041 * Computes a DRB cube using the BGDLIXE method. This method differs from
2042 * the BGDLIXA method in the last step.
2043 ***************************************************************************/
2045 const int& nrunav,
2046 const int& navgr,
2047 const int& nincl,
2048 const int& nexcl)
2049{
2050 // Extract COMPTEL event cube
2051 const GCOMEventCube* cube = dynamic_cast<const GCOMEventCube*>(this->events());
2052 if (cube == NULL) {
2053 std::string msg = "Observation \""+this->name()+"\" ("+this->id()+") "
2054 "does not contain a COMPTEL event cube. Please "
2055 "specify a COMPTEL observation containing and event "
2056 "cube.";
2058 }
2059
2060 // Check DRM
2061 if (!check_dri(drm)) {
2062 std::string msg = "Specified DRM cube is incompatible with DRE. Please "
2063 "specify a DRM with a data-space definition that is "
2064 "identical to that of the DRE.";
2066 }
2067
2068 // Initialise DRB and scratch DRI by cloning DRG
2069 m_drb = m_drg;
2070 GCOMDri dri = m_drg;
2071
2072 // Get references to relevant sky maps
2073 const GSkyMap& map_dre = cube->dre().map();
2074 const GSkyMap& map_drm = drm.map();
2075 GSkyMap map_drg = get_weighted_drg_map();
2076 GSkyMap& map_drb = const_cast<GSkyMap&>(m_drb.map());
2077 GSkyMap& map_dri = const_cast<GSkyMap&>(dri.map());
2078
2079 // Get data space dimensions
2080 int nchi = m_drg.nchi();
2081 int npsi = m_drg.npsi();
2082 int nphibar = m_drg.nphibar();
2083 int npix = nchi * npsi;
2084
2085 // Precompute half running average lengths
2086 int navgr2 = int(navgr/2);
2087
2088 // Initialise DRB and scratch DRI
2089 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2090 for (int ipix = 0; ipix < npix; ++ipix) {
2091 map_drb(ipix, iphibar) = 0.0;
2092 map_dri(ipix, iphibar) = 0.0;
2093 }
2094 }
2095
2096 // Phibar normalise DRG (Equation 3.12 in Rob van Dijk's PhD thesis).
2097 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2098 double sum_dre = 0.0;
2099 double sum_drm = 0.0;
2100 double sum_drg = 0.0;
2101 for (int ipix = 0; ipix < npix; ++ipix) {
2102 sum_dre += map_dre(ipix, iphibar);
2103 sum_drm += map_drm(ipix, iphibar);
2104 sum_drg += map_drg(ipix, iphibar);
2105 }
2106 if (sum_drg > 0.0) {
2107 double norm = (sum_dre - sum_drm) / sum_drg;
2108 for (int ipix = 0; ipix < npix; ++ipix) {
2109 map_dri(ipix, iphibar) = map_drg(ipix, iphibar) * norm;
2110 }
2111 }
2112 }
2113
2114 // Fit Phibar normalised DRG to DRE-DRM
2115 for (int ichi = 0; ichi < nchi; ++ichi) {
2116
2117 // Compute running average window in Chi
2118 int kchi_min = ichi - navgr2;
2119 int kchi_max = ichi + navgr2;
2120 if (kchi_min < 0) {
2121 kchi_min = 0;
2122 }
2123 if (kchi_max >= nchi) {
2124 kchi_max = nchi - 1;
2125 }
2126
2127 // Loop over Psi pixels
2128 for (int ipsi = 0; ipsi < npsi; ++ipsi) {
2129
2130 // Compute running average window in Psi
2131 int kpsi_min = ipsi - navgr2;
2132 int kpsi_max = ipsi + navgr2;
2133 if (kpsi_min < 0) {
2134 kpsi_min = 0;
2135 }
2136 if (kpsi_max >= npsi) {
2137 kpsi_max = npsi - 1;
2138 }
2139
2140 // Loop over Phibar layers
2141 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2142
2143 // Get Phibar index range for sums
2144 int ksel1 = 0;
2145 int kex1 = 0;
2146 int kex2 = 0;
2147 int ksel2 = 0;
2148 get_bgdlixa_phibar_indices(iphibar, nincl, nexcl,
2149 &ksel1, &kex1, &kex2, &ksel2);
2150
2151 // Initialise sums
2152 double sum_dre = 0.0;
2153 double sum_drm = 0.0;
2154 double sum_dri = 0.0;
2155
2156 // Compute running average
2157 for (int kchi = kchi_min; kchi <= kchi_max; ++kchi) {
2158 for (int kpsi = kpsi_min; kpsi <= kpsi_max; ++kpsi) {
2159
2160 // Get index
2161 int kpix = kchi + kpsi * nchi;
2162
2163 // Take sum over [ksel1, kex1]
2164 if (kex1 >= 0) {
2165 for (int kphibar = ksel1; kphibar <= kex1; ++kphibar) {
2166 sum_dre += map_dre(kpix, kphibar);
2167 sum_drm += map_drm(kpix, kphibar);
2168 sum_dri += map_dri(kpix, kphibar);
2169 }
2170 }
2171
2172 // Take sum over [kxe2, ksel2]
2173 if (kex2 < nphibar) {
2174 for (int kphibar = kex2; kphibar <= ksel2; ++kphibar) {
2175 sum_dre += map_dre(kpix, kphibar);
2176 sum_drm += map_drm(kpix, kphibar);
2177 sum_dri += map_dri(kpix, kphibar);
2178 }
2179 }
2180
2181 } // endfor: looped over kpsi
2182 } // endfor: looped over kchi
2183
2184 // Renormalize DRI locally to DRE-DRM
2185 int ipix = ichi + ipsi * nchi;
2186 if (sum_dri > 0.0) {
2187 double norm = (sum_dre - sum_drm) / sum_dri;
2188 map_drb(ipix, iphibar) = map_dri(ipix, iphibar) * norm;
2189 }
2190 else {
2191 map_drb(ipix, iphibar) = 0.0;
2192 }
2193
2194 } // endfor: looped over Phibar layers
2195
2196 } // endfor: looped over Psi pixels
2197
2198 } // endfor: looped over Chi pixels
2199
2200 // Phibar normalise DRB
2201 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2202 double sum_dre = 0.0;
2203 double sum_drm = 0.0;
2204 double sum_drb = 0.0;
2205 for (int ipix = 0; ipix < npix; ++ipix) {
2206 sum_dre += map_dre(ipix, iphibar);
2207 sum_drm += map_drm(ipix, iphibar);
2208 sum_drb += map_drb(ipix, iphibar);
2209 }
2210 if (sum_drb > 0.0) {
2211 double norm = (sum_dre - sum_drm) / sum_drb;
2212 for (int ipix = 0; ipix < npix; ++ipix) {
2213 map_drb(ipix, iphibar) *= norm;
2214 }
2215 }
2216 else {
2217 for (int ipix = 0; ipix < npix; ++ipix) {
2218 map_drb(ipix, iphibar) = 0.0;
2219 }
2220 }
2221 }
2222
2223 // Make sure that DRB is non-negative
2224 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2225 for (int ipix = 0; ipix < npix; ++ipix) {
2226 if (map_drb(ipix, iphibar) < 0.0) {
2227 map_drb(ipix, iphibar) = 0.0;
2228 }
2229 }
2230 }
2231
2232 // Return
2233 return;
2234}
2235
2236
2237/***********************************************************************//**
2238 * @brief Compute DRB cube using BGDLIXF method
2239 *
2240 * @param[in] drm DRM cube.
2241 * @param[in] nrunav Number of bins used for running average.
2242 * @param[in] navgr Number of bins used for averaging.
2243 * @param[in] nincl Number of Phibar layers to include.
2244 * @param[in] nexcl Number of Phibar layers to exclude.
2245 *
2246 * @exception GException::invalid_value
2247 * Observation does not contain an event cube
2248 * @exception GException::invalid_argument
2249 * DRM cube is incompatible with DRE
2250 *
2251 * Computes a DRB cube using the BGDLIXF method. This method differs from
2252 * the BGDLIXE method in the DRW instead of the DRG is used for background
2253 * model computation.
2254 ***************************************************************************/
2256 const int& nrunav,
2257 const int& navgr,
2258 const int& nincl,
2259 const int& nexcl)
2260{
2261 // Extract COMPTEL event cube
2262 const GCOMEventCube* cube = dynamic_cast<const GCOMEventCube*>(this->events());
2263 if (cube == NULL) {
2264 std::string msg = "Observation \""+this->name()+"\" ("+this->id()+") "
2265 "does not contain a COMPTEL event cube. Please "
2266 "specify a COMPTEL observation containing and event "
2267 "cube.";
2269 }
2270
2271 // Check DRM
2272 if (!check_dri(drm)) {
2273 std::string msg = "Specified DRM cube is incompatible with DRE. Please "
2274 "specify a DRM with a data-space definition that is "
2275 "identical to that of the DRE.";
2277 }
2278
2279 // Initialise DRB and scratch DRI by cloning DRW
2280 m_drb = m_drw;
2281 GCOMDri dri = m_drw;
2282
2283 // Get references to relevant sky maps
2284 const GSkyMap& map_dre = cube->dre().map();
2285 const GSkyMap& map_drm = drm.map();
2286 const GSkyMap& map_drw = m_drw.map();
2287 GSkyMap& map_drb = const_cast<GSkyMap&>(m_drb.map());
2288 GSkyMap& map_dri = const_cast<GSkyMap&>(dri.map());
2289
2290 // Get data space dimensions
2291 int nchi = m_drw.nchi();
2292 int npsi = m_drw.npsi();
2293 int nphibar = m_drw.nphibar();
2294 int npix = nchi * npsi;
2295
2296 // Precompute half running average lengths
2297 int navgr2 = int(navgr/2);
2298
2299 // Initialise DRB and scratch DRI
2300 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2301 for (int ipix = 0; ipix < npix; ++ipix) {
2302 map_drb(ipix, iphibar) = 0.0;
2303 map_dri(ipix, iphibar) = 0.0;
2304 }
2305 }
2306
2307 // Phibar normalise DRW
2308 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2309 double sum_dre = 0.0;
2310 double sum_drm = 0.0;
2311 double sum_drw = 0.0;
2312 for (int ipix = 0; ipix < npix; ++ipix) {
2313 sum_dre += map_dre(ipix, iphibar);
2314 sum_drm += map_drm(ipix, iphibar);
2315 sum_drw += map_drw(ipix, iphibar);
2316 }
2317 if (sum_drw > 0.0) {
2318 double norm = (sum_dre - sum_drm) / sum_drw;
2319 for (int ipix = 0; ipix < npix; ++ipix) {
2320 map_dri(ipix, iphibar) = map_drw(ipix, iphibar) * norm;
2321 }
2322 }
2323 }
2324
2325 // Fit Phibar normalised DRW to DRE-DRM
2326 for (int ichi = 0; ichi < nchi; ++ichi) {
2327
2328 // Compute running average window in Chi
2329 int kchi_min = ichi - navgr2;
2330 int kchi_max = ichi + navgr2;
2331 if (kchi_min < 0) {
2332 kchi_min = 0;
2333 }
2334 if (kchi_max >= nchi) {
2335 kchi_max = nchi - 1;
2336 }
2337
2338 // Loop over Psi pixels
2339 for (int ipsi = 0; ipsi < npsi; ++ipsi) {
2340
2341 // Compute running average window in Psi
2342 int kpsi_min = ipsi - navgr2;
2343 int kpsi_max = ipsi + navgr2;
2344 if (kpsi_min < 0) {
2345 kpsi_min = 0;
2346 }
2347 if (kpsi_max >= npsi) {
2348 kpsi_max = npsi - 1;
2349 }
2350
2351 // Loop over Phibar layers
2352 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2353
2354 // Get Phibar index range for sums
2355 int ksel1 = 0;
2356 int kex1 = 0;
2357 int kex2 = 0;
2358 int ksel2 = 0;
2359 get_bgdlixa_phibar_indices(iphibar, nincl, nexcl,
2360 &ksel1, &kex1, &kex2, &ksel2);
2361
2362 // Initialise sums
2363 double sum_dre = 0.0;
2364 double sum_drm = 0.0;
2365 double sum_dri = 0.0;
2366
2367 // Compute running average
2368 for (int kchi = kchi_min; kchi <= kchi_max; ++kchi) {
2369 for (int kpsi = kpsi_min; kpsi <= kpsi_max; ++kpsi) {
2370
2371 // Get index
2372 int kpix = kchi + kpsi * nchi;
2373
2374 // Take sum over [ksel1, kex1]
2375 if (kex1 >= 0) {
2376 for (int kphibar = ksel1; kphibar <= kex1; ++kphibar) {
2377 sum_dre += map_dre(kpix, kphibar);
2378 sum_drm += map_drm(kpix, kphibar);
2379 sum_dri += map_dri(kpix, kphibar);
2380 }
2381 }
2382
2383 // Take sum over [kxe2, ksel2]
2384 if (kex2 < nphibar) {
2385 for (int kphibar = kex2; kphibar <= ksel2; ++kphibar) {
2386 sum_dre += map_dre(kpix, kphibar);
2387 sum_drm += map_drm(kpix, kphibar);
2388 sum_dri += map_dri(kpix, kphibar);
2389 }
2390 }
2391
2392 } // endfor: looped over kpsi
2393 } // endfor: looped over kchi
2394
2395 // Renormalize DRI locally to DRE-DRM
2396 int ipix = ichi + ipsi * nchi;
2397 if (sum_dri > 0.0) {
2398 double norm = (sum_dre - sum_drm) / sum_dri;
2399 map_drb(ipix, iphibar) = map_dri(ipix, iphibar) * norm;
2400 }
2401 else {
2402 map_drb(ipix, iphibar) = 0.0;
2403 }
2404
2405 } // endfor: looped over Phibar layers
2406
2407 } // endfor: looped over Psi pixels
2408
2409 } // endfor: looped over Chi pixels
2410
2411 // Phibar normalise DRB
2412 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2413 double sum_dre = 0.0;
2414 double sum_drm = 0.0;
2415 double sum_drb = 0.0;
2416 for (int ipix = 0; ipix < npix; ++ipix) {
2417 sum_dre += map_dre(ipix, iphibar);
2418 sum_drm += map_drm(ipix, iphibar);
2419 sum_drb += map_drb(ipix, iphibar);
2420 }
2421 if (sum_drb > 0.0) {
2422 double norm = (sum_dre - sum_drm) / sum_drb;
2423 for (int ipix = 0; ipix < npix; ++ipix) {
2424 map_drb(ipix, iphibar) *= norm;
2425 }
2426 }
2427 else {
2428 for (int ipix = 0; ipix < npix; ++ipix) {
2429 map_drb(ipix, iphibar) = 0.0;
2430 }
2431 }
2432 }
2433
2434 // Make sure that DRB is non-negative
2435 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2436 for (int ipix = 0; ipix < npix; ++ipix) {
2437 if (map_drb(ipix, iphibar) < 0.0) {
2438 map_drb(ipix, iphibar) = 0.0;
2439 }
2440 }
2441 }
2442
2443 // Return
2444 return;
2445}
2446
2447
2448/***********************************************************************//**
2449 * @brief Return weighted DRG map
2450 *
2451 * @return Weighted DRG map.
2452 *
2453 * Returns a DRG as sky map where each pixel of the map is multiplied by the
2454 * solidangle of the pixel.
2455 ***************************************************************************/
2457{
2458 // Initialise
2459 GSkyMap drg = m_drg.map();
2460
2461 // Get data space dimensions
2462 int npix = drg.npix();
2463 int nphibar = drg.nmaps();
2464
2465 // Weight map
2466 for (int ipix = 0; ipix < npix; ++ipix) {
2467 double omega = drg.solidangle(ipix);
2468 for (int iphibar = 0; iphibar < nphibar; ++iphibar) {
2469 drg(ipix,iphibar) *= omega;
2470 }
2471 }
2472
2473 // Return weighted DRG map
2474 return drg;
2475}
2476
2477
2478/***********************************************************************//**
2479 * @brief Compute Phibar index range for BGDLIXA background method
2480 *
2481 * @param[in] iphibar Phibar layer index.
2482 * @param[in] nincl Number of Phibar layers to include.
2483 * @param[in] nexcl Number of Phibar layers to exclude.
2484 * @param[out] isel1 Start index for first sum.
2485 * @param[out] iex1 Stop index for first sum.
2486 * @param[out] iex2 Start index for second sum.
2487 * @param[out] isel2 Stop index for second sum.
2488 *
2489 * This method is a helper method for the BGDLIXA background method. It
2490 * computes the Phibar index range for the third step of the background
2491 * model computation. The third step corresponds to Equation (3.14) in Rob
2492 * van Dijk's PhD thesis.
2493 *
2494 * The Phibar sum will be taken over the index ranges [isel1, iex1] and
2495 * [ixe2, isel2].
2496 ***************************************************************************/
2498 const int& nincl,
2499 const int& nexcl,
2500 int* isel1,
2501 int* iex1,
2502 int* iex2,
2503 int* isel2) const
2504{
2505 // Get number of Phibar layers
2506 int nphibar = m_drg.nphibar();
2507 int imax = nphibar - 1;
2508
2509 // Precompute half running average lengths
2510 int nexcl2 = int(nexcl/2);
2511 int nincl2 = int(nincl/2);
2512
2513 // Compute Phibar index range without respecting boundaries
2514 *iex1 = iphibar - nexcl2 - 1;
2515 *iex2 = iphibar + nexcl2 + 1;
2516 *isel1 = iphibar - nincl2;
2517 *isel2 = iphibar + nincl2;
2518
2519 // If no Phibar layers are to be excluded then make sure that the
2520 // Phibar layer range is continuous
2521 if (nexcl == 0) {
2522 (*iex2)--;
2523 }
2524
2525 // Make sure that start index of first sum and stop index of second
2526 // some are within the validity range
2527 if (*isel1 < 0) {
2528 *isel1 = 0;
2529 }
2530 if (*isel2 > imax) {
2531 *isel2 = imax;
2532 }
2533
2534 // Make sure that the sums use always ncincl Phibar layers, also near
2535 // the edges
2536 if (*isel1 == 0) {
2537 *isel2 = nincl - 1;
2538 if (nincl > imax) {
2539 *isel2 = imax;
2540 }
2541
2542 }
2543 if (*isel2 == imax) {
2544 *isel1 = nphibar - nincl;
2545 if (*isel1 < 0) {
2546 *isel1 = 0;
2547 }
2548 }
2549
2550 // Return
2551 return;
2552}
2553
2554
2555/***********************************************************************//**
2556 * @brief Check whether bin should be used for likelihood analysis
2557 *
2558 * @param[in] index Event index.
2559 * @return True if event with specified @p index should be used.
2560 *
2561 * Implements the Phibar event selection.
2562 ***************************************************************************/
2564{
2565 // Initialise usage flag
2566 bool use = true;
2567
2568 // Compute Phibar layer
2569 int iphi = index / m_drg.map().npix();
2570
2571 // Test first Phibar layer selection
2572 if ((m_phi_first != -1) && (iphi < m_phi_first)) {
2573 use = false;
2574 }
2575 else {
2576 // Test last Phibar layer selection
2577 if ((m_phi_last != -1) && (iphi > m_phi_last)) {
2578 use = false;
2579 }
2580 }
2581
2582 // Return usage flag
2583 return use;
2584}
#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_BGDLIXF
#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
#define G_LOAD_DRW
#define G_LOAD_DRG
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:932
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:62
virtual void clear(void)
Clear COMPTEL Data Space.
Definition GCOMDri.cpp:227
int nchi(void) const
Return number of Chi bins.
Definition GCOMDri.hpp:242
const GSkyMap & map(void) const
Return DRI sky map.
Definition GCOMDri.hpp:278
int npsi(void) const
Return number of Psi bins.
Definition GCOMDri.hpp:254
int nphibar(void) const
Return number of Phibar bins.
Definition GCOMDri.hpp:266
void read(const GFitsImage &image)
Read COMPTEL Data Space from DRI FITS image.
Definition GCOMDri.cpp:955
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 Housekeeping Data collection class.
Definition GCOMHkds.hpp:51
int size(void) const
Return number of Housekeeping parameters in collection.
Definition GCOMHkds.hpp:151
void clear(void)
Clear Housekeeping Data collection.
Definition GCOMHkds.cpp:233
std::string print(const GChatter &chatter=NORMAL) const
Print Housekeeping Data collection.
Definition GCOMHkds.cpp:639
void extend(const GCOMHkds &hkds)
Extend Housekeeping Data collection.
Definition GCOMHkds.cpp:525
bool is_empty(void) const
Signals if there are no Housekeeping Data containers in collection.
Definition GCOMHkds.hpp:166
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:500
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 m_drw
Weighting cube.
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.
void load(const GFilename &drename, const GFilename &drbname, const GFilename &drwname, const GFilename &drgname, const GFilename &drxname)
Load data for a binned observation.
GFilename m_drxname
DRX filename.
const GFilename & drgname(void) const
Return DRG filename.
const GFilename & drxname(void) const
Return DRX filename.
double m_ontime
Ontime (sec)
void compute_drb_bgdlixa(const GCOMDri &drm, const int &nrunav=3, const int &navgr=3, const int &nincl=15, const int &nexcl=0)
Compute DRB cube using BGDLIXA method.
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.
virtual double npred(const GModel &model) const
Return total number of predicted counts for one model.
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.
void compute_drb_bgdlixe(const GCOMDri &drm, const int &nrunav=3, const int &navgr=3, const int &nincl=15, const int &nexcl=0)
Compute DRB cube using BGDLIXE method.
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 double grad_step_size(const GModelPar &par) const
Return gradient step size for a given model parameter.
std::vector< GFilename > m_hkdnames
HKD filenames.
virtual void read(const GXmlElement &xml)
Read observation from XML element.
void compute_drb_bgdlixf(const GCOMDri &drm, const int &nrunav=3, const int &navgr=3, const int &nincl=15, const int &nexcl=0)
Compute DRB cube using BGDLIXF method.
GSkyMap get_weighted_drg_map(void) const
Return weighted DRG map.
void compute_drb(const std::string &method, const GCOMDri &drm, const int &nrunav=3, const int &navgr=3, const int &nincl=15, const int &nexcl=0)
Compute DRB cube.
virtual void clear(void)
Clear COMPTEL observation.
GCOMHkds m_hkds
Housekeeping Data.
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.
const GCOMDri & drw(void) const
Return weighting cube.
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.
void load_drw(const GFilename &drwname)
Load weighting cube from DRW file.
const GFilename & drwname(void) const
Return DRW filename.
double m_ewidth
Energy width (MeV)
const GFilename & rspname(void) const
Return response cache filename.
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.
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.
GFilename m_timname
TIM filename.
GFilename m_drwname
DRW 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.
GFilename m_rspname
Response cache filename.
Interface for the COMPTEL instrument response function.
void save_cache(const GFilename &filename) const
Save response cache.
const std::string & rspname(void) const
Return response name.
void caldb(const GCaldb &caldb)
Set calibration database.
void load_cache(const GFilename &filename)
Load response cache.
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:342
Abstract interface for the event bin class.
Definition GEventBin.hpp:64
virtual double size(void) const =0
Abstract event bin container class.
Abstract event container class.
Definition GEvents.hpp:66
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 exists(void) const
Checks whether file exists.
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:157
const double & ontime(void) const
Returns ontime.
Definition GGti.hpp:243
Model parameter class.
Definition GModelPar.hpp:87
Abstract model class.
Definition GModel.hpp:100
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
GModel * append(const GModel &model)
Append model to container.
Definition GModels.cpp:420
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.
std::string m_id
Observation identifier.
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:427
const int & nx(void) const
Returns number of pixels in x coordinate.
Definition GSkyMap.hpp:399
const int & npix(void) const
Returns number of pixels.
Definition GSkyMap.hpp:383
const int & ny(void) const
Returns number of pixels in y coordinate.
Definition GSkyMap.hpp:415
const GSkyProjection * projection(void) const
Returns pointer to sky projection.
Definition GSkyMap.hpp:501
Abstract sky projection base class.
Vector class.
Definition GVector.hpp:46
const int & size(void) const
Return size of vector.
Definition GVector.hpp:180
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:1162
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:508
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:1757
int toint(const std::string &arg)
Convert string into integer value.
Definition GTools.cpp:840
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:1656
GFilename xml_file_reduce(const GXmlElement &xml, const std::string &filename)
Reduce file name provided for writing as XML attribute.
Definition GTools.cpp:1965
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:1615
GFilename xml_file_expand(const GXmlElement &xml, const std::string &filename)
Expand file name provided as XML attribute for loading.
Definition GTools.cpp:1908