def norm_and_guess(transimg, norm=True): """Normalize the transmission image and find initial fitting parameters""" odimg = trans2od(transimg) # determine CoM to use as parameter in fitting of n2D_radial to odimg com = center_of_mass(odimg) # guess initial fit parameters n0 = odimg[com[0] - 5:com[0] + 5, com[1] - 5:com[1] + 5].sum() * 1e-2 # av. central OD a = 4 # log(fugacity) # approximate cloud size, with minimum 10 pixels in case this does not work # use something better, like moment estimation! # for elliptical clouds this is way off, and for low OD it fails! bprime = 0.5 * (threshold_image( odimg.mean(axis=1), thres=0.1 * n0, below=False)).sum() bprime = max(bprime, 10) # normalize the background if norm: try: transimg = normalize_img(transimg, com, bprime) except NotImplementedError: print "Couldn't normalize the image" # this maxod is specific to each experiment and needs to be checked odimg = trans2od(transimg, maxod=3) com = center_of_mass(odimg) return transimg, odimg, com, n0, a, bprime
def norm_and_guess(transimg, norm=True): """Normalize the transmission image and find initial fitting parameters""" odimg = trans2od(transimg) # determine CoM to use as parameter in fitting of n2D_radial to odimg com = center_of_mass(odimg) # guess initial fit parameters n0 = odimg[com[0]-5:com[0]+5, com[1]-5:com[1]+5].sum()*1e-2 # av. central OD a = 4 # log(fugacity) # approximate cloud size, with minimum 10 pixels in case this does not work # use something better, like moment estimation! # for elliptical clouds this is way off, and for low OD it fails! bprime = 0.5*(threshold_image(odimg.mean(axis=1), thres=0.1*n0, below=False)).sum() bprime = max(bprime, 10) # normalize the background if norm: try: transimg = normalize_img(transimg, com, bprime) except NotImplementedError: print "Couldn't normalize the image" # this maxod is specific to each experiment and needs to be checked odimg = trans2od(transimg, maxod=3) com = center_of_mass(odimg) return transimg, odimg, com, n0, a, bprime
def find_ellipticity(transimg, normalize=True, tol=2e-3): """Determines the ellipticity of an atom cloud The ellipticity is found by an optimization routine. A value is tried and the sum of residuals between the radial line profiles and the averaged result is computed. This value is then minimized. This method is accurate but slow. An alternative option is to use the second moments of the image. **Inputs** * transimg: 2D array, containing the absorption image * normalize: bool, if True transimg is normalized with norm_and_guess(), otherwise the odimg is obtained directly from transimg. * tol: float, the required tolerance **Outputs** * ellip: float, the ellipticity of the atom cloud """ if normalize: transimg, odimg, com, n0, a, bprime = norm_and_guess(transimg) else: odimg = trans2od(transimg) com = center_of_mass(odimg) def ellipticity(ell): rcoord, rad_profile, rprofiles, angles = radial_interpolate(odimg, com,\ 0.3, elliptic=(ell, 0), full_output=True) od_cutoff = find_fitrange(rad_profile) av_err = radialprofile_errors(rprofiles, angles, rad_profile, \ od_cutoff, showfig=False, report=False) return av_err ellip = sp.optimize.fminbound(ellipticity, 0.6, 1.0, full_output=0, \ xtol=tol) print 'ellipticity = %1.3f'%ellip return ellip
def find_ellipticity(transimg, normalize=True, tol=2e-3): """Determines the ellipticity of an atom cloud The ellipticity is found by an optimization routine. A value is tried and the sum of residuals between the radial line profiles and the averaged result is computed. This value is then minimized. This method is accurate but slow. An alternative option is to use the second moments of the image. **Inputs** * transimg: 2D array, containing the absorption image * normalize: bool, if True transimg is normalized with norm_and_guess(), otherwise the odimg is obtained directly from transimg. * tol: float, the required tolerance **Outputs** * ellip: float, the ellipticity of the atom cloud """ if normalize: transimg, odimg, com, n0, a, bprime = norm_and_guess(transimg) else: odimg = trans2od(transimg) com = center_of_mass(odimg) def ellipticity(ell): rcoord, rad_profile, rprofiles, angles = radial_interpolate(odimg, com,\ 0.3, elliptic=(ell, 0), full_output=True) od_cutoff = find_fitrange(rad_profile) av_err = radialprofile_errors(rprofiles, angles, rad_profile, \ od_cutoff, showfig=False, report=False) return av_err ellip = sp.optimize.fminbound(ellipticity, 0.6, 1.0, full_output=0, \ xtol=tol) print 'ellipticity = %1.3f' % ellip return ellip
def generate_report(rawframes, transimg, img_name, pixcal, showpdf=True): """Generate a report with several image diagnostics The report comes in the form of a pdf file that has the name ``img_name``.pdf and is put in the same directory as the image. **Inputs** * rawframes: 3D array, containing the three raw frames * transimg: 2D array, containing the transmission image (properly ROIed) * img_name: string, the name of the image * pixcal: float, pixel size calibration in m/pix. * showpdf: bool, if True Acrobat Reader is launched to view the report """ odimg = trans2od(transimg) com = center_of_mass(odimg) rawfig = show_rawframes(rawframes) savefig('trans_rawframes.jpg') close() ellip = find_ellipticity(transimg) ellip_figname = 'ellipfit' # figure out how good the ellipticity determination is and create polar plot rcoord, rad_profile, rprofiles, angles = radial_interpolate(odimg, com,\ 0.3, elliptic=(ellip, 0), full_output=True) od_cutoff = find_fitrange(rad_profile) av_err = radialprofile_errors(rprofiles, angles, rad_profile, od_cutoff, \ showfig=True, savefig_name=ellip_figname, report=False) # fit the image ToverTF, N, com, ans, rcoord, od_prof, fit_prof = fit_img(transimg, \ showfig=False, elliptic=(ellip, 0), full_output='odysseus') # save the fit figure show_fitresult(rcoord, od_prof, fit_prof, ToverTF, N, figname='fitresult') # plot the residuals show_residuals(rcoord, od_prof, fit_prof, figname='residuals') fitresults = (ToverTF[0], N, ans[1], ans[2]) # fit with several fixed temperatures ans_gaussian, ans2, temps = fit_several_fixedT(rcoord, od_prof, od_cutoff, ans, ToverTF, pixcal) fig = plot_several_temp(rcoord, od_prof, fit_prof, ans, ans_gaussian, ans2, pixcal) fig.savefig('several_temps.png') close(fig) # save a figure zoomed in around the wing of the distribution ind = round(ans2[0][2]) istep = round(1./(rcoord[1]-rcoord[0]))*15 ind = mpl.mlab.find(rcoord>ind).min() fig2 = plot_several_temp(rcoord[ind-istep:ind+istep], od_prof[ind-istep:ind+istep], \ fit_prof[ind-istep:ind+istep], ans, ans_gaussian, ans2, pixcal) fig2.savefig('several_temps_zoomed.png') close(fig2) # create the report write_TeXreport('imgreport', img_name, ellip, ellip_figname, fitresults) print 'written TeX' pdfname = os.path.splitext(img_name)[0] TeX2pdf('imgreport', pdfname) print 'written pdf' # clean up image files pngfiles = ['ellipfit', 'fitresult', 'residuals', 'several_temps', \ 'several_temps_zoomed'] for pngfile in pngfiles: try: os.unlink(''.join([pngfile, '.png'])) except OSError: print "file %s.png does not exist, so can't clean it up" %pngfile jpgfiles = ['trans_rawframes'] for jpgfile in jpgfiles: try: os.unlink(''.join([jpgfile, '.jpg'])) except OSError: print "file %s.jpg does not exist, so can't clean it up" %jpgfile if showpdf: # launch acrobat reader with the report acrocmd = r"acroread %s.pdf" %re.sub(r" ", r"\ ", pdfname) acrocmd = re.sub(r";", r"\;", acrocmd) if platform.system()=='Windows': os.system(acrocmd) else: acrocmd = re.sub(r"acroread", r"xdg-open", acrocmd) os.system(acrocmd) return
def add_noise(img, ampl=0.05, noisetype='random', fringeargs=None): """Noise is added to an image. **Inputs** * img: 2d array, containing image data * ampl: float, amplitude of the noise * noisetype: string, value can be one of * 'random', adds unbiased white noise * 'linear_x', adds a linear gradient along x from 0 to ampl * 'linear_y', adds a linear gradient along y from 0 to ampl * 'fringes', adds fringes with parameters fringeargs * fringeargs: sequence, containing four values * angle: float, angle of fringes in radians with respect to the x-axis * freq: float, frequency of the fringes in pixels^{-1} * pos: tuple, central position of the fringes with respect to the CoM * size: float, size of the Gaussian envelope of the fringes **Outputs** * img: 2d array, the input image with noise added to it """ noisetypes = ['random', 'linear_x', 'linear_y', 'fringes'] if not noisetype in noisetypes: raise ValueError, \ """noisetype is one of: %s"""%noisetypes if noisetype=='random': img = img + (np.random.random_sample(img.shape)-0.5)*ampl elif noisetype=='linear_x': noise = np.ones(img.shape).transpose()*np.arange(img.shape[0])\ /img.shape[0]*ampl img = img + noise.transpose() elif noisetype=='linear_y': noise = np.ones(img.shape)*np.arange(img.shape[1])/img.shape[1]*ampl img = img + noise elif noisetype=='fringes': if not len(fringeargs)==4: print "fringeargs needs to contain four values: angle, freq, pos, size" angle, freq, pos, size = fringeargs xx, yy = np.mgrid[0:img.shape[0], 0:img.shape[1]] # center of mass coordinates odimg = trans2od(img) com = center_of_mass(odimg) xx0 = xx - com[0] - pos[0] yy0 = yy - com[1] - pos[1] yy0 = np.where(yy0==0, 1e-6, yy0) rr = np.sqrt(xx0**2 + yy0**2) # coordinate projection along fringe axis rangle = np.arctan(xx0.astype(float)/yy0) rangle = np.where(yy0>0, rangle, rangle + np.pi) rfringe = rr*np.cos(angle - rangle) noise = fitfuncs.gaussian(rr, ampl, size) * np.sin(2*np.pi*rfringe*freq) img = img + noise return img
def add_noise(img, ampl=0.05, noisetype='random', fringeargs=None): """Noise is added to an image. **Inputs** * img: 2d array, containing image data * ampl: float, amplitude of the noise * noisetype: string, value can be one of * 'random', adds unbiased white noise * 'linear_x', adds a linear gradient along x from 0 to ampl * 'linear_y', adds a linear gradient along y from 0 to ampl * 'fringes', adds fringes with parameters fringeargs * fringeargs: sequence, containing four values * angle: float, angle of fringes in radians with respect to the x-axis * freq: float, frequency of the fringes in pixels^{-1} * pos: tuple, central position of the fringes with respect to the CoM * size: float, size of the Gaussian envelope of the fringes **Outputs** * img: 2d array, the input image with noise added to it """ noisetypes = ['random', 'linear_x', 'linear_y', 'fringes'] if not noisetype in noisetypes: raise ValueError, \ """noisetype is one of: %s"""%noisetypes if noisetype == 'random': img = img + (np.random.random_sample(img.shape) - 0.5) * ampl elif noisetype == 'linear_x': noise = np.ones(img.shape).transpose()*np.arange(img.shape[0])\ /img.shape[0]*ampl img = img + noise.transpose() elif noisetype == 'linear_y': noise = np.ones(img.shape) * np.arange( img.shape[1]) / img.shape[1] * ampl img = img + noise elif noisetype == 'fringes': if not len(fringeargs) == 4: print "fringeargs needs to contain four values: angle, freq, pos, size" angle, freq, pos, size = fringeargs xx, yy = np.mgrid[0:img.shape[0], 0:img.shape[1]] # center of mass coordinates odimg = trans2od(img) com = center_of_mass(odimg) xx0 = xx - com[0] - pos[0] yy0 = yy - com[1] - pos[1] yy0 = np.where(yy0 == 0, 1e-6, yy0) rr = np.sqrt(xx0**2 + yy0**2) # coordinate projection along fringe axis rangle = np.arctan(xx0.astype(float) / yy0) rangle = np.where(yy0 > 0, rangle, rangle + np.pi) rfringe = rr * np.cos(angle - rangle) noise = fitfuncs.gaussian(rr, ampl, size) * np.sin( 2 * np.pi * rfringe * freq) img = img + noise return img
def generate_report(rawframes, transimg, img_name, pixcal, showpdf=True): """Generate a report with several image diagnostics The report comes in the form of a pdf file that has the name ``img_name``.pdf and is put in the same directory as the image. **Inputs** * rawframes: 3D array, containing the three raw frames * transimg: 2D array, containing the transmission image (properly ROIed) * img_name: string, the name of the image * pixcal: float, pixel size calibration in m/pix. * showpdf: bool, if True Acrobat Reader is launched to view the report """ odimg = trans2od(transimg) com = center_of_mass(odimg) rawfig = show_rawframes(rawframes) savefig('trans_rawframes.jpg') close() ellip = find_ellipticity(transimg) ellip_figname = 'ellipfit' # figure out how good the ellipticity determination is and create polar plot rcoord, rad_profile, rprofiles, angles = radial_interpolate(odimg, com,\ 0.3, elliptic=(ellip, 0), full_output=True) od_cutoff = find_fitrange(rad_profile) av_err = radialprofile_errors(rprofiles, angles, rad_profile, od_cutoff, \ showfig=True, savefig_name=ellip_figname, report=False) # fit the image ToverTF, N, com, ans, rcoord, od_prof, fit_prof = fit_img(transimg, \ showfig=False, elliptic=(ellip, 0), full_output='odysseus') # save the fit figure show_fitresult(rcoord, od_prof, fit_prof, ToverTF, N, figname='fitresult') # plot the residuals show_residuals(rcoord, od_prof, fit_prof, figname='residuals') fitresults = (ToverTF[0], N, ans[1], ans[2]) # fit with several fixed temperatures ans_gaussian, ans2, temps = fit_several_fixedT(rcoord, od_prof, od_cutoff, ans, ToverTF, pixcal) fig = plot_several_temp(rcoord, od_prof, fit_prof, ans, ans_gaussian, ans2, pixcal) fig.savefig('several_temps.png') close(fig) # save a figure zoomed in around the wing of the distribution ind = round(ans2[0][2]) istep = round(1. / (rcoord[1] - rcoord[0])) * 15 ind = mpl.mlab.find(rcoord > ind).min() fig2 = plot_several_temp(rcoord[ind-istep:ind+istep], od_prof[ind-istep:ind+istep], \ fit_prof[ind-istep:ind+istep], ans, ans_gaussian, ans2, pixcal) fig2.savefig('several_temps_zoomed.png') close(fig2) # create the report write_TeXreport('imgreport', img_name, ellip, ellip_figname, fitresults) print 'written TeX' pdfname = os.path.splitext(img_name)[0] TeX2pdf('imgreport', pdfname) print 'written pdf' # clean up image files pngfiles = ['ellipfit', 'fitresult', 'residuals', 'several_temps', \ 'several_temps_zoomed'] for pngfile in pngfiles: try: os.unlink(''.join([pngfile, '.png'])) except OSError: print "file %s.png does not exist, so can't clean it up" % pngfile jpgfiles = ['trans_rawframes'] for jpgfile in jpgfiles: try: os.unlink(''.join([jpgfile, '.jpg'])) except OSError: print "file %s.jpg does not exist, so can't clean it up" % jpgfile if showpdf: # launch acrobat reader with the report acrocmd = r"acroread %s.pdf" % re.sub(r" ", r"\ ", pdfname) acrocmd = re.sub(r";", r"\;", acrocmd) if platform.system() == 'Windows': os.system(acrocmd) else: acrocmd = re.sub(r"acroread", r"xdg-open", acrocmd) os.system(acrocmd) return
fname = 'NaBEC' #'NaBEC_56ms_tof' im = Image.open(''.join(['../../archives/2008-04-21/', fname, '.TIF'])) transimg = numpy.asarray(im) # normalize to background transmission of 1 bg = transimg[0:-20, :] transimg = transimg/(bg.sum()/bg.size) od10img = where(transimg>1e-10, -log10(transimg), 10) pixsize = 20e-6 #20 um/pixel mag = 2 # magnification mass_Na = 23*mp wr = 84 # radial trap freq in Hz t_tof = 56e-3 # time of flight in seconds # determine center of mass to use as parameter in fitting of n2D_radial to od10img com = cmass.center_of_mass(od10img) def n2D_bose_thermal(r, n0_th, r0_th): """Column density for a thermal Bose gas. Assume radial symmetry of the cloud, n0_th and r0_th are fit parameters. r is a 1d array with values of r with respect to the center of the atom cloud. """ return n0_th/g2(1)*g2(1-r**2/r0_th**2) def n2D_bose_condensed(r, n0_c, r0_c): """Column density for a condensed Bose gas. Assume radial symmetry of the cloud, n0_c and r0_c are fit parameters. r is a 1d array with values of r with respect to the center of the atom cloud. """
def test_center_of_mass(self): com_ones = center_of_mass(self.ones) assert_array_almost_equal(com_ones, (50, 50), decimal=1)
fname = 'NaBEC' #'NaBEC_56ms_tof' im = Image.open(''.join(['../../archives/2008-04-21/', fname, '.TIF'])) transimg = numpy.asarray(im) # normalize to background transmission of 1 bg = transimg[0:-20, :] transimg = transimg / (bg.sum() / bg.size) od10img = where(transimg > 1e-10, -log10(transimg), 10) pixsize = 20e-6 #20 um/pixel mag = 2 # magnification mass_Na = 23 * mp wr = 84 # radial trap freq in Hz t_tof = 56e-3 # time of flight in seconds # determine center of mass to use as parameter in fitting of n2D_radial to od10img com = cmass.center_of_mass(od10img) def n2D_bose_thermal(r, n0_th, r0_th): """Column density for a thermal Bose gas. Assume radial symmetry of the cloud, n0_th and r0_th are fit parameters. r is a 1d array with values of r with respect to the center of the atom cloud. """ return n0_th / g2(1) * g2(1 - r**2 / r0_th**2) def n2D_bose_condensed(r, n0_c, r0_c): """Column density for a condensed Bose gas. Assume radial symmetry of the cloud, n0_c and r0_c are fit parameters. r