Commit eaa9046a135ccaec791f71c6888321ec5c3162db

Authored by Jürgen Knödlseder
2 parents 791a04af beadce17

Merge branch 'integration' into devel

# Conflicts:
#	cscripts/cta_make_nodes.py
.gitignore
... ... @@ -12,6 +12,8 @@
12 12 *.toc
13 13 *.Pi
14 14 *.Tpi
  15 +*.gcno
  16 +*.gcda
15 17 .DS_Store
16 18 .cproject
17 19 .project
... ... @@ -41,6 +43,7 @@ depcomp
41 43 test-driver
42 44 testconf.sh
43 45 coverage-report-python.xml
  46 +coverage-report-cxx.xml
44 47  
45 48 doc/html
46 49 doc/man
... ...
Makefile.am
... ... @@ -93,7 +93,7 @@ cppncss:
93 93 # Add coverage rule
94 94 coverage:
95 95 @if type gcovr >/dev/null 2>&1; then \
96   - gcovr -r . -x -o coverage-report-cxx.xml; \
  96 + gcovr -r . -x --exclude-unreachable-branches -o coverage-report-cxx.xml; \
97 97 else \
98 98 echo "gcovr script not found in PATH."; \
99 99 fi; \
... ...
configure.ac
... ... @@ -87,6 +87,22 @@ AC_CANONICAL_HOST
87 87  
88 88  
89 89 #############################################################################
  90 +# Check for --enable-coverage option
  91 +#############################################################################
  92 +AC_MSG_CHECKING(whether to build ctools for code coverage measure)
  93 +AC_ARG_ENABLE([coverage],
  94 + AS_HELP_STRING([--enable-coverage],
  95 + [turn on code coverage measure [default=no]]),
  96 + [enable_coverage="$enableval"],
  97 + [enable_coverage="no"])
  98 +if test "x$enable_coverage" = "xyes"; then
  99 + AC_MSG_RESULT(yes)
  100 +else
  101 + AC_MSG_RESULT(no)
  102 +fi
  103 +
  104 +
  105 +#############################################################################
90 106 # Check for valid C++ compiler. This has to come before the check for #
91 107 # header files, otherwise we won't detect if the C++ compiler is missing. #
92 108 # #
... ... @@ -140,11 +156,23 @@ else
140 156 fi
141 157 AM_CONDITIONAL(IS_ELCAPITAN, test "x$osx_el_capitan" = "xyes")
142 158  
  159 +# If coverage is selected then save current C++ options
  160 +if test "x$enable_coverage" = "xyes"; then
  161 + SAVED_CXXFLAGS=$CXXFLAGS
  162 + SAVED_CFLAGS=$CFLAGS
  163 +fi
  164 +
143 165 # Our language is C++
144 166 AC_LANG(C++)
145 167 AC_PROG_CXX($cxx_list)
146 168 AC_PROG_CC($cc_list)
147 169  
  170 +# If coverage is selected then restore former C++ options
  171 +if test "x$enable_coverage" = "xyes"; then
  172 + CXXFLAGS=$SAVED_CXXFLAGS
  173 + CFLAGS=$SAVED_CFLAGS
  174 +fi
  175 +
148 176  
149 177 #############################################################################
150 178 # Darwin option: Determine architecture of universal library to be built #
... ... @@ -758,25 +786,22 @@ fi
758 786 #############################################################################
759 787 # Initialise Python coverage with empty string
760 788 PYTHON_COVERAGE=
  789 +COVERAGE_CXXFLAGS=
761 790  
762   -# Check for coverage option
763   -AC_MSG_CHECKING(whether to build ctools for code coverage measure)
764   -AC_ARG_ENABLE([coverage],
765   - AS_HELP_STRING([--enable-coverage],
766   - [turn on code coverage measure [default=no]]),
767   - [enable_coverage="$enableval"],
768   - [enable_coverage="no"])
  791 +# If coverage option has been selected then set some variables
769 792 if test "x$enable_coverage" = "xyes"; then
770 793 CXXFLAGS="--coverage $CXXFLAGS"
  794 + COVERAGE_CXXFLAGS="--coverage"
771 795 LDFLAGS="--coverage $LDFLAGS"
772 796 if test "x$has_python" = "xyes"; then
773   - PYTHON_COVERAGE="coverage run --append "
  797 + PYTHON_COVERAGE="coverage run --branch --append "
774 798 fi
775 799 AC_MSG_RESULT(yes)
776 800 else
777 801 AC_MSG_RESULT(no)
778 802 fi
779 803 AC_SUBST(PYTHON_COVERAGE)
  804 +AC_SUBST(COVERAGE_CXXFLAGS)
780 805  
781 806  
782 807 #############################################################################
... ... @@ -937,7 +962,7 @@ OPENMP_LIB_LDFLAGS=
937 962 #fi
938 963 AC_SUBST(OPENMP_LIB_LDFLAGS)
939 964  
940   -# Signal if ctools cannot be compiled as gammalibe requires OpenMP but ctools
  965 +# Signal if ctools cannot be compiled as gammalib requires OpenMP but ctools
941 966 # cannot be compiled with OpenMP
942 967 if test "x$enable_openmp" = "xno" && test "x$gammalib_with_openmp" = "xyes"; then
943 968 AC_MSG_ERROR([The GammaLib library has been built with openMP support but OpenMP is not available on this system. Please install OpenMP or re-build GammaLib without OpenMP support.])
... ...
cscripts/Makefile.am
... ... @@ -26,13 +26,17 @@ linkscripts = cspull cssens cstsdist cscaldb csresmap \
26 26 # Test scripts to be distributed in $(pyexecdir)/cscripts/tests
27 27 testscripts = tests/__init__.py \
28 28 ../test/test_python_cscripts.py \
29   - ../test/test_cscaldb.py
  29 + ../test/test_cscaldb.py \
  30 + ../test/test_cslightcrv.py
30 31  
31 32 # Test data to be distributed in $(pyexecdir)/cscripts/tests/data
32   -testdata =
  33 +testdata = ../test/data/crab.xml \
  34 + ../test/data/crab_events.fits.gz \
  35 + ../test/data/crab_cntmap.fits.gz \
  36 + ../test/data/exclusion.reg
33 37  
34 38 # Test IRFs to be distributed in $(pyexecdir)/cscripts/tests/irf
35   -testirf =
  39 +#testirf =
36 40  
37 41 # Distribute scripts and parfiles
38 42 EXTRA_DIST = $(binscripts) $(pythonscripts)
... ... @@ -46,8 +50,8 @@ testscriptsdir = $(pyexecdir)/cscripts/tests
46 50 testscripts_DATA = $(testscripts)
47 51 testdatadir = $(pyexecdir)/cscripts/tests/data
48 52 testdata_DATA = $(testdata)
49   -testirfdir = $(pyexecdir)/cscripts/tests/irf
50   -testirf_DATA = $(testirf)
  53 +#testirfdir = $(pyexecdir)/cscripts/tests/irf
  54 +#testirf_DATA = $(testirf)
51 55  
52 56 # Add hook rule to create symbolic links for cscripts
53 57 install-data-hook:
... ...
cscripts/csiactobs.py
... ... @@ -501,14 +501,14 @@ class csiactobs(ctools.cscript):
501 501 self._log("\n")
502 502  
503 503 # Append observation to XML and set attributes
504   - obs = lib.append("observation");
505   - obs.attribute("name", object_name);
506   - obs.attribute("id", str(obs_id));
507   - obs.attribute("instrument", telescope);
  504 + obs = lib.append("observation")
  505 + obs.attribute("name", object_name)
  506 + obs.attribute("id", str(obs_id))
  507 + obs.attribute("instrument", telescope)
508 508  
509 509 # Append event file
510 510 ev = gammalib.GXmlElement("parameter name=\"EventList\"")
511   - ev.attribute("file", eventfile);
  511 + ev.attribute("file", eventfile)
512 512  
513 513 # Append effective area
514 514 aeff = gammalib.GXmlElement("parameter name=\"EffectiveArea\"")
... ...
cscripts/cslightcrv.py
... ... @@ -76,12 +76,15 @@ class cslightcrv(ctools.cscript):
76 76 self._stacked = False
77 77  
78 78 # Initialise observation container from constructor arguments.
79   - self._obs = self._set_input_obs(argv)
  79 + self._obs, argv = self._set_input_obs(argv)
80 80  
81   - # Initialise application by calling the appropriate class
82   - # constructor.
  81 + # Initialise script by calling the appropriate class constructor.
83 82 self._init_cscript(argv)
84 83  
  84 + # Set logger properties
  85 + self._log_header()
  86 + self._log.date(True)
  87 +
85 88 # Return
86 89 return
87 90  
... ... @@ -91,12 +94,10 @@ class cslightcrv(ctools.cscript):
91 94 """
92 95 Get parameters from parfile.
93 96 """
94   - # Set observation if not done before
95   - if self._obs == None or self._obs.size() == 0:
96   - self._require_inobs("cslightcrv::_get_parameters()")
97   - self._obs = self._get_observations()
  97 + # Setup observations
  98 + self._setup_observations(self._obs)
98 99  
99   - # Set models if we have none
  100 + # Set models if there are none in the container
100 101 if self._obs.models().size() == 0:
101 102 self._obs.models(self["inmodel"].filename())
102 103  
... ... @@ -106,11 +107,18 @@ class cslightcrv(ctools.cscript):
106 107 # Get time boundaries
107 108 self._tbins = self._create_tbounds()
108 109  
109   - # Set stacked analysis flag if the requested number of energy bins
110   - # is not zero; otherwise an unbinned analysis will be done.
111   - self._stacked = False if self["enumbins"].integer() == 0 else True
  110 + # Set stacked analysis flag to True if the requested number of
  111 + # energy bins is positive. Otherwise an unbinned analysis will
  112 + # be done and the stacked analysis flag will be set to False.
  113 + if self["enumbins"].integer() > 0:
  114 + self._stacked = True
  115 + else:
  116 + self._stacked = False
112 117  
113   - # Make sure that other parameters are queried now and not later
  118 + # Make sure that remaining user parameters are queried now. We
  119 + # do not store the actual parameter values as we do not want
  120 + # too many instance attributes with enhances the maintenance
  121 + # costs.
114 122 self["emin"].real()
115 123 self["emax"].real()
116 124 if self._stacked:
... ... @@ -429,16 +437,26 @@ class cslightcrv(ctools.cscript):
429 437 if self._logExplicit():
430 438 self._log.header3("Creating point spread function cube")
431 439  
432   - # Create psf cube
  440 + # Compute spatial binning for point spread function and
  441 + # energy dispersion cubes
  442 + binsz = 0.1 * self["binsz"].real()
  443 + nxpix = self["nxpix"].integer() / 10
  444 + nypix = self["nypix"].integer() / 10
  445 + if nxpix < 2:
  446 + nxpix = 2
  447 + if nypix < 2:
  448 + nypix = 2
  449 +
  450 + # Create point spread function cube
