Commit 1fc91b4a17a5008f63b178ab79e19719bf286370
1 parent
a423b3ab
Add vetorate method for DRW computation (#4209)
Showing
4 changed files
with
1045 additions
and
48 deletions
inst/com/include/GCOMDris.hpp
... | ... | @@ -30,10 +30,13 @@ |
30 | 30 | /* __ Includes ___________________________________________________________ */ |
31 | 31 | #include <string> |
32 | 32 | #include <vector> |
33 | -#include "GCOMDri.hpp" | |
34 | 33 | #include "GContainer.hpp" |
34 | +#include "GNdarray.hpp" | |
35 | +#include "GOptimizerFunction.hpp" | |
36 | +#include "GCOMDri.hpp" | |
35 | 37 | |
36 | 38 | /* __ Forward declarations _______________________________________________ */ |
39 | +class GOptimizer; | |
37 | 40 | class GCOMObservation; |
38 | 41 | class GCOMEventList; |
39 | 42 | class GCOMSelection; |
... | ... | @@ -80,9 +83,38 @@ public: |
80 | 83 | const GCOMSelection& select = GCOMSelection(), |
81 | 84 | const double& zetamin = 5.0, |
82 | 85 | const double& timebin = 300.0, |
83 | - const std::string& method = "phibar"); | |
86 | + const std::string& method = "vetorate"); | |
84 | 87 | std::string print(const GChatter& chatter = NORMAL) const; |
85 | 88 | |
89 | + // Likelihood function | |
90 | + class likelihood : public GOptimizerFunction { | |
91 | + public: | |
92 | + // Constructors and destructors | |
93 | + likelihood(GCOMDris *dris, const int& ieng, const double& norm); | |
94 | + | |
95 | + // Implemented pure virtual base class methods | |
96 | + virtual void eval(const GOptimizerPars& pars); | |
97 | + virtual double value(void) const; | |
98 | + virtual GVector* gradient(void); | |
99 | + virtual GMatrixSparse* curvature(void); | |
100 | + | |
101 | + protected: | |
102 | + int m_ieng; //!< DRW energy bin | |
103 | + double m_norm; //!< Normalisation value | |
104 | + int m_noads; //!< Number of superpackets | |
105 | + int m_nphibar; //!< Number of phibar layers | |
106 | + GNdarray m_vetorate; //!< Vetorate array multiplied by EHA cut correction | |
107 | + GNdarray m_constrate; //!< Constant rate array multiplied by EHA cut correction | |
108 | + GNdarray m_diffrate; //!< Vetorate - Constant rate array | |
109 | + GNdarray m_vetorate_sum; //!< Time integrated vetorate array | |
110 | + GNdarray m_constrate_sum; //!< Time integrated constant rate array | |
111 | + GNdarray m_diffrate_sum; //!< Time integrated difference rate array | |
112 | + double m_value; //!< Function value | |
113 | + GVector m_gradient; //!< Gradient vector | |
114 | + GMatrixSparse m_curvature; //!< Curvature matrix | |
115 | + GCOMDris* m_this; //!< Pointer to GCOMDris object | |
116 | + }; | |
117 | + | |
86 | 118 | protected: |
87 | 119 | // Protected methods |
88 | 120 | void init_members(void); |
... | ... | @@ -98,9 +130,31 @@ protected: |
98 | 130 | const GCOMSelection& select, |
99 | 131 | const double& zetamin, |
100 | 132 | const double& timebin); |
133 | + void compute_drws_vetorate(const GCOMObservation& obs, | |
134 | + const GCOMEventList* events, | |
135 | + const GCOMSelection& select, | |
136 | + const double& zetamin); | |
137 | + void vetorate_setup(const GCOMObservation& obs, | |
138 | + const GCOMEventList* events, | |
139 | + const GCOMSelection& select, | |
140 | + const double& zetamin); | |
141 | + void vetorate_fit(void); | |
142 | + void vetorate_generate(const GCOMObservation& obs, | |
143 | + const GCOMSelection& select, | |
144 | + const double& zetamin); | |
145 | + void vetorate_save(const GFilename& filename) const; | |
146 | + void vetorate_load(const GFilename& filename); | |
101 | 147 | |
102 | 148 | // Protected data members |
103 | 149 | std::vector<GCOMDri> m_dris; //!< Data space instances |
150 | + | |
151 | + // Working arrays for vetorate computation | |
152 | + GNdarray m_wrk_counts; //!< 3D event cube array | |
153 | + GNdarray m_wrk_ehacutcorr; //!< 2D geometry response array | |
154 | + GNdarray m_wrk_vetorate; //!< 1D vetorates array | |
155 | + GNdarray m_wrk_constrate; //!< 1D constant rate array | |
156 | + GNdarray m_wrk_rate; //!< 2D rate array | |
157 | + std::vector<bool> m_wrk_use_sp; //!< 1D superpacket usage array | |
104 | 158 | }; |
105 | 159 | |
106 | 160 | |
... | ... | @@ -187,4 +241,46 @@ void GCOMDris::reserve(const int& num) |
187 | 241 | return; |
188 | 242 | } |
189 | 243 | |
244 | + | |
245 | +/***********************************************************************//** | |
246 | + * @brief Return log-likelihood value of optimizer function | |
247 | + * | |
248 | + * @return Log-likelihood value of optimizer function. | |
249 | + * | |
250 | + * Returns the log-likelihood value of optimizer function. | |
251 | + ***************************************************************************/ | |
252 | +inline | |
253 | +double GCOMDris::likelihood::value(void) const | |
254 | +{ | |
255 | + return m_value; | |
256 | +} | |
257 | + | |
258 | + | |
259 | +/***********************************************************************//** | |
260 | + * @brief Return pointer to gradient vector | |
261 | + * | |
262 | + * @return Pointer to gradient vector. | |
263 | + * | |
264 | + * Returns a pointer to the parameter gradient vector. | |
265 | + ***************************************************************************/ | |
266 | +inline | |
267 | +GVector* GCOMDris::likelihood::gradient(void) | |
268 | +{ | |
269 | + return &(m_gradient); | |
270 | +} | |
271 | + | |
272 | + | |
273 | +/***********************************************************************//** | |
274 | + * @brief Return pointer to curvature matrix | |
275 | + * | |
276 | + * @return Pointer to curvature matrix. | |
277 | + * | |
278 | + * Returns a pointer to the parameter curvature matrix. | |
279 | + ***************************************************************************/ | |
280 | +inline | |
281 | +GMatrixSparse* GCOMDris::likelihood::curvature(void) | |
282 | +{ | |
283 | + return &(m_curvature); | |
284 | +} | |
285 | + | |
190 | 286 | #endif /* GCOMDRIS_HPP */ | ... | ... |
inst/com/pyext/GCOMDris.i
inst/com/src/GCOMDris.cpp
... | ... | @@ -32,6 +32,12 @@ |
32 | 32 | #include <iostream> |
33 | 33 | #include "GException.hpp" |
34 | 34 | #include "GMath.hpp" |
35 | +#include "GFits.hpp" | |
36 | +#include "GFitsImageDouble.hpp" | |
37 | +#include "GFitsImageShort.hpp" | |
38 | +#include "GOptimizerPars.hpp" | |
39 | +#include "GOptimizerPar.hpp" | |
40 | +#include "GOptimizerLM.hpp" | |
35 | 41 | #include "GCOMTools.hpp" |
36 | 42 | #include "GCOMSupport.hpp" |
37 | 43 | #include "GCOMDri.hpp" |
... | ... | @@ -58,7 +64,8 @@ |
58 | 64 | #define G_COMPUTE_DRWS_EHACORR //!< Correct Earth horizon cut |
59 | 65 | |
60 | 66 | /* __ Debug definitions __________________________________________________ */ |
61 | -//#define G_DEBUG_COMPUTE_DRWS | |
67 | +#define G_DEBUG_COMPUTE_DRWS | |
68 | +#define G_DEBUG_SAVE_WORKING_ARRAYS | |
62 | 69 | |
63 | 70 | /* __ Constants __________________________________________________________ */ |
64 | 71 | |
... | ... | @@ -351,7 +358,7 @@ void GCOMDris::extend(const GCOMDris& dris) |
351 | 358 | * @param[in] select Selection set. |
352 | 359 | * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg). |
353 | 360 | * @param[in] timebin Time binning for rate determination (sec). |
354 | - * @param[in] method Method to compute DRWs ("energy" or "phibar"). | |
361 | + * @param[in] method Method to compute DRWs ("energy", "phibar" or "vetorate"). | |
355 | 362 | * |
356 | 363 | * @exception GException::invalid_value |
357 | 364 | * DRW with mismatching definition encountered in container. |
... | ... | @@ -407,6 +414,9 @@ void GCOMDris::compute_drws(const GCOMObservation& obs, |
407 | 414 | // Set all DRG bins to zero |
408 | 415 | m_dris[i].init_cube(); |
409 | 416 | |
417 | + // Set DRW header method parameter | |
418 | + m_dris[i].m_drw_method = method; | |
419 | + | |
410 | 420 | // Debug |
411 | 421 | #if defined(G_DEBUG_COMPUTE_DRWS) |
412 | 422 | std::cout << m_dris[i].print() << std::endl; |
... | ... | @@ -433,6 +443,11 @@ void GCOMDris::compute_drws(const GCOMObservation& obs, |
433 | 443 | compute_drws_phibar(obs, events, select, zetamin, timebin); |
434 | 444 | } |
435 | 445 | |
446 | + // Method C: Veto rate weighting | |
447 | + else if (method == "vetorate") { | |
448 | + compute_drws_vetorate(obs, events, select, zetamin); | |
449 | + } | |
450 | + | |
436 | 451 | // Normalise Phibar layers of all DRWs to unity |
437 | 452 | for (int i = 0; i < size(); ++i) { |
438 | 453 | |
... | ... | @@ -512,6 +527,14 @@ void GCOMDris::init_members(void) |
512 | 527 | // Initialise members |
513 | 528 | m_dris.clear(); |
514 | 529 | |
530 | + // Initialise working arrays | |
531 | + m_wrk_counts.clear(); | |
532 | + m_wrk_ehacutcorr.clear(); | |
533 | + m_wrk_vetorate.clear(); | |
534 | + m_wrk_constrate.clear(); | |
535 | + m_wrk_rate.clear(); | |
536 | + m_wrk_use_sp.clear(); | |
537 | + | |
515 | 538 | // Return |
516 | 539 | return; |
517 | 540 | } |
... | ... | @@ -527,6 +550,14 @@ void GCOMDris::copy_members(const GCOMDris& dris) |
527 | 550 | // Copy members |
528 | 551 | m_dris = dris.m_dris; |
529 | 552 | |
553 | + // Copy working arrays | |
554 | + m_wrk_counts = dris.m_wrk_counts; | |
555 | + m_wrk_ehacutcorr = dris.m_wrk_ehacutcorr; | |
556 | + m_wrk_vetorate = dris.m_wrk_vetorate; | |
557 | + m_wrk_constrate = dris.m_wrk_constrate; | |
558 | + m_wrk_rate = dris.m_wrk_rate; | |
559 | + m_wrk_use_sp = dris.m_wrk_use_sp; | |
560 | + | |
530 | 561 | // Return |
531 | 562 | return; |
532 | 563 | } |
... | ... | @@ -546,7 +577,7 @@ void GCOMDris::free_members(void) |
546 | 577 | * @brief Compute background weighting cubes using energy dependent rates |
547 | 578 | * |
548 | 579 | * @param[in] obs COMPTEL observation. |
549 | - * @param[in] event COMPTEL event list. | |
580 | + * @param[in] events COMPTEL event list. | |
550 | 581 | * @param[in] select Selection set. |
551 | 582 | * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg). |
552 | 583 | * @param[in] timebin Time binning for rate determination (sec). |
... | ... | @@ -869,7 +900,7 @@ void GCOMDris::compute_drws_energy(const GCOMObservation& obs, |
869 | 900 | * @brief Compute background weighting cubes using Phibar dependent rates |
870 | 901 | * |
871 | 902 | * @param[in] obs COMPTEL observation. |
872 | - * @param[in] event COMPTEL event list. | |
903 | + * @param[in] events COMPTEL event list. | |
873 | 904 | * @param[in] select Selection set. |
874 | 905 | * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg). |
875 | 906 | * @param[in] timebin Time binning for rate determination (sec). |
... | ... | @@ -1199,3 +1230,881 @@ void GCOMDris::compute_drws_phibar(const GCOMObservation& obs, |
1199 | 1230 | // Return |
1200 | 1231 | return; |
1201 | 1232 | } |
1233 | + | |
1234 | + | |
1235 | +/***********************************************************************//** | |
1236 | + * @brief Compute background weighting cubes using veto rates | |
1237 | + * | |
1238 | + * @param[in] obs COMPTEL observation. | |
1239 | + * @param[in] events COMPTEL event list. | |
1240 | + * @param[in] select Selection set. | |
1241 | + * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg). | |
1242 | + * | |
1243 | + * Compute DRW cubes for a COMPTEL observation. DRW cubes are event-rate | |
1244 | + * weighted geometry cubes which were multiplied by the solid angle of | |
1245 | + * the (Chi,Psi) pixels. | |
1246 | + ***************************************************************************/ | |
1247 | +void GCOMDris::compute_drws_vetorate(const GCOMObservation& obs, | |
1248 | + const GCOMEventList* events, | |
1249 | + const GCOMSelection& select, | |
1250 | + const double& zetamin) | |
1251 | +{ | |
1252 | + // Debug | |
1253 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1254 | + std::cout << "GCOMDris::compute_drws_vetorate" << std::endl; | |
1255 | + std::cout << "===============================" << std::endl; | |
1256 | + #endif | |
1257 | + | |
1258 | + // Setup working arrays | |
1259 | + vetorate_setup(obs, events, select, zetamin); | |
1260 | + | |
1261 | + // Debug: Save working arrays in FITS file | |
1262 | + #if defined(G_DEBUG_SAVE_WORKING_ARRAYS) | |
1263 | + vetorate_save("debug_gcomdris_compute_drws_vetorate.fits"); | |
1264 | + vetorate_load("debug_gcomdris_compute_drws_vetorate.fits"); | |
1265 | + #endif | |
1266 | + | |
1267 | + // Fit working arrays to determine f_prompt parameter | |
1268 | + vetorate_fit(); | |
1269 | + | |
1270 | + // Generate DRWs | |
1271 | + vetorate_generate(obs, select, zetamin); | |
1272 | + | |
1273 | + // Return | |
1274 | + return; | |
1275 | +} | |
1276 | + | |
1277 | + | |
1278 | +/***********************************************************************//** | |
1279 | + * @brief Setup working arrays for vetorate computation | |
1280 | + * | |
1281 | + * @param[in] obs COMPTEL observation. | |
1282 | + * @param[in] events COMPTEL event list. | |
1283 | + * @param[in] select Selection set. | |
1284 | + * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg). | |
1285 | + * | |
1286 | + * Setup working arrays for vetorate DRW computation. There are four working | |
1287 | + * arrays: | |
1288 | + * | |
1289 | + * @c m_wrk_counts is a 3D working array spanned by superpacket index, | |
1290 | + * phibar layer and energy bin, containing the number of events passing the | |
1291 | + * event selections for the specified bin. | |
1292 | + * | |
1293 | + * @c m_wrk_ehacutcorr is a 2D working array spanned by superpacket index | |
1294 | + * and phibar layer, containing the fraction of the solid-angle weighted | |
1295 | + * geometry that passes the Earth horizon cut for the specified bin. This | |
1296 | + * array represents the response to a given incident event rate. | |
1297 | + * | |
1298 | + * @c m_wrk_vetorate is a 1D working array, containing the veto rate as | |
1299 | + * function of superpacket index. | |
1300 | + * | |
1301 | + * @c m_wrk_use_sp is a 1D working array, signalling the usage of a given | |
1302 | + * superpacket. | |
1303 | + * | |
1304 | + * Note that the method also sets the superpacket usage and event selection | |
1305 | + * statistics of all DRWs. | |
1306 | + ***************************************************************************/ | |
1307 | +void GCOMDris::vetorate_setup(const GCOMObservation& obs, | |
1308 | + const GCOMEventList* events, | |
1309 | + const GCOMSelection& select, | |
1310 | + const double& zetamin) | |
1311 | +{ | |
1312 | + // Debug | |
1313 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1314 | + std::cout << "GCOMDris::vetorate_setup" << std::endl; | |
1315 | + std::cout << "========================" << std::endl; | |
1316 | + #endif | |
1317 | + | |
1318 | + // Initialise D1 & D2 module status | |
1319 | + GCOMStatus status; | |
1320 | + | |
1321 | + // Get pointer to first DRW (assume their definition is identical) | |
1322 | + const GCOMDri* dri0 = &(m_dris[0]); | |
1323 | + | |
1324 | + // Extract dimensions | |
1325 | + int noads = obs.oads().size(); | |
1326 | + int npix = dri0->m_dri.npix(); | |
1327 | + int nphibar = dri0->nphibar(); | |
1328 | + int neng = size(); | |
1329 | + | |
1330 | + // Debug | |
1331 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1332 | + std::cout << "Number of superpackets: " << noads << std::endl; | |
1333 | + std::cout << "Number of pixels: " << npix << std::endl; | |
1334 | + std::cout << "Number of Phibar layers: " << nphibar << std::endl; | |
1335 | + std::cout << "Number of energies: " << neng << std::endl; | |
1336 | + #endif | |
1337 | + | |
1338 | + // Define working arrays | |
1339 | + m_wrk_counts = GNdarray(noads, nphibar, neng); | |
1340 | + m_wrk_ehacutcorr = GNdarray(noads, nphibar); | |
1341 | + m_wrk_vetorate = GNdarray(noads); | |
1342 | + m_wrk_use_sp = std::vector<bool>(noads); | |
1343 | + | |
1344 | + // Allocate further working arrays | |
1345 | + GNdarray geo(npix); | |
1346 | + GNdarray eha(npix); | |
1347 | + | |
1348 | + // Setup node array and rate vector for veto rate interpolation | |
1349 | + const GCOMHkd& hdk = obs.hkds()["SCV2M"]; | |
1350 | + GNodeArray veto_times; | |
1351 | + std::vector<double> veto_rates; | |
1352 | + veto_times.reserve(hdk.size()); | |
1353 | + veto_rates.reserve(hdk.size()); | |
1354 | + for (int i = 0; i < hdk.size(); ++i) { | |
1355 | + double rate = hdk.value(i); | |
1356 | + if (rate > 0.0) { | |
1357 | + veto_times.append(hdk.time(i).secs()); | |
1358 | + veto_rates.push_back(rate); | |
1359 | + } | |
1360 | + } | |
1361 | + | |
1362 | + // Setup sky directions and solid angles for all (Chi, Psi) | |
1363 | + std::vector<GSkyDir> skys; | |
1364 | + std::vector<double> omegas; | |
1365 | + for (int index = 0; index < dri0->m_dri.npix(); ++index) { | |
1366 | + GSkyDir sky = dri0->m_dri.inx2dir(index); | |
1367 | + double omega = dri0->m_dri.solidangle(index); | |
1368 | + skys.push_back(sky); | |
1369 | + omegas.push_back(omega); | |
1370 | + } | |
1371 | + | |
1372 | + // Debug | |
1373 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1374 | + std::cout << "Setup node array for veto rate interpolation: "; | |
1375 | + std::cout << veto_times.size() << " times, "; | |
1376 | + std::cout << veto_rates.size() << " rates" << std::endl; | |
1377 | + #endif | |
1378 | + | |
1379 | + // Get Good Time Intervals. If a pulsar selection is specified then | |
1380 | + // reduce the Good Time Intervals to the validity intervals of the | |
1381 | + // pulsar emphemerides. | |
1382 | + GCOMTim tim = obs.tim(); | |
1383 | + if (select.has_pulsar()) { | |
1384 | + tim.reduce(select.pulsar().validity()); | |
1385 | + } | |
1386 | + | |
1387 | + // Initialise event counter | |
1388 | + int i_evt = 0; | |
1389 | + | |
1390 | + // Signal that loop should be terminated | |
1391 | + bool terminate = false; | |
1392 | + | |
1393 | + // Loop over Orbit Aspect Data | |
1394 | + for (int i_oad = 0; i_oad < noads; ++i_oad) { | |
1395 | + | |
1396 | + // Get reference to Orbit Aspect Data of superpacket | |
1397 | + const GCOMOad &oad = obs.oads()[i_oad]; | |
1398 | + | |
1399 | + // Check superpacket usage for all DRWs so that their statistics | |
1400 | + // get correctly updated | |
1401 | + m_wrk_use_sp[i_oad] = true; | |
1402 | + for (int i = 0; i < size(); ++i) { | |
1403 | + if (!m_dris[i].use_superpacket(oad, tim, select)) { | |
1404 | + m_wrk_use_sp[i_oad] = false; | |
1405 | + } | |
1406 | + } | |
1407 | + if (!m_wrk_use_sp[i_oad]) { | |
1408 | + continue; | |
1409 | + } | |
1410 | + | |
1411 | + // Get Orbit Aspect Data mid-time in seconds | |
1412 | + double time = oad.tstart().secs() + 0.5 * (oad.tstop() - oad.tstart()); | |
1413 | + | |
1414 | + // Prepare Earth horizon angle computation. The celestial system | |
1415 | + // is reinterpreted as the COMPTEL coordinate system, where the | |
1416 | + // 90 degrees - zenith angle becomes the declination and the azimuth | |
1417 | + // angle becomes Right Ascension. This allows us later to use the | |
1418 | + // GSkyDir::dist method to compute the distance between the geocentre | |
1419 | + // and the telescope Z-axis. | |
1420 | + double theta_geocentre = double(oad.gcel()); | |
1421 | + double phi_geocentre = double(oad.gcaz()); | |
1422 | + GSkyDir geocentre_comptel; | |
1423 | + geocentre_comptel.radec_deg(phi_geocentre, 90.0-theta_geocentre); | |
1424 | + | |
1425 | + // Compute solid-angle-corrected geometry factors and Earth horizon | |
1426 | + // angles for all (Chi,Psi) pixels | |
1427 | + double total_geo = 0.0; | |
1428 | + for (int index = 0; index < npix; ++index) { | |
1429 | + | |
1430 | + // Convert sky direction to COMPTEL coordinates | |
1431 | + double theta = oad.theta(skys[index]); | |
1432 | + double phi = oad.phi(skys[index]); | |
1433 | + | |
1434 | + // Compute geometric factor summed over all D1, D2 times | |
1435 | + // the solid angle of the weighting cube pixel | |
1436 | + double geometry = dri0->compute_geometry(oad.tjd(), theta, phi, | |
1437 | + select, status) * omegas[index]; | |
1438 | + | |
1439 | + // Store and sum up geometric factor | |
1440 | + geo(index) = geometry; | |
1441 | + total_geo += geometry; | |
1442 | + | |
1443 | + // Compute Earth horizon angle as the distance between the Earth | |
1444 | + // centre in COMPTEL coordinates and the (Chi, Psi) pixel in | |
1445 | + // COMPTEL coordinates minus the radius of the Earth. | |
1446 | + GSkyDir chipsi_comptel; | |
1447 | + chipsi_comptel.radec_deg(phi, 90.0-theta); | |
1448 | + eha(index) = geocentre_comptel.dist_deg(chipsi_comptel) - oad.georad(); | |
1449 | + | |
1450 | + } // endfor: looped over (Chi, Psi) | |
1451 | + | |
1452 | + // Compute Earth horizon cut correction factor for all Phibar layers | |
1453 | + if (total_geo > 0.0) { | |
1454 | + for (int iphibar = 0; iphibar < nphibar; ++iphibar) { | |
1455 | + double ehamin = double(iphibar) * dri0->m_phibin + zetamin; | |
1456 | + double accepted_geo = 0.0; | |
1457 | + for (int index = 0; index < npix; ++index) { | |
1458 | + if (eha(index) >= ehamin) { | |
1459 | + accepted_geo += geo(index); | |
1460 | + } | |
1461 | + } | |
1462 | + m_wrk_ehacutcorr(i_oad, iphibar) = accepted_geo / total_geo; | |
1463 | + } | |
1464 | + } | |
1465 | + | |
1466 | + // Compute veto rate for superpacket time if rates are available | |
1467 | + if (!veto_times.is_empty()) { | |
1468 | + double value = veto_times.interpolate(time, veto_rates); | |
1469 | + if (value > 0.0) { | |
1470 | + m_wrk_vetorate(i_oad) = value; | |
1471 | + } | |
1472 | + } | |
1473 | + | |
1474 | + // Collect all events within superpacket and store result in 3D array. | |
1475 | + // Break if the end of the event list was reached. | |
1476 | + for (; i_evt < events->size(); ++i_evt) { | |
1477 | + | |
1478 | + // Get pointer to event | |
1479 | + const GCOMEventAtom* event = (*events)[i_evt]; | |
1480 | + | |
1481 | + // Break loop if the end of the superpacket was reached | |
1482 | + if (event->time() > oad.tstop()) { | |
1483 | + break; | |
1484 | + } | |
1485 | + | |
1486 | + // Determine energy bin | |
1487 | + int ienergy = -1; | |
1488 | + for (int i = 0; i < size(); ++i) { | |
1489 | + if ((event->energy() >= m_dris[i].m_ebounds.emin()) && | |
1490 | + (event->energy() <= m_dris[i].m_ebounds.emax())) { | |
1491 | + ienergy = i; | |
1492 | + break; | |
1493 | + } | |
1494 | + } | |
1495 | + | |
1496 | + // Skip event if it is not contained in any energy bin | |
1497 | + if (ienergy == -1) { | |
1498 | + continue; | |
1499 | + } | |
1500 | + | |
1501 | + // Get pointer to appropriate DRW | |
1502 | + const GCOMDri* dri = &(m_dris[ienergy]); | |
1503 | + | |
1504 | + // Check GTIs if the DRW has GTIs | |
1505 | + if (dri->gti().size() > 0) { | |
1506 | + | |
1507 | + // Skip event if it lies before the GTI start | |
1508 | + if (event->time() < dri->gti().tstart()) { | |
1509 | + continue; | |
1510 | + } | |
1511 | + | |
1512 | + // Break Orbit Aspect Data loop if event lies after the GTI stop | |
1513 | + else if (event->time() > dri->gti().tstop()) { | |
1514 | + terminate = true; | |
1515 | + break; | |
1516 | + } | |
1517 | + | |
1518 | + } // endif: DRW had GTIs | |
1519 | + | |
1520 | + // Skip event if it lies before the superpacket start | |
1521 | + if (event->time() < oad.tstart()) { | |
1522 | + continue; | |
1523 | + } | |
1524 | + | |
1525 | + // Apply event selection | |
1526 | + if (!dri->m_selection.use_event(*event)) { | |
1527 | + continue; | |
1528 | + } | |
1529 | + | |
1530 | + // Compute Compton scatter angle index. Skip if it's invalid. | |
1531 | + int iphibar = int((event->phibar() - dri->m_phimin) / dri->m_phibin); | |
1532 | + if (iphibar < 0) { | |
1533 | + continue; | |
1534 | + } | |
1535 | + else if (iphibar >= dri->nphibar()) { | |
1536 | + continue; | |
1537 | + } | |
1538 | + | |
1539 | + // Check for Earth horizon angle. There is a constant EHA limit | |
1540 | + // over a Phibar layer to be compliant with the DRG. | |
1541 | + double ehamin = double(iphibar) * dri->m_phibin + zetamin; | |
1542 | + if (event->eha() < ehamin) { | |
1543 | + continue; | |
1544 | + } | |
1545 | + | |
1546 | + // Now fill the event in the 3D counts array | |
1547 | + m_wrk_counts(i_oad, iphibar, ienergy) += 1.0; | |
1548 | + | |
1549 | + } // endfor: collected events | |
1550 | + | |
1551 | + // Debug | |
1552 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1553 | + std::cout << "Superpacket " << i_oad; | |
1554 | + std::cout << " time=" << time; | |
1555 | + std::cout << " vetorate=" << m_wrk_vetorate(i_oad); | |
1556 | + std::cout << " total_geo=" << total_geo; | |
1557 | + std::cout << std::endl; | |
1558 | + #endif | |
1559 | + | |
1560 | + // Break Orbit Aspect Data loop if termination was signalled or if there | |
1561 | + // are no more events | |
1562 | + if (terminate || i_evt >= events->size()) { | |
1563 | + break; | |
1564 | + } | |
1565 | + | |
1566 | + } // endfor: looped over Orbit Aspect Data | |
1567 | + | |
1568 | + // Return | |
1569 | + return; | |
1570 | +} | |
1571 | + | |
1572 | + | |
1573 | +/***********************************************************************//** | |
1574 | + * @brief Fit working arrays for vetorate computation | |
1575 | + * | |
1576 | + * Determines the f_prompt parameter for each energy bin using a maximum | |
1577 | + * log-likelihood fit using the data in the working arrays for each energy | |
1578 | + * bin. Based on the fitted f_prompt parameter the method also computes the | |
1579 | + * expected background rate time variation for each energy bin. | |
1580 | + ***************************************************************************/ | |
1581 | +void GCOMDris::vetorate_fit(void) | |
1582 | +{ | |
1583 | + // Set constants | |
1584 | + const double fprompt_init = 0.5; // Initial f_prompt value | |
1585 | + const double norm = 1.0; // Model normalisation | |
1586 | + | |
1587 | + // Debug | |
1588 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1589 | + std::cout << "GCOMDris::vetorate_fit" << std::endl; | |
1590 | + std::cout << "======================" << std::endl; | |
1591 | + #endif | |
1592 | + | |
1593 | + // Extract dimension from working arrays | |
1594 | + int noads = m_wrk_counts.shape()[0]; | |
1595 | + int nphibar = m_wrk_counts.shape()[1]; | |
1596 | + int neng = m_wrk_counts.shape()[2]; | |
1597 | + | |
1598 | + // Debug | |
1599 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1600 | + std::cout << "Number of superpackets: " << noads << std::endl; | |
1601 | + std::cout << "Number of Phibar layers: " << nphibar << std::endl; | |
1602 | + std::cout << "Number of energies: " << neng << std::endl; | |
1603 | + #endif | |
1604 | + | |
1605 | + // Setup rate result array | |
1606 | + m_wrk_rate = GNdarray(noads, neng); | |
1607 | + | |
1608 | + // Setup normalised constant rate array and normalise veto rates | |
1609 | + m_wrk_constrate = GNdarray(noads); | |
1610 | + double nvetorate = 0.0; | |
1611 | + double nconstrate = 0.0; | |
1612 | + for (int ioad = 0; ioad < noads; ++ioad) { | |
1613 | + if (m_wrk_vetorate(ioad) > 0.0) { | |
1614 | + m_wrk_constrate(ioad) = 1.0; | |
1615 | + nvetorate += m_wrk_vetorate(ioad); | |
1616 | + nconstrate += m_wrk_constrate(ioad); | |
1617 | + } | |
1618 | + } | |
1619 | + if (nvetorate > 0.0) { | |
1620 | + for (int ioad = 0; ioad < noads; ++ioad) { | |
1621 | + m_wrk_vetorate(ioad) /= nvetorate; | |
1622 | + } | |
1623 | + } | |
1624 | + if (nconstrate > 0.0) { | |
1625 | + for (int ioad = 0; ioad < noads; ++ioad) { | |
1626 | + m_wrk_constrate(ioad) /= nconstrate; | |
1627 | + } | |
1628 | + } | |
1629 | + | |
1630 | + // Loop over energy bins | |
1631 | + for (int ieng = 0; ieng < neng; ++ieng) { | |
1632 | + | |
1633 | + // Set fprompt parameter | |
1634 | + GOptimizerPars pars; | |
1635 | + GOptimizerPar par("fprompt", fprompt_init); | |
1636 | + par.range(0.0, 1.0); | |
1637 | + par.factor_gradient(1.0); // To avoid zero gradient log message | |
1638 | + pars.append(par); | |
1639 | + | |
1640 | + // Set fit function | |
1641 | + GCOMDris::likelihood fct(this, ieng, norm); | |
1642 | + | |
1643 | + // Optimize function and compute errors | |
1644 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1645 | + GLog log; | |
1646 | + log.cout(true); | |
1647 | + GOptimizerLM opt(&log); | |
1648 | + #else | |
1649 | + GOptimizerLM opt; | |
1650 | + #endif | |
1651 | + opt.eps(0.1); | |
1652 | + opt.max_iter(500); | |
1653 | + opt.optimize(fct, pars); | |
1654 | + opt.errors(fct, pars); | |
1655 | + | |
1656 | + // Retrieve logL | |
1657 | + double logL = opt.value(); | |
1658 | + | |
1659 | + // Recover fprompt parameter and errors | |
1660 | + double fprompt = pars[0]->value(); | |
1661 | + double e_fprompt = pars[0]->error(); | |
1662 | + double fconst = 1.0 - fprompt; | |
1663 | + | |
1664 | + // Set resulting rate vector for this energy bin | |
1665 | + for (int ioad = 0; ioad < noads; ++ioad) { | |
1666 | + m_wrk_rate(ioad, ieng) = fprompt * m_wrk_vetorate(ioad) + | |
1667 | + fconst * m_wrk_constrate(ioad); | |
1668 | + } | |
1669 | + | |
1670 | + // Set DRW header parameters | |
1671 | + m_dris[ieng].m_drw_status = opt.status_string(); | |
1672 | + m_dris[ieng].m_drw_fprompt = fprompt; | |
1673 | + m_dris[ieng].m_drw_e_fprompt = e_fprompt; | |
1674 | + m_dris[ieng].m_drw_iter = opt.iter(); | |
1675 | + | |
1676 | + // Debug: Print fit results | |
1677 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1678 | + std::cout << ieng; | |
1679 | + std::cout << " logL=" << logL; | |
1680 | + std::cout << " fprompt=" << fprompt << " +/- " << e_fprompt; | |
1681 | + std::cout << std::endl; | |
1682 | + #endif | |
1683 | + | |
1684 | + } // endfor: looped over energy bins | |
1685 | + | |
1686 | + // Return | |
1687 | + return; | |
1688 | +} | |
1689 | + | |
1690 | + | |
1691 | +/***********************************************************************//** | |
1692 | + * @brief Generate DRWs | |
1693 | + * | |
1694 | + * @param[in] obs COMPTEL observation. | |
1695 | + * @param[in] select Selection set. | |
1696 | + * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg). | |
1697 | + ***************************************************************************/ | |
1698 | +void GCOMDris::vetorate_generate(const GCOMObservation& obs, | |
1699 | + const GCOMSelection& select, | |
1700 | + const double& zetamin) | |
1701 | +{ | |
1702 | + // Debug | |
1703 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1704 | + std::cout << "GCOMDris::vetorate_generate" << std::endl; | |
1705 | + std::cout << "===========================" << std::endl; | |
1706 | + #endif | |
1707 | + | |
1708 | + // Initialise D1 & D2 module status | |
1709 | + GCOMStatus status; | |
1710 | + | |
1711 | + // Get pointer to first DRW (assume their definition is identical) | |
1712 | + const GCOMDri* dri0 = &(m_dris[0]); | |
1713 | + | |
1714 | + // Extract dimensions | |
1715 | + int noads = obs.oads().size(); | |
1716 | + int npix = dri0->m_dri.npix(); | |
1717 | + int nphibar = dri0->nphibar(); | |
1718 | + int neng = size(); | |
1719 | + | |
1720 | + // Debug | |
1721 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1722 | + std::cout << "Number of superpackets: " << noads << std::endl; | |
1723 | + std::cout << "Number of pixels: " << npix << std::endl; | |
1724 | + std::cout << "Number of Phibar layers: " << nphibar << std::endl; | |
1725 | + std::cout << "Number of energies: " << neng << std::endl; | |
1726 | + #endif | |
1727 | + | |
1728 | + // Allocate geometry factor and Earth horizon angle working arrays | |
1729 | + GNdarray geometry(npix); | |
1730 | + GNdarray eha(npix); | |
1731 | + | |
1732 | + // Setup sky directions and solid angles for all (Chi, Psi) | |
1733 | + std::vector<GSkyDir> skys; | |
1734 | + std::vector<double> omegas; | |
1735 | + for (int index = 0; index < npix; ++index) { | |
1736 | + GSkyDir sky = dri0->m_dri.inx2dir(index); | |
1737 | + double omega = dri0->m_dri.solidangle(index); | |
1738 | + skys.push_back(sky); | |
1739 | + omegas.push_back(omega); | |
1740 | + } | |
1741 | + | |
1742 | + // Get Good Time Intervals. If a pulsar selection is specified then | |
1743 | + // reduce the Good Time Intervals to the validity intervals of the | |
1744 | + // pulsar emphemerides. | |
1745 | + GCOMTim tim = obs.tim(); | |
1746 | + if (select.has_pulsar()) { | |
1747 | + tim.reduce(select.pulsar().validity()); | |
1748 | + } | |
1749 | + | |
1750 | + // Loop over Orbit Aspect Data | |
1751 | + for (int i_oad = 0; i_oad < noads; ++i_oad) { | |
1752 | + | |
1753 | + // Get reference to Orbit Aspect Data of superpacket | |
1754 | + const GCOMOad &oad = obs.oads()[i_oad]; | |
1755 | + | |
1756 | + // Skip not-to-be-used superpackets | |
1757 | + if (!m_wrk_use_sp[i_oad]) { | |
1758 | + continue; | |
1759 | + } | |
1760 | + | |
1761 | + // Prepare Earth horizon angle computation. The celestial system | |
1762 | + // is reinterpreted as the COMPTEL coordinate system, where the | |
1763 | + // 90 degrees - zenith angle becomes the declination and the azimuth | |
1764 | + // angle becomes Right Ascension. This allows us later to use the | |
1765 | + // GSkyDir::dist method to compute the distance between the geocentre | |
1766 | + // and the telescope Z-axis. | |
1767 | + double theta_geocentre = double(oad.gcel()); | |
1768 | + double phi_geocentre = double(oad.gcaz()); | |
1769 | + GSkyDir geocentre_comptel; | |
1770 | + geocentre_comptel.radec_deg(phi_geocentre, 90.0-theta_geocentre); | |
1771 | + | |
1772 | + // Compute solid-angle-corrected geometry factors and Earth horizon | |
1773 | + // angles for all (Chi,Psi) pixels | |
1774 | + for (int index = 0; index < npix; ++index) { | |
1775 | + | |
1776 | + // Convert sky direction to COMPTEL coordinates | |
1777 | + double theta = oad.theta(skys[index]); | |
1778 | + double phi = oad.phi(skys[index]); | |
1779 | + | |
1780 | + // Compute geometric factor summed over all D1, D2 times | |
1781 | + // the solid angle of the weighting cube pixel | |
1782 | + geometry(index) = dri0->compute_geometry(oad.tjd(), theta, phi, | |
1783 | + select, status) * omegas[index]; | |
1784 | + | |
1785 | + // Compute Earth horizon angle as the distance between the Earth | |
1786 | + // centre in COMPTEL coordinates and the (Chi, Psi) pixel in | |
1787 | + // COMPTEL coordinates minus the radius of the Earth. | |
1788 | + GSkyDir chipsi_comptel; | |
1789 | + chipsi_comptel.radec_deg(phi, 90.0-theta); | |
1790 | + eha(index) = geocentre_comptel.dist_deg(chipsi_comptel) - oad.georad(); | |
1791 | + | |
1792 | + } // endfor: computed solid-angle-corrected geometry factors | |
1793 | + | |
1794 | + // Loop over all DRWs | |
1795 | + for (int i = 0; i < size(); ++i) { | |
1796 | + | |
1797 | + // Get pointer to appropriate DRW | |
1798 | + const GCOMDri* dri = &(m_dris[i]); | |
1799 | + | |
1800 | + // Loop over all Phibar layers | |
1801 | + for (int iphibar = 0; iphibar < nphibar; ++iphibar) { | |
1802 | + | |
1803 | + // Compute minimum Earth horizon angle for Phibar layer | |
1804 | + double ehamin = double(iphibar) * dri->m_phibin + zetamin; | |
1805 | + | |
1806 | + // Loop over all (Chi,Psi) pixels | |
1807 | + for (int index = 0; index < npix; ++index) { | |
1808 | + | |
1809 | + // If Earth horizon angle is equal or larger than the minimum | |
1810 | + // requirement then add up the rate weighted geometry factor | |
1811 | + if (eha(index) >= ehamin) { | |
1812 | + | |
1813 | + // Get data space index | |
1814 | + int inx = index + iphibar * npix; | |
1815 | + | |
1816 | + // Store geometry weighted with rate as DRW | |
1817 | + m_dris[i][inx] += geometry(index) * m_wrk_rate(i_oad, i); | |
1818 | + | |
1819 | + } // endif: Earth horizon cut passed | |
1820 | + | |
1821 | + } // endfor: looped over (Chi, Psi) | |
1822 | + | |
1823 | + } // endfor: looped over Phibar | |
1824 | + | |
1825 | + } // endfor: looped over all DRWs | |
1826 | + | |
1827 | + // Debug | |
1828 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1829 | + std::cout << "Superpacket " << i_oad << std::endl; | |
1830 | + #endif | |
1831 | + | |
1832 | + } // endfor: looped over Orbit Aspect Data | |
1833 | + | |
1834 | + // Return | |
1835 | + return; | |
1836 | +} | |
1837 | + | |
1838 | + | |
1839 | +/***********************************************************************//** | |
1840 | + * @brief Save working arrays for vetorate computation | |
1841 | + * | |
1842 | + * @param[in] filename FITS filename. | |
1843 | + * | |
1844 | + * Save working arrays for vetorate DRW computation in FITS file. | |
1845 | + ***************************************************************************/ | |
1846 | +void GCOMDris::vetorate_save(const GFilename& filename) const | |
1847 | +{ | |
1848 | + // Debug | |
1849 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1850 | + std::cout << "GCOMDris::vetorate_save" << std::endl; | |
1851 | + std::cout << "=======================" << std::endl; | |
1852 | + #endif | |
1853 | + | |
1854 | + // Extract dimension from working arrays | |
1855 | + int noads = m_wrk_counts.shape()[0]; | |
1856 | + int nphibar = m_wrk_counts.shape()[1]; | |
1857 | + int neng = m_wrk_counts.shape()[2]; | |
1858 | + | |
1859 | + // Allocate FITS images | |
1860 | + GFitsImageDouble image_counts(noads, nphibar, neng); | |
1861 | + GFitsImageDouble image_ehacutcorr(noads, nphibar); | |
1862 | + GFitsImageDouble image_vetorate(noads); | |
1863 | + GFitsImageShort image_use_sp(noads); | |
1864 | + | |
1865 | + // Fill FITS images from working arrays | |
1866 | + for (int ioad = 0; ioad < noads; ++ioad) { | |
1867 | + for (int iphibar = 0; iphibar < nphibar; ++iphibar) { | |
1868 | + for (int ienergy = 0; ienergy < neng; ++ienergy) { | |
1869 | + image_counts(ioad, iphibar, ienergy) = m_wrk_counts(ioad, iphibar, ienergy); | |
1870 | + } | |
1871 | + image_ehacutcorr(ioad, iphibar) = m_wrk_ehacutcorr(ioad, iphibar); | |
1872 | + } | |
1873 | + image_vetorate(ioad) = m_wrk_vetorate(ioad); | |
1874 | + image_use_sp(ioad) = (m_wrk_use_sp[ioad]) ? 1 : 0; | |
1875 | + } | |
1876 | + | |
1877 | + // Set image attributes | |
1878 | + image_counts.extname("COUNTS"); | |
1879 | + image_ehacutcorr.extname("EHACUTCORR"); | |
1880 | + image_vetorate.extname("VETORATE"); | |
1881 | + image_use_sp.extname("SPUSAGE"); | |
1882 | + | |
1883 | + // Create FITS file and append images | |
1884 | + GFits fits; | |
1885 | + fits.append(image_counts); | |
1886 | + fits.append(image_ehacutcorr); | |
1887 | + fits.append(image_vetorate); | |
1888 | + fits.append(image_use_sp); | |
1889 | + | |
1890 | + // Save FITS file | |
1891 | + fits.saveto(filename, true); | |
1892 | + | |
1893 | + // Return | |
1894 | + return; | |
1895 | +} | |
1896 | + | |
1897 | + | |
1898 | +/***********************************************************************//** | |
1899 | + * @brief Load working arrays for vetorate computation | |
1900 | + * | |
1901 | + * @param[in] filename FITS filename. | |
1902 | + * | |
1903 | + * Load working arrays for vetorate DRW computation from FITS file. | |
1904 | + ***************************************************************************/ | |
1905 | +void GCOMDris::vetorate_load(const GFilename& filename) | |
1906 | +{ | |
1907 | + // Debug | |
1908 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1909 | + std::cout << "GCOMDris::vetorate_load" << std::endl; | |
1910 | + std::cout << "=======================" << std::endl; | |
1911 | + #endif | |
1912 | + | |
1913 | + // Open FITS file | |
1914 | + GFits fits(filename); | |
1915 | + | |
1916 | + // Get images | |
1917 | + const GFitsImage* image_counts = fits.image("COUNTS"); | |
1918 | + const GFitsImage* image_ehacutcorr = fits.image("EHACUTCORR"); | |
1919 | + const GFitsImage* image_vetorate = fits.image("VETORATE"); | |
1920 | + const GFitsImage* image_use_sp = fits.image("SPUSAGE"); | |
1921 | + | |
1922 | + // Extract dimensions | |
1923 | + int noads = image_counts->naxes(0); | |
1924 | + int nphibar = image_counts->naxes(1); | |
1925 | + int neng = image_counts->naxes(2); | |
1926 | + | |
1927 | + // Debug | |
1928 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
1929 | + std::cout << "Number of superpackets: " << noads << std::endl; | |
1930 | + std::cout << "Number of Phibar layers: " << nphibar << std::endl; | |
1931 | + std::cout << "Number of energies: " << neng << std::endl; | |
1932 | + #endif | |
1933 | + | |
1934 | + // Allocate working array | |
1935 | + m_wrk_counts = GNdarray(noads, nphibar, neng); | |
1936 | + m_wrk_ehacutcorr = GNdarray(noads, nphibar); | |
1937 | + m_wrk_vetorate = GNdarray(noads); | |
1938 | + m_wrk_use_sp = std::vector<bool>(noads); | |
1939 | + | |
1940 | + // Extract data from images | |
1941 | + for (int ioad = 0; ioad < noads; ++ioad) { | |
1942 | + for (int iphibar = 0; iphibar < nphibar; ++iphibar) { | |
1943 | + for (int ienergy = 0; ienergy < neng; ++ienergy) { | |
1944 | + m_wrk_counts(ioad, iphibar, ienergy) = image_counts->pixel(ioad, iphibar, ienergy); | |
1945 | + } | |
1946 | + m_wrk_ehacutcorr(ioad, iphibar) = image_ehacutcorr->pixel(ioad, iphibar); | |
1947 | + } | |
1948 | + m_wrk_vetorate(ioad) = image_vetorate->pixel(ioad); | |
1949 | + m_wrk_use_sp[ioad] = (image_use_sp->pixel(ioad) == 1); | |
1950 | + } | |
1951 | + | |
1952 | + // Close FITS file | |
1953 | + fits.close(); | |
1954 | + | |
1955 | + // Return | |
1956 | + return; | |
1957 | +} | |
1958 | + | |
1959 | + | |
1960 | +/***********************************************************************//** | |
1961 | + * @brief Log-likelihood function constructor | |
1962 | + * | |
1963 | + * @param[in] dris Parent calling likelihood function. | |
1964 | + * @param[in] ieng DRW energy bin. | |
1965 | + * @param[in] norm Normalisation constant. | |
1966 | + * | |
1967 | + * Constructs the log-likelihood function that is used to determine the | |
1968 | + * value of f_prompt. | |
1969 | + ***************************************************************************/ | |
1970 | +GCOMDris::likelihood::likelihood(GCOMDris *dris, | |
1971 | + const int& ieng, | |
1972 | + const double& norm) : GOptimizerFunction() | |
1973 | +{ | |
1974 | + // Store arguments | |
1975 | + m_this = dris; | |
1976 | + m_ieng = ieng; | |
1977 | + m_norm = norm; | |
1978 | + | |
1979 | + // Set gradient and curvature members | |
1980 | + m_gradient = GVector(1); | |
1981 | + m_curvature = GMatrixSparse(1,1); | |
1982 | + | |
1983 | + // Extract dimension from working array | |
1984 | + m_noads = m_this->m_wrk_counts.shape()[0]; | |
1985 | + m_nphibar = m_this->m_wrk_counts.shape()[1]; | |
1986 | + | |
1987 | + // Multiply veto and constant rate by EHA cut correction. Rates are zero | |
1988 | + // in case that the vetorate is zero. | |
1989 | + m_vetorate = GNdarray(m_noads, m_nphibar); | |
1990 | + m_constrate = GNdarray(m_noads, m_nphibar); | |
1991 | + m_diffrate = GNdarray(m_noads, m_nphibar); | |
1992 | + for (int ioad = 0; ioad < m_noads; ++ioad) { | |
1993 | + double vetorate = m_this->m_wrk_vetorate(ioad); | |
1994 | + if (vetorate > 0.0) { | |
1995 | + double constrate = m_this->m_wrk_constrate(ioad); | |
1996 | + for (int iphibar = 0; iphibar < m_nphibar; ++iphibar) { | |
1997 | + m_vetorate(ioad, iphibar) = vetorate * m_this->m_wrk_ehacutcorr(ioad, iphibar); | |
1998 | + m_constrate(ioad, iphibar) = constrate * m_this->m_wrk_ehacutcorr(ioad, iphibar); | |
1999 | + m_diffrate(ioad, iphibar) = m_vetorate(ioad, iphibar) - m_constrate(ioad, iphibar); | |
2000 | + } | |
2001 | + } | |
2002 | + } | |
2003 | + | |
2004 | + // Compute rate sums | |
2005 | + m_vetorate_sum = GNdarray(m_nphibar); | |
2006 | + m_constrate_sum = GNdarray(m_nphibar); | |
2007 | + m_diffrate_sum = GNdarray(m_nphibar); | |
2008 | + for (int iphibar = 0; iphibar < m_nphibar; ++iphibar) { | |
2009 | + for (int ioad = 0; ioad < m_noads; ++ioad) { | |
2010 | + m_vetorate_sum(iphibar) += m_vetorate(ioad, iphibar); | |
2011 | + m_constrate_sum(iphibar) += m_constrate(ioad, iphibar); | |
2012 | + } | |
2013 | + m_diffrate_sum(iphibar) = m_vetorate_sum(iphibar) - m_constrate_sum(iphibar); | |
2014 | + } | |
2015 | + | |
2016 | + // Return | |
2017 | + return; | |
2018 | +} | |
2019 | + | |
2020 | + | |
2021 | +/***********************************************************************//** | |
2022 | + * @brief Log-likelihood function evaluation | |
2023 | + * | |
2024 | + * @param[in] pars Function parameters. | |
2025 | + * | |
2026 | + * Computes the log-likelihood function, its gradient and its curvature at | |
2027 | + * the specified function parameters. | |
2028 | + ***************************************************************************/ | |
2029 | +void GCOMDris::likelihood::eval(const GOptimizerPars& pars) | |
2030 | +{ | |
2031 | + // Recover parameters | |
2032 | + double fprompt = pars[0]->value(); | |
2033 | + double fconst = 1.0 - fprompt; | |
2034 | + | |
2035 | + // Extract dimension from working array | |
2036 | + int noads = m_this->m_wrk_counts.shape()[0]; | |
2037 | + int nphibar = m_this->m_wrk_counts.shape()[1]; | |
2038 | + | |
2039 | + // Allocate phibar normalisation arrays | |
2040 | + GNdarray nevents(nphibar); | |
2041 | + GNdarray nmodel(nphibar); | |
2042 | + GNdarray norm(nphibar); | |
2043 | + | |
2044 | + // Compute model | |
2045 | + GNdarray model = fprompt * m_vetorate + fconst * m_constrate; | |
2046 | + | |
2047 | + // Compute Phibar normalised model | |
2048 | + GNdarray model_norm = model; | |
2049 | + for (int iphibar = 0; iphibar < m_nphibar; ++iphibar) { | |
2050 | + for (int ioad = 0; ioad < m_noads; ++ioad) { | |
2051 | + if (model(ioad, iphibar) > 0.0) { | |
2052 | + nevents(iphibar) += m_this->m_wrk_counts(ioad, iphibar, m_ieng); | |
2053 | + nmodel(iphibar) += model(ioad, iphibar); | |
2054 | + } | |
2055 | + } | |
2056 | + if (nmodel(iphibar) > 0.0) { | |
2057 | + norm(iphibar) = m_norm * nevents(iphibar) / nmodel(iphibar); | |
2058 | + for (int ioad = 0; ioad < m_noads; ++ioad) { | |
2059 | + model_norm(ioad, iphibar) *= norm(iphibar); | |
2060 | + } | |
2061 | + } | |
2062 | + } | |
2063 | + | |
2064 | + // Compute LogL | |
2065 | + m_value = 0.0; | |
2066 | + for (int ioad = 0; ioad < m_noads; ++ioad) { | |
2067 | + for (int iphibar = 0; iphibar < m_nphibar; ++iphibar) { | |
2068 | + if (model_norm(ioad, iphibar) > 0.0) { | |
2069 | + m_value -= m_this->m_wrk_counts(ioad, iphibar, m_ieng) * | |
2070 | + std::log(model_norm(ioad, iphibar)) - model_norm(ioad, iphibar); | |
2071 | + } | |
2072 | + } | |
2073 | + } | |
2074 | + | |
2075 | + // Evaluate gradient and curvature | |
2076 | + for (int iphibar = 0; iphibar < m_nphibar; ++iphibar) { | |
2077 | + | |
2078 | + // Precompute normalisation gradient | |
2079 | + double nmodel2 = nmodel(iphibar) * nmodel(iphibar); | |
2080 | + double g_norm = -m_norm * nevents(iphibar) / nmodel2 * m_diffrate_sum(iphibar); | |
2081 | + | |
2082 | + // Loop over superpackets | |
2083 | + for (int ioad = 0; ioad < m_noads; ++ioad) { | |
2084 | + | |
2085 | + // Continue only if model is positive | |
2086 | + if (model_norm(ioad, iphibar) > 0.0) { | |
2087 | + | |
2088 | + // Pre computation | |
2089 | + double fb = m_this->m_wrk_counts(ioad, iphibar, m_ieng) / model_norm(ioad, iphibar); | |
2090 | + double fc = (1.0 - fb); | |
2091 | + double fa = fb / model_norm(ioad, iphibar); | |
2092 | + | |
2093 | + // Compute parameter gradient | |
2094 | + double g = norm(iphibar) * m_diffrate(ioad, iphibar) + g_norm * model(ioad, iphibar); | |
2095 | + | |
2096 | + // Update gradient | |
2097 | + m_gradient[0] += fc * g; | |
2098 | + | |
2099 | + // Update curvature | |
2100 | + m_curvature(0,0) += fa * g * g; | |
2101 | + | |
2102 | + } // endif: model was positive | |
2103 | + | |
2104 | + } // endfor: looped over superpackets | |
2105 | + | |
2106 | + } // endfor: looped over Phibar | |
2107 | + | |
2108 | + // Return | |
2109 | + return; | |
2110 | +} | ... | ... |
inst/com/test/dev/test_bgdlixf.py
... | ... | @@ -56,7 +56,6 @@ def get_veto_rates(xmlname): |
56 | 56 | |
57 | 57 | # Get 2nd Veto dome rates housekeeping data |
58 | 58 | hkd = com.hkds()['SCV2M'] |
59 | - print(hkd) | |
60 | 59 | |
61 | 60 | # Extract data |
62 | 61 | for i in range(hkd.size()): |
... | ... | @@ -73,35 +72,37 @@ def get_veto_rates(xmlname): |
73 | 72 | # ====================================== # |
74 | 73 | # Check time ordering of Veto dome rates # |
75 | 74 | # ====================================== # |
76 | -def check_veto_rates(xmlname): | |
75 | +def check_veto_rates(): | |
77 | 76 | """ |
78 | 77 | Check time ordering of Veto dome rates |
79 | - | |
80 | - Parameters | |
81 | - ---------- | |
82 | - xmlname : str | |
83 | - Observation definition XML file name | |
84 | 78 | """ |
85 | - # Load observations | |
86 | - obs = gammalib.GObservations(xmlname) | |
79 | + # Get all XML files | |
80 | + xmlnames = glob.glob('dbase/xml/vp*.xml') | |
81 | + xmlnames.sort() | |
87 | 82 | |
88 | - # Loop over observations | |
89 | - for com in obs: | |
83 | + # Loop over XML files | |
84 | + for xmlname in xmlnames: | |
90 | 85 | |
91 | - # Get 2nd Veto dome rates housekeeping data | |
92 | - hkd = com.hkds()['SCV2M'] | |
86 | + # Load observations | |
87 | + obs = gammalib.GObservations(xmlname) | |
93 | 88 | |
94 | - # Check times | |
95 | - nbad = 0 | |
96 | - for i in range(hkd.size()): | |
97 | - if i == 0: | |
98 | - last_time = hkd.time(i) | |
99 | - else: | |
100 | - if hkd.time(i) <= last_time: | |
101 | - nbad += 1 | |
102 | - print('%s: %.5f <= %.5f' % (com.id(), hkd.time(i).mjd(), last_time.mjd())) | |
103 | - if nbad == 0: | |
104 | - print('%s: ok.' % (com.id())) | |
89 | + # Loop over observations | |
90 | + for com in obs: | |
91 | + | |
92 | + # Get 2nd Veto dome rates housekeeping data | |
93 | + hkd = com.hkds()['SCV2M'] | |
94 | + | |
95 | + # Check times | |
96 | + nbad = 0 | |
97 | + for i in range(hkd.size()): | |
98 | + if i == 0: | |
99 | + last_time = hkd.time(i) | |
100 | + else: | |
101 | + if hkd.time(i) <= last_time: | |
102 | + nbad += 1 | |
103 | + print('%s: %.5f <= %.5f' % (com.id(), hkd.time(i).mjd(), last_time.mjd())) | |
104 | + if nbad == 0: | |
105 | + print('%s: ok.' % (com.id())) | |
105 | 106 | |
106 | 107 | # Return |
107 | 108 | return |
... | ... | @@ -147,23 +148,14 @@ if __name__ == '__main__': |
147 | 148 | print('* Test BGDLIXF rate fitting *') |
148 | 149 | print('*****************************') |
149 | 150 | |
150 | - # Set file names | |
151 | - #hkdname = '/project-data/comptel/data/phase01/vp0001_0/m20074_hkd.fits' | |
152 | - #hkdname = '/project-data/comptel/data/phase07/vp0701_0/m26689_hkd.fits' | |
153 | - #xmlname = 'dbase/xml/vp0001_0.xml' | |
154 | - | |
155 | - # Get all XML files | |
156 | - xmlnames = glob.glob('dbase/xml/vp*.xml') | |
157 | - xmlnames.sort() | |
151 | + # Check time ordering of veto rates | |
152 | + #check_veto_rates() | |
158 | 153 | |
159 | - # Loop over XML files | |
160 | - for xmlname in xmlnames: | |
161 | - | |
162 | - # Check Veto rates | |
163 | - check_veto_rates(xmlname) | |
154 | + # Set file names | |
155 | + xmlname = 'dbase/xml/vp0001_0.xml' | |
164 | 156 | |
165 | - # Get Veto dome rates | |
166 | - #rates = get_veto_rates(xmlname) | |
157 | + # Get Veto dome rates | |
158 | + rates = get_veto_rates(xmlname) | |
167 | 159 | |
168 | - # Show Veto dome rates | |
169 | - #show_veto_rates(rates) | |
160 | + # Show Veto dome rates | |
161 | + show_veto_rates(rates) | ... | ... |