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,6 +12,8 @@
12 *.toc 12 *.toc
13 *.Pi 13 *.Pi
14 *.Tpi 14 *.Tpi
  15 +*.gcno
  16 +*.gcda
15 .DS_Store 17 .DS_Store
16 .cproject 18 .cproject
17 .project 19 .project
@@ -41,6 +43,7 @@ depcomp @@ -41,6 +43,7 @@ depcomp
41 test-driver 43 test-driver
42 testconf.sh 44 testconf.sh
43 coverage-report-python.xml 45 coverage-report-python.xml
  46 +coverage-report-cxx.xml
44 47
45 doc/html 48 doc/html
46 doc/man 49 doc/man
Makefile.am
@@ -93,7 +93,7 @@ cppncss: @@ -93,7 +93,7 @@ cppncss:
93 # Add coverage rule 93 # Add coverage rule
94 coverage: 94 coverage:
95 @if type gcovr >/dev/null 2>&1; then \ 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 else \ 97 else \
98 echo "gcovr script not found in PATH."; \ 98 echo "gcovr script not found in PATH."; \
99 fi; \ 99 fi; \
configure.ac
@@ -87,6 +87,22 @@ AC_CANONICAL_HOST @@ -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 # Check for valid C++ compiler. This has to come before the check for # 106 # Check for valid C++ compiler. This has to come before the check for #
91 # header files, otherwise we won't detect if the C++ compiler is missing. # 107 # header files, otherwise we won't detect if the C++ compiler is missing. #
92 # # 108 # #
@@ -140,11 +156,23 @@ else @@ -140,11 +156,23 @@ else
140 fi 156 fi
141 AM_CONDITIONAL(IS_ELCAPITAN, test "x$osx_el_capitan" = "xyes") 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 # Our language is C++ 165 # Our language is C++
144 AC_LANG(C++) 166 AC_LANG(C++)
145 AC_PROG_CXX($cxx_list) 167 AC_PROG_CXX($cxx_list)
146 AC_PROG_CC($cc_list) 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 # Darwin option: Determine architecture of universal library to be built # 178 # Darwin option: Determine architecture of universal library to be built #
@@ -758,25 +786,22 @@ fi @@ -758,25 +786,22 @@ fi
758 ############################################################################# 786 #############################################################################
759 # Initialise Python coverage with empty string 787 # Initialise Python coverage with empty string
760 PYTHON_COVERAGE= 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 if test "x$enable_coverage" = "xyes"; then 792 if test "x$enable_coverage" = "xyes"; then
770 CXXFLAGS="--coverage $CXXFLAGS" 793 CXXFLAGS="--coverage $CXXFLAGS"
  794 + COVERAGE_CXXFLAGS="--coverage"
771 LDFLAGS="--coverage $LDFLAGS" 795 LDFLAGS="--coverage $LDFLAGS"
772 if test "x$has_python" = "xyes"; then 796 if test "x$has_python" = "xyes"; then
773 - PYTHON_COVERAGE="coverage run --append " 797 + PYTHON_COVERAGE="coverage run --branch --append "
774 fi 798 fi
775 AC_MSG_RESULT(yes) 799 AC_MSG_RESULT(yes)
776 else 800 else
777 AC_MSG_RESULT(no) 801 AC_MSG_RESULT(no)
778 fi 802 fi
779 AC_SUBST(PYTHON_COVERAGE) 803 AC_SUBST(PYTHON_COVERAGE)
  804 +AC_SUBST(COVERAGE_CXXFLAGS)
780 805
781 806
782 ############################################################################# 807 #############################################################################
@@ -937,7 +962,7 @@ OPENMP_LIB_LDFLAGS= @@ -937,7 +962,7 @@ OPENMP_LIB_LDFLAGS=
937 #fi 962 #fi
938 AC_SUBST(OPENMP_LIB_LDFLAGS) 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 # cannot be compiled with OpenMP 966 # cannot be compiled with OpenMP
942 if test "x$enable_openmp" = "xno" && test "x$gammalib_with_openmp" = "xyes"; then 967 if test "x$enable_openmp" = "xno" && test "x$gammalib_with_openmp" = "xyes"; then
943 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.]) 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,13 +26,17 @@ linkscripts = cspull cssens cstsdist cscaldb csresmap \
26 # Test scripts to be distributed in $(pyexecdir)/cscripts/tests 26 # Test scripts to be distributed in $(pyexecdir)/cscripts/tests
27 testscripts = tests/__init__.py \ 27 testscripts = tests/__init__.py \
28 ../test/test_python_cscripts.py \ 28 ../test/test_python_cscripts.py \
29 - ../test/test_cscaldb.py 29 + ../test/test_cscaldb.py \
  30 + ../test/test_cslightcrv.py
30 31
31 # Test data to be distributed in $(pyexecdir)/cscripts/tests/data 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 # Test IRFs to be distributed in $(pyexecdir)/cscripts/tests/irf 38 # Test IRFs to be distributed in $(pyexecdir)/cscripts/tests/irf
35 -testirf = 39 +#testirf =
36 40
37 # Distribute scripts and parfiles 41 # Distribute scripts and parfiles
38 EXTRA_DIST = $(binscripts) $(pythonscripts) 42 EXTRA_DIST = $(binscripts) $(pythonscripts)
@@ -46,8 +50,8 @@ testscriptsdir = $(pyexecdir)/cscripts/tests @@ -46,8 +50,8 @@ testscriptsdir = $(pyexecdir)/cscripts/tests
46 testscripts_DATA = $(testscripts) 50 testscripts_DATA = $(testscripts)
47 testdatadir = $(pyexecdir)/cscripts/tests/data 51 testdatadir = $(pyexecdir)/cscripts/tests/data
48 testdata_DATA = $(testdata) 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 # Add hook rule to create symbolic links for cscripts 56 # Add hook rule to create symbolic links for cscripts
53 install-data-hook: 57 install-data-hook:
cscripts/csiactobs.py
@@ -501,14 +501,14 @@ class csiactobs(ctools.cscript): @@ -501,14 +501,14 @@ class csiactobs(ctools.cscript):
501 self._log("\n") 501 self._log("\n")
502 502
503 # Append observation to XML and set attributes 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 # Append event file 509 # Append event file
510 ev = gammalib.GXmlElement("parameter name=\"EventList\"") 510 ev = gammalib.GXmlElement("parameter name=\"EventList\"")
511 - ev.attribute("file", eventfile); 511 + ev.attribute("file", eventfile)
512 512
513 # Append effective area 513 # Append effective area
514 aeff = gammalib.GXmlElement("parameter name=\"EffectiveArea\"") 514 aeff = gammalib.GXmlElement("parameter name=\"EffectiveArea\"")
cscripts/cslightcrv.py
@@ -76,12 +76,15 @@ class cslightcrv(ctools.cscript): @@ -76,12 +76,15 @@ class cslightcrv(ctools.cscript):
76 self._stacked = False 76 self._stacked = False
77 77
78 # Initialise observation container from constructor arguments. 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 self._init_cscript(argv) 82 self._init_cscript(argv)
84 83
  84 + # Set logger properties
  85 + self._log_header()
  86 + self._log.date(True)
  87 +
