def plot_linearity(self, maxdev, f1_pars, Ne, flux, max_dev=0.02): top_rect = [0.1, 0.3, 0.8, 0.6] bottom_rect = [0.1, 0.1, 0.8, 0.2] fig = pylab.figure() top_ax = fig.add_axes(top_rect) bot_ax = fig.add_axes(bottom_rect, sharex=top_ax) # Plot flux vs e-/pixel. top_ax.loglog(Ne, flux, 'ko') top_ax.loglog(Ne, f1(Ne), 'r-') top_ax.set_ylabel('flux') for label in top_ax.get_xticklabels(): label.set_visible(False) # Plot fractional residuals vs e-/pixel. bot_ax.semilogx(Ne, dNfrac, 'ko') bot_ax.semilogx(Ne, np.zeros(len(Ne)), 'r-') plot.setAxis(yrange=(-1.5 * max_dev, 1.5 * max_dev)) bot_ax.set_ylabel('fractional residual flux') bot_ax.set_xlabel('e-/pixel')
def plot(self, xrange=None, interactive=False, bins=100, win=None, subplot=(1, 1, 1), figsize=None, add_labels=False, frameLabels=False, amp=1, title=''): pylab_interactive_state = pylab.isinteractive() pylab.interactive(interactive) if win is None: if frameLabels: xlabel = 'Bias Corrected Event Signal (DN)' ylabel = 'Entries / bin' else: xlabel, ylabel = None, None win = plot.Window(subplot=subplot, figsize=figsize, xlabel=xlabel, ylabel=ylabel, size='large') else: win.select_subplot(*subplot) if frameLabels: bbox = win.axes[-1].get_position() points = bbox.get_points() points[0] += 0.025 points[1] += 0.025 bbox.set_points(points) win.axes[-1].set_position(bbox) if xrange is not None: self.xrange = xrange logscale = True if max(self.signals) <= 0: logscale = False try: hist = pylab.hist(self.signals, bins=bins, range=self.xrange, histtype='bar', color='b', log=logscale) yrange = 1, max(hist[0]) * 1.5 plot.setAxis(self.xrange, yrange) except: return win if add_labels: pylab.xlabel('Bias Corrected Event Signal (DN)') pylab.ylabel('Entries / bin') x = (hist[1][1:] + hist[1][:-1]) / 2. xx = np.linspace(x[0], x[-1], 1000) pylab.plot(xx, fe55_lines(xx, *self.pars), 'r--', markersize=3, linewidth=1) pylab.annotate(("Amp %i\nGain=%.2f e-/DN") % (amp, self.gain), (0.475, 0.8), xycoords='axes fraction', size='x-small') pylab.interactive(pylab_interactive_state) return win
def fe55_gain_fitter(signals, ccdtemp=-95, make_plot=False, xrange=None, bins=100, hist_nsig=10, title='', plot_filename=None, interactive=True, ylog=True): """ Function to fit the distribution of charge cluster DN values from a Fe55 dataset. A two Gaussian model of Mn K-alpha and K-beta lines is assumed with the ratio between the K-alpha and K-beta energies fixed at 5.889/6.49 and the the Gaussian width of the lines set equal. The gain (Ne/DN), location and sigma of the K-alpha peak (in units of DN) are returned as a tuple. If make_plot=True, then a matplotlib plot of the distribution and fit is displayed. If xrange is not None, then that 2-element tuple is used as the histogram x-range. If xrange is None, then the histogram x-range is set to +/- hist_nsig*clipped_stdev about the median of the signal distribution. """ flags = afwMath.MEDIAN | afwMath.STDEVCLIP try: stats = afwMath.makeStatistics(signals.tolist(), flags) except: print signals raise median = stats.getValue(afwMath.MEDIAN) stdev = stats.getValue(afwMath.STDEVCLIP) if xrange is None: # Set range of histogram to include both Kalpha and Kbeta peaks. xmin = max(median - hist_nsig * stdev, 200) xmax = min(median * 1785. / 1620. + hist_nsig * stdev, 1000) xrange = xmin, xmax # Save pylab interactive state. pylab_interactive_state = pylab.isinteractive() # Determine distribution mode and take that as the location of the # Kalpha peak hist = np.histogram(signals, bins=bins, range=xrange) xpeak = hist[1][np.where(hist[0] == max(hist[0]))][0] xrange = max(0, xpeak - 200), xpeak * 1785. / 1620. + 200 hist = np.histogram(signals, bins=bins, range=xrange) yrange = 1, max(hist[0]) * 1.5 if make_plot: if interactive: pylab.ion() else: pylab.ioff() # fig = pylab.figure() # axes = fig.add_subplot(111) win = plot.Window() hist = pylab.hist(signals, bins=bins, range=xrange, histtype='bar', color='b', log=ylog) if ylog: plot.setAxis(xrange, yrange) else: pylab.ioff() # hist = np.histogram(signals, bins=bins, range=xrange) x = (hist[1][1:] + hist[1][:-1]) / 2. y = hist[0] ntot = sum(y) # # Starting values for two Gaussian fit. The relative # normalizations are initially set at the expected line ratio # of K-alpha/K-beta = 0.88/0.12. The relative peak locations # and relative widths are fixed in fe55_lines(...) above. # p0 = (ntot * 0.88, median, stdev / 2., ntot * 0.12) pars, _ = scipy.optimize.curve_fit(fe55_lines, x, y, p0=p0) kalpha_peak, kalpha_sigma = pars[1], pars[2] fe55_yield = Fe55Yield(ccdtemp) gain = fe55_yield.alpha()[0] / kalpha_peak if make_plot: pylab.xlabel('Bias Corrected Event Signal (DN)') pylab.ylabel('Entries / bin') xx = np.linspace(x[0], x[-1], 1000) pylab.plot(xx, fe55_lines(xx, *pars), 'r--', markersize=3, linewidth=1) pylab.annotate(("K-alpha peak = %i DN\n\n" + "Gain = %.2f e-/DN\n\n") % (kalpha_peak, gain), (0.5, 0.7), xycoords='axes fraction') win.set_title(title) if plot_filename is not None: pylab.savefig(plot_filename) # Restore pylab interactive state. pylab.interactive(pylab_interactive_state) return gain, kalpha_peak, kalpha_sigma