433 451 psfcube = ctools.ctpsfcube(obs)
434 452 psfcube["incube"] = "NONE"
435 453 psfcube["usepnt"] = False
436 454 psfcube["ebinalg"] = "LOG"
437 455 psfcube["xref"] = self["xref"].real()
438 456 psfcube["yref"] = self["yref"].real()
439   - psfcube["binsz"] = self["binsz"].real()
440   - psfcube["nxpix"] = self["nxpix"].integer()
441   - psfcube["nypix"] = self["nypix"].integer()
  457 + psfcube["binsz"] = binsz
  458 + psfcube["nxpix"] = nxpix
  459 + psfcube["nypix"] = nypix
442 460 psfcube["enumbins"] = self["enumbins"].integer()
443 461 psfcube["emin"] = self["emin"].real()
444 462 psfcube["emax"] = self["emax"].real()
... ... @@ -453,16 +471,16 @@ class cslightcrv(ctools.cscript):
453 471 if self._logExplicit():
454 472 self._log.header3("Creating energy dispersion cube")
455 473  
456   - # Create edisp cube
  474 + # Create energy dispersion cube
457 475 edispcube = ctools.ctedispcube(obs)
458 476 edispcube["incube"] = "NONE"
459 477 edispcube["usepnt"] = False
460 478 edispcube["ebinalg"] = "LOG"
461 479 edispcube["xref"] = self["xref"].real()
462 480 edispcube["yref"] = self["yref"].real()
463   - edispcube["binsz"] = self["binsz"].real()
464   - edispcube["nxpix"] = self["nxpix"].integer()
465   - edispcube["nypix"] = self["nypix"].integer()
  481 + edispcube["binsz"] = binsz
  482 + edispcube["nxpix"] = nxpix
  483 + edispcube["nypix"] = nypix
466 484 edispcube["enumbins"] = self["enumbins"].integer()
467 485 edispcube["emin"] = self["emin"].real()
468 486 edispcube["emax"] = self["emax"].real()
... ...
cscripts/csobsinfo.py
... ... @@ -52,7 +52,7 @@ class csobsinfo(ctools.cscript):
52 52 self._gti = gammalib.GGti()
53 53  
54 54 # Initialise observation container from constructor arguments.
55   - self._obs = self._set_input_obs(argv)
  55 + self._obs, argv = self._set_input_obs(argv)
56 56  
57 57 # Initialise application by calling the appropriate class
58 58 # constructor.
... ...
cscripts/cspull.py
... ... @@ -18,7 +18,7 @@
18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19 #
20 20 # ==========================================================================
21   -import gammalib
  21 +#import gammalib
22 22 import ctools
23 23 from cscripts import obsutils
24 24 import sys
... ... @@ -62,7 +62,7 @@ class cspull(ctools.cscript):
62 62 self._log_clients = False
63 63  
64 64 # Initialise observation container from constructor arguments.
65   - self._obs = self._set_input_obs(argv)
  65 + self._obs, argv = self._set_input_obs(argv)
66 66  
67 67 # Initialise application by calling the appropriate class
68 68 # constructor.
... ... @@ -410,17 +410,17 @@ class cspull(ctools.cscript):
410 410  
411 411 # Write out result immediately
412 412 if seed == 0:
413   - file = open(self._outfile.url(), 'w')
414   - writer = csv.DictWriter(file, result['colnames'])
  413 + f = open(self._outfile.url(), 'w')
  414 + writer = csv.DictWriter(f, result['colnames'])
415 415 headers = {}
416 416 for n in result['colnames']:
417 417 headers[n] = n
418 418 writer.writerow(headers)
419 419 else:
420   - file = open(self._outfile.url(), 'a')
421   - writer = csv.DictWriter(file, result['colnames'])
  420 + f = open(self._outfile.url(), 'a')
  421 + writer = csv.DictWriter(f, result['colnames'])
422 422 writer.writerow(result['values'])
423   - file.close()
  423 + f.close()
424 424  
425 425 # Return
426 426 return
... ...
cscripts/csresmap.py
... ... @@ -74,7 +74,7 @@ class csresmap(ctools.cscript):
74 74 self._log_clients = False
75 75  
76 76 # Initialise observation container from constructor arguments.
77   - self._obs = self._set_input_obs(argv)
  77 + self._obs, argv = self._set_input_obs(argv)
78 78  
79 79 # Initialise application by calling the appropriate class
80 80 # constructor.
... ...
cscripts/cssens.py
... ... @@ -347,18 +347,18 @@ class cssens(ctools.cscript):
347 347 photon_flux_value = []
348 348 energy_flux_value = []
349 349 sensitivity_value = []
350   - iter = 0
  350 + iterations = 0
351 351 test_crab_flux = 0.1 # Initial test flux in Crab units (100 mCrab)
352 352  
353 353 # Loop until we break
354 354 while True:
355 355  
356 356 # Update iteration counter
357   - iter += 1
  357 + iterations += 1
358 358  
359 359 # Write header
360 360 if self._logExplicit():
361   - self._log.header2("Iteration "+str(iter))
  361 + self._log.header2("Iteration "+str(iterations))
