示例#1
0
 def send_to_mi(self):
     #TODO: get left and right selectors
     try:
         left = float(self.spinboxLeftVal.get())
         right = float(self.spinboxRightVal.get())
     except ValueError:
         messagebox.showinfo("Bad Input","Please enter in-range floating point numbers for the bounds.")
     if left < self.energies[0] or right > self.energies[-1]:
         messagebox.showinfo("Bad Input","Please enter in-range floating point numbers for the bounds.")
         return None
     r = binary_search_find_nearest(self.energies, right)
     l = binary_search_find_nearest(self.energies, left)
     self.controller.show_frame(ManualIntegrationPage)
     self.controller.frames[ManualIntegrationPage].populate_values(self.energies[l:r], self.cps[l:r])
     self.controller.frames[ManualIntegrationPage].add_peak_selector(self.get_possibilites(False))
示例#2
0
 def reanalyze(self):
     try:
         lowIndex = np.where(self.energies==self.spinboxLeftVal.get())[0][0]
         highIndex = np.where(self.energies==self.spinboxRightVal.get())[0][0] + 1
     except IndexError:
         lowIndex = binary_search_find_nearest(self.energies, self.spinboxLeftVal.get())
         highIndex = binary_search_find_nearest(self.energies, self.spinboxRightVal.get())
     guesses = [[float(j) for j in i.cget("text").split(", ")] for i in self.peakGUIList]
     guesses = list(chain.from_iterable(guesses))
     guesses = [self.slope, self.intercept] + guesses
     try:
         popt, pcov = curve_fit(self.controller.multiple_gaussian_and_secant, xdata = self.energies[lowIndex:highIndex], ydata = self.cps[lowIndex:highIndex], p0 = np.array(guesses))
         self.populate_values(self.startInd - 20 + lowIndex, self.startInd - 20 + highIndex, popt, np.diag(pcov)[2:])
     except RuntimeError:
         messagebox.showwarning("No fit found", "No good peak fit could be determined. Try entering fewer centroids.")
示例#3
0
 def update_right(self):
     temp = self.spinboxRightVal.get()
     try:
         newRange = self.energies[np.where(
             self.energies == self.spinboxLeftVal.get())[0][0] + 1:]
     except IndexError:
         newRange = self.energies[binary_search_find_nearest(
             self.energies, self.spinboxLeftVal.get())]
     self.spinboxRight.configure(values=newRange)
     self.spinboxRightVal.set(temp)
示例#4
0
 def update_right(self):
     temp = self.spinboxRightVal.get()
     if self.spinboxLeftVal.get() < self.energies[0]:
         messagebox.showinfo("Out of Bounds","Please enter an X value within the currently plotted points")
         self.spinboxLeftVal.set(self.energies[20])
         return None
     try:
         newRange = self.energies[np.where(self.energies==self.spinboxLeftVal.get())[0][0]+1:]
     except IndexError:
         newRange = self.energies[binary_search_find_nearest(self.energies, self.spinboxLeftVal.get()):]
     self.spinboxRight.configure(values=newRange)
     self.spinboxRightVal.set(temp)
