Exemple #1
10
''' Simple fit without fit error estimation.
For correct fit errors check the advanced example.
Bound should be defined. Eta has to be > 1.
'''

from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
import numpy as np
import pylandau

# Create fake data with possion error
mpv, eta, sigma, A = 30, 5, 4, 1000
x = np.arange(0, 100, 0.5)
y = pylandau.langau(x, mpv, eta, sigma, A)
yerr = np.random.normal(np.zeros_like(x), np.sqrt(y))
yerr[y < 1] = 1
y += yerr

# Fit with constrains
coeff, pcov = curve_fit(pylandau.langau, x, y,
                        sigma=yerr,
                        absolute_sigma=True,
                        p0=(mpv, eta, sigma, A),
                        bounds=(1, 10000))

# Plot
plt.errorbar(x, y, np.sqrt(pylandau.langau(x, *coeff)), fmt=".")
plt.plot(x, pylandau.langau(x, *coeff), "-")
plt.show()
Exemple #2
9
# Plot the Landau Gauss convolution (Langau) and cross check with convolution with scipy

import numpy as np
import pylandau
import matplotlib.pyplot as plt
from scipy.ndimage.filters import gaussian_filter1d

mpv, eta, sigma, A = 10, 1, 3, 1
x = np.arange(0, 50, 0.01)
y = pylandau.landau(x, mpv=mpv, eta=eta, A=A)
y_gconv = gaussian_filter1d(y, sigma=sigma / 0.01)
# Scaled means that the resulting Landau*Gauss function maximum is A at mpv
# Otherwise the underlying Landau function before convolution has the 
# function maximum A at mpv
y_gconv_2 = pylandau.langau(x, mpv, eta, sigma, A, scale_langau=False)
y_gconv_3 = pylandau.langau(x, mpv, eta, sigma, A, scale_langau=True)
plt.plot(x, y, label='Landau')
plt.plot(x, y_gconv_2, label='Langau')
plt.plot(x, y_gconv, '--', label='Langau Scipy')
plt.plot(x, y_gconv_3, label='Langau scaled')
plt.legend(loc=0)
plt.show()
Exemple #3
7
# Plot the functions using matplotlib

import numpy as np
import pylandau
import matplotlib.pyplot as plt

x = np.arange(0, 100, 0.01)
for A, eta, mpv in ((1, 1, 10), (1, 2, 30), (0.5, 5, 50)):
    # Use the function that calculates y values when given array
    plt.plot(x, pylandau.landau(x, mpv, eta, A), '-', label='mu=%1.1f, eta=%1.1f, A=%1.1f' % (mpv, eta, A))

    # Use the function that calculates the y value given a x value, (e.g. needed for minimizers)
    y = np.array([pylandau.get_landau(x_value, mpv, eta, A) for x_value in x])
    plt.plot(x, y, 'r--', label='mu=%1.1f, eta=%1.1f, A=%1.1f' % (mpv, eta, A))

    # Use the function that calculates the y value given a x value, (e.g. needed for minimizers)
    sigma = 10
    plt.plot(x, pylandau.langau(x, mpv, eta, sigma, A), '--', label='mu=%1.1f, eta=%1.1f, sigma=%1.1f, A=%1.1f' % (A, eta, sigma, mpv))
plt.legend(loc=0)
plt.show()
    def test_negative_amplitude(self):
        ''' Check exception for negative amplitude '''
        x = np.linspace(0, 100)
        with self.assertRaises(ValueError):
            pylandau.landau(x, A=-1)

        x = np.linspace(0, 100)
        with self.assertRaises(ValueError):
            pylandau.langau(x, A=-1)
Exemple #5
0
 def test_langau_stability(self, mpv, eta, sigma, A):
     ''' Check Langau outputs for same input parameters '''
     # Correct input to avoid oscillations
     if sigma > 100 * eta:
         sigma = eta
     assume(sigma * eta < constrains.LANGAU_MAX_ETA_SIGMA)
     x = np.linspace(mpv - 5 * sigma * eta, mpv + 5 * sigma * eta, 1000)
     y_1 = pylandau.langau(x, mpv=mpv, eta=eta, sigma=sigma, A=A)
     y_2 = pylandau.langau(x, mpv=mpv, eta=eta, sigma=sigma, A=A)
     self.assertTrue(np.all(y_1 == y_2))
Exemple #6
0
 def test_langau_stability(self, mpv, eta, sigma, A):
     ''' Check Langau outputs for same input parameters '''
     # Correct input to avoid oscillations
     if sigma > 100 * eta:
         sigma = eta
     assume(sigma * eta < constraints.LANGAU_MAX_ETA_SIGMA)
     x = np.linspace(mpv - 5 * sigma * eta, mpv + 5 * sigma * eta, 1000)
     y_1 = pylandau.langau(x, mpv=mpv, eta=eta, sigma=sigma, A=A)
     y_2 = pylandau.langau(x, mpv=mpv, eta=eta, sigma=sigma, A=A)
     self.assertTrue(np.all(y_1 == y_2))
 def test_landau_fallback(self, pars):
     ''' Check if langau is landau for sigma = 0 '''
     (mpv, eta, A) = pars
     x = np.linspace(mpv - 5 * eta, mpv + 5 * eta, 1000)
     y_1 = pylandau.landau(x, mpv=mpv, eta=eta, A=A)
     y_2 = pylandau.langau(x, mpv=mpv, eta=eta, sigma=0., A=A)
     self.assertTrue(np.all(y_1 == y_2))
 def test_landau_fallback(self, pars):
     ''' Check if langau is landau for sigma = 0 '''
     (mpv, eta, A) = pars
     x = np.linspace(mpv - 5 * eta, mpv + 5 * eta, 1000)
     y_1 = pylandau.landau(x, mpv=mpv, eta=eta, A=A)
     y_2 = pylandau.langau(x, mpv=mpv, eta=eta, sigma=0., A=A)
     self.assertTrue(np.all(y_1 == y_2))