362 362  
363 363 # Set source model. crab_prefactor is the Prefactor that
364 364 # corresponds to 1 Crab
... ... @@ -370,7 +370,7 @@ class cssens(ctools.cscript):
370 370 self._obs.models(src_model)
371 371  
372 372 # Simulate events
373   - sim = obsutils.sim(self._obs, nbins=self._enumbins, seed=iter,
  373 + sim = obsutils.sim(self._obs, nbins=self._enumbins, seed=iterations,
374 374 binsz=self._binsz, npix=self._npix,
375 375 log=self._log_clients, debug=self._debug,
376 376 edisp=self._edisp)
... ... @@ -464,8 +464,8 @@ class cssens(ctools.cscript):
464 464 # Get fitted Crab, photon and energy fluxes
465 465 crab_flux = result_all[self._srcname]['Prefactor'].value() / \
466 466 crab_prefactor
467   - crab_flux_err = result_all[self._srcname]['Prefactor'].error() / \
468   - crab_prefactor
  467 + #crab_flux_err = result_all[self._srcname]['Prefactor'].error() / \
  468 + # crab_prefactor
469 469 photon_flux = result_all[self._srcname].spectral().flux(emin, emax)
470 470 energy_flux = result_all[self._srcname].spectral().eflux(emin, emax)
471 471  
... ... @@ -511,7 +511,7 @@ class cssens(ctools.cscript):
511 511 for par in model:
512 512 self._log(str(par)+"\n")
513 513 elif self._logTerse():
514   - self._log.parformat("Iteration "+str(iter))
  514 + self._log.parformat("Iteration "+str(iterations))
515 515 self._log("TS=")
516 516 self._log(ts)
517 517 self._log(" ")
... ... @@ -549,7 +549,7 @@ class cssens(ctools.cscript):
549 549 sensitivity /= num
550 550  
551 551 # Compare average flux to last average
552   - if iter > self._num_avg:
  552 + if iterations > self._num_avg:
553 553 if test_crab_flux > 0:
554 554 ratio = crab_flux/test_crab_flux
555 555  
... ... @@ -570,7 +570,7 @@ class cssens(ctools.cscript):
570 570 test_crab_flux = crab_flux
571 571  
572 572 # Exit loop if number of trials exhausted
573   - if (iter >= self._max_iter):
  573 + if (iterations >= self._max_iter):
574 574 if self._logTerse():
575 575 self._log(" Test ended after "+str(self._max_iter)+
576 576 " iterations.\n")
... ...
cscripts/csspec.py
... ... @@ -60,7 +60,7 @@ class csspec(ctools.cscript):
60 60 self._debug = False
61 61  
62 62 # Initialise observation container from constructor arguments.
63   - self._obs = self._set_input_obs(argv)
  63 + self._obs, argv = self._set_input_obs(argv)
64 64  
65 65 # Initialise application by calling the appropriate class
66 66 # constructor.
... ... @@ -158,9 +158,10 @@ class csspec(ctools.cscript):
158 158  
159 159 # If no layers overlap then throw an exception
160 160 if (len(use_layers) == 0):
161   - msg = "Energy range ["+str(cube_ebounds.emin(i))+ \
162   - ", "+str(cube_ebounds.emax(i))+"] of counts "+ \
163   - "cube does not overlap with specified energy range ["+ \
  161 + msg = "Energy range ["+str(cube_ebounds.emin())+ \
  162 + ", "+str(cube_ebounds.emax())+"] of counts "+ \
  163 + "cube does not overlap with specified energy "+ \
  164 + "range ["+ \
164 165 str(emin)+", "+str(emax)+"]. Specify "+ \
165 166 "overlapping energy range."
166 167 raise RuntimeError(msg)
... ...
cscripts/cstsdist.py
... ... @@ -419,17 +419,17 @@ class cstsdist(ctools.cscript):
419 419  
420 420 # Write out result immediately
421 421 if seed == 0:
422   - file = open(self._outfile.url(), 'w')
423   - writer = csv.DictWriter(file, result['colnames'])
  422 + f = open(self._outfile.url(), 'w')
  423 + writer = csv.DictWriter(f, result['colnames'])
424 424 headers = {}
425 425 for n in result['colnames']:
426 426 headers[n] = n
427 427 writer.writerow(headers)
428 428 else:
429   - file = open(self._outfile.url(), 'a')
430   - writer = csv.DictWriter(file, result['colnames'])
  429 + f = open(self._outfile.url(), 'a')
  430 + writer = csv.DictWriter(f, result['colnames'])
431 431 writer.writerow(result['values'])
432   - file.close()
  432 + f.close()
433 433  
434 434 # Return
435 435 return
... ...
cscripts/cstsmapmerge.py
... ... @@ -414,8 +414,8 @@ class cstsmapmerge(ctools.cscript):
414 414 # Delete TS input maps if requested
415 415 if self._delete:
416 416 for filename in self._merged_files:
417   - os.remove(filename)
418   - if self._logTerse():
  417 + os.remove(filename)
  418 + if self._logTerse():
419 419 self._log(gammalib.parformat("Deleted input file"))
420 420 self._log(filename)
421 421 self._log("\n")
... ...
cscripts/cta_kb_bkgrates.py
... ... @@ -4,7 +4,7 @@
4 4 # into a column separated file function table. The table is automatically
5 5 # named "bkg_XXX.txt" where "XXX" is for example "kb_E_50h_v3".
6 6 #
7   -# Copyright (C) 2011-2014 Juergen Knoedlseder
  7 +# Copyright (C) 2011-2016 Juergen Knoedlseder
8 8 #
9 9 # This program is free software: you can redistribute it and/or modify
10 10 # it under the terms of the GNU General Public License as published by
... ... @@ -38,8 +38,8 @@ def make_file_function(irfname, filename):
38 38 filename - File function filename
39 39 """
40 40 # Open performance file and file function
41   - irf = open(irfname, "r")
42   - file = open(filename, "w")
  41 + irf = open(irfname, "r")
  42 + f = open(filename, "w")
43 43  
44 44 # Read data
45 45 for row in irf:
... ... @@ -53,12 +53,12 @@ def make_file_function(irfname, filename):
53 53 # Extract data
54 54 fields = row.replace(" ",",").replace(",,",",").rstrip("\n").split(",")
55 55 logE = float(fields[0])
56   - aeff = float(fields[1])
57   - r68 = float(fields[2])
  56 + #aeff = float(fields[1])
  57 + #r68 = float(fields[2])
58 58 r80 = float(fields[3])
59   - eres = float(fields[4])
  59 + #eres = float(fields[4])
60 60 bgd = float(fields[5])
61   - sens = float(fields[6])
  61 + #sens = float(fields[6])
62 62  
63 63 # Compute energy (in MeV)
64 64 energy = math.pow(10.0, logE)*1.0e6
... ... @@ -76,11 +76,11 @@ def make_file_function(irfname, filename):
76 76 bkg_rate = 0.0
77 77  
78 78 # Write
79   - file.write(str(energy)+" "+str(bkg_rate)+"\n")
  79 + f.write(str(energy)+" "+str(bkg_rate)+"\n")
80 80  
81 81 # Close files
82 82 irf.close()
83   - file.close()
  83 + f.close()
84 84  
85 85 # Return
86 86 return
... ... @@ -90,9 +90,7 @@ def make_file_function(irfname, filename):
90 90 # Main entry point #
91 91 # ================ #
92 92 if __name__ == '__main__':
93   - """
94   - Main entry point
95   - """
  93 +
96 94 # Set parameters
97 95 caldb = "/usr/local/gamma/share/caldb/data/cta/kb/"
98 96  
... ...
cscripts/cta_kb_root2caldb.py
... ... @@ -23,7 +23,8 @@
23 23 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 24 #
25 25 # ==========================================================================
26   -from ROOT import TFile, TH1F, TH2F
  26 +#from ROOT import TFile, TH1F, TH2F
  27 +from ROOT import TFile, TH1F
27 28 from datetime import datetime
28 29 import gammalib
29 30 import math
... ... @@ -506,11 +507,11 @@ if __name__ == &#39;__main__&#39;:
506 507 """
507 508 """
508 509 # Get ROOT filename from command line argument
509   - if (len(sys.argv) > 1):
510   - filename = sys.argv[1]
511   - else:
512   - db = "/Users/jurgen/Documents/Travail/Projects/CTA/WP-MC/root/Kb_all_20deg_root"
513   - #db = "/Users/jurgen/Documents/Travail/Projects/CTA/WP-MC/root/Kb_all_50deg_root"
  510 + #if (len(sys.argv) > 1):
  511 + # filename = sys.argv[1]
  512 + #else:
  513 + db = "/Users/jurgen/Documents/Travail/Projects/CTA/WP-MC/root/Kb_all_20deg_root"
  514 + #db = "/Users/jurgen/Documents/Travail/Projects/CTA/WP-MC/root/Kb_all_50deg_root"
514 515  
515 516 # Get list of all performance files
516 517 files = glob.glob(db+"/*.root")
... ... @@ -520,26 +521,26 @@ if __name__ == &#39;__main__&#39;:
520 521 irf = caldb("kb")
521 522  
522 523 # Loop over all files
523   - for file in files:
  524 + for f in files:
524 525  
525 526 # Get filename
526   - head, tail = os.path.split(file)
  527 + head, tail = os.path.split(f)
527 528  
528 529 # Build name
529 530 name = tail.strip(".root")
530 531 if name.find("kb_") != -1:
531 532 name = name.replace("_20deg", "")
532 533 elif name.find("IFAE_") != -1:
533   - name = name.replace("Subarray", "")
534   - name = name.replace("IFAE_", "")
535   - name = "IFAE_"+name
536   - i = name.find("hours")
537   - if i != -1:
538   - name = name[0:i+1]
  534 + name = name.replace("Subarray", "")
  535 + name = name.replace("IFAE_", "")
  536 + name = "IFAE_"+name
  537 + index = name.find("hours")
  538 + if index != -1:
  539 + name = name[0:index+1]
539 540 print(tail)
540 541  
541 542 # Open calibration file
542 543 irf.add(name)
543 544  
544 545 # Translate ROOT to CALDB information
545   - irf.root2caldb(file)
  546 + irf.root2caldb(f)
... ...
cscripts/cta_make_nodes.py
... ... @@ -20,7 +20,6 @@
20 20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 21 #
22 22 # ==========================================================================
23   -#import gammalib
24 23 import sys
25 24 import math
26 25  
... ... @@ -28,7 +27,7 @@ import math
28 27 # ============== #
29 28 # Write one node #
30 29 # ============== #
31   -def write_node(file, energy, scale):
  30 +def write_node(f, energy, scale):
32 31 """
33 32 Writes one node to XML file.
34 33 """
... ... @@ -37,22 +36,22 @@ def write_node(file, energy, scale):
37 36 str_scale = str(scale)
38 37  
39 38 # Write start tag
40   - file.write(' <node>\n')
  39 + f.write(' <node>\n')
41 40  
42 41 # 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 + f.write(' <parameter scale="1e6" name="Energy"')
  43 + f.write(' min="'+str_energy+'" max="'+str_energy+'"')
  44 + f.write(' value="'+str_energy+'"')
  45 + f.write(' free="0"/>\n')
47 46  
48 47 # 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 + f.write(' <parameter scale="'+str_scale+'" name="Intensity"')
  49 + f.write(' min="1e-5" max="1e5"')
  50 + f.write(' value="1.0"')
  51 + f.write(' free="1"/>\n')
53 52  
54 53 # Write end tag
55   - file.write(' </node>\n')
  54 + f.write(' </node>\n')
56 55  
57 56 # Return
58 57 return
... ... @@ -66,7 +65,7 @@ def create_nodes(emin, emax, enumbins):
66 65 Create nodes (energies in TeV).
67 66 """
68 67 # Open file
69   - file = open("nodes.xml", "w")
  68 + f = open("nodes.xml", "w")
70 69  
71 70 # Set node boundaries
72 71 elogmin = math.log10(float(emin))
... ... @@ -83,14 +82,14 @@ def create_nodes(emin, emax, enumbins):
83 82 scale = 3.45e-17 * math.pow(energy, -2.63)
84 83  
85 84 # Write node
86   - write_node(file, energy, scale)
  85 + write_node(f, energy, scale)
87 86  
88 87 # Debug
89 88 #sys.stdout.write(energy)
90 89 #sys.stdout.write(math.pow(10.0, int(math.log10(scale))-1.0)±"\n")
91 90  
92 91 # Close file
93   - file.close()
  92 + f.close()
94 93  
95 94 # Return
96 95 return
... ... @@ -100,9 +99,7 @@ def create_nodes(emin, emax, enumbins):
100 99 # Main script entry point #
101 100 # ======================= #
102 101 if __name__ == '__main__':
103   - """
104   - Compute nodes.
105   - """
  102 +
106 103 # Check command line
107 104 usage = "Usage: cta_make_nodes emin emax enumbins"
108 105 if len(sys.argv) < 3:
... ...
cscripts/cta_root2caldb.py
... ... @@ -3,7 +3,7 @@
3 3 # This script generates IRFs in the CALDB format of HEASARC using ROOT
4 4 # offaxis performance files.
5 5 # -------------------------------------------------------------------------
6   -# Copyright (C) 2011-2015 Juergen Knoedlseder
  6 +# Copyright (C) 2011-2016 Juergen Knoedlseder
7 7 # -------------------------------------------------------------------------
8 8 #
9 9 # This program is free software: you can redistribute it and/or modify
... ... @@ -24,12 +24,13 @@
24 24 # - gammalib
25 25 # - pyroot
26 26 # ==========================================================================
27   -from ROOT import TFile, TH1F, TH2F, TH3F
  27 +#from ROOT import TFile, TH1F, TH2F, TH3F
  28 +from ROOT import TFile, TH2F, TH3F
28 29 import gammalib
29 30 from datetime import datetime
30 31 import math
31   -import sys
32   -import glob
  32 +#import sys
  33 +#import glob
33 34 import os
34 35  
35 36  
... ...
pyext/ctool.i
... ... @@ -87,6 +87,7 @@ public:
87 87 %rename(_read_ahead) read_ahead() const;
88 88 %rename(_time_reference) time_reference() const;
89 89 %rename(_get_observations) get_observations(const bool& get_response = true);
  90 + %rename(_setup_observations) setup_observations(GObservations& obs);
90 91 %rename(_create_ebounds) create_ebounds();
91 92 %rename(_create_map) create_map(const GObservations& obs);
92 93 %rename(_create_cube) create_cube(const GObservations& obs);
... ... @@ -105,6 +106,7 @@ public:
105 106 const bool& read_ahead(void) const;
106 107 const GTimeReference& time_reference(void) const;
107 108 GObservations get_observations(const bool& get_response = true);
  109 + void setup_observations(GObservations& obs);
108 110  
109 111 // Protected methods that create objects from user parameters
110 112 GEbounds create_ebounds(void);
... ... @@ -170,14 +172,15 @@ public:
170 172  
171 173 # Initialise observation container from constructor arguments. In case that
172 174 # an observation container is provided as argument, this container will be
173   -# used to initialise the class.
  175 +# used to initialise the class. The function returns a tuple containing the
  176 +# observation container and the eventually reduced argument list.
174 177 def _set_input_obs(self, argv):
175 178 if len(argv) > 0 and isinstance(argv[0],gammalib.GObservations):
176 179 obs = argv[0]
177 180 argv = argv[1:]
178 181 else:
179 182 obs = gammalib.GObservations()
180   - return obs
  183 + return (obs, argv)
181 184 cscript._set_input_obs = _set_input_obs
182 185  
183 186 # Initialise application by calling the appropriate class constructor.
... ...
pyext/setup.py.in
1 1 #############################################################################
2 2 # Disutils setup file for ctools Python extension module #
3 3 # ------------------------------------------------------------------------- #
4   -# Copyright (C) 2011-2014 Juergen Knoedlseder #
  4 +# Copyright (C) 2011-2016 Juergen Knoedlseder #
5 5 # ------------------------------------------------------------------------- #
6 6 # #
7 7 # This program is free software: you can redistribute it and/or modify #
... ... @@ -27,35 +27,35 @@ import sys
27 27 # Detect execution mode
28 28 is_build = True
29 29 if (len(sys.argv) >= 2):
30   - if (sys.argv[1] == 'install'):
31   - is_build = False
  30 + if (sys.argv[1] == 'install'):
  31 + is_build = False
32 32 if is_build:
33   - sys.stdout.write("Python extension module building:\n")
  33 + sys.stdout.write("Python extension module building:\n")
34 34 else:
35   - sys.stdout.write("Python extension module installation:\n")
  35 + sys.stdout.write("Python extension module installation:\n")
36 36  
37 37 # Darwin MacPorts kluge: Remove -L/opt/local/lib path from LDSHARED as this
38 38 # overrides the GammaLib settings. Otherwise, MacPorts libraries would be
39 39 # used instead of the libraries selected by GammaLib
40 40 if sys.platform.lower().startswith("darwin"):
41   -
42   - # Get configuration variables
43   - cvars = sysconfig.get_config_vars()
44   -
45   - # Extract LDSHARED
46   - ldshared_old = cvars.get('LDSHARED')
47   - ldshared_new = ''
48   - ldshared_rm = ''
49   - for option in ldshared_old.split(' '):
50   - if option.lstrip().find('-L/opt/local/lib') != 0:
51   - ldshared_new += option + ' '
52   - else:
53   - ldshared_rm += option + ' '
54   - if (len(ldshared_rm) > 0):
55   - sys.stdout.write("Removed following option(s) from LDSHARED: "+ldshared_rm+"\n");
56   -
57   - # Set LDSHARED
58   - cvars['LDSHARED'] = ldshared_new
  41 +
  42 + # Get configuration variables
  43 + cvars = sysconfig.get_config_vars()
  44 +
  45 + # Extract LDSHARED
  46 + ldshared_old = cvars.get('LDSHARED')
  47 + ldshared_new = ''
  48 + ldshared_rm = ''
  49 + for option in ldshared_old.split(' '):
  50 + if option.lstrip().find('-L/opt/local/lib') != 0:
  51 + ldshared_new += option + ' '
  52 + else:
  53 + ldshared_rm += option + ' '
  54 + if (len(ldshared_rm) > 0):
  55 + sys.stdout.write("Removed following option(s) from LDSHARED: "+ldshared_rm+"\n");
  56 +
  57 + # Set LDSHARED
  58 + cvars['LDSHARED'] = ldshared_new
59 59  
60 60 # Set default include directories and data files
61 61 include_dirs = ['@prefix@/include/gammalib']
... ... @@ -66,8 +66,8 @@ libraries = [&#39;ctools&#39;,&#39;gamma&#39;]
66 66  
67 67 # Add install directory to runtime library path
68 68 if os.path.exists('@prefix@/lib'):
69   - library_dirs.append('@prefix@/lib')
70   - runtime_library_dirs.append('@prefix@/lib')
  69 + library_dirs.append('@prefix@/lib')
  70 + runtime_library_dirs.append('@prefix@/lib')
71 71  
72 72 # Add application include files. The method we use here is not very
73 73 # intelligent as it simple will add all names that start with 'ct'
... ... @@ -75,44 +75,49 @@ if os.path.exists(&#39;@prefix@/lib&#39;):
75 75 # add an explicit filter to avoid appending those.
76 76 dirs = glob.glob('../src/ct*')
77 77 for dir in dirs:
78   - if len(dir) > 0 and 'ctools' not in dir:
79   - path = os.path.abspath(dir)
80   - include_dirs.append(path)
  78 + if len(dir) > 0 and 'ctools' not in dir:
  79 + path = os.path.abspath(dir)
  80 + include_dirs.append(path)
81 81 include_dirs.append(os.path.abspath('../src/support'))
82 82  
83 83 # Add extra libraries
84 84 extra_libs = ('@PYTHON_EXTRA_LIBS@').split(',')
85 85 for extra_lib in extra_libs:
86   - if len(extra_lib) > 0:
87   - libraries.append(extra_lib)
  86 + if len(extra_lib) > 0:
  87 + libraries.append(extra_lib)
88 88  
89 89 # Get extra library paths
90 90 extra_lib_paths = ('@LDFLAGS@').split(' ')
91 91 for extra_lib_path in extra_lib_paths:
92   - if extra_lib_path.lstrip().find('-L') == 0:
93   - dir = extra_lib_path.lstrip().lstrip('-L')
94   - if len(dir) > 0:
95   - library_dirs.append(dir)
96   - runtime_library_dirs.append(dir)
  92 + if extra_lib_path.lstrip().find('-L') == 0:
  93 + dir = extra_lib_path.lstrip().lstrip('-L')
  94 + if len(dir) > 0:
  95 + library_dirs.append(dir)
  96 + runtime_library_dirs.append(dir)
97 97  
98 98 # Get extra include directories
99 99 extra_include_dirs = ('@CPPFLAGS@').split(' ')
100 100 for extra_include_dir in extra_include_dirs:
101   - if extra_include_dir.lstrip().find('-I') == 0:
102   - dir = extra_include_dir.lstrip().lstrip('-I')
103   - if len(dir) > 0:
104   - include_dirs.append(dir)
  101 + if extra_include_dir.lstrip().find('-I') == 0:
  102 + dir = extra_include_dir.lstrip().lstrip('-I')
  103 + if len(dir) > 0:
  104 + include_dirs.append(dir)
105 105  
106 106 # Set data files to install.
107 107 data_files=[('@prefix@/share/ctools/swig', install_files)]
108 108  
109 109 # Optionally enable OpenMP
110 110 if '@OPENMP_TRUE@' != '#':
111   - extra_compile_args = ['@OPENMP_CXXFLAGS@']
112   - extra_link_args = ['@OPENMP_CXXFLAGS@']
  111 + extra_compile_args = ['@OPENMP_CXXFLAGS@']
  112 + extra_link_args = ['@OPENMP_CXXFLAGS@']
113 113 else:
114   - extra_compile_args = []
115   - extra_link_args = []
  114 + extra_compile_args = []
  115 + extra_link_args = []
  116 +
  117 +# Append coverage CXXFLAGS
  118 +if len('@COVERAGE_CXXFLAGS@') > 0:
  119 + extra_compile_args.append('@COVERAGE_CXXFLAGS@')
  120 + extra_link_args.append('@COVERAGE_CXXFLAGS@')
116 121  
117 122 # Optionally add link flag for El Capitan post-processing of modules
118 123 if '@IS_ELCAPITAN_TRUE@' != '#':
... ... @@ -133,25 +138,25 @@ setup(name=&#39;@PACKAGE_NAME@&#39;,
133 138 runtime_library_dirs=runtime_library_dirs,
134 139 extra_compile_args=extra_compile_args,
135 140 extra_link_args=extra_link_args)],
136   - data_files=data_files,
137   - license="GNU GPL v3",
138   - long_description="CTA science analysis tools",
139   - platforms=["Linux", "Solaris", "Mac OS-X", "Unix", "BSD"],
  141 + data_files=data_files,
  142 + license="GNU GPL v3",
  143 + long_description="CTA science analysis tools",
  144 + platforms=["Linux", "Solaris", "Mac OS-X", "Unix", "BSD"],
140 145 )
141 146  
142 147 # Post-processing. A symbolic link is created to the directory containing the
143 148 # shared wrapper libraries so that we can add this directory to the PYTHONPATH
144 149 # for testing.
145 150 if is_build:
146   - try:
147   - os.chdir('build')
148   - os.remove('ctools')
149   - sys.stdout.write("Removed symbolic link build/ctools.\n")
150   - except:
151   - pass
152   - try:
153   - path = glob.glob('lib.*')
154   - os.symlink(path[0], 'ctools')
155   - sys.stdout.write("Created symbolic link build/ctools.\n")
156   - except:
157   - sys.stdout.write("WARNING: Failed to create symbolic link build/ctools.\n")
  151 + try:
  152 + os.chdir('build')
  153 + os.remove('ctools')
  154 + sys.stdout.write("Removed symbolic link build/ctools.\n")
  155 + except:
  156 + pass
  157 + try:
  158 + path = glob.glob('lib.*')
  159 + os.symlink(path[0], 'ctools')
  160 + sys.stdout.write("Created symbolic link build/ctools.\n")
  161 + except:
  162 + sys.stdout.write("WARNING: Failed to create symbolic link build/ctools.\n")
... ...
src/ctbin/ctbin.cpp
... ... @@ -62,7 +62,7 @@ ctbin::ctbin(void) : ctool(CTBIN_NAME, CTBIN_VERSION)
62 62  
63 63 // Return
64 64 return;
65   -}
  65 +} // GCOV_EXCL_LINE