85 # Return 88 # Return
86 return 89 return
87 90
@@ -91,12 +94,10 @@ class cslightcrv(ctools.cscript): @@ -91,12 +94,10 @@ class cslightcrv(ctools.cscript):
91 """ 94 """
92 Get parameters from parfile. 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 if self._obs.models().size() == 0: 101 if self._obs.models().size() == 0:
101 self._obs.models(self["inmodel"].filename()) 102 self._obs.models(self["inmodel"].filename())
102 103
@@ -106,11 +107,18 @@ class cslightcrv(ctools.cscript): @@ -106,11 +107,18 @@ class cslightcrv(ctools.cscript):
106 # Get time boundaries 107 # Get time boundaries
107 self._tbins = self._create_tbounds() 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 self["emin"].real() 122 self["emin"].real()
115 self["emax"].real() 123 self["emax"].real()
116 if self._stacked: 124 if self._stacked:
@@ -429,16 +437,26 @@ class cslightcrv(ctools.cscript): @@ -429,16 +437,26 @@ class cslightcrv(ctools.cscript):
429 if self._logExplicit(): 437 if self._logExplicit():
430 self._log.header3("Creating point spread function cube") 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 psfcube = ctools.ctpsfcube(obs) 451 psfcube = ctools.ctpsfcube(obs)
434 psfcube["incube"] = "NONE" 452 psfcube["incube"] = "NONE"
435 psfcube["usepnt"] = False 453 psfcube["usepnt"] = False
436 psfcube["ebinalg"] = "LOG" 454 psfcube["ebinalg"] = "LOG"
437 psfcube["xref"] = self["xref"].real() 455 psfcube["xref"] = self["xref"].real()
438 psfcube["yref"] = self["yref"].real() 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 psfcube["enumbins"] = self["enumbins"].integer() 460 psfcube["enumbins"] = self["enumbins"].integer()
443 psfcube["emin"] = self["emin"].real() 461 psfcube["emin"] = self["emin"].real()
444 psfcube["emax"] = self["emax"].real() 462 psfcube["emax"] = self["emax"].real()
@@ -453,16 +471,16 @@ class cslightcrv(ctools.cscript): @@ -453,16 +471,16 @@ class cslightcrv(ctools.cscript):
453 if self._logExplicit(): 471 if self._logExplicit():
454 self._log.header3("Creating energy dispersion cube") 472 self._log.header3("Creating energy dispersion cube")
455 473
456 - # Create edisp cube 474 + # Create energy dispersion cube
457 edispcube = ctools.ctedispcube(obs) 475 edispcube = ctools.ctedispcube(obs)
458 edispcube["incube"] = "NONE" 476 edispcube["incube"] = "NONE"
459 edispcube["usepnt"] = False 477 edispcube["usepnt"] = False
460 edispcube["ebinalg"] = "LOG" 478 edispcube["ebinalg"] = "LOG"
461 edispcube["xref"] = self["xref"].real() 479 edispcube["xref"] = self["xref"].real()
462 edispcube["yref"] = self["yref"].real() 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 edispcube["enumbins"] = self["enumbins"].integer() 484 edispcube["enumbins"] = self["enumbins"].integer()
467 edispcube["emin"] = self["emin"].real() 485 edispcube["emin"] = self["emin"].real()
468 edispcube["emax"] = self["emax"].real() 486 edispcube["emax"] = self["emax"].real()
cscripts/csobsinfo.py
@@ -52,7 +52,7 @@ class csobsinfo(ctools.cscript): @@ -52,7 +52,7 @@ class csobsinfo(ctools.cscript):
52 self._gti = gammalib.GGti() 52 self._gti = gammalib.GGti()
53 53
54 # Initialise observation container from constructor arguments. 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 # Initialise application by calling the appropriate class 57 # Initialise application by calling the appropriate class
58 # constructor. 58 # constructor.
cscripts/cspull.py
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # 19 #
20 # ========================================================================== 20 # ==========================================================================
21 -import gammalib 21 +#import gammalib
22 import ctools 22 import ctools
23 from cscripts import obsutils 23 from cscripts import obsutils
24 import sys 24 import sys
@@ -62,7 +62,7 @@ class cspull(ctools.cscript): @@ -62,7 +62,7 @@ class cspull(ctools.cscript):
62 self._log_clients = False 62 self._log_clients = False
63 63
64 # Initialise observation container from constructor arguments. 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 # Initialise application by calling the appropriate class 67 # Initialise application by calling the appropriate class
68 # constructor. 68 # constructor.
@@ -410,17 +410,17 @@ class cspull(ctools.cscript): @@ -410,17 +410,17 @@ class cspull(ctools.cscript):
410 410
411 # Write out result immediately 411 # Write out result immediately
412 if seed == 0: 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 headers = {} 415 headers = {}
416 for n in result['colnames']: 416 for n in result['colnames']:
417 headers[n] = n 417 headers[n] = n
418 writer.writerow(headers) 418 writer.writerow(headers)
419 else: 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 writer.writerow(result['values']) 422 writer.writerow(result['values'])
423 - file.close() 423 + f.close()
424 424
425 # Return 425 # Return
426 return 426 return
cscripts/csresmap.py
@@ -74,7 +74,7 @@ class csresmap(ctools.cscript): @@ -74,7 +74,7 @@ class csresmap(ctools.cscript):
74 self._log_clients = False 74 self._log_clients = False
75 75
76 # Initialise observation container from constructor arguments. 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 # Initialise application by calling the appropriate class 79 # Initialise application by calling the appropriate class
80 # constructor. 80 # constructor.
cscripts/cssens.py
@@ -347,18 +347,18 @@ class cssens(ctools.cscript): @@ -347,18 +347,18 @@ class cssens(ctools.cscript):
347 photon_flux_value = [] 347 photon_flux_value = []
348 energy_flux_value = [] 348 energy_flux_value = []
349 sensitivity_value = [] 349 sensitivity_value = []
350 - iter = 0 350 + iterations = 0
351 test_crab_flux = 0.1 # Initial test flux in Crab units (100 mCrab) 351 test_crab_flux = 0.1 # Initial test flux in Crab units (100 mCrab)
352 352
353 # Loop until we break 353 # Loop until we break
354 while True: 354 while True:
355 355
356 # Update iteration counter 356 # Update iteration counter
357 - iter += 1 357 + iterations += 1
358 358
359 # Write header 359 # Write header
360 if self._logExplicit(): 360 if self._logExplicit():
361 - self._log.header2("Iteration "+str(iter)) 361 + self._log.header2("Iteration "+str(iterations))
362 362
363 # Set source model. crab_prefactor is the Prefactor that 363 # Set source model. crab_prefactor is the Prefactor that
364 # corresponds to 1 Crab 364 # corresponds to 1 Crab
@@ -370,7 +370,7 @@ class cssens(ctools.cscript): @@ -370,7 +370,7 @@ class cssens(ctools.cscript):
370 self._obs.models(src_model) 370 self._obs.models(src_model)
371 371
372 # Simulate events 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 binsz=self._binsz, npix=self._npix, 374 binsz=self._binsz, npix=self._npix,
375 log=self._log_clients, debug=self._debug, 375 log=self._log_clients, debug=self._debug,
376 edisp=self._edisp) 376 edisp=self._edisp)
@@ -464,8 +464,8 @@ class cssens(ctools.cscript): @@ -464,8 +464,8 @@ class cssens(ctools.cscript):
464 # Get fitted Crab, photon and energy fluxes 464 # Get fitted Crab, photon and energy fluxes
465 crab_flux = result_all[self._srcname]['Prefactor'].value() / \ 465 crab_flux = result_all[self._srcname]['Prefactor'].value() / \
466 crab_prefactor 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 photon_flux = result_all[self._srcname].spectral().flux(emin, emax) 469 photon_flux = result_all[self._srcname].spectral().flux(emin, emax)
470 energy_flux = result_all[self._srcname].spectral().eflux(emin, emax) 470 energy_flux = result_all[self._srcname].spectral().eflux(emin, emax)
471 471
@@ -511,7 +511,7 @@ class cssens(ctools.cscript): @@ -511,7 +511,7 @@ class cssens(ctools.cscript):
511 for par in model: 511 for par in model:
512 self._log(str(par)+"\n") 512 self._log(str(par)+"\n")
513 elif self._logTerse(): 513 elif self._logTerse():
514 - self._log.parformat("Iteration "+str(iter)) 514 + self._log.parformat("Iteration "+str(iterations))
515 self._log("TS=") 515 self._log("TS=")
516 self._log(ts) 516 self._log(ts)
517 self._log(" ") 517 self._log(" ")
@@ -549,7 +549,7 @@ class cssens(ctools.cscript): @@ -549,7 +549,7 @@ class cssens(ctools.cscript):
549 sensitivity /= num 549 sensitivity /= num
550 550
551 # Compare average flux to last average 551 # Compare average flux to last average
552 - if iter > self._num_avg: 552 + if iterations > self._num_avg:
553 if test_crab_flux > 0: 553 if test_crab_flux > 0:
554 ratio = crab_flux/test_crab_flux 554 ratio = crab_flux/test_crab_flux
555 555
@@ -570,7 +570,7 @@ class cssens(ctools.cscript): @@ -570,7 +570,7 @@ class cssens(ctools.cscript):
570 test_crab_flux = crab_flux 570 test_crab_flux = crab_flux
571 571
572 # Exit loop if number of trials exhausted 572 # Exit loop if number of trials exhausted
573 - if (iter >= self._max_iter): 573 + if (iterations >= self._max_iter):
574 if self._logTerse(): 574 if self._logTerse():
575 self._log(" Test ended after "+str(self._max_iter)+ 575 self._log(" Test ended after "+str(self._max_iter)+
576 " iterations.\n") 576 " iterations.\n")
cscripts/csspec.py
@@ -60,7 +60,7 @@ class csspec(ctools.cscript): @@ -60,7 +60,7 @@ class csspec(ctools.cscript):
60 self._debug = False 60 self._debug = False
61 61
62 # Initialise observation container from constructor arguments. 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 # Initialise application by calling the appropriate class 65 # Initialise application by calling the appropriate class
66 # constructor. 66 # constructor.
@@ -158,9 +158,10 @@ class csspec(ctools.cscript): @@ -158,9 +158,10 @@ class csspec(ctools.cscript):
158 158
159 # If no layers overlap then throw an exception 159 # If no layers overlap then throw an exception
160 if (len(use_layers) == 0): 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 str(emin)+", "+str(emax)+"]. Specify "+ \ 165 str(emin)+", "+str(emax)+"]. Specify "+ \
165 "overlapping energy range." 166 "overlapping energy range."
166 raise RuntimeError(msg) 167 raise RuntimeError(msg)
cscripts/cstsdist.py
@@ -419,17 +419,17 @@ class cstsdist(ctools.cscript): @@ -419,17 +419,17 @@ class cstsdist(ctools.cscript):
419 419
420 # Write out result immediately 420 # Write out result immediately
421 if seed == 0: 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 headers = {} 424 headers = {}
425 for n in result['colnames']: 425 for n in result['colnames']:
426 headers[n] = n 426 headers[n] = n
427 writer.writerow(headers) 427 writer.writerow(headers)
428 else: 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 writer.writerow(result['values']) 431 writer.writerow(result['values'])
432 - file.close() 432 + f.close()
433 433
434 # Return 434 # Return
435 return 435 return
cscripts/cstsmapmerge.py
@@ -414,8 +414,8 @@ class cstsmapmerge(ctools.cscript): @@ -414,8 +414,8 @@ class cstsmapmerge(ctools.cscript):
414 # Delete TS input maps if requested 414 # Delete TS input maps if requested
415 if self._delete: 415 if self._delete:
416 for filename in self._merged_files: 416 for filename in self._merged_files:
417 - os.remove(filename)  
418 - if self._logTerse(): 417 + os.remove(filename)
  418 + if self._logTerse():