Exemple #9
0
 def _calc_landau(x):
     if self.simulate_data.dut_noise[dut_index]:
         # PyLandau Langau MPV parameter is the MPV of the Langau not the Landau only!
         y = pylandau.langau(
             x,
             mpv=mpv_charge,
             eta=mpv_charge / 10.,
             sigma=self.simulate_data.dut_noise[dut_index],
             scale_langau=False)
     else:
         y = pylandau.landau(x,
                             mpv=mpv_charge,
                             eta=mpv_charge / 10)
     return y
Exemple #10
0
def fitfunction_testbeam_array(x, mu, eta, sigma, A, p4, p5):
    global c 
    c+=1
    return  pylandau.langau(x, mu, eta, sigma, A) + p4 * np.exp(-x / p5)
Exemple #11
0
    def run(self):
        """Runs the routines to generate all langau specific data"""

        # Here events with only one cluster are choosen or two, you decide
        indNumClus = self.get_num_clusters(self.data, self.numClusters)
        indizes = np.concatenate(indNumClus)

        # Slice the data from the bas analysis for further calculations
        valid_events_clustersize = np.take(self.data["base"]["Clustersize"], indizes)
        valid_events_clusters = np.take(self.data["base"]["Clusters"], indizes)
        valid_events_Signal = np.take(self.data["base"]["Signal"],indizes)
        self.results_dict["Clustersize"] = []

        # TODO: here a non numba optimized version is used. We should use numba here!
        # Calculate the energy deposition PER Clustersize and add it to self.results_dict["Clustersize"]
        self.cluster_analysis(valid_events_Signal,
                              valid_events_clusters,
                              valid_events_clustersize)

        # With all the data from every clustersize add all together and fit the main langau to it
        finalE = np.zeros(0)
        finalNoise = np.zeros(0)
        for cluster in self.results_dict["Clustersize"]:
            # Clean up and extra energy cut
            indi = np.nonzero(cluster["signal"] > 0)[0]
            nogarbage = cluster["signal"][indi]
            # ultra_high_energy_cut
            indi = np.nonzero(nogarbage < self.Ecut)[0]
            cluster["signal"] = cluster["signal"][indi]
            finalE = np.append(finalE, cluster["signal"])
            finalNoise = np.append(finalNoise, cluster["noise"])

        # Fit the langau to the summ of all individual clusters
        coeff, _, _, error_bins, edges= self.fit_langau(finalE,
                                                  finalNoise,
                                                  bins=self.results_dict["bins"],
                                                  cut = self.ClusterCut)

        self.results_dict["signal"] = finalE
        self.results_dict["noise"] = finalNoise
        self.results_dict["langau_coeff"] = coeff
        plotxrange = np.arange(0., edges[-1], edges[-1] / 1000.)
        self.results_dict["langau_data"] = [
            plotxrange,pylandau.langau(plotxrange,*coeff)
        ]  # aka x and y data
        self.results_dict["data_error"] = error_bins

        # Seed cut langau, taking only the bare hit channels which are above seed cut levels
        if self.seed_cut_langau:
            seed_cut_channels = self.data["base"]["Channel_hit"]
            signals = self.data["base"]["Signal"]
            seedcutADC = []
            seedcutChannels = []
            for i, signal in enumerate(tqdm(signals, desc="(langau SC) Processing events")):
                if signal[seed_cut_channels[i]].any():
                    seedcutADC.append(signal[seed_cut_channels[i]])
                    seedcutChannels.append(seed_cut_channels[i])


            if self.Charge_scale:
                self.log.info("Converting ADC to electrons for SC Langau...")
                converted = self.main.calibration.convert_ADC_to_e(np.concatenate(seedcutADC), np.concatenate(seedcutChannels))
            else:
                converted = np.absolute(np.concatenate(seedcutADC))
            finalE = np.array(converted, dtype=np.float32)

            # get rid of 0 events
            indizes = np.nonzero(finalE > 0)[0]
            nogarbage = finalE[indizes]
            indizes = np.nonzero(nogarbage < self.Ecut)[0]  # ultra_high_energy_cut
            coeff, _, _, error_bins, edges = self.fit_langau(
                nogarbage[indizes], bins=self.results_dict["bins"], cut = self.SCCut)
            self.results_dict["signal_SC"] = nogarbage[indizes]
            self.results_dict["langau_coeff_SC"] = coeff
            plotxrange = np.arange(0., edges[-1], edges[-1]/1000.)
            self.results_dict["langau_data_SC"] = [
                plotxrange,pylandau.langau(plotxrange,*coeff)
            ]  # aka x and y data

#         Old attempts for multiprocessing, no speed up seen here
#             # Try joblib
#             #start = time()
#             #arg_instances = [(size, valid_events_clustersize,
#             #                  valid_events_Signal, valid_events_clusters,
#             #                  noise, charge_cal) for size in clustersize_list]
#             #results = Parallel(n_jobs=4, backend="threading")(map(delayed(self.process_cluster_size),
#             #                                                           arg_instances))
#             #for res in results:
#             #    self.results_dict[data]["Clustersize"].append(res)
        #
        # !!!!!!!!!!!!!!! NO SPEED BOOST HERE!!!!!!!!!!!!!!!!!!!!
        # General langau, where all clustersizes are considered
        # if self.poolsize > 1:
        #    paramslist = []
        #    for size in self.cluster_size_list:
        #        cls_ind = np.nonzero(valid_events_clustersize == size)[0]
        #        paramslist.append((cls_ind, valid_events_Signal,
        #                           valid_events_clusters,
        #                           self.main.calibration.convert_ADC_to_e,
        #                           self.main.noise))

        # COMMENT: lagau_cluster not defined!!!!
        # Here multiple cpu calculate the energy of the events per clustersize
        #    results = self.pool.starmap(self.langau_cluster, paramslist,
        #                                chunksize=1)

        #    self.results_dict["Clustersize"] = results


        return self.results_dict.copy()
