def _fft(self, reciprocal_lattice_vectors, d_min): reciprocal_space_grid, used_in_indexing = self._map_centroids_to_reciprocal_space_grid( reciprocal_lattice_vectors, d_min) logger.info("Number of centroids used: %i" % ((reciprocal_space_grid > 0).count(True))) # gb_to_bytes = 1073741824 # bytes_to_gb = 1/gb_to_bytes # (128**3)*8*2*bytes_to_gb # 0.03125 # (256**3)*8*2*bytes_to_gb # 0.25 # (512**3)*8*2*bytes_to_gb # 2.0 fft = fftpack.complex_to_complex_3d(self._gridding) grid_complex = flex.complex_double( reals=reciprocal_space_grid, imags=flex.double(reciprocal_space_grid.size(), 0), ) grid_transformed = fft.forward(grid_complex) grid_real = flex.pow2(flex.real(grid_transformed)) del grid_transformed return grid_real, used_in_indexing
def background_correct(data, raw_asic): prime_asic = get_factorizable_block(raw_asic) print "Working on block", prime_asic block = data.matrix_copy_block(i_row=prime_asic[0], i_column=prime_asic[1], n_rows=prime_asic[2] - prime_asic[0], n_columns=prime_asic[3] - prime_asic[1]) complex_data = flex.polar(block.as_double(), flex.double(flex.grid(block.focus()))) from scitbx import fftpack fft = fftpack.complex_to_complex_2d(block.focus()) # input data here fft.forward(complex_data) # your manipulation here low_pass_filter(complex_data) fft.backward(complex_data) # real data filtered_data = flex.real(complex_data) / (fft.n()[0] * fft.n()[1]) corrected_data = block - filtered_data.iround() requested_block = data.matrix_copy_block(i_row=raw_asic[0], i_column=raw_asic[1], n_rows=raw_asic[2] - raw_asic[0], n_columns=raw_asic[3] - raw_asic[1]) requested_block.matrix_paste_block_in_place( block=corrected_data, i_row=prime_asic[0] - raw_asic[0], i_column=prime_asic[1] - raw_asic[1]) return requested_block
def test_flatten(): from dials.algorithms.shoebox import MaskCode from dials.array_family import flex for shoebox, (XC, I) in random_shoeboxes(10, mask=True): assert not shoebox.flat zs = shoebox.zsize() ys = shoebox.ysize() xs = shoebox.xsize() expected_data = flex.real(flex.grid(1, ys, xs), 0) expected_mask = flex.int(flex.grid(1, ys, xs), 0) for k in range(zs): for j in range(ys): for i in range(xs): expected_data[0, j, i] += shoebox.data[k, j, i] expected_mask[0, j, i] |= shoebox.mask[k, j, i] if not (expected_mask[0, j, i] & MaskCode.Valid) or not ( shoebox.mask[k, j, i] & MaskCode.Valid): expected_mask[0, j, i] &= ~MaskCode.Valid shoebox.flatten() diff = expected_data.as_double() - shoebox.data.as_double() max_diff = flex.max(flex.abs(diff)) assert max_diff < 1e-7 assert expected_mask.all_eq(shoebox.mask) assert shoebox.flat assert shoebox.is_consistent()
def background_correct(data, raw_asic): prime_asic = get_factorizable_block(raw_asic) print "Working on block",prime_asic block = data.matrix_copy_block( i_row=prime_asic[0],i_column=prime_asic[1], n_rows=prime_asic[2]-prime_asic[0], n_columns=prime_asic[3]-prime_asic[1]) complex_data = flex.polar(block.as_double(),flex.double(flex.grid(block.focus()))) from scitbx import fftpack fft = fftpack.complex_to_complex_2d(block.focus()) # input data here fft.forward(complex_data) # your manipulation here low_pass_filter(complex_data) fft.backward(complex_data) # real data filtered_data = flex.real(complex_data)/(fft.n()[0]*fft.n()[1]) corrected_data = block - filtered_data.iround() requested_block = data.matrix_copy_block( i_row=raw_asic[0],i_column=raw_asic[1], n_rows=raw_asic[2]-raw_asic[0], n_columns=raw_asic[3]-raw_asic[1]) requested_block.matrix_paste_block_in_place( block = corrected_data, i_row = prime_asic[0] - raw_asic[0], i_column = prime_asic[1] - raw_asic[1] ) return requested_block
def tst_2d_zernike_mom(n, l, filename, h5file, flag): rebuilt = open(filename, 'w') # image = generate_image() # image=ImageToDat("/Users/wyf/Desktop/test11.png") image = preprocess_image(h5file, flag) # image = ImageToDat('cha.png') NP = int(smath.sqrt(image.size())) N = int(NP / 2) print "=====", NP, N grid_2d = math.two_d_grid(N, nmax) grid_2d.clean_space(image) grid_2d.construct_space_sum() zernike_2d_mom = math.two_d_zernike_moments(grid_2d, nmax) moments = zernike_2d_mom.moments() coefs = flex.real(moments) nl_array = math.nl_array(nmax) nls = nl_array.nl() nl_array.load_coefs(nls, coefs) lfg = math.log_factorial_generator(nmax) # print nl_array.get_coef(n,l)*2 for nl, c in zip(nls, moments): if (abs(c) < 1e-3): c = 0 print nl, c reconst = flex.complex_double(NP**2, 0) for nl, c in zip(nls, moments): n = nl[0] l = nl[1] if (l > 0): c = c * 2 #rzfa = math.zernike_2d_radial(n,l,lfg) rap = math.zernike_2d_polynome(n, l) #,rzfa) i = 0 for x in range(0, NP): x = x - N for y in range(0, NP): y = y - N rr = smath.sqrt(x * x + y * y) / N if rr > 1.0: value = 0.0 else: tt = smath.atan2(y, x) value = rap.f(rr, tt) reconst[i] = reconst[i] + value * c i = i + 1 i = 0 for x in range(0, NP): for y in range(0, NP): value = reconst[i].real print >> rebuilt, x, y, value i = i + 1 rebuilt.close()
def gaussian(size, a, x0, sx): from dials.array_family import flex result = flex.real(flex.grid(size)) index = [0] * len(size) while True: result[index] = evaluate_gaussian(index, a, x0, sx) for j in range(len(size)): index[j] += 1 if index[j] < size[j]: break index[j] = 0 if j == len(size) - 1: return result
def tst_2d_zm(n,l): nmax=max(n,20) np=100 points=flex.double(range(-np,np+1))/np grid = scitbx.math.two_d_grid(np, nmax) zm2d = scitbx.math.two_d_zernike_moments(grid, nmax) image = flex.vec3_double() output=file('testmap.dat','w') for x in points: for y in points: r=math.sqrt(x*x+y*y) if(r>1.0): value=0.0 else: value=zm2d.zernike_poly(n,l,x,y).real image.append([x*np+np,y*np+np, value]) grid.clean_space( image ) grid.construct_space_sum() zernike_2d_mom = scitbx.math.two_d_zernike_moments( grid, nmax ) moments = zernike_2d_mom.moments() coefs = flex.real( moments ) nl_array = scitbx.math.nl_array( nmax ) nls = nl_array.nl() for nl, c in zip( nls, moments): if(abs(c)<1e-3): c=0 print(nl, c) NP=np*2+1 reconst=zernike_2d_mom.zernike_map(nmax, np) i = 0 for x in range(0,NP): for y in range(0,NP): value=reconst[i].real if(value>0): print(x,y,image[i][2],value, file=output) i=i+1 output.close()
def tst_2d_zm(n,l): nmax=max(n,20) np=100 points=flex.double(range(-np,np+1))/np grid = math.two_d_grid(np, nmax) zm2d = math.two_d_zernike_moments(grid, nmax) image = flex.vec3_double() output=file('testmap.dat','w') for x in points: for y in points: r=smath.sqrt(x*x+y*y) if(r>1.0): value=0.0 else: value=zm2d.zernike_poly(n,l,x,y).real image.append([x*np+np,y*np+np, value]) grid.clean_space( image ) grid.construct_space_sum() zernike_2d_mom = math.two_d_zernike_moments( grid, nmax ) moments = zernike_2d_mom.moments() coefs = flex.real( moments ) nl_array = math.nl_array( nmax ) nls = nl_array.nl() for nl, c in zip( nls, moments): if(abs(c)<1e-3): c=0 print nl, c NP=np*2+1 reconst=zernike_2d_mom.zernike_map(nmax, np) i = 0 for x in range(0,NP): for y in range(0,NP): value=reconst[i].real if(value>0): print>>output, x,y,image[i][2],value i=i+1 output.close()
def background_correct_padded_block(data, raw_asic): Pad = padded_unpadded(data,raw_asic) block = Pad.get_padded_input_data() complex_data = flex.polar(block.as_double(),flex.double(flex.grid(block.focus()))) from scitbx import fftpack fft = fftpack.complex_to_complex_2d(block.focus()) # input data here fft.forward(complex_data) # your manipulation here low_pass_filter(complex_data) fft.backward(complex_data) # real data filtered_data = flex.real(complex_data)/(fft.n()[0]*fft.n()[1]) # XXX change this depending on float/int data type: corrected_data = block - filtered_data.iround() return Pad.get_unpadded_result_data(corrected_data)
def test_consistent(): from dials.array_family import flex for i in range(1000): x0 = random.randint(0, 1000) y0 = random.randint(0, 1000) z0 = random.randint(0, 1000) x1 = random.randint(1, 10) + x0 y1 = random.randint(1, 10) + y0 z1 = random.randint(1, 10) + z0 try: shoebox = Shoebox((x0, x1, y0, y1, z0, z1)) assert not shoebox.is_consistent() shoebox.allocate() assert shoebox.is_consistent() shoebox.data = flex.real(flex.grid(20, 20, 20)) assert not shoebox.is_consistent() shoebox.deallocate() assert not shoebox.is_consistent() except Exception: print(x0, y0, z0, x1, y1, z1) raise
def tst_2d_zernike_mom(n, l, file): # image = preprocess_image(h5file) image = ImageToDat(file) feature_maxtix = [] NP=int(smath.sqrt( image.size() )) N=int(NP/2) # print"=====",NP, N grid_2d = math.two_d_grid(N, nmax) grid_2d.clean_space( image ) grid_2d.construct_space_sum() zernike_2d_mom = math.two_d_zernike_moments( grid_2d, nmax ) moments = zernike_2d_mom.moments() coefs = flex.real( moments ) nl_array = math.nl_array( nmax ) nls = nl_array.nl() # nl_array.load_coefs( nls, coefs ) # lfg = math.log_factorial_generator(nmax) for nl, c in zip( nls, moments): if(abs(c)<1e-3): c=0 feature_maxtix.append(c.real) # print nl,c return feature_maxtix
def __init__(O, f_obs, f_calc=None, f_calc_abs=None, fca_sq_eps=1e-100): assert [f_calc, f_calc_abs].count(None) == 1 if (f_calc is not None): from scitbx.array_family import flex f_calc_abs = flex.abs(f_calc) O.k, O.k_d, O.k_d2 = calc_k(f_obs, f_calc_abs) O.t, O.g, O.c = calc_t(f_obs, f_calc_abs, O.k, O.k_d, O.k_d2) O.f_calc_gradients = None O.f_calc_hessians = None if (f_calc is not None): fca_sq = f_calc_abs**2 isel_zero = (fca_sq <= fca_sq_eps).iselection() f_calc_abs.set_selected(isel_zero, 1) fca_sq.set_selected(isel_zero, 1) O.f_calc_gradients = O.g / f_calc_abs * f_calc O.f_calc_gradients.set_selected(isel_zero, 0j) a = flex.real(f_calc) b = flex.imag(f_calc) aa, bb, ab = a * a, b * b, a * b haa = O.c * aa + O.g * bb / f_calc_abs hbb = O.c * bb + O.g * aa / f_calc_abs hab = (O.c - O.g / f_calc_abs) * a * b O.f_calc_hessians = flex.vec3_double(haa, hbb, hab) / fca_sq O.f_calc_hessians.set_selected(isel_zero, (0, 0, 0))
def __init__(O, f_obs, f_calc=None, f_calc_abs=None, fca_sq_eps=1e-100): assert [f_calc, f_calc_abs].count(None) == 1 if (f_calc is not None): from scitbx.array_family import flex f_calc_abs = flex.abs(f_calc) O.k, O.k_d, O.k_d2 = calc_k(f_obs, f_calc_abs) O.t, O.g, O.c = calc_t(f_obs, f_calc_abs, O.k, O.k_d, O.k_d2) O.f_calc_gradients = None O.f_calc_hessians = None if (f_calc is not None): fca_sq = f_calc_abs**2 isel_zero = (fca_sq <= fca_sq_eps).iselection() f_calc_abs.set_selected(isel_zero, 1) fca_sq.set_selected(isel_zero, 1) O.f_calc_gradients = O.g / f_calc_abs * f_calc O.f_calc_gradients.set_selected(isel_zero, 0j) a = flex.real(f_calc) b = flex.imag(f_calc) aa, bb, ab = a*a, b*b, a*b haa = O.c * aa + O.g * bb / f_calc_abs hbb = O.c * bb + O.g * aa / f_calc_abs hab = (O.c - O.g / f_calc_abs) * a * b O.f_calc_hessians = flex.vec3_double(haa, hbb, hab) / fca_sq O.f_calc_hessians.set_selected(isel_zero, (0,0,0))
def build_image(self, nm, cnm): print nm, cnm self.z2dg.load_coefs(nm, cnm) f = flex.real(self.z2dg.f()) f.reshape(flex.grid(self.np, self.np)) return f
def tst_2d_zernike_mom(n,l, N=100, filename=None): nmax = max(20,n) rebuilt=open('rebuilt.dat','w') tt1=time.time() if(filename is not None): image=read_data(filename) else: image=generate_image(n,l) NP=int(math.sqrt( image.size() )) N=NP/2 grid_2d = scitbx.math.two_d_grid(N, nmax) grid_2d.clean_space( image ) grid_2d.construct_space_sum() tt2=time.time() print("time used: ", tt2-tt1) zernike_2d_mom = scitbx.math.two_d_zernike_moments( grid_2d, nmax ) moments = zernike_2d_mom.moments() tt2=time.time() print("time used: ", tt2-tt1) coefs = flex.real( moments ) nl_array = scitbx.math.nl_array( nmax ) nls = nl_array.nl() nl_array.load_coefs( nls, coefs ) lfg = scitbx.math.log_factorial_generator(nmax) print(nl_array.get_coef(n,l)*2) for nl, c in zip( nls, moments): if(abs(c)<1e-3): c=0 print(nl, c) print() reconst=flex.complex_double(NP**2, 0) for nl,c in zip( nls, moments): n=nl[0] l=nl[1] if(l>0): c=c*2 #rzfa = scitbx.math.zernike_2d_radial(n,l,lfg) rap = scitbx.math.zernike_2d_polynome(n,l) #,rzfa) i=0 for x in range(0,NP): x=x-N for y in range(0,NP): y=y-N rr = math.sqrt(x*x+y*y)/N if rr>1.0: value=0.0 else: tt = math.atan2(y,x) value = rap.f(rr,tt) reconst[i]=reconst[i]+value*c i=i+1 i = 0 for x in range(0,NP): for y in range(0,NP): value=reconst[i].real if(value>0): print(x,y,image[i][2],value, file=rebuilt) i=i+1 rebuilt.close()
def tst_img_gen(): nmax = 20 ft = fast_tic(nmax) tzim = triple_zernike_integral_manager(nmax, ft.ennnm) print "(0,0)", tzim.get_integral(0, 4, 4, 0) print "(2,0)", tzim.get_integral(2, 4, 4, 0) print "(4,0)", tzim.get_integral(4, 4, 4, 0) * 5 print "(6,0)", tzim.get_integral(4, 4, 6, 0) print "(8,0)", tzim.get_integral(4, 4, 8, 0) * 9 print "(10,0)", tzim.get_integral(4, 4, 10, 0) #tzim = triple_zernike_integral_manager(5,num_int_triple_int) print "Building ball" import basic_shapes rod = basic_shapes.ball(261, nmax) ig = image_generator(rod, nmax) print "Buiding IG" nm, cnm = ig.get_coefs(rod) # test single coefficient this_nm = (4, 0) cnm = cnm * 0.0 for iii, nnn in enumerate(nm): if nnn[0] == this_nm[0]: if nnn[1] == this_nm[1]: cnm[iii] = 1.0 f = ig.build_image(nm, cnm) import zernike_phaser io = zernike_phaser.integration_object(261) #c2 = io.build_c2_function( f ) c2 = f * f zernike_phaser.write_generic_image(c2, "sp_c2.dat") zernike_phaser.write_generic_image(f, "sp.dat") nm, cnm = ig.get_coefs(c2) for n, nn in zip(nm, cnm): if (abs(nn) > 1e-6): print n, nn #*130**2.0 g = ig.build_image(nm, cnm) cnm = cnm * 0.0 for iii, nnn in enumerate(nm): if (nnn[1] == 0): if nnn[0] == 0: cnm[iii] = 0.1 if (nnn[0] == 4): cnm[iii] = 0.02857 * 5.0 if (nnn[0] == 8): cnm[iii] = 0.02857 * 9.0 zernike_phaser.write_generic_image(g, "sp_c2_r.dat") return nm, nnm = ig.get_coefs(f) g = ig.build_image(nm, nnm) h = generate_image(10, cnm, 100) h = flex.double(flex.real(h)) h.reshape(flex.grid(201, 201)) for c, i, j in zip(nm, cnm, nnm): print "#", c, i, j for ii in range(ig.np): for jj in range(ig.np): print ii, jj, f[(ii, jj)], g[(ii, jj)], h[(ii, jj)] print return #moms = ig.get_coefs( rod ) f = ig.build_image(nm, cnm) for ii in range(ig.np): for jj in range(ig.np): print ii, jj, rod[(ii, jj)], f[(ii, jj)] print return
def tst_image(n, N=100, filename=None): nmax = n nmax0 = 8 nl_array0 = math.nl_array(nmax0) nls0 = nl_array0.nl() nl_array = math.nl_array(nmax) nls = nl_array.nl() if (filename is not None): image = read_data(filename) else: moments = flex.random_double(nls0.size()) # moments=flex.double(nls.size(),0 ) # moments[3] = 1.0 # moments[7] = 1.0 image = generate_image(n, moments) orig = open('original.dat', 'w') for pt in image: print >> orig, pt[0], pt[1], pt[2] orig.close() Nq = 100 Nphi = 100 c2_image = from_I_to_C2(nmax, image, Nq, Nphi) c2_output = open('c2.dat', 'w') for pt in c2_image: print >> c2_output, pt[0], pt[1], pt[2] c2_output.close() coef_table = calc_integral_triple_zernike2d(nmax) moments[0] = 0 new_mom = moments.concatenate(flex.double(nls.size() - nls0.size(), 0)) nmax4c2 = 2 * nmax Inm = math.nl_c_array(nmax4c2) Inm.load_coefs(nls, new_mom) cnm = calc_Cnm_from_Inm(Inm, coef_table, nmax4c2) cnm_coef = cnm.coefs() print "#cnm[0]", cnm_coef[0] # cnm_coef[0]=0 ### calculate 2d zernike moments for C2_image ### image = c2_image NP = int(smath.sqrt(image.size())) N = NP / 2 grid_2d = math.two_d_grid(N, nmax) grid_2d.clean_space(image) grid_2d.construct_space_sum() zernike_2d_mom = math.two_d_zernike_moments(grid_2d, nmax) c2_moments = zernike_2d_mom.moments() #coefs = flex.real( c2_moments ) #cnm_coef = flex.real( c2_moments ) cnm_coef = c2_moments c2_reconst = generate_image2(n, cnm_coef, c2_image, Nq) c2_r = open('c2r.dat', 'w') for pt in c2_reconst: print >> c2_r, pt[0], pt[1], pt[2] c2_r.close() ls_score = 0 np_tot = c2_image.size() for p1, p2 in zip(c2_image, c2_reconst): ls_score += (p1[2] - p2[2])**2.0 print nmax, nls.size(), ls_score, np_tot * smath.log( ls_score / np_tot), "SUM" for nl, c2m in zip(nls, cnm_coef): print nl, c2m exit() # ### calculate 2d zernike moments for C2_image ### image = c2_image NP = int(smath.sqrt(image.size())) N = NP / 2 grid_2d = math.two_d_grid(N, nmax) grid_2d.clean_space(image) grid_2d.construct_space_sum() tt2 = time.time() zernike_2d_mom = math.two_d_zernike_moments(grid_2d, nmax) c2_moments = zernike_2d_mom.moments() #coefs = flex.real( c2_moments ) coefs = (c2_moments) for nl, c2m, c2mm in zip(nls, cnm_coef, coefs): if (nl[0] / 2 * 2 == nl[0]): print c2m, c2mm coefs = flex.real(moments) nl_array.load_coefs(nls, coefs) for nl, c in zip(nls, moments): if (abs(c) < 1e-3): c = 0 print nl, c print reconst = flex.complex_double(NP**2, 0) for nl, c in zip(nls, moments): n = nl[0] l = nl[1] if (l > 0): c = c * 2.0 rap = math.zernike_2d_polynome(n, l) i = 0 for x in range(0, NP): x = x - N for y in range(0, NP): y = y - N rr = smath.sqrt(x * x + y * y) / N if rr > 1.0: value = 0.0 else: tt = smath.atan2(y, x) value = rap.f(rr, tt) reconst[i] = reconst[i] + value * c i = i + 1 rebuilt = open('rebuilt.dat', 'w') i = 0 for x in range(0, NP): for y in range(0, NP): value = reconst[i].real print >> rebuilt, x, y, image[i][2], value i = i + 1 rebuilt.close()
def tst_2d_zernike_mom(n,l, N=100, filename=None): nmax = max(20,n) rebuilt=open('rebuilt.dat','w') tt1=time.time() if(filename is not None): image=read_data(filename) else: image=generate_image(n,l) NP=int(smath.sqrt( image.size() )) N=NP/2 grid_2d = math.two_d_grid(N, nmax) grid_2d.clean_space( image ) grid_2d.construct_space_sum() tt2=time.time() print "time used: ", tt2-tt1 zernike_2d_mom = math.two_d_zernike_moments( grid_2d, nmax ) moments = zernike_2d_mom.moments() tt2=time.time() print "time used: ", tt2-tt1 coefs = flex.real( moments ) nl_array = math.nl_array( nmax ) nls = nl_array.nl() nl_array.load_coefs( nls, coefs ) lfg = math.log_factorial_generator(nmax) print nl_array.get_coef(n,l)*2 for nl, c in zip( nls, moments): if(abs(c)<1e-3): c=0 print nl, c print reconst=flex.complex_double(NP**2, 0) for nl,c in zip( nls, moments): n=nl[0] l=nl[1] if(l>0): c=c*2 #rzfa = math.zernike_2d_radial(n,l,lfg) rap = math.zernike_2d_polynome(n,l) #,rzfa) i=0 for x in range(0,NP): x=x-N for y in range(0,NP): y=y-N rr = smath.sqrt(x*x+y*y)/N if rr>1.0: value=0.0 else: tt = smath.atan2(y,x) value = rap.f(rr,tt) reconst[i]=reconst[i]+value*c i=i+1 i = 0 for x in range(0,NP): for y in range(0,NP): value=reconst[i].real if(value>0): print>>rebuilt, x,y,image[i][2],value i=i+1 rebuilt.close()
def lewis(template, img): """The lewis() function computes the normalised cross-correlation (NCC) of an image, @p img, and a template, @p template. Both image and template must be two-dimensional, real, and finite. The image must be larger than the template, which in turn should contain more than one pixel, and the template must have positive variance. The function returns the correlation coefficients in the range [-1, +1]. See Lewis, J. P. (1995) "Fast Template Matching", Vision Interface, 120-123. @note This function should be equivalent to MATLAB's normxcorr2() function. @param img Two-dimensional intensity image @param template Two-dimensional intensity template @return Correlation coefficients """ import math import numpy from sys import float_info from scitbx import fftpack from scitbx.array_family import flex # Assert that image and template are two-dimensional arrays, and # that the template is no larger than image. Assert that template # is not flat. XXX Check for real and finite, too? assert len(img.focus()) == 2 and len(template.focus()) == 2 assert img.focus()[0] >= template.focus()[0] and img.focus()[1] >= template.focus()[1] assert template.sample_standard_deviation() > 0 # For conformance with MATLAB's normxcorr2() and geck 342320: for # numerical robustness, ensure that both image and template are # always non-negative. img_nn = img - min(0, flex.min(img)) template_nn = template - min(0, flex.min(template)) # Calculate the terms of the denominator of gamma. Must guard # against negative variance of the image due to inaccuracies in the # one-pass formula. img_sum = _summed_area_table(img_nn, template_nn.focus()[0], template_nn.focus()[1]) img_ssq = _summed_area_table(flex.pow2(img_nn), template_nn.focus()[0], template_nn.focus()[1]) f_sigma = img_ssq - img_sum * img_sum / (template_nn.focus()[0] * template_nn.focus()[1]) f_sigma.set_selected(f_sigma < 0, 0) f_sigma = flex.sqrt(f_sigma) t_sigma = (template_nn - flex.mean(template_nn)).norm() gamma_denominator = f_sigma * t_sigma # Zero-pad the image to permit partial overlap of template and # image, and embed the time-reversed template in a zero-padded array # of the same size. Zero-padding means the entire template is # always overlapping the image, and terms involving the template # mean cancel in the expansion of the numerator of gamma. # # Note: the NCC demands the template to be time-reversed, which can # be accomplished by conjugation in the frequency domain. An # implementation following that approach would however require # special care to be taken for the first rows and columns: # # from numpy import roll # t_embed.matrix_paste_block_in_place( # block=template_nn, # i_row=full[0] - template_nn.focus()[0], # i_column=full[1] - template_nn.focus()[1]) # t_embed = flex.double(roll( # roll(t_embed.as_numpy_array(), 1, axis=0), 1, axis=1)) # # Calculate correlation in frequency domain. XXX Could use spatial # domain calculation in cases where it's faster (see MATLAB's # implementation). full = (img_nn.focus()[0] + template_nn.focus()[0] - 1, img_nn.focus()[1] + template_nn.focus()[1] - 1) f_embed = flex.double(flex.grid(full)) f_embed.matrix_paste_block_in_place(block=img_nn, i_row=0, i_column=0) f_prime = flex.complex_double(reals=f_embed, imags=flex.double(flex.grid(full))) t_embed = flex.double(flex.grid(full)) t_embed.matrix_paste_block_in_place(block=template_nn.matrix_rot90(2), i_row=0, i_column=0) t_prime = flex.complex_double(reals=t_embed, imags=flex.double(flex.grid(full))) fft = fftpack.complex_to_complex_2d(full) fft.forward(f_prime) fft.forward(t_prime) gamma_numerator = f_prime * t_prime fft.backward(gamma_numerator) gamma_numerator = flex.real(gamma_numerator) / (fft.n()[0] * fft.n()[1]) - img_sum * flex.mean(template_nn) # For conformance with MATLAB: set the NCC to zero in regions where # the image has zero variance over the extent of the template. If, # due to small variances in the image or the template, a correlation # coefficient falls outside the range [-1, 1], set it to zero to # reflect the undefined 0/0 condition. tol = math.sqrt(math.ldexp(float_info.epsilon, math.frexp(flex.max(flex.abs(gamma_denominator)))[1] - 1)) sel = gamma_denominator <= tol gamma = gamma_numerator.set_selected(sel, 0) / gamma_denominator.set_selected(sel, 1) gamma.set_selected(flex.abs(gamma) > 1 + math.sqrt(float_info.epsilon), 0) return gamma