Commit 0d13fc6058437b50c52bc7bd35934e43aef26135

Authored by Rolf Buehler
1 parent 0d9c23cf

Spectrum points

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&amp; filename) @@ -511,7 +511,8 @@ void ctselect::select_events(GCTAObservation* obs, const std::string&amp; 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&amp; filename) @@ -520,7 +521,7 @@ void ctselect::select_events(GCTAObservation* obs, const std::string&amp; 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&amp; filename) @@ -565,26 +566,29 @@ void ctselect::select_events(GCTAObservation* obs, const std::string&amp; 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&amp; filename) @@ -645,11 +649,13 @@ void ctselect::select_events(GCTAObservation* obs, const std::string&amp; 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;