Commit fe0e6e0b359f90a69cf0c561276ffcb86f7e6fce

Authored by Jürgen Knödlseder
2 parents db16ee43 44a68b8f

Merge branch 'integration' into devel

# Conflicts:
#	README
.gitignore
... ... @@ -70,6 +70,8 @@ test/*.trs
70 70 test/test_cscripts.sh
71 71 test/reports/*.xml
72 72 test/butterfly.txt
  73 +test/model.reg
  74 +test/obs.reg
73 75 examples/*.fits
74 76 examples/*.xml
75 77 examples/*.dat
... ...
ChangeLog
  1 +2015-11-24 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu>
  2 +
  3 + * Version 1.1.0 released
  4 + ========================
  5 +
  6 + Add csobsinfo, csmodelinfo, csmodelmerge, cstsmapmerge (#1578)
  7 +
  8 +
1 9 2015-11-19 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu>
2 10  
3 11 * Version 1.0.0 released
... ...
1   -New Features and Important Changes in ctools 1.0.0
  1 +New Features and Important Changes in ctools 1.1.0
2 2  
3 3 Author(s) : Juergen Knoedlseder
4 4  
5   -19 November 2015
  5 +24 November 2015
6 6  
7 7  
8 8 1. Introduction
9 9 ---------------
10 10 This document briefly summarizes executable by executable the most important
11 11 changes made since the last release of ctools. The code complies to GammaLib
12   -version 1.0.0 or above.
  12 +version 1.1.0 or above.
13 13  
14 14  
15 15 2. Configuration
... ... @@ -82,8 +82,7 @@ None
82 82  
83 83 15. ctcubemask - CTA cube filtering
84 84 -----------------------------------
85   -Allow to ignore the spatial filtering by specifying NONE parameters for "ra",
86   -"dec" or "rad".
  85 +None
87 86  
88 87  
89 88 16. ctbutterfly - Generate butterfly diagrams
... ... @@ -103,10 +102,11 @@ None
103 102  
104 103 19. cscripts
105 104 ------------
106   -The csspec script now handled correctly stacked data. Dependent on the
107   -requested energy binning, it selects for each spectral energy bin the
108   -relevant energy bins from the counts cube and performs a maximum likelihood
109   -analysis.
  105 +The following scripts have been added:
  106 +- csobsinfo: dump information in observation container
  107 +- csmodelinfo: dump information in model container
  108 +- csmodelmerge: merge model containers into single container
  109 +- cstsmapmerge: merge sliced TS map into single map
110 110  
111 111  
112 112 20. Examples
... ...
1 1 ctools information
2 2 ==================
3   -Version: 1.0.0 (21 November 2015)
  3 +Version: 1.1.0 (24 November 2015)
4 4 Author: Juergen Knodlseder (jurgen.knodlseder@irap.omp.eu)
5   -GammaLib dependency: 1.0.0
  5 +GammaLib dependency: 1.1.0
6 6  
7 7  
8 8 License information
... ...
configure.ac
... ... @@ -29,7 +29,7 @@
29 29 #############################################################################
30 30 # Initialisation #
31 31 #############################################################################
32   -AC_INIT([ctools], [1.0.0], [jurgen.knodlseder@irap.omp.eu], [ctools])
  32 +AC_INIT([ctools], [1.1.0.dev], [jurgen.knodlseder@irap.omp.eu], [ctools])
33 33 AC_CONFIG_SRCDIR([src/ctselect/ctselect.cpp])
34 34 AC_CONFIG_MACRO_DIR([m4])
35 35 #AM_INIT_AUTOMAKE([gnu no-dependencies])
... ...
cscripts/Makefile.am
1 1 ## Process this file with automake to produce Makefile.in
2 2  
3   -# Scripts to be distributed in bindir
4   -binscripts = tsmerge.py
5   -
6 3 # Scripts to be distributed in $(pyexecdir)/cscripts
7 4 pythonscripts = __init__.py \
8 5 cspull.py cssens.py cstsdist.py cscaldb.py csresmap.py \
9   - cshessobs.py csobsdef.py csspec.py cslightcrv.py \
10   - csinfo.py \
  6 + cshessobs.py csobsdef.py csspec.py cslightcrv.py csobsinfo.py \
  7 + csinfo.py csmodelinfo.py csmodelmerge.py cstsmapmerge.py \
11 8 obsutils.py
12 9  
13 10 # Scripts for which symbolic links will be created in bindir
14 11 linkscripts = cspull cssens cstsdist cscaldb csresmap \
15   - cshessobs csobsdef csspec cslightcrv \
16   - csinfo
  12 + cshessobs csobsdef csspec cslightcrv csobsinfo \
  13 + csinfo csmodelinfo csmodelmerge cstsmapmerge
17 14  
18 15 # Distribute scripts
19 16 EXTRA_DIST = $(binscripts) $(pythonscripts)
... ...
cscripts/csmodelinfo.py 0 → 100755
  1 +#!/usr/bin/env python
  2 +# ==========================================================================
  3 +# Dump information about models into log file
  4 +#
  5 +# Copyright (C) 2015 Michael Mayer
  6 +#
  7 +# This program is free software: you can redistribute it and/or modify
  8 +# it under the terms of the GNU General Public License as published by
  9 +# the Free Software Foundation, either version 3 of the License, or
  10 +# (at your option) any later version.
  11 +#
  12 +# This program is distributed in the hope that it will be useful,
  13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 +# GNU General Public License for more details.
  16 +#
  17 +# You should have received a copy of the GNU General Public License
  18 +# along with this program. If not, see <http://www.gnu.org/licenses/>.
  19 +#
  20 +# ==========================================================================
  21 +import gammalib
  22 +import ctools
  23 +import sys
  24 +
  25 +
  26 +# ================= #
  27 +# csmodelinfo class #
  28 +# ================= #
  29 +class csmodelinfo(ctools.cscript):
  30 + """
  31 + This class dumps information about a model container into a logfile or
  32 + on screen. This might be helpful for quick access to the model container,
  33 + showing, e.g., number of sources, background models, free and fixed
  34 + parameters etc. The tool can also dump the models into a region file to
  35 + display e.g. with ds9.
  36 + """
  37 + def __init__(self, *argv):
  38 + """
  39 + Constructor.
  40 + """
  41 + # Set name
  42 + self.name = "csmodelinfo"
  43 + self.version = "1.1.0"
  44 +
  45 + # Make sure that parfile exists
  46 + file = self.parfile()
  47 +
  48 + # Initialise application
  49 + if len(argv) == 0:
  50 + ctools.cscript.__init__(self, self.name, self.version)
  51 + elif len(argv) == 1:
  52 + ctools.cscript.__init__(self, self.name, self.version, *argv)
  53 + else:
  54 + raise TypeError("Invalid number of arguments given.")
  55 +
  56 + # Set logger properties
  57 + self.log_header()
  58 + self.log.date(True)
  59 +
  60 + # Return
  61 + return
  62 +
  63 + def __del__(self):
  64 + """
  65 + Destructor.
  66 + """
  67 + # Return
  68 + return
  69 +
  70 + def parfile(self):
  71 + """
  72 + Check if parfile exists. If parfile does not exist then create a
  73 + default parfile. This kluge avoids shipping the cscript with a
  74 + parfile.
  75 + """
  76 +
  77 + # Set parfile name
  78 + parfile = self.name+".par"
  79 +
  80 + try:
  81 + pars = gammalib.GApplicationPars(parfile)
  82 + except:
  83 + # Signal that parfile was not found
  84 + print("Parfile \""+parfile+"\" not found. Create default parfile.")
  85 +
  86 + # Create default parfile
  87 + pars = gammalib.GApplicationPars()
  88 + pars.append(gammalib.GApplicationPar("inmodel","f","a","model.xml","","","Input model XML file"))
  89 + pars.append(gammalib.GApplicationPar("ds9file","f","h","NONE","","","DS9 region file containing models"))
  90 + pars.append(gammalib.GApplicationPar("pnt_type","s","h","cross","circle|box|diamond|cross|x|arrow|boxcircle","","Marker type for point sources"))
  91 + pars.append(gammalib.GApplicationPar("pnt_mark_size","i","h","12","","","Marker size for point sources"))
  92 + pars.append(gammalib.GApplicationPar("show_labels","b","h","yes","yes|no","","Add source labels?"))
  93 + pars.append(gammalib.GApplicationPar("width","i","h","2","","","Line width for regions"))
  94 + pars.append(gammalib.GApplicationPar("font","s","h","helvetica","helvetica|times|courier","","Font for source labels"))
  95 + pars.append(gammalib.GApplicationPar("fontsize","i","h","12","","","Font size for source labels"))
  96 + pars.append(gammalib.GApplicationPar("fonttype","s","h","normal","normal|bold","","Use normal or bold font?"))
  97 + pars.append(gammalib.GApplicationPar("fonttype2","s","h","roman","roman|italic","","Use roman or italic font?"))
  98 + pars.append(gammalib.GApplicationPar("show_ext_type","b","h","yes","yes|no","","Show type of extended model in source name"))
  99 + pars.append(gammalib.GApplicationPar("free_color","s","h","green","","","Color for sources with free parameters (any ds9 color or hex code)"))
  100 + pars.append(gammalib.GApplicationPar("fixed_color","s","h","magenta","","","Color for source without free parameters (any ds9 color or hex code)"))
  101 + pars.append_standard()
  102 + pars.append(gammalib.GApplicationPar("logfile","f","h","csmodelinfo.log","","","Log filename"))
  103 + pars.save(parfile)
  104 +
  105 + # Return
  106 + return
  107 +
  108 + def get_parameters(self):
  109 + """
  110 + Get parameters from parfile and setup the observation.
  111 + """
  112 + # Get models
  113 + self.models = gammalib.GModels(self["inmodel"].filename())
  114 +
  115 + # Get ds9 filename
  116 + self.ds9file = self["ds9file"].filename()
  117 +
  118 + # Get hidden parameters for region file
  119 + self.pnt_type = self["pnt_type"].string()
  120 + self.pnt_mark_size = self["pnt_mark_size"].integer()
  121 + self.show_labels = self["show_labels"].boolean()
  122 + self.width = self["width"].integer()
  123 + self.font = self["font"].string()
  124 + self.fontsize = self["fontsize"].integer()
  125 + self.fonttype = self["fonttype"].string()
  126 + self.fonttype2 = self["fonttype2"].string()
  127 + self.show_ext_type = self["show_ext_type"].boolean()
  128 + self.free_color = self["free_color"].string()
  129 + self.fixed_color = self["fixed_color"].string()
  130 +
  131 + # Return
  132 + return
  133 +
  134 + def run(self):
  135 + """
  136 + Run the script.
  137 + """
  138 + # Switch screen logging on in debug mode
  139 + if self.logDebug():
  140 + self.log.cout(True)
  141 +
  142 + # Get parameters
  143 + self.get_parameters()
  144 +
  145 + # Write input parameters into logger
  146 + if self.logTerse():
  147 + self.log_parameters()
  148 + self.log("\n")
  149 +
  150 + if self.logVerbose():
  151 + self.log("\n")
  152 + self.log.header1("Models in detail")
  153 + self.log("\n")
  154 + self.log(str(self.models))
  155 + self.log("\n")
  156 +
  157 + # Initialise output values
  158 + types = {}
  159 + instruments = {}
  160 + ts = {}
  161 + pars_at_limit = {}
  162 + free_src_pars = {}
  163 + n_par_total = 0
  164 + n_par_free = 0
  165 + n_par_fixed = 0
  166 + n_par_at_limit = 0
  167 + n_par_free_bkg = 0
  168 + n_par_free_src = 0
  169 + n_par_free_spec = 0
  170 + n_par_free_spat = 0
  171 + n_par_free_temp = 0
  172 +
  173 + # Loop over models and initialise dictionaries with model names
  174 + for model in self.models:
  175 + types[model.type()] = 0
  176 + instruments[model.instruments()] = 0
  177 + pars_at_limit[model.name()] = []
  178 +
  179 + # Loop over models again and fill values to be dumped
  180 + for model in self.models:
  181 +
  182 + # Model types
  183 + types[model.type()] += 1
  184 +
  185 + # Model instruments
  186 + instruments[model.instruments()] += 1
  187 +
  188 + # TS
  189 + if model.has_ts():
  190 + ts[model.name()] = model.ts()
  191 +
  192 + # Skymodel?
  193 + skymodel = (model.classname() == "GModelSky")
  194 + if skymodel:
  195 + free_src_pars[model.name()] = []
  196 +
  197 + # Loop over model parameters
  198 + for par in model:
  199 +
  200 + # Increment total parameters
  201 + n_par_total += 1
  202 +
  203 + # Check if parameter is at limit
  204 + if par.has_range():
  205 + if par.value() == par.min() or par.value() == par.max():
  206 + pars_at_limit[model.name()].append(par.name())
  207 + n_par_at_limit += 1
  208 +
  209 + # Check if model parameter is free/fixed and
  210 + # increment respective variable
  211 + if par.is_free():
  212 + n_par_free += 1
  213 + if skymodel:
  214 + free_src_pars[model.name()].append(par)
  215 + n_par_free_src += 1
  216 + else:
  217 + n_par_free_bkg += 1
  218 + else:
  219 + n_par_fixed += 1
  220 +
  221 + # If sky model, divide free parameters into spatial, spectral and temporal
  222 + if skymodel:
  223 + for par in model.spectral():
  224 + if par.is_free():
  225 + n_par_free_spec += 1
  226 + for par in model.spatial():
  227 + if par.is_free():
  228 + n_par_free_spat += 1
  229 + for par in model.temporal():
  230 + if par.is_free():
  231 + n_par_free_temp += 1
  232 +
  233 + # Log summary
  234 + self.log("\n")
  235 + self.log.header1("Summary")
  236 + self.log("\n")
  237 +
  238 + # Log instruments
  239 + self.log.header3("Instrument specific models")
  240 + for inst, n_inst in instruments.iteritems():
  241 + if inst == "":
  242 + inst = "All"
  243 + self.log.parformat(inst)
  244 + self.log(str(n_inst))
  245 + self.log("\n")
  246 +
  247 + # Log model types
  248 + self.log("\n")
  249 + self.log.header3("Model types")
  250 + for modeltype, n_types in types.iteritems():
  251 + self.log.parformat(modeltype)
  252 + self.log(str(n_types))
  253 + self.log("\n")
  254 +
  255 + # Log parameter information
  256 + self.log("\n")
  257 + self.log.header2("Parameter information")
  258 + self.log.parformat("All parameters")
  259 + self.log(str(n_par_total))
  260 + self.log("\n")
  261 + self.log.parformat("Fixed parameters")
  262 + self.log(str(n_par_fixed))
  263 + self.log("\n")
  264 + self.log.parformat("Free parameters (total)")
  265 + self.log(str(n_par_free))
  266 + self.log("\n")
  267 + self.log.parformat("Free background parameters")
  268 + self.log(str(n_par_free_bkg))
  269 + self.log("\n")
  270 + self.log.parformat("Free source parameters")
  271 + self.log(str(n_par_free_src))
  272 + self.log("\n")
  273 + if n_par_free_spec > 0:
  274 + self.log.parformat("Free spectral parameters")
  275 + self.log(str(n_par_free_spec))
  276 + self.log("\n")
  277 + if n_par_free_spat > 0:
  278 + self.log.parformat("Free spatial parameters")
  279 + self.log(str(n_par_free_spat))
  280 + self.log("\n")
  281 + if n_par_free_temp > 0:
  282 + self.log.parformat("Free temporal parameters")
  283 + self.log(str(n_par_free_temp))
  284 + self.log("\n")
  285 + self.log.parformat("Parameters at limit")
  286 + self.log(str(n_par_at_limit))
  287 + self.log("\n")
  288 + self.log("\n")
  289 +
  290 + # Log parameters at limit (if any)
  291 + if n_par_at_limit > 0:
  292 + self.log.header3("Parameters at limit")
  293 + for source, parameter in pars_at_limit.iteritems():
  294 + if len(parameter):
  295 + for par in parameter:
  296 + self.log.parformat(source)
  297 + self.log(par)
  298 + self.log("\n")
  299 +
  300 + # Log free parameters if requested
  301 + if self.logExplicit() and len(free_src_pars):
  302 + self.log("\n")
  303 + self.log.header2("Free source parameters")
  304 + for source, parameter in free_src_pars.iteritems():
  305 + if len(parameter):
  306 + self.log.header3(source)
  307 + for par in parameter:
  308 + self.log(str(par))
  309 + self.log("\n")
  310 + self.log("\n")
  311 +
  312 + # Log TS values if available
  313 + if len(ts):
  314 + self.log.header3("Test statistics")
  315 + for source,tsvalue in ts.iteritems():
  316 + self.log.parformat(source)
  317 + self.log("%.2f"%tsvalue)
  318 + self.log("\n")
  319 +
  320 + # Return
  321 + return
  322 +
  323 + def save(self):
  324 + """
  325 + Save models to ds9 region file if required
  326 + """
  327 +
  328 + # Check if ds9 file is valid
  329 + if not self.ds9file == "NONE":
  330 +
  331 + self.log("\n")
  332 + self.log.header1("Save region file")
  333 + self.log("\n")
  334 +
  335 + # Open file
  336 + f = open(self.ds9file,"w")
  337 +
  338 + # Write coordinate system
  339 + f.write("fk5\n")
  340 +
  341 + # Loop over models
  342 + for model in self.models:
  343 +
  344 + # Continue only if point source or extended source model
  345 + if model.type() == "PointSource" or model.type() == "ExtendedSource":
  346 +
  347 + line = self.model2ds9string(model)
  348 + if len(line):
  349 + f.write(line+"\n")
  350 +
  351 + # Logging for diffuse components
  352 + elif model.type() == "DiffuseSource":
  353 + self.log("Skipping diffuse model "+model.name()+"\n")
  354 +
  355 + # Logging for background components
  356 + else:
  357 + if self.logExplicit():
  358 + self.log("Skipping background model "+model.name()+"\n")
  359 +
  360 + # Close file
  361 + f.close()
  362 +
  363 + # Return
  364 + return
  365 +
  366 + def model2ds9string(self, model):
  367 + """
  368 + Converts model instance to ds9 region string
  369 + """
  370 +
  371 + # Initialise return string
  372 + ds9string = ""
  373 +
  374 + # Determine color
  375 + color = self.fixed_color
  376 + for par in model:
  377 + if par.is_free():
  378 + color = self.free_color
  379 + break
  380 +
  381 + # Initialise flag ot continue
  382 + is_valid = True
  383 +
  384 + # Retrieve model position
  385 + try:
  386 + modelpos = model.spatial().dir()
  387 + except AttributeError:
  388 + self.log("Skipping source "+model.name()+": Could not determine sky position\n")
  389 + is_valid = False
  390 +
  391 + # Continue only if position was found
  392 + if is_valid:
  393 +
  394 + # Retrieve model type and name
  395 + modeltype = model.type()
  396 + modelname = model.name()
  397 +
  398 + # Handle point source
  399 + if modeltype == "PointSource":
  400 +
  401 + ds9string += "point("
  402 + ds9string += str(modelpos.ra_deg())
  403 + ds9string += ","
  404 + ds9string += str(modelpos.dec_deg())
  405 + ds9string += ") # "
  406 + ds9string += "point="+self.pnt_type+" "
  407 + ds9string += str(self.pnt_mark_size)+" "
  408 +
  409 + # Hanlde extended sources
  410 + elif modeltype == "ExtendedSource":
  411 +
  412 + # Retrieve spatial model
  413 + spatial = model.spatial()
  414 + classname = spatial.classname()
  415 +
  416 + # Handle radial sources
  417 + if "Radial" in classname:
  418 +
  419 + # Retrieve short name of model class (e.g. "Gauss" or "Disk)
  420 + shorttype = classname.split("Radial")[-1]
  421 +
  422 + # Handle Disk and Shell model
  423 + if classname == "GModelSpatialRadialDisk" or classname == "GModelSpatialRadialShell":
  424 + size = spatial.radius()
  425 +
  426 + # Handle Gauss Model
  427 + elif classname == "GModelSpatialRadialGauss":
  428 + size = spatial.sigma()
  429 +
  430 + # Skip if source is unknown
  431 + else:
  432 + self.log("Skipping source "+model.name()+": Spatial model \""+classname+"\" unkown\n")
  433 + is_valid = False
  434 +
  435 + # Append radial ds9 string
  436 + if is_valid:
  437 + ds9string += "circle("
  438 + ds9string += str(modelpos.ra_deg())
  439 + ds9string += ","
  440 + ds9string += str(modelpos.dec_deg())
  441 + ds9string += ","
  442 + ds9string += str(size*3600.)+"\") #"
  443 +
  444 + # Handle elliptical sources
  445 + elif "Elliptical" in classname:
  446 +
  447 + # Retrieve short name and source size
  448 + shorttype = classname.split("Elliptical")[-1]
  449 + size1 = spatial.semimajor()
  450 + size2 = spatial.semiminor()
  451 + angle = spatial.posangle()
  452 +
  453 + # Append elliptical ds9 string
  454 + ds9string += "ellipse("
  455 + ds9string += str(modelpos.ra_deg())
  456 + ds9string += ","
  457 + ds9string += str(modelpos.dec_deg())
  458 + ds9string += ","
  459 + ds9string += str(size1*3600.)+"\""
  460 + ds9string += ","
  461 + ds9string += str(size2*3600.)+"\""
  462 + ds9string += ","
  463 + ds9string += str(angle+90.0)+") # "
  464 +
  465 + # Skip if source is neither radial nor elliptical
  466 + else:
  467 + self.log("Skipping source "+model.name()+": Spatial model neither \"Radial\" nor \"Elliptical\"\n")
  468 +
  469 + # Add short name to modelname
  470 + if self.show_ext_type:
  471 + modelname +=" ("+shorttype+")"
  472 +
  473 + # Add user defined attributes
  474 + ds9string += "color="+color+" "
  475 + ds9string += "width="+str(self.width)+" "
  476 + ds9string += "font=\""+self.font+" "+str(self.fontsize)+" "+self.fonttype+" "+self.fonttype2+"\" "
  477 + if self.show_labels:
  478 + ds9string += "text={"+modelname+"}"
  479 +
  480 + # Return string
  481 + return ds9string
  482 +
  483 + def execute(self):
  484 + """
  485 + Execute the script.
  486 + """
  487 + # Run the script
  488 + self.run()
  489 +
  490 + # Save ds9 file if required
  491 + self.save()
  492 +
  493 + # Return
  494 + return
  495 +
  496 +
  497 +# ======================== #
  498 +# Main routine entry point #
  499 +# ======================== #
  500 +if __name__ == '__main__':
  501 + """
  502 + Generates model information output.
  503 + """
  504 + # Create instance of application
  505 + app = csmodelinfo(sys.argv)
  506 +
  507 + # Open logfile
  508 + app.logFileOpen()
  509 +
  510 + # Execute application
  511 + app.execute()
... ...
cscripts/csmodelmerge.py 0 → 100755
  1 +#!/usr/bin/env python
  2 +# ==========================================================================
  3 +# Merges model XML files into one file
  4 +#
  5 +# Copyright (C) 2015 Michael Mayer
  6 +#
  7 +# This program is free software: you can redistribute it and/or modify
  8 +# it under the terms of the GNU General Public License as published by
  9 +# the Free Software Foundation, either version 3 of the License, or
  10 +# (at your option) any later version.
  11 +#
  12 +# This program is distributed in the hope that it will be useful,
  13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 +# GNU General Public License for more details.
  16 +#
  17 +# You should have received a copy of the GNU General Public License
  18 +# along with this program. If not, see <http://www.gnu.org/licenses/>.
  19 +#
  20 +# ==========================================================================
  21 +import gammalib
  22 +import ctools
  23 +import sys
  24 +import glob
  25 +
  26 +
  27 +# ================== #
  28 +# csmodelmerge class #
  29 +# ================== #
  30 +class csmodelmerge(ctools.cscript):
  31 + """
  32 + This class merges an arbitray number of model container into one output
  33 + model XML file.
  34 + """
  35 + def __init__(self, *argv):
  36 + """
  37 + Constructor.
  38 + """
  39 + # Set name
  40 + self.name = "csmodelmerge"
  41 + self.version = "1.1.0"
  42 +
  43 + # Make sure that parfile exists
  44 + file = self.parfile()
  45 +
  46 + # Initialise application
  47 + if len(argv) == 0:
  48 + ctools.cscript.__init__(self, self.name, self.version)
  49 + elif len(argv) == 1:
  50 + ctools.cscript.__init__(self, self.name, self.version, *argv)
  51 + else:
  52 + raise TypeError("Invalid number of arguments given.")
  53 +
  54 + # Set logger properties
  55 + self.log_header()
  56 + self.log.date(True)
  57 +
  58 + # Return
  59 + return
  60 +
  61 + def __del__(self):
  62 + """
  63 + Destructor.
  64 + """
  65 + # Return
  66 + return
  67 +
  68 + def parfile(self):
  69 + """
  70 + Check if parfile exists. If parfile does not exist then create a
  71 + default parfile. This kluge avoids shipping the cscript with a
  72 + parfile.
  73 + """
  74 +
  75 + # Set parfile name
  76 + parfile = self.name+".par"
  77 +
  78 + try:
  79 + pars = gammalib.GApplicationPars(parfile)
  80 + except:
  81 + # Signal that parfile was not found
  82 + print("Parfile \""+parfile+"\" not found. Create default parfile.")
  83 +
  84 + # Create default parfile
  85 + pars = gammalib.GApplicationPars()
  86 + pars.append(gammalib.GApplicationPar("inmodels","s","a","model.xml","","","Input model XML files"))
  87 + pars.append(gammalib.GApplicationPar("outmodel","f","a","NONE","","","Output model file"))
  88 + pars.append_standard()
  89 + pars.append(gammalib.GApplicationPar("logfile","f","h","csmodelmerge.log","","","Log filename"))
  90 + pars.save(parfile)
  91 +
  92 + # Return
  93 + return
  94 +
  95 + def get_parameters(self):
  96 + """
  97 + Get parameters from parfile and setup the observation.
  98 + """
  99 + # Get input models
  100 + self.inmodels = self["inmodels"].string()
  101 +
  102 + # Interpet inmodels string
  103 + # Handle ascii files
  104 + if "@" == self.inmodels[0]:
  105 + self.files = open(self.inmodels.replace("@","")).read().splitlines()
  106 +
  107 + # Handle wild card strings
  108 + elif "*" in self.inmodels:
  109 + self.files = glob.glob(self.inmodels)
  110 +
  111 + # Handle space-separated list
  112 + elif " " in self.inmodels:
  113 + self.files = self.inmodels.split(" ")
  114 +
  115 + # Handle comma-separated list
  116 + elif "," in self.inmodels:
  117 + self.files = self.inmodels.split(",")
  118 +
  119 + # Throw exception if input models cannot be decoded
  120 + else:
  121 + msg = "Parameter \"inmodels\" must contain either an @ASCII"+\
  122 + " file, a comma-separated or whitespace-separated list"+\
  123 + " of files or a wildcard string"
  124 + raise gammalib.GException.invalid_argument("csmodelmerge::get_parameters", msg)
  125 +
  126 + # Get output file
  127 + self.outmodel = self["outmodel"].filename()
  128 +
  129 + # Return
  130 + return
  131 +
  132 + def run(self):
  133 + """
  134 + Run the script.
  135 + """
  136 + # Switch screen logging on in debug mode
  137 + if self.logDebug():
  138 + self.log.cout(True)
  139 +
  140 + # Get parameters
  141 + self.get_parameters()
  142 +
  143 + # Write input parameters into logger
  144 + if self.logTerse():
  145 + self.log_parameters()
  146 + self.log("\n")
  147 +
  148 + # Dump header
  149 + if self.logTerse():
  150 + self.log("\n")
  151 + self.log.header1("Merging Models")
  152 + self.log("\n")
  153 +
  154 + # Initialise output model container
  155 + self.models = gammalib.GModels()
  156 +
  157 + # Loop over model files
  158 + for modelfile in self.files:
  159 +
  160 + # Logging
  161 + self.log("Adding "+modelfile)
  162 + self.log("\n")
  163 +
  164 + # Open models
  165 + model_add = gammalib.GModels(modelfile)
  166 +
  167 + # Append models to container
  168 + for model in model_add:
  169 + self.models.append(model)
  170 +
  171 + # Return
  172 + return
  173 +
  174 + def save(self):
  175 + """
  176 + Save pointings to ds9 region file if required
  177 + """
  178 + # Logging
  179 + if self.logExplicit():
  180 + self.log("\n")
  181 + self.log.header1("Saving model file")
  182 + self.log("\n")
  183 +
  184 + # Save models
  185 + self.models.save(self.outmodel)
  186 +
  187 + # Return
  188 + return
  189 +
  190 + def execute(self):
  191 + """
  192 + Execute the script.
  193 + """
  194 + # Run the script
  195 + self.run()
  196 +
  197 + # Save ds9 file if required
  198 + self.save()
  199 +
  200 + # Return
  201 + return
  202 +
  203 +
  204 +# ======================== #
  205 +# Main routine entry point #
  206 +# ======================== #
  207 +if __name__ == '__main__':
  208 + """
  209 + Merges model XML files
  210 + """
  211 + # Create instance of application
  212 + app = csmodelmerge(sys.argv)
  213 +
  214 + # Open logfile
  215 + app.logFileOpen()
  216 +
  217 + # Execute application
  218 + app.execute()
... ...
cscripts/csobsinfo.py 0 → 100755
  1 +#!/usr/bin/env python
  2 +# ==========================================================================
  3 +# Dump information about observation into log file
  4 +#
  5 +# Copyright (C) 2015 Michael Mayer
  6 +#
  7 +# This program is free software: you can redistribute it and/or modify
  8 +# it under the terms of the GNU General Public License as published by
  9 +# the Free Software Foundation, either version 3 of the License, or
  10 +# (at your option) any later version.
  11 +#
  12 +# This program is distributed in the hope that it will be useful,
  13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 +# GNU General Public License for more details.
  16 +#
  17 +# You should have received a copy of the GNU General Public License
  18 +# along with this program. If not, see <http://www.gnu.org/licenses/>.
  19 +#
  20 +# ==========================================================================
  21 +import gammalib
  22 +import ctools
  23 +import sys
  24 +
  25 +
  26 +# =============== #
  27 +# csobsinfo class #
  28 +# =============== #
  29 +class csobsinfo(ctools.cscript):
  30 + """
  31 + This class dumps information about an observation container into a
  32 + logfile or on screen. This might be helpful for quick access to an
  33 + observation container showing, e.g., total lifetime, energy range etc.
  34 + """
  35 + def __init__(self, *argv):
  36 + """
  37 + Constructor.
  38 + """
  39 + # Set name
  40 + self.name = "csobsinfo"
  41 + self.version = "1.1.0"
  42 +
  43 + # Make sure that parfile exists
  44 + file = self.parfile()
  45 +
  46 + # Initialise application
  47 + if len(argv) == 0:
  48 + ctools.cscript.__init__(self, self.name, self.version)
  49 + elif len(argv) == 1:
  50 + ctools.cscript.__init__(self, self.name, self.version, *argv)
  51 + else:
  52 + raise TypeError("Invalid number of arguments given.")
  53 +
  54 + # Set logger properties
  55 + self.log_header()
  56 + self.log.date(True)
  57 +
  58 + # Return
  59 + return
  60 +
  61 + def __del__(self):
  62 + """
  63 + Destructor.
  64 + """
  65 + # Return
  66 + return
  67 +
  68 + def parfile(self):
  69 + """
  70 + Check if parfile exists. If parfile does not exist then create a
  71 + default parfile. This kluge avoids shipping the cscript with a
  72 + parfile.
  73 + """
  74 +
  75 + # Set parfile name
  76 + parfile = self.name+".par"
  77 +
  78 + try:
  79 + pars = gammalib.GApplicationPars(parfile)
  80 + except:
  81 + # Signal that parfile was not found
  82 + print("Parfile \""+parfile+"\" not found. Create default parfile.")
  83 +
  84 + # Create default parfile
  85 + pars = gammalib.GApplicationPars()
  86 + pars.append(gammalib.GApplicationPar("inobs","f","a","obs.xml","","","Event list, counts cube, or observation definition file"))
  87 + pars.append(gammalib.GApplicationPar("offset","b","h","no","","","Compute offset from target to pointing positions"))
  88 + pars.append(gammalib.GApplicationPar("ra","r","a","0.0","","","Target Right Ascension"))
  89 + pars.append(gammalib.GApplicationPar("dec","r","a","0.0","","","Target Declination"))
  90 + pars.append(gammalib.GApplicationPar("ds9file","f","h","NONE","","","DS9 region file containing pointings"))
  91 + pars.append_standard()
  92 + pars.append(gammalib.GApplicationPar("logfile","f","h","csobsinfo.log","","","Log filename"))
  93 + pars.save(parfile)
  94 +
  95 + # Return
  96 + return
  97 +
  98 + def get_parameters(self):
  99 + """
  100 + Get parameters from parfile and setup the observation.
  101 + """
  102 + # Get parameters
  103 + self.require_inobs("csobsinfo::get_parameters")
  104 + self.obs = self.get_observations(False)
  105 +
  106 + # Initialise object position
  107 + self.obj_dir = gammalib.GSkyDir()
  108 +
  109 + # Get (optional) offset parameters
  110 + self.m_offset = self["offset"].boolean()
  111 + if self.m_offset:
  112 + ra = self["ra"].real()
  113 + dec = self["dec"].real()
  114 + self.obj_dir.radec_deg(ra,dec)
  115 +
  116 + # Get (optional) DS9 filename
  117 + self.ds9file = self["ds9file"].filename()
  118 +
  119 + # Return
  120 + return
  121 +
  122 + def run(self):
  123 + """
  124 + Run the script.
  125 + """
  126 + # Switch screen logging on in debug mode
  127 + if self.logDebug():
  128 + self.log.cout(True)
  129 +
  130 + # Get parameters
  131 + self.get_parameters()
  132 +
  133 + # Write input parameters into logger
  134 + if self.logTerse():
  135 + self.log_parameters()
  136 + self.log("\n")
  137 +
  138 + # Initialise arrays to store certain values for reuse
  139 + # Todo, think about using a python dictionary
  140 + self.offsets = []
  141 + self.zeniths = []
  142 + self.azimuths = []
  143 + self.pnt_ra = []
  144 + self.pnt_dec = []
  145 + obs_names = []
  146 +
  147 + # Initialise output to be filled
  148 + self.ebounds = gammalib.GEbounds()
  149 + self.gti = gammalib.GGti()
  150 + ontime = 0.0
  151 + livetime = 0.0
  152 + n_events = 0
  153 + n_eventbins = 0
  154 + n_obs_binned = 0
  155 + n_obs_unbinned = 0
  156 +
  157 + # Logging
  158 + self.log.header1("Looping over observations")
  159 +
  160 + # Loop over observations
  161 + for obs in self.obs:
  162 +
  163 +
  164 + # Skip non-CTA observations
  165 + if not obs.classname() == "GCTAObservation":
  166 + self.log("Skipping "+obs.instrument()+" observation\n")
  167 + continue
  168 +
  169 + # Use observed object as observation name
  170 + # if name is not given
  171 + obs_name = obs.name()
  172 + if obs_name == "":
  173 + obs_name = obs.object()
  174 +
  175 + # Logging
  176 + if self.logTerse():
  177 + self.log.header2(obs_name)
  178 +
  179 + # Retrieve observation name
  180 + obs_names.append(obs_name)
  181 +
  182 + # Retrieve energy boundaries
  183 + obs_bounds = obs.events().ebounds()
  184 +
  185 + # Retrieve time interval
  186 + obs_gti = obs.events().gti()
  187 +
  188 + # Compute mean time and dead time fraction in percent
  189 + tmean = (obs_gti.tstart() + obs_gti.tstop())
  190 + tmean *= 0.5
  191 + deadfrac = (1.0-obs.deadc(tmean))*100.0
  192 +
  193 + # Retrieve pointing and store Ra,Dec
  194 + pnt_dir = obs.pointing().dir()
  195 + self.pnt_ra.append(pnt_dir.ra_deg())
  196 + self.pnt_dec.append(pnt_dir.dec_deg())
  197 +
  198 + # If avaliable append energy boundaries
  199 + if obs_bounds.size() > 0 :
  200 + self.ebounds.merge(obs_bounds.emin(),obs_bounds.emax())
  201 +
  202 + # Append time interval
  203 + self.gti.merge(obs_gti.tstart(), obs_gti.tstop())
  204 +
  205 + # increment global livetime and ontime
  206 + ontime += obs.ontime()
  207 + livetime += obs.livetime()
  208 +
  209 + # Log the event type (binned or unbinned)
  210 + if self.logTerse():
  211 + self.log.parformat("binned")
  212 +
  213 + if obs.eventtype() == "CountsCube":
  214 + n_eventbins += obs.events().size()
  215 + n_obs_binned += 1
  216 + if self.logTerse():
  217 + self.log("yes")
  218 + self.log("\n")
  219 + self.log.parformat("Number of bins")
  220 + self.log(str(obs.events().size()))
  221 + self.log("\n")
  222 + else:
  223 + n_events += obs.events().size()
  224 + n_obs_unbinned += 1
  225 + if self.logTerse():
  226 + self.log("no")
  227 + self.log("\n")
  228 + self.log.parformat("Number of events")
  229 + self.log(str(obs.events().size()))
  230 + self.log("\n")
  231 +
  232 + # Log option
  233 + if self.logTerse():
  234 +
  235 + # Log the observation energy range (if available)
  236 + self.log.parformat("Energy range")
  237 + if obs_bounds.size() == 0:
  238 + self.log("undefined")
  239 + else:
  240 + self.log(str(obs_bounds.emin())+" - "+str(obs_bounds.emax()))
  241 + self.log("\n")
  242 +
  243 + # Log observation time interval
  244 + self.log.parformat("Time range (MJD)")
  245 + if obs_gti.size() == 0:
  246 + self.log("undefined")
  247 + else:
  248 + self.log(str(obs_gti.tstart().mjd())+" - "+str(obs_gti.tstop().mjd()))
  249 + self.log("\n")
  250 +
  251 + # Log ontime
  252 + self.log.parformat("Ontime [s]")
  253 + self.log(str(obs.ontime()))
  254 + self.log("\n")
  255 +
  256 + # Log livetime
  257 + self.log.parformat("Livetime [s]")
  258 + self.log(str(obs.livetime()))
  259 + self.log("\n")
  260 +
  261 + # Log dead time fraction
  262 + self.log.parformat("Dead-time fraction (%)")
  263 + self.log("%.3f" % (deadfrac))
  264 + self.log("\n")
  265 +
  266 + # Log pointing direction
  267 + self.log.parformat("Pointing")
  268 + self.log(str(pnt_dir))
  269 + self.log("\n")
  270 +
  271 + # Log offset if possible
  272 + if self.m_offset:
  273 + offset = pnt_dir.dist_deg(self.obj_dir)
  274 + self.offsets.append(offset)
  275 + self.log.parformat("Offset")
  276 + self.log("%.2f" % (offset))
  277 + self.log("\n")
  278 + else:
  279 + self.offsets.append(-1.0)
  280 +
  281 + # Retrieve zenith and azimuth and store for later use
  282 + zenith = obs.pointing().zenith()
  283 + azimuth = obs.pointing().azimuth()
  284 + self.zeniths.append(zenith)
  285 + self.azimuths.append(azimuth)
  286 +
  287 + # Log Zenith and Azimuth if required
  288 + if self.logExplicit():
  289 + self.log.parformat("Zenith angle")
  290 + self.log("%.2f" % (zenith))
  291 + self.log("\n")
  292 + self.log.parformat("Azimuth angle")
  293 + self.log("%.2f" % (azimuth))
  294 + self.log("\n\n")
  295 +
  296 + # Log summary
  297 + self.log("\n")
  298 + self.log.header1("Summary")
  299 +
  300 + # Log general summary
  301 + self.log.parformat("Unbinned observations")
  302 + self.log(str(n_obs_unbinned))
  303 + self.log("\n")
  304 + self.log.parformat("Number of events")
  305 + self.log(str(n_events))
  306 + self.log("\n")
  307 + self.log.parformat("Binned observations")
  308 + self.log(str(n_obs_binned))
  309 + self.log("\n")
  310 + self.log.parformat("Number of bins")
  311 + self.log(str(n_eventbins))
  312 + self.log("\n\n")
  313 +
  314 + # Log pointing summary
  315 + self.log.header3("Pointings")
  316 +
  317 + # Log mean offset if possible
  318 + if self.m_offset:
  319 + self.log.parformat("Mean offset angle")
  320 + self.log("%.2f" % (sum(self.offsets)/len(self.offsets)))
  321 + self.log("\n")
  322 +
  323 + # Log mean azimuth and zenith angle
  324 + self.log.parformat("Mean zenith angle")
  325 + self.log("%.2f" % (sum(self.zeniths)/len(self.zeniths)))
  326 + self.log("\n")
  327 + self.log.parformat("Mean azimuth angle")
  328 + self.log("%.2f" % (sum(self.azimuths)/len(self.azimuths)))
  329 + self.log("\n")
  330 +
  331 + # Log name of observations if requested
  332 + if self.logExplicit():
  333 + obs_set = set(obs_names)
  334 + for name in obs_set:
  335 + self.log.parformat("\""+name+"\"")
  336 + self.log(str(obs_names.count(name)))
  337 + self.log("\n")
  338 + self.log("\n")
  339 +
  340 + # Log energy range
  341 + self.log.header3("Energy range")
  342 + self.log.parformat("Emin")
  343 + if self.ebounds.size() == 0:
  344 + self.log("undefined")
  345 + else:
  346 + self.log(str(self.ebounds.emin()))
  347 + self.log("\n")
  348 + self.log.parformat("Emax")
  349 + if self.ebounds.size() == 0:
  350 + self.log("undefined")
  351 + else:
  352 + self.log(str(self.ebounds.emax()))
  353 + self.log("\n\n")
  354 +
  355 + # Log time range
  356 + self.log.header3("Time range")
  357 + self.log.parformat("Start [MJD]")
  358 + self.log(str(self.gti.tstart().mjd()))
  359 + self.log("\n")
  360 + self.log.parformat("Stop [MJD]")
  361 + self.log(str(self.gti.tstop().mjd()))
  362 + self.log("\n")
  363 +
  364 + # Log ontime and livetime in different units
  365 + self.log.parformat("Total ontime")
  366 + self.log("%.2f s = %.2f min = %.2f h" % (ontime, ontime/60., ontime/3600.))
  367 + self.log("\n")
  368 + self.log.parformat("Total livetime")
  369 + self.log("%.2f s = %.2f min = %.2f h" % (livetime, livetime/60.0, livetime/3600.))
  370 + self.log("\n")
  371 +
  372 + # Return
  373 + return
  374 +
  375 + def save(self):
  376 + """
  377 + Save pointings to ds9 region file if required
  378 + """
  379 +
  380 + # Check if ds9 file is valid
  381 + if not self.ds9file == "NONE":
  382 +
  383 + # Open file
  384 + f = open(self.ds9file,"w")
  385 +
  386 + # Write coordinate system
  387 + f.write("fk5\n")
  388 +
  389 + # Loop over pointings
  390 + for i in range(len(self.pnt_ra)):
  391 +
  392 + # Create string
  393 + line = "point("
  394 + line+=str(self.pnt_ra[i])+","+str(self.pnt_dec[i])+")"
  395 + line+=" # point=cross 20 width=3 \n"
  396 +
  397 + # Write to file
  398 + f.write(line)
  399 +
  400 + # Close file
  401 + f.close()
  402 +
  403 + # Return
  404 + return
  405 +
  406 +
  407 + def zeniths(self):
  408 + """
  409 + Return zenith angles
  410 + """
  411 + return self.zeniths
  412 +
  413 + def azimuths(self):
  414 + """
  415 + Return azimuth angles
  416 + """
  417 + return self.azimuths
  418 +
  419 + def offsets(self):
  420 + """
  421 + Return offset angles
  422 + """
  423 + return self.offsets
  424 +
  425 + def ebounds(self):
  426 + """
  427 + Return energy boundaries
  428 + """
  429 + return self.ebounds
  430 +
  431 + def gti(self):
  432 + """
  433 + Return good time intervals
  434 + """
  435 + return self.gti
  436 +
  437 + def execute(self):
  438 + """
  439 + Execute the script.
  440 + """
  441 + # Run the script
  442 + self.run()
  443 +
  444 + # Save ds9 file if required
  445 + self.save()
  446 +
  447 + # Return
  448 + return
  449 +
  450 +
  451 +# ======================== #
  452 +# Main routine entry point #
  453 +# ======================== #
  454 +if __name__ == '__main__':
  455 + """
  456 + Generates information about an observation container.
  457 + """
  458 + # Create instance of application
  459 + app = csobsinfo(sys.argv)
  460 +
  461 + # Open logfile
  462 + app.logFileOpen()
  463 +
  464 + # Execute application
  465 + app.execute()
... ...
cscripts/cstsmapmerge.py 0 → 100755
  1 +#!/usr/bin/env python
  2 +# ==========================================================================
  3 +# Merges sliced TS map files into one map
  4 +#
  5 +# Copyright (C) 2015 Michael Mayer
  6 +#
  7 +# This program is free software: you can redistribute it and/or modify
  8 +# it under the terms of the GNU General Public License as published by
  9 +# the Free Software Foundation, either version 3 of the License, or
  10 +# (at your option) any later version.
  11 +#
  12 +# This program is distributed in the hope that it will be useful,
  13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 +# GNU General Public License for more details.
  16 +#
  17 +# You should have received a copy of the GNU General Public License
  18 +# along with this program. If not, see <http://www.gnu.org/licenses/>.
  19 +#
  20 +# ==========================================================================
  21 +import gammalib
  22 +import ctools
  23 +import sys
  24 +import glob
  25 +import os
  26 +
  27 +
  28 +# ================== #
  29 +# cstsmapmerge class #
  30 +# ================== #
  31 +class cstsmapmerge(ctools.cscript):
  32 + """
  33 + This class merges TS map files into one TS map
  34 + """
  35 + def __init__(self, *argv):
  36 + """
  37 + Constructor.
  38 + """
  39 + # Set name
  40 + self.name = "cstsmapmerge"
  41 + self.version = "1.1.0"
  42 +
  43 + # Make sure that parfile exists
  44 + file = self.parfile()
  45 +
  46 + # Initialise application
  47 + if len(argv) == 0:
  48 + ctools.cscript.__init__(self, self.name, self.version)
  49 + elif len(argv) == 1:
  50 + ctools.cscript.__init__(self, self.name, self.version, *argv)
  51 + else:
  52 + raise TypeError("Invalid number of arguments given.")
  53 +
  54 + # Set logger properties
  55 + self.log_header()
  56 + self.log.date(True)
  57 +
  58 + # Return
  59 + return
  60 +
  61 + def __del__(self):
  62 + """
  63 + Destructor.
  64 + """
  65 + # Return
  66 + return
  67 +
  68 + def parfile(self):
  69 + """
  70 + Check if parfile exists. If parfile does not exist then create a
  71 + default parfile. This kluge avoids shipping the cscript with a
  72 + parfile.
  73 + """
  74 +
  75 + # Set parfile name
  76 + parfile = self.name+".par"
  77 +
  78 + try:
  79 + pars = gammalib.GApplicationPars(parfile)
  80 + except:
  81 + # Signal that parfile was not found
  82 + print("Parfile \""+parfile+"\" not found. Create default parfile.")
  83 +
  84 + # Create default parfile
  85 + pars = gammalib.GApplicationPars()
  86 + pars.append(gammalib.GApplicationPar("inmaps","s","a","tsmap.fits","","","Input TS map FITS files"))
  87 + pars.append(gammalib.GApplicationPar("outmap","f","a","NONE","","","Output TS map FITS file"))
  88 + pars.append(gammalib.GApplicationPar("overwrite","b","h","yes","","","Overwrite previously filled bins?"))
  89 + pars.append(gammalib.GApplicationPar("delete","b","h","no","","","Delete merged files?"))
  90 + pars.append_standard()
  91 + pars.append(gammalib.GApplicationPar("logfile","f","h","cstsmapmerge.log","","","Log filename"))
  92 + pars.save(parfile)
  93 +
  94 + # Return
  95 + return
  96 +
  97 + def get_parameters(self):
  98 + """
  99 + Get parameters from parfile and setup the observation.
  100 + """
  101 + # Get input models
  102 + self.inmodels = self["inmaps"].string()
  103 +
  104 + # Interpet inmodels string
  105 + # Handle ascii files
  106 + if "@" == self.inmodels[0]:
  107 + self.files = open(self.inmodels.replace("@","")).read().splitlines()
  108 +
  109 + # Handle wild card strings
  110 + elif "*" in self.inmodels:
  111 + self.files = glob.glob(self.inmodels)
  112 +
  113 + # Handle space-separated list
  114 + elif " " in self.inmodels:
  115 + self.files = self.inmodels.split(" ")
  116 +
  117 + # Handle comma-separated list
  118 + elif "," in self.inmodels:
  119 + self.files = self.inmodels.split(",")
  120 +
  121 + # Throw exception if input models cannot be decoded
  122 + else:
  123 + msg = "Parameter \"inmmaps\" must contain either an @ASCII file,"+\
  124 + " a comma-separated or whitespace-separated list of files"+\
  125 + " or a wildcard string"
  126 + raise gammalib.GException.invalid_argument("cstsmapmerge::get_parameters", msg)
  127 +
  128 + # Check number of files. We need at least two files.
  129 + if len(self.files) <= 1:
  130 + msg = "Need at least two files to start merging, "+\
  131 + str(len(self.files))+" files given."
  132 + raise gammalib.GException.invalid_argument("cstsmapmerge::get_parameters", msg)
  133 +
  134 + # Get output file
  135 + self.outmap = self["outmap"].filename()
  136 +
  137 + # Get other parameters
  138 + self.overwrite = self["overwrite"].boolean()
  139 + self.delete = self["delete"].boolean()
  140 +
  141 + # Return
  142 + return
  143 +
  144 + def init_map(self, fitsfile):
  145 + """
  146 + """
  147 + # Set filename
  148 + self.in_filename = fitsfile
  149 +
  150 + # Open FITS file
  151 + fits = gammalib.GFits(fitsfile)
  152 + self.tsmap = gammalib.GSkyMap()
  153 + self.tsmap.read(fits[0])
  154 + self.statusmap = gammalib.GSkyMap()
  155 + self.statusmap.read(fits["STATUS MAP"])
  156 +
  157 + # Get other maps
  158 + self.maps = []
  159 + self.mapnames = []
  160 +
  161 + # Loop over extensions
  162 + for hdu in fits:
  163 +
  164 + # Leave out primary and status extension
  165 + if hdu.extname() != "IMAGE" and hdu.extname() != "STATUS MAP":
  166 +
  167 + # Add present maps
  168 + skymap = gammalib.GSkyMap()
  169 + skymap.read(hdu)
  170 + self.maps.append(skymap)
  171 + self.mapnames.append(hdu.extname())
  172 +
  173 + # Close FITS file
  174 + fits.close()
  175 +
  176 + # Return
  177 + return
  178 +
  179 + # Add map instances to each other. In this way the TS maps get merged
  180 + def add(self, fitsfile):
  181 +
  182 + # open FITS file
  183 + fits = gammalib.GFits(fitsfile)
  184 + add_tsmap = gammalib.GSkyMap()
  185 + add_tsmap.read(fits[0])
  186 + add_statusmap = gammalib.GSkyMap()
  187 + add_statusmap.read(fits["STATUS MAP"])
  188 +
  189 + # Get other maps
  190 + add_maps = []
  191 +
  192 + # Loop over extensions
  193 + for hdu in fits:
  194 +
  195 + # Leave out primary and status extension
  196 + if hdu.extname() != "IMAGE" and hdu.extname() != "STATUS MAP":
  197 +
  198 + # Add present maps
  199 + skymap = gammalib.GSkyMap()
  200 + skymap.read(hdu)
  201 + add_maps.append(skymap)
  202 +
  203 + # Close FITS file
  204 + fits.close()
  205 +
  206 + # Compare size of other maps
  207 + if not len(add_maps) == len(self.maps):
  208 + self.error("Maps cannot be added: Maps from \""+self.in_filename+"\" do not match from \""+fitsfile+"\"")
  209 +
  210 + # Loop over bins
  211 + for i in range(self.tsmap.npix()):
  212 + if add_statusmap[i] > 0.5:
  213 +
  214 + # Throw exception if this bin has already been computed
  215 + if self.statusmap[i] > 0.5 and not self.overwrite:
  216 + msg = "Attempt to merge bin which apparently has already"+\
  217 + " been merged. File \""+fitsfile+"\" contains"+\
  218 + " already merged bins. Set hidden parameter"+\
  219 + " overwrite=yes to avoid this error."
  220 + raise gammalib.GException.invalid_value("cstsmapmerge::add", msg)
  221 +
  222 + # Copy TS values
  223 + self.tsmap[i] = add_tsmap[i]
  224 +
  225 + # Copy status
  226 + self.statusmap[i] = add_statusmap[i]
  227 +
  228 + # Loop over maps and copy entries
  229 + for j in range(len(self.maps)):
  230 + self.maps[j][i] = add_maps[j][i]
  231 +
  232 + # Return
  233 + return
  234 +
  235 + def run(self):
  236 + """
  237 + Run the script.
  238 + """
  239 + # Switch screen logging on in debug mode
  240 + if self.logDebug():
  241 + self.log.cout(True)
  242 +
  243 + # Get parameters
  244 + self.get_parameters()
  245 +
  246 + # Write input parameters into logger
  247 + if self.logTerse():
  248 + self.log_parameters()
  249 + self.log("\n")
  250 +
  251 + if self.logTerse():
  252 + self.log("\n")
  253 + self.log.header1("Merging sliced TS map files")
  254 + self.log("\n")
  255 +
  256 + # Initialise file to start with
  257 + file0 = ""
  258 +
  259 + self.added_files = []
  260 +
  261 + # Test files for the entry status map
  262 + # use the first one to appear useful
  263 + for fitsfile in self.files:
  264 + if not gammalib.is_fits(fitsfile):
  265 + self.log("Skipping file \""+fitsfile+" (not a FITS file)\n")
  266 + fits = gammalib.GFits(fitsfile)
  267 +
  268 + if fits.contains("STATUS MAP"):
  269 + self.log("Using file \""+fitsfile+"\" as initialising map\n")
  270 + file0 = fitsfile
  271 + break
  272 + else:
  273 + if self.logExplicit():
  274 + self.log("File \""+fitsfile+"\" has not \"STATUS MAP\" extension\n")
  275 +
  276 + # Print an error message if no suitable file was provided
  277 + if file0 == "":
  278 + if self.logTerse():
  279 + self.log("None of the provided file seems to be a sliced ts map file (no \"STATUS MAP\" extension)\n")
  280 +
  281 + # Otherwise merge files
  282 + else:
  283 +
  284 + # copy file list
  285 + workfiles = self.files
  286 +
  287 + # Remove entry which will be used to initalise the map
  288 + workfiles.remove(file0)
  289 +
  290 + # Initialise map from first file
  291 + self.init_map(file0)
  292 +
  293 + # Append to added files
  294 + self.added_files.append(file0)
  295 +
  296 + # Loop over files
  297 + for fitsfile in workfiles:
  298 +
  299 + # Skip if file is not FITS
  300 + if not gammalib.is_fits(fitsfile):
  301 + if self.logTerse():
  302 + self.log("Skipping file \""+fitsfile+" (not a FITS file)\n")
  303 + continue
  304 +
  305 + # Skip if file does not contain status map
  306 + fits = gammalib.GFits(fitsfile)
  307 + if not fits.contains("STATUS MAP"):
  308 + if self.logTerse():
  309 + self.log("Skipping file \""+fitsfile+" (not a FITS file)\n")
  310 + continue
  311 +
  312 + # Logging
  313 + if self.logTerse():
  314 + self.log("Adding TS map slice \""+fitsfile+"\"\n")
  315 +
  316 + # Add file
  317 + self.add(fitsfile)
  318 +
  319 + # Append to added files
  320 + self.added_files.append(fitsfile)
  321 +
  322 + # Return
  323 + return
  324 +
  325 + def save(self):
  326 + """
  327 + Save merged tsmap file and remove slices if requested
  328 + """
  329 +
  330 + # Logging
  331 + if self.logExplicit():
  332 + self.log("\n")
  333 + self.log.header1("Saving merged TS map")
  334 + self.log("\n")
  335 +
  336 + # Create FITS file
  337 + fits = gammalib.GFits()
  338 +
  339 + # Write TS map into primary
  340 + self.tsmap.write(fits)
  341 +
  342 + # Loop over maps and write them to fits
  343 + for i in range(len(self.maps)):
  344 + self.maps[i].write(fits)
  345 +
  346 + # Set map names as extensions
  347 + for i in range(len(self.mapnames)):
  348 + fits[i+1].extname(self.mapnames[i])
  349 +
  350 + # Check if map is fully done
  351 + done = True
  352 + for pix in self.statusmap:
  353 + if pix < 0.5:
  354 + done = False
  355 + break
  356 +
  357 + # Write Status map if we are not done yet
  358 + if not done:
  359 + self.statusmap.write(fits)
  360 + fits[fits.size()-1].extname("STATUS MAP")
  361 +
  362 + # Save FITS file
  363 + fits.saveto(self.outmap, self.clobber())
  364 + if self.logExplicit():
  365 + self.log("Saved output map to \""+self.outmap+"\"\n")
  366 + if self.delete:
  367 + if self.logTerse():
  368 + self.log("\n")
  369 + self.log.header1("Deleting slices")
  370 + self.log("\n")
  371 + for filename in self.added_files:
  372 + if self.logExplicit():
  373 + self.log("Deleting file \""+filename+"\"\n")
  374 + os.remove(filename)
  375 +
  376 + # Return
  377 + return
  378 +
  379 + def execute(self):
  380 + """
  381 + Execute the script.
  382 + """
  383 + # Run the script
  384 + self.run()
  385 +
  386 + # Save ds9 file if required
  387 + self.save()
  388 +
  389 + # Return
  390 + return
  391 +
  392 +
  393 +# ======================== #
  394 +# Main routine entry point #
  395 +# ======================== #
  396 +if __name__ == '__main__':
  397 + """
  398 + Merges ts map slices.
  399 + """
  400 + # Create instance of application
  401 + app = cstsmapmerge(sys.argv)
  402 +
  403 + # Open logfile
  404 + app.logFileOpen()
  405 +
  406 + # Execute application
  407 + app.execute()
... ...
cscripts/tsmerge.py deleted
1   -#!/usr/bin/env python
2   -
3   -import gammalib
4   -import sys
5   -import os
6   -import glob
7   -import json
8   -
9   -def print_help():
10   - print("")
11   - print("tsmerge.py expects two keyword argumens: use via command line as follows")
12   - print("tsmerge.py files=<list of files> outfile=<desired outfile name>")
13   - print("-------------------------------------------------------------------------")
14   - print("*** \"outfile\" should be a path to a fits file")
15   - print("*** \"files\" should be either be:")
16   - print(" - an ascii-file listing the files your want to merge")
17   - print(" OR - a wildcard string describing the files for merging")
18   - print("-------------------------------------------------------------------------")
19   - print("")
20   - print("Example: python tsmerge,py files=tsmap*.fits outfile=tsmap.fits")
21   - print("")
22   - sys.exit(-1)
23   -
24   -
25   -# Maps class holding the different sky maps
26   -# created by cttsmap
27   -class maps:
28   -
29   - # Constructor
30   - def __init__(self,fitsfile):
31   -
32   - self.filename = fitsfile
33   - if not os.path.isfile(fitsfile):
34   - self.error("Maps instance cannot be constructed: File \""+self.filename+"\" does not exist")
35   -
36   - # open FITS file
37   - fits = gammalib.GFits(fitsfile)
38   -
39   - # get TS map
40   - self.tsmap = gammalib.GSkyMap()
41   - self.tsmap.read(fits[0])
42   -
43   - # Get status map
44   - if not fits.contains("STATUS MAP"):
45   - self.error("No extension \"STATUS MAP\" found in \""+self.filename+"\"")
46   - self.statusmap = gammalib.GSkyMap()
47   - self.statusmap.read(fits["STATUS MAP"])
48   -
49   - # Get other maps
50   - self.maps = []
51   - self.mapnames = []
52   - for hdu in fits:
53   - if hdu.extname() != "IMAGE" and hdu.extname() != "STATUS MAP":
54   - skymap = gammalib.GSkyMap()
55   - skymap.read(hdu)
56   - self.maps.append(skymap)
57   - self.mapnames.append(hdu.extname())
58   -
59   - # len operator
60   - def __len__(self):
61   - return len(self.maps)
62   -
63   - # operator []
64   - def __getitem__(self,index):
65   - return self.maps[index]
66   -
67   - # Check the status map for completeness
68   - def check_status(self):
69   - check = True
70   - for pix in self.statusmap:
71   - if pix < 0.5:
72   - check = False
73   - break
74   - return check
75   -
76   - # Save maps to outfile
77   - def save(self,outfile):
78   -
79   - fits = gammalib.GFits()
80   - self.tsmap.write(fits)
81   -
82   - for i in range(len(self.maps)):
83   - self.maps[i].write(fits)
84   -
85   - for i in range(len(self.mapnames)):
86   - fits[i+1].extname(self.mapnames[i])
87   -
88   - if not self.check_status():
89   - self.statusmap.write(fits)
90   - fits[fits.size()-1].extname("STATUS MAP")
91   - fits.saveto(outfile,True)
92   -
93   - # Add map instances to each other
94   - # in this way the TS maps get merged
95   - def add(self,addmaps):
96   - if not len(addmaps) == len(self.maps):
97   - self.error("Maps cannot be added: Maps from \""+self.filename+"\" do not match from \""+addmaps.filename+"\"")
98   -
99   - # Loop over bins
100   - for i in range(self.tsmap.npix()):
101   - if addmaps.statusmap[i] > 0.5:
102   - self.tsmap[i] = addmaps.tsmap[i]
103   - self.statusmap[i] = addmaps.statusmap[i]
104   - for j in range(len(self.maps)):
105   - self.maps[j][i] = addmaps[j][i]
106   - # Unify error messages
107   - def error(self,message):
108   - print("*** ERROR ***: "+message)
109   - sys.exit(-1)
110   -
111   -
112   -def pars_from_argv(argv):
113   -
114   - if argv is None:
115   - argv = sys.argv
116   -
117   - args = []
118   - kwargs = {}
119   - for s in argv[1:]:
120   - if s.count('=') == 1:
121   - key, value = s.split('=', 1)
122   - else:
123   - key, value = None, s
124   - try:
125   - value = json.loads(value)
126   - except ValueError:
127   - pass
128   - if key:
129   - kwargs[key] = value
130   - else:
131   - args.append(value)
132   - return args, kwargs
133   -
134   -
135   -def get_kwargs(argv):
136   - kwargs = {}
137   -
138   - for s in argv:
139   - if s.count('=') == 1:
140   - key, value = s.split('=', 1)
141   - kwargs[key] = value
142   -
143   - else:
144   - print_help()
145   -
146   - return kwargs
147   -
148   -if __name__ == "__main__":
149   - # Initialise list of files
150   -
151   - kwargs = get_kwargs(sys.argv[1:])
152   - if "outfile" not in kwargs or "files" not in kwargs:
153   - print_help()
154   - outfile = kwargs["outfile"]
155   - files = kwargs["files"]
156   - allfiles = []
157   - if os.path.isfile(files):
158   - allfiles = open(files).read().splitlines()
159   - else:
160   - allfiles = glob.glob(files)
161   -
162   - # Initialise files to be merged
163   - mergefiles = []
164   -
165   - # Test files for the entry status map
166   - # and add them to the file list
167   - for fitsfile in allfiles:
168   - fits = gammalib.GFits(fitsfile)
169   - if fits.contains("STATUS MAP"):
170   - mergefiles.append(fitsfile)
171   - fits.close()
172   -
173   - # create a maps instance from the first file
174   - finalmaps = maps(mergefiles[0])
175   -
176   - # add other files to the maps instance
177   - for fitsfile in mergefiles[1:]:
178   - finalmaps.add(maps(fitsfile))
179   -
180   - # save the filled maps to file
181   - finalmaps.save(outfile=outfile)
ctools.pc.in
... ... @@ -6,9 +6,9 @@ includedir=${prefix}/include
6 6 Name: ctools
7 7 Description: CTA science analysis tools
8 8 URL: http://cta.irap.omp.eu/ctools
9   -Version: 1.0.0
  9 +Version: 1.1.0
10 10 Requires:
11   -Requires.private: gammalib >= 1.0.0
  11 +Requires.private: gammalib >= 1.1.0
12 12 Conflicts:
13 13 Cflags: -I${includedir}/ctools @OPENMP_CXXFLAGS@
14 14 Libs: -L${libdir} -lctools
... ...
doc/Doxyfile
... ... @@ -32,7 +32,7 @@ PROJECT_NAME = ctools
32 32 # This could be handy for archiving the generated documentation or
33 33 # if some version control system is used.
34 34  
35   -PROJECT_NUMBER = 1.0.0
  35 +PROJECT_NUMBER = 1.1.0.dev
36 36  
37 37 # Using the PROJECT_BRIEF tag one can provide an optional one line description
38 38 # for a project that appears at the top of each page and should give viewer
... ...
doc/source/conf.py
... ... @@ -66,10 +66,10 @@ copyright = u&#39;2014-2015, ctools developers&#39;
66 66 # built documents.
67 67 #
68 68 # The short X.Y version.
69   -version = '1.0'
  69 +version = '1.1'
70 70  
71 71 # The full version, including alpha/beta/rc tags.
72   -release = '1.0.0'
  72 +release = '1.1.0.dev'
73 73  
74 74 # The language for content autogenerated by Sphinx. Refer to documentation
75 75 # for a list of supported languages.
... ...
doc/source/reference_manual/cscaldb.rst
1   -.. _cscaldb: cscaldb ======= Dumps all available instrument response functions into log fil. Synopsis -------- This scripts dumps all instrument response functions that are available in the calibration database into the log file. If you want the information on the screen, add the ``debug=yes`` parameter. General parameters ------------------ None Standard parameters ------------------- ``(chatter = 2) [integer]`` Verbosity of the executable: chatter = 0: no information will be logged chatter = 1: only errors will be logged chatter = 2: errors and actions will be logged chatter = 3: report about the task execution chatter = 4: detailed report about the task execution ``(clobber = yes) [boolean]`` Specifies whether an existing output counts cube should be overwritten. ``(debug = no) [boolean]`` Enables debug mode. In debug mode the executable will dump any log file output to the console. ``(mode = ql) [string]`` Mode of automatic parameters (default is "ql", i.e. "query and learn"). Related tools ------------- None
2 1 \ No newline at end of file
  2 +.. _cscaldb: cscaldb ======= Dumps all available instrument response functions into log file. Synopsis -------- This scripts dumps all instrument response functions that are available in the calibration database into the log file. If you want the information on the screen, add the ``debug=yes`` parameter. General parameters ------------------ None Standard parameters ------------------- ``(chatter = 2) [integer]`` Verbosity of the executable: chatter = 0: no information will be logged chatter = 1: only errors will be logged chatter = 2: errors and actions will be logged chatter = 3: report about the task execution chatter = 4: detailed report about the task execution ``(clobber = yes) [boolean]`` Specifies whether an existing output counts cube should be overwritten. ``(debug = no) [boolean]`` Enables debug mode. In debug mode the executable will dump any log file output to the console. ``(mode = ql) [string]`` Mode of automatic parameters (default is "ql", i.e. "query and learn"). Related tools ------------- None
3 3 \ No newline at end of file
... ...
doc/source/reference_manual/csmodelinfo.rst 0 → 100644
  1 +.. _csmodelinfo:
  2 +
  3 +csmodelinfo
  4 +===========
  5 +
  6 +Dumps information about a model container into log file or on screen.
  7 +
  8 +
  9 +Synopsis
  10 +--------
  11 +
  12 +This script provides detailled information about a given model container.
  13 +It presents the number of parameters, the number of free parameters (sub-
  14 +divided by spectral, spatial and temporal type). The tool further creates
  15 +information about any parameter that is stuck at the parameter boundaries.
  16 +This might be quite useful for debugging a fit. Finally the tool also list
  17 +the TS values of each source that was fitted, in order have a quick overview
  18 +on these quantities on the screen.
  19 +
  20 +In addition the tool is also capable of exporting the input model XML container
  21 +to a region file which is compatible to be read with ds9 or other displying
  22 +tools. To create a region file, the hidden parameter "ds9file" needs to be
  23 +specified. There are quite a few further hidden parameters to steer e.g.
  24 +color, font, etc of the region file output.
  25 +
  26 +
  27 +General parameters
  28 +------------------
  29 +
  30 +``inmodel [file]``
  31 + Event list, counts cube, or observation definition file
  32 +
  33 +``(ds9file = NONE) [file]``
  34 + Output DS9 region file containing models
  35 +
  36 +``(pnt_type=cross) <circle|box|diamond|cross|x|arrow|boxcircle> [string]``
  37 + Marker type for point sources
  38 +
  39 +``pnt_mark_size [integer]``
  40 + Marker size for point sources
  41 +
  42 +``(show_labels=yes) [boolean]``
  43 + Add source labels?
  44 +
  45 +``(width=2) [integer]``
  46 + Line width for regions
  47 +
  48 + ``(font=helvetica) <helvetica|times|courier> [string]``
  49 + Font for source labels
  50 +
  51 +``(fontsize=12) [integer]``
  52 + Font size for source labels
  53 +
  54 +``(fonttype=normal) <normal|bold> [string]``
  55 + Use normal or bold font?
  56 +
  57 +``(fonttype2=roman) <roman|italic> [string]``
  58 + Use roman or italic font?
  59 +
  60 +``(show_ext_type=yes) [boolean]``
  61 + Show type of extended model in source name?
  62 +
  63 +``(free_color=green) [string]``
  64 + Color for sources with free parameters (any ds9 color or hex code)
  65 +
  66 +``(fixed_color=magenta) [string]``
  67 + Color for sources without free parameters (any ds9 color or hex code)
  68 +
  69 +
  70 +Standard parameters
  71 +-------------------
  72 +
  73 +``(chatter = 2) [integer]``
  74 + Verbosity of the executable:
  75 + chatter = 0: no information will be logged
  76 +
  77 + chatter = 1: only errors will be logged
  78 +
  79 + chatter = 2: errors and actions will be logged
  80 +
  81 + chatter = 3: report about the task execution
  82 +
  83 + chatter = 4: detailed report about the task execution
  84 +
  85 +``(clobber = yes) [boolean]``
  86 + Specifies whether an existing output counts cube should be overwritten.
  87 +
  88 +``(debug = no) [boolean]``
  89 + Enables debug mode. In debug mode the executable will dump any log file output to the console.
  90 +
  91 +``(mode = ql) [string]``
  92 + Mode of automatic parameters (default is "ql", i.e. "query and learn").
  93 +
  94 +``(logfile = csmodelinfo.log) [filename]``
  95 + Log filename.
  96 +
  97 +
  98 +Related tools or scripts
  99 +------------------------
  100 +
  101 +None
0 102 \ No newline at end of file
... ...
doc/source/reference_manual/csmodelmerge.rst 0 → 100644
  1 +.. _csmodelmerge:
  2 +
  3 +csmodelmerge
  4 +============
  5 +
  6 +Merges an arbitrary number of model XML files into a single file.
  7 +
  8 +
  9 +Synopsis
  10 +--------
  11 +
  12 +This script merges several model XML file into a single model XML file. The
  13 +files are passed via the ``inmodels`` parameter. There are 4 options to specify
  14 +a list of files that should be merged:
  15 +- a space-separated list of file names (e.g. model1.xml model2.xml)
  16 +- a comma-separated list of file names (e.g. model1.xml,model2.xml)
  17 +- a wildcard string (e.g. mymodel*.xml)
  18 +- an ASCII file containing the file names, one file per line (e.g. @mymodels.txt)
  19 +
  20 +Note that the "@" needs to be specified in case of an ASCII file name. It is
  21 +also important to note that models with the same name cannot be appended. The
  22 +tool will throw and exception if the provided file contain models with the same
  23 +name.
  24 +
  25 +
  26 +General parameters
  27 +------------------
  28 +
  29 +``inmodels [string]``
  30 + Input model XML files
  31 +
  32 +``outmodel [file]``
  33 + Output model file
  34 +
  35 +
  36 +Standard parameters
  37 +-------------------
  38 +
  39 +``(chatter = 2) [integer]``
  40 + Verbosity of the executable:
  41 + chatter = 0: no information will be logged
  42 +
  43 + chatter = 1: only errors will be logged
  44 +
  45 + chatter = 2: errors and actions will be logged
  46 +
  47 + chatter = 3: report about the task execution
  48 +
  49 + chatter = 4: detailed report about the task execution
  50 +
  51 +``(clobber = yes) [boolean]``
  52 + Specifies whether an existing output counts cube should be overwritten.
  53 +
  54 +``(debug = no) [boolean]``
  55 + Enables debug mode. In debug mode the executable will dump any log file output to the console.
  56 +
  57 +``(mode = ql) [string]``
  58 + Mode of automatic parameters (default is "ql", i.e. "query and learn").
  59 +
  60 +``(logfile = csmodelmerge.log) [filename]``
  61 + Log filename.
  62 +
  63 +
  64 +Related tools or scripts
  65 +------------------------
  66 +
  67 +None
0 68 \ No newline at end of file
... ...
doc/source/reference_manual/csobsinfo.rst 0 → 100644
  1 +.. _csobsinfo:
  2 +
  3 +csobsinfo
  4 +=========
  5 +
  6 +Dumps information about an observation container into log file or on
  7 +screen.
  8 +
  9 +
  10 +Synopsis
  11 +--------
  12 +
  13 +This script provides detailed information about a given observation container.
  14 +For IACT observations usually several observations with different configurations
  15 +are combined. The script computes e.g. the overall energy range which could be
  16 +an important input for :doc:`ctbin` to create a suitable energy range. In
  17 +addition the script prints the pointing attributes like the average
  18 +zenith/azimuth angle. If the hidden boolean parameter "offset" is specified to
  19 +"yes", the script queries for the target position and computes the run-by-run
  20 +offset as well as its average. In the observation summary, the time range of
  21 +the observations including total ontime and (dead-time corrected) livetime is
  22 +shown.
  23 +
  24 +The script further contains the hidden parameter "ds9file". If specified with
  25 +a file name, the tool writes out a ds9 region file including a cross for each
  26 +pointing position in the sky.
  27 +
  28 +When executed from within python, the script provides methods to return arrays
  29 +containing observation-wise parameters. This might be useful for graphical
  30 +display within a script. The following methods are implemented:
  31 +- zeniths (returning all zenith angles)
  32 +- azimuths (returning all azimuth angles)
  33 +- offsets (returning all offset angles, provided the hidden parameter offset=yes)
  34 +- ebounds (returning energy boundaries)
  35 +- gtis (returning good time intervals)
  36 +
  37 +
  38 +General parameters
  39 +------------------
  40 +
  41 +``inobs [file]``
  42 + Event list, counts cube, or observation definition file
  43 +
  44 +``(offset = no) [file]``
  45 + Compute offset from target to pointing positions
  46 +
  47 +``ra [real]``
  48 + Target right ascension for offset computation (only queried if offset=yes)
  49 +
  50 +``dec [real]``
  51 + Target declination for offset computation (only queried if offset=yes)
  52 +
  53 +``(ds9file = NONE) [file]``
  54 + DS9 region file containing pointings
  55 +
  56 +
  57 +Standard parameters
  58 +-------------------
  59 +
  60 +``(chatter = 2) [integer]``
  61 + Verbosity of the executable:
  62 + chatter = 0: no information will be logged
  63 +
  64 + chatter = 1: only errors will be logged
  65 +
  66 + chatter = 2: errors and actions will be logged
  67 +
  68 + chatter = 3: report about the task execution
  69 +
  70 + chatter = 4: detailed report about the task execution
  71 +
  72 +``(clobber = yes) [boolean]``
  73 + Specifies whether an existing output counts cube should be overwritten.
  74 +
  75 +``(debug = no) [boolean]``
  76 + Enables debug mode. In debug mode the executable will dump any log file output to the console.
  77 +
  78 +``(mode = ql) [string]``
  79 + Mode of automatic parameters (default is "ql", i.e. "query and learn").
  80 +
  81 +``(logfile = csobsinfo.log) [filename]``
  82 + Log filename.
  83 +
  84 +
  85 +Related tools or scripts
  86 +------------------------
  87 +
  88 +None
0 89 \ No newline at end of file
... ...
doc/source/reference_manual/cstsmapmerge.rst 0 → 100644
  1 +.. _cstsmapmerge:
  2 +
  3 +cstsmapmerge
  4 +============
  5 +
  6 +Merges slices of splitted tsmap computations.
  7 +
  8 +
  9 +Synopsis
  10 +--------
  11 +
  12 +In case a TS map has been computed using the option to split the calculations
  13 +into several jobs, this tool is required to merge the output into one final
  14 +map again. Running :doc:`cttsmap` with the hidden parameters ``binmin`` and
  15 +``binmax`` specified will result in several sliced TS maps. This script merges
  16 +them into one FITS file. The input slices can be passed via the ``inmaps``
  17 +parameter. There are 4 options to specify a list of files that should be merged:
  18 +- a space-separated list of file names (e.g. tsmap1.fits tsmap2.fits)
  19 +- a comma-separated list of file names (e.g. tsmap1.fits,tsmap2.fits)
  20 +- a wildcard string (e.g. tsmap*.xml)
  21 +- an ASCII file containing the file names, one file per line (e.g. @mymaps.txt)
  22 +
  23 +Note that the "@" needs to be specified in case of an ASCII file name.
  24 +
  25 +General parameters
  26 +------------------
  27 +
  28 +``inmaps [string]``
  29 + Input TS map FITS files
  30 +
  31 +``outmap [file]``
  32 + Output TS map FITS file
  33 +
  34 +``(overwrite=yes) [boolean]``
  35 + Overwrite previously filled bins?
  36 +
  37 +``(delete=no) [boolean]``
  38 + Delete merged files?
  39 +
  40 +
  41 +Standard parameters
  42 +-------------------
  43 +
  44 +``(chatter = 2) [integer]``
  45 + Verbosity of the executable:
  46 + chatter = 0: no information will be logged
  47 +
  48 + chatter = 1: only errors will be logged
  49 +
  50 + chatter = 2: errors and actions will be logged
  51 +
  52 + chatter = 3: report about the task execution
  53 +
  54 + chatter = 4: detailed report about the task execution
  55 +
  56 +``(clobber = yes) [boolean]``
  57 + Specifies whether an existing output counts cube should be overwritten.
  58 +
  59 +``(debug = no) [boolean]``
  60 + Enables debug mode. In debug mode the executable will dump any log file output to the console.
  61 +
  62 +``(mode = ql) [string]``
  63 + Mode of automatic parameters (default is "ql", i.e. "query and learn").
  64 +
  65 +``(logfile = cstsmapmerge.log) [filename]``
  66 + Log filename.
  67 +
  68 +
  69 +Related tools or scripts
  70 +------------------------
  71 +
  72 +:ref:`cstsmap`
... ...
doc/source/reference_manual/cttsmap.rst
... ... @@ -108,7 +108,8 @@ Standard parameters
108 108 Name of log file.
109 109  
110 110  
111   -Related tools
112   --------------
  111 +Related tools or scripts
  112 +------------------------
  113 +
  114 +:ref:`cstsmapmerge`
113 115  
114   -None
... ...
doc/source/reference_manual/index.rst
... ... @@ -45,3 +45,7 @@ cscripts
45 45 csspec --- Computes spectral points <csspec>
46 46 csresmap --- Generates residual map <csresmap>
47 47 cstsdist --- Generates TS distribution <cstsdist>
  48 + csobsinfo --- Shows observation container content <csobsinfo>
  49 + csmodelinfo --- Shows model container content <csmodelinfo>
  50 + csmodelmerge --- Merges several model containers into one file <csmodelmerge>
  51 + cstsmapmerge --- Merges slices from ts map computations <cstsmapmerge>
... ...
test/data/model_cube_background2.xml 0 → 100644
  1 +<?xml version="1.0" standalone="no"?>
  2 +<source_library title="source library">
  3 + <source name="CTABackgroundModel2" type="CTACubeBackground" instrument="CTA">
  4 + <spectrum type="PowerLaw">
  5 + <parameter name="Prefactor" scale="1.0" value="1.0" min="1e-3" max="1e+3" free="1"/>
  6 + <parameter name="Index" scale="1.0" value="0.0" min="-5.0" max="+5.0" free="1"/>
  7 + <parameter name="Scale" scale="1e6" value="1.0" min="0.01" max="1000.0" free="0"/>
  8 + </spectrum>
  9 + </source>
  10 +</source_library>
... ...
test/data/tsmap_0.fits 0 → 100644
No preview for this file type
test/data/tsmap_1.fits 0 → 100644
No preview for this file type
test/test_cscripts.sh.in
... ... @@ -36,7 +36,7 @@ $ECHO &quot;*****************&quot;
36 36 #
37 37 # Remove any existing result files
38 38 # ================================
39   -rm -rf *.fits *.xml *.dat
  39 +rm -rf *.fits *.xml *.dat *.reg
40 40  
41 41  
42 42 #
... ... @@ -74,6 +74,203 @@ $ECHO &quot; ok&quot;
74 74  
75 75  
76 76 #
  77 +# Test csobsinfo
  78 +# ==============
  79 +$ECHO -n "Test csobsinfo: "
  80 +chmod +x @abs_top_srcdir@/cscripts/csobsinfo.py
  81 +@abs_top_srcdir@/cscripts/csobsinfo.py \
  82 + inobs="obs.xml" \
  83 + ds9file="obs.reg" \
  84 + offset=yes \
  85 + ra="83.6331" \
  86 + dec="22.01" > csobsinfo.log
  87 +$ECHO -n "."
  88 +if [ -s "obs.reg" ]
  89 +then
  90 + $ECHO -n "."
  91 +else
  92 + $ECHO " obs.reg file is not valid"
  93 + exit 1
  94 +fi
  95 +$ECHO " ok"
  96 +
  97 +
  98 +#
  99 +# Test csmodelinfo
  100 +# ================
  101 +$ECHO -n "Test csmodelinfo: "
  102 +chmod +x @abs_top_srcdir@/cscripts/csmodelinfo.py
  103 +@abs_top_srcdir@/cscripts/csmodelinfo.py \
  104 + inmodel="data/crab.xml" \
  105 + ds9file="model.reg" > csmodelinfo.log
  106 +$ECHO -n "."
  107 +if [ -s "model.reg" ]
  108 +then
  109 + $ECHO -n "."
  110 +else
  111 + $ECHO " model.reg file is not valid"
  112 + exit 1
  113 +fi
  114 +$ECHO " ok"
  115 +
  116 +
  117 +#
  118 +# Test csmodelmerge (space-separated)
  119 +# ===================================
  120 +$ECHO -n "Test csmodelmerge (space-separated): "
  121 +chmod +x @abs_top_srcdir@/cscripts/csmodelmerge.py
  122 +@abs_top_srcdir@/cscripts/csmodelmerge.py \
  123 + inmodels="data/crab.xml data/source1.xml" \
  124 + outmodel="merged_models.xml" > csmodelmerge.log
  125 +$ECHO -n "."
  126 +if [ -s "merged_models.xml" ]
  127 +then
  128 + $ECHO -n "."
  129 +else
  130 + $ECHO " merged_models.xml file is not valid"
  131 + exit 1
  132 +fi
  133 +$ECHO " ok"
  134 +
  135 +
  136 +#
  137 +# Test csmodelmerge (comma-separated)
  138 +# ===================================
  139 +$ECHO -n "Test csmodelmerge (comma-separated): "
  140 +chmod +x @abs_top_srcdir@/cscripts/csmodelmerge.py
  141 +@abs_top_srcdir@/cscripts/csmodelmerge.py \
  142 + inmodels="data/crab.xml,data/source1.xml" \
  143 + outmodel="merged_models2.xml" > csmodelmerge.log
  144 +$ECHO -n "."
  145 +if [ -s "merged_models2.xml" ]
  146 +then
  147 + $ECHO -n "."
  148 +else
  149 + $ECHO " merged_models2.xml file is not valid"
  150 + exit 1
  151 +fi
  152 +$ECHO " ok"
  153 +
  154 +
  155 +#
  156 +# Test csmodelmerge (wildcard string)
  157 +# ===================================
  158 +$ECHO -n "Test csmodelmerge (wildcard string): "
  159 +chmod +x @abs_top_srcdir@/cscripts/csmodelmerge.py
  160 +@abs_top_srcdir@/cscripts/csmodelmerge.py \
  161 + inmodels="data/model_cube_background*.xml" \
  162 + outmodel="merged_models3.xml" > csmodelmerge.log
  163 +$ECHO -n "."
  164 +if [ -s "merged_models3.xml" ]
  165 +then
  166 + $ECHO -n "."
  167 +else
  168 + $ECHO " merged_models3.xml file is not valid"
  169 + exit 1
  170 +fi
  171 +$ECHO " ok"
  172 +
  173 +
  174 +#
  175 +# Test csmodelmerge (ascii-file)
  176 +# ==============================
  177 +ls data/model_cube_background* > models.txt
  178 +$ECHO -n "Test csmodelmerge (ascii-file): "
  179 +chmod +x @abs_top_srcdir@/cscripts/csmodelmerge.py
  180 +@abs_top_srcdir@/cscripts/csmodelmerge.py \
  181 + inmodels="@models.txt" \
  182 + outmodel="merged_models4.xml" > csmodelmerge.log
  183 +$ECHO -n "."
  184 +if [ -s "merged_models4.xml" ]
  185 +then
  186 + $ECHO -n "."
  187 +else
  188 + $ECHO " merged_models4.xml file is not valid"
  189 + exit 1
  190 +fi
  191 +$ECHO " ok"
  192 +rm models.txt
  193 +
  194 +
  195 +#
  196 +# Test cstsmapmerge (comma-separated)
  197 +# ===================================
  198 +$ECHO -n "Test cstsmapmerge (comma-separated): "
  199 +chmod +x @abs_top_srcdir@/cscripts/cstsmapmerge.py
  200 +@abs_top_srcdir@/cscripts/cstsmapmerge.py \
  201 + inmaps="data/tsmap_0.fits,data/tsmap_1.fits" \
  202 + outmap="merged_tsmap1.fits" > cstsmapmerge.log
  203 +$ECHO -n "."
  204 +if [ -s "merged_tsmap1.fits" ]
  205 +then
  206 + $ECHO -n "."
  207 +else
  208 + $ECHO " merged_tsmap1.fits file is not valid"
  209 + exit 1
  210 +fi
  211 +$ECHO " ok"
  212 +
  213 +
  214 +#
  215 +# Test cstsmapmerge (space-separated)
  216 +# ===================================
  217 +$ECHO -n "Test cstsmapmerge (space-separated): "
  218 +chmod +x @abs_top_srcdir@/cscripts/cstsmapmerge.py
  219 +@abs_top_srcdir@/cscripts/cstsmapmerge.py \
  220 + inmaps="data/tsmap_0.fits data/tsmap_1.fits" \
  221 + outmap="merged_tsmap2.fits" > cstsmapmerge.log
  222 +$ECHO -n "."
  223 +if [ -s "merged_tsmap2.fits" ]
  224 +then
  225 + $ECHO -n "."
  226 +else
  227 + $ECHO " merged_tsmap2.fits file is not valid"
  228 + exit 1
  229 +fi
  230 +$ECHO " ok"
  231 +
  232 +
  233 +#
  234 +# Test cstsmapmerge (wildcard string)
  235 +# ===================================
  236 +$ECHO -n "Test cstsmapmerge (wildcard string): "
  237 +chmod +x @abs_top_srcdir@/cscripts/cstsmapmerge.py
  238 +@abs_top_srcdir@/cscripts/cstsmapmerge.py \
  239 + inmaps="data/tsmap_*.fits" \
  240 + outmap="merged_tsmap3.fits" > cstsmapmerge.log
  241 +$ECHO -n "."
  242 +if [ -s "merged_tsmap3.fits" ]
  243 +then
  244 + $ECHO -n "."
  245 +else
  246 + $ECHO " merged_tsmap3.fits file is not valid"
  247 + exit 1
  248 +fi
  249 +$ECHO " ok"
  250 +
  251 +
  252 +#
  253 +# Test cstsmapmerge (ascii-file)
  254 +# ==============================
  255 +ls data/tsmap_*.fits > tsmaps.txt
  256 +$ECHO -n "Test cstsmapmerge (ascii-file): "
  257 +chmod +x @abs_top_srcdir@/cscripts/cstsmapmerge.py
  258 +@abs_top_srcdir@/cscripts/cstsmapmerge.py \
  259 + inmaps="@tsmaps.txt" \
  260 + outmap="merged_tsmap4.fits" > cstsmapmerge.log
  261 +$ECHO -n "."
  262 +if [ -s "merged_tsmap4.fits" ]
  263 +then
  264 + $ECHO -n "."
  265 +else
  266 + $ECHO " merged_tsmap4.fits file is not valid"
  267 + exit 1
  268 +fi
  269 +$ECHO " ok"
  270 +rm tsmaps.txt
  271 +
  272 +
  273 +#
77 274 # Test cspull
78 275 # ===========
79 276 $ECHO -n "Test cspull: "
... ...