66 66  
67 67  
68 68 /***********************************************************************//**
... ...
src/support/ctool.cpp
... ... @@ -49,6 +49,7 @@
49 49  
50 50  
51 51 /* __ Method name definitions ____________________________________________ */
  52 +#define G_SETUP_OBSERVATION "ctool::setup_observations(GObservations&)"
52 53 #define G_GET_MEAN_POINTING "ctool::get_mean_pointing(GObservations&)"
53 54 #define G_CREATE_EBOUNDS "ctool::create_ebounds()"
54 55 #define G_PROVIDE_HELP "ctool::provide_help()"
... ... @@ -378,7 +379,98 @@ GObservations ctool::get_observations(const bool&amp; get_response)
378 379  
379 380 // Return observation container
380 381 return obs;
  382 +}
  383 +
  384 +
  385 +/***********************************************************************//**
  386 + * @brief Setup observation container
  387 + *
  388 + * @param[in] obs Observation container
  389 + *
  390 + * @exception GException::invalid_value
  391 + * Invalid "inobs" parameter encountered.
  392 + *
  393 + * Setup an observation container by appending all required information that
  394 + * is missing using user parameters.
  395 + *
  396 + * If the observation container @p obs is empty, the method will extract the
  397 + * filename from the "inobs" parameter, and if the filename is neither empty
  398 + * nor "NONE", will load the observation container from the specified file.
  399 + * If the file is a FITS file, and dependent on the information that is found
  400 + * in the FITS file, the method will append a single CTA observation to the
  401 + * observation container, containing either an event list or a counts cube.
  402 + * Otherwise, the method assumes that the file is an observation definition
  403 + * XML file and will load that file into the observation container.
  404 + *
  405 + * If the filename is empty or "NONE", the method will throw an exception.
  406 + *
  407 + * The method will then setup the response for all CTA observations in the
  408 + * container (see the set_response() method for more information).
  409 + *
  410 + * The method will furthermore setup the observation boundaries for all CTA
  411 + * observations in the container that contain event lists (see the
  412 + * set_obs_bounds() method for more information).
  413 + ***************************************************************************/
  414 +void ctool::setup_observations(GObservations& obs)
  415 +{
  416 + // Load observations if there are none in the container
  417 + if (obs.size() == 0) {
  418 +
  419 + // Get the filename from the "inobs" parameter
  420 + GFilename filename((*this)["inobs"].filename());
  421 +
  422 + // Load observation container from file if the filename is neither
  423 + // "NONE" nor empty ...
  424 + if ((gammalib::toupper(filename.url()) != "NONE") &&
  425 + !filename.is_empty()) {
  426 +
  427 + // If file does not exist then throw an exceptions
  428 + if (!filename.exists()) {
  429 + std::string msg = "The \"inobs\" parameter \""+filename+
  430 + "\" specifies a file that does not "
  431 + "exist. Please specify a valid event "
  432 + "list, counts cube or observation "
  433 + "definition XML file.";
  434 + throw GException::invalid_value(G_SETUP_OBSERVATION, msg);
  435 + }
  436 +
  437 + // If the file is a FITS file then load it into a CTA
  438 + // observation and append that observation to the container ...
  439 + else if (filename.is_fits()) {
  440 + GCTAObservation cta(filename);
  441 + obs.append(cta);
  442 + }
  443 +
  444 + // ... otherwise it is assumed that the file is an observation
  445 + // definition XML file and the file is loaded into the
  446 + // observation container
  447 + else {
  448 + obs.load(filename);
  449 + }
  450 +
  451 + }
  452 +
  453 + // ... otherwise, if the filename is "NONE" or empty then throw
  454 + // an exception.
  455 + else {
  456 + std::string msg = "The \"inobs\" parameter \""+filename+
  457 + "\" is not a valid filename. Please specify "
  458 + "a valid event list, counts cube or "
  459 + "observation definition XML file.";
  460 + throw GException::invalid_value(G_SETUP_OBSERVATION, msg);
  461 + }
  462 +
  463 + } // endif: there were no observations in the container
  464 +
  465 + // Setup the response for all CTA observations in the observation
  466 + // container
  467 + set_response(obs);
381 468  
  469 + // Setup boundaries for all CTA observations containing event lists
  470 + set_obs_bounds(obs);
  471 +
  472 + // Return
  473 + return;
382 474 }
383 475  
384 476  
... ... @@ -595,15 +687,16 @@ GCTAEventCube ctool::create_cube(const GObservations&amp; obs)
595 687 * method furthermore sets the ontime, livetime and deadtime correction
596 688 * factor.
597 689 *
598   - * The following parameters are read:
599   - * ra - Right Ascension of pointing and RoI centre (deg)
600   - * dec - Declination of pointing and RoI centre (deg)
601   - * rad - Radius of RoI (deg)
602   - * deadc - Deadtime correction factor
603   - * tmin - Start time
604   - * tmax - Stop time
605   - * emin - Minimum energy (TeV)
606   - * emax - Maximum energy (TeV)
  690 + * The following parameters are read
  691 + *
  692 + * ra: Right Ascension of pointing and RoI centre (deg)
  693 + * dec: Declination of pointing and RoI centre (deg)
  694 + * rad: Radius of RoI (deg)
  695 + * deadc: Deadtime correction factor
  696 + * tmin: Start time
  697 + * tmax: Stop time
  698 + * emin: Minimum energy (TeV)
  699 + * emax: Maximum energy (TeV)
