From dbc26c65735f10938b2d90ade969cf1c60f0aad2 Mon Sep 17 00:00:00 2001 From: Chris Maffeo <cmaffeo2@illinois.edu> Date: Fri, 21 Dec 2018 13:12:54 -0600 Subject: [PATCH] Improved orientation spline updates for ssDNA --- mrdna/segmentmodel.py | 102 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 84 insertions(+), 18 deletions(-) diff --git a/mrdna/segmentmodel.py b/mrdna/segmentmodel.py index 5a9f4c5..23c7da0 100644 --- a/mrdna/segmentmodel.py +++ b/mrdna/segmentmodel.py @@ -1749,27 +1749,93 @@ class SegmentModel(ArbdModel): s.position_spline_params = (tck,u) - """ Get twist """ - cb = [e for e in zip(contours,beads) if 'orientation_bead' in e[1].__dict__] - beads = [b for c,b in cb] - contours = [c for c,b in cb] - ids = [b.idx for b in beads] - # if 'orientation_bead' in beads[0].__dict__: - if len(beads) > 3: - tangents = s.contour_to_tangent(contours) + """ Get orientation """ + def get_orientation_vector(bead,tangent): + if 'orientation_bead' in bead.__dict__: + o = bead.orientation_bead + oVec = bead_coordinates[o.idx,:] - bead_coordinates[bead.idx,:] + oVec = oVec - oVec.dot(tangent)*tangent + oVec = oVec/np.linalg.norm(oVec) + else: + oVec = None + return oVec + + def remove_tangential_projection(vector, tangent): + """ Assume tangent is normalized """ + v = vector - vector.dot(tangent)*tangent + return v/np.linalg.norm(v) + + def get_orientation_vector(bead,tangent): + if 'orientation_bead' in bead.__dict__: + o = bead.orientation_bead + oVec = bead_coordinates[o.idx,:] - bead_coordinates[bead.idx,:] + oVec = remove_tangential_projection(oVec,tangent) + else: + oVec = None + return oVec + + + def get_previous_idx_if_none(list_): + previous = None + result = [] + i = 0 + for e in list_: + if e is None: + result.append(previous) + else: + previous = i + i+=1 + return result + def get_next_idx_if_none(list_): + tmp = get_previous_idx_if_none(list_[::-1])[::-1] + return [ len(list_)-1-idx if idx is not None else idx for idx in tmp ] + + def fill_in_orientation_vectors(contours,orientation_vectors,tangents): + result = [] + last_idx = get_previous_idx_if_none( orientation_vectors ) + next_idx = get_next_idx_if_none( orientation_vectors ) + none_idx = 0 + for c,ov,t in zip(contours,orientation_vectors,tangents): + if ov is not None: + result.append(ov) + else: + p = last_idx[none_idx] + n = next_idx[none_idx] + none_idx += 1 + if p is None: + if n is None: + ## Should be quite rare; give something random if it happens + print("WARNING: unable to interpolate orientation") + o = np.array((1,0,0)) + result.append( remove_tangential_projection(o,t) ) + else: + o = orientation_vectors[n] + result.append( remove_tangential_projection(o,t) ) + else: + if n is None: + o = orientation_vectors[p] + result.append( remove_tangential_projection(o,t) ) + else: + cp,cn = [contours[i] for i in (p,n)] + op,on = [orientation_vectors[i] for i in (p,n)] + if (cn-cp) > 1e-6: + o = ((cn-c)*op+(c-cp)*on)/(cn-cp) + else: + o = op+on + result.append( remove_tangential_projection(o,t) ) + return result + + tangents = s.contour_to_tangent(contours) + orientation_vectors = [get_orientation_vector(b,t) for b,t in zip(beads,tangents)] + if len(beads) > 3 and any([e is not None for e in orientation_vectors] ): + orientation_vectors = fill_in_orientation_vectors(contours, orientation_vectors, tangents) + quats = [] lastq = None - for b,t in zip(beads,tangents): - o = b.orientation_bead - # positions - # angleVec = o.position - b.position - angleVec = bead_coordinates[o.idx,:] - bead_coordinates[b.idx,:] - angleVec = angleVec - angleVec.dot(t)*t - angleVec = angleVec/np.linalg.norm(angleVec) - y = np.cross(t,angleVec) + for b,t,oVec in zip(beads,tangents,orientation_vectors): + y = np.cross(t,oVec) assert( np.abs(np.linalg.norm(y) - 1) < 1e-2 ) - q = quaternion_from_matrix( np.array([angleVec,y,t]).T) - # q = quaternion_from_matrix( np.array([angleVec,y,t])) + q = quaternion_from_matrix( np.array([oVec,y,t]).T) if lastq is not None: if q.dot(lastq) < 0: -- GitLab