def __init__(self, symname, tgtaxis1, tgtaxis2, from_seg, *, tol=1.0, lever=50, to_seg=-1, distinct_axes=False): if from_seg == to_seg: raise ValueError('from_seg should not be same as to_seg') self.symname = symname self.from_seg = from_seg if len(tgtaxis1) == 2: tgtaxis1 += [0, 0, 0, 1], if len(tgtaxis2) == 2: tgtaxis2 += [0, 0, 0, 1], self.tgtaxis1 = (tgtaxis1[0], hm.hnormalized(tgtaxis1[1]), hm.hpoint(tgtaxis1[2])) self.tgtaxis2 = (tgtaxis2[0], hm.hnormalized(tgtaxis2[1]), hm.hpoint(tgtaxis2[2])) assert 3 == len(self.tgtaxis1) assert 3 == len(self.tgtaxis2) self.angle = hm.angle(tgtaxis1[1], tgtaxis2[1]) self.tol = tol self.lever = lever self.to_seg = to_seg self.rot_tol = tol / lever self.distinct_axes = distinct_axes # -z not same as z (for T33) self.sym_axes = [self.tgtaxis1, self.tgtaxis2]
def alignment(self, segpos, debug=0, **kw): cen1 = segpos[self.from_seg][..., :, 3] cen2 = segpos[self.to_seg][..., :, 3] ax1 = segpos[self.from_seg][..., :, 2] ax2 = segpos[self.to_seg][..., :, 2] if not self.distinct_axes and hm.angle(ax1, ax2) > np.pi / 2: ax2 = -ax2 p, q = hm.line_line_closest_points_pa(cen1, ax1, cen2, ax2) cen = (p + q) / 2 # ax1 = hm.hnormalized(cen1 - cen) # ax2 = hm.hnormalized(cen2 - cen) x = hm.align_vectors(ax1, ax2, self.tgtaxis1[1], self.tgtaxis2[1]) x[..., :, 3] = -x @ cen if debug: print('angs', hm.angle_degrees(ax1, ax2), hm.angle_degrees(self.tgtaxis1[1], self.tgtaxis2[1])) print('ax1', ax1) print('ax2', ax2) print('xax1', x @ ax1) print('tax1', self.tgtaxis1[1]) print('xax2', x @ ax2) print('tax2', self.tgtaxis2[1]) raise AssertionError # if not (np.allclose(x @ ax1, self.tgtaxis1[1], atol=1e-2) and # np.allclose(x @ ax2, self.tgtaxis2[1], atol=1e-2)): # print(hm.angle(self.tgtaxis1[1], self.tgtaxis2[1])) # print(hm.angle(ax1, ax2)) # print(x @ ax1) # print(self.tgtaxis1[1]) # print(x @ ax2) # print(self.tgtaxis2[1]) # raise AssertionError('hm.align_vectors sucks') return x
def alignment(self, segpos, out_cell_spacing=False, **kw): """ Alignment to move stuff to be in line with symdef file Args: segpos (lst): List of segment positions / coordinates. **kw I'll accept any "non-positional" argument as name = value, and store in a dictionary """ cen1 = segpos[self.from_seg][..., :, 3] ## 4th column is x,y,z translation cen2 = segpos[self.to_seg][..., :, 3] ax1 = segpos[self.from_seg][..., :, 2] ## 3rd column is axis ax2 = segpos[self.to_seg][..., :, 2] if hm.angle( ax1, ax2 ) > np.pi / 2: ## make sure to align with smaller axis choice ax2 = -ax2 if abs(hm.angle(self.tgtaxis1, self.tgtaxis2)) < 0.1: d = hm.proj_perp(ax1, cen2 - cen1) #vector delta between cen2 and cen1 Xalign = hm.align_vectors(ax1, d, self.tgtaxis1, [0, 1, 0, 0]) #align d to Y axis Xalign[..., :, 3] = -Xalign @ cen1 cell_dist = (Xalign @ cen2)[..., 1] else: Xalign = hm.align_vectors( ax1, ax2, self.tgtaxis1, self.tgtaxis2 ) ## utility function that tries to align ax1 and ax2 to the target axes Xalign[..., :, 3] = -Xalign @ cen1 ## move from_seg cen1 to origin cen2_0 = Xalign @ cen2 #moving cen2 by Xalign D = np.stack([ self.tgtaxis1[:3], [0, 1, 0], self.tgtaxis2[:3] ]).T #matrix where the columns are the things in the list #CHANGE Uy to an ARGUMENT SOON!!!! #print("D: ", D) A1offset, cell_dist, _ = np.linalg.inv( D ) @ cen2_0[: 3] #transform of A1 offest, cell distance (offset along other axis), and A2 offset (<-- we are ignoring this) Xalign[..., :, 3] = Xalign[..., :, 3] - (A1offset * self.tgtaxis1) #Xalign[..., :, 3] = Xalign[..., :, 3] + [0,cell_dist,0,0] if out_cell_spacing: #print(2*cell_dist) return Xalign, cell_dist else: return Xalign
def alignment(self, segpos, out_cell_spacing=False, **kw): """ Alignment to move stuff to be in line with symdef file Args: segpos (lst): List of segment positions / coordinates. **kw I'll accept any "non-positional" argument as name = value, and store in a dictionary """ cen1 = segpos[self.from_seg][..., :, 3] cen2 = segpos[self.to_seg][..., :, 3] ax1 = segpos[self.from_seg][..., :, 2] ## 3rd column is axis ax2 = segpos[self.to_seg][..., :, 2] ## make sure to align with smaller axis choice if hm.angle(ax1, ax2) > np.pi / 2: ax2 = -ax2 if abs(hm.angle(self.tgtaxis1, self.tgtaxis2)) < 0.1: # vector delta between cen2 and cen1 d = hm.proj_perp(ax1, cen2 - cen1) Xalign = hm.align_vectors(ax1, d, self.tgtaxis1, self.tgtaxis2_isects + [0]) # align d to Y axis Xalign[..., :, 3] = -Xalign @ cen1 cell_dist = (Xalign @ cen2)[..., 1] else: try: Xalign = hm.align_vectors(ax1, ax2, self.tgtaxis1, self.tgtaxis2) except AssertionError as e: print("align_vectors error") print(" ", ax1) print(" ", ax2) print(" ", self.tgtaxis1) print(" ", self.tgtaxis2) raise e Xalign[..., :, 3] = -Xalign @ cen1 ## move from_seg cen1 to origin cen2_0 = Xalign @ cen2 # moving cen2 by Xalign D = np.stack( [self.tgtaxis1[:3], self.tgtaxis2_isects, self.tgtaxis2[:3]]).T A1offset, cell_dist, _ = np.linalg.inv(D) @ cen2_0[:3] # transform of A1 offest, cell distance (offset along other axis), and A2 offset (<-- we are ignoring this) Xalign[..., :, 3] = Xalign[..., :, 3] - (A1offset * self.tgtaxis1) # Xalign[..., :, 3] = Xalign[..., :, 3] + [0,cell_dist,0,0] if out_cell_spacing: return Xalign, cell_dist else: return Xalign
def __init__( self, symname, tgtaxis1, tgtaxis2, from_seg, *, tolerance=1.0, lever=50, to_seg=-1, space_group_str=None, cell_dist_scale=1.0, tgtaxis2_isects=[0, 1, 0], ): """ Worms criteria for non-intersecting axes re: unbounded things assume tgtaxis1 goes through origin tgtaxis2 intersects tgtaxis2_isects Args: symname (str): Symmetry identifier, to label stuff and look up the symdef file. tgtaxis1: Target axis 1. tgtaxis2: Target axis 2. from_seg (int): The segment # to start at. tolerance (float): A geometry/alignment error threshold. Vaguely Angstroms. lever (float): Tradeoff with distances and angles for a lever-like object. To convert an angle error to a distance error for an oblong shape. to_seg (int): The segment # to end at. space_group_str: The target space group. """ self.symname = symname self.cell_dist_scale = cell_dist_scale self.tgtaxis1 = np.asarray( tgtaxis1, dtype="f8" ) ## we are treating these as vectors for now, make it an array if it isn't yet, set array type to 8-type float self.tgtaxis2 = np.asarray(tgtaxis2, dtype="f8") # print(self.tgtaxis1.shape) # print(np.linalg.norm(tgtaxis1)) self.tgtaxis1 /= np.linalg.norm( self.tgtaxis1) # normalize target axes to 1,1,1 self.tgtaxis2 /= np.linalg.norm(self.tgtaxis2) if hm.angle(self.tgtaxis1, self.tgtaxis2) > np.pi / 2: self.tgtaxis2 = -self.tgtaxis2 self.from_seg = from_seg self.tolerance = tolerance self.lever = lever self.to_seg = to_seg self.space_group_str = space_group_str ## if you want to store arguments, you have to write these self.argument lines self.target_angle = np.arccos( np.abs(hm.hdot(self.tgtaxis1, self.tgtaxis2)) ) ## already set to a non- self.argument in this function # print(self.target_angle * (180 / np.pi)) self.is_cyclic = False self.origin_seg = None self.tgtaxis2_isects = tgtaxis2_isects
def __init__(self, symname, tgtaxis1, tgtaxis2, from_seg=0, origin_seg=None, *, tolerance=1.0, lever=50, to_seg=-1, nondistinct_axes=False, segs=None, tgtaxis3=None): """ """ if from_seg == to_seg: raise ValueError("from_seg should not be same as to_seg") self.symname = symname self.from_seg = from_seg if len(tgtaxis1) == 2: tgtaxis1 += ([0, 0, 0, 1], ) if len(tgtaxis2) == 2: tgtaxis2 += ([0, 0, 0, 1], ) self.tgtaxis1 = ( tgtaxis1[0], hm.hnormalized(tgtaxis1[1]), hm.hpoint(tgtaxis1[2]), ) self.tgtaxis2 = ( tgtaxis2[0], hm.hnormalized(tgtaxis2[1]), hm.hpoint(tgtaxis2[2]), ) if tgtaxis3: if len(tgtaxis3) == 2: tgtaxis3 += ([0, 0, 0, 1], ) self.tgtaxis3 = ( tgtaxis3[0], hm.hnormalized(tgtaxis3[1]), hm.hpoint(tgtaxis3[2]), ) assert 3 == len(self.tgtaxis3) assert 3 == len(self.tgtaxis1) assert 3 == len(self.tgtaxis2) self.tgtangle = hm.angle(tgtaxis1[1], tgtaxis2[1]) self.tolerance = tolerance self.lever = lever self.to_seg = to_seg self.rot_tol = tolerance / lever self.nondistinct_axes = nondistinct_axes # -z not same as z (for T33) self.sym_axes = [self.tgtaxis1, self.tgtaxis2] self.is_cyclic = False self.origin_seg = None self.segs = segs