示例#5
0
 def edit_ROIs(self):
     """Edit ROIs for the program when submitted from ROI edit window"""
     self.ROIEditWindow.withdraw()
     self.isotopes = self.elements
     fitRanges = self.get_fitting_ranges(self.elements)
     self.fitRanges = fitRanges
     if len(self.graphEnergies) > 0:
         l = lambda x:binary_search_find_nearest(self.graphEnergies, x)
         fitIndices = [[l(p[1]), l(p[2])] for p in fitRanges]
         fitIndices = list(chain.from_iterable(fitIndices))
         self.fitIndices = fitIndices
         for i in self.polyFills:
             i.remove()
         self.polyFills = []
         for i in range(0, len(fitIndices), 2):
             self.polyFills.append(self.plotAxes.fill_between(self.graphEnergies[fitIndices[i]:fitIndices[i+1]],self.graphCPS[fitIndices[i]:fitIndices[i+1]]))
         self.canvas.draw()
    def do_peak_fitting(self, energies, cps, ROIs):
        """This function takes a lot of guesses at initial parameters, then uses a curve fitter to find the best-fitting peak equation"""
        peaks_to_return = []
        variances = []
        for region in ROIs:
            i = 0
            while energies[i] < region[0]:
                i += 1
            lowerBound = energies[i - 1]
            lowerIndex = i - 1
            while energies[i] < region[1]:
                i += 1
            upperBound = energies[i]
            upperIndex = i
            peaksInRange = []
            i = 0
            while float(self.all_peaks_sens[i][1]) < lowerBound:
                i += 1
            while i < len(self.all_peaks_sens) and float(
                    self.all_peaks_sens[i][1]) < upperBound:
                peaksInRange.append(self.all_peaks_sens[i])
                i += 1

            #Background line guessing algorthm (finds flat areas on each side of peak)
            thresh = 5000
            searchLeft = (lowerIndex + upperIndex) // 2
            searchRight = (lowerIndex + upperIndex) // 2 + 1
            if lowerBound < thresh:
                v1 = 25
                v2 = 10
                v3 = .05
            else:
                v1 = 100
                v2 = 50
                v3 = .015
            while not (
                (abs(
                    sum(cps[searchLeft - 4:searchLeft]) / 4 - cps[searchLeft])
                 < cps[searchLeft] / v1 and
                 abs(cps[searchLeft - 4] - cps[searchLeft]) < cps[searchLeft] /
                 v2 and abs(cps[searchLeft - 3] - cps[searchLeft]) <
                 cps[searchLeft] / v2 and
                 abs(cps[searchLeft - 2] - cps[searchLeft]) < cps[searchLeft] /
                 v2 and abs(cps[searchLeft - 1] - cps[searchLeft]) <
                 cps[searchLeft] / v2) or
                (sum(cps[searchLeft - 4:searchLeft + 1]) < v3)):
                searchLeft -= 1
            if lowerBound < thresh:
                while not ((abs(
                        sum(cps[searchRight + 1:searchRight + 5]) / 4 -
                        cps[searchRight]) < cps[searchRight] / v1
                            and abs(cps[searchRight + 1] - cps[searchRight]) <
                            cps[searchRight] / v2
                            and abs(cps[searchRight + 2] - cps[searchRight]) <
                            cps[searchRight] / v2
                            and abs(cps[searchRight + 3] - cps[searchRight]) <
                            cps[searchRight] / v2
                            and abs(cps[searchRight + 4] - cps[searchRight]) <
                            cps[searchRight] / v2) or
                           (sum(cps[searchRight + 1:searchRight + 5]) < v3)):
                    searchRight += 1
            else:
                while cps[searchRight] > cps[searchLeft]:
                    searchRight += 1
            while searchRight - searchLeft > 50:  #If our ROI is too wide
                v1 /= 2
                v2 /= 2
                v3 *= 2
                searchLeft = (lowerIndex + upperIndex) // 2
                searchRight = (lowerIndex + upperIndex) // 2 + 1
                while not ((abs(
                        sum(cps[searchLeft - 4:searchLeft]) / 4 -
                        cps[searchLeft]) < cps[searchLeft] / v1
                            and abs(cps[searchLeft - 4] - cps[searchLeft]) <
                            cps[searchLeft] / v2
                            and abs(cps[searchLeft - 3] - cps[searchLeft]) <
                            cps[searchLeft] / v2
                            and abs(cps[searchLeft - 2] - cps[searchLeft]) <
                            cps[searchLeft] / v2
                            and abs(cps[searchLeft - 1] - cps[searchLeft]) <
                            cps[searchLeft] / v2) or
                           (sum(cps[searchLeft - 4:searchLeft + 1]) < v3)):
                    searchLeft -= 1
                if lowerBound < thresh:
                    while not (
                        (abs(
                            sum(cps[searchRight + 1:searchRight + 5]) / 4 -
                            cps[searchRight]) < cps[searchRight] / v1
                         and abs(cps[searchRight + 1] - cps[searchRight]) <
                         cps[searchRight] / v2
                         and abs(cps[searchRight + 2] - cps[searchRight]) <
                         cps[searchRight] / v2
                         and abs(cps[searchRight + 3] - cps[searchRight]) <
                         cps[searchRight] / v2
                         and abs(cps[searchRight + 4] - cps[searchRight]) <
                         cps[searchRight] / v2) or
                        (sum(cps[searchRight + 1:searchRight + 5]) < v3)):
                        searchRight += 1
                else:
                    while cps[searchRight] > cps[searchLeft]:
                        searchRight += 1
            while searchRight - searchLeft < 15:  #If our ROI is too narrow, just widen it a bit
                searchLeft -= 1
                searchRight += 1

            enerToFit = energies[searchLeft:searchRight + 1]
            cpsToFit = cps[searchLeft:searchRight + 1]
            start = cpsToFit[0]
            end = cpsToFit[-1]
            tempData = copy.deepcopy(cpsToFit)
            slope = (end - start) / (enerToFit[-1] - enerToFit[0])
            intercept = start - enerToFit[0] * slope
            tempData = tempData - (slope * enerToFit +
                                   np.full_like(tempData, intercept))
            newMin = min(tempData)
            tempData = tempData - np.full_like(tempData, newMin)

            #Peak finding
            maxima = peakdet(cpsToFit, max(cpsToFit) / 50, enerToFit)
            guessedParams = [slope, intercept]
            for i, j in maxima:
                if j < max(cpsToFit) / 25:
                    maxima.remove((i, j))
            maxima = sorted(maxima, key=lambda x: -x[1])
            while len(maxima) * 3 + 2 > searchRight - searchLeft:
                del maxima[-1]

            #TODO: get width estimation from FWHM input
            for m, _ in maxima:
                guessedParams += [
                    m, cpsToFit[binary_search_find_nearest(enerToFit, m)], 1.00
                ]

            #Actual curve fitting
            if len(guessedParams) >= 5:
                try:
                    popt, pcov = curve_fit(self.multiple_gaussian_and_secant,
                                           enerToFit,
                                           cpsToFit,
                                           p0=guessedParams)
                    peaks_to_return.append([searchLeft, searchRight] +
                                           list(popt))
                    pvar = list(np.diag(pcov))[2:]
                    if len(pvar) == 0:
                        pvar = [.1, .1, .1]  #maybe change
                    variances.append(pvar)
                except RuntimeError:
                    try:
                        #fallack, use our guess for background line and give the algorithm less params to work with
                        popt, pcov = curve_fit(self.multiple_gaussian,
                                               enerToFit,
                                               tempData,
                                               p0=guessedParams[2:])
                        peaks_to_return.append([searchLeft, searchRight] +
                                               [slope, intercept] + list(popt))
                        pvar = list(np.diag(pcov))
                        if len(pvar) == 0:
                            pvar = [.1, .1, .1]  #maybe change
                        variances.append(pvar)
                    except RuntimeError:
                        peaks_to_return.append([searchLeft, searchRight])
                        variances.append([])
                        #TODO: as a catch-all for special cases, just integrate under the data. Present the graph of the data(with maybe even more context) to the researcher and let them choose the bounds
                        """self.show_frame(ManualIntegrationPage)
                        self.frames[ManualIntegrationPage].populate_values(enerToFit,cpsToFit)"""
                        #TODO: wait until we get a callback
                        #TODO: figure out variance for this case
                        #TODO: figure out how to differentiate integral data from fit data in find_elements
                        pass
            else:
                peaks_to_return.append([searchLeft, searchRight])
                variances.append([])
        """peaks_to_return = [[left bound, right bound, slope, intercept, ctr1, amp1, wid1...,ctrn,ampn,widn]]"""
        return peaks_to_return, variances
