Beispiel #1
0
    def _get_parameters(self):
        """
        Get parameters from parfile
        """
        # Initialise observation container if it is currently empty
        if self.obs().size() == 0:

            # If an observation definition file was provided then load it,
            # otherwise build a single observation with response information
            if self['inobs'].is_valid():
                self.obs(gammalib.GObservations(self['inobs'].filename()))
            else:
                cta = gammalib.GCTAObservation()
                caldb = gammalib.GCaldb('cta', self['caldb'].string())
                rsp = gammalib.GCTAResponseIrf(self['irf'].string(), caldb)
                cta.response(rsp)
                self.obs().append(cta)

        # Query input parameters
        self['emin'].real()
        self['emax'].real()
        self['aeffthres'].real()
        self['bkgthres'].real()

        # Query ahead output model filename
        if self._read_ahead():
            self['outfile'].filename()

        #  Write input parameters into logger
        self._log_parameters(gammalib.TERSE)

        # Return
        return
Beispiel #2
0
    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()

        # Get the calibration database
        caldb = gammalib.GCaldb()

        # Extract mission names from the calibration database
        missions = self._get_missions(caldb)

        # Loop over missions
        for mission in missions:

            # Skip all non-CTA instruments
            if mission != 'cta':
                continue

            # Write mission into logger
            self._log_header1(gammalib.TERSE, 'Mission: ' + mission)

            # Extract instruments
            instruments = self._get_instruments(caldb, mission)

            # Loop over instruments
            for instrument in instruments:

                # Write instrument into logger
                self._log_header3(
                    gammalib.TERSE,
                    'Response functions in database "' + instrument + '"')

                # Open calibration index file and retrieve calibrations
                filename = '/data/' + mission + '/' + instrument + '/caldb.indx'
                cifname = caldb.rootdir() + filename
                fits = gammalib.GFits(cifname)
                cif = fits['CIF']
                caltable = cif['CAL_CBD']

                # Extract response names
                names = self._get_response_names(caltable)

                # Print response name
                if self._logTerse():
                    for name in names:
                        self._log(name + '\n')
                    self._log('\n')

        # Return
        return
Beispiel #3
0
    def _make_dirs(self):
        """
        Make CALDB directories.
        """
        # Write header into logger
        if self._logTerse():
            self._log("\n")
            self._log.header2("Creating directory structure")

        # Create calibration database        
        caldb = gammalib.GCaldb(self["rootdir"].string())
        
        # Set calibration directory 
        self._cal_dir  = "data"
        self._cal_dir += "/"+self._mission.lower()
        self._cal_dir += "/"+self._caldb.lower()
        self._cal_dir += "/bcf/"+self["irf"].string()
        
        # Set absolute path
        self._base_dir = caldb.rootdir() +"/data"
        self._base_dir += "/"+self._mission.lower()
        self._base_dir += "/"+self._caldb.lower()
        
        # Set directory for irf file
        self._rsp_dir = caldb.rootdir() + "/" + self._cal_dir

        # Log resulting FITS table
        if self._logNormal():
            self._log(gammalib.parformat("Calibration directory"))
            self._log(self._cal_dir)
            self._log("\n")
            self._log(gammalib.parformat("Base directory"))
            self._log(self._base_dir)
            self._log("\n")
            if not os.path.isdir(self._rsp_dir):
                self._log(gammalib.parformat("IRF directory"))
            else:
                self._log(gammalib.parformat("IRF directory (existing)"))
            self._log(self._rsp_dir)
            self._log("\n")
        
        # Create IRF directory is it does not yet exist
        if not os.path.isdir(self._rsp_dir):
            os.makedirs(self._rsp_dir)

        # Return
        return
Beispiel #4
0
def show_irf():
    """
    Show Instrument Response Function
    """
    # Set usage string
    usage = 'show_irf.py [-p plotfile] caldb irf'

    # Set default options
    options = [{'option': '-p',    'value': ''},
               {'option': '-emin', 'value': None},
               {'option': '-emax', 'value': None},
               {'option': '-tmin', 'value': None},
               {'option': '-tmax', 'value': None}]

    # Get arguments and options from command line arguments
    args, options = cscripts.ioutils.get_args_options(options, usage)

    # Extract script parameters from options
    plotfile = options[0]['value']
    emin     = options[1]['value']
    emax     = options[2]['value']
    tmin     = options[3]['value']
    tmax     = options[4]['value']

    # Convert limits to float
    if emin != None:
        emin = float(emin)
    if emax != None:
        emax = float(emax)
    if tmin != None:
        tmin = float(tmin)
    if tmax != None:
        tmax = float(tmax)

    # Get IRF
    caldb = gammalib.GCaldb('cta', args[0])
    irf   = gammalib.GCTAResponseIrf(args[1], caldb)
    
    # Plot IRF
    plot_irf(irf, emin, emax, tmin, tmax, plotfile)

    # Return
    return
Beispiel #5
0
    def _make_dirs(self):
        """
        Make CALDB directories
        """
        # Write header into logger
        self._log_header2(gammalib.TERSE, 'Creating directory structure')

        # Create calibration database
        caldb = gammalib.GCaldb(self['rootdir'].string())

        # Set calibration directory
        self._cal_dir = 'data'
        self._cal_dir += '/' + self._mission.lower()
        self._cal_dir += '/' + self._caldb.lower()
        self._cal_dir += '/bcf/' + self['irf'].string()

        # Set absolute path
        self._base_dir = caldb.rootdir() + '/data'
        self._base_dir += '/' + self._mission.lower()
        self._base_dir += '/' + self._caldb.lower()

        # Set directory for irf file
        self._rsp_dir = caldb.rootdir() + '/' + self._cal_dir

        # Log resulting FITS table
        self._log_value(gammalib.NORMAL, 'Calibration directory',
                        self._cal_dir)
        self._log_value(gammalib.NORMAL, 'Base directory', self._base_dir)
        if not os.path.isdir(self._rsp_dir):
            name = 'IRF directory'
        else:
            name = 'IRF directory (existing)'
        self._log_value(gammalib.NORMAL, name, self._rsp_dir)

        # Create IRF directory is it does not yet exist
        if not os.path.isdir(self._rsp_dir):
            os.makedirs(self._rsp_dir)

        # Return
        return
