def print_values_gammalib(): """Print some Gammalib model values that can be used for unit tests. Gammalib uses normalised PDFs, i.e. eval() returns probability / steradian so that the integral is one. """ import numpy as np import gammalib # We need some dummy variables center = gammalib.GSkyDir() center.radec_deg(0, 0) energy = gammalib.GEnergy() time = gammalib.GTime() FWHM_TO_SIGMA = 1. / np.sqrt(8 * np.log(2)) g = gammalib.GModelSpatialRadialGauss( center, PIX_TO_DEG * FWHM_TO_SIGMA * GAUSS_FWHM) d = gammalib.GModelSpatialRadialDisk(center, PIX_TO_DEG * DISK_R0) s = gammalib.GModelSpatialRadialShell(center, PIX_TO_DEG * SHELL_R0, PIX_TO_DEG * SHELL_WIDTH) models = [('g', g), ('d', d), ('s', s)] for name, model in models: for theta in THETAS: theta_radians = np.radians(PIX_TO_DEG * theta) gammalib_value = model.eval(theta_radians, energy, time) sherpa_value = INTEGRAL * gammalib_value * np.radians( PIX_TO_DEG)**2 print name, theta, sherpa_value
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 show_events(events, xmlname, duration, emin, emax, ebins=30): """ Show events using matplotlib. """ # Create figure plt.figure(1) plt.title("MC simulated event spectrum (" + str(emin) + '-' + str(emax) + " TeV)") # Setup energy range covered by data ebds = gammalib.GEbounds(ebins, gammalib.GEnergy(emin, "TeV"), gammalib.GEnergy(emax, "TeV")) # Create energy axis energy = [] for i in range(ebds.size()): energy.append(ebds.elogmean(i).TeV()) # Fill histogram counts = [0.0 for i in range(ebds.size())] for event in events: index = ebds.index(event.energy()) counts[index] = counts[index] + 1.0 # Create error bars error = [math.sqrt(c) for c in counts] # Get model values sum = 0.0 models = gammalib.GModels(xmlname) m = models[0] model = [] t = gammalib.GTime() for i in range(ebds.size()): eval = ebds.elogmean(i) ewidth = ebds.emax(i) - ebds.emin(i) f = m.npred(eval, t, obs) * ewidth.MeV() * duration sum += f model.append(f) print(str(sum) + " events expected from spectrum (integration).") # Plot data plt.loglog(energy, counts, 'ro') plt.errorbar(energy, counts, error, fmt=None, ecolor='r') # Plot model plt.plot(energy, model, 'b-') # Set axes plt.xlabel("Energy (TeV)") plt.ylabel("Number of events") # Notify print("PLEASE CLOSE WINDOW TO CONTINUE ...") # Show plot plt.show() # Return return
def set_tmin_for_next_pointing(tmin, duration, array='South', sunzenith=105.0, moonzenith=90.0, skip_days=6.0): """ Set start time for next pointing Adds duration and 2 min for slew, and takes care of day and night. It is assumed that the night lasts from [0,10] and the day lasts from [10,24] Parameters ---------- tmin : float Start time of current pointing (sec) duration : float Duration of current pointing (sec) array : str, optional Array sunzenith : float, optional Sun zenith angle constraint (deg) moonzenith : float, optional Moon zenith angle constraint (deg) skip_days : float, optional Number of days to skip after Sun rise Returns ------- tmin : float Start time of new pointing """ # Set time tref = gammalib.GTimeReference(51544.5, 's', 'TT', 'LOCAL') time = gammalib.GTime(tmin, tref) # Add duration and 2 min for slew time += duration + 120.0 # If the Sun or the Moon is above zenith angle limit then increment # time until the Sun and the Moon is again below the limit add_days = skip_days while True: sun = zenith_sun(time, array=array) moon = zenith_moon(time, array=array) if sun < sunzenith and add_days > 0.0: time += 86400.0 * add_days add_days = 0.0 if sun < sunzenith or moon < moonzenith: time += 240.0 # Add 4 min and check again else: break # Convert back to seconds tmin = time.convert(tref) # Return start time return tmin
def plot_lookup(filename, ax, nengs=300, nthetas=300): """ Plot lookup table Parameters ---------- filename : str Lookup table filename ax : figure Subplot nengs : int, optional Number of energies nthetas : int, optional Number of offset angles """ # Load lookup table lookup = gammalib.GCTAModelSpatialLookup(filename) table = lookup.table() # Get boundaries axis_eng = table.axis('ENERG') axis_theta = table.axis('THETA') emin = table.axis_lo(axis_eng, 0) emax = table.axis_hi(axis_eng, table.axis_bins(axis_eng) - 1) tmin = table.axis_lo(axis_theta, 0) tmax = table.axis_hi(axis_theta, table.axis_bins(axis_theta) - 1) # Use log energies emin = math.log10(emin) emax = math.log10(emax) # Set axes denergy = (emax - emin) / (nengs - 1) dtheta = (tmax - tmin) / (nthetas - 1) logenergies = [emin + i * denergy for i in range(nengs)] thetas = [tmax - i * dtheta for i in range(nthetas)] # Initialise image image = [] # Set event time time = gammalib.GTime() # Loop over offset angles for theta in thetas: # Set event direction dir = gammalib.GCTAInstDir(theta * gammalib.deg2rad, 0.0) # Initialise row row = [] # Loop over energies for logenergy in logenergies: # Set event energy energy = gammalib.GEnergy() energy.log10TeV(logenergy) # Get lookup table value value = lookup.eval(dir, energy, time) # Append value row.append(value) # Append row image.append(row) # Plot image c = ax.imshow(image, extent=[emin, emax, tmin, tmax], cmap=plt.get_cmap('jet'), aspect=0.8) cbar = plt.colorbar(c, orientation='vertical', shrink=0.7) cbar.set_label('sr$^{-1}$', labelpad=-22, y=-0.05, rotation=0) # Plot title and axis ax.set_xlabel('log10(E/TeV)', fontsize=12) ax.set_ylabel('Offset angle (deg)', fontsize=12) # 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
shutil.copyfile(halo_fits_tmp2, halo_fits) printstat('halo_fits: ' + os.path.basename(halo_fits)) spatial = GModelSpatialDiffuseMap(halo_fits) spatial['Normalization'].fix() jfactor = veripy.read_halo_jfactor_fits(halo_fits) printstat( os.path.basename(halo_fits) + ' loaded into GModelSpatialDiffuseMap()') amin, amax, anpts = 1e-2, 8, 80 adelta_log = (log10(amax) - log10(amin)) / (anpts - 1) angs = [pow(10, log10(amin) + i * adelta_log) for i in range(anpts)] photon = gammalib.GPhoton() photon.energy(GEnergy(1, 'TeV')) photon.time(gammalib.GTime(0, 'sec')) svals = [[] for j in range(4)] for j in range(4): for i in range(anpts): skydir = gammalib.GSkyDir() if j == 0: skydir.lb_deg(sgra.l_deg() + angs[i], sgra.b_deg()) elif j == 1: skydir.lb_deg(sgra.l_deg() - angs[i], sgra.b_deg()) elif j == 2: skydir.lb_deg(sgra.l_deg(), sgra.b_deg() + angs[i]) elif j == 3: skydir.lb_deg(sgra.l_deg(), sgra.b_deg() - angs[i]) photon.dir(skydir) val = spatial.eval(photon) svals[j] += [val] fig = plt.figure() fax = fig.add_subplot(111) #for j in range(4) :
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 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 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 modmap(obs, eref=0.1, proj="TAN", coord="GAL", xval=0.0, yval=0.0, \ binsz=0.05, nxpix=200, nypix=200, \ outname="modmap.fits"): """ Make model map for a given reference energy by combining all observations. The model map will be evaluated for a given reference energy 'eref' and will be given in units of [counts/(sr MeV s)]. Parameters: obs - Observation container Keywords: eref - Reference energy for which model is created [TeV] (default: 0.1) proj - Projection type (e.g. TAN, CAR, STG, ...) (default: TAN) coord - Coordinate type (GAL, CEL) (default: GAL) xval - Reference longitude value [deg] (default: 0.0) yval - Reference latitude value [deg] (default: 0.0) binsz - Pixel size [deg/pixel] (default: 0.05) nxpix - Number of pixels in X direction (default: 200) nypix - Number of pixels in Y direction (default: 200) outname - Model map FITS filename (default: modmap.fits) """ # Allocate model map map = gammalib.GSkyMap(proj, coord, xval, yval, -binsz, binsz, nxpix, nypix, 1) # Set reference energy, time and direction. The time is not initialised and is # in fact not used (as the IRF is assumed to be time independent for now). # The sky direction is set later using the pixel values. energy = gammalib.GEnergy() time = gammalib.GTime() instdir = gammalib.GCTAInstDir() energy.TeV(eref) # Loop over all map pixels for pixel in range(map.npix()): # Get sky direction skydir = map.inx2dir(pixel) instdir.dir(skydir) # Create event atom for map pixel atom = gammalib.GCTAEventAtom() atom.dir(instdir) atom.energy(energy) atom.time(time) # Initialise model value value = 0.0 # Loop over all observations for run in obs: value += obs.models().eval(atom, run) # Set map value map[pixel] = value # Save sky map map.save(outname, True) # Return model map return map
from astropy.io import fits import os from utils import * # convert binary population model from txt format provided by Guillaume # to gammalib format # some additional binary population parameters not in the files (see README in binpop) # spectral index gamma = 2.5 # maximum latitude bmax = 2. # threshold energy for lightcurve (MeV) eref = 1.e6 # reference time for phasogram t0 = gammalib.GTime() t0.mjd(51544.5) def phasogram_file(phases, fname, outdir): # derive normalization from flux norm = phases[:, 1] / np.max(phases[:, 1]) # create fits columns and put them into table phase = fits.Column(name='PHASE', format='D', array=phases[:, 0]) norm = fits.Column(name='NORM', format='D', array=norm) tbhdu = fits.BinTableHDU.from_columns([phase, norm]) tbhdu.verify('fix') # write file tbhdu.writeto(fname, overwrite=True)
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
for ra in ra_list: dec = dec_list[number - 1] filename = 'events_' + 'LMC_' + modelname + '_KSP' + '0' + str( number) + '.fits' eventfile = gammalib.GFilename(filename) sim = ctools.ctobssim() sim["inmodel"] = model sim["seed"] = number + rndseed sim["outevents"] = filename sim["caldb"] = caldb_ sim["irf"] = irf_ sim["ra"] = ra sim["dec"] = dec sim["rad"] = rad sim["tmin"] = gammalib.GTime(tstart) sim["tmax"] = gammalib.GTime(tstart + duration) sim["emin"] = emin sim["emax"] = emax sim["debug"] = True sim.execute() #STORE THE OBSERVATION IN GObservations Class and store it in the .xml output file. #Allocate CTA observation obs = gammalib.GCTAObservation() #Set pointing direction pntdir = gammalib.GSkyDir() pntdir.radec_deg(ra, dec) pnt = gammalib.GCTAPointing()
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 _get_sensitivity(self, emin, emax, bkg_model, full_model): """ Determine sensitivity for given observations. Args: emin: Minimum energy for fitting and flux computation emax: Maximum energy for fitting and flux computation bkg_model: Background model full_model: Source model Returns: Result dictionary """ # Set TeV->erg conversion factor tev2erg = 1.6021764 # Set energy boundaries self._set_obs_ebounds(emin, emax) # Determine energy boundaries from first observation in the container loge = math.log10(math.sqrt(emin.TeV() * emax.TeV())) e_mean = math.pow(10.0, loge) erg_mean = e_mean * tev2erg # Compute Crab unit (this is the factor with which the Prefactor needs # to be multiplied to get 1 Crab crab_flux = self._get_crab_flux(emin, emax) src_flux = full_model[self._srcname].spectral().flux(emin, emax) crab_unit = crab_flux / src_flux # Write header if self._logTerse(): self._log("\n") self._log.header2("Energies: " + str(emin) + " - " + str(emax)) self._log.parformat("Crab flux") self._log(crab_flux) self._log(" ph/cm2/s\n") self._log.parformat("Source model flux") self._log(src_flux) self._log(" ph/cm2/s\n") self._log.parformat("Crab unit factor") self._log(crab_unit) self._log("\n") # Initialise loop crab_flux_value = [] photon_flux_value = [] energy_flux_value = [] sensitivity_value = [] iterations = 0 test_crab_flux = 0.1 # Initial test flux in Crab units (100 mCrab) # Loop until we break while True: # Update iteration counter iterations += 1 # Write header if self._logExplicit(): self._log.header2("Iteration " + str(iterations)) # Set source model. crab_prefactor is the Prefactor that # corresponds to 1 Crab src_model = full_model.copy() crab_prefactor = src_model[self._srcname]['Prefactor'].value() * \ crab_unit src_model[self._srcname]['Prefactor'].value(crab_prefactor * \ test_crab_flux) self._obs.models(src_model) # Simulate events sim = obsutils.sim(self._obs, nbins=self._enumbins, seed=iterations, binsz=self._binsz, npix=self._npix, log=self._log_clients, debug=self._debug, edisp=self._edisp) # Determine number of events in simulation nevents = 0.0 for run in sim: nevents += run.events().number() # Write simulation results if self._logExplicit(): self._log.header3("Simulation") self._log.parformat("Number of simulated events") self._log(nevents) self._log("\n") # Fit background only sim.models(bkg_model) like = obsutils.fit(sim, log=self._log_clients, debug=self._debug, edisp=self._edisp) result_bgm = like.obs().models().copy() LogL_bgm = like.opt().value() npred_bgm = like.obs().npred() # Assess quality based on a comparison between Npred and Nevents quality_bgm = npred_bgm - nevents # Write background fit results if self._logExplicit(): self._log.header3("Background model fit") self._log.parformat("log likelihood") self._log(LogL_bgm) self._log("\n") self._log.parformat("Number of predicted events") self._log(npred_bgm) self._log("\n") self._log.parformat("Fit quality") self._log(quality_bgm) self._log("\n") # Write model fit results if self._logExplicit(): for model in result_bgm: self._log.parformat("Model") self._log(model.name()) self._log("\n") for par in model: self._log(str(par) + "\n") # Fit background and test source sim.models(src_model) like = obsutils.fit(sim, log=self._log_clients, debug=self._debug, edisp=self._edisp) result_all = like.obs().models().copy() LogL_all = like.opt().value() npred_all = like.obs().npred() ts = 2.0 * (LogL_bgm - LogL_all) # Assess quality based on a comparison between Npred and Nevents quality_all = npred_all - nevents # Write background and test source fit results if self._logExplicit(): self._log.header3("Background and test source model fit") self._log.parformat("Test statistics") self._log(ts) self._log("\n") self._log.parformat("log likelihood") self._log(LogL_all) self._log("\n") self._log.parformat("Number of predicted events") self._log(npred_all) self._log("\n") self._log.parformat("Fit quality") self._log(quality_all) self._log("\n") # for model in result_all: self._log.parformat("Model") self._log(model.name()) self._log("\n") for par in model: self._log(str(par) + "\n") # Start over if TS was non-positive if ts <= 0.0: if self._logExplicit(): self._log("Non positive TS. Start over.\n") continue # Get fitted Crab, photon and energy fluxes crab_flux = result_all[self._srcname]['Prefactor'].value() / \ crab_prefactor #crab_flux_err = result_all[self._srcname]['Prefactor'].error() / \ # crab_prefactor photon_flux = result_all[self._srcname].spectral().flux(emin, emax) energy_flux = result_all[self._srcname].spectral().eflux( emin, emax) # Compute differential sensitivity in unit erg/cm2/s energy = gammalib.GEnergy(e_mean, "TeV") time = gammalib.GTime() sensitivity = result_all[self._srcname].spectral().eval(energy, time) * \ e_mean*erg_mean * 1.0e6 # Compute flux correction factor based on average TS correct = 1.0 if ts > 0: correct = math.sqrt(self._ts_thres / ts) # Compute extrapolated fluxes crab_flux = correct * crab_flux photon_flux = correct * photon_flux energy_flux = correct * energy_flux sensitivity = correct * sensitivity crab_flux_value.append(crab_flux) photon_flux_value.append(photon_flux) energy_flux_value.append(energy_flux) sensitivity_value.append(sensitivity) # Write background and test source fit results if self._logExplicit(): self._log.parformat("Photon flux") self._log(photon_flux) self._log(" ph/cm2/s\n") self._log.parformat("Energy flux") self._log(energy_flux) self._log(" erg/cm2/s\n") self._log.parformat("Crab flux") self._log(crab_flux * 1000.0) self._log(" mCrab\n") self._log.parformat("Differential sensitivity") self._log(sensitivity) self._log(" erg/cm2/s\n") for model in result_all: self._log.parformat("Model") self._log(model.name()) self._log("\n") for par in model: self._log(str(par) + "\n") elif self._logTerse(): self._log.parformat("Iteration " + str(iterations)) self._log("TS=") self._log(ts) self._log(" ") self._log("corr=") self._log(correct) self._log(" ") self._log(photon_flux) self._log(" ph/cm2/s = ") self._log(energy_flux) self._log(" erg/cm2/s = ") self._log(crab_flux * 1000.0) self._log(" mCrab = ") self._log(sensitivity) self._log(" erg/cm2/s\n") # Compute sliding average of extrapolated fitted prefactor, # photon and energy flux. This damps out fluctuations and # improves convergence crab_flux = 0.0 photon_flux = 0.0 energy_flux = 0.0 sensitivity = 0.0 num = 0.0 for k in range(self._num_avg): inx = len(crab_flux_value) - k - 1 if inx >= 0: crab_flux += crab_flux_value[inx] photon_flux += photon_flux_value[inx] energy_flux += energy_flux_value[inx] sensitivity += sensitivity_value[inx] num += 1.0 crab_flux /= num photon_flux /= num energy_flux /= num sensitivity /= num # Compare average flux to last average if iterations > self._num_avg: if test_crab_flux > 0: ratio = crab_flux / test_crab_flux # We have 2 convergence criteria: # 1. The average flux does not change # 2. The flux correction factor is small if ratio >= 0.99 and ratio <= 1.01 and \ correct >= 0.9 and correct <= 1.1: if self._logTerse(): self._log(" Converged (" + str(ratio) + ")\n") break else: if self._logTerse(): self._log(" Flux is zero.\n") break # Use average for next iteration test_crab_flux = crab_flux # Exit loop if number of trials exhausted if (iterations >= self._max_iter): if self._logTerse(): self._log(" Test ended after " + str(self._max_iter) + " iterations.\n") break # Write fit results if self._logTerse(): self._log.header3("Fit results") self._log.parformat("Test statistics") self._log(ts) self._log("\n") self._log.parformat("Photon flux") self._log(photon_flux) self._log(" ph/cm2/s\n") self._log.parformat("Energy flux") self._log(energy_flux) self._log(" erg/cm2/s\n") self._log.parformat("Crab flux") self._log(crab_flux * 1000.0) self._log(" mCrab\n") self._log.parformat("Differential sensitivity") self._log(sensitivity) self._log(" erg/cm2/s\n") self._log.parformat("Number of simulated events") self._log(nevents) self._log("\n") self._log.header3("Background and test source model fitting") self._log.parformat("log likelihood") self._log(LogL_all) self._log("\n") self._log.parformat("Number of predicted events") self._log(npred_all) self._log("\n") for model in result_all: self._log.parformat("Model") self._log(model.name()) self._log("\n") for par in model: self._log(str(par) + "\n") self._log.header3("Background model fit") self._log.parformat("log likelihood") self._log(LogL_bgm) self._log("\n") self._log.parformat("Number of predicted events") self._log(npred_bgm) self._log("\n") for model in result_bgm: self._log.parformat("Model") self._log(model.name()) self._log("\n") for par in model: self._log(str(par) + "\n") # Restore energy boundaries of observation container for i, obs in enumerate(self._obs): obs.events().ebounds(self._obs_ebounds[i]) # Store result result = {'loge': loge, 'emin': emin.TeV(), 'emax': emax.TeV(), \ 'crab_flux': crab_flux, 'photon_flux': photon_flux, \ 'energy_flux': energy_flux, \ 'sensitivity': sensitivity} # Return result return result
thiseref = args.mass / 4.0 e_ref = gammalib.GEnergy(thiseref, 'TeV') e_min = gammalib.GEnergy(args.emin, 'TeV') e_max = gammalib.GEnergy(args.emax, 'TeV') # Get expected dmflux at reference energy # for all sources in Models theo_flux = 0.0 for nameSource in nameSources: spec = models[nameSource].spectral() flux = spec.eval(e_ref, gammalib.GTime()) theo_flux += flux print('\t* dF/dE(@ {:.2f} TeV): {:.3e} ph/(MeV cm**2 s)'.format( thiseref, theo_flux)) # Creating th fits file to save all the relevant results dmfits = gammalib.GFits() # Creating table with number of rows equal to the number of sims table = gammalib.GFitsBinTable(args.nsims) # Creating columns for every parameter to save col_runID = gammalib.GFitsTableShortCol('RunID', args.nsims) col_events = gammalib.GFitsTableDoubleCol('CubeEvents', args.nsims) # col_oevents = gammalib.GFitsTableDoubleCol( 'ObsEvents' , args.nsims )
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 _background_spectrum(self, run, prefactor, index, emin=0.01, emax=100.0): # Handle constant spectral model if index == 0.0 and self._bkgpars <= 1: spec = gammalib.GModelSpectralConst() spec['Normalization'].min(prefactor / self._bkg_range_factor) spec['Normalization'].max(prefactor * self._bkg_range_factor) spec['Normalization'].value(prefactor) if self._bkgpars == 0: spec['Normalization'].fix() else: spec['Normalization'].free() else: # Create power law model if self._bkgpars <= 2: e = gammalib.GEnergy(1.0, 'TeV') spec = gammalib.GModelSpectralPlaw(prefactor, index, e) # Set parameter ranges spec[0].min(prefactor / self._bkg_range_factor) spec[0].max(prefactor * self._bkg_range_factor) spec[1].scale(1) spec[1].min(-5.0) spec[1].max(5.0) # Set number of free parameters if self._bkgpars == 0: spec[0].fix() spec[1].fix() elif self._bkgpars == 1: spec[0].free() spec[1].fix() else: spec[0].free() spec[1].free() else: # Create reference powerlaw plaw = gammalib.GModelSpectralPlaw( prefactor, index, gammalib.GEnergy(1.0, 'TeV')) # Create spectral model and energy values spec = gammalib.GModelSpectralNodes() bounds = gammalib.GEbounds(self._bkgpars, gammalib.GEnergy(emin, 'TeV'), gammalib.GEnergy(emax, 'TeV'), True) for i in range(bounds.size()): energy = bounds.elogmean(i) value = plaw.eval(energy, gammalib.GTime()) spec.append(energy, value) for par in spec: if 'Energy' in par.name(): par.fix() elif 'Intensity' in par.name(): value = par.value() par.scale(value) par.min(value / self._bkg_range_factor) par.max(value * self._bkg_range_factor) # Return spectrum return spec
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
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) events.ebounds(ebounds)
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 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 schedule_observations_v3(obsdef, tstart, dl_min=1.0, dl_max=5.0, array='South', skip_days=6.0, dzenith_max=5.0): """ Schedule observations Parameters ---------- obsdef : list of dict Observation definition tstart : float Start time (s) dl_min : float, optional Minimum longitude step (deg) dl_max : float, optional Maximum longitude step (deg) array : string Array site ('South' or 'North') skip_days : float, optional Number of days to skip after Sun rise Returns ------- obsdef : list of dict Scheduled observation definition """ # Initialise statistics nobs = len(obsdef) last_lon = 1000.0 last_lat = 0.0 lon_min_step = dl_min lon_max_step = dl_max n_blocked = 0 # Initialise time time = set_tmin_for_next_pointing(tstart, 0.0, array=array, skip_days=skip_days) # Initialise scheduled observation definitions scheduled_obsdef = [] # Schedule observations until all are treated while len(scheduled_obsdef) < nobs: # Find next valid observation with smallest zenith angle max_zenith = 0.0 min_zenith = 180.0 min_dzenith = 180.0 for obs in obsdef: # Consider next non-scheduled observation if not obs['scheduled']: # If latitude is comparable then skip observation. This leads # to a toggle between the positive and negative latitudes of # the two-row pattern if abs(obs['lat'] - last_lat) < 0.1: continue # If longitude difference is smaller than minimum longitude # step then skip observation if last_lon != 1000.0: if obs['lon'] - last_lon < lon_min_step: continue # If longitude difference is larger than maximum longitude # step the skip step if last_lon != 1000.0: if obs['lon'] - last_lon > lon_max_step: continue # Compute zenith angle dir = gammalib.GSkyDir() dir.lb_deg(obs['lon'], obs['lat']) tref = gammalib.GTimeReference(51544.5, 's', 'TT', 'LOCAL') gtime = gammalib.GTime(time, tref) zenith = zenith_dir(gtime, dir, array=array) # Compute zenith distance from culmination dzenith = zenith - obs['best_zenith'] # If zenith distance from culmination is worse by dzenith_max # deg then skip pointing if dzenith > dzenith_max: continue # Keep pointing with smallest distance from culmination if dzenith < min_dzenith: min_dzenith = dzenith min_zenith = zenith max_zenith = obs['maxzenith'] min_obs = obs # If an observation with an acceptable zenith angle was found then # use it if min_dzenith < dzenith_max: # Set time and duration min_obs['tmin'] = time # Set zenith angle min_obs['zenith'] = min_zenith # Assign IRF zenith if min_zenith < 30.0: irfz = 20 elif min_zenith < 50.0: irfz = 40 else: irfz = 60 irf = '{}_z{}_50h'.format(array, irfz) # Set IRF information min_obs['irf'] = irf # Schedule observation scheduled_obsdef.append(min_obs) # Update last pointing last_lon = min_obs['lon'] last_lat = min_obs['lat'] # Dump gtime = gammalib.GTime(time, tref) print('%8.3f %8.3f %8.3f %4d/%4d %s %s' % (min_obs['lon'], min_obs['lat'], min_zenith, len(scheduled_obsdef), nobs, gtime.utc(), min_obs['name'])) # Signal that observation was scheduled min_obs['scheduled'] = True # ... otherwise remove the longitude and latitude constraints else: # Remove constraints last_lon = 1000.0 last_lat = 0.0 # Log number of blocks n_blocked += 1 # If blocked for more than 5000 iterations signal if n_blocked > 5000: print('WARNING: Scheduling blocked') for obs in obsdef: if not obs['scheduled']: print('- %s %.2f %.2f %.2f %.2f' % (obs['name'], obs['lon'], obs['lat'], obs['best_zenith'], obs['maxzenith'])) break # Increment time for next pointing time = set_tmin_for_next_pointing(time, obs_time * 3600.0, array=array, skip_days=skip_days) # Return scheduled observation return scheduled_obsdef