Commit a0bc9bdf4397173fbe301dacec03224575318355
1 parent
70701752
Correct analysis scripts
Showing
4 changed files
with
755 additions
and
890 deletions
ChangeLog
NEWS
| 1 | -New Features and Important Changes in ctools 00-08-00 | |
| 1 | +New Features and Important Changes in ctools 1.0.0 | |
| 2 | 2 | |
| 3 | 3 | Author(s) : Juergen Knoedlseder |
| 4 | 4 | |
| 5 | -8 November 2014 | |
| 5 | +24 November 2014 | |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | 1. Introduction |
| ... | ... | @@ -10,16 +10,6 @@ Author(s) : Juergen Knoedlseder |
| 10 | 10 | This document briefly summarizes executable by executable the most |
| 11 | 11 | important changes made since the last release of ctools. |
| 12 | 12 | |
| 13 | -For all ctools, the public method interface was cleaned up so that | |
| 14 | -only methods that are really useful for an outside client are | |
| 15 | -exposed. Low-level methods that are used by the application are now | |
| 16 | -protected, as improper usage of these methods may lead to | |
| 17 | -unpredictable results. | |
| 18 | - | |
| 19 | -The ctool base class has been introduced and all tools now derive | |
| 20 | -from ctool instead of GApplication. This allows to avoid code | |
| 21 | -duplications and makes the code generally slimmer and more readable. | |
| 22 | - | |
| 23 | 13 | |
| 24 | 14 | 2. Configuration |
| 25 | 15 | ----------------- |
| ... | ... | @@ -33,108 +23,32 @@ None |
| 33 | 23 | |
| 34 | 24 | 4. Support model |
| 35 | 25 | ---------------- |
| 36 | -A support module has been introduced that will contain common classes | |
| 37 | -and functions. For the moment the only class in this module is the | |
| 38 | -ctool base class. | |
| 26 | +None | |
| 39 | 27 | |
| 40 | 28 | |
| 41 | 29 | 5. ctobssim - CTA observation simulation |
| 42 | 30 | ---------------------------------------- |
| 43 | -ctobssim was not fully thread save as the models were shared among the | |
| 44 | -threads which led to concurrent memory access when evaluating the Monte | |
| 45 | -Carlo cache. The models are now copied within the parallel section, | |
| 46 | -avoiding concurrent memory access (#1258). | |
| 47 | - | |
| 48 | -ctobssim now also supports the handling of energy dispersion. Energy | |
| 49 | -dispersion can be switched on or off using the hidden edisp parameter. | |
| 50 | - | |
| 51 | -The memory needs for ctobssim have been reduced by first working on a | |
| 52 | -local copy of the CTA observation (this de-allocates properly and memory | |
| 53 | -cache associated to the response functions), and by saving and disposing | |
| 54 | -the event lists immediately if called using the execute() method (this | |
| 55 | -is the method called when the tool is run from the command line). | |
| 31 | +None | |
| 56 | 32 | |
| 57 | 33 | |
| 58 | 34 | 6. ctselect - CTA event selection |
| 59 | 35 | --------------------------------- |
| 60 | -The temporary file is now properly close to avoid file opening errors | |
| 61 | -when iterating over ctselect (#1149). | |
| 62 | - | |
| 63 | -Non-CTA time references are now correctly handled by ctselect. While the | |
| 64 | -tmin and tmax parameters are given in CTA reference time, they are | |
| 65 | -internally converted to the reference time of the GTI before event | |
| 66 | -selection (#1329). | |
| 67 | - | |
| 68 | -ctselect now supports save and user energy thresholds (#1039). There | |
| 69 | -are three different possibilities for specifying a threshold. They | |
| 70 | -are toggled using the hidden usethres parameter: | |
| 71 | - | |
| 72 | -NONE: Use the emin and emax parameters to select an energy range. | |
| 73 | - This is the default mode which is identical to the previous | |
| 74 | - workings. The only difference is now that if the emin and/or | |
| 75 | - emax parameter is set to 0.0, the threshold will be ignored. | |
| 76 | - This allows to select all events above or below a given | |
| 77 | - threshold. | |
| 78 | - | |
| 79 | -DEFAULT: Use the save threshold that is found in the effective | |
| 80 | - area FITS header keywords LO_THRES and HI_THRES. If the | |
| 81 | - emin and emax parameters are non-zero, they will provide | |
| 82 | - an additional energy constraint. | |
| 83 | - | |
| 84 | -USER: Use the user specified threshold that are found in the | |
| 85 | - XML observation definition file. If the emin and emax | |
| 86 | - parameters are non-zero, they will provide an additional | |
| 87 | - energy constraint. | |
| 88 | - | |
| 89 | -Note that any existing energy boundaries will be used as envelope, | |
| 90 | -i.e. a wider energy threshold specification will have no effect. | |
| 36 | +None | |
| 91 | 37 | |
| 92 | 38 | |
| 93 | 39 | 7. ctbin - CTA event binning |
| 94 | 40 | ---------------------------- |
| 95 | -WARNING: The philosophy behind the ctbin tool changed fundamentally! | |
| 96 | - | |
| 97 | -ctbin now always produces a single counts cube on output. If a single | |
| 98 | -event list is specified on input, the functionnality is basically | |
| 99 | -unchanged. If multiple event lists are specified, however, events are | |
| 100 | -now merged into a single counts cube file. No observation definition | |
| 101 | -XML file is written anymore! | |
| 102 | - | |
| 103 | -So far, ctbin still writes pointing information in the counts cube, | |
| 104 | -although this is not necessarily meaningful if merging event lists | |
| 105 | -with different pointings. In the long run, pointing information will | |
| 106 | -be summarized in a pointings definition file, and will be removed | |
| 107 | -from the counts cube header. The logic is that the pointing definition | |
| 108 | -is set to the map centre. This is only identical to the pointing in | |
| 109 | -case of binning a single event list and using the usepnt=yes option | |
| 110 | -(or specifying the pointing manually as the xref and yref parameters). | |
| 111 | - | |
| 112 | -Memory usage has been reduced by disposing the event lists after their | |
| 113 | -usage. | |
| 41 | +None | |
| 114 | 42 | |
| 115 | 43 | |
| 116 | 44 | 8. ctlike - Maximum likelihood fitting |
| 117 | 45 | -------------------------------------- |
| 118 | -ctlike now has full access to the calibration database, allowing | |
| 119 | -the use for 2D response functions in FITS files. | |
| 120 | - | |
| 121 | -ctlike now also supports the handling of energy dispersion. Energy | |
| 122 | -dispersion can be switched on or off using the hidden edisp parameter. | |
| 46 | +None | |
| 123 | 47 | |
| 124 | 48 | |
| 125 | 49 | 9. cttsmap - Generation of Test Statistics map |
| 126 | 50 | ---------------------------------------------- |
| 127 | -The cttsmap tool has been added that provides a test statistics map | |
| 128 | -for a given set of observations. This tool is not restricted to CTA | |
| 129 | -data and will work for all types of instruments. | |
| 130 | - | |
| 131 | -cttsmap will move a test sources over a specified grid of positions | |
| 132 | -and compute the likelihood difference between having the source at | |
| 133 | -a given position and having not the source. Twice the likelihood | |
| 134 | -difference is called the Test Statistic. The computation is done for | |
| 135 | -a grid of positions, and the results is saved into a FITS file as | |
| 136 | -TS map. Also the value of the fitted parameters are stored as | |
| 137 | -extension in the FITS file. | |
| 51 | +None | |
| 138 | 52 | |
| 139 | 53 | |
| 140 | 54 | 10. ctskymap - CTA sky mapping |
| ... | ... | @@ -144,105 +58,45 @@ None |
| 144 | 58 | |
| 145 | 59 | 11. ctmodel - CTA counts cube modelling |
| 146 | 60 | --------------------------------------- |
| 147 | -WARNING: The philosophy behind the ctmodel tool changed fundamentally! | |
| 148 | - | |
| 149 | -ctmodel now always produces a single model cube on output. There are | |
| 150 | -two important input parameters: "infile" and "obsfile". "infile" | |
| 151 | -specifies a counts or model cube that is used to define the binning | |
| 152 | -of the model cube. The functionnality for this parameter is as before. | |
| 153 | -If "infile=NONE", the cube will be defined according to task parameters | |
| 154 | -that specify the spatial and the energy binning. The "obsfile" | |
| 155 | -parameter is new and allows specifying the observation definition | |
| 156 | -for which the model cube should be computed. If an event list or a | |
| 157 | -counts cube is presented, the pointing and Good Time Intervals will | |
| 158 | -be extracted from the FITS file header. If an observation definition | |
| 159 | -XML file is presented, ctmodel will now loop over all CTA observations | |
| 160 | -in the file and add the model values to the model cube. If no | |
| 161 | -response information is associated to the "obsfile" (which is typically | |
| 162 | -the case for event lists or counts cubes), the "caldb" and "irf" | |
| 163 | -parameters will be used to identify the response. | |
| 164 | - | |
| 165 | -ctmodel now has full access to the calibration database, allowing | |
| 166 | -the use for 2D response functions in FITS files. | |
| 167 | - | |
| 168 | -ctmodel now also supports the handling of energy dispersion. Energy | |
| 169 | -dispersion can be switched on or off using the hidden edisp parameter. | |
| 170 | - | |
| 171 | -Memory usage has been reduced by disposing the event lists after their | |
| 172 | -usage. | |
| 61 | +None | |
| 173 | 62 | |
| 174 | 63 | |
| 175 | 64 | 12. ctexpcube - CTA exposure cube generation |
| 176 | 65 | -------------------------------------------- |
| 177 | -The first version of the ctexpcube tool is included in the release. | |
| 178 | -ctexpcube computes the exposure cube for an observation definition | |
| 179 | -file. The cube definition may be taken from a counts cube or may be | |
| 180 | -specified by user parameters. | |
| 66 | +None | |
| 181 | 67 | |
| 182 | 68 | |
| 183 | 69 | 13. ctpsfcube - CTA point spread function cube generation |
| 184 | 70 | --------------------------------------------------------- |
| 185 | -The first version of the ctpsfcube tool is included in the release. | |
| 186 | -ctpsfcube computes the point spread function cube for an observation | |
| 187 | -definition file. The cube definition may be taken from a counts cube | |
| 188 | -or may be specified by user parameters. | |
| 71 | +None | |
| 189 | 72 | |
| 190 | 73 | |
| 191 | 74 | 14. ctbkgcube - CTA background cube generation |
| 192 | 75 | ---------------------------------------------- |
| 193 | -The first version of the ctbkgcube tool is included in the release. | |
| 194 | -ctbkgcube computes the background cube for an observation definition | |
| 195 | -file. The cube definition may be taken from a counts cube or may be | |
| 196 | -specified by user parameters. The tools also updates the input model | |
| 197 | -by replacing all IACT background model components by a single | |
| 198 | -background cube background model with a power law as spectral | |
| 199 | -parameter. The model container is available to Python using the | |
| 200 | -models() method or can be written into an XML file on disk. | |
| 76 | +None | |
| 201 | 77 | |
| 202 | 78 | |
| 203 | 79 | 15. ctcubemask - CTA cube filtering |
| 204 | 80 | ----------------------------------- |
| 205 | -The first version of the ctcubemask tool is included in the release. | |
| 206 | -ctcubemask allows filtering of bins in a counts cube by setting the | |
| 207 | -bin content to -1. Filtering can be done by energy, for a circular | |
| 208 | -Region of Interest (ROI) or using ds9 exclusion regions. | |
| 81 | +None | |
| 209 | 82 | |
| 210 | 83 | |
| 211 | 84 | 16. ctbutterfly - Generate butterfly diagrams |
| 212 | 85 | ============================================= |
| 213 | -The first version of the ctbutterfly tool is included in the release. | |
| 214 | -This tools derives a butterfly diagram from the fitted model parameters | |
| 215 | -for one specified source. The result will be written into an ASCII | |
| 216 | -file. | |
| 86 | +None | |
| 217 | 87 | |
| 218 | 88 | |
| 219 | 89 | 17. Examples |
| 220 | 90 | ------------ |
| 221 | -Added the following example scripts: | |
| 222 | -* pipeline_stacked.py (simulation and stacked analysis) | |
| 91 | +The following scripts have been adapted to fit the actual | |
| 92 | +interface definition | |
| 93 | +* make_binned_analysis.py | |
| 94 | +* make_unbinned_analysis.py | |
| 223 | 95 | |
| 224 | 96 | |
| 225 | 97 | 18. Scripts |
| 226 | 98 | ----------- |
| 227 | -Add logL and event statistics to cspull output file. | |
| 228 | - | |
| 229 | -Convert all tabs into spaces. | |
| 230 | - | |
| 231 | -The obsutils script has now been moved into the ctools module namespace. | |
| 232 | - | |
| 233 | -The following functions have been added to obsutils: | |
| 234 | -* set_obs() replaces the now obsolete set() function | |
| 235 | -* set_obs_list() returns an observation container filled with a list of | |
| 236 | - observations | |
| 237 | -* set_obs_patterns() defines standard patterns of CTA observations. | |
| 238 | - Current options are: | |
| 239 | - - "single": single pointing | |
| 240 | - - "four": four pointings offset by specific angle around centre | |
| 241 | -* spectrum() generates spectral points by fitting a source model in | |
| 242 | - specified energy bins. | |
| 243 | - | |
| 244 | -Add the csresmap script that uses ctbin and ctmodel to generate a | |
| 245 | -residual counts cube for a given model. | |
| 99 | +None | |
| 246 | 100 | |
| 247 | 101 | |
| 248 | 102 | 19. caldb | ... | ... |
examples/make_binned_analysis.py
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | # ctools. If matplotlib is installed, a counts spectrum and an offset |
| 5 | 5 | # histogram will be displayed. |
| 6 | 6 | # |
| 7 | -# Copyright (C) 2011-2012 Jurgen Knodlseder | |
| 7 | +# Copyright (C) 2011-2014 Jurgen Knodlseder | |
| 8 | 8 | # |
| 9 | 9 | # This program is free software: you can redistribute it and/or modify |
| 10 | 10 | # it under the terms of the GNU General Public License as published by |
| ... | ... | @@ -20,404 +20,404 @@ |
| 20 | 20 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 21 | 21 | # |
| 22 | 22 | # ========================================================================== |
| 23 | -from ctools import * | |
| 24 | -from gammalib import * | |
| 25 | -from math import * | |
| 23 | +import gammalib | |
| 24 | +import ctools | |
| 26 | 25 | import os |
| 27 | 26 | import glob |
| 28 | 27 | import sys |
| 28 | +import math | |
| 29 | 29 | try: |
| 30 | - import matplotlib.pyplot as plt | |
| 31 | - has_matplotlib = True | |
| 30 | + import matplotlib.pyplot as plt | |
| 31 | + has_matplotlib = True | |
| 32 | 32 | except: |
| 33 | - has_matplotlib = False | |
| 33 | + has_matplotlib = False | |
| 34 | 34 | |
| 35 | 35 | |
| 36 | 36 | # ============================= # |
| 37 | 37 | # Analysis pipeline - version 1 # |
| 38 | 38 | # ============================= # |
| 39 | 39 | def pipeline_v1(): |
| 40 | - """ | |
| 41 | - Binned analysis pipeline - save intermediate results. | |
| 40 | + """ | |
| 41 | + Binned analysis pipeline - save intermediate results. | |
| 42 | 42 | |
| 43 | 43 | This function implements an analysis pipeline that successively calls |
| 44 | 44 | ctobssim, ctbin and ctlike by saving the intermediate results as FITS |
| 45 | 45 | files on disk. This replicates the way how the analysis would be done |
| 46 | 46 | in a ftools-like approach. |
| 47 | - """ | |
| 48 | - # Set script parameters | |
| 49 | - model_name = "${CTOOLS}/share/models/crab.xml" | |
| 50 | - events_name = "events.fits" | |
| 51 | - cntmap_name = "cntmap.fits" | |
| 52 | - result_name = "results.xml" | |
| 53 | - caldb = "${CALDB}/data/cta/dummy/bcf" | |
| 54 | - irf = "cta_dummy_irf" | |
| 55 | - ra = 83.63 | |
| 56 | - dec = 22.01 | |
| 57 | - rad_sim = 10.0 | |
| 58 | - tstart = 0.0 | |
| 59 | - tstop = 1800.0 | |
| 60 | - emin = 0.1 | |
| 61 | - emax = 100.0 | |
| 62 | - enumbins = 20 | |
| 63 | - nxpix = 200 | |
| 64 | - nypix = 200 | |
| 65 | - binsz = 0.02 | |
| 66 | - coordsys = "CEL" | |
| 67 | - proj = "CAR" | |
| 68 | - | |
| 69 | - # Initialise timing | |
| 70 | - wall_seconds = 0.0 | |
| 71 | - cpu_seconds = 0.0 | |
| 72 | - | |
| 73 | - # Simulate events | |
| 74 | - sim = ctobssim() | |
| 75 | - sim.logFileOpen() # We need this to explicitely open the log file in Python mode | |
| 76 | - sim["infile"].filename(model_name) | |
| 77 | - sim["outfile"].filename(events_name) | |
| 78 | - sim["caldb"].string(caldb) | |
| 79 | - sim["irf"].string(irf) | |
| 80 | - sim["ra"].real(ra) | |
| 81 | - sim["dec"].real(dec) | |
| 82 | - sim["rad"].real(rad_sim) | |
| 83 | - sim["tmin"].real(tstart) | |
| 84 | - sim["tmax"].real(tstop) | |
| 85 | - sim["emin"].real(emin) | |
| 86 | - sim["emax"].real(emax) | |
| 87 | - sim.execute() | |
| 88 | - sys.stdout.write("Simulated events ("+str(sim.celapse())+" CPU seconds)\n") | |
| 89 | - | |
| 90 | - # Update timing | |
| 91 | - wall_seconds += sim.telapse() | |
| 92 | - cpu_seconds += sim.celapse() | |
| 93 | - | |
| 94 | - # Bin events into counts map | |
| 95 | - bin = ctbin() | |
| 96 | - bin.logFileOpen() # We need this to explicitely open the log file in Python mode | |
| 97 | - bin["evfile"].filename(events_name) | |
| 98 | - bin["outfile"].filename(cntmap_name) | |
| 99 | - bin["ebinalg"].string("LOG") | |
| 100 | - bin["emin"].real(emin) | |
| 101 | - bin["emax"].real(emax) | |
| 102 | - bin["enumbins"].integer(enumbins) | |
| 103 | - bin["nxpix"].integer(nxpix) | |
| 104 | - bin["nypix"].integer(nypix) | |
| 105 | - bin["binsz"].real(binsz) | |
| 106 | - bin["coordsys"].string(coordsys) | |
| 107 | - bin["xref"].real(ra) | |
| 108 | - bin["yref"].real(dec) | |
| 109 | - bin["proj"].string(proj) | |
| 110 | - bin.execute() | |
| 111 | - sys.stdout.write("Binned events into counts map ("+str(bin.celapse())+" CPU seconds)\n") | |
| 112 | - | |
| 113 | - # Update timing | |
| 114 | - wall_seconds += bin.telapse() | |
| 115 | - cpu_seconds += bin.celapse() | |
| 116 | - | |
| 117 | - # Perform maximum likelihood fitting | |
| 118 | - like = ctlike() | |
| 119 | - like.logFileOpen() # We need this to explicitely open the log file in Python mode | |
| 120 | - like["infile"].filename(cntmap_name) | |
| 121 | - like["srcmdl"].filename(model_name) | |
| 122 | - like["outmdl"].filename(result_name) | |
| 123 | - like["caldb"].string(caldb) | |
| 124 | - like["irf"].string(irf) | |
| 125 | - like.execute() | |
| 126 | - sys.stdout.write("Maximum likelihood fitting ("+str(like.celapse())+" CPU seconds)\n") | |
| 127 | - | |
| 128 | - # Update timing | |
| 129 | - wall_seconds += like.telapse() | |
| 130 | - cpu_seconds += like.celapse() | |
| 131 | - | |
| 132 | - # Show total times | |
| 133 | - sys.stdout.write("Total wall time elapsed: "+str(wall_seconds)+" seconds\n") | |
| 134 | - sys.stdout.write("Total CPU time used ...: "+str(cpu_seconds)+" seconds\n") | |
| 135 | - | |
| 136 | - # Return | |
| 137 | - return | |
| 47 | + """ | |
| 48 | + # Set script parameters | |
| 49 | + model_name = "${CTOOLS}/share/models/crab.xml" | |
| 50 | + events_name = "events.fits" | |
| 51 | + cntmap_name = "cntmap.fits" | |
| 52 | + result_name = "results.xml" | |
| 53 | + caldb = "${CALDB}/data/cta/dummy/bcf" | |
| 54 | + irf = "cta_dummy_irf" | |
| 55 | + ra = 83.63 | |
| 56 | + dec = 22.01 | |
| 57 | + rad_sim = 10.0 | |
| 58 | + tstart = 0.0 | |
| 59 | + tstop = 1800.0 | |
| 60 | + emin = 0.1 | |
| 61 | + emax = 100.0 | |
| 62 | + enumbins = 20 | |
| 63 | + nxpix = 200 | |
| 64 | + nypix = 200 | |
| 65 | + binsz = 0.02 | |
| 66 | + coordsys = "CEL" | |
| 67 | + proj = "CAR" | |
| 68 | + | |
| 69 | + # Initialise timing | |
| 70 | + wall_seconds = 0.0 | |
| 71 | + cpu_seconds = 0.0 | |
| 72 | + | |
| 73 | + # Simulate events | |
| 74 | + sim = ctools.ctobssim() | |
| 75 | + sim.logFileOpen() # We need this to explicitely open the log file in Python mode | |
| 76 | + sim["infile"].filename(model_name) | |
| 77 | + sim["outfile"].filename(events_name) | |
| 78 | + sim["caldb"].string(caldb) | |
| 79 | + sim["irf"].string(irf) | |
| 80 | + sim["ra"].real(ra) | |
| 81 | + sim["dec"].real(dec) | |
| 82 | + sim["rad"].real(rad_sim) | |
| 83 | + sim["tmin"].real(tstart) | |
| 84 | + sim["tmax"].real(tstop) | |
| 85 | + sim["emin"].real(emin) | |
| 86 | + sim["emax"].real(emax) | |
| 87 | + sim.execute() | |
| 88 | + sys.stdout.write("Simulated events ("+str(sim.celapse())+" CPU seconds)\n") | |
| 89 | + | |
| 90 | + # Update timing | |
| 91 | + wall_seconds += sim.telapse() | |
| 92 | + cpu_seconds += sim.celapse() | |
| 93 | + | |
| 94 | + # Bin events into counts map | |
| 95 | + bin = ctools.ctbin() | |
| 96 | + bin.logFileOpen() # We need this to explicitely open the log file in Python mode | |
| 97 | + bin["evfile"].filename(events_name) | |
| 98 | + bin["outfile"].filename(cntmap_name) | |
| 99 | + bin["ebinalg"].string("LOG") | |
| 100 | + bin["emin"].real(emin) | |
| 101 | + bin["emax"].real(emax) | |
| 102 | + bin["enumbins"].integer(enumbins) | |
| 103 | + bin["nxpix"].integer(nxpix) | |
| 104 | + bin["nypix"].integer(nypix) | |
| 105 | + bin["binsz"].real(binsz) | |
| 106 | + bin["coordsys"].string(coordsys) | |
| 107 | + bin["xref"].real(ra) | |
| 108 | + bin["yref"].real(dec) | |
| 109 | + bin["proj"].string(proj) | |
| 110 | + bin.execute() | |
| 111 | + sys.stdout.write("Binned events into counts map ("+str(bin.celapse())+" CPU seconds)\n") | |
| 112 | + | |
| 113 | + # Update timing | |
| 114 | + wall_seconds += bin.telapse() | |
| 115 | + cpu_seconds += bin.celapse() | |
| 116 | + | |
| 117 | + # Perform maximum likelihood fitting | |
| 118 | + like = ctools.ctlike() | |
| 119 | + like.logFileOpen() # We need this to explicitely open the log file in Python mode | |
| 120 | + like["infile"].filename(cntmap_name) | |
| 121 | + like["srcmdl"].filename(model_name) | |
| 122 | + like["outmdl"].filename(result_name) | |
| 123 | + like["caldb"].string(caldb) | |
| 124 | + like["irf"].string(irf) | |
| 125 | + like.execute() | |
| 126 | + sys.stdout.write("Maximum likelihood fitting ("+str(like.celapse())+" CPU seconds)\n") | |
| 127 | + | |
| 128 | + # Update timing | |
| 129 | + wall_seconds += like.telapse() | |
| 130 | + cpu_seconds += like.celapse() | |
| 131 | + | |
| 132 | + # Show total times | |
| 133 | + sys.stdout.write("Total wall time elapsed: "+str(wall_seconds)+" seconds\n") | |
| 134 | + sys.stdout.write("Total CPU time used ...: "+str(cpu_seconds)+" seconds\n") | |
| 135 | + | |
| 136 | + # Return | |
| 137 | + return | |
| 138 | 138 | |
| 139 | 139 | |
| 140 | 140 | # ============================= # |
| 141 | 141 | # Analysis pipeline - version 2 # |
| 142 | 142 | # ============================= # |
| 143 | 143 | def pipeline_v2(): |
| 144 | - """ | |
| 145 | - Binned analysis pipeline - keep intermediate results in memory. | |
| 144 | + """ | |
| 145 | + Binned analysis pipeline - keep intermediate results in memory. | |
| 146 | 146 | |
| 147 | 147 | This function implements an analysis pipeline that successively calls |
| 148 | 148 | ctobssim, ctbin and ctlike without saving the intermediate results as |
| 149 | - FITS files on disk. All data are hold in memory. | |
| 150 | - | |
| 151 | - At the end, results are plotted (if matplotlib is installed) | |
| 152 | - """ | |
| 153 | - # Set script parameters | |
| 154 | - model_name = "${CTOOLS}/share/models/crab.xml" | |
| 155 | - caldb = "${CALDB}/data/cta/dummy/bcf" | |
| 156 | - irf = "cta_dummy_irf" | |
| 157 | - ra = 83.63 | |
| 158 | - dec = 22.01 | |
| 159 | - rad_sim = 10.0 | |
| 160 | - tstart = 0.0 | |
| 161 | - tstop = 1800.0 | |
| 162 | - emin = 0.1 | |
| 163 | - emax = 100.0 | |
| 164 | - enumbins = 20 | |
| 165 | - nxpix = 200 | |
| 166 | - nypix = 200 | |
| 167 | - binsz = 0.02 | |
| 168 | - coordsys = "CEL" | |
| 169 | - proj = "CAR" | |
| 170 | - | |
| 171 | - # Initialise timing | |
| 172 | - wall_seconds = 0.0 | |
| 173 | - cpu_seconds = 0.0 | |
| 174 | - | |
| 175 | - # Simulate events | |
| 176 | - sim = ctobssim() | |
| 177 | - sim["infile"].filename(model_name) | |
| 178 | - sim["caldb"].string(caldb) | |
| 179 | - sim["irf"].string(irf) | |
| 180 | - sim["ra"].real(ra) | |
| 181 | - sim["dec"].real(dec) | |
| 182 | - sim["rad"].real(rad_sim) | |
| 183 | - sim["tmin"].real(tstart) | |
| 184 | - sim["tmax"].real(tstop) | |
| 185 | - sim["emin"].real(emin) | |
| 186 | - sim["emax"].real(emax) | |
| 187 | - sim.run() | |
| 188 | - sys.stdout.write("Simulated events ("+str(sim.celapse())+" CPU seconds)\n") | |
| 189 | - | |
| 190 | - # Update timing | |
| 191 | - wall_seconds += sim.telapse() | |
| 192 | - cpu_seconds += sim.celapse() | |
| 193 | - | |
| 194 | - # Bin events into counts map | |
| 195 | - bin = ctbin(sim.obs()) | |
| 196 | - bin["ebinalg"].string("LOG") | |
| 197 | - bin["emin"].real(emin) | |
| 198 | - bin["emax"].real(emax) | |
| 199 | - bin["enumbins"].integer(enumbins) | |
| 200 | - bin["nxpix"].integer(nxpix) | |
| 201 | - bin["nypix"].integer(nypix) | |
| 202 | - bin["binsz"].real(binsz) | |
| 203 | - bin["coordsys"].string(coordsys) | |
| 204 | - bin["xref"].real(ra) | |
| 205 | - bin["yref"].real(dec) | |
| 206 | - bin["proj"].string(proj) | |
| 207 | - bin.run() | |
| 208 | - sys.stdout.write("Binned events into counts map ("+str(bin.celapse())+" CPU seconds)\n") | |
| 209 | - | |
| 210 | - # Update timing | |
| 211 | - wall_seconds += bin.telapse() | |
| 212 | - cpu_seconds += bin.celapse() | |
| 213 | - | |
| 214 | - # Perform maximum likelihood fitting | |
| 215 | - like = ctlike(bin.obs()) | |
| 216 | - like.run() | |
| 217 | - sys.stdout.write("Maximum likelihood fitting ("+str(like.celapse())+" CPU seconds)\n") | |
| 218 | - | |
| 219 | - # Update timing | |
| 220 | - wall_seconds += like.telapse() | |
| 221 | - cpu_seconds += like.celapse() | |
| 222 | - | |
| 223 | - # Show total times | |
| 224 | - sys.stdout.write("Total wall time elapsed: "+str(wall_seconds)+" seconds\n") | |
| 225 | - sys.stdout.write("Total CPU time used ...: "+str(cpu_seconds)+" seconds\n") | |
| 226 | - | |
| 227 | - # Show model fitting results | |
| 228 | - #sys.stdout.write(like.obs().models()+"\n") | |
| 229 | - | |
| 230 | - # Plot counts | |
| 231 | - if has_matplotlib: | |
| 232 | - plot_counts(bin.obs()) | |
| 233 | - else: | |
| 234 | - sys.stdout.write("Matplotlib is not (correctly) installed on your system. No counts spectra are shown.\n") | |
| 235 | - | |
| 236 | - # Return | |
| 237 | - return | |
| 149 | + FITS files on disk. All data are hold in memory. | |
| 150 | + | |
| 151 | + At the end, results are plotted (if matplotlib is installed) | |
| 152 | + """ | |
| 153 | + # Set script parameters | |
| 154 | + model_name = "${CTOOLS}/share/models/crab.xml" | |
| 155 | + caldb = "${CALDB}/data/cta/dummy/bcf" | |
| 156 | + irf = "cta_dummy_irf" | |
| 157 | + ra = 83.63 | |
| 158 | + dec = 22.01 | |
| 159 | + rad_sim = 10.0 | |
| 160 | + tstart = 0.0 | |
| 161 | + tstop = 1800.0 | |
| 162 | + emin = 0.1 | |
| 163 | + emax = 100.0 | |
| 164 | + enumbins = 20 | |
| 165 | + nxpix = 200 | |
| 166 | + nypix = 200 | |
| 167 | + binsz = 0.02 | |
| 168 | + coordsys = "CEL" | |
| 169 | + proj = "CAR" | |
| 170 | + | |
| 171 | + # Initialise timing | |
| 172 | + wall_seconds = 0.0 | |
| 173 | + cpu_seconds = 0.0 | |
| 174 | + | |
| 175 | + # Simulate events | |
| 176 | + sim = ctools.ctobssim() | |
| 177 | + sim["infile"].filename(model_name) | |
| 178 | + sim["caldb"].string(caldb) | |
| 179 | + sim["irf"].string(irf) | |
| 180 | + sim["ra"].real(ra) | |
| 181 | + sim["dec"].real(dec) | |
| 182 | + sim["rad"].real(rad_sim) | |
| 183 | + sim["tmin"].real(tstart) | |
| 184 | + sim["tmax"].real(tstop) | |
| 185 | + sim["emin"].real(emin) | |
| 186 | + sim["emax"].real(emax) | |
| 187 | + sim.run() | |
| 188 | + sys.stdout.write("Simulated events ("+str(sim.celapse())+" CPU seconds)\n") | |
| 189 | + | |
| 190 | + # Update timing | |
| 191 | + wall_seconds += sim.telapse() | |
| 192 | + cpu_seconds += sim.celapse() | |
| 193 | + | |
| 194 | + # Bin events into counts map | |
| 195 | + bin = ctools.ctbin(sim.obs()) | |
| 196 | + bin["ebinalg"].string("LOG") | |
| 197 | + bin["emin"].real(emin) | |
| 198 | + bin["emax"].real(emax) | |
| 199 | + bin["enumbins"].integer(enumbins) | |
| 200 | + bin["nxpix"].integer(nxpix) | |
| 201 | + bin["nypix"].integer(nypix) | |
| 202 | + bin["binsz"].real(binsz) | |
| 203 | + bin["coordsys"].string(coordsys) | |
| 204 | + bin["xref"].real(ra) | |
| 205 | + bin["yref"].real(dec) | |
| 206 | + bin["proj"].string(proj) | |
| 207 | + bin.run() | |
| 208 | + sys.stdout.write("Binned events into counts map ("+str(bin.celapse())+" CPU seconds)\n") | |
| 209 | + | |
| 210 | + # Update timing | |
| 211 | + wall_seconds += bin.telapse() | |
| 212 | + cpu_seconds += bin.celapse() | |
| 213 | + | |
| 214 | + # Perform maximum likelihood fitting | |
| 215 | + like = ctools.ctlike(bin.obs()) | |
| 216 | + like.run() | |
| 217 | + sys.stdout.write("Maximum likelihood fitting ("+str(like.celapse())+" CPU seconds)\n") | |
| 218 | + | |
| 219 | + # Update timing | |
| 220 | + wall_seconds += like.telapse() | |
| 221 | + cpu_seconds += like.celapse() | |
| 222 | + | |
| 223 | + # Show total times | |
| 224 | + sys.stdout.write("Total wall time elapsed: "+str(wall_seconds)+" seconds\n") | |
| 225 | + sys.stdout.write("Total CPU time used ...: "+str(cpu_seconds)+" seconds\n") | |
| 226 | + | |
| 227 | + # Show model fitting results | |
| 228 | + #sys.stdout.write(like.obs().models()+"\n") | |
| 229 | + | |
| 230 | + # Plot counts | |
| 231 | + if has_matplotlib: | |
| 232 | + plot_counts(bin.obs()) | |
| 233 | + else: | |
| 234 | + sys.stdout.write("Matplotlib is not (correctly) installed on your system. No counts spectra are shown.\n") | |
| 235 | + | |
| 236 | + # Return | |
| 237 | + return | |
| 238 | 238 | |
| 239 | 239 | |
| 240 | 240 | # =========== # |
| 241 | 241 | # Plot counts # |
| 242 | 242 | # =========== # |
| 243 | 243 | def plot_counts(observations): |
| 244 | - """ | |
| 245 | - Plot counts. | |
| 246 | - """ | |
| 247 | - # Set legend fontsize | |
| 248 | - params = {'legend.fontsize': 10} | |
| 249 | - plt.rcParams.update(params) | |
| 250 | - | |
| 251 | - # Set plot styles | |
| 252 | - styles = ['b-', 'g-', 'y-', 'n-'] | |
| 253 | - | |
| 254 | - # Dump header | |
| 255 | - sys.stdout.write("\n") | |
| 256 | - sys.stdout.write("Make plots (using matplotlib):\n") | |
| 257 | - sys.stdout.write("==============================\n") | |
| 258 | - | |
| 259 | - # Create figure 1 | |
| 260 | - plt.figure(1,figsize=(12,6)) | |
| 261 | - plt.subplots_adjust(hspace=.7) | |
| 262 | - | |
| 263 | - # Create subplot 1 | |
| 264 | - plt.subplot(121) | |
| 265 | - plt.title("Spectrum (summed over all pixels)") | |
| 266 | - | |
| 267 | - # Loop over observations | |
| 268 | - for obs in observations: | |
| 269 | - | |
| 270 | - # Get event cube | |
| 271 | - cube = obs.events() | |
| 272 | - | |
| 273 | - # Create energy axis | |
| 274 | - energy = [] | |
| 275 | - ebounds = cube.ebounds() | |
| 276 | - for i in range(ebounds.size()): | |
| 277 | - energy.append(ebounds.elogmean(i).TeV()) | |
| 278 | - | |
| 279 | - # Create spectrum | |
| 280 | - sys.stdout.write("Extract data:\n") | |
| 281 | - counts = [0.0 for i in range(ebounds.size())] | |
| 282 | - for bin in cube: | |
| 283 | - index = ebounds.index(bin.energy()) | |
| 284 | - counts[index] = counts[index] + bin.counts() | |
| 285 | - | |
| 286 | - # Create error bars | |
| 287 | - error = [sqrt(c) for c in counts] | |
| 288 | - | |
| 289 | - # Plot spectrum | |
| 290 | - plt.loglog(energy, counts, 'ro', label='data') | |
| 291 | - plt.errorbar(energy, counts, error, fmt=None, ecolor='r') | |
| 292 | - | |
| 293 | - # Extract models | |
| 294 | - sys.stdout.write("Extract models:\n") | |
| 295 | - sum_model = [0.0 for i in range(ebounds.size())] | |
| 296 | - for k, m in enumerate(observations.models()): | |
| 297 | - sys.stdout.write("- "+m.name()+"\n") | |
| 298 | - model = [0.0 for i in range(ebounds.size())] | |
| 299 | - for bin in cube: | |
| 300 | - index = ebounds.index(bin.energy()) | |
| 301 | - prob = m.eval(bin, obs) | |
| 302 | - model[index] = model[index] + prob * bin.size() | |
| 303 | - for i in range(ebounds.size()): | |
| 304 | - sum_model[i] = sum_model[i] + model[i] | |
| 305 | - plt.loglog(energy, model, styles[k], label=m.name()) | |
| 306 | - plt.loglog(energy, sum_model, 'r-', label='total') | |
| 307 | - | |
| 308 | - # Put labels | |
| 309 | - plt.xlabel("Energy (TeV)") | |
| 310 | - plt.ylabel("Counts") | |
| 311 | - plt.legend(loc="lower left") | |
| 312 | - | |
| 313 | - # Create subplot 2 | |
| 314 | - plt.subplot(122) | |
| 315 | - plt.title("Offset (summed over all energies)") | |
| 316 | - | |
| 317 | - # Set Crab direction | |
| 318 | - crab = GSkyDir() | |
| 319 | - crab.radec_deg(83.63, 22.01) | |
| 320 | - | |
| 321 | - # Loop over observations | |
| 322 | - for obs in observations: | |
| 323 | - | |
| 324 | - # Get event cube | |
| 325 | - cube = obs.events() | |
| 326 | - | |
| 327 | - # Create offset histogram | |
| 328 | - sys.stdout.write("Extract data:\n") | |
| 329 | - nx = 30 | |
| 330 | - doffset2 = 0.01 | |
| 331 | - offset2 = [(i+0.5)*doffset2 for i in range(nx)] | |
| 332 | - counts = [0.0 for i in range(nx)] | |
| 333 | - for bin in cube: | |
| 334 | - off = GCTAInstDir(bin.dir()).dir().dist_deg(crab) | |
| 335 | - off2 = off*off | |
| 336 | - index = int(off2/doffset2) | |
| 337 | - if index < nx: | |
| 338 | - counts[index] = counts[index] + bin.counts() | |
| 339 | - | |
| 340 | - # Create error bars | |
| 341 | - error = [sqrt(c) for c in counts] | |
| 342 | - | |
| 343 | - # Plot distribution | |
| 344 | - plt.semilogy(offset2, counts, 'ro', label='data') | |
| 345 | - | |
| 346 | - # Extract models | |
| 347 | - sys.stdout.write("Extract models:\n") | |
| 348 | - sum_model = [0.0 for i in range(nx)] | |
| 349 | - for k, m in enumerate(observations.models()): | |
| 350 | - sys.stdout.write("- "+m.name()+"\n") | |
| 351 | - model = [0.0 for i in range(nx)] | |
| 352 | - for bin in cube: | |
| 353 | - off = GCTAInstDir(bin.dir()).dir().dist_deg(crab) | |
| 354 | - off2 = off*off | |
| 355 | - index = int(off2/doffset2) | |
| 356 | - if index < nx: | |
| 357 | - prob = m.eval(bin, obs) | |
| 358 | - model[index] = model[index] + prob * bin.size() | |
| 359 | - for i in range(nx): | |
| 360 | - sum_model[i] = sum_model[i] + model[i] | |
| 361 | - plt.plot(offset2, model, styles[k], label=m.name()) | |
| 362 | - plt.plot(offset2, sum_model, 'r-', label='total') | |
| 363 | - plt.ylim(ymin=0.1) | |
| 364 | - | |
| 365 | - # Put labels | |
| 366 | - plt.xlabel("Offset (deg^2)") | |
| 367 | - plt.ylabel("Counts") | |
| 368 | - plt.legend(loc="upper right") | |
| 369 | - | |
| 370 | - # Show counts spectra | |
| 371 | - plt.show() | |
| 372 | - | |
| 373 | - # Return | |
| 374 | - return | |
| 244 | + """ | |
| 245 | + Plot counts. | |
| 246 | + """ | |
| 247 | + # Set legend fontsize | |
| 248 | + params = {'legend.fontsize': 10} | |
| 249 | + plt.rcParams.update(params) | |
| 250 | + | |
| 251 | + # Set plot styles | |
| 252 | + styles = ['b-', 'g-', 'y-', 'n-'] | |
| 253 | + | |
| 254 | + # Dump header | |
| 255 | + sys.stdout.write("\n") | |
| 256 | + sys.stdout.write("Make plots (using matplotlib):\n") | |
| 257 | + sys.stdout.write("==============================\n") | |
| 258 | + | |
| 259 | + # Create figure 1 | |
| 260 | + plt.figure(1,figsize=(12,6)) | |
| 261 | + plt.subplots_adjust(hspace=.7) | |
| 262 | + | |
| 263 | + # Create subplot 1 | |
| 264 | + plt.subplot(121) | |
| 265 | + plt.title("Spectrum (summed over all pixels)") | |
| 266 | + | |
| 267 | + # Loop over observations | |
| 268 | + for obs in observations: | |
| 269 | + | |
| 270 | + # Get event cube | |
| 271 | + cube = obs.events() | |
| 272 | + | |
| 273 | + # Create energy axis | |
| 274 | + energy = [] | |
| 275 | + ebounds = cube.ebounds() | |
| 276 | + for i in range(ebounds.size()): | |
| 277 | + energy.append(ebounds.elogmean(i).TeV()) | |
| 278 | + | |
| 279 | + # Create spectrum | |
| 280 | + sys.stdout.write("Extract data:\n") | |
| 281 | + counts = [0.0 for i in range(ebounds.size())] | |
| 282 | + for bin in cube: | |
| 283 | + index = ebounds.index(bin.energy()) | |
| 284 | + counts[index] = counts[index] + bin.counts() | |
| 285 | + | |
| 286 | + # Create error bars | |
| 287 | + error = [math.sqrt(c) for c in counts] | |
| 288 | + | |
| 289 | + # Plot spectrum | |
| 290 | + plt.loglog(energy, counts, 'ro', label='data') | |
| 291 | + plt.errorbar(energy, counts, error, fmt=None, ecolor='r') | |
| 292 | + | |
| 293 | + # Extract models | |
| 294 | + sys.stdout.write("Extract models:\n") | |
| 295 | + sum_model = [0.0 for i in range(ebounds.size())] | |
| 296 | + for k, m in enumerate(observations.models()): | |
| 297 | + sys.stdout.write("- "+m.name()+"\n") | |
| 298 | + model = [0.0 for i in range(ebounds.size())] | |
| 299 | + for bin in cube: | |
| 300 | + index = ebounds.index(bin.energy()) | |
| 301 | + prob = m.eval(bin, obs) | |
| 302 | + model[index] = model[index] + prob * bin.size() | |
| 303 | + for i in range(ebounds.size()): | |
| 304 | + sum_model[i] = sum_model[i] + model[i] | |
| 305 | + plt.loglog(energy, model, styles[k], label=m.name()) | |
| 306 | + plt.loglog(energy, sum_model, 'r-', label='total') | |
| 307 | + | |
| 308 | + # Put labels | |
| 309 | + plt.xlabel("Energy (TeV)") | |
| 310 | + plt.ylabel("Counts") | |
| 311 | + plt.legend(loc="lower left") | |
| 312 | + | |
| 313 | + # Create subplot 2 | |
| 314 | + plt.subplot(122) | |
| 315 | + plt.title("Offset (summed over all energies)") | |
| 316 | + | |
| 317 | + # Set Crab direction | |
| 318 | + crab = gammalib.GSkyDir() | |
| 319 | + crab.radec_deg(83.63, 22.01) | |
| 320 | + | |
| 321 | + # Loop over observations | |
| 322 | + for obs in observations: | |
| 323 | + | |
| 324 | + # Get event cube | |
| 325 | + cube = obs.events() | |
| 326 | + | |
| 327 | + # Create offset histogram | |
| 328 | + sys.stdout.write("Extract data:\n") | |
| 329 | + nx = 30 | |
| 330 | + doffset2 = 0.01 | |
| 331 | + offset2 = [(i+0.5)*doffset2 for i in range(nx)] | |
| 332 | + counts = [0.0 for i in range(nx)] | |
| 333 | + for bin in cube: | |
| 334 | + off = gammalib.GCTAInstDir(bin.dir()).dir().dist_deg(crab) | |
| 335 | + off2 = off*off | |
| 336 | + index = int(off2/doffset2) | |
| 337 | + if index < nx: | |
| 338 | + counts[index] = counts[index] + bin.counts() | |
| 339 | + | |
| 340 | + # Create error bars | |
| 341 | + error = [math.sqrt(c) for c in counts] | |
| 342 | + | |
| 343 | + # Plot distribution | |
| 344 | + plt.semilogy(offset2, counts, 'ro', label='data') | |
| 345 | + | |
| 346 | + # Extract models | |
| 347 | + sys.stdout.write("Extract models:\n") | |
| 348 | + sum_model = [0.0 for i in range(nx)] | |
| 349 | + for k, m in enumerate(observations.models()): | |
| 350 | + sys.stdout.write("- "+m.name()+"\n") | |
| 351 | + model = [0.0 for i in range(nx)] | |
| 352 | + for bin in cube: | |
| 353 | + off = gammalib.GCTAInstDir(bin.dir()).dir().dist_deg(crab) | |
| 354 | + off2 = off*off | |
| 355 | + index = int(off2/doffset2) | |
| 356 | + if index < nx: | |
| 357 | + prob = m.eval(bin, obs) | |
| 358 | + model[index] = model[index] + prob * bin.size() | |
| 359 | + for i in range(nx): | |
| 360 | + sum_model[i] = sum_model[i] + model[i] | |
| 361 | + plt.plot(offset2, model, styles[k], label=m.name()) | |
| 362 | + plt.plot(offset2, sum_model, 'r-', label='total') | |
| 363 | + plt.ylim(ymin=0.1) | |
| 364 | + | |
| 365 | + # Put labels | |
| 366 | + plt.xlabel("Offset (deg^2)") | |
| 367 | + plt.ylabel("Counts") | |
| 368 | + plt.legend(loc="upper right") | |
| 369 | + | |
| 370 | + # Show counts spectra | |
| 371 | + plt.show() | |
| 372 | + | |
| 373 | + # Return | |
| 374 | + return | |
| 375 | 375 | |
| 376 | 376 | |
| 377 | 377 | #==========================# |
| 378 | 378 | # Main routine entry point # |
| 379 | 379 | #==========================# |
| 380 | 380 | if __name__ == '__main__': |
| 381 | - """ | |
| 382 | - CTA binned analysis script. | |
| 383 | - | |
| 384 | - This script implements the analysis steps to perform a binned analysis. | |
| 385 | - The steps include: | |
| 386 | - - Event simulation | |
| 387 | - - Event binning | |
| 388 | - - Binned maximum likelihood fitting | |
| 389 | - | |
| 390 | - Two variations of the script are implemented. One that calls the classes | |
| 391 | - like executables, storing the intermediate results on disk, and a second | |
| 392 | - that uses the results of the precedent class directly without storing | |
| 393 | - any data on disk. | |
| 394 | - | |
| 395 | - The second variation will also show a counts spectrum of the data after | |
| 396 | - fitting (only if matplotlib is available on your system). Note that the | |
| 397 | - counts spectrum is summed over the entire data space, i.e. no event selection | |
| 398 | - around the Crab has been performed. | |
| 399 | - """ | |
| 400 | - # Dump header | |
| 401 | - sys.stdout.write("*************************************\n") | |
| 402 | - sys.stdout.write("* CTA binned analysis scripts *\n") | |
| 403 | - sys.stdout.write("*************************************\n") | |
| 404 | - sys.stdout.write("... this script will take 1-2 minutes\n") | |
| 405 | - | |
| 406 | - # Remove any existing result files | |
| 407 | - list = [glob.glob("*.fits"), glob.glob("*.log"), glob.glob("*.xml")] | |
| 408 | - for files in list: | |
| 409 | - for file in files: | |
| 410 | - os.remove(file) | |
| 411 | - | |
| 412 | - # Save intermediate results on disk | |
| 413 | - sys.stdout.write("\n") | |
| 414 | - sys.stdout.write("Executable analysis pipeline:\n") | |
| 415 | - sys.stdout.write("=============================\n") | |
| 416 | - pipeline_v1() | |
| 417 | - | |
| 418 | - # Do analysis in memory | |
| 419 | - sys.stdout.write("\n") | |
| 420 | - sys.stdout.write("In memory analysis pipeline:\n") | |
| 421 | - sys.stdout.write("============================\n") | |
| 422 | - pipeline_v2() | |
| 423 | - sys.stdout.write("\n") | |
| 381 | + """ | |
| 382 | + CTA binned analysis script. | |
| 383 | + | |
| 384 | + This script implements the analysis steps to perform a binned analysis. | |
| 385 | + The steps include: | |
| 386 | + - Event simulation | |
| 387 | + - Event binning | |
| 388 | + - Binned maximum likelihood fitting | |
| 389 | + | |
| 390 | + Two variations of the script are implemented. One that calls the classes | |
| 391 | + like executables, storing the intermediate results on disk, and a second | |
| 392 | + that uses the results of the precedent class directly without storing | |
| 393 | + any data on disk. | |
| 394 | + | |
| 395 | + The second variation will also show a counts spectrum of the data after | |
| 396 | + fitting (only if matplotlib is available on your system). Note that the | |
| 397 | + counts spectrum is summed over the entire data space, i.e. no event selection | |
| 398 | + around the Crab has been performed. | |
| 399 | + """ | |
| 400 | + # Dump header | |
| 401 | + sys.stdout.write("*************************************\n") | |
| 402 | + sys.stdout.write("* CTA binned analysis scripts *\n") | |
| 403 | + sys.stdout.write("*************************************\n") | |
| 404 | + sys.stdout.write("... this script will take 1-2 minutes\n") | |
| 405 | + | |
| 406 | + # Remove any existing result files | |
| 407 | + list = [glob.glob("*.fits"), glob.glob("*.log"), glob.glob("*.xml")] | |
| 408 | + for files in list: | |
| 409 | + for file in files: | |
| 410 | + os.remove(file) | |
| 411 | + | |
| 412 | + # Save intermediate results on disk | |
| 413 | + sys.stdout.write("\n") | |
| 414 | + sys.stdout.write("Executable analysis pipeline:\n") | |
| 415 | + sys.stdout.write("=============================\n") | |
| 416 | + pipeline_v1() | |
| 417 | + | |
| 418 | + # Do analysis in memory | |
| 419 | + sys.stdout.write("\n") | |
| 420 | + sys.stdout.write("In memory analysis pipeline:\n") | |
| 421 | + sys.stdout.write("============================\n") | |
| 422 | + pipeline_v2() | |
| 423 | + sys.stdout.write("\n") | ... | ... |
examples/make_unbinned_analysis.py
| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | # Required 3rd party modules: |
| 8 | 8 | # None |
| 9 | 9 | # |
| 10 | -# Copyright (C) 2011 Jurgen Knodlseder | |
| 10 | +# Copyright (C) 2011-2014 Jurgen Knodlseder | |
| 11 | 11 | # |
| 12 | 12 | # This program is free software: you can redistribute it and/or modify |
| 13 | 13 | # it under the terms of the GNU General Public License as published by |
| ... | ... | @@ -23,399 +23,402 @@ |
| 23 | 23 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 24 | 24 | # |
| 25 | 25 | # ========================================================================== |
| 26 | -from ctools import * | |
| 27 | -from gammalib import * | |
| 28 | -from math import * | |
| 26 | +#from ctools import * | |
| 27 | +#from gammalib import * | |
| 28 | +#from math import * | |
| 29 | +import gammalib | |
| 30 | +import ctools | |
| 31 | +import math | |
| 29 | 32 | import os |
| 30 | 33 | import glob |
| 31 | 34 | import sys |
| 32 | 35 | try: |
| 33 | - import matplotlib.pyplot as plt | |
| 34 | - has_matplotlib = True | |
| 36 | + import matplotlib.pyplot as plt | |
| 37 | + has_matplotlib = True | |
| 35 | 38 | except: |
| 36 | - has_matplotlib = False | |
| 39 | + has_matplotlib = False | |
| 37 | 40 | |
| 38 | 41 | |
| 39 | 42 | # ============================= # |
| 40 | 43 | # Analysis pipeline - version 1 # |
| 41 | 44 | # ============================= # |
| 42 | 45 | def pipeline_v1(): |
| 43 | - """ | |
| 44 | - Unbinned analysis pipeline - save intermediate results. | |
| 46 | + """ | |
| 47 | + Unbinned analysis pipeline - save intermediate results. | |
| 45 | 48 | |
| 46 | 49 | This function implements an analysis pipeline that successively calls |
| 47 | 50 | ctobssim, ctselect and ctlike by saving the intermediate results as FITS |
| 48 | 51 | files on disk. This replicates the way how the analysis would be done |
| 49 | 52 | in a ftools-like approach. |
| 50 | - """ | |
| 51 | - # Set script parameters | |
| 52 | - model_name = "${CTOOLS}/share/models/crab.xml" | |
| 53 | - events_name = "events.fits" | |
| 54 | - selected_events_name = "selected_events.fits" | |
| 55 | - result_name = "results.xml" | |
| 56 | - caldb = "${CALDB}/data/cta/dummy/bcf" | |
| 57 | - irf = "cta_dummy_irf" | |
| 58 | - ra = 83.63 | |
| 59 | - dec = 22.01 | |
| 60 | - rad_sim = 10.0 | |
| 61 | - tstart = 0.0 | |
| 62 | - tstop = 1800.0 | |
| 63 | - emin = 0.1 | |
| 64 | - emax = 100.0 | |
| 65 | - rad_select = 3.0 | |
| 66 | - | |
| 67 | - # Initialise timing | |
| 68 | - wall_seconds = 0.0 | |
| 69 | - cpu_seconds = 0.0 | |
| 70 | - | |
| 71 | - # Simulate events | |
| 72 | - sim = ctobssim() | |
| 73 | - sim.logFileOpen() | |
| 74 | - sim["infile"].filename(model_name) | |
| 75 | - sim["outfile"].filename(events_name) | |
| 76 | - sim["caldb"].string(caldb) | |
| 77 | - sim["irf"].string(irf) | |
| 78 | - sim["ra"].real(ra) | |
| 79 | - sim["dec"].real(dec) | |
| 80 | - sim["rad"].real(rad_sim) | |
| 81 | - sim["tmin"].real(tstart) | |
| 82 | - sim["tmax"].real(tstop) | |
| 83 | - sim["emin"].real(emin) | |
| 84 | - sim["emax"].real(emax) | |
| 85 | - sim.execute() | |
| 86 | - print("Simulated events ("+str(sim.celapse())+" CPU seconds)") | |
| 87 | - | |
| 88 | - # Update timing | |
| 89 | - wall_seconds += sim.telapse() | |
| 90 | - cpu_seconds += sim.celapse() | |
| 91 | - | |
| 92 | - # Select events | |
| 93 | - select = ctselect() | |
| 94 | - select.logFileOpen() | |
| 95 | - select["infile"].filename(events_name) | |
| 96 | - select["outfile"].filename(selected_events_name) | |
| 97 | - select["ra"].real(ra) | |
| 98 | - select["dec"].real(dec) | |
| 99 | - select["rad"].real(rad_select) | |
| 100 | - select["tmin"].real(tstart) | |
| 101 | - select["tmax"].real(tstop) | |
| 102 | - select["emin"].real(emin) | |
| 103 | - select["emax"].real(emax) | |
| 104 | - select.execute() | |
| 105 | - print("Select event ("+str(select.celapse())+" CPU seconds)") | |
| 106 | - | |
| 107 | - # Update timing | |
| 108 | - wall_seconds += select.telapse() | |
| 109 | - cpu_seconds += select.celapse() | |
| 110 | - | |
| 111 | - # Perform maximum likelihood fitting | |
| 112 | - like = ctlike() | |
| 113 | - like.logFileOpen() | |
| 114 | - like["infile"].filename(selected_events_name) | |
| 115 | - like["srcmdl"].filename(model_name) | |
| 116 | - like["outmdl"].filename(result_name) | |
| 117 | - like["caldb"].string(caldb) | |
| 118 | - like["irf"].string(irf) | |
| 119 | - like.execute() | |
| 120 | - print("Maximum likelihood fitting ("+str(like.celapse())+" CPU seconds)") | |
| 121 | - | |
| 122 | - # Update timing | |
| 123 | - wall_seconds += like.telapse() | |
| 124 | - cpu_seconds += like.celapse() | |
| 125 | - | |
| 126 | - # Show total times | |
| 127 | - print("Total wall time elapsed: "+str(wall_seconds)+" seconds") | |
| 128 | - print("Total CPU time used ...: "+str(cpu_seconds)+" seconds") | |
| 129 | - | |
| 130 | - # Return | |
| 131 | - return | |
| 53 | + """ | |
| 54 | + # Set script parameters | |
| 55 | + model_name = "${CTOOLS}/share/models/crab.xml" | |
| 56 | + events_name = "events.fits" | |
| 57 | + selected_events_name = "selected_events.fits" | |
| 58 | + result_name = "results.xml" | |
| 59 | + caldb = "${CALDB}/data/cta/dummy/bcf" | |
| 60 | + irf = "cta_dummy_irf" | |
| 61 | + ra = 83.63 | |
| 62 | + dec = 22.01 | |
| 63 | + rad_sim = 10.0 | |
| 64 | + tstart = 0.0 | |
| 65 | + tstop = 1800.0 | |
| 66 | + emin = 0.1 | |
| 67 | + emax = 100.0 | |
| 68 | + rad_select = 3.0 | |
| 69 | + | |
| 70 | + # Initialise timing | |
| 71 | + wall_seconds = 0.0 | |
| 72 | + cpu_seconds = 0.0 | |
| 73 | + | |
| 74 | + # Simulate events | |
| 75 | + sim = ctools.ctobssim() | |
| 76 | + sim.logFileOpen() | |
| 77 | + sim["infile"].filename(model_name) | |
| 78 | + sim["outfile"].filename(events_name) | |
| 79 | + sim["caldb"].string(caldb) | |
| 80 | + sim["irf"].string(irf) | |
| 81 | + sim["ra"].real(ra) | |
| 82 | + sim["dec"].real(dec) | |
| 83 | + sim["rad"].real(rad_sim) | |
| 84 | + sim["tmin"].real(tstart) | |
| 85 | + sim["tmax"].real(tstop) | |
| 86 | + sim["emin"].real(emin) | |
| 87 | + sim["emax"].real(emax) | |
| 88 | + sim.execute() | |
| 89 | + print("Simulated events ("+str(sim.celapse())+" CPU seconds)") | |
| 90 | + | |
| 91 | + # Update timing | |
| 92 | + wall_seconds += sim.telapse() | |
| 93 | + cpu_seconds += sim.celapse() | |
| 94 | + | |
| 95 | + # Select events | |
| 96 | + select = ctools.ctselect() | |
| 97 | + select.logFileOpen() | |
| 98 | + select["infile"].filename(events_name) | |
| 99 | + select["outfile"].filename(selected_events_name) | |
| 100 | + select["ra"].real(ra) | |
| 101 | + select["dec"].real(dec) | |
| 102 | + select["rad"].real(rad_select) | |
| 103 | + select["tmin"].real(tstart) | |
| 104 | + select["tmax"].real(tstop) | |
| 105 | + select["emin"].real(emin) | |
| 106 | + select["emax"].real(emax) | |
| 107 | + select.execute() | |
| 108 | + print("Select event ("+str(select.celapse())+" CPU seconds)") | |
| 109 | + | |
| 110 | + # Update timing | |
| 111 | + wall_seconds += select.telapse() | |
| 112 | + cpu_seconds += select.celapse() | |
| 113 | + | |
| 114 | + # Perform maximum likelihood fitting | |
| 115 | + like = ctools.ctlike() | |
| 116 | + like.logFileOpen() | |
| 117 | + like["infile"].filename(selected_events_name) | |
| 118 | + like["srcmdl"].filename(model_name) | |
| 119 | + like["outmdl"].filename(result_name) | |
| 120 | + like["caldb"].string(caldb) | |
| 121 | + like["irf"].string(irf) | |
| 122 | + like.execute() | |
| 123 | + print("Maximum likelihood fitting ("+str(like.celapse())+" CPU seconds)") | |
| 124 | + | |
| 125 | + # Update timing | |
| 126 | + wall_seconds += like.telapse() | |
| 127 | + cpu_seconds += like.celapse() | |
| 128 | + | |
| 129 | + # Show total times | |
| 130 | + print("Total wall time elapsed: "+str(wall_seconds)+" seconds") | |
| 131 | + print("Total CPU time used ...: "+str(cpu_seconds)+" seconds") | |
| 132 | + | |
| 133 | + # Return | |
| 134 | + return | |
| 132 | 135 | |
| 133 | 136 | |
| 134 | 137 | # ============================= # |
| 135 | 138 | # Analysis pipeline - version 2 # |
| 136 | 139 | # ============================= # |
| 137 | 140 | def pipeline_v2(show_data): |
| 138 | - """ | |
| 139 | - Unbinned analysis pipeline - keep intermediate results in memory. | |
| 141 | + """ | |
| 142 | + Unbinned analysis pipeline - keep intermediate results in memory. | |
| 140 | 143 | |
| 141 | 144 | This function implements an analysis pipeline that successively calls |
| 142 | 145 | ctobssim, ctselect and ctlike without saving the intermediate results as |
| 143 | - FITS files on disk. All data is only hold in memory. | |
| 144 | - """ | |
| 145 | - # Set script parameters | |
| 146 | - model_name = "${CTOOLS}/share/models/crab.xml" | |
| 147 | - caldb = "${CALDB}/data/cta/dummy/bcf" | |
| 148 | - irf = "cta_dummy_irf" | |
| 149 | - ra = 83.63 | |
| 150 | - dec = 22.01 | |
| 151 | - rad_sim = 10.0 | |
| 152 | - tstart = 0.0 | |
| 153 | - tstop = 1800.0 | |
| 154 | - emin = 0.1 | |
| 155 | - emax = 100.0 | |
| 156 | - rad_select = 3.0 | |
| 157 | - | |
| 158 | - # Initialise timing | |
| 159 | - wall_seconds = 0.0 | |
| 160 | - cpu_seconds = 0.0 | |
| 161 | - | |
| 162 | - # Simulate events | |
| 163 | - sim = ctobssim() | |
| 164 | - sim["infile"].filename(model_name) | |
| 165 | - sim["caldb"].string(caldb) | |
| 166 | - sim["irf"].string(irf) | |
| 167 | - sim["ra"].real(ra) | |
| 168 | - sim["dec"].real(dec) | |
| 169 | - sim["rad"].real(rad_sim) | |
| 170 | - sim["tmin"].real(tstart) | |
| 171 | - sim["tmax"].real(tstop) | |
| 172 | - sim["emin"].real(emin) | |
| 173 | - sim["emax"].real(emax) | |
| 174 | - sim.run() | |
| 175 | - print("Simulated events ("+str(sim.celapse())+" CPU seconds)") | |
| 176 | - | |
| 177 | - # Update timing | |
| 178 | - wall_seconds += sim.telapse() | |
| 179 | - cpu_seconds += sim.celapse() | |
| 180 | - | |
| 181 | - # Select events | |
| 182 | - select = ctselect(sim.obs()) | |
| 183 | - select["ra"].real(ra) | |
| 184 | - select["dec"].real(dec) | |
| 185 | - select["rad"].real(rad_select) | |
| 186 | - select["tmin"].real(tstart) | |
| 187 | - select["tmax"].real(tstop) | |
| 188 | - select["emin"].real(emin) | |
| 189 | - select["emax"].real(emax) | |
| 190 | - select.run() | |
| 191 | - print("Select event ("+str(select.celapse())+" CPU seconds)") | |
| 192 | - | |
| 193 | - # Update timing | |
| 194 | - wall_seconds += select.telapse() | |
| 195 | - cpu_seconds += select.celapse() | |
| 196 | - | |
| 197 | - # Perform maximum likelihood fitting | |
| 198 | - like = ctlike(select.obs()) | |
| 199 | - like.run() | |
| 200 | - print("Maximum likelihood fitting ("+str(like.celapse())+" CPU seconds)") | |
| 201 | - | |
| 202 | - # Update timing | |
| 203 | - wall_seconds += like.telapse() | |
| 204 | - cpu_seconds += like.celapse() | |
| 205 | - | |
| 206 | - # Show total times | |
| 207 | - print("Total wall time elapsed: "+str(wall_seconds)+" seconds") | |
| 208 | - print("Total CPU time used ...: "+str(cpu_seconds)+" seconds") | |
| 209 | - | |
| 210 | - # Show model fitting results | |
| 211 | - #print like.obs().models() | |
| 212 | - | |
| 213 | - # Optionally plot counts | |
| 214 | - if show_data: | |
| 215 | - if has_matplotlib: | |
| 216 | - plot_counts(like.obs()) | |
| 217 | - else: | |
| 218 | - sys.stdout.write("Matplotlib is not (correctly) installed on your system. No counts spectra are shown.\n") | |
| 219 | - | |
| 220 | - # Return | |
| 221 | - return | |
| 146 | + FITS files on disk. All data is only hold in memory. | |
| 147 | + """ | |
| 148 | + # Set script parameters | |
| 149 | + model_name = "${CTOOLS}/share/models/crab.xml" | |
| 150 | + caldb = "${CALDB}/data/cta/dummy/bcf" | |
| 151 | + irf = "cta_dummy_irf" | |
| 152 | + ra = 83.63 | |
| 153 | + dec = 22.01 | |
| 154 | + rad_sim = 10.0 | |
| 155 | + tstart = 0.0 | |
| 156 | + tstop = 1800.0 | |
| 157 | + emin = 0.1 | |
| 158 | + emax = 100.0 | |
| 159 | + rad_select = 3.0 | |
| 160 | + | |
| 161 | + # Initialise timing | |
| 162 | + wall_seconds = 0.0 | |
| 163 | + cpu_seconds = 0.0 | |
| 164 | + | |
| 165 | + # Simulate events | |
| 166 | + sim = ctools.ctobssim() | |
| 167 | + sim["infile"].filename(model_name) | |
| 168 | + sim["caldb"].string(caldb) | |
| 169 | + sim["irf"].string(irf) | |
| 170 | + sim["ra"].real(ra) | |
| 171 | + sim["dec"].real(dec) | |
| 172 | + sim["rad"].real(rad_sim) | |
| 173 | + sim["tmin"].real(tstart) | |
| 174 | + sim["tmax"].real(tstop) | |
| 175 | + sim["emin"].real(emin) | |
| 176 | + sim["emax"].real(emax) | |
| 177 | + sim.run() | |
| 178 | + print("Simulated events ("+str(sim.celapse())+" CPU seconds)") | |
| 179 | + | |
| 180 | + # Update timing | |
| 181 | + wall_seconds += sim.telapse() | |
| 182 | + cpu_seconds += sim.celapse() | |
| 183 | + | |
| 184 | + # Select events | |
| 185 | + select = ctools.ctselect(sim.obs()) | |
| 186 | + select["ra"].real(ra) | |
| 187 | + select["dec"].real(dec) | |
| 188 | + select["rad"].real(rad_select) | |
| 189 | + select["tmin"].real(tstart) | |
| 190 | + select["tmax"].real(tstop) | |
| 191 | + select["emin"].real(emin) | |
| 192 | + select["emax"].real(emax) | |
| 193 | + select.run() | |
| 194 | + print("Select event ("+str(select.celapse())+" CPU seconds)") | |
| 195 | + | |
| 196 | + # Update timing | |
| 197 | + wall_seconds += select.telapse() | |
| 198 | + cpu_seconds += select.celapse() | |
| 199 | + | |
| 200 | + # Perform maximum likelihood fitting | |
| 201 | + like = ctools.ctlike(select.obs()) | |
| 202 | + like.run() | |
| 203 | + print("Maximum likelihood fitting ("+str(like.celapse())+" CPU seconds)") | |
| 204 | + | |
| 205 | + # Update timing | |
| 206 | + wall_seconds += like.telapse() | |
| 207 | + cpu_seconds += like.celapse() | |
| 208 | + | |
| 209 | + # Show total times | |
| 210 | + print("Total wall time elapsed: "+str(wall_seconds)+" seconds") | |
| 211 | + print("Total CPU time used ...: "+str(cpu_seconds)+" seconds") | |
| 212 | + | |
| 213 | + # Show model fitting results | |
| 214 | + #print like.obs().models() | |
| 215 | + | |
| 216 | + # Optionally plot counts | |
| 217 | + if show_data: | |
| 218 | + if has_matplotlib: | |
| 219 | + plot_counts(like.obs()) | |
| 220 | + else: | |
| 221 | + sys.stdout.write("Matplotlib is not (correctly) installed on your system. No counts spectra are shown.\n") | |
| 222 | + | |
| 223 | + # Return | |
| 224 | + return | |
| 222 | 225 | |
| 223 | 226 | |
| 224 | 227 | # =========== # |
| 225 | 228 | # Plot counts # |
| 226 | 229 | # =========== # |
| 227 | 230 | def plot_counts(observations): |
| 228 | - """ | |
| 229 | - Plot counts. | |
| 230 | - """ | |
| 231 | - # Set legend fontsize | |
| 232 | - params = {'legend.fontsize': 10} | |
| 233 | - plt.rcParams.update(params) | |
| 234 | - | |
| 235 | - # Set plot styles | |
| 236 | - styles = ['b-', 'g-', 'y-', 'n-'] | |
| 237 | - | |
| 238 | - # Dump header | |
| 239 | - print("") | |
| 240 | - print("Make plots (using matplotlib):") | |
| 241 | - print("==============================") | |
| 242 | - | |
| 243 | - # Create figure 1 | |
| 244 | - plt.figure(1,figsize=(12,6)) | |
| 245 | - plt.subplots_adjust(hspace=.7) | |
| 246 | - | |
| 247 | - # Create subplot 1 | |
| 248 | - plt.subplot(121) | |
| 249 | - plt.title("Spectrum (summed over all pixels)") | |
| 250 | - | |
| 251 | - # Loop over observations | |
| 252 | - for obs in observations: | |
| 253 | - | |
| 254 | - # Get event list | |
| 255 | - list = obs.events() | |
| 256 | - | |
| 257 | - # Create energy axis | |
| 258 | - ebounds = GEbounds(10, GEnergy(0.1, "TeV"), GEnergy(100.0, "TeV")) | |
| 259 | - energy = [ebounds.elogmean(i).TeV() for i in range(ebounds.size())] | |
| 260 | - | |
| 261 | - # Create spectrum | |
| 262 | - print("Extract data:") | |
| 263 | - counts = [0.0 for i in range(ebounds.size())] | |
| 264 | - print(list.size()) | |
| 265 | - for atom in list: | |
| 266 | - index = ebounds.index(atom.energy()) | |
| 267 | - counts[index] = counts[index] + 1.0 | |
| 268 | - | |
| 269 | - # Create error bars | |
| 270 | - error = [sqrt(c) for c in counts] | |
| 271 | - | |
| 272 | - # Plot spectrum | |
| 273 | - plt.loglog(energy, counts, 'ro', label='data') | |
| 274 | - #plt.errorbar(energy, counts, error, fmt=None, ecolor='r') | |
| 275 | - | |
| 276 | - # Extract models | |
| 277 | - #print("Extract models:") | |
| 278 | - #sum_model = [0.0 for i in range(ebounds.size())] | |
| 279 | - #for k, m in enumerate(observations.models()): | |
| 280 | - # print("- "+m.name()) | |
| 281 | - # model = [0.0 for i in range(ebounds.size())] | |
| 282 | - # for atom in list: | |
| 283 | - # index = ebounds.index(atom.energy()) | |
| 284 | - # prob = m.eval(atom, obs) | |
| 285 | - # model[index] = model[index] + prob * atom.size() | |
| 286 | - # for i in range(ebounds.size()): | |
| 287 | - # sum_model[i] = sum_model[i] + model[i] | |
| 288 | - # plt.loglog(energy, model, styles[k], label=m.name()) | |
| 289 | - #plt.loglog(energy, sum_model, 'r-', label='total') | |
| 290 | - | |
| 291 | - # Put labels | |
| 292 | - plt.xlabel("Energy (TeV)") | |
| 293 | - plt.ylabel("Counts") | |
| 294 | - plt.legend(loc="lower left") | |
| 295 | - | |
| 296 | - # Create subplot 2 | |
| 297 | - plt.subplot(122) | |
| 298 | - plt.title("Offset (summed over all energies)") | |
| 299 | - | |
| 300 | - # Set Crab direction | |
| 301 | - crab = GSkyDir() | |
| 302 | - crab.radec_deg(83.63, 22.01) | |
| 303 | - | |
| 304 | - # Loop over observations | |
| 305 | - for obs in observations: | |
| 306 | - | |
| 307 | - # Get event cube | |
| 308 | - list = obs.events() | |
| 309 | - | |
| 310 | - # Create offset histogram | |
| 311 | - print "Extract data:" | |
| 312 | - nx = 30 | |
| 313 | - doffset2 = 0.01 | |
| 314 | - offset2 = [(i+0.5)*doffset2 for i in range(nx)] | |
| 315 | - counts = [0.0 for i in range(nx)] | |
| 316 | - for atom in list: | |
| 317 | - off = GCTAInstDir(atom.dir()).dir().dist_deg(crab) | |
| 318 | - off2 = off*off | |
| 319 | - index = int(off2/doffset2) | |
| 320 | - if index < nx: | |
| 321 | - counts[index] = counts[index] + 1.0 | |
| 322 | - | |
| 323 | - # Create error bars | |
| 324 | - error = [sqrt(c) for c in counts] | |
| 325 | - | |
| 326 | - # Plot distribution | |
| 327 | - plt.semilogy(offset2, counts, 'ro', label='data') | |
| 328 | - | |
| 329 | - # Extract models | |
| 330 | - print "Extract models:" | |
| 331 | - sum_model = [0.0 for i in range(nx)] | |
| 332 | - for k, m in enumerate(observations.models()): | |
| 333 | - print "- "+m.name() | |
| 334 | - model = [0.0 for i in range(nx)] | |
| 335 | - for atom in list: | |
| 336 | - off = GCTAInstDir(atom.dir()).dir().dist_deg(crab) | |
| 337 | - off2 = off*off | |
| 338 | - index = int(off2/doffset2) | |
| 339 | - if index < nx: | |
| 340 | - prob = m.eval(atom, obs) | |
| 341 | - model[index] = model[index] + prob * atom.size() | |
| 342 | - for i in range(nx): | |
| 343 | - sum_model[i] = sum_model[i] + model[i] | |
| 344 | - #plt.plot(offset2, model, styles[k], label=m.name()) | |
| 345 | - #plt.plot(offset2, sum_model, 'r-', label='total') | |
| 346 | - #plt.ylim(ymin=0.1) | |
| 347 | - | |
| 348 | - # Put labels | |
| 349 | - plt.xlabel("Offset (deg^2)") | |
| 350 | - plt.ylabel("Counts") | |
| 351 | - plt.legend(loc="upper right") | |
| 352 | - | |
| 353 | - # Show counts spectra | |
| 354 | - plt.show() | |
| 355 | - | |
| 356 | - # Return | |
| 357 | - return | |
| 231 | + """ | |
| 232 | + Plot counts. | |
| 233 | + """ | |
| 234 | + # Set legend fontsize | |
| 235 | + params = {'legend.fontsize': 10} | |
| 236 | + plt.rcParams.update(params) | |
| 237 | + | |
| 238 | + # Set plot styles | |
| 239 | + styles = ['b-', 'g-', 'y-', 'n-'] | |
| 240 | + | |
| 241 | + # Dump header | |
| 242 | + print("") | |
| 243 | + print("Make plots (using matplotlib):") | |
| 244 | + print("==============================") | |
| 245 | + | |
| 246 | + # Create figure 1 | |
| 247 | + plt.figure(1,figsize=(12,6)) | |
| 248 | + plt.subplots_adjust(hspace=.7) | |
| 249 | + | |
| 250 | + # Create subplot 1 | |
| 251 | + plt.subplot(121) | |
| 252 | + plt.title("Spectrum (summed over all pixels)") | |
| 253 | + | |
| 254 | + # Loop over observations | |
| 255 | + for obs in observations: | |
| 256 | + | |
| 257 | + # Get event list | |
| 258 | + list = obs.events() | |
| 259 | + | |
| 260 | + # Create energy axis | |
| 261 | + ebounds = gammalib.GEbounds(10, gammalib.GEnergy(0.1, "TeV"), gammalib.GEnergy(100.0, "TeV")) | |
| 262 | + energy = [ebounds.elogmean(i).TeV() for i in range(ebounds.size())] | |
| 263 | + | |
| 264 | + # Create spectrum | |
| 265 | + print("Extract data:") | |
| 266 | + counts = [0.0 for i in range(ebounds.size())] | |
| 267 | + print(list.size()) | |
| 268 | + for atom in list: | |
| 269 | + index = ebounds.index(atom.energy()) | |
| 270 | + counts[index] = counts[index] + 1.0 | |
| 271 | + | |
| 272 | + # Create error bars | |
| 273 | + error = [math.sqrt(c) for c in counts] | |
| 274 | + | |
| 275 | + # Plot spectrum | |
| 276 | + plt.loglog(energy, counts, 'ro', label='data') | |
| 277 | + #plt.errorbar(energy, counts, error, fmt=None, ecolor='r') | |
| 278 | + | |
| 279 | + # Extract models | |
| 280 | + #print("Extract models:") | |
| 281 | + #sum_model = [0.0 for i in range(ebounds.size())] | |
| 282 | + #for k, m in enumerate(observations.models()): | |
| 283 | + # print("- "+m.name()) | |
| 284 | + # model = [0.0 for i in range(ebounds.size())] | |
| 285 | + # for atom in list: | |
| 286 | + # index = ebounds.index(atom.energy()) | |
| 287 | + # prob = m.eval(atom, obs) | |
| 288 | + # model[index] = model[index] + prob * atom.size() | |
| 289 | + # for i in range(ebounds.size()): | |
| 290 | + # sum_model[i] = sum_model[i] + model[i] | |
| 291 | + # plt.loglog(energy, model, styles[k], label=m.name()) | |
| 292 | + #plt.loglog(energy, sum_model, 'r-', label='total') | |
| 293 | + | |
| 294 | + # Put labels | |
| 295 | + plt.xlabel("Energy (TeV)") | |
| 296 | + plt.ylabel("Counts") | |
| 297 | + plt.legend(loc="lower left") | |
| 298 | + | |
| 299 | + # Create subplot 2 | |
| 300 | + plt.subplot(122) | |
| 301 | + plt.title("Offset (summed over all energies)") | |
| 302 | + | |
| 303 | + # Set Crab direction | |
| 304 | + crab = gammalib.GSkyDir() | |
| 305 | + crab.radec_deg(83.63, 22.01) | |
| 306 | + | |
| 307 | + # Loop over observations | |
| 308 | + for obs in observations: | |
| 309 | + | |
| 310 | + # Get event cube | |
| 311 | + list = obs.events() | |
| 312 | + | |
| 313 | + # Create offset histogram | |
| 314 | + print "Extract data:" | |
| 315 | + nx = 30 | |
| 316 | + doffset2 = 0.01 | |
| 317 | + offset2 = [(i+0.5)*doffset2 for i in range(nx)] | |
| 318 | + counts = [0.0 for i in range(nx)] | |
| 319 | + for atom in list: | |
| 320 | + off = gammalib.GCTAInstDir(atom.dir()).dir().dist_deg(crab) | |
| 321 | + off2 = off*off | |
| 322 | + index = int(off2/doffset2) | |
| 323 | + if index < nx: | |
| 324 | + counts[index] = counts[index] + 1.0 | |
| 325 | + | |
| 326 | + # Create error bars | |
| 327 | + error = [math.sqrt(c) for c in counts] | |
| 328 | + | |
| 329 | + # Plot distribution | |
| 330 | + plt.semilogy(offset2, counts, 'ro', label='data') | |
| 331 | + | |
| 332 | + # Extract models | |
| 333 | + print "Extract models:" | |
| 334 | + sum_model = [0.0 for i in range(nx)] | |
| 335 | + for k, m in enumerate(observations.models()): | |
| 336 | + print "- "+m.name() | |
| 337 | + model = [0.0 for i in range(nx)] | |
| 338 | + for atom in list: | |
| 339 | + off = gammalib.GCTAInstDir(atom.dir()).dir().dist_deg(crab) | |
| 340 | + off2 = off*off | |
| 341 | + index = int(off2/doffset2) | |
| 342 | + if index < nx: | |
| 343 | + prob = m.eval(atom, obs) | |
| 344 | + model[index] = model[index] + prob * atom.size() | |
| 345 | + for i in range(nx): | |
| 346 | + sum_model[i] = sum_model[i] + model[i] | |
| 347 | + #plt.plot(offset2, model, styles[k], label=m.name()) | |
| 348 | + #plt.plot(offset2, sum_model, 'r-', label='total') | |
| 349 | + #plt.ylim(ymin=0.1) | |
| 350 | + | |
| 351 | + # Put labels | |
| 352 | + plt.xlabel("Offset (deg^2)") | |
| 353 | + plt.ylabel("Counts") | |
| 354 | + plt.legend(loc="upper right") | |
| 355 | + | |
| 356 | + # Show counts spectra | |
| 357 | + plt.show() | |
| 358 | + | |
| 359 | + # Return | |
| 360 | + return | |
| 358 | 361 | |
| 359 | 362 | |
| 360 | 363 | #==========================# |
| 361 | 364 | # Main routine entry point # |
| 362 | 365 | #==========================# |
| 363 | 366 | if __name__ == '__main__': |
| 364 | - """ | |
| 365 | - CTA unbinned analysis script. | |
| 366 | - | |
| 367 | - This script implements the analysis steps to perform an unbinned analysis. | |
| 368 | - The steps include: | |
| 369 | - - Event simulation | |
| 370 | - - Event selection | |
| 371 | - - Binned maximum likelihood fitting | |
| 372 | - | |
| 373 | - Two variations of the script are implemented. One that calls the classes | |
| 374 | - like executables, storing the intermediate results on disk, and a second | |
| 375 | - that uses the results of the precedent class directly without storing | |
| 376 | - any data on disk. | |
| 377 | - """ | |
| 378 | - # Initialise flags | |
| 379 | - need_help = False | |
| 380 | - show_data = True | |
| 381 | - | |
| 382 | - # Test for command line arguments | |
| 383 | - print sys.argv[0] | |
| 384 | - if (len(sys.argv) > 1): | |
| 385 | - if sys.argv[1] == "-h": | |
| 386 | - need_help = True | |
| 387 | - elif sys.argv[1] == "-noshow": | |
| 388 | - show_data = False | |
| 389 | - else: | |
| 390 | - need_help = True | |
| 391 | - | |
| 392 | - # Print help if needed and exit | |
| 393 | - if need_help: | |
| 394 | - print "Usage: example_binned.py [OPTIONS]" | |
| 395 | - print " -h Display this usage message" | |
| 396 | - print " -noshow Do not show data using matplotlib" | |
| 397 | - sys.exit() | |
| 398 | - | |
| 399 | - # Dump header | |
| 400 | - print "*********************************" | |
| 401 | - print "* CTA unbinned analysis scripts *" | |
| 402 | - print "*********************************" | |
| 403 | - | |
| 404 | - # Remove any existing result files | |
| 405 | - list = [glob.glob("*.fits"), glob.glob("*.log"), glob.glob("*.xml")] | |
| 406 | - for files in list: | |
| 407 | - for file in files: | |
| 408 | - os.remove(file) | |
| 409 | - | |
| 410 | - # Save intermediate results on disk | |
| 411 | - print "" | |
| 412 | - print "Executable analysis pipeline:" | |
| 413 | - print "=============================" | |
| 414 | - pipeline_v1() | |
| 415 | - | |
| 416 | - # Do analysis in memory | |
| 417 | - print "" | |
| 418 | - print "In memory analysis pipeline:" | |
| 419 | - print "============================" | |
| 420 | - pipeline_v2(show_data) | |
| 421 | - print "" | |
| 367 | + """ | |
| 368 | + CTA unbinned analysis script. | |
| 369 | + | |
| 370 | + This script implements the analysis steps to perform an unbinned analysis. | |
| 371 | + The steps include: | |
| 372 | + - Event simulation | |
| 373 | + - Event selection | |
| 374 | + - Binned maximum likelihood fitting | |
| 375 | + | |
| 376 | + Two variations of the script are implemented. One that calls the classes | |
| 377 | + like executables, storing the intermediate results on disk, and a second | |
| 378 | + that uses the results of the precedent class directly without storing | |
| 379 | + any data on disk. | |
| 380 | + """ | |
| 381 | + # Initialise flags | |
| 382 | + need_help = False | |
| 383 | + show_data = True | |
| 384 | + | |
| 385 | + # Test for command line arguments | |
| 386 | + print sys.argv[0] | |
| 387 | + if (len(sys.argv) > 1): | |
| 388 | + if sys.argv[1] == "-h": | |
| 389 | + need_help = True | |
| 390 | + elif sys.argv[1] == "-noshow": | |
| 391 | + show_data = False | |
| 392 | + else: | |
| 393 | + need_help = True | |
| 394 | + | |
| 395 | + # Print help if needed and exit | |
| 396 | + if need_help: | |
| 397 | + print "Usage: example_binned.py [OPTIONS]" | |
| 398 | + print " -h Display this usage message" | |
| 399 | + print " -noshow Do not show data using matplotlib" | |
| 400 | + sys.exit() | |
| 401 | + | |
| 402 | + # Dump header | |
| 403 | + print "*********************************" | |
| 404 | + print "* CTA unbinned analysis scripts *" | |
| 405 | + print "*********************************" | |
| 406 | + | |
| 407 | + # Remove any existing result files | |
| 408 | + list = [glob.glob("*.fits"), glob.glob("*.log"), glob.glob("*.xml")] | |
| 409 | + for files in list: | |
| 410 | + for file in files: | |
| 411 | + os.remove(file) | |
| 412 | + | |
| 413 | + # Save intermediate results on disk | |
| 414 | + print "" | |
| 415 | + print "Executable analysis pipeline:" | |
| 416 | + print "=============================" | |
| 417 | + pipeline_v1() | |
| 418 | + | |
| 419 | + # Do analysis in memory | |
| 420 | + print "" | |
| 421 | + print "In memory analysis pipeline:" | |
| 422 | + print "============================" | |
| 423 | + pipeline_v2(show_data) | |
| 424 | + print "" | ... | ... |