Beispiel #6
0
def show_one_response(rspname, dbname, name, rootdir=None, color='r'):
    """
    Show one response.

    Parameters
    ----------
    rspname : str
        Response name
    dbname : str
        Database name
    name : str
        Name of the response function
    rootdir : str, optional
        Response root directory
    color : str, optional
        Color for plot
    """
    # Set-up calibration database
    caldb = gammalib.GCaldb()
    if rootdir != None:
        caldb.rootdir(rootdir)
    if gammalib.dir_exists(dbname):
        caldb.rootdir(dbname)
    else:
        caldb.open('cta', dbname)

    # Load response function
    rsp = gammalib.GCTAResponseIrf(rspname, caldb)

    # Show effective area
    show_one_effective_area(rsp, name, color=color)

    # Show background rate
    show_one_background_rate(rsp, name, color=color)

    # Show sensitivity
    show_one_sensitivity(rsp, name, color=color)

    # Return
    return
Beispiel #7
0
    def _check_response(self, caldb, irf):
        """
        Check response
        """
        # Open calibration database
        db = gammalib.GCaldb('caldb')
        db.open('cta', caldb)

        # Get filenames of response components
        expr = 'NAME(' + irf + ')'
        aeff = gammalib.GFilename(db.filename('', '', 'EFF_AREA', '', '',
                                              expr))
        psf = gammalib.GFilename(db.filename('', '', 'RPSF', '', '', expr))
        edisp = gammalib.GFilename(db.filename('', '', 'EDISP', '', '', expr))
        bkg = gammalib.GFilename(db.filename('', '', 'BKG', '', '', expr))

        # Check whether files exist
        self.test_assert(aeff.exists(), 'Effective area file exists')
        self.test_assert(psf.exists(), 'Point spread function file exists')
        self.test_assert(edisp.exists(), 'Energy dispersion file exists')
        self.test_assert(bkg.exists(), 'Background file exists')

        # Return
        return