Exemple #12
0
 def minimizeMe(mpv, eta, sigma, A):
     chi2 = np.sum(
         np.square(y - langau(x, mpv, eta, sigma, A).astype(float)) /
         np.square(yerr.astype(float)))
     return chi2 / (x.shape[0] - 5)  # devide by NDF
Exemple #13
0
def fit_landau_migrad(x, y, p0, limit_mpv, limit_eta, limit_sigma, limit_A):
    def minimizeMe(mpv, eta, sigma, A):
        chi2 = np.sum(
            np.square(y - langau(x, mpv, eta, sigma, A).astype(float)) /
            np.square(yerr.astype(float)))
        return chi2 / (x.shape[0] - 5)  # devide by NDF

    # Prefit to get correct errors
    yerr = np.sqrt(y)  # Assume error from measured data
    yerr[y < 1] = 1
    m = iminuit.Minuit(minimizeMe,
                       mpv=p0[0],
                       limit_mpv=limit_mpv,
                       error_mpv=1,
                       eta=p0[1],
                       error_eta=0.1,
                       limit_eta=limit_eta,
                       sigma=p0[2],
                       error_sigma=0.1,
                       limit_sigma=limit_sigma,
                       A=p0[3],
                       error_A=1,
                       limit_A=limit_A,
                       errordef=1,
                       print_level=2)
    m.migrad()

    if not m.get_fmin().is_valid:
        raise RuntimeError('Fit did not converge')

    # Main fit with model errors
    yerr = np.sqrt(
        langau(x,
               mpv=m.values['mpv'],
               eta=m.values['eta'],
               sigma=m.values['sigma'],
               A=m.values['A']))  # Assume error from measured data
    yerr[y < 1] = 1

    m = iminuit.Minuit(minimizeMe,
                       mpv=m.values['mpv'],
                       limit_mpv=limit_mpv,
                       error_mpv=1,
                       eta=m.values['eta'],
                       error_eta=0.1,
                       limit_eta=limit_eta,
                       sigma=m.values['sigma'],
                       error_sigma=0.1,
                       limit_sigma=limit_sigma,
                       A=m.values['A'],
                       error_A=1,
                       limit_A=limit_A,
                       errordef=1,
                       print_level=2)
    m.migrad()

    fit_values = m.values

    values = np.array([
        fit_values['mpv'], fit_values['eta'], fit_values['sigma'],
        fit_values['A']
    ])

    m.hesse()

    m.minos()
    minos_errors = m.get_merrors()

    if not minos_errors['mpv'].is_valid:
        print(
            'Warning: MPV error determination with Minos failed! You can still use Hesse errors.'
        )

    errors = np.array([(minos_errors['mpv'].lower, minos_errors['mpv'].upper),
                       (minos_errors['eta'].lower, minos_errors['eta'].upper),
                       (minos_errors['sigma'].lower,
                        minos_errors['sigma'].upper),
                       (minos_errors['A'].lower, minos_errors['A'].upper)])

    return values, errors, m
Exemple #14
0
 def test_langau_mpv(self, mpv):
     ''' Check Langau MPV position '''
     x = np.linspace(mpv - 10, mpv + 10, 1000)
     y = pylandau.langau(x, mpv=mpv, eta=1., sigma=1., A=1.)
     delta = x[1] - x[0]
     self.assertAlmostEqual(x[np.argmax(y)], mpv, delta=delta)
Exemple #15
0
 def _fitfunction_testbeam(self, x, *p):
     '''
         Custom fit function for testbeam histograms.
     '''
     mu, eta, sigma, A, p4, p5 = p
     return landau.langau(x, mu, eta, sigma, A) + p4*np.exp(-x/p5)
Exemple #16
0
    if not minos_errors['mpv'].is_valid:
        print('Warning: MPV error determination with Minos failed! You can still use Hesse errors.')

    errors = np.array([(minos_errors['mpv'].lower, minos_errors['mpv'].upper),
                       (minos_errors['eta'].lower, minos_errors['eta'].upper),
                       (minos_errors['sigma'].lower, minos_errors['sigma'].upper),
                       (minos_errors['A'].lower, minos_errors['A'].upper)])

    return values, errors, m

if __name__ == '__main__':
    # Fake counting experiment with Landgaus distribution
    x = np.arange(100).astype(np.float)
    y = langau(x,
               mpv=30.,
               eta=5.,
               sigma=4.,
               A=1000.)
    # Add poisson error
    y += np.random.normal(np.zeros_like(y), np.sqrt(y))

    # Fit the data with numerical exact error estimation
    # Taking into account correlations
    values, errors, m = fit_landau_migrad(x,
                                          y,
                                          p0=[x.shape[0] / 2., 10., 10., np.max(y)],
                                          limit_mpv=(10., 100.),
                                          limit_eta=(2., 20.),
                                          limit_sigma=(2., 20.),
                                          limit_A=(500., 1500.))
def fitfunction(x, *p):
    '''
    Fitfunction used for testbeam data
    '''
    mu, eta, sigma, A, p4, p5 = p
    return  landau.langau(x, mu, eta, sigma, A) + p4*np.exp(-x/p5)
