def generate_predictions(self, experiment, reflections, parameters): # Create the mosaicity model parameterisation = MosaicityParameterisation(parameters) # The crystal A and beam s0 A = matrix.sqr(experiment.crystal.get_A()) s0 = matrix.col(experiment.beam.get_s0()) s0_length = s0.length() # Compute all the vectors s1_cal = flex.vec3_double() s2_cal = flex.vec3_double() for i in range(len(reflections)): # Compute the reciprocal lattice vector h = matrix.col(reflections[i]["miller_index"]) r = A * h s2 = s0 + r # Rotate the covariance matrix R = compute_change_of_basis_operation(s0, s2) S = R * parameterisation.sigma() * R.transpose() mu = R * s2 assert abs(1 - mu.normalize().dot(matrix.col((0, 0, 1)))) < 1e-7 # Partition the mean vector mu1 = matrix.col((mu[0], mu[1])) mu2 = mu[2] # Partition the covariance matrix S11 = matrix.sqr((S[0], S[1], S[3], S[4])) S12 = matrix.col((S[2], S[5])) S21 = matrix.col((S[6], S[7])).transpose() S22 = S[8] # Compute the conditional mean mubar = mu1 + S12 * (1 / S22) * (s0_length - mu2) # Compute the vector and rotate v = matrix.col( (mubar[0], mubar[1], s0_length)).normalize() * s0_length s1 = R.transpose() * v # Append the 2 vectors s1_cal.append(s1) s2_cal.append(s2) # Return the predicted vectors return s1_cal, s2_cal
def compute_mean_plane(mu, sigma, s0): z = matrix.col((0, 0, 1)) R = compute_change_of_basis_operation(s0, mu) sigma_1 = R * sigma * R.transpose() mu_1 = R * mu assert abs(1 - mu_1.normalize().dot(z)) < 1e-7 sigma_11 = matrix.sqr((sigma_1[0], sigma_1[1], sigma_1[3], sigma_1[4])) sigma_12 = matrix.col((sigma_1[2], sigma_1[5])) sigma_21 = matrix.col((sigma_1[3], sigma_1[7])).transpose() sigma_22 = sigma_1[8] mu1 = matrix.col((mu_1[0], mu_1[1])) mu2 = mu_1[2] mu_new_1 = mu1 + sigma_12 * (1 / sigma_22) * (s0.length() - mu2) v = matrix.col((mu_new_1[0], mu_new_1[1], s0.length())).normalize() * s0.length() x_new = R.transpose() * v return x_new
def _compute_partiality(self): s0 = matrix.col(self.experiments[0].beam.get_s0()) partiality = flex.double(len(self.reflections)) for k in range(len(self.reflections)): s1 = matrix.col(self.reflections[k]["s1"]) s2 = matrix.col(self.reflections[k]["s2"]) sbox = self.reflections[k]["shoebox"] sigma = MosaicityParameterisation(self._profile_parameters).sigma() R = compute_change_of_basis_operation(s0, s2) S = R * sigma * R.transpose() mu = R * s2 assert abs(1 - mu.normalize().dot(matrix.col((0, 0, 1)))) < 1e-7 S11 = matrix.sqr((S[0], S[1], S[3], S[4])) S12 = matrix.col((S[2], S[5])) S21 = matrix.col((S[6], S[7])).transpose() S22 = S[8] mu1 = matrix.col((mu[0], mu[1])) mu2 = mu[2] partiality[k] = exp(-0.5 * (s0.length() - mu2) * (1 / S22) * (s0.length() - mu2)) self.reflections["partiality"] = partiality
def generate_from_reflections(s0, sigma, reflections): """ Generate a list of normally distributed observations """ s2_list = [] ctot_list = [] xbar_list = [] Sobs_list = [] # Loop through the list for k in range(len(reflections)): # Compute position in reciprocal space of the centre of the rlp s2 = matrix.col(reflections["s2"][k]) # Rotate the covariance matrix R = compute_change_of_basis_operation(s0, s2) sigmap = R * sigma * R.transpose() # Rotate to get mu mu = R * s2 assert abs(mu.normalize().dot(matrix.col((0, 0, 1))) - 1) < 1e-7 # Partition the matrix sigma11 = matrix.sqr((sigmap[0], sigmap[1], sigmap[3], sigmap[4])) sigma12 = matrix.col((sigmap[2], sigmap[5])) sigma21 = matrix.col((sigmap[6], sigmap[7])).transpose() sigma22 = sigmap[8] # Compute the conditional distribution mu1 = matrix.col((mu[0], mu[1])) mu2 = mu[2] z = s0.length() sigma_bar = sigma11 - sigma12 * (1 / sigma22) * sigma21 mu_bar = mu1 + sigma12 * (z - mu2) / sigma22 P = exp(-0.5 * (z - mu2) ** 2 / sigma22) R = uniform(0, 1.0) print(k, P, R) if P < R: continue # Compute the scale factor and intensity scale = exp(-0.5 * (z - mu2) ** 2 / sigma22) # I = (z-mu2)**2 * 100#uniform(100,10000)#poisson(scale * uniform(100,1000)) I = uniform(50, 1000) if I <= 1: continue # Simulate some observations # a = 7.5 # b = 15.0 / (12*sqrt(sigma_bar[0])) # c = 15.0 / (12*sqrt(sigma_bar[3])) # D = flex.double(flex.grid(15,15)) points = multivariate_normal(mu_bar, sigma_bar.as_list_of_lists(), int(I)) # for x, y in points: # i = int(a + b*x) # j = int(a + c*y) # if j >= 0 and j < D.all()[0] and i >= 0 and i < D.all()[1]: # D[j,i] += 1 # Compute the observed mean for each observation ctot = 0 xbar = matrix.col((0, 0)) for x in points: xbar += matrix.col(x) ctot = len(points) xbar /= ctot # Compute the observed covariance for each observation Sobs = matrix.sqr((0, 0, 0, 0)) for x in points: x = matrix.col(x) Sobs += (x - xbar) * (x - xbar).transpose() # # Compute the observed mean for each observation # ctot = 0 # xbar = matrix.col((0, 0)) # for j in range(D.all()[0]): # for i in range(D.all()[1]): # ctot += D[j,i] # x = matrix.col(( # (i+0.5-a)/b, # (j+0.5-a)/c)) # xbar += x*D[j,i] # if ctot <= 0: # continue # xbar /= ctot # # Compute the observed covariance for each observation # Sobs = matrix.sqr((0, 0, 0, 0)) # for j in range(D.all()[0]): # for i in range(D.all()[1]): # x = matrix.col(( # (i+0.5-a)/b, # (j+0.5-a)/c)) # Sobs += (x-xbar)*(x-xbar).transpose()*D[j,i] s2_list.append(s2) ctot_list.append(ctot) xbar_list.append(xbar) Sobs_list.append(list(Sobs)) return s2_list, ctot_list, xbar_list, Sobs_list
def generate_simple_binned(s0, sigma, N=100): """ Generate a list of normally distributed observations """ s2_list = [] ctot_list = [] xbar_list = [] Sobs_list = [] # Loop through the list for k in range(N): # Compute position in reciprocal space of the centre of the rlp s2_direction = matrix.col( (uniform(0, 1), uniform(0, 1), uniform(0, 1)) ).normalize() # Rotate the covariance matrix R = compute_change_of_basis_operation(s0, s2_direction) sigmap = R * sigma * R.transpose() s2_magnitude = normal(s0.length(), sqrt(sigmap[8])) s2 = s2_direction * s2_magnitude # Rotate to get mu mu = R * s2 assert abs(mu.normalize().dot(matrix.col((0, 0, 1))) - 1) < 1e-7 # Partition the matrix sigma11 = matrix.sqr((sigmap[0], sigmap[1], sigmap[3], sigmap[4])) sigma12 = matrix.col((sigmap[2], sigmap[5])) sigma21 = matrix.col((sigmap[6], sigmap[7])).transpose() sigma22 = sigmap[8] # Compute the conditional distribution mu1 = matrix.col((mu[0], mu[1])) mu2 = mu[2] z = s0.length() sigma_bar = sigma11 - sigma12 * (1 / sigma22) * sigma21 mu_bar = mu1 + sigma12 * (z - mu2) / sigma22 # Compute the scale factor and intensity scale = exp(-0.5 * (z - mu2) ** 2 / sigma22) I = uniform(50, 1000) if I <= 1: continue # Simulate some observations a = 7.5 b = 15.0 / (12 * sqrt(sigma_bar[0])) c = 15.0 / (12 * sqrt(sigma_bar[3])) D = flex.double(flex.grid(15, 15)) points = multivariate_normal(mu_bar, sigma_bar.as_list_of_lists(), int(I)) for x, y in points: i = int(a + b * x) j = int(a + c * y) if j >= 0 and j < D.all()[0] and i >= 0 and i < D.all()[1]: D[j, i] += 1 # Compute the observed mean for each observation ctot = 0 xbar = matrix.col((0, 0)) for j in range(D.all()[0]): for i in range(D.all()[1]): ctot += D[j, i] x = matrix.col(((i + 0.5 - a) / b, (j + 0.5 - a) / c)) xbar += x * D[j, i] if ctot <= 0: continue xbar /= ctot # Compute the observed covariance for each observation Sobs = matrix.sqr((0, 0, 0, 0)) for j in range(D.all()[0]): for i in range(D.all()[1]): x = matrix.col(((i + 0.5 - a) / b, (j + 0.5 - a) / c)) Sobs += (x - xbar) * (x - xbar).transpose() * D[j, i] Sobs /= ctot s2_list.append(s2) ctot_list.append(ctot) xbar_list.append(xbar) Sobs_list.append(list(Sobs)) return s2_list, ctot_list, xbar_list, Sobs_list
def generate_with_wavelength_spread2( D, s0, spot_covariance, wavelength_variance, N=100 ): """ Generate a list of normally distributed observations """ s2_list = [] ctot_list = [] xbar_list = [] Sobs_list = [] D_inv = D.inverse() # Loop through the list for k in range(N): # Compute position in reciprocal space of the centre of the rlp s2_direction = matrix.col( (uniform(0, 1), uniform(0, 1), uniform(1, 1)) ).normalize() # Compute the local spread in energy q0 = s2_direction.normalize() * s0.length() - s0 wavelength_variance_local = wavelength_variance * (q0.dot(q0) / 2) ** 2 # Rotate the covariance matrix R = compute_change_of_basis_operation(s0, s2_direction) sigmap = R * spot_covariance * R.transpose() sigma_spread = sigmap[8] + wavelength_variance_local s2_magnitude = normal(s0.length(), sqrt(sigma_spread)) # s2_magnitude = normal(s0.length(), sqrt(sigmap[8])) s2 = s2_direction * s2_magnitude resolution = 1.0 / (2.0 * s0.length() * sin(0.5 * s0.angle(s2))) # print resolution # Rotate to get mu mu = R * s2 assert abs(mu.normalize().dot(matrix.col((0, 0, 1))) - 1) < 1e-7 # Partition matrix S11 = matrix.sqr((sigmap[0], sigmap[1], sigmap[3], sigmap[4])) S12 = matrix.col((sigmap[2], sigmap[5])) S21 = matrix.col((sigmap[6], sigmap[7])).transpose() S22 = sigmap[8] # Apply the wavelength spread to the sigma Sp_22 = S22 * wavelength_variance_local / (S22 + wavelength_variance_local) Sp_12 = S12 * Sp_22 / S22 Sp_11 = S11 - (S12 * (1 / S22) * S21) * (1 - Sp_22 / S22) Sigma3 = matrix.sqr( ( Sp_11[0], Sp_11[1], Sp_12[0], Sp_11[2], Sp_11[3], Sp_12[1], Sp_12[0], Sp_12[1], Sp_22, ) ) # Apply the wavelength spread to the mean mu1 = mu mu2 = matrix.col((0, 0, s0.length())) z0 = (mu1[2] * wavelength_variance_local + mu2[2] * S22) / ( S22 + wavelength_variance_local ) x0 = matrix.col((mu1[0], mu1[1])) + S12 * (1 / S22) * (z0 - mu1[2]) mu3 = matrix.col((x0[0], x0[1], z0)) # Apply the wavelength spread to the sigma # Sigma1_inv = sigmap.inverse() # Sigma2_inv = matrix.sqr(( # 0, 0, 0, # 0, 0, 0, # 0, 0, 1/wavelength_variance_local)) # Sigma3_inv = Sigma1_inv + Sigma2_inv # Sigma3 = Sigma3_inv.inverse() # # Apply the wavelength spread to the mean # mu1 = mu # mu2 = matrix.col((0, 0, s0.length())) # mu3 = Sigma3*(Sigma1_inv*mu1 + Sigma2_inv*mu2) # Rotate the sigma and mean vector back Sigma3 = R.transpose() * Sigma3 * R s3 = R.transpose() * mu3 q3 = s3 - s0 # Compute the scale factor and intensity I = uniform(50, 1000) if I <= 1: continue # Simulate some observations points = multivariate_normal(q3, Sigma3.as_list_of_lists(), int(I)) X = [] Y = [] # Generate points for p in points: p = matrix.col(p) # Compute wavelength and diffracting vector for point wavelength = -2.0 * s0.normalize().dot(p) / (p.dot(p)) s0w = s0.normalize() / wavelength s1w = s0w + p assert abs(s1w.length() - s0w.length()) < 1e-10 # Do the ray projection onto the detector v = D * s1w assert v[2] > 0 x = v[0] / v[2] y = v[1] / v[2] X.append(x) Y.append(y) # Compute observed mean on detector xmean = sum(X) / len(X) ymean = sum(Y) / len(Y) # Map onto coordinate system and compute mean ctot = len(X) xbar = matrix.col((0, 0)) # cs = CoordinateSystem2d(s0, s2) for x, y in zip(X, Y): s = (D_inv * matrix.col((x, y, 1))).normalize() * s0.length() e = R * (s - s2.normalize() * s0.length()) e1, e2 = e[0], e[1] # e1, e2 = cs.from_beam_vector(s) xbar += matrix.col((e1, e2)) xbar /= ctot # Compute variance Sobs = matrix.sqr((0, 0, 0, 0)) for x, y in zip(X, Y): s = (D_inv * matrix.col((x, y, 1))).normalize() * s0.length() e = R * (s - s2.normalize() * s0.length()) e1, e2 = e[0], e[1] # e1, e2 = cs.from_beam_vector(s) x = matrix.col((e1, e2)) Sobs += (x - xbar) * (x - xbar).transpose() Sobs /= ctot # print tuple(xbar), tuple(Sobs) s2_list.append(s2) ctot_list.append(ctot) xbar_list.append(xbar) Sobs_list.append(list(Sobs)) return s2_list, ctot_list, xbar_list, Sobs_list
def generate_with_wavelength_spread(s0, sigma_spot, sigma_wavelength, N=100): """ Generate a list of normally distributed observations """ s2_list = [] ctot_list = [] xbar_list = [] Sobs_list = [] # Loop through the list for k in range(N): # Compute position in reciprocal space of the centre of the rlp s2_direction = matrix.col( (uniform(0, 1), uniform(0, 1), uniform(0, 1)) ).normalize() # Compute the local spread in energy q0 = s2_direction.normalize() * s0.length() - s0 sigma_wavelength_local = sqrt(sigma_wavelength) * q0.dot(q0) / 2 # Rotate the covariance matrix R = compute_change_of_basis_operation(s0, s2_direction) sigmap = R * sigma_spot * R.transpose() s2_magnitude = normal( s0.length(), sqrt(sigmap[8] + sigma_wavelength_local ** 2) ) # s2_magnitude = normal(s0.length(), sqrt(sigmap[8])) s2 = s2_direction * s2_magnitude # Rotate to get mu mu = R * s2 assert abs(mu.normalize().dot(matrix.col((0, 0, 1))) - 1) < 1e-7 # Apply the wavelength spread to the sigma Sigma1_inv = sigmap.inverse() Sigma2_inv = matrix.sqr( (0, 0, 0, 0, 0, 0, 0, 0, 1 / sigma_wavelength_local ** 2) ) Sigma3_inv = Sigma1_inv + Sigma2_inv Sigma3 = Sigma3_inv.inverse() # Apply the wavelength spread to the mean mu1 = mu mu2 = matrix.col((0, 0, s0.length())) mu3 = Sigma3 * (Sigma1_inv * mu1 + Sigma2_inv * mu2) # Marginal sigma and mean Sigma_marginal = matrix.sqr((Sigma3[0], Sigma3[1], Sigma3[3], Sigma3[4])) mu_marginal = matrix.col((mu3[0], mu3[1])) # Compute the scale factor and intensity I = uniform(50, 1000) if I <= 1: continue # # Simulate some observations # points = multivariate_normal(mu_bar, sigma_bar.as_list_of_lists(), int(I)) # # Compute the observed mean for each observation # ctot = 0 # xbar = matrix.col((0, 0)) # for x in points: # xbar += matrix.col(x) # ctot = len(points) # xbar /= ctot # # Compute the observed covariance for each observation # Sobs = matrix.sqr((0, 0, 0, 0)) # for x in points: # x = matrix.col(x) # Sobs += (x-xbar)*(x-xbar).transpose() # Sobs /= ctot ctot = I xbar = mu_marginal Sobs = Sigma_marginal s2_list.append(s2) ctot_list.append(ctot) xbar_list.append(xbar) Sobs_list.append(list(Sobs)) return s2_list, ctot_list, xbar_list, Sobs_list
def generate_from_reflections2(A, s0, sigma, reflections): """ Generate a list of normally distributed observations """ sp_list = [] h_list = [] ctot_list = [] xbar_list = [] Sobs_list = [] # Loop through the list for k in range(len(reflections)): # Compute position in reciprocal space of the centre of the rlp h = matrix.col(reflections["miller_index"][k]) r = matrix.sqr(A) * h s2 = s0 + r sp = s2 # Rotate the covariance matrix R = compute_change_of_basis_operation(s0, sp) sigmap = R * sigma * R.transpose() # Rotate to get mu mu = R * s2 assert abs(mu.normalize().dot(matrix.col((0, 0, 1))) - 1) < 1e-7 # Partition the matrix sigma11 = matrix.sqr((sigmap[0], sigmap[1], sigmap[3], sigmap[4])) sigma12 = matrix.col((sigmap[2], sigmap[5])) sigma21 = matrix.col((sigmap[6], sigmap[7])).transpose() sigma22 = sigmap[8] # Compute the conditional distribution mu1 = matrix.col((mu[0], mu[1])) mu2 = mu[2] z = s0.length() sigma_bar = sigma11 - sigma12 * (1 / sigma22) * sigma21 mu_bar = mu1 + sigma12 * (z - mu2) / sigma22 # Perform rejection sampling to get a normally distributed set of # reflections P = exp(-0.5 * (z - mu2) ** 2 / sigma22) R = uniform(0, 1.0) if P < R: continue # Compute the scale factor and intensity scale = exp(-0.5 * (z - mu2) ** 2 / sigma22) I = uniform(50, 1000) if I <= 1: continue # Simulate some observations points = multivariate_normal(mu_bar, sigma_bar.as_list_of_lists(), int(I)) # Compute the observed mean for each observation ctot = 0 xbar = matrix.col((0, 0)) for x in points: xbar += matrix.col(x) ctot = len(points) xbar /= ctot # Compute the observed covariance for each observation Sobs = matrix.sqr((0, 0, 0, 0)) for x in points: x = matrix.col(x) Sobs += (x - xbar) * (x - xbar).transpose() Sobs /= ctot sp_list.append(sp) h_list.append(h) ctot_list.append(ctot) xbar_list.append(xbar) Sobs_list.append(list(Sobs)) return sp_list, h_list, ctot_list, xbar_list, Sobs_list
def generate_simple(s0, sigma, N=100): """ Generate a list of normally distributed observations """ s2_list = [] ctot_list = [] xbar_list = [] Sobs_list = [] # Loop through the list for k in range(N): # Compute position in reciprocal space of the centre of the rlp s2_direction = matrix.col( (uniform(0, 1), uniform(0, 1), uniform(0, 1)) ).normalize() # Rotate the covariance matrix R = compute_change_of_basis_operation(s0, s2_direction) sigmap = R * sigma * R.transpose() s2_magnitude = normal(s0.length(), sqrt(sigmap[8])) s2 = s2_direction * s2_magnitude # Rotate to get mu mu = R * s2 assert abs(mu.normalize().dot(matrix.col((0, 0, 1))) - 1) < 1e-7 # Partition the matrix sigma11 = matrix.sqr((sigmap[0], sigmap[1], sigmap[3], sigmap[4])) sigma12 = matrix.col((sigmap[2], sigmap[5])) sigma21 = matrix.col((sigmap[6], sigmap[7])).transpose() sigma22 = sigmap[8] # Compute the conditional distribution mu1 = matrix.col((mu[0], mu[1])) mu2 = mu[2] z = s0.length() sigma_bar = sigma11 - sigma12 * (1 / sigma22) * sigma21 mu_bar = mu1 + sigma12 * (z - mu2) / sigma22 # Compute the scale factor and intensity scale = exp(-0.5 * (z - mu2) ** 2 / sigma22) I = uniform(50, 1000) if I <= 1: continue # Simulate some observations points = multivariate_normal(mu_bar, sigma_bar.as_list_of_lists(), int(I)) # Compute the observed mean for each observation ctot = 0 xbar = matrix.col((0, 0)) for x in points: xbar += matrix.col(x) ctot = len(points) xbar /= ctot # Compute the observed covariance for each observation Sobs = matrix.sqr((0, 0, 0, 0)) for x in points: x = matrix.col(x) Sobs += (x - xbar) * (x - xbar).transpose() Sobs /= ctot s2_list.append(s2) ctot_list.append(ctot) xbar_list.append(xbar) Sobs_list.append(list(Sobs)) return s2_list, ctot_list, xbar_list, Sobs_list
def __init__(self, experiment, parameters, dmin=None): print("") print("Predicting reflections") # Set a resolution range if dmin is None: s0 = experiment.beam.get_s0() dmin = experiment.detector.get_max_resolution(s0) # Create the index generator index_generator = IndexGenerator( experiment.crystal.get_unit_cell(), experiment.crystal.get_space_group().type(), dmin, ) # Get an array of miller indices miller_indices_to_test = index_generator.to_array() print("Generated %d miller indices" % len(miller_indices_to_test)) # Get the covariance matrix sigma = MosaicityParameterisation(parameters).sigma() sigma_inv = sigma.inverse() # Compute quantile quantile = chisq_quantile(3, 0.997) # Get stuff from experiment A = matrix.sqr(experiment.crystal.get_A()) s0 = matrix.col(experiment.beam.get_s0()) # Loop through miller indices and check each is in range print( "Checking reflections against MVN quantile %f with Mahalabonis distance %f" % (0.997, sqrt(quantile))) panel = experiment.detector[0] miller_indices = flex.miller_index() entering = flex.bool() s1_list = flex.vec3_double() s2_list = flex.vec3_double() xyzcalpx = flex.vec3_double() xyzcalmm = flex.vec3_double() panel_list = flex.size_t() for h in miller_indices_to_test: r = A * h s2 = s0 + r s3 = s2.normalize() * s0.length() d = ((s3 - s2).transpose() * sigma_inv * (s3 - s2))[0] if d < quantile: e = s2.length() < s0.length() R = compute_change_of_basis_operation(s0, s2) S = R * sigma * R.transpose() mu = R * s2 assert abs(1 - mu.normalize().dot(matrix.col((0, 0, 1)))) < 1e-7 S11 = matrix.sqr((S[0], S[1], S[3], S[4])) S12 = matrix.col((S[2], S[5])) S21 = matrix.col((S[6], S[7])).transpose() S22 = S[8] mu1 = matrix.col((mu[0], mu[1])) mu2 = mu[2] mubar = mu1 + S12 * (1 / S22) * (s0.length() - mu2) v = (matrix.col( (mubar[0], mubar[1], s0.length())).normalize() * s0.length()) s1 = R.transpose() * v try: xymm = panel.get_ray_intersection(s1) except Exception: continue xypx = panel.millimeter_to_pixel(xymm) miller_indices.append(h) entering.append(e) panel_list.append(0) s1_list.append(s1) s2_list.append(s2) xyzcalpx.append((xypx[0], xypx[1], 0)) xyzcalmm.append((xymm[0], xymm[1], 0)) self._reflections = flex.reflection_table() self._reflections["miller_index"] = miller_indices self._reflections["entering"] = entering self._reflections["s1"] = s1_list self._reflections["s2"] = s2_list self._reflections["xyzcal.px"] = xyzcalpx self._reflections["xyzcal.mm"] = xyzcalmm self._reflections["panel"] = panel_list self._reflections["id"] = flex.int(len(self._reflections), 0) print("Predicted %d reflections" % len(self._reflections))
def compute(self, reflections): print("Computing mask for %d reflections" % len(reflections)) # Compute quantile quantile = chisq_quantile(2, 0.997) D = quantile panel = self.experiment.detector[0] print("ML: %f" % sqrt(D)) for k in range(len(reflections)): s1 = matrix.col(reflections[k]["s1"]) s2 = matrix.col(reflections[k]["s2"]) sbox = reflections[k]["shoebox"] s0 = matrix.col(self.experiment.beam.get_s0()) s0_length = s0.length() # Ensure our values are ok assert s1.length() > 0 sigma = MosaicityParameterisation(self.parameters).sigma() R = compute_change_of_basis_operation(s0, s2) S = R * sigma * R.transpose() mu = R * s2 assert abs(1 - mu.normalize().dot(matrix.col((0, 0, 1)))) < 1e-7 S11 = matrix.sqr((S[0], S[1], S[3], S[4])) S12 = matrix.col((S[2], S[5])) S21 = matrix.col((S[6], S[7])).transpose() S22 = S[8] mu1 = matrix.col((mu[0], mu[1])) mu2 = mu[2] mubar = mu1 + S12 * (1 / S22) * (s0.length() - mu2) Sbar = S11 - S12 * (1 / S22) * S21 Sbar_inv = Sbar.inverse() mask = sbox.mask x0, x1, y0, y1, _, _ = sbox.bbox cs = CoordinateSystem2d(s0, s2) for j in range(mask.all()[1]): for i in range(mask.all()[2]): ii = i + x0 jj = j + y0 s1 = panel.get_pixel_lab_coord((ii, jj)) s2 = panel.get_pixel_lab_coord((ii + 1, jj)) s3 = panel.get_pixel_lab_coord((ii, jj + 1)) s4 = panel.get_pixel_lab_coord((ii + 1, jj + 1)) s1 = matrix.col(s1).normalize() * s0_length s2 = matrix.col(s2).normalize() * s0_length s3 = matrix.col(s3).normalize() * s0_length s4 = matrix.col(s4).normalize() * s0_length x1 = matrix.col(cs.from_beam_vector(s1)) x2 = matrix.col(cs.from_beam_vector(s2)) x3 = matrix.col(cs.from_beam_vector(s3)) x4 = matrix.col(cs.from_beam_vector(s4)) d1 = ((x1 - mubar).transpose() * Sbar_inv * (x1 - mubar))[0] d2 = ((x2 - mubar).transpose() * Sbar_inv * (x2 - mubar))[0] d3 = ((x3 - mubar).transpose() * Sbar_inv * (x3 - mubar))[0] d4 = ((x4 - mubar).transpose() * Sbar_inv * (x4 - mubar))[0] if min([d1, d2, d3, d4]) < D: mask[0, j, i] = mask[0, j, i] | MaskCode.Foreground else: mask[0, j, i] = mask[0, j, i] | MaskCode.Background
def compute(self, reflections): print("Computing bbox for %d reflections" % len(reflections)) # Compute quantile quantile = chisq_quantile(2, 0.997) D = sqrt(quantile) * 2 bbox = flex.int6() print("ML: %f" % D) for i in range(len(reflections)): s1 = matrix.col(reflections[i]["s1"]) s2 = matrix.col(reflections[i]["s2"]) s0 = matrix.col(self.experiment.beam.get_s0()) # Ensure our values are ok assert s1.length() > 0 sigma = MosaicityParameterisation(self.parameters).sigma() R = compute_change_of_basis_operation(s0, s2) S = R * sigma * R.transpose() mu = R * s2 assert abs(1 - mu.normalize().dot(matrix.col((0, 0, 1)))) < 1e-7 S11 = matrix.sqr((S[0], S[1], S[3], S[4])) S12 = matrix.col((S[2], S[5])) S21 = matrix.col((S[6], S[7])).transpose() S22 = S[8] mu1 = matrix.col((mu[0], mu[1])) mu2 = mu[2] mubar = mu1 + S12 * (1 / S22) * (s0.length() - mu2) Sbar = S11 - S12 * (1 / S22) * S21 eigen_decomposition = eigensystem.real_symmetric( Sbar.as_flex_double_matrix()) Q = matrix.sqr(eigen_decomposition.vectors()) L = matrix.diag(eigen_decomposition.values()) max_L = max(L) delta = sqrt(max_L) * D p1 = mubar + matrix.col((-delta, -delta)) p2 = mubar + matrix.col((-delta, +delta)) p3 = mubar + matrix.col((+delta, -delta)) p4 = mubar + matrix.col((+delta, +delta)) p1 = matrix.col((p1[0], p1[1], s0.length())).normalize() p2 = matrix.col((p2[0], p2[1], s0.length())).normalize() p3 = matrix.col((p3[0], p3[1], s0.length())).normalize() p4 = matrix.col((p4[0], p4[1], s0.length())).normalize() x1 = R.transpose() * p1 x2 = R.transpose() * p2 x3 = R.transpose() * p3 x4 = R.transpose() * p4 xy1 = self.experiment.detector[0].get_ray_intersection_px(x1) xy2 = self.experiment.detector[0].get_ray_intersection_px(x2) xy3 = self.experiment.detector[0].get_ray_intersection_px(x3) xy4 = self.experiment.detector[0].get_ray_intersection_px(x4) xx = (xy1[0], xy2[0], xy3[0], xy4[0]) yy = (xy1[1], xy2[1], xy3[1], xy4[1]) x0, x1 = int(floor(min(xx))) - 1, int(ceil(max(xx))) + 1 y0, y1 = int(floor(min(yy))) - 1, int(ceil(max(yy))) + 1 assert x1 > x0 assert y1 > y0 bbox.append((x0, x1, y0, y1, 0, 1)) reflections["bbox"] = bbox x0, x1, y0, y1, _, _ = bbox.parts() xsize, ysize = self.experiment.detector[0].get_image_size() selection = (x1 > 0) & (y1 > 0) & (x0 < xsize) & (y0 < ysize) reflections = reflections.select(selection) print("Filtered reflecions with bbox outside image range") print("Kept %d reflections" % len(reflections)) return reflections