From 66bcd1533aeff72fe7ce403a9f4a45213ff63b1f Mon Sep 17 00:00:00 2001 From: Guenter Quast <guenter.quast@kit.edu> Date: Sun, 14 Apr 2024 22:16:27 +0200 Subject: [PATCH] improved graphics --- examples/findPeaks.py | 67 +++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/examples/findPeaks.py b/examples/findPeaks.py index 8333da8..0c81fbd 100755 --- a/examples/findPeaks.py +++ b/examples/findPeaks.py @@ -3,10 +3,9 @@ algorithm: perform a tow-stage determination of peak posisions: - 1. scipi.signal.find_peaks() is run on a smoothed histogram - of channel counts. - 1. the output is used as a starting point for histogram fits - with kafe2 based on the binned neg-log-likelhood cost function. + 1. scipi.signal.find_peaks() is run on a smoothened histogram of channel counts. + 2. the characteristica of identified peaks are used as starting points for + histogram fits with kafe2 based on the binned neg-log-likelhood method. """ import argparse @@ -20,7 +19,6 @@ from scipy.signal import find_peaks from PhyPraKit import meanFilter from kafe2 import HistFit, HistContainer, Plot, plot - #define fit function def gauss_plus_bkg(x, Ns=1000, mu=1000, sig=50., Nb=100., s=0., mn=0, mx=1.) : """Gaussian shape on linear background; @@ -39,7 +37,7 @@ def gauss_plus_bkg(x, Ns=1000, mu=1000, sig=50., Nb=100., s=0., mn=0, mx=1.) : B = (1 + (x-mu)*s) / (s/2*(mx**2 - mn**2) + (1-s*mu)*(mx - mn)) return Ns*S + Nb*B -# parse input +# define command line arguments ... parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('filename', nargs='?', default='Co60.hst') parser.add_argument('-p','--prominence', @@ -60,7 +58,7 @@ parser.add_argument('-t','--threshold', parser.add_argument('-n','--noplot', action='store_true') parser.add_argument('-k','--kafe2_plots', action='store_true') parser.add_argument('-v','--verbose', action='store_true') - +# ... and parse command line input args = parser.parse_args() filename=args.filename # some constants for peak-finder @@ -82,54 +80,54 @@ hst = np.loadtxt(filename, dtype=np.uint32) bin_edges= np.linspace(0, len(hst), len(hst)+1, endpoint=True) # find maxima with scipy.signal.find_peaks() -# smoothen data to reduce statistical noise before running peak finder +# firts, smoothen data to reduce statistical noise hst_s = meanFilter(hst, max(1, min_width//4)) +# search for peaks peaks, peak_props = find_peaks(hst_s, prominence=min_prominence, width=min_width, rel_height=rel_height, wlen=350) -print(len(peaks), "peaks found: ", peaks) -print("prominences: ", peak_props["prominences"]) -print("left_bases: ", peak_props["left_bases"]) -print("right_bases: ", peak_props["right_bases"]) -print("fwhms: ", peak_props["widths"]) +if verbose: + print(len(peaks), "peaks found: ", peaks) + print("prominences: ", peak_props["prominences"]) + print("left_bases: ", peak_props["left_bases"]) + print("right_bases: ", peak_props["right_bases"]) + print("fwhms: ", peak_props["widths"]) + prominences = peak_props["prominences"] left_bases = peak_props["left_bases"] right_bases = peak_props["right_bases"] fwhms = peak_props["widths"] # perform fit for precise determination -# put data in kafe2 HistContainer +# put data in kafe2 HistContainer hdata = HistContainer(bin_edges=bin_edges) hdata.set_bins(hst) -hdata.label = "spectrum" - +hdata.label = "spectrum data" +# initialize arrays for output fit_results=[] plot_ranges = np.zeros([len(peaks)+1, 2]) plot_ranges2 = np.zeros([len(peaks)+1, 2]) - print("\n"+"*==* fit results:") -print(" mu ± d_mu ( sig sig/mu FWHM/mu )") +print(" mu ± d_mu ( sig sig/mu FWHM/mu )") +# run fits for all identified peaks for i, p in enumerate(peaks): wid = int(fit_range_factor*fwhms[i]) base = (hst[left_bases[i]]+hst[right_bases[i]])/2. - # print(p, wid, base) - mn = max(min_channel, int(p-wid)) mx = int(p+wid) bins = range(mn, mx+1) counts = hst[mn : mx] - label = "peak "+str(i) hfit_data = HistContainer(bin_edges = bins) hfit_data.label="peak " + str(i) hfit_data.set_bins(counts) #Fit - fit = HistFit(data = hfit_data, model_function = gauss_plus_bkg, density=False) - # !!! Startwerte setzen !!! + fit = HistFit(data = hfit_data, model_function = gauss_plus_bkg, density=False) + # !!! set initial values fit.set_parameter_values(mu=p, sig=wid, Nb=base*(mx-mn)) fit.fix_parameter("mn", mn) fit.fix_parameter("mx", mx) - # einige Parameter auf "vernünftige" Bereiche festlegen + # limit parameters to reasonable values fit.limit_parameter("sig", 0., None) fit.limit_parameter("Ns", 0., None) #fit.limit_parameter("Nb", 0., None) # biases uncertainty if at zero boundary @@ -143,7 +141,7 @@ for i, p in enumerate(peaks): fit.report() # optionally, report fit results # show and save results - print("{} Peak {}: {:.2f} ± {:.2g} ( {:.2f} {:.1f}% {:.1f}% )".format(i, p, + print("{} peak@{}: {:.2f} ± {:.2g} ( {:.2f} {:.1f}% {:.1f}% )".format(i+1, p, fit.parameter_values[1], fit.parameter_errors[1], fit.parameter_values[2], @@ -172,17 +170,18 @@ ax1.grid(linestyle='dotted', which='both') if plot: # show spectrum and result of find_peaks xhst = np.linspace(0, len(hst), len(hst), endpoint=False) +0.5 - ax0.plot(xhst, hst_s, 'b-', linewidth=3, label = 'smoothed channel counts') - ax0.errorbar(xhst, hst, yerr=np.sqrt(hst), label='channel counts', - fmt='.', color='grey', markersize=2, linewidth=2, alpha=0.5) - ax0.plot(peaks, hst_s[peaks], '*', color='red', markersize=10, label='result of find_peaks()') + ax0.plot(xhst, hst_s, 'b-', linewidth=1, zorder=2, label = 'smoothed channel counts') + ax0.errorbar(xhst, hst, yerr=np.sqrt(hst), zorder=1, label='channel counts', + fmt='.', color='grey', markersize=2, linewidth=2, alpha=0.5, ) + ax0.plot(peaks, hst_s[peaks], '*', color='red', markersize=10, zorder=3, + label='result of find_peaks()') ax0.legend(loc = 'best') # show fitted peaks - ax1.errorbar(xhst, hst, yerr=np.sqrt(hst), fmt='.', color='grey', alpha=0.1, + ax1.errorbar(xhst, hst, yerr=np.sqrt(hst), fmt='.', color='grey', alpha=0.25, zorder=1, label = 'channel counts') # select colors for peaks - pcolors = ('cadetblue', 'orange', 'olive', 'orchid', 'turquoise', + pcolors = ('steelblue', 'darkorange', 'green', 'orchid', 'turquoise', 'tomato', 'green', 'pink', 'salmon', 'yellowgreen' ) for i, fit in enumerate(fit_results): # plot fitted peak in fit range @@ -190,12 +189,12 @@ if plot: xplt = np.linspace(plot_ranges[i][0], plot_ranges[i][1], 10*int((plot_ranges[i][1]-plot_ranges[i][0]))) ax1.plot(xplt, gauss_plus_bkg(xplt, *fit.parameter_values), - linestyle = 'solid', linewidth=3, color= colr, + linestyle = 'solid', linewidth=3, color= colr, zorder=2, label='peak ' + str(i+1) + '@' + str(int(10*fit.parameter_values[1])/10.) ) # plot fitted peak near fit region xplt2 = np.linspace(plot_ranges2[i][0], plot_ranges2[i][1], 10*int((plot_ranges[i][1]-plot_ranges[i][0]))) - ax1.plot(xplt2, gauss_plus_bkg(xplt2, *fit.parameter_values), + ax1.plot(xplt2, gauss_plus_bkg(xplt2, *fit.parameter_values), zorder=2, linestyle = 'dotted', linewidth=2, color = colr) # show fitted peak properties mu = fit.parameter_values[1] @@ -208,7 +207,7 @@ if plot: ax1.vlines(mu, 0, mx - h, linewidth=1, linestyle='dashed', color='goldenrod') ax1.hlines(mx-h/2, mu-fwhm/2, mu+fwhm/2, - linewidth=2, color='gold') + linewidth=2, color='goldenrod') ax1.legend(loc = 'best') if kafe2_plots: -- GitLab