Commit bb9a556d85a74a6a24f53ab3dbeb4dde46508ef8
1 parent
6887a0c9
Implement csfootprint script (#3592)
Showing
10 changed files
with
1055 additions
and
3 deletions
cscripts/Makefile.am
| 1 | ############################################################################# | 1 | ############################################################################# |
| 2 | # Makefile for cscripts scripts # | 2 | # Makefile for cscripts scripts # |
| 3 | # ------------------------------------------------------------------------- # | 3 | # ------------------------------------------------------------------------- # |
| 4 | -# Copyright (C) 2016-2021 Juergen Knoedlseder # | 4 | +# Copyright (C) 2016-2022 Juergen Knoedlseder # |
| 5 | # ------------------------------------------------------------------------- # | 5 | # ------------------------------------------------------------------------- # |
| 6 | # # | 6 | # # |
| 7 | # This program is free software: you can redistribute it and/or modify # | 7 | # This program is free software: you can redistribute it and/or modify # |
| @@ -25,6 +25,7 @@ pythonscripts = $(top_builddir)/cscripts/__init__.py \ | @@ -25,6 +25,7 @@ pythonscripts = $(top_builddir)/cscripts/__init__.py \ | ||
| 25 | $(srcdir)/csbkgmodel.py \ | 25 | $(srcdir)/csbkgmodel.py \ |
| 26 | $(srcdir)/cscaldb.py \ | 26 | $(srcdir)/cscaldb.py \ |
| 27 | $(srcdir)/csebins.py \ | 27 | $(srcdir)/csebins.py \ |
| 28 | + $(srcdir)/csfootprint.py \ | ||
| 28 | $(srcdir)/csinfo.py \ | 29 | $(srcdir)/csinfo.py \ |
| 29 | $(srcdir)/cslightcrv.py \ | 30 | $(srcdir)/cslightcrv.py \ |
| 30 | $(srcdir)/csmodelinfo.py \ | 31 | $(srcdir)/csmodelinfo.py \ |
| @@ -88,6 +89,7 @@ parfiles = $(srcdir)/csadd2caldb.par \ | @@ -88,6 +89,7 @@ parfiles = $(srcdir)/csadd2caldb.par \ | ||
| 88 | $(srcdir)/cstsmapsplit.par \ | 89 | $(srcdir)/cstsmapsplit.par \ |
| 89 | $(srcdir)/csviscube.par \ | 90 | $(srcdir)/csviscube.par \ |
| 90 | $(srcdir)/csscs.par \ | 91 | $(srcdir)/csscs.par \ |
| 92 | + $(srcdir)/csfootprint.par \ | ||
| 91 | $(srcdir)/csworkflow.par \ | 93 | $(srcdir)/csworkflow.par \ |
| 92 | $(srcdir)/csfindobs.par \ | 94 | $(srcdir)/csfindobs.par \ |
| 93 | $(srcdir)/csiactcopy.par \ | 95 | $(srcdir)/csiactcopy.par \ |
| @@ -123,6 +125,7 @@ linkscripts = csadd2caldb \ | @@ -123,6 +125,7 @@ linkscripts = csadd2caldb \ | ||
| 123 | cstsmapsplit \ | 125 | cstsmapsplit \ |
| 124 | csviscube \ | 126 | csviscube \ |
| 125 | csscs \ | 127 | csscs \ |
| 128 | + csfootprint \ | ||
| 126 | csworkflow \ | 129 | csworkflow \ |
| 127 | csfindobs \ | 130 | csfindobs \ |
| 128 | csiactcopy \ | 131 | csiactcopy \ |
| @@ -163,6 +166,7 @@ testscripts = $(srcdir)/tests/__init__.py \ | @@ -163,6 +166,7 @@ testscripts = $(srcdir)/tests/__init__.py \ | ||
| 163 | $(top_srcdir)/test/test_cstsmapsplit.py \ | 166 | $(top_srcdir)/test/test_cstsmapsplit.py \ |
| 164 | $(top_srcdir)/test/test_csviscube.py \ | 167 | $(top_srcdir)/test/test_csviscube.py \ |
| 165 | $(top_srcdir)/test/test_csscs.py \ | 168 | $(top_srcdir)/test/test_csscs.py \ |
| 169 | + $(top_srcdir)/test/test_csfootprint.py \ | ||
| 166 | $(top_srcdir)/test/test_csworkflow.py \ | 170 | $(top_srcdir)/test/test_csworkflow.py \ |
| 167 | $(top_srcdir)/test/test_obsutils.py \ | 171 | $(top_srcdir)/test/test_obsutils.py \ |
| 168 | $(top_srcdir)/test/test_mputils.py \ | 172 | $(top_srcdir)/test/test_mputils.py \ |
cscripts/__init__.py.in
| 1 | # ========================================================================== | 1 | # ========================================================================== |
| 2 | # cscripts Python module | 2 | # cscripts Python module |
| 3 | # | 3 | # |
| 4 | -# Copyright (C) 2015-2021 Juergen Knoedlseder | 4 | +# Copyright (C) 2015-2022 Juergen Knoedlseder |
| 5 | # | 5 | # |
| 6 | # This program is free software: you can redistribute it and/or modify | 6 | # This program is free software: you can redistribute it and/or modify |
| 7 | # it under the terms of the GNU General Public License as published by | 7 | # it under the terms of the GNU General Public License as published by |
| @@ -28,6 +28,7 @@ __all__ = [ | @@ -28,6 +28,7 @@ __all__ = [ | ||
| 28 | "csbkgmodel", | 28 | "csbkgmodel", |
| 29 | "cscaldb", | 29 | "cscaldb", |
| 30 | "csebins", | 30 | "csebins", |
| 31 | + "csfootprint", | ||
| 31 | "csinfo", | 32 | "csinfo", |
| 32 | "cslightcrv", | 33 | "cslightcrv", |
| 33 | "csmodelinfo", | 34 | "csmodelinfo", |
| @@ -94,6 +95,7 @@ from cscripts.cstsmapmerge import cstsmapmerge | @@ -94,6 +95,7 @@ from cscripts.cstsmapmerge import cstsmapmerge | ||
| 94 | from cscripts.cstsmapsplit import cstsmapsplit | 95 | from cscripts.cstsmapsplit import cstsmapsplit |
| 95 | from cscripts.csviscube import csviscube | 96 | from cscripts.csviscube import csviscube |
| 96 | from cscripts.csscs import csscs | 97 | from cscripts.csscs import csscs |
| 98 | +from cscripts.csfootprint import csfootprint | ||
| 97 | from cscripts.csworkflow import csworkflow | 99 | from cscripts.csworkflow import csworkflow |
| 98 | from cscripts import obsutils | 100 | from cscripts import obsutils |
| 99 | from cscripts import modutils | 101 | from cscripts import modutils |
cscripts/csfootprint.par
0 → 100644
| 1 | +############################################################################# | ||
| 2 | +# # | ||
| 3 | +# Science Analysis Tools # | ||
| 4 | +# # | ||
| 5 | +# ------------------------------------------------------------------------- # | ||
| 6 | +# # | ||
| 7 | +# File: csfootprint.par # | ||
| 8 | +# # | ||
| 9 | +# Author: Juergen Knoedlseder # | ||
| 10 | +# Jurgen.Knodlseder@irap.omp.eu # | ||
| 11 | +# IRAP # | ||
| 12 | +# # | ||
| 13 | +# Purpose: Parameter file for the csfootprint script # | ||
| 14 | +# # | ||
| 15 | +############################################################################# | ||
| 16 | +# | ||
| 17 | +# Input and output parameters | ||
| 18 | +#============================ | ||
| 19 | +infile, f, h, $HOME/.gamma/statistics.xml,,, "Input high-level statistics XML file" | ||
| 20 | +outfile, f, a, NONE,,, "Output graphics file (NONE if no graphics should be generated)" | ||
| 21 | + | ||
| 22 | +# | ||
| 23 | +# Script parameters | ||
| 24 | +#================== | ||
| 25 | +tmin, t, a, NONE,,, "Start time for report (UTC string, JD, MJD or MET in seconds)" | ||
| 26 | +tmax, t, a, NONE,,, "Stop time for report (UTC string, JD, MJD or MET in seconds)" | ||
| 27 | + | ||
| 28 | +# | ||
| 29 | +# Standard parameters | ||
| 30 | +#==================== | ||
| 31 | +chatter, i, h, 2,0,4, "Chattiness of output" | ||
| 32 | +clobber, b, h, yes,,, "Overwrite existing output files with new output files?" | ||
| 33 | +debug, b, h, no,,, "Activate debugging mode?" | ||
| 34 | +mode, s, h, ql,,, "Mode of automatic parameters" | ||
| 35 | +logfile, f, h, csfootprint.log,,, "Log filename" |
cscripts/csfootprint.py
0 → 100755
| 1 | +#! /usr/bin/env python | ||
| 2 | +# ========================================================================== | ||
| 3 | +# Carbon footprint report script | ||
| 4 | +# | ||
| 5 | +# Copyright (C) 2022 Juergen Knoedlseder | ||
| 6 | +# | ||
| 7 | +# This program is free software: you can redistribute it and/or modify | ||
| 8 | +# it under the terms of the GNU General Public License as published by | ||
| 9 | +# the Free Software Foundation, either version 3 of the License, or | ||
| 10 | +# (at your option) any later version. | ||
| 11 | +# | ||
| 12 | +# This program is distributed in the hope that it will be useful, | ||
| 13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | +# GNU General Public License for more details. | ||
| 16 | +# | ||
| 17 | +# You should have received a copy of the GNU General Public License | ||
| 18 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 19 | +# | ||
| 20 | +# ========================================================================== | ||
| 21 | +import sys | ||
| 22 | +import gammalib | ||
| 23 | +import ctools | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +# ================= # | ||
| 27 | +# csfootprint class # | ||
| 28 | +# ================= # | ||
| 29 | +class csfootprint(ctools.cscript): | ||
| 30 | + """ | ||
| 31 | + Carbon footprint report script | ||
| 32 | + """ | ||
| 33 | + | ||
| 34 | + # Constructor | ||
| 35 | + def __init__(self, *argv): | ||
| 36 | + """ | ||
| 37 | + Constructor | ||
| 38 | + | ||
| 39 | + Parameters | ||
| 40 | + ---------- | ||
| 41 | + argv : list of str | ||
| 42 | + List of IRAF command line parameter strings of the form | ||
| 43 | + ``parameter=3``. | ||
| 44 | + """ | ||
| 45 | + # Initialise application by calling the base class constructor | ||
| 46 | + self._init_cscript(self.__class__.__name__, ctools.__version__, argv) | ||
| 47 | + | ||
| 48 | + # Return | ||
| 49 | + return | ||
| 50 | + | ||
| 51 | + # State methods for pickling | ||
| 52 | + def __getstate__(self): | ||
| 53 | + """ | ||
| 54 | + Extend ctools.cscript __getstate__ method | ||
| 55 | + | ||
| 56 | + Returns | ||
| 57 | + ------- | ||
| 58 | + state : dict | ||
| 59 | + Pickled instance | ||
| 60 | + """ | ||
| 61 | + # Set pickled dictionary | ||
| 62 | + state = {'base' : ctools.cscript.__getstate__(self)} | ||
| 63 | + | ||
| 64 | + # Return pickled dictionary | ||
| 65 | + return state | ||
| 66 | + | ||
| 67 | + def __setstate__(self, state): | ||
| 68 | + """ | ||
| 69 | + Extend ctools.cscript __setstate__ method | ||
| 70 | + | ||
| 71 | + Parameters | ||
| 72 | + ---------- | ||
| 73 | + state : dict | ||
| 74 | + Pickled instance | ||
| 75 | + """ | ||
| 76 | + # Set state | ||
| 77 | + ctools.cscript.__setstate__(self, state['base']) | ||
| 78 | + | ||
| 79 | + # Return | ||
| 80 | + return | ||
| 81 | + | ||
| 82 | + | ||
| 83 | + # Private methods | ||
| 84 | + def _get_parameters(self): | ||
| 85 | + """ | ||
| 86 | + Get parameters from parfile | ||
| 87 | + """ | ||
| 88 | + # Query input parameters | ||
| 89 | + self['infile'].filename() | ||
| 90 | + if self['tmin'].is_valid(): | ||
| 91 | + self['tmin'].time() | ||
| 92 | + if self['tmax'].is_valid(): | ||
| 93 | + self['tmax'].time() | ||
| 94 | + | ||
| 95 | + # Query ahead output model filename | ||
| 96 | + if self._read_ahead(): | ||
| 97 | + if self['outfile'].is_valid(): | ||
| 98 | + self['outfile'].filename() | ||
| 99 | + | ||
| 100 | + # Write input parameters into logger | ||
| 101 | + self._log_parameters(gammalib.TERSE) | ||
| 102 | + | ||
| 103 | + # Return | ||
| 104 | + return | ||
| 105 | + | ||
| 106 | + # Load statistics | ||
| 107 | + def _load_statistics(self): | ||
| 108 | + """ | ||
| 109 | + Load statistics | ||
| 110 | + """ | ||
| 111 | + # Initialise statistics | ||
| 112 | + statistics = {} | ||
| 113 | + | ||
| 114 | + # Get filename | ||
| 115 | + infile = self['infile'].filename() | ||
| 116 | + | ||
| 117 | + # Load XML file | ||
| 118 | + xml = gammalib.GXml() | ||
| 119 | + xml.load(infile) | ||
| 120 | + | ||
| 121 | + # Get useful nodes | ||
| 122 | + header = xml.element('statistics > header') | ||
| 123 | + data = xml.element('statistics > data') | ||
| 124 | + dates = header.element('dates') | ||
| 125 | + countries = data.element('countries') | ||
| 126 | + versions = data.element('versions') | ||
| 127 | + daily = data.element('daily') | ||
| 128 | + | ||
| 129 | + # Extract header dates information | ||
| 130 | + statistics['creation'] = dates.element('creation').string() | ||
| 131 | + statistics['modified'] = dates.element('modified').string() | ||
| 132 | + statistics['start'] = dates.element('start').string() | ||
| 133 | + statistics['stop'] = dates.element('stop').string() | ||
| 134 | + | ||
| 135 | + # Set used time interval [start,stop] | ||
| 136 | + if self['tmin'].is_valid(): | ||
| 137 | + start = self['tmin'].time().utc() | ||
| 138 | + if start < statistics['start']: | ||
| 139 | + start = statistics['start'] | ||
| 140 | + else: | ||
| 141 | + start = statistics['start'] | ||
| 142 | + if self['tmax'].is_valid(): | ||
| 143 | + stop = self['tmax'].time().utc() | ||
| 144 | + if stop > statistics['stop']: | ||
| 145 | + stop = statistics['stop'] | ||
| 146 | + else: | ||
| 147 | + stop = statistics['stop'] | ||
| 148 | + | ||
| 149 | + # Set used time interval | ||
| 150 | + statistics['use_start'] = start | ||
| 151 | + statistics['use_stop'] = stop | ||
| 152 | + | ||
| 153 | + # Extract list of countries | ||
| 154 | + statistics['countries'] = [] | ||
| 155 | + num = countries.elements() | ||
| 156 | + for i in range(num): | ||
| 157 | + element = countries.element(i) | ||
| 158 | + country = element.name() | ||
| 159 | + calls = element.attribute('calls') | ||
| 160 | + wall = element.attribute('wall') | ||
| 161 | + cpu = element.attribute('cpu') | ||
| 162 | + gCO2e = element.attribute('gCO2e') | ||
| 163 | + entry = {'country': country, 'calls': calls, 'wall': wall, | ||
| 164 | + 'cpu': cpu, 'gCO2e': gCO2e} | ||
| 165 | + statistics['countries'].append(entry) | ||
| 166 | + | ||
| 167 | + # Extract list of versions | ||
| 168 | + statistics['versions'] = [] | ||
| 169 | + num = versions.elements() | ||
| 170 | + for i in range(num): | ||
| 171 | + element = versions.element(i) | ||
| 172 | + version = element.name() | ||
| 173 | + calls = element.attribute('calls') | ||
| 174 | + wall = element.attribute('wall') | ||
| 175 | + cpu = element.attribute('cpu') | ||
| 176 | + gCO2e = element.attribute('gCO2e') | ||
| 177 | + entry = {'version': version, 'calls': calls, 'wall': wall, | ||
| 178 | + 'cpu': cpu, 'gCO2e': gCO2e} | ||
| 179 | + statistics['versions'].append(entry) | ||
| 180 | + | ||
| 181 | + # Extract daily and tools statistics | ||
| 182 | + statistics['daily'] = [] | ||
| 183 | + statistics['tools'] = [] | ||
| 184 | + num = daily.elements() | ||
| 185 | + total_calls = 0 | ||
| 186 | + total_wall = 0.0 | ||
| 187 | + total_cpu = 0.0 | ||
| 188 | + total_gCO2e = 0.0 | ||
| 189 | + for i in range(num): | ||
| 190 | + | ||
| 191 | + # Get date | ||
| 192 | + element = daily.element(i) | ||
| 193 | + date = element.element('value',0).string() | ||
| 194 | + | ||
| 195 | + # Continue if date is out of range | ||
| 196 | + if date < start[0:10] or date > stop[0:10]: | ||
| 197 | + continue | ||
| 198 | + | ||
| 199 | + # Collect information | ||
| 200 | + tools = element.element('tools',0) | ||
| 201 | + ntools = tools.elements() | ||
| 202 | + sum_calls = 0 | ||
| 203 | + sum_wall = 0.0 | ||
| 204 | + sum_cpu = 0.0 | ||
| 205 | + sum_gCO2e = 0.0 | ||
| 206 | + for k in range(ntools): | ||
| 207 | + | ||
| 208 | + # Extract information | ||
| 209 | + tool = tools.element(k) | ||
| 210 | + name = tool.name() | ||
| 211 | + calls = int(tool.attribute('calls')) | ||
| 212 | + wall = float(tool.attribute('wall')) | ||
| 213 | + cpu = float(tool.attribute('cpu')) | ||
| 214 | + gCO2e = float(tool.attribute('gCO2e')) | ||
| 215 | + | ||
| 216 | + # Update sums | ||
| 217 | + sum_calls += calls | ||
| 218 | + sum_wall += wall | ||
| 219 | + sum_cpu += cpu | ||
| 220 | + sum_gCO2e += gCO2e | ||
| 221 | + | ||
| 222 | + # Update tools data | ||
| 223 | + if name in statistics['tools']: | ||
| 224 | + statistics['tools'][name]['calls'] += calls | ||
| 225 | + statistics['tools'][name]['wall'] += wall | ||
| 226 | + statistics['tools'][name]['cpu'] += cpu | ||
| 227 | + statistics['tools'][name]['gCO2e'] += gCO2e | ||
| 228 | + else: | ||
| 229 | + entry = {'name': name, 'calls': calls, 'wall': wall, | ||
| 230 | + 'cpu': cpu, 'gCO2e': gCO2e} | ||
| 231 | + statistics['tools'].append(entry) | ||
| 232 | + | ||
| 233 | + # Update totals | ||
| 234 | + total_calls += sum_calls | ||
| 235 | + total_wall += sum_wall | ||
| 236 | + total_cpu += sum_cpu | ||
| 237 | + total_gCO2e += sum_gCO2e | ||
| 238 | + | ||
| 239 | + # Set entry | ||
| 240 | + entry = {'date': date, 'calls': sum_calls, 'wall': sum_wall, | ||
| 241 | + 'cpu': sum_cpu, 'gCO2e': sum_gCO2e} | ||
| 242 | + statistics['daily'].append(entry) | ||
| 243 | + | ||
| 244 | + # Update total statistics | ||
| 245 | + statistics['calls'] = total_calls | ||
| 246 | + statistics['wall'] = total_wall | ||
| 247 | + statistics['cpu'] = total_cpu | ||
| 248 | + statistics['gCO2e'] = total_gCO2e | ||
| 249 | + | ||
| 250 | + # Return statistics | ||
| 251 | + return statistics | ||
| 252 | + | ||
| 253 | + # Format time | ||
| 254 | + def _format_time(self, seconds): | ||
| 255 | + """ | ||
| 256 | + Format time | ||
| 257 | + | ||
| 258 | + Parameters | ||
| 259 | + ---------- | ||
| 260 | + seconds : float | ||
| 261 | + Time in seconds | ||
| 262 | + """ | ||
| 263 | + # Format according to precision | ||
| 264 | + if seconds < 60.0: | ||
| 265 | + format = '%.3f seconds' % (seconds) | ||
| 266 | + elif seconds < 3600.0: | ||
| 267 | + format = '%.3f minutes' % (seconds/60.0) | ||
| 268 | + else: | ||
| 269 | + format = '%.3f hours' % (seconds/3600.0) | ||
| 270 | + | ||
| 271 | + # Return format | ||
| 272 | + return format | ||
| 273 | + | ||
| 274 | + # Format carbon footprint | ||
| 275 | + def _format_footprint(self, gCO2e): | ||
| 276 | + """ | ||
| 277 | + Format carbon footprint | ||
| 278 | + | ||
| 279 | + Parameters | ||
| 280 | + ---------- | ||
| 281 | + gCO2e : float | ||
| 282 | + Carbon footprint in gCO2e | ||
| 283 | + """ | ||
| 284 | + # Format according to precision | ||
| 285 | + if gCO2e < 1000.0: | ||
| 286 | + format = '%.3f g CO2e' % (gCO2e) | ||
| 287 | + elif seconds < 1.0e6: | ||
| 288 | + format = '%.3f kg CO2e' % (gCO2e/1000.0) | ||
| 289 | + else: | ||
| 290 | + format = '%.3f t CO2e' % (gCO2e/1.0e6) | ||
| 291 | + | ||
| 292 | + # Return format | ||
| 293 | + return format | ||
| 294 | + | ||
| 295 | + # Log global statistics | ||
| 296 | + def _global_statistics(self, statistics): | ||
| 297 | + """ | ||
| 298 | + Log global statistics | ||
| 299 | + | ||
| 300 | + Parameters | ||
| 301 | + ---------- | ||
| 302 | + statistics : dict | ||
| 303 | + Statistics dictionary | ||
| 304 | + """ | ||
| 305 | + # Log header | ||
| 306 | + self._log_header1(gammalib.TERSE, 'Global statistics') | ||
| 307 | + | ||
| 308 | + # Derive information | ||
| 309 | + tstart = gammalib.GTime(statistics['use_start']) | ||
| 310 | + tstop = gammalib.GTime(statistics['use_stop']) | ||
| 311 | + duration = tstop - tstart | ||
| 312 | + if statistics['cpu'] != 0.0: | ||
| 313 | + ci_cpu = statistics['gCO2e']/(statistics['cpu']/3600.0) | ||
| 314 | + else: | ||
| 315 | + ci_cpu = 0.0 | ||
| 316 | + if duration != 0.0: | ||
| 317 | + fp_dur = statistics['gCO2e']/(duration * gammalib.sec2day) | ||
| 318 | + else: | ||
| 319 | + fp_dur = 0.0 | ||
| 320 | + fp_yr = fp_dur * 365.25 | ||
| 321 | + dur_str = self._format_time(duration) | ||
| 322 | + if statistics['wall'] != 0.0: | ||
| 323 | + load_str = '%.1f %%' % (statistics['cpu']/statistics['wall']*100.0) | ||
| 324 | + else: | ||
| 325 | + load_str = 'undefined' | ||
| 326 | + ci_cpu_str = self._format_footprint(ci_cpu) + ' / CPU hour' | ||
| 327 | + fp_dur_str = self._format_footprint(fp_dur) + ' / day' | ||
| 328 | + fp_yr_str = self._format_footprint(fp_yr) + ' / year' | ||
| 329 | + wall_str = self._format_time(statistics['wall']) | ||
| 330 | + cpu_str = self._format_time(statistics['cpu']) | ||
| 331 | + gCO2e_str = self._format_footprint(statistics['gCO2e']) | ||
| 332 | + date_str = '%s - %s' % (statistics['start'], statistics['stop']) | ||
| 333 | + use_str = '%s - %s' % (statistics['use_start'], statistics['use_stop']) | ||
| 334 | + | ||
| 335 | + # Log report information | ||
| 336 | + self._log_value(gammalib.NORMAL, 'Creation date', statistics['creation']) | ||
| 337 | + self._log_value(gammalib.NORMAL, 'Last statistics update', statistics['modified']) | ||
| 338 | + self._log_value(gammalib.NORMAL, 'Statistics date interval', date_str) | ||
| 339 | + self._log_value(gammalib.NORMAL, 'Used date interval', use_str) | ||
| 340 | + self._log_value(gammalib.NORMAL, 'Duration of used interval', dur_str) | ||
| 341 | + self._log_value(gammalib.NORMAL, 'Total number of ctool runs', statistics['calls']) | ||
| 342 | + self._log_value(gammalib.NORMAL, 'Total wall clock time', wall_str) | ||
| 343 | + self._log_value(gammalib.NORMAL, 'Total CPU time', cpu_str) | ||
| 344 | + self._log_value(gammalib.NORMAL, 'Average CPU load', load_str) | ||
| 345 | + self._log_value(gammalib.NORMAL, 'Total carbon footprint', gCO2e_str) | ||
| 346 | + self._log_value(gammalib.NORMAL, 'Average carbon intensity', ci_cpu_str) | ||
| 347 | + self._log_value(gammalib.NORMAL, 'Average daily footprint', fp_dur_str) | ||
| 348 | + self._log_value(gammalib.NORMAL, 'Expected annual footprint', fp_yr_str) | ||
| 349 | + | ||
| 350 | + # Return | ||
| 351 | + return | ||
| 352 | + | ||
| 353 | + # Log daily statistics | ||
| 354 | + def _daily_statistics(self, statistics): | ||
| 355 | + """ | ||
| 356 | + Log daily statistics | ||
| 357 | + | ||
| 358 | + Parameters | ||
| 359 | + ---------- | ||
| 360 | + statistics : dict | ||
| 361 | + Statistics dictionary | ||
| 362 | + """ | ||
| 363 | + # Log header | ||
| 364 | + self._log_header1(gammalib.TERSE, 'Daily statistics') | ||
| 365 | + | ||
| 366 | + # Log daily carbon footprint statistics | ||
| 367 | + self._log_header3(gammalib.NORMAL, 'Carbon footprint') | ||
| 368 | + | ||
| 369 | + # Loop over daily entries | ||
| 370 | + for entry in statistics['daily']: | ||
| 371 | + self._log_value(gammalib.NORMAL, entry['date'], self._format_footprint(entry['gCO2e'])) | ||
| 372 | + | ||
| 373 | + # Log daily run statistics | ||
| 374 | + self._log_header3(gammalib.NORMAL, 'ctools or cscript calls') | ||
| 375 | + | ||
| 376 | + # Loop over daily entries | ||
| 377 | + for entry in statistics['daily']: | ||
| 378 | + self._log_value(gammalib.NORMAL, entry['date'], entry['calls']) | ||
| 379 | + | ||
| 380 | + # Log daily carbon footprint statistics | ||
| 381 | + self._log_header3(gammalib.NORMAL, 'Used wall clock time') | ||
| 382 | + | ||
| 383 | + # Loop over daily entries | ||
| 384 | + for entry in statistics['daily']: | ||
| 385 | + self._log_value(gammalib.NORMAL, entry['date'], self._format_time(entry['wall'])) | ||
| 386 | + | ||
| 387 | + # Log daily carbon footprint statistics | ||
| 388 | + self._log_header3(gammalib.NORMAL, 'Used CPU time') | ||
| 389 | + | ||
| 390 | + # Loop over daily entries | ||
| 391 | + for entry in statistics['daily']: | ||
| 392 | + self._log_value(gammalib.NORMAL, entry['date'], self._format_time(entry['cpu'])) | ||
| 393 | + | ||
| 394 | + # Return | ||
| 395 | + return | ||
| 396 | + | ||
| 397 | + # Log tools statistics | ||
| 398 | + def _tools_statistics(self, statistics): | ||
| 399 | + """ | ||
| 400 | + Log tools statistics | ||
| 401 | + | ||
| 402 | + Parameters | ||
| 403 | + ---------- | ||
| 404 | + statistics : dict | ||
| 405 | + Statistics dictionary | ||
| 406 | + """ | ||
| 407 | + # Get Python version information | ||
| 408 | + req_version = (2,4) | ||
| 409 | + cur_version = sys.version_info | ||
| 410 | + | ||
| 411 | + # Log header | ||
| 412 | + self._log_header1(gammalib.TERSE, 'ctools and cscripts statistics') | ||
| 413 | + | ||
| 414 | + # Log daily carbon footprint statistics | ||
| 415 | + self._log_header3(gammalib.NORMAL, 'Carbon footprint') | ||
| 416 | + | ||
| 417 | + # Optionally sort list | ||
| 418 | + if cur_version > req_version: | ||
| 419 | + sorted_entries = sorted(statistics['tools'], key=lambda d: d['gCO2e'], reverse=True) | ||
| 420 | + else: | ||
| 421 | + sorted_entries = statistics['tools'] | ||
| 422 | + | ||
| 423 | + # Loop over entries | ||
| 424 | + for i, entry in enumerate(sorted_entries): | ||
| 425 | + if i < 10: | ||
| 426 | + level = gammalib.NORMAL | ||
| 427 | + else: | ||
| 428 | + level = gammalib.EXPLICIT | ||
| 429 | + self._log_value(level, entry['name'], self._format_footprint(entry['gCO2e'])) | ||
| 430 | + if len(sorted_entries) > 9 and self['chatter'].integer() < 3: | ||
| 431 | + self._log_string(gammalib.NORMAL, ' ... (list truncated after 10 entries) ...') | ||
| 432 | + | ||
| 433 | + # Log daily run statistics | ||
| 434 | + self._log_header3(gammalib.NORMAL, 'ctools or cscript calls') | ||
| 435 | + | ||
| 436 | + # Optionally sort list | ||
| 437 | + if cur_version > req_version: | ||
| 438 | + sorted_entries = sorted(statistics['tools'], key=lambda d: d['calls'], reverse=True) | ||
| 439 | + else: | ||
| 440 | + sorted_entries = statistics['tools'] | ||
| 441 | + | ||
| 442 | + # Loop over entries | ||
| 443 | + for i, entry in enumerate(sorted_entries): | ||
| 444 | + if i < 10: | ||
| 445 | + level = gammalib.NORMAL | ||
| 446 | + else: | ||
| 447 | + level = gammalib.EXPLICIT | ||
| 448 | + self._log_value(level, entry['name'], entry['calls']) | ||
| 449 | + if len(sorted_entries) > 9 and self['chatter'].integer() < 3: | ||
| 450 | + self._log_string(gammalib.NORMAL, ' ... (list truncated after 10 entries) ...') | ||
| 451 | + | ||
| 452 | + # Log daily carbon footprint statistics | ||
| 453 | + self._log_header3(gammalib.NORMAL, 'Used wall clock time') | ||
| 454 | + | ||
| 455 | + # Optionally sort list | ||
| 456 | + if cur_version > req_version: | ||
| 457 | + sorted_entries = sorted(statistics['tools'], key=lambda d: d['wall'], reverse=True) | ||
| 458 | + else: | ||
| 459 | + sorted_entries = statistics['tools'] | ||
| 460 | + | ||
| 461 | + # Loop over entries | ||
| 462 | + for i, entry in enumerate(sorted_entries): | ||
| 463 | + if i < 10: | ||
| 464 | + level = gammalib.NORMAL | ||
| 465 | + else: | ||
| 466 | + level = gammalib.EXPLICIT | ||
| 467 | + self._log_value(level, entry['name'], self._format_time(entry['wall'])) | ||
| 468 | + if len(sorted_entries) > 9 and self['chatter'].integer() < 3: | ||
| 469 | + self._log_string(gammalib.NORMAL, ' ... (list truncated after 10 entries) ...') | ||
| 470 | + | ||
| 471 | + # Log daily carbon footprint statistics | ||
| 472 | + self._log_header3(gammalib.NORMAL, 'Used CPU time') | ||
| 473 | + | ||
| 474 | + # Optionally sort list | ||
| 475 | + if cur_version > req_version: | ||
| 476 | + sorted_entries = sorted(statistics['tools'], key=lambda d: d['cpu'], reverse=True) | ||
| 477 | + else: | ||
| 478 | + sorted_entries = statistics['tools'] | ||
| 479 | + | ||
| 480 | + # Loop over entries | ||
| 481 | + for i, entry in enumerate(sorted_entries): | ||
| 482 | + if i < 10: | ||
| 483 | + level = gammalib.NORMAL | ||
| 484 | + else: | ||
| 485 | + level = gammalib.EXPLICIT | ||
| 486 | + self._log_value(level, entry['name'], self._format_time(entry['cpu'])) | ||
| 487 | + if len(sorted_entries) > 9 and self['chatter'].integer() < 3: | ||
| 488 | + self._log_string(gammalib.NORMAL, ' ... (list truncated after 10 entries) ...') | ||
| 489 | + | ||
| 490 | + | ||
| 491 | + # Return | ||
| 492 | + return | ||
| 493 | + | ||
| 494 | + | ||
| 495 | + # Public methods | ||
| 496 | + def run(self): | ||
| 497 | + """ | ||
| 498 | + Run the script | ||
| 499 | + """ | ||
| 500 | + # Switch screen logging on in debug mode | ||
| 501 | + if self._logDebug(): | ||
| 502 | + self._log.cout(True) | ||
| 503 | + | ||
| 504 | + # Get parameters | ||
| 505 | + self._get_parameters() | ||
| 506 | + | ||
| 507 | + # Log header | ||
| 508 | + self._log_header1(gammalib.TERSE, 'Load statistics data') | ||
| 509 | + | ||
| 510 | + # Load statistics | ||
| 511 | + statistics = self._load_statistics() | ||
| 512 | + | ||
| 513 | + # Log statistics | ||
| 514 | + self._global_statistics(statistics) | ||
| 515 | + self._daily_statistics(statistics) | ||
| 516 | + self._tools_statistics(statistics) | ||
| 517 | + | ||
| 518 | + # Return | ||
| 519 | + return | ||
| 520 | + | ||
| 521 | + def save(self): | ||
| 522 | + """ | ||
| 523 | + Save something | ||
| 524 | + """ | ||
| 525 | + # Write header | ||
| 526 | + self._log_header1(gammalib.TERSE, 'Save graphics') | ||
| 527 | + | ||
| 528 | + # Continue only if filename is valid | ||
| 529 | + if self['outfile'].is_valid(): | ||
| 530 | + | ||
| 531 | + # Implement saving of graphics file | ||
| 532 | + pass | ||
| 533 | + | ||
| 534 | + # ... signal that no graphics file was specified | ||
| 535 | + else: | ||
| 536 | + self._log_value(gammalib.NORMAL, 'Graphics file', 'not specified') | ||
| 537 | + | ||
| 538 | + # Return | ||
| 539 | + return | ||
| 540 | + | ||
| 541 | + | ||
| 542 | +# ======================== # | ||
| 543 | +# Main routine entry point # | ||
| 544 | +# ======================== # | ||
| 545 | +if __name__ == '__main__': | ||
| 546 | + | ||
| 547 | + # Create instance of application | ||
| 548 | + app = csfootprint(sys.argv) | ||
| 549 | + | ||
| 550 | + # Execute application | ||
| 551 | + app.execute() |
doc/source/users/environment.rst
| @@ -60,4 +60,104 @@ computation took, and :math:`{\rm Carbon\,\,footprint}` is the carbon footprint | @@ -60,4 +60,104 @@ computation took, and :math:`{\rm Carbon\,\,footprint}` is the carbon footprint | ||
| 60 | 60 | ||
| 61 | The carbon footprint of all ctools and cscript runs are stored in an ASCII file | 61 | The carbon footprint of all ctools and cscript runs are stored in an ASCII file |
| 62 | that you will find in a folder under your home directory, named ``.gamma/statistics.csv``. | 62 | that you will find in a folder under your home directory, named ``.gamma/statistics.csv``. |
| 63 | +This file is regularly scanned and purged by the GammaLib daemon that creates the | ||
| 64 | +high-level statistics file ``.gamma/statistics.xml`` that is in the same folder. You may | ||
| 65 | +display the content of this file using the ``csfootprint`` script: | ||
| 66 | + | ||
| 67 | +.. code-block:: bash | ||
| 68 | + | ||
| 69 | + $ csfootprint debug=yes | ||
| 70 | + Start time for report (UTC string, JD, MJD or MET in seconds) [NONE] | ||
| 71 | + Stop time for report (UTC string, JD, MJD or MET in seconds) [NONE] | ||
| 72 | + Output graphics file (NONE if no graphics should be generated) [NONE] | ||
| 73 | + ... | ||
| 74 | + 2022-02-20T14:38:29: +===================+ | ||
| 75 | + 2022-02-20T14:38:29: | Global statistics | | ||
| 76 | + 2022-02-20T14:38:29: +===================+ | ||
| 77 | + 2022-02-20T14:38:29: Creation date .............: 2022-02-19T22:09:05 | ||
| 78 | + 2022-02-20T14:38:29: Last statistics update ....: 2022-02-20T14:35:20 | ||
| 79 | + 2022-02-20T14:38:29: Statistics date interval ..: 2022-02-18T22:21:56 - 2022-02-20T14:35:17 | ||
| 80 | + 2022-02-20T14:38:29: Used date interval ........: 2022-02-18T22:21:56 - 2022-02-20T14:35:17 | ||
| 81 | + 2022-02-20T14:38:29: Duration of used interval .: 40.222 hours | ||
| 82 | + 2022-02-20T14:38:29: Total number of ctool runs : 3104 | ||
| 83 | + 2022-02-20T14:38:29: Total wall clock time .....: 34.200 minutes | ||
| 84 | + 2022-02-20T14:38:29: Total CPU time ............: 27.543 minutes | ||
| 85 | + 2022-02-20T14:38:29: Average CPU load ..........: 80.5 % | ||
| 86 | + 2022-02-20T14:38:29: Total carbon footprint ....: 1.623 g CO2e | ||
| 87 | + 2022-02-20T14:38:29: Average carbon intensity ..: 3.535 g CO2e / CPU hour | ||
| 88 | + 2022-02-20T14:38:29: Average daily footprint ...: 0.968 g CO2e / day | ||
| 89 | + 2022-02-20T14:38:29: Expected annual footprint .: 353.632 g CO2e / year | ||
| 90 | + 2022-02-20T14:38:29: | ||
| 91 | + 2022-02-20T14:38:29: +==================+ | ||
| 92 | + 2022-02-20T14:38:29: | Daily statistics | | ||
| 93 | + 2022-02-20T14:38:29: +==================+ | ||
| 94 | + 2022-02-20T14:38:29: === Carbon footprint === | ||
| 95 | + 2022-02-20T14:38:29: 2022-02-18 ................: 1.336 g CO2e | ||
| 96 | + 2022-02-20T14:38:29: 2022-02-19 ................: 0.010 g CO2e | ||
| 97 | + 2022-02-20T14:38:29: 2022-02-20 ................: 0.277 g CO2e | ||
| 98 | + 2022-02-20T14:38:29: === ctools or cscript calls === | ||
| 99 | + 2022-02-20T14:38:29: 2022-02-18 ................: 2895 | ||
| 100 | + 2022-02-20T14:38:29: 2022-02-19 ................: 80 | ||
| 101 | + 2022-02-20T14:38:29: 2022-02-20 ................: 129 | ||
| 102 | + 2022-02-20T14:38:29: === Used wall clock time === | ||
| 103 | + 2022-02-20T14:38:29: 2022-02-18 ................: 25.483 minutes | ||
| 104 | + 2022-02-20T14:38:29: 2022-02-19 ................: 1.033 minutes | ||
| 105 | + 2022-02-20T14:38:29: 2022-02-20 ................: 7.683 minutes | ||
| 106 | + 2022-02-20T14:38:29: === Used CPU time === | ||
| 107 | + 2022-02-20T14:38:29: 2022-02-18 ................: 22.682 minutes | ||
| 108 | + 2022-02-20T14:38:29: 2022-02-19 ................: 9.895 seconds | ||
| 109 | + 2022-02-20T14:38:29: 2022-02-20 ................: 4.695 minutes | ||
| 110 | + 2022-02-20T14:38:29: | ||
| 111 | + 2022-02-20T14:38:29: +================================+ | ||
| 112 | + 2022-02-20T14:38:29: | ctools and cscripts statistics | | ||
| 113 | + 2022-02-20T14:38:29: +================================+ | ||
| 114 | + 2022-02-20T14:38:29: === Carbon footprint === | ||
| 115 | + 2022-02-20T14:38:29: ctlike ....................: 0.318 g CO2e | ||
| 116 | + 2022-02-20T14:38:29: cspull ....................: 0.186 g CO2e | ||
| 117 | + 2022-02-20T14:38:29: csbkgmodel ................: 0.178 g CO2e | ||
| 118 | + 2022-02-20T14:38:29: ctobssim ..................: 0.172 g CO2e | ||
| 119 | + 2022-02-20T14:38:29: ctobssim ..................: 0.087 g CO2e | ||
| 120 | + 2022-02-20T14:38:29: comobsbin .................: 0.081 g CO2e | ||
| 121 | + 2022-02-20T14:38:29: comlixmap .................: 0.069 g CO2e | ||
| 122 | + 2022-02-20T14:38:29: ctulimit ..................: 0.064 g CO2e | ||
| 123 | + 2022-02-20T14:38:29: cstsdist ..................: 0.058 g CO2e | ||
| 124 | + 2022-02-20T14:38:29: ctselect ..................: 0.044 g CO2e | ||
| 125 | + 2022-02-20T14:38:29: ... (list truncated after 10 entries) ... | ||
| 126 | + 2022-02-20T14:38:29: === ctools or cscript calls === | ||
| 127 | + 2022-02-20T14:38:29: ctobssim ..................: 1795 | ||
| 128 | + 2022-02-20T14:38:29: ctlike ....................: 220 | ||
| 129 | + 2022-02-20T14:38:29: ctselect ..................: 87 | ||
| 130 | + 2022-02-20T14:38:29: csfootprint ...............: 80 | ||
| 131 | + 2022-02-20T14:38:29: cscaldb ...................: 79 | ||
| 132 | + 2022-02-20T14:38:29: csscs .....................: 55 | ||
| 133 | + 2022-02-20T14:38:29: ctulimit ..................: 54 | ||
| 134 | + 2022-02-20T14:38:29: ctcubemask ................: 51 | ||
| 135 | + 2022-02-20T14:38:29: csphagen ..................: 46 | ||
| 136 | + 2022-02-20T14:38:29: ctbin .....................: 31 | ||
| 137 | + 2022-02-20T14:38:29: ... (list truncated after 10 entries) ... | ||
| 138 | + 2022-02-20T14:38:29: === Used wall clock time === | ||
| 139 | + 2022-02-20T14:38:29: ctlike ....................: 5.367 minutes | ||
| 140 | + 2022-02-20T14:38:29: cspull ....................: 3.817 minutes | ||
| 141 | + 2022-02-20T14:38:29: csbkgmodel ................: 3.067 minutes | ||
| 142 | + 2022-02-20T14:38:29: ctobssim ..................: 2.967 minutes | ||
| 143 | + 2022-02-20T14:38:29: csfootprint ...............: 2.300 minutes | ||
| 144 | + 2022-02-20T14:38:29: ctobssim ..................: 1.483 minutes | ||
| 145 | + 2022-02-20T14:38:29: comobsbin .................: 1.367 minutes | ||
| 146 | + 2022-02-20T14:38:29: cstsdist ..................: 1.300 minutes | ||
| 147 | + 2022-02-20T14:38:29: comlixmap .................: 1.183 minutes | ||
| 148 | + 2022-02-20T14:38:29: ctselect ..................: 1.083 minutes | ||
| 149 | + 2022-02-20T14:38:29: ... (list truncated after 10 entries) ... | ||
| 150 | + 2022-02-20T14:38:29: === Used CPU time === | ||
| 151 | + 2022-02-20T14:38:29: ctlike ....................: 5.392 minutes | ||
| 152 | + 2022-02-20T14:38:29: cspull ....................: 3.157 minutes | ||
| 153 | + 2022-02-20T14:38:29: csbkgmodel ................: 3.029 minutes | ||
| 154 | + 2022-02-20T14:38:29: ctobssim ..................: 2.921 minutes | ||
| 155 | + 2022-02-20T14:38:29: ctobssim ..................: 1.469 minutes | ||
| 156 | + 2022-02-20T14:38:29: comobsbin .................: 1.367 minutes | ||
| 157 | + 2022-02-20T14:38:29: comlixmap .................: 1.169 minutes | ||
| 158 | + 2022-02-20T14:38:29: ctulimit ..................: 1.086 minutes | ||
| 159 | + 2022-02-20T14:38:29: cstsdist ..................: 58.978 seconds | ||
| 160 | + 2022-02-20T14:38:29: ctselect ..................: 45.005 seconds | ||
| 161 | + 2022-02-20T14:38:29: ... (list truncated after 10 entries) ... | ||
| 162 | + | ||
| 63 | 163 |
doc/source/users/reference_manual/csfootprint.rst
0 → 100644
| 1 | +.. _csfootprint: | ||
| 2 | + | ||
| 3 | +csfootprint | ||
| 4 | +=========== | ||
| 5 | + | ||
| 6 | +Generates a carbon footprint report for the usage of ctools on your computed. | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +Synopsis | ||
| 10 | +-------- | ||
| 11 | + | ||
| 12 | +This script generates a carbon footprint report based on the usage of ctools | ||
| 13 | +on your computed. ctools usage statistics are collected in the file | ||
| 14 | +``~/.gamma/statistics.xml`` that is located in the user's home directory. The | ||
| 15 | +information file is updated using a dedicated daemon that works in the background | ||
| 16 | +and collects information about ctools usage. | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +General parameters | ||
| 20 | +------------------ | ||
| 21 | + | ||
| 22 | +``(infile = $HOME/.gamma/statistics.xml) [file]`` | ||
| 23 | + Input high-level statistics XML file. | ||
| 24 | + | ||
| 25 | +``outfile [file]`` | ||
| 26 | + Output graphics file (``NONE`` if no graphics should be generated). | ||
| 27 | + | ||
| 28 | +``tmin [time]`` | ||
| 29 | + Start time for footprint reporting (UTC string, JD, MJD or MET in seconds). | ||
| 30 | + Start times given in MET seconds are counted with respect to the time | ||
| 31 | + reference of the input observation(s). | ||
| 32 | + If ``INDEF``, ``NONE``, ``UNDEF`` or ``UNDEFINED`` is passed as value, the | ||
| 33 | + report will be generated for the full data provided in the statistics | ||
| 34 | + file. | ||
| 35 | + | ||
| 36 | +``tmax [time]`` | ||
| 37 | + Stop time for footprint reporting (UTC string, JD, MJD or MET in seconds). | ||
| 38 | + Stop times given in MET seconds are counted with respect to the time | ||
| 39 | + reference of the input observation(s). | ||
| 40 | + If ``INDEF``, ``NONE``, ``UNDEF`` or ``UNDEFINED`` is passed as value, the | ||
| 41 | + report will be generated for the full data provided in the statistics | ||
| 42 | + file. | ||
| 43 | + | ||
| 44 | + | ||
| 45 | +Standard parameters | ||
| 46 | +------------------- | ||
| 47 | + | ||
| 48 | +``(chatter = 2) [integer]`` | ||
| 49 | + Verbosity of the executable: | ||
| 50 | + ``chatter = 0``: no information will be logged | ||
| 51 | + | ||
| 52 | + ``chatter = 1``: only errors will be logged | ||
| 53 | + | ||
| 54 | + ``chatter = 2``: errors and actions will be logged | ||
| 55 | + | ||
| 56 | + ``chatter = 3``: report about the task execution | ||
| 57 | + | ||
| 58 | + ``chatter = 4``: detailed report about the task execution | ||
| 59 | + | ||
| 60 | +``(clobber = yes) [boolean]`` | ||
| 61 | + Specifies whether an existing output file should be overwritten. | ||
| 62 | + | ||
| 63 | +``(debug = no) [boolean]`` | ||
| 64 | + Enables debug mode. In debug mode the executable will dump any log file output to the console. | ||
| 65 | + | ||
| 66 | +``(mode = ql) [string]`` | ||
| 67 | + Mode of automatic parameters (default is ``ql``, i.e. "query and learn"). | ||
| 68 | + | ||
| 69 | +``(logfile = csfootprint.log) [string]`` | ||
| 70 | + Name of log file. | ||
| 71 | + | ||
| 72 | + | ||
| 73 | +Related tools or scripts | ||
| 74 | +------------------------ | ||
| 75 | + | ||
| 76 | +None |
doc/source/users/reference_manual/index.rst
| @@ -57,6 +57,7 @@ CTA and IACT analysis tools and scripts | @@ -57,6 +57,7 @@ CTA and IACT analysis tools and scripts | ||
| 57 | ctskymap --- Generates sky map <ctskymap> | 57 | ctskymap --- Generates sky map <ctskymap> |
| 58 | csbkgmodel --- Generates background model for 3D analysis <csbkgmodel> | 58 | csbkgmodel --- Generates background model for 3D analysis <csbkgmodel> |
| 59 | csebins --- Generates energy boundaries for stacked analysis <csebins> | 59 | csebins --- Generates energy boundaries for stacked analysis <csebins> |
| 60 | + csfootprint --- Generates carbon footprint report <csfootprint> | ||
| 60 | csobsdef --- Generates observation definition file <csobsdef> | 61 | csobsdef --- Generates observation definition file <csobsdef> |
| 61 | csobsselect --- Select observations from observation definition file <csobsselect> | 62 | csobsselect --- Select observations from observation definition file <csobsselect> |
| 62 | csphagen --- Generates PHA, ARF, RMF files based on source/background regions <csphagen> | 63 | csphagen --- Generates PHA, ARF, RMF files based on source/background regions <csphagen> |
test/data/statistics.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | +<statistics title="High-level statistic"> | ||
| 3 | + <header> | ||
| 4 | + <dates> | ||
| 5 | + <creation>2022-02-19T22:09:05</creation> | ||
| 6 | + <modified>2022-02-20T14:35:20</modified> | ||
| 7 | + <start>2022-02-18T22:21:56</start> | ||
| 8 | + <stop>2022-02-20T14:35:17</stop> | ||
| 9 | + </dates> | ||
| 10 | + <countries> | ||
| 11 | + <country>FR</country> | ||
| 12 | + </countries> | ||
| 13 | + </header> | ||
| 14 | + <data> | ||
| 15 | + <daily> | ||
| 16 | + <date> | ||
| 17 | + <value>2022-02-18</value> | ||
| 18 | + <tools> | ||
| 19 | + <test_GApplication version="1.0.0" calls="10" wall="0" cpu="0.034568" gCO2e="3.6524768e-05" /> | ||
| 20 | + <ctobssim version="2.0.0.dev" calls="1795" wall="178" cpu="175.230736" gCO2e="0.172060195882" /> | ||
| 21 | + <ctselect version="2.0.0.dev" calls="87" wall="65" cpu="45.005446" gCO2e="0.0441931424436" /> | ||
| 22 | + <ctphase version="2.0.0.dev" calls="13" wall="0" cpu="0.162489" gCO2e="0.0001595595941" /> | ||
| 23 | + <ctfindvar version="2.0.0.dev" calls="9" wall="3" cpu="2.356012" gCO2e="0.002313321049" /> | ||
| 24 | + <ctbin version="2.0.0.dev" calls="31" wall="6" cpu="4.978268" gCO2e="0.004889514038" /> | ||
| 25 | + <ctlike version="2.0.0.dev" calls="220" wall="322" cpu="323.513057" gCO2e="0.31765157135" /> | ||
| 26 | + <cttsmap version="2.0.0.dev" calls="10" wall="12" cpu="10.679273" gCO2e="0.01048572233" /> | ||
| 27 | + <ctmodel version="2.0.0.dev" calls="28" wall="6" cpu="4.591355" gCO2e="0.004508190556" /> | ||
| 28 | + <ctskymap version="2.0.0.dev" calls="19" wall="1" cpu="0.433249" gCO2e="0.0004254149905" /> | ||
| 29 | + <ctexpcube version="2.0.0.dev" calls="24" wall="6" cpu="4.030692" gCO2e="0.00395767278" /> | ||
| 30 | + <ctpsfcube version="2.0.0.dev" calls="23" wall="5" cpu="3.274088" gCO2e="0.003214774076" /> | ||
| 31 | + <ctedispcube version="2.0.0.dev" calls="14" wall="3" cpu="3.050093" gCO2e="0.002994823833" /> | ||
| 32 | + <ctbkgcube version="2.0.0.dev" calls="23" wall="6" cpu="2.757245" gCO2e="0.002707299323" /> | ||
| 33 | + <ctmapcube version="2.0.0.dev" calls="14" wall="14" cpu="4.75437" gCO2e="0.0046682128217" /> | ||
| 34 | + <ctcubemask version="2.0.0.dev" calls="51" wall="8" cpu="1.13723" gCO2e="0.0011201495309" /> | ||
| 35 | + <ctbutterfly version="2.0.0.dev" calls="5" wall="1" cpu="0.759734" gCO2e="0.0007459676696" /> | ||
| 36 | + <ctulimit version="2.0.0.dev" calls="54" wall="64" cpu="65.159264" gCO2e="0.06397913951" /> | ||
| 37 | + <cterror version="2.0.0.dev" calls="10" wall="25" cpu="25.103675" gCO2e="0.02464868358" /> | ||
| 38 | + <ctprob version="2.0.0.dev" calls="11" wall="4" cpu="1.608447" gCO2e="0.0015793075709" /> | ||
| 39 | + <cscript_test version="2.0.0.dev" calls="27" wall="3" cpu="0.913572" gCO2e="0.000897810804" /> | ||
| 40 | + <ctobservation_test version="2.0.0.dev" calls="2" wall="0" cpu="0.002656" gCO2e="2.608842e-06" /> | ||
| 41 | + <ctlikelihood_test version="2.0.0.dev" calls="1" wall="0" cpu="0.000474" gCO2e="4.673725e-07" /> | ||
| 42 | + <csadd2caldb version="2.0.0.dev" calls="7" wall="0" cpu="0.082939" gCO2e="8.1443581e-05" /> | ||
| 43 | + <csbkgmodel version="2.0.0.dev" calls="16" wall="184" cpu="181.730569" gCO2e="0.178436729885" /> | ||
| 44 | + <cscaldb version="2.0.0.dev" calls="6" wall="0" cpu="0.020241" gCO2e="1.9882967e-05" /> | ||
| 45 | + <csebins version="2.0.0.dev" calls="3" wall="1" cpu="0.586342" gCO2e="0.000575717516" /> | ||
| 46 | + <csobsselect version="2.0.0.dev" calls="18" wall="1" cpu="0.091911" gCO2e="9.1630531e-05" /> | ||
| 47 | + <cslightcrv version="2.0.0.dev" calls="27" wall="45" cpu="29.142719" gCO2e="0.028614540668" /> | ||
| 48 | + <csphagen version="2.0.0.dev" calls="46" wall="38" cpu="33.605548" gCO2e="0.032996623152" /> | ||
| 49 | + <csmodelinfo version="2.0.0.dev" calls="4" wall="2" cpu="0.510316" gCO2e="0.000501071409" /> | ||
| 50 | + <csmodelmerge version="2.0.0.dev" calls="6" wall="0" cpu="0.035814" gCO2e="3.5175674e-05" /> | ||
| 51 | + <csmodelselect version="2.0.0.dev" calls="3" wall="0" cpu="0.032228" gCO2e="3.164878e-05" /> | ||
| 52 | + <csmodelsois version="2.0.0.dev" calls="4" wall="5" cpu="4.443827" gCO2e="0.004363287526" /> | ||
| 53 | + <csobs2caldb version="2.0.0.dev" calls="4" wall="0" cpu="0.536876" gCO2e="0.00052715198" /> | ||
| 54 | + <csobsdef version="2.0.0.dev" calls="5" wall="2" cpu="2.083649" gCO2e="0.002045889685" /> | ||
| 55 | + <csobsinfo version="2.0.0.dev" calls="5" wall="3" cpu="2.06328" gCO2e="0.00202735977" /> | ||
| 56 | + <csphasecrv version="2.0.0.dev" calls="26" wall="29" cpu="16.067829" gCO2e="0.015776636533" /> | ||
| 57 | + <cspull version="2.0.0.dev" calls="24" wall="6" cpu="2.647948" gCO2e="0.002599984392" /> | ||
| 58 | + <csresmap version="2.0.0.dev" calls="6" wall="0" cpu="0.614617" gCO2e="0.0006034869" /> | ||
| 59 | + <csresspec version="2.0.0.dev" calls="8" wall="3" cpu="3.078816" gCO2e="0.003023022045" /> | ||
| 60 | + <csroot2caldb version="2.0.0.dev" calls="2" wall="1" cpu="0.036487" gCO2e="3.58296e-05" /> | ||
| 61 | + <cssens version="2.0.0.dev" calls="12" wall="25" cpu="12.589562" gCO2e="0.012361392076" /> | ||
| 62 | + <csspec version="2.0.0.dev" calls="18" wall="64" cpu="43.689946" gCO2e="0.042898087855" /> | ||
| 63 | + <cssrcdetect version="2.0.0.dev" calls="3" wall="1" cpu="0.155595" gCO2e="0.00015277975" /> | ||
| 64 | + <cstsdist version="2.0.0.dev" calls="17" wall="78" cpu="58.977613" gCO2e="0.057908662799" /> | ||
| 65 | + <cstsmapmerge version="2.0.0.dev" calls="7" wall="0" cpu="0.054628" gCO2e="5.3648664e-05" /> | ||
| 66 | + <cstsmapsplit version="2.0.0.dev" calls="7" wall="3" cpu="0.686096" gCO2e="0.000673666381" /> | ||
| 67 | + <csviscube version="2.0.0.dev" calls="2" wall="1" cpu="1.127427" gCO2e="0.0011069963" /> | ||
| 68 | + <csscs version="2.0.0.dev" calls="55" wall="32" cpu="23.301421" gCO2e="0.022879160613" /> | ||
| 69 | + <csworkflow version="2.0.0.dev" calls="3" wall="22" cpu="21.524805" gCO2e="0.021134671" /> | ||
| 70 | + <mputils_test version="2.0.0.dev" calls="9" wall="0" cpu="0.019627" gCO2e="1.92879525e-05" /> | ||
| 71 | + <csfindobs version="2.0.0.dev" calls="5" wall="0" cpu="0.03152" gCO2e="3.0956552e-05" /> | ||
| 72 | + <csiactcopy version="2.0.0.dev" calls="8" wall="2" cpu="0.12279" gCO2e="0.000120576215" /> | ||
| 73 | + <csiactdata version="2.0.0.dev" calls="4" wall="0" cpu="0.023479" gCO2e="2.3057371e-05" /> | ||
| 74 | + <csiactobs version="2.0.0.dev" calls="9" wall="7" cpu="4.970589" gCO2e="0.004880509978" /> | ||
| 75 | + <comobsselect version="2.0.0.dev" calls="2" wall="1" cpu="0.118271" gCO2e="0.0001161293" /> | ||
| 76 | + <comobsbin version="2.0.0.dev" calls="3" wall="82" cpu="82.020818" gCO2e="0.080534191756" /> | ||
| 77 | + <comobsback version="2.0.0.dev" calls="5" wall="21" cpu="21.588201" gCO2e="0.02119691057" /> | ||
| 78 | + <comobsmodel version="2.0.0.dev" calls="3" wall="1" cpu="0.475343" gCO2e="0.000466731257" /> | ||
| 79 | + <comobsadd version="2.0.0.dev" calls="3" wall="2" cpu="1.467164" gCO2e="0.00144057658" /> | ||
| 80 | + <comobsres version="2.0.0.dev" calls="3" wall="19" cpu="17.898668" gCO2e="0.017574257417" /> | ||
| 81 | + <comobssim version="2.0.0.dev" calls="3" wall="1" cpu="0.355431" gCO2e="0.000348993711" /> | ||
| 82 | + <comlixfit version="2.0.0.dev" calls="5" wall="44" cpu="42.639466" gCO2e="0.041866632735" /> | ||
| 83 | + <comlixmap version="2.0.0.dev" calls="5" wall="71" cpu="70.110307" gCO2e="0.06883955744" /> | ||
| 84 | + <comsrcdetect version="2.0.0.dev" calls="3" wall="0" cpu="0.035303" gCO2e="3.4668041e-05" /> | ||
| 85 | + </tools> | ||
| 86 | + </date> | ||
| 87 | + <date> | ||
| 88 | + <value>2022-02-19</value> | ||
| 89 | + <tools> | ||
| 90 | + <cscaldb version="2.0.0.dev" calls="79" wall="27" cpu="2.098166" gCO2e="0.00206024862" /> | ||
| 91 | + <ctobssim version="2.0.0.dev" calls="1" wall="35" cpu="7.797325" gCO2e="0.007656001" /> | ||
| 92 | + </tools> | ||
| 93 | + </date> | ||
| 94 | + <date> | ||
| 95 | + <value>2022-02-20</value> | ||
| 96 | + <tools> | ||
| 97 | + <ctobssim version="2.0.0.dev" calls="14" wall="89" cpu="88.139225" gCO2e="0.086544736" /> | ||
| 98 | + <ctlike version="2.0.0.dev" calls="14" wall="1" cpu="2.907895" gCO2e="0.0028552129" /> | ||
| 99 | + <cspull version="2.0.0.dev" calls="10" wall="229" cpu="189.407517" gCO2e="0.1859745197" /> | ||
| 100 | + <test_GApplication version="1.0.0" calls="4" wall="1" cpu="0.020321" gCO2e="2.2644983e-05" country="FR" /> | ||
| 101 | + <cscaldb version="2.0.0.dev" country="FR" calls="7" wall="3" cpu="0.194611" gCO2e="0.00019109055" /> | ||
| 102 | + <csfootprint version="2.0.0.dev" country="FR" calls="80" wall="138" cpu="1.05496" gCO2e="0.00103598216" /> | ||
| 103 | + </tools> | ||
| 104 | + </date> | ||
| 105 | + </daily> | ||
| 106 | + <countries> | ||
| 107 | + <FR version="2.0.0.dev" calls="83" wall="140" cpu="1.136547" gCO2e="0.00111609432" /> | ||
| 108 | + </countries> | ||
| 109 | + <versions> | ||
| 110 | + <2.0.0.dev calls="82" wall="138" cpu="1.109517" gCO2e="0.00108955228" /> | ||
| 111 | + </versions> | ||
| 112 | + </data> | ||
| 113 | +</statistics> |
test/test_csfootprint.py
0 → 100644
| 1 | +#! /usr/bin/env python | ||
| 2 | +# ========================================================================== | ||
| 3 | +# This scripts performs unit tests for the csfootprint script. | ||
| 4 | +# | ||
| 5 | +# Copyright (C) 2022 Juergen Knoedlseder | ||
| 6 | +# | ||
| 7 | +# This program is free software: you can redistribute it and/or modify | ||
| 8 | +# it under the terms of the GNU General Public License as published by | ||
| 9 | +# the Free Software Foundation, either version 3 of the License, or | ||
| 10 | +# (at your option) any later version. | ||
| 11 | +# | ||
| 12 | +# This program is distributed in the hope that it will be useful, | ||
| 13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | +# GNU General Public License for more details. | ||
| 16 | +# | ||
| 17 | +# You should have received a copy of the GNU General Public License | ||
| 18 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 19 | +# | ||
| 20 | +# ========================================================================== | ||
| 21 | +import os | ||
| 22 | +import gammalib | ||
| 23 | +import cscripts | ||
| 24 | +from testing import test | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +# ================================= # | ||
| 28 | +# Test class for csfootprint script # | ||
| 29 | +# ================================= # | ||
| 30 | +class Test(test): | ||
| 31 | + """ | ||
| 32 | + Test class for csfootprint script | ||
| 33 | + | ||
| 34 | + This test class makes unit tests for the csfootprint script 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 | + # Set members | ||
| 47 | + self._infile = self._datadir + '/statistics.xml' | ||
| 48 | + | ||
| 49 | + # Return | ||
| 50 | + return | ||
| 51 | + | ||
| 52 | + # Set test functions | ||
| 53 | + def set(self): | ||
| 54 | + """ | ||
| 55 | + Set all test functions | ||
| 56 | + """ | ||
| 57 | + # Set test name | ||
| 58 | + self.name('csfootprint') | ||
| 59 | + | ||
| 60 | + # Append tests | ||
| 61 | + self.append(self._test_cmd, 'Test csfootprint on command line') | ||
| 62 | + self.append(self._test_python, 'Test csfootprint from Python') | ||
| 63 | + self.append(self._test_pickeling, 'Test csfootprint pickeling') | ||
| 64 | + | ||
| 65 | + # Return | ||
| 66 | + return | ||
| 67 | + | ||
| 68 | + # Test csfootprint on command line | ||
| 69 | + def _test_cmd(self): | ||
| 70 | + """ | ||
| 71 | + Test csfootprint on the command line | ||
| 72 | + """ | ||
| 73 | + # Set script name | ||
| 74 | + csfootprint = self._script('csfootprint') | ||
| 75 | + | ||
| 76 | + # Setup csfootprint command | ||
| 77 | + cmd = csfootprint+' infile="'+self._infile+'" outfile=NONE tmin=NONE'+ \ | ||
| 78 | + ' tmax=NONE logfile="csfootprint_cmd1.log" chatter=1' | ||
| 79 | + | ||
| 80 | + # Check if execution was successful | ||
| 81 | + self.test_value(self._execute(cmd), 0, | ||
| 82 | + 'Check successful execution from command line') | ||
| 83 | + | ||
| 84 | + # Setup csfootprint command | ||
| 85 | + cmd = csfootprint+' infile="file_that_does_not_exist.xml" outfile=NONE tmin=NONE'+ \ | ||
| 86 | + ' tmax=NONE logfile="csfootprint_cmd1.log" chatter=1' | ||
| 87 | + | ||
| 88 | + # Check if execution was successful | ||
| 89 | + self.test_assert(self._execute(cmd, success=False) != 0, | ||
| 90 | + 'Check invalid input file when executed from command line') | ||
| 91 | + | ||
| 92 | + # Check csfootprint --help | ||
| 93 | + self._check_help(csfootprint) | ||
| 94 | + | ||
| 95 | + # Return | ||
| 96 | + return | ||
| 97 | + | ||
| 98 | + # Test csfootprint from Python | ||
| 99 | + def _test_python(self): | ||
| 100 | + """ | ||
| 101 | + Test csfootprint from Python | ||
| 102 | + """ | ||
| 103 | + # Allocate csfootprint | ||
| 104 | + script = cscripts.csfootprint() | ||
| 105 | + | ||
| 106 | + # Check that saving does not nothing | ||
| 107 | + script['infile'] = self._infile | ||
| 108 | + script['outfile'] = 'NONE' | ||
| 109 | + script['tmin'] = 'NONE' | ||
| 110 | + script['tmax'] = 'NONE' | ||
| 111 | + script['logfile'] = 'csfootprint_py0.log' | ||
| 112 | + script['chatter'] = 2 | ||
| 113 | + | ||
| 114 | + # Run csfootprint script | ||
| 115 | + script.logFileOpen() | ||
| 116 | + script.run() | ||
| 117 | + | ||
| 118 | + # Check result | ||
| 119 | + self._check_result(script) | ||
| 120 | + | ||
| 121 | + # Return | ||
| 122 | + return | ||
| 123 | + | ||
| 124 | + # Test csfootprint pickeling | ||
| 125 | + def _test_pickeling(self): | ||
| 126 | + """ | ||
| 127 | + Test csfootprint pickeling | ||
| 128 | + """ | ||
| 129 | + # Perform pickeling test of empty class | ||
| 130 | + self._pickeling(cscripts.csfootprint()) | ||
| 131 | + | ||
| 132 | + # Setup script for pickling text | ||
| 133 | + script = cscripts.csfootprint() | ||
| 134 | + script['infile'] = self._infile | ||
| 135 | + script['outfile'] = 'NONE' | ||
| 136 | + script['tmin'] = 'NONE' | ||
| 137 | + script['tmax'] = 'NONE' | ||
| 138 | + script['logfile'] = 'csfootprint_py1_pickle.log' | ||
| 139 | + script['chatter'] = 2 | ||
| 140 | + | ||
| 141 | + # Perform pickeling tests of filled class | ||
| 142 | + obj = self._pickeling(script) | ||
| 143 | + | ||
| 144 | + # Run csfootprint script and save result | ||
| 145 | + obj.logFileOpen() # Make sure we get a log file | ||
| 146 | + obj.run() | ||
| 147 | + obj.save() | ||
| 148 | + | ||
| 149 | + # Check result | ||
| 150 | + self._check_result(script) | ||
| 151 | + | ||
| 152 | + # Return | ||
| 153 | + return | ||
| 154 | + | ||
| 155 | + # Check csfootprint result | ||
| 156 | + def _check_result(self, script): | ||
| 157 | + """ | ||
| 158 | + Check content of script | ||
| 159 | + | ||
| 160 | + Parameters | ||
| 161 | + ---------- | ||
| 162 | + script : `~cscripts.csfootprint` | ||
| 163 | + csfootprint instance | ||
| 164 | + """ | ||
| 165 | + # TODO: Implement test on script result | ||
| 166 | + | ||
| 167 | + # Return | ||
| 168 | + return |
test/test_python_cscripts.py
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | # ========================================================================== | 2 | # ========================================================================== |
| 3 | # This scripts performs unit tests for cscripts | 3 | # This scripts performs unit tests for cscripts |
| 4 | # | 4 | # |
| 5 | -# Copyright (C) 2016-2021 Juergen Knoedlseder | 5 | +# Copyright (C) 2016-2022 Juergen Knoedlseder |
| 6 | # | 6 | # |
| 7 | # This program is free software: you can redistribute it and/or modify | 7 | # This program is free software: you can redistribute it and/or modify |
| 8 | # it under the terms of the GNU General Public License as published by | 8 | # it under the terms of the GNU General Public License as published by |
| @@ -28,6 +28,7 @@ import test_cscaldb | @@ -28,6 +28,7 @@ import test_cscaldb | ||
| 28 | import test_csadd2caldb | 28 | import test_csadd2caldb |
| 29 | import test_csbkgmodel | 29 | import test_csbkgmodel |
| 30 | import test_csebins | 30 | import test_csebins |
| 31 | +import test_csfootprint | ||
| 31 | import test_csfindobs | 32 | import test_csfindobs |
| 32 | import test_csinfo | 33 | import test_csinfo |
| 33 | import test_cslightcrv | 34 | import test_cslightcrv |
| @@ -146,6 +147,7 @@ def test(installed=False, debug=False): | @@ -146,6 +147,7 @@ def test(installed=False, debug=False): | ||
| 146 | test_cstsmapsplit.Test(), | 147 | test_cstsmapsplit.Test(), |
| 147 | test_csviscube.Test(), | 148 | test_csviscube.Test(), |
| 148 | test_csscs.Test(), | 149 | test_csscs.Test(), |
| 150 | + test_csfootprint.Test(), | ||
| 149 | test_csworkflow.Test(), | 151 | test_csworkflow.Test(), |
| 150 | test_obsutils.Test(), | 152 | test_obsutils.Test(), |
| 151 | test_mputils.Test()] | 153 | test_mputils.Test()] |