419 self._log(gammalib.parformat("Deleted input file")) 419 self._log(gammalib.parformat("Deleted input file"))
420 self._log(filename) 420 self._log(filename)
421 self._log("\n") 421 self._log("\n")
cscripts/cta_kb_bkgrates.py
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 # into a column separated file function table. The table is automatically 4 # into a column separated file function table. The table is automatically
5 # named "bkg_XXX.txt" where "XXX" is for example "kb_E_50h_v3". 5 # named "bkg_XXX.txt" where "XXX" is for example "kb_E_50h_v3".
6 # 6 #
7 -# Copyright (C) 2011-2014 Juergen Knoedlseder 7 +# Copyright (C) 2011-2016 Juergen Knoedlseder
8 # 8 #
9 # This program is free software: you can redistribute it and/or modify 9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by 10 # it under the terms of the GNU General Public License as published by
@@ -38,8 +38,8 @@ def make_file_function(irfname, filename): @@ -38,8 +38,8 @@ def make_file_function(irfname, filename):
38 filename - File function filename 38 filename - File function filename
39 """ 39 """
40 # Open performance file and file function 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 # Read data 44 # Read data
45 for row in irf: 45 for row in irf:
@@ -53,12 +53,12 @@ def make_file_function(irfname, filename): @@ -53,12 +53,12 @@ def make_file_function(irfname, filename):
53 # Extract data 53 # Extract data
54 fields = row.replace(" ",",").replace(",,",",").rstrip("\n").split(",") 54 fields = row.replace(" ",",").replace(",,",",").rstrip("\n").split(",")
55 logE = float(fields[0]) 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 r80 = float(fields[3]) 58 r80 = float(fields[3])
59 - eres = float(fields[4]) 59 + #eres = float(fields[4])
60 bgd = float(fields[5]) 60 bgd = float(fields[5])
61 - sens = float(fields[6]) 61 + #sens = float(fields[6])
62 62
63 # Compute energy (in MeV) 63 # Compute energy (in MeV)
64 energy = math.pow(10.0, logE)*1.0e6 64 energy = math.pow(10.0, logE)*1.0e6
@@ -76,11 +76,11 @@ def make_file_function(irfname, filename): @@ -76,11 +76,11 @@ def make_file_function(irfname, filename):
76 bkg_rate = 0.0 76 bkg_rate = 0.0
77 77
78 # Write 78 # Write
79 - file.write(str(energy)+" "+str(bkg_rate)+"\n") 79 + f.write(str(energy)+" "+str(bkg_rate)+"\n")
80 80
81 # Close files 81 # Close files
82 irf.close() 82 irf.close()
83 - file.close() 83 + f.close()
84 84
85 # Return 85 # Return
86 return 86 return
@@ -90,9 +90,7 @@ def make_file_function(irfname, filename): @@ -90,9 +90,7 @@ def make_file_function(irfname, filename):
90 # Main entry point # 90 # Main entry point #
91 # ================ # 91 # ================ #
92 if __name__ == '__main__': 92 if __name__ == '__main__':
93 - """  
94 - Main entry point  
95 - """ 93 +
96 # Set parameters 94 # Set parameters
97 caldb = "/usr/local/gamma/share/caldb/data/cta/kb/" 95 caldb = "/usr/local/gamma/share/caldb/data/cta/kb/"
98 96
cscripts/cta_kb_root2caldb.py
@@ -23,7 +23,8 @@ @@ -23,7 +23,8 @@
23 # along with this program. If not, see <http://www.gnu.org/licenses/>. 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 from datetime import datetime 28 from datetime import datetime
28 import gammalib 29 import gammalib
29 import math 30 import math
@@ -506,11 +507,11 @@ if __name__ == &#39;__main__&#39;: @@ -506,11 +507,11 @@ if __name__ == &#39;__main__&#39;:
506 """ 507 """
507 """ 508 """
508 # Get ROOT filename from command line argument 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 # Get list of all performance files 516 # Get list of all performance files
516 files = glob.glob(db+"/*.root") 517 files = glob.glob(db+"/*.root")
@@ -520,26 +521,26 @@ if __name__ == &#39;__main__&#39;: @@ -520,26 +521,26 @@ if __name__ == &#39;__main__&#39;:
520 irf = caldb("kb") 521 irf = caldb("kb")
521 522
522 # Loop over all files 523 # Loop over all files
523 - for file in files: 524 + for f in files:
524 525
525 # Get filename 526 # Get filename
526 - head, tail = os.path.split(file) 527 + head, tail = os.path.split(f)
527 528
528 # Build name 529 # Build name
529 name = tail.strip(".root") 530 name = tail.strip(".root")
530 if name.find("kb_") != -1: 531 if name.find("kb_") != -1:
531 name = name.replace("_20deg", "") 532 name = name.replace("_20deg", "")
532 elif name.find("IFAE_") != -1: 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 print(tail) 540 print(tail)
540 541
541 # Open calibration file 542 # Open calibration file
542 irf.add(name) 543 irf.add(name)
543 544
544 # Translate ROOT to CALDB information 545 # Translate ROOT to CALDB information
545 - irf.root2caldb(file) 546 + irf.root2caldb(f)
cscripts/cta_make_nodes.py
@@ -20,7 +20,6 @@ @@ -20,7 +20,6 @@
20 # along with this program. If not, see <http://www.gnu.org/licenses/>. 20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 # 21 #
22 # ========================================================================== 22 # ==========================================================================
23 -#import gammalib  
24 import sys 23 import sys
25 import math 24 import math
26 25
@@ -28,7 +27,7 @@ import math @@ -28,7 +27,7 @@ import math
28 # ============== # 27 # ============== #
29 # Write one node # 28 # Write one node #
30 # ============== # 29 # ============== #
31 -def write_node(file, energy, scale): 30 +def write_node(f, energy, scale):
32 """ 31 """
33 Writes one node to XML file. 32 Writes one node to XML file.
34 """ 33 """
@@ -37,22 +36,22 @@ def write_node(file, energy, scale): @@ -37,22 +36,22 @@ def write_node(file, energy, scale):
37 str_scale = str(scale) 36 str_scale = str(scale)
38 37
39 # Write start tag 38 # Write start tag
40 - file.write(' <node>\n') 39 + f.write(' <node>\n')
41 40
42 # Write energy 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 # Write intensity 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 # Write end tag 53 # Write end tag
55 - file.write(' </node>\n') 54 + f.write(' </node>\n')
56 55
57 # Return 56 # Return
58 return 57 return
@@ -66,7 +65,7 @@ def create_nodes(emin, emax, enumbins): @@ -66,7 +65,7 @@ def create_nodes(emin, emax, enumbins):
66 Create nodes (energies in TeV). 65 Create nodes (energies in TeV).
67 """ 66 """
68 # Open file 67 # Open file
69 - file = open("nodes.xml", "w") 68 + f = open("nodes.xml", "w")
70 69
71 # Set node boundaries 70 # Set node boundaries
72 elogmin = math.log10(float(emin)) 71 elogmin = math.log10(float(emin))
@@ -83,14 +82,14 @@ def create_nodes(emin, emax, enumbins): @@ -83,14 +82,14 @@ def create_nodes(emin, emax, enumbins):
83 scale = 3.45e-17 * math.pow(energy, -2.63) 82 scale = 3.45e-17 * math.pow(energy, -2.63)
84 83
85 # Write node 84 # Write node
86 - write_node(file, energy, scale) 85 + write_node(f, energy, scale)
87 86
88 # Debug 87 # Debug
89 #sys.stdout.write(energy) 88 #sys.stdout.write(energy)
90 #sys.stdout.write(math.pow(10.0, int(math.log10(scale))-1.0)±"\n") 89 #sys.stdout.write(math.pow(10.0, int(math.log10(scale))-1.0)±"\n")
91 90
92 # Close file 91 # Close file
93 - file.close() 92 + f.close()
94 93
95 # Return 94 # Return
96 return 95 return
@@ -100,9 +99,7 @@ def create_nodes(emin, emax, enumbins): @@ -100,9 +99,7 @@ def create_nodes(emin, emax, enumbins):
100 # Main script entry point # 99 # Main script entry point #
101 # ======================= # 100 # ======================= #
102 if __name__ == '__main__': 101 if __name__ == '__main__':
103 - """  
104 - Compute nodes.  
105 - """ 102 +
106 # Check command line 103 # Check command line
107 usage = "Usage: cta_make_nodes emin emax enumbins" 104 usage = "Usage: cta_make_nodes emin emax enumbins"
108 if len(sys.argv) < 3: 105 if len(sys.argv) < 3:
cscripts/cta_root2caldb.py
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 # This script generates IRFs in the CALDB format of HEASARC using ROOT 3 # This script generates IRFs in the CALDB format of HEASARC using ROOT
4 # offaxis performance files. 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 # This program is free software: you can redistribute it and/or modify 9 # This program is free software: you can redistribute it and/or modify
@@ -24,12 +24,13 @@ @@ -24,12 +24,13 @@
24 # - gammalib 24 # - gammalib
25 # - pyroot 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 import gammalib 29 import gammalib
29 from datetime import datetime 30 from datetime import datetime
30 import math 31 import math
31 -import sys  
32 -import glob 32 +#import sys
  33 +#import glob