示例#7
0
 def show_side_to_side(self, fname1, fname2, area, xlim, stacked, win, f):
     """Side-by-side Graph Creator"""
     if fname1 == "" or fname2 == "" or fname1 == fname2:
         tk.messagebox.showinfo("Bad Input","Please add 2 distinct files for comaprison")
         return None
     fig = Figure(figsize=(10,5), dpi=100)
     f1Ind = self.files.index(fname1)
     f1Ener = self.fileInfo[f1Ind][2]
     f1CPS = self.fileInfo[f1Ind][3]
     
     f2Ind = self.files.index(fname2)
     f2Ener = self.fileInfo[f2Ind][2]
     f2CPS = self.fileInfo[f2Ind][3]
     
     if area == "Current Bounds":
         left = xlim[0]
         right = xlim[1]
         f1Left = max(binary_search_find_nearest(f1Ener, left), 5)
         f1Right = min(binary_search_find_nearest(f1Ener, right), len(f1Ener)-5)
         f2Left = max(binary_search_find_nearest(f2Ener, left), 5)
         f2Right = min(binary_search_find_nearest(f2Ener, right), len(f1Ener)-5)
         if stacked:
             a = fig.add_subplot(111)
             a.plot(f1Ener[f1Left-5:f1Right+5],f1CPS[f1Left-5:f1Right+5], label=fname1)
             a.plot(f2Ener[f2Left-5:f2Right+5],f2CPS[f2Left-5:f2Right+5], label=fname2)
             a.set_xlim(*xlim)
         else:
             a = fig.add_subplot(121)
             a.plot(f1Ener[f1Left-5:f1Right+5],f1CPS[f1Left-5:f1Right+5])
             b = fig.add_subplot(122)
             b.plot(f2Ener[f2Left-5:f2Right+5],f2CPS[f2Left-5:f2Right+5])
             a.set_xlim(*xlim)
             b.set_xlim(*xlim)
     elif area == "All Data":
         if stacked:
             a = fig.add_subplot(111)
             a.plot(f1Ener, f1CPS)
             a.plot(f2Ener, f2CPS)
         else:
             a = fig.add_subplot(121)
             a.plot(f1Ener, f1CPS, label=fname1)
             b = fig.add_subplot(122)
             b.plot(f2Ener, f2CPS, label=fname2)
     else:
         bounds = area.split(": ")[1].split("-")
         left = float(bounds[0])
         right = float(bounds[1])
         f1Left = max(binary_search_find_nearest(f1Ener, left), 5)
         f1Right = min(binary_search_find_nearest(f1Ener, right), len(f1Ener)-5)
         f2Left = max(binary_search_find_nearest(f2Ener, left), 5)
         f2Right = min(binary_search_find_nearest(f2Ener, right), len(f1Ener)-5)
         if stacked:
             a = fig.add_subplot(111)
             a.plot(f1Ener[f1Left-5:f1Right+5],f1CPS[f1Left-5:f1Right+5], label=fname1)
             a.plot(f2Ener[f2Left-5:f2Right+5],f2CPS[f2Left-5:f2Right+5], label=fname2)
             a.set_xlim(left, right)
         else:
             a = fig.add_subplot(121)
             a.plot(f1Ener[f1Left-5:f1Right+5],f1CPS[f1Left-5:f1Right+5])
             b = fig.add_subplot(122)
             b.plot(f2Ener[f2Left-5:f2Right+5],f2CPS[f2Left-5:f2Right+5])
             a.set_xlim(left, right)
             b.set_xlim(left, right)
     if stacked:
         fig.set_size_inches(5,5)
         a.set_title("Side-by-Side", size=14)
         a.legend(fontsize=8)
         a.set_xlabel("Energy (kEv)")
         a.set_ylabel("Counts per Second")
     else:
         a.set_title(fname1, fontsize=10)
         a.set_xlabel("Energy (kEv)")
         a.set_ylabel("Counts per Second")
         
         b.set_title(fname2, fontsize = 10)
         b.set_xlabel("Energy (kEv)")
         b.set_ylabel("Counts per Second")
     f.destroy()
     c = FigureCanvasTkAgg(fig, win)
     c.draw()
     c.get_tk_widget().grid(row=0,column=0,columnspan=6, rowspan=6)