Beispiel #8
0
    def _test_python(self):
        """
        Test ctselect from Python
        """
        # Allocate empty ctselect tool
        select = ctools.ctselect()

        # Check that empty ctselect tool holds an empty observation
        self._check_obs(select.obs(), nobs=0)

        # Check that saving does nothing
        select['outobs'] = 'ctselect_py0.fits'
        select['logfile'] = 'ctselect_py0.log'
        select.logFileOpen()
        select.save()
        self.test_assert(not os.path.isfile('ctselect_py0.fits'),
                         'Check that no event list has been created')

        # Check that clearing does not lead to an exception or segfault
        select.clear()

        # Now set ctselect parameters
        select['inobs'] = self._events
        select['rad'] = 1.0
        select['tmin'] = '2020-01-01T00:01:10'
        select['tmax'] = '2020-01-01T00:03:40'
        select['emin'] = 2.0
        select['emax'] = 80.0
        select['outobs'] = 'ctselect_py1.fits'
        select['logfile'] = 'ctselect_py1.log'
        select['chatter'] = 2

        # Run ctselect tool
        select.logFileOpen()  # Make sure we get a log file
        select.run()
        select.save()

        # Check result file
        self._check_result_file('ctselect_py1.fits')

        # Copy ctselect tool
        cpy_select = select.copy()

        # Check observation of ctselect copy
        self._check_obs(cpy_select.obs())

        # Execute copy of ctselect tool again, now with a higher chatter
        # level than before and without any selection. Since the tools
        # still holds the same selected observation container from before
        # the number of events will be identical.
        cpy_select['rad'] = 'NONE'
        cpy_select['tmin'] = 'NONE'
        cpy_select['tmax'] = 'NONE'
        cpy_select['emin'] = 'NONE'
        cpy_select['emax'] = 'NONE'
        cpy_select['outobs'] = 'ctselect_py2.fits'
        cpy_select['logfile'] = 'ctselect_py2.log'
        cpy_select['chatter'] = 3
        cpy_select['publish'] = True
        cpy_select.logFileOpen()  # Needed to get a new log file
        cpy_select.execute()

        # Check result file
        self._check_result_file('ctselect_py2.fits')

        # Execute again the copy of ctselect tool again, now manually specifying the
        # RoI centres. We also set the minimum values
        # to valid event selections, but since the maximum values are still
        # 'NONE', no event selections should occur.
        cpy_select['usepnt'] = False
        cpy_select['ra'] = 83.63
        cpy_select['dec'] = 22.01
        cpy_select['tmin'] = '2020-01-01T00:01:10'
        cpy_select['emin'] = 2.0
        cpy_select['usethres'] = 'USER'
        cpy_select['outobs'] = 'ctselect_py3.fits'
        cpy_select['logfile'] = 'ctselect_py3.log'
        cpy_select['chatter'] = 4
        cpy_select.logFileOpen()  # Needed to get a new log file
        cpy_select.execute()

        # Check result file
        self._check_result_file('ctselect_py3.fits')

        # Now clear copy of ctselect tool
        cpy_select.clear()

        # Check that cleared ctselect tool holds no observations and events
        self._check_obs(cpy_select.obs(), nobs=0)

        # Get mixed observation container
        obs = self._obs_mixed()

        # Attach response function to first observation which is the
        # event list. This is necessary to run the ctselect tool with
        # "DEFAULT" thresholds.
        obs[0].response('South_0.5h', gammalib.GCaldb('cta', 'prod2'))

        # Setup ctselect tool from observation container. An energy range
        # beyond the energies covered in the event file is specified, hence
        # an empty event list will be saved.
        select = ctools.ctselect(obs)
        select['rad'] = 1.0
        select['tmin'] = '2020-01-01T00:01:10'
        select['tmax'] = '2020-01-01T00:03:40'
        select['emin'] = 120.0
        select['emax'] = 130.0
        select['expr'] = 'DETX == 0'
        select['usethres'] = 'DEFAULT'  # Has no impact as IRF has no keywords
        select['outobs'] = 'ctselect_py4.fits'
        select['logfile'] = 'ctselect_py4.log'
        select['chatter'] = 3

        # Execute tool
        select.logFileOpen()  # Needed to get a new log file
        select.execute()

        # Check result file
        self._check_result_file('ctselect_py4.fits', nevents=0)

        # Setup ctselect tool for an invalid event file
        select = ctools.ctselect()
        select['inobs'] = self._invalid_events
        select['rad'] = 1.0
        select['tmin'] = '2020-01-01T00:01:10'
        select['tmax'] = '2020-01-01T00:03:40'
        select['emin'] = 2.0
        select['emax'] = 80.0
        select['outobs'] = 'ctselect_py5.fits'
        select['logfile'] = 'ctselect_py5.log'
        select['chatter'] = 3

        # Execute tool
        select.logFileOpen()  # Needed to get a new log file
        self.test_try('Test invalid event file')
        try:
            select.execute()
            self.test_try_failure('Exception not thrown')
        except ValueError:
            self.test_try_success()

        # Setup ctselect tool from event list with extension name. The "emax"
        # value should be ignored.
        select = ctools.ctselect()
        select['inobs'] = self._events + '[EVENTS]'
        select['rad'] = 1.0
        select['tmin'] = '2020-01-01T00:01:10'
        select['tmax'] = '2020-01-01T00:03:40'
        select['emin'] = 2.0
        select['emax'] = 0.0  # Signals that "emax" should be ignored
        select['outobs'] = 'ctselect_py6.fits'
        select['logfile'] = 'ctselect_py6.log'
        select['chatter'] = 3

        # Execute tool
        select.logFileOpen()  # Needed to get a new log file
        select.execute()

        # Check result file
        self._check_result_file('ctselect_py6.fits')

        # Now ignore the "emin" value.
        select = ctools.ctselect()
        select['inobs'] = self._events + '[EVENTS]'
        select['rad'] = 1.0
        select['tmin'] = '2020-01-01T00:01:10'
        select['tmax'] = '2020-01-01T00:03:40'
        select['emin'] = 0.0  # Signals that "emin" should be ignored
        select['emax'] = 80.0
        select['outobs'] = 'ctselect_py7.fits'
        select['logfile'] = 'ctselect_py7.log'
        select['chatter'] = 3

        # Execute tool
        select.logFileOpen()  # Needed to get a new log file
        select.execute()

        # Check result file
        self._check_result_file('ctselect_py7.fits', nevents=60)

        # Now set "emin > emax"
        select['emin'] = 150.0
        select['emax'] = 80.0
        select['outobs'] = 'ctselect_py8.fits'
        select['logfile'] = 'ctselect_py8.log'
        select['chatter'] = 3

        # Execute tool
        select.logFileOpen()  # Needed to get a new log file
        select.execute()

        # Check result file
        self._check_result_file('ctselect_py8.fits', nevents=0)

        # Setup ctselect tool with an RoI that is displaced and of the same
        # size as the original RoI. This should cause an exception to occur
        select = ctools.ctselect()
        select['inobs'] = self._events
        select['usepnt'] = False
        select['ra'] = 83.63
        select['dec'] = 24.01
        select['rad'] = 2.0
        select['tmin'] = '2020-01-01T00:01:10'
        select['tmax'] = '2020-01-01T00:03:40'
        select['emin'] = 2.0
        select['emax'] = 80.0
        select['outobs'] = 'ctselect_py9.fits'
        select['logfile'] = 'ctselect_py9.log'
        select['chatter'] = 3

        # Execute tool
        select.logFileOpen()  # Needed to get a new log file
        self.test_try('Testing selection of invalid RoI')
        try:
            select.execute()
            self.test_try_failure('Exception not thrown')
        except ValueError:
            self.test_try_success()

        # Now force selection and verify that the execution succeeds
        select['forcesel'] = True
        select['outobs'] = 'ctselect_py10.fits'
        select['logfile'] = 'ctselect_py10.log'

        # Execute tool
        select.logFileOpen()  # Needed to get a new log file
        select.execute()

        # Check result file
        self._check_result_file('ctselect_py10.fits', nevents=31, rad=2.0)

        # Finally test a custom defined RoI enclosed in the original one
        select = ctools.ctselect()
        select['inobs'] = self._events
        select['usepnt'] = False
        select['ra'] = 83.63
        select['dec'] = 24.01
        select['rad'] = 0.4
        select['tmin'] = '2020-01-01T00:01:10'
        select['tmax'] = '2020-01-01T00:03:40'
        select['emin'] = 2.0
        select['emax'] = 80.0
        select['outobs'] = 'ctselect_py11.fits'
        select['logfile'] = 'ctselect_py11.log'
        select['chatter'] = 3

        # Execute tool
        select.logFileOpen()  # Needed to get a new log file
        select.execute()

        # Check result file
        self._check_result_file('ctselect_py11.fits',
                                nevents=1,
                                dec=24.01,
                                rad=0.4)

        # Now test phase cut
        select = ctools.ctselect()
        select['inobs'] = self._phased_events
        select['rad'] = 1.0
        select['tmin'] = 'INDEF'
        select['tmax'] = 'INDEF'
        select['emin'] = 1.0
        select['emax'] = 100.0
        select['phase'] = '0.1:0.4,0.6:0.8'
        select['outobs'] = 'ctselect_py12.fits'
        select['logfile'] = 'ctselect_py12.log'
        select['chatter'] = 2

        # Run ctselect tool
        select.logFileOpen()  # Make sure we get a log file
        select.execute()

        # Check result file
        self._check_result_file('ctselect_py12.fits', nevents=365, dec=22.01)

        # Now test another phase cut
        select = ctools.ctselect()
        select['inobs'] = self._phased_events
        select['rad'] = 1.0
        select['tmin'] = 'INDEF'
        select['tmax'] = 'INDEF'
        select['emin'] = 1.0
        select['emax'] = 100.0
        select['phase'] = '0.8:0.3'
        select['outobs'] = 'ctselect_py13.fits'
        select['logfile'] = 'ctselect_py13.log'
        select['chatter'] = 2

        # Run ctselect tool
        select.logFileOpen()  # Make sure we get a log file
        select.execute()

        # Check result file
        self._check_result_file('ctselect_py13.fits', nevents=395, dec=22.01)

        # Test invalid minimum phase value
        self.test_try('Test invalid minimum phase value')
        try:
            select['phase'] = '-0.1:0.3'
            select['outobs'] = 'ctselect_py14.fits'
            select['logfile'] = 'ctselect_py14.log'
            select.logFileOpen()
            select.execute()
            self.test_try_failure('Exception not thrown for "-0.1:0.3"')
        except ValueError:
            self.test_try_success()

        # Test invalid minimum phase value
        self.test_try('Test invalid minimum phase value')
        try:
            select['phase'] = '1.1:0.3'
            select['outobs'] = 'ctselect_py15.fits'
            select['logfile'] = 'ctselect_py15.log'
            select.logFileOpen()
            select.execute()
            self.test_try_failure('Exception not thrown for "1.1:0.3"')
        except ValueError:
            self.test_try_success()

        # Test invalid maximum phase value
        self.test_try('Test invalid maximum phase value')
        try:
            select['phase'] = '0.1:-0.3'
            select['outobs'] = 'ctselect_py16.fits'
            select['logfile'] = 'ctselect_py16.log'
            select.logFileOpen()
            select.execute()
            self.test_try_failure('Exception not thrown for "0.1:-0.3"')
        except ValueError:
            self.test_try_success()

        # Test invalid maximum phase value
        self.test_try('Test invalid maximum phase value')
        try:
            select['phase'] = '0.1:1.1'
            select['outobs'] = 'ctselect_py17.fits'
            select['logfile'] = 'ctselect_py17.log'
            select.logFileOpen()
            select.execute()
            self.test_try_failure('Exception not thrown for "0.1:1.1"')
        except ValueError:
            self.test_try_success()

        # Test invalid phase string
        self.test_try('Test invalid phase string')
        try:
            select['phase'] = '0.1:'
            select['outobs'] = 'ctselect_py18.fits'
            select['logfile'] = 'ctselect_py18.log'
            select.logFileOpen()
            select.execute()
            self.test_try_failure('Exception not thrown for "0.1:"')
        except ValueError:
            self.test_try_success()

        # Test invalid phase string
        self.test_try('Test invalid phase string')
        try:
            select['phase'] = ':1.0'
            select['outobs'] = 'ctselect_py19.fits'
            select['logfile'] = 'ctselect_py19.log'
            select.logFileOpen()
            select.execute()
            self.test_try_failure('Exception not thrown for ":1.0"')
        except ValueError:
            self.test_try_success()

        # Test invalid phase string
        self.test_try('Test invalid phase string')
        try:
            select['phase'] = '0.1-1.0'
            select['outobs'] = 'ctselect_py20.fits'
            select['logfile'] = 'ctselect_py20.log'
            select.logFileOpen()
            select.execute()
            self.test_try_failure('Exception not thrown for "0.1-1.0"')
        except ValueError:
            self.test_try_success()

        # Return
        return