Exemple #18
0
    def fit_testbeam_spectrum(self, x, y, p0, fit_range=None, ymax=None, debug=False, detail=False):
        '''
            Fit custom fitfunction to spectrum from testbeam and plot both data and fitted function.
            Parameters:
                x:np.ndarray       -    x-values of histogrammed data.
                y:np.ndarray       -    y-values of histogrammed data.
                p0:tuple           -    Set of startparameters for fit. Format: (mu, eta, sigma, A).
                fit_range:tuple    -    [Optional] Region where the fit should be performed. Obtained automatically if None.
                ymax:int           -    [Optional] Maximum of y-axis of plot. Obtained automatically if None.
                debug:boolean      -    [Optional] If set, the fitfunction is plotted with startparameters for debugging.
        '''
        self.error = False
        threshold = self.find_threshold(y)
        if not fit_range or fit_range == 'auto':
            fit_range = (threshold, np.round(np.amax(x)))
        if ymax is None:
            ymax = 1.1*np.amax(y)
        
        plot_range = (threshold, np.round(np.amax(x)))

        try:
            p, _ = curve_fit(self._fitfunction_testbeam, x[(x > fit_range[0]) & (x < fit_range[1])], y[(x > fit_range[0]) & (x < fit_range[1])], p0=p0)
            
            mpv = float(x[np.argmax(landau.langau(x, p[0], p[1], p[2], p[3]))])
            
            if debug:
                p = p0
                
            if p[0] <= threshold:
                logging.error('Encountered an error during analysis of file %s: Peak is below threshold!' % (self.f))
                self.errorfiles.append([os.path.join(self.dirpath, self.f), 'Fit: Peak below threshold!'])
                self.error = True
            elif p[3] <= 0:
                logging.error('Encountered an error during analysis of file %s: Amplitude is negative!' % (self.f))
                self.errorfiles.append([os.path.join(self.dirpath, self.f), 'Fit: Amplitude is negative!'])
                self.error = True
            elif (10. * float(p[1]) < float(p[2])):
                logging.error('Encountered an error during analysis of file %s: Oscillation occurred!' % (self.f))
                self.errorfiles.append([os.path.join(self.dirpath, self.f), 'Fit: Oscillation occurred!'])
                #self.error = True
        except RuntimeError as e:
            logging.error('Encountered an error during analysis of file %s: %s' % (self.f, e))
            self.errorfiles.append([os.path.join(self.dirpath, self.f), e])
            self.error = True
        
        if self.error:
            p = p0
            mpv = p0[0]
        else:
            p = tuple([abs(e) for e in p])
        
        logging.debug('Fitparameters:\nMPV = %1.2f\nmu = %1.3f\neta = %1.3f\nsigma = %1.3f\nA = %1.3f\np4 = %1.3f\np5 = %1.3f' % ((mpv,) + p))
        
        plt.cla()
        plt.plot(x[(x > plot_range[0]) & (x < plot_range[1])], y[(x > plot_range[0]) & (x < plot_range[1])], label='Data', color='blue', zorder=0, linewidth=1)
        plt.fill_between(x[(x > plot_range[0]) & (x < plot_range[1])], y[(x > plot_range[0]) & (x < plot_range[1])], facecolor='blue', alpha=0.3, zorder=0)
        plt.plot(x[(x > fit_range[0]) & (x < fit_range[1])], self._fitfunction_testbeam(x, *p)[(x > fit_range[0]) & (x < fit_range[1])], label='Fit', color='red', zorder=2, linewidth=1)
        
        if detail:
            plt.plot(x[(x > fit_range[0]) & (x < fit_range[1])], landau.langau(x, *p[:4])[(x > fit_range[0]) & (x < fit_range[1])], label='Langau', color='purple', linestyle='--', zorder=2, linewidth=1)
            plt.plot(x[(x > fit_range[0]) & (x < fit_range[1])], p[4]*np.exp(-x/p[5])[(x > fit_range[0]) & (x < fit_range[1])], label='Exponential', color='yellow', linestyle='--', zorder=2, linewidth=1)
            plt.plot([mpv, mpv], [0., ymax], label='MPV', color='green', linestyle='--')
        
        if self._energy_calibrated:
            plt.xlim(self._energy_intercept, np.round(np.amax(x)))
        else:
            plt.xlim(0, np.round(np.amax(x)))
        plt.ylim(0, ymax)
        plt.legend(loc=1, fontsize=12)
        plt.grid()
        plt.title(self.title)
        plt.xlabel('Energy [%s]' % self._energy_unit)
        plt.ylabel('Count')
        
        ax = plt.axes()
        textstr = '$N = %i$' % self.event_count
        if self._darkframe_corrected:
            textstr += '\nDarkframe-cor.'
        if self.error:
            textstr += '\nFit failed!'
        else:
            textstr += '\nFit parameters:\n$MPV = %1.2f$\n$\mu=%.2f$\n$\eta=%.2f$\n$\sigma=%.2f$\n$A=%.2f$\n$p_4=%.2f$\n$p_5=%.2f$' % ((mpv,) + p)
        box = AnchoredText(textstr, loc=5)
        ax.add_artist(box)
        ax.annotate('Threshold', xy=(threshold,0), xytext=(threshold,-0.1*ymax), horizontalalignment='center', arrowprops=dict(facecolor='black', shrink=0.05, width=0, headwidth=0))
        
        plt.savefig(self.outfile + '.' + self.outformat)
Exemple #19
0
 def minimizeMe(mpv, eta, sigma, A):
     chi2 = np.sum(np.square(y - langau(x, mpv, eta, sigma, A).astype(float)) / np.square(yerr.astype(float)))
     return chi2 / (x.shape[0] - 5)  # devide by NDF
