def get_chiral_diff(self, edges, arc1, arc2, count=[]): narcs1 = normalized_vectors(arc1) narcs2 = normalized_vectors(arc2) ### DEBUG #atoms = ["H", "F", "He", "Cl", "N", "O"] R = rotation_from_vectors(narcs2, narcs1) #FIXME(pboyd): ensure that this is the right rotation!!! I think it's supposed to rotate narcs2 narcs1 = (np.dot(R[:3,:3], narcs1.T)).T #narcs2 = (np.dot(R[:3,:3], narcs2.T)).T #or1 = np.zeros(3) #or2 = np.array([3., 3., 0.]) #xyz_str1 = "C %9.5f %9.5f %9.5f\n"%(or1[0], or1[1], or1[2]) #xyz_str2 = "C %9.5f %9.5f %9.5f\n"%(or2[0], or2[1], or2[2]) #for ind, (i, j) in enumerate(zip(narcs1,narcs2)): # at = atoms[ind] # pos = i[:3] + or1 # xyz_str1 += "%s %9.5f %9.5f %9.5f\n"%(at, pos[0], pos[1], pos[2]) # pos = j + or2 # xyz_str2 += "%s %9.5f %9.5f %9.5f\n"%(at, pos[0], pos[1], pos[2]) #xyz_file = open("debugging.xyz", 'a') #xyz_file.writelines("%i\ndebug\n"%(len(narcs1)*2+2)) #xyz_file.writelines(xyz_str1) #xyz_file.writelines(xyz_str2) #xyz_file.close() ### DEBUG #CI_1 = self.chiral_invariant(edges, narcs1) #CI_2 = self.chiral_invariant(edges, narcs2) #count.append(1) #ff = open("CI1", 'a') #ff.writelines('%i %e\n'%(len(count), CI_1)) #ff.close() #ff = open("CI2", 'a') #ff.writelines('%i %e\n'%(len(count), CI_2)) #ff.close() #print 'edge assignment ', ','.join([p[2] for p in edges]) #print 'lattice arcs CI ', CI_1 #print 'connect point CI ', CI_2 #if all(item >= 0 for item in (CI_1, CI_2)) or all(item < 0 for item in (CI_1, CI_2)): # return np.absolute(CI_1 - CI_2) #else: # return 150000. return np.sum(np.absolute((narcs1 - narcs2).flatten()))
def closest_match_vertices(self, sbu): g = self._net.graph if sbu.two_connected and not sbu.linear: cp_v = normalized_vectors([ self.vector_from_cp_intersecting_pt(cp, sbu) for cp in sbu.connect_points]) else: cp_v = normalized_vectors([self.vector_from_cp_SBU(cp, sbu) for cp in sbu.connect_points]) ipv = self.scaled_ipmatrix(np.inner(cp_v, cp_v)) inds = np.triu_indices(ipv.shape[0], k=1) max, min = np.absolute(ipv[inds]).max(), np.absolute(ipv[inds]).min() cmatch = [] for v in self.sbu_vertices: ee = self._net.neighbours(v) l_arcs = self._net.lattice_arcs[self._net.return_indices(ee)] lai = np.dot(np.dot(l_arcs, self._net.metric_tensor), l_arcs.T) ipc = self.scaled_ipmatrix(lai) imax, imin = np.absolute(ipc[inds]).max(), np.absolute(ipc[inds]).min() mm = np.sum(np.absolute([max-imax, min-imin])) cmatch.append((mm, v)) return sorted(cmatch)
def report_errors(self, sbu_vects, arcs, rot_mat): rotation = np.dot(rot_mat[:3,:3], sbu_vects.T) v = normalized_vectors(rotation.T) angles = np.array([calc_angle(v1, v2) for v1, v2 in zip(v, arcs)]) mean, std = np.mean(angles), np.std(angles) return mean, std
def sbu_orient(self, v, cell): """Least squares optimization of orientation matrix. Obtained from: Soderkvist & Wedin 'Determining the movements of the skeleton using well configured markers' J. Biomech. 26, 12, 1993, 1473-1477. DOI: 10.1016/0021-9290(93)90098-Y""" g = self._net.graph sbu = self._vertex_sbu[v] edges = self._net.neighbours(v) debug("Orienting SBU: %i, %s on vertex %s"%(sbu.identifier, sbu.name, v)) # re-index the edges to match the order of the connect points in the sbu list indexed_edges = sbu.edge_assignments coefficients = np.array([1. if e in self._net.out_edges(v) else -1. for e in indexed_edges]) if len(indexed_edges) != sbu.degree: error("There was an error assigning edges "+ "to the sbu %s"%(sbu.name)) Terminate(errcode=1) inds = self._net.return_indices(indexed_edges) la = self._net.lattice_arcs[inds] if self._net.ndim == 2: la = np.hstack((la, np.zeros((la.shape[0], 1)))) arcs = np.dot(la, cell) arcs = normalized_vectors(arcs) * coefficients[:, None] sbu_vects = normalized_vectors(np.array([self.vector_from_cp_SBU(cp, sbu) for cp in sbu.connect_points])) #print np.dot(arcs, arcs.T) #sf = self._net.scale_factor #la = self._net.lattice_arcs #mt = self._net.metric_tensor/sf #obj = la*mt*la.T #print obj # issue for ditopic SBUs where the inner product matrices could invert the # angles (particularly for ZIFs) if sbu.degree == 2 and not sbu.linear: sbu_vects = normalized_vectors(np.array([ self.vector_from_cp_intersecting_pt(cp, sbu) for cp in sbu.connect_points])) # define the plane generated by the edges #print "arc angle %9.5f"%(180.*calc_angle(*arcs)/np.pi) #print "sbu angle %9.5f"%(180.*calc_angle(*sbu_vects)/np.pi) # For some reason the least squares rotation matrix # does not work well with just two vectors, so a third # orthonormal vector is included to create the proper # rotation matrix arc3 = np.cross(arcs[0], arcs[1]) arc3 /= np.linalg.norm(arc3) cp3 = np.cross(sbu_vects[0], sbu_vects[1]) cp3 /= np.linalg.norm(cp3) sbu_vects = np.vstack((sbu_vects, cp3)) arcs = np.vstack((arcs, arc3)) R = rotation_from_vectors(sbu_vects, arcs) mean, std = self.report_errors(sbu_vects, arcs, rot_mat=R) ### DEBUGGGGGG #or1 = np.zeros(3) #or2 = np.array([3., 3., 0.]) #xyz_str1 = "C %9.5f %9.5f %9.5f\n"%(or1[0], or1[1], or1[2]) #xyz_str2 = "C %9.5f %9.5f %9.5f\n"%(or2[0], or2[1], or2[2]) #atms = ["H", "F", "O", "He", "N", "Cl"] #sbu_rot_vects = np.dot(R[:3,:3], sbu_vects.T) #for ind, (i, j) in enumerate(zip(arcs, sbu_rot_vects.T)): # at = atms[ind] # pos = i + or1 # xyz_str1 += "%s %9.5f %9.5f %9.5f\n"%(at, pos[0], pos[1], pos[2]) # pos = j + or2 # xyz_str2 += "%s %9.5f %9.5f %9.5f\n"%(at, pos[0], pos[1], pos[2]) #xyz_file = open("debug_rotation_function.xyz", 'a') #xyz_file.writelines("%i\ndebug\n"%(len(sbu_rot_vects.T)*2+2)) #xyz_file.writelines(xyz_str1) #xyz_file.writelines(xyz_str2) #xyz_file.close() ### DEBUGGGGGG mean, std = self.report_errors(sbu_vects, arcs, rot_mat=R) debug("Average orientation error: %12.6f +/- %9.6f degrees"%(mean/DEG2RAD, std/DEG2RAD)) sbu.rotate(R)
def assign_edge_labels(self, vertex): """Edge assignment is geometry dependent. This will try to find the best assignment based on inner product comparison with the non-placed lattice arcs.""" sbu = self._vertex_sbu[vertex] local_arcs = sbu.connect_points edges = self._net.neighbours(vertex) indices = self._net.return_indices(edges) lattice_arcs = self._net.lattice_arcs e_assign = {} if sbu.two_connected and not sbu.linear: vects = [self.vector_from_cp_intersecting_pt(cp, sbu) for cp in local_arcs] else: vects = [self.vector_from_cp_SBU(cp, sbu) for cp in local_arcs] norm_cp = normalized_vectors(vects) li = self.normalized_ipmatrix(vects) min, chi_diff=15000., 15000. cc, assign = None, None # print("hi1") debug("%s assigned to %s"%(sbu.name, vertex)) # print("hi2") cell = Cell() cell.mkcell(self._net.get_3d_params()) if self._net.ndim == 2: lattice_arcs = np.hstack((lattice_arcs, np.zeros((lattice_arcs.shape[0],1)))) lattice_vects = np.dot(lattice_arcs, cell.lattice) count = 0 # print("hi1") print('Number of edges {}'.format(len(edges))) print(edges) for i, e in enumerate(itertools.combinations(edges, len(edges))): print(e) count += 1 indices = self._net.return_indices(e) #node_arcs = lattice_arcs[indices]*\ # self._net.metric_tensor*lattice_arcs[indices].T #max = node_arcs.max() #la = np.empty((len(indices),len(indices))) #for (i,j), val in np.ndenumerate(node_arcs): # if i==j: # la[i,j] = val/max # else: # v = val/np.sqrt(node_arcs[i,i])/np.sqrt(node_arcs[j,j]) # la[i,j] = v # la[j,i] = v # using tensor product of the incidences coeff = np.array([-1. if j in self._net.in_edges(vertex) else 1. for j in e]) #td = np.tensordot(coeff, coeff, axes=0) #diff = np.multiply(li, td) - la #inds = np.triu_indices(diff.shape[0], k=1) #xmax, xmin = np.absolute(diff[inds]).max(), np.absolute(diff[inds]).min() #mm = np.sum(diff) #mm = np.sum(np.absolute(np.multiply(li,td) - la)) # NB Chirality matters!!! # get the cell lv_arc = (np.array(lattice_vects[indices]) * coeff[:, None]) # get the lattice arcs mm = self.get_chiral_diff(e, lv_arc, vects) print("hi1") print(i,mm) #norm_arc = normalized_vectors(lv_arc) # orient the lattice arcs to the first sbu vector... #print count , self.chiral_match(e, oriented_arc, norm_cp) #print count, np.allclose(norm_cp, oriented_arc, atol=0.01) #or1 = np.zeros(3) #or2 = np.array([3., 3., 0.]) #xyz_str1 = "C %9.5f %9.5f %9.5f\n"%(or1[0], or1[1], or1[2]) #xyz_str2 = "C %9.5f %9.5f %9.5f\n"%(or2[0], or2[1], or2[2]) #for ind, (i, j) in enumerate(zip(norm_cp,oriented_arc)): # at = atoms[ind] # pos = i[:3] + or1 # xyz_str1 += "%s %9.5f %9.5f %9.5f\n"%(at, pos[0], pos[1], pos[2]) # pos = j + or2 # xyz_str2 += "%s %9.5f %9.5f %9.5f\n"%(at, pos[0], pos[1], pos[2]) #xyz_file = open("debugging.xyz", 'a') #xyz_file.writelines("%i\ndebug\n"%(len(norm_cp)*2+2)) #xyz_file.writelines(xyz_str1) #xyz_file.writelines(xyz_str2) #xyz_file.close() #print "arc CI", CI_ar, "cp CI", CI_cp #if (mm < min) and (diff < chi_diff): #print("hi1") if (mm <= min):# and self.chiral_match(e, norm_arc, norm_cp):#, tol=xmax): min = mm print("mm smaller min") assign = e else: print('mm larger min') #CI = self.chiral_invariant(assign, norm_arc) #axis = np.array([1., 3., 1.]) #angle = np.pi/3. #R = rotation_matrix(axis, angle) #new_norm = np.dot(R[:3,:3], norm_arc.T) #nCI = self.chiral_invariant(assign, new_norm.T) #print "Rotation invariant?", CI, nCI # NB special MULT function for connect points #print("hi1") cp_vert = [i[0] if i[0] != vertex else i[1] for i in assign] #print 'CI diff', chi_diff #print 'tensor diff', mm #print("hi1") sbu.edge_assignments = assign for cp, v in zip(local_arcs, cp_vert): cp.vertex_assign = v
def normalized_ipmatrix(self, vectors): v = normalized_vectors(vectors) return np.inner(v,v)
def assign_edge_labels(self, vertex): """Edge assignment is geometry dependent. This will try to find the best assignment based on inner product comparison with the non-placed lattice arcs.""" sbu = self._vertex_sbu[vertex] local_arcs = sbu.connect_points edges = self._net.neighbours(vertex) indices = self._net.return_indices(edges) lattice_arcs = self._net.lattice_arcs e_assign = {} if sbu.two_connected and not sbu.linear: vects = [self.vector_from_cp_intersecting_pt(cp, sbu) for cp in local_arcs] else: vects = [self.vector_from_cp_SBU(cp, sbu) for cp in local_arcs] norm_cp = normalized_vectors(vects) li = self.normalized_ipmatrix(vects) min, chi_diff=15000., 15000. cc, assign = None, None debug("%s assigned to %s"%(sbu.name, vertex)) cell = Cell() cell.mkcell(self._net.get_3d_params()) if self._net.ndim == 2: lattice_arcs = np.hstack((lattice_arcs, np.zeros((lattice_arcs.shape[0],1)))) lattice_vects = np.dot(lattice_arcs, cell.lattice) count = 0 for e in itertools.permutations(edges): count += 1 indices = self._net.return_indices(e) #node_arcs = lattice_arcs[indices]*\ # self._net.metric_tensor*lattice_arcs[indices].T #max = node_arcs.max() #la = np.empty((len(indices),len(indices))) #for (i,j), val in np.ndenumerate(node_arcs): # if i==j: # la[i,j] = val/max # else: # v = val/np.sqrt(node_arcs[i,i])/np.sqrt(node_arcs[j,j]) # la[i,j] = v # la[j,i] = v # using tensor product of the incidences coeff = np.array([-1. if j in self._net.in_edges(vertex) else 1. for j in e]) #td = np.tensordot(coeff, coeff, axes=0) #diff = np.multiply(li, td) - la #inds = np.triu_indices(diff.shape[0], k=1) #xmax, xmin = np.absolute(diff[inds]).max(), np.absolute(diff[inds]).min() #mm = np.sum(diff) #mm = np.sum(np.absolute(np.multiply(li,td) - la)) # NB Chirality matters!!! # get the cell lv_arc = (np.array(lattice_vects[indices]) * coeff[:, None]) # get the lattice arcs mm = self.get_chiral_diff(e, lv_arc, vects) #norm_arc = normalized_vectors(lv_arc) # orient the lattice arcs to the first sbu vector... #print count , self.chiral_match(e, oriented_arc, norm_cp) #print count, np.allclose(norm_cp, oriented_arc, atol=0.01) #or1 = np.zeros(3) #or2 = np.array([3., 3., 0.]) #xyz_str1 = "C %9.5f %9.5f %9.5f\n"%(or1[0], or1[1], or1[2]) #xyz_str2 = "C %9.5f %9.5f %9.5f\n"%(or2[0], or2[1], or2[2]) #for ind, (i, j) in enumerate(zip(norm_cp,oriented_arc)): # at = atoms[ind] # pos = i[:3] + or1 # xyz_str1 += "%s %9.5f %9.5f %9.5f\n"%(at, pos[0], pos[1], pos[2]) # pos = j + or2 # xyz_str2 += "%s %9.5f %9.5f %9.5f\n"%(at, pos[0], pos[1], pos[2]) #xyz_file = open("debugging.xyz", 'a') #xyz_file.writelines("%i\ndebug\n"%(len(norm_cp)*2+2)) #xyz_file.writelines(xyz_str1) #xyz_file.writelines(xyz_str2) #xyz_file.close() #print "arc CI", CI_ar, "cp CI", CI_cp #if (mm < min) and (diff < chi_diff): if (mm <= min):# and self.chiral_match(e, norm_arc, norm_cp):#, tol=xmax): min = mm assign = e #CI = self.chiral_invariant(assign, norm_arc) #axis = np.array([1., 3., 1.]) #angle = np.pi/3. #R = rotation_matrix(axis, angle) #new_norm = np.dot(R[:3,:3], norm_arc.T) #nCI = self.chiral_invariant(assign, new_norm.T) #print "Rotation invariant?", CI, nCI # NB special MULT function for connect points cp_vert = [i[0] if i[0] != vertex else i[1] for i in assign] #print 'CI diff', chi_diff #print 'tensor diff', mm sbu.edge_assignments = assign for cp, v in zip(local_arcs, cp_vert): cp.vertex_assign = v