Beispiel #9
0
    def _test_python(self):
        """
        Test csbkgmodel from Python
        """
        # Set-up csbkgmodel
        bkgmodel = cscripts.csbkgmodel()
        bkgmodel['inobs'] = self._events
        bkgmodel['caldb'] = self._caldb
        bkgmodel['irf'] = self._irf
        bkgmodel['instrument'] = 'CTA'
        bkgmodel['spatial'] = 'GAUSS'
        bkgmodel['gradient'] = True
        bkgmodel['spectral'] = 'NODES'
        bkgmodel['ebinalg'] = 'LOG'
        bkgmodel['emin'] = 1.0
        bkgmodel['emax'] = 100.0
        bkgmodel['enumbins'] = 8
        bkgmodel['runwise'] = True
        bkgmodel['rad'] = 2.0
        bkgmodel['chatter'] = 2
        bkgmodel['outmodel'] = 'csbkgmodel_py1.xml'
        bkgmodel['logfile'] = 'csbkgmodel_py1.log'

        # Run csbkgmodel script and save background model
        bkgmodel.logFileOpen()  # Make sure we get a log file
        bkgmodel.run()
        bkgmodel.save()

        # Check background model
        self._check_bkg_model('csbkgmodel_py1.xml')

        # Now test without gradient, power law and not runwise
        bkgmodel = cscripts.csbkgmodel()
        bkgmodel['inobs'] = self._events
        bkgmodel['caldb'] = self._caldb
        bkgmodel['irf'] = self._irf
        bkgmodel['instrument'] = 'CTA'
        bkgmodel['spatial'] = 'GAUSS'
        bkgmodel['gradient'] = False
        bkgmodel['spectral'] = 'PLAW'
        bkgmodel['ebinalg'] = 'LOG'
        bkgmodel['emin'] = 1.0
        bkgmodel['emax'] = 100.0
        bkgmodel['enumbins'] = 8
        bkgmodel['runwise'] = False
        bkgmodel['rad'] = 2.0
        bkgmodel['chatter'] = 3
        bkgmodel['outmodel'] = 'csbkgmodel_py2.xml'
        bkgmodel['logfile'] = 'csbkgmodel_py2.log'

        # Execute csbkgmodel script
        bkgmodel.logFileOpen()  # Make sure we get a log file
        bkgmodel.execute()

        # Check background model
        self._check_bkg_model('csbkgmodel_py2.xml')

        # Now test AEFF model
        bkgmodel = cscripts.csbkgmodel()
        bkgmodel['inobs'] = self._events
        bkgmodel['caldb'] = self._caldb
        bkgmodel['irf'] = self._irf
        bkgmodel['instrument'] = 'CTA'
        bkgmodel['spatial'] = 'AEFF'
        bkgmodel['gradient'] = False
        bkgmodel['spectral'] = 'PLAW'
        bkgmodel['ebinalg'] = 'LOG'
        bkgmodel['emin'] = 1.0
        bkgmodel['emax'] = 100.0
        bkgmodel['enumbins'] = 8
        bkgmodel['runwise'] = False
        bkgmodel['rad'] = 2.0
        bkgmodel['chatter'] = 4
        bkgmodel['outmodel'] = 'csbkgmodel_py3.xml'
        bkgmodel['logfile'] = 'csbkgmodel_py3.log'

        # Execute csbkgmodel script
        bkgmodel.logFileOpen()  # Make sure we get a log file
        bkgmodel.execute()

        # Check background model
        self._check_bkg_model('csbkgmodel_py3.xml')

        # Now test IRF model
        bkgmodel = cscripts.csbkgmodel()
        bkgmodel['inobs'] = self._events
        bkgmodel['caldb'] = self._caldb
        bkgmodel['irf'] = self._irf
        bkgmodel['instrument'] = 'CTA'
        bkgmodel['spatial'] = 'IRF'
        bkgmodel['gradient'] = False
        bkgmodel['spectral'] = 'PLAW'
        bkgmodel['ebinalg'] = 'LOG'
        bkgmodel['emin'] = 1.0
        bkgmodel['emax'] = 100.0
        bkgmodel['enumbins'] = 8
        bkgmodel['runwise'] = False
        bkgmodel['rad'] = 2.0
        bkgmodel['chatter'] = 4
        bkgmodel['outmodel'] = 'csbkgmodel_py4.xml'
        bkgmodel['logfile'] = 'csbkgmodel_py4.log'

        # Execute csbkgmodel script
        bkgmodel.logFileOpen()  # Make sure we get a log file
        bkgmodel.execute()

        # Check background model
        self._check_bkg_model('csbkgmodel_py4.xml')

        # Test with multiple input observations
        obs = gammalib.GObservations()
        for s, events in enumerate([self._myevents1, self._myevents2]):
            run = gammalib.GCTAObservation(events)
            run.id(str(s + 1))
            run.response(self._irf, gammalib.GCaldb('cta', self._caldb))
            obs.append(run)

        # Set-up csbkgmodel
        bkgmodel = cscripts.csbkgmodel(obs)
        bkgmodel['instrument'] = 'CTA'
        bkgmodel['spatial'] = 'GAUSS'
        bkgmodel['gradient'] = True
        bkgmodel['spectral'] = 'NODES'
        bkgmodel['ebinalg'] = 'POW'
        bkgmodel['emin'] = 1.0
        bkgmodel['emax'] = 100.0
        bkgmodel['enumbins'] = 8
        bkgmodel['ebingamma'] = 1.1
        bkgmodel['runwise'] = True
        bkgmodel['rad'] = 2.0
        bkgmodel['chatter'] = 2
        bkgmodel['outmodel'] = 'csbkgmodel_py5.xml'
        bkgmodel['logfile'] = 'csbkgmodel_py5.log'

        # Execute csbkgmodel script
        bkgmodel.logFileOpen()  # Make sure we get a log file
        bkgmodel.execute()

        # Check background model
        self._check_bkg_model('csbkgmodel_py5.xml', nmodels=2)

        # Test GAUSS(E) spatial model
        bkgmodel = cscripts.csbkgmodel()
        bkgmodel['inobs'] = self._events
        bkgmodel['caldb'] = self._caldb
        bkgmodel['irf'] = self._irf
        bkgmodel['instrument'] = 'CTA'
        bkgmodel['spatial'] = 'GAUSS(E)'
        bkgmodel['snumbins'] = 2
        bkgmodel['smin'] = 1.0
        bkgmodel['smax'] = 10.0
        bkgmodel['gradient'] = True
        bkgmodel['spectral'] = 'NODES'
        bkgmodel['ebinalg'] = 'LOG'
        bkgmodel['emin'] = 1.0
        bkgmodel['emax'] = 100.0
        bkgmodel['enumbins'] = 8
        bkgmodel['runwise'] = True
        bkgmodel['rad'] = 2.0
        bkgmodel['chatter'] = 2
        bkgmodel['outmodel'] = 'csbkgmodel_py6.xml'
        bkgmodel['logfile'] = 'csbkgmodel_py6.log'

        # Run csbkgmodel script and save background model
        bkgmodel.logFileOpen()  # Make sure we get a log file
        bkgmodel.execute()

        # Check background model
        self._check_bkg_model('csbkgmodel_py6.xml')

        # Test LOOKUP spatial model
        bkgmodel = cscripts.csbkgmodel()
        bkgmodel['inobs'] = self._events
        bkgmodel['caldb'] = self._caldb
        bkgmodel['irf'] = self._irf
        bkgmodel['instrument'] = 'CTA'
        bkgmodel['spatial'] = 'LOOKUP'
        bkgmodel['slufile'] = self._lookup
        bkgmodel['gradient'] = True
        bkgmodel['spectral'] = 'NODES'
        bkgmodel['ebinalg'] = 'LOG'
        bkgmodel['emin'] = 1.0
        bkgmodel['emax'] = 100.0
        bkgmodel['enumbins'] = 8
        bkgmodel['runwise'] = True
        bkgmodel['rad'] = 2.0
        bkgmodel['chatter'] = 2
        bkgmodel['outmodel'] = 'csbkgmodel_py7.xml'
        bkgmodel['logfile'] = 'csbkgmodel_py7.log'

        # Run csbkgmodel script and save background model
        bkgmodel.logFileOpen()  # Make sure we get a log file
        bkgmodel.execute()

        # Check background model
        self._check_bkg_model('csbkgmodel_py7.xml')

        # Test PROFILE spatial model
        bkgmodel = cscripts.csbkgmodel()
        bkgmodel['inobs'] = self._events
        bkgmodel['caldb'] = self._caldb
        bkgmodel['irf'] = self._irf
        bkgmodel['instrument'] = 'CTA'
        bkgmodel['spatial'] = 'PROFILE'
        bkgmodel['gradient'] = True
        bkgmodel['spectral'] = 'NODES'
        bkgmodel['ebinalg'] = 'LOG'
        bkgmodel['emin'] = 1.0
        bkgmodel['emax'] = 100.0
        bkgmodel['enumbins'] = 8
        bkgmodel['runwise'] = True
        bkgmodel['rad'] = 2.0
        bkgmodel['chatter'] = 2
        bkgmodel['outmodel'] = 'csbkgmodel_py8.xml'
        bkgmodel['logfile'] = 'csbkgmodel_py8.log'

        # Run csbkgmodel script and save background model
        bkgmodel.logFileOpen()  # Make sure we get a log file
        bkgmodel.execute()

        # Check background model
        self._check_bkg_model('csbkgmodel_py8.xml')

        # Test POLYNOM spatial model
        bkgmodel = cscripts.csbkgmodel()
        bkgmodel['inobs'] = self._events
        bkgmodel['caldb'] = self._caldb
        bkgmodel['irf'] = self._irf
        bkgmodel['instrument'] = 'CTA'
        bkgmodel['spatial'] = 'POLYNOM'
        bkgmodel['gradient'] = True
        bkgmodel['spectral'] = 'NODES'
        bkgmodel['ebinalg'] = 'LOG'
        bkgmodel['emin'] = 1.0
        bkgmodel['emax'] = 100.0
        bkgmodel['enumbins'] = 8
        bkgmodel['runwise'] = True
        bkgmodel['rad'] = 2.0
        bkgmodel['chatter'] = 2
        bkgmodel['outmodel'] = 'csbkgmodel_py9.xml'
        bkgmodel['logfile'] = 'csbkgmodel_py9.log'

        # Run csbkgmodel script and save background model
        bkgmodel.logFileOpen()  # Make sure we get a log file
        bkgmodel.execute()

        # Check background model
        self._check_bkg_model('csbkgmodel_py9.xml')

        # Check with data from multiple instruments
        new_inst = 'INST2'
        obs_multi_inst = gammalib.GObservations(obs)
        for run in obs_multi_inst:
            run.instrument(new_inst)
        obs_multi_inst.extend(obs)

        # Set-up csbkgmodel
        bkgmodel = cscripts.csbkgmodel(obs_multi_inst)
        bkgmodel['instrument'] = new_inst
        bkgmodel['spatial'] = 'GAUSS'
        bkgmodel['gradient'] = True
        bkgmodel['spectral'] = 'NODES'
        bkgmodel['ebinalg'] = 'POW'
        bkgmodel['emin'] = 1.0
        bkgmodel['emax'] = 100.0
        bkgmodel['enumbins'] = 8
        bkgmodel['ebingamma'] = 1.1
        bkgmodel['runwise'] = True
        bkgmodel['rad'] = 2.0
        bkgmodel['chatter'] = 2
        bkgmodel['outmodel'] = 'csbkgmodel_py10.xml'
        bkgmodel['logfile'] = 'csbkgmodel_py10.log'

        # Execute csbkgmodel script
        bkgmodel.logFileOpen()  # Make sure we get a log file
        bkgmodel.execute()

        # Check background model
        self._check_bkg_model('csbkgmodel_py10.xml', nmodels=obs.size())

        # Return
        return
