def importfn(i,arg,options): base = base_name(arg,nodir=not options.usefoldername) output = os.path.join(os.path.join(".","micrographs"),base+".hdf") cmd = "e2proc2d.py %s %s --inplace"%(arg,output) cmdext=[] if options.invert: cmdext.append(" --mult=-1") if options.edgenorm: cmdext.append(" --process=normalize.edgemean") if options.xraypixel: cmdext.append(" --process=threshold.clampminmax.nsigma:nsigma=4") if len(cmdext)>0 or arg!=output: cmd+="".join(cmdext) launch_childprocess(cmd) if options.moverawdata: os.rename(arg,os.path.join(originalsdir,os.path.basename(arg))) # We estimate the defocus and B-factor (no astigmatism) from the micrograph and store it in info and the header if options.ctfest : d=EMData(output,0) if d["nx"]<1000 or d["ny"]<1000 : print("CTF estimation will only work with images at least 1000x1000 in size") sys.exit(1) if d["nx"]<2000 : box=256 elif d["nx"]<4000 : box=512 elif d["nx"]<6000 : box=768 else : box=1024 import e2ctf ds=1.0/(options.apix*box) ffta=None nbx=0 for x in range(100,d["nx"]-box,box): for y in range(100,d["ny"]-box,box): clip=d.get_clip(Region(x,y,box,box)) clip.process_inplace("normalize.edgemean") fft=clip.do_fft() fft.ri2inten() if ffta==None: ffta=fft else: ffta+=fft nbx+=1 ffta.mult(1.0/(nbx*box**2)) ffta.process_inplace("math.sqrt") ffta["is_intensity"]=0 # These 2 steps are done so the 2-D display of the FFT looks better. Things would still work properly in 1-D without it fftbg=ffta.process("math.nonconvex") fft1d=ffta.calc_radial_dist(ffta.get_ysize()/2,0.0,1.0,1) # note that this handles the ri2inten averages properly # Compute 1-D curve and background bg_1d=e2ctf.low_bg_curve(fft1d,ds) #initial fit, background adjustment, refine fit, final background adjustment ctf=e2ctf.ctf_fit(fft1d,bg_1d,bg_1d,ffta,fftbg,options.voltage,options.cs,options.ac,options.phaseplate,options.apix,1,dfhint=(options.defocusmin,options.defocusmax)) bgAdj(ctf,fft1d) ctf=e2ctf.ctf_fit(fft1d,ctf.background,ctf.background,ffta,fftbg,options.voltage,options.cs,options.ac,options.phaseplate,options.apix,1,dfhint=(options.defocusmin,options.defocusmax)) bgAdj(ctf,fft1d) if options.astigmatism : e2ctf.ctf_fit_stig(ffta,fftbg,ctf) #ctf.background=bg_1d #ctf.dsbg=ds db=js_open_dict(info_name(arg,nodir=not options.usefoldername)) db["ctf_frame"]=[box,ctf,(box/2,box/2),set(),5,1] db["quality"]=5 db.close() print(info_name(arg,nodir=not options.usefoldername),ctf)
def main(): progname = os.path.basename(sys.argv[0]) usage = """prog [options] micrographs/<micrograph_name> This program will allow you to serially compute and write the 1D background subtracted power spectra for multiple micrographs. For the best background subtraction results, it is highly recommended to run this program within a project where CTF correction has been performed (i.e. running e2rawdata.py and/or e2ctf.py). """ parser = EMArgumentParser(usage=usage,version=EMANVERSION) parser.add_pos_argument(name="images",help="Calculate the power spectra of these images.", default="")#, guitype='filebox', browser="EMBrowserWidget(withmodal=True,multiselect=True)", row=0, col=0,rowspan=1, colspan=2, mode="eval") parser.add_argument("--apix",type=float,help="Angstroms per pixel for all images",default=None)#, guitype='floatbox', row=3, col=0, rowspan=1, colspan=1, mode="eval['self.pm().getAPIX()']") parser.add_argument("--constbfactor",type=float,help="Set B-factor to fixed specified value, negative value autofits. Default is 200.0.",default=-1.0)#, guitype='floatbox', row=8, col=0, rowspan=1, colspan=1, mode='eval[-1.0]') parser.add_argument("--voltage",type=float,help="Microscope voltage in KV. Default is 200.0.",default=None)# guitype='floatbox', row=3, col=1, rowspan=1, colspan=1, mode="eval['self.pm().getVoltage()']") parser.add_argument("--cs",type=float,help="Microscope Cs (spherical aberation). Default is 4.1.",default=None)#, guitype='floatbox', row=4, col=0, rowspan=1, colspan=1, mode="eval['self.pm().getCS()']") parser.add_argument("--ac",type=float,help="Amplitude contrast (percentage). Default is 10.0",default=None)#, guitype='floatbox', row=4, col=1, rowspan=1, colspan=1, mode="eval") parser.add_argument("--box",type=int,help="Forced box size in grid mode.. ",default=512)#, guitype='intbox', row=5, col=0, rowspan=1, colspan=1, mode="eval") parser.add_argument("--oversamp",type=float,help="Oversample power spectrum. Default 1.0.",default=1.0)#, guitype='intbox', row=5, col=0, rowspan=1, colspan=1, mode="eval") parser.add_argument("--nobgsub",action="store_true",help="Skip background subtraction",default=False)#, guitype='floatbox', row=3, col=0, rowspan=1, colspan=1, mode="eval['self.pm().getAPIX()']") parser.add_argument("--pad",type=int,help="Exclude this many pixels around the edge of input micrograph(s) when computing power spectra.",default=64)#, guitype='intbox', row=5, col=0, rowspan=1, colspan=1, mode="eval") parser.add_argument("--ppid", type=int, help="Set the PID of the parent process, used for cross platform PPID",default=-1) parser.add_argument("--verbose", "-v", dest="verbose", action="store", metavar="n", type=int, default=0, help="verbose level [0-9], higner number means higher level of verboseness") (options, args) = parser.parse_args() logid=E2init(sys.argv,options.ppid) try: os.mkdir('micrographs') except: pass if options.box<64 : print("Box size too small. Using larger box size of 512 pixels).") options.box=512 box=options.box voltage=options.voltage cs=options.cs ac=options.ac constbfactor=options.constbfactor pad = options.pad if options.oversamp < 1: print("Oversamp must be greater than or equal to 1. Using --oversamp=1 instead.") oversamp = max(options.oversamp,1) for curset,arg in enumerate(args): sys.stdout.write("\r{}/{}: {}".format(curset+1,len(args),arg)) sys.stdout.flush() data = EMData(arg,0) if options.apix == None: try: apix = data["apix_x"] except: print("Could not find apix. Please specify using --apix or assign the corresponding header parameter, i.e. 'apix_x'.") sys.exit(1) else: apix = options.apix noctfflag = False try: ctf=js_open_dict(info_name(arg,nodir=True))["ctf"][0] print("") print("\tDefocus: {}".format(ctf.defocus)) print("\tVoltage: {}".format(ctf.voltage)) print("\tApix: {}".format(ctf.apix)) print("\tCs: {}".format(ctf.cs)) print("\tAC: {}".format(ctf.ampcont)) except: print("Could not find CTF parameters. Skipping background subtraction.") #ctf = EMAN2Ctf() #ctf.from_dict({'defocus':0.0,'dfdiff':0.0,'dfang':0.0,'bfactor':200.0,'ampcont':10.0,'voltage':200.0,'cs':4.1,'apix':apix,'dsbg':-1}) #if options.voltage!=None : ctf.voltage=options.voltage #if options.ac != None: ctf.ampcont = options.ac #if options.cs!=None : ctf.cs=options.cs #if options.constbfactor>0 : ctf.bfactor=options.constbfactor noctfflag = True ds=old_div(1.0,(apix*box*oversamp)) nx=old_div(data["nx"],box)-1 cumulfft=EMData(box,box) cumulfft.do_fft_inplace() nbx=0 for ix,x in enumerate(range(nx)): for iy,y in enumerate(range(old_div(data["ny"],box)-1)): # read the data and make the FFT clip=data.get_clip(Region(x*box+old_div(box,2),y*box+old_div(box,2),box,box)) clip.process_inplace("normalize.edgemean") if oversamp>1 : clip=clip.get_clip(Region(0,0,box*oversamp,box*oversamp)) # since we aren't using phases, doesn't matter if we center it or not fft=clip.do_fft() fft.ri2inten() cumulfft+=fft nbx+=1 cumulfft.mult(old_div(1.0,(nbx*box**2))) cumulfft.process_inplace("math.sqrt") cumulfft["is_intensity"]=0 # These 2 steps are done so the 2-D display of the FFT looks better. Things would still work properly in 1-D without it fftbg=cumulfft.process("math.nonconvex") fft1d=cumulfft.calc_radial_dist(old_div(cumulfft.get_ysize(),2),0.0,1.0,1) # note that this handles the ri2inten averages properly if options.nobgsub or noctfflag: s=np.arange(0,ds*len(fft1d),ds) pwsfn = "micrographs/{}-pws.txt".format(base_name(arg)) try: os.remove(pwsfn) except: pass with open(pwsfn,"w") as pwsf: pwsf.write("# s(1/A); PWS(s)\n") for i in range(len(fft1d)): pwsf.write("{}\t{}\n".format(s[i],fft1d[i])) else: # Compute 1-D curve and background bg_1d=e2ctf.low_bg_curve(fft1d,ds) ctf.background=bg_1d ctf.dsbg=ds fft1d=np.asarray(fft1d) ds=ctf.dsbg bg_1d=list(ctf.background) xyd=XYData() # Find the minimum value near the origin, which we'll use as a zero (though it likely should not be) mv=(fft1d[1],1) fz=int(old_div(ctf.zero(0),(ds*2))) for lz in range(1,fz): mv=min(mv,(fft1d[lz],lz)) xyd.insort(mv[1],mv[0]) # now we add all of the zero locations to our XYData object for i in range(100): z=int(old_div(ctf.zero(i),ds)) if z>=len(bg_1d)-1: break if fft1d[z-1]<fft1d[z] and fft1d[z-1]<fft1d[z+1]: mv=(z-1,fft1d[z-1]) elif fft1d[z]<fft1d[z+1] : mv=(z,fft1d[z]) else : mv=(z+1,fft1d[z+1]) xyd.insort(mv[0],mv[1]) # new background is interpolated XYData ctf.background=[xyd.get_yatx_smooth(i,1) for i in range(len(bg_1d))] # if our first point (between the origin and the first 0) is too high, we readjust it once bs=[fft1d[i]-ctf.background[i] for i in range(fz)] if min(bs)<0 : mv=(bs[0],fft1d[0],0) for i in range(1,fz): mv=min(mv,(bs[i],fft1d[i],i)) xyd.set_x(0,mv[2]) xyd.set_y(0,mv[1]) ctf.background=[xyd.get_yatx_smooth(i,1) for i in range(len(bg_1d))] bg1d=np.array(ctf.background) r=len(ctf.background) s=np.arange(0,ds*r,ds) try: bgsub=fft1d-bg1d except: print("Error computing bgsub on this image") continue fit=np.array(ctf.compute_1d(len(s)*2,ds,Ctf.CtfType.CTF_AMP)) # The fit curve fit=fit*fit # squared # auto-amplitude for b-factor adjustment rto,nrto=0,0 for i in range(int(old_div(.04,ds))+1,min(int(old_div(0.15,ds)),len(s)-1)): if bgsub[i]>0 : rto+=fit[i] nrto+=fabs(bgsub[i]) if nrto==0 : rto=1.0 else : rto/=nrto fit=[old_div(fit[i],rto) for i in range(len(s))] pwsfn = "micrographs/{}-pws.txt".format(base_name(arg)) try: os.remove(pwsfn) except: pass with open(pwsfn,"w") as pwsf: pwsf.write("# s(1/A); PWS-BG(s); CTF Fit(s); PWS(s); BG(s)\n") for i in range(len(fft1d)): pwsf.write("{}\t{}\t{}\t{}\t{}\n".format(s[i],bgsub[i],fit[i],fft1d[i],bg1d[i])) print("\nPower spectra files saved within the 'micrographs' directory.")
def main(): progname = os.path.basename(sys.argv[0]) usage = """prog [options] <micrograph1, micrograph2....> Use this program to import and filter raw micrographs. If you choose to filter and/or convert format, this program will process each micrograph and dump them into the directory './micrographs.', otherwise the micrographs will simply be moved into './micrographs'. If you select the option --moverawdata AND you filter or change format, your original micrographs will be moved into the directory './raw_micrographs' and your filtered micrographs will be in './micrographs as usual. BDB files are not moved, but they can be processed.""" parser = EMArgumentParser(usage=usage, version=EMANVERSION) parser.add_pos_argument( name="micrographs", help="List the micrographs to filter here.", default="", guitype='filebox', browser="EMRawDataTable(withmodal=True,multiselect=True)", row=0, col=0, rowspan=1, colspan=2, mode='filter') parser.add_pos_argument( name="import_files", help="List the files to import/filter here.", default="", guitype='filebox', browser="EMBrowserWidget(withmodal=True,multiselect=True)", row=0, col=0, rowspan=1, colspan=2, mode='import') parser.add_header( name="filterheader", help='Options below this label are specific to filtering', title="### filtering options ###", row=1, col=0, rowspan=1, colspan=2, mode='import,filter') parser.add_argument("--invert", action="store_true", help="Invert contrast", default=False, guitype='boolbox', row=2, col=0, rowspan=1, colspan=1, mode='filter[True]') parser.add_argument("--edgenorm", action="store_true", help="Edge normalize", default=False, guitype='boolbox', row=2, col=1, rowspan=1, colspan=1, mode='filter[True]') parser.add_argument( "--usefoldername", action="store_true", help= "If you have the same image filename in multiple folders, and need to import into the same project, this will prepend the folder name on each image name", default=False, guitype='boolbox', row=2, col=2, rowspan=1, colspan=1, mode="import[False]") parser.add_argument("--xraypixel", action="store_true", help="Filter X-ray pixels", default=False, guitype='boolbox', row=3, col=0, rowspan=1, colspan=1, mode='filter[True]') parser.add_argument("--ctfest", action="store_true", help="Estimate defocus from whole micrograph", default=False, guitype='boolbox', row=3, col=1, rowspan=1, colspan=1, mode='filter[True]') parser.add_argument("--astigmatism", action="store_true", help="Includes astigmatism in automatic fitting", default=False, guitype='boolbox', row=3, col=2, rowspan=1, colspan=1, mode='filter[False]') parser.add_argument( "--moverawdata", action="store_true", help="Move raw data to directory ./raw_micrographs after filtration", default=False) parser.add_argument("--apix", type=float, help="Angstroms per pixel for all images", default=None, guitype='floatbox', row=5, col=0, rowspan=1, colspan=1, mode="filter['self.pm().getAPIX()']") parser.add_argument("--voltage", type=float, help="Microscope voltage in KV", default=None, guitype='floatbox', row=5, col=1, rowspan=1, colspan=1, mode="filter['self.pm().getVoltage()']") parser.add_argument("--cs", type=float, help="Microscope Cs (spherical aberation)", default=None, guitype='floatbox', row=6, col=0, rowspan=1, colspan=1, mode="filter['self.pm().getCS()']") parser.add_argument("--ac", type=float, help="Amplitude contrast (percentage, default=10)", default=10, guitype='floatbox', row=6, col=1, rowspan=1, colspan=1, mode="filter") parser.add_argument("--defocusmin", type=float, help="Minimum autofit defocus", default=0.6, guitype='floatbox', row=8, col=0, rowspan=1, colspan=1, mode="filter[0.6]") parser.add_argument("--defocusmax", type=float, help="Maximum autofit defocus", default=4, guitype='floatbox', row=8, col=1, rowspan=1, colspan=1, mode='filter[4.0]') parser.add_argument( "--ppid", type=int, help="Set the PID of the parent process, used for cross platform PPID", default=-1) (options, args) = parser.parse_args() microdir = os.path.join(".", "micrographs") if not os.access(microdir, os.R_OK): os.mkdir("micrographs") logid = E2init(sys.argv, options.ppid) # After filtration we move micrographs to a directory 'raw_micrographs', if desired if options.moverawdata: originalsdir = os.path.join(".", "raw_micrographs") if not os.access(originalsdir, os.R_OK): os.mkdir("raw_micrographs") for i, arg in enumerate(args): base = base_name(arg, nodir=not options.usefoldername) output = os.path.join(os.path.join(".", "micrographs"), base + ".hdf") cmd = "e2proc2d.py %s %s --inplace" % (arg, output) if options.invert: cmd += " --mult=-1" if options.edgenorm: cmd += " --process=normalize.edgemean" if options.xraypixel: cmd += " --process=threshold.clampminmax.nsigma:nsigma=4" launch_childprocess(cmd) if options.moverawdata: os.rename(arg, os.path.join(originalsdir, os.path.basename(arg))) # We estimate the defocus and B-factor (no astigmatism) from the micrograph and store it in info and the header if options.ctfest: d = EMData(output, 0) if d["nx"] < 1200 or d["ny"] < 1200: print "CTF estimation will only work with images at least 1200x1200 in size" sys.exit(1) import e2ctf ds = 1.0 / (options.apix * 512) ffta = None nbx = 0 for x in range(100, d["nx"] - 512, 512): for y in range(100, d["ny"] - 512, 512): clip = d.get_clip(Region(x, y, 512, 512)) clip.process_inplace("normalize.edgemean") fft = clip.do_fft() fft.ri2inten() if ffta == None: ffta = fft else: ffta += fft nbx += 1 ffta.mult(1.0 / (nbx * 512**2)) ffta.process_inplace("math.sqrt") ffta[ "is_intensity"] = 0 # These 2 steps are done so the 2-D display of the FFT looks better. Things would still work properly in 1-D without it fftbg = ffta.process("math.nonconvex") fft1d = ffta.calc_radial_dist( ffta.get_ysize() / 2, 0.0, 1.0, 1) # note that this handles the ri2inten averages properly # Compute 1-D curve and background bg_1d = e2ctf.low_bg_curve(fft1d, ds) #initial fit, background adjustment, refine fit, final background adjustment ctf = e2ctf.ctf_fit(fft1d, bg_1d, bg_1d, ffta, fftbg, options.voltage, options.cs, options.ac, options.apix, 1, dfhint=(options.defocusmin, options.defocusmax)) bgAdj(ctf, fft1d) ctf = e2ctf.ctf_fit(fft1d, ctf.background, ctf.background, ffta, fftbg, options.voltage, options.cs, options.ac, options.apix, 1, dfhint=(options.defocusmin, options.defocusmax)) bgAdj(ctf, fft1d) if options.astigmatism: e2ctf.ctf_fit_stig(ffta, fftbg, ctf) #ctf.background=bg_1d #ctf.dsbg=ds db = js_open_dict(info_name(arg, nodir=not options.usefoldername)) db["ctf_frame"] = [512, ctf, (256, 256), set(), 5, 1] print info_name(arg, nodir=not options.usefoldername), ctf E2progress(logid, (float(i) / float(len(args)))) E2end(logid)
def fit_defocus(options,img_file,fft_avg,voltage,cs,ampcont,phaseplate,apix,target_defocus,defocusmin=0.5,defocusmax=9.0,defocusstep=0.1): """Fit defocus from an incoherent average of tiles Author: Jesus Montoya, [email protected], 09/2019 """ print("\n(fit_defocus) entering function") tilesize = fft_avg['ny'] fft_bg = fft_avg.process("math.nonconvex") fft_avg_1d = fft_avg.calc_radial_dist(old_div(fft_avg.get_ysize(),2),0.0,1.0,1) # note that this handles the ri2inten averages properly #print("\n(e2tomo_ctfraw)(fit_defocus) fft_avg_1d={}".format(fft_avg_1d)) ctf = EMAN2Ctf() #print("\n(e2tomo_ctfraw)(fit_defocus) apix={}".format(apix)) #print("\n(e2tomo_ctfraw)(fit_defocus) tilesize={}".format(tilesize)) # Compute 1-D curve and background ds = old_div(1.0,( apix * tilesize )) #print("\n(e2tomo_ctfraw)(fit_defocus) ds={}".format(ds)) bg_1d = e2ctf.low_bg_curve(fft_avg_1d,ds) #print("\n(e2tomo_ctfraw)(fit_defocus) bg_1d={}".format(bg_1d)) dfhint=( defocusmin, defocusmax, defocusstep ) ctf = e2ctf.ctf_fit( fft_avg_1d, bg_1d, bg_1d, fft_avg, fft_bg, float(voltage), float(cs), float(ampcont), phaseplate, float(apix), bgadj=1, autohp=True, dfhint=dfhint) #print("\n(e2tomo_ctfraw)(fit_defocus) ctf={}".format(ctf)) #bg_sub = numpy.array(fft_avg_1d) - numpy.array(bg_1d) bg_sub,bg_1d = e2ctf.calc_1dfrom2d(ctf, fft_avg, fft_bg) fit = ctf_get_fit_curve(ctf, ds, fft_avg_1d, bg_1d, bg_sub) fit/=max(fit) #ctf = adjust_ctf_bg(ctf,fft_avg_1d) #maxres,bfactor = ctf_fit_bfactor_and_maxres( list(bg_sub),ds,ctf) #print("\ndefocus={}, FIRST trial".format(ctf.defocus)) ctf2 = EMAN2Ctf() dfhint2=(max(dfhint[0],ctf.defocus-0.1),min(dfhint[1],ctf.defocus+0.1),min(old_div(dfhint[2],2.0),0.01)) ctf2 = e2ctf.ctf_fit( fft_avg_1d, bg_1d, bg_1d, fft_avg, fft_bg, float(voltage), float(cs), float(ampcont), phaseplate, float(apix), bgadj=1, autohp=True, dfhint=dfhint2 ) bg_sub2,bg_1d2 = e2ctf.calc_1dfrom2d(ctf2, fft_avg, fft_bg) #bg_sub2,bg_1d2 = e2ctf.calc_1dfrom2d(ctf2, fft_avg, fft_bg) fit2 = ctf_get_fit_curve(ctf2, ds, fft_avg_1d, bg_1d2, bg_sub2) fit2/=max(fit2) #maxres,bfactor = ctf_fit_bfactor_and_maxres( list(bg_sub2),ds,ctf) #print("\nmaxres calc={}, bfactor={}, defocus={}, SECOND trial".format(maxres,ctf2.bfactor,ctf2.defocus)) bg_sub_final = numpy.array(bg_sub2) - numpy.array(bg_1d2) bg_sub_final/=max(bg_sub_final) import matplotlib.pyplot as plt if options.plots or options.debug: r = len(ctf.background) s = numpy.arange(0,ds*r,ds) if options.debug: plt.plot(s, fit2, 'k') plt.plot(s, bg_sub_final, 'b') plt.show() if options.plots: extension = os.path.splitext(os.path.basename( img_file ))[-1] print("\n(fit_defocus) should save plots") ps_file = img_file.replace(extension,'_1d_ps.txt') if ps_file == img_file: print("\nERROR: risk of overwritting input image") sys.exit(1) write_txt(s,bg_sub_final,ps_file) #with open(options.path + '/' + pfile,'w') as f: # lines = [ str(s[i])+'\t'+str(bg_sub_final[i])+'\n' for i in range(len(s-1))] # lines.append( str(s[-1]) + '\t' + str(bg_sub_final[-1]) ) #the last element does not need a 'return' or 'line break' fit_file = img_file.replace(extension,'_1d_fit.txt') if fit_file == img_file: print("\nERROR: risk of overwritting input image") sys.exit(1) #with open(options.path + '/' + pfile,'w') as f: # lines = [ str(s[i])+'\t'+str(bg_sub_final[i])+'\n' for i in range(len(s-1))] # lines.append( str(s[-1]) + '\t' + str(bg_sub_final[-1]) ) #the last element does not need a 'return' or 'line break' write_txt(s,fit2,fit_file) print("\n(fit_defocus) leaving function") return ctf
def recalc_real(self): "Called to recompute the power spectra, also updates plot" self.needupdate=False if self.data==None : self.procthread=None return self.incalc=True # to avoid incorrect plot updates # To simplify expressions parms=self.parms[self.curset] apix=self.sapix.getValue() if len(parms)==5 : parms.append(1) # for old projects where there was no oversampling specification else: parms[5]=max(1,int(parms[5])) ds=1.0/(apix*parms[0]*parms[5]) # Mode where user drags the box around the parent image if self.calcmode==0: # extract the data and do an fft clip=self.data.get_clip(Region(parms[2][0],parms[2][1],parms[0],parms[0])) clip.process_inplace("normalize.edgemean") if parms[5]>1 : clip=clip.get_clip(Region(0,0,parms[0]*parms[5],parms[0]*parms[5])) # since we aren't using phases, doesn't matter if we center it or not self.fft=clip.do_fft() # self.fft.mult(1.0/parms[0]**2) self.fft.mult(1.0/parms[0]) # mode where user selects/deselcts tiled image set elif self.calcmode==1: # update the box display on the image nx=self.data["nx"]/parms[0]-1 self.fft=None nbx=0 for x in range(nx): for y in range(self.data["ny"]/parms[0]-1): # User deselected this one if int(x+y*nx) in parms[3] : continue # read the data and make the FFT clip=self.data.get_clip(Region(x*parms[0]+parms[0]/2,y*parms[0]+parms[0]/2,parms[0],parms[0])) clip.process_inplace("normalize.edgemean") if parms[5]>1 : clip=clip.get_clip(Region(0,0,parms[0]*parms[5],parms[0]*parms[5])) # since we aren't using phases, doesn't matter if we center it or not fft=clip.do_fft() # fft.mult(parms[0]) fft.ri2inten() if self.fft==None: self.fft=fft else: self.fft+=fft nbx+=1 self.fft.mult(1.0/(nbx*parms[0]**2)) self.fft.process_inplace("math.sqrt") self.fft["is_intensity"]=0 # These 2 steps are done so the 2-D display of the FFT looks better. Things would still work properly in 1-D without it # self.fft.mult(1.0/(nbx*parms[0]**2)) self.fftbg=self.fft.process("math.nonconvex") self.fft1d=self.fft.calc_radial_dist(self.fft.get_ysize()/2,0.0,1.0,1) # note that this handles the ri2inten averages properly if self.plotmode==2 or self.plotmode==3: self.fft1dang=array(self.fft.calc_radial_dist(self.fft.get_ysize()/2,0.0,1.0,4,self.sang45.getValue()*.017453292,1)) # This form generates 4 sequential power spectra representing angular ranges self.fft1dang=self.fft1dang.reshape((4,self.fft.get_ysize()/2)) else: self.fft1dang=None # Compute 1-D curve and background bg_1d=e2ctf.low_bg_curve(self.fft1d,ds) parms[1].background=bg_1d parms[1].dsbg=ds self.fft1d=array(self.fft1d) self.needredisp=True self.incalc=False time.sleep(.2) # help make sure update has a chance self.procthread=None self.bgAdj()
def main(): progname = os.path.basename(sys.argv[0]) usage = """prog [options] <micrograph1, micrograph2....> Use this program to import and filter raw micrographs. If you choose to filter and/or convert format, this program will process each micrograph and dump them into the directory './micrographs.', otherwise the micrographs will simply be moved into './micrographs'. If you select the option --moverawdata AND you filter or change format, your original micrographs will be moved into the directory './raw_micrographs' and your filtered micrographs will be in './micrographs as usual. BDB files are not moved, but they can be processed.""" parser = EMArgumentParser(usage=usage,version=EMANVERSION) parser.add_pos_argument(name="micrographs",help="List the micrographs to filter here.", default="", guitype='filebox', browser="EMRawDataTable(withmodal=True,multiselect=True)", row=0, col=0,rowspan=1, colspan=2, mode='filter') parser.add_pos_argument(name="import_files",help="List the files to import/filter here.", default="", guitype='filebox', browser="EMBrowserWidget(withmodal=True,multiselect=True)", row=0, col=0,rowspan=1, colspan=2, mode='import') parser.add_header(name="filterheader", help='Options below this label are specific to filtering', title="### filtering options ###", row=1, col=0, rowspan=1, colspan=2, mode='import,filter') parser.add_argument("--invert",action="store_true",help="Invert contrast",default=False, guitype='boolbox', row=2, col=0, rowspan=1, colspan=1, mode='filter[True]') parser.add_argument("--edgenorm",action="store_true",help="Edge normalize",default=False, guitype='boolbox', row=2, col=1, rowspan=1, colspan=1, mode='filter[True]') parser.add_argument("--usefoldername",action="store_true",help="If you have the same image filename in multiple folders, and need to import into the same project, this will prepend the folder name on each image name",default=False,guitype='boolbox',row=2, col=2, rowspan=1, colspan=1, mode="import[False]") parser.add_argument("--xraypixel",action="store_true",help="Filter X-ray pixels",default=False, guitype='boolbox', row=3, col=0, rowspan=1, colspan=1, mode='filter[True]') parser.add_argument("--ctfest",action="store_true",help="Estimate defocus from whole micrograph",default=False, guitype='boolbox', row=3, col=1, rowspan=1, colspan=1, mode='filter[True]') parser.add_argument("--astigmatism",action="store_true",help="Includes astigmatism in automatic fitting",default=False, guitype='boolbox', row=3, col=2, rowspan=1, colspan=1, mode='filter[False]') parser.add_argument("--moverawdata",action="store_true",help="Move raw data to directory ./raw_micrographs after filtration",default=False) parser.add_argument("--apix",type=float,help="Angstroms per pixel for all images",default=None, guitype='floatbox', row=5, col=0, rowspan=1, colspan=1, mode="filter['self.pm().getAPIX()']") parser.add_argument("--voltage",type=float,help="Microscope voltage in KV",default=None, guitype='floatbox', row=5, col=1, rowspan=1, colspan=1, mode="filter['self.pm().getVoltage()']") parser.add_argument("--cs",type=float,help="Microscope Cs (spherical aberation)",default=None, guitype='floatbox', row=6, col=0, rowspan=1, colspan=1, mode="filter['self.pm().getCS()']") parser.add_argument("--ac",type=float,help="Amplitude contrast (percentage, default=10)",default=10, guitype='floatbox', row=6, col=1, rowspan=1, colspan=1, mode="filter") parser.add_argument("--defocusmin",type=float,help="Minimum autofit defocus",default=0.6, guitype='floatbox', row=8, col=0, rowspan=1, colspan=1, mode="filter[0.6]") parser.add_argument("--defocusmax",type=float,help="Maximum autofit defocus",default=4, guitype='floatbox', row=8, col=1, rowspan=1, colspan=1, mode='filter[4.0]') parser.add_argument("--ppid", type=int, help="Set the PID of the parent process, used for cross platform PPID",default=-1) (options, args) = parser.parse_args() microdir = os.path.join(".","micrographs") if not os.access(microdir, os.R_OK): os.mkdir("micrographs") logid=E2init(sys.argv,options.ppid) # After filtration we move micrographs to a directory 'raw_micrographs', if desired if options.moverawdata: originalsdir = os.path.join(".","raw_micrographs") if not os.access(originalsdir, os.R_OK): os.mkdir("raw_micrographs") for i,arg in enumerate(args): base = base_name(arg,nodir=not options.usefoldername) output = os.path.join(os.path.join(".","micrographs"),base+".hdf") cmd = "e2proc2d.py %s %s --inplace"%(arg,output) if options.invert: cmd += " --mult=-1" if options.edgenorm: cmd += " --process=normalize.edgemean" if options.xraypixel: cmd += " --process=threshold.clampminmax.nsigma:nsigma=4" launch_childprocess(cmd) if options.moverawdata: os.rename(arg,os.path.join(originalsdir,os.path.basename(arg))) # We estimate the defocus and B-factor (no astigmatism) from the micrograph and store it in info and the header if options.ctfest : d=EMData(output,0) if d["nx"]<1200 or d["ny"]<1200 : print "CTF estimation will only work with images at least 1200x1200 in size" sys.exit(1) import e2ctf ds=1.0/(options.apix*512) ffta=None nbx=0 for x in range(100,d["nx"]-512,512): for y in range(100,d["ny"]-512,512): clip=d.get_clip(Region(x,y,512,512)) clip.process_inplace("normalize.edgemean") fft=clip.do_fft() fft.ri2inten() if ffta==None: ffta=fft else: ffta+=fft nbx+=1 ffta.mult(1.0/(nbx*512**2)) ffta.process_inplace("math.sqrt") ffta["is_intensity"]=0 # These 2 steps are done so the 2-D display of the FFT looks better. Things would still work properly in 1-D without it fftbg=ffta.process("math.nonconvex") fft1d=ffta.calc_radial_dist(ffta.get_ysize()/2,0.0,1.0,1) # note that this handles the ri2inten averages properly # Compute 1-D curve and background bg_1d=e2ctf.low_bg_curve(fft1d,ds) #initial fit, background adjustment, refine fit, final background adjustment ctf=e2ctf.ctf_fit(fft1d,bg_1d,bg_1d,ffta,fftbg,options.voltage,options.cs,options.ac,options.apix,1,dfhint=(options.defocusmin,options.defocusmax)) bgAdj(ctf,fft1d) ctf=e2ctf.ctf_fit(fft1d,ctf.background,ctf.background,ffta,fftbg,options.voltage,options.cs,options.ac,options.apix,1,dfhint=(options.defocusmin,options.defocusmax)) bgAdj(ctf,fft1d) if options.astigmatism : e2ctf.ctf_fit_stig(ffta,fftbg,ctf) #ctf.background=bg_1d #ctf.dsbg=ds db=js_open_dict(info_name(arg,nodir=not options.usefoldername)) db["ctf_frame"]=[512,ctf,(256,256),set(),5,1] print info_name(arg,nodir=not options.usefoldername),ctf E2progress(logid,(float(i)/float(len(args)))) E2end(logid)