Commit 45c4368b7bcc02f8a721037b63d8a41b19f5f7fc

Authored by Jürgen Knödlseder
2 parents 496847f0 f369b08f

Merge branch 'integration' into devel

include/GModelSpatialComposite.hpp
@@ -78,21 +78,25 @@ public: @@ -78,21 +78,25 @@ public:
78 // Other methods 78 // Other methods
79 int components(void) const; 79 int components(void) const;
80 void append(const GModelSpatial& component, 80 void append(const GModelSpatial& component,
81 - const std::string& name = ""); 81 + const std::string& name = "",
  82 + const double& scale = 1.0);
82 const GModelSpatial* component(const int& index) const; 83 const GModelSpatial* component(const int& index) const;
83 const GModelSpatial* component(const std::string& name) const; 84 const GModelSpatial* component(const std::string& name) const;
  85 + double scale(const int& index) const;
  86 + double sum_of_scales(void) const;
84 87
85 88
86 protected: 89 protected:
87 // Protected methods 90 // Protected methods
88 - void init_members(void);  
89 - void copy_members(const GModelSpatialComposite& model);  
90 - void free_members(void); 91 + void init_members(void);
  92 + void copy_members(const GModelSpatialComposite& model);
  93 + void free_members(void);
91 94
92 // Protected members 95 // Protected members
93 - std::string m_type; //!< Model type  
94 - std::vector<GModelSpatial*> m_components; //!< Components  
95 - std::vector<std::string> m_component_names; //!< Component names 96 + std::string m_type; //!< Model type
  97 + std::vector<GModelSpatial*> m_components; //!< Components
  98 + std::vector<std::string> m_names; //!< Component names
  99 + std::vector<double> m_scales; //!< Component scales
96 }; 100 };
97 101
98 102
inst/cta/src/GCTAResponseCube.cpp
@@ -1530,14 +1530,16 @@ double GCTAResponseCube::irf_composite(const GEvent&amp; event, @@ -1530,14 +1530,16 @@ double GCTAResponseCube::irf_composite(const GEvent&amp; event,
1530 GSource src(source.name(), spat, source.energy(), source.time()); 1530 GSource src(source.name(), spat, source.energy(), source.time());
1531 1531
1532 // Compute irf value 1532 // Compute irf value
1533 - irf += this->irf(event, source, obs); 1533 + irf += this->irf(event, source, obs) * model->scale(i);
1534 1534
1535 } 1535 }
1536 1536
1537 // Divide by number of model components 1537 // Divide by number of model components
1538 - if (model->components() > 0) {  
1539 - irf /= double(model->components()); 1538 + double sum = model->sum_of_scales();
  1539 + if (sum > 0.0) {
  1540 + irf /= sum;
1540 } 1541 }
1541 1542
  1543 + // Return IRF value
1542 return irf; 1544 return irf;
1543 } 1545 }
inst/cta/src/GCTAResponseIrf.cpp
@@ -2883,13 +2883,14 @@ double GCTAResponseIrf::irf_composite(const GEvent&amp; event, @@ -2883,13 +2883,14 @@ double GCTAResponseIrf::irf_composite(const GEvent&amp; event,
2883 GSource src(source.name(), spat, source.energy(), source.time()); 2883 GSource src(source.name(), spat, source.energy(), source.time());
2884 2884
2885 // Compute irf value 2885 // Compute irf value
2886 - irf += this->irf(event, src, obs); 2886 + irf += this->irf(event, src, obs) * model->scale(i);
2887 2887
2888 } 2888 }
2889 2889
2890 // Divide by number of model components 2890 // Divide by number of model components
2891 - if (model->components() > 0) {  
2892 - irf /= double(model->components()); 2891 + double sum = model->sum_of_scales();
  2892 + if (sum > 0.0) {
  2893 + irf /= sum;
2893 } 2894 }
2894 2895
2895 // Return IRF value 2896 // Return IRF value
@@ -3536,13 +3537,15 @@ double GCTAResponseIrf::nroi_composite(const GModelSky&amp; model, @@ -3536,13 +3537,15 @@ double GCTAResponseIrf::nroi_composite(const GModelSky&amp; model,
3536 sky.spatial(comp->component(i)); 3537 sky.spatial(comp->component(i));
3537 3538
3538 // Compute nroi 3539 // Compute nroi
3539 - nroi += this->nroi(sky, srcEng, srcTime, obsEng, obsTime, obs); 3540 + nroi += this->nroi(sky, srcEng, srcTime, obsEng, obsTime, obs) *
  3541 + comp->scale(i);
3540 3542
3541 } 3543 }
3542 3544
3543 // Divide by number of model components 3545 // Divide by number of model components
3544 - if (comp->components() > 0) {  
3545 - nroi /= double(comp->components()); 3546 + double sum = comp->sum_of_scales();
  3547 + if (sum > 0.0) {
  3548 + nroi /= sum;
3546 } 3549 }
3547 3550
3548 // Return nroi 3551 // Return nroi
pyext/GModelSpatialComposite.i
@@ -63,9 +63,12 @@ public: @@ -63,9 +63,12 @@ public:
63 // Other methods 63 // Other methods
64 int components(void) const; 64 int components(void) const;
65 void append(const GModelSpatial& component, 65 void append(const GModelSpatial& component,
66 - const std::string& name = ""); 66 + const std::string& name = "",
  67 + const double& scale = 1.0);
