Commit 1a159a4ccaf6f71deee3e26d5b76c06d9ca9a616

Authored by L. Tibaldo
1 parent 1aa24101

implemented model_gamma e wstat value methods

inst/cta/include/GCTAOnOffObservation.hpp
... ... @@ -112,6 +112,7 @@ public:
112 112 const GPha& off_spec(void) const;
113 113 const GArf& arf(void) const;
114 114 const GRmf& rmf(void) const;
  115 + GPha model_gamma(const GModels& models) const;
115 116  
116 117 protected:
117 118 // Protected methods
... ... @@ -138,6 +139,14 @@ protected:
138 139 double N_bgd(const GModels& models, const int& ibin, GVector* grad) const;
139 140  
140 141 // Likelihood methods
  142 + double wstat_value(double non,
  143 + double noff,
  144 + double alpha,
  145 + double ngam,
  146 + double& nonpred,
  147 + double& nbgd,
  148 + double& dlogLdsky,
  149 + double& d2logLdsky2);
141 150 virtual double likelihood_cstat(const GModels& models,
142 151 GVector* gradient,
143 152 GMatrixSparse* curvature,
... ...
inst/cta/pyext/GCTAOnOffObservation.i
... ... @@ -116,6 +116,7 @@ public:
116 116 const GPha& off_spec(void) const;
117 117 const GArf& arf(void) const;
118 118 const GRmf& rmf(void) const;
  119 + GPha model_gamma(const GModels& models) const;
119 120 };
120 121  
121 122  
... ...
inst/cta/src/GCTAOnOffObservation.cpp
... ... @@ -1735,6 +1735,37 @@ double GCTAOnOffObservation::N_bgd(const GModels& models,
1735 1735 return value;
1736 1736 }
1737 1737  
  1738 +/***********************************************************************
  1739 + * @brief Compute predicted gamma-ray counts Pha for given model
  1740 + *
  1741 + * @param[in] models Model container.
  1742 + * @return model gamma Pha.
  1743 + *
  1744 + * Returns spectrum of predicted number of source events in the On regions
  1745 + *
  1746 + ***********************************************************************/
  1747 +GPha GCTAOnOffObservation::model_gamma(const GModels& models) const
  1748 +{
  1749 + // Get number of model parameters in model container
  1750 + int npars = models.npars();
  1751 +
  1752 + // Create dummy gradient vectors to provide required argument to N_gamma
  1753 + GVector dummy_grad(npars);
  1754 +
  1755 + // Initialise output Pha
  1756 + GEbounds ereco = m_arf.ebounds();
  1757 + GPha gammas = GPha(ereco);
  1758 +
  1759 + // Loop over all energy bins
  1760 + for (int i = 0; i < m_on_spec.size(); ++i) {
  1761 + double ngam = N_gamma(models, i, &dummy_grad);
  1762 + gammas.fill(ereco.emean(i),ngam);
  1763 + }
  1764 +
  1765 + // Return model coun pha
  1766 + return gammas;
  1767 +}
  1768 +
