Commit 4ee3b15e45d912814c9a69d2f56a49d2fad4b4ca
1 parent
fd75ab1d
Use matplotlib in comobsres if it is available
Showing
1 changed file
with
130 additions
and
0 deletions
modules/comscripts/comobsres.py
| @@ -498,6 +498,128 @@ class comobsres(ctools.csobservation): | @@ -498,6 +498,128 @@ class comobsres(ctools.csobservation): | ||
| 498 | # Return | 498 | # Return |
| 499 | return sig | 499 | return sig |
| 500 | 500 | ||
| 501 | + def _plot_sighist(self, sighist, nbins=80, sigma_min=-6.0, sigma_max=6.0, fontsize=11, title=None): | ||
| 502 | + """ | ||
| 503 | + Plot the significance distribution | ||
| 504 | + | ||
| 505 | + Parameters | ||
| 506 | + ---------- | ||
| 507 | + sighist : list of floats | ||
| 508 | + Significance values | ||
| 509 | + nbins : int, optional | ||
| 510 | + Number of histogram bins | ||
| 511 | + sigma_min : float, optional | ||
| 512 | + Lower limit of the x axis in the plot | ||
| 513 | + sigma_max : float, optional | ||
| 514 | + Upper limit of the x axis in the plot | ||
| 515 | + fontsize : int, optional | ||
| 516 | + Font size for axes | ||
| 517 | + title : str, optional | ||
| 518 | + Title string | ||
| 519 | + """ | ||
| 520 | + # Plot only if matplotlib is available | ||
| 521 | + try: | ||
| 522 | + | ||
| 523 | + # Import matplotlib | ||
| 524 | + import matplotlib.pyplot as plt | ||
| 525 | + | ||
| 526 | + # Plot histogram | ||
| 527 | + self._plot_histogram(sighist, nbins=nbins, sigma_min=sigma_min, | ||
| 528 | + sigma_max=sigma_max, fontsize=fontsize, | ||
| 529 | + title=title) | ||
| 530 | + | ||
| 531 | + except (ImportError, RuntimeError): | ||
| 532 | + | ||
| 533 | + # Inform about impossibility to plot | ||
| 534 | + self._log_string(gammalib.NORMAL, 'matplotlib not available, '+ | ||
| 535 | + 'no significance histogram plotted.') | ||
| 536 | + | ||
| 537 | + # Return | ||
| 538 | + return | ||
| 539 | + | ||
| 540 | + def _plot_histogram(self, sighist, nbins=80, sigma_min=-6.0, sigma_max=6.0, fontsize=11, title=None): | ||
| 541 | + """ | ||
| 542 | + Plot the significance distribution | ||
| 543 | + | ||
| 544 | + Parameters | ||
| 545 | + ---------- | ||
| 546 | + sighist : list of floats | ||
| 547 | + Significance values | ||
| 548 | + nbins : int, optional | ||
| 549 | + Number of histogram bins | ||
| 550 | + sigma_min : float, optional | ||
| 551 | + Lower limit of the x axis in the plot | ||
| 552 | + sigma_max : float, optional | ||
| 553 | + Upper limit of the x axis in the plot | ||
| 554 | + fontsize : int, optional | ||
| 555 | + Font size for axes | ||
| 556 | + title : str, optional | ||
| 557 | + Title string | ||
| 558 | + """ | ||
| 559 | + # Compute bin edges, hence use nbins+1 | ||
| 560 | + binwidth = (sigma_max - sigma_min) / float(nbins) | ||
| 561 | + bin_edges = [sigma_min + binwidth*i for i in range(nbins+1)] | ||
| 562 | + | ||
| 563 | + # Draw significance histogram | ||
| 564 | + f, ax = plt.subplots() | ||
| 565 | + y, _, _ = plt.hist(sighist, bins=bin_edges, histtype='step', color='k') | ||
| 566 | + | ||
| 567 | + # Set initial Gaussian parameters | ||
| 568 | + y_max = float(y.max()) | ||
| 569 | + par1 = gammalib.GOptimizerPar('Norm', y_max) | ||
| 570 | + par2 = gammalib.GOptimizerPar('Mean', 0.0) | ||
| 571 | + par3 = gammalib.GOptimizerPar('Sigma', 1.0) | ||
| 572 | + pars = gammalib.GOptimizerPars() | ||
| 573 | + pars.append(par1) | ||
| 574 | + pars.append(par2) | ||
| 575 | + pars.append(par3) | ||
| 576 | + | ||
| 577 | + # Set fit function | ||
| 578 | + x = [0.5*(bin_edges[i]+bin_edges[i+1]) for i in range(nbins)] | ||
| 579 | + fct = gaussian(x, y) | ||
| 580 | + | ||
| 581 | + # Optimize function and compute errors | ||
| 582 | + opt = gammalib.GOptimizerLM() | ||
| 583 | + opt.optimize(fct, pars) | ||
| 584 | + opt.errors(fct, pars) | ||
| 585 | + | ||
| 586 | + # Recover parameters and errors | ||
| 587 | + norm = pars[0].value() | ||
| 588 | + e_norm = pars[0].error() | ||
| 589 | + mean = pars[1].value() | ||
| 590 | + e_mean = pars[1].error() | ||
| 591 | + sigma = pars[2].value() | ||
| 592 | + e_sigma = pars[2].error() | ||
| 593 | + | ||
| 594 | + # Draw text box | ||
| 595 | + msg = 'mean: %.3f +/- %.3f \n width: %.3f +/- %.3f' % \ | ||
| 596 | + (mean, e_mean, sigma, e_sigma) | ||
| 597 | + ax.text(0.97, 0.95, msg, ha='right', va='top', | ||
| 598 | + bbox=dict(edgecolor='red', facecolor='white'), | ||
| 599 | + transform=ax.transAxes, fontsize=8) | ||
| 600 | + | ||
| 601 | + # Plot the normal | ||
| 602 | + yvals = [norm * math.exp(-0.5*(x-mean)**2/(sigma**2)) for x in bin_edges] | ||
| 603 | + ax.plot(bin_edges, yvals, 'r-') | ||
| 604 | + | ||
| 605 | + # Configure the plot | ||
| 606 | + ax.set_ylim(0.5, ax.get_ylim()[1]*2.5) | ||
| 607 | + ax.set_xlim(sigma_min, sigma_max) | ||
| 608 | + ax.set_xlabel('Significance', fontsize=fontsize) | ||
| 609 | + ax.set_ylabel('Entries', fontsize=fontsize) | ||
| 610 | + ax.grid() | ||
| 611 | + ax.set_yscale('log') | ||
| 612 | + | ||
| 613 | + # Add title | ||
| 614 | + if title != None: | ||
| 615 | + ax.set_title(title) | ||
| 616 | + | ||
| 617 | + # Save figure | ||
| 618 | + plt.savefig(title+'.png') | ||
| 619 | + | ||
| 620 | + # Return | ||
| 621 | + return | ||
| 622 | + | ||
| 501 | 623 | ||
| 502 | # Public methods | 624 | # Public methods |
| 503 | def run(self): | 625 | def run(self): |
| @@ -582,6 +704,10 @@ class comobsres(ctools.csobservation): | @@ -582,6 +704,10 @@ class comobsres(ctools.csobservation): | ||
| 582 | # Fill residual map | 704 | # Fill residual map |
| 583 | sig = self._fill_map(dre, drm, imap) | 705 | sig = self._fill_map(dre, drm, imap) |
| 584 | 706 | ||
| 707 | + # Generate significance histogram | ||
| 708 | + if self['png'].boolean(): | ||
| 709 | + self._plot_sighist(sig, title='%s_map' % (fname)) | ||
| 710 | + | ||
| 585 | # Build DRI residuals | 711 | # Build DRI residuals |
| 586 | if self['dri'].boolean(): | 712 | if self['dri'].boolean(): |
| 587 | 713 | ||
| @@ -591,6 +717,10 @@ class comobsres(ctools.csobservation): | @@ -591,6 +717,10 @@ class comobsres(ctools.csobservation): | ||
| 591 | # Generate residual data space | 717 | # Generate residual data space |
| 592 | sig = self._compute_residual_dri(dre, drm, imap, '%s' % fname, group) | 718 | sig = self._compute_residual_dri(dre, drm, imap, '%s' % fname, group) |
| 593 | 719 | ||
| 720 | + # Generate significance histogram | ||
| 721 | + if self['png'].boolean(): | ||
| 722 | + self._plot_sighist(sig, title='%s_dri' % fname) | ||
| 723 | + | ||
| 594 | # Return | 724 | # Return |
| 595 | return | 725 | return |
| 596 | 726 |