Beispiel #10
0
    def _test_python(self):
        """
        Test csphagen from Python
        """
        # Same test as from command line
        phagen = cscripts.csphagen()
        phagen['inobs'] = self._myevents1
        phagen['inmodel'] = 'NONE'
        phagen['caldb'] = self._caldb
        phagen['irf'] = self._irf
        phagen['ebinalg'] = 'LOG'
        phagen['emin'] = 0.1
        phagen['emax'] = 100.0
        phagen['enumbins'] = self._nbins
        phagen['coordsys'] = 'CEL'
        phagen['ra'] = 83.633
        phagen['dec'] = 22.0145
        phagen['rad'] = 0.2
        phagen['stack'] = False
        phagen['inexclusion'] = self._exclusion
        phagen['bkgmethod'] = 'REFLECTED'
        phagen['etruemin'] = 0.05
        phagen['etruemax'] = 150.0
        phagen['etruebins'] = 5
        phagen['outobs'] = 'csphagen_py1_obs.xml'
        phagen['outmodel'] = 'csphagen_py1_model.xml'
        phagen['prefix'] = 'csphagen_py1'
        phagen['logfile'] = 'csphagen_py1.log'
        phagen['chatter'] = 1

        # Execute script
        phagen.execute()

        # Check output
        self._check_output('csphagen_py1', self._nbins, self._nreg_with_excl)
        self._check_outobs('csphagen_py1_obs.xml', 1)

        # Now test without exclusion region
        phagen = cscripts.csphagen()
        phagen['inobs'] = self._myevents1
        phagen['inmodel'] = 'NONE'
        phagen['caldb'] = self._caldb
        phagen['irf'] = self._irf
        phagen['ebinalg'] = 'LOG'
        phagen['emin'] = 0.1
        phagen['emax'] = 100.0
        phagen['enumbins'] = self._nbins
        phagen['coordsys'] = 'CEL'
        phagen['ra'] = 83.633
        phagen['dec'] = 22.0145
        phagen['rad'] = 0.2
        phagen['stack'] = False
        phagen['bkgmethod'] = 'REFLECTED'
        phagen['etruemin'] = 0.05
        phagen['etruemax'] = 150.0
        phagen['etruebins'] = 5
        phagen['outobs'] = 'csphagen_py2_obs.xml'
        phagen['outmodel'] = 'csphagen_py2_model.xml'
        phagen['prefix'] = 'csphagen_py2'
        phagen['logfile'] = 'csphagen_py2.log'
        phagen['chatter'] = 2

        # Execute script
        phagen.execute()

        # Check output
        self._check_output('csphagen_py2', self._nbins, self._nreg_wo_excl)
        self._check_outobs('csphagen_py2_obs.xml', 1)

        # Test with multiple input observations, no stacking
        # Create observation container
        obs = gammalib.GObservations()
        for s, events in enumerate([self._myevents1, self._myevents2]):
            run = gammalib.GCTAObservation(events)
            run.id(str(s + 1))
            run.response(self._irf, gammalib.GCaldb('cta', self._caldb))
            obs.append(run)

        # Setup csphagen
        phagen = cscripts.csphagen(obs)
        phagen['inmodel'] = 'NONE'
        phagen['ebinalg'] = 'LOG'
        phagen['emin'] = 0.1
        phagen['emax'] = 100.0
        phagen['enumbins'] = self._nbins
        phagen['coordsys'] = 'CEL'
        phagen['ra'] = 83.633
        phagen['dec'] = 22.0145
        phagen['rad'] = 0.2
        phagen['stack'] = False
        phagen['inexclusion'] = self._exclusion
        phagen['bkgmethod'] = 'REFLECTED'
        phagen['etruemin'] = 0.05
        phagen['etruemax'] = 150.0
        phagen['etruebins'] = 5
        phagen['outobs'] = 'csphagen_py3_obs.xml'
        phagen['outmodel'] = 'csphagen_py3_model.xml'
        phagen['prefix'] = 'csphagen_py3'
        phagen['logfile'] = 'csphagen_py3.log'
        phagen['chatter'] = 3

        # Run script
        phagen.execute()

        # Check output
        for s in range(2):
            self._check_output('csphagen_py3_' + str(s + 1), self._nbins,
                               self._nreg_mul[s])
        self._check_outobs('csphagen_py3_obs.xml', 2)

        # Setup csphagen for test with multiple input observations and stacking
        phagen = cscripts.csphagen(obs)
        phagen['inmodel'] = 'NONE'
        phagen['ebinalg'] = 'LOG'
        phagen['emin'] = 0.1
        phagen['emax'] = 100.0
        phagen['enumbins'] = self._nbins
        phagen['coordsys'] = 'CEL'
        phagen['ra'] = 83.633
        phagen['dec'] = 22.0145
        phagen['rad'] = 0.2
        phagen['stack'] = True
        phagen['inexclusion'] = self._exclusion
        phagen['bkgmethod'] = 'REFLECTED'
        phagen['etruemin'] = 0.05
        phagen['etruemax'] = 150.0
        phagen['etruebins'] = 5
        phagen['outobs'] = 'csphagen_py4_obs.xml'
        phagen['outmodel'] = 'csphagen_py4_model.xml'
        phagen['prefix'] = 'csphagen_py4'
        phagen['logfile'] = 'csphagen_py4.log'
        phagen['chatter'] = 4

        # Execute script
        phagen.execute()

        # Check output
        for s in range(2):
            self._check_output('csphagen_py4_stacked',
                               self._nbins,
                               0,
                               check_regions=False)
        self._check_outobs('csphagen_py4_obs.xml', 1)

        # Setup csphagen for test with custom On and Off regions provided
        phagen = cscripts.csphagen()
        phagen['inobs'] = self._myevents1
        phagen['inmodel'] = 'NONE'
        phagen['caldb'] = self._caldb
        phagen['irf'] = self._irf
        phagen['ebinalg'] = 'LOG'
        phagen['emin'] = 0.1
        phagen['emax'] = 100.0
        phagen['enumbins'] = self._nbins
        phagen['bkgmethod'] = 'CUSTOM'
        phagen['srcregfile'] = self._regfile_src
        phagen['bkgregfile'] = self._regfile_bkg
        phagen['etruemin'] = 0.05
        phagen['etruemax'] = 150.0
        phagen['etruebins'] = 5
        phagen['stack'] = False
        phagen['outobs'] = 'csphagen_py5_obs.xml'
        phagen['outmodel'] = 'csphagen_py5_model.xml'
        phagen['prefix'] = 'csphagen_py5'
        phagen['logfile'] = 'csphagen_py5.log'
        phagen['chatter'] = 2

        # Execute script
        phagen.execute()

        # Check output
        self._check_output('csphagen_py5', self._nbins, self._nreg_bkg_reg)
        self._check_outobs('csphagen_py5_obs.xml', 1)

        # Append off regions to observation container
        for run in obs:
            run.off_regions(gammalib.GSkyRegions(self._regfile_bkg))

        # Setup csphagen for test with multiple input observations and stacking
        phagen = cscripts.csphagen(obs)
        phagen['inmodel'] = 'NONE'
        phagen['ebinalg'] = 'LOG'
        phagen['emin'] = 0.1
        phagen['emax'] = 100.0
        phagen['enumbins'] = self._nbins
        phagen['coordsys'] = 'CEL'
        phagen['stack'] = True
        phagen['inexclusion'] = self._exclusion
        phagen['bkgmethod'] = 'CUSTOM'
        phagen['srcregfile'] = self._regfile_src
        phagen['etruemin'] = 0.05
        phagen['etruemax'] = 150.0
        phagen['etruebins'] = 5
        phagen['outobs'] = 'csphagen_py6_obs.xml'
        phagen['outmodel'] = 'csphagen_py6_model.xml'
        phagen['prefix'] = 'csphagen_py6'
        phagen['logfile'] = 'csphagen_py6.log'
        phagen['chatter'] = 4

        # Execute script
        phagen.execute()

        # Check output
        for s in range(2):
            self._check_output('csphagen_py6_stacked',
                               self._nbins,
                               0,
                               check_regions=False)
        self._check_outobs('csphagen_py6_obs.xml', 1)

        # Return
        return
