Commit bd0a89b5138be117f37f0883b0334f4e98b2cf5e
Merge branch '3592-csfootprint' into 3592-daemon
Showing
1 changed file
with
98 additions
and
7 deletions
cscripts/csfootprint.py
| @@ -45,6 +45,9 @@ class csfootprint(ctools.cscript): | @@ -45,6 +45,9 @@ class csfootprint(ctools.cscript): | ||
| 45 | # Initialise application by calling the base class constructor | 45 | # Initialise application by calling the base class constructor |
| 46 | self._init_cscript(self.__class__.__name__, ctools.__version__, argv) | 46 | self._init_cscript(self.__class__.__name__, ctools.__version__, argv) |
| 47 | 47 | ||
| 48 | + # Initialise members | ||
| 49 | + self._statistics = {} | ||
| 50 | + | ||
| 48 | # Return | 51 | # Return |
| 49 | return | 52 | return |
| 50 | 53 | ||
| @@ -59,7 +62,8 @@ class csfootprint(ctools.cscript): | @@ -59,7 +62,8 @@ class csfootprint(ctools.cscript): | ||
| 59 | Pickled instance | 62 | Pickled instance |
| 60 | """ | 63 | """ |
| 61 | # Set pickled dictionary | 64 | # Set pickled dictionary |
| 62 | - state = {'base' : ctools.cscript.__getstate__(self)} | 65 | + state = {'base' : ctools.cscript.__getstate__(self), |
| 66 | + 'statistics' : self._statistics} | ||
| 63 | 67 | ||
| 64 | # Return pickled dictionary | 68 | # Return pickled dictionary |
| 65 | return state | 69 | return state |
| @@ -75,6 +79,7 @@ class csfootprint(ctools.cscript): | @@ -75,6 +79,7 @@ class csfootprint(ctools.cscript): | ||
| 75 | """ | 79 | """ |
| 76 | # Set state | 80 | # Set state |
| 77 | ctools.cscript.__setstate__(self, state['base']) | 81 | ctools.cscript.__setstate__(self, state['base']) |
| 82 | + self._statistics = state['statistics'] | ||
| 78 | 83 | ||
| 79 | # Return | 84 | # Return |
| 80 | return | 85 | return |
| @@ -494,6 +499,89 @@ class csfootprint(ctools.cscript): | @@ -494,6 +499,89 @@ class csfootprint(ctools.cscript): | ||
| 494 | # Return | 499 | # Return |
| 495 | return | 500 | return |
| 496 | 501 | ||
| 502 | + # Create figure | ||
| 503 | + def _create_figure(self, outfile, statistics): | ||
| 504 | + """ | ||
| 505 | + Create figure | ||
| 506 | + | ||
| 507 | + Parameters | ||
| 508 | + ---------- | ||
| 509 | + outfile : str | ||
| 510 | + Figure file name | ||
| 511 | + statistics : dict | ||
| 512 | + Statistics dictionary | ||
| 513 | + """ | ||
| 514 | + # Optionally use matplotlib to create a figure | ||
| 515 | + try: | ||
| 516 | + | ||
| 517 | + # Import matplotlib | ||
| 518 | + import matplotlib.pyplot as plt | ||
| 519 | + import matplotlib.gridspec as gridspec | ||
| 520 | + | ||
| 521 | + # Create figure | ||
| 522 | + fig = plt.figure(figsize=(15.0,7.8)) | ||
| 523 | + | ||
| 524 | + # Create title and subtitle | ||
| 525 | + title = 'ctools carbon footprint report' | ||
| 526 | + subtitle = r'Dates: %s - %s' % \ | ||
| 527 | + (statistics['use_start'], statistics['use_stop']) | ||
| 528 | + fig.suptitle(title, fontsize=16) | ||
| 529 | + fig.text(0.5, 0.93, subtitle, fontsize=12, ha='center') | ||
| 530 | + | ||
| 531 | + # Set plot margins | ||
| 532 | + fig.subplots_adjust(left=0.07, bottom=0.07, right=0.97, top=0.88, wspace=0.3, hspace=0.35) | ||
| 533 | + | ||
| 534 | + # Divide figure | ||
| 535 | + gs1 = gridspec.GridSpec(3,3) | ||
| 536 | + ax1 = fig.add_subplot(gs1[0,0:2]) | ||
| 537 | + ax2 = fig.add_subplot(gs1[0,2]) | ||
| 538 | + | ||
| 539 | + # Plot daily footprint | ||
| 540 | + self._plot_daily(ax1, statistics) | ||
| 541 | + | ||
| 542 | + #plt.show() | ||
| 543 | + | ||
| 544 | + # Save figure | ||
| 545 | + fig.savefig(outfile, dpi=300) | ||
| 546 | + | ||
| 547 | + # Log file creation | ||
| 548 | + self._log_value(gammalib.NORMAL, 'Graphics file', outfile) | ||
| 549 | + | ||
| 550 | + # Catch exceptions | ||
| 551 | + except (ImportError, RuntimeError): | ||
| 552 | + | ||
| 553 | + # Log file creation | ||
| 554 | + self._log_value(gammalib.NORMAL, 'Graphics file', 'matplotlib not available') | ||
| 555 | + | ||
| 556 | + # Return | ||
| 557 | + return | ||
| 558 | + | ||
| 559 | + # Plot daily footprint | ||
| 560 | + def _plot_daily(self, ax, statistics): | ||
| 561 | + """ | ||
| 562 | + Plot daily footprint | ||
| 563 | + | ||
| 564 | + Parameters | ||
| 565 | + ---------- | ||
| 566 | + ax : pyplot | ||
| 567 | + Plotting frame | ||
| 568 | + statistics : dict | ||
| 569 | + Statistics dictionary | ||
| 570 | + """ | ||
| 571 | + # Create bar data | ||
| 572 | + days = [i for i, _ in enumerate(statistics['daily'])] | ||
| 573 | + data = [entry['gCO2e'] for entry in statistics['daily']] | ||
| 574 | + | ||
| 575 | + # Plot bar data | ||
| 576 | + ax.bar(days, data, 1.0, bottom=0.0, color='red') | ||
| 577 | + | ||
| 578 | + # Set labels | ||
| 579 | + ax.set_title('Footprint') | ||
| 580 | + ax.set_xlabel('Days since %s' % statistics['use_start'][0:10]) | ||
| 581 | + ax.set_ylabel(r'g CO$_2$e') | ||
| 582 | + | ||
| 583 | + # Return | ||
| 584 | + return | ||
| 497 | 585 | ||
| 498 | # Public methods | 586 | # Public methods |
| 499 | def process(self): | 587 | def process(self): |
| @@ -507,12 +595,12 @@ class csfootprint(ctools.cscript): | @@ -507,12 +595,12 @@ class csfootprint(ctools.cscript): | ||
| 507 | self._log_header1(gammalib.TERSE, 'Load statistics data') | 595 | self._log_header1(gammalib.TERSE, 'Load statistics data') |
| 508 | 596 | ||
| 509 | # Load statistics | 597 | # Load statistics |
| 510 | - statistics = self._load_statistics() | 598 | + self._statistics = self._load_statistics() |
| 511 | 599 | ||
| 512 | # Log statistics | 600 | # Log statistics |
| 513 | - self._global_statistics(statistics) | ||
| 514 | - self._daily_statistics(statistics) | ||
| 515 | - self._tools_statistics(statistics) | 601 | + self._global_statistics(self._statistics) |
| 602 | + self._daily_statistics(self._statistics) | ||
| 603 | + self._tools_statistics(self._statistics) | ||
| 516 | 604 | ||
| 517 | # Return | 605 | # Return |
| 518 | return | 606 | return |
| @@ -527,8 +615,11 @@ class csfootprint(ctools.cscript): | @@ -527,8 +615,11 @@ class csfootprint(ctools.cscript): | ||
| 527 | # Continue only if filename is valid | 615 | # Continue only if filename is valid |
| 528 | if self['outfile'].is_valid(): | 616 | if self['outfile'].is_valid(): |
| 529 | 617 | ||
| 530 | - # Implement saving of graphics file | ||
| 531 | - pass | 618 | + # Get outfile |
| 619 | + outfile = self['outfile'].filename() | ||
| 620 | + | ||
| 621 | + # Create figure | ||
| 622 | + self._create_figure(outfile.url(), self._statistics) | ||
| 532 | 623 | ||
| 533 | # ... signal that no graphics file was specified | 624 | # ... signal that no graphics file was specified |
| 534 | else: | 625 | else: |