33 import os 34 import os
34 35
35 36
pyext/ctool.i
@@ -87,6 +87,7 @@ public: @@ -87,6 +87,7 @@ public:
87 %rename(_read_ahead) read_ahead() const; 87 %rename(_read_ahead) read_ahead() const;
88 %rename(_time_reference) time_reference() const; 88 %rename(_time_reference) time_reference() const;
89 %rename(_get_observations) get_observations(const bool& get_response = true); 89 %rename(_get_observations) get_observations(const bool& get_response = true);
  90 + %rename(_setup_observations) setup_observations(GObservations& obs);
90 %rename(_create_ebounds) create_ebounds(); 91 %rename(_create_ebounds) create_ebounds();
91 %rename(_create_map) create_map(const GObservations& obs); 92 %rename(_create_map) create_map(const GObservations& obs);
92 %rename(_create_cube) create_cube(const GObservations& obs); 93 %rename(_create_cube) create_cube(const GObservations& obs);
@@ -105,6 +106,7 @@ public: @@ -105,6 +106,7 @@ public:
105 const bool& read_ahead(void) const; 106 const bool& read_ahead(void) const;
106 const GTimeReference& time_reference(void) const; 107 const GTimeReference& time_reference(void) const;
107 GObservations get_observations(const bool& get_response = true); 108 GObservations get_observations(const bool& get_response = true);
  109 + void setup_observations(GObservations& obs);