Beispiel #11
0
rad = 3  #Radius of ROI
emin = 0.1  #Minimum energy in TeV
emax = 100.0  #Maximum energy in TeV
tstart = 0.0  #Starting time
duration = 204000  #Duration of each observation
deadc = 0.95  #Dead time

#Binning
binsz = 0.1  #Spatial binning
nxpix = 100
nypix = 100
enumbins = 20  #Energy bins

#I need to define the calibration files in two ways because "ctobssim" can read simply this, but gammalib GObservation class needs the full path
caldb = gammalib.GCaldb(
    config.CTOOLS_PATH +
    "/share/caldb/data/cta/prod3b-v1/bcf/South_z40_average_50h"
)  #Calibration Files for gammalib class
irf = "irf_file.fits"

caldb_ = 'prod3b-v1'  #Calibration files for ctobssim
irf_ = 'South_z40_average_50h'

debug = True

Component = 'CTABackgroundModel'  #Components that we are simulating: IRF, DM, Leptonic, Leptonic+Irf, etc. This is needed to read and write consistent filenames to be used by other programs.

#Define Paths
PATH_HERE = "../pipes_in_py"  #Path where we are running
PATH_MODEL = "../../models/"  #Path where the model to simulate is stored
#PATH_OBS = config.DATA_PATH+"/Obs_"+Component+"/" #Path to store the observation files. I create a different directory to store  each component (or set of components) data.
PATH_OBS = "/home/bernardos/LMC/test_ctools/"  #Path to store the observation files. I create a different directory to store  each component (or set of components) data.
Beispiel #12
0
import gammalib as g
import sys
import numpy as np

