def select_best_combo_of(ai,better_than=0.15,candidates=20,basis=15): """Take the first few candidates of ai.combos(). Search for all combos with hkl obs-calc better than a certain fraction limit, then handle absences, and return the best one""" best_combo = None base_likelihood = 0.30 best_likelihood = base_likelihood C = ai.combos(basis) maxtry = min(candidates,len(C)) try_counter = 0 solutions = SolutionTracker() if diagnostic: for x in range(ai.n_candidates()): directional_show(ai[x],message="BC%d"%x) for combo in C: #print "COMBO: (%d,%d,%d)"%(combo[0],combo[1],combo[2]) try: HC = HandleCombo(ai,combo) #HC.handle_absences() #might need to add this in later if ai.rmsdev() < better_than: model_likelihood = 1. - ai.rmsdev() # provisional expression for likelihood if model_likelihood > best_likelihood: best_likelihood = model_likelihood this_solution = {'combo':combo,'model_likelihood':model_likelihood, 'volume':ai.getOrientation().unit_cell().volume()} solutions.append(this_solution) try_counter+=1 except (FewSpots) as f: #print "COMBO: (%d,%d,%d) rejected on too few spots"%(combo[0],combo[1],combo[2]) #printcombo(ai,combo) continue except (SmallUnitCellVolume) as f: #print "Small COMBO: (%d,%d,%d) rejected on small cell volume"%(combo[0],combo[1],combo[2]) continue except (KGerror) as f: #print "KG COMBO: (%d,%d,%d) rejected on Krivy-Gruber iterations"%(combo[0],combo[1],combo[2]) #printcombo(ai,combo) continue except ValueError as f : if str(f).find("Corrupt metrical matrix")>=0: continue # colinear or coplanar except (RuntimeError) as f: if str(f).find("Iteration limit exceeded")>0: continue if str(f).find("Matrix is not invertible")>=0: continue# colinear or coplanar print "Report this problem to LABELIT developers:" print "COMBO: (%d,%d,%d) rejected on C++ runtime error"%(combo[0],combo[1],combo[2]) #printcombo(ai,combo) continue except Exception: raise if solutions.halts(): return solutions if try_counter == maxtry: break return solutions
def hemisphere(self,ai,size = 30,cutoff_divisor = 4.,verbose=True): unrefined_basis_vectors = self.get_top_solutions(ai,self.angles,size, cutoff_divisor,grid=self.incr) if verbose: for i in xrange(len(unrefined_basis_vectors)): D = unrefined_basis_vectors[i]; if diagnostic: directional_show(D, "SE%5d"%i) ai.setSolutions(unrefined_basis_vectors)
def get_top_solutions(self, ai, input_directions, size, cutoff_divisor, grid): kval_cutoff = ai.getXyzSize() / cutoff_divisor hemisphere_solutions = flex.Direction() hemisphere_solutions.reserve(size) #print "# of input directions", len(input_directions) for i in range(len(input_directions)): D = sampled_direction = ai.fft_result(input_directions[i]) #hardcoded parameter in for silicon example. Not sure at this point how #robust the algorithm is when this value is relaxed. if D.real < self.max_cell and sampled_direction.kval > kval_cutoff: if diagnostic: directional_show(D, "%5d" % i) hemisphere_solutions.append(sampled_direction) if (hemisphere_solutions.size() < 3): return hemisphere_solutions kvals = flex.double([ hemisphere_solutions[x].kval for x in range(len(hemisphere_solutions)) ]) perm = flex.sort_permutation(kvals, True) # need to be more clever than just taking the top 30. # one huge cluster around a strong basis direction could dominate the # whole hemisphere map, preventing the discovery of three basis vectors perm_idx = 0 unique_clusters = 0 hemisphere_solutions_sort = flex.Direction() while perm_idx < len(perm) and \ unique_clusters < size: test_item = hemisphere_solutions[perm[perm_idx]] direction_ok = True for list_item in hemisphere_solutions_sort: distance = math.sqrt( math.pow(list_item.dvec[0] - test_item.dvec[0], 2) + math.pow(list_item.dvec[1] - test_item.dvec[1], 2) + math.pow(list_item.dvec[2] - test_item.dvec[2], 2)) if distance < 0.087: #i.e., 5 degrees radius for clustering analysis direction_ok = False break if direction_ok: unique_clusters += 1 hemisphere_solutions_sort.append(test_item) perm_idx += 1 return hemisphere_solutions_sort
def hemisphere(self, ai, size=30, cutoff_divisor=4., verbose=True): unrefined_basis_vectors = self.get_top_solutions(ai, self.angles, size, cutoff_divisor, grid=self.incr) if verbose: for i in range(len(unrefined_basis_vectors)): D = unrefined_basis_vectors[i] if diagnostic: directional_show(D, "SE%5d" % i) ai.setSolutions(unrefined_basis_vectors)
def get_top_solutions(self,ai,input_directions,size,cutoff_divisor,grid): kval_cutoff = ai.getXyzSize()/cutoff_divisor; hemisphere_solutions = flex.Direction(); hemisphere_solutions.reserve(size); #print "# of input directions", len(input_directions) for i in xrange(len(input_directions)): D = sampled_direction = ai.fft_result(input_directions[i]) #hardcoded parameter in for silicon example. Not sure at this point how #robust the algorithm is when this value is relaxed. if D.real < self.max_cell and sampled_direction.kval > kval_cutoff: if diagnostic: directional_show(D, "%5d"%i) hemisphere_solutions.append(sampled_direction) if (hemisphere_solutions.size()<3): return hemisphere_solutions kvals = flex.double([ hemisphere_solutions[x].kval for x in xrange(len(hemisphere_solutions))]) perm = flex.sort_permutation(kvals,True) # need to be more clever than just taking the top 30. # one huge cluster around a strong basis direction could dominate the # whole hemisphere map, preventing the discovery of three basis vectors perm_idx = 0 unique_clusters = 0 hemisphere_solutions_sort = flex.Direction() while perm_idx < len(perm) and \ unique_clusters < size: test_item = hemisphere_solutions[perm[perm_idx]] direction_ok = True for list_item in hemisphere_solutions_sort: distance = math.sqrt(math.pow(list_item.dvec[0]-test_item.dvec[0],2) + math.pow(list_item.dvec[1]-test_item.dvec[1],2) + math.pow(list_item.dvec[2]-test_item.dvec[2],2) ) if distance < 0.087: #i.e., 5 degrees radius for clustering analysis direction_ok=False break if direction_ok: unique_clusters+=1 hemisphere_solutions_sort.append(test_item) perm_idx+=1 return hemisphere_solutions_sort;
def select_best_combo_of(ai, better_than=0.15, candidates=20, basis=15): """Take the first few candidates of ai.combos(). Search for all combos with hkl obs-calc better than a certain fraction limit, then handle absences, and return the best one""" best_combo = None base_likelihood = 0.30 best_likelihood = base_likelihood C = ai.combos(basis) maxtry = min(candidates, len(C)) try_counter = 0 solutions = SolutionTracker() if diagnostic: for x in xrange(ai.n_candidates()): directional_show(ai[x], message="BC%d" % x) for combo in C: #print "COMBO: (%d,%d,%d)"%(combo[0],combo[1],combo[2]) try: HC = HandleCombo(ai, combo) #HC.handle_absences() #might need to add this in later if ai.rmsdev() < better_than: model_likelihood = 1. - ai.rmsdev( ) # provisional expression for likelihood if model_likelihood > best_likelihood: best_likelihood = model_likelihood this_solution = { 'combo': combo, 'model_likelihood': model_likelihood, 'volume': ai.getOrientation().unit_cell().volume() } solutions.append(this_solution) try_counter += 1 except (FewSpots), f: #print "COMBO: (%d,%d,%d) rejected on too few spots"%(combo[0],combo[1],combo[2]) #printcombo(ai,combo) continue except (SmallUnitCellVolume), f: #print "Small COMBO: (%d,%d,%d) rejected on small cell volume"%(combo[0],combo[1],combo[2]) continue
def select_best_combo_of(ai,better_than=0.15,candidates=20,basis=15): """Take the first few candidates of ai.combos(). Search for all combos with hkl obs-calc better than a certain fraction limit, then handle absences, and return the best one""" best_combo = None base_likelihood = 0.30 best_likelihood = base_likelihood C = ai.combos(basis) maxtry = min(candidates,len(C)) try_counter = 0 solutions = SolutionTracker() if diagnostic: for x in xrange(ai.n_candidates()): directional_show(ai[x],message="BC%d"%x) for combo in C: #print "COMBO: (%d,%d,%d)"%(combo[0],combo[1],combo[2]) try: HC = HandleCombo(ai,combo) #HC.handle_absences() #might need to add this in later if ai.rmsdev() < better_than: model_likelihood = 1. - ai.rmsdev() # provisional expression for likelihood if model_likelihood > best_likelihood: best_likelihood = model_likelihood this_solution = {'combo':combo,'model_likelihood':model_likelihood, 'volume':ai.getOrientation().unit_cell().volume()} solutions.append(this_solution) try_counter+=1 except (FewSpots),f: #print "COMBO: (%d,%d,%d) rejected on too few spots"%(combo[0],combo[1],combo[2]) #printcombo(ai,combo) continue except (SmallUnitCellVolume),f: #print "Small COMBO: (%d,%d,%d) rejected on small cell volume"%(combo[0],combo[1],combo[2]) continue
def force_cell(index_engine,target_cell,verbose=False): if verbose: print "N candidates:",index_engine.n_candidates() from rstbx.dps_core import directional_show for x in xrange(index_engine.n_candidates()): directional_show( index_engine[x], "vector %d:"%x ) Ns = index_engine.n_candidates() best = {"score":1.E100} orth = target_cell.orthogonalization_matrix() for working_cell,cb_op in generate_unimodular_cells(target_cell): #print "---->",working_cell, working_cell.volume() vectors = {"a":{"match":[],"length":working_cell.parameters()[0]}, "b":{"match":[],"length":working_cell.parameters()[1]}, "c":{"match":[],"length":working_cell.parameters()[2]}, } for key in vectors.keys(): for ns in xrange(Ns): if is_length_match(vectors[key]["length"],index_engine[ns].real): vectors[key]["match"].append(ns) #print key, vectors[key] lines = {"alpha":{"match":[],"points":("b","c"),"angle":working_cell.parameters()[3],"hit":False}, "beta":{"match":[],"points":("c","a"),"angle":working_cell.parameters()[4],"hit":False}, "gamma":{"match":[],"points":("a","b"),"angle":working_cell.parameters()[5],"hit":False}, } for key in lines.keys(): xmatch = len(vectors[lines[key]["points"][0]]["match"]) ymatch = len(vectors[lines[key]["points"][1]]["match"]) for xi in xrange(xmatch): for yi in xrange(ymatch): xkey = vectors[lines[key]["points"][0]]["match"][abs(xi)] ykey = vectors[lines[key]["points"][1]]["match"][abs(yi)] #print key,xkey,ykey, xvector = col(index_engine[xkey].dvec) yvector = col(index_engine[ykey].dvec) #print xvector.dot(yvector), costheta = xvector.dot(yvector)/math.sqrt(xvector.dot(xvector)*yvector.dot(yvector)) angle = math.acos(costheta)*180./math.pi #print "angle %.2f"%angle, if is_angle_match(angle, lines[key]["angle"]): #print "*****",; lines[key]["hit"]=True lines[key]["match"].append((xkey,ykey)) if lines["alpha"]["hit"] and lines["beta"]["hit"] and lines["gamma"]["hit"]: #print "HELLO HIT" #for key in lines.keys(): # print key, lines[key] tri = get_triangle(lines) #print "Triangle:",tri if tri==None: continue direct_matrix = sqr(( index_engine[tri[0]].bvec()[0],index_engine[tri[0]].bvec()[1],index_engine[tri[0]].bvec()[2], index_engine[tri[1]].bvec()[0],index_engine[tri[1]].bvec()[1],index_engine[tri[1]].bvec()[2], index_engine[tri[2]].bvec()[0],index_engine[tri[2]].bvec()[1],index_engine[tri[2]].bvec()[2], )) ori = Orientation(direct_matrix,False) #print "Found unit cell",ori.unit_cell() #print "compatible",ori.unit_cell().change_basis(cb_op.inverse()), modo = ori.unit_cell().change_basis(cb_op.inverse()).orthogonalization_matrix() diff = ( modo[0]-orth[0],modo[1]-orth[1],modo[2]-orth[2],modo[4]-orth[4],modo[5]-orth[5],modo[8]-orth[8]) score = math.sqrt(diff[0]*diff[0]+diff[1]*diff[1]+diff[2]*diff[2]+diff[3]*diff[3]+diff[4]*diff[4]+diff[5]*diff[5]) #print "score %.1f"%score,tri if score<best["score"]: best = {"score":score,"triangle":tri,"orientation":ori.change_basis(sqr(cb_op.inverse().c().r().as_double()).transpose())} if verbose: print "Best score %.1f, triangle %12s"%(best["score"],str(best["triangle"])),best["orientation"].unit_cell() return best
def force_cell(index_engine,target_cell,verbose=False): if verbose: print("N candidates:",index_engine.n_candidates()) from rstbx.dps_core import directional_show for x in range(index_engine.n_candidates()): directional_show( index_engine[x], "vector %d:"%x ) Ns = index_engine.n_candidates() best = {"score":1.E100} orth = target_cell.orthogonalization_matrix() for working_cell,cb_op in generate_unimodular_cells(target_cell): #print "---->",working_cell, working_cell.volume() vectors = {"a":{"match":[],"length":working_cell.parameters()[0]}, "b":{"match":[],"length":working_cell.parameters()[1]}, "c":{"match":[],"length":working_cell.parameters()[2]}, } for key in vectors.keys(): for ns in range(Ns): if is_length_match(vectors[key]["length"],index_engine[ns].real): vectors[key]["match"].append(ns) #print key, vectors[key] lines = {"alpha":{"match":[],"points":("b","c"),"angle":working_cell.parameters()[3],"hit":False}, "beta":{"match":[],"points":("c","a"),"angle":working_cell.parameters()[4],"hit":False}, "gamma":{"match":[],"points":("a","b"),"angle":working_cell.parameters()[5],"hit":False}, } for key in lines.keys(): xmatch = len(vectors[lines[key]["points"][0]]["match"]) ymatch = len(vectors[lines[key]["points"][1]]["match"]) for xi in range(xmatch): for yi in range(ymatch): xkey = vectors[lines[key]["points"][0]]["match"][abs(xi)] ykey = vectors[lines[key]["points"][1]]["match"][abs(yi)] #print key,xkey,ykey, xvector = col(index_engine[xkey].dvec) yvector = col(index_engine[ykey].dvec) #print xvector.dot(yvector), costheta = xvector.dot(yvector)/math.sqrt(xvector.dot(xvector)*yvector.dot(yvector)) angle = math.acos(costheta)*180./math.pi #print "angle %.2f"%angle, if is_angle_match(angle, lines[key]["angle"]): #print "*****",; lines[key]["hit"]=True lines[key]["match"].append((xkey,ykey)) if lines["alpha"]["hit"] and lines["beta"]["hit"] and lines["gamma"]["hit"]: #print "HELLO HIT" #for key in lines.keys(): # print key, lines[key] tri = get_triangle(lines) #print "Triangle:",tri if tri==None: continue direct_matrix = sqr(( index_engine[tri[0]].bvec()[0],index_engine[tri[0]].bvec()[1],index_engine[tri[0]].bvec()[2], index_engine[tri[1]].bvec()[0],index_engine[tri[1]].bvec()[1],index_engine[tri[1]].bvec()[2], index_engine[tri[2]].bvec()[0],index_engine[tri[2]].bvec()[1],index_engine[tri[2]].bvec()[2], )) ori = Orientation(direct_matrix,False) #print "Found unit cell",ori.unit_cell() #print "compatible",ori.unit_cell().change_basis(cb_op.inverse()), modo = ori.unit_cell().change_basis(cb_op.inverse()).orthogonalization_matrix() diff = ( modo[0]-orth[0],modo[1]-orth[1],modo[2]-orth[2],modo[4]-orth[4],modo[5]-orth[5],modo[8]-orth[8]) score = math.sqrt(diff[0]*diff[0]+diff[1]*diff[1]+diff[2]*diff[2]+diff[3]*diff[3]+diff[4]*diff[4]+diff[5]*diff[5]) #print "score %.1f"%score,tri if score<best["score"]: best = {"score":score,"triangle":tri,"orientation":ori.change_basis(sqr(cb_op.inverse().c().r().as_double()).transpose())} if verbose: print("Best score %.1f, triangle %12s"%(best["score"],str(best["triangle"])),best["orientation"].unit_cell()) return best