108 110
109 // Protected methods that create objects from user parameters 111 // Protected methods that create objects from user parameters
110 GEbounds create_ebounds(void); 112 GEbounds create_ebounds(void);
@@ -170,14 +172,15 @@ public: @@ -170,14 +172,15 @@ public:
170 172
171 # Initialise observation container from constructor arguments. In case that 173 # Initialise observation container from constructor arguments. In case that
172 # an observation container is provided as argument, this container will be 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 def _set_input_obs(self, argv): 177 def _set_input_obs(self, argv):
175 if len(argv) > 0 and isinstance(argv[0],gammalib.GObservations): 178 if len(argv) > 0 and isinstance(argv[0],gammalib.GObservations):
176 obs = argv[0] 179 obs = argv[0]
177 argv = argv[1:] 180 argv = argv[1:]
178 else: 181 else:
179 obs = gammalib.GObservations() 182 obs = gammalib.GObservations()
180 - return obs 183 + return (obs, argv)
181 cscript._set_input_obs = _set_input_obs 184 cscript._set_input_obs = _set_input_obs
182 185
183 # Initialise application by calling the appropriate class constructor. 186 # Initialise application by calling the appropriate class constructor.
pyext/setup.py.in
1 ############################################################################# 1 #############################################################################
2 # Disutils setup file for ctools Python extension module # 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 # This program is free software: you can redistribute it and/or modify # 7 # This program is free software: you can redistribute it and/or modify #
@@ -27,35 +27,35 @@ import sys @@ -27,35 +27,35 @@ import sys
27 # Detect execution mode 27 # Detect execution mode
28 is_build = True 28 is_build = True
29 if (len(sys.argv) >= 2): 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 if is_build: 32 if is_build:
33 - sys.stdout.write("Python extension module building:\n") 33 + sys.stdout.write("Python extension module building:\n")
34 else: 34 else:
35 - sys.stdout.write("Python extension module installation:\n") 35 + sys.stdout.write("Python extension module installation:\n")
36 36
37 # Darwin MacPorts kluge: Remove -L/opt/local/lib path from LDSHARED as this 37 # Darwin MacPorts kluge: Remove -L/opt/local/lib path from LDSHARED as this
38 # overrides the GammaLib settings. Otherwise, MacPorts libraries would be 38 # overrides the GammaLib settings. Otherwise, MacPorts libraries would be
39 # used instead of the libraries selected by GammaLib 39 # used instead of the libraries selected by GammaLib
40 if sys.platform.lower().startswith("darwin"): 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 # Set default include directories and data files 60 # Set default include directories and data files
61 include_dirs = ['@prefix@/include/gammalib'] 61 include_dirs = ['@prefix@/include/gammalib']
@@ -66,8 +66,8 @@ libraries = [&#39;ctools&#39;,&#39;gamma&#39;] @@ -66,8 +66,8 @@ libraries = [&#39;ctools&#39;,&#39;gamma&#39;]
66 66
67 # Add install directory to runtime library path 67 # Add install directory to runtime library path
68 if os.path.exists('@prefix@/lib'): 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 # Add application include files. The method we use here is not very 72 # Add application include files. The method we use here is not very
73 # intelligent as it simple will add all names that start with 'ct' 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,44 +75,49 @@ if os.path.exists(&#39;@prefix@/lib&#39;):
75 # add an explicit filter to avoid appending those. 75 # add an explicit filter to avoid appending those.
76 dirs = glob.glob('../src/ct*') 76 dirs = glob.glob('../src/ct*')
77 for dir in dirs: 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 include_dirs.append(os.path.abspath('../src/support')) 81 include_dirs.append(os.path.abspath('../src/support'))
82 82
83 # Add extra libraries 83 # Add extra libraries
84 extra_libs = ('@PYTHON_EXTRA_LIBS@').split(',') 84 extra_libs = ('@PYTHON_EXTRA_LIBS@').split(',')
85 for extra_lib in extra_libs: 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 # Get extra library paths 89 # Get extra library paths
90 extra_lib_paths = ('@LDFLAGS@').split(' ') 90 extra_lib_paths = ('@LDFLAGS@').split(' ')
91 for extra_lib_path in extra_lib_paths: 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 # Get extra include directories 98 # Get extra include directories
99 extra_include_dirs = ('@CPPFLAGS@').split(' ') 99 extra_include_dirs = ('@CPPFLAGS@').split(' ')
100 for extra_include_dir in extra_include_dirs: 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 # Set data files to install. 106 # Set data files to install.
107 data_files=[('@prefix@/share/ctools/swig', install_files)] 107 data_files=[('@prefix@/share/ctools/swig', install_files)]
108 108
109 # Optionally enable OpenMP 109 # Optionally enable OpenMP
110 if '@OPENMP_TRUE@' != '#': 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 else: 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 # Optionally add link flag for El Capitan post-processing of modules 122 # Optionally add link flag for El Capitan post-processing of modules
118 if '@IS_ELCAPITAN_TRUE@' != '#': 123 if '@IS_ELCAPITAN_TRUE@' != '#':
@@ -133,25 +138,25 @@ setup(name=&#39;@PACKAGE_NAME@&#39;, @@ -133,25 +138,25 @@ setup(name=&#39;@PACKAGE_NAME@&#39;,
133 runtime_library_dirs=runtime_library_dirs, 138 runtime_library_dirs=runtime_library_dirs,
134 extra_compile_args=extra_compile_args, 139 extra_compile_args=extra_compile_args,
135 extra_link_args=extra_link_args)], 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 # Post-processing. A symbolic link is created to the directory containing the 147 # Post-processing. A symbolic link is created to the directory containing the
143 # shared wrapper libraries so that we can add this directory to the PYTHONPATH 148 # shared wrapper libraries so that we can add this directory to the PYTHONPATH
144 # for testing. 149 # for testing.
145 if is_build: 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,7 +62,7 @@ ctbin::ctbin(void) : ctool(CTBIN_NAME, CTBIN_VERSION)
62 62
63 // Return 63 // Return
64 return; 64 return;
65 -} 65 +} // GCOV_EXCL_LINE
66 66
67 67
68 /***********************************************************************//** 68 /***********************************************************************//**
src/support/ctool.cpp
@@ -49,6 +49,7 @@ @@ -49,6 +49,7 @@
49 49
50 50
51 /* __ Method name definitions ____________________________________________ */ 51 /* __ Method name definitions ____________________________________________ */
  52 +#define G_SETUP_OBSERVATION "ctool::setup_observations(GObservations&)"
