Commit a28f64882575ebe84bd413a8d4613d11cebedb06
Merge branch 'devel' of https://cta-gitlab.irap.omp.eu/ctools/ctools into 2207-c…
…tskymap_RING_bkgsubtract
Showing
20 changed files
with
1071 additions
and
89 deletions
ChangeLog
| 1 | -2017-08-08 | |
| 1 | +2017-10-11 | |
| 2 | 2 | |
| 3 | 3 | * Version 1.5.0 released |
| 4 | 4 | ======================== |
| 5 | 5 | |
| 6 | + Add keywords to sky maps produced by ctskymap (#2194) | |
| 7 | + Enhance efficiency of computations in ctmodel (#2189) | |
| 8 | + Add csmodelsois script (#2180) | |
| 6 | 9 | Use t-type parameters for all "tmin" and "tmax" parameters (#1864) |
| 7 | 10 | |
| 8 | 11 | ... | ... |
NEWS
| 1 | 1 | New Features and Important Changes in ctools 1.5.0 |
| 2 | 2 | |
| 3 | -8 August 2017 | |
| 3 | +11 October 2017 | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | Introduction |
| ... | ... | @@ -53,7 +53,9 @@ None |
| 53 | 53 | |
| 54 | 54 | ctskymap - CTA sky mapping |
| 55 | 55 | -------------------------- |
| 56 | -None | |
| 56 | +Header keywords informing about the dates and times covered by the observations | |
| 57 | +used to generate the skymap, as well as the event energy range, are now appended | |
| 58 | +as header keywords to the FITS file (#2194). | |
| 57 | 59 | |
| 58 | 60 | |
| 59 | 61 | ctmodel - CTA counts cube modelling |
| ... | ... | @@ -61,6 +63,11 @@ ctmodel - CTA counts cube modelling |
| 61 | 63 | Use t-type parameters for "tmin" and "tmax" to all specifying times in various |
| 62 | 64 | formats (#1864). |
| 63 | 65 | |
| 66 | +The tool now also checks which models actually overlap with the RoI of a given | |
| 67 | +observation and then only use these models to compute the model cube. The | |
| 68 | +parallelization of the tool has also been optimised so that diffuse models are | |
| 69 | +not loaded over and over again (#2189). | |
| 70 | + | |
| 64 | 71 | |
| 65 | 72 | ctexpcube - CTA exposure cube generation |
| 66 | 73 | ---------------------------------------- |
| ... | ... | @@ -119,6 +126,9 @@ None |
| 119 | 126 | |
| 120 | 127 | cscripts |
| 121 | 128 | -------- |
| 129 | +Add csmodelsois script that replaces selected models in a model container by | |
| 130 | +a diffuse map cube (#2180). | |
| 131 | + | |
| 122 | 132 | Use t-type parameters for "tmin" and "tmax" to all specifying times in various |
| 123 | 133 | formats (#1864). |
| 124 | 134 | ... | ... |
cscripts/Makefile.am
| ... | ... | @@ -28,6 +28,7 @@ pythonscripts = $(top_builddir)/cscripts/__init__.py \ |
| 28 | 28 | $(srcdir)/csmodelinfo.py \ |
| 29 | 29 | $(srcdir)/csmodelmerge.py \ |
| 30 | 30 | $(srcdir)/csmodelselect.py \ |
| 31 | + $(srcdir)/csmodelsois.py \ | |
| 31 | 32 | $(srcdir)/csobs2caldb.py \ |
| 32 | 33 | $(srcdir)/csobsdef.py \ |
| 33 | 34 | $(srcdir)/csobsinfo.py \ |
| ... | ... | @@ -60,6 +61,7 @@ parfiles = $(srcdir)/cscaldb.par \ |
| 60 | 61 | $(srcdir)/csmodelinfo.par \ |
| 61 | 62 | $(srcdir)/csmodelmerge.par \ |
| 62 | 63 | $(srcdir)/csmodelselect.par \ |
| 64 | + $(srcdir)/csmodelsois.par \ | |
| 63 | 65 | $(srcdir)/csobs2caldb.par \ |
| 64 | 66 | $(srcdir)/csobsdef.par \ |
| 65 | 67 | $(srcdir)/csobsinfo.par \ |
| ... | ... | @@ -89,6 +91,7 @@ linkscripts = cscaldb \ |
| 89 | 91 | csmodelinfo \ |
| 90 | 92 | csmodelmerge \ |
| 91 | 93 | csmodelselect \ |
| 94 | + csmodelsois \ | |
| 92 | 95 | csobs2caldb \ |
| 93 | 96 | csobsdef \ |
| 94 | 97 | csobsinfo \ |
| ... | ... | @@ -123,6 +126,7 @@ testscripts = $(srcdir)/tests/__init__.py \ |
| 123 | 126 | $(top_srcdir)/test/test_csmodelinfo.py \ |
| 124 | 127 | $(top_srcdir)/test/test_csmodelmerge.py \ |
| 125 | 128 | $(top_srcdir)/test/test_csmodelselect.py \ |
| 129 | + $(top_srcdir)/test/test_csmodelsois.py \ | |
| 126 | 130 | $(top_srcdir)/test/test_csobs2caldb.py \ |
| 127 | 131 | $(top_srcdir)/test/test_csobsdef.py \ |
| 128 | 132 | $(top_srcdir)/test/test_csobsinfo.py \ | ... | ... |
cscripts/__init__.py.in
| 1 | 1 | # ========================================================================== |
| 2 | 2 | # cscripts Python module |
| 3 | 3 | # |
| 4 | -# Copyright (C) 2015-2016 Juergen Knoedlseder | |
| 4 | +# Copyright (C) 2015-2017 Juergen Knoedlseder | |
| 5 | 5 | # |
| 6 | 6 | # This program is free software: you can redistribute it and/or modify |
| 7 | 7 | # it under the terms of the GNU General Public License as published by |
| ... | ... | @@ -31,6 +31,7 @@ __all__ = [ |
| 31 | 31 | "csmodelinfo", |
| 32 | 32 | "csmodelmerge", |
| 33 | 33 | "csmodelselect", |
| 34 | + "csmodelsois", | |
| 34 | 35 | "csobs2caldb", |
| 35 | 36 | "csobsdef", |
| 36 | 37 | "csobsinfo", |
| ... | ... | @@ -66,6 +67,7 @@ from cscripts.cslightcrv import cslightcrv |
| 66 | 67 | from cscripts.csmodelinfo import csmodelinfo |
| 67 | 68 | from cscripts.csmodelmerge import csmodelmerge |
| 68 | 69 | from cscripts.csmodelselect import csmodelselect |
| 70 | +from cscripts.csmodelsois import csmodelsois | |
| 69 | 71 | from cscripts.csobs2caldb import csobs2caldb |
| 70 | 72 | from cscripts.csobsdef import csobsdef |
| 71 | 73 | from cscripts.csobsinfo import csobsinfo | ... | ... |
cscripts/csmodelsois.par
0 → 100644
| 1 | +############################################################################# | |
| 2 | +# # | |
| 3 | +# CTA Science Analysis Tools # | |
| 4 | +# # | |
| 5 | +# ------------------------------------------------------------------------- # | |
| 6 | +# # | |
| 7 | +# File: csmodelsois.par # | |
| 8 | +# # | |
| 9 | +# Author: Josh Cardenzana # | |
| 10 | +# josh.cardenzana@irap.omp.eu # | |
| 11 | +# IRAP # | |
| 12 | +# # | |
| 13 | +# Purpose: Parameter file for the csmodelsois application # | |
| 14 | +# # | |
| 15 | +############################################################################# | |
| 16 | +# | |
| 17 | +# General parameters | |
| 18 | +#=================== | |
| 19 | +inmodel, f, a, $CTOOLS/share/models/crab.xml,,, "Input model definition XML file" | |
| 20 | +outcube, f, a, mapcube.fits,,, "Output map cube file" | |
| 21 | +ptsrcsig, r, h, 1.0,0,60, "Point source Gaussian sigma in arcmin" | |
| 22 | +soilist, s, a, ,,, "CSV list of sources to exclude from cube model" | |
| 23 | +outmodel, f, a, model.xml,,, "Output model definition XML file" | |
| 24 | + | |
| 25 | +# | |
| 26 | +# Energy binning parameters | |
| 27 | +#========================== | |
| 28 | +ebinalg, s, a, LOG,FILE|LIN|LOG,, "Algorithm for defining energy bins" | |
| 29 | +emin, r, a, 0.1,,, "Start value for first energy bin in TeV" | |
| 30 | +emax, r, a, 100.0,,, "Stop value for last energy bin in TeV" | |
| 31 | +enumbins, i, a, 20,1,200, "Number of energy bins" | |
| 32 | +ebinfile, f, a, NONE,,, "Name of the file containing the energy bin definition" | |
| 33 | + | |
| 34 | +# | |
| 35 | +# Spatial binning parameters | |
| 36 | +#=========================== | |
| 37 | +nxpix, i, a, 200,,, "Size of the X axis in pixels" | |
| 38 | +nypix, i, a, 200,,, "Size of the Y axis in pixels" | |
| 39 | +binsz, r, a, 0.02,,, "Image scale (in degrees/pixel)" | |
| 40 | +coordsys, s, a, CEL,CEL|GAL,,"Coordinate system (CEL - celestial, GAL - galactic)" | |
| 41 | +proj, s, a, CAR,AIT|AZP|CAR|GLS|MER|MOL|SFL|SIN|STG|TAN,, "Projection method" | |
| 42 | +ra, r, a, 83.63,0,360, "Right ascension of image center (in degrees)" | |
| 43 | +dec, r, a, 22.01,-90,90, "Declination of image center (in degrees)" | |
| 44 | +glon, r, a, 184.55,0,360, "Galactic longitude of image center (in degrees)" | |
| 45 | +glat, r, a, -5.80,-90,90, "Galactic latitude of image center (in degrees)" | |
| 46 | + | |
| 47 | +# | |
| 48 | +# Standard parameters | |
| 49 | +#==================== | |
| 50 | +publish, b, h, no,,, "Publish map cube on VO Hub?" | |
| 51 | +chatter, i, h, 2,0,4, "Chattiness of output" | |
| 52 | +clobber, b, h, yes,,, "Overwrite existing output files with new output files?" | |
| 53 | +debug, b, h, no,,, "Debugging mode activated" | |
| 54 | +mode, s, h, "ql",,, "Mode of automatic parameters" | |
| 55 | +logfile, f, h, "csmodelsois.log",,, "Log filename" | ... | ... |
cscripts/csmodelsois.py
0 → 100755
| 1 | +#! /usr/bin/env python | |
| 2 | +# ========================================================================== | |
| 3 | +# Puts subset of sources in diffuse model cube | |
| 4 | +# | |
| 5 | +# Copyright (C) 2017 Josh Cardenzana | |
| 6 | +# | |
| 7 | +# This program is free software: you can redistribute it and/or modify | |
| 8 | +# it under the terms of the GNU General Public License as published by | |
| 9 | +# the Free Software Foundation, either version 3 of the License, or | |
| 10 | +# (at your option) any later version. | |
| 11 | +# | |
| 12 | +# This program is distributed in the hope that it will be useful, | |
| 13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | +# GNU General Public License for more details. | |
| 16 | +# | |
| 17 | +# You should have received a copy of the GNU General Public License | |
| 18 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 19 | +# | |
| 20 | +# ========================================================================== | |
| 21 | +import sys | |
| 22 | +import gammalib | |
| 23 | +import ctools | |
| 24 | + | |
| 25 | + | |
| 26 | +# ================= # | |
| 27 | +# csmodelsois class # | |
| 28 | +# ================= # | |
| 29 | +class csmodelsois(ctools.cscript): | |
| 30 | + """ | |
| 31 | + Puts subset of sources in diffuse model cube | |
| 32 | + | |
| 33 | + The csmodelsois class puts a subset of sources in a model definition | |
| 34 | + XML file into a model cube and generates a new model definition XML file | |
| 35 | + in which the subset of sources is replaced by a model of type | |
| 36 | + DiffuseMapCube. | |
| 37 | + """ | |
| 38 | + | |
| 39 | + # Constructor | |
| 40 | + def __init__(self, *argv): | |
| 41 | + """ | |
| 42 | + Constructor | |
| 43 | + | |
| 44 | + Parameters | |
| 45 | + ---------- | |
| 46 | + argv : list of parameters | |
| 47 | + | |
| 48 | + Raises | |
| 49 | + ------ | |
| 50 | + TypeError | |
| 51 | + An invalid number of command line arguments was provided. | |
| 52 | + """ | |
| 53 | + # Set name and version | |
| 54 | + self._name = 'csmodelsois' | |
| 55 | + self._version = ctools.__version__ | |
| 56 | + | |
| 57 | + # Initialize parameters | |
| 58 | + self._init_members() | |
| 59 | + | |
| 60 | + # Initialise application by calling the appropriate class constructor | |
| 61 | + self._init_cscript(argv) | |
| 62 | + | |
| 63 | + # Return | |
| 64 | + return | |
| 65 | + | |
| 66 | + | |
| 67 | + # Private methods | |
| 68 | + def _init_members(self): | |
| 69 | + """ | |
| 70 | + Initialize the parameters for this object | |
| 71 | + """ | |
| 72 | + # Initialise parameters | |
| 73 | + self.cubegen = ctools.ctmapcube() # Implements ctmapcube for generate the cube | |
| 74 | + self.m_models = gammalib.GModels() # Stores the full list of input models | |
| 75 | + self.cubemodels = gammalib.GModels() # Stores the list of models to be written to file | |
| 76 | + | |
| 77 | + # Return | |
| 78 | + return | |
| 79 | + | |
| 80 | + def _get_parameters(self): | |
| 81 | + """ | |
| 82 | + Get parameters from parfile | |
| 83 | + """ | |
| 84 | + # Query input parameters | |
| 85 | + self['inmodel'].filename() | |
| 86 | + self['soilist'].string() | |
| 87 | + | |
| 88 | + # Read input parameters | |
| 89 | + ptsrcsig = self['ptsrcsig'].real() | |
| 90 | + | |
| 91 | + # Get the cube centre coordinates | |
| 92 | + self.cubegen['coordsys'].string(self['coordsys'].string()) | |
| 93 | + if self['coordsys'].string() == 'CEL': | |
| 94 | + self.cubegen['xref'].real(self['ra'].real()) | |
| 95 | + self.cubegen['yref'].real(self['dec'].real()) | |
| 96 | + else: | |
| 97 | + self.cubegen['xref'].real(self['glon'].real()) | |
| 98 | + self.cubegen['yref'].real(self['glat'].real()) | |
| 99 | + | |
| 100 | + # Get spatial binning parameters | |
| 101 | + self.cubegen['binsz'].real(self['binsz'].real()) | |
| 102 | + self.cubegen['nxpix'].integer(self['nxpix'].integer()) | |
| 103 | + self.cubegen['nypix'].integer(self['nypix'].integer()) | |
| 104 | + self.cubegen['proj'].string(self['proj'].string()) | |
| 105 | + | |
| 106 | + # Get the energy binning parameters | |
| 107 | + self.cubegen['ebinalg'].string(self['ebinalg'].string()) | |
| 108 | + if self['ebinalg'].string() == 'FILE': | |
| 109 | + self.cubegen['ebinfile'].filename(self['ebinfile'].filename()) | |
| 110 | + else: | |
| 111 | + self.cubegen['emin'].real(self['emin'].real()) | |
| 112 | + self.cubegen['emax'].real(self['emax'].real()) | |
| 113 | + self.cubegen['enumbins'].integer(self['enumbins'].integer()) | |
| 114 | + | |
| 115 | + # Get remaining hidden parameters | |
| 116 | + self.cubegen['ptsrcsig'].real(ptsrcsig) | |
| 117 | + | |
| 118 | + # Read optionally output cube filenames | |
| 119 | + if self._read_ahead(): | |
| 120 | + self.cubegen['outcube'].filename(self['outcube'].filename()) | |
| 121 | + self['outmodel'].filename() | |
| 122 | + | |
| 123 | + # Write parameters into logger | |
| 124 | + self._log_parameters(gammalib.TERSE); | |
| 125 | + | |
| 126 | + return | |
| 127 | + | |
| 128 | + def _gen_cubemodel(self): | |
| 129 | + """ | |
| 130 | + Generates a binned model from the model file using ctmapcube | |
| 131 | + """ | |
| 132 | + # Get a list of sources we DONT want to put into the cube | |
| 133 | + sources = self['soilist'].string().split(',') | |
| 134 | + | |
| 135 | + # Load the model into a model container | |
| 136 | + if (self.m_models.size() == 0): | |
| 137 | + self.m_models = gammalib.GModels(self['inmodel'].filename()) | |
| 138 | + | |
| 139 | + # Store a copy of the models | |
| 140 | + self.cubemodels = self.m_models.copy() | |
| 141 | + | |
| 142 | + # Loop through models and pull out all models not in the list | |
| 143 | + models2remove = [] | |
| 144 | + for model in self.m_models: | |
| 145 | + | |
| 146 | + # If model is not a sky model then continue | |
| 147 | + if model.classname() != 'GModelSky': | |
| 148 | + self.cubemodels.remove(model.name()) | |
| 149 | + | |
| 150 | + # ... otherwise, if model is in list of sources the remove it | |
| 151 | + # from the container | |
| 152 | + elif model.name() in sources: | |
| 153 | + self.cubemodels.remove(model.name()) | |
| 154 | + | |
| 155 | + # Log the number of models to be put into the cube | |
| 156 | + self._log_value(self['chatter'].integer(), 'Numner of cube models', | |
| 157 | + self.cubemodels.size()) | |
| 158 | + | |
| 159 | + # Return | |
| 160 | + return | |
| 161 | + | |
| 162 | + | |
| 163 | + # Public methods | |
| 164 | + def run(self): | |
| 165 | + """ | |
| 166 | + Implements the actual bulk of the script's tasks | |
| 167 | + """ | |
| 168 | + # Switch screen logging on in debug mode | |
| 169 | + if self._logDebug(): | |
| 170 | + self._log.cout(True) | |
| 171 | + | |
| 172 | + # Get parameters | |
| 173 | + self._get_parameters() | |
| 174 | + | |
| 175 | + # Set the models to put into the cube | |
| 176 | + self._gen_cubemodel() | |
| 177 | + | |
| 178 | + # Only run if there still models to be filled into the cube | |
| 179 | + if not self.cubemodels.is_empty(): | |
| 180 | + | |
| 181 | + # Log action | |
| 182 | + self._log_string(gammalib.NORMAL, 'Generating model cube') | |
| 183 | + | |
| 184 | + # Fill the cube models into the ctmapcube object | |
| 185 | + self.cubegen.models(self.cubemodels) | |
| 186 | + | |
| 187 | + # Run the map generating method | |
| 188 | + self.cubegen.run() | |
| 189 | + | |
| 190 | + else: | |
| 191 | + self._log_string(gammalib.NORMAL, | |
| 192 | + 'List of models is empty, nothing will be done') | |
| 193 | + | |
| 194 | + # Return | |
| 195 | + return | |
| 196 | + | |
| 197 | + def execute(self): | |
| 198 | + """ | |
| 199 | + Execute the script | |
| 200 | + """ | |
| 201 | + # Open logfile | |
| 202 | + self.logFileOpen() | |
| 203 | + | |
| 204 | + # Read ahead output parameters | |
| 205 | + self._read_ahead(True) | |
| 206 | + | |
| 207 | + # Run the script | |
| 208 | + self.run() | |
| 209 | + | |
| 210 | + # Save model | |
| 211 | + self.save() | |
| 212 | + | |
| 213 | + # Return | |
| 214 | + return | |
| 215 | + | |
| 216 | + def save(self): | |
| 217 | + """ | |
| 218 | + Save the cube and optionally the updated XML model file | |
| 219 | + """ | |
| 220 | + # Save the generated cube if the cube and filename are not empty | |
| 221 | + if ((not self.cubegen.mapcube().cube().is_empty()) and | |
| 222 | + self._is_valid_filename(self['outcube'].filename())): | |
| 223 | + self.cubegen.mapcube().save(self['outcube'].filename(), | |
| 224 | + self['clobber'].boolean()) | |
| 225 | + | |
| 226 | + # If requested, save the updated list of models | |
| 227 | + if self._is_valid_filename(self['outmodel'].filename()): | |
| 228 | + | |
| 229 | + # Generate a list of models that will be output to file | |
| 230 | + outmodels = gammalib.GModels(self.m_models) | |
| 231 | + | |
| 232 | + # Remove all models used in the generated cube | |
| 233 | + for model in self.cubemodels: | |
| 234 | + outmodels.remove(model.name()) | |
| 235 | + | |
| 236 | + # Generate the actual cube model | |
| 237 | + spat = gammalib.GModelSpatialDiffuseCube(self['outcube'].filename()) | |
| 238 | + spec = gammalib.GModelSpectralConst() | |
| 239 | + newmodel = gammalib.GModelSky(spat, spec) | |
| 240 | + | |
| 241 | + # Give the model a default name | |
| 242 | + newmodel.name(self.cubemodelname()) | |
| 243 | + | |
| 244 | + # Now append the model to the list of output models | |
| 245 | + outmodels.append(newmodel) | |
| 246 | + | |
| 247 | + # Save the model list | |
| 248 | + outmodels.save(self['outmodel'].filename()) | |
| 249 | + | |
| 250 | + # Return | |
| 251 | + return | |
| 252 | + | |
| 253 | + def mapcube(self): | |
| 254 | + """ | |
| 255 | + Return the mapcube generated by the underlying 'ctmapcube' object | |
| 256 | + """ | |
| 257 | + # Return | |
| 258 | + return self.cubegen.mapcube() | |
| 259 | + | |
| 260 | + def cubemodelname(self): | |
| 261 | + """ | |
| 262 | + Return the name to be given to the cube model in the output XML file | |
| 263 | + """ | |
| 264 | + # Return | |
| 265 | + return 'FixedSourcesCube' | |
| 266 | + | |
| 267 | + def models(self, models): | |
| 268 | + """ | |
| 269 | + Set the models | |
| 270 | + | |
| 271 | + Parameters | |
| 272 | + ------- | |
| 273 | + models : `~gammalib.GModels` | |
| 274 | + Model container | |
| 275 | + """ | |
| 276 | + # Set models | |
| 277 | + self.m_models = models | |
| 278 | + | |
| 279 | + # Return | |
| 280 | + return | |
| 281 | + | |
| 282 | + | |
| 283 | +# ======================== # | |
| 284 | +# Main routine entry point # | |
| 285 | +# ======================== # | |
| 286 | +if __name__ == '__main__': | |
| 287 | + | |
| 288 | + # Create instance of application | |
| 289 | + app = csmodelsois(sys.argv) | |
| 290 | + | |
| 291 | + # Execute application | |
| 292 | + app.execute() | ... | ... |
doc/source/admin/release_history/1.5.rst
| ... | ... | @@ -22,11 +22,16 @@ Bug fixes |
| 22 | 22 | Improvements |
| 23 | 23 | ------------ |
| 24 | 24 | |
| 25 | -* TBW | |
| 25 | +* [`2194 <https://cta-redmine.irap.omp.eu/issues/2194>`_] - | |
| 26 | + Add keywords to sky maps produced by :ref:`ctskymap` | |
| 27 | +* [`2189 <https://cta-redmine.irap.omp.eu/issues/2189>`_] - | |
| 28 | + Enhance efficiency of computations in :ref:`ctmodel` | |
| 26 | 29 | |
| 27 | 30 | |
| 28 | 31 | New features |
| 29 | 32 | ------------ |
| 30 | 33 | |
| 34 | +* [`2180 <https://cta-redmine.irap.omp.eu/issues/2180>`_] - | |
| 35 | + Add :ref:`csmodelsois` script | |
| 31 | 36 | * [`1864 <https://cta-redmine.irap.omp.eu/issues/1864>`_] - |
| 32 | 37 | Use t-type parameters for all ``tmin`` and ``tmax`` parameters | ... | ... |
doc/source/users/reference_manual/csmodelsois.rst
0 → 100644
| 1 | +.. _csmodelsois: | |
| 2 | + | |
| 3 | +csmodelsois | |
| 4 | +=========== | |
| 5 | + | |
| 6 | +Generate a map cube from a subset of models in an input model. | |
| 7 | + | |
| 8 | + | |
| 9 | +Synopsis | |
| 10 | +---------- | |
| 11 | + | |
| 12 | +This tool generates a map cube from a subset of sky model components contained | |
| 13 | +in an input model. A map cube is a series of sky maps, each spanned by Right | |
| 14 | +Ascension or Galactic longitude and Declination or Galactic latitude. Each | |
| 15 | +map corresponds to a specific photon energy. The energy binning of the map | |
| 16 | +cube may be either linear, logarithmic, or custom defined using an input | |
| 17 | +file. | |
| 18 | + | |
| 19 | +csmodelsois generates a map cube FITS file comprising two extensions. The | |
| 20 | +primary extension contains a 3-dimensional image containing the map cube | |
| 21 | +values. A second extension named ``ENERGIES`` contains a binary table that | |
| 22 | +defines the energy values of each map in the cube. | |
| 23 | + | |
| 24 | +Optionally, csmodelsois can also output an updated model XML file in which all | |
| 25 | +sources from the input model XML file used to generate the map cube are | |
| 26 | +replaced with an updated model that uses the generated map cube. This is done | |
| 27 | +by specifying the 'outmodel' parameter. The 'soilist' parameter specifies a | |
| 28 | +list of source names (separated by ',') to be excluded from the generated | |
| 29 | +cube. | |
| 30 | + | |
| 31 | +General parameters | |
| 32 | +------------------ | |
| 33 | + | |
| 34 | +``inmodel [file]`` | |
| 35 | + Input model XML file. | |
| 36 | + | |
| 37 | +``outmodel [file]`` | |
| 38 | + Output model XML file (not generated if set to ``NONE``). | |
| 39 | + | |
| 40 | +``outcube [file]`` | |
| 41 | + Output map cube file. | |
| 42 | + | |
| 43 | +``soilist [string]`` | |
| 44 | + CSV list of sources to be excluded from the generated map cube. | |
| 45 | + | |
| 46 | +``(ptsrcsig = 1.0) [real]`` | |
| 47 | + Sigma of Gaussian to be used for point sources (in arcmin). | |
| 48 | + | |
| 49 | +``ebinalg <FILE|LIN|LOG> [string]`` | |
| 50 | + Algorithm for defining energy bins. | |
| 51 | + | |
| 52 | +``emin [real]`` | |
| 53 | + Lower energy value for first energy bin (in TeV). | |
| 54 | + | |
| 55 | +``emax [real]`` | |
| 56 | + Upper energy value for last energy bin (in TeV). | |
| 57 | + | |
| 58 | +``enumbins [integer]`` | |
| 59 | + Number of energy bins. | |
| 60 | + | |
| 61 | +``ebinfile [file]`` | |
| 62 | + Name of the file containing the energy bin definition. | |
| 63 | + | |
| 64 | +``nxpix [integer]`` | |
| 65 | + Number of cube bins in Right Ascension or Galactic longitude. | |
| 66 | + | |
| 67 | +``nypix [integer]`` | |
| 68 | + Number of cube bins in Declination or Galactic latitude. | |
| 69 | + | |
| 70 | +``binsz [real]`` | |
| 71 | + Image scale (in degrees/pixel). | |
| 72 | + | |
| 73 | +``coordsys <CEL|GAL> [string]`` | |
| 74 | + Coordinate system (CEL - celestial, GAL - galactic). | |
| 75 | + | |
| 76 | +``proj <AIT|AZP|CAR|GLS|MER|MOL|SFL|SIN|STG|TAN> [string]`` | |
| 77 | + Projection method. | |
| 78 | + | |
| 79 | +``ra [real]`` | |
| 80 | + Right Ascension of cube centre (J2000, in degrees). | |
| 81 | + | |
| 82 | +``dec [real]`` | |
| 83 | + Declination of cube centre (J2000, in degrees). | |
| 84 | + | |
| 85 | +``glon [real]`` | |
| 86 | + Galactic longitude of cube centre (in degrees). | |
| 87 | + | |
| 88 | +``glat [real]`` | |
| 89 | + Galactic latitude of cube centre (in degrees). | |
| 90 | + | |
| 91 | + | |
| 92 | +Standard parameters | |
| 93 | +------------------- | |
| 94 | + | |
| 95 | +``(publish = no) [boolean]`` | |
| 96 | + Specifies whether the map cube should be published on VO Hub. | |
| 97 | + | |
| 98 | +``(chatter = 2) [integer]`` | |
| 99 | + Verbosity of the executable: | |
| 100 | + ``chatter = 0``: no information will be logged | |
| 101 | + | |
| 102 | + ``chatter = 1``: only errors will be logged | |
| 103 | + | |
| 104 | + ``chatter = 2``: errors and actions will be logged | |
| 105 | + | |
| 106 | + ``chatter = 3``: report about the task execution | |
| 107 | + | |
| 108 | + ``chatter = 4``: detailed report about the task execution | |
| 109 | + | |
| 110 | +``(clobber = yes) [boolean]`` | |
| 111 | + Specifies whether an existing output counts cube file should be overwritten. | |
| 112 | + | |
| 113 | +``(debug = no) [boolean]`` | |
| 114 | + Enables debug mode. In debug mode the executable will dump any log file output to the console. | |
| 115 | + | |
| 116 | +``(mode = ql) [string]`` | |
| 117 | + Mode of automatic parameters (default is "ql", i.e. "query and learn"). | |
| 118 | + | |
| 119 | +``(logfile = csmodelsois.log) [string]`` | |
| 120 | + Name of log file. | |
| 121 | + | |
| 122 | + | |
| 123 | +Related tools or scripts | |
| 124 | +------------------------ | |
| 125 | + | |
| 126 | +:ref:`ctmapcube` | ... | ... |
doc/source/users/reference_manual/ctmapcube.rst
| ... | ... | @@ -36,40 +36,40 @@ General parameters |
| 36 | 36 | |
| 37 | 37 | ``ebinalg <FILE|LIN|LOG> [string]`` |
| 38 | 38 | Algorithm for defining energy bins. |
| 39 | - | |
| 39 | + | |
| 40 | 40 | ``emin [real]`` |
| 41 | 41 | Lower energy value for first energy bin (in TeV). |
| 42 | - | |
| 42 | + | |
| 43 | 43 | ``emax [real]`` |
| 44 | 44 | Upper energy value for last energy bin (in TeV). |
| 45 | - | |
| 45 | + | |
| 46 | 46 | ``enumbins [integer]`` |
| 47 | 47 | Number of energy bins. |
| 48 | - | |
| 48 | + | |
| 49 | 49 | ``ebinfile [file]`` |
| 50 | 50 | Name of the file containing the energy bin definition. |
| 51 | - | |
| 51 | + | |
| 52 | 52 | ``nxpix [integer]`` |
| 53 | 53 | Number of cube bins in Right Ascension or Galactic longitude. |
| 54 | - | |
| 54 | + | |
| 55 | 55 | ``nypix [integer]`` |
| 56 | 56 | Number of cube bins in Declination or Galactic latitude. |
| 57 | - | |
| 57 | + | |
| 58 | 58 | ``binsz [real]`` |
| 59 | 59 | Image scale (in degrees/pixel). |
| 60 | - | |
| 60 | + | |
| 61 | 61 | ``coordsys <CEL|GAL> [string]`` |
| 62 | 62 | Coordinate system (CEL - celestial, GAL - galactic). |
| 63 | - | |
| 63 | + | |
| 64 | 64 | ``proj <AIT|AZP|CAR|GLS|MER|MOL|SFL|SIN|STG|TAN> [string]`` |
| 65 | 65 | Projection method. |
| 66 | - | |
| 66 | + | |
| 67 | 67 | ``xref [real]`` |
| 68 | 68 | Right Ascension / Galactic longitude of cube centre (J2000, in degrees). |
| 69 | - | |
| 69 | + | |
| 70 | 70 | ``yref [real]`` |
| 71 | 71 | Declination / Galactic latitude of cube centre (J2000, in degrees). |
| 72 | - | |
| 72 | + | |
| 73 | 73 | |
| 74 | 74 | Standard parameters |
| 75 | 75 | ------------------- |
| ... | ... | @@ -80,21 +80,21 @@ Standard parameters |
| 80 | 80 | ``(chatter = 2) [integer]`` |
| 81 | 81 | Verbosity of the executable: |
| 82 | 82 | ``chatter = 0``: no information will be logged |
| 83 | - | |
| 83 | + | |
| 84 | 84 | ``chatter = 1``: only errors will be logged |
| 85 | - | |
| 85 | + | |
| 86 | 86 | ``chatter = 2``: errors and actions will be logged |
| 87 | - | |
| 87 | + | |
| 88 | 88 | ``chatter = 3``: report about the task execution |
| 89 | - | |
| 89 | + | |
| 90 | 90 | ``chatter = 4``: detailed report about the task execution |
| 91 | - | |
| 91 | + | |
| 92 | 92 | ``(clobber = yes) [boolean]`` |
| 93 | 93 | Specifies whether an existing output counts cube file should be overwritten. |
| 94 | - | |
| 94 | + | |
| 95 | 95 | ``(debug = no) [boolean]`` |
| 96 | 96 | Enables debug mode. In debug mode the executable will dump any log file output to the console. |
| 97 | - | |
| 97 | + | |
| 98 | 98 | ``(mode = ql) [string]`` |
| 99 | 99 | Mode of automatic parameters (default is "ql", i.e. "query and learn"). |
| 100 | 100 | |
| ... | ... | @@ -105,4 +105,4 @@ Standard parameters |
| 105 | 105 | Related tools or scripts |
| 106 | 106 | ------------------------ |
| 107 | 107 | |
| 108 | -None | |
| 108 | +:ref:`csmodelsois` | ... | ... |
examples/show_spectrum.py
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | # ========================================================================== |
| 3 | 3 | # Display spectrum generated by csspec |
| 4 | 4 | # |
| 5 | -# Copyright (C) 2015-2016 Juergen Knoedlseder | |
| 5 | +# Copyright (C) 2015-2017 Juergen Knoedlseder | |
| 6 | 6 | # |
| 7 | 7 | # This program is free software: you can redistribute it and/or modify |
| 8 | 8 | # it under the terms of the GNU General Public License as published by |
| ... | ... | @@ -91,6 +91,9 @@ def plot_spectrum(filename, plotfile): |
| 91 | 91 | ul_ed_engs.append(c_ed.real(row)) |
| 92 | 92 | ul_eu_engs.append(c_eu.real(row)) |
| 93 | 93 | |
| 94 | + # Set upper limit errors | |
| 95 | + yerr = [0.6 * x for x in ul_flux] | |
| 96 | + | |
| 94 | 97 | # Plot the spectrum |
| 95 | 98 | plt.figure() |
| 96 | 99 | plt.loglog() |
| ... | ... | @@ -98,7 +101,7 @@ def plot_spectrum(filename, plotfile): |
| 98 | 101 | plt.errorbar(energies, flux, yerr=e_flux, xerr=[ed_engs, eu_engs], |
| 99 | 102 | fmt='ro') |
| 100 | 103 | plt.errorbar(ul_energies, ul_flux, xerr=[ul_ed_engs, ul_eu_engs], |
| 101 | - yerr=1.0e-11, uplims=True, fmt='ro') | |
| 104 | + yerr=yerr, uplims=True, fmt='ro') | |
| 102 | 105 | plt.xlabel('Energy (TeV)') |
| 103 | 106 | plt.ylabel(r'E $\times$ dN/dE (erg cm$^{-2}$ s$^{-1}$)') |
| 104 | 107 | ... | ... |
pyext/ctobservation.i
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctobservation - Base class for observation tools * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2016 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2016-2017 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -89,6 +89,7 @@ public: |
| 89 | 89 | |
| 90 | 90 | // Public methods |
| 91 | 91 | const GObservations& obs(void) const; |
| 92 | + void write_ogip_keywords(GFitsHDU* hdu) const; | |
| 92 | 93 | |
| 93 | 94 | // Make methods private in Python by prepending an underscore |
| 94 | 95 | %rename(_first_unbinned_observation) first_unbinned_observation; | ... | ... |
src/ctmodel/ctmodel.cpp
| ... | ... | @@ -235,48 +235,55 @@ void ctmodel::run(void) |
| 235 | 235 | log_header1(TERSE, "Generate model cube"); |
| 236 | 236 | |
| 237 | 237 | // Loop over all observations in the container |
| 238 | - #pragma omp parallel for | |
| 239 | - for (int i = 0; i < m_obs.size(); ++i) { | |
| 238 | + #pragma omp parallel | |
| 239 | + { | |
| 240 | + // Create a models object for this core | |
| 241 | + GModels models(m_obs.models()); | |
| 240 | 242 | |
| 241 | - // Get CTA observation | |
| 242 | - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | |
| 243 | - | |
| 244 | - // Skip observation if it's not CTA | |
| 245 | - if (obs == NULL) { | |
| 246 | - log_header3(TERSE, get_obs_header(m_obs[i])); | |
| 247 | - std::string msg = " Skipping "+m_obs[i]->instrument()+ | |
| 248 | - " observation"; | |
| 249 | - log_string(NORMAL, msg); | |
| 250 | - } | |
| 251 | - | |
| 252 | - // Fill cube and leave loop if we are binned mode (meaning we | |
| 253 | - // only have one binned observation) | |
| 254 | - else if (m_binned) { | |
| 255 | - fill_cube(obs); | |
| 256 | - i = m_obs.size(); | |
| 257 | - } | |
| 258 | - | |
| 259 | - // Skip observation if we have a binned observation | |
| 260 | - else if (obs->eventtype() == "CountsCube") { | |
| 261 | - log_header3(TERSE, get_obs_header(m_obs[i])); | |
| 262 | - std::string msg = " Skipping binned "+m_obs[i]->instrument()+ | |
| 263 | - " observation"; | |
| 264 | - log_string(NORMAL, msg); | |
| 265 | - } | |
| 266 | - | |
| 267 | - // Otherwise, everything seems to be fine, so fill the cube from obs | |
| 268 | - else { | |
| 269 | - // Fill the cube | |
| 270 | - fill_cube(obs); | |
| 243 | + #pragma omp for schedule(static,1) | |
| 244 | + for (int i = 0; i < m_obs.size(); ++i) { | |
| 271 | 245 | |
| 272 | - // Dispose events to free memory if event file exists on disk | |
| 273 | - if (obs->eventfile().length() > 0 && obs->eventfile().exists()) { | |
| 274 | - obs->dispose_events(); | |
| 246 | + // Get CTA observation | |
| 247 | + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | |
| 248 | + | |
| 249 | + // Skip observation if it's not CTA | |
| 250 | + if (obs == NULL) { | |
| 251 | + log_header3(TERSE, get_obs_header(m_obs[i])); | |
| 252 | + std::string msg = " Skipping "+m_obs[i]->instrument()+ | |
| 253 | + " observation"; | |
| 254 | + log_string(NORMAL, msg); | |
| 275 | 255 | } |
| 276 | - } | |
| 277 | - | |
| 278 | - } // endfor: looped over observations | |
| 256 | + | |
| 257 | + // Fill cube and leave loop if we are binned mode (meaning we | |
| 258 | + // only have one binned observation) | |
| 259 | + else if (m_binned) { | |
| 260 | + fill_cube(obs, models); | |
| 261 | + i = m_obs.size(); | |
| 262 | + } | |
| 263 | + | |
| 264 | + // Skip observation if we have a binned observation | |
| 265 | + else if (obs->eventtype() == "CountsCube") { | |
| 266 | + log_header3(TERSE, get_obs_header(m_obs[i])); | |
| 267 | + std::string msg = " Skipping binned "+m_obs[i]->instrument()+ | |
| 268 | + " observation"; | |
| 269 | + log_string(NORMAL, msg); | |
| 270 | + } | |
| 271 | + | |
| 272 | + // Otherwise, everything seems to be fine, so fill the cube from obs | |
| 273 | + else { | |
| 274 | + // Fill the cube | |
| 275 | + fill_cube(obs, models); | |
| 276 | + | |
| 277 | + // Dispose events to free memory if event file exists on disk | |
| 278 | + if (obs->eventfile().length() > 0 && obs->eventfile().exists()) { | |
| 279 | + obs->dispose_events(); | |
| 280 | + } | |
| 281 | + } | |
| 282 | + | |
| 283 | + } // endfor: looped over observations | |
| 279 | 284 | |
| 285 | + } // end openmp parallel section | |
| 286 | + | |
| 280 | 287 | // Write model cube into header |
| 281 | 288 | log_header1(NORMAL, "Model cube"); |
| 282 | 289 | log_string(NORMAL, m_cube.print()); |
| ... | ... | @@ -789,7 +796,7 @@ void ctmodel::extract_cube_properties(void) |
| 789 | 796 | * GTI of the model cube so that cube GTI is a list of the GTIs of all |
| 790 | 797 | * observations that were used to generate the model cube. |
| 791 | 798 | ***************************************************************************/ |
| 792 | -void ctmodel::fill_cube(const GCTAObservation* obs) | |
| 799 | +void ctmodel::fill_cube(const GCTAObservation* obs, GModels& models) | |
| 793 | 800 | { |
| 794 | 801 | // Get number of spatial and spectral bins in counts cube |
| 795 | 802 | int npix = m_cube.npix(); |
| ... | ... | @@ -819,8 +826,8 @@ void ctmodel::fill_cube(const GCTAObservation* obs) |
| 819 | 826 | int num_outside_roi = 0; |
| 820 | 827 | |
| 821 | 828 | // Extract copy of models from observation container |
| 822 | - GModels models(m_obs.models()); | |
| 823 | - | |
| 829 | + GModels ex_models = trim_models(models, roi); | |
| 830 | + | |
| 824 | 831 | // Get pointer to event cube pixels |
| 825 | 832 | double* pixels = const_cast<double*>(m_cube.counts().pixels()); |
| 826 | 833 | |
| ... | ... | @@ -877,6 +884,9 @@ void ctmodel::fill_cube(const GCTAObservation* obs) |
| 877 | 884 | |
| 878 | 885 | } // endfor: looped over all cube bins |
| 879 | 886 | |
| 887 | + // Re-append the models to the main model | |
| 888 | + models.extend(ex_models); | |
| 889 | + | |
| 880 | 890 | // Update GTIs |
| 881 | 891 | #pragma omp critical(ctmodel_fill_cube) |
| 882 | 892 | { |
| ... | ... | @@ -905,3 +915,66 @@ void ctmodel::fill_cube(const GCTAObservation* obs) |
| 905 | 915 | // Return |
| 906 | 916 | return; |
| 907 | 917 | } |
| 918 | + | |
| 919 | + | |
| 920 | +/***********************************************************************//** | |
| 921 | + * @brief Find the models falling inside a defined region of interest. | |
| 922 | + * | |
| 923 | + * @param[in,out] all_models Model container to be trimmed. | |
| 924 | + * @param[in] roi Observation region of interest. | |
| 925 | + * @return New model container containing only models inside RoI. | |
| 926 | + * | |
| 927 | + * Note that a buffer is added to the observation region to ensure that | |
| 928 | + * point sources (which have radius=0) are appropriately included if they | |
| 929 | + * fall near the edge of the observation. | |
| 930 | + ***************************************************************************/ | |
| 931 | +GModels ctmodel::trim_models(GModels& all_models, const GCTARoi& roi) | |
| 932 | +{ | |
| 933 | + // Create the model container containing only models in RoI | |
| 934 | + GModels excluded_models; | |
| 935 | + | |
| 936 | + // Do nothing if roi is not valid. This will be the case for binned data | |
| 937 | + // sets as they have the default roi radius of 0. In this case we would | |
| 938 | + // remove ALL models, which is obviously incorrect. So we keep all models | |
| 939 | + // when filling based on a counts cube. | |
| 940 | + if (!roi.is_valid()) { | |
| 941 | + return excluded_models; | |
| 942 | + } | |
| 943 | + | |
| 944 | + // Remove all models that dont overlap with the region of interest. Note | |
| 945 | + // that an extra factor is used since point sources have regions of | |
| 946 | + // radius 0, which is a problem when they fall just barely outside the | |
| 947 | + // RoI. This ensures point sources are appropriately included. | |
| 948 | + GSkyRegionCircle obsreg(roi.centre().dir(), roi.radius()+0.5); | |
| 949 | + | |
| 950 | + // Loop over the models in the passed container | |
| 951 | + for (int i = 0; i < all_models.size(); ++i) { | |
| 952 | + | |
| 953 | + // Cast the model to a GModelSky object | |
| 954 | + GModelSky* model = dynamic_cast<GModelSky*>(all_models[i]); | |
| 955 | + | |
| 956 | + // If model is not a GModelSky model than skip | |
| 957 | + if (model == NULL) { | |
| 958 | + continue; | |
| 959 | + } | |
| 960 | + | |
| 961 | + // Otherwise, exclude the model if it isn't a diffuse cube and it | |
| 962 | + // doesn't overlap with the observation. | |
| 963 | + if (!(model->spatial()->code() == GMODEL_SPATIAL_DIFFUSE) && | |
| 964 | + (!model->spatial()->region()->overlaps(obsreg))) { | |
| 965 | + | |
| 966 | + // Append model to the excluded models | |
| 967 | + excluded_models.append(*model); | |
| 968 | + | |
| 969 | + // Remove model | |
| 970 | + all_models.remove(i); | |
| 971 | + | |
| 972 | + // Decrement to prevent skipping models | |
| 973 | + i--; | |
| 974 | + } | |
| 975 | + | |
| 976 | + } // endfor: looped over all models | |
| 977 | + | |
| 978 | + // Return excluded models | |
| 979 | + return excluded_models; | |
| 980 | +} | ... | ... |
src/ctmodel/ctmodel.hpp
| ... | ... | @@ -74,14 +74,15 @@ public: |
| 74 | 74 | |
| 75 | 75 | protected: |
| 76 | 76 | // Protected methods |
| 77 | - void init_members(void); | |
| 78 | - void copy_members(const ctmodel& app); | |
| 79 | - void free_members(void); | |
| 80 | - void get_parameters(void); | |
| 81 | - void get_obs(void); | |
| 82 | - void extract_cube_properties(void); | |
| 83 | - void fill_cube(const GCTAObservation* obs); | |
| 84 | - bool has_cube(void) const; | |
| 77 | + void init_members(void); | |
| 78 | + void copy_members(const ctmodel& app); | |
| 79 | + void free_members(void); | |
| 80 | + void get_parameters(void); | |
| 81 | + void get_obs(void); | |
| 82 | + void extract_cube_properties(void); | |
| 83 | + void fill_cube(const GCTAObservation* obs, GModels& models); | |
| 84 | + bool has_cube(void) const; | |
| 85 | + GModels trim_models(GModels& all_models, const GCTARoi& roi); | |
| 85 | 86 | |
| 86 | 87 | // User parameters |
| 87 | 88 | GFilename m_outcube; //!< Output model cube | ... | ... |
src/ctskymap/ctskymap.cpp
| ... | ... | @@ -281,23 +281,39 @@ void ctskymap::save(void) |
| 281 | 281 | GFits fits; |
| 282 | 282 | |
| 283 | 283 | // Write sky map into FITS file |
| 284 | - m_skymap.write(fits); | |
| 284 | + GFitsHDU* hdu = m_skymap.write(fits); | |
| 285 | + | |
| 286 | + // Write keywords into sky map extension | |
| 287 | + write_ogip_keywords(hdu); | |
| 288 | + write_hdu_keywords(hdu); | |
| 285 | 289 | |
| 286 | 290 | // If background subtraction is requested then write background map |
| 287 | 291 | // and significance map to FITS file |
| 288 | 292 | if (m_bkgsubtract != "NONE") { |
| 289 | 293 | |
| 290 | 294 | // Write background map into FITS file |
| 291 | - m_bkgmap.write(fits); | |
| 295 | + hdu = m_bkgmap.write(fits); | |
| 292 | 296 | |
| 293 | 297 | // Set background map extension name |
| 294 | - fits[fits.size()-1]->extname("BACKGROUND"); | |
| 298 | + if (hdu != NULL) { | |
| 299 | + hdu->extname("BACKGROUND"); | |
| 300 | + } | |
| 301 | + | |
| 302 | + // Write keywords into background extension | |
| 303 | + write_ogip_keywords(hdu); | |
| 304 | + write_hdu_keywords(hdu); | |
| 295 | 305 | |
| 296 | 306 | // Write significance map into FITS file |
| 297 | - m_sigmap.write(fits); | |
| 307 | + hdu = m_sigmap.write(fits); | |
| 298 | 308 | |
| 299 | 309 | // Set significance map extension name |
| 300 | - fits[fits.size()-1]->extname("SIGNIFICANCE"); | |
| 310 | + if (hdu != NULL) { | |
| 311 | + hdu->extname("SIGNIFICANCE"); | |
| 312 | + } | |
| 313 | + | |
| 314 | + // Write keywords into significance extension | |
| 315 | + write_ogip_keywords(hdu); | |
| 316 | + write_hdu_keywords(hdu); | |
| 301 | 317 | |
| 302 | 318 | } // endif: background subtraction was requested |
| 303 | 319 | |
| ... | ... | @@ -525,7 +541,7 @@ void ctskymap::map_events(GCTAObservation* obs) |
| 525 | 541 | // Make sure that the observation holds a CTA event list. If this |
| 526 | 542 | // is not the case then throw an exception. |
| 527 | 543 | if (events == NULL) { |
| 528 | - throw GException::no_list(G_BIN_EVENTS); | |
| 544 | + throw GException::no_list(G_MAP_EVENTS); | |
| 529 | 545 | } |
| 530 | 546 | |
| 531 | 547 | // Setup energy range covered by data |
| ... | ... | @@ -647,7 +663,7 @@ void ctskymap::map_background_irf(GCTAObservation* obs) |
| 647 | 663 | get_obs_header(obs)+" to compute IRF background. " |
| 648 | 664 | "Please specify response information or use " |
| 649 | 665 | "another background subtraction method."; |
| 650 | - throw GException::invalid_value(G_BKG_SUBTRACT_IRF, msg); | |
| 666 | + throw GException::invalid_value(G_MAP_BACKGROUND_IRF, msg); | |
| 651 | 667 | } |
| 652 | 668 | |
| 653 | 669 | // Get IRF background template |
| ... | ... | @@ -659,7 +675,7 @@ void ctskymap::map_background_irf(GCTAObservation* obs) |
| 659 | 675 | "response function for "+ |
| 660 | 676 | get_obs_header(obs)+". Please specify an instrument " |
| 661 | 677 | "response function containing a background template."; |
| 662 | - throw GException::invalid_value(G_BKG_SUBTRACT_IRF, msg); | |
| 678 | + throw GException::invalid_value(G_MAP_BACKGROUND_IRF, msg); | |
| 663 | 679 | } |
| 664 | 680 | |
| 665 | 681 | // Compute natural logarithm of energy range in MeV |
| ... | ... | @@ -860,6 +876,30 @@ void ctskymap::map_background_ring(GCTAObservation* obs) |
| 860 | 876 | return; |
| 861 | 877 | } |
| 862 | 878 | |
| 879 | +/***********************************************************************//** | |
| 880 | + * @brief Write keywords in FITS HDU | |
| 881 | + * | |
| 882 | + * @param[in,out] hdu Pointer to FITS HDU. | |
| 883 | + * | |
| 884 | + * Writes keywords in FITS HDU. | |
| 885 | + ***************************************************************************/ | |
| 886 | +void ctskymap::write_hdu_keywords(GFitsHDU* hdu) const | |
| 887 | +{ | |
| 888 | + // Continue only if pointer is valid | |
| 889 | + if (hdu != NULL) { | |
| 890 | + | |
| 891 | + // Set keywords | |
| 892 | + hdu->card("BKGSUB", m_bkgsubtract, "Background substraction method"); | |
| 893 | + hdu->card("E_MIN", m_emin, "[TeV] Lower energy boundary"); | |
| 894 | + hdu->card("E_MAX", m_emax, "[TeV] Upper energy boundary"); | |
| 895 | + hdu->card("EUNIT", "TeV", "Units for E_MIN and E_MAX"); | |
| 896 | + | |
| 897 | + } // endif: pointer was valid | |
| 898 | + | |
| 899 | + // Return | |
| 900 | + return; | |
| 901 | +} | |
| 902 | + | |
| 863 | 903 | |
| 864 | 904 | /***********************************************************************//** |
| 865 | 905 | * @brief Computes the bin-by-bin significance if background subtraction requested | ... | ... |
src/ctskymap/ctskymap.hpp
src/support/ctobservation.cpp
| ... | ... | @@ -192,6 +192,53 @@ ctobservation& ctobservation::operator=(const ctobservation& app) |
| 192 | 192 | = = |
| 193 | 193 | ==========================================================================*/ |
| 194 | 194 | |
| 195 | +/***********************************************************************//** | |
| 196 | + * @brief Write OGIP keywords in FITS HDU | |
| 197 | + * | |
| 198 | + * @param[in,out] hdu Pointer to FITS HDU. | |
| 199 | + * | |
| 200 | + * Writes OGIP keywords in FITS HDU. | |
| 201 | + ***************************************************************************/ | |
| 202 | +void ctobservation::write_ogip_keywords(GFitsHDU* hdu) const | |
| 203 | +{ | |
| 204 | + // Continue only if pointer is valid | |
| 205 | + if (hdu != NULL) { | |
| 206 | + | |
| 207 | + // Set creator | |
| 208 | + std::string creator = this->name() + " v" + this->version(); | |
| 209 | + | |
| 210 | + // Compute times | |
| 211 | + std::string utc_obs = m_ogip_tstart.utc(); | |
| 212 | + std::string utc_end = m_ogip_tstop.utc(); | |
| 213 | + std::string date_obs = utc_obs.substr(0, 10); | |
| 214 | + std::string time_obs = utc_obs.substr(11, 8); | |
| 215 | + std::string date_end = utc_end.substr(0, 10); | |
| 216 | + std::string time_end = utc_end.substr(11, 8); | |
| 217 | + | |
| 218 | + // Compute deadtime correction | |
| 219 | + double deadc = (m_ogip_ontime > 0.0) ? m_ogip_livetime / m_ogip_ontime : 1.0; | |
| 220 | + | |
| 221 | + // Set observation information | |
| 222 | + hdu->card("CREATOR", creator, "Program which created the file"); | |
| 223 | + hdu->card("TELESCOP", m_ogip_telescope, "Telescope"); | |
| 224 | + | |
| 225 | + // Set observation time information | |
| 226 | + hdu->card("DATE_OBS", date_obs, "Observation start date"); | |
| 227 | + hdu->card("TIME_OBS", time_obs, "Observation start time"); | |
| 228 | + hdu->card("DATE_END", date_end, "Observation end date"); | |
| 229 | + hdu->card("TIME_END", time_end, "Observation end time"); | |
| 230 | + hdu->card("TELAPSE", m_ogip_telapse, "[s] Elapsed time"); | |
| 231 | + hdu->card("ONTIME", m_ogip_ontime, "[s] Total good time including deadtime"); | |
| 232 | + hdu->card("LIVETIME", m_ogip_livetime, "[s] Total livetime"); | |
| 233 | + hdu->card("EXPOSURE", m_ogip_exposure, "[s] Exposure time"); | |
| 234 | + hdu->card("DEADC", deadc, "Deadtime correction factor"); | |
| 235 | + | |
| 236 | + } // endif: pointer was valid | |
| 237 | + | |
| 238 | + // Return | |
| 239 | + return; | |
| 240 | +} | |
| 241 | + | |
| 195 | 242 | |
| 196 | 243 | /*========================================================================== |
| 197 | 244 | = = |
| ... | ... | @@ -208,6 +255,13 @@ void ctobservation::init_members(void) |
| 208 | 255 | m_obs.clear(); |
| 209 | 256 | |
| 210 | 257 | // Initialise private members |
| 258 | + m_ogip_telescope.clear(); | |
| 259 | + m_ogip_tstart.clear(); | |
| 260 | + m_ogip_tstop.clear(); | |
| 261 | + m_ogip_telapse = 0.0; | |
| 262 | + m_ogip_exposure = 0.0; | |
| 263 | + m_ogip_ontime = 0.0; | |
| 264 | + m_ogip_livetime = 0.0; | |
| 211 | 265 | m_index_unbinned = 0; |
| 212 | 266 | |
| 213 | 267 | // Return |
| ... | ... | @@ -226,6 +280,13 @@ void ctobservation::copy_members(const ctobservation& app) |
| 226 | 280 | m_obs = app.m_obs; |
| 227 | 281 | |
| 228 | 282 | // Copy private members |
| 283 | + m_ogip_telescope = app.m_ogip_telescope; | |
| 284 | + m_ogip_tstart = app.m_ogip_tstart; | |
| 285 | + m_ogip_tstop = app.m_ogip_tstop; | |
| 286 | + m_ogip_telapse = app.m_ogip_telapse; | |
| 287 | + m_ogip_exposure = app.m_ogip_exposure; | |
| 288 | + m_ogip_ontime = app.m_ogip_ontime; | |
| 289 | + m_ogip_livetime = app.m_ogip_livetime; | |
| 229 | 290 | m_index_unbinned = app.m_index_unbinned; |
| 230 | 291 | |
| 231 | 292 | // Return |
| ... | ... | @@ -258,6 +319,15 @@ const GCTAObservation* ctobservation::first_unbinned_observation(void) const |
| 258 | 319 | // Initialise index |
| 259 | 320 | m_index_unbinned = 0; |
| 260 | 321 | |
| 322 | + // Initialise OGIP members | |
| 323 | + m_ogip_telescope.clear(); | |
| 324 | + m_ogip_tstart.clear(); | |
| 325 | + m_ogip_tstop.clear(); | |
| 326 | + m_ogip_telapse = 0.0; | |
| 327 | + m_ogip_exposure = 0.0; | |
| 328 | + m_ogip_ontime = 0.0; | |
| 329 | + m_ogip_livetime = 0.0; | |
| 330 | + | |
| 261 | 331 | // Get next unbinned CTA observation |
| 262 | 332 | const GCTAObservation* obs = next_unbinned_observation(); |
| 263 | 333 | |
| ... | ... | @@ -323,6 +393,31 @@ const GCTAObservation* ctobservation::next_unbinned_observation(void) const |
| 323 | 393 | |
| 324 | 394 | } // endfor: looped over all observation |
| 325 | 395 | |
| 396 | + // Update OGIP members | |
| 397 | + if (obs != NULL) { | |
| 398 | + if (m_ogip_telapse == 0.0) { | |
| 399 | + m_ogip_telescope = obs->instrument(); | |
| 400 | + m_ogip_tstart = obs->gti().tstart(); | |
| 401 | + m_ogip_tstop = obs->gti().tstop(); | |
| 402 | + m_ogip_telapse = obs->gti().telapse(); | |
| 403 | + m_ogip_exposure = obs->ontime(); | |
| 404 | + m_ogip_ontime = obs->ontime(); | |
| 405 | + m_ogip_livetime = obs->livetime(); | |
| 406 | + } | |
| 407 | + else { | |
| 408 | + if (obs->gti().tstart() < m_ogip_tstart) { | |
| 409 | + m_ogip_tstart = obs->gti().tstart(); | |
| 410 | + } | |
| 411 | + if (obs->gti().tstop() > m_ogip_tstop) { | |
| 412 | + m_ogip_tstop = obs->gti().tstop(); | |
| 413 | + } | |
| 414 | + m_ogip_telapse += obs->gti().telapse(); | |
| 415 | + m_ogip_exposure += obs->ontime(); | |
| 416 | + m_ogip_ontime += obs->ontime(); | |
| 417 | + m_ogip_livetime += obs->livetime(); | |
| 418 | + } | |
| 419 | + } | |
| 420 | + | |
| 326 | 421 | // Return next CTA observation |
| 327 | 422 | return obs; |
| 328 | 423 | } | ... | ... |
src/support/ctobservation.hpp
| ... | ... | @@ -63,6 +63,7 @@ public: |
| 63 | 63 | |
| 64 | 64 | // Methods |
| 65 | 65 | const GObservations& obs(void) const; |
| 66 | + void write_ogip_keywords(GFitsHDU* hdu) const; | |
| 66 | 67 | |
| 67 | 68 | #ifndef SWIG |
| 68 | 69 | protected: |
| ... | ... | @@ -82,11 +83,18 @@ protected: |
| 82 | 83 | void save_events_xml(void); |
| 83 | 84 | |
| 84 | 85 | // Protected members |
| 85 | - GObservations m_obs; //!< Observation container | |
| 86 | + GObservations m_obs; //!< Observation container | |
| 86 | 87 | |
| 87 | 88 | private: |
| 88 | 89 | // Private members |
| 89 | - mutable int m_index_unbinned; //!< Current index of unbinned observation | |
| 90 | + mutable std::string m_ogip_telescope; //!< Name of telescope | |
| 91 | + mutable GTime m_ogip_tstart; //!< Start time for OGIP keywords | |
| 92 | + mutable GTime m_ogip_tstop; //!< Stop time for OGIP keywords | |
| 93 | + mutable double m_ogip_telapse; //!< Elapsed time | |
| 94 | + mutable double m_ogip_exposure; //!< Exposure time | |
| 95 | + mutable double m_ogip_ontime; //!< Ontime for OGIP keywords | |
| 96 | + mutable double m_ogip_livetime; //!< Livetime for OGIP keywords | |
| 97 | + mutable int m_index_unbinned; //!< Current index of unbinned observation | |
| 90 | 98 | }; |
| 91 | 99 | |
| 92 | 100 | ... | ... |
test/test_csmodelsois.py
0 → 100755
| 1 | +#! /usr/bin/env python | |
| 2 | +# ========================================================================== | |
| 3 | +# This scripts performs unit tests for the csmodelsois tool. | |
| 4 | +# | |
| 5 | +# Copyright (C) 2017 Josh Cardenzana | |
| 6 | +# | |
| 7 | +# This program is free software: you can redistribute it and/or modify | |
| 8 | +# it under the terms of the GNU General Public License as published by | |
| 9 | +# the Free Software Foundation, either version 3 of the License, or | |
| 10 | +# (at your option) any later version. | |
| 11 | +# | |
| 12 | +# This program is distributed in the hope that it will be useful, | |
| 13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | +# GNU General Public License for more details. | |
| 16 | +# | |
| 17 | +# You should have received a copy of the GNU General Public License | |
| 18 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 19 | +# | |
| 20 | +# ========================================================================== | |
| 21 | +import os | |
| 22 | +import gammalib | |
| 23 | +import cscripts | |
| 24 | +from testing import test | |
| 25 | + | |
| 26 | + | |
| 27 | +# =============================== # | |
| 28 | +# Test class for csmodelsois tool # | |
| 29 | +# =============================== # | |
| 30 | +class Test(test): | |
| 31 | + """ | |
| 32 | + Test class for csmodelsois tool | |
| 33 | + | |
| 34 | + This test class makes unit tests for the csmodelsois tool by using it from | |
| 35 | + the command line and from Python. | |
| 36 | + """ | |
| 37 | + | |
| 38 | + # Constructor | |
| 39 | + def __init__(self): | |
| 40 | + """ | |
| 41 | + Constructor | |
| 42 | + """ | |
| 43 | + # Call base class constructor | |
| 44 | + test.__init__(self) | |
| 45 | + | |
| 46 | + # Return | |
| 47 | + return | |
| 48 | + | |
| 49 | + # Set test functions | |
| 50 | + def set(self): | |
| 51 | + """ | |
| 52 | + Set all test functions | |
| 53 | + """ | |
| 54 | + # Set test name | |
| 55 | + self.name('csmodelsois') | |
| 56 | + | |
| 57 | + # Append tests | |
| 58 | + self.append(self._test_cmd, 'Test csmodelsois on command line') | |
| 59 | + self.append(self._test_python, 'Test csmodelsois from Python') | |
| 60 | + | |
| 61 | + # Return | |
| 62 | + return | |
| 63 | + | |
| 64 | + # Test csmodelsois on command line | |
| 65 | + def _test_cmd(self): | |
| 66 | + """ | |
| 67 | + Test csmodelsois on the command line | |
| 68 | + """ | |
| 69 | + # Set tool name | |
| 70 | + csmodelsois = self._script('csmodelsois') | |
| 71 | + | |
| 72 | + # Setup csmodelsois command | |
| 73 | + cmd = csmodelsois+' inmodel="'+self._model+'"'+ \ | |
| 74 | + ' outcube="csmodelsois_cmd1.fits"'+\ | |
| 75 | + ' emin=0.1 emax=100.0 enumbins=10 ebinalg=LOG'+ \ | |
| 76 | + ' nxpix=100 nypix=100 binsz=0.04 coordsys=CEL'+ \ | |
| 77 | + ' soilist="" outmodel=NONE'+ \ | |
| 78 | + ' ra=83.63 dec=22.01 proj=CAR'+ \ | |
| 79 | + ' logfile="csmodelsois_cmd1.log" chatter=1' | |
| 80 | + | |
| 81 | + # Check if execution of wrong command fails | |
| 82 | + self.test_assert(self._execute('command_that_does_not_exist') != 0, | |
| 83 | + 'Self test of test script') | |
| 84 | + | |
| 85 | + # Check if execution was successful | |
| 86 | + self.test_assert(self._execute(cmd) == 0, | |
| 87 | + 'Check successful execution from command line') | |
| 88 | + | |
| 89 | + # Check map cube | |
| 90 | + self._check_result_file('csmodelsois_cmd1.fits') | |
| 91 | + | |
| 92 | + # Setup csmodelsois command | |
| 93 | + cmd = csmodelsois+' inmodel="events_that_do_not_exist.fits"'+ \ | |
| 94 | + ' outcube="ccsmodelsois_cmd2.fits"'+\ | |
| 95 | + ' emin=0.1 emax=100.0 enumbins=10 ebinalg=LOG'+ \ | |
| 96 | + ' nxpix=100 nypix=100 binsz=0.04 coordsys=CEL'+ \ | |
| 97 | + ' soilist="" outmodel=NONE'+ \ | |
| 98 | + ' ra=83.63 dec=22.01 proj=CAR'+ \ | |
| 99 | + ' logfile="csmodelsois_cmd2.log"' | |
| 100 | + | |
| 101 | + # Check if execution failed | |
| 102 | + self.test_assert(self._execute(cmd) != 0, | |
| 103 | + 'Check invalid input file when executed from command line') | |
| 104 | + | |
| 105 | + # Check csmodelsois --help | |
| 106 | + self._check_help(csmodelsois) | |
| 107 | + | |
| 108 | + # Return | |
| 109 | + return | |
| 110 | + | |
| 111 | + # Test csmodelsois from Python | |
| 112 | + def _test_python(self): | |
| 113 | + """ | |
| 114 | + Test csmodelsois from Python | |
| 115 | + """ | |
| 116 | + # Allocate csmodelsois | |
| 117 | + modelsois = cscripts.csmodelsois() | |
| 118 | + | |
| 119 | + # Check that empty csmodelsois tool holds an map cube that has no | |
| 120 | + # energy bins | |
| 121 | + self._check_cube(modelsois.mapcube(), nmaps=0, npixels=0) | |
| 122 | + | |
| 123 | + # Check that saving does nothing | |
| 124 | + modelsois['outcube'] = 'csmodelsois_py0.fits' | |
| 125 | + modelsois['outmodel'] = 'NONE' | |
| 126 | + modelsois['logfile'] = 'csmodelsois_py0.log' | |
| 127 | + modelsois.logFileOpen() | |
| 128 | + modelsois.save() | |
| 129 | + self.test_assert(not os.path.isfile('csmodelsois_py0.fits'), | |
| 130 | + 'Check that no map cube has been created') | |
| 131 | + | |
| 132 | + # Check that clearing does not lead to an exception or segfault | |
| 133 | + modelsois.clear() | |
| 134 | + | |
| 135 | + # Now set csmodelsois parameters | |
| 136 | + modelsois['inmodel'] = self._model | |
| 137 | + modelsois['ebinalg'] = 'LOG' | |
| 138 | + modelsois['emin'] = 0.1 | |
| 139 | + modelsois['emax'] = 100.0 | |
| 140 | + modelsois['enumbins'] = 10 | |
| 141 | + modelsois['nxpix'] = 100 | |
| 142 | + modelsois['nypix'] = 100 | |
| 143 | + modelsois['binsz'] = 0.04 | |
| 144 | + modelsois['coordsys'] = 'CEL' | |
| 145 | + modelsois['proj'] = 'CAR' | |
| 146 | + modelsois['ra'] = 83.63 | |
| 147 | + modelsois['dec'] = 22.01 | |
| 148 | + modelsois['ptsrcsig'] = 1.0 | |
| 149 | + modelsois['outcube'] = 'csmodelsois_py1.fits' | |
| 150 | + modelsois['logfile'] = 'csmodelsois_py1.log' | |
| 151 | + modelsois['chatter'] = 2 | |
| 152 | + modelsois['soilist'] = '' | |
| 153 | + modelsois['outmodel'] = 'NONE' | |
| 154 | + | |
| 155 | + # Run csmodelsois tool | |
| 156 | + modelsois.logFileOpen() # Make sure we get a log file | |
| 157 | + modelsois.run() | |
| 158 | + | |
| 159 | + # Save map cube | |
| 160 | + modelsois.save() | |
| 161 | + | |
| 162 | + # Check map cube | |
| 163 | + self._check_result_file('csmodelsois_py1.fits') | |
| 164 | + | |
| 165 | + # Allocate csmodelsois scripts, set models and do now a linear | |
| 166 | + # binning; also do not use Gaussian point sources | |
| 167 | + modelsois = cscripts.csmodelsois() | |
| 168 | + modelsois['inmodel'] = self._model | |
| 169 | + modelsois['ebinalg'] = 'LIN' | |
| 170 | + modelsois['emin'] = 0.1 | |
| 171 | + modelsois['emax'] = 100.0 | |
| 172 | + modelsois['enumbins'] = 10 | |
| 173 | + modelsois['nxpix'] = 100 | |
| 174 | + modelsois['nypix'] = 100 | |
| 175 | + modelsois['binsz'] = 0.04 | |
| 176 | + modelsois['coordsys'] = 'CEL' | |
| 177 | + modelsois['proj'] = 'CAR' | |
| 178 | + modelsois['ra'] = 83.63 | |
| 179 | + modelsois['dec'] = 22.01 | |
| 180 | + modelsois['ptsrcsig'] = 0.0 | |
| 181 | + modelsois['outcube'] = 'csmodelsois_py2.fits' | |
| 182 | + modelsois['logfile'] = 'csmodelsois_py2.log' | |
| 183 | + modelsois['chatter'] = 4 | |
| 184 | + modelsois['soilist'] = '' | |
| 185 | + modelsois['outmodel'] = 'NONE' | |
| 186 | + | |
| 187 | + # Execute mapcube | |
| 188 | + modelsois.logFileOpen() # Needed to get a new log file | |
| 189 | + modelsois.execute() | |
| 190 | + | |
| 191 | + # Check result file | |
| 192 | + self._check_result_file('csmodelsois_py2.fits') | |
| 193 | + | |
| 194 | + # Update output filenames and output a new model file | |
| 195 | + modelsois['outcube'] = 'csmodelsois_py3.fits' | |
| 196 | + modelsois['logfile'] = 'csmodelsois_py3.log' | |
| 197 | + modelsois['outmodel'] = 'csmodelsois_py3.xml' | |
| 198 | + | |
| 199 | + # Execute the file | |
| 200 | + modelsois.logFileOpen() | |
| 201 | + modelsois.execute() | |
| 202 | + | |
| 203 | + # Now check that the output model file doesnt contain a Crab Sources | |
| 204 | + models3 = gammalib.GModels('csmodelsois_py3.xml') | |
| 205 | + self.test_assert(not models3.contains('Crab'), | |
| 206 | + 'Check Crab model is not present') | |
| 207 | + self.test_assert(models3.contains(modelsois.cubemodelname()), | |
| 208 | + 'Check cube model is present') | |
| 209 | + self._check_result_file('csmodelsois_py3.fits') | |
| 210 | + | |
| 211 | + # Return | |
| 212 | + return | |
| 213 | + | |
| 214 | + # Check result file | |
| 215 | + def _check_result_file(self, filename): | |
| 216 | + """ | |
| 217 | + Check content of map cube | |
| 218 | + | |
| 219 | + Parameters | |
| 220 | + ---------- | |
| 221 | + filename : str | |
| 222 | + Map cube file name | |
| 223 | + """ | |
| 224 | + # Load map cube | |
| 225 | + cube = gammalib.GModelSpatialDiffuseCube(filename) | |
| 226 | + | |
| 227 | + # Check map cube | |
| 228 | + self._check_cube(cube) | |
| 229 | + | |
| 230 | + # Return | |
| 231 | + return | |
| 232 | + | |
| 233 | + # Check map cube | |
| 234 | + def _check_cube(self, cube, nmaps=11, npixels=10000): | |
| 235 | + """ | |
| 236 | + Check map cube | |
| 237 | + | |
| 238 | + Parameters | |
| 239 | + ---------- | |
| 240 | + cube : `~gammalib.GModelSpatialDiffuseCube` | |
| 241 | + Map cube | |
| 242 | + nmaps : int, optional | |
| 243 | + Number of maps | |
| 244 | + npixels : int, optional | |
| 245 | + Number of pixels | |
| 246 | + """ | |
| 247 | + # Get energies (this forces loading in case the map cube is not | |
| 248 | + # loaded) | |
| 249 | + energies = cube.energies() | |
| 250 | + self.test_value(len(cube.energies()), nmaps, 'Check number of energies') | |
| 251 | + | |
| 252 | + # Check dimensions | |
| 253 | + self.test_value(cube.maps(), nmaps, 'Check number of maps') | |
| 254 | + self.test_value(cube.pixels(), npixels, 'Check number of pixels') | |
| 255 | + | |
| 256 | + # Return | |
| 257 | + return | ... | ... |
test/test_ctskymap.py
| ... | ... | @@ -221,7 +221,7 @@ class Test(test): |
| 221 | 221 | skymap['proj'] = 'CAR' |
| 222 | 222 | skymap['xref'] = 184.5575 |
| 223 | 223 | skymap['yref'] = -5.7844 |
| 224 | - skymap['bkgsubtract'] = 'IRF' | |
| 224 | + skymap['bkgsubtract'] = 'IRF' | |
| 225 | 225 | skymap['caldb'] = self._caldb |
| 226 | 226 | skymap['irf'] = self._irf |
| 227 | 227 | skymap['outmap'] = 'ctskymap_py4.fits' |
| ... | ... | @@ -234,6 +234,8 @@ class Test(test): |
| 234 | 234 | |
| 235 | 235 | # Check result file |
| 236 | 236 | self._check_result_file('ctskymap_py4.fits') |
| 237 | + self._check_result_file('ctskymap_py4.fits[BACKGROUND]') | |
| 238 | + self._check_result_file('ctskymap_py4.fits[SIGNIFICANCE]') | |
| 237 | 239 | |
| 238 | 240 | # ================================ |
| 239 | 241 | # TEST RING BACKGROUND SUBTRACTION |
| ... | ... | @@ -268,6 +270,8 @@ class Test(test): |
| 268 | 270 | |
| 269 | 271 | # Check result file |
| 270 | 272 | self._check_result_file('ctskymap_py5.fits', 100, 100) |
| 273 | + self._check_result_file('ctskymap_py5.fits[BACKGROUND]', 100, 100) | |
| 274 | + self._check_result_file('ctskymap_py5.fits[SIGNIFICANCE]', 100, 100) | |
| 271 | 275 | |
| 272 | 276 | # Return |
| 273 | 277 | return | ... | ... |
test/test_python_cscripts.py
| ... | ... | @@ -32,6 +32,7 @@ import test_cslightcrv |
| 32 | 32 | import test_csmodelinfo |
| 33 | 33 | import test_csmodelmerge |
| 34 | 34 | import test_csmodelselect |
| 35 | +import test_csmodelsois | |
| 35 | 36 | import test_csobs2caldb |
| 36 | 37 | import test_csobsdef |
| 37 | 38 | import test_csobsinfo |
| ... | ... | @@ -121,6 +122,7 @@ def test(installed=False, debug=False): |
| 121 | 122 | test_csmodelinfo.Test(), |
| 122 | 123 | test_csmodelmerge.Test(), |
| 123 | 124 | test_csmodelselect.Test(), |
| 125 | + test_csmodelsois.Test(), | |
| 124 | 126 | test_csobs2caldb.Test(), |
| 125 | 127 | test_csobsdef.Test(), |
| 126 | 128 | test_csobsinfo.Test(), |
| ... | ... | @@ -145,7 +147,7 @@ def test(installed=False, debug=False): |
| 145 | 147 | |
| 146 | 148 | # Check for VHEFITS environment variable |
| 147 | 149 | if 'VHEFITS' in os.environ: |
| 148 | - | |
| 150 | + | |
| 149 | 151 | # If the environment variable exists then unset it for the test |
| 150 | 152 | # cases. Since Python is executed in a subprocess this will not |
| 151 | 153 | # impact the environment variable in the parent shell. | ... | ... |