示例#8
0
 def edit_ROIs(self):
     """Edit ROIs for the program when submitted from ROI edit window"""
     self.ROIEditWindow.withdraw()
     elementMap = {
         'Hydrogen': 'H',
         'Helium': 'He',
         'Lithium': 'Li',
         'Beryllium': 'Be',
         'Boron': 'B',
         'Carbon': 'C',
         'Nitrogen': 'N',
         'Oxygen': 'O',
         'Fluorine': 'F',
         'Neon': 'Ne',
         'Sodium': 'Na',
         'Magnesium': 'Mg',
         'Aluminum': 'Al',
         'Silicon': 'Si',
         'Phosphorus': 'P',
         'Sulfur': 'S',
         'Chlorine': 'Cl',
         'Argon': 'Ar',
         'Potassium': 'K',
         'Calcium': 'Ca',
         'Scandium': 'Sc',
         'Titanium': 'Ti',
         'Vanadium': 'V',
         'Chromium': 'Cr',
         'Manganese': 'Mn',
         'Iron': 'Fe',
         'Cobalt': 'Co',
         'Nickel': 'Ni',
         'Copper': 'Cu',
         'Zinc': 'Zn',
         'Gallium': 'Ga',
         'Germanium': 'Ge',
         'Arsenic': 'As',
         'Selenium': 'Se',
         'Bromine': 'Br',
         'Krypton': 'Kr',
         'Rubidium': 'Rb',
         'Strontium': 'Sr',
         'Yttrium': 'Y',
         'Zirconium': 'Zr',
         'Niobium': 'Nb',
         'Molybdenum': 'Mo',
         'Technetium': 'Tc',
         'Ruthenium': 'Ru',
         'Rhodium': 'Rh',
         'Palladium': 'Pd',
         'Silver': 'Ag',
         'Cadmium': 'Cd',
         'Indium': 'In',
         'Tin': 'Sn',
         'Antimony': 'Sb',
         'Tellurium': 'Te',
         'Iodine': 'I',
         'Xenon': 'Xe',
         'Caesium': 'Cs',
         'Barium': 'Ba',
         'Lanthanum': 'La',
         'Cerium': 'Ce',
         'Praseodymium': 'Pr',
         'Neodymium': 'Nd',
         'Promethium': 'Pm',
         'Samarium': 'Sm',
         'Europium': 'Eu',
         'Gadolinium': 'Gd',
         'Terbium': 'Tb',
         'Dysprosium': 'Dy',
         'Holmium': 'Ho',
         'Erbium': 'Er',
         'Thulium': 'Tm',
         'Ytterbium': 'Yb',
         'Lutetium': 'Lu',
         'Hafnium': 'Hf',
         'Tantalum': 'Ta',
         'Tungsten': 'W',
         'Rhenium': 'Re',
         'Osmium': 'Os',
         'Iridium': 'Ir',
         'Platinum': 'Pt',
         'Gold': 'Au',
         'Mercury': 'Hg',
         'Thallium': 'Tl',
         'Lead': 'Pb',
         'Bismuth': 'Bi',
         'Polonium': 'Po',
         'Astatine': 'At',
         'Radon': 'Rn',
         'Francium': 'Fr',
         'Radium': 'Ra',
         'Actinium': 'Ac',
         'Thorium': 'Th',
         'Protactinium': 'Pa',
         'Uranium': 'U',
         'Neptunium': 'Np',
         'Plutonium': 'Pu',
         'Americium': 'Am',
         'Curium': 'Cm',
         'Berkelium': 'Bk',
         'Californium': 'Cf',
         'Einsteinium': 'Es',
         'Fermium': 'Fm',
         'Mendelevium': 'Md',
         'Nobelium': 'No',
         'Lawrencium': 'Lr',
         'Rutherfordium': 'Rf',
         'Dubnium': 'Db',
         'Seaborgium': 'Sg',
         'Bohrium': 'Bh',
         'Hassium': 'Hs',
         'Meitnerium': 'Mt',
         'Darmstadtium': 'Ds',
         'Roentgenium': 'Rg',
         'Copernicium': 'Cn',
         'Ununtrium': 'Uut',
         'Flerovium': 'Fl',
         'Ununpentium': 'Uup',
         'Livermorium': 'Lv',
         'Ununseptium': 'Uus',
         'Ununoctium': 'Uuo'
     }
     self.elementSymbols = [elementMap[e] for e in self.elements]
     fitRanges = self.get_fitting_ranges(self.elementSymbols)
     self.fitRanges = fitRanges
     if len(self.graphEnergies) > 0:
         l = lambda x: binary_search_find_nearest(self.graphEnergies, x)
         fitIndices = list(map(l, fitRanges))
         self.fitIndices = fitIndices
         for i in self.polyFills:
             i.remove()
         self.polyFills = []
         for i in range(0, len(fitIndices), 2):
             self.polyFills.append(
                 self.plotAxes.fill_between(
                     self.graphEnergies[fitIndices[i]:fitIndices[i + 1]],
                     self.graphCPS[fitIndices[i]:fitIndices[i + 1]]))
         self.canvas.draw()