67 const GModelSpatial* component(const int& index) const; 68 const GModelSpatial* component(const int& index) const;
68 const GModelSpatial* component(const std::string& name) const; 69 const GModelSpatial* component(const std::string& name) const;
  70 + double scale(const int& index) const;
  71 + double sum_of_scales(void) const;
69 }; 72 };
70 73
71 74
src/model/GModelSpatialComposite.cpp
@@ -234,23 +234,23 @@ GModelSpatialComposite* GModelSpatialComposite::clone(void) const @@ -234,23 +234,23 @@ GModelSpatialComposite* GModelSpatialComposite::clone(void) const
234 * @param[in] gradients Compute gradients? 234 * @param[in] gradients Compute gradients?
235 * @return Model value. 235 * @return Model value.
236 * 236 *
237 - * Evaluates the spatial composite model by summing all model components and  
238 - * dividing the sum by the number of components. 237 + * Evaluates the spatial composite model by summing all model components,
  238 + * weighting by their scale and dividing the sum of all scales.
239 ***************************************************************************/ 239 ***************************************************************************/
240 double GModelSpatialComposite::eval(const GPhoton& photon, 240 double GModelSpatialComposite::eval(const GPhoton& photon,
241 const bool& gradients) const 241 const bool& gradients) const
242 { 242 {
243 - // Initalise value 243 + // Initialise value
244 double value = 0.0; 244 double value = 0.0;
245 245
246 // Sum over all components 246 // Sum over all components
247 for (int i = 0; i < m_components.size(); ++i) { 247 for (int i = 0; i < m_components.size(); ++i) {
248 - value += m_components[i]->eval(photon, gradients); 248 + value += m_components[i]->eval(photon, gradients) * m_scales[i];
249 } 249 }
250 250
251 - // Normalise sum by the number of components  
252 - if (m_components.size() > 0) {  
253 - value /= double(m_components.size()); 251 + // Normalise sum by sum of scales
  252 + if (sum_of_scales() > 0) {
  253 + value /= sum_of_scales();
254 } 254 }
255 255
256 // Return value 256 // Return value
@@ -273,8 +273,22 @@ GSkyDir GModelSpatialComposite::mc(const GEnergy&amp; energy, @@ -273,8 +273,22 @@ GSkyDir GModelSpatialComposite::mc(const GEnergy&amp; energy,
273 const GTime& time, 273 const GTime& time,
274 GRan& ran) const 274 GRan& ran) const
275 { 275 {
276 - // Randomly choose one model component  
277 - int index = int(ran.uniform() * double(m_components.size())); 276 + // Randomly choose one model component weighted by scale
  277 +
  278 + // Calculate random number
  279 + double random = ran.uniform() * sum_of_scales();
  280 +
  281 + // Find index of chosen model component
  282 + double sum = 0.0;
  283 + int index = 0;
  284 + for (int i = 0; i < m_scales.size(); ++i) {
  285 + sum += m_scales[i];
  286 + if (random <= sum) {
  287 + index = i;
  288 + break;
  289 + }
  290 + }
  291 +
278 if (index >= m_components.size()) { 292 if (index >= m_components.size()) {
279 index = m_components.size(); 293 index = m_components.size();
280 } 294 }
@@ -305,7 +319,7 @@ bool GModelSpatialComposite::contains(const GSkyDir&amp; dir, @@ -305,7 +319,7 @@ bool GModelSpatialComposite::contains(const GSkyDir&amp; dir,
305 319
306 // Loop over all components 320 // Loop over all components
307 for (int i = 0; i < m_components.size(); ++i) { 321 for (int i = 0; i < m_components.size(); ++i) {
308 - if (m_components[i]->contains(dir, margin)) { 322 + if (m_components[i]->contains(dir, margin) && m_scales[i] != 0.0) {
309 containment = true; 323 containment = true;
310 break; 324 break;
311 } 325 }
@@ -341,10 +355,18 @@ void GModelSpatialComposite::read(const GXmlElement&amp; xml) @@ -341,10 +355,18 @@ void GModelSpatialComposite::read(const GXmlElement&amp; xml)
341 GModelSpatial* ptr = registry.alloc(*spec); 355 GModelSpatial* ptr = registry.alloc(*spec);
342 356
343 // Get component attribute from XML file 357 // Get component attribute from XML file
344 - std::string component_name = spec->attribute("component"); 358 + std::string name = spec->attribute("component");
345 359
  360 + // Initialise scale
  361 + double scale = 1.0;
  362 +
  363 + // Get scale value
  364 + if (spec-> has_attribute("scale")) {
  365 + scale = gammalib::todouble(spec->attribute("scale"));
  366 + }
  367 +
346 // Append spatial component to container 368 // Append spatial component to container
347 - append(*ptr, component_name); 369 + append(*ptr, name, scale);
348 370
349 } // endfor: loop over components 371 } // endfor: loop over components
350 372
@@ -394,8 +416,7 @@ void GModelSpatialComposite::write(GXmlElement&amp; xml) const @@ -394,8 +416,7 @@ void GModelSpatialComposite::write(GXmlElement&amp; xml) const
394 // Find XML element with matching name 416 // Find XML element with matching name
395 GXmlElement *matching_model = NULL; 417 GXmlElement *matching_model = NULL;
396 for (int k = 0; k < xml.elements("spatialModel"); ++k) { 418 for (int k = 0; k < xml.elements("spatialModel"); ++k) {
397 - if (xml.element("spatialModel", k)->attribute("name") ==  
398 - m_component_names[i]) { 419 + if (xml.element("spatialModel", k)->attribute("name") == m_names[i]) {
399 matching_model = xml.element("spatialModel", k); 420 matching_model = xml.element("spatialModel", k);
400 break; 421 break;
401 } 422 }
@@ -424,12 +445,22 @@ void GModelSpatialComposite::write(GXmlElement&amp; xml) const @@ -424,12 +445,22 @@ void GModelSpatialComposite::write(GXmlElement&amp; xml) const
424 // If an XML element exists then use it ... 445 // If an XML element exists then use it ...
425 if (matching_model != NULL) { 446 if (matching_model != NULL) {
426 spatial->write(*matching_model); 447 spatial->write(*matching_model);
  448 +
  449 + // Write scale to XML element if needed
  450 + if (m_scales[i] != 1.0 || matching_model->has_attribute("scale")) {
  451 + matching_model->attribute("scale", gammalib::str(m_scales[i]));
  452 + }
427 } 453 }
428 454
429 // ... otherwise create new XML element 455 // ... otherwise create new XML element
430 else { 456 else {
431 GXmlElement element("spatialModel"); 457 GXmlElement element("spatialModel");
432 spatial->write(element); 458 spatial->write(element);
  459 +
  460 + // Write scale to XML element if needed
  461 + if (m_scales[i] != 1.0) {
  462 + element.attribute("scale", gammalib::str(m_scales[i]));
  463 + }
433 xml.append(element); 464 xml.append(element);
434 } 465 }
435 466
@@ -448,13 +479,15 @@ void GModelSpatialComposite::write(GXmlElement&amp; xml) const @@ -448,13 +479,15 @@ void GModelSpatialComposite::write(GXmlElement&amp; xml) const
448 /***********************************************************************//** 479 /***********************************************************************//**
449 * @brief Append spatial component 480 * @brief Append spatial component
450 * 481 *
451 - * @param[in] component Spatial model component to append  
452 - * @param[in] name Name of spatial model (can be empty)  
453 - * 482 + * @param[in] component Spatial model component to append.
  483 + * @param[in] name Name of spatial model (can be empty).
  484 + * @param[in] scale Optional spatial model scaling factor.
  485 + *
454 * Appends a spatial component to the composite model 486 * Appends a spatial component to the composite model
455 ***************************************************************************/ 487 ***************************************************************************/
456 void GModelSpatialComposite::append(const GModelSpatial& component, 488 void GModelSpatialComposite::append(const GModelSpatial& component,
457 - const std::string& name) 489 + const std::string& name,
  490 + const double& scale)
458 { 491 {
459 // Append model container 492 // Append model container
460 m_components.push_back(component.clone()); 493 m_components.push_back(component.clone());
@@ -467,7 +500,7 @@ void GModelSpatialComposite::append(const GModelSpatial&amp; component, @@ -467,7 +500,7 @@ void GModelSpatialComposite::append(const GModelSpatial&amp; component,
467 : gammalib::str(m_components.size()); 500 : gammalib::str(m_components.size());
468 501
469 // Check if component name is unique, throw exception if not 502 // Check if component name is unique, throw exception if not
470 - if (gammalib::contains(m_component_names, component_name)) { 503 + if (gammalib::contains(m_names, component_name)) {
471 std::string msg = "Attempt to append component \""+component_name+"\" " 504 std::string msg = "Attempt to append component \""+component_name+"\" "
472 "to composite spatial model, but a component with the " 505 "to composite spatial model, but a component with the "
473 "same name exists already. Each component needs a " 506 "same name exists already. Each component needs a "
@@ -476,7 +509,7 @@ void GModelSpatialComposite::append(const GModelSpatial&amp; component, @@ -476,7 +509,7 @@ void GModelSpatialComposite::append(const GModelSpatial&amp; component,
476 } 509 }
477 510
478 // Add component name 511 // Add component name
479 - m_component_names.push_back(component_name); 512 + m_names.push_back(component_name);
480 513
481 // Get number of spectral parameters from model 514 // Get number of spectral parameters from model
482 int npars = m_components[index]->size(); 515 int npars = m_components[index]->size();
@@ -495,6 +528,9 @@ void GModelSpatialComposite::append(const GModelSpatial&amp; component, @@ -495,6 +528,9 @@ void GModelSpatialComposite::append(const GModelSpatial&amp; component,
495 528
496 } // endfor: loop over model parameters 529 } // endfor: loop over model parameters
497 530
  531 + // Push back model scale
  532 + m_scales.push_back(scale);
  533 +
498 // Return 534 // Return
499 return; 535 return;
500 } 536 }
@@ -539,8 +575,8 @@ const GModelSpatial* GModelSpatialComposite::component(const std::string&amp; name) @@ -539,8 +575,8 @@ const GModelSpatial* GModelSpatialComposite::component(const std::string&amp; name)
539 { 575 {
540 // Check if model name is found 576 // Check if model name is found
541 int index = -1; 577 int index = -1;
542 - for (int i = 0; i < m_component_names.size(); ++i) {  
543 - if (m_component_names[i] == name) { 578 + for (int i = 0; i < m_names.size(); ++i) {
  579 + if (m_names[i] == name) {
544 index = i; 580 index = i;
545 break; 581 break;
546 } 582 }
@@ -557,6 +593,51 @@ const GModelSpatial* GModelSpatialComposite::component(const std::string&amp; name) @@ -557,6 +593,51 @@ const GModelSpatial* GModelSpatialComposite::component(const std::string&amp; name)
557 return m_components[index]; 593 return m_components[index];
558 } 594 }
559 595
  596 +/***********************************************************************//**
  597 + * @brief Returns scale of spatial component
  598 + *
  599 + * @param[in] index Index of spatial component [0,...,components()-1].
  600 + * @return Scale.
  601 + *
  602 + * @exception GException::out_of_range
  603 + * Index is out of range.
  604 + *
  605 + * Returns the scale of a spatial component to the composite model
  606 + ***************************************************************************/
  607 +double GModelSpatialComposite::scale(const int& index) const
  608 +{
  609 + // Check if index is in validity range
  610 + if (index < 0 || index >= m_components.size()) {
  611 + throw GException::out_of_range(G_COMPONENT_INDEX, "Component Index",
  612 + index, m_components.size());
  613 + }
  614 +
  615 + // Return spatial component scale
  616 + return m_scales[index];
  617 +}
  618 +
  619 +
  620 +/***********************************************************************//**
  621 + * @brief Returns sum of all model scales
  622 + *
  623 + * @return Sum of all model scales
  624 + ***************************************************************************/
  625 +double GModelSpatialComposite::sum_of_scales(void) const
  626 +{
  627 + // Initialise sum
  628 + double sum = 0.0;
  629 +
  630 + // Loop over all component scales
  631 + for (int i = 0; i < m_scales.size(); ++i) {
  632 +
  633 + // Add scale to sum
  634 + sum += m_scales[i];
  635 + }
  636 +
  637 + // Return sum
  638 + return sum;
  639 +}
  640 +
560 641
561 /***********************************************************************//** 642 /***********************************************************************//**
562 * @brief Print composite spatial model information 643 * @brief Print composite spatial model information
@@ -609,7 +690,8 @@ void GModelSpatialComposite::init_members(void) @@ -609,7 +690,8 @@ void GModelSpatialComposite::init_members(void)
609 690
610 // Initialise models vector 691 // Initialise models vector
611 m_components.clear(); 692 m_components.clear();
612 - m_component_names.clear(); 693 + m_names.clear();
  694 + m_scales.clear();
613 695
614 // Return 696 // Return
615 return; 697 return;
@@ -624,8 +706,9 @@ void GModelSpatialComposite::init_members(void) @@ -624,8 +706,9 @@ void GModelSpatialComposite::init_members(void)
624 void GModelSpatialComposite::copy_members(const GModelSpatialComposite& model) 706 void GModelSpatialComposite::copy_members(const GModelSpatialComposite& model)
625 { 707 {
626 // Copy members 708 // Copy members
627 - m_type = model.m_type;  
628 - m_component_names = model.m_component_names; 709 + m_type = model.m_type;
  710 + m_names = model.m_names;
  711 + m_scales = model.m_scales;
629 712
630 // Initialise components 713 // Initialise components
631 m_components.clear(); 714 m_components.clear();
test/data/model_spatial_composite.xml
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/> 11 <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
12 <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/> 12 <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
13 </spatialModel> 13 </spatialModel>
14 - <spatialModel type="RadialGaussian"> 14 + <spatialModel type="RadialGaussian" scale="3.0">
15 <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/> 15 <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
16 <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/> 16 <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
17 <parameter name="Sigma" scale="1.0" value="0.20" min="0.01" max="10" free="1"/> 17 <parameter name="Sigma" scale="1.0" value="0.20" min="0.01" max="10" free="1"/>
test/test_GModel.cpp
@@ -1423,7 +1423,7 @@ void TestGModel::test_spatial_composite(void) @@ -1423,7 +1423,7 @@ void TestGModel::test_spatial_composite(void)
1423 1423
1424 // Test append method 1424 // Test append method
1425 model1.append(GModelSpatialPointSource(dir)); 1425 model1.append(GModelSpatialPointSource(dir));
1426 - model1.append(GModelSpatialRadialGauss(dir, 0.2)); 1426 + model1.append(GModelSpatialRadialGauss(dir, 0.2), "", 1.5);
1427 test_value(model1.components(), 2); 1427 test_value(model1.components(), 2);
1428 test_value(model1.size(), 5); 1428 test_value(model1.size(), 5);
1429 1429
@@ -1433,6 +1433,9 @@ void TestGModel::test_spatial_composite(void) @@ -1433,6 +1433,9 @@ void TestGModel::test_spatial_composite(void)
1433 GModelSpatialComposite model2(*element); 1433 GModelSpatialComposite model2(*element);
1434 test_value(model2.size(), 5); 1434 test_value(model2.size(), 5);
1435 test_value(model2.type(), "Composite", "Check model type"); 1435 test_value(model2.type(), "Composite", "Check model type");
  1436 + test_value(model2.scale(0), 1.0);
  1437 + test_value(model2.scale(1), 3.0);
  1438 + test_value(model2.sum_of_scales(), 4.0);
1436 1439
1437 // Test access of individual parameters 1440 // Test access of individual parameters
1438 test_value(model2["2:RA"].value(), 83.6331); 1441 test_value(model2["2:RA"].value(), 83.6331);