From 7ffdf594e9eebe82ca44cbb3c1ed412571fe20fe Mon Sep 17 00:00:00 2001 From: Chris Maffeo <cmaffeo2@illinois.edu> Date: Tue, 28 Jul 2020 18:41:35 -0500 Subject: [PATCH] Fixed model_from_lists for 3'-to-5' structures; fixed issue with single-nucleotide 'crossovers'; added debug flag for tracing strands --- mrdna/readers/segmentmodel_from_lists.py | 30 ++++++--------- mrdna/segmentmodel.py | 48 +++++++++++++++++------- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/mrdna/readers/segmentmodel_from_lists.py b/mrdna/readers/segmentmodel_from_lists.py index 96f610a..c1ce49b 100644 --- a/mrdna/readers/segmentmodel_from_lists.py +++ b/mrdna/readers/segmentmodel_from_lists.py @@ -307,24 +307,17 @@ def model_from_basepair_stack_3prime(coordinate, basepair, stack, three_prime, assert( np.all(bps[ss_residues] == -1) ) for s,c in zip(strands, strand_is_circular): - ss_residues = s[np.where(hmap[s] < 0)[0]] - if len(ss_residues) == 0: continue - resid_diff = np.diff(ss_residues) - - tmp = np.where( resid_diff != 1 )[0] - first_res = ss_residues[0] - for i in tmp: - ids = np.arange(first_res, ss_residues[i]+1) - assert( np.all(hmap[ids] == -1) ) - hmap[ids] = hid - hrank[ids] = ids-first_res - first_res = ss_residues[i+1] - hid += 1 - ids = np.arange(first_res, ss_residues[-1]+1) - assert( np.all(hmap[ids] == -1) ) - hmap[ids] = hid - hrank[ids] = ids-first_res - hid+=1 + strand_segment_ends = [i for i in np.where( np.diff(hmap[s]) != 0 )[0]] + [len(s)-1] + seg_start = 0 + for i in strand_segment_ends: + if hmap[s[i]] < 0: + ## Found single-stranded segment + ids = s[seg_start:i+1] + assert( np.all(hmap[ids] == -1) ) + hmap[ids] = hid + hrank[ids] = np.arange(i+1-seg_start) + hid+=1 + seg_start = i+1 single_stranded_helices = np.arange(double_stranded_helices[-1]+1,hid) @@ -419,6 +412,7 @@ def model_from_basepair_stack_3prime(coordinate, basepair, stack, three_prime, s = allSegments[hid] s.sequence = [sequence[r] for r in sorted(resids,key=lambda x: hrank[x])] + ## Build model model = SegmentModel( allSegments, max_basepairs_per_bead = max_basepairs_per_bead, diff --git a/mrdna/segmentmodel.py b/mrdna/segmentmodel.py index b7603b7..3e1c069 100644 --- a/mrdna/segmentmodel.py +++ b/mrdna/segmentmodel.py @@ -23,7 +23,6 @@ from .model.spring_from_lp import k_twist as twist_spring_from_lp import csv - # import pdb """ TODO: @@ -48,6 +47,9 @@ TODO: - refactor parts of Segment into an abstract_polymer class - make each call generate_bead_model, generate_atomic_model, generate_oxdna_model return an object with only have a reference to original object """ + +_DEBUG_TRACE = False + class CircularDnaError(Exception): pass @@ -947,7 +949,8 @@ class Segment(ConnectableElement, Group): ## Stop if we found the 3prime end if l.on_fwd_strand == is_fwd and l.type_ == "3prime" and l.connection is None: - # print(" found end at",l) + if _DEBUG_TRACE: + print(" found end at",l) return pos, None, None, None, None ## Check location connections @@ -957,15 +960,17 @@ class Segment(ConnectableElement, Group): ## Found a location on the same strand? if l.on_fwd_strand == is_fwd: - # print(" passing through",l) - # print("from {}, connection {} to {}".format(nt_pos,l,B)) + if _DEBUG_TRACE: + print(" passing through",l) + print("from {}, connection {} to {}".format(nt_pos,l,B)) Bpos = B.get_nt_pos() return pos, B.container, Bpos, B.on_fwd_strand, 0.5 ## Stop at other strand crossovers so basepairs line up elif c.type_ == "crossover": if nt_pos == pos: continue - # print(" pausing at",l) + if _DEBUG_TRACE: + print(" pausing at",l) return pos, l.container, pos+(2*is_fwd-1), is_fwd, 0 raise Exception("Shouldn't be here") @@ -1350,14 +1355,26 @@ class SingleStrandedSegment(Segment): assert(nt < self.num_nt) assert(other_nt < other.num_nt) - if nt in (0,1,self.num_nt-1) and other_nt in (0,1,other.num_nt-1): - if nt_on_5prime == True: - other_end = other.start5 if strands_fwd[1] else other.end5 - self.connect_end3( other_end ) - else: - other_end = other.end3 if strands_fwd[1] else other.start3 - self.connect_start5( other_end ) - return + if nt_on_5prime: + if nt == self.num_nt-1 and other_nt in (0,other.num_nt-1): + other_end = None + if strands_fwd[1] and other_nt == 0: + other_end = other.start5 + elif (not strands_fwd[1]) and other_nt == other.num_nt-1: + other_end = other.end5 + if other_end is not None: + self.connect_end3( other_end ) + return + else: + if nt == 0 and other_nt in (0,other.num_nt-1): + other_end = None + if strands_fwd[1] and other_nt == other.num_nt-1: + other_end = other.end3 + elif (not strands_fwd[1]) and other_nt == 0: + other_end = other.start3 + if other_end is not None: + self.connect_start5( other_end ) + return # c1 = self.nt_pos_to_contour(nt) # # TODOTODO @@ -3194,7 +3211,8 @@ class SegmentModel(ArbdModel): if locs is None: continue # for pos, is_fwd in locs: for l in locs: - # print("Tracing",l) + if _DEBUG_TRACE: + print("Tracing 5prime",l) # TODOTODO pos = seg.contour_to_nt_pos(l.address, round_nt=True) is_fwd = l.on_fwd_strand @@ -3240,6 +3258,8 @@ class SegmentModel(ArbdModel): history = [] if not strands_cover_segment(seg, is_fwd): pos = nt = find_nt_not_in_strand(seg, is_fwd) + if _DEBUG_TRACE: + print("Tracing circular strand", pos, is_fwd) s = Strand(segname="S{:03d}".format(len(strands)), is_circular = True) history = _recursively_build_strand(s, seg, pos, is_fwd) -- GitLab