52 #define G_GET_MEAN_POINTING "ctool::get_mean_pointing(GObservations&)" 53 #define G_GET_MEAN_POINTING "ctool::get_mean_pointing(GObservations&)"
53 #define G_CREATE_EBOUNDS "ctool::create_ebounds()" 54 #define G_CREATE_EBOUNDS "ctool::create_ebounds()"
54 #define G_PROVIDE_HELP "ctool::provide_help()" 55 #define G_PROVIDE_HELP "ctool::provide_help()"
@@ -378,7 +379,98 @@ GObservations ctool::get_observations(const bool&amp; get_response) @@ -378,7 +379,98 @@ GObservations ctool::get_observations(const bool&amp; get_response)
378 379
379 // Return observation container 380 // Return observation container
380 return obs; 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,15 +687,16 @@ GCTAEventCube ctool::create_cube(const GObservations&amp; obs)
595 * method furthermore sets the ontime, livetime and deadtime correction 687 * method furthermore sets the ontime, livetime and deadtime correction
596 * factor. 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 GCTAObservation ctool::create_cta_obs(void) 701 GCTAObservation ctool::create_cta_obs(void)
609 { 702 {
@@ -804,12 +897,9 @@ void ctool::require_inobs_nocube(const std::string&amp; method) @@ -804,12 +897,9 @@ void ctool::require_inobs_nocube(const std::string&amp; method)
804 * 897 *
805 * @param[in,out] obs Observation container 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 void ctool::set_response(GObservations& obs) 904 void ctool::set_response(GObservations& obs)
815 { 905 {
@@ -841,69 +931,83 @@ void ctool::set_response(GObservations&amp; obs) @@ -841,69 +931,83 @@ void ctool::set_response(GObservations&amp; obs)
841 * 931 *
842 * @param[in,out] obs CTA observation 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 * a counts cube the method first attempts to set the response information 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 void ctool::set_obs_response(GCTAObservation* obs) 958 void ctool::set_obs_response(GCTAObservation* obs)
858 { 959 {
859 // Initialise response flag 960 // Initialise response flag
860 bool has_response = false; 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 if (dynamic_cast<const GCTAEventCube*>(obs->events()) != NULL) { 966 if (dynamic_cast<const GCTAEventCube*>(obs->events()) != NULL) {
865 if (has_par("expcube") && has_par("psfcube") && 967 if (has_par("expcube") && has_par("psfcube") &&
866 has_par("edispcube") && has_par("bkgcube")) { 968 has_par("edispcube") && has_par("bkgcube")) {
867 969
868 // Get filenames 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 // Get exposure, PSF and background cubes 984 // Get exposure, PSF and background cubes
882 GCTACubeExposure exposure(expcube); 985 GCTACubeExposure exposure(expcube);
883 GCTACubePsf psf(psfcube); 986 GCTACubePsf psf(psfcube);
884 GCTACubeBackground background(bkgcube); 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 GCTACubeEdisp edisp(edispcube); 994 GCTACubeEdisp edisp(edispcube);
890 obs->response(exposure, psf, edisp, background); 995 obs->response(exposure, psf, edisp, background);
891 } 996 }
892 else { 997 else {
893 - // Set reponse  
894 obs->response(exposure, psf, background); 998 obs->response(exposure, psf, background);
895 } 999 }
896 1000
897 - // Signal response availability 1001 + // Signal that response is available
898 has_response = true; 1002 has_response = true;
899 1003
900 } // endif: filenames were available 1004 } // endif: filenames were available
901 1005
902 - } // endif: expcube and psfcube parameters exist 1006 + } // endif: expcube, psfcube and bkdcube parameters valid
903 } // endif: observation contains a counts cube 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 if (!has_response) { 1011 if (!has_response) {
908 1012
909 // Load response information 1013 // Load response information
@@ -938,59 +1042,70 @@ void ctool::set_obs_response(GCTAObservation* obs) @@ -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 * @param[in,out] obs Observation container 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 void ctool::set_obs_bounds(GObservations& obs) 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 for (int i = 0; i < obs.size(); ++i) { 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 GCTAObservation* cta = dynamic_cast<GCTAObservation*>(obs[i]); 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 } // endfor: looped over observations 1110 } // endfor: looped over observations
996 1111
src/support/ctool.hpp
@@ -72,6 +72,7 @@ protected: @@ -72,6 +72,7 @@ protected:
72 const bool& read_ahead(void) const; 72 const bool& read_ahead(void) const;
73 const GTimeReference& time_reference(void) const; 73 const GTimeReference& time_reference(void) const;
74 GObservations get_observations(const bool& get_response = true); 74 GObservations get_observations(const bool& get_response = true);
  75 + void setup_observations(GObservations& obs);
75 76
76 // Protected methods that create objects from user parameters 77 // Protected methods that create objects from user parameters
77 GEbounds create_ebounds(void); 78 GEbounds create_ebounds(void);
test/test_cscaldb.py
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # 19 #
20 # ========================================================================== 20 # ==========================================================================
  21 +import os
21 import gammalib 22 import gammalib
22 import cscripts 23 import cscripts
23 24
@@ -28,7 +29,11 @@ import cscripts @@ -28,7 +29,11 @@ import cscripts
28 class Test(gammalib.GPythonTestSuite): 29 class Test(gammalib.GPythonTestSuite):
29 """ 30 """
30 Test class for cscaldb script. 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 # Constructor 37 # Constructor
33 def __init__(self): 38 def __init__(self):
34 """ 39 """
@@ -49,15 +54,15 @@ class Test(gammalib.GPythonTestSuite): @@ -49,15 +54,15 @@ class Test(gammalib.GPythonTestSuite):
49 self.name("cscaldb") 54 self.name("cscaldb")
50 55
51 # Append tests 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 # Return 59 # Return
55 return 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 # Set-up cscaldb 67 # Set-up cscaldb
63 caldb = cscripts.cscaldb() 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 #! /usr/bin/env python 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 # Copyright (C) 2014-2016 Juergen Knoedlseder 5 # Copyright (C) 2014-2016 Juergen Knoedlseder
6 # 6 #
@@ -18,16 +18,20 @@ @@ -18,16 +18,20 @@
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # 19 #
20 # ========================================================================== 20 # ==========================================================================
  21 +import os
21 import gammalib 22 import gammalib
22 import ctools 23 import ctools
23 24
24 25
25 -# =========================== #  
26 -# Test class for ctbin module #  
27 -# =========================== # 26 +# ========================= #
  27 +# Test class for ctbin tool #
  28 +# ========================= #
28 class Test(gammalib.GPythonTestSuite): 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 # Constructor 37 # Constructor
@@ -53,15 +57,68 @@ class Test(gammalib.GPythonTestSuite): @@ -53,15 +57,68 @@ class Test(gammalib.GPythonTestSuite):
53 self.name("ctbin") 57 self.name("ctbin")
54 58
55 # Append tests 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 # Return 63 # Return
59 return 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 # Set-up ctbin 123 # Set-up ctbin
67 bin = ctools.ctbin() 124 bin = ctools.ctbin()
@@ -83,15 +140,15 @@ class Test(gammalib.GPythonTestSuite): @@ -83,15 +140,15 @@ class Test(gammalib.GPythonTestSuite):
83 bin.run() 140 bin.run()
84 141
85 # Check content of observation and cube 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 # Test copy constructor 146 # Test copy constructor
90 cpy_bin = bin.copy() 147 cpy_bin = bin.copy()
91 148
92 # Check content of observation and cube 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 # Run copy of ctbin tool again 153 # Run copy of ctbin tool again
97 cpy_bin.run() 154 cpy_bin.run()
@@ -100,8 +157,8 @@ class Test(gammalib.GPythonTestSuite): @@ -100,8 +157,8 @@ class Test(gammalib.GPythonTestSuite):
100 # event cube as on input the observation is binned, and any binned 157 # event cube as on input the observation is binned, and any binned
101 # observation will be skipped, hence the counts cube should be 158 # observation will be skipped, hence the counts cube should be
102 # empty. 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 # Clear and run copy of ctbin again 163 # Clear and run copy of ctbin again
107 #cpy_bin.clear() 164 #cpy_bin.clear()
@@ -115,7 +172,7 @@ class Test(gammalib.GPythonTestSuite): @@ -115,7 +172,7 @@ class Test(gammalib.GPythonTestSuite):
115 172
116 # Load counts cube and check content. 173 # Load counts cube and check content.
117 evt = gammalib.GCTAEventCube("cntmap.fits") 174 evt = gammalib.GCTAEventCube("cntmap.fits")
118 - self._test_cube(evt, 5542) 175 + self._check_cube(evt, 5542)
119 176
120 # Prepare observation container for stacked analysis 177 # Prepare observation container for stacked analysis
121 cta = gammalib.GCTAObservation(self._events_name) 178 cta = gammalib.GCTAObservation(self._events_name)
@@ -147,13 +204,12 @@ class Test(gammalib.GPythonTestSuite): @@ -147,13 +204,12 @@ class Test(gammalib.GPythonTestSuite):
147 204
148 # Check content of observation and cube (need multiplier=3 since 205 # Check content of observation and cube (need multiplier=3 since
149 # three identical observations have been appended) 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 bin["ebinalg"] = "LOG" 213 bin["ebinalg"] = "LOG"
158 bin["emin"] = 0.1 214 bin["emin"] = 0.1
159 bin["emax"] = 100.0 215 bin["emax"] = 100.0
@@ -166,21 +222,29 @@ class Test(gammalib.GPythonTestSuite): @@ -166,21 +222,29 @@ class Test(gammalib.GPythonTestSuite):
166 bin["xref"] = 83.63 222 bin["xref"] = 83.63
167 bin["yref"] = 22.01 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 # Return 241 # Return
178 return 242 return
179 243
180 # Check observation 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 Args: 249 Args:
186 ctbin: ctbin instance 250 ctbin: ctbin instance
@@ -206,15 +270,15 @@ class Test(gammalib.GPythonTestSuite): @@ -206,15 +270,15 @@ class Test(gammalib.GPythonTestSuite):
206 "Pointing Declination is 22.01 deg") 270 "Pointing Declination is 22.01 deg")
207 271
208 # Test event cube 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 # Return 275 # Return
212 return 276 return
213 277
214 # Check event cube 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 Args: 283 Args:
220 cube: Event cube 284 cube: Event cube
test/test_ctobssim.py
1 #! /usr/bin/env python 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 # Copyright (C) 2014-2016 Juergen Knoedlseder 5 # Copyright (C) 2014-2016 Juergen Knoedlseder
6 # 6 #
@@ -18,17 +18,21 @@ @@ -18,17 +18,21 @@
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # 19 #
20 # ========================================================================== 20 # ==========================================================================
  21 +import os
21 import gammalib 22 import gammalib
22 import ctools 23 import ctools
23 from cscripts import obsutils 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 class Test(gammalib.GPythonTestSuite): 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 # Constructor 38 # Constructor
@@ -56,16 +60,67 @@ class Test(gammalib.GPythonTestSuite): @@ -56,16 +60,67 @@ class Test(gammalib.GPythonTestSuite):
56 self.name("ctobssim") 60 self.name("ctobssim")
57 61
58 # Append tests 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 # Return 66 # Return
63 return 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 # Set-up ctobssim 125 # Set-up ctobssim
71 sim = ctools.ctobssim() 126 sim = ctools.ctobssim()
test/test_python_cscripts.py
@@ -18,12 +18,13 @@ @@ -18,12 +18,13 @@
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # 19 #
20 # ========================================================================== 20 # ==========================================================================
  21 +import os
  22 +import sys
21 import gammalib 23 import gammalib
22 import cscripts 24 import cscripts
23 -import sys  
24 -import os  
25 sys.path.append(os.path.dirname(os.path.abspath(__file__))) 25 sys.path.append(os.path.dirname(os.path.abspath(__file__)))
26 import test_cscaldb 26 import test_cscaldb
  27 +import test_cslightcrv
27 28
28 29
29 # ================== # 30 # ================== #
@@ -37,13 +38,16 @@ def test(installed=False): @@ -37,13 +38,16 @@ def test(installed=False):
37 suites = gammalib.GTestSuites("cscripts Python module unit testing") 38 suites = gammalib.GTestSuites("cscripts Python module unit testing")
38 39
39 # Allocate test suites and append them to the container 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 # Setup unit tests 44 # Setup unit tests
43 suite_cscaldb.set() 45 suite_cscaldb.set()
  46 + suite_cslightcrv.set()
44 47
45 # Append tests to container 48 # Append tests to container
46 suites.append(suite_cscaldb) 49 suites.append(suite_cscaldb)
  50 + suites.append(suite_cslightcrv)
47 51
48 # If we have an installed version then create a temporary directory and 52 # If we have an installed version then create a temporary directory and
49 # copy over all information that is needed 53 # copy over all information that is needed
@@ -60,9 +64,13 @@ def test(installed=False): @@ -60,9 +64,13 @@ def test(installed=False):
60 dirname = os.path.dirname(testdir) 64 dirname = os.path.dirname(testdir)
61 65
62 # Copy over test data and irf 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 #os.system("cp -r %s %s" % (dirname+"/irf", "irf")) 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 # Set PFILES environment variable 74 # Set PFILES environment variable
67 try: 75 try:
68 os.mkdir("pfiles") 76 os.mkdir("pfiles")
@@ -97,8 +105,6 @@ def test(installed=False): @@ -97,8 +105,6 @@ def test(installed=False):
97 # Main routine entry point # 105 # Main routine entry point #
98 # ======================== # 106 # ======================== #
99 if __name__ == '__main__': 107 if __name__ == '__main__':
100 - """  
101 - Perform unit testing for cscripts used from Python.  
102 - """ 108 +
103 # Run tests 109 # Run tests
104 test() 110 test()
test/test_python_ctools.py
@@ -40,15 +40,15 @@ import test_cterror @@ -40,15 +40,15 @@ import test_cterror
40 import test_pipelines 40 import test_pipelines
41 41
42 42
43 -# ================== #  
44 -# Perform unit tests #  
45 -# ================== # 43 +# ========================= #
  44 +# Perform ctools unit tests #
  45 +# ========================= #
46 def test(installed=False): 46 def test(installed=False):
47 """ 47 """
48 - Perform unit testing for Python interface. 48 + Perform unit testing for ctools.
49 """ 49 """
50 # Allocate test suite container 50 # Allocate test suite container
51 - suites = gammalib.GTestSuites("ctools Python module unit testing") 51 + suites = gammalib.GTestSuites("ctools unit testing")
52 52
53 # Allocate test suites and append them to the container 53 # Allocate test suites and append them to the container
54 suite_ctobssim = test_ctobssim.Test() 54 suite_ctobssim = test_ctobssim.Test()
@@ -153,8 +153,6 @@ def test(installed=False): @@ -153,8 +153,6 @@ def test(installed=False):
153 # Main routine entry point # 153 # Main routine entry point #
154 # ======================== # 154 # ======================== #
155 if __name__ == '__main__': 155 if __name__ == '__main__':
156 - """  
157 - Perform unit testing for Python interface.  
158 - """ 156 +
159 # Run tests 157 # Run tests
160 test() 158 test()