Commit 209428cfb6d8e8333bb30b8993c664810e511130
1 parent
d0096357
Add ctlike results to XML file (#3431)
Showing
5 changed files
with
149 additions
and
63 deletions
ChangeLog
NEWS
| ... | ... | @@ -76,6 +76,9 @@ None |
| 76 | 76 | |
| 77 | 77 | ctlike - Maximum likelihood fitting |
| 78 | 78 | ----------------------------------- |
| 79 | +The model fitting results, such as log-likelihood value, number of iterations | |
| 80 | +etc. are now added to the output XML file (#3431). | |
| 81 | + | |
| 79 | 82 | A bug was fixed in the implementation of the fix_spat_for_ts parameter that |
| 80 | 83 | only fixed the spatial parameters for the first of the sky models but left |
| 81 | 84 | the spatial parameters free for all additional sky models. Now the parameters | ... | ... |
doc/source/admin/release_history/2.0.rst
src/ctlike/ctlike.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctlike - Maximum likelihood fitting tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2019 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2010-2020 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -236,10 +236,10 @@ void ctlike::run(void) |
| 236 | 236 | // Store copy of curvature matrix |
| 237 | 237 | GMatrixSparse curvature = |
| 238 | 238 | *(const_cast<GObservations::likelihood&>(m_obs.function()).curvature()); |
| 239 | - | |
| 239 | + | |
| 240 | 240 | // Store Npred |
| 241 | - double npred = m_obs.npred(); | |
| 242 | - | |
| 241 | + m_npred = m_obs.npred(); | |
| 242 | + | |
| 243 | 243 | // Store models for which TS should be computed |
| 244 | 244 | std::vector<std::string> ts_srcs; |
| 245 | 245 | GModels models_orig = m_obs.models(); |
| ... | ... | @@ -308,11 +308,11 @@ void ctlike::run(void) |
| 308 | 308 | } // endif: requested TS computation |
| 309 | 309 | |
| 310 | 310 | // Compute number of observed events in all observations |
| 311 | - double num_events = 0.0; | |
| 311 | + m_nobs = 0.0; | |
| 312 | 312 | for (int i = 0; i < m_obs.size(); ++i) { |
| 313 | 313 | double data = m_obs[i]->nobserved(); |
| 314 | 314 | if (data >= 0.0) { |
| 315 | - num_events += data; | |
| 315 | + m_nobs += data; | |
| 316 | 316 | } |
| 317 | 317 | } |
| 318 | 318 | |
| ... | ... | @@ -320,9 +320,9 @@ void ctlike::run(void) |
| 320 | 320 | log_header1(NORMAL, "Maximum likelihood optimisation results"); |
| 321 | 321 | log_string(NORMAL, m_opt.print(m_chatter)); |
| 322 | 322 | log_value(NORMAL, "Maximum log likelihood", gammalib::str(m_logL,3)); |
| 323 | - log_value(NORMAL, "Observed events (Nobs)", gammalib::str(num_events,3)); | |
| 324 | - log_value(NORMAL, "Predicted events (Npred)", gammalib::str(npred,3)+ | |
| 325 | - " (Nobs - Npred = "+gammalib::str(num_events-npred)+")"); | |
| 323 | + log_value(NORMAL, "Observed events (Nobs)", gammalib::str(m_nobs,3)); | |
| 324 | + log_value(NORMAL, "Predicted events (Npred)", gammalib::str(m_npred,3)+ | |
| 325 | + " (Nobs - Npred = "+gammalib::str(m_nobs-m_npred)+")"); | |
| 326 | 326 | log_string(NORMAL, m_obs.models().print(m_chatter)); |
| 327 | 327 | |
| 328 | 328 | // Restore energy dispersion flags of all CTA observations |
| ... | ... | @@ -356,6 +356,9 @@ void ctlike::save(void) |
| 356 | 356 | // Save model only if filename is valid |
| 357 | 357 | if ((*this)["outmodel"].is_valid()) { |
| 358 | 358 | |
| 359 | + // Generate XML instance | |
| 360 | + GXml xml = xml_result(); | |
| 361 | + | |
| 359 | 362 | // Get output filename |
| 360 | 363 | m_outmodel = (*this)["outmodel"].filename(); |
| 361 | 364 | |
| ... | ... | @@ -363,9 +366,9 @@ void ctlike::save(void) |
| 363 | 366 | log_value(NORMAL, "Model definition file", m_outmodel.url()); |
| 364 | 367 | |
| 365 | 368 | // Write results out as XML model |
| 366 | - m_obs.models().save(m_outmodel); | |
| 369 | + xml.save(m_outmodel); | |
| 367 | 370 | |
| 368 | - } | |
| 371 | + } // endif: filename was valid | |
| 369 | 372 | |
| 370 | 373 | // ... otherwise signal that file was not saved |
| 371 | 374 | else { |
| ... | ... | @@ -396,6 +399,69 @@ void ctlike::save(void) |
| 396 | 399 | } |
| 397 | 400 | |
| 398 | 401 | |
| 402 | +/*========================================================================== | |
| 403 | + = = | |
| 404 | + = Private methods = | |
| 405 | + = = | |
| 406 | + ==========================================================================*/ | |
| 407 | + | |
| 408 | +/***********************************************************************//** | |
| 409 | + * @brief Initialise class members | |
| 410 | + ***************************************************************************/ | |
| 411 | +void ctlike::init_members(void) | |
| 412 | +{ | |
| 413 | + // Initialise members | |
| 414 | + m_outmodel.clear(); | |
| 415 | + m_outcovmat.clear(); | |
| 416 | + m_refit = false; | |
| 417 | + m_apply_edisp = false; | |
| 418 | + m_fix_spat_for_ts = false; | |
| 419 | + m_chatter = static_cast<GChatter>(2); | |
| 420 | + m_logL = 0.0; | |
| 421 | + m_nobs = 0.0; | |
| 422 | + m_npred = 0.0; | |
| 423 | + | |
| 424 | + // Set logger properties | |
| 425 | + log.date(true); | |
| 426 | + | |
| 427 | + // Return | |
| 428 | + return; | |
| 429 | +} | |
| 430 | + | |
| 431 | + | |
| 432 | +/***********************************************************************//** | |
| 433 | + * @brief Copy class members | |
| 434 | + * | |
| 435 | + * @param[in] app Application. | |
| 436 | + ***************************************************************************/ | |
| 437 | +void ctlike::copy_members(const ctlike& app) | |
| 438 | +{ | |
| 439 | + // Copy attributes | |
| 440 | + m_refit = app.m_refit; | |
| 441 | + m_outmodel = app.m_outmodel; | |
| 442 | + m_outcovmat = app.m_outcovmat; | |
| 443 | + m_apply_edisp = app.m_apply_edisp; | |
| 444 | + m_fix_spat_for_ts = app.m_fix_spat_for_ts; | |
| 445 | + m_chatter = app.m_chatter; | |
| 446 | + m_logL = app.m_logL; | |
| 447 | + m_nobs = app.m_nobs; | |
| 448 | + m_npred = app.m_npred; | |
| 449 | + | |
| 450 | + // Return | |
| 451 | + return; | |
| 452 | +} | |
| 453 | + | |
| 454 | + | |
| 455 | +/***********************************************************************//** | |
| 456 | + * @brief Delete class members | |
| 457 | + ***************************************************************************/ | |
| 458 | +void ctlike::free_members(void) | |
| 459 | +{ | |
| 460 | + // Return | |
| 461 | + return; | |
| 462 | +} | |
| 463 | + | |
| 464 | + | |
| 399 | 465 | /***********************************************************************//** |
| 400 | 466 | * @brief Get application parameters |
| 401 | 467 | * |
| ... | ... | @@ -562,60 +628,70 @@ double ctlike::reoptimize_lm(void) |
| 562 | 628 | } |
| 563 | 629 | |
| 564 | 630 | |
| 565 | -/*========================================================================== | |
| 566 | - = = | |
| 567 | - = Private methods = | |
| 568 | - = = | |
| 569 | - ==========================================================================*/ | |
| 570 | - | |
| 571 | -/***********************************************************************//** | |
| 572 | - * @brief Initialise class members | |
| 573 | - ***************************************************************************/ | |
| 574 | -void ctlike::init_members(void) | |
| 575 | -{ | |
| 576 | - // Initialise members | |
| 577 | - m_outmodel.clear(); | |
| 578 | - m_outcovmat.clear(); | |
| 579 | - m_refit = false; | |
| 580 | - m_logL = 0.0; | |
| 581 | - m_apply_edisp = false; | |
| 582 | - m_fix_spat_for_ts = false; | |
| 583 | - m_chatter = static_cast<GChatter>(2); | |
| 584 | - | |
| 585 | - // Set logger properties | |
| 586 | - log.date(true); | |
| 587 | - | |
| 588 | - // Return | |
| 589 | - return; | |
| 590 | -} | |
| 591 | - | |
| 592 | - | |
| 593 | 631 | /***********************************************************************//** |
| 594 | - * @brief Copy class members | |
| 632 | + * @brief Generate XML result | |
| 595 | 633 | * |
| 596 | - * @param[in] app Application. | |
| 634 | + * @return XML result | |
| 635 | + * | |
| 636 | + * Generates the XML result composed of the ctlike results and the model | |
| 637 | + * fitting results. | |
| 597 | 638 | ***************************************************************************/ |
| 598 | -void ctlike::copy_members(const ctlike& app) | |
| 639 | +GXml ctlike::xml_result(void) const | |
| 599 | 640 | { |
| 600 | - // Copy attributes | |
| 601 | - m_refit = app.m_refit; | |
| 602 | - m_outmodel = app.m_outmodel; | |
| 603 | - m_outcovmat = app.m_outcovmat; | |
| 604 | - m_logL = app.m_logL; | |
| 605 | - m_apply_edisp = app.m_apply_edisp; | |
| 606 | - m_fix_spat_for_ts = app.m_fix_spat_for_ts; | |
| 607 | - m_chatter = app.m_chatter; | |
| 608 | - | |
| 609 | - // Return | |
| 610 | - return; | |
| 611 | -} | |
| 641 | + // Initialise XML result | |
| 642 | + GXml xml; | |
| 643 | + | |
| 644 | + // Set fit status | |
| 645 | + std::string status; | |
| 646 | + switch (m_opt.status()) { | |
| 647 | + case G_LM_CONVERGED: | |
| 648 | + status.append("converged"); | |
| 649 | + break; | |
| 650 | + case G_LM_STALLED: | |
| 651 | + status.append("stalled"); | |
| 652 | + break; | |
| 653 | + case G_LM_SINGULAR: | |
| 654 | + status.append("singular curvature matrix encountered"); | |
| 655 | + break; | |
| 656 | + case G_LM_NOT_POSTIVE_DEFINITE: | |
| 657 | + status.append("curvature matrix not positive definite"); | |
| 658 | + break; | |
| 659 | + case G_LM_BAD_ERRORS: | |
| 660 | + status.append("errors are inaccurate"); | |
| 661 | + break; | |
| 662 | + default: | |
| 663 | + status.append("unknown"); | |
| 664 | + break; | |
| 665 | + } | |
| 612 | 666 | |
| 667 | + // Set flag strings | |
| 668 | + std::string refit = (m_refit) ? "yes" : "no"; | |
| 669 | + std::string edisp = (m_apply_edisp) ? "yes" : "no"; | |
| 670 | + std::string fix_spat_for_ts = (m_fix_spat_for_ts) ? "yes" : "no"; | |
| 613 | 671 | |
| 614 | -/***********************************************************************//** | |
| 615 | - * @brief Delete class members | |
| 616 | - ***************************************************************************/ | |
| 617 | -void ctlike::free_members(void) | |
| 618 | -{ | |
| 619 | - // Return | |
| 620 | - return; | |
| 672 | + // Write ctlike results into XML instance | |
| 673 | + if (xml.elements("ctlike_results") == 0) { | |
| 674 | + xml.append(GXmlElement("ctlike_results title=\"ctlike fit results\"")); | |
| 675 | + } | |
| 676 | + GXmlElement* result = xml.element("ctlike_results", 0); | |
| 677 | + result->append(GXmlElement("status", status)); | |
| 678 | + result->append(GXmlElement("log-likelihood", m_logL)); | |
| 679 | + result->append(GXmlElement("precision", m_opt.eps())); | |
| 680 | + result->append(GXmlElement("iterations", m_opt.iter())); | |
| 681 | + result->append(GXmlElement("lambda", m_opt.lambda())); | |
| 682 | + result->append(GXmlElement("total_parameters", m_opt.npars())); | |
| 683 | + result->append(GXmlElement("fitted_parameters", m_opt.nfree())); | |
| 684 | + result->append(GXmlElement("observed-events", m_nobs)); | |
| 685 | + result->append(GXmlElement("predicted-events", m_npred)); | |
| 686 | + result->append(GXmlElement("refit", refit)); | |
| 687 | + result->append(GXmlElement("edisp", edisp)); | |
| 688 | + result->append(GXmlElement("fix-spatial-for-ts", fix_spat_for_ts)); | |
| 689 | + result->append(GXmlElement("elapsed-time", this->telapse())); | |
| 690 | + result->append(GXmlElement("cpu-seconds", this->celapse())); | |
| 691 | + | |
| 692 | + // Write model results into XML instance | |
| 693 | + m_obs.models().write(xml); | |
| 694 | + | |
| 695 | + // Return XML result | |
| 696 | + return xml; | |
| 621 | 697 | } | ... | ... |
src/ctlike/ctlike.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctlike - Maximum likelihood fitting tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2018 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2010-2020 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -65,17 +65,20 @@ protected: |
| 65 | 65 | void get_parameters(void); |
| 66 | 66 | void optimize_lm(void); |
| 67 | 67 | double reoptimize_lm(void); |
| 68 | + GXml xml_result(void) const; | |
| 68 | 69 | |
| 69 | 70 | // User parameters |
| 70 | - bool m_refit; //!< Refitting | |
| 71 | 71 | GFilename m_outmodel; //!< Source model output XML file name |
| 72 | 72 | GFilename m_outcovmat; //!< Covariance matrix output file name |
| 73 | + bool m_refit; //!< Refitting | |
| 73 | 74 | bool m_apply_edisp; //!< Apply energy dispersion? |
| 74 | 75 | bool m_fix_spat_for_ts; //!< Fix spatial parameters for TS computation? |
| 75 | 76 | GChatter m_chatter; //!< Chattiness |
| 76 | 77 | |
| 77 | 78 | // Members |
| 78 | 79 | double m_logL; //!< Maximum log likelihood |
| 80 | + double m_nobs; //!< Number of observed events | |
| 81 | + double m_npred; //!< Number of predicted events | |
| 79 | 82 | }; |
| 80 | 83 | |
| 81 | 84 | #endif /* CTLIKE_HPP */ | ... | ... |