def __init__(self, *argv): """ Constructor. """ # Set name self._name = 'csobsinfo' self._version = '1.1.0' # Initialise class members self._obj_dir = None self._compute_offset = False self._offsets = [] self._zeniths = [] self._azimuths = [] self._pnt_ra = [] self._pnt_dec = [] self._ebounds = gammalib.GEbounds() self._gti = gammalib.GGti() # Initialise observation container from constructor arguments. self._obs, argv = self._set_input_obs(argv) # Initialise application by calling the appropriate class # constructor. self._init_cscript(argv) # Return return
def __init__(self, *argv): """ Constructor. """ # Set name self._name = "cslightcrv" self._version = "1.1.0" # Initialise some members self._srcname = "" self._tbins = gammalib.GGti() self._stacked = False self._fits = gammalib.GFits() # Initialise observation container from constructor arguments. self._obs, argv = self._set_input_obs(argv) # Initialise script by calling the appropriate class constructor. self._init_cscript(argv) # Set logger properties self._log_header() self._log.date(True) # Return return
def createobs(ra=86.171648, dec=-1.4774586, rad=5.0, emin=0.1, emax=100.0, duration=360000.0, deadc=0.95, ): obs = gammalib.GCTAObservation() # Set pointing direction pntdir = gammalib.GSkyDir() pntdir.radec_deg(ra, dec) pnt = gammalib.GCTAPointing() pnt.dir(pntdir) obs.pointing(pnt) # Set ROI roi = gammalib.GCTARoi() instdir = gammalib.GCTAInstDir() instdir.dir(pntdir) roi.centre(instdir) roi.radius(rad) # Set GTI gti = gammalib.GGti() start = gammalib.GTime(0.0) stop = gammalib.GTime(duration) gti.append(start, stop) # Set energy boundaries ebounds = gammalib.GEbounds() e_min = gammalib.GEnergy() e_max = gammalib.GEnergy() e_min.TeV(emin) e_max.TeV(emax) ebounds.append(e_min, e_max) # Allocate event list events = gammalib.GCTAEventList() events.roi(roi) events.gti(gti) events.ebounds(ebounds) obs.events(events) # Set ontime, livetime, and deadtime correction factor obs.ontime(duration) obs.livetime(duration * deadc) obs.deadc(deadc) # Return observation return obs
def __init__(self, *argv): """ Constructor """ # Initialise application by calling the appropriate class constructor self._init_csobservation(self.__class__.__name__, ctools.__version__, argv) # Initialise some members self._srcname = '' self._tbins = gammalib.GGti() self._onoff = False self._stacked = False self._fits = gammalib.GFits() # Return return
def create_lightcurve_gti(obsname, gtiname): """ Generate lightcurve for GTIs Parameters ---------- obsname : str Observation definition XML file gtiname : str GTI output filename """ # Load observations obs = gammalib.GObservations(obsname) # Initialize GTIs gti = gammalib.GGti() # Loop over observations for run in obs: # Get start time and ontime of GTIs tstart = run.gti().tstart().copy() ontime = run.gti().ontime() # Set time bins tbin = ontime / 14.0 # Loop over time bins for i in range(14): # Compute stop time tstop = tstart + tbin # Append GTI gti.append(tstart, tstop) # Update start time tstart = tstop.copy() # Save GTIs gti.save(gtiname, True) # Return return
def __init__(self, *argv): """ Constructor. """ # Initialise application by calling the appropriate class constructor self._init_csobservation(self.__class__.__name__, ctools.__version__, argv) # Initialise class members self._obj_dir = None self._compute_offset = False self._offsets = [] self._zeniths = [] self._azimuths = [] self._pnt_ra = [] self._pnt_dec = [] self._ebounds = gammalib.GEbounds() self._gti = gammalib.GGti() # Return return
def _create_tbounds(self): """ Creates light curve time bins. The method reads the following user parameters: tbinalg: Time binning algorithm tbinfile: Time binning file (FITS or ASCII) tmin: Start time (MJD) tmax: Stop time (MJD) tbins: Number of time bins Returns: Light curve bins in form of a GTI. """ # Initialise Good Time Intervals gti = gammalib.GGti() # Get algorithm to use for defining the time intervals algorithm = self["tbinalg"].string() # Handle a FITS or a ASCII file for time bin definition if algorithm == "FILE": # Get the filename filename = self["tbinfile"].filename() # If the file a FITS file then load GTIs if filename.is_fits(): gti.load(filename) # ... otherwise load file as CSV ASCII file csv = gammalib.GCsv(filename) for i in range(csv.nrows()): tmin = gammalib.GTime() tmax = gammalib.GTime() tmin.mjd(csv.real(i, 0)) tmax.mjd(csv.real(i, 1)) gti.append(tmin, tmax) # Handle linear time binning elif algorithm == "LIN": # Get start and stop time and number of time bins time_min = self["tmin"].real() time_max = self["tmax"].real() nbins = self["tbins"].integer() # Compute time step and setup time intervals time_step = (time_max - time_min) / float(nbins) for i in range(nbins): tmin = gammalib.GTime() tmax = gammalib.GTime() tmin.mjd(time_min + i * time_step) tmax.mjd(time_min + (i + 1) * time_step) gti.append(tmin, tmax) # Handle usage of observation GTIs elif algorithm == "GTI": # Append the GTIs of all observations for obs in self._obs: for i in range(obs.events().gti().size()): gti.append(obs.events().gti().tstart(i), obs.events().gti().tstop(i)) # ... otherwise raise an exception (this should never occur) else: raise AttributeError('Paramter tbinalg="' + algorithm + '" unknown. ' 'Must be one of "FILE", "LIN" or "GTI".') # Return Good Time Intervals return gti
def run(self): """ Run the script Raises ------ RuntimeError Invalid pointing definition file format """ # Switch screen logging on in debug mode if self._logDebug(): self._log.cout(True) # Get parameters self._get_parameters() # Write header into logger self._log_header1(gammalib.TERSE, 'Creating observation definition XML file') # Load pointing definition file if it is not already set. Extract # the number of columns and pointings if self._pntdef.size() == 0: self._pntdef = gammalib.GCsv(self['inpnt'].filename(), ',') ncols = self._pntdef.ncols() npnt = self._pntdef.nrows() - 1 # Raise an exception if there is no header information if self._pntdef.nrows() < 1: raise RuntimeError('No header found in pointing definition file.') # Clear observation container self._obs.clear() # Initialise observation identifier counter identifier = 1 # Extract header columns from pointing definition file and put them # into a list header = [] for col in range(ncols): header.append(self._pntdef[0, col]) # Loop over all pointings for pnt in range(npnt): # Set pointing definition CSV file row index row = pnt + 1 # Create empty CTA observation obs = gammalib.GCTAObservation() # Set observation name. If no observation name was given then # use "None". if 'name' in header: name = self._pntdef[row, header.index('name')] else: name = self['name'].string() obs.name(name) # Set observation identifier. If no observation identified was # given the use the internal counter. if 'id' in header: obsid = self._pntdef[row, header.index('id')] else: obsid = '%6.6d' % identifier identifier += 1 obs.id(obsid) # Set pointing. Either use "ra" and "dec" or "lon" and "lat". # If none of these pairs are given then raise an exception. if 'ra' in header and 'dec' in header: ra = float(self._pntdef[row, header.index('ra')]) dec = float(self._pntdef[row, header.index('dec')]) pntdir = gammalib.GSkyDir() pntdir.radec_deg(ra, dec) elif 'lon' in header and 'lat' in header: lon = float(self._pntdef[row, header.index('lon')]) lat = float(self._pntdef[row, header.index('lat')]) pntdir = gammalib.GSkyDir() pntdir.lb_deg(lon, lat) else: raise RuntimeError('No (ra,dec) or (lon,lat) columns ' 'found in pointing definition file.') obs.pointing(gammalib.GCTAPointing(pntdir)) # Set response function. If no "caldb" or "irf" information is # provided then use the user parameter values. if 'caldb' in header: caldb = self._pntdef[row, header.index('caldb')] else: caldb = self['caldb'].string() if 'irf' in header: irf = self._pntdef[row, header.index('irf')] else: irf = self['irf'].string() if caldb != '' and irf != '': obs = self._set_irf(obs, caldb, irf) # Set deadtime correction factor. If no information is provided # then use the user parameter value "deadc". if 'deadc' in header: deadc = float(self._pntdef[row, header.index('deadc')]) else: deadc = self['deadc'].real() obs.deadc(deadc) # Set Good Time Interval. If no information is provided then use # the user parameter values "tmin" and "duration". if 'tmin' in header: self._tmin = float(self._pntdef[row, header.index('tmin')]) if 'duration' in header: duration = float(self._pntdef[row, header.index('duration')]) else: duration = self['duration'].real() tref = gammalib.GTimeReference(self['mjdref'].real(), 's') tmin = self._tmin tmax = self._tmin + duration gti = gammalib.GGti(tref) tstart = gammalib.GTime(tmin, tref) tstop = gammalib.GTime(tmax, tref) self._tmin = tmax gti.append(tstart, tstop) obs.ontime(gti.ontime()) obs.livetime(gti.ontime() * deadc) # Set Energy Boundaries. If no "emin" or "emax" information is # provided then use the user parameter values in case they are # valid. has_emin = False has_emax = False if 'emin' in header: emin = float(self._pntdef[row, header.index('emin')]) has_emin = True else: if self['emin'].is_valid(): emin = self['emin'].real() has_emin = True if 'emax' in header: emax = float(self._pntdef[row, header.index('emax')]) has_emax = True else: if self['emax'].is_valid(): emax = self['emax'].real() has_emax = True has_ebounds = has_emin and has_emax if has_ebounds: ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, 'TeV'), gammalib.GEnergy(emax, 'TeV')) # Set ROI. If no ROI radius is provided then use the user # parameters "rad". has_roi = False if 'rad' in header: rad = float(self._pntdef[row, header.index('rad')]) has_roi = True else: if self['rad'].is_valid(): rad = self['rad'].real() has_roi = True if has_roi: roi = gammalib.GCTARoi(gammalib.GCTAInstDir(pntdir), rad) # Create an empty event list event_list = gammalib.GCTAEventList() event_list.gti(gti) # If available, set the energy boundaries and the ROI if has_ebounds: event_list.ebounds(ebounds) if has_roi: event_list.roi(roi) # Attach event list to CTA observation obs.events(event_list) # Write observation into logger name = obs.instrument() + ' observation' value = 'Name="%s" ID="%s"' % (obs.name(), obs.id()) self._log_value(gammalib.NORMAL, name, value) self._log_string(gammalib.EXPLICIT, str(obs) + '\n') # Append observation self._obs.append(obs) # Return return
def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \ emin=0.1, emax=100.0, rad=5.0, \ irf="South_50h", caldb="prod2", id="000000"): """ Set a single CTA observation. The function sets a single CTA observation containing an empty CTA event list. By looping over this function you can add CTA observations to the observation container. Args: pntdir: Pointing direction [GSkyDir] Kwargs: tstart: Start time (seconds) (default: 0.0) duration: Duration of observation (seconds) (default: 1800.0) deadc: Deadtime correction factor (default: 0.95) emin: Minimum event energy (TeV) (default: 0.1) emax: Maximum event energy (TeV) (default: 100.0) rad: ROI radius used for analysis (deg) (default: 5.0) irf: Instrument response function (default: "South_50h") caldb: Calibration database path (default: "prod2") id: Run identifier (default: "000000") """ # Allocate CTA observation obs_cta = gammalib.GCTAObservation() # Set calibration database db = gammalib.GCaldb() if (gammalib.dir_exists(caldb)): db.rootdir(caldb) else: db.open("cta", caldb) # Set pointing direction pnt = gammalib.GCTAPointing() pnt.dir(pntdir) obs_cta.pointing(pnt) # Set ROI roi = gammalib.GCTARoi() instdir = gammalib.GCTAInstDir() instdir.dir(pntdir) roi.centre(instdir) roi.radius(rad) # Set GTI gti = gammalib.GGti() gti.append(gammalib.GTime(tstart), gammalib.GTime(tstart + duration)) # Set energy boundaries ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, "TeV"), gammalib.GEnergy(emax, "TeV")) # Allocate event list events = gammalib.GCTAEventList() events.roi(roi) events.gti(gti) events.ebounds(ebounds) obs_cta.events(events) # Set instrument response obs_cta.response(irf, db) # Set ontime, livetime, and deadtime correction factor obs_cta.ontime(duration) obs_cta.livetime(duration * deadc) obs_cta.deadc(deadc) obs_cta.id(id) # Return CTA observation return obs_cta
def _create_tbounds(self): """ Creates light curve time bins Returns ------- gti : `~gammalib.GGti` Light curve bins in form of Good Time Intervals """ # Initialise Good Time Intervals gti = gammalib.GGti() # Get algorithm to use for defining the time intervals. Possible # values are "FILE", "LIN" and "GTI". This is enforced at # parameter file level, hence no checking is needed. algorithm = self['tbinalg'].string() # If the algorithm is "FILE" then handle a FITS or an ASCII file for # the time bin definition if algorithm == 'FILE': # Get the filename filename = self['tbinfile'].filename() # If the file a FITS file then load GTIs directly if filename.is_fits(): gti.load(filename) # ... otherwise load file the ASCII file as CSV file and construct # the GTIs from the rows of the CSV file. It is expected that the # CSV file has two columns containing the "START" and "STOP" # values of the time bins. No header row is expected. csv = gammalib.GCsv(filename) for i in range(csv.nrows()): tmin = gammalib.GTime() tmax = gammalib.GTime() tmin.mjd(csv.real(i, 0)) tmax.mjd(csv.real(i, 1)) gti.append(tmin, tmax) # If the algorithm is "LIN" then use a linear time binning, defined by # the "tmin", "tmax" and "tbins" user parameters elif algorithm == 'LIN': # Get start and stop time and number of time bins time_min = self['tmin'].time(ctools.time_reference) time_max = self['tmax'].time(ctools.time_reference) nbins = self['tbins'].integer() # Compute time step in seconds and setup the GTIs time_step = (time_max - time_min) / float(nbins) for i in range(nbins): tmin = time_min + i * time_step tmax = time_min + (i + 1) * time_step gti.append(tmin, tmax) # If the algorithm is "GTI" then extract the GTIs from the observations # in the container and use them for the light curve time binning elif algorithm == 'GTI': # Append the GTIs of all observations for obs in self.obs(): for i in range(obs.events().gti().size()): gti.append(obs.events().gti().tstart(i), obs.events().gti().tstop(i)) # Return Good Time Intervals return gti
def _test_get_stacked_response(self): """ Test get_stacked_response() function """ # Set-up observation container obs = self._setup_sim() # Set-up counts cube map = gammalib.GSkyMap('CAR','CEL',83.6331,22.0145,0.1,0.1,10,10,5) emin = gammalib.GEnergy(0.1, 'TeV') emax = gammalib.GEnergy(100.0, 'TeV') ebds = gammalib.GEbounds(5, emin, emax) tmin = gammalib.GTime(0.0) tmax = gammalib.GTime(1000.0) gti = gammalib.GGti(tmin, tmax) cntcube = gammalib.GCTAEventCube(map, ebds, gti) # Get stacked response res = obsutils.get_stacked_response(obs, cntcube, edisp=False) # Check result self.test_value(res['expcube'].cube().npix(), 100, 'Check number of exposure cube pixels') self.test_value(res['expcube'].cube().nmaps(), 91, 'Check number of exposure cube maps') self.test_value(res['psfcube'].cube().npix(), 4, 'Check number of PSF cube pixels') self.test_value(res['psfcube'].cube().nmaps(), 18200, 'Check number of PSF cube maps') self.test_value(res['bkgcube'].cube().npix(), 100, 'Check number of background cube pixels') self.test_value(res['bkgcube'].cube().nmaps(), 5, 'Check number of background cube maps') # Get stacked response with energy dispersion res = obsutils.get_stacked_response(obs, cntcube, edisp=True) # Check result self.test_value(res['expcube'].cube().npix(), 100, 'Check number of exposure cube pixels') self.test_value(res['expcube'].cube().nmaps(), 105, 'Check number of exposure cube maps') self.test_value(res['psfcube'].cube().npix(), 4, 'Check number of PSF cube pixels') self.test_value(res['psfcube'].cube().nmaps(), 21000, 'Check number of PSF cube maps') self.test_value(res['bkgcube'].cube().npix(), 100, 'Check number of background cube pixels') self.test_value(res['bkgcube'].cube().nmaps(), 5, 'Check number of background cube maps') self.test_value(res['edispcube'].cube().npix(), 4, 'Check number of energy dispersion cube pixels') self.test_value(res['edispcube'].cube().nmaps(), 10500, 'Check number of energy dispersion cube maps') # Set-up counts cube with large number of energy bins ebds = gammalib.GEbounds(100, emin, emax) cntcube = gammalib.GCTAEventCube(map, ebds, gti) # Get stacked response with xref/yref set and large number of energy bins res = obsutils.get_stacked_response(obs, cntcube, edisp=False) # Check result self.test_value(res['expcube'].cube().npix(), 100, 'Check number of exposure cube pixels') self.test_value(res['expcube'].cube().nmaps(), 91, 'Check number of exposure cube maps') self.test_value(res['psfcube'].cube().npix(), 4, 'Check number of PSF cube pixels') self.test_value(res['psfcube'].cube().nmaps(), 18200, 'Check number of PSF cube maps') self.test_value(res['bkgcube'].cube().npix(), 100, 'Check number of background cube pixels') self.test_value(res['bkgcube'].cube().nmaps(), 100, 'Check number of background cube maps') # Return return
def run(self): """ Run the script. Raises ------ RuntimeError Invalid pointing definition file format. """ # Switch screen logging on in debug mode if self._logDebug(): self._log.cout(True) # Get parameters self._get_parameters() # Write header into logger if self._logTerse(): self._log('\n') self._log.header1('Creating observation definition XML file') # Load pointing definition file if it is not already set if self._pntdef.size() == 0: self._pntdef = gammalib.GCsv(self['inpnt'].filename(), ',') ncols = self._pntdef.ncols() npnt = self._pntdef.nrows()-1 # Throw an exception is there is no header information if self._pntdef.nrows() < 1: raise RuntimeError('No header found in pointing definition file.') # Clear observation container self._obs.clear() identifier = 1 # Extract header from pointing definition file header = [] for col in range(ncols): header.append(self._pntdef[0,col]) # Loop over all pointings for pnt in range(npnt): # Set row index row = pnt + 1 # Create CTA observation obs = gammalib.GCTAObservation() # Set observation name if 'name' in header: name = self._pntdef[row, header.index('name')] else: name = 'None' obs.name(name) # Set identifier if 'id' in header: id_ = self._pntdef[row, header.index('id')] else: id_ = '%6.6d' % identifier identifier += 1 obs.id(id_) # Set pointing if 'ra' in header and 'dec' in header: ra = float(self._pntdef[row, header.index('ra')]) dec = float(self._pntdef[row, header.index('dec')]) pntdir = gammalib.GSkyDir() pntdir.radec_deg(ra,dec) elif 'lon' in header and 'lat' in header: lon = float(self._pntdef[row, header.index('lon')]) lat = float(self._pntdef[row, header.index('lat')]) pntdir = gammalib.GSkyDir() pntdir.lb_deg(lon,lat) else: raise RuntimeError('No (ra,dec) or (lon,lat) columns ' 'found in pointing definition file.') obs.pointing(gammalib.GCTAPointing(pntdir)) # Set response function if 'caldb' in header: caldb = self._pntdef[row, header.index('caldb')] else: caldb = self['caldb'].string() if 'irf' in header: irf = self._pntdef[row, header.index('irf')] else: irf = self['irf'].string() if caldb != '' and irf != '': obs = self._set_response(obs, caldb, irf) # Set deadtime correction factor if 'deadc' in header: deadc = float(self._pntdef[row, header.index('deadc')]) else: deadc = self['deadc'].real() obs.deadc(deadc) # Set Good Time Interval if 'duration' in header: duration = float(self._pntdef[row, header.index('duration')]) else: duration = self['duration'].real() tmin = self._tmin tmax = self._tmin + duration gti = gammalib.GGti(self._time_reference()) tstart = gammalib.GTime(tmin, self._time_reference()) tstop = gammalib.GTime(tmax, self._time_reference()) self._tmin = tmax gti.append(tstart, tstop) obs.ontime(gti.ontime()) obs.livetime(gti.ontime()*deadc) # Set Energy Boundaries has_emin = False has_emax = False if 'emin' in header: emin = float(self._pntdef[row, header.index('emin')]) has_emin = True else: if self['emin'].is_valid(): emin = self['emin'].real() has_emin = True if 'emax' in header: emax = float(self._pntdef[row, header.index('emax')]) has_emax = True else: if self['emax'].is_valid(): emax = self['emax'].real() has_emax = True has_ebounds = has_emin and has_emax if has_ebounds: ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, 'TeV'), gammalib.GEnergy(emax, 'TeV')) # Set ROI has_roi = False if 'rad' in header: rad = float(self._pntdef[row, header.index('rad')]) has_roi = True else: if self['rad'].is_valid(): rad = self['rad'].real() has_roi = True if has_roi: roi = gammalib.GCTARoi(gammalib.GCTAInstDir(pntdir), rad) # Create an empty event list list_ = gammalib.GCTAEventList() list_.gti(gti) # Set optional information if has_ebounds: list_.ebounds(ebounds) if has_roi: list_.roi(roi) # Attach event list to CTA observation obs.events(list_) # Write observation into logger if self._logExplicit(): self._log(str(obs)) self._log('\n') elif self._logTerse(): self._log(gammalib.parformat(obs.instrument()+' observation')) self._log('Name="'+obs.name()+'" ') self._log('ID="'+obs.id()+'"\n') # Append observation self._obs.append(obs) # Return return
def set_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.98, \ emin=0.1, emax=100.0, rad=5.0, \ irf='South_50h', caldb='prod2', obsid='000000'): """ Set a single CTA observation The function sets a single CTA observation containing an empty CTA event list. By looping over this function CTA observations can be added to the observation container. Parameters ---------- pntdir : `~gammalib.GSkyDir` Pointing direction tstart : float, optional Start time (s) duration : float, optional Duration of observation (s) deadc : float, optional Deadtime correction factor emin : float, optional Minimum event energy (TeV) emax : float, optional Maximum event energy (TeV) rad : float, optional ROI radius used for analysis (deg) irf : str, optional Instrument response function caldb : str, optional Calibration database path obsid : str, optional Observation identifier Returns ------- obs : `~gammalib.GCTAObservation` CTA observation """ # Allocate CTA observation obs = gammalib.GCTAObservation() # Set CTA calibration database db = gammalib.GCaldb() if (gammalib.dir_exists(caldb)): db.rootdir(caldb) else: db.open('cta', caldb) # Set pointing direction for CTA observation pnt = gammalib.GCTAPointing() pnt.dir(pntdir) obs.pointing(pnt) # Set ROI roi = gammalib.GCTARoi() instdir = gammalib.GCTAInstDir() instdir.dir(pntdir) roi.centre(instdir) roi.radius(rad) # Set GTI gti = gammalib.GGti() gti.append(gammalib.GTime(tstart), gammalib.GTime(tstart + duration)) # Set energy boundaries ebounds = gammalib.GEbounds(gammalib.GEnergy(emin, 'TeV'), gammalib.GEnergy(emax, 'TeV')) # Allocate event list events = gammalib.GCTAEventList() # Set ROI, GTI and energy boundaries for event list events.roi(roi) events.gti(gti) events.ebounds(ebounds) # Set the event list as the events for CTA observation obs.events(events) # Set instrument response for CTA observation obs.response(irf, db) # Set ontime, livetime, and deadtime correction factor for CTA observation obs.ontime(duration) obs.livetime(duration * deadc) obs.deadc(deadc) obs.id(obsid) # Return CTA observation 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() # Initialise arrays to store certain values for reuse # Todo, think about using a python dictionary self._offsets = [] self._zeniths = [] self._azimuths = [] self._pnt_ra = [] self._pnt_dec = [] self._ebounds = gammalib.GEbounds() self._gti = gammalib.GGti() obs_names = [] # Initialise output to be filled ontime = 0.0 livetime = 0.0 n_events = 0 n_eventbins = 0 n_obs_binned = 0 n_obs_unbinned = 0 # Write header if self._logTerse(): self._log('\n') self._log.header1(gammalib.number('Observation', self._obs.size())) # Loop over observations for obs in self._obs: # Skip non-CTA observations if not obs.classname() == 'GCTAObservation': self._log('Skipping ' + obs.instrument() + ' observation\n') continue # Use observed object as observation name if name is not given obs_name = obs.name() if obs_name == '': obs_name = obs.object() # Logging if self._logTerse(): self._log.header2(obs_name) # Retrieve observation name obs_names.append(obs_name) # Retrieve energy boundaries obs_bounds = obs.events().ebounds() # Retrieve time interval obs_gti = obs.events().gti() # Compute mean time and dead time fraction in percent deadfrac = (1.0 - obs.deadc()) * 100.0 # Retrieve pointing and store Ra,Dec pnt_dir = obs.pointing().dir() self._pnt_ra.append(pnt_dir.ra_deg()) self._pnt_dec.append(pnt_dir.dec_deg()) # If avaliable append energy boundaries if obs_bounds.size() > 0: self._ebounds.append(obs_bounds.emin(), obs_bounds.emax()) # Append time interval self._gti.append(obs_gti.tstart(), obs_gti.tstop()) # Increment global livetime and ontime ontime += obs.ontime() livetime += obs.livetime() # Bookkeeping if obs.eventtype() == 'CountsCube': n_eventbins += obs.events().size() n_obs_binned += 1 if self._logTerse(): self._log.parformat('Binned') self._log('yes\n') self._log.parformat('Number of bins') self._log(str(obs.events().size())) self._log('\n') else: n_events += obs.events().size() n_obs_unbinned += 1 if self._logTerse(): self._log.parformat('Binned') self._log('no\n') self._log.parformat('Number of events') self._log(str(obs.events().size())) self._log('\n') # Retrieve zenith and azimuth and store for later use zenith = obs.pointing().zenith() azimuth = obs.pointing().azimuth() self._zeniths.append(zenith) self._azimuths.append(azimuth) # Optionally compute offset with respect to target direction if self._compute_offset: offset = pnt_dir.dist_deg(self._obj_dir) self._offsets.append(offset) else: self._offsets.append(-1.0) # Optionally log details if self._logTerse(): # Log the observation energy range (if available) self._log.parformat('Energy range') if obs_bounds.size() == 0: self._log('undefined') else: self._log(str(obs_bounds.emin())) self._log(' - ') self._log(str(obs_bounds.emax())) self._log('\n') # Log observation time interval self._log.parformat('Time range (MJD)') if obs_gti.size() == 0: self._log('undefined') else: self._log(str(obs_gti.tstart().mjd())) self._log(' - ') self._log(str(obs_gti.tstop().mjd())) self._log('\n') # Log ontime self._log.parformat('Ontime') self._log(str(obs.ontime())) self._log(' s\n') # Log livetime self._log.parformat('Livetime') self._log(str(obs.livetime())) self._log(' s\n') # Log dead time fraction self._log.parformat('Deadtime fraction (%)') self._log('%.3f' % (deadfrac)) self._log('\n') # Log pointing direction self._log.parformat('Pointing') self._log(str(pnt_dir)) self._log('\n') # Optionally log offset with respect to target direction if self._compute_offset: self._log.parformat('Offset from target') self._log('%.2f' % (offset)) self._log(' deg\n') # Log Zenith and Azimuth if required self._log.parformat('Zenith angle') self._log('%.2f' % (zenith)) self._log(' deg\n') self._log.parformat('Azimuth angle') self._log('%.2f' % (azimuth)) self._log(' deg\n') # Log summary if self._logTerse(): # Write header self._log('\n') self._log.header1('Summary') # Log general summary self._log.header3('Observations') self._log.parformat('Unbinned observations') self._log(str(n_obs_unbinned)) self._log('\n') self._log.parformat('Binned observations') self._log(str(n_obs_binned)) self._log('\n') self._log.header3('Events') self._log.parformat('Number of events') self._log(str(n_events)) self._log('\n') self._log.parformat('Number of bins') self._log(str(n_eventbins)) self._log('\n') # Log pointing summary self._log.header3('Pointings') # Log mean offset if possible if self._compute_offset: self._log.parformat('Mean offset angle') self._log('%.2f' % (sum(self._offsets) / len(self._offsets))) self._log(' deg\n') # Log mean azimuth and zenith angle self._log.parformat('Mean zenith angle') self._log('%.2f' % (sum(self._zeniths) / len(self._zeniths))) self._log(' deg\n') self._log.parformat('Mean azimuth angle') self._log('%.2f' % (sum(self._azimuths) / len(self._azimuths))) self._log(' deg\n') # Optionally log names of observations. Note that the set class # is used to extract all different observation names from the # list of observation names, and the set class is only available # from Python 2.4 on. if self._logExplicit() and sys.version_info >= (2, 4): obs_set = set(obs_names) for name in obs_set: self._log.parformat('"' + name + '"') self._log(str(obs_names.count(name))) self._log('\n') self._log('\n') # Log energy range self._log.header3('Energy range') self._log.parformat('Minimum energy') if self._ebounds.size() == 0: self._log('undefined') else: self._log(str(self._ebounds.emin())) self._log('\n') self._log.parformat('Maximum energy') if self._ebounds.size() == 0: self._log('undefined') else: self._log(str(self._ebounds.emax())) self._log('\n') # Log time range self._log.header3('Time range') self._log.parformat('Start (MJD)') self._log(str(self._gti.tstart().mjd())) self._log('\n') self._log.parformat('Stop (MJD)') self._log(str(self._gti.tstop().mjd())) self._log('\n') # Log ontime and livetime in different units self._log.parformat('Total ontime') self._log('%.2f s = %.2f min = %.2f h' % (ontime, ontime / 60., ontime / 3600.)) self._log('\n') self._log.parformat('Total livetime') self._log('%.2f s = %.2f min = %.2f h' % (livetime, livetime / 60.0, livetime / 3600.)) self._log('\n') # 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() # Initialise arrays to store certain values for reuse # Todo, think about using a python dictionary self._offsets = [] self._zeniths = [] self._azimuths = [] self._pnt_ra = [] self._pnt_dec = [] self._ebounds = gammalib.GEbounds() self._gti = gammalib.GGti() obs_names = [] # Initialise output to be filled ontime = 0.0 livetime = 0.0 n_events = 0 n_eventbins = 0 n_obs_binned = 0 n_obs_unbinned = 0 # Write header if self._logTerse(): self._log('\n') self._log.header1(gammalib.number('Observation', self.obs().size())) # Loop over observations for obs in self.obs(): # Skip non-CTA observations if not obs.classname() == 'GCTAObservation': self._log('Skipping ' + obs.instrument() + ' observation\n') continue # Use observed object as observation name if name is not given obs_name = obs.name() if obs_name == '': obs_name = obs.object() # Logging if self._logExplicit(): obs_id = obs.id() if obs_id != '': log_name = obs_name + ' (ID=' + obs_id + ')' else: log_name = obs_name self._log.header2(log_name) # Retrieve observation name obs_names.append(obs_name) # Retrieve energy boundaries obs_bounds = obs.events().ebounds() # Retrieve time interval obs_gti = obs.events().gti() # Compute mean time and dead time fraction in percent deadfrac = (1.0 - obs.deadc()) * 100.0 # Retrieve pointing and store Ra,Dec pnt_dir = obs.pointing().dir() self._pnt_ra.append(pnt_dir.ra_deg()) self._pnt_dec.append(pnt_dir.dec_deg()) # If avaliable append energy boundaries if obs_bounds.size() > 0: self._ebounds.append(obs_bounds.emin(), obs_bounds.emax()) # Append time interval self._gti.append(obs_gti.tstart(), obs_gti.tstop()) # Increment global livetime and ontime ontime += obs.ontime() livetime += obs.livetime() # Bookkeeping if obs.eventtype() == 'CountsCube': n_eventbins += obs.events().size() n_obs_binned += 1 is_binned = 'yes' is_what = 'Number of bins' else: n_events += obs.events().size() n_obs_unbinned += 1 is_binned = 'no' is_what = 'Number of events' self._log_value(gammalib.EXPLICIT, 'Binned', is_binned) self._log_value(gammalib.EXPLICIT, is_what, obs.events().size()) # Retrieve zenith and azimuth and store for later use zenith = obs.pointing().zenith() azimuth = obs.pointing().azimuth() self._zeniths.append(zenith) self._azimuths.append(azimuth) # Optionally compute offset with respect to target direction if self._compute_offset: offset = pnt_dir.dist_deg(self._obj_dir) self._offsets.append(offset) # Optionally log details if self._logExplicit(): # Log the observation energy range (if available) self._log.parformat('Energy range') if obs_bounds.size() == 0: self._log('undefined') else: self._log(str(obs_bounds.emin())) self._log(' - ') self._log(str(obs_bounds.emax())) self._log('\n') # Log observation time interval self._log.parformat('Time range (MJD)') if obs_gti.size() == 0: self._log('undefined') else: self._log(str(obs_gti.tstart().mjd())) self._log(' - ') self._log(str(obs_gti.tstop().mjd())) self._log('\n') # Log observation information self._log_value(gammalib.EXPLICIT, 'Ontime', '%.3f s' % obs.ontime()) self._log_value(gammalib.EXPLICIT, 'Livetime', '%.3f s' % obs.livetime()) self._log_value(gammalib.EXPLICIT, 'Deadtime fraction', '%.3f %%' % deadfrac) self._log_value(gammalib.EXPLICIT, 'Pointing', pnt_dir) # Optionally log offset with respect to target direction if self._compute_offset: self._log_value(gammalib.EXPLICIT, 'Offset from target', '%.2f deg' % offset) # Log Zenith and Azimuth angles self._log_value(gammalib.EXPLICIT, 'Zenith angle', '%.2f deg' % zenith) self._log_value(gammalib.EXPLICIT, 'Azimuth angle', '%.2f deg' % azimuth) # Write summary header self._log_header1(gammalib.NORMAL, 'Summary') # Log general summary self._log_header3(gammalib.NORMAL, 'Observations') self._log_value(gammalib.NORMAL, 'Unbinned observations', n_obs_unbinned) self._log_value(gammalib.NORMAL, 'Binned observations', n_obs_binned) self._log_header3(gammalib.NORMAL, 'Events') self._log_value(gammalib.NORMAL, 'Number of events', n_events) self._log_value(gammalib.NORMAL, 'Number of bins', n_eventbins) # Compute mean offset, azimuth and zenith angle if len(self._offsets) > 0: mean_offset = '%.2f deg' % (sum(self._offsets) / len(self._offsets)) else: mean_offset = 'Unknown' if len(self._zeniths) > 0: mean_zenith = '%.2f deg' % (sum(self._zeniths) / len(self._zeniths)) else: mean_zenith = 'Unknown' if len(self._azimuths) > 0: mean_azimuth = '%.2f deg' % (sum(self._azimuths) / len(self._azimuths)) else: mean_azimuth = 'Unknown' # Log mean offset, azimuth and zenith angle self._log_header3(gammalib.NORMAL, 'Pointings') self._log_value(gammalib.NORMAL, 'Mean offset angle', mean_offset) self._log_value(gammalib.NORMAL, 'Mean zenith angle', mean_zenith) self._log_value(gammalib.NORMAL, 'Mean azimuth angle', mean_azimuth) # Optionally log names of observations. Note that the set class is # used to extract all different observation names from the list of # observation names, and the set class is only available from # Python 2.4 on. if sys.version_info >= (2, 4): obs_set = set(obs_names) for name in obs_set: self._log_value(gammalib.EXPLICIT, '"' + name + '"', obs_names.count(name)) # Get energy boundary information if self._ebounds.size() == 0: min_value = 'undefined' max_value = 'undefined' else: min_value = str(self._ebounds.emin()) max_value = str(self._ebounds.emax()) # Log energy range self._log_header3(gammalib.NORMAL, 'Energy range') self._log_value(gammalib.NORMAL, 'Minimum energy', min_value) self._log_value(gammalib.NORMAL, 'Maximum energy', max_value) # Log time range mjd = '%.3f - %.3f' % (self._gti.tstart().mjd(), self._gti.tstop().mjd()) utc = '%s - %s' % (self._gti.tstart().utc(), self._gti.tstop().utc()) self._log_header3(gammalib.NORMAL, 'Time range') self._log_value(gammalib.NORMAL, 'MJD (days)', mjd) self._log_value(gammalib.NORMAL, 'UTC', utc) # Log ontime and livetime in different units on_time = '%.2f s = %.2f min = %.2f h' % \ (ontime, ontime/60., ontime/3600.) live_time = '%.2f s = %.2f min = %.2f h' % \ (livetime, livetime/60., livetime/3600.) self._log_value(gammalib.NORMAL, 'Total ontime', on_time) self._log_value(gammalib.NORMAL, 'Total livetime', live_time) # Return return
pnt = gammalib.GCTAPointing() pnt.dir(pntdir) obs.pointing(pnt) #Set ROI roi = gammalib.GCTARoi() instdir = gammalib.GCTAInstDir() instdir.dir(pntdir) roi.centre(instdir) roi.radius(rad) #Set GTI gti = gammalib.GGti() start = gammalib.GTime(tstart) stop = gammalib.GTime(tstart + duration) gti.append(start, stop) #Set Energy Boundaries ebounds = gammalib.GEbounds() e_min = gammalib.GEnergy(emin, 'TeV') e_max = gammalib.GEnergy(emax, 'TeV') ebounds.append(e_min, e_max) #Allocate event list events = gammalib.GCTAEventList(eventfile) obs.eventfile(eventfile) events.roi(roi) events.gti(gti)
def set(RA=83.63, DEC=22.01, tstart=0.0, duration=1800.0, deadc=0.95, emin=0.1, emax=100.0, rad=5.0, irf="cta_dummy_irf", caldb="$GAMMALIB/share/caldb/cta"): """ Create one CTA observation Copied from ctools/scripts/obsutils.py and modified a bit. """ # Allocate CTA observation obs = gammalib.GCTAObservation() # Set pointing direction pntdir = gammalib.GSkyDir() pntdir.radec_deg(RA, DEC) pnt = gammalib.GCTAPointing() pnt.dir(pntdir) obs.pointing(pnt) # Set ROI roi = gammalib.GCTARoi() instdir = gammalib.GCTAInstDir() instdir.dir(pntdir) roi.centre(instdir) roi.radius(rad) # Set GTI gti = gammalib.GGti() start = gammalib.GTime(tstart) stop = gammalib.GTime(tstart + duration) gti.append(start, stop) # Set energy boundaries ebounds = gammalib.GEbounds() e_min = gammalib.GEnergy() e_max = gammalib.GEnergy() e_min.TeV(emin) e_max.TeV(emax) ebounds.append(e_min, e_max) # Allocate event list events = gammalib.GCTAEventList() events.roi(roi) events.gti(gti) events.ebounds(ebounds) obs.events(events) # Set instrument response obs.response(irf, caldb) # Set ontime, livetime, and deadtime correction factor obs.ontime(duration) obs.livetime(duration * deadc) obs.deadc(deadc) # Return observation return obs
def show_residuals(obslist=None, emin=0.2, emax=20.0, ebins=20, npix=200, binsz=0.02, suffix=''): """ Show residuals for all OFF observations Parameters ---------- obslist : list of ints, optional Index of observations to stack emin : float, optional Minimum energy (TeV) emax : float, optional Maximum energy (TeV) ebins : int, optional Number of energy bins npix : int, optional Number of spatial pixels binsz : float, optional Spatial bin size suffix : str, optional Plot filename suffix """ # Set XML filename obsname = '$HESSDATA/obs/obs_off.xml' # Generate background lookup generate_background_lookup(obslist=obslist, suffix=suffix) # If observation list is specified and suffix is empty then build suffix if obslist != None and suffix == '': for obs in obslist: suffix += '_%2.2d' % obs # Set stacked cube filenames cntfile = 'off_stacked_counts%s.fits' % (suffix) modfile = 'off_stacked_model%s.fits' % (suffix) # If stacked cubes exist then load them if os.path.isfile(cntfile) and os.path.isfile(modfile): cntcube_stacked = gammalib.GCTAEventCube(cntfile) modcube_stacked = gammalib.GCTAEventCube(modfile) # ... otherwise generate them else: # Define counts and model cubes for stacking map = gammalib.GSkyMap('TAN', 'CEL', 0.0, 0.0, -binsz, binsz, npix, npix, ebins) ebds = gammalib.GEbounds(ebins, gammalib.GEnergy(emin, 'TeV'), gammalib.GEnergy(emax, 'TeV')) gti = gammalib.GGti(gammalib.GTime(0.0, 's'), gammalib.GTime(1.0, 's')) cntcube_stacked = gammalib.GCTAEventCube(map, ebds, gti) modcube_stacked = gammalib.GCTAEventCube(map, ebds, gti) # Load observations inobs = gammalib.GObservations(obsname) # Loop over runs in observations for i, run in enumerate(inobs): # If an observation list is defined then skip observation if it # is not in list if obslist != None: if i not in obslist: continue # Build observation container with single run obs = gammalib.GObservations() obs.append(run) # Select events obs = select_events(obs, emin=emin, emax=emax) # Generate background model models = get_bkg_model(obs, suffix=suffix) # Attach models to observation container obs.models(models) # Create counts cube cntcube = create_cntcube(obs, emin=emin, emax=emax, ebins=ebins, npix=npix, binsz=binsz) # Create model cube modcube = create_modcube(obs, cntcube) # Stack cubes cntcube_stacked = stack_cube(cntcube_stacked, cntcube) modcube_stacked = stack_cube(modcube_stacked, modcube) # Stop after first run #break # Save cubes cntcube_stacked.save(cntfile, True) modcube_stacked.save(modfile, True) # Plot stacked cubes plot(cntcube_stacked, modcube_stacked, suffix=suffix) plot_sectors(cntcube_stacked, modcube_stacked, suffix=suffix) plot_radial_profiles(cntcube_stacked, modcube_stacked, suffix=suffix) # Return return
def createobs(ra=86.171648, dec=-1.4774586, rad=5.0, emin=0.1, emax=100.0, duration=360000.0, deadc=0.95, irf="South_50h", caldb="prod2"): """ Create CTA observation. """ # Allocate CTA observation obs = gammalib.GCTAObservation() # Set calibration database db = gammalib.GCaldb() if (gammalib.dir_exists(caldb)): db.rootdir(caldb) else: db.open("cta", caldb) # Set pointing direction pntdir = gammalib.GSkyDir() pntdir.radec_deg(ra, dec) pnt = gammalib.GCTAPointing() pnt.dir(pntdir) obs.pointing(pnt) # Set ROI roi = gammalib.GCTARoi() instdir = gammalib.GCTAInstDir() instdir.dir(pntdir) roi.centre(instdir) roi.radius(rad) # Set GTI gti = gammalib.GGti() start = gammalib.GTime(0.0) stop = gammalib.GTime(duration) gti.append(start, stop) # Set energy boundaries ebounds = gammalib.GEbounds() e_min = gammalib.GEnergy() e_max = gammalib.GEnergy() e_min.TeV(emin) e_max.TeV(emax) ebounds.append(e_min, e_max) # Allocate event list events = gammalib.GCTAEventList() events.roi(roi) events.gti(gti) events.ebounds(ebounds) obs.events(events) # Set instrument response obs.response(irf, db) # Set ontime, livetime, and deadtime correction factor obs.ontime(duration) obs.livetime(duration*deadc) obs.deadc(deadc) # Return observation return obs