Exemple #20
0
def lnlike(theta):
    #parameters.set_params(pd.pyListToVec(theta))
    #params = pd.vector()
    #params[:] = theta
    #parameters.set_params(params)
    #f = pd.fit(parameters)
    #chisq = f.generateChiSquare()
    #print "chisq = " + str(chisq)

    #below is OK for traditional chisquared calculation
    #should find a way to do this dynamically at some point, based on input parameters.
    #y = pylandau.langau(E, float(theta[0]), 64, 45, float(theta[1])) #units in keV, mpv, width, sigma, scale
    #y2 = pylandau.langau(E,float(theta[2]), 64, 45, float(theta[3]))
    #y3 = pylandau.langau(E,float(theta[4]), 64, 45, float(theta[5]))

    #y4 = y+y2#+y3

    chisq = 0.0
    #for value1,value2 in zip(C,y4):
     #   chisq += math.pow((value1-value2),2)/np.sqrt(value1)

    #I have to figure out ssh for this computer, or put all of this on the server at UML!(DUH OF COURSE)
    #At least for the doublet,I have to reduce scale parameter to relative ratio
    #For triplet, I could proceed with same scale parameter and normalize using 3 parameter
    #could reduce parameters by turning scale between 2 low energy peaks into a ratio
    #ratioLowE = theta[1]/theta[5]

    #changing to correlation between scale factors (ratio dependence)
    #could also introduce scale factor
    #below is for "unbinned" log(likelihood) calculation
    
    #for doublet
    #fractionTot = float(theta[2]+theta[3])
    
    #ratio is better constrained
    y = pylandau.langau(x1, float(theta[0]), 64, 45, float(theta[2])) #units in keV, mpv, width, sigma, scale
    y2 = pylandau.langau(x1,float(theta[1]), 64, 45, 1.-float(theta[2])) #if prior between 0 and 1 this should converge to fractional distribution

    # #remember to redo params and priors dan!
    y4 = y+y2


    #for triplet
    # fractionTot = float(theta[3]+theta[4]+theta[5])
    # #fractionTot = float(theta[5])

    #going to make theta[3] the log of the intensity ratio between low energy peak1 to peak2
    #theta[4] is then fraction that goes to high energy peak (I hope the math below works out for the individual fractions)

    # fraction12 = theta[3]
    # # fraction12 = np.exp(theta[3])

    # y = pylandau.langau(x1, float(theta[0]), 64, 45, float(1.-theta[4])/float(1+fraction12)) #units in keV, mpv, width, sigma, scale
    # y2 = pylandau.langau(x1,float(theta[1]), 64, 45, float(theta[4])) #if prior between 0 and 1 this should converge to fractional distribution
    # y3 = pylandau.langau(x1,float(theta[2]), 64, 45, float(fraction12)*float(1.-theta[4])/float(1+fraction12))

    # #remember to redo params and priors dan!
    # y4 = y+y2+y3




    #original
    #y = pylandau.langau(x1, float(theta[0]), 64, 45, float(theta[1])) #units in keV, mpv, width, sigma, scale
    #y2 = pylandau.langau(x1,float(theta[2]), 64, 45, float(theta[3]))
    #y3 = pylandau.langau(x1,float(theta[4]), 64, 45, float(theta[5]))

    #if I get rid of normalize perhaps I will recover absolute heigh information
    #of course it collapses to largest values since this "maximizes" probability
    normalize = np.trapz(y4)
    #normalize = 1.

    for energy in E: #because of binning of x1, energy is mapped -0.5 from the entry
        chisq += np.log(y4[int(energy-0.5)]/normalize) #for likelihood analysis the the probability that a model is correct for n points is by comparing the model distribution, P, at points, p_n, and multiplying them all P(p_1)*P(p_2)*...*P(p_n). Thus when taking the log these can all be added together. This is the natural way to do these kind of fits, though time consuming.

    #I'm appending the temperature parameter beta to the end of the 

    return chisq
Exemple #21
0
 def test_langau_A(self, A):
     ''' Check Langau amplitude '''
     mpv = 1.
     x = np.linspace(mpv - 10, mpv + 10, 1000)
     y = pylandau.langau(x, mpv=mpv, eta=1., sigma=1., A=A)
     self.assertAlmostEqual(y.max(), A, delta=1e-4 * A)
Exemple #22
0
# Plot the functions using matplotlib

import numpy as np
import pylandau
import matplotlib.pyplot as plt

x = np.arange(0, 100, 0.01)
for A, eta, mpv in ((1, 1, 10), (1, 2, 30), (0.5, 5, 50)):
    # Use the function that calculates y values when given array
    plt.plot(x,
             pylandau.landau(x, mpv, eta, A),
             '-',
             label='mu=%1.1f, eta=%1.1f, A=%1.1f' % (mpv, eta, A))

    # Use the function that calculates the y value given a x value, (e.g. needed for minimizers)
    y = np.array([pylandau.get_landau(x_value, mpv, eta, A) for x_value in x])
    plt.plot(x, y, 'r--', label='mu=%1.1f, eta=%1.1f, A=%1.1f' % (mpv, eta, A))

    # Use the function that calculates the y value given a x value, (e.g. needed for minimizers)
    sigma = 10
    plt.plot(x,
             pylandau.langau(x, mpv, eta, sigma, A),
             '--',
             label='mu=%1.1f, eta=%1.1f, sigma=%1.1f, A=%1.1f' %
             (A, eta, sigma, mpv))
