From 671f16053f14a6cb1e75ed64a3f618385f039b68 Mon Sep 17 00:00:00 2001 From: Chris Maffeo <cmaffeo2@illinois.edu> Date: Mon, 17 Sep 2018 15:45:44 -0500 Subject: [PATCH] Fixed multiple issues; 3-prime ends of nucleotides now terminate correctly; strands not cleared unless atoms exist; strands regenerated with atomic model; cadnano models initialized with more correct azimuthal angle --- mrdna/model/arbdmodel.py | 13 ++++++------- mrdna/model/nbPot.py | 22 +++++++++++++++------- mrdna/readers/cadnano_segments.py | 5 +++-- mrdna/segmentmodel.py | 21 +++++++++++++++------ 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/mrdna/model/arbdmodel.py b/mrdna/model/arbdmodel.py index cd21983..6fb1c03 100644 --- a/mrdna/model/arbdmodel.py +++ b/mrdna/model/arbdmodel.py @@ -1105,13 +1105,12 @@ cellBasisVector3 0 0 {cellZ} if {{$nLast == 0}} {{ temperature 300 - fixedAtoms on - fixedAtomsForces on - fixedAtomsFile $prefix.pdb - fixedAtomsCol B - minimize 2400 - - fixedAtoms off + # fixedAtoms on + # fixedAtomsForces on + # fixedAtomsFile $prefix.pdb + # fixedAtomsCol B + # minimize 2400 + # fixedAtoms off minimize 2400 }} else {{ bincoordinates {output_directory}/$prefix-$nLast.restart.coor diff --git a/mrdna/model/nbPot.py b/mrdna/model/nbPot.py index 1b9c145..56e46b9 100644 --- a/mrdna/model/nbPot.py +++ b/mrdna/model/nbPot.py @@ -3,8 +3,8 @@ import scipy.optimize as opt from scipy.interpolate import interp1d from scipy.signal import savgol_filter as savgol -from .nonbonded import NonbondedScheme -from .. import get_resource_path +from mrdna.model.nonbonded import NonbondedScheme +from mrdna import get_resource_path dxParam = -1 @@ -33,7 +33,7 @@ y0 = d[:,0] # kcal/mol for 10bp with 10bp, according to JY y0 = y0 - np.mean(y0[x0>(38.5 + dxParam)]) # set 0 to tail of potential y0 = savgol(y0, int(5.0/(x0[1]-x0[0])), 3) # smooth potential -def pot(x,*parms): +def parametric_potential(x,*parms): x = np.array(x) u = interp1d(x0, np.array(parms), bounds_error = False, fill_value="extrapolate", @@ -41,7 +41,7 @@ def pot(x,*parms): u[x>np.max(x0)] = 0 return u -def potForBp(potfn,x,numBp,*parms): +def integrated_potential(potfn,x,numBp,*parms): u = np.zeros(np.shape(x)) for h in range(-numBp,numBp+1): r = np.sqrt(x**2 + (3.4*h)**2) @@ -50,7 +50,8 @@ def potForBp(potfn,x,numBp,*parms): return u def fitFun(x,*parms): - return 10 * potForBp(pot,x,20,*parms) + ## 1-turn iteracting with 4 turns (more is not needed) + return 10 * integrated_potential(parametric_potential,x,20,*parms) xinterp = np.linspace(np.min(x0),np.max(x0),1000) # interpolate potentialb yinterp = interp1d(x0,y0)(xinterp) @@ -62,9 +63,9 @@ def nbPot(x,bps1,bps2): if larger >= 2: largerInt = int(0.5*larger) smaller *= larger/(2*largerInt) - y = smaller * potForBp(pot,x,largerInt,*popt) + y = smaller * integrated_potential(parametric_potential,x,largerInt,*popt) else: - y = smaller * larger * pot(x,*popt) + y = smaller * larger * parametric_potential(x,*popt) y = maxForce(x,y, 100) y = savgol(y, int(5.0/(x0[1]-x0[0])), 3) return y @@ -99,3 +100,10 @@ class nbDnaScheme(NonbondedScheme): u = nbPot(r, 0.5*typeA.nts, 0.5*typeB.nts) return u nbDnaScheme = nbDnaScheme() + +if __name__ == "__main__": + ## run some tests + np.savetxt("jj-filtered.dat", np.array((x0,y0)).T) + y = fitFun(x,*popt) + np.savetxt("1-bp-fit.dat", np.array((x,y)).T), + diff --git a/mrdna/readers/cadnano_segments.py b/mrdna/readers/cadnano_segments.py index 849de60..59fb2fe 100644 --- a/mrdna/readers/cadnano_segments.py +++ b/mrdna/readers/cadnano_segments.py @@ -5,7 +5,7 @@ import os,sys from glob import glob import re -from ..coords import readArbdCoords, readAvgArbdCoords +from ..coords import readArbdCoords, readAvgArbdCoords, rotationAboutAxis from ..segmentmodel import SegmentModel, SingleStrandedSegment, DoubleStrandedSegment from ..model.dna_sequence import m13 as m13seq @@ -311,7 +311,8 @@ class cadnano_part(SegmentModel): ## TODO get sequence from cadnano api if zMid in strandOccupancies[0] and zMid in strandOccupancies[1]: kwargs['num_bp'] = numBps - seg = DoubleStrandedSegment(**kwargs,**posargs1) + start_orientation = rotationAboutAxis(np.array((0,0,1)), (zid1-3.25)*34) + seg = DoubleStrandedSegment(**kwargs,**posargs1, start_orientation = start_orientation) elif zMid in strandOccupancies[0]: kwargs['num_nt'] = numBps seg = SingleStrandedSegment(**kwargs,**posargs1) diff --git a/mrdna/segmentmodel.py b/mrdna/segmentmodel.py index f260055..c8efc6a 100644 --- a/mrdna/segmentmodel.py +++ b/mrdna/segmentmodel.py @@ -506,6 +506,9 @@ class Segment(ConnectableElement, Group): else: orientation0 = np.eye(3) if axis.dot(zAxis) > 0 else \ rotationAboutAxis( np.array((1,0,0)), 180, normalizeAxis=False ) + if self.start_orientation is not None: + orientation0 = orientation0.dot(self.start_orientation) + orientation = rotationAboutAxis( axis, self.twist_per_nt*self.contour_to_nt_pos(s), normalizeAxis=False ) orientation = orientation.dot(orientation0) else: @@ -572,7 +575,7 @@ class Segment(ConnectableElement, Group): if scale is not None and scale != 1: for a in atoms: a.position = scale*a.position - a.beta = 0 + a.fixed = 1 atoms.position = pos - atoms.atoms_by_name["C1'"].collapsedPosition() else: if scale is not None and scale != 1: @@ -583,7 +586,7 @@ class Segment(ConnectableElement, Group): for a in atoms: if a.name[-1] in ("'","P","T"): a.position = scale*(a.position-r0) + r0 - a.beta = 0 + a.fixed = 1 atoms.position = pos atoms.contour_position = contour_position @@ -1321,14 +1324,15 @@ class Strand(Group): # pdb.set_trace() # assert(s.end != s.start) assert( s.num_nt == 1 or (np.linalg.norm( seg.contour_to_position(contour[-1]) - seg.contour_to_position(contour[0]) ) > 0.1) ) + nucleotide_count = 0 for c,seq in zip(contour,s.get_sequence()): + nucleotide_count += 1 if last is None and not self.is_circular: seq = "5"+seq - if strand_segment_count == len(s.strand_segments) and c == 1 and not self.is_circular: + if strand_segment_count == len(s.strand_segments) and nucleotide_count == s.num_nt and not self.is_circular: seq = seq+"3" nt = seg._generate_atomic_nucleotide( c, s.is_fwd, seq, scale, s ) - s.add(nt) ## Join last basepairs if last is not None: @@ -1515,6 +1519,7 @@ class SegmentModel(ArbdModel): for seg in self.segments: for d in ('fwd','rev'): seg.strand_pieces[d] = [] + self._generate_strands() def clear_beads(self): return self._clear_beads() @@ -1525,7 +1530,8 @@ class SegmentModel(ArbdModel): s.clear_all() self.clear_all(keep_children=True) - self.clear_atomic() + if len(self.strands[0].children[0].children) > 0: + self.clear_atomic() ## Check that it worked assert( len([b for b in self]) == 0 ) @@ -2355,6 +2361,9 @@ class SegmentModel(ArbdModel): try: for s in self.strands: self.children.remove(s) + for seg in self.segments: + for d in ('fwd','rev'): + seg.strand_pieces[d] = [] except: ... self.strands = strands = [] @@ -2674,7 +2683,7 @@ class SegmentModel(ArbdModel): # print("WARNING: could not find 'P' atom in {}:{} or {}:{}".format( segI, ntI_idx, segJ, ntJ_idx )) ... - print("PUSH BONDS:", len(push_bonds)) + # print("PUSH BONDS:", len(push_bonds)) if not self.useTclForces: with open("%s.exb" % output_name, 'a') as fh: -- GitLab