607 700 ***************************************************************************/
608 701 GCTAObservation ctool::create_cta_obs(void)
609 702 {
... ... @@ -804,12 +897,9 @@ void ctool::require_inobs_nocube(const std::string&amp; method)
804 897 *
805 898 * @param[in,out] obs Observation container
806 899 *
807   - * Set the response for a CTA observations in the container that so far have
808   - * no response using the "caldb" and "irf" task parameters.
809   - *
810   - * The following parameters are read:
811   - * caldb - Calibration database
812   - * irf - Instrument response function
  900 + * Set the response for all CTA observations in the container that so far
  901 + * have no response information available. See the set_obs_response()
  902 + * method for more information about the user parameters that are read.
813 903 ***************************************************************************/
814 904 void ctool::set_response(GObservations& obs)
815 905 {
... ... @@ -841,69 +931,83 @@ void ctool::set_response(GObservations&amp; obs)
841 931 *
842 932 * @param[in,out] obs CTA observation
843 933 *
844   - * Set the response for a CTA observation. If the CTA observation contains
  934 + * Set the response for one CTA observation. If the CTA observation contains
845 935 * a counts cube the method first attempts to set the response information
846   - * using the @a expcube and @a psfcube user parameters. If this is not
847   - * successful (for example because the parameters do not exist or their
848   - * value is NONE or blank), the method will set the response information
849   - * from the @a caldb and @a irf user parameters.
  936 + * using the following user parameters
  937 + *
  938 + * expcube: Exposure cube file
  939 + * psfcube: Point spread function cube file
  940 + * edispcube: Energy dispersion cube file (optional)
  941 + * bkgcube: Background cube file
  942 + *
  943 + * If none of the @p expcube, @p psfcube and @p bkgcube parameters is
  944 + * "NONE" or empty, the method will allocate a stacked response for the
  945 + * observation. In case that an energy dispersion cube is provided using
  946 + * the @p edispcube parameter, this energy dispersion cube is also loaded
  947 + * and attached to the stacked response function.
  948 + *
  949 + * In case that any of the @p expcube, @p psfcube and @p bkgcube parameters
  950 + * is "NONE" or empty, the method will assume that a IRF response should
  951 + * be used, and will attempty to set the response information using the
  952 + * following user parameters
  953 + *
  954 + * caldb: Calibration database
  955 + * irf: Instrument response function
850 956 *
851   - * The following parameters are read:
852   - * expcube - Exposure cube file (optional)
853   - * psfcube - PSF cube file (optional)
854   - * caldb - Calibration database (optional)
855   - * irf - Instrument response function (optional)
856 957 ***************************************************************************/
857 958 void ctool::set_obs_response(GCTAObservation* obs)
858 959 {
859 960 // Initialise response flag
860 961 bool has_response = false;
861 962  
862   - // If the observation contains a counts cube, then first check whether
863   - // the expcube and psfcube parameters exist and are not NONE
  963 + // If the observation contains a counts cube, then check whether
  964 + // response information for a stacked analysis is provided, and if so,
  965 + // set that response information for the CTA observation
864 966 if (dynamic_cast<const GCTAEventCube*>(obs->events()) != NULL) {
865 967 if (has_par("expcube") && has_par("psfcube") &&
866 968 has_par("edispcube") && has_par("bkgcube")) {
867 969  
868 970 // Get filenames
869   - std::string expcube = (*this)["expcube"].filename();
870   - std::string psfcube = (*this)["psfcube"].filename();
871   - std::string edispcube = (*this)["edispcube"].filename();
872   - std::string bkgcube = (*this)["bkgcube"].filename();
873   -
874   - // Extract response information if available
875   - if ((expcube != "NONE") && (psfcube != "NONE") &&
876   - (bkgcube != "NONE") &&
877   - (gammalib::strip_whitespace(expcube) != "") &&
878   - (gammalib::strip_whitespace(psfcube) != "") &&
879   - (gammalib::strip_whitespace(bkgcube) != "")) {
  971 + GFilename expcube((*this)["expcube"].filename());
  972 + GFilename psfcube((*this)["psfcube"].filename());
  973 + GFilename edispcube((*this)["edispcube"].filename());
  974 + GFilename bkgcube((*this)["bkgcube"].filename());
  975 +
  976 + // Extract stacked response information if available
  977 + if ((gammalib::toupper(expcube.url()) != "NONE") &&
  978 + (gammalib::toupper(psfcube.url()) != "NONE") &&
  979 + (gammalib::toupper(bkgcube.url()) != "NONE") &&
  980 + !expcube.is_empty() &&
  981 + !psfcube.is_empty() &&
  982 + !bkgcube.is_empty()) {
880 983  
881 984 // Get exposure, PSF and background cubes
882 985 GCTACubeExposure exposure(expcube);
883 986 GCTACubePsf psf(psfcube);
884 987 GCTACubeBackground background(bkgcube);
885 988  
886   - // Optionally load energy dispersion cube
887   - if ((edispcube != "NONE") &&
888   - (gammalib::strip_whitespace(edispcube) != "")) {
  989 + // If an energy dispersion cube is available, get also
  990 + // this cube, and set all information as stacked response
  991 + // for this CTA observation
  992 + if ((gammalib::toupper(edispcube.url()) != "NONE") &&
  993 + !edispcube.is_empty()) {
889 994 GCTACubeEdisp edisp(edispcube);
890 995 obs->response(exposure, psf, edisp, background);
891 996 }
892 997 else {
893   - // Set reponse
894 998 obs->response(exposure, psf, background);
895 999 }
896 1000  
897   - // Signal response availability
  1001 + // Signal that response is available
898 1002 has_response = true;
899 1003  
900 1004 } // endif: filenames were available
901 1005  
902   - } // endif: expcube and psfcube parameters exist
  1006 + } // endif: expcube, psfcube and bkdcube parameters valid
903 1007 } // endif: observation contains a counts cube
904 1008  
905   - // If we have not yet response information then get it now
906   - // from the caldb and irf parameters
  1009 + // If we have not yet response information then get it now from the
  1010 + // caldb and irf user parameters
907 1011 if (!has_response) {
908 1012  
909 1013 // Load response information
... ... @@ -938,59 +1042,70 @@ void ctool::set_obs_response(GCTAObservation* obs)
938 1042  
939 1043  
940 1044 /***********************************************************************//**
941   - * @brief Set observation boundaries
  1045 + * @brief Set observation boundaries for all CTA observations
942 1046 *
943 1047 * @param[in,out] obs Observation container
  1048 + *
  1049 + * Sets the observation boundaries for all CTA observations in the container
  1050 + * that contain event lists. If the energy boundaries of an event list are
  1051 + * empty, the method gets the
  1052 + *
  1053 + * emin: Minimum energy (TeV)
  1054 + * emax: Maximum energy (TeV)
  1055 + *
  1056 + * user parameters and sets a single energy boundary element @p [emin,emax].
  1057 + *
  1058 + * If the RoI radius of the event list is invalid, the method gets the
  1059 + *
  1060 + * rad: Region of Interest radius (deg)
  1061 + *
  1062 + * user parameter to set the radius of the RoI, and uses the CTA pointing
  1063 + * direction to set the centre of the RoI.
944 1064 ***************************************************************************/
945 1065 void ctool::set_obs_bounds(GObservations& obs)
946 1066 {
947   - // Setup response for all observations
  1067 + // Loop over all observations in the container
948 1068 for (int i = 0; i < obs.size(); ++i) {
949 1069  
950   - // Is this observation a CTA observation?
  1070 + // Get pointer to CTA observation
951 1071 GCTAObservation* cta = dynamic_cast<GCTAObservation*>(obs[i]);
952 1072  
953   - // Continue only if observation is CTA and has events
954   - if ((cta != NULL) && (cta->has_events())) {
955   -
956   - // Get pointer on event list
957   - GCTAEventList* list = const_cast<GCTAEventList*>(dynamic_cast<const GCTAEventList*>(cta->events()));
958   -
959   - // Continue only if it's valid
960   - if (list != NULL) {
961   -
962   - // If there are no energy boundaries then read the user
963   - // parameters and add them
964   - if (list->ebounds().is_empty()) {
965   -
966   - // If there are "emin" and "emax" parameters then use
967   - // them
968   - if (has_par("emin") && has_par("emax")) {
969   - double emin = (*this)["emin"].real();
970   - double emax = (*this)["emax"].real();
971   - GEbounds ebounds(GEnergy(emin, "TeV"),
972   - GEnergy(emax, "TeV"));
973   - list->ebounds(ebounds);
974   - }
975   -
976   - }
  1073 + // Fall through if observation is not a CTA observation or if it
  1074 + // does not contain events
  1075 + if ((cta == NULL) || (!cta->has_events())) {
  1076 + continue;
  1077 + }
977 1078  
978   - // If there is no ROI then read the user parameters and add
979   - // them
980   - if (list->roi().radius() == 0) {
981   -
982   - // If there is a "rad" parameter then use it
983   - if (has_par("rad")) {
984   - double rad = (*this)["rad"].real();
985   - GCTARoi roi(GCTAInstDir(cta->pointing().dir()), rad);
986   - list->roi(roi);
987   - }
  1079 + // Get pointer on CTA event list
  1080 + GCTAEventList* list = const_cast<GCTAEventList*>
  1081 + (dynamic_cast<const GCTAEventList*>(cta->events()));
988 1082  
989   - }
  1083 + // Fall through if CTA observation does not contain an event list
  1084 + if (list == NULL) {
  1085 + continue;
  1086 + }
990 1087  
991   - } // endif: list was valid
  1088 + // If there are no energy boundaries then read the "emin" and "emax"
  1089 + // user parameters and add them
  1090 + if (list->ebounds().is_empty()) {
  1091 + if (has_par("emin") && has_par("emax")) {
  1092 + double emin((*this)["emin"].real());
  1093 + double emax((*this)["emax"].real());
  1094 + GEbounds ebounds(GEnergy(emin, "TeV"),
  1095 + GEnergy(emax, "TeV"));
  1096 + list->ebounds(ebounds);
  1097 + }
  1098 + }
992 1099  
993   - } // endif: observation was CTA
  1100 + // If there is no RoI then read the "rad" user parameters and use
  1101 + // the pointing direction to set the RoI
  1102 + if (list->roi().radius() == 0) {
  1103 + if (has_par("rad")) {
  1104 + double rad = (*this)["rad"].real();
  1105 + GCTARoi roi(GCTAInstDir(cta->pointing().dir()), rad);
  1106 + list->roi(roi);
  1107 + }
  1108 + }
994 1109  
995 1110 } // endfor: looped over observations
996 1111  
... ...
src/support/ctool.hpp
... ... @@ -72,6 +72,7 @@ protected:
72 72 const bool& read_ahead(void) const;
73 73 const GTimeReference& time_reference(void) const;
74 74 GObservations get_observations(const bool& get_response = true);
  75 + void setup_observations(GObservations& obs);
75 76  
76 77 // Protected methods that create objects from user parameters
77 78 GEbounds create_ebounds(void);
... ...
test/test_cscaldb.py
... ... @@ -18,6 +18,7 @@
18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19 #
20 20 # ==========================================================================
  21 +import os
21 22 import gammalib
22 23 import cscripts
23 24  
... ... @@ -28,7 +29,11 @@ import cscripts
28 29 class Test(gammalib.GPythonTestSuite):
29 30 """
30 31 Test class for cscaldb script.
  32 +
  33 + This test class makes unit tests for the cslightcrv script by using it
  34 + from the command line and from Python.
31 35 """
  36 +
32 37 # Constructor
33 38 def __init__(self):
34 39 """
... ... @@ -49,15 +54,15 @@ class Test(gammalib.GPythonTestSuite):
49 54 self.name("cscaldb")
50 55  
51 56 # Append tests
52   - self.append(self._test_functional, "Test cscaldb functionality")
  57 + self.append(self._test_python, "Test cscaldb from Python")
53 58  
54 59 # Return
55 60 return
56 61  
57   - # Test cscaldb functionality
58   - def _test_functional(self):
  62 + # Test cscaldb from Python
  63 + def _test_python(self):
59 64 """
60   - Test cscaldb functionality.
  65 + Test cscaldb from Python.
61 66 """
62 67 # Set-up cscaldb
63 68 caldb = cscripts.cscaldb()
... ...
test/test_cslightcrv.py 0 → 100755
  1 +#! /usr/bin/env python
  2 +# ==========================================================================
  3 +# This scripts performs unit tests for the cslightcrv script.
  4 +#
  5 +# Copyright (C) 2016 Juergen Knoedlseder
  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 os
  22 +import gammalib
  23 +import cscripts
  24 +
  25 +
  26 +# ================================ #
  27 +# Test class for cslightcrv script #
  28 +# ================================ #
  29 +class Test(gammalib.GPythonTestSuite):
  30 + """
  31 + Test class for cslightcrv script.
  32 +
  33 + This test class makes unit tests for the cslightcrv script by using it
  34 + from the command line and from Python.
  35 + """
  36 +
  37 + # Constructor
  38 + def __init__(self):
  39 + """
  40 + Constructor.
  41 + """
  42 + # Call base class constructor
  43 + gammalib.GPythonTestSuite.__init__(self)
  44 +
  45 + # Set members
  46 + self._events_name = "data/crab_events.fits"
  47 + self._model_name = "data/crab.xml"
  48 +
  49 + # Return
  50 + return
  51 +
  52 + # Set test functions
  53 + def set(self):
  54 + """
  55 + Set all test functions.
  56 + """
  57 + # Set test name
  58 + self.name("cslightcrv")
  59 +
  60 + # Append tests
  61 + self.append(self._test_cmd, "Test cslightcrv on command line")
  62 + self.append(self._test_python, "Test cslightcrv from Python")
  63 +
  64 + # Return
  65 + return
  66 +
  67 + # Test cslightcrv on command line
  68 + def _test_cmd(self):
  69 + """
  70 + Test cslightcrv on the command line.
  71 + """
  72 + # Kluge to set the command (installed version has no README file)
  73 + if os.path.isfile("README"):
  74 + cslightcrv = "../cscripts/cslightcrv.py"
  75 + else:
  76 + cslightcrv = "cslightcrv"
  77 +
  78 + # Setup cslightcrv command
  79 + cmd = cslightcrv+' inobs="'+self._events_name+'"'+ \
  80 + ' inmodel="'+self._model_name+'"'+ \
  81 + ' srcname="Crab" caldb="prod2" irf="South_0.5h"'+ \
  82 + ' tbinalg="LIN" tmin=51544.50 tmax=51544.53'+ \
  83 + ' tbins=3 enumbins=0 emin=0.1 emax=100.0'+ \
  84 + ' outfile="lightcurve_cmd1.fits"'
  85 +
  86 + # Execute cslightcrv, make sure we catch any exception
  87 + try:
  88 + rc = os.system(cmd+" >/dev/null 2>&1")
  89 + except:
  90 + pass
  91 +
  92 + # Check if execution was successful
  93 + self.test_assert(rc == 0,
  94 + "Successful cslightcrv execution on command line")
  95 +
  96 + # Check light curve
  97 + self._check_light_curve("lightcurve_cmd1.fits", 3)
  98 +
  99 + # Setup cslightcrv command
  100 + cmd = cslightcrv+' inobs="events_that_do_not_exist.fits"'+ \
  101 + ' inmodel="'+self._model_name+'"'+ \
  102 + ' srcname="Crab" caldb="prod2" irf="South_0.5h"'+ \
  103 + ' tbinalg="LIN" tmin=51544.50 tmax=51544.53'+ \
  104 + ' tbins=3 enumbins=0 emin=0.1 emax=100.0'+ \
  105 + ' outfile="lightcurve_cmd1.fits"'
  106 +
  107 + # Execute cslightcrv, make sure we catch any exception
  108 + try:
  109 + rc = os.system(cmd+" >/dev/null 2>&1")
  110 + except:
  111 + pass
  112 +
  113 + # Check if execution failed
  114 + self.test_assert(rc != 0,
  115 + "Failure of cslightcrv execution on command line")
  116 +
  117 + # Return
  118 + return
  119 +
  120 + # Test cslightcrv from Python
  121 + def _test_python(self):
  122 + """
  123 + Test cslightcrv from Python.
  124 + """
  125 + # Set-up unbinned cslightcrv
  126 + lcrv = cscripts.cslightcrv()
  127 + lcrv["inobs"] = self._events_name
  128 + lcrv["inmodel"] = self._model_name
  129 + lcrv["srcname"] = "Crab"
  130 + lcrv["caldb"] = "prod2"
  131 + lcrv["irf"] = "South_0.5h"
  132 + lcrv["tbinalg"] = "LIN"
  133 + lcrv["tmin"] = 51544.50
  134 + lcrv["tmax"] = 51544.53
  135 + lcrv["tbins"] = 3
  136 + lcrv["enumbins"] = 0
  137 + lcrv["emin"] = 0.1
  138 + lcrv["emax"] = 100.0
  139 + lcrv["outfile"] = "lightcurve_py1.fits"
  140 +
  141 + # Run cslightcrv script and save light curve
  142 + lcrv.run()
  143 + lcrv.save()
  144 +
  145 + # Check light curve
  146 + self._check_light_curve("lightcurve_py1.fits", 3)
  147 +
  148 + # Now use FILE as time bin algorithm. For this we need first to
  149 + # create an ASCII file. We use now 6 time bins. The ASCII file
  150 + # is saved into the file "lightcurve_py2.dat".
  151 + csv = gammalib.GCsv(2,2)
  152 + tmin = 51544.50
  153 + tdelta = 0.01
  154 + for i in range(csv.nrows()):
  155 + csv[i,0] = "%.5f" % (tmin + i * tdelta)
  156 + csv[i,1] = "%.5f" % (tmin + (i+1) * tdelta)
  157 + csv.save("lightcurve_py2.dat", " ", True)
  158 +
  159 + # Set-up unbinned cslightcrv
  160 + lcrv = cscripts.cslightcrv()
  161 + lcrv["inobs"] = self._events_name
  162 + lcrv["inmodel"] = self._model_name
  163 + lcrv["srcname"] = "Crab"
  164 + lcrv["caldb"] = "prod2"
  165 + lcrv["irf"] = "South_0.5h"
  166 + lcrv["tbinalg"] = "FILE"
  167 + lcrv["tbinfile"] = "lightcurve_py2.dat"
  168 + lcrv["enumbins"] = 0
  169 + lcrv["emin"] = 0.1
  170 + lcrv["emax"] = 100.0
  171 + lcrv["outfile"] = "lightcurve_py2.fits"
  172 +
  173 + # Execute cslightcrv script
  174 + lcrv.execute()
  175 +
  176 + # Check light curve
  177 + self._check_light_curve("lightcurve_py2.fits", 2)
  178 +
  179 + # Now we setup an observation container on input. We attached the
  180 + # model to the observation container so that cslightcrv should
  181 + # no longer query for the parameter.
  182 + cta = gammalib.GCTAObservation(self._events_name)
  183 + obs = gammalib.GObservations()
  184 + obs.append(cta)
  185 + obs.models(self._model_name)
  186 +
  187 + # Set-up unbinned cslightcrv from observation container. Now use
  188 + # the GTI algorithm so that we test all timing algorithms.
  189 + lcrv = cscripts.cslightcrv(obs)
  190 + lcrv["srcname"] = "Crab"
  191 + lcrv["caldb"] = "prod2"
  192 + lcrv["irf"] = "South_0.5h"
  193 + lcrv["tbinalg"] = "GTI"
  194 + lcrv["enumbins"] = 0
  195 + lcrv["emin"] = 0.1
  196 + lcrv["emax"] = 100.0
  197 + lcrv["outfile"] = "lightcurve_py3.fits"
  198 +
  199 + # Execute cslightcrv script
  200 + lcrv.execute()
  201 +
  202 + # Check light curve
  203 + self._check_light_curve("lightcurve_py3.fits", 1)
  204 +
  205 + # Finally we set-up a binned cslightcrv
  206 + lcrv = cscripts.cslightcrv()
  207 + lcrv["inobs"] = self._events_name
  208 + lcrv["inmodel"] = self._model_name
  209 + lcrv["srcname"] = "Crab"
  210 + lcrv["caldb"] = "prod2"
  211 + lcrv["irf"] = "South_0.5h"
  212 + lcrv["tbinalg"] = "LIN"
  213 + lcrv["tmin"] = 51544.50
  214 + lcrv["tmax"] = 51544.53
  215 + lcrv["tbins"] = 2
  216 + lcrv["emin"] = 0.1
  217 + lcrv["emax"] = 100.0
  218 + lcrv["enumbins"] = 10
  219 + lcrv["coordsys"] = "CEL"
  220 + lcrv["proj"] = "TAN"
  221 + lcrv["xref"] = 83.63
  222 + lcrv["yref"] = 22.01
  223 + lcrv["nxpix"] = 20
  224 + lcrv["nypix"] = 20
  225 + lcrv["binsz"] = 0.02
  226 + lcrv["outfile"] = "lightcurve_py4.fits"
  227 +
  228 + # Execute cslightcrv script
  229 + lcrv.execute()
  230 +
  231 + # Check light curve
  232 + self._check_light_curve("lightcurve_py4.fits", 2)
  233 +
  234 + # Return
  235 + return
  236 +
  237 + # Check light curve result file
  238 + def _check_light_curve(self, filename, bins):
  239 + """
  240 + Check light curve file.
  241 + """
  242 + # Expected column names
  243 + cols = ["MJD", "e_MJD", "Prefactor", "e_Prefactor",
  244 + "Index", "e_Index", "TS", "UpperLimit"]
  245 +
  246 + # Open FITS file
  247 + fits = gammalib.GFits(filename)
  248 +
  249 + # Check FITS file structure
  250 + self.test_value(fits.size(), 2,
  251 + 'Check for 2 extensions in light curve FITS file')
  252 + self.test_assert(fits.contains("LIGHTCURVE"),
  253 + 'FITS file contains "LIGHTCURVE" extension')
  254 +
  255 + # Get LIGHTCURVE table
  256 + table = fits["LIGHTCURVE"]
  257 +
  258 + # Check FITS table structure
  259 + self.test_value(table.ncols(), len(cols),
  260 + 'Check for %d columns in light curve FITS table' % len(cols))
  261 + self.test_value(table.nrows(), bins,
  262 + 'Check for %d rows in light curve FITS table' % bins)
  263 + for col in cols:
  264 + self.test_assert(table.contains(col),
  265 + 'FITS file contains "'+col+'" column')
  266 +
  267 + # Close FITS file
  268 + fits.close()
  269 +
  270 + # Return
  271 + return
... ...
test/test_ctbin.py
1 1 #! /usr/bin/env python
2 2 # ==========================================================================
3   -# This scripts performs unit tests for the ctbin module.
  3 +# This scripts performs unit tests for the ctbin tool.
4 4 #
5 5 # Copyright (C) 2014-2016 Juergen Knoedlseder
6 6 #
... ... @@ -18,16 +18,20 @@
18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19 #
20 20 # ==========================================================================
  21 +import os
21 22 import gammalib
22 23 import ctools
23 24  
24 25  
25   -# =========================== #
26   -# Test class for ctbin module #
27   -# =========================== #
  26 +# ========================= #
  27 +# Test class for ctbin tool #
  28 +# ========================= #
28 29 class Test(gammalib.GPythonTestSuite):
29 30 """
30   - Test class for ctbin module.
  31 + Test class for ctbin tool.
  32 +
  33 + This test class makes unit tests for the ctbin tool by using it from
  34 + the command line and from Python.
31 35 """
32 36  
33 37 # Constructor
... ... @@ -53,15 +57,68 @@ class Test(gammalib.GPythonTestSuite):
53 57 self.name("ctbin")
54 58  
55 59 # Append tests
56   - self.append(self._test_ctbin, "Test ctbin")
  60 + self.append(self._test_cmd, "Test ctbin on command line")
  61 + self.append(self._test_python, "Test ctbin from Python")
57 62  
58 63 # Return
59 64 return
60 65  
61   - # Test ctbin
62   - def _test_ctbin(self):
  66 + # Test ctbin on command line
  67 + def _test_cmd(self):
63 68 """
64   - Test ctbin.
  69 + Test ctbin on the command line.
  70 + """
  71 + # Kluge to set the command (installed version has no README file)
  72 + if os.path.isfile("README"):
  73 + ctbin = "../src/ctbin/ctbin"
  74 + else:
  75 + ctbin = "ctbin"
  76 +
  77 + # Setup ctbin command
  78 + cmd = ctbin+' inobs="'+self._events_name+'"'+ \
  79 + ' outcube="cntmap_cmd1.fits"'+\
  80 + ' emin=0.1 emax=100.0 enumbins=20 ebinalg="LOG"'+ \
  81 + ' nxpix=200 nypix=200 binsz=0.02 coordsys="CEL"'+ \
  82 + ' xref=83.63 yref=22.01 proj="CAR"'
  83 +
  84 + # Execute ctbin, make sure we catch any exception
  85 + try:
  86 + rc = os.system(cmd+" >/dev/null 2>&1")
  87 + except:
  88 + pass
  89 +
  90 + # Check if execution was successful
  91 + self.test_assert(rc == 0,
  92 + "Successful ctbin execution on command line")
  93 +
  94 + # Load counts cube and check content.
  95 + evt = gammalib.GCTAEventCube("cntmap_cmd1.fits")
  96 + self._check_cube(evt, 5542)
  97 +
  98 + # Setup ctbin command
  99 + cmd = ctbin+' inobs="events_that_do_not_exist.fits"'+ \
  100 + ' outcube="cntmap_cmd2.fits"'+\
  101 + ' emin=0.1 emax=100.0 enumbins=20 ebinalg="LOG"'+ \
  102 + ' nxpix=200 nypix=200 binsz=0.02 coordsys="CEL"'+ \
  103 + ' xref=83.63 yref=22.01 proj="CAR"'
  104 +
  105 + # Execute ctbin, make sure we catch any exception
  106 + try:
  107 + rc = os.system(cmd+" >/dev/null 2>&1")
  108 + except:
  109 + pass
  110 +
  111 + # Check if execution failed
  112 + self.test_assert(rc != 0,
  113 + "Failure of ctbin execution on command line")
  114 +
  115 + # Return
  116 + return
  117 +
  118 + # Test ctbin from Python
  119 + def _test_python(self):
  120 + """
  121 + Test ctbin from Python.
65 122 """
66 123 # Set-up ctbin
67 124 bin = ctools.ctbin()
... ... @@ -83,15 +140,15 @@ class Test(gammalib.GPythonTestSuite):
83 140 bin.run()
84 141  
85 142 # Check content of observation and cube
86   - self._test_observation(bin, 5542)
87   - self._test_cube(bin.cube(), 5542)
  143 + self._check_observation(bin, 5542)
  144 + self._check_cube(bin.cube(), 5542)
88 145  
89 146 # Test copy constructor
90 147 cpy_bin = bin.copy()
91 148  
92 149 # Check content of observation and cube
93   - self._test_observation(cpy_bin, 5542)
94   - self._test_cube(cpy_bin.cube(), 5542)
  150 + self._check_observation(cpy_bin, 5542)
  151 + self._check_cube(cpy_bin.cube(), 5542)
95 152  
96 153 # Run copy of ctbin tool again
97 154 cpy_bin.run()
... ... @@ -100,8 +157,8 @@ class Test(gammalib.GPythonTestSuite):
100 157 # event cube as on input the observation is binned, and any binned
101 158 # observation will be skipped, hence the counts cube should be
102 159 # empty.
103   - self._test_observation(cpy_bin, 0)
104   - self._test_cube(cpy_bin.cube(), 0)
  160 + self._check_observation(cpy_bin, 0)
  161 + self._check_cube(cpy_bin.cube(), 0)
105 162  
106 163 # Clear and run copy of ctbin again
107 164 #cpy_bin.clear()
... ... @@ -115,7 +172,7 @@ class Test(gammalib.GPythonTestSuite):
115 172  
116 173 # Load counts cube and check content.
117 174 evt = gammalib.GCTAEventCube("cntmap.fits")
118   - self._test_cube(evt, 5542)
  175 + self._check_cube(evt, 5542)
119 176  
120 177 # Prepare observation container for stacked analysis
121 178 cta = gammalib.GCTAObservation(self._events_name)
... ... @@ -147,13 +204,12 @@ class Test(gammalib.GPythonTestSuite):
147 204  
148 205 # Check content of observation and cube (need multiplier=3 since
149 206 # three identical observations have been appended)
150   - self._test_observation(bin, 5542, multiplier=3)
151   - self._test_cube(bin.cube(), 5542, multiplier=3)
  207 + self._check_observation(bin, 5542, multiplier=3)
  208 + self._check_cube(bin.cube(), 5542, multiplier=3)
152 209  
153   - # Set-up ctbin with invalid event file
154   - bin = ctools.ctbin()
155   - bin["inobs"] = "event_file_that_does_not_exist.fits"
156   - bin["outcube"] = "cntmap.fits"
  210 + # Set-up ctbin using an observation container
  211 + bin = ctools.ctbin(obs)
  212 + bin["outcube"] = "cntmap2.fits"
157 213 bin["ebinalg"] = "LOG"
158 214 bin["emin"] = 0.1
159 215 bin["emax"] = 100.0
... ... @@ -166,21 +222,29 @@ class Test(gammalib.GPythonTestSuite):
166 222 bin["xref"] = 83.63
167 223 bin["yref"] = 22.01
168 224  
169   - # Run ctbin tool
170   - self.test_try("Run ctbin with invalid event file")
171   - try:
172   - bin.run()
173   - self.test_try_failure()
174   - except:
175   - self.test_try_success()
  225 + # Execute ctbin tool
  226 + bin.execute()
  227 +
  228 + # Load counts cube and check content.
  229 + evt = gammalib.GCTAEventCube("cntmap2.fits")
  230 + self._check_cube(evt, 5542, multiplier=3)
  231 +
  232 + # Clear tool
  233 + #bin.clear()
  234 +#what(): *** ERROR in GApplicationPars::write(std::string&): Unable to open parameter file "pfiles/".
  235 +
  236 + # Check content of observation and cube
  237 + #self.test_value(bin.obs().size(), 0, "There is no observation")
  238 + #self.test_value(bin.cube().size(), 0, "0 event bins")
  239 + #self.test_value(bin.cube().number(), 0, "0 events")
176 240  
177 241 # Return
178 242 return
179 243  
180 244 # Check observation
181   - def _test_observation(self, ctbin, nevents, multiplier=1):
  245 + def _check_observation(self, ctbin, nevents, multiplier=1):
182 246 """
183   - Test content of an observation.
  247 + Check content of an observation.
184 248  
185 249 Args:
186 250 ctbin: ctbin instance
... ... @@ -206,15 +270,15 @@ class Test(gammalib.GPythonTestSuite):
206 270 "Pointing Declination is 22.01 deg")
207 271  
208 272 # Test event cube
209   - self._test_cube(obs.events(), nevents, multiplier=multiplier)
  273 + self._check_cube(obs.events(), nevents, multiplier=multiplier)
210 274  
211 275 # Return
212 276 return
213 277  
214 278 # Check event cube
215   - def _test_cube(self, cube, nevents, multiplier=1):
  279 + def _check_cube(self, cube, nevents, multiplier=1):
216 280 """
217   - Test content of event cube."
  281 + Check content of event cube."
218 282  
219 283 Args:
220 284 cube: Event cube
... ...
test/test_ctobssim.py
1 1 #! /usr/bin/env python
2 2 # ==========================================================================
3   -# This scripts performs unit tests for the ctobssim module.
  3 +# This scripts performs unit tests for the ctobssim tool.
4 4 #
5 5 # Copyright (C) 2014-2016 Juergen Knoedlseder
6 6 #
... ... @@ -18,17 +18,21 @@
18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19 #
20 20 # ==========================================================================
  21 +import os
21 22 import gammalib
22 23 import ctools
23 24 from cscripts import obsutils
24 25  
25 26  
26   -# ============================== #
27   -# Test class for ctobssim module #
28   -# ============================== #
  27 +# ============================ #
  28 +# Test class for ctobssim tool #
  29 +# ============================ #
29 30 class Test(gammalib.GPythonTestSuite):
30 31 """
31   - Test class for ctobssim module.
  32 + Test class for ctobssim tools.
  33 +
  34 + This test class makes unit tests for the ctobssim tool by using it from
  35 + the command line and from Python.
32 36 """
33 37  
34 38 # Constructor
... ... @@ -56,16 +60,67 @@ class Test(gammalib.GPythonTestSuite):
56 60 self.name("ctobssim")
57 61  
58 62 # Append tests
59   - self.append(self._test_ctobssim, "Test ctobssim")
60   - #self.append(self._test_container, "Test ctobssim on observation container")
  63 + self.append(self._test_ctobssim_cmd, "Test ctobssim on command line")
  64 + self.append(self._test_ctobssim_python, "Test ctobssim from Python")
61 65  
62 66 # Return
63 67 return
64 68  
65   - # Test ctobssim
66   - def _test_ctobssim(self):
  69 + # Test ctobssim on command line
  70 + def _test_ctobssim_cmd(self):
67 71 """
68   - Test ctobssim.
  72 + Test ctobssim on the command line.
  73 + """
  74 + # Kluge to set the command (installed version has no README file)
  75 + if os.path.isfile("README"):
  76 + ctobssim = "../src/ctobssim/ctobssim"
  77 + else:
  78 + ctobssim = "ctobssim"
  79 +
  80 + # Setup ctobssim command
  81 + cmd = ctobssim+' inmodel="data/crab.xml" outevents="events.fits"'+ \
  82 + ' caldb="irf" irf="cta_dummy_irf" '+ \
  83 + ' ra=83.63 dec=22.01 rad=10.0'+ \
  84 + ' tmin=0.0 tmax=1800.0 emin=0.1 emax=100.0'
  85 +
  86 + # Execute ctobssim, make sure we catch any exception
  87 + try:
  88 + rc = os.system(cmd+" >/dev/null 2>&1")
  89 + except:
  90 + pass
  91 +
  92 + # Check if execution was successful
  93 + self.test_assert(rc == 0,
  94 + "Successful ctobssim execution on command line")
  95 +
  96 + # Load counts cube and check content.
  97 + evt = gammalib.GCTAEventList("events.fits")
  98 + self._test_list(evt, 4119)
  99 +
  100 + # Setup ctobssim command
  101 + cmd = ctobssim+' inmodel="model_that_does_not_exist.xml"'+ \
  102 + ' outevents="events.fits"'+ \
  103 + ' caldb="irf" irf="cta_dummy_irf" '+ \
  104 + ' ra=83.63 dec=22.01 rad=10.0'+ \
  105 + ' tmin=0.0 tmax=1800.0 emin=0.1 emax=100.0'
  106 +
  107 + # Execute ctobssim, make sure we catch any exception
  108 + try:
  109 + rc = os.system(cmd+" >/dev/null 2>&1")
  110 + except:
  111 + pass
  112 +
  113 + # Check if execution failed
  114 + self.test_assert(rc != 0,
  115 + "Failure of ctobssim execution on command line")
  116 +
  117 + # Return
  118 + return
  119 +
  120 + # Test ctobssim from Python
  121 + def _test_ctobssim_python(self):
  122 + """
  123 + Test ctobssim from Python.
69 124 """
70 125 # Set-up ctobssim
71 126 sim = ctools.ctobssim()
... ...
test/test_python_cscripts.py
... ... @@ -18,12 +18,13 @@
18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19 #
20 20 # ==========================================================================
  21 +import os
  22 +import sys
21 23 import gammalib
22 24 import cscripts
23   -import sys
24   -import os
25 25 sys.path.append(os.path.dirname(os.path.abspath(__file__)))
26 26 import test_cscaldb
  27 +import test_cslightcrv
27 28  
28 29  
29 30 # ================== #
... ... @@ -37,13 +38,16 @@ def test(installed=False):
37 38 suites = gammalib.GTestSuites("cscripts Python module unit testing")
38 39  
39 40 # Allocate test suites and append them to the container
40   - suite_cscaldb = test_cscaldb.Test()
  41 + suite_cscaldb = test_cscaldb.Test()
  42 + suite_cslightcrv = test_cslightcrv.Test()
41 43  
42 44 # Setup unit tests
43 45 suite_cscaldb.set()
  46 + suite_cslightcrv.set()
44 47  
45 48 # Append tests to container
46 49 suites.append(suite_cscaldb)
  50 + suites.append(suite_cslightcrv)
47 51  
48 52 # If we have an installed version then create a temporary directory and
49 53 # copy over all information that is needed
... ... @@ -60,9 +64,13 @@ def test(installed=False):
60 64 dirname = os.path.dirname(testdir)
61 65  
62 66 # Copy over test data and irf
63   - #os.system("cp -r %s %s" % (dirname+"/data", "data"))
  67 + os.system("cp -r %s %s" % (dirname+"/data", "data"))
64 68 #os.system("cp -r %s %s" % (dirname+"/irf", "irf"))
65 69  
  70 + # ... otherwise set the calibration database
  71 + else:
  72 + os.environ['CALDB'] = "../caldb"
  73 +
66 74 # Set PFILES environment variable
67 75 try:
68 76 os.mkdir("pfiles")
... ... @@ -97,8 +105,6 @@ def test(installed=False):
97 105 # Main routine entry point #
98 106 # ======================== #
99 107 if __name__ == '__main__':
100   - """
101   - Perform unit testing for cscripts used from Python.
102   - """
  108 +
103 109 # Run tests
104 110 test()
... ...
test/test_python_ctools.py
... ... @@ -40,15 +40,15 @@ import test_cterror
40 40 import test_pipelines
41 41  
42 42  
43   -# ================== #
44   -# Perform unit tests #
45   -# ================== #
  43 +# ========================= #
  44 +# Perform ctools unit tests #
  45 +# ========================= #
46 46 def test(installed=False):
47 47 """
48   - Perform unit testing for Python interface.
  48 + Perform unit testing for ctools.
49 49 """
50 50 # Allocate test suite container
51   - suites = gammalib.GTestSuites("ctools Python module unit testing")
  51 + suites = gammalib.GTestSuites("ctools unit testing")
52 52  
53 53 # Allocate test suites and append them to the container
54 54 suite_ctobssim = test_ctobssim.Test()
... ... @@ -153,8 +153,6 @@ def test(installed=False):
153 153 # Main routine entry point #
154 154 # ======================== #
155 155 if __name__ == '__main__':
156   - """
157   - Perform unit testing for Python interface.
158   - """
  156 +
159 157 # Run tests
160 158 test()
... ...