Commit 0d13fc6058437b50c52bc7bd35934e43aef26135
1 parent
0d9c23cf
Spectrum points
Showing
3 changed files
with
157 additions
and
29 deletions
scripts/obsutils.py
| @@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
| 20 | # ========================================================================== | 20 | # ========================================================================== |
| 21 | import ctools | 21 | import ctools |
| 22 | import gammalib | 22 | import gammalib |
| 23 | - | 23 | +import numpy |
| 24 | 24 | ||
| 25 | # ===================== # | 25 | # ===================== # |
| 26 | # Simulate observations # | 26 | # Simulate observations # |
| @@ -516,3 +516,92 @@ def set_obs_patterns(pattern, ra=83.6331, dec=22.0145, offset=1.5): | @@ -516,3 +516,92 @@ def set_obs_patterns(pattern, ra=83.6331, dec=22.0145, offset=1.5): | ||
| 516 | 516 | ||
| 517 | # Return observation definition list | 517 | # Return observation definition list |
| 518 | return obsdeflist | 518 | return obsdeflist |
| 519 | + | ||
| 520 | +# =================================================# | ||
| 521 | +# Make spectrum for one Source in aCTA Observation # | ||
| 522 | +# ================================================ # | ||
| 523 | +def getlogbins(nbins=12,emin=0.1,emax=100): | ||
| 524 | + """ | ||
| 525 | + Returns list with logarithmiscenergy bins in | ||
| 526 | + format [[emin1,emax1],[emin2,emax2],..] | ||
| 527 | + | ||
| 528 | + Parameters: | ||
| 529 | + nbins Number of bins | ||
| 530 | + emin Minimum energy | ||
| 531 | + emax Maximum energy | ||
| 532 | + """ | ||
| 533 | + lgemin=numpy.log10(emin) | ||
| 534 | + lgemax=numpy.log10(emax) | ||
| 535 | + lgbins=[] | ||
| 536 | + lgedges=numpy.arange(lgemin,lgemax,(lgemax-lgemin)/nbins) | ||
| 537 | + lgedges=numpy.append(lgedges,[lgemax]) | ||
| 538 | + for ii in range(len(lgedges)-1): | ||
| 539 | + lgbins.append([lgedges[ii],lgedges[ii+1]]) | ||
| 540 | + ebins=numpy.power(10,lgbins) | ||
| 541 | + return ebins | ||
| 542 | +def specpoints(obs,source,ebins): | ||
| 543 | + """ | ||
| 544 | + Returns spectral points in the given binning for | ||
| 545 | + the passed observations and source. | ||
| 546 | + | ||
| 547 | + Parameters: | ||
| 548 | + obs - Pointing direction | ||
| 549 | + source - Source name for which spectrum should be done | ||
| 550 | + ebins - Binning passed as a list in units of TeV as | ||
| 551 | + [[emin1,emax1],[emin2,emax2],..] | ||
| 552 | + Keywords: | ||
| 553 | + """ | ||
| 554 | + #Fix all parameters except prefactor | ||
| 555 | + for model in obs.models(): | ||
| 556 | + for par in range(model.size()): | ||
| 557 | + model[par].fix() | ||
| 558 | + | ||
| 559 | + opt_spectral = obs.models()[source].spectral() | ||
| 560 | + opt_spectral["Prefactor"].free() | ||
| 561 | + | ||
| 562 | + #Define spectrum dictionary, units are in format readable by astropy | ||
| 563 | + pars = {"value":[],"eu_value":[],"ed_value":[],"unit":[]} | ||
| 564 | + spec = {"energy":pars.copy(),"flux":pars.copy(),"TS":[]} | ||
| 565 | + | ||
| 566 | + #Loop over energy bins, fit and write result to spectrum | ||
| 567 | + for ebin in ebins: | ||
| 568 | + #Get logarithmic bin center and flux value of all energy fit | ||
| 569 | + ecenter = numpy.power(10,(numpy.log10(ebin[1])+numpy.log10(ebin[0]))/2.) | ||
| 570 | + allflux = opt_spectral.eval(gammalib.GEnergy(ecenter,"TeV"),gammalib.GTime(0)) | ||
| 571 | + | ||
| 572 | + #Clone observations and reset energy thresholds | ||
| 573 | + select = ctools.ctselect(obs) | ||
| 574 | + select["ra"].real(-1.0) | ||
| 575 | + select["dec"].real(-1.0) | ||
| 576 | + select["rad"].real(-1.0) | ||
| 577 | + select["tmin"].real(0) | ||
| 578 | + select["tmax"].real(0) | ||
| 579 | + select["emin"].real(ebin[0]) | ||
| 580 | + select["emax"].real(ebin[1]) | ||
| 581 | + select.run() | ||
| 582 | + obsclone = select.obs() | ||
| 583 | + | ||
| 584 | + #Refit and write out to spectrum | ||
| 585 | + binlike=fit(obsclone,log=False, debug=False, edisp=False) | ||
| 586 | + binopt_spectral = binlike.obs().models()[source].spectral() | ||
| 587 | + binflux=binopt_spectral.eval(gammalib.GEnergy(ecenter,"TeV"),gammalib.GTime(0)) | ||
| 588 | + if binopt_spectral["Prefactor"].value()>0: | ||
| 589 | + relerr=binopt_spectral["Prefactor"].error()/binopt_spectral["Prefactor"].value() | ||
| 590 | + else: | ||
| 591 | + relerr=0 | ||
| 592 | + | ||
| 593 | + #Store and convert to TeV from MeV | ||
| 594 | + spec["energy"]["value"].append(ecenter) | ||
| 595 | + spec["energy"]["ed_value"].append(ecenter-ebin[0]) | ||
| 596 | + spec["energy"]["eu_value"].append(ebin[1]-ecenter) | ||
| 597 | + spec["energy"]["unit"].append("1e12 eV") | ||
| 598 | + | ||
| 599 | + spec["flux"]["value"].append(binflux*1e6) | ||
| 600 | + spec["flux"]["ed_value"].append(relerr*binflux*1e6) | ||
| 601 | + spec["flux"]["eu_value"].append(relerr*binflux*1e6) | ||
| 602 | + spec["flux"]["unit"].append("cm-2 1e-12 eV-1") | ||
| 603 | + | ||
| 604 | + spec["TS"].append(binlike.obs().models()[source].ts()) | ||
| 605 | + | ||
| 606 | + #Return spectrum | ||
| 607 | + return spec |
src/ctlike/ctlike.cpp
| @@ -267,6 +267,39 @@ void ctlike::run(void) | @@ -267,6 +267,39 @@ void ctlike::run(void) | ||
| 267 | 267 | ||
| 268 | // Optimize model parameters using LM optimizer | 268 | // Optimize model parameters using LM optimizer |
| 269 | optimize_lm(); | 269 | optimize_lm(); |
| 270 | + | ||
| 271 | + // Store original models and max. likelihood | ||
| 272 | + double logL_src=m_logL; | ||
| 273 | + GModels* models_orig = m_obs.models().clone(); | ||
| 274 | + | ||
| 275 | + //Store models whith free parameters | ||
| 276 | + std::vector<std::string> free_srcs; | ||
| 277 | + GModels models = m_obs.models(); | ||
| 278 | + for (int ii=0; ii < models.size();ii++){ | ||
| 279 | + GModel* model = models[ii]; | ||
| 280 | + for(int jj=0; jj < model->size();jj++){ | ||
| 281 | + GModelPar par = model->at(jj); | ||
| 282 | + if (par.is_free()){ | ||
| 283 | + free_srcs.push_back(model->name()); | ||
| 284 | + break; | ||
| 285 | + } | ||
| 286 | + } | ||
| 287 | + } | ||
| 288 | + //Loop over stored models, remove source and refit | ||
| 289 | + for (int ii=0; ii < free_srcs.size();ii++){ | ||
| 290 | + models.remove(free_srcs[ii]); | ||
| 291 | + m_obs.models(models); | ||
| 292 | + optimize_lm(); | ||
| 293 | + double logL_nosrc=m_logL; | ||
| 294 | + double TS = 2* (logL_src-logL_nosrc); | ||
| 295 | + std::string name = free_srcs[ii]; | ||
| 296 | + (*models_orig)[name]->ts(TS); | ||
| 297 | + models = *models_orig; | ||
| 298 | + } | ||
| 299 | + // Restore best fit values | ||
| 300 | + // TODO: store fit results before and avoid refitting | ||
| 301 | + m_obs.models(*models_orig); | ||
| 302 | + optimize_lm(); | ||
| 270 | 303 | ||
| 271 | // Compute number of observed events in all observations | 304 | // Compute number of observed events in all observations |
| 272 | double num_events = 0.0; | 305 | double num_events = 0.0; |
src/ctselect/ctselect.cpp
| @@ -511,7 +511,8 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) | @@ -511,7 +511,8 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) | ||
| 511 | 511 | ||
| 512 | // Set requested selections | 512 | // Set requested selections |
| 513 | bool select_time = (m_tmin != 0.0 || m_tmax != 0.0); | 513 | bool select_time = (m_tmin != 0.0 || m_tmax != 0.0); |
| 514 | - | 514 | + bool select_roi = ((m_dec != -1.0 && m_ra != -1.0 && m_rad != -1.0) || m_usepnt); |
| 515 | + | ||
| 515 | // Set RA/DEC selection | 516 | // Set RA/DEC selection |
| 516 | double ra = m_ra; | 517 | double ra = m_ra; |
| 517 | double dec = m_dec; | 518 | double dec = m_dec; |
| @@ -520,7 +521,7 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) | @@ -520,7 +521,7 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) | ||
| 520 | ra = pnt.dir().ra_deg(); | 521 | ra = pnt.dir().ra_deg(); |
| 521 | dec = pnt.dir().dec_deg(); | 522 | dec = pnt.dir().dec_deg(); |
| 522 | } | 523 | } |
| 523 | - | 524 | + |
| 524 | // Set time selection interval. We make sure here that the time selection | 525 | // Set time selection interval. We make sure here that the time selection |
| 525 | // interval cannot be wider than the GTIs covering the data. This is done | 526 | // interval cannot be wider than the GTIs covering the data. This is done |
| 526 | // using GGti's reduce() method. | 527 | // using GGti's reduce() method. |
| @@ -565,26 +566,29 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) | @@ -565,26 +566,29 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) | ||
| 565 | log << gammalib::parformat("Energy range"); | 566 | log << gammalib::parformat("Energy range"); |
| 566 | log << m_emin << " - " << m_emax << " TeV" << std::endl; | 567 | log << m_emin << " - " << m_emax << " TeV" << std::endl; |
| 567 | } | 568 | } |
| 568 | - if (selection.length() > 0) { | ||
| 569 | - selection += " && "; | ||
| 570 | - } | ||
| 571 | 569 | ||
| 572 | // Make ROI selection | 570 | // Make ROI selection |
| 573 | - sprintf(cra, "%.6f", ra); | ||
| 574 | - sprintf(cdec, "%.6f", dec); | ||
| 575 | - sprintf(crad, "%.6f", m_rad); | ||
| 576 | - selection += "ANGSEP("+std::string(cra)+"," + | ||
| 577 | - std::string(cdec)+",RA,DEC) <= " + | ||
| 578 | - std::string(crad); | ||
| 579 | - if (logTerse()) { | ||
| 580 | - log << gammalib::parformat("Acceptance cone centre"); | ||
| 581 | - log << "RA=" << ra << ", DEC=" << dec << " deg" << std::endl; | ||
| 582 | - log << gammalib::parformat("Acceptance cone radius"); | ||
| 583 | - log << m_rad << " deg" << std::endl; | ||
| 584 | - } | ||
| 585 | - if (logTerse()) { | ||
| 586 | - log << gammalib::parformat("cfitsio selection"); | ||
| 587 | - log << selection << std::endl; | 571 | + if (select_roi){ |
| 572 | + if (selection.length() > 0) { | ||
| 573 | + selection += " && "; | ||
| 574 | + } | ||
| 575 | + | ||
| 576 | + sprintf(cra, "%.6f", ra); | ||
| 577 | + sprintf(cdec, "%.6f", dec); | ||
| 578 | + sprintf(crad, "%.6f", m_rad); | ||
| 579 | + selection += "ANGSEP("+std::string(cra)+"," + | ||
| 580 | + std::string(cdec)+",RA,DEC) <= " + | ||
| 581 | + std::string(crad); | ||
| 582 | + if (logTerse()) { | ||
| 583 | + log << gammalib::parformat("Acceptance cone centre"); | ||
| 584 | + log << "RA=" << ra << ", DEC=" << dec << " deg" << std::endl; | ||
| 585 | + log << gammalib::parformat("Acceptance cone radius"); | ||
| 586 | + log << m_rad << " deg" << std::endl; | ||
| 587 | + } | ||
| 588 | + if (logTerse()) { | ||
| 589 | + log << gammalib::parformat("cfitsio selection"); | ||
| 590 | + log << selection << std::endl; | ||
| 591 | + } | ||
| 588 | } | 592 | } |
| 589 | 593 | ||
| 590 | // Add additional expression | 594 | // Add additional expression |
| @@ -645,11 +649,13 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) | @@ -645,11 +649,13 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) | ||
| 645 | // Get CTA event list pointer | 649 | // Get CTA event list pointer |
| 646 | GCTAEventList* list = | 650 | GCTAEventList* list = |
| 647 | static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events())); | 651 | static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events())); |
| 648 | - | ||
| 649 | - // Set ROI | ||
| 650 | - GCTAInstDir instdir; | ||
| 651 | - instdir.dir().radec_deg(ra, dec); | ||
| 652 | - list->roi(GCTARoi(instdir, m_rad)); | 652 | + |
| 653 | + if (select_roi){ | ||
| 654 | + // Set ROI | ||
| 655 | + GCTAInstDir instdir; | ||
| 656 | + instdir.dir().radec_deg(ra, dec); | ||
| 657 | + list->roi(GCTARoi(instdir, m_rad)); | ||
| 658 | + } | ||
| 653 | 659 | ||
| 654 | // Set GTI | 660 | // Set GTI |
| 655 | list->gti(gti); | 661 | list->gti(gti); |
| @@ -689,9 +695,9 @@ void ctselect::init_members(void) | @@ -689,9 +695,9 @@ void ctselect::init_members(void) | ||
| 689 | m_outfile.clear(); | 695 | m_outfile.clear(); |
| 690 | m_prefix.clear(); | 696 | m_prefix.clear(); |
| 691 | m_usepnt = false; | 697 | m_usepnt = false; |
| 692 | - m_ra = 0.0; | ||
| 693 | - m_dec = 0.0; | ||
| 694 | - m_rad = 0.0; | 698 | + m_ra = -1.0; |
| 699 | + m_dec = -1.0; | ||
| 700 | + m_rad = -1.0; | ||
| 695 | m_tmin = 0.0; | 701 | m_tmin = 0.0; |
| 696 | m_tmax = 0.0; | 702 | m_tmax = 0.0; |
| 697 | m_emin = 0.0; | 703 | m_emin = 0.0; |