Commit 6dca3a06ad8c20bb4d704b9ce2bd222f3b0726f6
1 parent
4a6eab84
Assume constant background in the absence of an IRF template in GCTAOnOffObserva…
…tion::compute_bgd (#2683)
Showing
1 changed file
with
196 additions
and
168 deletions
inst/cta/src/GCTAOnOffObservation.cpp
| ... | ... | @@ -293,8 +293,8 @@ GCTAOnOffObservation::GCTAOnOffObservation(const GObservations& obs) : |
| 293 | 293 | // Signal first On/Off observation |
| 294 | 294 | bool first = true; |
| 295 | 295 | |
| 296 | - // Initialise exposure | |
| 297 | - double exposure = 0.0; | |
| 296 | + // Initialise total exposure | |
| 297 | + double total_exposure = 0.0; | |
| 298 | 298 | |
| 299 | 299 | // Allocate observation energy range |
| 300 | 300 | GEnergy emin_obs; |
| ... | ... | @@ -323,38 +323,35 @@ GCTAOnOffObservation::GCTAOnOffObservation(const GObservations& obs) : |
| 323 | 323 | GArf arf_stacked = this->arf_stacked(onoff->arf(), emin, emax); |
| 324 | 324 | GRmf rmf_stacked = this->rmf_stacked(onoff->rmf(), emin, emax); |
| 325 | 325 | |
| 326 | + // Get exposure for observation | |
| 327 | + double exposure = onoff->on_spec().exposure(); | |
| 328 | + | |
| 326 | 329 | // If this is the first On/Off observation then store the data to |
| 327 | 330 | // initialise the data definition |
| 328 | 331 | if (first) { |
| 329 | 332 | |
| 330 | - // Store PHA, ARF and RMF | |
| 331 | - m_on_spec = onoff->on_spec(); | |
| 332 | - m_off_spec = onoff->off_spec(); | |
| 333 | - m_arf = arf_stacked * onoff->on_spec().exposure(); | |
| 334 | - m_rmf = rmf_stacked; | |
| 335 | - m_ontime = onoff->ontime(); | |
| 336 | - m_livetime = onoff->livetime(); | |
| 337 | - exposure = onoff->on_spec().exposure(); | |
| 333 | + // Store PHA, ARF and RMF, set exposure, ontime and livetime | |
| 334 | + m_on_spec = onoff->on_spec(); | |
| 335 | + m_off_spec = onoff->off_spec(); | |
| 336 | + m_arf = arf_stacked * exposure; | |
| 337 | + m_rmf = rmf_stacked; | |
| 338 | + total_exposure = exposure; | |
| 339 | + m_ontime = onoff->ontime(); | |
| 340 | + m_livetime = onoff->livetime(); | |
| 338 | 341 | |
| 339 | 342 | // Compute number of background events/MeV from BACKRESP column |
| 340 | 343 | // and store result intermediately into BACKRESP column of off |
| 341 | 344 | // spectum |
| 342 | 345 | std::vector<double>& backresp = m_off_spec["BACKRESP"]; |
| 343 | 346 | for (int i = 0; i < backresp.size(); ++i) { |
| 344 | - backresp[i] *= onoff->on_spec().exposure(); | |
| 347 | + backresp[i] *= exposure; | |
| 345 | 348 | } |
| 346 | 349 | |
| 347 | - // Compute background scaling factor contribution. Handle the case | |
| 348 | - // where there is no background response, which may happen if no | |
| 349 | - // IRF template exists. In that case we do not weight with the | |
| 350 | - // background response. | |
| 350 | + // Compute background scaling factor contribution | |
| 351 | 351 | for (int i = 0; i < m_on_spec.size(); ++i) { |
| 352 | 352 | double background = onoff->off_spec()["BACKRESP"][i]; |
| 353 | - double exposure = onoff->on_spec().exposure(); | |
| 354 | 353 | double alpha = onoff->on_spec().backscal(i); |
| 355 | - double scale = (background > 0.0) | |
| 356 | - ? alpha * background * exposure | |
| 357 | - : alpha * exposure; | |
| 354 | + double scale = alpha * background * exposure; | |
| 358 | 355 | m_on_spec.backscal(i,scale); |
| 359 | 356 | } |
| 360 | 357 | |
| ... | ... | @@ -410,44 +407,36 @@ GCTAOnOffObservation::GCTAOnOffObservation(const GObservations& obs) : |
| 410 | 407 | m_on_spec += onoff->on_spec(); |
| 411 | 408 | m_off_spec += onoff->off_spec(); |
| 412 | 409 | |
| 413 | - // Compute background scaling factor contribution. Handle the case | |
| 414 | - // where there is no background response, which may happen if no | |
| 415 | - // IRF template exists. In that case we do not weight with the | |
| 416 | - // background response. | |
| 410 | + // Compute background scaling factor contribution | |
| 417 | 411 | for (int i = 0; i < m_on_spec.size(); ++i) { |
| 418 | 412 | double background = onoff->off_spec()["BACKRESP"][i]; |
| 419 | 413 | double alpha = onoff->on_spec().backscal(i); |
| 420 | - double scale = m_on_spec.backscal(i) + | |
| 421 | - ((background > 0.0) | |
| 422 | - ? alpha * background * onoff->on_spec().exposure() | |
| 423 | - : alpha * onoff->on_spec().exposure()); | |
| 424 | - m_on_spec.backscal(i,scale); | |
| 414 | + double scale = alpha * background * exposure; | |
| 415 | + m_on_spec.backscal(i, m_on_spec.backscal(i) + scale); | |
| 425 | 416 | } |
| 426 | 417 | |
| 427 | 418 | // Add ARF |
| 428 | - m_arf += arf_stacked * onoff->on_spec().exposure(); | |
| 419 | + m_arf += arf_stacked * exposure; | |
| 429 | 420 | |
| 430 | 421 | // Add number of background events/MeV from BACKRESP column |
| 431 | 422 | const std::vector<double>& src = onoff->off_spec()["BACKRESP"]; |
| 432 | 423 | std::vector<double>& dst = m_off_spec["BACKRESP"]; |
| 433 | 424 | for (int i = 0; i < dst.size(); ++i) { |
| 434 | - dst[i] += src[i] * onoff->on_spec().exposure(); | |
| 425 | + dst[i] += src[i] * exposure; | |
| 435 | 426 | } |
| 436 | 427 | |
| 437 | 428 | // Add RMF |
| 438 | 429 | for (int itrue = 0; itrue < m_rmf.ntrue(); ++itrue) { |
| 439 | - double arf = arf_stacked[itrue] * onoff->on_spec().exposure(); | |
| 430 | + double arf = arf_stacked[itrue] * exposure; | |
| 440 | 431 | for (int imeasured = 0; imeasured < m_rmf.nmeasured(); ++imeasured) { |
| 441 | 432 | m_rmf(itrue,imeasured) += rmf_stacked(itrue,imeasured) * arf; |
| 442 | 433 | } |
| 443 | 434 | } |
| 444 | 435 | |
| 445 | - // Add exposure | |
| 446 | - exposure += onoff->on_spec().exposure(); | |
| 447 | - | |
| 448 | - // Add ontime and livetime | |
| 449 | - m_ontime += onoff->ontime(); | |
| 450 | - m_livetime += onoff->livetime(); | |
| 436 | + // Add exposure, ontime and livetime | |
| 437 | + total_exposure += exposure; | |
| 438 | + m_ontime += onoff->ontime(); | |
| 439 | + m_livetime += onoff->livetime(); | |
| 451 | 440 | |
| 452 | 441 | // Update observation energy range |
| 453 | 442 | if (emin < emin_obs) { |
| ... | ... | @@ -461,9 +450,7 @@ GCTAOnOffObservation::GCTAOnOffObservation(const GObservations& obs) : |
| 461 | 450 | |
| 462 | 451 | } // endfor: looped over observations |
| 463 | 452 | |
| 464 | - // Compute stacked background scaling factor. Handle the case where there | |
| 465 | - // is no background response, which may happen if no IRF template exists. | |
| 466 | - // In that case we simply have to devide by the exposure. | |
| 453 | + // Compute stacked background scaling factor | |
| 467 | 454 | for (int i = 0; i < m_on_spec.size(); ++i) { |
| 468 | 455 | double norm = m_off_spec["BACKRESP"][i]; |
| 469 | 456 | if (norm > 0.0) { |
| ... | ... | @@ -471,8 +458,7 @@ GCTAOnOffObservation::GCTAOnOffObservation(const GObservations& obs) : |
| 471 | 458 | m_on_spec.backscal(i,scale); |
| 472 | 459 | } |
| 473 | 460 | else { |
| 474 | - double scale = m_on_spec.backscal(i) / exposure; | |
| 475 | - m_on_spec.backscal(i,scale); | |
| 461 | + m_on_spec.backscal(i,0.0); | |
| 476 | 462 | } |
| 477 | 463 | } |
| 478 | 464 | |
| ... | ... | @@ -487,15 +473,15 @@ GCTAOnOffObservation::GCTAOnOffObservation(const GObservations& obs) : |
| 487 | 473 | } |
| 488 | 474 | |
| 489 | 475 | // Compute ARF |
| 490 | - if (exposure > 0.0) { | |
| 491 | - m_arf /= exposure; | |
| 476 | + if (total_exposure > 0.0) { | |
| 477 | + m_arf /= total_exposure; | |
| 492 | 478 | } |
| 493 | 479 | |
| 494 | 480 | // Compute background events/MeV/sec and store them in BACKRESP column |
| 495 | - if (exposure > 0.0) { | |
| 481 | + if (total_exposure > 0.0) { | |
| 496 | 482 | std::vector<double>& backresp = m_off_spec["BACKRESP"]; |
| 497 | 483 | for (int i = 0; i < backresp.size(); ++i) { |
| 498 | - backresp[i] /= exposure; | |
| 484 | + backresp[i] /= total_exposure; | |
| 499 | 485 | } |
| 500 | 486 | } |
| 501 | 487 | |
| ... | ... | @@ -834,6 +820,122 @@ double GCTAOnOffObservation::likelihood(const GModels& models, |
| 834 | 820 | } |
| 835 | 821 | |
| 836 | 822 | |
| 823 | +/*********************************************************************** | |
| 824 | + * @brief Compute predicted gamma-ray counts for given model | |
| 825 | + * | |
| 826 | + * @param[in] models Model container. | |
| 827 | + * @return Model PHA with predicted gamma-ray counts. | |
| 828 | + * | |
| 829 | + * Returns spectrum of predicted number of source events in the On | |
| 830 | + * regions. | |
| 831 | + ***********************************************************************/ | |
| 832 | +GPha GCTAOnOffObservation::model_gamma(const GModels& models) const | |
| 833 | +{ | |
| 834 | + // Get number of model parameters in model container | |
| 835 | + int npars = models.npars(); | |
| 836 | + | |
| 837 | + // Create dummy gradient vectors to provide required argument to N_gamma | |
| 838 | + GVector dummy_grad(npars); | |
| 839 | + | |
| 840 | + // Initialise output spectrum | |
| 841 | + GEbounds ereco = m_on_spec.ebounds(); | |
| 842 | + GPha gammas = GPha(ereco); | |
| 843 | + | |
| 844 | + // Loop over all energy bins | |
| 845 | + for (int i = 0; i < m_on_spec.size(); ++i) { | |
| 846 | + gammas.fill(ereco.emean(i), N_gamma(models, i, &dummy_grad)); | |
| 847 | + } | |
| 848 | + | |
| 849 | + // Return predicted gamma-ray counts spectrum | |
| 850 | + return gammas; | |
| 851 | +} | |
| 852 | + | |
| 853 | + | |
| 854 | +/*********************************************************************** | |
| 855 | + * @brief Compute predicted background counts PHA for given model | |
| 856 | + * | |
| 857 | + * @param[in] models Model container. | |
| 858 | + * @return Model background PHA. | |
| 859 | + * | |
| 860 | + * Returns spectrum of predicted number of background events in the Off | |
| 861 | + * regions. The computation method changed depending on the statistic used | |
| 862 | + * to match the spectrum used for likelihood fitting. | |
| 863 | + * To be noted: for the WSTAT statistic the model background depends on | |
| 864 | + * on the model adopted for gamma rays, that therefore need to be passed | |
| 865 | + * to this function. | |
| 866 | + ***********************************************************************/ | |
| 867 | +GPha GCTAOnOffObservation::model_background(const GModels& models) const | |
| 868 | +{ | |
| 869 | + // Get number of model parameters in model container | |
| 870 | + int npars = models.npars(); | |
| 871 | + | |
| 872 | + // Create dummy gradient vectors to provide required argument to N_gamma | |
| 873 | + GVector dummy_grad(npars); | |
| 874 | + | |
| 875 | + // Initialise output spectrum | |
| 876 | + GEbounds ereco = m_on_spec.ebounds(); | |
| 877 | + GPha bgds = GPha(ereco); | |
| 878 | + | |
| 879 | + // Extract statistic for this observation | |
| 880 | + std::string statistic = gammalib::toupper(this->statistic()); | |
| 881 | + | |
| 882 | + // Loop over all energy bins | |
| 883 | + for (int i = 0; i < m_on_spec.size(); ++i) { | |
| 884 | + | |
| 885 | + // Initialise variable to store number of background counts | |
| 886 | + double nbgd = 0.0; | |
| 887 | + | |
| 888 | + // Choose background evaluation method based on fit statistics | |
| 889 | + | |
| 890 | + // CSTAT | |
| 891 | + if ((statistic == "POISSON") || (statistic == "CSTAT")) { | |
| 892 | + nbgd = N_bgd(models, i, &dummy_grad); | |
| 893 | + } | |
| 894 | + | |
| 895 | + // ... or Poisson statistic with measured background | |
| 896 | + else if (statistic == "WSTAT") { | |
| 897 | + | |
| 898 | + // Get number of On and Off counts | |
| 899 | + double non = m_on_spec[i]; | |
| 900 | + double noff = m_off_spec[i]; | |
| 901 | + | |
| 902 | + // Get background scaling | |
| 903 | + double alpha = m_on_spec.backscal(i); | |
| 904 | + | |
| 905 | + // Get number of gamma and background events (and corresponding | |
| 906 | + // spectral model gradients) | |
| 907 | + double ngam = N_gamma(models, i, &dummy_grad); | |
| 908 | + | |
| 909 | + // Initialise variables for likelihood computation | |
| 910 | + double nonpred = 0.0; | |
| 911 | + double dlogLdsky = 0.0; | |
| 912 | + double d2logLdsky2 = 0.0; | |
| 913 | + | |
| 914 | + // Perform likelihood profiling and derive likelihood value | |
| 915 | + // The number of background counts is updated to the profile value | |
| 916 | + double logL = wstat_value(non, noff, alpha, ngam, nonpred, nbgd, | |
| 917 | + dlogLdsky,d2logLdsky2); | |
| 918 | + | |
| 919 | + } // endelse: WSTAT | |
| 920 | + | |
| 921 | + // ... or unsupported | |
| 922 | + else { | |
| 923 | + std::string msg = "Invalid statistic \""+statistic+"\" encountered. " | |
| 924 | + "Either specify \"POISSON\", \"CSTAT\" or " | |
| 925 | + "\"WSTAT\"."; | |
| 926 | + throw GException::invalid_value(G_MODEL_BACKGROUND, msg); | |
| 927 | + } | |
| 928 | + | |
| 929 | + // Fill background spectrum | |
| 930 | + bgds.fill(ereco.emean(i), nbgd); | |
| 931 | + | |
| 932 | + } // endfor: looped over energy bins | |
| 933 | + | |
| 934 | + // Return model count spectrum | |
| 935 | + return bgds; | |
| 936 | +} | |
| 937 | + | |
| 938 | + | |
| 837 | 939 | /***********************************************************************//** |
| 838 | 940 | * @brief Print On/Off observation information |
| 839 | 941 | * |
| ... | ... | @@ -1470,13 +1572,15 @@ void GCTAOnOffObservation::compute_arf_cut(const GCTAObservation& obs, |
| 1470 | 1572 | * \f$\Omega_{{\rm off},p}\f$ is the solid angle in units of \f${\rm sr}\f$ |
| 1471 | 1573 | * of the pixel index \f$p\f$ in the Off region \f${\rm off}\f$. |
| 1472 | 1574 | * |
| 1473 | - * If @p use_irf_bkg is @c false, all `BACKRESP` elements will be set to | |
| 1474 | - * zero, i.e. | |
| 1575 | + * If @p use_irf_bkg is @c false, `BACKRESP` will be computed using | |
| 1475 | 1576 | * |
| 1476 | 1577 | * \f[ |
| 1477 | - * {\tt BACKRESP}(E_{\rm reco}) = 0 | |
| 1578 | + * {\tt BACKRESP}(E_{\rm reco}) = \sum_{\rm off} \sum_p \Omega_{{\rm off},p} | |
| 1478 | 1579 | * \f] |
| 1479 | 1580 | * |
| 1581 | + * which actually assumes that the background rate is constant over the | |
| 1582 | + * field of view. | |
| 1583 | + * | |
| 1480 | 1584 | * @todo Integrate background rate over energy bin instead of computing the |
| 1481 | 1585 | * rate at the energy bin centre. |
| 1482 | 1586 | ***************************************************************************/ |
| ... | ... | @@ -1494,12 +1598,12 @@ void GCTAOnOffObservation::compute_bgd(const GCTAObservation& obs, |
| 1494 | 1598 | // Initialise background rates to zero |
| 1495 | 1599 | std::vector<double> background(nreco, 0.0); |
| 1496 | 1600 | |
| 1601 | + // Get CTA observation pointing direction | |
| 1602 | + GCTAPointing obspnt = obs.pointing(); | |
| 1603 | + | |
| 1497 | 1604 | // Continue only if the IRF background template should be used |
| 1498 | 1605 | if (use_irf_bkg) { |
| 1499 | 1606 | |
| 1500 | - // Get CTA observation pointing direction | |
| 1501 | - GCTAPointing obspnt = obs.pointing(); | |
| 1502 | - | |
| 1503 | 1607 | // Get CTA background |
| 1504 | 1608 | const GCTABackground& bgd = gammalib::cta_rsp_bkg(G_COMPUTE_BGD, obs); |
| 1505 | 1609 | |
| ... | ... | @@ -1545,6 +1649,46 @@ void GCTAOnOffObservation::compute_bgd(const GCTAObservation& obs, |
| 1545 | 1649 | |
| 1546 | 1650 | } // endif: IRF background template was used |
| 1547 | 1651 | |
| 1652 | + // ... otherwise | |
| 1653 | + else { | |
| 1654 | + | |
| 1655 | + // Loop over regions | |
| 1656 | + for (int k = 0; k < off.size(); ++k) { | |
| 1657 | + | |
| 1658 | + // Get pointer on sky region map | |
| 1659 | + const GSkyRegionMap* off_map = | |
| 1660 | + static_cast<const GSkyRegionMap*>(off[k]); | |
| 1661 | + | |
| 1662 | + // Loop over pixels in Off region map and integrate | |
| 1663 | + // background rate | |
| 1664 | + for (int j = 0; j < off_map->nonzero_indices().size(); ++j) { | |
| 1665 | + | |
| 1666 | + // Get pixel index | |
| 1667 | + int pixidx = off_map->nonzero_indices()[j]; | |
| 1668 | + | |
| 1669 | + // Get direction to pixel center | |
| 1670 | + GSkyDir pixdir = off_map->map().inx2dir(pixidx); | |
| 1671 | + | |
| 1672 | + // Translate sky direction into instrument direction | |
| 1673 | + GCTAInstDir pixinstdir = obspnt.instdir(pixdir); | |
| 1674 | + | |
| 1675 | + // Get solid angle subtended by this pixel | |
| 1676 | + double pixsolid = off_map->map().solidangle(pixidx); | |
| 1677 | + | |
| 1678 | + // Loop over energy bins | |
| 1679 | + for (int i = 0; i < nreco; ++i) { | |
| 1680 | + | |
| 1681 | + // Get background rate in events/s/MeV | |
| 1682 | + background[i] += pixsolid; | |
| 1683 | + | |
| 1684 | + } // endfor: looped over energy bins | |
| 1685 | + | |
| 1686 | + } // endfor: looped over all pixels in map | |
| 1687 | + | |
| 1688 | + } // endfor: looped over all regions | |
| 1689 | + | |
| 1690 | + } // endelse: no IRF background template was used | |
| 1691 | + | |
| 1548 | 1692 | // Append background vector to Off spectrum |
| 1549 | 1693 | m_off_spec.append("BACKRESP", background); |
| 1550 | 1694 | |
| ... | ... | @@ -2318,122 +2462,6 @@ double GCTAOnOffObservation::N_bgd(const GModels& models, |
| 2318 | 2462 | } |
| 2319 | 2463 | |
| 2320 | 2464 | |
| 2321 | -/*********************************************************************** | |
| 2322 | - * @brief Compute predicted gamma-ray counts for given model | |
| 2323 | - * | |
| 2324 | - * @param[in] models Model container. | |
| 2325 | - * @return Model PHA with predicted gamma-ray counts. | |
| 2326 | - * | |
| 2327 | - * Returns spectrum of predicted number of source events in the On | |
| 2328 | - * regions. | |
| 2329 | - ***********************************************************************/ | |
| 2330 | -GPha GCTAOnOffObservation::model_gamma(const GModels& models) const | |
| 2331 | -{ | |
| 2332 | - // Get number of model parameters in model container | |
| 2333 | - int npars = models.npars(); | |
| 2334 | - | |
| 2335 | - // Create dummy gradient vectors to provide required argument to N_gamma | |
| 2336 | - GVector dummy_grad(npars); | |
| 2337 | - | |
| 2338 | - // Initialise output spectrum | |
| 2339 | - GEbounds ereco = m_on_spec.ebounds(); | |
| 2340 | - GPha gammas = GPha(ereco); | |
| 2341 | - | |
| 2342 | - // Loop over all energy bins | |
| 2343 | - for (int i = 0; i < m_on_spec.size(); ++i) { | |
| 2344 | - gammas.fill(ereco.emean(i), N_gamma(models, i, &dummy_grad)); | |
| 2345 | - } | |
| 2346 | - | |
| 2347 | - // Return predicted gamma-ray counts spectrum | |
| 2348 | - return gammas; | |
| 2349 | -} | |
| 2350 | - | |
| 2351 | - | |
| 2352 | -/*********************************************************************** | |
| 2353 | - * @brief Compute predicted background counts PHA for given model | |
| 2354 | - * | |
| 2355 | - * @param[in] models Model container. | |
| 2356 | - * @return Model background PHA. | |
| 2357 | - * | |
| 2358 | - * Returns spectrum of predicted number of background events in the Off | |
| 2359 | - * regions. The computation method changed depending on the statistic used | |
| 2360 | - * to match the spectrum used for likelihood fitting. | |
| 2361 | - * To be noted: for the WSTAT statistic the model background depends on | |
| 2362 | - * on the model adopted for gamma rays, that therefore need to be passed | |
| 2363 | - * to this function. | |
| 2364 | - ***********************************************************************/ | |
| 2365 | -GPha GCTAOnOffObservation::model_background(const GModels& models) const | |
| 2366 | -{ | |
| 2367 | - // Get number of model parameters in model container | |
| 2368 | - int npars = models.npars(); | |
| 2369 | - | |
| 2370 | - // Create dummy gradient vectors to provide required argument to N_gamma | |
| 2371 | - GVector dummy_grad(npars); | |
| 2372 | - | |
| 2373 | - // Initialise output spectrum | |
| 2374 | - GEbounds ereco = m_on_spec.ebounds(); | |
| 2375 | - GPha bgds = GPha(ereco); | |
| 2376 | - | |
| 2377 | - // Extract statistic for this observation | |
| 2378 | - std::string statistic = gammalib::toupper(this->statistic()); | |
| 2379 | - | |
| 2380 | - // Loop over all energy bins | |
| 2381 | - for (int i = 0; i < m_on_spec.size(); ++i) { | |
| 2382 | - | |
| 2383 | - // Initialise variable to store number of background counts | |
| 2384 | - double nbgd = 0.0; | |
| 2385 | - | |
| 2386 | - // Choose background evaluation method based on fit statistics | |
| 2387 | - | |
| 2388 | - // CSTAT | |
| 2389 | - if ((statistic == "POISSON") || (statistic == "CSTAT")) { | |
| 2390 | - nbgd = N_bgd(models, i, &dummy_grad); | |
| 2391 | - } | |
| 2392 | - | |
| 2393 | - // ... or Poisson statistic with measured background | |
| 2394 | - else if (statistic == "WSTAT") { | |
| 2395 | - | |
| 2396 | - // Get number of On and Off counts | |
| 2397 | - double non = m_on_spec[i]; | |
| 2398 | - double noff = m_off_spec[i]; | |
| 2399 | - | |
| 2400 | - // Get background scaling | |
| 2401 | - double alpha = m_on_spec.backscal(i); | |
| 2402 | - | |
| 2403 | - // Get number of gamma and background events (and corresponding | |
| 2404 | - // spectral model gradients) | |
| 2405 | - double ngam = N_gamma(models, i, &dummy_grad); | |
| 2406 | - | |
| 2407 | - // Initialise variables for likelihood computation | |
| 2408 | - double nonpred = 0.0; | |
| 2409 | - double dlogLdsky = 0.0; | |
| 2410 | - double d2logLdsky2 = 0.0; | |
| 2411 | - | |
| 2412 | - // Perform likelihood profiling and derive likelihood value | |
| 2413 | - // The number of background counts is updated to the profile value | |
| 2414 | - double logL = wstat_value(non, noff, alpha, ngam, nonpred, nbgd, | |
| 2415 | - dlogLdsky,d2logLdsky2); | |
| 2416 | - | |
| 2417 | - } // endelse: WSTAT | |
| 2418 | - | |
| 2419 | - // ... or unsupported | |
| 2420 | - else { | |
| 2421 | - std::string msg = "Invalid statistic \""+statistic+"\" encountered. " | |
| 2422 | - "Either specify \"POISSON\", \"CSTAT\" or " | |
| 2423 | - "\"WSTAT\"."; | |
| 2424 | - throw GException::invalid_value(G_MODEL_BACKGROUND, msg); | |
| 2425 | - } | |
| 2426 | - | |
| 2427 | - // Fill background spectrum | |
| 2428 | - bgds.fill(ereco.emean(i), nbgd); | |
| 2429 | - | |
| 2430 | - } // endfor: looped over energy bins | |
| 2431 | - | |
| 2432 | - // Return model count spectrum | |
| 2433 | - return bgds; | |
| 2434 | -} | |
| 2435 | - | |
| 2436 | - | |
| 2437 | 2465 | /***********************************************************************//** |
| 2438 | 2466 | * @brief Evaluate log-likelihood function for On/Off analysis in the |
| 2439 | 2467 | * case of Poisson signal with modeled Poisson background | ... | ... |