gobs = g.GCTAObservation()
caldb = g.GCaldb('cta', 'prod3b')
irf = 'South_z20_average_30m'
gobs.response(irf, caldb)

rsp = gobs.response()
# print(rsp)
"""
=== GCTAResponseIrf ===
 Caldb mission .............: cta
 Caldb instrument ..........: prod3b
 Response name .............: South_z20_average_30m
 Energy dispersion .........: Not used
 Safe energy range .........: undefined
=== GCaldb ===
 Database root .............: /home/sim/anaconda3/envs/cta_pipe/share/caldb
 Selected Mission ..........: CTA
 Selected Instrument .......: PROD3B
 Calibration Index File ....: /home/sim/anaconda3/envs/cta_pipe/share/caldb/data/cta/prod3b/caldb.indx
 Number of entries .........: 144
=== GCTAAeff2D ===
 Filename ..................: /home/sim/anaconda3/envs/cta_pipe/share/caldb/data/cta/prod3b-v1/bcf/South_z20_average_30m/irf_file.fits
 Number of energy bins .....: 42
 Number of offset bins .....: 6
 Log10(Energy) range .......: 0.0125892544165254 - 199.526229858398 TeV
 Offset angle range ........: 0 - 6 deg
 Lower energy threshold ....: not specified
Beispiel #13
0
#Observation variables

rad = 5  #Radius of ROI
emin = 0.03  #Minimum energy in TeV
emax = 100.0  #Maximum enery in TeV
tstart = 0.0  #Starting time
duration = 180000  #Ending time
deadc = 0.95  #Dead time

binsz = 0.5  #Spatial binning
nxpix = 20
nypix = 20
enumbins = 20

caldb = gammalib.GCaldb(config.CTOOLS_PATH +
                        "/share/caldb/data/cta/1dc/bcf/South_z20_50h"
                        )  #Calibration Files for gammalib class
irf = "irf_file.fits"

caldb_ = "1dc"
irf_ = "South_z20_50h"

#Get model name
models = gammalib.GModels(PATH_MODEL + "LMC_closer_files.xml")
for model in models:
    modelcontainer = gammalib.GModels()
    modelname = model.name()
    srctype = model.type()
    par = model.spectral().at(0)
    if srctype == 'PointSource' and par.is_free():
        modelcontainer.append(model)
Beispiel #14
0
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
Beispiel #15
0
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
Beispiel #16
0
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