Commit 45c4368b7bcc02f8a721037b63d8a41b19f5f7fc
Merge branch 'integration' into devel
Showing
7 changed files
with
142 additions
and
44 deletions
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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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); | ... | ... |