def ctselect(self): # ctselect application and set parameters self.info("Running ctselect to cut on events") self.validate() if self.m_obs: filter = ct.ctselect(self.m_obs) else: filter = ct.ctselect() filter["infile"] = self.m_raw_evt filter["outfile"] = self.m_evtfile filter["usepnt"].boolean(self.m_usepnt) # Use pointing for map centre filter["ra"] = self.m_ra filter["dec"] = self.m_dec filter["rad"] = self.m_roi filter["tmin"] = self.m_tmin filter["tmax"] = self.m_tmax filter["emin"].real(self.m_emin) filter["emax"].real(self.m_emax) filter["expr"] = "" filter.logFileOpen() filter.run() if not(self.m_obs): filter.save() if self.m_obs: # Make a deep copy of the observation that will be returned # (the ctbin object will go out of scope one the function is # left) self.m_obs = filter.obs().copy()
def selection_run(self, input_obs_list, output_obs_list, tmin=0, tmax=None, energy=[None, None], prefix='selected_', log_file='ctselect.log', force=False, save=False): if tmin < 0 or tmax < 1 or tmin >= tmax: raise Exception("ctselect needs better tmin/tmax") select = ctools.ctselect() if isinstance(input_obs_list, gammalib.GObservations): select.obs(input_obs_list) elif os.path.isfile(input_obs_list): # observations list from file select["inobs"] = input_obs_list else: raise Exception('Cannot understand input obs list for csphagen') select["rad"] = "INDEF" select["ra"] = "INDEF" select["dec"] = "INDEF" select["tmin"] = tmin select["tmax"] = tmax select["emin"] = energy[0] if energy[0] else "INDEF" select["emax"] = energy[1] if energy[1] else "INDEF" select["prefix"] = prefix select["outobs"] = output_obs_list select["logfile"] = log_file if force or not os.path.isfile(output_obs_list): select.logFileOpen() select.run() elif os.path.isfile(output_obs_list): basename, ext = os.path.splitext(output_obs_list) if ext == '.xml': select = ctools.ctselect( gammalib.GObservations(output_obs_list)) else: # .fits container = gammalib.GObservations() gcta_obs = gammalib.GCTAObservation(output_obs_list) container.append(gcta_obs) select.obs(container) else: raise Exception("Cannot proceed with ctselect") saved = False if (save and force) or (save and not os.path.isfile(output_obs_list)): select.save() # why it doesn't save anytime? saved = True logger.info("Files {} created.".format(output_obs_list)) return select
def ctselect(self, log=False, debug=False): ''' Create ctselect instance with given parameters Parameters --------- log : save or not the log file debug : debug mode or not. This will print a lot of information ''' self.info("Running ctselect to cut on events") if self.m_obs: filter = ct.ctselect(self.m_obs) else: filter = ct.ctselect() ## for k in self.config.keys(): try: for kk in self.config[k].keys(): if filter._has_par(kk): filter[kk] = self.config[k][kk] except: if filter._has_par(k): filter[k] = self.config[k] filter["inobs"] = join(self.workdir, self.config['file']["inobs"]) filter["outobs"] = join(self.workdir, self.config['file']["selectedevent"]) filter.logFileOpen() if self.verbose: print filter # Optionally open the log file if log: filter.logFileOpen() # Optionally switch-on debugging model if debug: filter["debug"].boolean(True) filter.run() if not (self.m_obs): filter.save() if self.m_obs: # Make a deep copy of the observation that will be returned # (the ctbin object will go out of scope one the function is # left) self.m_obs = filter.obs().copy()
def _select_events(self, obs): """ Select events within a given RoI radius Parameters ---------- obs : `~gammalib.GObservations()` Observation container Returns ------- obs : `~gammalib.GObservations()` Observation container """ # Setup task parameters select = ctools.ctselect(obs) select['ra'] = 'UNDEF' select['dec'] = 'UNDEF' select['rad'] = self['rad'].real() select['tmin'] = 'UNDEF' select['tmax'] = 'UNDEF' select['emin'] = self['emin'].real() select['emax'] = self['emax'].real() select['usethres'] = 'DEFAULT' # Select events select.run() # Extract observation obs = select.obs().copy() # Return observation return obs
def ctselect(self, log=False,debug=False, **kwargs): ''' Create ctselect instance with given parameters Parameters --------- log : save or not the log file debug : debug mode or not. This will print a lot of information ''' self.info("Running ctselect to cut on events") self.filter = ct.ctselect() self._fill_app( self.filter,log=log,debug=debug, **kwargs) self.filter["outobs"] = join(self.outdir,self.config['file']["selectedevent"]) if self.verbose: print self.filter self.filter.run() self.filter.save() self.info("Saved selected events to {0:s}".format(self.filter["outobs"])) # change the inobs (data) to the selected data set self.config['file']["inobs"] = self.config['file']["selectedevent"] del self.filter
def test_functional(self): """ Test ctselect functionnality. """ # Set-up ctselect select = ctools.ctselect() select["inobs"].filename(self.events_name) select["outobs"].filename("selected_events.fits") select["ra"].real(83.63) select["dec"].real(22.01) select["rad"].real(3.0) select["tmin"].real(0.0) select["tmax"].real(1800.0) select["emin"].real(0.1) select["emax"].real(100.0) # Run tool self.test_try("Run ctselect") try: select.run() self.test_try_success() except: self.test_try_failure("Exception occured in ctselect.") # Save events self.test_try("Save events") try: select.save() self.test_try_success() except: self.test_try_failure("Exception occured in saving events.") # Return return
def test_functional(self): """ Test ctselect functionnality. """ # Set-up ctselect select = ctools.ctselect() select["inobs"] = self.events_name select["outobs"] = "selected_events.fits" select["ra"] = 83.63 select["dec"] = 22.01 select["rad"] = 3 select["tmin"] = 0 select["tmax"] = 1800 select["emin"] = 0.1 select["emax"] = 100 # Run tool self.test_try("Run ctselect") try: select.run() self.test_try_success() except: self.test_try_failure("Exception occured in ctselect.") # Save events self.test_try("Save events") try: select.save() self.test_try_success() except: self.test_try_failure("Exception occured in saving events.") # Return return
def test_unbinned_mem(self): """ Test unbinned in-memory pipeline. """ # Set script parameters model_name = "data/crab.xml" caldb = "irf" irf = "cta_dummy_irf" ra = 83.63 dec = 22.01 rad_sim = 10.0 tstart = 0.0 tstop = 1800.0 emin = 0.1 emax = 100.0 rad_select = 3.0 # Simulate events sim = ctools.ctobssim() sim["inmodel"].filename(model_name) sim["caldb"].string(caldb) sim["irf"].string(irf) sim["ra"].real(ra) sim["dec"].real(dec) sim["rad"].real(rad_sim) sim["tmin"].real(tstart) sim["tmax"].real(tstop) sim["emin"].real(emin) sim["emax"].real(emax) self.test_try("Run ctobssim") try: sim.run() self.test_try_success() except: self.test_try_failure("Exception occured in ctobssim.") # Select events select = ctools.ctselect(sim.obs()) select["ra"].real(ra) select["dec"].real(dec) select["rad"].real(rad_select) select["tmin"].real(tstart) select["tmax"].real(tstop) select["emin"].real(emin) select["emax"].real(emax) self.test_try("Run ctselect") try: select.run() self.test_try_success() except: self.test_try_failure("Exception occured in ctselect.") # Perform maximum likelihood fitting like = ctools.ctlike(select.obs()) self.test_try("Run ctlike") try: like.run() self.test_try_success() except: self.test_try_failure("Exception occured in ctlike.")
def _test_python(self): """ Test ctselect from Python """ # Set-up ctselect select = ctools.ctselect() select['inobs'] = self._events select['outobs'] = 'ctselect_py1.fits' select['ra'] = 83.63 select['dec'] = 22.01 select['rad'] = 3 select['tmin'] = 0 select['tmax'] = 1800 select['emin'] = 0.1 select['emax'] = 100 select['logfile'] = 'ctselect_py1.log' select['chatter'] = 2 # Run ctselect tool select.logFileOpen() # Make sure we get a log file select.run() select.save() # Check result file self._check_result_file('ctselect_py1.fits') # Return return
def unbinned_pipeline(duration): """ Unbinned analysis pipeline. """ # Set script parameters model_name = "${CTOOLS}/share/models/crab.xml" caldb = "prod2" irf = "South_50h" ra = 83.63 dec = 22.01 rad_sim = 10.0 tstart = 0.0 tstop = duration emin = 0.1 emax = 100.0 rad_select = 3.0 # Get start CPU time tstart = time.clock() # Simulate events sim = ctools.ctobssim() sim["inmodel"].filename(model_name) sim["caldb"].string(caldb) sim["irf"].string(irf) sim["ra"].real(ra) sim["dec"].real(dec) sim["rad"].real(rad_sim) sim["tmin"].real(tstart) sim["tmax"].real(tstop) sim["emin"].real(emin) sim["emax"].real(emax) sim.run() # Select events select = ctools.ctselect(sim.obs()) select["ra"].real(ra) select["dec"].real(dec) select["rad"].real(rad_select) select["tmin"].real(tstart) select["tmax"].real(tstop) select["emin"].real(emin) select["emax"].real(emax) select.run() # Get ctlike start CPU time tctlike = time.clock() # Perform maximum likelihood fitting like = ctools.ctlike(select.obs()) like.run() # Get stop CPU time tstop = time.clock() telapsed = tstop - tstart tctlike = tstop - tctlike # Return return telapsed, tctlike
def unbinned_pipeline(model_name, duration): """ Unbinned analysis pipeline. """ # Set script parameters caldb = "prod2" irf = "South_50h" ra = 83.63 dec = 22.01 rad_sim = 10.0 tstart = 0.0 tstop = duration emin = 0.1 emax = 100.0 rad_select = 3.0 # Get start CPU time cpu_start = time.clock() # Simulate events sim = ctools.ctobssim() sim["inmodel"] = model_name sim["caldb"] = caldb sim["irf"] = irf sim["ra"] = ra sim["dec"] = dec sim["rad"] = rad_sim sim["tmin"] = tstart sim["tmax"] = tstop sim["emin"] = emin sim["emax"] = emax sim.run() # Select events select = ctools.ctselect(sim.obs()) select["ra"] = ra select["dec"] = dec select["rad"] = rad_select select["tmin"] = tstart select["tmax"] = tstop select["emin"] = emin select["emax"] = emax select.run() # Get ctlike start CPU time cpu_ctlike = time.clock() # Perform maximum likelihood fitting like = ctools.ctlike(select.obs()) like.run() # Get stop CPU time and compute elapsed times cpu_stop = time.clock() cpu_elapsed = cpu_stop - cpu_start cpu_ctlike = cpu_stop - cpu_ctlike # Return return cpu_elapsed, cpu_ctlike
def run_pipeline(obs, ra=83.63, dec=22.01, rad=3.0, emin=0.1, emax=100.0, tmin=0.0, tmax=0.0, debug=False): """ Simulation and binned analysis pipeline Parameters ---------- obs : `~gammalib.GObservations` Observation container ra : float, optional Right Ascension of Region of Interest centre (deg) dec : float, optional Declination of Region of Interest centre (deg) rad : float, optional Radius of Region of Interest (deg) emin : float, optional Minimum energy (TeV) emax : float, optional Maximum energy (TeV) tmin : float, optional Start time (s) tmax : float, optional Stop time (s) debug : bool, optional Debug function """ # Simulate events sim = ctools.ctobssim(obs) sim['debug'] = debug sim.run() # Select events select = ctools.ctselect(sim.obs()) select['ra'] = ra select['dec'] = dec select['rad'] = rad select['emin'] = emin select['emax'] = emax select['tmin'] = tmin select['tmax'] = tmax select['debug'] = debug select.run() # Perform maximum likelihood fitting like = ctools.ctlike(select.obs()) like['debug'] = True # Switch this always on for results in console like.run() # Return return
def test_unbinned_fits(self): """ Test unbinned pipeline with FITS file saving """ # Set script parameters events_name = 'events.fits' selected_events_name = 'selected_events.fits' result_name = 'results.xml' ra = 83.63 dec = 22.01 rad_sim = 3.0 rad_select = 2.0 tstart = 0.0 tstop = 300.0 emin = 1.0 emax = 100.0 # Simulate events sim = ctools.ctobssim() sim['inmodel'] = self._model sim['outevents'] = events_name sim['caldb'] = self._caldb sim['irf'] = self._irf sim['ra'] = ra sim['dec'] = dec sim['rad'] = rad_sim sim['tmin'] = tstart sim['tmax'] = tstop sim['emin'] = emin sim['emax'] = emax sim.execute() # Select events select = ctools.ctselect() select['inobs'] = events_name select['outobs'] = selected_events_name select['ra'] = ra select['dec'] = dec select['rad'] = rad_select select['tmin'] = tstart select['tmax'] = tstop select['emin'] = emin select['emax'] = emax select.execute() # Perform maximum likelihood fitting like = ctools.ctlike() like['inobs'] = selected_events_name like['inmodel'] = self._model like['outmodel'] = result_name like['caldb'] = self._caldb like['irf'] = self._irf like.execute() # Return return
def test_unbinned_fits(self): """ Test unbinned pipeline with FITS file saving """ # Set script parameters events_name = 'events.fits' selected_events_name = 'selected_events.fits' result_name = 'results.xml' ra = 83.63 dec = 22.01 rad_sim = 10.0 rad_select = 3.0 tstart = 0.0 tstop = 300.0 emin = 0.1 emax = 100.0 # Simulate events sim = ctools.ctobssim() sim['inmodel'] = self._model sim['outevents'] = events_name sim['caldb'] = self._caldb sim['irf'] = self._irf sim['ra'] = ra sim['dec'] = dec sim['rad'] = rad_sim sim['tmin'] = tstart sim['tmax'] = tstop sim['emin'] = emin sim['emax'] = emax sim.execute() # Select events select = ctools.ctselect() select['inobs'] = events_name select['outobs'] = selected_events_name select['ra'] = ra select['dec'] = dec select['rad'] = rad_select select['tmin'] = tstart select['tmax'] = tstop select['emin'] = emin select['emax'] = emax select.execute() # Perform maximum likelihood fitting like = ctools.ctlike() like['inobs'] = selected_events_name like['inmodel'] = self._model like['outmodel'] = result_name like['caldb'] = self._caldb like['irf'] = self._irf like.execute() # Return return
def run_pipeline(obs, ra=83.63, dec=22.01, rad=3.0, emin=0.1, emax=100.0, tmin=0.0, tmax=0.0, model="${CTOOLS}/share/models/crab.xml", caldb="prod2", irf="South_50h", debug=False): """ Simulation and unbinned analysis pipeline. Keywords: ra - RA of cube centre [deg] (default: 83.63) dec - DEC of cube centre [deg] (default: 22.01) rad - Selection radius [deg] (default: 3.0) emin - Minimum energy of cube [TeV] (default: 0.1) emax - Maximum energy of cube [TeV] (default: 100.0) tmin - Start time [MET] (default: 0.0) tmax - Stop time [MET] (default: 0.0) model - Model Xml file caldb - Calibration database path (default: "dummy") irf - Instrument response function (default: cta_dummy_irf) debug - Enable debugging (default: False) """ # Get model # Simulate events sim = ctools.ctobssim(obs) sim["debug"] = debug sim["outevents"] = "obs.xml" sim.execute() # Select events select = ctools.ctselect() select["inobs"] = "obs.xml" select["outobs"] = "obs_selected.xml" select["ra"] = ra select["dec"] = dec select["rad"] = rad select["emin"] = emin select["emax"] = emax select["tmin"] = tmin select["tmax"] = tmax select["debug"] = debug select.execute() # Perform maximum likelihood fitting like = ctools.ctlike() like["inobs"] = "obs_selected.xml" like["inmodel"] = model like["outmodel"] = "fit_results.xml" like["caldb"] = caldb like["irf"] = irf like["debug"] = True # Switch this always on for results in console like.execute() # Return return
def ctselect(self, RA, DEC): select = ctools.ctselect() select["inobs"] = 'events.fits' select["outobs"] = 'selected_events.fits' select["ra"] = RA select["dec"] = DEC select["rad"] = 5 select["tmin"] = '2020-01-01T00:00:00' select["tmax"] = '2020-01-01T01:00:00' select["emin"] = 0.3 select["emax"] = 150.0 select.run() select.save()
def test_unbinned_mem(self): """ Test unbinned in-memory pipeline """ # Set script parameters ra = 83.63 dec = 22.01 rad_sim = 3.0 rad_select = 2.0 tstart = 0.0 tstop = 300.0 emin = 1.0 emax = 100.0 # Simulate events sim = ctools.ctobssim() sim['inmodel'] = self._model sim['caldb'] = self._caldb sim['irf'] = self._irf sim['ra'] = ra sim['dec'] = dec sim['rad'] = rad_sim sim['tmin'] = tstart sim['tmax'] = tstop sim['emin'] = emin sim['emax'] = emax sim.run() # Select events select = ctools.ctselect(sim.obs()) select['ra'] = ra select['dec'] = dec select['rad'] = rad_select select['tmin'] = tstart select['tmax'] = tstop select['emin'] = emin select['emax'] = emax select.run() # Perform maximum likelihood fitting like = ctools.ctlike(select.obs()) like.run() # Return return
def test_unbinned_mem(self): """ Test unbinned in-memory pipeline """ # Set script parameters ra = 83.63 dec = 22.01 rad_sim = 10.0 rad_select = 3.0 tstart = 0.0 tstop = 300.0 emin = 0.1 emax = 100.0 # Simulate events sim = ctools.ctobssim() sim['inmodel'] = self._model sim['caldb'] = self._caldb sim['irf'] = self._irf sim['ra'] = ra sim['dec'] = dec sim['rad'] = rad_sim sim['tmin'] = tstart sim['tmax'] = tstop sim['emin'] = emin sim['emax'] = emax sim.run() # Select events select = ctools.ctselect(sim.obs()) select['ra'] = ra select['dec'] = dec select['rad'] = rad_select select['tmin'] = tstart select['tmax'] = tstop select['emin'] = emin select['emax'] = emax select.run() # Perform maximum likelihood fitting like = ctools.ctlike(select.obs()) like.run() # Return return
def run_pipeline(obs, ra=83.63, dec=22.01, rad=3.0, \ emin=0.1, emax=100.0, \ tmin=0.0, tmax=0.0, \ debug=False): """ Simulation and unbinned analysis pipeline. Keywords: ra - RA of cube centre [deg] (default: 83.63) dec - DEC of cube centre [deg] (default: 22.01) rad - Selection radius [deg] (default: 3.0) emin - Minimum energy of cube [TeV] (default: 0.1) emax - Maximum energy of cube [TeV] (default: 100.0) tmin - Start time [MET] (default: 0.0) tmax - Stop time [MET] (default: 0.0) debug - Enable debugging (default: False) """ # Simulate events sim = ctools.ctobssim(obs) sim["debug"].boolean(debug) sim.run() # Select events select = ctools.ctselect(sim.obs()) select["ra"].real(ra) select["dec"].real(dec) select["rad"].real(rad) select["emin"].real(emin) select["emax"].real(emax) select["tmin"].real(tmin) select["tmax"].real(tmax) select["debug"].boolean(debug) select.run() # Perform maximum likelihood fitting like = ctools.ctlike(select.obs()) like["debug"].boolean(True) # Switch this always on for results in console like.run() # Return return
def select_events(events_file, selected_file, tmax=100, force=0): if tmax < 1: print("need tmax > 0 to select events") exit(1) log_file = os.path.join(os.path.dirname(selected_file), "ctselect_" + str(tmax) + ".log") if not os.path.isfile(selected_file) or force == 1: select = ctools.ctselect() select.clear() select["inobs"] = events_file select["rad"] = "INDEF" select["tmin"] = 0 select["tmax"] = tmax select["emin"] = "INDEF" select["emax"] = "INDEF" select["outobs"] = selected_file select["logfile"] = log_file select.logFileOpen() select.run() select.save() sys.stderr.write("File '%s' created.\n" % selected_file) return True
def select_events(obs, emin='UNDEF', emax='UNDEF', rad=2.0): """ Select events within a given RoI radius Parameters ---------- obs : `~gammalib.GObservations` Observation container emin : float, optional Minimum energy (TeV) emax : float, optional Maximum energy (TeV) rad : float, optional Radial selection radius (deg) Returns ------- obs : `~gammalib.GObservations` Observation container """ # Setup task parameters select = ctools.ctselect(obs) select['ra'] = 'UNDEF' select['dec'] = 'UNDEF' select['rad'] = rad select['tmin'] = 'UNDEF' select['tmax'] = 'UNDEF' select['emin'] = emin select['emax'] = emax select['usethres'] = 'DEFAULT' # Select events select.run() # Extract observation obs = select.obs().copy() # Return observation return obs
def selectData(cfg): """ Select data with ctselect """ outputdir = cfg.getValue('general', 'outputdir') select = ctools.ctselect() select["inobs"] = outputdir + '/' + cfg.getValue('csiactobs', 'obs_output') select["outobs"] = outputdir + '/' + cfg.getValue('ctselect', 'output') select["ra"] = cfg.getValue('model', 'coords', 'ra') select["dec"] = cfg.getValue('model', 'coords', 'dec') select["rad"] = cfg.getValue('ctselect', 'radius') select["emin"] = cfg.getValue('ctselect', 'emin') select["emax"] = cfg.getValue('ctselect', 'emax') select["tmin"] = cfg.getValue('ctselect', 'tmin') select["tmax"] = cfg.getValue('ctselect', 'tmax') select["usethres"] = cfg.getValue('ctselect', 'usethres') if cfg.getValue('general', 'debug') is True: select["debug"] = True #select["prefix"] = outputdir + '/' + 'selected_' select.run() select.save() os.system("mv selected_events_*.fits " + outputdir + "/.")
def phase_events(name, lon, lat, rad=0.2, lc=True): """ Phase events Parameters ---------- name : string Source name lon : float Galactic longitude of binary (deg) lat : float Galactic latitude of binary (deg) rad : float, optional Angular cut (deg) lc : bool, optional Use light curve """ # Dump header print('Phase events') # Enter working directory cwd = enter_wd(name) # Set filenames if lc: suffix = '' else: suffix = '_const' inxml = 'gps_obs_simulated%s.xml' % (suffix) outxml = 'gps_obs_phased%s.xml' % (suffix) prefix = 'phased%s/' % (suffix) outxml2 = 'gps_obs_selected_phased%s.xml' % (suffix) prefix2 = 'selected_phased%s/' % (suffix) # Continue only if phased events do not exist if not os.path.isfile(outxml): # Create directory try: os.makedirs('phased%s' % suffix) except: pass # Setup task parameters phase = ctools.ctphase() phase['inobs'] = inxml phase['outobs'] = outxml phase['prefix'] = prefix phase['inmodel'] = 'gps_models.xml' phase['srcname'] = name phase.logFileOpen() # Phase events phase.execute() # Continue only if selected phased events do not exist if not os.path.isfile(outxml2): # Create directory try: os.makedirs('selected_phased%s' % suffix) except: pass # Set source position dir = gammalib.GSkyDir() dir.lb_deg(lon, lat) # Setup task parameters select = ctools.ctselect() select['inobs'] = outxml select['outobs'] = outxml2 select['prefix'] = prefix2 select['usepnt'] = False select['ra'] = dir.ra_deg() select['dec'] = dir.dec_deg() select['rad'] = rad select['emin'] = 'NONE' select['emax'] = 'NONE' select['tmin'] = 'NONE' select['tmax'] = 'NONE' select.logFileOpen() # Select events select.execute() # Exit working directory exit_wd(cwd) # Return return
plt.title(r'Gamma-Ray Annihilation Spectrum: $m_{\chi}$ = %s' % str(dm_mass)) plt.xlabel(r'Energy $\left \{ log_{10} \mathrm{TeV} \right \}$') plt.ylabel( r'$\frac{dN}{dE} \left \{ \frac{1}{s*cm^{2}*\mathrm{TeV}} \right \}$') plt.xscale('log') plt.yscale('log') plt.ylim([ymin, ymax]) plt.savefig('logs/spec.png', dpi=100) plt.clf() halo_fits_tot_jfactor = veripy.read_halo_jfactor_fits(halo_fits) print(get_time(), 'starting ctselect') t3 = time.time() sel = ctools.ctselect(obs) sel['usepnt'] = True sel['ra'] = sgra.ra_deg() # 'NONE' sel['dec'] = sgra.dec_deg() # 'NONE' sel['rad'] = span / 2 # 'NONE' sel['tmin'] = 0.0 sel['tmax'] = 0.0 sel['emin'] = emin sel['emax'] = emax sel['logfile'] = 'logs/ctselect.log' sel.logFileOpen() sel.run() sel.logFileClose() t4 = time.time() printstat('%.1f seconds to run ctselect' % (t4 - t3))
def run(self): """ Run the script. """ # Switch screen logging on in debug mode if self._logDebug(): self._log.cout(True) # Get parameters self._get_parameters() # Write spectral binning into header if self._logTerse(): self._log("\n") self._log.header1("Spectral binning") if self._binned_mode: cube_ebounds = self._obs[0].events().ebounds() self._log.parformat("Counts cube energy range") self._log(str(cube_ebounds.emin())) self._log(" - ") self._log(str(cube_ebounds.emax())) self._log("\n") for i in range(self._ebounds.size()): self._log.parformat("Bin " + str(i + 1)) self._log(str(self._ebounds.emin(i))) self._log(" - ") self._log(str(self._ebounds.emax(i))) self._log("\n") # Write observation into logger if self._logTerse(): self._log("\n") self._log.header1("Observation") self._log(str(self._obs)) self._log("\n") # Write header if self._logTerse(): self._log("\n") self._log.header1("Adjust model parameters") # Adjust model parameters dependent on input user parameters for model in self._obs.models(): # Set TS flag for all models to false. # Source of interest will be set to true later model.tscalc(False) # Log model name if self._logExplicit(): self._log.header3(model.name()) # Deal with the source of interest if model.name() == self._srcname: for par in model: if par.is_free() and self._logExplicit(): self._log(" Fixing \"" + par.name() + "\"\n") par.fix() normpar = model.spectral()[0] if normpar.is_fixed() and self._logExplicit(): self._log(" Freeing \"" + normpar.name() + "\"\n") normpar.free() if self._calc_ts: model.tscalc(True) elif self._fix_bkg and not model.classname() == "GModelSky": for par in model: if par.is_free() and self._logExplicit(): self._log(" Fixing \"" + par.name() + "\"\n") par.fix() elif self._fix_srcs and model.classname() == "GModelSky": for par in model: if par.is_free() and self._logExplicit(): self._log(" Fixing \"" + par.name() + "\"\n") par.fix() # Write header if self._logTerse(): self._log("\n") self._log.header1("Generate spectrum") self._log(str(self._ebounds)) # Initialise FITS Table with extension "SPECTRUM" table = gammalib.GFitsBinTable(self._ebounds.size()) table.extname("SPECTRUM") # Add Header for compatibility with gammalib.GMWLSpectrum table.card("INSTRUME", "CTA", "Name of Instrument") table.card("TELESCOP", "CTA", "Name of Telescope") # Create FITS table columns nrows = self._ebounds.size() energy = gammalib.GFitsTableDoubleCol("Energy", nrows) energy_low = gammalib.GFitsTableDoubleCol("ed_Energy", nrows) energy_high = gammalib.GFitsTableDoubleCol("eu_Energy", nrows) flux = gammalib.GFitsTableDoubleCol("Flux", nrows) flux_err = gammalib.GFitsTableDoubleCol("e_Flux", nrows) TSvalues = gammalib.GFitsTableDoubleCol("TS", nrows) ulim_values = gammalib.GFitsTableDoubleCol("UpperLimit", nrows) Npred_values = gammalib.GFitsTableDoubleCol("Npred", nrows) energy.unit("TeV") energy_low.unit("TeV") energy_high.unit("TeV") flux.unit("erg/cm2/s") flux_err.unit("erg/cm2/s") ulim_values.unit("erg/cm2/s") # Loop over energy bins for i in range(nrows): # Log information if self._logExplicit(): self._log("\n") self._log.header2("Energy bin " + str(i + 1)) # Get energy boundaries emin = self._ebounds.emin(i) emax = self._ebounds.emax(i) elogmean = self._ebounds.elogmean(i) elogmean2 = elogmean.MeV() * elogmean.MeV() # Store energy as TeV energy[i] = elogmean.TeV() # Store energy errors energy_low[i] = (elogmean - emin).TeV() energy_high[i] = (emax - elogmean).TeV() # Use ctselect for unbinned analysis if not self._binned_mode: # Log information if self._logExplicit(): self._log.header3("Selecting events") # Select events select = ctools.ctselect(self._obs) select["emin"] = emin.TeV() select["emax"] = emax.TeV() select["tmin"] = "UNDEFINED" select["tmax"] = "UNDEFINED" select["rad"] = "UNDEFINED" select["ra"] = "UNDEFINED" select["dec"] = "UNDEFINED" select.run() # Retrieve observation obs = select.obs() # Use ctcubemask for binned analysis else: # Header if self._logExplicit(): self._log.header3("Filtering cube") # Select layers cubemask = ctools.ctcubemask(self._obs) cubemask["regfile"] = "NONE" cubemask["ra"] = "UNDEFINED" cubemask["dec"] = "UNDEFINED" cubemask["rad"] = "UNDEFINED" cubemask["emin"] = emin.TeV() cubemask["emax"] = emax.TeV() cubemask.run() # Set new binned observation obs = cubemask.obs() # Header if self._logExplicit(): self._log.header3("Performing fit") # Likelihood like = ctools.ctlike(obs) like["edisp"] = self._edisp like.run() # Skip bin if no event was present if like.obs().logL() == 0.0: # Log information if self._logExplicit(): self._log("No event in this bin. ") self._log("Likelihood is zero. ") self._log("Bin is skipped.") # Set all values to 0 flux[i] = 0.0 flux_err[i] = 0.0 TSvalues[i] = 0.0 ulim_values[i] = 0.0 Npred_values[i] = 0.0 continue # Get results fitted_models = like.obs().models() source = fitted_models[self._srcname] # Calculate Upper Limit ulimit_value = -1.0 if self._calc_ulimit: # Logging information if self._logExplicit(): self._log.header3("Computing upper limit") # Create upper limit object ulimit = ctools.ctulimit(like.obs()) ulimit["srcname"] = self._srcname ulimit["eref"] = elogmean.TeV() # Try to run upper limit and catch exceptions try: ulimit.run() ulimit_value = ulimit.diff_ulimit() except: if self._logExplicit(): self._log("Upper limit calculation failed.") ulimit_value = -1.0 # Get TS value TS = -1.0 if self._calc_ts: TS = source.ts() # Compute Npred value (only works for unbinned analysis) Npred = 0.0 if not self._binned_mode: for observation in like.obs(): Npred += observation.npred(source) # Get differential flux fitted_flux = source.spectral().eval(elogmean) # Compute flux error parvalue = source.spectral()[0].value() rel_error = source.spectral()[0].error() / parvalue e_flux = fitted_flux * rel_error # Set values for storage TSvalues[i] = TS # Set npred values Npred_values[i] = Npred # Convert fluxes to nuFnu flux[i] = fitted_flux * elogmean2 * gammalib.MeV2erg flux_err[i] = e_flux * elogmean2 * gammalib.MeV2erg if ulimit_value > 0.0: ulim_values[i] = ulimit_value * elogmean2 * gammalib.MeV2erg # Log information if self._logTerse(): self._log("\n") self._log.parformat("Bin " + str(i + 1)) self._log(str(flux[i])) self._log(" +/- ") self._log(str(flux_err[i])) if self._calc_ulimit and ulim_values[i] > 0.0: self._log(" [< " + str(ulim_values[i]) + "]") self._log(" erg/cm2/s") if self._calc_ts and TSvalues[i] > 0.0: self._log(" (TS = " + str(TS) + ")") # Append filled columns to fits table table.append(energy) table.append(energy_low) table.append(energy_high) table.append(flux) table.append(flux_err) table.append(TSvalues) table.append(ulim_values) table.append(Npred_values) # Create the FITS file now self._fits = gammalib.GFits() self._fits.append(table) # Return return
def test_unbinned_fits(self): """ Test unbinned pipeline with FITS file saving. """ # Set script parameters model_name = "data/crab.xml" events_name = "events.fits" selected_events_name = "selected_events.fits" result_name = "results.xml" caldb = "irf" irf = "cta_dummy_irf" ra = 83.63 dec = 22.01 rad_sim = 10.0 tstart = 0.0 tstop = 1800.0 emin = 0.1 emax = 100.0 rad_select = 3.0 # Simulate events sim = ctools.ctobssim() sim["inmodel"].filename(model_name) sim["outevents"].filename(events_name) sim["caldb"].string(caldb) sim["irf"].string(irf) sim["ra"].real(ra) sim["dec"].real(dec) sim["rad"].real(rad_sim) sim["tmin"].real(tstart) sim["tmax"].real(tstop) sim["emin"].real(emin) sim["emax"].real(emax) self.test_try("Execute ctobssim") try: sim.execute() self.test_try_success() except: self.test_try_failure("Exception occured in ctobssim.") # Select events select = ctools.ctselect() select["inobs"].filename(events_name) select["outobs"].filename(selected_events_name) select["ra"].real(ra) select["dec"].real(dec) select["rad"].real(rad_select) select["tmin"].real(tstart) select["tmax"].real(tstop) select["emin"].real(emin) select["emax"].real(emax) self.test_try("Execute ctselect") try: select.execute() self.test_try_success() except: self.test_try_failure("Exception occured in ctselect.") # Perform maximum likelihood fitting like = ctools.ctlike() like["inobs"].filename(selected_events_name) like["inmodel"].filename(model_name) like["outmodel"].filename(result_name) like["caldb"].string(caldb) like["irf"].string(irf) self.test_try("Execute ctlike") try: like.execute() self.test_try_success() except: self.test_try_failure("Exception occured in ctlike.")
def run_pipeline(obs, ra=83.63, dec=22.01, rad=3.0, emin=0.1, emax=100.0, tmin=0.0, tmax=0.0, model='data/crab.xml', caldb='prod2', irf='South_0.5h', debug=False): """ Simulation and unbinned analysis pipeline Parameters ---------- obs : `~gammalib.GObservations` Observation container ra : float, optional Right Ascension of Region of Interest centre (deg) dec : float, optional Declination of Region of Interest centre (deg) rad : float, optional Radius of Region of Interest (deg) emin : float, optional Minimum energy (TeV) emax : float, optional Maximum energy (TeV) tmin : float, optional Start time (s) tmax : float, optional Stop time (s) model : str, optional Model definition XML file caldb : str, optional Calibration database path irf : str, optional Instrument response function debug : bool, optional Debug function """ # Get model # Simulate events sim = ctools.ctobssim(obs) sim['debug'] = debug sim['outevents'] = 'obs.xml' sim.execute() # Select events select = ctools.ctselect() select['inobs'] = 'obs.xml' select['outobs'] = 'obs_selected.xml' select['ra'] = ra select['dec'] = dec select['rad'] = rad select['emin'] = emin select['emax'] = emax select['tmin'] = tmin select['tmax'] = tmax select['debug'] = debug select.execute() # Perform maximum likelihood fitting like = ctools.ctlike() like['inobs'] = 'obs_selected.xml' like['inmodel'] = model like['outmodel'] = 'fit_results.xml' like['caldb'] = caldb like['irf'] = irf like['debug'] = True # Switch this always on for results in console like.execute() # Return return
def grb_simulation(sim_in, config_in, model_xml, fits_header_0, counter): """ Function to handle the GRB simulation. :param sim_in: the yaml file for the simulation (unpacked as a dict of dicts) :param config_in: the yaml file for the job handling (unpacked as a dict of dicts) :param model_xml: the XML model name for the source under analysis :param fits_header_0: header for the fits file of the GRB model to use. Used in the visibility calculation :param counter: integer number. counts the id of the source realization :return: significance obtained with the activated detection methods """ src_name = model_xml.split('/')[-1].split('model_')[1][:-4] print(src_name, counter) ctools_pipe_path = create_path(config_in['exe']['software_path']) ctobss_params = sim_in['ctobssim'] seed = int(counter)*10 # PARAMETERS FROM THE CTOBSSIM sim_t_min = u.Quantity(ctobss_params['time']['t_min']).to_value(u.s) sim_t_max = u.Quantity(ctobss_params['time']['t_max']).to_value(u.s) sim_e_min = u.Quantity(ctobss_params['energy']['e_min']).to_value(u.TeV) sim_e_max = u.Quantity(ctobss_params['energy']['e_max']).to_value(u.TeV) sim_rad = ctobss_params['radius'] models = sim_in['source'] source_type = models['type'] if source_type == "GRB": phase_path = "/" + models['phase'] elif source_type == "GW": phase_path = "" output_path = create_path(sim_in['output']['path'] + phase_path + '/' + src_name) save_simulation = ctobss_params['save_simulation'] with open(f"{output_path}/GRB-{src_name}_seed-{seed}.txt", "w") as f: f.write(f"GRB,seed,time_start,time_end,sigma_lima,sqrt_TS_onoff,sqrt_TS_std\n") # VISIBILITY PART # choose between AUTO mode (use visibility) and MANUAL mode (manually insert IRF) simulation_mode = sim_in['IRF']['mode'] if simulation_mode == "auto": print("using visibility to get IRFs") # GRB information from the fits header ra = fits_header_0['RA'] dec = fits_header_0['DEC'] t0 = Time(fits_header_0['GRBJD']) irf_dict = sim_in['IRF'] site = irf_dict['site'] obs_condition = Observability(site=site) obs_condition.set_irf(irf_dict) t_zero_mode = ctobss_params['time']['t_zero'].lower() if t_zero_mode == "VIS": # check if the source is visible one day after the onset of the source print("time starts when source becomes visible") obs_condition.Proposal_obTime = 86400 condition_check = obs_condition.check(RA=ra, DEC=dec, t_start=t0) elif t_zero_mode == "ONSET": print("time starts from the onset of the GRB") condition_check = obs_condition.check(RA=ra, DEC=dec, t_start=t0, t_min=sim_t_min, t_max=sim_t_max) else: print(f"Choose some proper mode between 'VIS' and 'ONSET'. {t_zero_mode} is not a valid one.") sys.exit() # NO IRF in AUTO mode ==> No simulation! == EXIT! if len(condition_check) == 0: f.write(f"{src_name},{seed}, -1, -1, -1, -1, -1\n") sys.exit() elif simulation_mode == "manual": print("manual picking IRF") # find proper IRF name irf = IRFPicker(sim_in, ctools_pipe_path) name_irf = irf.irf_pick() backgrounds_path = create_path(ctobss_params['bckgrnd_path']) fits_background_list = glob.glob( f"{backgrounds_path}/{irf.prod_number}_{irf.prod_version}_{name_irf}/background*.fits") if len(fits_background_list) == 0: print(f"No background for IRF {name_irf}") sys.exit() fits_background_list = sorted(fits_background_list, key=sort_background) background_fits = fits_background_list[int(counter) - 1] obs_back = gammalib.GCTAObservation(background_fits) else: print(f"wrong input for IRF - mode. Input is {simulation_mode}. Use 'auto' or 'manual' instead") sys.exit() if irf.prod_number == "3b" and irf.prod_version == 0: caldb = "prod3b" else: caldb = f'prod{irf.prod_number}-v{irf.prod_version}' # source simulation sim = ctools.ctobssim() sim['inmodel'] = model_xml sim['caldb'] = caldb sim['irf'] = name_irf sim['ra'] = 0.0 sim['dec'] = 0.0 sim['rad'] = sim_rad sim['tmin'] = sim_t_min sim['tmax'] = sim_t_max sim['emin'] = sim_e_min sim['emax'] = sim_e_max sim['seed'] = seed sim.run() obs = sim.obs() # # move the source photons from closer to (RA,DEC)=(0,0), where the background is located # for event in obs[0].events(): # # ra_evt = event.dir().dir().ra() # dec_evt = event.dir().dir().dec() # ra_evt_deg = event.dir().dir().ra_deg() # dec_evt_deg = event.dir().dir().dec_deg() # # ra_corrected = (ra_evt_deg - ra_pointing)*np.cos(dec_evt) # dec_corrected = dec_evt_deg - dec_pointing # event.dir().dir().radec_deg(ra_corrected, dec_corrected) # append all background events to GRB ones ==> there's just one observation and not two for event in obs_back.events(): obs[0].events().append(event) # ctselect to save data on disk if save_simulation: event_list_path = create_path(f"{ctobss_params['output_path']}/{src_name}/") #obs.save(f"{event_list_path}/event_list_source-{src_name}_seed-{seed:03}.fits") select_time = ctools.ctselect(obs) select_time['rad'] = sim_rad select_time['tmin'] = sim_t_min select_time['tmax'] = sim_t_max select_time['emin'] = sim_e_min select_time['emax'] = sim_e_max select_time['outobs'] = f"{event_list_path}/event_list_source-{src_name}_{seed:03}.fits" select_time.run() sys.exit() # delete all 70+ models from the obs def file...not needed any more obs.models(gammalib.GModels()) # CTSELECT select_time = sim_in['ctselect']['time_cut'] slices = int(select_time['t_slices']) if slices == 0: times = [sim_t_min, sim_t_max] times_start = times[:-1] times_end = times[1:] elif slices > 0: time_mode = select_time['mode'] if time_mode == "log": times = np.logspace(np.log10(sim_t_min), np.log10(sim_t_max), slices + 1, endpoint=True) elif time_mode == "lin": times = np.linspace(sim_t_min, sim_t_max, slices + 1, endpoint=True) else: print(f"{time_mode} not valid. Use 'log' or 'lin' ") sys.exit() if select_time['obs_mode'] == "iter": times_start = times[:-1] times_end = times[1:] elif select_time['obs_mode'] == "cumul": times_start = np.repeat(times[0], slices) # this is to use the same array structure for the loop times_end = times[1:] elif select_time['obs_mode'] == "all": begins, ends = np.meshgrid(times[:-1], times[1:]) mask_times = begins < ends times_start = begins[mask_times].ravel() times_end = ends[mask_times].ravel() else: print(f"obs_mode: {select_time['obs_mode']} not supported") sys.exit() else: print(f"value {slices} not supported...check yaml file") sys.exit() # ------------------------------------ # ----- TIME LOOP STARTS HERE -------- # ------------------------------------ ctlike_mode = sim_in['detection'] mode_1 = ctlike_mode['counts'] mode_2 = ctlike_mode['ctlike-onoff'] mode_3 = ctlike_mode['ctlike-std'] for t_in, t_end in zip(times_start, times_end): sigma_onoff = 0 sqrt_ts_like_onoff = 0 sqrt_ts_like_std = 0 print("-----------------------------") print(f"t_in: {t_in:.2f}, t_end: {t_end:.2f}") # different ctlikes (onoff or std) need different files. # will be appended here and used later on for the final likelihood dict_obs_select_time = {} # perform time selection for this specific time bin select_time = ctools.ctselect(obs) select_time['rad'] = sim_rad select_time['tmin'] = t_in select_time['tmax'] = t_end select_time['emin'] = sim_e_min select_time['emax'] = sim_e_max select_time.run() if mode_1: fits_temp_title = f"skymap_{seed}_{t_in:.2f}_{t_end:.2f}.fits" pars_counts = ctlike_mode['pars_counts'] scale = float(pars_counts['scale']) npix = 2*int(sim_rad/scale) skymap = ctools.ctskymap(select_time.obs().copy()) skymap['emin'] = sim_e_min skymap['emax'] = sim_e_max skymap['nxpix'] = npix skymap['nypix'] = npix skymap['binsz'] = scale skymap['proj'] = 'TAN' skymap['coordsys'] = 'CEL' skymap['xref'] = 0 skymap['yref'] = 0 skymap['bkgsubtract'] = 'RING' skymap['roiradius'] = pars_counts['roiradius'] skymap['inradius'] = pars_counts['inradius'] skymap['outradius'] = pars_counts['outradius'] skymap['iterations'] = pars_counts['iterations'] skymap['threshold'] = pars_counts['threshold'] skymap['outmap'] = fits_temp_title skymap.execute() input_fits = fits.open(fits_temp_title) datain = input_fits[2].data datain[np.isnan(datain)] = 0.0 datain[np.isinf(datain)] = 0.0 sigma_onoff = np.max(datain) os.remove(fits_temp_title) if mode_3: dict_obs_select_time['std'] = select_time.obs().copy() if mode_2: onoff_time_sel = cscripts.csphagen(select_time.obs().copy()) onoff_time_sel['inmodel'] = 'NONE' onoff_time_sel['ebinalg'] = 'LOG' onoff_time_sel['emin'] = sim_e_min onoff_time_sel['emax'] = sim_e_max onoff_time_sel['enumbins'] = 30 onoff_time_sel['coordsys'] = 'CEL' onoff_time_sel['ra'] = 0.0 onoff_time_sel['dec'] = 0.5 onoff_time_sel['rad'] = 0.2 onoff_time_sel['bkgmethod'] = 'REFLECTED' onoff_time_sel['use_model_bkg'] = False onoff_time_sel['stack'] = False onoff_time_sel.run() dict_obs_select_time['onoff'] = onoff_time_sel.obs().copy() del onoff_time_sel # print(f"sigma ON/OFF: {sigma_onoff:.2f}") if mode_2 or mode_3: # Low Energy PL fitting # to be saved in this dict dict_pl_ctlike_out = {} e_min_pl_ctlike = 0.030 e_max_pl_ctlike = 0.080 # simple ctobssim copy and select for ctlike-std select_pl_ctlike = ctools.ctselect(select_time.obs().copy()) select_pl_ctlike['rad'] = 3 select_pl_ctlike['tmin'] = t_in select_pl_ctlike['tmax'] = t_end select_pl_ctlike['emin'] = e_min_pl_ctlike select_pl_ctlike['emax'] = e_max_pl_ctlike select_pl_ctlike.run() # create test source src_dir = gammalib.GSkyDir() src_dir.radec_deg(0, 0.5) spatial = gammalib.GModelSpatialPointSource(src_dir) # create and append source spectral model spectral = gammalib.GModelSpectralPlaw() spectral['Prefactor'].value(5.5e-16) spectral['Prefactor'].scale(1e-16) spectral['Index'].value(-2.6) spectral['Index'].scale(-1.0) spectral['PivotEnergy'].value(50000) spectral['PivotEnergy'].scale(1e3) model_src = gammalib.GModelSky(spatial, spectral) model_src.name('PL_fit_temp') model_src.tscalc(True) spectral_back = gammalib.GModelSpectralPlaw() spectral_back['Prefactor'].value(1.0) spectral_back['Prefactor'].scale(1.0) spectral_back['Index'].value(0) spectral_back['PivotEnergy'].value(300000) spectral_back['PivotEnergy'].scale(1e6) if mode_2: back_model = gammalib.GCTAModelIrfBackground() back_model.instruments('CTAOnOff') back_model.name('Background') back_model.spectral(spectral_back.copy()) onoff_pl_ctlike_lima = cscripts.csphagen(select_pl_ctlike.obs().copy()) onoff_pl_ctlike_lima['inmodel'] = 'NONE' onoff_pl_ctlike_lima['ebinalg'] = 'LOG' onoff_pl_ctlike_lima['emin'] = e_min_pl_ctlike onoff_pl_ctlike_lima['emax'] = e_max_pl_ctlike onoff_pl_ctlike_lima['enumbins'] = 30 onoff_pl_ctlike_lima['coordsys'] = 'CEL' onoff_pl_ctlike_lima['ra'] = 0.0 onoff_pl_ctlike_lima['dec'] = 0.5 onoff_pl_ctlike_lima['rad'] = 0.2 onoff_pl_ctlike_lima['bkgmethod'] = 'REFLECTED' onoff_pl_ctlike_lima['use_model_bkg'] = False onoff_pl_ctlike_lima['stack'] = False onoff_pl_ctlike_lima.run() onoff_pl_ctlike_lima.obs().models(gammalib.GModels()) onoff_pl_ctlike_lima.obs().models().append(model_src.copy()) onoff_pl_ctlike_lima.obs().models().append(back_model.copy()) like_pl = ctools.ctlike(onoff_pl_ctlike_lima.obs()) like_pl['refit'] = True like_pl.run() dict_pl_ctlike_out['onoff'] = like_pl.obs().copy() del onoff_pl_ctlike_lima del like_pl if mode_3: models_ctlike_std = gammalib.GModels() models_ctlike_std.append(model_src.copy()) back_model = gammalib.GCTAModelIrfBackground() back_model.instruments('CTA') back_model.name('Background') back_model.spectral(spectral_back.copy()) models_ctlike_std.append(back_model) # save models xmlmodel_PL_ctlike_std = 'test_model_PL_ctlike_std.xml' models_ctlike_std.save(xmlmodel_PL_ctlike_std) del models_ctlike_std like_pl = ctools.ctlike(select_pl_ctlike.obs().copy()) like_pl['inmodel'] = xmlmodel_PL_ctlike_std like_pl['refit'] = True like_pl.run() dict_pl_ctlike_out['std'] = like_pl.obs().copy() del like_pl del spatial del spectral del model_src del select_pl_ctlike # EXTENDED CTLIKE for key in dict_obs_select_time.keys(): likelihood_pl_out = dict_pl_ctlike_out[key] selected_data = dict_obs_select_time[key] pref_out_pl = likelihood_pl_out.models()[0]['Prefactor'].value() index_out_pl = likelihood_pl_out.models()[0]['Index'].value() pivot_out_pl = likelihood_pl_out.models()[0]['PivotEnergy'].value() expplaw = gammalib.GModelSpectralExpPlaw() expplaw['Prefactor'].value(pref_out_pl) expplaw['Index'].value(index_out_pl) expplaw['PivotEnergy'].value(pivot_out_pl) expplaw['CutoffEnergy'].value(80e3) if key == "onoff": selected_data.models()[0].name(src_name) selected_data.models()[0].tscalc(True) selected_data.models()[0].spectral(expplaw.copy()) like = ctools.ctlike(selected_data) like['refit'] = True like.run() ts = like.obs().models()[0].ts() if ts > 0: sqrt_ts_like_onoff = np.sqrt(like.obs().models()[0].ts()) else: sqrt_ts_like_onoff = 0 del like if key == "std": models_fit_ctlike = gammalib.GModels() # create test source src_dir = gammalib.GSkyDir() src_dir.radec_deg(0, 0.5) spatial = gammalib.GModelSpatialPointSource(src_dir) # append spatial and spectral models model_src = gammalib.GModelSky(spatial, expplaw.copy()) model_src.name('Source_fit') model_src.tscalc(True) models_fit_ctlike.append(model_src) # create and append background back_model = gammalib.GCTAModelIrfBackground() back_model.instruments('CTA') back_model.name('Background') spectral_back = gammalib.GModelSpectralPlaw() spectral_back['Prefactor'].value(1.0) spectral_back['Prefactor'].scale(1.0) spectral_back['Index'].value(0) spectral_back['PivotEnergy'].value(300000) spectral_back['PivotEnergy'].scale(1e6) back_model.spectral(spectral_back) models_fit_ctlike.append(back_model) # save models input_ctlike_xml = "model_GRB_fit_ctlike_in.xml" models_fit_ctlike.save(input_ctlike_xml) del models_fit_ctlike like = ctools.ctlike(selected_data) like['inmodel'] = input_ctlike_xml like['refit'] = True like.run() ts = like.obs().models()[0].ts() if ts > 0: sqrt_ts_like_std = np.sqrt(like.obs().models()[0].ts()) else: sqrt_ts_like_std = 0 del like # E_cut_off = like.obs().models()[0]['CutoffEnergy'].value() # E_cut_off_error = like.obs().models()[0]['CutoffEnergy'].error() # print(f"sqrt(TS) {key}: {np.sqrt(ts_like):.2f}") # print(f"E_cut_off {key}: {E_cut_off:.2f} +- {E_cut_off_error:.2f}") del dict_pl_ctlike_out f.write(f"{src_name},{seed},{t_in:.2f},{t_end:.2f},{sigma_onoff:.2f},{sqrt_ts_like_onoff:.2f},{sqrt_ts_like_std:.2f}\n") del dict_obs_select_time del select_time
def run_ana_dataprep(self, obsID=None): """ This function is used to prepare the data to the analysis. Parameters ---------- - obsID (str): list of obsID to be used in data preparation. By default, all of the are used. """ #----- Check binned/stacked if self.method_binned == False: self.method_stack = False #----- Create the output directory if needed if not os.path.exists(self.output_dir): os.mkdir(self.output_dir) #----- Make sure the map definition is ok if self.map_UsePtgRef: self._match_cluster_to_pointing( ) # Cluster map defined using pointings self._match_anamap_to_pointing( ) # Analysis map defined using pointings #----- Get the obs ID to run obsID = self._check_obsID(obsID) if not self.silent: print('----- ObsID to be analysed: ' + str(obsID)) print('') self.obs_setup.match_bkg_id() # make sure Bkg are unique #----- Observation definition file self.obs_setup.write_pnt(self.output_dir + '/Ana_Pnt.def', obsid=obsID) self.obs_setup.run_csobsdef(self.output_dir + '/Ana_Pnt.def', self.output_dir + '/Ana_ObsDef.xml') #----- Get the events xml file for the considered obsID self._write_new_xmlevent_from_obsid( self.output_dir + '/Events.xml', self.output_dir + '/Ana_Events.xml', obsID) #----- Data selection sel = ctools.ctselect() sel['inobs'] = self.output_dir + '/Ana_Events.xml' sel['outobs'] = self.output_dir + '/Ana_EventsSelected.xml' sel['prefix'] = self.output_dir + '/Ana_Selected' sel['usepnt'] = False sel['ra'] = self.map_coord.icrs.ra.to_value('deg') sel['dec'] = self.map_coord.icrs.dec.to_value('deg') sel['rad'] = self.map_fov.to_value('deg') * np.sqrt(2) / 2.0 sel['forcesel'] = True sel['emin'] = self.spec_emin.to_value('TeV') sel['emax'] = self.spec_emax.to_value('TeV') if self.time_tmin is not None: sel['tmin'] = self.time_tmin else: sel['tmin'] = 'NONE' if self.time_tmax is not None: sel['tmax'] = self.time_tmax else: sel['tmax'] = 'NONE' sel['phase'] = 'NONE' sel['expr'] = '' sel['usethres'] = 'NONE' sel['logfile'] = self.output_dir + '/Ana_EventsSelected_log.txt' sel['chatter'] = 2 sel.logFileOpen() sel.execute() sel.logFileClose() if not self.silent: print(sel) print('') #----- Model map_template_fov = np.amin(self.cluster.map_fov.to_value('deg')) if (not self.silent) and ( 2 * self.cluster.theta_truncation.to_value('deg') > map_template_fov): print( 'WARNING: the cluster extent is larger than the model map field of view.' ) print( ' The recovered normalization will thus be biased low.' ) print('') self._make_model(prefix='Ana_Model_Input', obsID=obsID) # Compute the model files #----- Binning (needed even if unbinned likelihood) for stacklist in [True, False]: ctscube = cubemaking.counts_cube(self.output_dir, self.map_reso, self.map_coord, self.map_fov, self.spec_emin, self.spec_emax, self.spec_enumbins, self.spec_ebinalg, stack=stacklist, logfile=self.output_dir + '/Ana_Countscube_log.txt', silent=self.silent) expcube = cubemaking.exp_cube(self.output_dir, self.map_reso, self.map_coord, self.map_fov, self.spec_emin, self.spec_emax, self.spec_enumbins, self.spec_ebinalg, logfile=self.output_dir + '/Ana_Expcube_log.txt', silent=self.silent) psfcube = cubemaking.psf_cube(self.output_dir, self.map_reso, self.map_coord, self.map_fov, self.spec_emin, self.spec_emax, self.spec_enumbins, self.spec_ebinalg, logfile=self.output_dir + '/Ana_Psfcube_log.txt', silent=self.silent) bkgcube = cubemaking.bkg_cube(self.output_dir, logfile=self.output_dir + '/Ana_Bkgcube_log.txt', silent=self.silent) if self.spec_edisp: edcube = cubemaking.edisp_cube(self.output_dir, self.map_coord, self.map_fov, self.spec_emin, self.spec_emax, self.spec_enumbins, self.spec_ebinalg, logfile=self.output_dir + '/Ana_Edispcube_log.txt', silent=self.silent)
def sim_select_like(sim_yaml, jobs_in, model_xml, background_fits, counter): """ :param sim_yaml: :param jobs_in: :param model_xml: :param background_fits: :param counter: :return: """ #print("----------------------------") print(model_xml.split('/')[-1], counter) config_in = yaml.safe_load(open(jobs_in)) ctools_pipe_path = create_path(config_in['exe']['software_path']) sim_in = yaml.safe_load(open(sim_yaml)) ctobss_params = sim_in['ctobssim'] # find proper IRF name irf = IRFPicker(sim_in, ctools_pipe_path) name_irf = irf.irf_pick() if irf.prod_version == "3b" and irf.prod_number == 0: caldb = "prod3b" else: caldb = f'prod{irf.prod_number}-v{irf.prod_version}' # loading background (this is a way of doing it without saving any file) # output.save("name.xml") to save the file obs_def = gammalib.GObservations() background_id = f"{str(int(counter) + 1).zfill(6)}" output = gammalib.GXml() level0 = gammalib.GXmlElement('observation_list title="observation library"') level1 = gammalib.GXmlElement(f'observation name="name_source" id="{background_id}" instrument="CTA"') level2 = gammalib.GXmlElement(f'parameter name="EventList" file="{background_fits}"') level1.append(level2) level0.append(level1) output.append(level0) obs_def.read(output) seed = int(counter)*10 # do the simulation sim = ctools.ctobssim() sim['inmodel'] = model_xml sim['caldb'] = caldb sim['irf'] = name_irf sim['ra'] = 0 sim['dec'] = 0 sim['rad'] = ctobss_params['radius'] sim['tmin'] = u.Quantity(ctobss_params['time']['t_min']).to_value(u.s) sim['tmax'] = u.Quantity(ctobss_params['time']['t_max']).to_value(u.s) sim['emin'] = u.Quantity(ctobss_params['energy']['e_min']).to_value(u.TeV) sim['emax'] = u.Quantity(ctobss_params['energy']['e_max']).to_value(u.TeV) sim['seed'] = seed sim.run() obs_def.append(sim.obs()[0]) # for obs in obs_def: # print(obs.id(), obs.nobserved()) select = ctools.ctselect(obs_def) select['rad'] = 3 select['tmin'] = 0 select['tmax'] = 50 select['emin'] = 0.05 select['emax'] = 1.0 select.run()
print('\n') print( f'\tstarting values for inteval {m + 1}: ON - {on_reg_counts} ; OFF - {off_reg_counts}' ) # excluding energy ranges below the threshold associated with zenith angle if en_steps[m] >= sim_e_min: r = reg_rad[m] print(f'\tregion radius: {r}') e_start = en_steps[m] e_stop = en_steps[m + 1] # print (sim_e_min) print( f'\tEnergy interval: {e_start},{e_stop}' ) # print(f'position on:{x[0]},{y[0]}') select = ctools.ctselect() select[ 'inobs'] = 'events_full_GRB.fits' select['usepnt'] = False select['ra'] = x[0] select['dec'] = y[0] select['rad'] = r select['tmin'] = t_slice_start select['tmax'] = t_slice_stop select['emin'] = e_start select['emax'] = e_stop select.run() on_reg_counts += select.obs( ).nobserved() print(
def spectrum(obs, source, ebounds): """ Returns spectral points in the given binning for the passed observations and source. Please note that specpoints can make spectra for any given spectral model, as long as it has a "Prefactor" or "Integral" parameter which scales the function Parameters: obs - Observation container source - Source name for which spectrum should be computed ebounds - GEbounds energy boundaries Keywords: None """ # Check if parameters Prefactor or Integral exist to scale mdoel normpar = "Prefactor" srcmodel = obs.models()[source] if not srcmodel.has_par(normpar): if srcmodel.has_par("Integral"): normpar = "Integral" else: print("Error: your spectral model of "+source+"does not"+\ "have a scaling parameter named 'Prefactor'"+\ " or 'Integral'") return # Fix all parameters except prefactor opt_spectral = srcmodel.spectral() for model in obs.models(): for par in range(model.size()): model[par].fix() opt_spectral[normpar].free() # Define spectrum dictionary, units are in format readable by astropy spec = {"energy":{"value":[],"eu_value":[],"ed_value":[],"unit":"none"}, "flux" :{"value":[],"eu_value":[],"ed_value":[],"unit":"none"}, "TS" :{"value":[],"eu_value":[],"ed_value":[],"unit":"none"}} # Loop over energy bins, fit and write result to spectrum for i in range(len(ebounds)): # Get logarithmic bin center and flux value of all energy fit ecenter = ebounds.elogmean(i) allflux = opt_spectral.eval(ecenter, gammalib.GTime(0.0)) # Clone observations and reset energy thresholds select = ctools.ctselect(obs) select["ra"].value("UNDEF") select["dec"].value("UNDEF") select["rad"].value("UNDEF") select["tmin"].real(0.0) select["tmax"].real(0.0) select["emin"].real(ebounds.emin(i).TeV()) select["emax"].real(ebounds.emax(i).TeV()) select.run() # Refit and write out to spectrum binlike = fit(select.obs(), log=False, debug=False, edisp=False) binopt_spectral = binlike.obs().models()[source].spectral() binflux = binopt_spectral.eval(ecenter, gammalib.GTime(0.0)) if binopt_spectral[normpar].value() > 0.0: relerr = binopt_spectral[normpar].error()/binopt_spectral[normpar].value() else: relerr = 0.0 # Store and convert to TeV from MeV spec["energy"]["value"].append(ecenter.TeV()) spec["energy"]["ed_value"].append(ecenter.TeV()-ebounds.emin(i).TeV()) spec["energy"]["eu_value"].append(ebounds.emax(i).TeV()-ecenter.TeV()) spec["energy"]["unit"] = "TeV" spec["flux"]["value"].append(binflux*1.0e6) spec["flux"]["ed_value"].append(relerr*binflux*1.0e6) spec["flux"]["eu_value"].append(relerr*binflux*1.0e6) spec["flux"]["unit"] = "ph/cm2/s/TeV" spec["TS"]["value"].append(binlike.obs().models()[source].ts()) # Return spectrum return spec
def run(self): """ Run the script """ # Switch screen logging on in debug mode if self._logDebug(): self._log.cout(True) # Get parameters self._get_parameters() # Write observation into logger self._log_observations(gammalib.NORMAL, self.obs(), 'Observation') # Get time boundaries tmin = self._tbins.tstart(0) tmax = self._tbins.tstop(self._tbins.size() - 1) # Select events select = ctools.ctselect(self.obs()) select['emin'] = self['emin'].real() select['emax'] = self['emax'].real() select['tmin'] = tmin.convert(ctools.time_reference) select['tmax'] = tmax.convert(ctools.time_reference) select['rad'] = 'UNDEFINED' select['ra'] = 'UNDEFINED' select['dec'] = 'UNDEFINED' select.run() # Extract observations self.obs(select.obs().copy()) # Write observation into logger self._log_header1( gammalib.TERSE, gammalib.number('Selected observation', len(self.obs()))) # Adjust model parameters dependent on user parameters self._adjust_model_pars() # Write header self._log_header1(gammalib.TERSE, 'Generate lightcurve') # Initialise list of result dictionaries results = [] # Get source parameters pars = self._get_free_par_names() # Loop over time bins for i in range(self._tbins.size()): # Get time boundaries tmin = self._tbins.tstart(i) tmax = self._tbins.tstop(i) # Write time bin into header self._log_header2(gammalib.TERSE, 'MJD %f - %f ' % (tmin.mjd(), tmax.mjd())) # Compute time bin center and time width twidth = 0.5 * (tmax - tmin) # in seconds tmean = tmin + twidth # Initialise result dictionary result = { 'mjd': tmean.mjd(), 'e_mjd': twidth / gammalib.sec_in_day, 'ts': 0.0, 'ul_diff': 0.0, 'ul_flux': 0.0, 'ul_eflux': 0.0, 'pars': pars, 'values': {} } # Log information self._log_header3(gammalib.EXPLICIT, 'Selecting events') # Select events select = ctools.ctselect(self.obs()) select['emin'] = self['emin'].real() select['emax'] = self['emax'].real() select['tmin'] = tmin.convert(ctools.time_reference) select['tmax'] = tmax.convert(ctools.time_reference) select['rad'] = 'UNDEFINED' select['ra'] = 'UNDEFINED' select['dec'] = 'UNDEFINED' select.run() # Retrieve observation obs = select.obs() # Deal with stacked and On/Off Observations if self._stacked or self._onoff: # If a stacked analysis is requested bin the events # and compute the stacked response functions and setup # an observation container with a single stacked observation. if self._stacked: new_obs = obsutils.get_stacked_obs(self, obs) # ... otherwise if On/Off analysis is requested generate # the On/Off observations and response elif self._onoff: new_obs = obsutils.get_onoff_obs(self, obs) # Extract models models = new_obs.models() # Fix background models if required if self['fix_bkg'].boolean(): for model in models: if model.classname() != 'GModelSky': for par in model: par.fix() # Put back models new_obs.models(models) # Continue with new oberservation container obs = new_obs # Header self._log_header3(gammalib.EXPLICIT, 'Fitting the data') # Do maximum likelihood model fitting if obs.size() > 0: like = ctools.ctlike(obs) like['edisp'] = self['edisp'].boolean() like.run() # Skip bin if no event was present if like.obs().logL() == 0.0: # Signal skipping of bin self._log_value(gammalib.TERSE, 'Warning', 'No event in this time bin, skip bin.') # Set all results to 0 for par in pars: result['values'][par] = 0.0 result['values']['e_' + par] = 0.0 # Append result results.append(result) # Continue with next time bin continue # Retrieve model fitting results for source of interest source = like.obs().models()[self._srcname] # Extract parameter values for par in pars: result['values'][par] = source[par].value() result['values']['e_' + par] = source[par].error() # Calculate upper limit (-1 if not computed) #ul_diff, ul_flux, ul_eflux = self._compute_ulimit(like.obs()) ul_diff, ul_flux, ul_eflux = self._compute_ulimit(obs) if ul_diff > 0.0: result['ul_diff'] = ul_diff result['ul_flux'] = ul_flux result['ul_eflux'] = ul_eflux # Extract Test Statistic value if self['calc_ts'].boolean(): result['ts'] = source.ts() # Append result to list of dictionaries results.append(result) # Log results for this time bin self._log.header3('Results') pars = self._get_free_par_names() for par in pars: value = source[par].value() error = source[par].error() unit = source[par].unit() self._log_value( gammalib.NORMAL, par, str(value) + ' +/- ' + str(error) + ' ' + unit) if ul_diff > 0.0: self._log_value(gammalib.NORMAL, 'Upper flux limit', str(result['ul_diff']) + ' ph/cm2/s/MeV') self._log_value(gammalib.NORMAL, 'Upper flux limit', str(result['ul_flux']) + ' ph/cm2/s') self._log_value(gammalib.NORMAL, 'Upper flux limit', str(result['ul_eflux']) + ' erg/cm2/s') if self['calc_ts'].boolean(): self._log_value(gammalib.NORMAL, 'Test Statistic', result['ts']) # Otherwise, if observations size is 0, signal bin is skipped and # fill results table with zeros else: self._log_value( gammalib.TERSE, 'Warning', 'No observations available in this time bin, ' 'skip bin.') # Set all results to 0 for par in pars: result['values'][par] = 0.0 result['values']['e_' + par] = 0.0 # Append result results.append(result) # Continue with next time bin continue # Create FITS table from results table = self._create_fits_table(results) # Create FITS file and append FITS table to FITS file self._fits = gammalib.GFits() self._fits.append(table) # Optionally publish light curve if self['publish'].boolean(): self.publish() # Return return
def pipeline(model_name): """ Unbinned analysis pipeline - keep intermediate results in memory. This function implements an analysis pipeline that successively calls ctobssim, ctselect and ctlike without saving the intermediate results as FITS files on disk. All data is only hold in memory. """ # Set script parameters caldb = "prod2" irf = "South_50h" ra = 83.63 dec = 22.01 rad_sim = 10.0 tstart = 0.0 tstop = 1800.0 emin = 0.1 emax = 100.0 rad_select = 3.0 # Write model name print("*** Model: "+model_name+" ************************************") # Initialise timing wall_seconds = 0.0 cpu_seconds = 0.0 # Simulate events sim = ctools.ctobssim() sim["inmodel"] = model_name sim["caldb"] = caldb sim["irf"] = irf sim["ra"] = ra sim["dec"] = dec sim["rad"] = rad_sim sim["tmin"] = tstart sim["tmax"] = tstop sim["emin"] = emin sim["emax"] = emax sim.run() # Select events select = ctools.ctselect(sim.obs()) select["ra"] = ra select["dec"] = dec select["rad"] = rad_select select["tmin"] = tstart select["tmax"] = tstop select["emin"] = emin select["emax"] = emax select.run() # Perform maximum likelihood fitting like = ctools.ctlike(select.obs()) like.run() # Show model fitting results print(like.obs().models()[0]) # Return return
def _test_python(self): """ Test ctselect from Python """ # Allocate empty ctselect tool select = ctools.ctselect() # Check that empty ctselect tool holds an empty observation self._check_obs(select.obs(), nobs=0) # Check that saving does nothing select['outobs'] = 'ctselect_py0.fits' select['logfile'] = 'ctselect_py0.log' select.logFileOpen() select.save() self.test_assert(not os.path.isfile('ctselect_py0.fits'), 'Check that no event list has been created') # Check that clearing does not lead to an exception or segfault select.clear() # Now set ctselect parameters select['inobs'] = self._events select['rad'] = 1.0 select['tmin'] = '2020-01-01T00:01:10' select['tmax'] = '2020-01-01T00:03:40' select['emin'] = 2.0 select['emax'] = 80.0 select['outobs'] = 'ctselect_py1.fits' select['logfile'] = 'ctselect_py1.log' select['chatter'] = 2 # Run ctselect tool select.logFileOpen() # Make sure we get a log file select.run() select.save() # Check result file self._check_result_file('ctselect_py1.fits') # Copy ctselect tool cpy_select = select.copy() # Check observation of ctselect copy self._check_obs(cpy_select.obs()) # Execute copy of ctselect tool again, now with a higher chatter # level than before and without any selection. Since the tools # still holds the same selected observation container from before # the number of events will be identical. cpy_select['rad'] = 'NONE' cpy_select['tmin'] = 'NONE' cpy_select['tmax'] = 'NONE' cpy_select['emin'] = 'NONE' cpy_select['emax'] = 'NONE' cpy_select['outobs'] = 'ctselect_py2.fits' cpy_select['logfile'] = 'ctselect_py2.log' cpy_select['chatter'] = 3 cpy_select['publish'] = True cpy_select.logFileOpen() # Needed to get a new log file cpy_select.execute() # Check result file self._check_result_file('ctselect_py2.fits') # Execute again the copy of ctselect tool again, now manually specifying the # RoI centres. We also set the minimum values # to valid event selections, but since the maximum values are still # 'NONE', no event selections should occur. cpy_select['usepnt'] = False cpy_select['ra'] = 83.63 cpy_select['dec'] = 22.01 cpy_select['tmin'] = '2020-01-01T00:01:10' cpy_select['emin'] = 2.0 cpy_select['usethres'] = 'USER' cpy_select['outobs'] = 'ctselect_py3.fits' cpy_select['logfile'] = 'ctselect_py3.log' cpy_select['chatter'] = 4 cpy_select.logFileOpen() # Needed to get a new log file cpy_select.execute() # Check result file self._check_result_file('ctselect_py3.fits') # Now clear copy of ctselect tool cpy_select.clear() # Check that cleared ctselect tool holds no observations and events self._check_obs(cpy_select.obs(), nobs=0) # Get mixed observation container obs = self._obs_mixed() # Attach response function to first observation which is the # event list. This is necessary to run the ctselect tool with # "DEFAULT" thresholds. obs[0].response('South_0.5h', gammalib.GCaldb('cta', 'prod2')) # Setup ctselect tool from observation container. An energy range # beyond the energies covered in the event file is specified, hence # an empty event list will be saved. select = ctools.ctselect(obs) select['rad'] = 1.0 select['tmin'] = '2020-01-01T00:01:10' select['tmax'] = '2020-01-01T00:03:40' select['emin'] = 120.0 select['emax'] = 130.0 select['expr'] = 'DETX == 0' select['usethres'] = 'DEFAULT' # Has no impact as IRF has no keywords select['outobs'] = 'ctselect_py4.fits' select['logfile'] = 'ctselect_py4.log' select['chatter'] = 3 # Execute tool select.logFileOpen() # Needed to get a new log file select.execute() # Check result file self._check_result_file('ctselect_py4.fits', nevents=0) # Setup ctselect tool for an invalid event file select = ctools.ctselect() select['inobs'] = self._invalid_events select['rad'] = 1.0 select['tmin'] = '2020-01-01T00:01:10' select['tmax'] = '2020-01-01T00:03:40' select['emin'] = 2.0 select['emax'] = 80.0 select['outobs'] = 'ctselect_py5.fits' select['logfile'] = 'ctselect_py5.log' select['chatter'] = 3 # Execute tool select.logFileOpen() # Needed to get a new log file self.test_try('Test invalid event file') try: select.execute() self.test_try_failure('Exception not thrown') except ValueError: self.test_try_success() # Setup ctselect tool from event list with extension name. The "emax" # value should be ignored. select = ctools.ctselect() select['inobs'] = self._events + '[EVENTS]' select['rad'] = 1.0 select['tmin'] = '2020-01-01T00:01:10' select['tmax'] = '2020-01-01T00:03:40' select['emin'] = 2.0 select['emax'] = 0.0 # Signals that "emax" should be ignored select['outobs'] = 'ctselect_py6.fits' select['logfile'] = 'ctselect_py6.log' select['chatter'] = 3 # Execute tool select.logFileOpen() # Needed to get a new log file select.execute() # Check result file self._check_result_file('ctselect_py6.fits') # Now ignore the "emin" value. select = ctools.ctselect() select['inobs'] = self._events + '[EVENTS]' select['rad'] = 1.0 select['tmin'] = '2020-01-01T00:01:10' select['tmax'] = '2020-01-01T00:03:40' select['emin'] = 0.0 # Signals that "emin" should be ignored select['emax'] = 80.0 select['outobs'] = 'ctselect_py7.fits' select['logfile'] = 'ctselect_py7.log' select['chatter'] = 3 # Execute tool select.logFileOpen() # Needed to get a new log file select.execute() # Check result file self._check_result_file('ctselect_py7.fits', nevents=60) # Now set "emin > emax" select['emin'] = 150.0 select['emax'] = 80.0 select['outobs'] = 'ctselect_py8.fits' select['logfile'] = 'ctselect_py8.log' select['chatter'] = 3 # Execute tool select.logFileOpen() # Needed to get a new log file select.execute() # Check result file self._check_result_file('ctselect_py8.fits', nevents=0) # Setup ctselect tool with an RoI that is displaced and of the same # size as the original RoI. This should cause an exception to occur select = ctools.ctselect() select['inobs'] = self._events select['usepnt'] = False select['ra'] = 83.63 select['dec'] = 24.01 select['rad'] = 2.0 select['tmin'] = '2020-01-01T00:01:10' select['tmax'] = '2020-01-01T00:03:40' select['emin'] = 2.0 select['emax'] = 80.0 select['outobs'] = 'ctselect_py9.fits' select['logfile'] = 'ctselect_py9.log' select['chatter'] = 3 # Execute tool select.logFileOpen() # Needed to get a new log file self.test_try('Testing selection of invalid RoI') try: select.execute() self.test_try_failure('Exception not thrown') except ValueError: self.test_try_success() # Now force selection and verify that the execution succeeds select['forcesel'] = True select['outobs'] = 'ctselect_py10.fits' select['logfile'] = 'ctselect_py10.log' # Execute tool select.logFileOpen() # Needed to get a new log file select.execute() # Check result file self._check_result_file('ctselect_py10.fits', nevents=31, rad=2.0) # Finally test a custom defined RoI enclosed in the original one select = ctools.ctselect() select['inobs'] = self._events select['usepnt'] = False select['ra'] = 83.63 select['dec'] = 24.01 select['rad'] = 0.4 select['tmin'] = '2020-01-01T00:01:10' select['tmax'] = '2020-01-01T00:03:40' select['emin'] = 2.0 select['emax'] = 80.0 select['outobs'] = 'ctselect_py11.fits' select['logfile'] = 'ctselect_py11.log' select['chatter'] = 3 # Execute tool select.logFileOpen() # Needed to get a new log file select.execute() # Check result file self._check_result_file('ctselect_py11.fits', nevents=1, dec=24.01, rad=0.4) # Now test phase cut select = ctools.ctselect() select['inobs'] = self._phased_events select['rad'] = 1.0 select['tmin'] = 'INDEF' select['tmax'] = 'INDEF' select['emin'] = 1.0 select['emax'] = 100.0 select['phase'] = '0.1:0.4,0.6:0.8' select['outobs'] = 'ctselect_py12.fits' select['logfile'] = 'ctselect_py12.log' select['chatter'] = 2 # Run ctselect tool select.logFileOpen() # Make sure we get a log file select.execute() # Check result file self._check_result_file('ctselect_py12.fits', nevents=365, dec=22.01) # Now test another phase cut select = ctools.ctselect() select['inobs'] = self._phased_events select['rad'] = 1.0 select['tmin'] = 'INDEF' select['tmax'] = 'INDEF' select['emin'] = 1.0 select['emax'] = 100.0 select['phase'] = '0.8:0.3' select['outobs'] = 'ctselect_py13.fits' select['logfile'] = 'ctselect_py13.log' select['chatter'] = 2 # Run ctselect tool select.logFileOpen() # Make sure we get a log file select.execute() # Check result file self._check_result_file('ctselect_py13.fits', nevents=395, dec=22.01) # Test invalid minimum phase value self.test_try('Test invalid minimum phase value') try: select['phase'] = '-0.1:0.3' select['outobs'] = 'ctselect_py14.fits' select['logfile'] = 'ctselect_py14.log' select.logFileOpen() select.execute() self.test_try_failure('Exception not thrown for "-0.1:0.3"') except ValueError: self.test_try_success() # Test invalid minimum phase value self.test_try('Test invalid minimum phase value') try: select['phase'] = '1.1:0.3' select['outobs'] = 'ctselect_py15.fits' select['logfile'] = 'ctselect_py15.log' select.logFileOpen() select.execute() self.test_try_failure('Exception not thrown for "1.1:0.3"') except ValueError: self.test_try_success() # Test invalid maximum phase value self.test_try('Test invalid maximum phase value') try: select['phase'] = '0.1:-0.3' select['outobs'] = 'ctselect_py16.fits' select['logfile'] = 'ctselect_py16.log' select.logFileOpen() select.execute() self.test_try_failure('Exception not thrown for "0.1:-0.3"') except ValueError: self.test_try_success() # Test invalid maximum phase value self.test_try('Test invalid maximum phase value') try: select['phase'] = '0.1:1.1' select['outobs'] = 'ctselect_py17.fits' select['logfile'] = 'ctselect_py17.log' select.logFileOpen() select.execute() self.test_try_failure('Exception not thrown for "0.1:1.1"') except ValueError: self.test_try_success() # Test invalid phase string self.test_try('Test invalid phase string') try: select['phase'] = '0.1:' select['outobs'] = 'ctselect_py18.fits' select['logfile'] = 'ctselect_py18.log' select.logFileOpen() select.execute() self.test_try_failure('Exception not thrown for "0.1:"') except ValueError: self.test_try_success() # Test invalid phase string self.test_try('Test invalid phase string') try: select['phase'] = ':1.0' select['outobs'] = 'ctselect_py19.fits' select['logfile'] = 'ctselect_py19.log' select.logFileOpen() select.execute() self.test_try_failure('Exception not thrown for ":1.0"') except ValueError: self.test_try_success() # Test invalid phase string self.test_try('Test invalid phase string') try: select['phase'] = '0.1-1.0' select['outobs'] = 'ctselect_py20.fits' select['logfile'] = 'ctselect_py20.log' select.logFileOpen() select.execute() self.test_try_failure('Exception not thrown for "0.1-1.0"') except ValueError: self.test_try_success() # Return return
def _phase_bin(self, phbin): # Write time bin into header self._log_header2(gammalib.TERSE, 'PHASE %f - %f' % (phbin[0], phbin[1])) # Select events select = ctools.ctselect(self.obs().copy()) select['emin'] = self['emin'].real() select['emax'] = self['emax'].real() select['tmin'] = 'UNDEFINED' select['tmax'] = 'UNDEFINED' select['rad'] = 'UNDEFINED' select['ra'] = 'UNDEFINED' select['dec'] = 'UNDEFINED' select['expr'] = 'PHASE>' + str(phbin[0]) + ' && PHASE<' + str( phbin[1]) select.run() # Set phase string phstr = str(phbin[0]) + '-' + str(phbin[1]) # Add phase to observation id for i in range(0, select.obs().size()): oldid = select.obs()[i].id() select.obs()[i].id(oldid + '_' + phstr) obs = select.obs() # If an On/Off analysis is requested generate the On/Off observations if self._onoff: obs = obsutils.get_onoff_obs(self, select.obs(), nthreads=1) # ... otherwise, if stacked analysis is requested then bin the # events and compute the stacked response functions and setup # an observation container with a single stacked observation. elif self._stacked: obs = obsutils.get_stacked_obs(self, select.obs()) # Header self._log_header3(gammalib.EXPLICIT, 'Fitting the data') # The On/Off analysis can produce empty observation containers, # e.g., when on-axis observations are used. To avoid ctlike asking # for a new observation container (or hang, if in interactive mode) # we'll run ctlike only if the size is >0 if obs.size() > 0: # Do maximum likelihood model fitting like = ctools.ctlike(obs) like['edisp'] = self['edisp'].boolean() like['nthreads'] = 1 # Avoids OpenMP conflict like.run() # Renormalize models to phase selection # TODO move the scaling from the temporal to the spectral component for model in like.obs().models(): scaled_norm = model['Normalization'].value() / (phbin[1] - phbin[0]) model['Normalization'].value(scaled_norm) # Store fit model fitmodels = like.obs().models().copy() # ... otherwise we set an empty model container else: self._log_string( gammalib.TERSE, 'PHASE %f - %f: no observations available' ' for fitting' % (phbin[0], phbin[1])) # Set empty models container fitmodels = gammalib.GModels() # Set results result = {'phstr': phstr, 'fitmodels': fitmodels} # Return results return result
def run(self): """ Run the script. """ # Switch screen logging on in debug mode if self._logDebug(): self._log.cout(True) # Get parameters self._get_parameters() # Write observation into logger if self._logTerse(): self._log("\n") self._log.header1("Observation") self._log(str(self._obs)) self._log("\n") # Adjust model parameters dependent on user parameters self._adjust_model_pars() # Write header if self._logTerse(): self._log("\n") self._log.header1("Generate lightcurve") # Initialise list of result dictionaries results = [] # Get source parameters pars = self._get_free_par_names() # Loop over time bins for i in range(self._tbins.size()): # Get time boundaries tmin = self._tbins.tstart(i) tmax = self._tbins.tstop(i) # Write time bin into header if self._logTerse(): self._log.header2("MJD " + str(tmin.mjd()) + "-" + str(tmax.mjd())) # Compute time bin center and time width twidth = 0.5 * (tmax - tmin) # in seconds tmean = tmin + twidth # Initialise result dictionary result = { 'mjd': tmean.mjd(), 'e_mjd': twidth / gammalib.sec_in_day, 'ts': 0.0, 'ulimit': 0.0, 'pars': pars, 'values': {} } # Log information if self._logExplicit(): self._log.header3("Selecting events") # Select events select = ctools.ctselect(self._obs) select["emin"] = self["emin"].real() select["emax"] = self["emax"].real() select["tmin"] = tmin.convert(self._time_reference()) select["tmax"] = tmax.convert(self._time_reference()) select["rad"] = "UNDEFINED" select["ra"] = "UNDEFINED" select["dec"] = "UNDEFINED" select.run() # Retrieve observation obs = select.obs() # If a stacked analysis is requested then bin the events # and compute the stacked response functions and setup # an observation container with a single stacked observation. if self._stacked: obs = self._bin_observation(obs) # Header if self._logExplicit(): self._log.header3("Fitting the data") # Do maximum likelihood model fitting like = ctools.ctlike(obs) like["edisp"] = self["edisp"].boolean() like.run() # Skip bin if no event was present if like.obs().logL() == 0.0: # Signal skipping of bin if self._logTerse(): self._log(gammalib.parformat("Warning")) self._log("No event in this time bin, skip bin.\n") # Set all results to 0 for par in pars: result['values'][par] = 0.0 result['values']["e_" + par] = 0.0 # Append result results.append(result) # Continue with next time bin continue # Retrieve model fitting results for source of interest source = like.obs().models()[self._srcname] # Extract parameter values for par in pars: result['values'][par] = source.spectral()[par].value() result['values']["e_" + par] = source.spectral()[par].error() # Calculate upper limit (-1 if not computed) ulimit_value = self._compute_ulimit(like.obs()) if ulimit_value > 0.0: result['ulimit'] = ulimit_value # Extract Test Statistic value if self["calc_ts"].boolean(): result['ts'] = source.ts() # Append result to list of dictionaries results.append(result) # Log results for this time bin if self._logNormal(): self._log.header3("Results") pars = self._get_free_par_names() for par in pars: value = source.spectral()[par].value() error = source.spectral()[par].error() unit = source.spectral()[par].unit() self._log(gammalib.parformat(par)) self._log(str(value)) self._log(" +/- ") self._log(str(error)) self._log(" ") self._log(unit) self._log("\n") if result['ulimit'] > 0.0: self._log(gammalib.parformat("Upper flux limit")) self._log(str(result['ulimit']) + " ph/cm2/s\n") if self["calc_ts"].boolean(): self._log(gammalib.parformat("Test Statistic")) self._log(str(result['ts']) + "\n") # Create FITS table from results table = self._create_fits_table(results) # Create FITS file and append FITS table to FITS file self._fits = gammalib.GFits() self._fits.append(table) # Return return
def _select_obs(self, emin, emax): """ Select observations for energy interval Parameters ---------- emin : `~gammalib.GEnergy()` Minimum energy emax : `~gammalib.GEnergy()` Maximum energy Returns ------- obs : `~gammalib.GObservations` Observation container """ # Use ctcubemask for binned analysis if self._binned_mode: # Write header self._log_header3(gammalib.EXPLICIT, 'Filtering cube') # Select layers cubemask = ctools.ctcubemask(self.obs()) cubemask['regfile'] = 'NONE' cubemask['ra'] = 'UNDEFINED' cubemask['dec'] = 'UNDEFINED' cubemask['rad'] = 'UNDEFINED' cubemask['emin'] = emin.TeV() cubemask['emax'] = emax.TeV() # If chatter level is verbose and debugging is requested then # switch also on the debug model in ctcubemask if self._logVerbose() and self._logDebug(): cubemask['debug'] = True # Select layers cubemask.run() # Set new binned observation obs = cubemask.obs().copy() # Use ... elif self._onoff_mode: # Write header self._log_header3(gammalib.EXPLICIT, 'Filtering PHA, ARF and RMF') # Initialise observation container obs = gammalib.GObservations() # Loop over all input observations and select energy bins for # all On/Off observations for run in self.obs(): if run.classname() == 'GCTAOnOffObservation': obs.append(self._select_onoff_obs(run, emin, emax)) # Append models obs.models(self.obs().models()) # Use ctselect for unbinned analysis else: # Write header self._log_header3(gammalib.EXPLICIT, 'Selecting events') # Select events select = ctools.ctselect(self.obs()) select['ra'] = 'UNDEFINED' select['dec'] = 'UNDEFINED' select['rad'] = 'UNDEFINED' select['emin'] = emin.TeV() select['emax'] = emax.TeV() select['tmin'] = 'UNDEFINED' select['tmax'] = 'UNDEFINED' # If chatter level is verbose and debugging is requested then # switch also on the debug model in ctselect if self._logVerbose() and self._logDebug(): select['debug'] = True # Run ctselect select.run() # Retrieve observation obs = select.obs().copy() # Return observation container return obs
def run(self): """ Run the script. """ # Switch screen logging on in debug mode if self.logDebug(): self.log.cout(True) # Get parameters self.get_parameters() # Write input parameters into logger if self.logTerse(): self.log_parameters() self.log("\n") # Write observation into logger if self.logTerse(): self.log("\n") self.log.header1("Observation") self.log(str(self.obs)) self.log("\n") # Write header if self.logTerse(): self.log("\n") self.log.header1("Adjust model parameters") # Adjust model parameters dependent on input user parameters for model in self.obs.models(): # Set TS flag for all models to false. # Source of interest will be set to true later model.tscalc(False) # Log model name if self.logExplicit(): self.log.header3(model.name()) # Deal with the source of interest if model.name() == self.m_srcname: if self.m_calc_ts: model.tscalc(True) elif self.m_fix_bkg and not model.classname() == "GModelSky": for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() elif self.m_fix_srcs and model.classname() == "GModelSky": for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() # Write header if self.logTerse(): self.log("\n") self.log.header1("Generate lightcurve") # Initialise FITS Table with extension "LIGHTCURVE" table = gammalib.GFitsBinTable(self.m_tbins.size()) table.extname("LIGHTCURVE") # Add Header for compatibility with gammalib.GMWLSpectrum table.card("INSTRUME", "CTA", "Name of Instrument") table.card("TELESCOP", "CTA", "Name of Telescope") # Create FITS table columns MJD = gammalib.GFitsTableDoubleCol("MJD", self.m_tbins.size()) MJD.unit("days") e_MJD = gammalib.GFitsTableDoubleCol("e_MJD", self.m_tbins.size()) e_MJD.unit("days") # Create a FITS column for every free parameter columns = [] for par in self.obs.models()[self.m_srcname]: if par.is_free(): col = gammalib.GFitsTableDoubleCol(par.name(), self.m_tbins.size()) col.unit(par.unit()) columns.append(col) e_col = gammalib.GFitsTableDoubleCol("e_"+par.name(), self.m_tbins.size()) e_col.unit(par.unit()) columns.append(e_col) # Create TS and upper limit columns TSvalues = gammalib.GFitsTableDoubleCol("TS", self.m_tbins.size()) ulim_values = gammalib.GFitsTableDoubleCol("UpperLimit", self.m_tbins.size()) ulim_values.unit("ph/cm2/s") # Loop over energy bins for i in range(self.m_tbins.size()): # Log information if self.logTerse(): self.log("\n") self.log.header2("Time bin "+str(i)) # Get time boundaries tmin = self.m_tbins.tstart(i) tmax = self.m_tbins.tstop(i) # Compute time bin center and time width tmean = (tmin + tmax) tmean *= 0.5 twidth = (tmax - tmin) twidth *= 0.5 # Store time as MJD MJD[i] = tmean.mjd() e_MJD[i] = twidth.days() # Log information if self.logExplicit(): self.log.header3("Selecting events") # Select events select = ctools.ctselect(self.obs) select["emin"].real(self.m_emin) select["emax"].real(self.m_emax) select["tmin"].real(tmin.convert(select.time_reference())) select["tmax"].real(tmax.convert(select.time_reference())) select["rad"].value("UNDEFINED") select["ra"].value("UNDEFINED") select["dec"].value("UNDEFINED") select.run() # Retrieve observation obs = select.obs() # Binned analysis if self.m_binned: # Header if self.logTerse(): self.log.header3("Binning events") # Bin events bin = ctools.ctbin(select.obs()) bin["usepnt"].boolean(False) bin["ebinalg"].string("LOG") bin["xref"].real(self.m_xref) bin["yref"].real(self.m_yref) bin["binsz"].real(self.m_binsz) bin["nxpix"].integer(self.m_nxpix) bin["nypix"].integer(self.m_nypix) bin["enumbins"].integer(self.m_ebins) bin["emin"].real(self.m_emin) bin["emax"].real(self.m_emax) bin["coordsys"].string(self.m_coordsys) bin["proj"].string(self.m_proj) bin.run() # Header if self.logTerse(): self.log.header3("Creating exposure cube") # Create exposure cube expcube = ctools.ctexpcube(select.obs()) expcube["incube"].filename("NONE") expcube["usepnt"].boolean(False) expcube["ebinalg"].string("LOG") expcube["xref"].real(self.m_xref) expcube["yref"].real(self.m_yref) expcube["binsz"].real(self.m_binsz) expcube["nxpix"].integer(self.m_nxpix) expcube["nypix"].integer(self.m_nypix) expcube["enumbins"].integer(self.m_ebins) expcube["emin"].real(self.m_emin) expcube["emax"].real(self.m_emax) expcube["coordsys"].string(self.m_coordsys) expcube["proj"].string(self.m_proj) expcube.run() # Header if self.logTerse(): self.log.header3("Creating PSF cube") # Create psf cube psfcube = ctools.ctpsfcube(select.obs()) psfcube["incube"].filename("NONE") psfcube["usepnt"].boolean(False) psfcube["ebinalg"].string("LOG") psfcube["xref"].real(self.m_xref) psfcube["yref"].real(self.m_yref) psfcube["binsz"].real(self.m_binsz) psfcube["nxpix"].integer(self.m_nxpix) psfcube["nypix"].integer(self.m_nypix) psfcube["enumbins"].integer(self.m_ebins) psfcube["emin"].real(self.m_emin) psfcube["emax"].real(self.m_emax) psfcube["coordsys"].string(self.m_coordsys) psfcube["proj"].string(self.m_proj) psfcube.run() # Header if self.logTerse(): self.log.header3("Creating background cube") # Create background cube bkgcube = ctools.ctbkgcube(select.obs()) bkgcube["incube"].filename("NONE") bkgcube["usepnt"].boolean(False) bkgcube["ebinalg"].string("LOG") bkgcube["xref"].real(self.m_xref) bkgcube["yref"].real(self.m_yref) bkgcube["binsz"].real(self.m_binsz) bkgcube["nxpix"].integer(self.m_nxpix) bkgcube["nypix"].integer(self.m_nypix) bkgcube["enumbins"].integer(self.m_ebins) bkgcube["emin"].real(self.m_emin) bkgcube["emax"].real(self.m_emax) bkgcube["coordsys"].string(self.m_coordsys) bkgcube["proj"].string(self.m_proj) bkgcube.run() # Set new binned observation obs = bin.obs() # Set precomputed binned response obs[0].response(expcube.expcube(), psfcube.psfcube(), bkgcube.bkgcube()) # Get new models models = bkgcube.models() # Fix background models if required if self.m_fix_bkg: for model in models: if not model.classname() == "GModelSky": for par in model: par.fix() # Set new models to binned observation obs.models(models) # Header if self.logTerse(): self.log.header3("Performing fit") # Likelihood like = ctools.ctlike(obs) like.run() # Skip bin if no event was present if like.obs().logL() == 0.0: # Log information if self.logTerse(): self.log("No event in this time bin. Bin is skipped\n") # Set all values to 0 for col in columns: col[i] = 0.0 TSvalues[i] = 0.0 ulim_values[i] = 0.0 continue # Get results fitted_models = like.obs().models() source = fitted_models[self.m_srcname] # Calculate Upper Limit ulimit_value = -1.0 if self.m_calc_ulimit: # Logging information if self.logTerse(): self.log.header3("Computing upper limit") # Create upper limit object ulimit = ctools.ctulimit(like.obs()) ulimit["srcname"].string(self.m_srcname) ulimit["eref"].real(1.0) # Try to run upper limit and catch exceptions try: ulimit.run() ulimit_value = ulimit.flux_ulimit() except: if self.logTerse(): self.log("Upper limit calculation failed\n") ulimit_value = -1.0 # Get TS value TS = -1.0 if self.m_calc_ts: TS = source.ts() # Set values for storage TSvalues[i] = TS # Set FITS column values for col in columns: if "e_" == col.name()[:2]: col[i] = source.spectral()[col.name()[2:]].error() else: col[i] = source.spectral()[col.name()].value() # Store upper limit value if available if ulimit_value > 0.0: ulim_values[i] = ulimit_value # Log information if self.logExplicit(): self.log.header3("Results of bin "+str(i)+": MJD "+str(tmin.mjd())+"-"+str(tmax.mjd())) for col in columns: if "e_" == col.name()[:2]: continue value = source.spectral()[col.name()].value() error = source.spectral()[col.name()].error() unit = source.spectral()[col.name()].unit() self.log(" > "+col.name()+": "+str(value)+" +- "+str(error)+" "+unit+"\n") if self.m_calc_ts and TSvalues[i] > 0.0: self.log(" > TS = "+str(TS)+" \n") if self.m_calc_ulimit and ulim_values[i] > 0.0: self.log(" > UL = "+str(ulim_values[i])+" [ph/cm2/s]") self.log("\n") # Append filles columns to fits table table.append(MJD) table.append(e_MJD) for col in columns: table.append(col) table.append(TSvalues) table.append(ulim_values) # Create the FITS file now self.fits = gammalib.GFits() self.fits.append(table) # Return return
def run(self): """ Run the script. """ # Switch screen logging on in debug mode if self.logDebug(): self.log.cout(True) # Get parameters self.get_parameters() # Write input parameters into logger if self.logTerse(): self.log_parameters() self.log("\n") # Write observation into logger if self.logTerse(): self.log("\n") self.log.header1("Observation") self.log(str(self.obs)) self.log("\n") # Write header if self.logTerse(): self.log("\n") self.log.header1("Adjust model parameters") # Adjust model parameters dependent on input user parameters for model in self.obs.models(): # Set TS flag for all models to false. # Source of interest will be set to true later model.tscalc(False) # Log model name if self.logExplicit(): self.log.header3(model.name()) # Deal with the source of interest if model.name() == self.m_srcname: for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() if par.is_fixed() and self.logExplicit(): self.log(" Freeing \""+par.name()+"\"\n") model.spectral()[0].free() if self.m_calc_ts: model.tscalc(True) elif self.m_fix_bkg and not model.classname() == "GModelSky": for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() elif self.m_fix_srcs and model.classname() == "GModelSky": for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() # Write header if self.logTerse(): self.log("\n") self.log.header1("Generate spectrum") # Initialise FITS Table with extension "SPECTRUM" table = gammalib.GFitsBinTable(self.m_ebounds.size()) table.extname("SPECTRUM") # Add Header for compatibility with gammalib.GMWLSpectrum table.card("INSTRUME", "CTA", "Name of Instrument") table.card("TELESCOP", "CTA", "Name of Telescope") # Create FITS table columns energy = gammalib.GFitsTableDoubleCol("Energy", self.m_ebounds.size()) energy.unit("TeV") energy_low = gammalib.GFitsTableDoubleCol("ed_Energy", self.m_ebounds.size()) energy_low.unit("TeV") energy_high = gammalib.GFitsTableDoubleCol("eu_Energy", self.m_ebounds.size()) energy_high.unit("TeV") flux = gammalib.GFitsTableDoubleCol("Flux", self.m_ebounds.size()) flux.unit("erg/cm2/s") flux_err = gammalib.GFitsTableDoubleCol("e_Flux", self.m_ebounds.size()) flux_err.unit("erg/cm2/s") TSvalues = gammalib.GFitsTableDoubleCol("TS", self.m_ebounds.size()) ulim_values = gammalib.GFitsTableDoubleCol("UpperLimit", self.m_ebounds.size()) ulim_values.unit("erg/cm2/s") # Loop over energy bins for i in range(self.m_ebounds.size()): # Log information if self.logTerse(): self.log("\n") self.log.header2("Energy bin "+str(i)) # Get energy boundaries emin = self.m_ebounds.emin(i) emax = self.m_ebounds.emax(i) elogmean = self.m_ebounds.elogmean(i) elogmean2 = elogmean.MeV() * elogmean.MeV() # Store energy as TeV energy[i] = elogmean.TeV() # Store energy errors energy_low[i] = (elogmean - emin).TeV() energy_high[i] = (emax - elogmean).TeV() # Log information if self.logExplicit(): self.log.header3("Selecting events") # Select events select = ctools.ctselect(self.obs) select["emin"].real(emin.TeV()) select["emax"].real(emax.TeV()) select["tmin"].value("UNDEFINED") select["tmax"].value("UNDEFINED") select["rad"].value("UNDEFINED") select["ra"].value("UNDEFINED") select["dec"].value("UNDEFINED") select.run() # Retrieve observation obs = select.obs() # Binned analysis if self.m_binned: # Header if self.logTerse(): self.log.header3("Binning events") # Bin events bin = ctools.ctbin(select.obs()) bin["usepnt"].boolean(False) bin["ebinalg"].string("LOG") bin["xref"].real(self.m_xref) bin["yref"].real(self.m_yref) bin["binsz"].real(self.m_binsz) bin["nxpix"].integer(self.m_nxpix) bin["nypix"].integer(self.m_nypix) bin["enumbins"].integer(self.m_ebins) bin["emin"].real(emin.TeV()) bin["emax"].real(emax.TeV()) bin["coordsys"].string(self.m_coordsys) bin["proj"].string(self.m_proj) bin.run() # Header if self.logTerse(): self.log.header3("Creating exposure cube") # Create exposure cube expcube = ctools.ctexpcube(select.obs()) expcube["incube"].filename("NONE") expcube["usepnt"].boolean(False) expcube["ebinalg"].string("LOG") expcube["xref"].real(self.m_xref) expcube["yref"].real(self.m_yref) expcube["binsz"].real(self.m_binsz) expcube["nxpix"].integer(self.m_nxpix) expcube["nypix"].integer(self.m_nypix) expcube["enumbins"].integer(self.m_ebins) expcube["emin"].real(emin.TeV()) expcube["emax"].real(emax.TeV()) expcube["coordsys"].string(self.m_coordsys) expcube["proj"].string(self.m_proj) expcube.run() # Header if self.logTerse(): self.log.header3("Creating PSF cube") # Create psf cube psfcube = ctools.ctpsfcube(select.obs()) psfcube["incube"].filename("NONE") psfcube["usepnt"].boolean(False) psfcube["ebinalg"].string("LOG") psfcube["xref"].real(self.m_xref) psfcube["yref"].real(self.m_yref) psfcube["binsz"].real(self.m_binsz) psfcube["nxpix"].integer(self.m_nxpix) psfcube["nypix"].integer(self.m_nypix) psfcube["enumbins"].integer(self.m_ebins) psfcube["emin"].real(emin.TeV()) psfcube["emax"].real(emax.TeV()) psfcube["coordsys"].string(self.m_coordsys) psfcube["proj"].string(self.m_proj) psfcube.run() # Header if self.logTerse(): self.log.header3("Creating background cube") # Create background cube bkgcube = ctools.ctbkgcube(select.obs()) bkgcube["incube"].filename("NONE") bkgcube["usepnt"].boolean(False) bkgcube["ebinalg"].string("LOG") bkgcube["xref"].real(self.m_xref) bkgcube["yref"].real(self.m_yref) bkgcube["binsz"].real(self.m_binsz) bkgcube["nxpix"].integer(self.m_nxpix) bkgcube["nypix"].integer(self.m_nypix) bkgcube["enumbins"].integer(self.m_ebins) bkgcube["emin"].real(emin.TeV()) bkgcube["emax"].real(emax.TeV()) bkgcube["coordsys"].string(self.m_coordsys) bkgcube["proj"].string(self.m_proj) bkgcube.run() # Set new binned observation obs = bin.obs() # Set precomputed binned response obs[0].response(expcube.expcube(), psfcube.psfcube(), bkgcube.bkgcube()) # Get new models models = bkgcube.models() # Fix background models if required if self.m_fix_bkg: for model in models: if not model.classname() == "GModelSky": for par in model: par.fix() # Set new models to binned observation obs.models(models) # Header if self.logTerse(): self.log.header3("Performing fit") # Likelihood like = ctools.ctlike(obs) like.run() # Skip bin if no event was present if like.obs().logL() == 0.0: # Log information if self.logTerse(): self.log("No event in this bin. Bin is skipped\n") # Set all values to 0 flux[i] = 0.0 flux_err[i] = 0.0 TSvalues[i] = 0.0 ulim_values[i] = 0.0 continue # Get results fitted_models = like.obs().models() source = fitted_models[self.m_srcname] # Calculate Upper Limit ulimit_value = -1.0 if self.m_calc_ulimit: # Logging information if self.logTerse(): self.log.header3("Computing upper limit") # Create upper limit object ulimit = ctools.ctulimit(like.obs()) ulimit["srcname"].string(self.m_srcname) ulimit["eref"].real(elogmean.TeV()) # Try to run upper limit and catch exceptions try: ulimit.run() ulimit_value = ulimit.diff_ulimit() except: if self.logTerse(): self.log("Upper limit calculation failed\n") ulimit_value = -1.0 # Get TS value TS = -1.0 if self.m_calc_ts: TS = source.ts() # Get differential flux fitted_flux = source.spectral().eval(elogmean,gammalib.GTime()) # Compute flux error parvalue = source.spectral()[0].value() rel_error = source.spectral()[0].error()/parvalue e_flux = fitted_flux*rel_error # Set values for storage TSvalues[i] = TS # Convert fluxes to nuFnu flux[i] = fitted_flux * elogmean2 * gammalib.MeV2erg flux_err[i] = e_flux * elogmean2 * gammalib.MeV2erg if ulimit_value > 0.0: ulim_values[i] = ulimit_value * elogmean2 * gammalib.MeV2erg # Log information if self.logExplicit(): self.log("Bin "+str(i)+" ["+str(emin.TeV())+"-"+str(emax.TeV())+"] TeV: ") self.log("Flux = "+str(flux[i])) self.log(" +- "+str(flux_err[i])+" [erg/cm2/s]") if self.m_calc_ts and TSvalues[i] > 0.0: self.log(", TS = "+str(TS)) if self.m_calc_ulimit and ulim_values[i] > 0.0: self.log(", UL = "+str(ulim_values[i])+" [erg/cm2/s]") self.log("\n") # Append filles columns to fits table table.append(energy) table.append(energy_low) table.append(energy_high) table.append(flux) table.append(flux_err) table.append(TSvalues) table.append(ulim_values) # Create the FITS file now self.fits = gammalib.GFits() self.fits.append(table) # Return return
def run(self): """ Run the script """ # Switch screen logging on in debug mode if self._logDebug(): self._log.cout(True) # Get parameters self._get_parameters() # Write observation into logger self._log_observations(gammalib.NORMAL, self.obs(), 'Observation') # Store and clear observations to split them into phase bins orig_obs = self.obs().copy() # Dictionary to save phase fitted models self._fitmodels = {} # Write header self._log_header1(gammalib.TERSE, 'Generate phase curve') # Loop over all phases for phbin in self._phbins: # Write time bin into header self._log_header2(gammalib.TERSE, 'PHASE %f - %f' % (phbin[0], phbin[1])) # Select events select = ctools.ctselect(orig_obs) select['emin'] = self['emin'].real() select['emax'] = self['emax'].real() select['tmin'] = 'UNDEFINED' select['tmax'] = 'UNDEFINED' select['rad'] = 'UNDEFINED' select['ra'] = 'UNDEFINED' select['dec'] = 'UNDEFINED' select['expr'] = 'PHASE>'+str(phbin[0])+' && PHASE<'+str(phbin[1]) select.run() # Set phase string phstr = str(phbin[0]) + '-' + str(phbin[1]) # Add phase to observation id for i in range(0,select.obs().size()): oldid = select.obs()[i].id() select.obs()[i].id(oldid+'_'+phstr) obs = select.obs() # If an On/Off analysis is requested generate the On/Off observations if self._onoff: obs = obsutils.get_onoff_obs(self, select.obs()) # ... otherwise, if stacked analysis is requested then bin the # events and compute the stacked response functions and setup # an observation container with a single stacked observation. elif self._stacked: obs = obsutils.get_stacked_obs(self, select.obs()) # Header self._log_header3(gammalib.EXPLICIT, 'Fitting the data') # The On/Off analysis can produce empty observation containers, # e.g., when on-axis observations are used. To avoid ctlike asking # for a new observation container (or hang, if in interactive mode) # we'll run ctlike only if the size is >0 if obs.size() > 0: # Do maximum likelihood model fitting like = ctools.ctlike(obs) like['edisp'] = self['edisp'].boolean() like.run() # Renormalize models to phase selection # TODO move the scaling from the temporal to the spectral component for model in like.obs().models(): scaled_norm = model['Normalization'].value()/(phbin[1]-phbin[0]) model['Normalization'].value(scaled_norm) # Store fit model self._fitmodels[phstr] = like.obs().models().copy() # ... otherwise we set an empty model container else: self._log_string(gammalib.TERSE, 'PHASE %f - %f: no observations available' ' for fitting' %(phbin[0], phbin[1])) # Set empty models container self._fitmodels[phstr] = gammalib.GModels() # Create FITS file self._create_fits() # Optionally publish phase curve if self['publish'].boolean(): self.publish() # Return return
def prepare(obsname, bkgname, rad=2.0, emin=0.3, emax=50.0, ebins=20): """ Prepare events for analysis Parameters ---------- obsname : str Observation definition XML file bkgname : str Background model definition XML file rad : float, optional Selection radius (degrees) emin : float, optional Minimum energy for analysis (TeV) emax : float, optional Maximum energy for analysis (TeV) ebins : int, optional Number of energy bins """ # Set filenames cntcube = 'rx_stacked%2.2d_cntcube.fits' % ebins expcube = 'rx_stacked%2.2d_expcube.fits' % ebins psfcube = 'rx_stacked%2.2d_psfcube.fits' % ebins edispcube = 'rx_stacked%2.2d_edispcube.fits' % ebins bkgcube = 'rx_stacked%2.2d_bkgcube.fits' % ebins obsname_binned = add_attribute(obsname, '_binned%2.2d' % ebins) bkgname_stacked = add_attribute(bkgname, '_stacked') obsname_stacked = add_attribute(obsname, '_stacked%2.2d' % ebins) obsname_stacked_edisp = add_attribute(obsname_stacked, '_edisp') # Generate background lookup generate_background_lookup() # Continue only if selected events do not exist if not os.path.isfile(obsname): # Setup task parameters select = ctools.ctselect() select['inobs'] = '$HESSDATA/obs/obs_rx.xml' select['outobs'] = obsname select['ra'] = 'UNDEF' select['dec'] = 'UNDEF' select['rad'] = rad select['tmin'] = 'UNDEF' select['tmax'] = 'UNDEF' select['emin'] = emin select['emax'] = emax select['usethres'] = 'DEFAULT' select['logfile'] = 'rx_hess_select_events.log' select.logFileOpen() # Select events select.execute() # Continue only if background model does not exist if not os.path.isfile(bkgname): # Setup task parameters bkg = cscripts.csbkgmodel() bkg['inobs'] = '$HESSDATA/obs/obs_rx.xml' bkg['outmodel'] = bkgname bkg['instrument'] = 'HESS' bkg['spatial'] = 'LOOKUP' bkg['slufile'] = 'off_lookup.fits' bkg['gradient'] = True bkg['spectral'] = 'NODES' bkg['ebinalg'] = 'LOG' bkg['emin'] = emin bkg['emax'] = 30.0 bkg['enumbins'] = 8 bkg['runwise'] = True bkg['rad'] = rad bkg['logfile'] = 'rx_hess_create_background.log' bkg.logFileOpen() # Generate background model bkg.execute() # Continue only if counts cube does not exist if not os.path.isfile(cntcube): # Setup task parameters ctbin = ctools.ctbin() ctbin['inobs'] = obsname ctbin['outobs'] = cntcube ctbin['ebinalg'] = 'LOG' ctbin['emin'] = emin ctbin['emax'] = emax ctbin['enumbins'] = ebins ctbin['coordsys'] = 'CEL' ctbin['proj'] = 'TAN' ctbin['xref'] = 258.1125 ctbin['yref'] = -39.6867 ctbin['nxpix'] = 300 ctbin['nypix'] = 300 ctbin['binsz'] = 0.02 ctbin['logfile'] = 'rx_hess_create_cntcube.log' ctbin.logFileOpen() # Generate counts cube ctbin.execute() # Continue only if counts cubes for binned analysis do not exist if not os.path.isfile(obsname_binned): # Setup task parameters ctbin = ctools.ctbin() ctbin['inobs'] = obsname ctbin['outobs'] = obsname_binned ctbin['stack'] = False ctbin['usepnt'] = True ctbin['ebinalg'] = 'LOG' ctbin['emin'] = emin ctbin['emax'] = emax ctbin['enumbins'] = ebins ctbin['coordsys'] = 'CEL' ctbin['proj'] = 'TAN' ctbin['nxpix'] = 200 ctbin['nypix'] = 200 ctbin['binsz'] = 0.02 ctbin['logfile'] = 'rx_hess_create_cntcube_binned.log' ctbin.logFileOpen() # Generate counts cubes ctbin.execute() # Continue only if exposure cube does not exist if not os.path.isfile(expcube): # Setup task parameters ctexpcube = ctools.ctexpcube() ctexpcube['inobs'] = obsname ctexpcube['incube'] = 'NONE' ctexpcube['ebinalg'] = 'LOG' ctexpcube['emin'] = 0.1 # Full energy range ctexpcube['emax'] = 100.0 # Full energy range ctexpcube['enumbins'] = 300 # Factor ~3 oversampling of IRF ctexpcube['coordsys'] = 'CEL' ctexpcube['proj'] = 'TAN' ctexpcube['xref'] = 258.1125 ctexpcube['yref'] = -39.6867 ctexpcube['nxpix'] = 300 ctexpcube['nypix'] = 300 ctexpcube['binsz'] = 0.02 ctexpcube['outcube'] = expcube ctexpcube['logfile'] = 'rx_hess_create_expcube.log' ctexpcube.logFileOpen() # Generate exposure cube ctexpcube.execute() # Continue only if PSF cube does not exist if not os.path.isfile(psfcube): # Setup task parameters ctpsfcube = ctools.ctpsfcube() ctpsfcube['inobs'] = obsname ctpsfcube['incube'] = 'NONE' ctpsfcube['ebinalg'] = 'LOG' ctpsfcube['emin'] = 0.1 # Full energy range ctpsfcube['emax'] = 100.0 # Full energy range ctpsfcube['enumbins'] = 300 # Factor ~3 oversampling of IRF ctpsfcube['coordsys'] = 'CEL' ctpsfcube['proj'] = 'TAN' ctpsfcube['xref'] = 258.1125 ctpsfcube['yref'] = -39.6867 ctpsfcube['nxpix'] = 30 ctpsfcube['nypix'] = 30 ctpsfcube['binsz'] = 0.2 ctpsfcube['amax'] = 0.7 # Full H.E.S.S. PSF range ctpsfcube['anumbins'] = 300 # Factor ~2 oversampling of IRF ctpsfcube['outcube'] = psfcube ctpsfcube['logfile'] = 'rx_hess_create_psfcube.log' ctpsfcube.logFileOpen() # Generate PSF cube ctpsfcube.execute() # Continue only if energy dispersion cube does not exist if not os.path.isfile(edispcube): # Setup task parameters ctedispcube = ctools.ctedispcube() ctedispcube['inobs'] = obsname ctedispcube['incube'] = 'NONE' ctedispcube['ebinalg'] = 'LOG' ctedispcube['emin'] = 0.1 # Full energy range ctedispcube['emax'] = 100.0 # Full energy range ctedispcube['enumbins'] = 300 # Factor ~3 oversampling of IRF ctedispcube['coordsys'] = 'CEL' ctedispcube['proj'] = 'TAN' ctedispcube['xref'] = 258.1125 ctedispcube['yref'] = -39.6867 ctedispcube['nxpix'] = 30 ctedispcube['nypix'] = 30 ctedispcube['binsz'] = 0.2 ctedispcube['migramax'] = 5.0 ctedispcube['migrabins'] = 300 ctedispcube['outcube'] = edispcube ctedispcube['logfile'] = 'rx_hess_create_edispcube.log' ctedispcube.logFileOpen() # Generate energy dispersion cube ctedispcube.execute() # Continue only if background cube does not exist if not os.path.isfile(bkgcube): # Setup task parameters ctbkgcube = ctools.ctbkgcube() ctbkgcube['inobs'] = obsname ctbkgcube['incube'] = cntcube ctbkgcube['inmodel'] = bkgname ctbkgcube['outcube'] = bkgcube ctbkgcube['outmodel'] = bkgname_stacked ctbkgcube['logfile'] = 'rx_hess_create_bkgcube.log' ctbkgcube.logFileOpen() # Generate background cube ctbkgcube.execute() # Continue only if stacked observation definition XML file does not # exist if not os.path.isfile(obsname_stacked): # Build stacked observation run = gammalib.GCTAObservation(cntcube, expcube, psfcube, bkgcube) run.name('RX J1713.7-3946') run.instrument('HESS') # Append to observation container obs = gammalib.GObservations() obs.append(run) # Save observation container obs.save(obsname_stacked) # Continue only if stacked observation definition XML file with energy # energy dispersion enabled does not exist if not os.path.isfile(obsname_stacked_edisp): # Build stacked observation run = gammalib.GCTAObservation(cntcube, expcube, psfcube, edispcube, bkgcube) run.name('RX J1713.7-3946') run.instrument('HESS') # Append to observation container obs = gammalib.GObservations() obs.append(run) # Save observation container obs.save(obsname_stacked_edisp) # Continue only if stacked model definition XML file does exist if os.path.isfile(bkgname_stacked): # Load model definition XML files joint = gammalib.GModels(bkgname) stacked = gammalib.GModels(bkgname_stacked) # Get spectral component of joint file and remplace it as spectral # component of stacked file spectrum = joint[0].spectral() for i in range(spectrum.nodes()): spectrum.intensity(i, 1.0) spectrum.autoscale() stacked[0].spectral(spectrum) # Save stacked model stacked.save(bkgname_stacked) # Return return
def run(self): """ Run the script. """ # Switch screen logging on in debug mode if self.logDebug(): self.log.cout(True) # Get parameters self.get_parameters() # Write input parameters into logger if self.logTerse(): self.log_parameters() self.log("\n") # Write spectral binning into header if self.logTerse(): self.log("\n") self.log.header1("Spectral binning") if self.m_binned_mode: cube_ebounds = self.obs[0].events().ebounds() self.log.parformat("Counts cube energy range") self.log(str(cube_ebounds.emin())) self.log(" - ") self.log(str(cube_ebounds.emax())) self.log("\n") for i in range(self.m_ebounds.size()): self.log.parformat("Bin "+str(i+1)) self.log(str(self.m_ebounds.emin(i))) self.log(" - ") self.log(str(self.m_ebounds.emax(i))) self.log("\n") # Write observation into logger if self.logTerse(): self.log("\n") self.log.header1("Observation") self.log(str(self.obs)) self.log("\n") # Write header if self.logTerse(): self.log("\n") self.log.header1("Adjust model parameters") # Adjust model parameters dependent on input user parameters for model in self.obs.models(): # Set TS flag for all models to false. # Source of interest will be set to true later model.tscalc(False) # Log model name if self.logExplicit(): self.log.header3(model.name()) # Deal with the source of interest if model.name() == self.m_srcname: for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() normpar = model.spectral()[0] if normpar.is_fixed() and self.logExplicit(): self.log(" Freeing \""+normpar.name()+"\"\n") normpar.free() if self.m_calc_ts: model.tscalc(True) elif self.m_fix_bkg and not model.classname() == "GModelSky": for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() elif self.m_fix_srcs and model.classname() == "GModelSky": for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() # Write header if self.logTerse(): self.log("\n") self.log.header1("Generate spectrum") self.log(str(self.m_ebounds)) # Initialise FITS Table with extension "SPECTRUM" table = gammalib.GFitsBinTable(self.m_ebounds.size()) table.extname("SPECTRUM") # Add Header for compatibility with gammalib.GMWLSpectrum table.card("INSTRUME", "CTA", "Name of Instrument") table.card("TELESCOP", "CTA", "Name of Telescope") # Create FITS table columns energy = gammalib.GFitsTableDoubleCol("Energy", self.m_ebounds.size()) energy_low = gammalib.GFitsTableDoubleCol("ed_Energy", self.m_ebounds.size()) energy_high = gammalib.GFitsTableDoubleCol("eu_Energy", self.m_ebounds.size()) flux = gammalib.GFitsTableDoubleCol("Flux", self.m_ebounds.size()) flux_err = gammalib.GFitsTableDoubleCol("e_Flux", self.m_ebounds.size()) TSvalues = gammalib.GFitsTableDoubleCol("TS", self.m_ebounds.size()) ulim_values = gammalib.GFitsTableDoubleCol("UpperLimit", self.m_ebounds.size()) Npred_values = gammalib.GFitsTableDoubleCol("Npred", self.m_ebounds.size()) energy.unit("TeV") energy_low.unit("TeV") energy_high.unit("TeV") flux.unit("erg/cm2/s") flux_err.unit("erg/cm2/s") ulim_values.unit("erg/cm2/s") # Loop over energy bins for i in range(self.m_ebounds.size()): # Log information if self.logExplicit(): self.log("\n") self.log.header2("Energy bin "+str(i+1)) # Get energy boundaries emin = self.m_ebounds.emin(i) emax = self.m_ebounds.emax(i) elogmean = self.m_ebounds.elogmean(i) elogmean2 = elogmean.MeV() * elogmean.MeV() # Store energy as TeV energy[i] = elogmean.TeV() # Store energy errors energy_low[i] = (elogmean - emin).TeV() energy_high[i] = (emax - elogmean).TeV() # use ctselect for unbinned analysis if not self.m_binned_mode: # Log information if self.logExplicit(): self.log.header3("Selecting events") # Select events select = ctools.ctselect(self.obs) select["emin"] = emin.TeV() select["emax"] = emax.TeV() select["tmin"] = "UNDEFINED" select["tmax"] = "UNDEFINED" select["rad"] = "UNDEFINED" select["ra"] = "UNDEFINED" select["dec"] = "UNDEFINED" select.run() # Retrieve observation obs = select.obs() # use ctcubemask for binned analysis else: # Header if self.logExplicit(): self.log.header3("Filtering cube") # Select layers cubemask = ctools.ctcubemask(self.obs) cubemask["regfile"] = "NONE" cubemask["ra"] = "UNDEFINED" cubemask["dec"] = "UNDEFINED" cubemask["rad"] = "UNDEFINED" cubemask["emin"] = emin.TeV() cubemask["emax"] = emax.TeV() cubemask.run() # Set new binned observation obs = cubemask.obs() # Header if self.logExplicit(): self.log.header3("Performing fit") # Likelihood like = ctools.ctlike(obs) like["edisp"] = self.m_edisp like.run() # Skip bin if no event was present if like.obs().logL() == 0.0: # Log information if self.logExplicit(): self.log("No event in this bin. ") self.log("Likelihood is zero. ") self.log("Bin is skipped.") # Set all values to 0 flux[i] = 0.0 flux_err[i] = 0.0 TSvalues[i] = 0.0 ulim_values[i] = 0.0 Npred_values[i] = 0.0 continue # Get results fitted_models = like.obs().models() source = fitted_models[self.m_srcname] # Calculate Upper Limit ulimit_value = -1.0 if self.m_calc_ulimit: # Logging information if self.logExplicit(): self.log.header3("Computing upper limit") # Create upper limit object ulimit = ctools.ctulimit(like.obs()) ulimit["srcname"] = self.m_srcname ulimit["eref"] = elogmean.TeV() # Try to run upper limit and catch exceptions try: ulimit.run() ulimit_value = ulimit.diff_ulimit() except: if self.logExplicit(): self.log("Upper limit calculation failed.") ulimit_value = -1.0 # Get TS value TS = -1.0 if self.m_calc_ts: TS = source.ts() # Compute Npred value (only works for unbinned analysis) Npred = 0.0 if not self.m_binned_mode: for observation in like.obs(): Npred += observation.npred(source) # Get differential flux fitted_flux = source.spectral().eval(elogmean,gammalib.GTime()) # Compute flux error parvalue = source.spectral()[0].value() rel_error = source.spectral()[0].error() / parvalue e_flux = fitted_flux * rel_error # Set values for storage TSvalues[i] = TS # Set npred values Npred_values[i] = Npred # Convert fluxes to nuFnu flux[i] = fitted_flux * elogmean2 * gammalib.MeV2erg flux_err[i] = e_flux * elogmean2 * gammalib.MeV2erg if ulimit_value > 0.0: ulim_values[i] = ulimit_value * elogmean2 * gammalib.MeV2erg # Log information if self.logTerse(): self.log("\n") self.log.parformat("Bin "+str(i+1)) self.log(str(flux[i])) self.log(" +/- ") self.log(str(flux_err[i])) if self.m_calc_ulimit and ulim_values[i] > 0.0: self.log(" [< "+str(ulim_values[i])+"]") self.log(" erg/cm2/s") if self.m_calc_ts and TSvalues[i] > 0.0: self.log(" (TS = "+str(TS)+")") # Append filled columns to fits table table.append(energy) table.append(energy_low) table.append(energy_high) table.append(flux) table.append(flux_err) table.append(TSvalues) table.append(ulim_values) table.append(Npred_values) # Create the FITS file now self.fits = gammalib.GFits() self.fits.append(table) # Return return
def pipeline(model_name): """ Unbinned in-memory analysis pipeline This function implements an analysis pipeline that successively calls ctobssim, ctselect and ctlike without saving the intermediate results as FITS files on disk. All data is only hold in memory. """ # Set script parameters caldb = 'prod2' irf = 'South_0.5h' ra = 83.63 dec = 22.01 rad_sim = 5.0 tstart = 0.0 tstop = 180.0 emin = 0.1 emax = 100.0 rad_select = 3.0 # Write model name print('*** Model: ' + model_name + ' ************************************') # Initialise timing wall_seconds = 0.0 cpu_seconds = 0.0 # Simulate events sim = ctools.ctobssim() sim['inmodel'] = model_name sim['caldb'] = caldb sim['irf'] = irf sim['ra'] = ra sim['dec'] = dec sim['rad'] = rad_sim sim['tmin'] = tstart sim['tmax'] = tstop sim['emin'] = emin sim['emax'] = emax sim.run() # Select events select = ctools.ctselect(sim.obs()) select['ra'] = ra select['dec'] = dec select['rad'] = rad_select select['tmin'] = tstart select['tmax'] = tstop select['emin'] = emin select['emax'] = emax select.run() # Perform maximum likelihood fitting like = ctools.ctlike(select.obs()) like.run() # Show model fitting results print(like.obs().models()[0]) # Return return
def run(self): """ Run the script """ # Switch screen logging on in debug mode if self._logDebug(): self._log.cout(True) # Get parameters self._get_parameters() # Write observation into logger self._log_observations(gammalib.NORMAL, self.obs(), 'Observation') # Get time boundaries tmin = self._tbins.tstart(0) tmax = self._tbins.tstop(self._tbins.size()-1) # Select events select = ctools.ctselect(self.obs()) select['emin'] = self['emin'].real() select['emax'] = self['emax'].real() select['tmin'] = tmin.convert(ctools.time_reference) select['tmax'] = tmax.convert(ctools.time_reference) select['rad'] = 'UNDEFINED' select['ra'] = 'UNDEFINED' select['dec'] = 'UNDEFINED' select.run() # Extract observations self.obs(select.obs().copy()) # Write observation into logger self._log_header1(gammalib.TERSE, gammalib.number('Selected observation', len(self.obs()))) # Adjust model parameters dependent on user parameters self._adjust_model_pars() # Write header self._log_header1(gammalib.TERSE, 'Generate lightcurve') # Initialise list of result dictionaries results = [] # Get source parameters pars = self._get_free_par_names() # Loop over time bins for i in range(self._tbins.size()): # Get time boundaries tmin = self._tbins.tstart(i) tmax = self._tbins.tstop(i) # Write time bin into header self._log_header2(gammalib.TERSE, 'MJD %f - %f ' % (tmin.mjd(), tmax.mjd())) # Compute time bin center and time width twidth = 0.5 * (tmax - tmin) # in seconds tmean = tmin + twidth # Initialise result dictionary result = {'mjd': tmean.mjd(), 'e_mjd': twidth / gammalib.sec_in_day, 'ts': 0.0, 'ul_diff': 0.0, 'ul_flux': 0.0, 'ul_eflux': 0.0, 'pars': pars, 'values': {}} # Log information self._log_header3(gammalib.EXPLICIT, 'Selecting events') # Select events select = ctools.ctselect(self.obs()) select['emin'] = self['emin'].real() select['emax'] = self['emax'].real() select['tmin'] = tmin.convert(ctools.time_reference) select['tmax'] = tmax.convert(ctools.time_reference) select['rad'] = 'UNDEFINED' select['ra'] = 'UNDEFINED' select['dec'] = 'UNDEFINED' select.run() # Retrieve observation obs = select.obs() # Deal with stacked and On/Off Observations if self._stacked or self._onoff: # If a stacked analysis is requested bin the events # and compute the stacked response functions and setup # an observation container with a single stacked observation. if self._stacked: new_obs = obsutils.get_stacked_obs(self, obs) # ... otherwise if On/Off analysis is requested generate # the On/Off observations and response elif self._onoff: new_obs = obsutils.get_onoff_obs(self, obs) # Extract models models = new_obs.models() # Fix background models if required if self['fix_bkg'].boolean(): for model in models: if model.classname() != 'GModelSky': for par in model: par.fix() # Put back models new_obs.models(models) # Continue with new oberservation container obs = new_obs # Header self._log_header3(gammalib.EXPLICIT, 'Fitting the data') # Do maximum likelihood model fitting if obs.size() > 0: like = ctools.ctlike(obs) like['edisp'] = self['edisp'].boolean() like.run() # Skip bin if no event was present if like.obs().logL() == 0.0: # Signal skipping of bin self._log_value(gammalib.TERSE, 'Warning', 'No event in this time bin, skip bin.') # Set all results to 0 for par in pars: result['values'][par] = 0.0 result['values']['e_'+par] = 0.0 # Append result results.append(result) # Continue with next time bin continue # Retrieve model fitting results for source of interest source = like.obs().models()[self._srcname] # Extract parameter values for par in pars: result['values'][par] = source[par].value() result['values']['e_'+par] = source[par].error() # Calculate upper limit (-1 if not computed) #ul_diff, ul_flux, ul_eflux = self._compute_ulimit(like.obs()) ul_diff, ul_flux, ul_eflux = self._compute_ulimit(obs) if ul_diff > 0.0: result['ul_diff'] = ul_diff result['ul_flux'] = ul_flux result['ul_eflux'] = ul_eflux # Extract Test Statistic value if self['calc_ts'].boolean(): result['ts'] = source.ts() # Append result to list of dictionaries results.append(result) # Log results for this time bin self._log.header3('Results') pars = self._get_free_par_names() for par in pars: value = source[par].value() error = source[par].error() unit = source[par].unit() self._log_value(gammalib.NORMAL, par, str(value)+' +/- '+str(error)+' '+unit) if ul_diff > 0.0: self._log_value(gammalib.NORMAL, 'Upper flux limit', str(result['ul_diff'])+' ph/cm2/s/MeV') self._log_value(gammalib.NORMAL, 'Upper flux limit', str(result['ul_flux'])+' ph/cm2/s') self._log_value(gammalib.NORMAL, 'Upper flux limit', str(result['ul_eflux'])+' erg/cm2/s') if self['calc_ts'].boolean(): self._log_value(gammalib.NORMAL, 'Test Statistic', result['ts']) # Otherwise, if observations size is 0, signal bin is skipped and # fill results table with zeros else: self._log_value(gammalib.TERSE, 'Warning', 'No observations available in this time bin, ' 'skip bin.') # Set all results to 0 for par in pars: result['values'][par] = 0.0 result['values']['e_' + par] = 0.0 # Append result results.append(result) # Continue with next time bin continue # Create FITS table from results table = self._create_fits_table(results) # Create FITS file and append FITS table to FITS file self._fits = gammalib.GFits() self._fits.append(table) # Optionally publish light curve if self['publish'].boolean(): self.publish() # Return return
def _select_obs(self, emin, emax): """ Select observations for energy interval Parameters ---------- emin : `~gammalib.GEnergy()` Minimum energy emax : `~gammalib.GEnergy()` Maximum energy Returns ------- obs : `~gammalib.GObservations` Observation container """ # Use ctcubemask for binned analysis if self._binned_mode: # Write header self._log_header3(gammalib.EXPLICIT, 'Filtering cube') # Select layers cubemask = ctools.ctcubemask(self.obs()) cubemask['regfile'] = 'NONE' cubemask['ra'] = 'UNDEFINED' cubemask['dec'] = 'UNDEFINED' cubemask['rad'] = 'UNDEFINED' cubemask['emin'] = emin.TeV() cubemask['emax'] = emax.TeV() cubemask.run() # Set new binned observation obs = cubemask.obs().copy() # Use ... elif self._onoff_mode: # Write header self._log_header3(gammalib.EXPLICIT, 'Filtering PHA, ARF and RMF') # Initialise observation container obs = gammalib.GObservations() # Loop over all input observations and select energy bins for # all On/Off observations for run in self.obs(): if run.classname() == 'GCTAOnOffObservation': obs.append(self._select_onoff_obs(run, emin, emax)) # Append models obs.models(self.obs().models()) # Use ctselect for unbinned analysis else: # Write header self._log_header3(gammalib.EXPLICIT, 'Selecting events') # Select events select = ctools.ctselect(self.obs()) select['ra'] = 'UNDEFINED' select['dec'] = 'UNDEFINED' select['rad'] = 'UNDEFINED' select['emin'] = emin.TeV() select['emax'] = emax.TeV() select['tmin'] = 'UNDEFINED' select['tmax'] = 'UNDEFINED' select.run() # Retrieve observation obs = select.obs().copy() # Return observation container return obs
def run_pipeline(self, debug=False, seed=0): """ Test unbinned pipeline with FITS file saving """ # Set script parameters events_name = 'events.fits' cubefile_name = '' selected_events_name = 'selected_events.fits' result_name = 'results.xml' if self.simfilename and self.eventfilename: print('error') exit(10) ############ Simulate events if self.simfilename: # Setup simulation model if self.simfilename: self.obs.models(gammalib.GModels(self.simfilename)) if self.runconf.WorkInMemory == 0: print('# Generate simulated event list on disk') # Simulate events on disk sim = ctools.ctobssim(self.obs) sim['outevents'] = events_name sim['debug'] = debug sim['seed'] = seed sim.execute() self.eventfilename = events_name if self.runconf.WorkInMemory == 1: print('# Generate simulated event list in memory') # Simulate events on memory sim = ctools.ctobssim(self.obs) sim['debug'] = debug sim['seed'] = seed sim.run() #if self.runfilename is not present # import into DB if any # exit(0) ############ Get events from DB if not self.simfilename and not self.eventfilename: #load from DB print('# Load event list from DB') #write selected_events_name if self.runconf.timeref_timesys == 'tt': tstart_tt = self.runconf.tmin tstop_tt = self.runconf.tmax if self.runconf.timeref_timesys == 'mjd': tstart_tt = Utility.convert_mjd_to_tt(self.runconf.tmin) tstop_tt = Utility.convert_mjd_to_tt(self.runconf.tmax) #tstart_tt = self.runconf.tmin #tstop_tt = self.runconf.tmax observationid = self.obsconf.id print("tstart" + str(tstart_tt)) print("tstop" + str(tstart_tt)) print(self.runconf.timeref_timesys) conf_dictionary = get_path_conf() path_base_fits = conf_dictionary['path_base_fits'] tref_mjd = self.runconf.timeref if self.runconf.roi_frame == 'fk5': obs_ra = self.obsconf.roi_ra obs_dec = self.obsconf.roi_dec else: exit(10) emin = self.runconf.emin emax = self.runconf.emax fov = self.obsconf.roi_fov instrumentname = self.obsconf.instrument datarepository_dictionary = get_data_repository(instrumentname) datarepositoryid = datarepository_dictionary['datarepositoryid'] print("before write fits") print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) events_name = write_fits(tstart_tt, tstop_tt, observationid, datarepositoryid, path_base_fits, tref_mjd, obs_ra, obs_dec, emin, emax, 180, instrumentname) print("after write fits") print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) print("fitsname" + events_name) if self.runconf.WorkInMemory == 2: print('# Load event list from disk') #Load events from fits file on memory sim = ctools.ctobssim(self.obs) events = sim.obs()[0].events() for event in events: print(event) #events.load(events_name) events.load(selected_events_name) ############ Select events if self.runconf.WorkInMemory == 1: print('# Select event list in memory') select = ctools.ctselect(sim.obs()) #using file if self.runconf.WorkInMemory == 0: print('# Select event list from disk') select = ctools.ctselect() select['inobs'] = events_name select['outobs'] = selected_events_name select['ra'] = self.runconf.roi_ra select['dec'] = self.runconf.roi_dec select['rad'] = self.runconf.roi_ringrad select['tmin'] = 'MJD ' + str(self.runconf.tmin) #select['tmin'] = 'INDEF' #select['tmin'] = 0.0 #select['tmin'] = 'MJD 55197.0007660185' #select['tmax'] = self.runconf.tmax #select['tmax'] = 'INDEF' select['tmax'] = 'MJD ' + str(self.runconf.tmax) #select['tmax'] = 55197.0007660185 + self.runconf.tmax / 86400. select['emin'] = self.runconf.emin select['emax'] = self.runconf.emax if self.runconf.WorkInMemory == 1: select.run() if self.runconf.WorkInMemory == 0: select.execute() print("after select events") print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) #print(self.runconf.roi_ra) #print(self.runconf.roi_dec) #print(self.obsconf.obs_fov) #print(self.runconf.tmin) #print(self.runconf.tmax) #print(self.runconf.emin) #print(self.runconf.emax) #print(select.obs()[0]) print("select --") print(select) print("select --") if self.runconf.WorkInMemory == 2: print('# Load event list from disk') #Load events from fits file on memory sim = ctools.ctobssim(self.obs) events = sim.obs()[0].events() for event in events: print(event) #events.load(events_name) events.load(selected_events_name) print('Event list generated ----------------------') if self.runconf.WorkInMemory == 0: print(self.obs) print("obs --") print(self.obs[0]) print("obs 0 --") localobs = self.obs if self.runconf.WorkInMemory == 1: print(select.obs()) print(select.obs()[0]) localobs = select.obs() for run in localobs: print('run ---' + selected_events_name) print("before ctbin") print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) print(run) # Create container with a single observation container = gammalib.GObservations() container.append(run) if self.runconf.MakeCtsMap == 1: cubefile_name = 'cube.fits' #event file in memory or read from fits file on memory if self.runconf.WorkInMemory == 1: bin = ctools.ctbin(container) if self.runconf.WorkInMemory == 0: #event file on disk bin = ctools.ctbin() bin['inobs'] = selected_events_name #make binned map on disk bin['outcube'] = cubefile_name #common configs bin['ebinalg'] = self.runconf.cts_ebinalg bin['emin'] = self.runconf.emin bin['emax'] = self.runconf.emax bin['enumbins'] = self.runconf.cts_enumbins bin['nxpix'] = ceil(self.runconf.roi_ringrad * 2 / self.runconf.cts_binsz) bin['nypix'] = ceil(self.runconf.roi_ringrad * 2 / self.runconf.cts_binsz) bin['binsz'] = self.runconf.cts_binsz bin['coordsys'] = self.runconf.cts_coordsys bin['usepnt'] = self.runconf.cts_usepnt # Use pointing for map centre bin['proj'] = self.runconf.cts_proj bin['xref'] = self.runconf.roi_ra bin['yref'] = self.runconf.roi_dec print("-- bin") print(bin) #make binned map on disk if self.runconf.WorkInMemory == 0: bin.execute() # Set observation ID if make binned map on disk bin.obs()[0].id(cubefile_name) bin.obs()[0].eventfile(cubefile_name) os.system('mkdir -p ' + self.runconf.resdir) shutil.copy( './cube.fits', self.runconf.resdir + '/' + self.runconf.runprefix + '_cube.fits') if self.runconf.CtsMapToPng == 1: title = 'OBS ' + str( self.obsconf.id) + ' / MJD ' + str( self.runconf.tmin) + ' - ' + 'MJD ' + str( self.runconf.tmax) SkyImage.display(cubefile_name, "sky1.png", 2, title) #SkyImage.dispalywithds9_cts1(cubefile_name, "sky2", 10) #copy results os.system('mkdir -p ' + self.runconf.resdir) shutil.copy( './sky1.png', self.runconf.resdir + '/' + self.runconf.runprefix + '_sky1.png') #make binned map on memory if self.runconf.WorkInMemory == 1: bin.run() # Append result to observations #localobs.extend(bin.obs()) print("after ctbin") print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) #print(obs) #print(obs[0]) print(str(self.obsconf.caldb)) #hypothesis builders #3GHextractor # 3GH Extractor code if self.runconf.HypothesisGenerator3GH and cubefile_name: self.analysisfilename = CTA3GHextractor_wrapper.extract_source( cubefile_name) print(self.analysisfilename) #cv2.waitKey(0) print('HypothesisGeneratorEG3') #eseguire MLE print('analysisfilename: ' + self.analysisfilename) if self.analysisfilename: print('before MLE') print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) # Perform maximum likelihood fitting if self.runconf.WorkInMemory == 1: like = ctools.ctlike(select.obs()) if self.runconf.WorkInMemory == 0: like = ctools.ctlike() if (self.runconf.binned == "1"): like['inobs'] = cubefile_name like['expcube'] = "NONE" like['psfcube'] = "NONE" like['edispcube'] = "NONE" like['bkgcube'] = "NONE" like['statistic'] = "CHI2" if (self.runconf.binned == "0"): like['inobs'] = selected_events_name like['statistic'] = "DEFAULT" like['inmodel'] = self.analysisfilename like['outmodel'] = result_name like['caldb'] = str(self.obsconf.caldb) like['irf'] = self.obsconf.irf like.execute() print(like) logL = like.opt().value() print(like.obs().models()) print("after MLE") print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) # insert logL into results.xml tree = etree.parse(result_name) contentnav = tree.find(".//source[@type='PointSource']") #contentdiv = contentnav.getparent() #contentnav.set("ts",str(logL)) contentnav.set("runid", str(self.runconf.runid)) #print(etree.tostring(tree,encoding="unicode",pretty_print=True)) f = open(result_name, 'w') f.write( etree.tostring(tree, encoding="unicode", pretty_print=True)) f.close() os.system('mkdir -p ' + self.runconf.resdir) shutil.copy( './results.xml', self.runconf.resdir + '/' + self.runconf.runprefix + '_results.xml') if self.runconf.deleterun == "1": cmd = 'rm -r ' + self.runconf.rundir os.system(cmd) if self.runconf.HypothesisGenerator3GH: CTA3GHextractor_wrapper.print_graphs(self.simfilename, result_name, self.analysisfilename) #cv2.destroyAllWindows() print('HypothesisGeneratorEG3') # Return return
obsselect.execute() obsselect = cscripts.csobsselect() obsselect['inobs'] = '$CTADATA/obs/obs_gc_baseline.xml' obsselect['pntselect'] = 'CIRCLE' obsselect['coordsys'] = 'GAL' obsselect['glon'] = 0.0 obsselect['glat'] = 0.0 obsselect['rad'] = 5.0 obsselect['tmin'] = 'NONE' obsselect['tmax'] = 'NONE' obsselect['outobs'] = 'obs_gc.xml' obsselect["debug"] = debug obsselect.execute() select = ctools.ctselect() select['inobs'] = 'obs_gps.xml' select['ra'] = 'NONE' select['dec'] = 'NONE' select['rad'] = 'NONE' select['tmin'] = 'NONE' select['tmax'] = 'NONE' select['emin'] = 0.1 select['emax'] = 100.0 select['outobs'] = 'obs_selected_gps.xml' select["debug"] = debug select.execute() select = ctools.ctselect() select['inobs'] = 'obs_gc.xml' select['ra'] = 'NONE'
def pipeline(model_name): """ Unbinned in-memory analysis pipeline This function implements an analysis pipeline that successively calls ctobssim, ctselect and ctlike without saving the intermediate results as FITS files on disk. All data is only hold in memory. """ # Set script parameters caldb = 'prod2' irf = 'South_0.5h' ra = 83.63 dec = 22.01 rad_sim = 5.0 tstart = 0.0 tstop = 180.0 emin = 0.1 emax = 100.0 rad_select = 3.0 # Write model name print('*** Model: '+model_name+' ************************************') # Initialise timing wall_seconds = 0.0 cpu_seconds = 0.0 # Simulate events sim = ctools.ctobssim() sim['inmodel'] = model_name sim['caldb'] = caldb sim['irf'] = irf sim['ra'] = ra sim['dec'] = dec sim['rad'] = rad_sim sim['tmin'] = tstart sim['tmax'] = tstop sim['emin'] = emin sim['emax'] = emax sim.run() # Select events select = ctools.ctselect(sim.obs()) select['ra'] = ra select['dec'] = dec select['rad'] = rad_select select['tmin'] = tstart select['tmax'] = tstop select['emin'] = emin select['emax'] = emax select.run() # Perform maximum likelihood fitting like = ctools.ctlike(select.obs()) like.run() # Show model fitting results print(like.obs().models()[0]) # Return return