def __init__(self,fn=None,pars=None,x0=None,y0=None,r0=None,sigma=None,IMG=None,mask=None): self.mask = mask self.IMG = mask self.pars = Parameters() self.pars.add('amp', 2,min=0,max=10) self.pars.add('bg', 1) self.pars.add('bgexp', 4.,min=1.,max=4.) self.pars.add('r0', 1500,min=1000,max=2000)#,vary=False) self.pars.add('sigma', 2,min=.1, max=100)#,vary=False) self.pars.add('x0',XCEN,min=XCEN-10,max=XCEN+10) self.pars.add('y0',YCEN,min=YCEN-10,max=YCEN+10) super(RingFit,self).__init__(fn=fn,pars=pars)
def histfitqrings(histstot, qx, Ix=None, PF=False): ''' fit the hists''' histspar = np.zeros((histstot.shape[0], 2)) histsparpois = histspar * 0 histsfit = histstot * 0 histsfitpois = histstot * 0 for i in range(histstot.shape[0]): if (PF): print("iteration {} or {}".format(i, histstot.shape[0])) #kbar = np.interp(i,sqx,sqy) pars = Parameters() pars.add('M', value=4, vary=True) if (Ix is not None): pars.add('kbar', value=Ix[i], vary=False) else: pars.add('kbar', value=2., vary=True) xdata = np.arange(histstot.shape[1]) ydata = histstot[i] fitfn = FitObject(negbinomialdist, pars) fitfnpois = FitObject(poissondist, pars) fitfn.fit(xdata, ydata) fitfnpois.fit(xdata, ydata) pars = fitfn.mn.params parspois = fitfnpois.mn.params histsfit[i] = fitfn.fn(xdata, pars) histsfitpois[i] = fitfnpois.fn(xdata, pars) histspar[i] = np.array([pars['kbar'].value, pars['M'].value]) histsparpois[i] = np.array( [parspois['kbar'].value, parspois['M'].value]) return histsfit, histspar, histsfitpois, histsparpois
def __init__(self, fn=None, pars=None, IMG=None, mask=None): self.mask = mask self.IMG = mask if (pars is None): pars = { 'amp': 1, 'x0': 0., 'y0': 0, 'sigmax': 1., 'sigmay': 1., 'const': 0 } if (hasattr(pars['amp'], "value")): self.pars = pars else: self.pars = Parameters() for key in pars: self.pars.add(key, pars[key]) super(Gauss2DFitter, self).__init__(fn=gauss2Dfitfunc, pars=pars)
def twolinefit(xdata, ydata, m1=None, m2=None, xc=None, yc=None, varyslopes=True, plotwin=None): ''' Two line fit func fits to two lines with slopes m1 and m2 intersecting at point (xc, yc) m1= ,m2= : set m1 and m2 initial parameters (not necessary) Default is 1 varyslopes= True : set to false to fix slopes (need to set m1 and m2 then) set plotwin to a window number to plot to that window number ''' if (m1 is None): m1 = 1 if (m2 is None): m2 = 1 if (xc is None): xc = 0 if (yc is None): yc = 0 pars = Parameters() pars.add('m1', value=m1, vary=varyslopes) pars.add('m2', value=m2, vary=varyslopes) pars.add('xc', value=xc, vary=True) pars.add('yc', value=yc, vary=True) fitfn = FitObject(fn=twolinefitfunc, pars=pars) fitfn.fit(xdata, ydata) yfit = twolinefitfunc(xdata, fitfn.pars) if (plotwin is not None): plt.figure(plotwin) plt.plot(xdata, ydata, 'ko') #compute with finer spacing xfit = np.linspace(np.min(xdata), np.max(xdata)) yfit2 = twolinefitfunc(xfit, fitfn.pars) plt.plot(xfit, yfit2, 'r') pars = fitfn.pars return yfit, pars
def polyfit(xdata, ydata, a=None, b=None, varyexps=False, plotwin=None, positive=False): ''' quick lin fit func poly fit y = sum(a[i]*x**b[i]) note : assumes that the exponents are not varied. If that's ever necessary, set varyexps to True. Also, it is recommended you always set a and b, don't rely on default vals as they may change. If plot win set, plot results in a window''' if (a is None): a = [0, 1, 1] if (b is None): b = [0, 1, 2] if (positive is True): minval = 0 else: minval = None pars = Parameters() for i in range(len(a)): pars.add('a{}'.format(i), value=a[i], vary=True, min=minval) pars.add('b{}'.format(i), value=b[i], vary=varyexps) fitfn = FitObject(fn=polyfitfunc, pars=pars) fitfn.fit(xdata, ydata) yfit = polyfitfunc(xdata, fitfn.pars) pars = fitfn.pars if (plotwin is not None): plt.figure(plotwin) plt.plot(xdata, ydata, 'ko') #compute with finer spacing xfit = np.linspace(np.min(xdata), np.max(xdata)) yfit2 = polyfitfunc(xfit, fitfn.pars) plt.plot(xfit, yfit2, 'r') return yfit, pars
def linfit(xdata,ydata,a=None,b=None,plotwin=None): ''' quick lin fit func linear fit y = a + b*x If plot win set, plot results in a window''' if a is None: a = 1 if b is None: b = 1. pars = Parameters() pars.add('a' , value= a, vary= True) pars.add('b' , value = b, vary= True) fitfn = FitObject(fn=linfitfunc,pars=pars) fitfn.fit(xdata,ydata) yfit = linfitfunc(xdata,fitfn.pars) if(plotwin is not None): plt.figure(plotwin) plt.plot(xdata,ydata,'ko') #compute with finer spacing xfit = np.linspace(np.min(xdata),np.max(xdata)); yfit2 = linfitfunc(xfit,fitfn.pars) plt.plot(xfit,yfit2,'r') return yfit, fitfn.pars
class RingFitObject(FitObject): '''A class to fit a ring for detector calibration.''' def __init__(self,fn=None,pars=None,x0=None,y0=None,r0=None,sigma=None,IMG=None,mask=None): self.mask = mask self.IMG = mask self.pars = Parameters() self.pars.add('amp', 2,min=0,max=10) self.pars.add('bg', 1) self.pars.add('bgexp', 4.,min=1.,max=4.) self.pars.add('r0', 1500,min=1000,max=2000)#,vary=False) self.pars.add('sigma', 2,min=.1, max=100)#,vary=False) self.pars.add('x0',XCEN,min=XCEN-10,max=XCEN+10) self.pars.add('y0',YCEN,min=YCEN-10,max=YCEN+10) super(RingFit,self).__init__(fn=fn,pars=pars) #setting parameters (can type rngfitobj.set and hit tab to see them) def setr0(self,r0,min=None,max=None,vary=None): self.pars['r0'].value = r0 if(min is not None): self.pars['r0'].min = min if(max is not None): self.pars['r0'].max = max if(vary is not None): self.pars['r0'].vary = vary def setamp(self,amp,min=None,max=None,vary=None): self.pars['amp'].value = amp if(min is not None): self.pars['amp'].min = min if(max is not None): self.pars['amp'].max = max if(vary is not None): self.pars['amp'].vary = vary def setx0(self,x0,min=None,max=None,vary=None): self.pars['x0'].value = x0 if(min is not None): self.pars['x0'].min = min if(max is not None): self.pars['x0'].max = max if(vary is not None): self.pars['x0'].vary = vary def sety0(self,y0,min=None,max=None,vary=None): self.pars['y0'].value = y0 if(min is not None): self.pars['y0'].min = min if(max is not None): self.pars['y0'].max = max if(vary is not None): self.pars['y0'].vary = vary def setsigma(self,sigma,min=None,max=None,vary=None): self.pars['sigma'].value = sigma if(min is not None): self.pars['sigma'].min = min if(max is not None): self.pars['sigma'].max = max if(vary is not None): self.pars['sigma'].vary = vary def setbg(self,bg,min=None,max=None,vary=None): self.pars['bg'].value = bg if(min is not None): self.pars['bg'].min = min if(max is not None): self.pars['bg'].max = max if(vary is not None): self.pars['bg'].vary = vary def setbgexp(self,bgexp,min=None,max=None,vary=None): self.pars['bgexp'].value = bgexp if(min is not None): self.pars['bgexp'].min = min if(max is not None): self.pars['bgexp'].max = max if(vary is not None): self.pars['bgexp'].vary = vary def setmask(self,mask): self.mask = mask self.pixellist = np.where(mask.ravel() == 1) def setIMG(self,IMG): self.IMG = IMG def fit(self,IMG=None,mask=None): ''' Fit the function. If not data is given use previous data.''' if(IMG is None): IMG = self.IMG if(self.IMG is None): print("Cannot fit, no data in fit object (please supply data)") return else: self.IMG = IMG if(mask is None): mask = self.mask if(self.mask is None): print("Cannot fit, no data in fit object (please supply data)") return else: self.mask = mask pixellist = self.pixellist x = np.arange(IMG.shape[1]) y = np.arange(IMG.shape[0]) X,Y = np.meshgrid(x,y) xy = np.array([X.ravel()[pixellist],Y.ravel()[pixellist]]) erbs = np.ones(len(pixellist[0]))*1 fitobj.fit(xy,data,erbs=erbs) super(RingFit,self).fit(xdata,ydata,erbs=wdata) def getfit(self): ''' Get the current fitted image.''' pars = self.pars data = np.zeros(self.IMG.shape) data.ravel()[pixellist] = self.fn(xy,pars) data.ravel()[pixellist] = self.fn(xy,fitobj.pars) return data def getfitparams(self): return self.pars
#sample fit to the fit object #include a fit function from fit.fitfns import spheresqfunc, sspheresqfunc, savitzky_golay, spherepolygauss import numpy as np from fit.FitObject import FitObject, Parameters import matplotlib.pyplot as plt plt.figure(0) #initialize the parameters pars = Parameters() pars.add('amp', value=1, vary=False) pars.add('radius', value=100, vary=True) pars.add('window', value=21, vary=True) ndata = 400 xdata = np.linspace(1e-4, .1, ndata) ydata = spheresqfunc(xdata, pars) + np.random.random(ndata) * .01 erbs = xdata * 0 + .01 fitfn = FitObject(fn=sspheresqfunc, pars=pars) fitfn.fit(xdata, ydata, erbs) fitfn.plot(xdata, ydata, logxy=[1, 1]) fitfn.printpars() plt.figure(1) #Try a different distribution pars = Parameters() pars.add('amp', value=1, vary=True) pars.add('radius', value=100, vary=True) pars.add('FWHM', value=10, vary=True) pars.add('parasitic', value=1e-3, vary=True) pars.add('bg', value=0, vary=False) ndata = 400
class Gauss2DFitter(FitObject): '''A class to fit a Gaussian peak. ''' def __init__(self, fn=None, pars=None, IMG=None, mask=None): self.mask = mask self.IMG = mask if (pars is None): pars = { 'amp': 1, 'x0': 0., 'y0': 0, 'sigmax': 1., 'sigmay': 1., 'const': 0 } if (hasattr(pars['amp'], "value")): self.pars = pars else: self.pars = Parameters() for key in pars: self.pars.add(key, pars[key]) super(Gauss2DFitter, self).__init__(fn=gauss2Dfitfunc, pars=pars) def fit(self, IMG=None, mask=None): ''' Fit the function. If not data is given use previous data.''' if (IMG is None): IMG = self.IMG if (self.IMG is None): print("Cannot fit, no data in fit object (please supply data)") return else: self.IMG = IMG if (mask is None): mask = self.mask if (self.mask is None): print("Cannot fit, no data in fit object (please supply data)") return else: self.mask = mask pixellist = self.pixellist x = np.arange(IMG.shape[1]) y = np.arange(IMG.shape[0]) X, Y = np.meshgrid(x, y) xy = np.array([X.ravel()[pixellist], Y.ravel()[pixellist]]) erbs = np.ones(len(pixellist[0])) * 1 fitobj.fit(xy, data, erbs=erbs) super(Gauss2DFitter, self).fit(xdata, ydata, erbs=wdata) def setmask(self, mask): self.mask = mask self.pixellist = np.where(mask.ravel() == 1) def setIMG(self, IMG): self.IMG = IMG def fit(self, IMG=None, mask=None): ''' Fit the function. If not data is given use previous data.''' if (IMG is None): IMG = self.IMG if (self.IMG is None): print("Cannot fit, no data in fit object (please supply data)") return else: self.IMG = IMG if (mask is None): mask = self.mask if (self.mask is None): print("Cannot fit, no data in fit object (please supply data)") return else: self.mask = mask pixellist = self.pixellist x = np.arange(IMG.shape[1]) y = np.arange(IMG.shape[0]) X, Y = np.meshgrid(x, y) xy = np.array([X.ravel()[pixellist], Y.ravel()[pixellist]]) erbs = np.ones(len(pixellist[0])) * 1 fitobj.fit(xy, data, erbs=erbs) super(RingFit, self).fit(xdata, ydata, erbs=wdata) def getfit(self): ''' Get the current fitted image.''' pars = self.pars data = np.zeros(self.IMG.shape) data.ravel()[pixellist] = self.fn(xy, pars) data.ravel()[pixellist] = self.fn(xy, fitobj.pars) return data def getfitparams(self): return self.pars
def fitAgBHring(IMG, mask=None, pars=None, plotwin=None, clims=None): ''' Fit an AgBH (silver behenate) ring plotwin : if set, plot to the window desired. pars : a Parameters object of the initial guess Parameters. If not set the program will ask you for a best guess. mask : a mask clims : if specified, these will be the color limits of the image plot windows default is to take min and max of *masked* image ''' qAGBH = 2 * np.pi / CONST_AgBHpeak if (plotwin is not None): plt.figure(plotwin) if (mask is None): mask = np.ones(IMG.shape) img = IMG * (mask + .1) plt.imshow(img) if (clims is None): plt.clim(np.min(img * mask), np.max(img * mask)) plt.draw() plt.pause(.001) pixellist = np.where(mask.ravel() == 1) print( "\n\nfitAgBH: An attempt to fit the first silver behenate ring on a 2D area det" ) print("Note if plotting, the masked region is brightened w.r.t. the rest") print("Some tips: \n \ 1. Try to set mask to only select region near where the ring is\n\ for a better fit\n\ 2. Try a fit without the parasitic bg or const scattering first.\n\ ") if (pars is None): pars = Parameters() print( "You did not specify parameters, so I will ask you a few questions" ) print("Specify the variables in one of two ways, either:") print(": value, min, max") print("or") print(": value") #it is "raw_input" in python 2x xcenvals = np.array( input("beam center x position guess: ").split(",")).astype(float) pars.add('x0', xcenvals[0], min=xcenvals[0] - 40, max=xcenvals[0] + 40) if (len(xcenvals) == 3): pars['x0'].min = xcenvals[1] pars['x0'].max = xcenvals[2] ycenvals = np.array( input("beam center y position guess: ").split(",")).astype(float) pars.add('y0', ycenvals[0], min=ycenvals[0] - 40, max=ycenvals[0] + 40) if (len(ycenvals) == 3): pars['y0'].min = ycenvals[1] pars['y0'].max = ycenvals[2] if (plotwin is not None): print("Plotted estimate of S(q) from given xcen, ycen") sqx, sqy = circavg(IMG, x0=xcenvals[0], y0=ycenvals[0], mask=mask) plt.figure(plotwin + 2) plt.cla() w = np.where(sqy > 0) plt.loglog(sqx[w], sqy[w]) ampvals = np.array( input("amplitude of ring: ").split(",")).astype(float) pars.add('amp', ampvals[0], min=0, max=1e9) if (len(ampvals) == 3): pars['amp'].min = ampvals[1] pars['amp'].max = ampvals[1] ringvals = np.array( input("Ring location (in pixels from center of beam, approx):"). split(",")).astype(float) pars.add('r0', ringvals[0], min=0, max=4 * ringvals[0]) if (len(ringvals) == 3): pars['r0'].min = ringvals[1] pars['r0'].max = ringvals[2] sigmavals = np.array( input("sigma of ring (FWHM for Lorentzian) :").split(",")).astype( float) pars.add('sigma', sigmavals[0], min=.1, max=100) #,vary=False) if (len(sigmavals) == 3): pars['sigma'].min = sigmavals[1] pars['sigma'].max = sigmavals[2] bgvals = input("1/q^4 background (enter nothing to not vary): ") if (len(bgvals) == 0): pars.add('bg', 0, vary=False) pars.add('bgexp', 4., vary=False) else: bgvals = np.array(bgvals.split(",")).astype(float) pars.add('bg', bgvals[0], vary=False) pars.add('bgexp', 4., vary=True, min=1, max=4) if (len(bgvals) == 3): pars['bg'].min = bgvals[1] pars['bgexp'].max = bgvals[2] constvals = input("Constant background (enter nothing to not vary):") if (len(constvals) == 0): pars.add('const', 0, vary=False) else: constvals = np.array(constvals.split(",")).astype(float) pars.add("const", constvals[0]) if (len(constvals) == 3): pars['const'].min = constvals[1] pars['const'].max = constvals[2] data = IMG.ravel()[pixellist] fitobj = FitObject(fn=ring2Dlorentzfitfunc, pars=pars) x = np.arange(IMG.shape[1]) y = np.arange(IMG.shape[0]) X, Y = np.meshgrid(x, y) xy = np.array([X.ravel()[pixellist], Y.ravel()[pixellist]]) erbs = np.ones(len(pixellist[0])) datatest = np.zeros(IMG.shape) fitobj.fit(xy, data, erbs=erbs) datatest.ravel()[pixellist] = fitobj.fn(xy, fitobj.pars) XCENFIT = fitobj.pars['x0'].value YCENFIT = fitobj.pars['y0'].value RFIT = fitobj.pars['r0'].value SIGMAFIT = fitobj.pars['sigma'].value CONSTFIT = fitobj.pars['const'].value BGFIT = fitobj.pars['bg'].value BGEXPFIT = fitobj.pars['bgexp'].value print("x center fit: {:3.2f}; y center fit: {:3.2f}; radius fit: {:3.2f}". format(XCENFIT, YCENFIT, RFIT)) print( "ring FWHM : {:3.2f}; const background: {:3.2f}; parasitic bg: {:3.2f}/q^{:3.2f}" .format(SIGMAFIT, CONSTFIT, BGFIT, BGEXPFIT)) sqd_x, sqd_y = circavg(IMG, x0=XCENFIT, y0=YCENFIT, mask=mask) sqf_x, sqf_y = circavg(datatest, x0=XCENFIT, y0=YCENFIT, mask=mask) if (plotwin is not None): plt.figure(plotwin) plt.cla() plt.imshow(IMG * mask) if (clims is None): plt.clim(np.min(img * mask), np.max(img * mask)) plcirc([XCENFIT, YCENFIT], RFIT, 'b') #plt.clim(np.min(IMG*mask),np.max(IMG*mask)) plt.figure(plotwin + 1) plt.cla() plt.imshow(datatest * mask) if (clims is None): plt.clim(np.min(img * mask), np.max(img * mask)) #plt.clim(np.min(IMG*mask),np.max(IMG*mask)) plcirc([XCENFIT, YCENFIT], RFIT, 'b') plt.figure(plotwin + 2) plt.cla() plt.loglog(sqd_x, sqd_y) plt.loglog(sqf_x, sqf_y, 'r') plt.gca().autoscale_view('tight') plt.draw() plt.pause(0.001) resp = input("Get det distance?(y for yes, anything else for no): ") if (resp == 'y'): wv = float(input("wavelength (in angs): ")) dpix = float(input("pix size (in m): ")) L, err = getdistfrompeak(qAGBH, wv, dpix, RFIT) print( "Your length is approximately {:4.2f} m, and error in calc (from Ewald curvature) approx {:4.2f}%" .format(L, err)) print("done")
def __init__(self, pars=None, xdata=None, ydata=None): #default is to plot in logxy 1,1 self.logxy = [1, 1] self.xdata = xdata self.ydata = ydata self.wdata = None if (pars is None): pars = Parameters() pars.add("amp", value=1., vary=True) pars.add("rbar", value=500., vary=True) pars.add("z", value=100., vary=True) pars.add("parasitic", value=0., vary=False) pars.add("bg", value=0., vary=False) else: #If it's not in the Parameters object format, convert it if (not hasattr(pars["amp"], "value")): pars1 = pars pars = Parameters() for key in pars1: pars.add(key, value=pars1[key]) super(SchultzFitObject, self).__init__(fn=sqsphereschultz, pars=pars)