1738 1769  
1739 1770 /***********************************************************************//**
1740 1771 * @brief Evaluate log-likelihood function for On/Off analysis in the
... ... @@ -2062,6 +2093,303 @@ double GCTAOnOffObservation::likelihood_cstat(const GModels&amp; models,
2062 2093 return value;
2063 2094 }
2064 2095  
  2096 +/***********************************************************************//**
  2097 + * @brief Evaluate log-likelihood value in energy bin for On/Off analysis
  2098 + * by profiling over the number of background counts
  2099 + *
  2100 + * @param[in] non number of On counts
  2101 + * @param[in] noff number of Off counts
  2102 + * @param[in] alpha background scaling rate
  2103 + * @param[in] ngam number of predicted gamma-ray counts
  2104 + * @param[in,out] nonpred number of predicted On counts
  2105 + * @param[in,out] nbgd number of predicted background counts
  2106 + * @param[in,out] dlogLdsky first derivative of log-like w.r.t. sky pars
  2107 + * @param[in,out] d2logLdsky2 second derivative of log-like w.r.t. sky pars
  2108 + * @return Log-likelihood value.
  2109 + *
  2110 + * Computes the log-likelihood value for the On/Off observation in an energy bin
  2111 + * by treating the number of background counts as nuisance parameter. The method
  2112 + * performs an analytical minimisation of the Poisson likelihood and updates
  2113 + * the relevant values.
  2114 + * In the general case, the log-likelihood function is computed using
  2115 + *
  2116 + * \f[
  2117 + * L = \mu_s + (1+\alpha) \mu_b - n_{\rm on} - n_{\rm off} -
  2118 + * n_{\rm on} \left( \ln(\mu_s + \alpha \mu_b) - \ln(n_{\rm on})
  2119 + * \right) -
  2120 + * n_{\rm off} \left( \ln(\mu_b) - \ln(n_{\rm off}) \right)
  2121 + * \f]
  2122 + *
  2123 + * where
  2124 + *
  2125 + * \f[
  2126 + * \mu_b = \frac{C+D}{2\alpha(1+\alpha)}
  2127 + * \f]
  2128 + *
  2129 + * are the estimated number of background counts with
  2130 + *
  2131 + * \f[
  2132 + * C = \alpha (n_{\rm on} + n_{\rm off}) - (1 + \alpha) \mu_s
  2133 + * \f]
  2134 + *
  2135 + * and
  2136 + *
  2137 + * \f[
  2138 + * D = \sqrt{C^2 + 4 (1 + \alpha) \, \alpha \, n_{\rm off} \, \mu_s}
  2139 + * \f]
  2140 + *
  2141 + * \
  2142 + *
  2143 + * The first derivative of the log-likelihood function is given by
  2144 + *
  2145 + * \f[
  2146 + * \frac{\delta L}{\delta \mu_s} =
  2147 + * 1 + (1 + \alpha) \frac{\delta \mu_b}{\delta \mu_s} -
  2148 + * \frac{n_{\rm on}}{\mu_s + \alpha \mu_b} \left( 1 + \alpha
  2149 + * \frac{\delta \mu_b}{\delta \mu_s} \right) -
  2150 + * \frac{n_{\rm off}}{\mu_b} \frac{\delta \mu_b}{\delta \mu_s}
  2151 + * \f]
  2152 + *
  2153 + * with
  2154 + *
  2155 + * \f[
  2156 + * \frac{\delta \mu_b}{\delta \mu_s} =
  2157 + * \frac{n_{\rm off} - C}{D} - \frac{1}{2 \alpha}
  2158 + * \f]
  2159 + *
  2160 + * The second derivative of the log-likelihood function is given by
  2161 + *
  2162 + * \f[
  2163 + * \frac{\delta^2 L}{\delta \mu_s^2} =
  2164 + * \frac{n_{\rm on}}{(\mu_s + \alpha \mu_b)^2} \left( 1 + \alpha
  2165 + * \frac{\delta \mu_b}{\delta \mu_s} \right) +
  2166 + * \frac{\delta^2 \mu_b}{\delta \mu_s^2} \left( (1 + \alpha) -
  2167 + * \frac{\alpha n_{\rm on}}{\mu_s + \alpha \mu_b} -
  2168 + * \frac{n_{\rm off}}{\mu_b} \right) +
  2169 + * \frac{\delta \mu_b}{\delta \mu_s} \left(
  2170 + * \frac{\alpha n_{\rm on}}{(\mu_s + \alpha \mu_b)^2} \left(
  2171 + * 1 + \alpha \frac{\delta \mu_b}{\delta \mu_s} \right) +
  2172 + * \frac{n_{\rm off}}{\mu_b^2} \frac{\delta \mu_b}{\delta \mu_s}
  2173 + * \right)
  2174 + * \f]
  2175 + *
  2176 + * with
  2177 + *
  2178 + * \f[
  2179 + * \frac{\delta^2 \mu_b}{\delta \mu_s^2} =
  2180 + * \frac{-1}{2 \alpha} \left(
  2181 + * \frac{1}{D} \frac{\delta C}{\delta \mu_s} +
  2182 + * \frac{2 \alpha \, n_{\rm off} - C}{D^2} \frac{\delta D}{\delta \mu_s}
  2183 + * \right)
  2184 + * \f]
  2185 + *
  2186 + * where
  2187 + *
  2188 + * \f[
  2189 + * \frac{\delta C}{\delta \mu_s} = -(1 + \alpha)
  2190 + * \f]
  2191 + *
  2192 + * and
  2193 + *
  2194 + * \f[
  2195 + * \frac{\delta D}{\delta \mu_s} =
  2196 + * \frac{4 (1 + \alpha) \, \alpha \, n_{\rm off} - 2 \, C \, (1 + \alpha)}
  2197 + * {2D}
  2198 + * \f]
  2199 + *
  2200 + * In the special case \f$n_{\rm on}=n_{\rm off}=0\f$ the formal
  2201 + * background estimate becomes negative, hence we set \f$\mu_b=0\f$ and
  2202 + * the log-likelihood function becomes
  2203 + *
  2204 + * \f[
  2205 + * L = \mu_s
  2206 + * \f]
  2207 + *
  2208 + * the first derivative
  2209 + *
  2210 + * \f[
  2211 + * \frac{\delta L}{\delta \mu_s} = 1
  2212 + * \f]
  2213 + *
  2214 + * and the second derivative
  2215 + *
  2216 + * \f[
  2217 + * \frac{\delta^2 L}{\delta \mu_s^2} = 0
  2218 + * \f]
  2219 + *
  2220 + * In the special case \f$n_{\rm on}=0\f$ and \f$n_{\rm off}>0\f$
  2221 + * the log-likelihood function becomes
  2222 + *
  2223 + * \f[
  2224 + * L = \mu_s + n_{\rm off} \ln(1 + \alpha)
  2225 + * \f]
  2226 + *
  2227 + * the background estimate
  2228 + *
  2229 + * \f[
  2230 + * \mu_b = \frac{n_{\rm off}}{1+\alpha}
  2231 + * \f]
  2232 + *
  2233 + * the first derivative
  2234 + *
  2235 + * \f[
  2236 + * \frac{\delta L}{\delta \mu_s} = 1
  2237 + * \f]
  2238 + *
  2239 + * and the second derivative
  2240 + *
  2241 + * \f[
  2242 + * \frac{\delta^2 L}{\delta \mu_s^2} = 0
  2243 + * \f]
  2244 + *
  2245 + * In the special case \f$n_{\rm on}>0\f$ and \f$n_{\rm off}=0\f$
  2246 + * the background estimate becomes
  2247 + *
  2248 + * \f[
  2249 + * \mu_b = \frac{n_{\rm on}}{1+\alpha} - \frac{\mu_s}{\alpha}
  2250 + * \f]
  2251 + *
  2252 + * which is positive for
  2253 + *
  2254 + * \f[
  2255 + * \mu_s < n_{\rm on} \frac{\alpha}{1+\alpha}
  2256 + * \f]
  2257 + *
  2258 + * For positive \f$\mu_b\f$ the log-likelihood function is given by
  2259 + *
  2260 + * \f[
  2261 + * L = -\frac{\mu_s}{\alpha}
  2262 + * - n_{\rm on} \ln \left(\frac{\alpha}{1 + \alpha} \right)
  2263 + * \f]
  2264 + *
  2265 + * the first derivative
  2266 + *
  2267 + * \f[
  2268 + * \frac{\delta L}{\delta \mu_s} = -\frac{1}{\alpha}
  2269 + * \f]
  2270 + *
  2271 + * and the second derivative
  2272 + *
  2273 + * \f[
  2274 + * \frac{\delta^2 L}{\delta \mu_s^2} = 0
  2275 + * \f]
  2276 + *
  2277 + * For negative \f$\mu_b\f$ we set \f$\mu_b=0\f$ and the log-likelihood
  2278 + * function becomes
  2279 + *
  2280 + * \f[
  2281 + * L = \mu_s - n_{\rm on} -
  2282 + * n_{\rm on} \left( \ln(\mu_s) - \ln(n_{\rm on}) \right)
  2283 + * \f]
  2284 + *
  2285 + * the first derivative
  2286 + *
  2287 + * \f[
  2288 + * \frac{\delta L}{\delta \mu_s} = 1 - \frac{n_{\rm on}}{\mu_s}
  2289 + * \f]
  2290 + *
  2291 + * and the second derivative
  2292 + *
  2293 + * \f[
  2294 + * \frac{\delta^2 L}{\delta \mu_s^2} = \frac{1}{\mu_s^2}
  2295 + * \f]
  2296 + *
  2297 + * Note that the fit results may be biased and the statistical errors
  2298 + * overestimated if for some bins \f$n_{\rm on}=0\f$ and/or
  2299 + * \f$n_{\rm off}=0\f$ (i.e. if the special cases are encountered).
  2300 + ***********************************************************************/
  2301 +
  2302 +double wstat_value(double non,
  2303 + double noff,
  2304 + double alpha,
  2305 + double ngam,
  2306 + double& nonpred,
  2307 + double& nbgd,
  2308 + double& dlogLdsky,
  2309 + double& d2logLdsky2)
  2310 +{
  2311 + // Initialise log-likelihood value
  2312 + double logL;
  2313 +
  2314 + // Precompute some values
  2315 + double alphap1 = alpha + 1.0;
  2316 + double alpharat = alpha / alphap1;
  2317 +
  2318 + // Calculate number of background events, profile likelihood value
  2319 + // and likelihood derivatives
  2320 +
  2321 + // Special case noff = 0
  2322 + if (noff == 0.0) {
  2323 +
  2324 + // Case A: non = 0. In this case nbgd < 0 hence we set nbgd = 0
  2325 + if (non == 0.0) {
  2326 + nonpred = ngam;
  2327 + logL = ngam;
  2328 + dlogLdsky = 1.0;
  2329 + d2logLdsky2 = 0.0;
  2330 + }
  2331 +
  2332 + // Case B: nbgd is positive
  2333 + else if (ngam < non * alpharat) {
  2334 + double nbgd = non / alphap1 - ngam / alpha;
  2335 + nonpred = ngam + alpha * nbgd;
  2336 + logL = -ngam / alpha - non * std::log(alpharat);
  2337 + dlogLdsky = -1.0/alpha;
  2338 + d2logLdsky2 = 0.0;
  2339 + }
  2340 +
  2341 + // Case C: nbgd is zero or negative, hence set nbgd = 0
  2342 + else {
  2343 + nonpred = ngam;
  2344 + logL = ngam + non * (std::log(non) - std::log(ngam) - 1.0);
  2345 + dlogLdsky = 1.0 - non / ngam;
  2346 + d2logLdsky2 = non / (ngam * ngam);
  2347 + }
  2348 +
  2349 + } // endif: noff = 0
  2350 +
  2351 + // Special case non = 0
  2352 + else if (non == 0.0) {
  2353 + nonpred = ngam + alpharat * noff;
  2354 + logL = ngam + noff * std::log(alphap1);
  2355 + dlogLdsky = 1.0;
  2356 + d2logLdsky2 = 0.0;
  2357 + } // endif: non = 0
  2358 +
  2359 + // General case
  2360 + else {
  2361 +
  2362 + // Compute log-likelihood value
  2363 + double alphat2 = 2.0 * alpha;
  2364 + double C = alpha * (non + noff) - alphap1 * ngam;
  2365 + double D = std::sqrt(C*C + 4.0 * alpha * alphap1 * noff * ngam);
  2366 + double nbgd = (C + D) / (alphat2 * alphap1);
  2367 + nonpred = ngam + alpha * nbgd;
  2368 + logL = ngam + alphap1 * nbgd - non - noff -
  2369 + non * (std::log(nonpred) - std::log(non)) -
  2370 + noff * (std::log(nbgd) - std::log(noff));
  2371 +
  2372 + // Compute derivatives
  2373 + double f0 = alphat2 * noff - C;
  2374 + double dCds = -alphap1;
  2375 + double dDds = (C * dCds + 2.0 * alphap1 * alpha * noff) / D;
  2376 + double dbds = (f0 / D - 1.0) / alphat2;
  2377 + double d2bds2 = (-dCds / D - f0 / (D*D) * dDds) / alphat2;
  2378 + double f1 = alphap1 - alpha*non/nonpred - noff/nbgd;
  2379 + double f2 = nonpred * nonpred;
  2380 + double dpds = 1.0 + alpha * dbds;
  2381 + double f3 = non / f2 * dpds;
  2382 + dlogLdsky = 1.0 - non / nonpred + dbds * f1;
  2383 + d2logLdsky2 = f3 + d2bds2 * f1 +
  2384 + dbds * (alpha * f3 + noff / (nbgd*nbgd) * dbds);
  2385 +
  2386 + } // endelse: general case
  2387 +
  2388 + // Return
  2389 + return logL;
  2390 +}
  2391 +
  2392 +
2065 2393  
2066 2394 /***********************************************************************//**
2067 2395 * @brief Evaluate log-likelihood function for On/Off analysis in the
... ...