plt.legend(loc=0)
plt.show()
Exemple #23
0
def fit_landau_migrad(x, y, p0, limit_mpv, limit_eta, limit_sigma, limit_A):
    def minimizeMe(mpv, eta, sigma, A):
        chi2 = np.sum(np.square(y - langau(x, mpv, eta, sigma, A).astype(float)) / np.square(yerr.astype(float)))
        return chi2 / (x.shape[0] - 5)  # devide by NDF

    # Prefit to get correct errors
    yerr = np.sqrt(y)  # Assume error from measured data
    yerr[y < 1] = 1
    m = iminuit.Minuit(minimizeMe,
                       mpv=p0[0],
                       limit_mpv=limit_mpv,
                       error_mpv=1,
                       eta=p0[1],
                       error_eta=0.1,
                       limit_eta=limit_eta,
                       sigma=p0[2],
                       error_sigma=0.1,
                       limit_sigma=limit_sigma,
                       A=p0[3],
                       error_A=1,
                       limit_A=limit_A,
                       errordef=1,
                       print_level=2)
    m.migrad()

    if not m.get_fmin().is_valid:
        raise RuntimeError('Fit did not converge')

    # Main fit with model errors
    yerr = np.sqrt(langau(x,
                          mpv=m.values['mpv'],
                          eta=m.values['eta'],
                          sigma=m.values['sigma'],
                          A=m.values['A']))  # Assume error from measured data
    yerr[y < 1] = 1

    m = iminuit.Minuit(minimizeMe,
                       mpv=m.values['mpv'],
                       limit_mpv=limit_mpv,
                       error_mpv=1,
                       eta=m.values['eta'],
                       error_eta=0.1,
                       limit_eta=limit_eta,
                       sigma=m.values['sigma'],
                       error_sigma=0.1,
                       limit_sigma=limit_sigma,
                       A=m.values['A'],
                       error_A=1,
                       limit_A=limit_A,
                       errordef=1,
                       print_level=2)
    m.migrad()

    fit_values = m.values

    values = np.array([fit_values['mpv'],
                       fit_values['eta'],
                       fit_values['sigma'],
                       fit_values['A']])

    m.hesse()

    m.minos()
    minos_errors = m.get_merrors()

    if not minos_errors['mpv'].is_valid:
        print('Warning: MPV error determination with Minos failed! You can still use Hesse errors.')

    errors = np.array([(minos_errors['mpv'].lower, minos_errors['mpv'].upper),
                       (minos_errors['eta'].lower, minos_errors['eta'].upper),
                       (minos_errors['sigma'].lower, minos_errors['sigma'].upper),
                       (minos_errors['A'].lower, minos_errors['A'].upper)])

    return values, errors, m
Exemple #24
0
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
import numpy as np
import pylandau
import math
import csv

# Create fake data with possion error
mpv, eta, sigma, A = 30, 5, 4, 1000
x = np.arange(0, 100, 0.5)
y = pylandau.langau(x, mpv, eta, sigma, A)
yerr = np.random.normal(np.zeros_like(x), np.sqrt(y))
yerr[y < 1] = 1
y += yerr

#read in tab delimited data file
energies = []
counts = []
countsErr = np.array([])
with open('decayEnergy_100kevBins_filter2.txt', 'r') as f:
    next(f)  # skip headings
    reader = csv.reader(f, delimiter='\t')
    for energy, count in reader:
        energies.append(energy)
        counts.append(count)

E = np.array(energies, dtype=float)
C = np.array(counts, dtype=float)

#np.sqrt(E)
Exemple #25
0
            'Warning: MPV error determination with Minos failed! You can still use Hesse errors.'
        )

    errors = np.array([(minos_errors['mpv'].lower, minos_errors['mpv'].upper),
                       (minos_errors['eta'].lower, minos_errors['eta'].upper),
                       (minos_errors['sigma'].lower,
                        minos_errors['sigma'].upper),
                       (minos_errors['A'].lower, minos_errors['A'].upper)])

    return values, errors, m


if __name__ == '__main__':
    # Fake counting experiment with Landgaus distribution
    x = np.arange(100).astype(np.float)
    y = langau(x, mpv=30., eta=5., sigma=4., A=1000.)
    # Add poisson error
    y += np.random.normal(np.zeros_like(y), np.sqrt(y))

    # Fit the data with numerical exact error estimation
    # Taking into account correlations
    values, errors, m = fit_landau_migrad(
        x,
        y,
        p0=[x.shape[0] / 2., 10., 10., np.max(y)],
        limit_mpv=(10., 100.),
        limit_eta=(2., 20.),
        limit_sigma=(2., 20.),
        limit_A=(500., 1500.))

    # Plot fit result
