Commit 59d3205fd82194ed570ced239171e9d7020b9e81
Merge branch '3510-test-rst' into integration
Showing
22 changed files
with
1021 additions
and
147 deletions
.gitignore
| @@ -99,6 +99,7 @@ test/butterfly.txt | @@ -99,6 +99,7 @@ test/butterfly.txt | ||
| 99 | test/.coverage | 99 | test/.coverage |
| 100 | test/test_python_ctools.sh | 100 | test/test_python_ctools.sh |
| 101 | test/test_python_cscripts.sh | 101 | test/test_python_cscripts.sh |
| 102 | +test/tutorials | ||
| 102 | examples/*.fits | 103 | examples/*.fits |
| 103 | examples/*.xml | 104 | examples/*.xml |
| 104 | examples/*.dat | 105 | examples/*.dat |
ChangeLog
| 1 | -2020-12-03 | 1 | +2020-02-03 |
| 2 | 2 | ||
| 3 | * Version 2.0.0 released | 3 | * Version 2.0.0 released |
| 4 | ======================== | 4 | ======================== |
| 5 | 5 | ||
| 6 | + Add Sphinx tutorials test script (#3510) | ||
| 6 | Add "refit_if_failed" parameter to ctlike | 7 | Add "refit_if_failed" parameter to ctlike |
| 7 | Add models() method to ctobssim (#3441) | 8 | Add models() method to ctobssim (#3441) |
| 8 | Add ctlike results to XML file (#3431) | 9 | Add ctlike results to XML file (#3431) |
Makefile.am
| 1 | ############################################################################# | 1 | ############################################################################# |
| 2 | # Makefile for ctools package # | 2 | # Makefile for ctools package # |
| 3 | # ------------------------------------------------------------------------- # | 3 | # ------------------------------------------------------------------------- # |
| 4 | -# Copyright (C) 2016-2017 Juergen Knoedlseder # | 4 | +# Copyright (C) 2016-2021 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 # |
| @@ -211,13 +211,23 @@ valgrind: | @@ -211,13 +211,23 @@ valgrind: | ||
| 211 | # Add science verification rule | 211 | # Add science verification rule |
| 212 | science-verification: | 212 | science-verification: |
| 213 | @if type test/science_verification.py >/dev/null 2>&1; then \ | 213 | @if type test/science_verification.py >/dev/null 2>&1; then \ |
| 214 | - cd test; \ | ||
| 215 | - ./science_verification.py; \ | ||
| 216 | - cd ..; \ | 214 | + cd test; \ |
| 215 | + ./science_verification.py; \ | ||
| 216 | + cd ..; \ | ||
| 217 | else \ | 217 | else \ |
| 218 | echo "science_verification.py not found in test."; \ | 218 | echo "science_verification.py not found in test."; \ |
| 219 | fi | 219 | fi |
| 220 | 220 | ||
| 221 | +# Add tutorials verification rule | ||
| 222 | +check-tutorials: | ||
| 223 | + @if type test/tutorials.py >/dev/null 2>&1; then \ | ||
| 224 | + cd test; \ | ||
| 225 | + ./tutorials.py; \ | ||
| 226 | + cd ..; \ | ||
| 227 | + else \ | ||
| 228 | + echo "tutorials.py not found in test."; \ | ||
| 229 | + fi | ||
| 230 | + | ||
| 221 | # Add Sphinx rule | 231 | # Add Sphinx rule |
| 222 | sphinx: | 232 | sphinx: |
| 223 | @if type sphinx-build >/dev/null 2>&1; then \ | 233 | @if type sphinx-build >/dev/null 2>&1; then \ |
NEWS
| 1 | New Features and Important Changes in ctools 2.0.0 | 1 | New Features and Important Changes in ctools 2.0.0 |
| 2 | 2 | ||
| 3 | -3 December 2020 | 3 | +3 February 2021 |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | Introduction | 6 | Introduction |
| @@ -16,7 +16,8 @@ None | @@ -16,7 +16,8 @@ None | ||
| 16 | 16 | ||
| 17 | Documentation | 17 | Documentation |
| 18 | ------------- | 18 | ------------- |
| 19 | -None | 19 | +Add test/tutorials.py script and check-tutorial target to test the code in the |
| 20 | +Sphinx tutorials (#3510). | ||
| 20 | 21 | ||
| 21 | 22 | ||
| 22 | Python interface | 23 | Python interface |
README.md
| 1 | ctools information | 1 | ctools information |
| 2 | ================== | 2 | ================== |
| 3 | -* Version: 2.0.0.dev (3 December 2020) | 3 | +* Version: 2.0.0.dev (3 February 2021) |
| 4 | * GammaLib dependency: 2.0.0.dev | 4 | * GammaLib dependency: 2.0.0.dev |
| 5 | 5 | ||
| 6 | [](https://cta-jenkins.irap.omp.eu/job/ctools-integrate-os/) | 6 | [](https://cta-jenkins.irap.omp.eu/job/ctools-integrate-os/) |
cscripts/csspec.py
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | # ========================================================================== | 2 | # ========================================================================== |
| 3 | # Generates a spectrum. | 3 | # Generates a spectrum. |
| 4 | # | 4 | # |
| 5 | -# Copyright (C) 2014-2020 Michael Mayer | 5 | +# Copyright (C) 2014-2021 Michael Mayer |
| 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 |
| 8 | # it under the terms of the GNU General Public License as published by | 8 | # it under the terms of the GNU General Public License as published by |
| @@ -1071,7 +1071,7 @@ class csspec(ctools.csobservation): | @@ -1071,7 +1071,7 @@ class csspec(ctools.csobservation): | ||
| 1071 | energy_high = gammalib.GFitsTableDoubleCol('e_max', nrows) | 1071 | energy_high = gammalib.GFitsTableDoubleCol('e_max', nrows) |
| 1072 | norm = gammalib.GFitsTableDoubleCol('norm', nrows) | 1072 | norm = gammalib.GFitsTableDoubleCol('norm', nrows) |
| 1073 | norm_err = gammalib.GFitsTableDoubleCol('norm_err', nrows) | 1073 | norm_err = gammalib.GFitsTableDoubleCol('norm_err', nrows) |
| 1074 | - ulim_values = gammalib.GFitsTableDoubleCol('norm_ul', nrows) | 1074 | + norm_ul = gammalib.GFitsTableDoubleCol('norm_ul', nrows) |
| 1075 | e2dnde = gammalib.GFitsTableDoubleCol('ref_e2dnde', nrows) | 1075 | e2dnde = gammalib.GFitsTableDoubleCol('ref_e2dnde', nrows) |
| 1076 | dnde = gammalib.GFitsTableDoubleCol('ref_dnde', nrows) | 1076 | dnde = gammalib.GFitsTableDoubleCol('ref_dnde', nrows) |
| 1077 | Npred_values = gammalib.GFitsTableDoubleCol('ref_npred', nrows) | 1077 | Npred_values = gammalib.GFitsTableDoubleCol('ref_npred', nrows) |
| @@ -1084,7 +1084,7 @@ class csspec(ctools.csobservation): | @@ -1084,7 +1084,7 @@ class csspec(ctools.csobservation): | ||
| 1084 | energy_high.unit('TeV') | 1084 | energy_high.unit('TeV') |
| 1085 | norm.unit('') | 1085 | norm.unit('') |
| 1086 | norm_err.unit('') | 1086 | norm_err.unit('') |
| 1087 | - ulim_values.unit('') | 1087 | + norm_ul.unit('') |
| 1088 | e2dnde.unit('erg/cm2/s') | 1088 | e2dnde.unit('erg/cm2/s') |
| 1089 | dnde.unit('counts/MeV/cm2/s') | 1089 | dnde.unit('counts/MeV/cm2/s') |
| 1090 | Npred_values.unit('counts') | 1090 | Npred_values.unit('counts') |
| @@ -1098,8 +1098,12 @@ class csspec(ctools.csobservation): | @@ -1098,8 +1098,12 @@ class csspec(ctools.csobservation): | ||
| 1098 | energy_low[i] = result['energy_low'] | 1098 | energy_low[i] = result['energy_low'] |
| 1099 | energy_high[i] = result['energy_high'] | 1099 | energy_high[i] = result['energy_high'] |
| 1100 | norm[i] = 1.0 | 1100 | norm[i] = 1.0 |
| 1101 | - norm_err[i] = result['flux_err'] / result['flux'] | ||
| 1102 | - ulim_values[i] = result['ulimit'] / result['flux'] | 1101 | + if result['flux'] != 0.0: |
| 1102 | + norm_err[i] = result['flux_err'] / result['flux'] | ||
| 1103 | + norm_ul[i] = result['ulimit'] / result['flux'] | ||
| 1104 | + else: | ||
| 1105 | + norm_err[i] = 0.0 | ||
| 1106 | + norm_ul[i] = 0.0 | ||
| 1103 | e2dnde[i] = result['e2dnde'] | 1107 | e2dnde[i] = result['e2dnde'] |
| 1104 | dnde[i] = result['flux'] | 1108 | dnde[i] = result['flux'] |
| 1105 | Npred_values[i] = result['Npred'] | 1109 | Npred_values[i] = result['Npred'] |
| @@ -1109,7 +1113,10 @@ class csspec(ctools.csobservation): | @@ -1109,7 +1113,10 @@ class csspec(ctools.csobservation): | ||
| 1109 | # Add likelihood scan values | 1113 | # Add likelihood scan values |
| 1110 | for fbin in range(ncols): | 1114 | for fbin in range(ncols): |
| 1111 | dloglike_scan[i,fbin] = result['dloglike'][fbin] | 1115 | dloglike_scan[i,fbin] = result['dloglike'][fbin] |
| 1112 | - norm_scan[i,fbin] = result['norm_scan'][fbin] / result['flux'] | 1116 | + if result['flux'] != 0.0: |
| 1117 | + norm_scan[i,fbin] = result['norm_scan'][fbin] / result['flux'] | ||
| 1118 | + else: | ||
| 1119 | + norm_scan[i,fbin] = 0.0 | ||
| 1113 | 1120 | ||
| 1114 | # Initialise FITS Table with extension "SPECTRUM" | 1121 | # Initialise FITS Table with extension "SPECTRUM" |
| 1115 | table = gammalib.GFitsBinTable(nrows) | 1122 | table = gammalib.GFitsBinTable(nrows) |
| @@ -1125,7 +1132,7 @@ class csspec(ctools.csobservation): | @@ -1125,7 +1132,7 @@ class csspec(ctools.csobservation): | ||
| 1125 | table.append(energy_high) | 1132 | table.append(energy_high) |
| 1126 | table.append(norm) | 1133 | table.append(norm) |
| 1127 | table.append(norm_err) | 1134 | table.append(norm_err) |
| 1128 | - table.append(ulim_values) | 1135 | + table.append(norm_ul) |
| 1129 | table.append(e2dnde) | 1136 | table.append(e2dnde) |
| 1130 | table.append(dnde) | 1137 | table.append(dnde) |
| 1131 | table.append(TSvalues) | 1138 | table.append(TSvalues) |
cscripts/cstsmapsplit.py
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | # ========================================================================== | 2 | # ========================================================================== |
| 3 | # Create commands to split TS map computation | 3 | # Create commands to split TS map computation |
| 4 | # | 4 | # |
| 5 | -# Copyright (C) 2016-2019 Michael Mayer | 5 | +# Copyright (C) 2016-2021 Michael Mayer |
| 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 |
| 8 | # it under the terms of the GNU General Public License as published by | 8 | # it under the terms of the GNU General Public License as published by |
| @@ -247,6 +247,9 @@ class cstsmapsplit(ctools.cslikelihood): | @@ -247,6 +247,9 @@ class cstsmapsplit(ctools.cslikelihood): | ||
| 247 | for cmd in self._cmd: | 247 | for cmd in self._cmd: |
| 248 | f.write(cmd + '\n') | 248 | f.write(cmd + '\n') |
| 249 | 249 | ||
| 250 | + # Add wait statement | ||
| 251 | + f.write('wait\n') | ||
| 252 | + | ||
| 250 | # Close file | 253 | # Close file |
| 251 | f.close() | 254 | f.close() |
| 252 | 255 |
doc/source/users/tutorials/1dc/CasA_model.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | +<source_library title="source library"> | ||
| 3 | + <source name="Cassiopeia A" type="PointSource"> | ||
| 4 | + <spectrum type="PowerLaw"> | ||
| 5 | + <parameter name="Prefactor" value="1.45" scale="1e-18" min="0" free="1"/> | ||
| 6 | + <parameter name="Index" value="2.75" scale="-1" min="-10" max="10" free="1"/> | ||
| 7 | + <parameter name="PivotEnergy" value="1" scale="1e6" free="0"/> | ||
| 8 | + </spectrum> | ||
| 9 | + <spatialModel type="PointSource"> | ||
| 10 | + <parameter name="RA" value="350.8500" scale="1" free="0"/> | ||
| 11 | + <parameter name="DEC" value="58.8150" scale="1" free="0"/> | ||
| 12 | + </spatialModel> | ||
| 13 | + </source> | ||
| 14 | + <source name="Background model" type="CTAIrfBackground" instrument="CTA"> | ||
| 15 | + <spectrum type="PowerLaw"> | ||
| 16 | + <parameter name="Prefactor" value="1" scale="1" min="0.001" max="1000" free="1"/> | ||
| 17 | + <parameter name="Index" value="0" scale="1" min="-5" max="5" free="1"/> | ||
| 18 | + <parameter name="Scale" value="1" scale="1e6" min="0.01" max="1000" free="0"/> | ||
| 19 | + </spectrum> | ||
| 20 | + </source> | ||
| 21 | +</source_library> |
doc/source/users/tutorials/1dc/first_fitting.rst
| @@ -39,7 +39,7 @@ You run the :ref:`ctlike` tool as follows: | @@ -39,7 +39,7 @@ You run the :ref:`ctlike` tool as follows: | ||
| 39 | Input model definition XML file [$CTOOLS/share/models/crab.xml] bkgcube.xml | 39 | Input model definition XML file [$CTOOLS/share/models/crab.xml] bkgcube.xml |
| 40 | Output model definition XML file [crab_results.xml] results_stacked.xml | 40 | Output model definition XML file [crab_results.xml] results_stacked.xml |
| 41 | 41 | ||
| 42 | -The tool will take a few minutes (on Mac OS X) to perform the model fitting, | 42 | +The tool will take a few minutes (on Mac OS) to perform the model fitting, |
| 43 | and will write the results into an updated | 43 | and will write the results into an updated |
| 44 | :ref:`model definition file <glossary_moddef>` | 44 | :ref:`model definition file <glossary_moddef>` |
| 45 | containing the fitted model parameters and their statistical uncertainties. | 45 | containing the fitted model parameters and their statistical uncertainties. |
| @@ -124,7 +124,7 @@ You create the butterfly diagram for ``Src001`` using | @@ -124,7 +124,7 @@ You create the butterfly diagram for ``Src001`` using | ||
| 124 | Stop value for last energy bin in TeV [100.0] | 124 | Stop value for last energy bin in TeV [100.0] |
| 125 | Output ASCII file [butterfly.txt] butterfly_src001.txt | 125 | Output ASCII file [butterfly.txt] butterfly_src001.txt |
| 126 | 126 | ||
| 127 | -and for `Src003`` using | 127 | +and for ``Src003`` using |
| 128 | 128 | ||
| 129 | .. code-block:: bash | 129 | .. code-block:: bash |
| 130 | 130 | ||
| @@ -192,28 +192,14 @@ a maximum likelihood model fit. | @@ -192,28 +192,14 @@ a maximum likelihood model fit. | ||
| 192 | 192 | ||
| 193 | Obviously, ``Src001`` has a spectral cut-off (red flux points) and hence is not | 193 | Obviously, ``Src001`` has a spectral cut-off (red flux points) and hence is not |
| 194 | adequately described by a power law model. You should therefore replace the | 194 | adequately described by a power law model. You should therefore replace the |
| 195 | -power law in the | ||
| 196 | -:ref:`model definition file <glossary_moddef>` | ||
| 197 | -by an exponentially cutoff power law, as shown below: | ||
| 198 | - | ||
| 199 | -.. code-block:: xml | ||
| 200 | - | ||
| 201 | - <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 202 | - <source_library title="source library"> | ||
| 203 | - <source name="Src001" type="PointSource"> | ||
| 204 | - <spectrum type="ExponentialCutoffPowerLaw"> | ||
| 205 | - <parameter name="Prefactor" scale="1e-18" value="5.7" min="1e-07" max="1000.0" free="1"/> | ||
| 206 | - <parameter name="Index" scale="-1" value="2.48" min="0.0" max="+5.0" free="1"/> | ||
| 207 | - <parameter name="CutoffEnergy" scale="1e7" value="1.0" min="0.01" max="1000.0" free="1"/> | ||
| 208 | - <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/> | ||
| 209 | - </spectrum> | ||
| 210 | - <spatialModel type="PointSource"> | ||
| 211 | - <parameter name="RA" value="266.424004498437" scale="1" free="1" /> | ||
| 212 | - <parameter name="DEC" value="-29.0049010253548" scale="1" free="1" /> | ||
| 213 | - </spatialModel> | ||
| 214 | - </source> | ||
| 215 | - ... | ||
| 216 | - </source_library> | 195 | +power law spectrum in the :ref:`model definition file <glossary_moddef>` |
| 196 | +by an exponentially cutoff power law spectrum, as shown below (only the first | ||
| 197 | +lines of the :ref:`model definition file <glossary_moddef>` are shown for | ||
| 198 | +illustration): | ||
| 199 | + | ||
| 200 | +.. literalinclude:: results_stacked_eplaw.xml | ||
| 201 | + :language: xml | ||
| 202 | + :lines: 1-16 | ||
| 217 | 203 | ||
| 218 | Fitting this model to the data improves the fit and the resulting butterfly | 204 | Fitting this model to the data improves the fit and the resulting butterfly |
| 219 | diagram follows now reasonably well the spectral points: | 205 | diagram follows now reasonably well the spectral points: |
doc/source/users/tutorials/1dc/first_onoff.rst
| @@ -208,6 +208,7 @@ follows: | @@ -208,6 +208,7 @@ follows: | ||
| 208 | Output observation definition XML file [onoff_obs.xml] | 208 | Output observation definition XML file [onoff_obs.xml] |
| 209 | Output model definition XML file [onoff_model.xml] | 209 | Output model definition XML file [onoff_model.xml] |
| 210 | Method for background estimation (REFLECTED|CUSTOM) [REFLECTED] | 210 | Method for background estimation (REFLECTED|CUSTOM) [REFLECTED] |
| 211 | + Shape of the source region (CIRCLE|RECT) [CIRCLE] | ||
| 211 | Coordinate system (CEL - celestial, GAL - galactic) (CEL|GAL) [CEL] | 212 | Coordinate system (CEL - celestial, GAL - galactic) (CEL|GAL) [CEL] |
| 212 | Right Ascension of source region centre (deg) (0-360) [83.63] 350.85 | 213 | Right Ascension of source region centre (deg) (0-360) [83.63] 350.85 |
| 213 | Declination of source region centre (deg) (-90-90) [22.01] 58.815 | 214 | Declination of source region centre (deg) (-90-90) [22.01] 58.815 |
| @@ -355,29 +356,8 @@ The fit result can be inspected by peeking the log file: | @@ -355,29 +356,8 @@ The fit result can be inspected by peeking the log file: | ||
| 355 | provided as input model to :ref:`csphagen`. Here an example for an | 356 | provided as input model to :ref:`csphagen`. Here an example for an |
| 356 | input model: | 357 | input model: |
| 357 | 358 | ||
| 358 | - .. code-block:: xml | ||
| 359 | - | ||
| 360 | - <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 361 | - <source_library title="source library"> | ||
| 362 | - <source name="Cassiopeia A" type="PointSource"> | ||
| 363 | - <spectrum type="PowerLaw"> | ||
| 364 | - <parameter name="Prefactor" value="1.45" scale="1e-18" min="0" free="1"/> | ||
| 365 | - <parameter name="Index" value="2.75" scale="-1" min="-10" max="10" free="1"/> | ||
| 366 | - <parameter name="PivotEnergy" value="1" scale="1e6" free="0"/> | ||
| 367 | - </spectrum> | ||
| 368 | - <spatialModel type="PointSource"> | ||
| 369 | - <parameter name="RA" value="350.8500" scale="1" free="0"/> | ||
| 370 | - <parameter name="DEC" value="58.8150" scale="1" free="0"/> | ||
| 371 | - </spatialModel> | ||
| 372 | - </source> | ||
| 373 | - <source name="Background model" type="CTAIrfBackground" instrument="CTA"> | ||
| 374 | - <spectrum type="PowerLaw"> | ||
| 375 | - <parameter name="Prefactor" value="1" scale="1" min="0.001" max="1000" free="1"/> | ||
| 376 | - <parameter name="Index" value="0" scale="1" min="-5" max="5" free="1"/> | ||
| 377 | - <parameter name="Scale" value="1" scale="1e6" min="0.01" max="1000" free="0"/> | ||
| 378 | - </spectrum> | ||
| 379 | - </source> | ||
| 380 | - </source_library> | 359 | + .. literalinclude:: CasA_model.xml |
| 360 | + :language: xml | ||
| 381 | 361 | ||
| 382 | Now rerun :ref:`csphagen` as follows: | 362 | Now rerun :ref:`csphagen` as follows: |
| 383 | 363 | ||
| @@ -395,6 +375,7 @@ The fit result can be inspected by peeking the log file: | @@ -395,6 +375,7 @@ The fit result can be inspected by peeking the log file: | ||
| 395 | Output observation definition XML file [onoff_obs.xml] onoff_obs_cstat.xml | 375 | Output observation definition XML file [onoff_obs.xml] onoff_obs_cstat.xml |
| 396 | Output model definition XML file [onoff_model.xml] onoff_model_cstat.xml | 376 | Output model definition XML file [onoff_model.xml] onoff_model_cstat.xml |
| 397 | Method for background estimation (REFLECTED|CUSTOM) [REFLECTED] | 377 | Method for background estimation (REFLECTED|CUSTOM) [REFLECTED] |
| 378 | + Shape of the source region (CIRCLE|RECT) [CIRCLE] | ||
| 398 | Coordinate system (CEL - celestial, GAL - galactic) (CEL|GAL) [CEL] | 379 | Coordinate system (CEL - celestial, GAL - galactic) (CEL|GAL) [CEL] |
| 399 | Right Ascension of source region centre (deg) (0-360) [350.85] | 380 | Right Ascension of source region centre (deg) (0-360) [350.85] |
| 400 | Declination of source region centre (deg) (-90-90) [58.815] | 381 | Declination of source region centre (deg) (-90-90) [58.815] |
| @@ -452,7 +433,7 @@ Like for a binned or unbinned analysis, you can create a butterfly diagram by ty | @@ -452,7 +433,7 @@ Like for a binned or unbinned analysis, you can create a butterfly diagram by ty | ||
| 452 | 433 | ||
| 453 | $ ctbutterfly | 434 | $ ctbutterfly |
| 454 | Input event list, counts cube or observation definition XML file [events.fits] onoff_obs.xml | 435 | Input event list, counts cube or observation definition XML file [events.fits] onoff_obs.xml |
| 455 | - Source of interest [Crab] Cassiopeia A | 436 | + Source of interest [Crab] Dummy |
| 456 | Input model definition XML file [$CTOOLS/share/models/crab.xml] CasA_results.xml | 437 | Input model definition XML file [$CTOOLS/share/models/crab.xml] CasA_results.xml |
| 457 | Lower energy limit (TeV) [0.1] | 438 | Lower energy limit (TeV) [0.1] |
| 458 | Upper energy limit (TeV) [100.0] 50.0 | 439 | Upper energy limit (TeV) [100.0] 50.0 |
| @@ -465,7 +446,7 @@ and the SED by typing | @@ -465,7 +446,7 @@ and the SED by typing | ||
| 465 | $ csspec | 446 | $ csspec |
| 466 | Input event list, counts cube, or observation definition XML file [events.fits] onoff_obs.xml | 447 | Input event list, counts cube, or observation definition XML file [events.fits] onoff_obs.xml |
| 467 | Input model definition XML file [$CTOOLS/share/models/crab.xml] CasA_results.xml | 448 | Input model definition XML file [$CTOOLS/share/models/crab.xml] CasA_results.xml |
| 468 | - Source name [Crab] Cassiopeia A | 449 | + Source name [Crab] Dummy |
| 469 | Spectrum generation method (SLICE|NODES|AUTO) [AUTO] | 450 | Spectrum generation method (SLICE|NODES|AUTO) [AUTO] |
| 470 | Binning algorithm (FILE|LIN|LOG|POW) [LOG] | 451 | Binning algorithm (FILE|LIN|LOG|POW) [LOG] |
| 471 | Lower energy limit (TeV) [0.1] | 452 | Lower energy limit (TeV) [0.1] |
doc/source/users/tutorials/1dc/results_stacked_eplaw.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | +<source_library title="source library"> | ||
| 3 | + <source name="Src001" type="PointSource"> | ||
| 4 | + <spectrum type="ExponentialCutoffPowerLaw"> | ||
| 5 | + <parameter name="Prefactor" scale="1e-18" value="5.7" min="1e-07" max="1000.0" free="1"/> | ||
| 6 | + <parameter name="Index" scale="-1" value="2.48" min="0.0" max="+5.0" free="1"/> | ||
| 7 | + <parameter name="CutoffEnergy" scale="1e7" value="1.0" min="0.01" max="1000.0" free="1"/> | ||
| 8 | + <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/> | ||
| 9 | + </spectrum> | ||
| 10 | + <spatialModel type="PointSource"> | ||
| 11 | + <parameter name="RA" value="266.424004498437" scale="1" free="1"/> | ||
| 12 | + <parameter name="DEC" value="-29.0049010253548" scale="1" free="1"/> | ||
| 13 | + </spatialModel> | ||
| 14 | + </source> | ||
| 15 | + <source name="Src002" type="PointSource"> | ||
| 16 | + <spectrum type="PowerLaw"> | ||
| 17 | + <parameter name="Prefactor" value="1" scale="5.7e-18" min="0" free="1" /> | ||
| 18 | + <parameter name="Index" value="1" scale="-2.48" min="-4.03225806451613" max="4.03225806451613" free="1" /> | ||
| 19 | + <parameter name="PivotEnergy" value="1" scale="300000" free="0" /> | ||
| 20 | + </spectrum> | ||
| 21 | + <spatialModel type="PointSource"> | ||
| 22 | + <parameter name="RA" value="264.802012181975" error="0" scale="1" free="1" /> | ||
| 23 | + <parameter name="DEC" value="-31.0050720432975" error="0" scale="1" free="1" /> | ||
| 24 | + </spatialModel> | ||
| 25 | + </source> | ||
| 26 | + <source name="Src003" type="PointSource"> | ||
| 27 | + <spectrum type="PowerLaw"> | ||
| 28 | + <parameter name="Prefactor" value="1" error="0" scale="5.7e-18" min="0" free="1" /> | ||
| 29 | + <parameter name="Index" value="1" error="-0" scale="-2.48" min="-4.03225806451613" max="4.03225806451613" free="1" /> | ||
| 30 | + <parameter name="PivotEnergy" value="1" scale="300000" free="0" /> | ||
| 31 | + </spectrum> | ||
| 32 | + <spatialModel type="PointSource"> | ||
| 33 | + <parameter name="RA" value="266.831945177213" error="0" scale="1" free="1" /> | ||
| 34 | + <parameter name="DEC" value="-28.1460284439951" error="0" scale="1" free="1" /> | ||
| 35 | + </spatialModel> | ||
| 36 | + </source> | ||
| 37 | + <source name="Src004" type="PointSource"> | ||
| 38 | + <spectrum type="PowerLaw"> | ||
| 39 | + <parameter name="Prefactor" value="1" error="0" scale="5.7e-18" min="0" free="1" /> | ||
| 40 | + <parameter name="Index" value="1" error="-0" scale="-2.48" min="-4.03225806451613" max="4.03225806451613" free="1" /> | ||
| 41 | + <parameter name="PivotEnergy" value="1" scale="300000" free="0" /> | ||
| 42 | + </spectrum> | ||
| 43 | + <spatialModel type="PointSource"> | ||
| 44 | + <parameter name="RA" value="268.244867737546" error="0" scale="1" free="1" /> | ||
| 45 | + <parameter name="DEC" value="-30.3728286753247" error="0" scale="1" free="1" /> | ||
| 46 | + </spatialModel> | ||
| 47 | + </source> | ||
| 48 | + <source name="Src005" type="PointSource"> | ||
| 49 | + <spectrum type="PowerLaw"> | ||
| 50 | + <parameter name="Prefactor" value="1" error="0" scale="5.7e-18" min="0" free="1" /> | ||
| 51 | + <parameter name="Index" value="1" error="-0" scale="-2.48" min="-4.03225806451613" max="4.03225806451613" free="1" /> | ||
| 52 | + <parameter name="PivotEnergy" value="1" scale="300000" free="0" /> | ||
| 53 | + </spectrum> | ||
| 54 | + <spatialModel type="PointSource"> | ||
| 55 | + <parameter name="RA" value="270.424492131939" error="0" scale="1" free="1" /> | ||
| 56 | + <parameter name="DEC" value="-29.6624142779832" error="0" scale="1" free="1" /> | ||
| 57 | + </spatialModel> | ||
| 58 | + </source> | ||
| 59 | + <source name="Src006" type="PointSource"> | ||
| 60 | + <spectrum type="PowerLaw"> | ||
| 61 | + <parameter name="Prefactor" value="1" error="0" scale="5.7e-18" min="0" free="1" /> | ||
| 62 | + <parameter name="Index" value="1" error="-0" scale="-2.48" min="-4.03225806451613" max="4.03225806451613" free="1" /> | ||
| 63 | + <parameter name="PivotEnergy" value="1" scale="300000" free="0" /> | ||
| 64 | + </spectrum> | ||
| 65 | + <spatialModel type="PointSource"> | ||
| 66 | + <parameter name="RA" value="263.809469183313" error="0" scale="1" free="1" /> | ||
| 67 | + <parameter name="DEC" value="-31.2230130593475" error="0" scale="1" free="1" /> | ||
| 68 | + </spatialModel> | ||
| 69 | + </source> | ||
| 70 | + <source name="BackgroundModel" type="CTACubeBackground" instrument="CTA,HESS,MAGIC,VERITAS"> | ||
| 71 | + <spectrum type="PowerLaw"> | ||
| 72 | + <parameter name="Prefactor" value="1" error="0" scale="1" min="0.01" max="100" free="1" /> | ||
| 73 | + <parameter name="Index" value="0" error="0" scale="1" min="-5" max="5" free="1" /> | ||
| 74 | + <parameter name="PivotEnergy" value="1" scale="1000000" free="0" /> | ||
| 75 | + </spectrum> | ||
| 76 | + </source> | ||
| 77 | +</source_library> |
doc/source/users/tutorials/1dc/show_onoff_spectrum.py
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | # ========================================================================== | 2 | # ========================================================================== |
| 3 | # Display butterfly generated by ctbutterfly and spectrum generated by csspec | 3 | # Display butterfly generated by ctbutterfly and spectrum generated by csspec |
| 4 | # | 4 | # |
| 5 | -# Copyright (C) 2018 Juergen Knoedlseder | 5 | +# Copyright (C) 2018-2021 Juergen Knoedlseder |
| 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 |
| 8 | # it under the terms of the GNU General Public License as published by | 8 | # it under the terms of the GNU General Public License as published by |
| @@ -51,13 +51,14 @@ def plot_spectrum_butterfly(specfile, butterfile, fmt='o', color='red'): | @@ -51,13 +51,14 @@ def plot_spectrum_butterfly(specfile, butterfile, fmt='o', color='red'): | ||
| 51 | # Read spectrum file | 51 | # Read spectrum file |
| 52 | fits = gammalib.GFits(specfile) | 52 | fits = gammalib.GFits(specfile) |
| 53 | table = fits.table(1) | 53 | table = fits.table(1) |
| 54 | - c_energy = table['Energy'] | ||
| 55 | - c_ed = table['ed_Energy'] | ||
| 56 | - c_eu = table['eu_Energy'] | ||
| 57 | - c_flux = table['Flux'] | ||
| 58 | - c_eflux = table['e_Flux'] | ||
| 59 | - c_ts = table['TS'] | ||
| 60 | - c_upper = table['UpperLimit'] | 54 | + c_energy = table['e_ref'] |
| 55 | + c_ed = table['e_min'] | ||
| 56 | + c_eu = table['e_max'] | ||
| 57 | + c_flux = table['ref_e2dnde'] | ||
| 58 | + c_norm = table['norm'] | ||
| 59 | + c_eflux = table['norm_err'] | ||
| 60 | + c_upper = table['norm_ul'] | ||
| 61 | + c_ts = table['ts'] | ||
| 61 | 62 | ||
| 62 | # Read butterfly file | 63 | # Read butterfly file |
| 63 | csv = gammalib.GCsv(butterfile) | 64 | csv = gammalib.GCsv(butterfile) |
| @@ -83,22 +84,23 @@ def plot_spectrum_butterfly(specfile, butterfile, fmt='o', color='red'): | @@ -83,22 +84,23 @@ def plot_spectrum_butterfly(specfile, butterfile, fmt='o', color='red'): | ||
| 83 | 84 | ||
| 84 | # Get Test Statistic, flux and flux error | 85 | # Get Test Statistic, flux and flux error |
| 85 | ts = c_ts.real(row) | 86 | ts = c_ts.real(row) |
| 86 | - flx = c_flux.real(row) | ||
| 87 | - e_flx = c_eflux.real(row) | 87 | + norm = c_norm.real(row) |
| 88 | + flx = norm * c_flux.real(row) | ||
| 89 | + e_flx = flx * c_eflux.real(row) | ||
| 88 | 90 | ||
| 89 | # If Test Statistic is larger than 9 and flux error is smaller than | 91 | # If Test Statistic is larger than 9 and flux error is smaller than |
| 90 | # flux then append flux plots ... | 92 | # flux then append flux plots ... |
| 91 | if ts > 9.0 and e_flx < flx: | 93 | if ts > 9.0 and e_flx < flx: |
| 92 | energies.append(c_energy.real(row)) | 94 | energies.append(c_energy.real(row)) |
| 93 | - flux.append(c_flux.real(row)) | 95 | + flux.append(flx) |
| 94 | ed_engs.append(c_ed.real(row)) | 96 | ed_engs.append(c_ed.real(row)) |
| 95 | eu_engs.append(c_eu.real(row)) | 97 | eu_engs.append(c_eu.real(row)) |
| 96 | - e_flux.append(c_eflux.real(row)) | 98 | + e_flux.append(e_flx) |
| 97 | 99 | ||
| 98 | # ... otherwise append upper limit | 100 | # ... otherwise append upper limit |
| 99 | else: | 101 | else: |
| 100 | ul_energies.append(c_energy.real(row)) | 102 | ul_energies.append(c_energy.real(row)) |
| 101 | - ul_flux.append(c_upper.real(row)) | 103 | + ul_flux.append(flx*c_upper.real(row)) |
| 102 | ul_ed_engs.append(c_ed.real(row)) | 104 | ul_ed_engs.append(c_ed.real(row)) |
| 103 | ul_eu_engs.append(c_eu.real(row)) | 105 | ul_eu_engs.append(c_eu.real(row)) |
| 104 | 106 | ||
| @@ -152,16 +154,18 @@ def show_spectrum_butterfly(): | @@ -152,16 +154,18 @@ def show_spectrum_butterfly(): | ||
| 152 | plt.grid() | 154 | plt.grid() |
| 153 | 155 | ||
| 154 | # Set usage string | 156 | # Set usage string |
| 155 | - usage = 'show_onoff_spectrum.py [-t title] [specfile] [butterfile]' | 157 | + usage = 'show_onoff_spectrum.py [-p plotfile] [-t title] [specfile] [butterfile]' |
| 156 | 158 | ||
| 157 | # Set default options | 159 | # Set default options |
| 158 | - options = [{'option': '-t', 'value': 'Cassiopeia A'}] | 160 | + options = [{'option': '-p', 'value': ''}, |
| 161 | + {'option': '-t', 'value': 'Cassiopeia A'}] | ||
| 159 | 162 | ||
| 160 | # Get arguments and options from command line arguments | 163 | # Get arguments and options from command line arguments |
| 161 | args, options = cscripts.ioutils.get_args_options(options, usage) | 164 | args, options = cscripts.ioutils.get_args_options(options, usage) |
| 162 | 165 | ||
| 163 | # Extract script parameters from options | 166 | # Extract script parameters from options |
| 164 | - title = options[0]['value'] | 167 | + plotfile = options[0]['value'] |
| 168 | + title = options[1]['value'] | ||
| 165 | 169 | ||
| 166 | # Set filenames | 170 | # Set filenames |
| 167 | specfile = 'spectrum.fits' | 171 | specfile = 'spectrum.fits' |
| @@ -182,7 +186,10 @@ def show_spectrum_butterfly(): | @@ -182,7 +186,10 @@ def show_spectrum_butterfly(): | ||
| 182 | plt.title(title) | 186 | plt.title(title) |
| 183 | 187 | ||
| 184 | # Show figure | 188 | # Show figure |
| 185 | - plt.show() | 189 | + if len(plotfile) > 0: |
| 190 | + plt.savefig(plotfile) | ||
| 191 | + else: | ||
| 192 | + plt.show() | ||
| 186 | 193 | ||
| 187 | # Return | 194 | # Return |
| 188 | return | 195 | return |
doc/source/users/tutorials/howto/extended_model.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | +<source_library title="source library"> | ||
| 3 | + <source name="Src001" type="PointSource"> | ||
| 4 | + <spectrum type="ExponentialCutoffPowerLaw"> | ||
| 5 | + <parameter name="Prefactor" scale="1e-18" value="5.7" min="1e-07" max="1000.0" free="1"/> | ||
| 6 | + <parameter name="Index" scale="-1" value="2.48" min="0.0" max="+5.0" free="1"/> | ||
| 7 | + <parameter name="CutoffEnergy" scale="1e7" value="1.0" min="0.01" max="1000.0" free="1"/> | ||
| 8 | + <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/> | ||
| 9 | + </spectrum> | ||
| 10 | + <spatialModel type="PointSource"> | ||
| 11 | + <parameter name="RA" scale="1" value="266.424" free="1" /> | ||
| 12 | + <parameter name="DEC" scale="1" value="-29.005" free="1" /> | ||
| 13 | + </spatialModel> | ||
| 14 | + </source> | ||
| 15 | + <source name="Src002" type="PointSource"> | ||
| 16 | + <spectrum type="PowerLaw"> | ||
| 17 | + <parameter name="Prefactor" scale="1e-18" value="5.7" min="1e-07" max="1000.0" free="1"/> | ||
| 18 | + <parameter name="Index" scale="-1" value="2.48" min="0.0" max="5.0" free="1"/> | ||
| 19 | + <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/> | ||
| 20 | + </spectrum> | ||
| 21 | + <spatialModel type="PointSource"> | ||
| 22 | + <parameter name="RA" scale="1" value="266.832" free="1" /> | ||
| 23 | + <parameter name="DEC" scale="1" value="-28.146" free="1" /> | ||
| 24 | + </spatialModel> | ||
| 25 | + </source> | ||
| 26 | + <source name="Src003" type="ExtendedSource" tscalc="1"> | ||
| 27 | + <spectrum type="PowerLaw"> | ||
| 28 | + <parameter name="Prefactor" scale="5.7e-18" value="1.0" min="0" max="1000.0" free="1"/> | ||
| 29 | + <parameter name="Index" scale="-2.48" value="1.0" min="-4.0" max="4.0" free="1"/> | ||
| 30 | + <parameter name="PivotEnergy" scale="300000" value="1.0" free="0" /> | ||
| 31 | + </spectrum> | ||
| 32 | + <spatialModel type="RadialDisk"> | ||
| 33 | + <parameter name="RA" scale="1.0" value="266.3070" min="-360" max="360" free="1"/> | ||
| 34 | + <parameter name="DEC" scale="1.0" value="-30.1876" min="-90" max="90" free="1"/> | ||
| 35 | + <parameter name="Radius" scale="1.0" value="0.3" min="0.001" max="10" free="1"/> | ||
| 36 | + </spatialModel> | ||
| 37 | + </source> | ||
| 38 | + <source name="IEM" type="DiffuseSource"> | ||
| 39 | + <spectrum type="ConstantValue"> | ||
| 40 | + <parameter name="Value" scale="1" value="1" min="1e-05" max="100000" free="1"/> | ||
| 41 | + </spectrum> | ||
| 42 | + <spatialModel type="MapCubeFunction" file="$CTADATA/models/cube_iem.fits"> | ||
| 43 | + <parameter name="Normalization" scale="1" value="1" min="0.001" max="1000" free="0"/> | ||
| 44 | + </spatialModel> | ||
| 45 | + </source> | ||
| 46 | + <source name="Background" type="CTACubeBackground" instrument="CTA"> | ||
| 47 | + <spectrum type="PowerLaw"> | ||
| 48 | + <parameter name="Prefactor" scale="1" value="1" min="0.01" max="100" free="1"/> | ||
| 49 | + <parameter name="Index" scale="1" value="0" min="-5" max="5" free="1"/> | ||
| 50 | + <parameter name="PivotEnergy" scale="1000000" value="1" min="0.01" max="1000.0" free="0"/> | ||
| 51 | + </spectrum> | ||
| 52 | + </source> | ||
| 53 | +</source_library> |
doc/source/users/tutorials/howto/howto_connect_irfs.rst
| @@ -52,21 +52,11 @@ array: | @@ -52,21 +52,11 @@ array: | ||
| 52 | Output event data file or observation definition XML file [north.fits] south.fits | 52 | Output event data file or observation definition XML file [north.fits] south.fits |
| 53 | 53 | ||
| 54 | You now need to combine the information about these two observations in an | 54 | You now need to combine the information about these two observations in an |
| 55 | -observation definition XML file: | 55 | +observation definition XML file. Let's put the following content in in the |
| 56 | +``obs_irf.xml``: | ||
| 56 | 57 | ||
| 57 | -.. code-block:: xml | ||
| 58 | - | ||
| 59 | - <?xml version="1.0" standalone="no"?> | ||
| 60 | - <observation_list title="observation library"> | ||
| 61 | - <observation name="Crab" id="00001" instrument="CTA"> | ||
| 62 | - <parameter name="EventList" file="north.fits"/> | ||
| 63 | - <parameter name="Calibration" database="prod2" response="North_0.5h"/> | ||
| 64 | - </observation> | ||
| 65 | - <observation name="Crab" id="00002" instrument="CTA"> | ||
| 66 | - <parameter name="EventList" file="south.fits"/> | ||
| 67 | - <parameter name="Calibration" database="prod2" response="South_0.5h"/> | ||
| 68 | - </observation> | ||
| 69 | - </observation_list> | 58 | +.. literalinclude:: obs_irf.xml |
| 59 | + :language: xml | ||
| 70 | 60 | ||
| 71 | Each observation now has a ``Calibration`` parameter with the attributes | 61 | Each observation now has a ``Calibration`` parameter with the attributes |
| 72 | ``database`` and ``response``. | 62 | ``database`` and ``response``. |
doc/source/users/tutorials/howto/howto_extent.rst
| @@ -33,22 +33,12 @@ To do this, copy the 1DC :ref:`model definition <glossary_moddef>` file | @@ -33,22 +33,12 @@ To do this, copy the 1DC :ref:`model definition <glossary_moddef>` file | ||
| 33 | 33 | ||
| 34 | $ cp $CTOOLS/share/models/1dc_howto.xml extended_model.xml | 34 | $ cp $CTOOLS/share/models/1dc_howto.xml extended_model.xml |
| 35 | 35 | ||
| 36 | -and add the following source to it | ||
| 37 | - | ||
| 38 | -.. code-block:: xml | ||
| 39 | - | ||
| 40 | - <source name="Src003" type="ExtendedSource" tscalc="1"> | ||
| 41 | - <spectrum type="PowerLaw"> | ||
| 42 | - <parameter name="Prefactor" scale="5.7e-18" value="1.0" min="0" max="1000.0" free="1"/> | ||
| 43 | - <parameter name="Index" scale="-2.48" value="1.0" min="-4.0" max="4.0" free="1"/> | ||
| 44 | - <parameter name="PivotEnergy" scale="300000" value="1.0" free="0" /> | ||
| 45 | - </spectrum> | ||
| 46 | - <spatialModel type="RadialDisk"> | ||
| 47 | - <parameter name="RA" scale="1.0" value="266.3070" min="-360" max="360" free="1"/> | ||
| 48 | - <parameter name="DEC" scale="1.0" value="-30.1876" min="-90" max="90" free="1"/> | ||
| 49 | - <parameter name="Radius" scale="1.0" value="0.3" min="0.001" max="10" free="1"/> | ||
| 50 | - </spatialModel> | ||
| 51 | - </source> | 36 | +to :download:`extended_model.xml <extended_model.xml>` and add the following |
| 37 | +source to it: | ||
| 38 | + | ||
| 39 | +.. literalinclude:: extended_model.xml | ||
| 40 | + :language: xml | ||
| 41 | + :lines: 26-37 | ||
| 52 | 42 | ||
| 53 | Then run :ref:`ctlike` to fit the parameters of ``Src003`` together with the | 43 | Then run :ref:`ctlike` to fit the parameters of ``Src003`` together with the |
| 54 | other source parameters | 44 | other source parameters |
doc/source/users/tutorials/howto/howto_ts.rst
| @@ -19,28 +19,13 @@ Copy the 1DC :ref:`model definition <glossary_moddef>` file | @@ -19,28 +19,13 @@ Copy the 1DC :ref:`model definition <glossary_moddef>` file | ||
| 19 | $ cp $CTOOLS/share/models/1dc_howto.xml ts_model.xml | 19 | $ cp $CTOOLS/share/models/1dc_howto.xml ts_model.xml |
| 20 | 20 | ||
| 21 | and modify the file by adding ``tscalc="1"`` to the ``<source>`` tag for | 21 | and modify the file by adding ``tscalc="1"`` to the ``<source>`` tag for |
| 22 | -source ``Src1``. Your | 22 | +source ``Src1``. The first lines of the :download:`ts_model.xml <ts_model.xml>` |
| 23 | :ref:`model definition XML file <glossary_moddef>` | 23 | :ref:`model definition XML file <glossary_moddef>` |
| 24 | should then look like this: | 24 | should then look like this: |
| 25 | 25 | ||
| 26 | -.. code-block:: xml | ||
| 27 | - | ||
| 28 | - <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 29 | - <source_library title="source library"> | ||
| 30 | - <source name="Src001" type="PointSource" tscalc="1"> | ||
| 31 | - <spectrum type="ExponentialCutoffPowerLaw"> | ||
| 32 | - <parameter name="Prefactor" scale="1e-18" value="5.7" min="1e-07" max="1000.0" free="1"/> | ||
| 33 | - <parameter name="Index" scale="-1" value="2.48" min="0.0" max="+5.0" free="1"/> | ||
| 34 | - <parameter name="CutoffEnergy" scale="1e7" value="1.0" min="0.01" max="1000.0" free="1"/> | ||
| 35 | - <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/> | ||
| 36 | - </spectrum> | ||
| 37 | - <spatialModel type="PointSource"> | ||
| 38 | - <parameter name="RA" scale="1" value="266.424" free="1" /> | ||
| 39 | - <parameter name="DEC" scale="1" value="-29.005" free="1" /> | ||
| 40 | - </spatialModel> | ||
| 41 | - </source> | ||
| 42 | - ... | ||
| 43 | - </source_library> | 26 | +.. literalinclude:: ts_model.xml |
| 27 | + :language: xml | ||
| 28 | + :lines: 1-14 | ||
| 44 | 29 | ||
| 45 | Then run :ref:`ctlike` to compute the so-called Test Statistic, which is twice | 30 | Then run :ref:`ctlike` to compute the so-called Test Statistic, which is twice |
| 46 | the difference between the log-likelihood value obtained for a fit that includes | 31 | the difference between the log-likelihood value obtained for a fit that includes |
doc/source/users/tutorials/howto/howto_tsmap.rst
| @@ -100,12 +100,13 @@ The figure below shows the resulting Test Statistic map. | @@ -100,12 +100,13 @@ The figure below shows the resulting Test Statistic map. | ||
| 100 | cttsmap inobs=cntcube.fits inmodel=$CTOOLS/share/models/test_cube.xml srcname=Test expcube=expcube.fits psfcube=psfcube.fits bkgcube=bkgcube.fits nxpix=10 nypix=10 binsz=0.05 coordsys=GAL proj=CAR xref=0.0 yref=0.0 logL0=-447785.5939102234 binmin=70 binmax=80 outmap=tsmap_split_7.fits logfile=tsmap_split_7.log & | 100 | cttsmap inobs=cntcube.fits inmodel=$CTOOLS/share/models/test_cube.xml srcname=Test expcube=expcube.fits psfcube=psfcube.fits bkgcube=bkgcube.fits nxpix=10 nypix=10 binsz=0.05 coordsys=GAL proj=CAR xref=0.0 yref=0.0 logL0=-447785.5939102234 binmin=70 binmax=80 outmap=tsmap_split_7.fits logfile=tsmap_split_7.log & |
| 101 | cttsmap inobs=cntcube.fits inmodel=$CTOOLS/share/models/test_cube.xml srcname=Test expcube=expcube.fits psfcube=psfcube.fits bkgcube=bkgcube.fits nxpix=10 nypix=10 binsz=0.05 coordsys=GAL proj=CAR xref=0.0 yref=0.0 logL0=-447785.5939102234 binmin=80 binmax=90 outmap=tsmap_split_8.fits logfile=tsmap_split_8.log & | 101 | cttsmap inobs=cntcube.fits inmodel=$CTOOLS/share/models/test_cube.xml srcname=Test expcube=expcube.fits psfcube=psfcube.fits bkgcube=bkgcube.fits nxpix=10 nypix=10 binsz=0.05 coordsys=GAL proj=CAR xref=0.0 yref=0.0 logL0=-447785.5939102234 binmin=80 binmax=90 outmap=tsmap_split_8.fits logfile=tsmap_split_8.log & |
| 102 | cttsmap inobs=cntcube.fits inmodel=$CTOOLS/share/models/test_cube.xml srcname=Test expcube=expcube.fits psfcube=psfcube.fits bkgcube=bkgcube.fits nxpix=10 nypix=10 binsz=0.05 coordsys=GAL proj=CAR xref=0.0 yref=0.0 logL0=-447785.5939102234 binmin=90 binmax=100 outmap=tsmap_split_9.fits logfile=tsmap_split_9.log & | 102 | cttsmap inobs=cntcube.fits inmodel=$CTOOLS/share/models/test_cube.xml srcname=Test expcube=expcube.fits psfcube=psfcube.fits bkgcube=bkgcube.fits nxpix=10 nypix=10 binsz=0.05 coordsys=GAL proj=CAR xref=0.0 yref=0.0 logL0=-447785.5939102234 binmin=90 binmax=100 outmap=tsmap_split_9.fits logfile=tsmap_split_9.log & |
| 103 | + wait | ||
| 103 | 104 | ||
| 104 | Now run the ASCII file by typing | 105 | Now run the ASCII file by typing |
| 105 | 106 | ||
| 106 | .. code-block:: bash | 107 | .. code-block:: bash |
| 107 | 108 | ||
| 108 | - ./tsmap_commands.dat | 109 | + $ ./tsmap_commands.dat |
| 109 | 110 | ||
| 110 | This will execute 10 :ref:`cttsmap` jobs in parallel. Each of the jobs will | 111 | This will execute 10 :ref:`cttsmap` jobs in parallel. Each of the jobs will |
| 111 | compute 10 pixels of the Test Statistic map. You combine the resulting 10 | 112 | compute 10 pixels of the Test Statistic map. You combine the resulting 10 |
doc/source/users/tutorials/howto/howto_ulimit.rst
| @@ -22,21 +22,12 @@ To do this, copy the 1DC :ref:`model definition <glossary_moddef>` file | @@ -22,21 +22,12 @@ To do this, copy the 1DC :ref:`model definition <glossary_moddef>` file | ||
| 22 | 22 | ||
| 23 | $ cp $CTOOLS/share/models/1dc_howto.xml ulimit_model.xml | 23 | $ cp $CTOOLS/share/models/1dc_howto.xml ulimit_model.xml |
| 24 | 24 | ||
| 25 | -and add the following source to it | ||
| 26 | - | ||
| 27 | -.. code-block:: xml | ||
| 28 | - | ||
| 29 | - <source name="Test" type="PointSource"> | ||
| 30 | - <spectrum type="PowerLaw"> | ||
| 31 | - <parameter name="Prefactor" value="1" scale="1.0e-20" min="0" free="1"/> | ||
| 32 | - <parameter name="Index" value="1" scale="-2.48" min="-5" max="5" free="0"/> | ||
| 33 | - <parameter name="PivotEnergy" value="1" scale="300000" free="0"/> | ||
| 34 | - </spectrum> | ||
| 35 | - <spatialModel type="PointSource"> | ||
| 36 | - <parameter name="GLON" value="0.1" scale="1" free="0"/> | ||
| 37 | - <parameter name="GLAT" value="0.4" scale="1" free="0"/> | ||
| 38 | - </spatialModel> | ||
| 39 | - </source> | 25 | +to :download:`ulimit_model.xml <ulimit_model.xml>` and add the following |
| 26 | +source to it: | ||
| 27 | + | ||
| 28 | +.. literalinclude:: ulimit_model.xml | ||
| 29 | + :language: xml | ||
| 30 | + :lines: 3-13 | ||
| 40 | 31 | ||
| 41 | Now run the :ref:`ctulimit` tool as follows: | 32 | Now run the :ref:`ctulimit` tool as follows: |
| 42 | 33 |
doc/source/users/tutorials/howto/obs_irf.xml
0 → 100644
| 1 | +<?xml version="1.0" standalone="no"?> | ||
| 2 | +<observation_list title="observation library"> | ||
| 3 | + <observation name="Crab" id="00001" instrument="CTA"> | ||
| 4 | + <parameter name="EventList" file="north.fits"/> | ||
| 5 | + <parameter name="Calibration" database="prod2" response="North_0.5h"/> | ||
| 6 | + </observation> | ||
| 7 | + <observation name="Crab" id="00002" instrument="CTA"> | ||
| 8 | + <parameter name="EventList" file="south.fits"/> | ||
| 9 | + <parameter name="Calibration" database="prod2" response="South_0.5h"/> | ||
| 10 | + </observation> | ||
| 11 | +</observation_list> | ||
| 12 | + |
doc/source/users/tutorials/howto/ts_model.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | +<source_library title="source library"> | ||
| 3 | + <source name="Src001" type="PointSource" tscalc="1"> | ||
| 4 | + <spectrum type="ExponentialCutoffPowerLaw"> | ||
| 5 | + <parameter name="Prefactor" scale="1e-18" value="5.7" min="1e-07" max="1000.0" free="1"/> | ||
| 6 | + <parameter name="Index" scale="-1" value="2.48" min="0.0" max="+5.0" free="1"/> | ||
| 7 | + <parameter name="CutoffEnergy" scale="1e7" value="1.0" min="0.01" max="1000.0" free="1"/> | ||
| 8 | + <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/> | ||
| 9 | + </spectrum> | ||
| 10 | + <spatialModel type="PointSource"> | ||
| 11 | + <parameter name="RA" scale="1" value="266.424" free="1" /> | ||
| 12 | + <parameter name="DEC" scale="1" value="-29.005" free="1" /> | ||
| 13 | + </spatialModel> | ||
| 14 | + </source> | ||
| 15 | + <source name="Src002" type="PointSource"> | ||
| 16 | + <spectrum type="PowerLaw"> | ||
| 17 | + <parameter name="Prefactor" scale="1e-18" value="5.7" min="1e-07" max="1000.0" free="1"/> | ||
| 18 | + <parameter name="Index" scale="-1" value="2.48" min="0.0" max="5.0" free="1"/> | ||
| 19 | + <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/> | ||
| 20 | + </spectrum> | ||
| 21 | + <spatialModel type="PointSource"> | ||
| 22 | + <parameter name="RA" scale="1" value="266.832" free="1" /> | ||
| 23 | + <parameter name="DEC" scale="1" value="-28.146" free="1" /> | ||
| 24 | + </spatialModel> | ||
| 25 | + </source> | ||
| 26 | + <source name="IEM" type="DiffuseSource"> | ||
| 27 | + <spectrum type="ConstantValue"> | ||
| 28 | + <parameter name="Value" scale="1" value="1" min="1e-05" max="100000" free="1"/> | ||
| 29 | + </spectrum> | ||
| 30 | + <spatialModel type="MapCubeFunction" file="$CTADATA/models/cube_iem.fits"> | ||
| 31 | + <parameter name="Normalization" scale="1" value="1" min="0.001" max="1000" free="0"/> | ||
| 32 | + </spatialModel> | ||
| 33 | + </source> | ||
| 34 | + <source name="Background" type="CTACubeBackground" instrument="CTA"> | ||
| 35 | + <spectrum type="PowerLaw"> | ||
| 36 | + <parameter name="Prefactor" scale="1" value="1" min="0.01" max="100" free="1"/> | ||
| 37 | + <parameter name="Index" scale="1" value="0" min="-5" max="5" free="1"/> | ||
| 38 | + <parameter name="PivotEnergy" scale="1000000" value="1" min="0.01" max="1000.0" free="0"/> | ||
| 39 | + </spectrum> | ||
| 40 | + </source> | ||
| 41 | +</source_library> |
doc/source/users/tutorials/howto/ulimit_model.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | +<source_library title="source library"> | ||
| 3 | + <source name="Test" type="PointSource"> | ||
| 4 | + <spectrum type="PowerLaw"> | ||
| 5 | + <parameter name="Prefactor" value="1" scale="1.0e-20" min="0" free="1"/> | ||
| 6 | + <parameter name="Index" value="1" scale="-2.48" min="-5" max="5" free="0"/> | ||
| 7 | + <parameter name="PivotEnergy" value="1" scale="300000" free="0"/> | ||
| 8 | + </spectrum> | ||
| 9 | + <spatialModel type="PointSource"> | ||
| 10 | + <parameter name="GLON" value="0.1" scale="1" free="0"/> | ||
| 11 | + <parameter name="GLAT" value="0.4" scale="1" free="0"/> | ||
| 12 | + </spatialModel> | ||
| 13 | + </source> | ||
| 14 | + <source name="Src001" type="PointSource"> | ||
| 15 | + <spectrum type="ExponentialCutoffPowerLaw"> | ||
| 16 | + <parameter name="Prefactor" scale="1e-18" value="5.7" min="1e-07" max="1000.0" free="1"/> | ||
| 17 | + <parameter name="Index" scale="-1" value="2.48" min="0.0" max="+5.0" free="1"/> | ||
| 18 | + <parameter name="CutoffEnergy" scale="1e7" value="1.0" min="0.01" max="1000.0" free="1"/> | ||
| 19 | + <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/> | ||
| 20 | + </spectrum> | ||
| 21 | + <spatialModel type="PointSource"> | ||
| 22 | + <parameter name="RA" scale="1" value="266.424" free="1" /> | ||
| 23 | + <parameter name="DEC" scale="1" value="-29.005" free="1" /> | ||
| 24 | + </spatialModel> | ||
| 25 | + </source> | ||
| 26 | + <source name="Src002" type="PointSource"> | ||
| 27 | + <spectrum type="PowerLaw"> | ||
| 28 | + <parameter name="Prefactor" scale="1e-18" value="5.7" min="1e-07" max="1000.0" free="1"/> | ||
| 29 | + <parameter name="Index" scale="-1" value="2.48" min="0.0" max="5.0" free="1"/> | ||
| 30 | + <parameter name="PivotEnergy" scale="1e6" value="0.3" min="0.01" max="1000.0" free="0"/> | ||
| 31 | + </spectrum> | ||
| 32 | + <spatialModel type="PointSource"> | ||
| 33 | + <parameter name="RA" scale="1" value="266.832" free="1" /> | ||
| 34 | + <parameter name="DEC" scale="1" value="-28.146" free="1" /> | ||
| 35 | + </spatialModel> | ||
| 36 | + </source> | ||
| 37 | + <source name="IEM" type="DiffuseSource"> | ||
| 38 | + <spectrum type="ConstantValue"> | ||
| 39 | + <parameter name="Value" scale="1" value="1" min="1e-05" max="100000" free="1"/> | ||
| 40 | + </spectrum> | ||
| 41 | + <spatialModel type="MapCubeFunction" file="$CTADATA/models/cube_iem.fits"> | ||
| 42 | + <parameter name="Normalization" scale="1" value="1" min="0.001" max="1000" free="0"/> | ||
| 43 | + </spatialModel> | ||
| 44 | + </source> | ||
| 45 | + <source name="Background" type="CTACubeBackground" instrument="CTA"> | ||
| 46 | + <spectrum type="PowerLaw"> | ||
| 47 | + <parameter name="Prefactor" scale="1" value="1" min="0.01" max="100" free="1"/> | ||
| 48 | + <parameter name="Index" scale="1" value="0" min="-5" max="5" free="1"/> | ||
| 49 | + <parameter name="PivotEnergy" scale="1000000" value="1" min="0.01" max="1000.0" free="0"/> | ||
| 50 | + </spectrum> | ||
| 51 | + </source> | ||
| 52 | +</source_library> |
test/tutorials.py
0 → 100755
| 1 | +#! /usr/bin/env python | ||
| 2 | +# ========================================================================== | ||
| 3 | +# This script tests the Sphinx tutorials | ||
| 4 | +# | ||
| 5 | +# Usage: | ||
| 6 | +# ./tutorials.py | ||
| 7 | +# | ||
| 8 | +# -------------------------------------------------------------------------- | ||
| 9 | +# | ||
| 10 | +# Copyright (C) 2021 Juergen Knoedlseder | ||
| 11 | +# | ||
| 12 | +# This program is free software: you can redistribute it and/or modify | ||
| 13 | +# it under the terms of the GNU General Public License as published by | ||
| 14 | +# the Free Software Foundation, either version 3 of the License, or | ||
| 15 | +# (at your option) any later version. | ||
| 16 | +# | ||
| 17 | +# This program is distributed in the hope that it will be useful, | ||
| 18 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | +# GNU General Public License for more details. | ||
| 21 | +# | ||
| 22 | +# You should have received a copy of the GNU General Public License | ||
| 23 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 24 | +# | ||
| 25 | +# ========================================================================== | ||
| 26 | +import os | ||
| 27 | +import sys | ||
| 28 | +import stat | ||
| 29 | +import subprocess | ||
| 30 | +import gammalib | ||
| 31 | +import ctools | ||
| 32 | +import cscripts | ||
| 33 | + | ||
| 34 | + | ||
| 35 | +# ===================================== # | ||
| 36 | +# Test class for tutorials verification # | ||
| 37 | +# ===================================== # | ||
| 38 | +class tutorials(gammalib.GPythonTestSuite): | ||
| 39 | + """ | ||
| 40 | + Test class for tutorials verification | ||
| 41 | + """ | ||
| 42 | + # Constructor | ||
| 43 | + def __init__(self): | ||
| 44 | + """ | ||
| 45 | + Constructor | ||
| 46 | + """ | ||
| 47 | + # Call base class constructor | ||
| 48 | + gammalib.GPythonTestSuite.__init__(self) | ||
| 49 | + | ||
| 50 | + # Initialise private members | ||
| 51 | + self._rst_step = 0 # Step counter | ||
| 52 | + self._rst_path = '' # Path where the tested RST file resides | ||
| 53 | + self._cwd = '.' # Current working directory | ||
| 54 | + | ||
| 55 | + # Return | ||
| 56 | + return | ||
| 57 | + | ||
| 58 | + # Clean pfiles directory | ||
| 59 | + def _clean_pfiles(self): | ||
| 60 | + """ | ||
| 61 | + Clean pfiles directory | ||
| 62 | + """ | ||
| 63 | + # Remove all files from pfiles directory | ||
| 64 | + os.system('rm -rf %s/*.par' % os.environ['PFILES']) | ||
| 65 | + | ||
| 66 | + # Return | ||
| 67 | + return | ||
| 68 | + | ||
| 69 | + # Set result directory | ||
| 70 | + def _set_result_dir(self, path): | ||
| 71 | + """ | ||
| 72 | + Set result directory | ||
| 73 | + | ||
| 74 | + Parameters | ||
| 75 | + ---------- | ||
| 76 | + path : str | ||
| 77 | + Result directory path | ||
| 78 | + """ | ||
| 79 | + # Set default working directory | ||
| 80 | + os.chdir(self._cwd) | ||
| 81 | + | ||
| 82 | + # Create result directory | ||
| 83 | + try: | ||
| 84 | + os.makedirs(path) | ||
| 85 | + except: | ||
| 86 | + pass | ||
| 87 | + | ||
| 88 | + # Clear result directory | ||
| 89 | + os.system('rm -rf %s/*' % path) | ||
| 90 | + | ||
| 91 | + # Step in result directory | ||
| 92 | + os.chdir(path) | ||
| 93 | + | ||
| 94 | + # Return | ||
| 95 | + return | ||
| 96 | + | ||
| 97 | + # Test command execution | ||
| 98 | + def _test_execute_cmd(self, cmd, args): | ||
| 99 | + """ | ||
| 100 | + Test command execution | ||
| 101 | + | ||
| 102 | + Tests the execution of a command. Currently supported commands are: | ||
| 103 | + - cd | ||
| 104 | + - mkdir | ||
| 105 | + - nano | ||
| 106 | + - ./xxxxxx (any command xxxxxx that resides in the directory of the RST file) | ||
| 107 | + | ||
| 108 | + Parameters | ||
| 109 | + ---------- | ||
| 110 | + cmd : str | ||
| 111 | + Command line | ||
| 112 | + args : list of str | ||
| 113 | + Additional lines following the command line | ||
| 114 | + """ | ||
| 115 | + # Split command line | ||
| 116 | + cmdline = cmd.split(' ') | ||
| 117 | + | ||
| 118 | + # Check command line | ||
| 119 | + self.test_assert((len(cmdline) > 0), 'Test that command line is not empty.', cmd) | ||
| 120 | + | ||
| 121 | + # Continue only if valid | ||
| 122 | + if len(cmdline) > 0: | ||
| 123 | + | ||
| 124 | + # Extract command | ||
| 125 | + command = gammalib.strip_whitespace(cmdline[0]) | ||
| 126 | + | ||
| 127 | + # Handle "mkdir" command | ||
| 128 | + if command == 'mkdir': | ||
| 129 | + self.test_value(len(cmdline), 2, 'Test number of arguments for "mkdir".') | ||
| 130 | + self.test_value(len(args), 0, 'Test that no lines follow "mkdir".') | ||
| 131 | + if len(cmdline) > 1: | ||
| 132 | + dirname = gammalib.strip_whitespace(cmdline[1]) | ||
| 133 | + os.system('mkdir -p %s' % dirname) | ||
| 134 | + | ||
| 135 | + # Handle "cd" command | ||
| 136 | + elif command == 'cd': | ||
| 137 | + self.test_value(len(cmdline), 2, 'Test number of arguments for "cd".') | ||
| 138 | + self.test_value(len(args), 0, 'Test that no lines follow "cd".') | ||
| 139 | + if len(cmdline) > 1: | ||
| 140 | + dirname = gammalib.strip_whitespace(cmdline[1]) | ||
| 141 | + os.chdir(dirname) | ||
| 142 | + | ||
| 143 | + # Handle "cp" command | ||
| 144 | + elif command == 'cp': | ||
| 145 | + self.test_value(len(cmdline), 3, 'Test number of arguments for "cp".') | ||
| 146 | + self.test_value(len(args), 0, 'Test that no lines follow "cp".') | ||
| 147 | + if len(cmdline) > 2: | ||
| 148 | + src = gammalib.expand_env(gammalib.strip_whitespace(cmdline[1])) | ||
| 149 | + dst = gammalib.expand_env(gammalib.strip_whitespace(cmdline[2])) | ||
| 150 | + os.system('cp %s %s' % (src, dst)) | ||
| 151 | + | ||
| 152 | + # Handle "nano" command | ||
| 153 | + elif command == 'nano': | ||
| 154 | + self.test_value(len(cmdline), 2, 'Test number of arguments for "nano".') | ||
| 155 | + self.test_assert((len(args) > 0), 'Test that lines follow "nano".') | ||
| 156 | + if len(cmdline) > 1: | ||
| 157 | + fname = gammalib.strip_whitespace(cmdline[1]) | ||
| 158 | + f = open(fname, 'wb') | ||
| 159 | + for arg in args: | ||
| 160 | + f.write(arg) | ||
| 161 | + f.close() | ||
| 162 | + | ||
| 163 | + # Handle script execution | ||
| 164 | + elif command[0:2] == './': | ||
| 165 | + | ||
| 166 | + # Set script name. If the script does not exist in result | ||
| 167 | + # directory then assume it exists in Sphinx rst directory | ||
| 168 | + if os.path.isfile(command[2:]): | ||
| 169 | + script = './%s' % (command[2:]) | ||
| 170 | + else: | ||
| 171 | + script = '%s/%s' % (self._rst_path, command[2:]) | ||
| 172 | + | ||
| 173 | + # Make sure that script is executable | ||
| 174 | + mode = os.stat(script).st_mode | ||
| 175 | + mode |= (mode & 0o444) >> 2 | ||
| 176 | + os.chmod(script, mode) | ||
| 177 | + | ||
| 178 | + # Build command line | ||
| 179 | + plotname, _ = os.path.splitext(command[2:]) | ||
| 180 | + cmd = '%s -p %s.png' % (script, plotname) | ||
| 181 | + self.test_assert((len(args) == 0), 'Test script "%s".' % command[2:]) | ||
| 182 | + | ||
| 183 | + # Execute command, make sure we catch any exception | ||
| 184 | + try: | ||
| 185 | + rc = os.system(cmd+' > tutorials_test_output.dmp 2>&1') | ||
| 186 | + except: | ||
| 187 | + rc = -1 | ||
| 188 | + | ||
| 189 | + # If an exception occured then put output on screen | ||
| 190 | + msg = '' | ||
| 191 | + if rc != 0: | ||
| 192 | + f = open('tutorials_test_output.dmp', 'r') | ||
| 193 | + for line in f: | ||
| 194 | + msg += line | ||
| 195 | + f.close() | ||
| 196 | + | ||
| 197 | + # Remove test output | ||
| 198 | + os.remove('tutorials_test_output.dmp') | ||
| 199 | + | ||
| 200 | + # Set error flag and text | ||
| 201 | + name = 'Test execution of "%s".' % command[2:] | ||
| 202 | + self.test_value(rc, 0, name, msg) | ||
| 203 | + | ||
| 204 | + # Handle plotting scripts | ||
| 205 | + elif command[0:7] == '$CTOOLS': | ||
| 206 | + | ||
| 207 | + # Build command line | ||
| 208 | + script = gammalib.expand_env(cmdline[0]) | ||
| 209 | + filename = cmdline[1] | ||
| 210 | + plotname, _ = os.path.splitext(filename) | ||
| 211 | + cmd = '%s -p %s.png %s' % (script, plotname, filename) | ||
| 212 | + self.test_assert((len(args) == 0), 'Test script "%s".' % command) | ||
| 213 | + | ||
| 214 | + # Execute command, make sure we catch any exception | ||
| 215 | + try: | ||
| 216 | + rc = os.system(cmd+' > tutorials_test_output.dmp 2>&1') | ||
| 217 | + except: | ||
| 218 | + rc = -1 | ||
| 219 | + | ||
| 220 | + # If an exception occured then put output on screen | ||
| 221 | + msg = '' | ||
| 222 | + if rc != 0: | ||
| 223 | + f = open('tutorials_test_output.dmp', 'r') | ||
| 224 | + for line in f: | ||
| 225 | + msg += line | ||
| 226 | + f.close() | ||
| 227 | + | ||
| 228 | + # Remove test output | ||
| 229 | + os.remove('tutorials_test_output.dmp') | ||
| 230 | + | ||
| 231 | + # Set error flag and text | ||
| 232 | + name = 'Test execution of "%s".' % script | ||
| 233 | + self.test_value(rc, 0, name, msg) | ||
| 234 | + | ||
| 235 | + # Handle unsupported Xspec commands | ||
| 236 | + elif command[0:5] == 'xspec': | ||
| 237 | + pass | ||
| 238 | + | ||
| 239 | + # Signal that the command was not known | ||
| 240 | + else: | ||
| 241 | + name = 'Test command "%s".' % command | ||
| 242 | + msg = 'Unknown command "%s"' % command | ||
| 243 | + self.test_assert(False, name, msg) | ||
| 244 | + | ||
| 245 | + # Return | ||
| 246 | + return | ||
| 247 | + | ||
| 248 | + # Test line execution | ||
| 249 | + def _test_line_execution(self, lines): | ||
| 250 | + """ | ||
| 251 | + Test the execution of a sequence of commands | ||
| 252 | + | ||
| 253 | + Parameters | ||
| 254 | + ---------- | ||
| 255 | + lines : list of str | ||
| 256 | + Command lines | ||
| 257 | + """ | ||
| 258 | + # Initialise commands and arguments | ||
| 259 | + cmd = '' | ||
| 260 | + args = '' | ||
| 261 | + | ||
| 262 | + # Loop over all lines | ||
| 263 | + for line in lines: | ||
| 264 | + | ||
| 265 | + # If line starts with a string then extract or execute command | ||
| 266 | + if line[0:2] == '$ ': | ||
| 267 | + | ||
| 268 | + # If we have a command then execute it | ||
| 269 | + if cmd != '': | ||
| 270 | + self._test_execute_cmd(cmd, args) | ||
| 271 | + | ||
| 272 | + # Set new command | ||
| 273 | + cmd = line[2:] | ||
| 274 | + args = '' | ||
| 275 | + | ||
| 276 | + # ... otherwise add argument | ||
| 277 | + else: | ||
| 278 | + args += '%s\n' % (gammalib.strip_whitespace(line)) | ||
| 279 | + | ||
| 280 | + # If there is a pending command then execute it | ||
| 281 | + if cmd != '': | ||
| 282 | + self._test_execute_cmd(cmd, args) | ||
| 283 | + | ||
| 284 | + # Return | ||
| 285 | + return | ||
| 286 | + | ||
| 287 | + # Test ctool or cscript execution | ||
| 288 | + def _test_ctool_execution(self, tool, lines): | ||
| 289 | + """ | ||
| 290 | + Test the execution of a ctool or cscript | ||
| 291 | + | ||
| 292 | + The methods test the execution of a ctool or cscript as executed from | ||
| 293 | + the command line emulating the entering of the queried parameters. Any | ||
| 294 | + error that occurs in the execution will be signaled and the Python | ||
| 295 | + traceback will be put in the error message field. | ||
| 296 | + | ||
| 297 | + Parameters | ||
| 298 | + ---------- | ||
| 299 | + tool : str | ||
| 300 | + ctool name | ||
| 301 | + lines : list of str | ||
| 302 | + Command lines | ||
| 303 | + """ | ||
| 304 | + # Increment step counter | ||
| 305 | + self._rst_step += 1 | ||
| 306 | + | ||
| 307 | + # Initialise arguments | ||
| 308 | + args = '' | ||
| 309 | + | ||
| 310 | + # Set command | ||
| 311 | + cmd = tool.split(' ') | ||
| 312 | + | ||
| 313 | + # Append lines | ||
| 314 | + for line in lines: | ||
| 315 | + pos = line.find(']') | ||
| 316 | + if pos != -1: | ||
| 317 | + arg = gammalib.strip_whitespace(line[pos+1:]) | ||
| 318 | + args += '%s\n' % arg | ||
| 319 | + | ||
| 320 | + # Create subprocess for tool | ||
| 321 | + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, | ||
| 322 | + stdin=subprocess.PIPE, | ||
| 323 | + stderr=subprocess.PIPE) | ||
| 324 | + | ||
| 325 | + # Write command line parameters | ||
| 326 | + p.stdin.write(b'%s' % args) | ||
| 327 | + | ||
| 328 | + # Get results | ||
| 329 | + res = p.communicate() | ||
| 330 | + | ||
| 331 | + # Close pipeline | ||
| 332 | + p.stdin.close() | ||
| 333 | + | ||
| 334 | + # Set error flag and message | ||
| 335 | + if '*** ERROR' in res[0]: | ||
| 336 | + success = False | ||
| 337 | + msg = res[0] | ||
| 338 | + elif len(res[1]) > 0: | ||
| 339 | + success = False | ||
| 340 | + msg = res[1] | ||
| 341 | + else: | ||
| 342 | + success = True | ||
| 343 | + msg = '' | ||
| 344 | + name = 'Test execution of "%s".' % tool | ||
| 345 | + self.test_assert(success, name, msg) | ||
| 346 | + | ||
| 347 | + # Preprend step counter to logfile | ||
| 348 | + logfile = gammalib.GFilename('%s.log' % (cmd[0])) | ||
| 349 | + if logfile.exists(): | ||
| 350 | + src = logfile.url() | ||
| 351 | + dst = '%2.2d_%s' % (self._rst_step, src) | ||
| 352 | + os.system('mv %s %s' % (src, dst)) | ||
| 353 | + | ||
| 354 | + # Return | ||
| 355 | + return | ||
| 356 | + | ||
| 357 | + # Test workflow step | ||
| 358 | + def _test_step(self, tool, lines): | ||
| 359 | + """ | ||
| 360 | + Test workflow step | ||
| 361 | + | ||
| 362 | + Parameters | ||
| 363 | + ---------- | ||
| 364 | + tool : str | ||
| 365 | + Tool name | ||
| 366 | + lines : list of str | ||
| 367 | + Command lines | ||
| 368 | + """ | ||
| 369 | + # If tool is a ctool or cscript then test ctool or cscript execution | ||
| 370 | + if tool[0:2] == 'ct' or tool[0:2] == 'cs': | ||
| 371 | + self._test_ctool_execution(tool, lines) | ||
| 372 | + | ||
| 373 | + # ... otherwise test line execution | ||
| 374 | + else: | ||
| 375 | + all_lines = ['$ %s' % tool] | ||
| 376 | + all_lines.extend(lines) | ||
| 377 | + self._test_line_execution(all_lines) | ||
| 378 | + | ||
| 379 | + # Return | ||
| 380 | + return | ||
| 381 | + | ||
| 382 | + # Copy file | ||
| 383 | + def _copy_file(self, filename): | ||
| 384 | + """ | ||
| 385 | + Copy file from rst directory into working directory | ||
| 386 | + """ | ||
| 387 | + # Set source filename | ||
| 388 | + src = self._rst_path + '/' + filename | ||
| 389 | + | ||
| 390 | + # Copy file | ||
| 391 | + os.system('cp %s %s' % (src, filename)) | ||
| 392 | + | ||
| 393 | + # Return | ||
| 394 | + return | ||
| 395 | + | ||
| 396 | + # Test Sphinx rst file | ||
| 397 | + def _test_rst_file(self, filename): | ||
| 398 | + """ | ||
| 399 | + Test Sphinx rst file | ||
| 400 | + | ||
| 401 | + Parameters | ||
| 402 | + ---------- | ||
| 403 | + filename : str | ||
| 404 | + Sphinx rst filename | ||
| 405 | + """ | ||
| 406 | + # Set RST path | ||
| 407 | + self._rst_path = os.path.abspath(os.path.dirname(filename)) | ||
| 408 | + | ||
| 409 | + # Open RST file | ||
| 410 | + f = open(filename, 'r') | ||
| 411 | + | ||
| 412 | + # Signal code block | ||
| 413 | + code = False | ||
| 414 | + | ||
| 415 | + # Loop over lines | ||
| 416 | + for line in f: | ||
| 417 | + | ||
| 418 | + # If we are not in a code block then check whether a code block | ||
| 419 | + # starts | ||
| 420 | + if not code: | ||
| 421 | + | ||
| 422 | + # Check for start of a code block | ||
| 423 | + pos = line.find('code-block:: bash') | ||
| 424 | + if pos != -1: | ||
| 425 | + code = True | ||
| 426 | + start = -1 | ||
| 427 | + tool = '' | ||
| 428 | + lines = [] | ||
| 429 | + continue | ||
| 430 | + | ||
| 431 | + # ... otherwise check for literalinclude, and if found, copy | ||
| 432 | + # relevant file | ||
| 433 | + pos = line.find('literalinclude::') | ||
| 434 | + if pos != -1: | ||
| 435 | + filename = gammalib.strip_whitespace(line[pos+16:-1]) | ||
| 436 | + self._copy_file(filename) | ||
| 437 | + continue | ||
| 438 | + | ||
| 439 | + # ... otherwise | ||
| 440 | + else: | ||
| 441 | + | ||
| 442 | + # If we have no tool name then find tool name | ||
| 443 | + if tool == '': | ||
| 444 | + pos = line.find(' $ ') | ||
| 445 | + if pos != -1: | ||
| 446 | + start = pos+1 | ||
| 447 | + tool = line[pos+3:-1] | ||
| 448 | + continue | ||
| 449 | + | ||
| 450 | + # ... otherwise append lines or test step | ||
| 451 | + else: | ||
| 452 | + blank = gammalib.strip_whitespace(line[0:start]) | ||
| 453 | + cmd = line[start:-1] | ||
| 454 | + if len(blank) == 0 and cmd[0] != ' ': | ||
| 455 | + lines.append(cmd) | ||
| 456 | + continue | ||
| 457 | + else: | ||
| 458 | + self._test_step(tool, lines) | ||
| 459 | + code = False | ||
| 460 | + continue | ||
| 461 | + | ||
| 462 | + # Test step if some code is pending | ||
| 463 | + if code: | ||
| 464 | + self._test_step(tool, lines) | ||
| 465 | + | ||
| 466 | + # Return | ||
| 467 | + return | ||
| 468 | + | ||
| 469 | + # Set test functions | ||
| 470 | + def set(self): | ||
| 471 | + """ | ||
| 472 | + Set all test functions | ||
| 473 | + """ | ||
| 474 | + # Set current working directory | ||
| 475 | + self._cwd = os.path.abspath(os.getcwd()) | ||
| 476 | + | ||
| 477 | + # Set test name | ||
| 478 | + self.name('Tutorials Verification') | ||
| 479 | + | ||
| 480 | + # Append tutorials | ||
| 481 | + self.append(self.tutorials_quickstart, 'Test quickstart tutorial') | ||
| 482 | + self.append(self.tutorials_howto, 'Test howto tutorial') | ||
| 483 | + self.append(self.tutorials_1dc, 'Test 1DC tutorial') | ||
| 484 | + | ||
| 485 | + # Return | ||
| 486 | + return | ||
| 487 | + | ||
| 488 | + # Test quickstart tutorials | ||
| 489 | + def tutorials_quickstart(self): | ||
| 490 | + """ | ||
| 491 | + Test quickstart tutorials | ||
| 492 | + """ | ||
| 493 | + # Set Sphinx rst file path | ||
| 494 | + os.chdir(self._cwd) | ||
| 495 | + path = os.path.abspath('../doc/source/users/tutorials/quickstart') | ||
| 496 | + | ||
| 497 | + # Set result directory | ||
| 498 | + self._set_result_dir('tutorials/quickstart') | ||
| 499 | + | ||
| 500 | + # Clean pfiles | ||
| 501 | + self._clean_pfiles() | ||
| 502 | + | ||
| 503 | + # Initialise step counter | ||
| 504 | + self._rst_step = 0 | ||
| 505 | + | ||
| 506 | + # Test Sphinx rst files | ||
| 507 | + self._test_rst_file('%s/simulating.rst' % path) | ||
| 508 | + self._test_rst_file('%s/selecting.rst' % path) | ||
| 509 | + self._test_rst_file('%s/skymap.rst' % path) | ||
| 510 | + self._test_rst_file('%s/binning.rst' % path) | ||
| 511 | + self._test_rst_file('%s/response.rst' % path) | ||
| 512 | + self._test_rst_file('%s/fitting.rst' % path) | ||
| 513 | + self._test_rst_file('%s/residual_map.rst' % path) | ||
| 514 | + self._test_rst_file('%s/residual_spectrum.rst' % path) | ||
| 515 | + self._test_rst_file('%s/butterfly.rst' % path) | ||
| 516 | + self._test_rst_file('%s/spectrum.rst' % path) | ||
| 517 | + self._test_rst_file('%s/unbinned.rst' % path) | ||
| 518 | + self._test_rst_file('%s/energy_dispersion.rst' % path) | ||
| 519 | + self._test_rst_file('%s/onoff.rst' % path) | ||
| 520 | + | ||
| 521 | + # Reset working directory | ||
| 522 | + os.chdir(self._cwd) | ||
| 523 | + | ||
| 524 | + # Return | ||
| 525 | + return | ||
| 526 | + | ||
| 527 | + # Test 1DC tutorials | ||
| 528 | + def tutorials_1dc(self): | ||
| 529 | + """ | ||
| 530 | + Test 1DC tutorials | ||
| 531 | + """ | ||
| 532 | + # Continue only if CTADATA1DC environment variable is set | ||
| 533 | + if 'CTADATA1DC' in os.environ: | ||
| 534 | + | ||
| 535 | + # Set environment variables | ||
| 536 | + os.environ['CTADATA'] = os.environ['CTADATA1DC'] | ||
| 537 | + os.environ['CALDB'] = os.environ['CTADATA1DC']+'/caldb' | ||
| 538 | + | ||
| 539 | + # Set Sphinx rst file paths | ||
| 540 | + os.chdir(self._cwd) | ||
| 541 | + path_1dc = os.path.abspath('../doc/source/users/tutorials/1dc') | ||
| 542 | + path_howto = os.path.abspath('../doc/source/users/tutorials/howto') | ||
| 543 | + | ||
| 544 | + # Set result directory | ||
| 545 | + self._set_result_dir('tutorials/1dc') | ||
| 546 | + | ||
| 547 | + # Clean pfiles | ||
| 548 | + self._clean_pfiles() | ||
| 549 | + | ||
| 550 | + # Initialise step counter | ||
| 551 | + self._rst_step = 0 | ||
| 552 | + | ||
| 553 | + # Test Sphinx rst files | ||
| 554 | + self._test_rst_file('%s/first_select_obs.rst' % path_1dc) | ||
| 555 | + self._test_rst_file('%s/first_select_events.rst' % path_1dc) | ||
| 556 | + self._test_rst_file('%s/first_skymap.rst' % path_1dc) | ||
| 557 | + self._test_rst_file('%s/first_detect.rst' % path_1dc) | ||
| 558 | + self._test_rst_file('%s/first_stacked.rst' % path_1dc) | ||
| 559 | + self._test_rst_file('%s/first_fitting.rst' % path_1dc) | ||
| 560 | + self._test_rst_file('%s/first_improving.rst' % path_1dc) | ||
| 561 | + self._test_rst_file('%s/first_unbinned.rst' % path_1dc) | ||
| 562 | + | ||
| 563 | + # Test Sphinx rst files | ||
| 564 | + self._test_rst_file('%s/howto_ts.rst' % path_howto) | ||
| 565 | + self._test_rst_file('%s/howto_tsmap.rst' % path_howto) | ||
| 566 | + self._test_rst_file('%s/howto_extent.rst' % path_howto) | ||
| 567 | + self._test_rst_file('%s/howto_ulimit.rst' % path_howto) | ||
| 568 | + self._test_rst_file('%s/howto_lightcurve.rst' % path_howto) | ||
| 569 | + self._test_rst_file('%s/howto_phasecurve.rst' % path_howto) | ||
| 570 | + self._test_rst_file('%s/howto_exclude.rst' % path_howto) | ||
| 571 | + | ||
| 572 | + # Reset working directory | ||
| 573 | + os.chdir(self._cwd) | ||
| 574 | + | ||
| 575 | + # Clean pfiles | ||
| 576 | + self._clean_pfiles() | ||
| 577 | + | ||
| 578 | + # Initialise step counter | ||
| 579 | + self._rst_step = 0 | ||
| 580 | + | ||
| 581 | + # Test Sphinx rst file for On/Off analysis | ||
| 582 | + self._test_rst_file('%s/first_onoff.rst' % path_1dc) | ||
| 583 | + | ||
| 584 | + # Reset working directory | ||
| 585 | + os.chdir(self._cwd) | ||
| 586 | + | ||
| 587 | + # Return | ||
| 588 | + return | ||
| 589 | + | ||
| 590 | + # Test howto tutorials | ||
| 591 | + def tutorials_howto(self): | ||
| 592 | + """ | ||
| 593 | + Test howto tutorials | ||
| 594 | + """ | ||
| 595 | + # Set Sphinx rst file path | ||
| 596 | + os.chdir(self._cwd) | ||
| 597 | + path = os.path.abspath('../doc/source/users/tutorials/howto') | ||
| 598 | + | ||
| 599 | + # Set result directory | ||
| 600 | + self._set_result_dir('tutorials/howto') | ||
| 601 | + | ||
| 602 | + # Initialise step counter | ||
| 603 | + self._rst_step = 0 | ||
| 604 | + | ||
| 605 | + # Test Sphinx rst files | ||
| 606 | + self._clean_pfiles() | ||
| 607 | + self._test_rst_file('%s/howto_connect_irfs.rst' % path) | ||
| 608 | + self._clean_pfiles() | ||
| 609 | + self._test_rst_file('%s/howto_xspec.rst' % path) | ||
| 610 | + | ||
| 611 | + # Reset working directory | ||
| 612 | + os.chdir(self._cwd) | ||
| 613 | + | ||
| 614 | + # Return | ||
| 615 | + return | ||
| 616 | + | ||
| 617 | + | ||
| 618 | + | ||
| 619 | +# ======================== # | ||
| 620 | +# Main routine entry point # | ||
| 621 | +# ======================== # | ||
| 622 | +if __name__ == '__main__': | ||
| 623 | + | ||
| 624 | + # Allocate test suite container | ||
| 625 | + suites = gammalib.GTestSuites('ctools tutorials verification') | ||
| 626 | + | ||
| 627 | + # Allocate test suite and append it to the container | ||
| 628 | + suite_tutorials = tutorials() | ||
| 629 | + | ||
| 630 | + # Setup test suit | ||
| 631 | + suite_tutorials.set() | ||
| 632 | + | ||
| 633 | + # Append test suite to container | ||
| 634 | + suites.append(suite_tutorials) | ||
| 635 | + | ||
| 636 | + # Create tutorials/pfiles directory | ||
| 637 | + try: | ||
| 638 | + os.makedirs('tutorials/pfiles') | ||
| 639 | + except: | ||
| 640 | + pass | ||
| 641 | + | ||
| 642 | + # Set PFILES environment variable | ||
| 643 | + os.environ['PFILES'] = os.path.abspath('tutorials/pfiles') | ||
| 644 | + | ||
| 645 | + # Get current working directory | ||
| 646 | + cwd = os.getcwd() | ||
| 647 | + | ||
| 648 | + # Run test suite | ||
| 649 | + success = suites.run() | ||
| 650 | + | ||
| 651 | + # Reset working directory | ||
| 652 | + os.chdir(cwd) | ||
| 653 | + | ||
| 654 | + # Save test results | ||
| 655 | + suites.save('reports/tutorials.xml') | ||
| 656 | + | ||
| 657 | + # Set return code | ||
| 658 | + if success: | ||
| 659 | + rc = 0 | ||
| 660 | + else: | ||
| 661 | + rc = 1 | ||
| 662 | + | ||
| 663 | + # Exit with return code | ||
| 664 | + sys.exit(rc) |