Commit bb9a556d85a74a6a24f53ab3dbeb4dde46508ef8

Authored by Jürgen Knödlseder
1 parent 6887a0c9

Implement csfootprint script (#3592)

cscripts/Makefile.am
1 1 #############################################################################
2 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 7 # This program is free software: you can redistribute it and/or modify #
... ... @@ -25,6 +25,7 @@ pythonscripts = $(top_builddir)/cscripts/__init__.py \
25 25 $(srcdir)/csbkgmodel.py \
26 26 $(srcdir)/cscaldb.py \
27 27 $(srcdir)/csebins.py \
  28 + $(srcdir)/csfootprint.py \
28 29 $(srcdir)/csinfo.py \
29 30 $(srcdir)/cslightcrv.py \
30 31 $(srcdir)/csmodelinfo.py \
... ... @@ -88,6 +89,7 @@ parfiles = $(srcdir)/csadd2caldb.par \
88 89 $(srcdir)/cstsmapsplit.par \
89 90 $(srcdir)/csviscube.par \
90 91 $(srcdir)/csscs.par \
  92 + $(srcdir)/csfootprint.par \
91 93 $(srcdir)/csworkflow.par \
92 94 $(srcdir)/csfindobs.par \
93 95 $(srcdir)/csiactcopy.par \
... ... @@ -123,6 +125,7 @@ linkscripts = csadd2caldb \
123 125 cstsmapsplit \
124 126 csviscube \
125 127 csscs \
  128 + csfootprint \
126 129 csworkflow \
127 130 csfindobs \
128 131 csiactcopy \
... ... @@ -163,6 +166,7 @@ testscripts = $(srcdir)/tests/__init__.py \
163 166 $(top_srcdir)/test/test_cstsmapsplit.py \
164 167 $(top_srcdir)/test/test_csviscube.py \
165 168 $(top_srcdir)/test/test_csscs.py \
  169 + $(top_srcdir)/test/test_csfootprint.py \
166 170 $(top_srcdir)/test/test_csworkflow.py \
167 171 $(top_srcdir)/test/test_obsutils.py \
168 172 $(top_srcdir)/test/test_mputils.py \
... ...
cscripts/__init__.py.in
1 1 # ==========================================================================
2 2 # cscripts Python module
3 3 #
4   -# Copyright (C) 2015-2021 Juergen Knoedlseder
  4 +# Copyright (C) 2015-2022 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
... ... @@ -28,6 +28,7 @@ __all__ = [
28 28 "csbkgmodel",
29 29 "cscaldb",
30 30 "csebins",
  31 + "csfootprint",
31 32 "csinfo",
32 33 "cslightcrv",
33 34 "csmodelinfo",
... ... @@ -94,6 +95,7 @@ from cscripts.cstsmapmerge import cstsmapmerge
94 95 from cscripts.cstsmapsplit import cstsmapsplit
95 96 from cscripts.csviscube import csviscube
96 97 from cscripts.csscs import csscs
  98 +from cscripts.csfootprint import csfootprint
97 99 from cscripts.csworkflow import csworkflow
98 100 from cscripts import obsutils
99 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 60  
61 61 The carbon footprint of all ctools and cscript runs are stored in an ASCII file
62 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 57 ctskymap --- Generates sky map <ctskymap>
58 58 csbkgmodel --- Generates background model for 3D analysis <csbkgmodel>
59 59 csebins --- Generates energy boundaries for stacked analysis <csebins>
  60 + csfootprint --- Generates carbon footprint report <csfootprint>
60 61 csobsdef --- Generates observation definition file <csobsdef>
61 62 csobsselect --- Select observations from observation definition file <csobsselect>
62 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 2 # ==========================================================================
3 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 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
... ... @@ -28,6 +28,7 @@ import test_cscaldb
28 28 import test_csadd2caldb
29 29 import test_csbkgmodel
30 30 import test_csebins
  31 +import test_csfootprint
31 32 import test_csfindobs
32 33 import test_csinfo
33 34 import test_cslightcrv
... ... @@ -146,6 +147,7 @@ def test(installed=False, debug=False):
146 147 test_cstsmapsplit.Test(),
147 148 test_csviscube.Test(),
148 149 test_csscs.Test(),
  150 + test_csfootprint.Test(),
149 151 test_csworkflow.Test(),
150 152 test_obsutils.Test(),
151 153 test_mputils.Test()]
... ...