Exemple #26
0
    def fit_langau(self, x, y, p0, fit_range, ymax=None, debug=False):
        '''
            Fit a simple langau function only to peak of arbitrary spectrum and plot both data and fitted function.
            Parameters:
                x:np.ndarray       -    x-values of histogrammed data.
                y:np.ndarray       -    y-values of histogrammed data.
                p0:tuple           -    Set of startparameters for fit. Format: (mu, eta, sigma, A).
                fit_range:tuple    -    Approximate region of peak where the fit should be performed.
                ymax:int           -    [Optional] Maximum of y-axis of plot. Obtained automatically if None.
                debug:boolean      -    [Optional] If set, the fitfunction is plotted with startparameters for debugging.
        '''
        self.error = False
        threshold = self.find_threshold(y)
        plot_range = (threshold, np.round(np.amax(x)))
        
        if fit_range is None:
            fit_range = (threshold, np.round(np.amax(x)))
        if ymax is None:
            ymax = 1.1*np.amax(y)
        
        try:
            p, _ = curve_fit(landau.langau, x[(x > fit_range[0]) & (x < fit_range[1])], y[(x > fit_range[0]) & (x < fit_range[1])], p0=p0)
            if debug:
                p = p0
        except RuntimeError as e:
            logging.error('Encountered an error during analysis of file %s: %s' % (os.path.join(self.dirpath, self.f), e))
            self.errorfiles.append([os.path.join(self.dirpath, self.f), e])
            self.error = True
            p = p0

        if p[3] <= 0:
            logging.error('Encountered an error during analysis of file %s: Amplitude is negative!' % (os.path.join(self.dirpath, self.f)))
            self.errorfiles.append([os.path.join(self.dirpath, self.f), 'Fit: Amplitude is negative!'])
            self.error = True
            p = p0
        
        p = tuple([abs(e) for e in p])
        
        logging.debug('Fitparameters:\nmu = %1.3f\neta = %1.3f\nsigma = %1.3f\nA = %1.3f' % tuple(p))
        
        plt.cla()
        plt.plot(x[(x > plot_range[0]) & (x < plot_range[1])], y[(x > plot_range[0]) & (x < plot_range[1])], label='Data', color='blue', zorder=0, linewidth=1)
        plt.fill_between(x[(x > plot_range[0]) & (x < plot_range[1])], y[(x > plot_range[0]) & (x < plot_range[1])], facecolor='blue', alpha=0.3, zorder=0)
        plt.plot(x[(x > fit_range[0]) & (x < fit_range[1])], landau.langau(x, *p)[(x > fit_range[0]) & (x < fit_range[1])], label='Fit', color='red', zorder=2, linewidth=1)
        
        if self._energy_calibrated:
            plt.xlim(self._energy_intercept,np.round(np.amax(x)))
        else:
            plt.xlim(0,np.round(np.amax(x)))
        plt.ylim(0,ymax)
        plt.legend(loc=1, fontsize=12)
        plt.grid()
        plt.title(self.title)
        plt.xlabel('Energy [%s]' % self._energy_unit)
        plt.ylabel('Count')
        
        ax = plt.axes()
        textstr = '$N = %i$' % self.event_count
        if self._darkframe_corrected:
            textstr += '\nDarkframe-cor.'
        if self.error:
            textstr += '\nFit failed!'
        else:
            textstr += '\nFit parameters:\n$\mu=%.2f$\n$\eta=%.2f$\n$\sigma=%.2f$\n$A=%.2f$' % (p)
        box = AnchoredText(textstr, loc=5)
        ax.add_artist(box)
        ax.annotate('Threshold', xy=(threshold,0), xytext=(threshold,-0.1*ymax), horizontalalignment='center', arrowprops=dict(facecolor='black', shrink=0.05, width=0, headwidth=0))
        
        plt.savefig(self.outfile + '.' + self.outformat)
Exemple #27
0
# Plot the Landau Gauss convolution (Langau) and cross check with convolution with scipy

import numpy as np
import pylandau
import matplotlib.pyplot as plt
from scipy.ndimage.filters import gaussian_filter1d

mpv, eta, sigma, A = 10, 1, 3, 1
x = np.arange(0, 50, 0.01)
y = pylandau.landau(x, mpv=mpv, eta=eta, A=A)
y_gconv = gaussian_filter1d(y, sigma=sigma / 0.01)
# Scaled means that the resulting Landau*Gauss function maximum is A at mpv
# Otherwise the underlying Landau function before convolution has the
# function maximum A at mpv
y_gconv_2 = pylandau.langau(x, mpv, eta, sigma, A, scale_langau=False)
y_gconv_3 = pylandau.langau(x, mpv, eta, sigma, A, scale_langau=True)
plt.plot(x, y, label='Landau')
plt.plot(x, y_gconv_2, label='Langau')
plt.plot(x, y_gconv, '--', label='Langau Scipy')
plt.plot(x, y_gconv_3, label='Langau scaled')
plt.legend(loc=0)
plt.show()
''' Simple fit without fit error estimation.
For correct fit errors check the advanced example.
Bound should be defined. Eta has to be > 1.
'''

from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
import numpy as np
import pylandau

# Create fake data with possion error
mpv, eta, sigma, A = 30, 5, 4, 1000
x = np.arange(0, 100, 0.5)
y = pylandau.langau(x, mpv, eta, sigma, A)
yerr = np.random.normal(np.zeros_like(x), np.sqrt(y))
yerr[y < 1] = 1
y += yerr

# Fit with constrains
coeff, pcov = curve_fit(pylandau.langau,
                        x,
                        y,
                        sigma=yerr,
                        absolute_sigma=True,
                        p0=(mpv, eta, sigma, A),
                        bounds=(1, 10000))

# Plot
plt.errorbar(x, y, np.sqrt(pylandau.langau(x, *coeff)), fmt=".")
print coeff
plt.plot(x, pylandau.langau(x, *coeff), "-")
Exemple #29
0
 def test_langau_mpv(self, mpv):
     ''' Check Langau MPV position '''
     x = np.linspace(mpv - 10, mpv + 10, 1000)
     y = pylandau.langau(x, mpv=mpv, eta=1., sigma=1., A=1.)
     delta = x[1] - x[0]
     self.assertAlmostEqual(x[np.argmax(y)], mpv, delta=delta)
Exemple #30
0
 def test_langau_A(self, A):
     ''' Check Langau amplitude '''
     mpv = 1.
     x = np.linspace(mpv - 10, mpv + 10, 1000)
     y = pylandau.langau(x, mpv=mpv, eta=1., sigma=1., A=A)
     self.assertAlmostEqual(y.max(), A, delta=1e-4 * A)
