Commit 4ee3b15e45d912814c9a69d2f56a49d2fad4b4ca

Authored by Jürgen Knödlseder
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