def db_compute_fsc(a, b, apix, pathname, dbname): fsc = a.calc_fourier_shell_correlation(b) third = len(fsc)/3 xaxis = fsc[0:third] plot = fsc[third:2*third] error = fsc[2*third:] convergence_db_name = "bdb:"+pathname+"#convergence.results" db = db_open_dict(convergence_db_name) tmpaxis = [x/apix for x in xaxis] db[dbname] = [tmpaxis[1:],plot[1:]] #db["error_"+s+"_fsc"] = [xaxis,error] #we're not plotting the errors db_close_dict(convergence_db_name)
def main(): progname = os.path.basename(sys.argv[0]) usage = """prog [options] <volume> <mask> <output> WARNING: Do not use this program. The whole concept has been replaced by "gold standard" refinement. Note that this method has not yet been published, and is not yet a reliable scheme for resolution determination. DO NOT EXPECT RELIABLE ANSWERS AT THIS POINT ! This will compute an FSC resolution curve from a single structure by comparing the power spectrum of the noise region to the power spectrum of the reconstructed particle. The 'mask' input should mask out the particle, and should be a 'soft' mask. Sharp edges on the mask may ruin the results. proc3d (EMAN1) with the automask2 option can produce appropriate masks. The 3rd parameter (in automask2) should be about 10 percent of the box size. This will not work with particles that have been tightly masked already. If doing an EMAN1 reconstruction with the amask= option, you must also use the refmaskali option (in the refine command). Note that the resultant curve is guaranteed to go to zero at near Nyquist because it assumes that the SNR is zero near Nyquist. If your data is undersampled, the resulting curve may also be inaccurate. Models should also not be heavily low-pass filtered """ parser = EMArgumentParser(usage=usage, version=EMANVERSION) parser.add_pos_argument(name="volume", help="Volume to compute resolution on.", default="", guitype='filebox', row=0, col=0, rowspan=1, colspan=2) parser.add_pos_argument( name="mask", help= "Mask for the volume. The volume is masked by this file (should be ssoft mask).", default="", guitype='filebox', row=1, col=0, rowspan=1, colspan=2) parser.add_pos_argument( name="output", help="Name of the output file. These data will contain FSC stats.", default="", guitype='strbox', row=2, col=0, rowspan=1, colspan=2) parser.add_header( name="eotestheader", help='Options below this label are specific to e2resolution', title="### e2resolution options ###", row=3, col=0, rowspan=1, colspan=2) parser.add_argument("--apix", "-A", type=float, help="A/voxel", default=-1.0, guitype='floatbox', row=4, col=0, rowspan=1, colspan=1) parser.add_argument( "--path", type=str, help= "The name the e2refine directory that contains the reconstruction data. If specified will place curves generated in bdb:path#convergence.results", guitype='dirbox', default=None, dirbasename='refine', row=4, col=1, rowspan=1, colspan=1) 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() if len(args) < 3: parser.error("Input and output files required") E2n = E2init(sys.argv, options.ppid) #options.align=parsemodopt(options.align) print( "WARNING: e2resolution is an experimental program. It does not (yet) produce reliable resolution curves in most cases." ) print("read models") data = EMData(args[0], 0) mask = EMData(args[1], 0) # mask.to_one() # mask.process_inplace("mask.gaussian",{"outer_radius":mask.get_xsize()/6,"inner_radius":mask.get_xsize()/6}) mask.write_image("msk.mrc", 0) # inverted mask maski = mask.copy() maski *= -1.0 maski += 1.0 maski.process_inplace( "mask.gaussian", { "outer_radius": old_div(mask.get_xsize(), 6), "inner_radius": old_div(mask.get_xsize(), 3) }) maski.write_image("msk2.mrc", 0) noise = data.copy() noise *= maski data *= mask print("compute FFT") dataf = data.do_fft() noisef = noise.do_fft() print("compute power 1") datapow = dataf.calc_radial_dist( old_div(dataf.get_ysize(), 2) - 1, 1, 1, 1) print("compute power 2") noisepow = noisef.calc_radial_dist( old_div(noisef.get_ysize(), 2) - 1, 1, 1, 1) x = list(range(1, len(datapow) + 1)) if options.apix > 0: x = [old_div(i, (len(datapow) * options.apix * 2.0)) for i in x] else: x = [old_div(i, (len(datapow) * data["apix_x"] * 2.0)) for i in x] # normalize noise near Nyquist s = 0 sn = 0 for i in range(int(len(noisepow) * .9), len(noisepow) - 1): if datapow[i] < datapow[i + 1] or noisepow[i] < noisepow[i + 1]: continue s += old_div(datapow[i], noisepow[i]) sn += 1.0 if sn == 0: print("Warning, strange normalization") s = old_div(datapow[int(len(noisepow) * .9)], noisepow[int(len(noisepow) * .9)]) else: s /= sn noisepow = [i * s for i in noisepow] # # # normalize based on volume # datapow=[v/mask["mean"] for v in datapow] # noisepow=[v/maski["mean"] for v in noisepow] # compute signal to noise ratio snr = [] for i in range(len(datapow)): try: snr.append(old_div((datapow[i] - noisepow[i]), noisepow[i])) except: snr.append(0) # convert to FSC fsc = [old_div(i, (2.0 + i)) for i in snr] out = open(args[2], "w") for i in range(len(fsc)): out.write("%f\t%f\n" % (x[i], fsc[i])) out.close() out = open(args[2] + ".dat", "w") for i in range(len(fsc)): out.write("%f\t%f\n" % (x[i], datapow[i])) out.close() out = open(args[2] + ".noi", "w") for i in range(len(noisepow)): out.write("%f\t%f\n" % (x[i], noisepow[i])) out.close() if options.path != None: s = base_name(args[0]) db = db_open_dict("bdb:" + options.path + "#convergence.results") db[s + "res_fsc"] = [ x, fsc ] # warning, changing this naming convention will disrupt forms in the workflow (make them fail) db[s + "res_datapow"] = [x, datapow] db[s + "res_noisepow"] = [x, noisepow] db_close_dict("bdb:" + options.path + "#convergence.results") E2end(E2n)
def filter_shrink(input_bdb_name, output_stack_path, output_bdb_name, alignYN=False, filtrad=None, shrink=None, verbose=False): """ Filters and shrinks image stack. Arguments: input_bdb_name : Input BDB stack (in the form bdb:DIRECTORY#STACK) output_stack_path : Name for output image stack (MRCS/HDF/etc.) output_bdb_name : Name for output BDB stack (in the form bdb:DIRECTORY#STACK) alignYN: (boolean) Whether to apply alignments filtrad : Filter radius, reciprocal pixels shrink : Downsampling factor combined_params_file : Output combined alignment parameters verbose : (boolean) Whether to write to screen """ input_stack = EMData.read_images(input_bdb_name) num_imgs = EMUtil.get_image_count(input_bdb_name) box_size = input_stack[0].get_attr('nx') if options.shrink: sub_rate = float(1) / options.shrink box_size = int(float(box_size) / options.shrink + 0.5) if verbose: print('sub_rate', sub_rate, type(sub_rate), box_size, options.shrink) # Initialize stack & BDB aligned_stack_obj = EMData(box_size, box_size, num_imgs) new_bdb_dict = db_open_dict(output_bdb_name) # Loop through images for img_num in range(len(input_stack)): img_orig = input_stack[img_num] try: alpha, sx, sy, mirror, scale = get_params2D(img_orig) except RuntimeError: print('\nERROR! Exiting with RuntimeError') img_prev = input_stack[img_num - 1] print('\nPrevious particle: %s %s' % (img_num - 1, img_prev.get_attr_dict())) print('\nCurrent particle: %s %s' % (img_num, img_orig.get_attr_dict())) exit() # Optionally apply alignment parameters if alignYN: img_ali = rot_shift2D(img_orig, alpha, sx, sy, mirror, scale, "quadratic") else: img_ali = img_orig if verbose and img_num == 0: print('\nimg_orig.get_attr_dict0', img_orig.get_attr_dict()) img_ali_dict = img_ali.get_attr_dict() print('\nimg_ali.get_attr_dict1\n', img_ali.get_attr_dict()) if filtrad: img_ali = filt_gaussl(img_ali, filtrad) if shrink: img_ali = resample(img_ali, sub_rate) #### (Maybe update resample_ratio) img_ali_dict = img_ali.get_attr_dict() img_ali_dict["data_path"] = os.path.join( '..', STACKFILEDIR, os.path.basename(output_stack_path)) img_ali_dict["ptcl_source_coord_id"] = img_num new_bdb_dict[img_num] = img_ali_dict aligned_stack_obj.insert_clip(img_ali, (0, 0, img_num)) # End image-loop aligned_stack_obj.write_image(output_stack_path) db_close_dict(output_bdb_name) return num_imgs
def main(): progname = os.path.basename(sys.argv[0]) usage = """prog [options] <volume> <mask> <output> WARNING: Do not use this program. The whole concept has been replaced by "gold standard" refinement. Note that this method has not yet been published, and is not yet a reliable scheme for resolution determination. DO NOT EXPECT RELIABLE ANSWERS AT THIS POINT ! This will compute an FSC resolution curve from a single structure by comparing the power spectrum of the noise region to the power spectrum of the reconstructed particle. The 'mask' input should mask out the particle, and should be a 'soft' mask. Sharp edges on the mask may ruin the results. proc3d (EMAN1) with the automask2 option can produce appropriate masks. The 3rd parameter (in automask2) should be about 10 percent of the box size. This will not work with particles that have been tightly masked already. If doing an EMAN1 reconstruction with the amask= option, you must also use the refmaskali option (in the refine command). Note that the resultant curve is guaranteed to go to zero at near Nyquist because it assumes that the SNR is zero near Nyquist. If your data is undersampled, the resulting curve may also be inaccurate. Models should also not be heavily low-pass filtered """ parser = EMArgumentParser(usage=usage,version=EMANVERSION) parser.add_pos_argument(name="volume",help="Volume to compute resolution on.", default="", guitype='filebox', row=0, col=0,rowspan=1, colspan=2) parser.add_pos_argument(name="mask",help="Mask for the volume. The volume is masked by this file (should be ssoft mask).", default="", guitype='filebox', row=1, col=0,rowspan=1, colspan=2) parser.add_pos_argument(name="output",help="Name of the output file. These data will contain FSC stats.", default="", guitype='strbox', row=2, col=0,rowspan=1, colspan=2) parser.add_header(name="eotestheader", help='Options below this label are specific to e2resolution', title="### e2resolution options ###", row=3, col=0, rowspan=1, colspan=2) parser.add_argument("--apix", "-A", type=float, help="A/voxel", default=-1.0, guitype='floatbox', row=4, col=0, rowspan=1, colspan=1) parser.add_argument("--path", type=str,help="The name the e2refine directory that contains the reconstruction data. If specified will place curves generated in bdb:path#convergence.results", guitype='dirbox', default=None, dirbasename='refine', row=4, col=1,rowspan=1, colspan=1) 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() if len(args)<3 : parser.error("Input and output files required") E2n=E2init(sys.argv,options.ppid) #options.align=parsemodopt(options.align) print "WARNING: e2resolution is an experimental program. It does not (yet) produce reliable resolution curves in most cases." print "read models" data=EMData(args[0],0) mask=EMData(args[1],0) # mask.to_one() # mask.process_inplace("mask.gaussian",{"outer_radius":mask.get_xsize()/6,"inner_radius":mask.get_xsize()/6}) mask.write_image("msk.mrc",0) # inverted mask maski=mask.copy() maski*=-1.0 maski+=1.0 maski.process_inplace("mask.gaussian",{"outer_radius":mask.get_xsize()/6,"inner_radius":mask.get_xsize()/3}) maski.write_image("msk2.mrc",0) noise=data.copy() noise*=maski data*=mask print "compute FFT" dataf=data.do_fft() noisef=noise.do_fft() print "compute power 1" datapow=dataf.calc_radial_dist(dataf.get_ysize()/2-1,1,1,1) print "compute power 2" noisepow=noisef.calc_radial_dist(noisef.get_ysize()/2-1,1,1,1) x=range(1,len(datapow)+1) if options.apix>0: x=[i/(len(datapow)*options.apix*2.0) for i in x] else: x=[i/(len(datapow)*data["apix_x"]*2.0) for i in x] # normalize noise near Nyquist s=0 sn=0 for i in range(int(len(noisepow)*.9),len(noisepow)-1): if datapow[i]<datapow[i+1] or noisepow[i]<noisepow[i+1] : continue s+=datapow[i]/noisepow[i] sn+=1.0 if sn==0 : print "Warning, strange normalization" s=datapow[int(len(noisepow)*.9)]/noisepow[int(len(noisepow)*.9)] else: s/=sn noisepow=[i*s for i in noisepow] # # # normalize based on volume # datapow=[v/mask["mean"] for v in datapow] # noisepow=[v/maski["mean"] for v in noisepow] # compute signal to noise ratio snr=[] for i in range(len(datapow)): try: snr.append((datapow[i]-noisepow[i])/noisepow[i]) except: snr.append(0) # convert to FSC fsc=[i/(2.0+i) for i in snr] out=file(args[2],"w") for i in range(len(fsc)): out.write("%f\t%f\n"%(x[i],fsc[i])) out.close() out=file(args[2]+".dat","w") for i in range(len(fsc)): out.write("%f\t%f\n"%(x[i],datapow[i])) out.close() out=file(args[2]+".noi","w") for i in range(len(noisepow)): out.write("%f\t%f\n"%(x[i],noisepow[i])) out.close() if options.path != None: s = base_name(args[0]) db = db_open_dict("bdb:"+options.path+"#convergence.results") db[s+"res_fsc"] = [x,fsc] # warning, changing this naming convention will disrupt forms in the workflow (make them fail) db[s+"res_datapow"] = [x,datapow] db[s+"res_noisepow"] = [x,noisepow] db_close_dict("bdb:"+options.path+"#convergence.results") E2end(E2n)