Exemple #31
0
    def run(self):
        """Calculates the langau for the specified data"""

        # Which clusters need to be considered
        clustersize_list = self.main.kwargs["configs"].get("langau", {}).get(
            "clustersize", [-1])
        if type(clustersize_list) != list:
            clustersize_list = list(clustersize_list)

        if clustersize_list[0] == -1:
            clustersize_list = list(
                range(1, self.main.kwargs["configs"]["max_cluster_size"] +
                      1))  # If nothing is specified

        # Go over all datafiles
        for data in tqdm(self.data, desc="(langau) Processing file:"):
            self.results_dict[data] = {}
            indNumClus = self.get_num_clusters(
                self.data[data], self.numClusters
            )  # Here events with only one cluster are choosen
            indizes = np.concatenate(indNumClus)
            valid_events_clustersize = np.take(
                self.data[data]["base"]["Clustersize"], indizes)
            valid_events_clusters = np.take(
                self.data[data]["base"]["Clusters"], indizes)
            valid_events_Signal = np.take(
                self.data[data]["base"]["Signal"],
                indizes)  # Get the clustersizes of valid events
            # Get events which show only cluster in its data
            charge_cal, noise = self.main.calibration.charge_cal, self.main.noise
            self.results_dict[data]["Clustersize"] = []

            # General langau, where all clustersizes are considered
            if self.main.usejit and self.poolsize > 1:
                paramslist = []
                for size in clustersize_list:
                    cls_ind = np.nonzero(valid_events_clustersize == size)[0]
                    paramslist.append(
                        (cls_ind, valid_events_Signal, valid_events_clusters,
                         self.main.calibration.charge_cal, self.main.noise))

                # Here multiple cpu calculate the energy of the events per clustersize
                results = self.pool.starmap(langau_cluster,
                                            paramslist,
                                            chunksize=1)

                self.results_dict[data]["Clustersize"] = results

            else:
                for size in tqdm(clustersize_list,
                                 desc="(langau) Processing clustersize"):
                    # get the events with the different clustersizes
                    ClusInd = [[], []]
                    for i, event in enumerate(valid_events_clustersize):
                        # cls_ind = np.nonzero(valid_events_clustersize == size)[0]
                        for j, clus in enumerate(event):
                            if clus == size:
                                ClusInd[0].extend([i])
                                ClusInd[1].extend([j])

                    signal_clst_event = []
                    noise_clst_event = []
                    for i, ind in tqdm(enumerate(ClusInd[0]),
                                       desc="(langau) Processing event"):
                        y = ClusInd[1][i]
                        # Signal calculations
                        signal_clst_event.append(
                            np.take(valid_events_Signal[ind],
                                    valid_events_clusters[ind][y]))
                        # Noise Calculations
                        noise_clst_event.append(
                            np.take(noise, valid_events_clusters[ind]
                                    [y]))  # Get the Noise of an event

                    totalE = np.sum(convert_ADC_to_e(signal_clst_event,
                                                     charge_cal),
                                    axis=1)
                    totalNoise = np.sqrt(
                        np.sum(convert_ADC_to_e(noise_clst_event, charge_cal),
                               axis=1)
                    )  # eError is a list containing electron signal noise

                    # incrementor += 1

                    preresults = {"signal": totalE, "noise": totalNoise}

                    self.results_dict[data]["Clustersize"].append(preresults)

            # With all the data from every clustersize add all together and fit the langau to it
            finalE = np.zeros(0)
            finalNoise = np.zeros(0)
            for cluster in self.results_dict[data]["Clustersize"]:
                indi = np.nonzero(
                    cluster["signal"] > 0)[0]  # Clean up and extra energy cut
                nogarbage = cluster["signal"][indi]
                indi = np.nonzero(
                    nogarbage < self.Ecut)[0]  # ultra_high_energy_cut
                cluster["signal"] = cluster["signal"][indi]
                finalE = np.append(finalE, cluster["signal"])
                finalNoise = np.append(finalNoise, cluster["noise"])

            # Fit the langau to it

            coeff, pcov, hist, error_bins = self.fit_langau(finalE,
                                                            finalNoise,
                                                            bins=self.bins)
            self.results_dict[data]["signal"] = finalE
            self.results_dict[data]["noise"] = finalNoise
            self.results_dict[data]["langau_coeff"] = coeff
            self.results_dict[data]["langau_data"] = [
                np.arange(1., 100000., 1000.),
                pylandau.langau(np.arange(1., 100000., 1000.), *coeff)
            ]  # aka x and y data
            self.results_dict[data]["data_error"] = error_bins

            # Consider now only the seedcut hits for the langau,
            if self.main.kwargs["configs"].get("langau",
                                               {}).get("seed_cut_langau",
                                                       False):
                seed_cut_channels = self.data[data]["base"]["Channel_hit"]
                signals = self.data[data]["base"]["Signal"]
                finalE = []
                seedcutADC = []
                for i, signal in enumerate(
                        tqdm(signals, desc="(langau SC) Processing events")):
                    if signal[seed_cut_channels[i]].any():
                        seedcutADC.append(signal[seed_cut_channels[i]])

                self.log.info("Converting ADC to electrons...")
                converted = convert_ADC_to_e(seedcutADC, charge_cal)
                for conv in converted:
                    finalE.append(sum(conv))
                finalE = np.array(finalE, dtype=np.float32)

                # get rid of 0 events
                indizes = np.nonzero(finalE > 0)[0]
                nogarbage = finalE[indizes]
                indizes = np.nonzero(
                    nogarbage < self.Ecut)[0]  # ultra_high_energy_cut
                coeff, pcov, hist, error_bins = self.fit_langau(
                    nogarbage[indizes], bins=self.bins)
                # coeff, pcov, hist, error_bins = self.fit_langau(nogarbage, bins=500)
                self.results_dict[data]["signal_SC"] = nogarbage[indizes]
                self.results_dict[data]["langau_coeff_SC"] = coeff
                self.results_dict[data]["langau_data_SC"] = [
                    np.arange(1., 100000., 1000.),
                    pylandau.langau(np.arange(1., 100000., 1000.), *coeff)
                ]  # aka x and y data

        return self.results_dict.copy()