Commit d9a9c73fc2157eb85560603620092b56416433c1
1 parent
a448964c
Convert tabs to spaces.
Showing
5 changed files
with
1262 additions
and
1262 deletions
scripts/cssens.py
| @@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
| 17 | # | 17 | # |
| 18 | # The source is modelled as a point source | 18 | # The source is modelled as a point source |
| 19 | # | 19 | # |
| 20 | -# Copyright (C) 2011 Jurgen Knodlseder | 20 | +# Copyright (C) 2011-2014 Juergen Knoedlseder |
| 21 | # | 21 | # |
| 22 | # This program is free software: you can redistribute it and/or modify | 22 | # This program is free software: you can redistribute it and/or modify |
| 23 | # it under the terms of the GNU General Public License as published by | 23 | # it under the terms of the GNU General Public License as published by |
| @@ -45,682 +45,682 @@ import math | @@ -45,682 +45,682 @@ import math | ||
| 45 | # cssens class # | 45 | # cssens class # |
| 46 | # ============ # | 46 | # ============ # |
| 47 | class cssens(GApplication): | 47 | class cssens(GApplication): |
| 48 | - """ | ||
| 49 | - This class implements the sensitivity computation script. It derives | ||
| 50 | - from the GammaLib::GApplication class which provides support for parameter | ||
| 51 | - files, command line arguments, and logging. In that way the Python | ||
| 52 | - script behaves just as a regular ctool. | ||
| 53 | - """ | ||
| 54 | - def __init__(self, *argv): | ||
| 55 | - """ | ||
| 56 | - Constructor. | ||
| 57 | - """ | ||
| 58 | - # Set name | ||
| 59 | - self.name = "cssens" | ||
| 60 | - self.version = "0.3.0" | ||
| 61 | - | ||
| 62 | - # Make sure that parfile exists | ||
| 63 | - file = self.parfile() | ||
| 64 | - | ||
| 65 | - # Initialise application | ||
| 66 | - if len(argv) == 0: | ||
| 67 | - GApplication.__init__(self, self.name, self.version) | ||
| 68 | - elif len(argv) ==1: | ||
| 69 | - GApplication.__init__(self, self.name, self.version, *argv) | ||
| 70 | - else: | ||
| 71 | - raise TypeError("Invalid number of arguments given.") | ||
| 72 | - | ||
| 73 | - # Set logger properties | ||
| 74 | - self.logFileOpen() | ||
| 75 | - self.log_header() | ||
| 76 | - self.log.date(True) | ||
| 77 | - | ||
| 78 | - # Return | ||
| 79 | - return | ||
| 80 | - | ||
| 81 | - def __del__(self): | ||
| 82 | - """ | ||
| 83 | - Destructor. | ||
| 84 | - """ | ||
| 85 | - # Write separator into logger | ||
| 86 | - if self.logTerse(): | ||
| 87 | - self.log("\n") | ||
| 88 | - | ||
| 89 | - # Return | ||
| 90 | - return | ||
| 91 | - | ||
| 92 | - def parfile(self): | ||
| 93 | - """ | ||
| 94 | - Check if parfile exists. If parfile does not exist then create a | ||
| 95 | - default parfile. This kluge avoids shipping the cscript with a parfile. | ||
| 96 | - """ | ||
| 97 | - # Set parfile name | ||
| 98 | - parfile = self.name+".par" | ||
| 99 | - | ||
| 100 | - try: | ||
| 101 | - pars = GApplicationPars(parfile) | ||
| 102 | - except: | ||
| 103 | - # Signal if parfile was not found | ||
| 104 | - sys.stdout.write("Parfile "+parfile+" not found. Create default parfile.\n") | ||
| 105 | - | ||
| 106 | - # Create default parfile | ||
| 107 | - pars = GApplicationPars() | ||
| 108 | - pars.append(GApplicationPar("outfile","f","h","sensitivity.dat","","","Output file name")) | ||
| 109 | - pars.append(GApplicationPar("caldb","s","a","$GAMMALIB/share/caldb/cta","","","Calibration database")) | ||
| 110 | - pars.append(GApplicationPar("irf","s","a","cta_dummy_irf","","","Instrument response function")) | ||
| 111 | - pars.append(GApplicationPar("type","s","a","point","","","Source model type (point/gauss/shell/disk)")) | ||
| 112 | - pars.append(GApplicationPar("offset","r","a","0.0","0.0","","Source offset angle (deg)")) | ||
| 113 | - pars.append(GApplicationPar("bkg","s","a","$GAMMALIB/share/models/bkg_dummy.txt","","","Background model file function (none=power law for E)")) | ||
| 114 | - pars.append(GApplicationPar("duration","r","a","180000.0","","","Effective exposure time (s)")) | ||
| 115 | - pars.append(GApplicationPar("rad","r","a","5.0","","","Radius of ROI (deg)")) | ||
| 116 | - pars.append(GApplicationPar("enumbins","i","h","0","","","Number of energy bins (0=unbinned)")) | ||
| 117 | - pars.append(GApplicationPar("npix","i","h","200","","","Number of pixels for binned")) | ||
| 118 | - pars.append(GApplicationPar("binsz","r","h","0.05","","","Pixel size for binned (deg/pixel)")) | ||
| 119 | - pars.append(GApplicationPar("sigma","r","h","5.0","","","Significance threshold")) | ||
| 120 | - pars.append(GApplicationPar("ts_use","b","h","yes","","","Use TS?")) | ||
| 121 | - pars.append(GApplicationPar("index","r","h","-2.48","","","Assumed spectral index")) | ||
| 122 | - pars.append(GApplicationPar("radius","r","h","0.1","","","Extended source model radius")) | ||
| 123 | - pars.append(GApplicationPar("width","r","h","0.05","","","Extended source model width")) | ||
| 124 | - pars.append(GApplicationPar("max_iter","i","h","50","","","Maximum number of iterations")) | ||
| 125 | - pars.append(GApplicationPar("num_avg","i","h","3","","","Number of iterations for sliding average")) | ||
| 126 | - pars.append_standard() | ||
| 127 | - pars.save(parfile) | ||
| 128 | - | ||
| 129 | - # Return | ||
| 130 | - return | ||
| 131 | - | ||
| 132 | - def get_parameters(self): | ||
| 133 | - """ | ||
| 134 | - Get parameters from parfile. | ||
| 135 | - """ | ||
| 136 | - # Get parameters | ||
| 137 | - self.m_outfile = self["outfile"].filename() | ||
| 138 | - self.m_caldb = self["caldb"].string() | ||
| 139 | - self.m_irf = self["irf"].string() | ||
| 140 | - self.m_type = self["type"].string() | ||
| 141 | - self.m_offset = self["offset"].real() | ||
| 142 | - self.m_bkg = self["bkg"].string() | ||
| 143 | - self.m_duration = self["duration"].real() | ||
| 144 | - self.m_roi = self["rad"].real() | ||
| 145 | - self.m_nbins = self["enumbins"].integer() | ||
| 146 | - self.m_npix = self["npix"].integer() | ||
| 147 | - self.m_binsz = self["binsz"].real() | ||
| 148 | - self.m_ts_thres = self["sigma"].real()*self["sigma"].real() | ||
| 149 | - self.m_use_ts = self["ts_use"].boolean() | ||
| 150 | - self.m_index = self["index"].real() | ||
| 151 | - self.m_radius = self["radius"].real() | ||
| 152 | - self.m_width = self["width"].real() | ||
| 153 | - self.m_max_iter = self["max_iter"].integer() | ||
| 154 | - self.m_num_avg = self["num_avg"].integer() | ||
| 155 | - | ||
| 156 | - # Set some fixed parameters | ||
| 157 | - self.m_log = False # Logging in client tools | ||
| 158 | - self.m_debug = False # Debugging in client tools | ||
| 159 | - | ||
| 160 | - # Return | ||
| 161 | - return | ||
| 162 | - | ||
| 163 | - def execute(self): | ||
| 164 | - """ | ||
| 165 | - Execute the script. | ||
| 166 | - """ | ||
| 167 | - # Run the script | ||
| 168 | - self.run() | ||
| 169 | - | ||
| 170 | - # Return | ||
| 171 | - return | ||
| 172 | - | ||
| 173 | - def run(self): | ||
| 174 | - """ | ||
| 175 | - Run the script. | ||
| 176 | - """ | ||
| 177 | - # Switch screen logging on in debug mode | ||
| 178 | - if self.logDebug(): | ||
| 179 | - self.log.cout(True) | ||
| 180 | - | ||
| 181 | - # Get parameters | ||
| 182 | - self.get_parameters() | ||
| 183 | - | ||
| 184 | - # Write input parameters into logger | ||
| 185 | - if self.logTerse(): | ||
| 186 | - self.log_parameters() | ||
| 187 | - self.log("\n") | ||
| 188 | - | ||
| 189 | - # Initialise script | ||
| 190 | - colnames = ['loge', 'emin', 'emax', 'crab', 'pflux', 'eflux', 'diffSens'] | ||
| 191 | - results = [] | ||
| 192 | - | ||
| 193 | - # Initialise models. Note that we centre the point source at the Galactic | ||
| 194 | - # center as our observation is also centred at the Galactic centre, so | ||
| 195 | - # we're onaxis. | ||
| 196 | - bkg_model = GModels() | ||
| 197 | - full_model = GModels() | ||
| 198 | - bkg_model.append(self.set_bkg_model()) | ||
| 199 | - full_model.append(self.set_bkg_model()) | ||
| 200 | - full_model.append(self.set_src_model(0.0, \ | ||
| 201 | - self.m_offset, \ | ||
| 202 | - type=self.m_type, \ | ||
| 203 | - index=self.m_index)) | ||
| 204 | - | ||
| 205 | - # Write models into logger | ||
| 206 | - if self.logTerse(): | ||
| 207 | - self.log("\n") | ||
| 208 | - self.log.header1("Models") | ||
| 209 | - self.log.header2("Background model") | ||
| 210 | - self.log(str(bkg_model)) | ||
| 211 | - self.log("\n\n") | ||
| 212 | - self.log.header2("Full model") | ||
| 213 | - self.log(str(full_model)) | ||
| 214 | - self.log("\n") | ||
| 215 | - | ||
| 216 | - # Write heder | ||
| 217 | - if self.logTerse(): | ||
| 218 | - self.log("\n") | ||
| 219 | - self.log.header1("Sensitivity determination") | ||
| 220 | - | ||
| 221 | - # Loop over energy bands. The number of energy band is still | ||
| 222 | - # fixed ... | ||
| 223 | - for ieng in range(21): | ||
| 224 | - | ||
| 225 | - # Set energies | ||
| 226 | - loge = -1.7 + ieng * 0.2 | ||
| 227 | - emean = pow(10.0, loge) | ||
| 228 | - emin = pow(10.0, loge-0.1) | ||
| 229 | - emax = pow(10.0, loge+0.1) | ||
| 230 | - | ||
| 231 | - # Setup observation(s) | ||
| 232 | - obs = self.set_obs(emin=emin, emax=emax) | ||
| 233 | - | ||
| 234 | - # Determine sensitivity | ||
| 235 | - result = self.get_sensitivity(obs, bkg_model, full_model) | ||
| 236 | - | ||
| 237 | - # Write results | ||
| 238 | - if ieng == 0: | ||
| 239 | - f = open(self.m_outfile, 'w') | ||
| 240 | - writer = csv.DictWriter(f, colnames) | ||
| 241 | - writer.writerow(dict((_,_) for _ in colnames)) | ||
| 242 | - writer.writerow(result) | ||
| 243 | - f.close() | ||
| 244 | - else: | ||
| 245 | - f = open(self.m_outfile, 'a') | ||
| 246 | - writer = csv.DictWriter(f, colnames) | ||
| 247 | - writer.writerow(result) | ||
| 248 | - f.close() | ||
| 249 | - | ||
| 250 | - # Append results | ||
| 251 | - results.append(result) | ||
| 252 | - | ||
| 253 | - # Return | ||
| 254 | - return | ||
| 255 | - | ||
| 256 | - def set_obs(self, lpnt=0.0, bpnt=0.0, emin=0.1, emax=100.0): | ||
| 257 | - """ | ||
| 258 | - Returns an observation container with a single CTA observation. | ||
| 259 | - | ||
| 260 | - Keywords: | ||
| 261 | - lpnt - Galactic longitude of pointing [deg] (default: 0.0) | ||
| 262 | - bpnt - Galactic latitude of pointing [deg] (default: 0.0) | ||
| 263 | - emin - Minimum energy [TeV] (default: 0.1) | ||
| 264 | - emax - Maximum energy [TeV] (default: 100.0) | ||
| 265 | - """ | ||
| 266 | - # Allocate observation container | ||
| 267 | - obs = GObservations() | ||
| 268 | - | ||
| 269 | - # Set single pointing | ||
| 270 | - pntdir = GSkyDir() | ||
| 271 | - pntdir.lb_deg(lpnt, bpnt) | ||
| 272 | - | ||
| 273 | - # Create CTA observation | ||
| 274 | - run = obsutils.set(pntdir, caldb=self.m_caldb, irf=self.m_irf, \ | ||
| 275 | - duration=self.m_duration, \ | 48 | + """ |
| 49 | + This class implements the sensitivity computation script. It derives | ||
| 50 | + from the GammaLib::GApplication class which provides support for parameter | ||
| 51 | + files, command line arguments, and logging. In that way the Python | ||
| 52 | + script behaves just as a regular ctool. | ||
| 53 | + """ | ||
| 54 | + def __init__(self, *argv): | ||
| 55 | + """ | ||
| 56 | + Constructor. | ||
| 57 | + """ | ||
| 58 | + # Set name | ||
| 59 | + self.name = "cssens" | ||
| 60 | + self.version = "0.3.0" | ||
| 61 | + | ||
| 62 | + # Make sure that parfile exists | ||
| 63 | + file = self.parfile() | ||
| 64 | + | ||
| 65 | + # Initialise application | ||
| 66 | + if len(argv) == 0: | ||
| 67 | + GApplication.__init__(self, self.name, self.version) | ||
| 68 | + elif len(argv) ==1: | ||
| 69 | + GApplication.__init__(self, self.name, self.version, *argv) | ||
| 70 | + else: | ||
| 71 | + raise TypeError("Invalid number of arguments given.") | ||
| 72 | + | ||
| 73 | + # Set logger properties | ||
| 74 | + self.logFileOpen() | ||
| 75 | + self.log_header() | ||
| 76 | + self.log.date(True) | ||
| 77 | + | ||
| 78 | + # Return | ||
| 79 | + return | ||
| 80 | + | ||
| 81 | + def __del__(self): | ||
| 82 | + """ | ||
| 83 | + Destructor. | ||
| 84 | + """ | ||
| 85 | + # Write separator into logger | ||
| 86 | + if self.logTerse(): | ||
| 87 | + self.log("\n") | ||
| 88 | + | ||
| 89 | + # Return | ||
| 90 | + return | ||
| 91 | + | ||
| 92 | + def parfile(self): | ||
| 93 | + """ | ||
| 94 | + Check if parfile exists. If parfile does not exist then create a | ||
| 95 | + default parfile. This kluge avoids shipping the cscript with a parfile. | ||
| 96 | + """ | ||
| 97 | + # Set parfile name | ||
| 98 | + parfile = self.name+".par" | ||
| 99 | + | ||
| 100 | + try: | ||
| 101 | + pars = GApplicationPars(parfile) | ||
| 102 | + except: | ||
| 103 | + # Signal if parfile was not found | ||
| 104 | + sys.stdout.write("Parfile "+parfile+" not found. Create default parfile.\n") | ||
| 105 | + | ||
| 106 | + # Create default parfile | ||
| 107 | + pars = GApplicationPars() | ||
| 108 | + pars.append(GApplicationPar("outfile","f","h","sensitivity.dat","","","Output file name")) | ||
| 109 | + pars.append(GApplicationPar("caldb","s","a","$GAMMALIB/share/caldb/cta","","","Calibration database")) | ||
| 110 | + pars.append(GApplicationPar("irf","s","a","cta_dummy_irf","","","Instrument response function")) | ||
| 111 | + pars.append(GApplicationPar("type","s","a","point","","","Source model type (point/gauss/shell/disk)")) | ||
| 112 | + pars.append(GApplicationPar("offset","r","a","0.0","0.0","","Source offset angle (deg)")) | ||
| 113 | + pars.append(GApplicationPar("bkg","s","a","$GAMMALIB/share/models/bkg_dummy.txt","","","Background model file function (none=power law for E)")) | ||
| 114 | + pars.append(GApplicationPar("duration","r","a","180000.0","","","Effective exposure time (s)")) | ||
| 115 | + pars.append(GApplicationPar("rad","r","a","5.0","","","Radius of ROI (deg)")) | ||
| 116 | + pars.append(GApplicationPar("enumbins","i","h","0","","","Number of energy bins (0=unbinned)")) | ||
| 117 | + pars.append(GApplicationPar("npix","i","h","200","","","Number of pixels for binned")) | ||
| 118 | + pars.append(GApplicationPar("binsz","r","h","0.05","","","Pixel size for binned (deg/pixel)")) | ||
| 119 | + pars.append(GApplicationPar("sigma","r","h","5.0","","","Significance threshold")) | ||
| 120 | + pars.append(GApplicationPar("ts_use","b","h","yes","","","Use TS?")) | ||
| 121 | + pars.append(GApplicationPar("index","r","h","-2.48","","","Assumed spectral index")) | ||
| 122 | + pars.append(GApplicationPar("radius","r","h","0.1","","","Extended source model radius")) | ||
| 123 | + pars.append(GApplicationPar("width","r","h","0.05","","","Extended source model width")) | ||
| 124 | + pars.append(GApplicationPar("max_iter","i","h","50","","","Maximum number of iterations")) | ||
| 125 | + pars.append(GApplicationPar("num_avg","i","h","3","","","Number of iterations for sliding average")) | ||
| 126 | + pars.append_standard() | ||
| 127 | + pars.save(parfile) | ||
| 128 | + | ||
| 129 | + # Return | ||
| 130 | + return | ||
| 131 | + | ||
| 132 | + def get_parameters(self): | ||
| 133 | + """ | ||
| 134 | + Get parameters from parfile. | ||
| 135 | + """ | ||
| 136 | + # Get parameters | ||
| 137 | + self.m_outfile = self["outfile"].filename() | ||
| 138 | + self.m_caldb = self["caldb"].string() | ||
| 139 | + self.m_irf = self["irf"].string() | ||
| 140 | + self.m_type = self["type"].string() | ||
| 141 | + self.m_offset = self["offset"].real() | ||
| 142 | + self.m_bkg = self["bkg"].string() | ||
| 143 | + self.m_duration = self["duration"].real() | ||
| 144 | + self.m_roi = self["rad"].real() | ||
| 145 | + self.m_nbins = self["enumbins"].integer() | ||
| 146 | + self.m_npix = self["npix"].integer() | ||
| 147 | + self.m_binsz = self["binsz"].real() | ||
| 148 | + self.m_ts_thres = self["sigma"].real()*self["sigma"].real() | ||
| 149 | + self.m_use_ts = self["ts_use"].boolean() | ||
| 150 | + self.m_index = self["index"].real() | ||
| 151 | + self.m_radius = self["radius"].real() | ||
| 152 | + self.m_width = self["width"].real() | ||
| 153 | + self.m_max_iter = self["max_iter"].integer() | ||
| 154 | + self.m_num_avg = self["num_avg"].integer() | ||
| 155 | + | ||
| 156 | + # Set some fixed parameters | ||
| 157 | + self.m_log = False # Logging in client tools | ||
| 158 | + self.m_debug = False # Debugging in client tools | ||
| 159 | + | ||
| 160 | + # Return | ||
| 161 | + return | ||
| 162 | + | ||
| 163 | + def execute(self): | ||
| 164 | + """ | ||
| 165 | + Execute the script. | ||
| 166 | + """ | ||
| 167 | + # Run the script | ||
| 168 | + self.run() | ||
| 169 | + | ||
| 170 | + # Return | ||
| 171 | + return | ||
| 172 | + | ||
| 173 | + def run(self): | ||
| 174 | + """ | ||
| 175 | + Run the script. | ||
| 176 | + """ | ||
| 177 | + # Switch screen logging on in debug mode | ||
| 178 | + if self.logDebug(): | ||
| 179 | + self.log.cout(True) | ||
| 180 | + | ||
| 181 | + # Get parameters | ||
| 182 | + self.get_parameters() | ||
| 183 | + | ||
| 184 | + # Write input parameters into logger | ||
| 185 | + if self.logTerse(): | ||
| 186 | + self.log_parameters() | ||
| 187 | + self.log("\n") | ||
| 188 | + | ||
| 189 | + # Initialise script | ||
| 190 | + colnames = ['loge', 'emin', 'emax', 'crab', 'pflux', 'eflux', 'diffSens'] | ||
| 191 | + results = [] | ||
| 192 | + | ||
| 193 | + # Initialise models. Note that we centre the point source at the Galactic | ||
| 194 | + # center as our observation is also centred at the Galactic centre, so | ||
| 195 | + # we're onaxis. | ||
| 196 | + bkg_model = GModels() | ||
| 197 | + full_model = GModels() | ||
| 198 | + bkg_model.append(self.set_bkg_model()) | ||
| 199 | + full_model.append(self.set_bkg_model()) | ||
| 200 | + full_model.append(self.set_src_model(0.0, \ | ||
| 201 | + self.m_offset, \ | ||
| 202 | + type=self.m_type, \ | ||
| 203 | + index=self.m_index)) | ||
| 204 | + | ||
| 205 | + # Write models into logger | ||
| 206 | + if self.logTerse(): | ||
| 207 | + self.log("\n") | ||
| 208 | + self.log.header1("Models") | ||
| 209 | + self.log.header2("Background model") | ||
| 210 | + self.log(str(bkg_model)) | ||
| 211 | + self.log("\n\n") | ||
| 212 | + self.log.header2("Full model") | ||
| 213 | + self.log(str(full_model)) | ||
| 214 | + self.log("\n") | ||
| 215 | + | ||
| 216 | + # Write heder | ||
| 217 | + if self.logTerse(): | ||
| 218 | + self.log("\n") | ||
| 219 | + self.log.header1("Sensitivity determination") | ||
| 220 | + | ||
| 221 | + # Loop over energy bands. The number of energy band is still | ||
| 222 | + # fixed ... | ||
| 223 | + for ieng in range(21): | ||
| 224 | + | ||
| 225 | + # Set energies | ||
| 226 | + loge = -1.7 + ieng * 0.2 | ||
| 227 | + emean = pow(10.0, loge) | ||
| 228 | + emin = pow(10.0, loge-0.1) | ||
| 229 | + emax = pow(10.0, loge+0.1) | ||
| 230 | + | ||
| 231 | + # Setup observation(s) | ||
| 232 | + obs = self.set_obs(emin=emin, emax=emax) | ||
| 233 | + | ||
| 234 | + # Determine sensitivity | ||
| 235 | + result = self.get_sensitivity(obs, bkg_model, full_model) | ||
| 236 | + | ||
| 237 | + # Write results | ||
| 238 | + if ieng == 0: | ||
| 239 | + f = open(self.m_outfile, 'w') | ||
| 240 | + writer = csv.DictWriter(f, colnames) | ||
| 241 | + writer.writerow(dict((_,_) for _ in colnames)) | ||
| 242 | + writer.writerow(result) | ||
| 243 | + f.close() | ||
| 244 | + else: | ||
| 245 | + f = open(self.m_outfile, 'a') | ||
| 246 | + writer = csv.DictWriter(f, colnames) | ||
| 247 | + writer.writerow(result) | ||
| 248 | + f.close() | ||
| 249 | + | ||
| 250 | + # Append results | ||
| 251 | + results.append(result) | ||
| 252 | + | ||
| 253 | + # Return | ||
| 254 | + return | ||
| 255 | + | ||
| 256 | + def set_obs(self, lpnt=0.0, bpnt=0.0, emin=0.1, emax=100.0): | ||
| 257 | + """ | ||
| 258 | + Returns an observation container with a single CTA observation. | ||
| 259 | + | ||
| 260 | + Keywords: | ||
| 261 | + lpnt - Galactic longitude of pointing [deg] (default: 0.0) | ||
| 262 | + bpnt - Galactic latitude of pointing [deg] (default: 0.0) | ||
| 263 | + emin - Minimum energy [TeV] (default: 0.1) | ||
| 264 | + emax - Maximum energy [TeV] (default: 100.0) | ||
| 265 | + """ | ||
| 266 | + # Allocate observation container | ||
| 267 | + obs = GObservations() | ||
| 268 | + | ||
| 269 | + # Set single pointing | ||
| 270 | + pntdir = GSkyDir() | ||
| 271 | + pntdir.lb_deg(lpnt, bpnt) | ||
| 272 | + | ||
| 273 | + # Create CTA observation | ||
| 274 | + run = obsutils.set(pntdir, caldb=self.m_caldb, irf=self.m_irf, \ | ||
| 275 | + duration=self.m_duration, \ | ||
| 276 | emin=emin, emax=emax, rad=self.m_roi) | 276 | emin=emin, emax=emax, rad=self.m_roi) |
| 277 | - | ||
| 278 | - # Append observation to container | ||
| 279 | - obs.append(run) | ||
| 280 | - | ||
| 281 | - # Return observation container | ||
| 282 | - return obs | ||
| 283 | - | ||
| 284 | - def set_bkg_model(self, fitidx=False): | ||
| 285 | - """ | ||
| 286 | - Setup standard CTA background model. We use a simple power law here, | ||
| 287 | - scaled to Konrad's E configuration performance table. | ||
| 288 | - | ||
| 289 | - Keywords: | ||
| 290 | - fitidx - Fit spectral index (default: False) | ||
| 291 | - """ | ||
| 292 | - # Define radial component | ||
| 293 | - radial = GCTAModelRadialGauss(3.0) | ||
| 294 | - | ||
| 295 | - # Define spectral component. If a background model is given then | ||
| 296 | - # use a file function. Otherwise use a static power law. | ||
| 297 | - if len(self.m_bkg) > 0: | ||
| 298 | - spectrum = GModelSpectralFunc(self.m_bkg, 1.0) | ||
| 299 | - else: | ||
| 300 | - spectrum = GModelSpectralPlaw(61.8e-6, -1.85, GEnergy(1.0, "TeV")) | ||
| 301 | - if fitidx: | ||
| 302 | - spectrum["Index"].free() | ||
| 303 | - else: | ||
| 304 | - spectrum["Index"].fix() | ||
| 305 | - | ||
| 306 | - # Create background model | ||
| 307 | - model = GCTAModelRadialAcceptance(radial, spectrum) | ||
| 308 | - model.name("Background") | ||
| 309 | - model.instruments("CTA") | ||
| 310 | - | ||
| 311 | - # Return background model | ||
| 312 | - return model | ||
| 313 | - | ||
| 314 | - def set_src_model(self, l, b, flux=1.0, index=-2.48, \ | 277 | + |
| 278 | + # Append observation to container | ||
| 279 | + obs.append(run) | ||
| 280 | + | ||
| 281 | + # Return observation container | ||
| 282 | + return obs | ||
| 283 | + | ||
| 284 | + def set_bkg_model(self, fitidx=False): | ||
| 285 | + """ | ||
| 286 | + Setup standard CTA background model. We use a simple power law here, | ||
| 287 | + scaled to Konrad's E configuration performance table. | ||
| 288 | + | ||
| 289 | + Keywords: | ||
| 290 | + fitidx - Fit spectral index (default: False) | ||
| 291 | + """ | ||
| 292 | + # Define radial component | ||
| 293 | + radial = GCTAModelRadialGauss(3.0) | ||
| 294 | + | ||
| 295 | + # Define spectral component. If a background model is given then | ||
| 296 | + # use a file function. Otherwise use a static power law. | ||
| 297 | + if len(self.m_bkg) > 0: | ||
| 298 | + spectrum = GModelSpectralFunc(self.m_bkg, 1.0) | ||
| 299 | + else: | ||
| 300 | + spectrum = GModelSpectralPlaw(61.8e-6, -1.85, GEnergy(1.0, "TeV")) | ||
| 301 | + if fitidx: | ||
| 302 | + spectrum["Index"].free() | ||
| 303 | + else: | ||
| 304 | + spectrum["Index"].fix() | ||
| 305 | + | ||
| 306 | + # Create background model | ||
| 307 | + model = GCTAModelRadialAcceptance(radial, spectrum) | ||
| 308 | + model.name("Background") | ||
| 309 | + model.instruments("CTA") | ||
| 310 | + | ||
| 311 | + # Return background model | ||
| 312 | + return model | ||
| 313 | + | ||
| 314 | + def set_src_model(self, l, b, flux=1.0, index=-2.48, \ | ||
| 315 | type="point", fitpos=False, fitidx=False): | 315 | type="point", fitpos=False, fitidx=False): |
| 316 | - """ | ||
| 317 | - Returns a single source with Crab-like spectrum. The source flux | ||
| 318 | - can be scaled in Crab units. The Crab spectrum is based on MAGIC | ||
| 319 | - observations (Albert et al. 2008, ApJ, 674, 1037). | ||
| 320 | - | ||
| 321 | - Parameters: | ||
| 322 | - l - Galactic longitude of source location [deg] | ||
| 323 | - b - Galactic latitude of source location [deg] | ||
| 324 | - Keywords: | ||
| 325 | - flux - Source flux [Crabs] | ||
| 326 | - index - Spectral index | ||
| 327 | - type - Source type ("point", "gauss", "disk", "shell") | ||
| 328 | - fitpos - Fit position and size? (default: False) | ||
| 329 | - fitidx - Fit index? (default: False) | ||
| 330 | - """ | ||
| 331 | - # Set source location | ||
| 332 | - location = GSkyDir() | ||
| 333 | - location.lb_deg(l, b) | ||
| 334 | - | ||
| 335 | - # Set source spectrum | ||
| 336 | - spectrum = GModelSpectralPlaw(flux*5.7e-16, index, GEnergy(0.3, "TeV") | ||
| 337 | - if fitidx: | ||
| 338 | - spectrum["Index"].free() | ||
| 339 | - else: | ||
| 340 | - spectrum["Index"].fix() | ||
| 341 | - | ||
| 342 | - # Set source | ||
| 343 | - if type == "point": | ||
| 344 | - spatial = GModelSpatialPointSource(location) | ||
| 345 | - if fitpos: | ||
| 346 | - spatial["RA"].free() | ||
| 347 | - spatial["DEC"].free() | ||
| 348 | - else: | ||
| 349 | - spatial["RA"].fix() | ||
| 350 | - spatial["DEC"].fix() | ||
| 351 | - elif type == "gauss": | ||
| 352 | - spatial = GModelSpatialRadialGauss(location, self.m_radius) | ||
| 353 | - if fitpos: | ||
| 354 | - spatial["RA"].free() | ||
| 355 | - spatial["DEC"].free() | ||
| 356 | - spatial["Sigma"].free() | ||
| 357 | - else: | ||
| 358 | - spatial["RA"].fix() | ||
| 359 | - spatial["DEC"].fix() | ||
| 360 | - spatial["Sigma"].fix() | ||
| 361 | - elif type == "disk": | ||
| 362 | - spatial = GModelSpatialRadialDisk(location, self.m_radius) | ||
| 363 | - if fitpos: | ||
| 364 | - spatial["RA"].free() | ||
| 365 | - spatial["DEC"].free() | ||
| 366 | - spatial["Radius"].free() | ||
| 367 | - else: | ||
| 368 | - spatial["RA"].fix() | ||
| 369 | - spatial["DEC"].fix() | ||
| 370 | - spatial["Radius"].fix() | ||
| 371 | - elif type == "shell": | ||
| 372 | - spatial = GModelSpatialRadialShell(location, self.m_radius, self.m_width) | ||
| 373 | - if fitpos: | ||
| 374 | - spatial["RA"].free() | ||
| 375 | - spatial["DEC"].free() | ||
| 376 | - spatial["Radius"].free() | ||
| 377 | - spatial["Width"].free() | ||
| 378 | - else: | ||
| 379 | - spatial["RA"].fix() | ||
| 380 | - spatial["DEC"].fix() | ||
| 381 | - spatial["Radius"].fix() | ||
| 382 | - spatial["Width"].fix() | ||
| 383 | - else: | ||
| 384 | - self.log("ERROR: Unknown source type '"+type+"'.\n") | ||
| 385 | - return None | 316 | + """ |
| 317 | + Returns a single source with Crab-like spectrum. The source flux | ||
| 318 | + can be scaled in Crab units. The Crab spectrum is based on MAGIC | ||
| 319 | + observations (Albert et al. 2008, ApJ, 674, 1037). | ||
| 320 | + | ||
| 321 | + Parameters: | ||
| 322 | + l - Galactic longitude of source location [deg] | ||
| 323 | + b - Galactic latitude of source location [deg] | ||
| 324 | + Keywords: | ||
| 325 | + flux - Source flux [Crabs] | ||
| 326 | + index - Spectral index | ||
| 327 | + type - Source type ("point", "gauss", "disk", "shell") | ||
| 328 | + fitpos - Fit position and size? (default: False) | ||
| 329 | + fitidx - Fit index? (default: False) | ||
| 330 | + """ | ||
| 331 | + # Set source location | ||
| 332 | + location = GSkyDir() | ||
| 333 | + location.lb_deg(l, b) | ||
| 334 | + | ||
| 335 | + # Set source spectrum | ||
| 336 | + spectrum = GModelSpectralPlaw(flux*5.7e-16, index, GEnergy(0.3, "TeV") | ||
| 337 | + if fitidx: | ||
| 338 | + spectrum["Index"].free() | ||
| 339 | + else: | ||
| 340 | + spectrum["Index"].fix() | ||
| 341 | + | ||
| 342 | + # Set source | ||
| 343 | + if type == "point": | ||
| 344 | + spatial = GModelSpatialPointSource(location) | ||
| 345 | + if fitpos: | ||
| 346 | + spatial["RA"].free() | ||
| 347 | + spatial["DEC"].free() | ||
| 348 | + else: | ||
| 349 | + spatial["RA"].fix() | ||
| 350 | + spatial["DEC"].fix() | ||
| 351 | + elif type == "gauss": | ||
| 352 | + spatial = GModelSpatialRadialGauss(location, self.m_radius) | ||
| 353 | + if fitpos: | ||
| 354 | + spatial["RA"].free() | ||
| 355 | + spatial["DEC"].free() | ||
| 356 | + spatial["Sigma"].free() | ||
| 357 | + else: | ||
| 358 | + spatial["RA"].fix() | ||
| 359 | + spatial["DEC"].fix() | ||
| 360 | + spatial["Sigma"].fix() | ||
| 361 | + elif type == "disk": | ||
| 362 | + spatial = GModelSpatialRadialDisk(location, self.m_radius) | ||
| 363 | + if fitpos: | ||
| 364 | + spatial["RA"].free() | ||
| 365 | + spatial["DEC"].free() | ||
| 366 | + spatial["Radius"].free() | ||
| 367 | + else: | ||
| 368 | + spatial["RA"].fix() | ||
| 369 | + spatial["DEC"].fix() | ||
| 370 | + spatial["Radius"].fix() | ||
| 371 | + elif type == "shell": | ||
| 372 | + spatial = GModelSpatialRadialShell(location, self.m_radius, self.m_width) | ||
| 373 | + if fitpos: | ||
| 374 | + spatial["RA"].free() | ||
| 375 | + spatial["DEC"].free() | ||
| 376 | + spatial["Radius"].free() | ||
| 377 | + spatial["Width"].free() | ||
| 378 | + else: | ||
| 379 | + spatial["RA"].fix() | ||
| 380 | + spatial["DEC"].fix() | ||
| 381 | + spatial["Radius"].fix() | ||
| 382 | + spatial["Width"].fix() | ||
| 383 | + else: | ||
| 384 | + self.log("ERROR: Unknown source type '"+type+"'.\n") | ||
| 385 | + return None | ||
| 386 | source = GModelSky(spatial, spectrum) | 386 | source = GModelSky(spatial, spectrum) |
| 387 | - | ||
| 388 | - # Set source name | ||
| 389 | - source.name("Test") | ||
| 390 | - | ||
| 391 | - # Return source | ||
| 392 | - return source | ||
| 393 | - | ||
| 394 | - def get_sensitivity(self, obs, bkg_model, full_model): | ||
| 395 | - """ | ||
| 396 | - Determine sensitivity for a given observations. | ||
| 397 | - | ||
| 398 | - Parameters: | ||
| 399 | - obs - Observation container | ||
| 400 | - bkg_model - Background model | ||
| 401 | - full_model - Source model | ||
| 402 | - """ | ||
| 403 | - # Set TeV->erg conversion factor | ||
| 404 | - tev2erg = 1.6021764 | ||
| 405 | - | ||
| 406 | - # Determine energy boundaries from first observation in | ||
| 407 | - # the container | ||
| 408 | - for run in obs: | ||
| 409 | - emin = run.events().ebounds().emin() | ||
| 410 | - emax = run.events().ebounds().emax() | ||
| 411 | - loge = math.log10(math.sqrt(emin.TeV()*emax.TeV())) | ||
| 412 | - erg_mean = math.pow(10.0, loge) * tev2erg | ||
| 413 | - erg_width = (emax.TeV()-emin.TeV()) * tev2erg | ||
| 414 | - break | ||
| 415 | - | ||
| 416 | - # Write header | ||
| 417 | - if self.logTerse(): | ||
| 418 | - self.log("\n") | ||
| 419 | - self.log.header2("Energies: "+str(emin)+" - "+str(emax)) | ||
| 420 | - | ||
| 421 | - # Initialise loop | ||
| 422 | - flux_value = [] | ||
| 423 | - pflux_value = [] | ||
| 424 | - eflux_value = [] | ||
| 425 | - diffSens_value = [] | ||
| 426 | - iter = 0 | ||
| 427 | - test_flux = 0.1 # This is the initial test flux in Crab units | ||
| 428 | - | ||
| 429 | - # Loop until we break | ||
| 430 | - while True: | ||
| 431 | - | ||
| 432 | - # Update iteration counter | ||
| 433 | - iter += 1 | ||
| 434 | - | ||
| 435 | - # Write header | ||
| 436 | - if self.logExplicit(): | ||
| 437 | - self.log.header2("Iteration "+str(iter)) | ||
| 438 | - | ||
| 439 | - # Set test flux | ||
| 440 | - full_model["Test"]['Prefactor'].value(test_flux) | ||
| 441 | - obs.models(full_model) | ||
| 442 | - | ||
| 443 | - # Simulate events | ||
| 444 | - sim = obsutils.sim(obs, nbins=self.m_nbins, seed=iter, \ | ||
| 445 | - binsz=self.m_binsz, npix=self.m_npix, \ | ||
| 446 | - log=self.m_log, debug=self.m_debug) | ||
| 447 | - | ||
| 448 | - # Determine number of events in simulation | ||
| 449 | - nevents = 0.0 | ||
| 450 | - for run in sim: | ||
| 451 | - nevents += run.events().number() | ||
| 452 | - | ||
| 453 | - # Write simulation results | ||
| 454 | - if self.logExplicit(): | ||
| 455 | - self.log.header3("Simulation") | ||
| 456 | - self.log.parformat("Number of simulated events") | ||
| 457 | - self.log(nevents) | ||
| 458 | - self.log("\n") | ||
| 459 | - | ||
| 460 | - # Fit background only | ||
| 461 | - sim.models(bkg_model) | ||
| 462 | - like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) | ||
| 463 | - result_bgm = like.obs().models().copy() | ||
| 464 | - LogL_bgm = like.opt().value() | ||
| 465 | - npred_bgm = like.obs().npred() | ||
| 466 | - | ||
| 467 | - # Assess quality based on a comparison between Npred and Nevents | ||
| 468 | - quality_bgm = npred_bgm-nevents | ||
| 469 | - | ||
| 470 | - # Write background fit results | ||
| 471 | - if self.logExplicit(): | ||
| 472 | - self.log.header3("Background model fit") | ||
| 473 | - self.log.parformat("log likelihood") | ||
| 474 | - self.log(LogL_bgm) | ||
| 475 | - self.log("\n") | ||
| 476 | - self.log.parformat("Number of predicted events") | ||
| 477 | - self.log(npred_bgm) | ||
| 478 | - self.log("\n") | ||
| 479 | - self.log.parformat("Fit quality") | ||
| 480 | - self.log(quality_bgm) | ||
| 481 | - self.log("\n") | ||
| 482 | - | ||
| 483 | - # Start over if the fit quality was bad | ||
| 484 | - if abs(quality_bgm) > 3.0: | ||
| 485 | - if self.logExplicit(): | ||
| 486 | - self.log("Fit quality outside required range. Start over.\n") | ||
| 487 | - continue | ||
| 488 | - | ||
| 489 | - # Write model fit results | ||
| 490 | - if self.logExplicit(): | ||
| 491 | - for model in result_bgm: | ||
| 492 | - self.log.parformat("Model") | ||
| 493 | - self.log(model.name()) | ||
| 494 | - self.log("\n") | ||
| 495 | - for par in model: | ||
| 496 | - self.log(str(par)+"\n") | ||
| 497 | - | ||
| 498 | - # Fit background and test source | ||
| 499 | - sim.models(full_model) | ||
| 500 | - like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) | ||
| 501 | - result_all = like.obs().models().copy() | ||
| 502 | - LogL_all = like.opt().value() | ||
| 503 | - npred_all = like.obs().npred() | ||
| 504 | - ts = 2.0*(LogL_bgm-LogL_all) | ||
| 505 | - | ||
| 506 | - # Assess quality based on a comparison between Npred and Nevents | ||
| 507 | - quality_all = npred_all-nevents | ||
| 508 | - | ||
| 509 | - # Write background and test source fit results | ||
| 510 | - if self.logExplicit(): | ||
| 511 | - self.log.header3("Background and test source model fit") | ||
| 512 | - self.log.parformat("Test statistics") | ||
| 513 | - self.log(ts) | ||
| 514 | - self.log("\n") | ||
| 515 | - self.log.parformat("log likelihood") | ||
| 516 | - self.log(LogL_all) | ||
| 517 | - self.log("\n") | ||
| 518 | - self.log.parformat("Number of predicted events") | ||
| 519 | - self.log(npred_all) | ||
| 520 | - self.log("\n") | ||
| 521 | - self.log.parformat("Fit quality") | ||
| 522 | - self.log(quality_all) | ||
| 523 | - self.log("\n") | ||
| 524 | - # | ||
| 525 | - for model in result_all: | ||
| 526 | - self.log.parformat("Model") | ||
| 527 | - self.log(model.name()) | ||
| 528 | - self.log("\n") | ||
| 529 | - for par in model: | ||
| 530 | - self.log(str(par)+"\n") | ||
| 531 | - | ||
| 532 | - # Start over if the fit quality was bad | ||
| 533 | - if abs(quality_all) > 3.0: | ||
| 534 | - if self.logExplicit(): | ||
| 535 | - self.log("Fit quality outside required range. Start over.\n") | ||
| 536 | - continue | ||
| 537 | - | ||
| 538 | - # Start over if TS was non-positive | ||
| 539 | - if ts <= 0.0: | ||
| 540 | - if self.logExplicit(): | ||
| 541 | - self.log("Non positive TS. Start over.\n") | ||
| 542 | - continue | ||
| 543 | - | ||
| 544 | - # Get fitted Crab, photon and energy fluxes | ||
| 545 | - cflux = result_all["Test"]['Prefactor'].value() | ||
| 546 | - cflux_err = result_all["Test"]['Prefactor'].error() | ||
| 547 | - pflux = result_all["Test"].spectral().flux(emin, emax) | ||
| 548 | - eflux = result_all["Test"].spectral().eflux(emin, emax) | ||
| 549 | - | ||
| 550 | - # Compute differential sensitivity | ||
| 551 | - diffSens = pflux / erg_width * erg_mean*erg_mean | ||
| 552 | - | ||
| 553 | - # Compute flux correction factor based on average TS | ||
| 554 | - correct = 1.0 | ||
| 555 | - if self.m_use_ts: | ||
| 556 | - if ts > 0: | ||
| 557 | - correct = math.sqrt(self.m_ts_thres/ts) | ||
| 558 | - else: | ||
| 559 | - if cflux > 0 and cflux_err > 0: | ||
| 560 | - correct = math.sqrt(self.m_ts_thres)/(cflux/cflux_err) | ||
| 561 | - | ||
| 562 | - # Compute extrapolated fluxes | ||
| 563 | - flux = correct * cflux | ||
| 564 | - pflux = correct * pflux | ||
| 565 | - eflux = correct * eflux | ||
| 566 | - diffSens = correct * diffSens | ||
| 567 | - flux_value.append(flux) | ||
| 568 | - pflux_value.append(pflux) | ||
| 569 | - eflux_value.append(eflux) | ||
| 570 | - diffSens_value.append(diffSens) | ||
| 571 | - | ||
| 572 | - # Write background and test source fit results | ||
| 573 | - if self.logExplicit(): | ||
| 574 | - self.log.parformat("Photon flux") | ||
| 575 | - self.log(pflux) | ||
| 576 | - self.log(" ph/cm2/s\n") | ||
| 577 | - self.log.parformat("Energy flux") | ||
| 578 | - self.log(eflux) | ||
| 579 | - self.log(" erg/cm2/s\n") | ||
| 580 | - self.log.parformat("Crab flux") | ||
| 581 | - self.log(cflux*1000.0) | ||
| 582 | - self.log(" mCrab\n") | ||
| 583 | - self.log.parformat("Differential sensitivity") | ||
| 584 | - self.log(diffSens) | ||
| 585 | - self.log(" erg/cm2/s\n") | ||
| 586 | - for model in result_all: | ||
| 587 | - self.log.parformat("Model") | ||
| 588 | - self.log(model.name()) | ||
| 589 | - self.log("\n") | ||
| 590 | - for par in model: | ||
| 591 | - self.log(str(par)+"\n") | ||
| 592 | - elif self.logTerse(): | ||
| 593 | - self.log.parformat("Iteration "+str(iter)) | ||
| 594 | - self.log("TS=") | ||
| 595 | - self.log(ts) | ||
| 596 | - self.log(" ") | ||
| 597 | - self.log("corr=") | ||
| 598 | - self.log(correct) | ||
| 599 | - self.log(" ") | ||
| 600 | - self.log(pflux) | ||
| 601 | - self.log(" ph/cm2/s = ") | ||
| 602 | - self.log(eflux) | ||
| 603 | - self.log(" erg/cm2/s = ") | ||
| 604 | - self.log(cflux*1000.0) | ||
| 605 | - self.log(" mCrab = ") | ||
| 606 | - self.log(diffSens) | ||
| 607 | - self.log(" erg/cm2/s\n") | ||
| 608 | - | ||
| 609 | - # Compute sliding average of extrapolated fitted prefactor, | ||
| 610 | - # photon and energy flux. This damps out fluctuations and | ||
| 611 | - # improves convergence | ||
| 612 | - flux = 0.0 | ||
| 613 | - pflux = 0.0 | ||
| 614 | - eflux = 0.0 | ||
| 615 | - diffSens = 0.0 | ||
| 616 | - num = 0.0 | ||
| 617 | - for k in range(self.m_num_avg): | ||
| 618 | - inx = len(flux_value) - k - 1 | ||
| 619 | - if inx >= 0: | ||
| 620 | - flux += flux_value[inx] | ||
| 621 | - pflux += pflux_value[inx] | ||
| 622 | - eflux += eflux_value[inx] | ||
| 623 | - diffSens += diffSens_value[inx] | ||
| 624 | - num += 1.0 | ||
| 625 | - flux /= num | ||
| 626 | - pflux /= num | ||
| 627 | - eflux /= num | ||
| 628 | - diffSens /= num | ||
| 629 | - | ||
| 630 | - # Compare average flux to last average | ||
| 631 | - if iter > self.m_num_avg: | ||
| 632 | - if test_flux > 0: | ||
| 633 | - ratio = flux/test_flux | ||
| 634 | - | ||
| 635 | - # We have 2 convergence criteria: | ||
| 636 | - # 1. The average flux does not change | ||
| 637 | - # 2. The flux correction factor is small | ||
| 638 | - if ratio >= 0.99 and ratio <= 1.01 and \ | ||
| 639 | - correct >= 0.9 and correct <= 1.1: | ||
| 640 | - if self.logTerse(): | ||
| 641 | - self.log(" Converged ("+str(ratio)+")\n") | ||
| 642 | - break | ||
| 643 | - else: | ||
| 644 | - if self.logTerse(): | ||
| 645 | - self.log(" Flux is zero.\n") | ||
| 646 | - break | ||
| 647 | - | ||
| 648 | - # Use average for next iteration | ||
| 649 | - test_flux = flux | ||
| 650 | - | ||
| 651 | - # Exit loop if number of trials exhausted | ||
| 652 | - if (iter >= self.m_max_iter): | ||
| 653 | - if self.logTerse(): | ||
| 654 | - self.log(" Test ended after "+str(self.m_max_iter)+" iterations.\n") | ||
| 655 | - break | ||
| 656 | - | ||
| 657 | - # Write fit results | ||
| 658 | - if self.logTerse(): | ||
| 659 | - self.log.header3("Fit results") | ||
| 660 | - self.log.parformat("Test statistics") | ||
| 661 | - self.log(ts) | ||
| 662 | - self.log("\n") | ||
| 663 | - self.log.parformat("Photon flux") | ||
| 664 | - self.log(pflux) | ||
| 665 | - self.log(" ph/cm2/s\n") | ||
| 666 | - self.log.parformat("Energy flux") | ||
| 667 | - self.log(eflux) | ||
| 668 | - self.log(" erg/cm2/s\n") | ||
| 669 | - self.log.parformat("Crab flux") | ||
| 670 | - self.log(cflux*1000.0) | ||
| 671 | - self.log(" mCrab\n") | ||
| 672 | - self.log.parformat("Differential sensitivity") | ||
| 673 | - self.log(diffSens) | ||
| 674 | - self.log(" erg/cm2/s\n") | ||
| 675 | - self.log.parformat("Number of simulated events") | ||
| 676 | - self.log(nevents) | ||
| 677 | - self.log("\n") | ||
| 678 | - self.log.header3("Background and test source model fitting") | ||
| 679 | - self.log.parformat("log likelihood") | ||
| 680 | - self.log(LogL_all) | ||
| 681 | - self.log("\n") | ||
| 682 | - self.log.parformat("Number of predicted events") | ||
| 683 | - self.log(npred_all) | ||
| 684 | - self.log("\n") | ||
| 685 | - for model in result_all: | ||
| 686 | - self.log.parformat("Model") | ||
| 687 | - self.log(model.name()) | ||
| 688 | - self.log("\n") | ||
| 689 | - for par in model: | ||
| 690 | - self.log(str(par)+"\n") | ||
| 691 | - self.log.header3("Background model fit") | ||
| 692 | - self.log.parformat("log likelihood") | ||
| 693 | - self.log(LogL_bgm) | ||
| 694 | - self.log("\n") | ||
| 695 | - self.log.parformat("Number of predicted events") | ||
| 696 | - self.log(npred_bgm) | ||
| 697 | - self.log("\n") | ||
| 698 | - for model in result_bgm: | ||
| 699 | - self.log.parformat("Model") | ||
| 700 | - self.log(model.name()) | ||
| 701 | - self.log("\n") | ||
| 702 | - for par in model: | ||
| 703 | - self.log(str(par)+"\n") | ||
| 704 | - | ||
| 705 | - # Store result | ||
| 706 | - result = {'loge': loge, 'emin': emin.TeV(), 'emax': emax.TeV(), \ | ||
| 707 | - 'crab': flux, 'pflux': pflux, 'eflux': eflux, \ | ||
| 708 | - 'diffSens': diffSens} | ||
| 709 | - | ||
| 710 | - # Return result | ||
| 711 | - return result | 387 | + |
| 388 | + # Set source name | ||
| 389 | + source.name("Test") | ||
| 390 | + | ||
| 391 | + # Return source | ||
| 392 | + return source | ||
| 393 | + | ||
| 394 | + def get_sensitivity(self, obs, bkg_model, full_model): | ||
| 395 | + """ | ||
| 396 | + Determine sensitivity for a given observations. | ||
| 397 | + | ||
| 398 | + Parameters: | ||
| 399 | + obs - Observation container | ||
| 400 | + bkg_model - Background model | ||
| 401 | + full_model - Source model | ||
| 402 | + """ | ||
| 403 | + # Set TeV->erg conversion factor | ||
| 404 | + tev2erg = 1.6021764 | ||
| 405 | + | ||
| 406 | + # Determine energy boundaries from first observation in | ||
| 407 | + # the container | ||
| 408 | + for run in obs: | ||
| 409 | + emin = run.events().ebounds().emin() | ||
| 410 | + emax = run.events().ebounds().emax() | ||
| 411 | + loge = math.log10(math.sqrt(emin.TeV()*emax.TeV())) | ||
| 412 | + erg_mean = math.pow(10.0, loge) * tev2erg | ||
| 413 | + erg_width = (emax.TeV()-emin.TeV()) * tev2erg | ||
| 414 | + break | ||
| 415 | + | ||
| 416 | + # Write header | ||
| 417 | + if self.logTerse(): | ||
| 418 | + self.log("\n") | ||
| 419 | + self.log.header2("Energies: "+str(emin)+" - "+str(emax)) | ||
| 420 | + | ||
| 421 | + # Initialise loop | ||
| 422 | + flux_value = [] | ||
| 423 | + pflux_value = [] | ||
| 424 | + eflux_value = [] | ||
| 425 | + diffSens_value = [] | ||
| 426 | + iter = 0 | ||
| 427 | + test_flux = 0.1 # This is the initial test flux in Crab units | ||
| 428 | + | ||
| 429 | + # Loop until we break | ||
| 430 | + while True: | ||
| 431 | + | ||
| 432 | + # Update iteration counter | ||
| 433 | + iter += 1 | ||
| 434 | + | ||
| 435 | + # Write header | ||
| 436 | + if self.logExplicit(): | ||
| 437 | + self.log.header2("Iteration "+str(iter)) | ||
| 438 | + | ||
| 439 | + # Set test flux | ||
| 440 | + full_model["Test"]['Prefactor'].value(test_flux) | ||
| 441 | + obs.models(full_model) | ||
| 442 | + | ||
| 443 | + # Simulate events | ||
| 444 | + sim = obsutils.sim(obs, nbins=self.m_nbins, seed=iter, \ | ||
| 445 | + binsz=self.m_binsz, npix=self.m_npix, \ | ||
| 446 | + log=self.m_log, debug=self.m_debug) | ||
| 447 | + | ||
| 448 | + # Determine number of events in simulation | ||
| 449 | + nevents = 0.0 | ||
| 450 | + for run in sim: | ||
| 451 | + nevents += run.events().number() | ||
| 452 | + | ||
| 453 | + # Write simulation results | ||
| 454 | + if self.logExplicit(): | ||
| 455 | + self.log.header3("Simulation") | ||
| 456 | + self.log.parformat("Number of simulated events") | ||
| 457 | + self.log(nevents) | ||
| 458 | + self.log("\n") | ||
| 459 | + | ||
| 460 | + # Fit background only | ||
| 461 | + sim.models(bkg_model) | ||
| 462 | + like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) | ||
| 463 | + result_bgm = like.obs().models().copy() | ||
| 464 | + LogL_bgm = like.opt().value() | ||
| 465 | + npred_bgm = like.obs().npred() | ||
| 466 | + | ||
| 467 | + # Assess quality based on a comparison between Npred and Nevents | ||
| 468 | + quality_bgm = npred_bgm-nevents | ||
| 469 | + | ||
| 470 | + # Write background fit results | ||
| 471 | + if self.logExplicit(): | ||
| 472 | + self.log.header3("Background model fit") | ||
| 473 | + self.log.parformat("log likelihood") | ||
| 474 | + self.log(LogL_bgm) | ||
| 475 | + self.log("\n") | ||
| 476 | + self.log.parformat("Number of predicted events") | ||
| 477 | + self.log(npred_bgm) | ||
| 478 | + self.log("\n") | ||
| 479 | + self.log.parformat("Fit quality") | ||
| 480 | + self.log(quality_bgm) | ||
| 481 | + self.log("\n") | ||
| 482 | + | ||
| 483 | + # Start over if the fit quality was bad | ||
| 484 | + if abs(quality_bgm) > 3.0: | ||
| 485 | + if self.logExplicit(): | ||
| 486 | + self.log("Fit quality outside required range. Start over.\n") | ||
| 487 | + continue | ||
| 488 | + | ||
| 489 | + # Write model fit results | ||
| 490 | + if self.logExplicit(): | ||
| 491 | + for model in result_bgm: | ||
| 492 | + self.log.parformat("Model") | ||
| 493 | + self.log(model.name()) | ||
| 494 | + self.log("\n") | ||
| 495 | + for par in model: | ||
| 496 | + self.log(str(par)+"\n") | ||
| 497 | + | ||
| 498 | + # Fit background and test source | ||
| 499 | + sim.models(full_model) | ||
| 500 | + like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) | ||
| 501 | + result_all = like.obs().models().copy() | ||
| 502 | + LogL_all = like.opt().value() | ||
| 503 | + npred_all = like.obs().npred() | ||
| 504 | + ts = 2.0*(LogL_bgm-LogL_all) | ||
| 505 | + | ||
| 506 | + # Assess quality based on a comparison between Npred and Nevents | ||
| 507 | + quality_all = npred_all-nevents | ||
| 508 | + | ||
| 509 | + # Write background and test source fit results | ||
| 510 | + if self.logExplicit(): | ||
| 511 | + self.log.header3("Background and test source model fit") | ||
| 512 | + self.log.parformat("Test statistics") | ||
| 513 | + self.log(ts) | ||
| 514 | + self.log("\n") | ||
| 515 | + self.log.parformat("log likelihood") | ||
| 516 | + self.log(LogL_all) | ||
| 517 | + self.log("\n") | ||
| 518 | + self.log.parformat("Number of predicted events") | ||
| 519 | + self.log(npred_all) | ||
| 520 | + self.log("\n") | ||
| 521 | + self.log.parformat("Fit quality") | ||
| 522 | + self.log(quality_all) | ||
| 523 | + self.log("\n") | ||
| 524 | + # | ||
| 525 | + for model in result_all: | ||
| 526 | + self.log.parformat("Model") | ||
| 527 | + self.log(model.name()) | ||
| 528 | + self.log("\n") | ||
| 529 | + for par in model: | ||
| 530 | + self.log(str(par)+"\n") | ||
| 531 | + | ||
| 532 | + # Start over if the fit quality was bad | ||
| 533 | + if abs(quality_all) > 3.0: | ||
| 534 | + if self.logExplicit(): | ||
| 535 | + self.log("Fit quality outside required range. Start over.\n") | ||
| 536 | + continue | ||
| 537 | + | ||
| 538 | + # Start over if TS was non-positive | ||
| 539 | + if ts <= 0.0: | ||
| 540 | + if self.logExplicit(): | ||
| 541 | + self.log("Non positive TS. Start over.\n") | ||
| 542 | + continue | ||
| 543 | + | ||
| 544 | + # Get fitted Crab, photon and energy fluxes | ||
| 545 | + cflux = result_all["Test"]['Prefactor'].value() | ||
| 546 | + cflux_err = result_all["Test"]['Prefactor'].error() | ||
| 547 | + pflux = result_all["Test"].spectral().flux(emin, emax) | ||
| 548 | + eflux = result_all["Test"].spectral().eflux(emin, emax) | ||
| 549 | + | ||
| 550 | + # Compute differential sensitivity | ||
| 551 | + diffSens = pflux / erg_width * erg_mean*erg_mean | ||
| 552 | + | ||
| 553 | + # Compute flux correction factor based on average TS | ||
| 554 | + correct = 1.0 | ||
| 555 | + if self.m_use_ts: | ||
| 556 | + if ts > 0: | ||
| 557 | + correct = math.sqrt(self.m_ts_thres/ts) | ||
| 558 | + else: | ||
| 559 | + if cflux > 0 and cflux_err > 0: | ||
| 560 | + correct = math.sqrt(self.m_ts_thres)/(cflux/cflux_err) | ||
| 561 | + | ||
| 562 | + # Compute extrapolated fluxes | ||
| 563 | + flux = correct * cflux | ||
| 564 | + pflux = correct * pflux | ||
| 565 | + eflux = correct * eflux | ||
| 566 | + diffSens = correct * diffSens | ||
| 567 | + flux_value.append(flux) | ||
| 568 | + pflux_value.append(pflux) | ||
| 569 | + eflux_value.append(eflux) | ||
| 570 | + diffSens_value.append(diffSens) | ||
| 571 | + | ||
| 572 | + # Write background and test source fit results | ||
| 573 | + if self.logExplicit(): | ||
| 574 | + self.log.parformat("Photon flux") | ||
| 575 | + self.log(pflux) | ||
| 576 | + self.log(" ph/cm2/s\n") | ||
| 577 | + self.log.parformat("Energy flux") | ||
| 578 | + self.log(eflux) | ||
| 579 | + self.log(" erg/cm2/s\n") | ||
| 580 | + self.log.parformat("Crab flux") | ||
| 581 | + self.log(cflux*1000.0) | ||
| 582 | + self.log(" mCrab\n") | ||
| 583 | + self.log.parformat("Differential sensitivity") | ||
| 584 | + self.log(diffSens) | ||
| 585 | + self.log(" erg/cm2/s\n") | ||
| 586 | + for model in result_all: | ||
| 587 | + self.log.parformat("Model") | ||
| 588 | + self.log(model.name()) | ||
| 589 | + self.log("\n") | ||
| 590 | + for par in model: | ||
| 591 | + self.log(str(par)+"\n") | ||
| 592 | + elif self.logTerse(): | ||
| 593 | + self.log.parformat("Iteration "+str(iter)) | ||
| 594 | + self.log("TS=") | ||
| 595 | + self.log(ts) | ||
| 596 | + self.log(" ") | ||
| 597 | + self.log("corr=") | ||
| 598 | + self.log(correct) | ||
| 599 | + self.log(" ") | ||
| 600 | + self.log(pflux) | ||
| 601 | + self.log(" ph/cm2/s = ") | ||
| 602 | + self.log(eflux) | ||
| 603 | + self.log(" erg/cm2/s = ") | ||
| 604 | + self.log(cflux*1000.0) | ||
| 605 | + self.log(" mCrab = ") | ||
| 606 | + self.log(diffSens) | ||
| 607 | + self.log(" erg/cm2/s\n") | ||
| 608 | + | ||
| 609 | + # Compute sliding average of extrapolated fitted prefactor, | ||
| 610 | + # photon and energy flux. This damps out fluctuations and | ||
| 611 | + # improves convergence | ||
| 612 | + flux = 0.0 | ||
| 613 | + pflux = 0.0 | ||
| 614 | + eflux = 0.0 | ||
| 615 | + diffSens = 0.0 | ||
| 616 | + num = 0.0 | ||
| 617 | + for k in range(self.m_num_avg): | ||
| 618 | + inx = len(flux_value) - k - 1 | ||
| 619 | + if inx >= 0: | ||
| 620 | + flux += flux_value[inx] | ||
| 621 | + pflux += pflux_value[inx] | ||
| 622 | + eflux += eflux_value[inx] | ||
| 623 | + diffSens += diffSens_value[inx] | ||
| 624 | + num += 1.0 | ||
| 625 | + flux /= num | ||
| 626 | + pflux /= num | ||
| 627 | + eflux /= num | ||
| 628 | + diffSens /= num | ||
| 629 | + | ||
| 630 | + # Compare average flux to last average | ||
| 631 | + if iter > self.m_num_avg: | ||
| 632 | + if test_flux > 0: | ||
| 633 | + ratio = flux/test_flux | ||
| 634 | + | ||
| 635 | + # We have 2 convergence criteria: | ||
| 636 | + # 1. The average flux does not change | ||
| 637 | + # 2. The flux correction factor is small | ||
| 638 | + if ratio >= 0.99 and ratio <= 1.01 and \ | ||
| 639 | + correct >= 0.9 and correct <= 1.1: | ||
| 640 | + if self.logTerse(): | ||
| 641 | + self.log(" Converged ("+str(ratio)+")\n") | ||
| 642 | + break | ||
| 643 | + else: | ||
| 644 | + if self.logTerse(): | ||
| 645 | + self.log(" Flux is zero.\n") | ||
| 646 | + break | ||
| 647 | + | ||
| 648 | + # Use average for next iteration | ||
| 649 | + test_flux = flux | ||
| 650 | + | ||
| 651 | + # Exit loop if number of trials exhausted | ||
| 652 | + if (iter >= self.m_max_iter): | ||
| 653 | + if self.logTerse(): | ||
| 654 | + self.log(" Test ended after "+str(self.m_max_iter)+" iterations.\n") | ||
| 655 | + break | ||
| 656 | + | ||
| 657 | + # Write fit results | ||
| 658 | + if self.logTerse(): | ||
| 659 | + self.log.header3("Fit results") | ||
| 660 | + self.log.parformat("Test statistics") | ||
| 661 | + self.log(ts) | ||
| 662 | + self.log("\n") | ||
| 663 | + self.log.parformat("Photon flux") | ||
| 664 | + self.log(pflux) | ||
| 665 | + self.log(" ph/cm2/s\n") | ||
| 666 | + self.log.parformat("Energy flux") | ||
| 667 | + self.log(eflux) | ||
| 668 | + self.log(" erg/cm2/s\n") | ||
| 669 | + self.log.parformat("Crab flux") | ||
| 670 | + self.log(cflux*1000.0) | ||
| 671 | + self.log(" mCrab\n") | ||
| 672 | + self.log.parformat("Differential sensitivity") | ||
| 673 | + self.log(diffSens) | ||
| 674 | + self.log(" erg/cm2/s\n") | ||
| 675 | + self.log.parformat("Number of simulated events") | ||
| 676 | + self.log(nevents) | ||
| 677 | + self.log("\n") | ||
| 678 | + self.log.header3("Background and test source model fitting") | ||
| 679 | + self.log.parformat("log likelihood") | ||
| 680 | + self.log(LogL_all) | ||
| 681 | + self.log("\n") | ||
| 682 | + self.log.parformat("Number of predicted events") | ||
| 683 | + self.log(npred_all) | ||
| 684 | + self.log("\n") | ||
| 685 | + for model in result_all: | ||
| 686 | + self.log.parformat("Model") | ||
| 687 | + self.log(model.name()) | ||
| 688 | + self.log("\n") | ||
| 689 | + for par in model: | ||
| 690 | + self.log(str(par)+"\n") | ||
| 691 | + self.log.header3("Background model fit") | ||
| 692 | + self.log.parformat("log likelihood") | ||
| 693 | + self.log(LogL_bgm) | ||
| 694 | + self.log("\n") | ||
| 695 | + self.log.parformat("Number of predicted events") | ||
| 696 | + self.log(npred_bgm) | ||
| 697 | + self.log("\n") | ||
| 698 | + for model in result_bgm: | ||
| 699 | + self.log.parformat("Model") | ||
| 700 | + self.log(model.name()) | ||
| 701 | + self.log("\n") | ||
| 702 | + for par in model: | ||
| 703 | + self.log(str(par)+"\n") | ||
| 704 | + | ||
| 705 | + # Store result | ||
| 706 | + result = {'loge': loge, 'emin': emin.TeV(), 'emax': emax.TeV(), \ | ||
| 707 | + 'crab': flux, 'pflux': pflux, 'eflux': eflux, \ | ||
| 708 | + 'diffSens': diffSens} | ||
| 709 | + | ||
| 710 | + # Return result | ||
| 711 | + return result | ||
| 712 | 712 | ||
| 713 | 713 | ||
| 714 | # ======================== # | 714 | # ======================== # |
| 715 | # Main routine entry point # | 715 | # Main routine entry point # |
| 716 | # ======================== # | 716 | # ======================== # |
| 717 | if __name__ == '__main__': | 717 | if __name__ == '__main__': |
| 718 | - """ | ||
| 719 | - CTA ctlike-based sensitivity estimator. | ||
| 720 | - """ | ||
| 721 | - # Create instance of application | ||
| 722 | - app = cssens(sys.argv) | ||
| 723 | - | ||
| 724 | - # Run application | ||
| 725 | - app.execute() | ||
| 726 | - | ||
| 727 | \ No newline at end of file | 718 | \ No newline at end of file |
| 719 | + """ | ||
| 720 | + CTA ctlike-based sensitivity estimator. | ||
| 721 | + """ | ||
| 722 | + # Create instance of application | ||
| 723 | + app = cssens(sys.argv) | ||
| 724 | + | ||
| 725 | + # Run application | ||
| 726 | + app.execute() | ||
| 727 | + | ||
| 728 | \ No newline at end of file | 728 | \ No newline at end of file |
scripts/cstsdist.py
| @@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
| 3 | # This script generates the TS distribution for a particular model based | 3 | # This script generates the TS distribution for a particular model based |
| 4 | # on Monte-Carlo simulations. | 4 | # on Monte-Carlo simulations. |
| 5 | # | 5 | # |
| 6 | -# Copyright (C) 2011-2013 Jurgen Knodlseder | 6 | +# Copyright (C) 2011-2014 Juergen Knoedlseder |
| 7 | # | 7 | # |
| 8 | # This program is free software: you can redistribute it and/or modify | 8 | # This program is free software: you can redistribute it and/or modify |
| 9 | # it under the terms of the GNU General Public License as published by | 9 | # it under the terms of the GNU General Public License as published by |
| @@ -31,486 +31,486 @@ import math | @@ -31,486 +31,486 @@ import math | ||
| 31 | # cstsdist class # | 31 | # cstsdist class # |
| 32 | # ============== # | 32 | # ============== # |
| 33 | class cstsdist(GApplication): | 33 | class cstsdist(GApplication): |
| 34 | - """ | ||
| 35 | - This class implements the TS distribution generation script. It derives | ||
| 36 | - from the GammaLib::GApplication class which provides support for parameter | ||
| 37 | - files, command line arguments, and logging. In that way the Python | ||
| 38 | - script behaves just as a regular ctool. | ||
| 39 | - """ | ||
| 40 | - def __init__(self, *argv): | ||
| 41 | - """ | ||
| 42 | - Constructor. | ||
| 43 | - """ | ||
| 44 | - # Set name | ||
| 45 | - self.name = "cstsdist" | ||
| 46 | - self.version = "0.1.0" | ||
| 47 | - | ||
| 48 | - # Initialise some members | ||
| 49 | - self.obs = None | ||
| 50 | - self.bkg_model = None | ||
| 51 | - self.full_model = None | ||
| 52 | - | ||
| 53 | - # Make sure that parfile exists | ||
| 54 | - file = self.parfile() | 34 | + """ |
| 35 | + This class implements the TS distribution generation script. It derives | ||
| 36 | + from the GammaLib::GApplication class which provides support for parameter | ||
| 37 | + files, command line arguments, and logging. In that way the Python | ||
| 38 | + script behaves just as a regular ctool. | ||
| 39 | + """ | ||
| 40 | + def __init__(self, *argv): | ||
| 41 | + """ | ||
| 42 | + Constructor. | ||
| 43 | + """ | ||
| 44 | + # Set name | ||
| 45 | + self.name = "cstsdist" | ||
| 46 | + self.version = "0.1.0" | ||
| 47 | + | ||
| 48 | + # Initialise some members | ||
| 49 | + self.obs = None | ||
| 50 | + self.bkg_model = None | ||
| 51 | + self.full_model = None | ||
| 52 | + | ||
| 53 | + # Make sure that parfile exists | ||
| 54 | + file = self.parfile() | ||
| 55 | 55 | ||
| 56 | - # Initialise application | ||
| 57 | - if len(argv) == 0: | ||
| 58 | - GApplication.__init__(self, self.name, self.version) | ||
| 59 | - elif len(argv) ==1: | ||
| 60 | - GApplication.__init__(self, self.name, self.version, *argv) | ||
| 61 | - else: | ||
| 62 | - raise TypeError("Invalid number of arguments given.") | 56 | + # Initialise application |
| 57 | + if len(argv) == 0: | ||
| 58 | + GApplication.__init__(self, self.name, self.version) | ||
| 59 | + elif len(argv) ==1: | ||
| 60 | + GApplication.__init__(self, self.name, self.version, *argv) | ||
| 61 | + else: | ||
| 62 | + raise TypeError("Invalid number of arguments given.") | ||
| 63 | 63 | ||
| 64 | - # Set logger properties | ||
| 65 | - self.log_header() | ||
| 66 | - self.log.date(True) | 64 | + # Set logger properties |
| 65 | + self.log_header() | ||
| 66 | + self.log.date(True) | ||
| 67 | 67 | ||
| 68 | - # Return | ||
| 69 | - return | ||
| 70 | - | ||
| 71 | - def __del__(self): | ||
| 72 | - """ | ||
| 73 | - Destructor. | ||
| 74 | - """ | ||
| 75 | - # Write separator into logger | ||
| 76 | - if self.logTerse(): | ||
| 77 | - self.log("\n") | ||
| 78 | - | ||
| 79 | - # Return | ||
| 80 | - return | 68 | + # Return |
| 69 | + return | ||
| 70 | + | ||
| 71 | + def __del__(self): | ||
| 72 | + """ | ||
| 73 | + Destructor. | ||
| 74 | + """ | ||
| 75 | + # Write separator into logger | ||
| 76 | + if self.logTerse(): | ||
| 77 | + self.log("\n") | ||
| 78 | + | ||
| 79 | + # Return | ||
| 80 | + return | ||
| 81 | 81 | ||
| 82 | - def parfile(self): | ||
| 83 | - """ | ||
| 84 | - Check if parfile exists. If parfile does not exist then create a | ||
| 85 | - default parfile. This kluge avoids shipping the cscript with a parfile. | ||
| 86 | - """ | ||
| 87 | - # Set parfile name | ||
| 88 | - parfile = self.name+".par" | ||
| 89 | - | ||
| 90 | - try: | ||
| 91 | - pars = GApplicationPars(parfile) | ||
| 92 | - except: | ||
| 93 | - # Signal if parfile was not found | ||
| 94 | - sys.stdout.write("Parfile "+parfile+" not found. Create default parfile.\n") | ||
| 95 | - | ||
| 96 | - # Create default parfile | ||
| 97 | - pars = GApplicationPars() | ||
| 98 | - pars.append(GApplicationPar("outfile","f","h","ts.dat","","","Output file name")) | ||
| 99 | - pars.append(GApplicationPar("ntrials","i","a","10","","","Number of trials")) | ||
| 100 | - pars.append(GApplicationPar("caldb","s","a","$GAMMALIB/share/caldb/cta","","","Calibration database")) | ||
| 101 | - pars.append(GApplicationPar("irf","s","a","cta_dummy_irf","","","Instrument response function")) | ||
| 102 | - pars.append(GApplicationPar("type","s","a","point","","","Source model type (point/gauss/shell/disk)")) | ||
| 103 | - pars.append(GApplicationPar("index","r","h","-2.48","","","Spectral index")) | ||
| 104 | - pars.append(GApplicationPar("offset","r","a","0.0","0.0","","Source offset angle (deg)")) | ||
| 105 | - pars.append(GApplicationPar("bkg","s","a","$GAMMALIB/share/models/bkg_dummy.txt","","","Background model file function (none=power law for E)")) | ||
| 106 | - pars.append(GApplicationPar("emin","r","a","0.1","0.0","","Lower energy limit (TeV)")) | ||
| 107 | - pars.append(GApplicationPar("emax","r","a","100.0","0.0","","Upper energy limit (TeV)")) | ||
| 108 | - pars.append(GApplicationPar("enumbins","i","a","0","","","Number of energy bins (0=unbinned)")) | ||
| 109 | - pars.append(GApplicationPar("duration","r","a","180000.0","","","Effective exposure time (s)")) | ||
| 110 | - pars.append(GApplicationPar("rad","r","h","5.0","","","Radius of ROI (deg)")) | ||
| 111 | - pars.append(GApplicationPar("npix","i","h","200","","","Number of pixels for binned")) | ||
| 112 | - pars.append(GApplicationPar("binsz","r","h","0.05","","","Pixel size for binned (deg/pixel)")) | ||
| 113 | - pars.append_standard() | ||
| 114 | - pars.save(parfile) | ||
| 115 | - | ||
| 116 | - # Return | ||
| 117 | - return | ||
| 118 | - | ||
| 119 | - def get_parameters(self): | ||
| 120 | - """ | ||
| 121 | - Get parameters from parfile and setup the observation. | ||
| 122 | - """ | ||
| 123 | - # Get parameters | ||
| 124 | - self.m_outfile = self["outfile"].filename() | ||
| 125 | - self.m_ntrials = self["ntrials"].integer() | ||
| 126 | - self.m_caldb = self["caldb"].string() | ||
| 127 | - self.m_irf = self["irf"].string() | ||
| 128 | - self.m_type = self["type"].string() | ||
| 129 | - self.m_index = self["index"].real() | ||
| 130 | - self.m_offset = self["offset"].real() | ||
| 131 | - self.m_bkg = self["bkg"].string() | ||
| 132 | - self.m_emin = self["emin"].real() | ||
| 133 | - self.m_emax = self["emax"].real() | ||
| 134 | - self.m_enumbins = self["enumbins"].integer() | ||
| 135 | - self.m_duration = self["duration"].real() | ||
| 136 | - self.m_rad = self["rad"].real() | ||
| 137 | - self.m_npix = self["npix"].integer() | ||
| 138 | - self.m_binsz = self["binsz"].real() | 82 | + def parfile(self): |
| 83 | + """ | ||
| 84 | + Check if parfile exists. If parfile does not exist then create a | ||
| 85 | + default parfile. This kluge avoids shipping the cscript with a parfile. | ||
| 86 | + """ | ||
| 87 | + # Set parfile name | ||
| 88 | + parfile = self.name+".par" | ||
| 89 | + | ||
| 90 | + try: | ||
| 91 | + pars = GApplicationPars(parfile) | ||
| 92 | + except: | ||
| 93 | + # Signal if parfile was not found | ||
| 94 | + sys.stdout.write("Parfile "+parfile+" not found. Create default parfile.\n") | ||
| 95 | + | ||
| 96 | + # Create default parfile | ||
| 97 | + pars = GApplicationPars() | ||
| 98 | + pars.append(GApplicationPar("outfile","f","h","ts.dat","","","Output file name")) | ||
| 99 | + pars.append(GApplicationPar("ntrials","i","a","10","","","Number of trials")) | ||
| 100 | + pars.append(GApplicationPar("caldb","s","a","$GAMMALIB/share/caldb/cta","","","Calibration database")) | ||
| 101 | + pars.append(GApplicationPar("irf","s","a","cta_dummy_irf","","","Instrument response function")) | ||
| 102 | + pars.append(GApplicationPar("type","s","a","point","","","Source model type (point/gauss/shell/disk)")) | ||
| 103 | + pars.append(GApplicationPar("index","r","h","-2.48","","","Spectral index")) | ||
| 104 | + pars.append(GApplicationPar("offset","r","a","0.0","0.0","","Source offset angle (deg)")) | ||
| 105 | + pars.append(GApplicationPar("bkg","s","a","$GAMMALIB/share/models/bkg_dummy.txt","","","Background model file function (none=power law for E)")) | ||
| 106 | + pars.append(GApplicationPar("emin","r","a","0.1","0.0","","Lower energy limit (TeV)")) | ||
| 107 | + pars.append(GApplicationPar("emax","r","a","100.0","0.0","","Upper energy limit (TeV)")) | ||
| 108 | + pars.append(GApplicationPar("enumbins","i","a","0","","","Number of energy bins (0=unbinned)")) | ||
| 109 | + pars.append(GApplicationPar("duration","r","a","180000.0","","","Effective exposure time (s)")) | ||
| 110 | + pars.append(GApplicationPar("rad","r","h","5.0","","","Radius of ROI (deg)")) | ||
| 111 | + pars.append(GApplicationPar("npix","i","h","200","","","Number of pixels for binned")) | ||
| 112 | + pars.append(GApplicationPar("binsz","r","h","0.05","","","Pixel size for binned (deg/pixel)")) | ||
| 113 | + pars.append_standard() | ||
| 114 | + pars.save(parfile) | ||
| 115 | + | ||
| 116 | + # Return | ||
| 117 | + return | ||
| 118 | + | ||
| 119 | + def get_parameters(self): | ||
| 120 | + """ | ||
| 121 | + Get parameters from parfile and setup the observation. | ||
| 122 | + """ | ||
| 123 | + # Get parameters | ||
| 124 | + self.m_outfile = self["outfile"].filename() | ||
| 125 | + self.m_ntrials = self["ntrials"].integer() | ||
| 126 | + self.m_caldb = self["caldb"].string() | ||
| 127 | + self.m_irf = self["irf"].string() | ||
| 128 | + self.m_type = self["type"].string() | ||
| 129 | + self.m_index = self["index"].real() | ||
| 130 | + self.m_offset = self["offset"].real() | ||
| 131 | + self.m_bkg = self["bkg"].string() | ||
| 132 | + self.m_emin = self["emin"].real() | ||
| 133 | + self.m_emax = self["emax"].real() | ||
| 134 | + self.m_enumbins = self["enumbins"].integer() | ||
| 135 | + self.m_duration = self["duration"].real() | ||
| 136 | + self.m_rad = self["rad"].real() | ||
| 137 | + self.m_npix = self["npix"].integer() | ||
| 138 | + self.m_binsz = self["binsz"].real() | ||
| 139 | 139 | ||
| 140 | - # Set some fixed parameters | ||
| 141 | - self.m_log = False # Logging in client tools | ||
| 142 | - self.m_debug = False # Debugging in client tools | ||
| 143 | - | ||
| 144 | - # Setup observation | ||
| 145 | - self.obs = self.set_obs(emin=self.m_emin, emax=self.m_emax) | ||
| 146 | - | ||
| 147 | - # Initialise models. Note that we centre the point source at the Galactic | ||
| 148 | - # center as our observation is also centred at the Galactic centre, so | ||
| 149 | - # we're onaxis. | ||
| 150 | - self.bkg_model = GModels() | ||
| 151 | - self.full_model = GModels() | ||
| 152 | - self.bkg_model.append(self.set_bkg_model()) | ||
| 153 | - self.full_model.append(self.set_bkg_model()) | ||
| 154 | - self.full_model.append(self.set_src_model(0.0, self.m_offset, \ | ||
| 155 | - flux=0.010, \ | ||
| 156 | - type=self.m_type, \ | ||
| 157 | - index=self.m_index)) | 140 | + # Set some fixed parameters |
| 141 | + self.m_log = False # Logging in client tools | ||
| 142 | + self.m_debug = False # Debugging in client tools | ||
| 143 | + | ||
| 144 | + # Setup observation | ||
| 145 | + self.obs = self.set_obs(emin=self.m_emin, emax=self.m_emax) | ||
| 146 | + | ||
| 147 | + # Initialise models. Note that we centre the point source at the Galactic | ||
| 148 | + # center as our observation is also centred at the Galactic centre, so | ||
| 149 | + # we're onaxis. | ||
| 150 | + self.bkg_model = GModels() | ||
| 151 | + self.full_model = GModels() | ||
| 152 | + self.bkg_model.append(self.set_bkg_model()) | ||
| 153 | + self.full_model.append(self.set_bkg_model()) | ||
| 154 | + self.full_model.append(self.set_src_model(0.0, self.m_offset, \ | ||
| 155 | + flux=0.010, \ | ||
| 156 | + type=self.m_type, \ | ||
| 157 | + index=self.m_index)) | ||
| 158 | 158 | ||
| 159 | - # Attach background model to observation container | ||
| 160 | - self.obs.models(self.bkg_model) | ||
| 161 | - | ||
| 162 | - # Return | ||
| 163 | - return | ||
| 164 | - | ||
| 165 | - def models(self, models): | ||
| 166 | - """ | ||
| 167 | - Set model. | ||
| 168 | - """ | ||
| 169 | - # Copy models | ||
| 170 | - self.model = models.copy() | ||
| 171 | - | ||
| 172 | - # Return | ||
| 173 | - return | ||
| 174 | - | ||
| 175 | - def execute(self): | ||
| 176 | - """ | ||
| 177 | - Execute the script. | ||
| 178 | - """ | ||
| 179 | - # Run the script | ||
| 180 | - self.run() | ||
| 181 | - | ||
| 182 | - # Return | ||
| 183 | - return | 159 | + # Attach background model to observation container |
| 160 | + self.obs.models(self.bkg_model) | ||
| 161 | + | ||
| 162 | + # Return | ||
| 163 | + return | ||
| 164 | + | ||
| 165 | + def models(self, models): | ||
| 166 | + """ | ||
| 167 | + Set model. | ||
| 168 | + """ | ||
| 169 | + # Copy models | ||
| 170 | + self.model = models.copy() | ||
| 171 | + | ||
| 172 | + # Return | ||
| 173 | + return | ||
| 174 | + | ||
| 175 | + def execute(self): | ||
| 176 | + """ | ||
| 177 | + Execute the script. | ||
| 178 | + """ | ||
| 179 | + # Run the script | ||
| 180 | + self.run() | ||
| 181 | + | ||
| 182 | + # Return | ||
| 183 | + return | ||
| 184 | 184 | ||
| 185 | - def run(self): | ||
| 186 | - """ | ||
| 187 | - Run the script. | ||
| 188 | - """ | ||
| 189 | - # Switch screen logging on in debug mode | ||
| 190 | - if self.logDebug(): | ||
| 191 | - self.log.cout(True) | 185 | + def run(self): |
| 186 | + """ | ||
| 187 | + Run the script. | ||
| 188 | + """ | ||
| 189 | + # Switch screen logging on in debug mode | ||
| 190 | + if self.logDebug(): | ||
| 191 | + self.log.cout(True) | ||
| 192 | 192 | ||
| 193 | - # Get parameters | ||
| 194 | - self.get_parameters() | ||
| 195 | - | ||
| 196 | - # Write input parameters into logger | ||
| 197 | - if self.logTerse(): | ||
| 198 | - self.log_parameters() | ||
| 199 | - self.log("\n") | ||
| 200 | - | ||
| 201 | - # Write observation into logger | ||
| 202 | - if self.logTerse(): | ||
| 203 | - self.log("\n") | ||
| 204 | - self.log.header1("Observation") | ||
| 205 | - self.log(str(self.obs)) | ||
| 206 | - self.log("\n") | 193 | + # Get parameters |
| 194 | + self.get_parameters() | ||
| 195 | + | ||
| 196 | + # Write input parameters into logger | ||
| 197 | + if self.logTerse(): | ||
| 198 | + self.log_parameters() | ||
| 199 | + self.log("\n") | ||
| 200 | + | ||
| 201 | + # Write observation into logger | ||
| 202 | + if self.logTerse(): | ||
| 203 | + self.log("\n") | ||
| 204 | + self.log.header1("Observation") | ||
| 205 | + self.log(str(self.obs)) | ||
| 206 | + self.log("\n") | ||
| 207 | 207 | ||
| 208 | - # Write models into logger | ||
| 209 | - if self.logTerse(): | ||
| 210 | - self.log("\n") | ||
| 211 | - self.log.header1("Test model") | ||
| 212 | - self.log(str(self.full_model)) | ||
| 213 | - self.log("\n") | 208 | + # Write models into logger |
| 209 | + if self.logTerse(): | ||
| 210 | + self.log("\n") | ||
| 211 | + self.log.header1("Test model") | ||
| 212 | + self.log(str(self.full_model)) | ||
| 213 | + self.log("\n") | ||
| 214 | 214 | ||
| 215 | - # Write header | ||
| 216 | - if self.logTerse(): | ||
| 217 | - self.log("\n") | ||
| 218 | - self.log.header1("Generate TS distribution") | 215 | + # Write header |
| 216 | + if self.logTerse(): | ||
| 217 | + self.log("\n") | ||
| 218 | + self.log.header1("Generate TS distribution") | ||
| 219 | 219 | ||
| 220 | - # Loop over trials | ||
| 221 | - for seed in range(self.m_ntrials): | ||
| 222 | - | ||
| 223 | - # Make a trial | ||
| 224 | - result = self.trial(seed) | ||
| 225 | - | ||
| 226 | - # Write out result immediately | ||
| 227 | - if seed == 0: | ||
| 228 | - file = open(self.m_outfile, 'w') | ||
| 229 | - writer = csv.DictWriter(file, result['colnames']) | ||
| 230 | - writer.writerow(dict((_,_) for _ in result['colnames'])) | ||
| 231 | - else: | ||
| 232 | - file = open(self.m_outfile, 'a') | ||
| 233 | - writer = csv.DictWriter(file, result['colnames']) | ||
| 234 | - writer.writerow(result['values']) | ||
| 235 | - file.close() | ||
| 236 | - | ||
| 237 | - # Return | ||
| 238 | - return | ||
| 239 | - | ||
| 240 | - def set_obs(self, lpnt=0.0, bpnt=0.0, emin=0.1, emax=100.0): | ||
| 241 | - """ | ||
| 242 | - Returns an observation container with a single CTA observation. | ||
| 243 | - | ||
| 244 | - Keywords: | ||
| 245 | - lpnt - Galactic longitude of pointing [deg] (default: 0.0) | ||
| 246 | - bpnt - Galactic latitude of pointing [deg] (default: 0.0) | ||
| 247 | - emin - Minimum energy [TeV] (default: 0.1) | ||
| 248 | - emax - Maximum energy [TeV] (default: 100.0) | ||
| 249 | - """ | ||
| 250 | - # Allocate observation container | ||
| 251 | - obs = GObservations() | ||
| 252 | - | ||
| 253 | - # Set single pointing | ||
| 254 | - pntdir = GSkyDir() | ||
| 255 | - pntdir.lb_deg(lpnt, bpnt) | ||
| 256 | - | ||
| 257 | - # Create CTA observation | ||
| 258 | - run = obsutils.set(pntdir, caldb=self.m_caldb, irf=self.m_irf, \ | ||
| 259 | - duration=self.m_duration, \ | 220 | + # Loop over trials |
| 221 | + for seed in range(self.m_ntrials): | ||
| 222 | + | ||
| 223 | + # Make a trial | ||
| 224 | + result = self.trial(seed) | ||
| 225 | + | ||
| 226 | + # Write out result immediately | ||
| 227 | + if seed == 0: | ||
| 228 | + file = open(self.m_outfile, 'w') | ||
| 229 | + writer = csv.DictWriter(file, result['colnames']) | ||
| 230 | + writer.writerow(dict((_,_) for _ in result['colnames'])) | ||
| 231 | + else: | ||
| 232 | + file = open(self.m_outfile, 'a') | ||
| 233 | + writer = csv.DictWriter(file, result['colnames']) | ||
| 234 | + writer.writerow(result['values']) | ||
| 235 | + file.close() | ||
| 236 | + | ||
| 237 | + # Return | ||
| 238 | + return | ||
| 239 | + | ||
| 240 | + def set_obs(self, lpnt=0.0, bpnt=0.0, emin=0.1, emax=100.0): | ||
| 241 | + """ | ||
| 242 | + Returns an observation container with a single CTA observation. | ||
| 243 | + | ||
| 244 | + Keywords: | ||
| 245 | + lpnt - Galactic longitude of pointing [deg] (default: 0.0) | ||
| 246 | + bpnt - Galactic latitude of pointing [deg] (default: 0.0) | ||
| 247 | + emin - Minimum energy [TeV] (default: 0.1) | ||
| 248 | + emax - Maximum energy [TeV] (default: 100.0) | ||
| 249 | + """ | ||
| 250 | + # Allocate observation container | ||
| 251 | + obs = GObservations() | ||
| 252 | + | ||
| 253 | + # Set single pointing | ||
| 254 | + pntdir = GSkyDir() | ||
| 255 | + pntdir.lb_deg(lpnt, bpnt) | ||
| 256 | + | ||
| 257 | + # Create CTA observation | ||
| 258 | + run = obsutils.set(pntdir, caldb=self.m_caldb, irf=self.m_irf, \ | ||
| 259 | + duration=self.m_duration, \ | ||
| 260 | emin=emin, emax=emax, rad=self.m_rad) | 260 | emin=emin, emax=emax, rad=self.m_rad) |
| 261 | - | ||
| 262 | - # Append observation to container | ||
| 263 | - obs.append(run) | ||
| 264 | - | ||
| 265 | - # Return observation container | ||
| 266 | - return obs | ||
| 267 | - | ||
| 268 | - def set_bkg_model(self, fitsigma=False): | ||
| 269 | - """ | ||
| 270 | - Setup CTA background model. | ||
| 271 | - """ | ||
| 272 | - # Define radial component | ||
| 273 | - radial = GCTAModelRadialGauss(3.0) | ||
| 274 | - if fitsigma: | ||
| 275 | - radial["Sigma"].free() | ||
| 276 | - else: | ||
| 277 | - radial["Sigma"].fix() | ||
| 278 | - | ||
| 279 | - # Define spectral component | ||
| 280 | - spectrum = GModelSpectralFunc(self.m_bkg, 1.0) | ||
| 281 | - | ||
| 282 | - # Create background model | ||
| 283 | - model = GCTAModelRadialAcceptance(radial, spectrum) | ||
| 284 | - model.name("Background") | ||
| 285 | - model.instruments("CTA") | ||
| 286 | - | ||
| 287 | - # Return background model | ||
| 288 | - return model | ||
| 289 | - | ||
| 290 | - def set_src_model(self, l, b, flux=1.0, index=-2.48, \ | 261 | + |
| 262 | + # Append observation to container | ||
| 263 | + obs.append(run) | ||
| 264 | + | ||
| 265 | + # Return observation container | ||
| 266 | + return obs | ||
| 267 | + | ||
| 268 | + def set_bkg_model(self, fitsigma=False): | ||
| 269 | + """ | ||
| 270 | + Setup CTA background model. | ||
| 271 | + """ | ||
| 272 | + # Define radial component | ||
| 273 | + radial = GCTAModelRadialGauss(3.0) | ||
| 274 | + if fitsigma: | ||
| 275 | + radial["Sigma"].free() | ||
| 276 | + else: | ||
| 277 | + radial["Sigma"].fix() | ||
| 278 | + | ||
| 279 | + # Define spectral component | ||
| 280 | + spectrum = GModelSpectralFunc(self.m_bkg, 1.0) | ||
| 281 | + | ||
| 282 | + # Create background model | ||
| 283 | + model = GCTAModelRadialAcceptance(radial, spectrum) | ||
| 284 | + model.name("Background") | ||
| 285 | + model.instruments("CTA") | ||
| 286 | + | ||
| 287 | + # Return background model | ||
| 288 | + return model | ||
| 289 | + | ||
| 290 | + def set_src_model(self, l, b, flux=1.0, index=-2.48, \ | ||
| 291 | type="point", sigma=1.0, radius=1.0, width=0.1, \ | 291 | type="point", sigma=1.0, radius=1.0, width=0.1, \ |
| 292 | fitpos=False, fitidx=False): | 292 | fitpos=False, fitidx=False): |
| 293 | - """ | ||
| 294 | - Returns a single source with Crab-like spectrum. The source flux | ||
| 295 | - can be scaled in Crab units. The Crab spectrum is based on MAGIC | ||
| 296 | - observations (Albert et al. 2008, ApJ, 674, 1037). | 293 | + """ |
| 294 | + Returns a single source with Crab-like spectrum. The source flux | ||
| 295 | + can be scaled in Crab units. The Crab spectrum is based on MAGIC | ||
| 296 | + observations (Albert et al. 2008, ApJ, 674, 1037). | ||
| 297 | 297 | ||
| 298 | - Parameters: | ||
| 299 | - l - Galactic longitude of source location [deg] | ||
| 300 | - b - Galactic latitude of source location [deg] | ||
| 301 | - Keywords: | ||
| 302 | - flux - Source flux [Crabs] | ||
| 303 | - index - Spectral index | ||
| 304 | - type - Source type ("point", "gauss", "disk", "shell") | ||
| 305 | - sigma - Gaussian sigma (for type="gauss") | ||
| 306 | - radius - Disk or shell inner radius [deg] (for type="disk" and type="shell") | ||
| 307 | - width - Shell width [deg] (for type="shell") | ||
| 308 | - fitpos - Fit position? (default: True) | ||
| 309 | - fitidx - Fit index? (default: True) | ||
| 310 | - """ | ||
| 311 | - # Set source location | ||
| 312 | - location = GSkyDir() | ||
| 313 | - location.lb_deg(l, b) | ||
| 314 | - | ||
| 315 | - # Set source spectrum | ||
| 316 | - spectrum = GModelSpectralPlaw(flux*5.7e-16, index, GEnergy(0.3, "TeV")) | ||
| 317 | - if fitidx: | ||
| 318 | - spectrum["Index"].free() | ||
| 319 | - else: | ||
| 320 | - spectrum["Index"].fix() | 298 | + Parameters: |
| 299 | + l - Galactic longitude of source location [deg] | ||
| 300 | + b - Galactic latitude of source location [deg] | ||
| 301 | + Keywords: | ||
| 302 | + flux - Source flux [Crabs] | ||
| 303 | + index - Spectral index | ||
| 304 | + type - Source type ("point", "gauss", "disk", "shell") | ||
| 305 | + sigma - Gaussian sigma (for type="gauss") | ||
| 306 | + radius - Disk or shell inner radius [deg] (for type="disk" and type="shell") | ||
| 307 | + width - Shell width [deg] (for type="shell") | ||
| 308 | + fitpos - Fit position? (default: True) | ||
| 309 | + fitidx - Fit index? (default: True) | ||
| 310 | + """ | ||
| 311 | + # Set source location | ||
| 312 | + location = GSkyDir() | ||
| 313 | + location.lb_deg(l, b) | ||
| 314 | + | ||
| 315 | + # Set source spectrum | ||
| 316 | + spectrum = GModelSpectralPlaw(flux*5.7e-16, index, GEnergy(0.3, "TeV")) | ||
| 317 | + if fitidx: | ||
| 318 | + spectrum["Index"].free() | ||
| 319 | + else: | ||
| 320 | + spectrum["Index"].fix() | ||
| 321 | 321 | ||
| 322 | - # Set source | ||
| 323 | - if type == "point": | ||
| 324 | - spatial = GModelSpatialPointSource(location) | ||
| 325 | - if fitpos: | ||
| 326 | - spatial[0].free() | ||
| 327 | - spatial[1].free() | ||
| 328 | - elif type == "gauss": | ||
| 329 | - spatial = GModelSpatialRadialGauss(location, sigma) | ||
| 330 | - if fitpos: | ||
| 331 | - spatial[0].free() | ||
| 332 | - spatial[1].free() | ||
| 333 | - elif type == "disk": | ||
| 334 | - spatial = GModelSpatialRadialDisk(location, radius) | ||
| 335 | - if fitpos: | ||
| 336 | - spatial[0].free() | ||
| 337 | - spatial[1].free() | ||
| 338 | - elif type == "shell": | ||
| 339 | - spatial = GModelSpatialRadialShell(location, radius, width) | ||
| 340 | - if fitpos: | ||
| 341 | - spatial[0].free() | ||
| 342 | - spatial[1].free() | ||
| 343 | - else: | ||
| 344 | - self.log("ERROR: Unknown source type '"+type+"'.\n") | ||
| 345 | - return None | ||
| 346 | - source = GModelSky(spatial, spectrum) | ||
| 347 | - | ||
| 348 | - # Set source name | ||
| 349 | - source.name("Test") | ||
| 350 | - | ||
| 351 | - # Return source | ||
| 352 | - return source | ||
| 353 | - | ||
| 354 | - def trial(self, seed): | ||
| 355 | - """ | ||
| 356 | - Create the TS for a single trial. | ||
| 357 | - | ||
| 358 | - Parameters: | ||
| 359 | - seed - Random number generator seed | ||
| 360 | - """ | ||
| 361 | - # Write header | ||
| 362 | - if self.logExplicit(): | ||
| 363 | - self.log.header2("Trial "+str(seed+1)) | 322 | + # Set source |
| 323 | + if type == "point": | ||
| 324 | + spatial = GModelSpatialPointSource(location) | ||
| 325 | + if fitpos: | ||
| 326 | + spatial[0].free() | ||
| 327 | + spatial[1].free() | ||
| 328 | + elif type == "gauss": | ||
| 329 | + spatial = GModelSpatialRadialGauss(location, sigma) | ||
| 330 | + if fitpos: | ||
| 331 | + spatial[0].free() | ||
| 332 | + spatial[1].free() | ||
| 333 | + elif type == "disk": | ||
| 334 | + spatial = GModelSpatialRadialDisk(location, radius) | ||
| 335 | + if fitpos: | ||
| 336 | + spatial[0].free() | ||
| 337 | + spatial[1].free() | ||
| 338 | + elif type == "shell": | ||
| 339 | + spatial = GModelSpatialRadialShell(location, radius, width) | ||
| 340 | + if fitpos: | ||
| 341 | + spatial[0].free() | ||
| 342 | + spatial[1].free() | ||
| 343 | + else: | ||
| 344 | + self.log("ERROR: Unknown source type '"+type+"'.\n") | ||
| 345 | + return None | ||
| 346 | + source = GModelSky(spatial, spectrum) | ||
| 347 | + | ||
| 348 | + # Set source name | ||
| 349 | + source.name("Test") | ||
| 350 | + | ||
| 351 | + # Return source | ||
| 352 | + return source | ||
| 353 | + | ||
| 354 | + def trial(self, seed): | ||
| 355 | + """ | ||
| 356 | + Create the TS for a single trial. | ||
| 357 | + | ||
| 358 | + Parameters: | ||
| 359 | + seed - Random number generator seed | ||
| 360 | + """ | ||
| 361 | + # Write header | ||
| 362 | + if self.logExplicit(): | ||
| 363 | + self.log.header2("Trial "+str(seed+1)) | ||
| 364 | 364 | ||
| 365 | - # Simulate events | ||
| 366 | - sim = obsutils.sim(self.obs, \ | ||
| 367 | - nbins=self.m_enumbins, \ | ||
| 368 | - seed=seed, \ | ||
| 369 | - binsz=self.m_binsz, \ | ||
| 370 | - npix=self.m_npix, \ | ||
| 371 | - log=self.m_log, debug=self.m_debug) | 365 | + # Simulate events |
| 366 | + sim = obsutils.sim(self.obs, \ | ||
| 367 | + nbins=self.m_enumbins, \ | ||
| 368 | + seed=seed, \ | ||
| 369 | + binsz=self.m_binsz, \ | ||
| 370 | + npix=self.m_npix, \ | ||
| 371 | + log=self.m_log, debug=self.m_debug) | ||
| 372 | 372 | ||
| 373 | - # Determine number of events in simulation | ||
| 374 | - nevents = 0.0 | ||
| 375 | - for run in sim: | ||
| 376 | - nevents += run.events().number() | 373 | + # Determine number of events in simulation |
| 374 | + nevents = 0.0 | ||
| 375 | + for run in sim: | ||
| 376 | + nevents += run.events().number() | ||
| 377 | 377 | ||
| 378 | - # Write simulation results | ||
| 379 | - if self.logExplicit(): | ||
| 380 | - self.log.header3("Simulation") | ||
| 381 | - self.log.parformat("Number of simulated events") | ||
| 382 | - self.log(nevents) | ||
| 383 | - self.log("\n") | 378 | + # Write simulation results |
| 379 | + if self.logExplicit(): | ||
| 380 | + self.log.header3("Simulation") | ||
| 381 | + self.log.parformat("Number of simulated events") | ||
| 382 | + self.log(nevents) | ||
| 383 | + self.log("\n") | ||
| 384 | 384 | ||
| 385 | - # Fit background only | ||
| 386 | - sim.models(self.bkg_model) | ||
| 387 | - like_bgm = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) | ||
| 388 | - result_bgm = like_bgm.obs().models() | ||
| 389 | - LogL_bgm = like_bgm.opt().value() | ||
| 390 | - npred_bgm = like_bgm.obs().npred() | 385 | + # Fit background only |
| 386 | + sim.models(self.bkg_model) | ||
| 387 | + like_bgm = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) | ||
| 388 | + result_bgm = like_bgm.obs().models() | ||
| 389 | + LogL_bgm = like_bgm.opt().value() | ||
| 390 | + npred_bgm = like_bgm.obs().npred() | ||
| 391 | 391 | ||
| 392 | - # Write background fit results | ||
| 393 | - if self.logExplicit(): | ||
| 394 | - self.log.header3("Background model fit") | ||
| 395 | - self.log.parformat("log likelihood") | ||
| 396 | - self.log(LogL_bgm) | ||
| 397 | - self.log("\n") | ||
| 398 | - self.log.parformat("Number of predicted events") | ||
| 399 | - self.log(npred_bgm) | ||
| 400 | - self.log("\n") | ||
| 401 | - for model in result_bgm: | ||
| 402 | - self.log.parformat("Model") | ||
| 403 | - self.log(model.name()) | ||
| 404 | - self.log("\n") | ||
| 405 | - for par in model: | ||
| 406 | - self.log(str(par)+"\n") | 392 | + # Write background fit results |
| 393 | + if self.logExplicit(): | ||
| 394 | + self.log.header3("Background model fit") | ||
| 395 | + self.log.parformat("log likelihood") | ||
| 396 | + self.log(LogL_bgm) | ||
| 397 | + self.log("\n") | ||
| 398 | + self.log.parformat("Number of predicted events") | ||
| 399 | + self.log(npred_bgm) | ||
| 400 | + self.log("\n") | ||
| 401 | + for model in result_bgm: | ||
| 402 | + self.log.parformat("Model") | ||
| 403 | + self.log(model.name()) | ||
| 404 | + self.log("\n") | ||
| 405 | + for par in model: | ||
| 406 | + self.log(str(par)+"\n") | ||
| 407 | 407 | ||
| 408 | - # Fit background and test source | ||
| 409 | - sim.models(self.full_model) | ||
| 410 | - like_all = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) | ||
| 411 | - result_all = like_all.obs().models() | ||
| 412 | - LogL_all = like_all.opt().value() | ||
| 413 | - npred_all = like_all.obs().npred() | ||
| 414 | - ts = 2.0*(LogL_bgm-LogL_all) | ||
| 415 | - | ||
| 416 | - # Write background and test source fit results | ||
| 417 | - if self.logExplicit(): | ||
| 418 | - self.log.header3("Background and test source model fit") | ||
| 419 | - self.log.parformat("Test statistics") | ||
| 420 | - self.log(ts) | ||
| 421 | - self.log("\n") | ||
| 422 | - self.log.parformat("log likelihood") | ||
| 423 | - self.log(LogL_all) | ||
| 424 | - self.log("\n") | ||
| 425 | - self.log.parformat("Number of predicted events") | ||
| 426 | - self.log(npred_all) | ||
| 427 | - self.log("\n") | ||
| 428 | - for model in result_all: | ||
| 429 | - self.log.parformat("Model") | ||
| 430 | - self.log(model.name()) | ||
| 431 | - self.log("\n") | ||
| 432 | - for par in model: | ||
| 433 | - self.log(str(par)+"\n") | ||
| 434 | - | ||
| 435 | - # Write result | ||
| 436 | - elif self.logTerse(): | ||
| 437 | - self.log.parformat("Trial "+str(seed)) | ||
| 438 | - self.log("TS=") | ||
| 439 | - self.log(ts) | ||
| 440 | - self.log(" Prefactor=") | ||
| 441 | - self.log(result_all["Test"]["Prefactor"].value()) | ||
| 442 | - self.log("+/-") | ||
| 443 | - self.log(result_all["Test"]["Prefactor"].error()) | ||
| 444 | - self.log("\n") | ||
| 445 | - | ||
| 446 | - # Initialise results | ||
| 447 | - colnames = [] | ||
| 448 | - values = {} | ||
| 449 | - | ||
| 450 | - # Set TS value | ||
| 451 | - colnames.append("TS") | ||
| 452 | - values["TS"] = ts | 408 | + # Fit background and test source |
| 409 | + sim.models(self.full_model) | ||
| 410 | + like_all = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) | ||
| 411 | + result_all = like_all.obs().models() | ||
| 412 | + LogL_all = like_all.opt().value() | ||
| 413 | + npred_all = like_all.obs().npred() | ||
| 414 | + ts = 2.0*(LogL_bgm-LogL_all) | ||
| 415 | + | ||
| 416 | + # Write background and test source fit results | ||
| 417 | + if self.logExplicit(): | ||
| 418 | + self.log.header3("Background and test source model fit") | ||
| 419 | + self.log.parformat("Test statistics") | ||
| 420 | + self.log(ts) | ||
| 421 | + self.log("\n") | ||
| 422 | + self.log.parformat("log likelihood") | ||
| 423 | + self.log(LogL_all) | ||
| 424 | + self.log("\n") | ||
| 425 | + self.log.parformat("Number of predicted events") | ||
| 426 | + self.log(npred_all) | ||
| 427 | + self.log("\n") | ||
| 428 | + for model in result_all: | ||
| 429 | + self.log.parformat("Model") | ||
| 430 | + self.log(model.name()) | ||
| 431 | + self.log("\n") | ||
| 432 | + for par in model: | ||
| 433 | + self.log(str(par)+"\n") | ||
| 434 | + | ||
| 435 | + # Write result | ||
| 436 | + elif self.logTerse(): | ||
| 437 | + self.log.parformat("Trial "+str(seed)) | ||
| 438 | + self.log("TS=") | ||
| 439 | + self.log(ts) | ||
| 440 | + self.log(" Prefactor=") | ||
| 441 | + self.log(result_all["Test"]["Prefactor"].value()) | ||
| 442 | + self.log("+/-") | ||
| 443 | + self.log(result_all["Test"]["Prefactor"].error()) | ||
| 444 | + self.log("\n") | ||
| 445 | + | ||
| 446 | + # Initialise results | ||
| 447 | + colnames = [] | ||
| 448 | + values = {} | ||
| 449 | + | ||
| 450 | + # Set TS value | ||
| 451 | + colnames.append("TS") | ||
| 452 | + values["TS"] = ts | ||
| 453 | 453 | ||
| 454 | - # Set logL for background fit | ||
| 455 | - colnames.append("LogL_bgm") | ||
| 456 | - values["LogL_bgm"] = LogL_bgm | 454 | + # Set logL for background fit |
| 455 | + colnames.append("LogL_bgm") | ||
| 456 | + values["LogL_bgm"] = LogL_bgm | ||
| 457 | 457 | ||
| 458 | - # Set logL for full fit | ||
| 459 | - colnames.append("LogL_all") | ||
| 460 | - values["LogL_all"] = LogL_all | 458 | + # Set logL for full fit |
| 459 | + colnames.append("LogL_all") | ||
| 460 | + values["LogL_all"] = LogL_all | ||
| 461 | 461 | ||
| 462 | - # Set Nevents | ||
| 463 | - colnames.append("Nevents") | ||
| 464 | - values["Nevents"] = nevents | 462 | + # Set Nevents |
| 463 | + colnames.append("Nevents") | ||
| 464 | + values["Nevents"] = nevents | ||
| 465 | 465 | ||
| 466 | - # Set Npred for background fit | ||
| 467 | - colnames.append("Npred_bkg") | ||
| 468 | - values["Npred_bkg"] = npred_bgm | 466 | + # Set Npred for background fit |
| 467 | + colnames.append("Npred_bkg") | ||
| 468 | + values["Npred_bkg"] = npred_bgm | ||
| 469 | 469 | ||
| 470 | - # Set Npred for full fit | ||
| 471 | - colnames.append("Npred_all") | ||
| 472 | - values["Npred_all"] = npred_all | ||
| 473 | - | ||
| 474 | - # Gather free full fit parameters | ||
| 475 | - for i in range(result_all.size()): | ||
| 476 | - model = result_all[i] | ||
| 477 | - model_name = model.name() | ||
| 478 | - for k in range(model.size()): | ||
| 479 | - par = model[k] | ||
| 480 | - if par.is_free(): | ||
| 481 | - | ||
| 482 | - # Set parameter name | ||
| 483 | - name = model_name+"_"+par.name() | ||
| 484 | - | ||
| 485 | - # Append value | ||
| 486 | - colnames.append(name) | ||
| 487 | - values[name] = par.value() | ||
| 488 | - | ||
| 489 | - # Append error | ||
| 490 | - name = "Unc_"+name | ||
| 491 | - colnames.append(name) | ||
| 492 | - values[name] = par.error() | ||
| 493 | - | ||
| 494 | - # Bundle together results | ||
| 495 | - result = {'colnames': colnames, 'values': values} | ||
| 496 | - | ||
| 497 | - # Return | ||
| 498 | - return result | 470 | + # Set Npred for full fit |
| 471 | + colnames.append("Npred_all") | ||
| 472 | + values["Npred_all"] = npred_all | ||
| 473 | + | ||
| 474 | + # Gather free full fit parameters | ||
| 475 | + for i in range(result_all.size()): | ||
| 476 | + model = result_all[i] | ||
| 477 | + model_name = model.name() | ||
| 478 | + for k in range(model.size()): | ||
| 479 | + par = model[k] | ||
| 480 | + if par.is_free(): | ||
| 481 | + | ||
| 482 | + # Set parameter name | ||
| 483 | + name = model_name+"_"+par.name() | ||
| 484 | + | ||
| 485 | + # Append value | ||
| 486 | + colnames.append(name) | ||
| 487 | + values[name] = par.value() | ||
| 488 | + | ||
| 489 | + # Append error | ||
| 490 | + name = "Unc_"+name | ||
| 491 | + colnames.append(name) | ||
| 492 | + values[name] = par.error() | ||
| 493 | + | ||
| 494 | + # Bundle together results | ||
| 495 | + result = {'colnames': colnames, 'values': values} | ||
| 496 | + | ||
| 497 | + # Return | ||
| 498 | + return result | ||
| 499 | 499 | ||
| 500 | 500 | ||
| 501 | # ======================== # | 501 | # ======================== # |
| 502 | # Main routine entry point # | 502 | # Main routine entry point # |
| 503 | # ======================== # | 503 | # ======================== # |
| 504 | if __name__ == '__main__': | 504 | if __name__ == '__main__': |
| 505 | - """ | ||
| 506 | - Generates TS distribution. | ||
| 507 | - """ | ||
| 508 | - # Create instance of application | ||
| 509 | - app = cstsdist(sys.argv) | ||
| 510 | - | ||
| 511 | - # Open logfile | ||
| 512 | - app.logFileOpen() | ||
| 513 | - | ||
| 514 | - # Execute application | ||
| 515 | - app.execute() | ||
| 516 | - | ||
| 517 | \ No newline at end of file | 505 | \ No newline at end of file |
| 506 | + """ | ||
| 507 | + Generates TS distribution. | ||
| 508 | + """ | ||
| 509 | + # Create instance of application | ||
| 510 | + app = cstsdist(sys.argv) | ||
| 511 | + | ||
| 512 | + # Open logfile | ||
| 513 | + app.logFileOpen() | ||
| 514 | + | ||
| 515 | + # Execute application | ||
| 516 | + app.execute() | ||
| 517 | + | ||
| 518 | \ No newline at end of file | 518 | \ No newline at end of file |
scripts/cta_kb_bkgrates.py
| @@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
| 4 | # into a column separated file function table. The table is automatically | 4 | # into a column separated file function table. The table is automatically |
| 5 | # named "bkg_XXX.txt" where "XXX" is for example "kb_E_50h_v3". | 5 | # named "bkg_XXX.txt" where "XXX" is for example "kb_E_50h_v3". |
| 6 | # | 6 | # |
| 7 | -# Copyright (C) 2011 Jurgen Knodlseder | 7 | +# Copyright (C) 2011-2014 Juergen Knoedlseder |
| 8 | # | 8 | # |
| 9 | # This program is free software: you can redistribute it and/or modify | 9 | # This program is free software: you can redistribute it and/or modify |
| 10 | # it under the terms of the GNU General Public License as published by | 10 | # it under the terms of the GNU General Public License as published by |
| @@ -29,78 +29,78 @@ import sys | @@ -29,78 +29,78 @@ import sys | ||
| 29 | # Generate file function from model # | 29 | # Generate file function from model # |
| 30 | # ================================= # | 30 | # ================================= # |
| 31 | def make_file_function(irfname, filename): | 31 | def make_file_function(irfname, filename): |
| 32 | - """ | ||
| 33 | - Generate file function from model. | ||
| 34 | - | ||
| 35 | - Parameters: | ||
| 36 | - irfname - IRF filename | ||
| 37 | - filename - File function filename | ||
| 38 | - """ | ||
| 39 | - # Open performance file and file function | ||
| 40 | - irf = open(irfname, "r") | ||
| 41 | - file = open(filename, "w") | ||
| 42 | - | ||
| 43 | - # Read data | ||
| 44 | - for row in irf: | ||
| 45 | - | ||
| 46 | - # Skip header and trailer | ||
| 47 | - if row.find("log(E)") != -1: | ||
| 48 | - continue | ||
| 49 | - if row.find("--------") != -1: | ||
| 50 | - break | ||
| 51 | - | ||
| 52 | - # Extract data | ||
| 53 | - fields = row.replace(" ",",").replace(",,",",").rstrip("\n").split(",") | ||
| 54 | - logE = float(fields[0]) | ||
| 55 | - aeff = float(fields[1]) | ||
| 56 | - r68 = float(fields[2]) | ||
| 57 | - r80 = float(fields[3]) | ||
| 58 | - eres = float(fields[4]) | ||
| 59 | - bgd = float(fields[5]) | ||
| 60 | - sens = float(fields[6]) | ||
| 61 | - | ||
| 62 | - # Compute energy (in MeV) | ||
| 63 | - energy = math.pow(10.0, logE)*1.0e6 | ||
| 64 | - emin = math.pow(10.0, logE-0.1)*1.0e6 | ||
| 65 | - emax = math.pow(10.0, logE+0.1)*1.0e6 | ||
| 66 | - ewidth = emax-emin | ||
| 67 | - | ||
| 68 | - # Compute solid angle of r80 region in sr | ||
| 69 | - omega = 2.0 * math.pi * (1.0 - math.cos(math.radians(r80))) | ||
| 70 | - | ||
| 71 | - # Compute background rate per steradian and MeV | ||
| 72 | - bkg_rate = bgd/omega/ewidth | 32 | + """ |
| 33 | + Generate file function from model. | ||
| 34 | + | ||
| 35 | + Parameters: | ||
| 36 | + irfname - IRF filename | ||
| 37 | + filename - File function filename | ||
| 38 | + """ | ||
| 39 | + # Open performance file and file function | ||
| 40 | + irf = open(irfname, "r") | ||
| 41 | + file = open(filename, "w") | ||
| 42 | + | ||
| 43 | + # Read data | ||
| 44 | + for row in irf: | ||
| 45 | + | ||
| 46 | + # Skip header and trailer | ||
| 47 | + if row.find("log(E)") != -1: | ||
| 48 | + continue | ||
| 49 | + if row.find("--------") != -1: | ||
| 50 | + break | ||
| 51 | + | ||
| 52 | + # Extract data | ||
| 53 | + fields = row.replace(" ",",").replace(",,",",").rstrip("\n").split(",") | ||
| 54 | + logE = float(fields[0]) | ||
| 55 | + aeff = float(fields[1]) | ||
| 56 | + r68 = float(fields[2]) | ||
| 57 | + r80 = float(fields[3]) | ||
| 58 | + eres = float(fields[4]) | ||
| 59 | + bgd = float(fields[5]) | ||
| 60 | + sens = float(fields[6]) | ||
| 61 | + | ||
| 62 | + # Compute energy (in MeV) | ||
| 63 | + energy = math.pow(10.0, logE)*1.0e6 | ||
| 64 | + emin = math.pow(10.0, logE-0.1)*1.0e6 | ||
| 65 | + emax = math.pow(10.0, logE+0.1)*1.0e6 | ||
| 66 | + ewidth = emax-emin | ||
| 67 | + | ||
| 68 | + # Compute solid angle of r80 region in sr | ||
| 69 | + omega = 2.0 * math.pi * (1.0 - math.cos(math.radians(r80))) | ||
| 70 | + | ||
| 71 | + # Compute background rate per steradian and MeV | ||
| 72 | + bkg_rate = bgd/omega/ewidth | ||
| 73 | 73 | ||
| 74 | - # Write | ||
| 75 | - file.write(str(energy)+" "+str(bkg_rate)+"\n") | ||
| 76 | - | ||
| 77 | - # Close files | ||
| 78 | - irf.close() | ||
| 79 | - file.close() | ||
| 80 | - | ||
| 81 | - # Return | ||
| 82 | - return | 74 | + # Write |
| 75 | + file.write(str(energy)+" "+str(bkg_rate)+"\n") | ||
| 76 | + | ||
| 77 | + # Close files | ||
| 78 | + irf.close() | ||
| 79 | + file.close() | ||
| 80 | + | ||
| 81 | + # Return | ||
| 82 | + return | ||
| 83 | 83 | ||
| 84 | 84 | ||
| 85 | # ================ # | 85 | # ================ # |
| 86 | # Main entry point # | 86 | # Main entry point # |
| 87 | # ================ # | 87 | # ================ # |
| 88 | if __name__ == '__main__': | 88 | if __name__ == '__main__': |
| 89 | - """ | ||
| 90 | - Main entry point | ||
| 91 | - """ | ||
| 92 | - # Get IRF from command line argument | ||
| 93 | - if (len(sys.argv) > 1): | ||
| 94 | - irf = sys.argv[1] | ||
| 95 | - else: | ||
| 96 | - irf = "kb_E_50h_v3" | 89 | + """ |
| 90 | + Main entry point | ||
| 91 | + """ | ||
| 92 | + # Get IRF from command line argument | ||
| 93 | + if (len(sys.argv) > 1): | ||
| 94 | + irf = sys.argv[1] | ||
| 95 | + else: | ||
| 96 | + irf = "kb_E_50h_v3" | ||
| 97 | 97 | ||
| 98 | - # Set parameters | ||
| 99 | - caldb = "/usr/local/gamma/share/caldb/cta" | ||
| 100 | - | ||
| 101 | - # Set filenames | ||
| 102 | - irfname = caldb+"/"+irf+".dat" | ||
| 103 | - filename = "bkg_"+irf+".txt" | ||
| 104 | - | ||
| 105 | - # Read | ||
| 106 | - make_file_function(irfname, filename) | 98 | + # Set parameters |
| 99 | + caldb = "/usr/local/gamma/share/caldb/cta" | ||
| 100 | + | ||
| 101 | + # Set filenames | ||
| 102 | + irfname = caldb+"/"+irf+".dat" | ||
| 103 | + filename = "bkg_"+irf+".txt" | ||
| 104 | + | ||
| 105 | + # Read | ||
| 106 | + make_file_function(irfname, filename) |
scripts/cta_make_nodes.py
| @@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
| 4 | # logarithmically spaced energy bins. The intensity scale is set to the | 4 | # logarithmically spaced energy bins. The intensity scale is set to the |
| 5 | # HESS Crab intensity (assuming a power law). | 5 | # HESS Crab intensity (assuming a power law). |
| 6 | # | 6 | # |
| 7 | -# Copyright (C) 2012 Juergen Knoedlseder | 7 | +# Copyright (C) 2012-2014 Juergen Knoedlseder |
| 8 | # | 8 | # |
| 9 | # This program is free software: you can redistribute it and/or modify | 9 | # This program is free software: you can redistribute it and/or modify |
| 10 | # it under the terms of the GNU General Public License as published by | 10 | # it under the terms of the GNU General Public License as published by |
| @@ -29,91 +29,91 @@ import math | @@ -29,91 +29,91 @@ import math | ||
| 29 | # Write one node # | 29 | # Write one node # |
| 30 | # ============== # | 30 | # ============== # |
| 31 | def write_node(file, energy, scale): | 31 | def write_node(file, energy, scale): |
| 32 | - """ | ||
| 33 | - Writes one node to XML file. | ||
| 34 | - """ | ||
| 35 | - # Convert to strings | ||
| 36 | - str_energy = str(energy) | ||
| 37 | - str_scale = str(scale) | 32 | + """ |
| 33 | + Writes one node to XML file. | ||
| 34 | + """ | ||
| 35 | + # Convert to strings | ||
| 36 | + str_energy = str(energy) | ||
| 37 | + str_scale = str(scale) | ||
| 38 | 38 | ||
| 39 | - # Write start tag | ||
| 40 | - file.write(' <node>\n') | 39 | + # Write start tag |
| 40 | + file.write(' <node>\n') | ||
| 41 | 41 | ||
| 42 | - # Write energy | ||
| 43 | - file.write(' <parameter scale="1e6" name="Energy"') | ||
| 44 | - file.write(' min="'+str_energy+'" max="'+str_energy+'"') | ||
| 45 | - file.write(' value="'+str_energy+'"') | ||
| 46 | - file.write(' free="0"/>\n') | 42 | + # Write energy |
| 43 | + file.write(' <parameter scale="1e6" name="Energy"') | ||
| 44 | + file.write(' min="'+str_energy+'" max="'+str_energy+'"') | ||
| 45 | + file.write(' value="'+str_energy+'"') | ||
| 46 | + file.write(' free="0"/>\n') | ||
| 47 | 47 | ||
| 48 | - # Write intensity | ||
| 49 | - file.write(' <parameter scale="'+str_scale+'" name="Intensity"') | ||
| 50 | - file.write(' min="1e-5" max="1e5"') | ||
| 51 | - file.write(' value="1.0"') | ||
| 52 | - file.write(' free="1"/>\n') | 48 | + # Write intensity |
| 49 | + file.write(' <parameter scale="'+str_scale+'" name="Intensity"') | ||
| 50 | + file.write(' min="1e-5" max="1e5"') | ||
| 51 | + file.write(' value="1.0"') | ||
| 52 | + file.write(' free="1"/>\n') | ||
| 53 | 53 | ||
| 54 | - # Write end tag | ||
| 55 | - file.write(' </node>\n') | 54 | + # Write end tag |
| 55 | + file.write(' </node>\n') | ||
| 56 | 56 | ||
| 57 | - # Return | ||
| 58 | - return | ||
| 59 | - | 57 | + # Return |
| 58 | + return | ||
| 59 | + | ||
| 60 | 60 | ||
| 61 | # ============ # | 61 | # ============ # |
| 62 | # Create nodes # | 62 | # Create nodes # |
| 63 | # ============ # | 63 | # ============ # |
| 64 | def create_nodes(emin, emax, enumbins): | 64 | def create_nodes(emin, emax, enumbins): |
| 65 | - """ | ||
| 66 | - Create nodes (energies in TeV). | ||
| 67 | - """ | ||
| 68 | - # Open file | ||
| 69 | - file = open("nodes.xml", "w") | 65 | + """ |
| 66 | + Create nodes (energies in TeV). | ||
| 67 | + """ | ||
| 68 | + # Open file | ||
| 69 | + file = open("nodes.xml", "w") | ||
| 70 | 70 | ||
| 71 | - # Set node boundaries | ||
| 72 | - elogmin = math.log10(float(emin)) | ||
| 73 | - elogmax = math.log10(float(emax)) | ||
| 74 | - elogbin = (elogmax - elogmin)/(float(enumbins)-1.0) | ||
| 75 | - | ||
| 76 | - # Fill arrays | ||
| 77 | - for i in range(int(enumbins)): | ||
| 78 | - | ||
| 79 | - # Compute energy | ||
| 80 | - energy = math.pow(10.0, i*elogbin+elogmin) | ||
| 81 | - | ||
| 82 | - # Compute scale (HESS Crab spectrum) | ||
| 83 | - scale = 3.45e-17 * math.pow(energy, -2.63) | ||
| 84 | - | ||
| 85 | - # Write node | ||
| 86 | - write_node(file, energy, scale) | ||
| 87 | - | ||
| 88 | - # Debug | ||
| 89 | - #sys.stdout.write(energy) | 71 | + # Set node boundaries |
| 72 | + elogmin = math.log10(float(emin)) | ||
| 73 | + elogmax = math.log10(float(emax)) | ||
| 74 | + elogbin = (elogmax - elogmin)/(float(enumbins)-1.0) | ||
| 75 | + | ||
| 76 | + # Fill arrays | ||
| 77 | + for i in range(int(enumbins)): | ||
| 78 | + | ||
| 79 | + # Compute energy | ||
| 80 | + energy = math.pow(10.0, i*elogbin+elogmin) | ||
| 81 | + | ||
| 82 | + # Compute scale (HESS Crab spectrum) | ||
| 83 | + scale = 3.45e-17 * math.pow(energy, -2.63) | ||
| 84 | + | ||
| 85 | + # Write node | ||
| 86 | + write_node(file, energy, scale) | ||
| 87 | + | ||
| 88 | + # Debug | ||
| 89 | + #sys.stdout.write(energy) | ||
| 90 | #sys.stdout.write(math.pow(10.0, int(math.log10(scale))-1.0)±"\n") | 90 | #sys.stdout.write(math.pow(10.0, int(math.log10(scale))-1.0)±"\n") |
| 91 | - | ||
| 92 | - # Close file | ||
| 93 | - file.close() | ||
| 94 | - | ||
| 95 | - # Return | ||
| 96 | - return | ||
| 97 | - | 91 | + |
| 92 | + # Close file | ||
| 93 | + file.close() | ||
| 94 | + | ||
| 95 | + # Return | ||
| 96 | + return | ||
| 97 | + | ||
| 98 | 98 | ||
| 99 | # ======================= # | 99 | # ======================= # |
| 100 | # Main script entry point # | 100 | # Main script entry point # |
| 101 | # ======================= # | 101 | # ======================= # |
| 102 | if __name__ == '__main__': | 102 | if __name__ == '__main__': |
| 103 | - """ | ||
| 104 | - Compute nodes. | ||
| 105 | - """ | ||
| 106 | - # Check command line | ||
| 107 | - usage = "Usage: cta_make_nodes emin emax enumbins" | ||
| 108 | - if len(sys.argv) < 3: | ||
| 109 | - sys.stdout.write(usage+"\n") | ||
| 110 | - sys.exit() | ||
| 111 | - | ||
| 112 | - # Extract parameters | ||
| 113 | - emin = sys.argv[1] | ||
| 114 | - emax = sys.argv[2] | ||
| 115 | - enumbins = sys.argv[3] | 103 | + """ |
| 104 | + Compute nodes. | ||
| 105 | + """ | ||
| 106 | + # Check command line | ||
| 107 | + usage = "Usage: cta_make_nodes emin emax enumbins" | ||
| 108 | + if len(sys.argv) < 3: | ||
| 109 | + sys.stdout.write(usage+"\n") | ||
| 110 | + sys.exit() | ||
| 111 | + | ||
| 112 | + # Extract parameters | ||
| 113 | + emin = sys.argv[1] | ||
| 114 | + emax = sys.argv[2] | ||
| 115 | + enumbins = sys.argv[3] | ||
| 116 | 116 | ||
| 117 | - # Create nodes | ||
| 118 | - create_nodes(emin, emax, enumbins) | ||
| 119 | - | 117 | + # Create nodes |
| 118 | + create_nodes(emin, emax, enumbins) | ||
| 119 | + |
scripts/cta_root2irf.py
| @@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
| 11 | # area (i.e. the area before applying any theta cut). This is required by | 11 | # area (i.e. the area before applying any theta cut). This is required by |
| 12 | # GammaLib as the maximum likelihood analysis does not imply any theta cut. | 12 | # GammaLib as the maximum likelihood analysis does not imply any theta cut. |
| 13 | # | 13 | # |
| 14 | -# Copyright (C) 2011 Jurgen Knodlseder | 14 | +# Copyright (C) 2011-2014 Juergen Knoedlseder |
| 15 | # | 15 | # |
| 16 | # This program is free software: you can redistribute it and/or modify | 16 | # This program is free software: you can redistribute it and/or modify |
| 17 | # it under the terms of the GNU General Public License as published by | 17 | # it under the terms of the GNU General Public License as published by |