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 78 // Other methods
79 79 int components(void) const;
80 80 void append(const GModelSpatial& component,
81   - const std::string& name = "");
  81 + const std::string& name = "",
  82 + const double& scale = 1.0);
82 83 const GModelSpatial* component(const int& index) const;
83 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 89 protected:
87 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 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 1530 GSource src(source.name(), spat, source.energy(), source.time());
1531 1531  
1532 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 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 1544 return irf;
1543 1545 }
... ...
inst/cta/src/GCTAResponseIrf.cpp
... ... @@ -2883,13 +2883,14 @@ double GCTAResponseIrf::irf_composite(const GEvent&amp; event,
2883 2883 GSource src(source.name(), spat, source.energy(), source.time());
2884 2884  
2885 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 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 2896 // Return IRF value
... ... @@ -3536,13 +3537,15 @@ double GCTAResponseIrf::nroi_composite(const GModelSky&amp; model,
3536 3537 sky.spatial(comp->component(i));
3537 3538  
3538 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 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 3551 // Return nroi
... ...
pyext/GModelSpatialComposite.i
... ... @@ -63,9 +63,12 @@ public:
63 63 // Other methods
64 64 int components(void) const;
65 65 void append(const GModelSpatial& component,
66   - const std::string& name = "");
  66 + const std::string& name = "",
  67 + const double& scale = 1.0);
67 68 const GModelSpatial* component(const int& index) const;
68 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 234 * @param[in] gradients Compute gradients?
235 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 240 double GModelSpatialComposite::eval(const GPhoton& photon,
241 241 const bool& gradients) const
242 242 {
243   - // Initalise value
  243 + // Initialise value
244 244 double value = 0.0;
245 245  
246 246 // Sum over all components
247 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 256 // Return value
... ... @@ -273,8 +273,22 @@ GSkyDir GModelSpatialComposite::mc(const GEnergy&amp; energy,
273 273 const GTime& time,
274 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 292 if (index >= m_components.size()) {
279 293 index = m_components.size();
280 294 }
... ... @@ -305,7 +319,7 @@ bool GModelSpatialComposite::contains(const GSkyDir&amp; dir,
305 319  
306 320 // Loop over all components
307 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 323 containment = true;
310 324 break;
311 325 }
... ... @@ -341,10 +355,18 @@ void GModelSpatialComposite::read(const GXmlElement&amp; xml)
341 355 GModelSpatial* ptr = registry.alloc(*spec);
342 356  
343 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 368 // Append spatial component to container
347   - append(*ptr, component_name);
  369 + append(*ptr, name, scale);
348 370  
349 371 } // endfor: loop over components
350 372  
... ... @@ -394,8 +416,7 @@ void GModelSpatialComposite::write(GXmlElement&amp; xml) const
394 416 // Find XML element with matching name
395 417 GXmlElement *matching_model = NULL;
396 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 420 matching_model = xml.element("spatialModel", k);
400 421 break;
401 422 }
... ... @@ -424,12 +445,22 @@ void GModelSpatialComposite::write(GXmlElement&amp; xml) const
424 445 // If an XML element exists then use it ...
425 446 if (matching_model != NULL) {
426 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 455 // ... otherwise create new XML element
430 456 else {
431 457 GXmlElement element("spatialModel");
432 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 464 xml.append(element);
434 465 }
435 466  
... ... @@ -448,13 +479,15 @@ void GModelSpatialComposite::write(GXmlElement&amp; xml) const
448 479 /***********************************************************************//**
449 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 486 * Appends a spatial component to the composite model
455 487 ***************************************************************************/
456 488 void GModelSpatialComposite::append(const GModelSpatial& component,
457   - const std::string& name)
  489 + const std::string& name,
  490 + const double& scale)
458 491 {
459 492 // Append model container
460 493 m_components.push_back(component.clone());
... ... @@ -467,7 +500,7 @@ void GModelSpatialComposite::append(const GModelSpatial&amp; component,
467 500 : gammalib::str(m_components.size());
468 501  
469 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 504 std::string msg = "Attempt to append component \""+component_name+"\" "
472 505 "to composite spatial model, but a component with the "
473 506 "same name exists already. Each component needs a "
... ... @@ -476,7 +509,7 @@ void GModelSpatialComposite::append(const GModelSpatial&amp; component,
476 509 }
477 510  
478 511 // Add component name
479   - m_component_names.push_back(component_name);
  512 + m_names.push_back(component_name);
480 513  
481 514 // Get number of spectral parameters from model
482 515 int npars = m_components[index]->size();
... ... @@ -495,6 +528,9 @@ void GModelSpatialComposite::append(const GModelSpatial&amp; component,
495 528  
496 529 } // endfor: loop over model parameters
497 530  
  531 + // Push back model scale
  532 + m_scales.push_back(scale);
  533 +
498 534 // Return
499 535 return;
500 536 }
... ... @@ -539,8 +575,8 @@ const GModelSpatial* GModelSpatialComposite::component(const std::string&amp; name)
539 575 {
540 576 // Check if model name is found
541 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 580 index = i;
545 581 break;
546 582 }
... ... @@ -557,6 +593,51 @@ const GModelSpatial* GModelSpatialComposite::component(const std::string&amp; name)
557 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 643 * @brief Print composite spatial model information
... ... @@ -609,7 +690,8 @@ void GModelSpatialComposite::init_members(void)
609 690  
610 691 // Initialise models vector
611 692 m_components.clear();
612   - m_component_names.clear();
  693 + m_names.clear();
  694 + m_scales.clear();
613 695  
614 696 // Return
615 697 return;
... ... @@ -624,8 +706,9 @@ void GModelSpatialComposite::init_members(void)
624 706 void GModelSpatialComposite::copy_members(const GModelSpatialComposite& model)
625 707 {
626 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 713 // Initialise components
631 714 m_components.clear();
... ...
test/data/model_spatial_composite.xml
... ... @@ -11,7 +11,7 @@
11 11 <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
12 12 <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
13 13 </spatialModel>
14   - <spatialModel type="RadialGaussian">
  14 + <spatialModel type="RadialGaussian" scale="3.0">
15 15 <parameter name="RA" scale="1.0" value="83.6331" min="-360" max="360" free="1"/>
16 16 <parameter name="DEC" scale="1.0" value="22.0145" min="-90" max="90" free="1"/>
17 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 1423  
1424 1424 // Test append method
1425 1425 model1.append(GModelSpatialPointSource(dir));
1426   - model1.append(GModelSpatialRadialGauss(dir, 0.2));
  1426 + model1.append(GModelSpatialRadialGauss(dir, 0.2), "", 1.5);
1427 1427 test_value(model1.components(), 2);
1428 1428 test_value(model1.size(), 5);
1429 1429  
... ... @@ -1433,6 +1433,9 @@ void TestGModel::test_spatial_composite(void)
1433 1433 GModelSpatialComposite model2(*element);
1434 1434 test_value(model2.size(), 5);
1435 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 1440 // Test access of individual parameters
1438 1441 test_value(model2["2:RA"].value(), 83.6331);
... ...