From 3fefcc4906a2f35ab30cf7ecb5a3cb7866a51019 Mon Sep 17 00:00:00 2001
From: pinyili2 <pinyili2@illinois.edu>
Date: Sun, 4 Aug 2024 17:29:14 -0500
Subject: [PATCH] a

---
 .../.ipynb_checkpoints/__init__-checkpoint.py |   39 -
 .../cadnano_segments-checkpoint.py            |  727 ------------
 .../segmentmodel_from_lists-checkpoint.py     |  495 --------
 ...egmentmodel_from_oxdna_pinyi-checkpoint.py |  162 ---
 .../.ipynb_checkpoints/test-checkpoint.ipynb  | 1053 +++++++++++++++--
 .../readers/.segmentmodel_from_cadnano.py.swp |  Bin 0 -> 16384 bytes
 mrdna/readers/cadnano_segments.py             |  319 ++---
 mrdna/readers/libs                            |    1 +
 mrdna/readers/list.pdb                        |   14 +-
 mrdna/readers/list.psf                        |   20 +-
 mrdna/readers/test.ipynb                      | 1053 +++++++++++++++--
 mrdna/readers/test.json.oxdna                 |  418 +++++++
 mrdna/readers/test.json.top                   |  416 +++++++
 mrdna/readers/test.virt2nuc                   |  Bin 0 -> 6565 bytes
 mrdna/readers/test2.ipynb                     |  973 +++++++++++++++
 15 files changed, 3891 insertions(+), 1799 deletions(-)
 delete mode 100644 mrdna/readers/.ipynb_checkpoints/__init__-checkpoint.py
 delete mode 100644 mrdna/readers/.ipynb_checkpoints/cadnano_segments-checkpoint.py
 delete mode 100644 mrdna/readers/.ipynb_checkpoints/segmentmodel_from_lists-checkpoint.py
 delete mode 100644 mrdna/readers/.ipynb_checkpoints/segmentmodel_from_oxdna_pinyi-checkpoint.py
 create mode 100644 mrdna/readers/.segmentmodel_from_cadnano.py.swp
 create mode 120000 mrdna/readers/libs
 create mode 100644 mrdna/readers/test.json.oxdna
 create mode 100644 mrdna/readers/test.json.top
 create mode 100644 mrdna/readers/test.virt2nuc
 create mode 100644 mrdna/readers/test2.ipynb

diff --git a/mrdna/readers/.ipynb_checkpoints/__init__-checkpoint.py b/mrdna/readers/.ipynb_checkpoints/__init__-checkpoint.py
deleted file mode 100644
index 7e0e4db..0000000
--- a/mrdna/readers/.ipynb_checkpoints/__init__-checkpoint.py
+++ /dev/null
@@ -1,39 +0,0 @@
-## TODO: make module this package conform to a single style for input/output
-
-def read_cadnano(json_file, sequence=None, fill_sequence='T', **model_parameters):
-    from .cadnano_segments import read_json_file
-    from .cadnano_segments import read_model as model_from_cadnano_json
-
-    data = read_json_file(json_file)
-    return model_from_cadnano_json(data, sequence, fill_sequence, **model_parameters)
-
-def read_vhelix(maya_file, **model_parameters):
-    from .polygon_mesh import parse_maya_file, convert_maya_bases_to_segment_model
-
-    maya_bases = parse_maya_file(maya_file)
-    model = convert_maya_bases_to_segment_model( maya_bases, **model_parameters )
-    return model
-
-def read_list(infile,**model_parameters):
-    import numpy as np
-    try:
-        data = np.loadtxt(infile)
-    except:
-        data = np.loadtxt(infile,skiprows=1) # strip header
-    coords = data[:,:3]*10
-    bp = data[:,3]
-    stack = data[:,4]
-    three_prime = data[:,5]
-
-    from .segmentmodel_from_lists import model_from_basepair_stack_3prime
-    return model_from_basepair_stack_3prime(coords, bp, stack, three_prime)
-
-
-def read_atomic_pdb(pdb_file, **model_parameters):
-    from .segmentmodel_from_pdb import SegmentModelFromPdb
-    return SegmentModelFromPdb(pdb_file)
-
-def read_oxdna(coordinate_file, topology_file, idealized_coordinate_file=None, **model_parameters):
-    """ Idealized coordinate file: coordinates for detecting stacks and base pairs, defaults to coordinate_file """ 
-    from .segmentmodel_from_oxdna import mrdna_model_from_oxdna
-    return mrdna_model_from_oxdna(coordinate_file, topology_file, idealized_coordinate_file, **model_parameters)
diff --git a/mrdna/readers/.ipynb_checkpoints/cadnano_segments-checkpoint.py b/mrdna/readers/.ipynb_checkpoints/cadnano_segments-checkpoint.py
deleted file mode 100644
index b39bd2e..0000000
--- a/mrdna/readers/.ipynb_checkpoints/cadnano_segments-checkpoint.py
+++ /dev/null
@@ -1,727 +0,0 @@
-# -*- coding: utf-8 -*-
-import pdb
-import numpy as np
-import os,sys
-from glob import glob
-import re
-
-from ..arbdmodel.coords import readArbdCoords, readAvgArbdCoords, rotationAboutAxis
-from ..segmentmodel import SegmentModel, SingleStrandedSegment, DoubleStrandedSegment
-from ..model.dna_sequence import m13 as m13seq
-
-
-## TODO: separate SegmentModel from ArbdModel so multiple parts can be combined
-## TODO: catch circular strands in "get_5prime" cadnano calls
-## TODO: handle special motifs
-##   - doubly-nicked helices
-##   - helices that should be stacked across an empty region (crossovers from and end in the helix to another end in the helix)
-##   - circular constructs
-
-def combineRegionLists(loHi1,loHi2,intersect=False):
-
-    """Combines two lists of (lo,hi) pairs specifying integer
-    regions a single list of regions.  """
-
-    ## Validate input
-    for l in (loHi1,loHi2):
-        ## Assert each region in lists is sorted
-        for pair in l:
-            assert(len(pair) == 2)
-            assert(pair[0] <= pair[1])
-
-    if len(loHi1) == 0:
-        if intersect:
-            return []
-        else:
-            return loHi2
-    if len(loHi2) == 0:
-        if intersect:
-            return []
-        else:
-            return loHi1
-
-    ## Break input into lists of compact regions
-    compactRegions1,compactRegions2 = [[],[]]
-    for compactRegions,loHi in zip(
-            [compactRegions1,compactRegions2],
-            [loHi1,loHi2]):
-        tmp = []
-        lastHi = loHi[0][0]-1
-        for lo,hi in loHi:
-            if lo-1 != lastHi:
-                compactRegions.append(tmp)
-                tmp = []
-            tmp.append((lo,hi))
-            lastHi = hi
-        if len(tmp) > 0:
-            compactRegions.append(tmp)
-
-    ## Build result
-    result = []
-    region = []
-    i,j = [0,0]
-    compactRegions1.append([[1e10]])
-    compactRegions2.append([[1e10]])
-    while i < len(compactRegions1)-1 or j < len(compactRegions2)-1:
-        cr1 = compactRegions1[i]
-        cr2 = compactRegions2[j]
-
-        ## initialize region
-        if len(region) == 0:
-            if cr1[0][0] <= cr2[0][0]:
-                region = cr1
-                i += 1
-                continue
-            else:
-                region = cr2
-                j += 1
-                continue
-
-        if region[-1][-1] >= cr1[0][0]:
-            region = combineCompactRegionLists(region, cr1, intersect=False)
-            i+=1
-        elif region[-1][-1] >= cr2[0][0]:
-            region = combineCompactRegionLists(region, cr2, intersect=False)
-            j+=1
-        else:
-            result.extend(region)
-            region = []
-
-    assert( len(region) > 0 )
-    result.extend(region)
-    result = sorted(result)
-
-    # print("loHi1:",loHi1)
-    # print("loHi2:",loHi2)
-    # print(result,"\n")
-
-    if intersect:
-        lo = max( [loHi1[0][0], loHi2[0][0]] )
-        hi = min( [loHi1[-1][1], loHi2[-1][1]] )
-        result = [r for r in result if r[0] >= lo and r[1] <= hi]
-
-    return result
-
-def combineCompactRegionLists(loHi1,loHi2,intersect=False):
-
-    """Combines two lists of (lo,hi) pairs specifying regions within a
-    compact integer set into a single list of regions.
-
-    examples:
-    loHi1 = [[0,4],[5,7]]
-    loHi2 = [[2,4],[5,9]]
-    out = [(0, 1), (2, 4), (5, 7), (8, 9)]
-
-    loHi1 = [[0,3],[5,7]]
-    loHi2 = [[2,4],[5,9]]
-    out = [(0, 1), (2, 3), (4, 4), (5, 7), (8, 9)]
-    """
-
-    ## Validate input
-    for l in (loHi1,loHi2):
-        ## Assert each region in lists is sorted
-        for pair in l:
-            assert(len(pair) == 2)
-            assert(pair[0] <= pair[1])
-        ## Assert lists are compact
-        for pair1,pair2 in zip(l[::2],l[1::2]):
-            assert(pair1[1]+1 == pair2[0])
-
-    if len(loHi1) == 0:
-        if intersect:
-            return []
-        else:
-            return loHi2
-    if len(loHi2) == 0:
-        if intersect:
-            return []
-        else:
-            return loHi1
-
-    ## Find the ends of the region
-    lo = min( [loHi1[0][0], loHi2[0][0]] )
-    hi = max( [loHi1[-1][1], loHi2[-1][1]] )
-
-    ## Make a list of indices where each region will be split
-    splitAfter = []
-    for l,h in loHi2:
-        if l != lo:
-            splitAfter.append(l-1)
-        if h != hi:
-            splitAfter.append(h)
-
-    for l,h in loHi1:
-        if l != lo:
-            splitAfter.append(l-1)
-        if h != hi:
-            splitAfter.append(h)
-    splitAfter = sorted(list(set(splitAfter)))
-
-    # print("splitAfter:",splitAfter)
-
-    split=[]
-    last = -2
-    for s in splitAfter:
-        split.append(s)
-        last = s
-
-    # print("split:",split)
-    returnList = [(i+1,j) if i != j else (i,j) for i,j in zip([lo-1]+split,split+[hi])]
-
-    if intersect:
-        lo = max( [loHi1[0][0], loHi2[0][0]] )
-        hi = min( [loHi1[-1][1], loHi2[-1][1]] )
-        returnList = [r for r in returnList if r[0] >= lo and r[1] <= hi]
-
-    # print("loHi1:",loHi1)
-    # print("loHi2:",loHi2)
-    # print(returnList,"\n")
-    return returnList
-
-class cadnano_part(SegmentModel):
-    def __init__(self, part, 
-                 **kwargs
-    ):
-        self.part = part
-        self.lattice_type = _get_lattice(part)
-
-        self._cadnano_part_to_segments(part)
-        # SegmentModel.__init__(self,...)
-        # self.segments = [seg for hid,segs in self.helices.items() for seg in segs]
-        self.segments = [seg for hid,segs in sorted(self.helices.items()) for seg in segs]
-        self._add_intrahelical_connections()
-        self._add_crossovers()
-        self._add_prime_ends()
-        SegmentModel.__init__(self, self.segments,
-                              **kwargs)
-
-    def _get_helix_angle(self, helix_id, indices):
-        """ Get "start_orientation" for helix """
-        # import ipdb
-        # ipdb.set_trace()
-
-        """ FROM CADNANO2.5
-        + angle is CCW
-        - angle is CW
-        Right handed DNA rotates clockwise from 5' to 3'
-        we use the convention the 5' end starts at 0 degrees
-        and it's pair is minor_groove_angle degrees away
-        direction, hence the minus signs.  eulerZ
-        """
-
-        hp, bpr, tpr, eulerZ, mgroove = self.part.vh_properties.loc[helix_id,
-                                                                    ['helical_pitch',
-                                                                     'bases_per_repeat',
-                                                                     'turns_per_repeat',
-                                                                     'eulerZ',
-                                                                     'minor_groove_angle']]
-        twist_per_base = tpr*360./bpr
-        # angle = eulerZ - twist_per_base*indices + 0.5*mgroove + 180
-        angle = eulerZ + twist_per_base*indices - 0.5*mgroove
-        return angle
-
-    def _cadnano_part_to_segments(self,part):
-        try:
-            from cadnano.cnenum import PointType
-        except:
-            try:
-                from cadnano.proxies.cnenum import PointType
-            except:
-                from cadnano.proxies.cnenum import PointEnum as PointType
-
-        segments = dict()
-        self.helices = helices = dict()
-        self.helix_ranges = helix_ranges = dict()
-
-        props = part.getModelProperties().copy()
-        
-        if props.get('point_type') == PointType.ARBITRARY:
-            # TODO add code to encode Parts with ARBITRARY point configurations
-            raise NotImplementedError("Not implemented")
-        else:
-            try:
-                vh_props, origins = part.helixPropertiesAndOrigins()
-            except:
-                origins = {hid:part.getVirtualHelixOrigin(hid)[:2] for hid in part.getidNums()}
-
-        self.origins = origins
-
-        vh_list = []
-        strand_list = []
-        xover_list = []
-        self.xovers_from = dict()
-        self.xovers_to = dict()
-
-        try:
-            numHID = part.getMaxIdNum() + 1
-        except:
-            numHID = part.getIdNumMax() + 1
-
-        for id_num in range(numHID):
-            try:
-                offset_and_size = part.getOffsetAndSize(id_num)
-            except:
-                offset_and_size = None
-            if offset_and_size is None:
-                ## Add a placeholder for empty helix
-                vh_list.append((id_num, 0))
-                strand_list.append(None)
-            else:
-                offset, size = offset_and_size
-                vh_list.append((id_num, size))
-                fwd_ss, rev_ss = part.getStrandSets(id_num)
-                fwd_idxs, fwd_colors  = fwd_ss.dump(xover_list)
-                rev_idxs, rev_colors  = rev_ss.dump(xover_list)
-                strand_list.append((fwd_idxs, rev_idxs))
-
-            self.xovers_from[id_num] = []
-            self.xovers_to[id_num] = []
-
-        for xo in xover_list:
-            h1,f1,z1,h2,f2,z2 = xo
-            self.xovers_from[h1].append(xo)
-            self.xovers_to[h2].append(xo)
-
-        ## Get lists of 5/3prime ends
-        strands5 = [o.strand5p() for o in part.oligos()]
-        strands3 = [o.strand3p() for o in part.oligos()]
-        
-        self._5prime_list = [(s.idNum(),s.isForward(),s.idx5Prime()) for s in strands5]
-        self._3prime_list = [(s.idNum(),s.isForward(),s.idx3Prime()) for s in strands3]
-
-        ## Get dictionary of insertions 
-        self.insertions = allInsertions = part.insertions()
-        self.strand_occupancies = dict()
-
-        ## Build helices 
-        for hid in range(numHID):
-            # print("Working on helix",hid)
-            helices[hid] = []
-            helix_ranges[hid] = []
-            self.strand_occupancies[hid] = []
-
-            helixStrands = strand_list[hid]
-            if helixStrands is None: continue
-
-            ## Build list of tuples containing (idx,length) of insertions/skips
-            insertions = sorted( [(i[0],i[1].length()) for i in allInsertions[hid].items()],
-                                 key=lambda x: x[0] )
-
-            ## TODO: make the following code (until "regions = ...") more readable
-            ## Build list of strand ends and list of mandatory node locations
-            ends1,ends2 = self._helixStrandsToEnds(helixStrands)
-
-            ## Find crossovers for this helix
-            reqNodeZids = sorted(list(set( ends1 + ends2 ) ) )
-            
-            ## Build lists of which nt sites are occupied in the helix
-            strandOccupancies = [ [x for i in range(0,len(e),2) 
-                                   for x in range(e[i],e[i+1]+1)] 
-                                  for e in (ends1,ends2) ]
-            self.strand_occupancies[hid] = strandOccupancies
-
-            ends1,ends2 = [ [(e[i],e[i+1]) for i in range(0,len(e),2)] for e in (ends1,ends2) ]
-
-            regions = combineRegionLists(ends1,ends2)
-
-            ## Split regions in event of ssDNA crossover
-            split_regions = []
-            for zid1,zid2 in regions:
-                zMid = int(0.5*(zid1+zid2))
-                if zMid in strandOccupancies[0] and zMid in strandOccupancies[1]:
-                    split_regions.append( (zid1,zid2) )
-                else:
-                    is_fwd = zMid in strandOccupancies[0]
-                    ends = [z for h,f,z in self._get_crossover_locations( hid, range(zid1+1,zid2), is_fwd )]
-                    z1 = zid1
-                    for z in sorted(ends):
-                        z2 = z
-                        if z2 > z1:
-                            split_regions.append( (z1,z2) )
-                            z1 = z2+1
-                    z2 = zid2
-                    split_regions.append( (z1,z2) )
-
-            # if hid == 43:
-            #     import pdb
-            for zid1,zid2 in split_regions:
-                zMid = int(0.5*(zid1+zid2))
-                assert( zMid in strandOccupancies[0] or zMid in strandOccupancies[1] )
-
-                bp_to_zidx = []
-                insertion_dict = {idx:length for idx,length in insertions}
-                for i in range(zid1,zid2+1):
-                    if i in insertion_dict:
-                        l = insertion_dict[i]
-                    else:
-                        l = 0
-                    for j in range(i,i+1+l):
-                        bp_to_zidx.append(i)
-                numBps = len(bp_to_zidx)
-
-                # print("Adding helix with length",numBps,zid1,zid2)
-
-                name = "%d-%d" % (hid,len(helices[hid]))
-                # "H%03d" % hid
-                kwargs = dict(name=name, segname=name, occupancy=hid)
-
-                posargs1 = dict( start_position = self._get_cadnano_position(hid,zid1-0.25),
-                                 end_position   = self._get_cadnano_position(hid,zid2+0.25) )
-                posargs2 = dict( start_position = posargs1['end_position'],
-                                 end_position = posargs1['start_position'])
-
-                ## TODO get sequence from cadnano api
-                if zMid in strandOccupancies[0] and zMid in strandOccupancies[1]:
-                    kwargs['num_bp'] = numBps
-                    _angle = self._get_helix_angle(hid, zid1)
-                    start_orientation = rotationAboutAxis(np.array((0,0,1)), _angle)
-                    seg = DoubleStrandedSegment(**kwargs,**posargs1, start_orientation = start_orientation)
-                elif zMid in strandOccupancies[0]:
-                    kwargs['num_nt'] = numBps
-                    seg = SingleStrandedSegment(**kwargs,**posargs1)
-                elif zMid in strandOccupancies[1]:
-                    kwargs['num_nt'] = numBps
-                    seg = SingleStrandedSegment(**kwargs,**posargs2)
-                else:
-                    raise Exception("Segment could not be found")
-
-                seg._cadnano_helix = hid
-                seg._cadnano_start = zid1
-                seg._cadnano_end   = zid2
-                seg._cadnano_bp_to_zidx = bp_to_zidx
-
-                def callback(segment):
-                    for b in segment.beads:
-                        bp = int(round(b.get_nt_position(segment)))
-                        if bp < 0: bp = 0
-                        if bp >= segment.num_nt: bp = segment.num_nt-1
-                        try:
-                            b.beta = segment._cadnano_bp_to_zidx[bp]
-                            if 'orientation_bead' in b.__dict__:
-                                b.orientation_bead.beta = segment._cadnano_bp_to_zidx[bp]
-                        except:
-                            pass
-                seg._generate_bead_callbacks.append(callback)
-
-                def atomic_callback(nucleotide, bp_to_zidx=bp_to_zidx):
-                    nt = nucleotide
-                    segment = nucleotide.parent.segment
-                    bp = int(round(segment.contour_to_nt_pos( nt.contour_position )))
-                    if bp < 0: bp = 0
-                    if bp >= segment.num_nt: bp = segment.num_nt-1
-                    try:
-                        nt.beta = bp_to_zidx[bp]
-                        nt.parent.occupancy = segment.occupancy
-                    except:
-                        pass
-                seg._generate_nucleotide_callbacks.append(atomic_callback)
-
-
-                helices[hid].append( seg )
-                helix_ranges[hid].append( (zid1,zid2) )
-
-    def _get_cadnano_position(self, hid, zid):
-        return [10*a for a in self.origins[hid]] + [-3.4*zid]
-
-    def _helixStrandsToEnds(self, helixStrands):
-        """Utility method to convert cadnano strand lists into list of
-        indices of terminal points"""
-
-        endLists = [[],[]]
-        for endList, strandList in zip(endLists,helixStrands):
-            lastStrand = None
-            for s in strandList:
-                if lastStrand is None:
-                    ## first strand
-                    endList.append(s[0])
-                elif lastStrand[1] != s[0]-1: 
-                    assert( s[0] > lastStrand[1] )
-                    endList.extend( [lastStrand[1], s[0]] )
-                lastStrand = s
-            if lastStrand is not None:
-                endList.append(lastStrand[1])
-        return endLists
-
-    def _helix_strands_to_segment_ranges(self, helix_strands):
-        """Utility method to convert cadnano strand lists into list of
-        indices of terminal points"""
-        def _join(strands):
-            ends = []
-            lastEnd = None
-            for start,end in strands:
-                if lastEnd is None:
-                    ends.append([start])
-                elif lastEnd != start-1:
-                    ends[-1].append(lastEnd)
-                    ends.append([start])
-                lastEnd = end
-            if lastEnd is not None:
-                ends[-1].append(lastEnd)
-            return ends
-
-        s1,s2 = [_join(s) for s in helix_strands]
-        i = j = 0
-        
-        ## iterate through strands
-        while i < len(s1) and j < len(s2):
-            min(s1[i][0],s2[j][0])
-
-    def _get_segment(self, hid, zid):
-        ## TODO: rename these variables to segments
-        segs = self.helices[hid]
-        ranges = self.helix_ranges[hid]
-        for i in range(len(ranges)):
-            zmin,zmax = ranges[i]
-            if zmin <= zid and zid <= zmax:
-                return segs[i]
-        raise Exception("Could not find segment in helix %d at position %d" % (hid,zid))
-                
-    def _get_nucleotide(self, hid, zid):
-        raise Exception("Deprecated")
-        seg = self._get_segment(hid,zid)
-        sid = self.helices[hid].index(seg)
-        zmin,zmax = self.helix_ranges[hid][sid]
-
-        nt = zid-zmin
-
-        ## Find insertions
-        # TODO: for i in range(zmin,zid+1): ?
-        for i in range(zmin,zid):
-            if i in self.insertions[hid]:
-                nt += self.insertions[hid][i].length()
-        return nt
-
-    def _get_segment_nucleotide(self, hid, zid, get_forward_location=False):
-        """ returns segments and zero-based nucleotide index """
-        seg = self._get_segment(hid,zid)
-        sid = self.helices[hid].index(seg)
-        zmin,zmax = self.helix_ranges[hid][sid]
-
-        zMid = int(0.5*(zmin+zmax))
-        occ = self.strand_occupancies[hid]
-        ins = self.insertions[hid]
-
-        ## TODO combine if/else when nested TODO is resolved
-        # if zid in self.insertions[hid]:
-        #     import pdb
-        #     pdb.set_trace()
-
-        if (zMid not in occ[0]) and (zMid in occ[1]):
-            ## reversed ssDNA strand
-            nt = zmax-zid
-            # TODO: for i in range(zmin,zid+1): ?
-            for i in range(zid,zmax+1):
-                if i in self.insertions[hid]:
-                    nt += self.insertions[hid][i].length()
-        else:
-            ## normal condition
-            if get_forward_location:
-                while zid in ins and ins[zid].length() < 0 and zid <= zmax:
-                    zid+=1
-            # else:
-            #     while zid in ins and ins[zid].length() > 0 and zid >= zmax:
-            #         zid-=1
-            nt = zid-zmin
-            for i in range(zmin,zid):
-                if i in ins:
-                    nt += ins[i].length()
-
-            if not get_forward_location and zid in ins:
-                nt += ins[zid].length()
-                
-        ## Find insertions
-        return seg, nt
-
-        
-
-    """ Routines to add connnections between helices """
-    def _add_intrahelical_connections(self):
-        for hid,segs in self.helices.items():
-            occ = self.strand_occupancies[hid]
-            for i in range(len(segs)-1):
-                seg1,seg2 = [segs[j] for j in (i,i+1)]
-                if isinstance(seg1,SingleStrandedSegment) and isinstance(seg2,SingleStrandedSegment):
-                    continue
-                r1,r2 = [self.helix_ranges[hid][j] for j in (i,i+1)]
-                if r1[1]+1 == r2[0]:
-                    ## TODO: handle nicks that are at intrahelical connections(?)
-                    zmid1 = int(0.5*(r1[0]+r1[1]))
-                    zmid2 = int(0.5*(r2[0]+r2[1]))
-
-                    ## TODO: validate
-                    if zmid1 in occ[0] and zmid2 in occ[0]:
-                        seg1.connect_end3(seg2.start5)
-
-                    if zmid1 in occ[1] and zmid2 in occ[1]:
-                        if zmid1 in occ[0]:
-                            end = seg1.end5
-                        else:
-                            end = seg1.start5
-                        if zmid2 in occ[0]:
-                            seg2.connect_start3(end)
-                        else:
-                            seg2.connect_end3(end)
-                        
-
-    def _get_crossover_locations(self, helix_idx, nt_idx_range, fwd_strand=None):
-        xos = []
-        def append_if_in_range(h,f,z):
-            if fwd_strand in (None,f) and z in nt_idx_range:
-                xos.append((h,f,z))
-
-        for xo in self.xovers_from[helix_idx]:
-            ## h1,f1,z1,h2,f2,z2 = xo[3:]
-
-            append_if_in_range(*xo[:3])
-        for xo in self.xovers_to[helix_idx]:
-            append_if_in_range(*xo[3:])
-        return xos
-
-    def _add_crossovers(self):
-        for hid,xos in self.xovers_from.items():
-            for h1,f1,z1,h2,f2,z2 in xos:
-                seg1, nt1 = self._get_segment_nucleotide(h1,z1,not f1)
-                seg2, nt2 = self._get_segment_nucleotide(h2,z2,f2)
-                ## TODO: use different types of crossovers
-                ## fwd?
-                ## 5'-to-3' direction
-                if isinstance(seg1, SingleStrandedSegment): f1 = True
-                if isinstance(seg2, SingleStrandedSegment): f2 = True
-                seg1.add_crossover(nt1,seg2,nt2,[f1,f2])
-
-    def _add_prime_ends(self):
-        for h,fwd,z in self._5prime_list:
-            seg, nt = self._get_segment_nucleotide(h,z, fwd)
-            if isinstance(seg, SingleStrandedSegment): fwd = True
-            # print("adding 5prime",seg.name,nt,fwd)
-            seg.add_5prime(nt,fwd)
-
-        for h,fwd,z in self._3prime_list:
-            seg, nt = self._get_segment_nucleotide(h,z, not fwd)
-            if isinstance(seg, SingleStrandedSegment): fwd = True
-            # print("adding 3prime",seg.name,nt,fwd)
-            seg.add_3prime(nt,fwd) 
-   
-    def get_bead(self, hid, zid):
-        # get segment, get nucleotide,
-        seg, nt = self._get_segment_nucleotide(h,z)
-        # return seg.get_nearest_bead(seg,nt / seg.num_nt)
-        return seg.get_nearest_bead(seg,nt / (seg.num_nt-1))
-        
-def read_json_file(filename):
-    import json
-    import re
-
-    try:
-        with open(filename) as ch:
-            data = json.load(ch)
-    except:
-        with open(filename) as ch:
-            content = ""
-            for l in ch:
-                l = re.sub(r"'", r'"', l)
-                # https://stackoverflow.com/questions/4033633/handling-lazy-json-in-python-expecting-property-name
-                # l = re.sub(r"{\s*(\w)", r'{"\1', l)
-                # l = re.sub(r",\s*(\w)", r',"\1', l)
-                # l = re.sub(r"(\w):", r'\1":', l)
-                content += l+"\n"
-            data = json.loads(content)
-    return data
-
-def decode_cadnano_part(json_data):
-    import cadnano
-    from cadnano.document import Document
-
-    try:
-        doc = Document()
-        cadnano.fileio.v3decode.decode(doc, json_data)
-        decoder = 3
-    except:
-        doc = Document()
-        cadnano.fileio.v2decode.decode(doc, json_data)
-        decoder = 2
-
-    parts = [p for p in doc.getParts()]
-    if len(parts) != 1:
-        raise Exception("Only documents containing a single cadnano part are implemented at this time.")
-    part = parts[0]
-
-    if decoder == 2:
-        """ It seems cadnano2.5 (as of ce6ff019) does not set the EulerZ for square lattice structures correctly, doing so here """
-        l = _get_lattice(part)
-        if l == 'square':
-            for id_num in part.getIdNums():
-                if part.vh_properties.loc[id_num,'eulerZ'] == 0:
-                    part.vh_properties.loc[id_num,'eulerZ'] = 360*(6/10.5)
-
-    return part
-
-def _get_lattice(part):
-    lattice_type = None
-    _gt = part.getGridType()
-    try:
-        lattice_type = _gt.name.lower()
-    except:
-        if _gt == 1:
-            lattice_type = 'square'
-        elif _gt == 2:
-            lattice_type = 'honeycomb'
-        else:
-            print("WARNING: unable to determine cadnano part lattice type")
-    return lattice_type
-
-def package_archive( name, directory ):
-    ...
-
-def read_model(json_data, sequence=None, fill_sequence='T', **kwargs):
-    """ Read in data """
-    part = decode_cadnano_part(json_data)
-    model = cadnano_part(part,
-                         **kwargs)
-
-    # TODO
-    # try:
-    #     model.set_cadnano_sequence()
-    # finally:
-    #     ...
-    #     if sequence is not None and len() :
-    #         model.strands[0].set_sequence(seq)
-
-    if sequence is None or len(sequence) == 0:
-        ## default m13mp18
-        model.set_sequence(m13seq,force=False, fill_sequence=fill_sequence)
-    else:
-        model.set_sequence(sequence, fill_sequence=fill_sequence)
-
-    return model
-
-# pynvml.nvmlInit()
-# gpus = range(pynvml.nvmlDeviceGetCount())
-# pynvml.nvmlShutdown()
-# gpus = [0,1,2]
-# print(gpus)
-
-if __name__ == '__main__':
-    loHi1 = [[0,4],[5,7]]
-    loHi2 = [[2,4],[5,9]]
-    out = [(0, 1), (2, 4), (5, 7), (8, 9)]
-    print(loHi1)
-    print(loHi2)
-    print(combineRegionLists(loHi1,loHi2))
-    print(combineCompactRegionLists(loHi1,loHi2))
-
-    loHi1 = [[0,3],[5,7]]
-    loHi2 = [[2,4],[5,9]]
-    out = [(0, 1), (2, 3), (4, 4), (5, 7), (8, 9)]
-    print(loHi1)
-    print(loHi2)
-    print(combineRegionLists(loHi1,loHi2))
-    print(combineCompactRegionLists(loHi1,loHi2))
-
-    combineRegionLists
-    
-    # for f in glob('json/*'):
-    #     print("Working on {}".format(f))
-    #     out = re.match('json/(.*).json',f).group(1)
-    #     data = read_json_file(f)
-    #     run_simulation_protocol( out, "job-id", data, gpu=0 )
diff --git a/mrdna/readers/.ipynb_checkpoints/segmentmodel_from_lists-checkpoint.py b/mrdna/readers/.ipynb_checkpoints/segmentmodel_from_lists-checkpoint.py
deleted file mode 100644
index 84eb17e..0000000
--- a/mrdna/readers/.ipynb_checkpoints/segmentmodel_from_lists-checkpoint.py
+++ /dev/null
@@ -1,495 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import pdb
-import numpy as np
-import os,sys
-import scipy
-
-from mrdna import logger, devlogger
-from ..segmentmodel import SegmentModel, SingleStrandedSegment, DoubleStrandedSegment
-from ..arbdmodel.coords import quaternion_from_matrix, rotationAboutAxis, quaternion_slerp
-from .. import get_resource_path
-
-ref_stack_position = np.array((-2.41851735, -0.259761333, 3.39999978))
-
-def _three_prime_list_to_five_prime(three_prime):
-    five_prime = -np.ones(three_prime.shape, dtype=int)
-    has_three_prime = np.where(three_prime >= 0)[0]
-    five_prime[three_prime[has_three_prime]] = has_three_prime
-    return five_prime  
-
-def _primes_list_to_strands(three_prime, five_prime):
-    five_prime_ends = np.where(five_prime < 0)[0]
-    strands = []
-    strand_is_circular = []
-    
-    idx_to_strand = -np.ones(three_prime.shape, dtype=int)
-
-    def build_strand(nt_idx, conditional):
-        strand = [nt_idx]
-        idx_to_strand[nt_idx] = len(strands)
-        while conditional(nt_idx):
-            nt_idx = three_prime[nt_idx]
-            strand.append(nt_idx)
-            idx_to_strand[nt_idx] = len(strands)
-        strands.append( np.array(strand, dtype=int) )
-
-    for nt_idx in five_prime_ends:
-        build_strand(nt_idx,
-                     lambda nt: three_prime[nt] >= 0)
-        strand_is_circular.append(False)
-
-    while True:
-        ## print("WARNING: working on circular strand {}".format(len(strands)))
-        ids = np.where(idx_to_strand < 0)[0]
-        if len(ids) == 0: break
-        build_strand(ids[0],
-                     lambda nt: three_prime[nt] >= 0 and \
-                     idx_to_strand[three_prime[nt]] < 0)
-        strand_is_circular.append(True)
-
-    return strands, strand_is_circular
-
-def find_stacks(centers, transforms):
-
-    ## Find orientation and center of each nucleotide
-    expected_stack_positions = []
-    for R,c in zip(transforms,centers):
-        expected_stack_positions.append( c + ref_stack_position.dot(R) )
-
-    expected_stack_positions = np.array(expected_stack_positions, dtype=np.float32)
-
-    dists = scipy.spatial.distance_matrix(expected_stack_positions, centers)
-    dists = dists + 5*np.eye(len(dists))
-    idx1, idx2 = np.where(dists < 3.5)
-
-    ## Convert distances to stacks
-    stacks_above = -np.ones(len(centers), dtype=int)
-    _z = np.array((0,0,1))
-    for i in np.unique(idx1):
-        js = idx2[ idx1 == i ]
-        with np.errstate(divide='ignore',invalid='ignore'):
-            angles = [np.arccos( transforms[j].T.dot( transforms[i].dot(_z) ).dot( _z ) ) for j in js]
-        angles = np.array( angles )
-        tmp = np.argmin(dists[i][js] + 1.0*angles)
-        j = js[tmp]
-        stacks_above[i] = j
-
-    return stacks_above
-
-def basepairs_and_stacks_to_helixmap(basepairs,stacks_above):
-
-    helixmap = -np.ones(basepairs.shape, dtype=int)
-    helixrank = -np.ones(basepairs.shape)
-    is_fwd = np.ones(basepairs.shape, dtype=int)
-    
-    ## Remove stacks with nts lacking a basepairs
-    nobp = np.where(basepairs < 0)[0]
-    stacks_above[nobp] = -1
-    stacks_with_nobp = np.in1d(stacks_above, nobp)
-    stacks_above[stacks_with_nobp] = -1
-
-    end_ids = np.where( (stacks_above < 0)*(basepairs >= 0) )[0]
-
-    hid = 0
-    for end in end_ids:
-        if helixmap[end] >= 0:
-            continue
-        rank = 0
-        nt = basepairs[end]
-        bp = basepairs[nt]
-        assert( bp == end )
-        if helixmap[nt] >= 0 or helixmap[bp] >= 0:
-            logger.warning(f'Ill-formed helix: problematic basepair or stacking data near nucleotide {nt} or {bp}... skipping')
-            continue
-        # assert(helixmap[nt] == -1)
-        # assert(helixmap[bp] == -1)
-        helixmap[nt] = helixmap[bp] = hid
-        helixrank[nt] = helixrank[bp] = rank
-        is_fwd[bp] = 0
-        rank +=1
-
-        _tmp = [(nt,bp)]
-        
-        while stacks_above[nt] >= 0:
-            nt = stacks_above[nt]
-            if basepairs[nt] < 0: break
-            bp = basepairs[nt]
-            if helixmap[nt] >= 0 or helixmap[bp] >= 0:
-                logger.warning(f'Ill-formed helix: problematic basepair or stacking data near nucleotide {nt} or {bp}... skipping')
-                break
-            helixmap[nt] = helixmap[bp] = hid
-            helixrank[nt] = helixrank[bp] = rank
-            is_fwd[bp] = 0
-            _tmp.append((nt,bp))
-            rank +=1
-
-        hid += 1
-
-    ## Create "helix" for each circular segment
-    intrahelical = []
-    processed = set()
-    unclaimed_bases = np.where( (basepairs >= 0)*(helixmap == -1) )[0]
-    for nt0 in unclaimed_bases:
-        if nt0 in processed: continue
-
-        nt = nt0
-        all_nts = [nt]
-
-        rank = 0
-        nt = nt0
-        bp = basepairs[nt]
-        if helixmap[nt] >= 0 or helixmap[bp] >= 0:
-            logger.warning(f'Ill-formed cylic helix: problematic basepair or stacking data near nucleotide {nt} or {bp}... skipping')
-            continue
-        helixmap[nt] = helixmap[bp] = hid
-        helixrank[nt] = helixrank[bp] = rank
-        is_fwd[bp] = 0
-        rank +=1
-        processed.add(nt)
-        processed.add(bp)
-
-        counter = 0
-        while stacks_above[nt] >= 0:
-            lastnt = nt
-            nt = stacks_above[nt]
-            bp = basepairs[nt]
-            if nt == nt0 or nt == basepairs[nt0]:
-                intrahelical.append((lastnt,nt0))
-                break
-                
-            assert( bp >= 0 )
-            if helixmap[nt] >= 0 or helixmap[bp] >= 0:
-                logger.warning(f'Ill-formed cyclic helix: problematic basepair or stacking data near nucleotide {nt} or {bp}... skipping')
-                break
-            
-            helixmap[nt] = helixmap[bp] = hid
-            helixrank[nt] = helixrank[bp] = rank
-            is_fwd[bp] = 0
-            processed.add(nt)
-            processed.add(bp)
-            rank +=1
-        hid += 1
-
-    return helixmap, helixrank, is_fwd, intrahelical
-
-
-def set_splines(seg, coordinate, hid, hmap, hrank, fwd, basepair, orientation=None):
-    maxrank = np.max( hrank[hmap==hid] )
-    if maxrank == 0:
-        ids = np.where((hmap == hid))[0]
-        pos = np.mean( [coordinate[r,:] for r in ids ], axis=0 )
-        coords = [pos,pos]
-        contours = [0,1]
-        if orientation is not None:
-            ids = np.where((hmap == hid) * fwd)[0]
-            assert( len(ids) == 1 )
-            q = quaternion_from_matrix( orientation[ids[0]] )
-            quats = [q, q]
-            coords[-1] = pos + orientation[ids[0]].dot(np.array((0,0,1)))
-
-    else:
-        coords,contours,quats = [[],[],[]]
-        last_q = None
-        for rank in range(int(maxrank)+1):
-            ids = np.where((hmap == hid) * (hrank == rank))[0]
-                
-            coords.append(np.mean( [coordinate[r,:] for r in ids ], axis=0 ))
-            contours.append( float(rank+0.5)/(maxrank+1) )
-            if orientation is not None:
-                ids = np.where((hmap == hid) * (hrank == rank) * fwd)[0]
-                assert(len(ids) == 1)
-                q = quaternion_from_matrix( orientation[ids[0]] )
-
-                if last_q is not None and last_q.dot(q) < 0:
-                    q = -q
-
-                ## Average quaterion with reverse direction
-                bp = basepair[ids[0]]
-                if bp >= 0:
-                    bp_o = orientation[bp].dot(rotationAboutAxis(np.array((1,0,0)),180))
-                    q2 = quaternion_from_matrix( bp_o )
-                    if q.dot(q2) < 0:
-                        q2 = -q2
-
-                    ## probably good enough, but slerp is better: q = (q + q2)*0.5
-                    q = quaternion_slerp(q,q2,0.5)
-
-                quats.append(q)
-                last_q = q
-
-    coords = np.array(coords)
-    seg.set_splines(contours,coords)
-    if orientation is not None:
-        quats = np.array(quats)
-        seg.set_orientation_splines(contours,quats)
-
-    seg.start_position = coords[0,:]
-    seg.end_position = coords[-1,:]
-
-
-def model_from_basepair_stack_3prime(coordinate, basepair, stack, three_prime,
-                                     sequence=None, orientation=None,
-                                     max_basepairs_per_bead = 5,
-                                     max_nucleotides_per_bead = 5,
-                                     local_twist = False,
-                                     dimensions=(5000,5000,5000),
-                                     **model_parameters):
-    """ 
-    Creates a SegmentModel object from lists of each nucleotide's
-    basepair, its stack (on 3' side) and its 3'-connected nucleotide
-
-    The first argument should be an N-by-3 numpy array containing the
-    coordinate of each nucleotide, where N is the number of
-    nucleotides. The following three arguments should be integer lists
-    where the i-th element corresponds to the i-th nucleotide; the
-    list element should the integer index of the corresponding
-    basepaired / stacked / phosphodiester-bonded nucleotide. If there
-    is no such nucleotide, the value should be -1.
-
-    Args:
-        basepair:  List of each nucleotide's basepair's index
-        stack:  List containing index of the nucleotide stacked on the 3' of each nucleotide
-        three_prime:  List of each nucleotide's the 3' end of each nucleotide
-
-    Returns:
-        SegmentModel
-    """
-
-    """ Validate Input """
-    inputs = (basepair,three_prime)
-    try:
-        basepair,three_prime = [np.array(a,dtype=int) for a in inputs]
-    except:
-        raise TypeError("One or more of the input lists could not be converted into a numpy array")
-    inputs = (basepair,three_prime)
-    coordinate = np.array(coordinate)
-
-    if np.any( [len(a.shape) > 1 for a in inputs] ):
-        raise ValueError("One or more of the input lists has the wrong dimensionality")
-
-    if len(coordinate.shape) != 2:
-        raise ValueError("Coordinate array has the wrong dimensionality")
-
-    inputs = (coordinate,basepair,three_prime)
-    if not np.all(np.diff([len(a) for a in inputs]) == 0):
-        raise ValueError("Inputs are not the same length")
-        
-    num_nt = len(basepair)
-    if sequence is not None and len(sequence) != num_nt:
-        raise ValueError("The 'sequence' parameter is the wrong length {} != {}".format(len(sequence),num_nt))
-
-    if orientation is not None:
-        orientation = np.array(orientation)
-        if len(orientation.shape) != 3:
-            raise ValueError("The 'orientation' array has the wrong dimensionality (should be Nx3x3)")
-        if orientation.shape != (num_nt,3,3):
-            raise ValueError("The 'orientation' array is not properly formatted")
-
-    if stack is None:
-        if orientation is not None:
-            stack = find_stacks(coordinate, orientation)
-        else:
-            ## Guess stacking based on 3' connectivity
-            stack = np.array(three_prime,dtype=int) # Assume nts on 3' ends are stacked
-            _stack_below = _three_prime_list_to_five_prime(stack)
-            _has_bp = (basepair >= 0)
-            _nostack = np.where( (stack == -1)*_has_bp )[0]
-            _has_stack_below = _stack_below[basepair[_nostack]] >= 0
-            _nostack2 = _nostack[_has_stack_below]
-            stack[_nostack2] = basepair[_stack_below[basepair[_nostack2]]]
-
-    else:
-        try:
-            stack = np.array(stack,dtype=int)
-        except:
-            raise TypeError("The 'stack' array could not be converted into a numpy integer array")
-
-        if len(stack.shape) != 1:
-            raise ValueError("The 'stack' array has the wrong dimensionality")
-
-        if len(stack) != num_nt:
-            raise ValueError("The length of the 'stack' array does not match other inputs")
-
-    bps = basepair              # alias
-
-    """ Fix stacks: require that the stack of a bp of a base's stack is its bp """
-    _has_bp =  (bps >= 0)
-    _has_stack = (stack >= 0)
-    _stack_has_basepair = (bps[stack] >= 0) * _has_stack
-    stack = np.where( (stack[bps[stack]] == bps) * _has_bp * _has_stack * _has_bp,
-                      stack, -np.ones(len(stack),dtype=int) )
-
-    five_prime = _three_prime_list_to_five_prime(three_prime)
-
-    """ Build map of dsDNA helices and strands """
-    hmap,hrank,fwd,intrahelical = basepairs_and_stacks_to_helixmap(bps,stack)
-    double_stranded_helices = np.unique(hmap[hmap >= 0])    
-    strands, strand_is_circular = _primes_list_to_strands(three_prime, five_prime)
-
-    """ Add ssDNA to hmap """
-    if len(double_stranded_helices) > 0:
-        hid = double_stranded_helices[-1]+1
-    else:
-        hid = 0
-    ss_residues = hmap < 0
-    #
-    if np.any(bps[ss_residues] != -1):
-        logger.warning(f'{np.sum(bps[ss_residues] != -1)} ssDNA nucleotides appear to have basepairs... ignoring')
-    
-    for s,c in zip(strands, strand_is_circular):
-        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
-
-    if len(double_stranded_helices) > 0:
-        single_stranded_helices = np.arange(double_stranded_helices[-1]+1,hid)
-    else:
-        single_stranded_helices = np.arange(hid)
-
-    ## Create double-stranded segments
-    doubleSegments = []
-    for hid in double_stranded_helices:
-        seg = DoubleStrandedSegment(name=str(hid),
-                                    num_bp = np.sum(hmap==hid)//2)
-        set_splines(seg, coordinate, hid, hmap, hrank, fwd, basepair, orientation)
-
-        assert(hid == len(doubleSegments))
-        doubleSegments.append(seg)
-
-    ## Create single-stranded segments
-    singleSegments = []
-    for hid in single_stranded_helices:
-        seg = SingleStrandedSegment(name=str(hid),
-                                    num_nt = np.sum(hmap==hid))
-        set_splines(seg, coordinate, hid, hmap, hrank, fwd, basepair, orientation)
-
-        assert(hid == len(doubleSegments) + len(singleSegments))
-        singleSegments.append(seg)
-
-    ## Find crossovers and 5prime/3prime ends
-    crossovers,prime5,prime3 = [[],[],[]]
-    for s,c in zip(strands,strand_is_circular):
-        tmp = np.where(np.diff(hmap[s]) != 0)[0]
-        for i in tmp:
-            crossovers.append( (s[i],s[i+1]) )
-        if c:
-            if hmap[s[-1]] != hmap[s[0]]:
-                crossovers.append( (s[-1],s[0]) )
-        else:
-            prime5.append(s[0])
-            prime3.append(s[-1])
-
-    ## Add connections
-    allSegments = doubleSegments+singleSegments
-
-    for r1,r2 in crossovers:
-        seg1,seg2 = [allSegments[hmap[i]] for i in (r1,r2)]
-        nt1,nt2 = [hrank[i] for i in (r1,r2)]
-        f1,f2 = [fwd[i] for i in (r1,r2)]
-
-        ## Handle connections at the ends
-        is_terminal1 = (nt1,f1) in ((0,0),(seg1.num_nt-1,1))
-        is_terminal2 = (nt2,f2) in ((0,1),(seg2.num_nt-1,0))
-
-        print(seg1,seg2, r1, r2, is_terminal1, is_terminal2)
-        if is_terminal1 or is_terminal2:
-            """ Ensure that we don't have three-way dsDNA junctions """
-            if is_terminal1 and (bps[r1] >= 0) and (five_prime[bps[r1]] >= 0) and (three_prime[r1] >= 0):
-                if (bps[five_prime[bps[r1]]] >= 0) and (bps[three_prime[r1]] >= 0):
-                    # is_terminal1 = (three_prime[r1] == bps[five_prime[bps[r1]]])
-                    is_terminal1 = hmap[five_prime[bps[r1]]] == hmap[three_prime[r1]]
-            if is_terminal2 and (bps[r2] >= 0) and (three_prime[bps[r2]] >= 0) and (five_prime[r2] >= 0):
-                if (bps[three_prime[bps[r2]]] >= 0) and (bps[five_prime[r2]] >= 0):
-                    # is_terminal2 = (five_prime[r2] == bps[three_prime[bps[r2]]])
-                    is_terminal2 = hmap[three_prime[bps[r2]]] == hmap[five_prime[r2]]
-                
-            """ Place connection """
-            if is_terminal1 and is_terminal2:
-                end1 = seg1.end3 if f1 else seg1.start3
-                end2 = seg2.start5 if f2 else seg2.end5
-                seg1._connect_ends( end1, end2, type_='intrahelical')
-            else:
-                seg1.add_crossover(nt1,seg2,nt2,[f1,f2],type_="terminal_crossover")
-        else:
-            seg1.add_crossover(nt1,seg2,nt2,[f1,f2])
-
-    ## Add 5prime/3prime ends
-    for r in prime5:
-        seg = allSegments[hmap[r]]
-        seg.add_5prime(hrank[r],fwd[r])
-    for r in prime3:
-        seg = allSegments[hmap[r]]
-        seg.add_3prime(hrank[r],fwd[r])
-
-    ## Add intrahelical connections to circular helical sections
-    for nt0,nt1 in intrahelical:
-        seg = allSegments[hmap[nt0]]
-        assert( seg is allSegments[hmap[nt1]] )
-        if three_prime[nt0] >= 0:
-            if hmap[nt0] == hmap[three_prime[nt0]]:
-                seg.connect_end3(seg.start5)
-
-        bp0,bp1 = [bps[nt] for nt in (nt0,nt1)]
-        if three_prime[bp1] >= 0:
-            if hmap[bp1] == hmap[three_prime[bp1]]:
-                seg.connect_start3(seg.end5)
-
-    ## Assign sequence
-    if sequence is not None:
-        for hid in range(len(allSegments)):
-            resids = np.where( (hmap==hid)*(fwd==1) )[0]
-            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,
-                          max_nucleotides_per_bead = max_nucleotides_per_bead,
-                          local_twist = local_twist,
-                          dimensions = dimensions,
-                          **model_parameters )
-
-
-    model._reader_list_coordinates = coordinate
-    model._reader_list_basepair = basepair
-    model._reader_list_stack = stack
-    model._reader_list_three_prime = three_prime
-    model._reader_list_five_prime = five_prime
-    model._reader_list_sequence = sequence
-    model._reader_list_orientation = orientation
-    model._reader_list_hmap = hmap
-    model._reader_list_fwd = fwd
-    model._reader_list_hrank = hrank
-
-    if sequence is None:
-        for s in model.segments:
-            s.randomize_unset_sequence()
-
-    return model
-
-def UNIT_circular():
-    """ Make a circular DNA strand, with dsDNA in the middle """
-    coordinate = [(0,0,3.4*i) for i in range(7)]
-    stack = -1*np.ones(len(coordinate))
-    three_prime = [ 1, 2, 4,-1, 6, 3, 0]
-    basepair    = [-1,-1, 3, 2, 5, 4,-1]
-    stack       = [-1,-1, 4,-1,-1, 3,-1]
-    for i in [3,5]:
-        coordinate[i] = (1,0,3.4*i)
-
-    model = model_from_basepair_stack_3prime(coordinate, basepair, stack, three_prime,
-                                             max_basepairs_per_bead=1,
-                                             max_nucleotides_per_bead=1,
-                                             local_twist=True)
-
-    model.simulate(output_name='circular', directory='unittest')
diff --git a/mrdna/readers/.ipynb_checkpoints/segmentmodel_from_oxdna_pinyi-checkpoint.py b/mrdna/readers/.ipynb_checkpoints/segmentmodel_from_oxdna_pinyi-checkpoint.py
deleted file mode 100644
index b107283..0000000
--- a/mrdna/readers/.ipynb_checkpoints/segmentmodel_from_oxdna_pinyi-checkpoint.py
+++ /dev/null
@@ -1,162 +0,0 @@
-from mrdna import logger, devlogger
-from .segmentmodel_from_lists import model_from_basepair_stack_3prime
-from ..arbdmodel.coords import rotationAboutAxis
-
-from oxlibs import *
-import numpy as np
-from scipy.spatial import distance_matrix
-
-_seq_to_int_dict = dict(A=0,T=1,C=2,G=3)
-_seq_to_int_dict = {k:str(v) for k,v in _seq_to_int_dict.items()}
-
-_yrot = rotationAboutAxis(axis=(0,1,0), angle=180).dot(rotationAboutAxis(axis=(0,0,1),angle=-40))
-
-def mrdna_model_from_oxdna(coordinate_file, topology_file, virt2nuc=None, **model_parameters):
-    """ Construct an mrdna model from oxDNA coordinate and topology files """
-    top_data = np.loadtxt(topology_file, skiprows=1,
-                          unpack=True,
-                          dtype=np.dtype('i4,U1,i4,i4')
-                          )
-    conf_data = np.loadtxt(idealized_coordinate_file, skiprows=3)
-    
-    if idealized_coordinate_file is not None:
-        import pickle
-        df = pickle.load(virt2nuc)
-        vh_vb2nuc_rev, vhelix_pattern=df
-        
-
-
-    ## Reverse direction so indices run 5'-to-3'
-    top_data = [a[::-1] for a in top_data]
-    conf_data = conf_data[::-1,:]
-
-    r = conf_data[:,:3] * 8.518
-    base_dir = conf_data[:,3:6]
-    # basepair_pos = r + base_dir*6.0
-    basepair_pos = r + base_dir*10.0
-    normal_dir = -conf_data[:,6:9]
-    perp_dir = np.cross(base_dir, normal_dir)
-    orientation = np.array([np.array(o).T.dot(_yrot) for o in zip(perp_dir,-base_dir,-normal_dir)])
-    
-    def _get_bp(sequence=None):
-        dists = distance_matrix(r,basepair_pos) + np.eye(len(r))*1000
-        dists = 0.5*(dists + dists.T)
-        
-        bp = np.array([np.argmin(da) for da in dists])
-
-        for i,j in enumerate(bp):
-            if j == -1: continue
-            # devlogger.info(f'bp {i} {j} {dists[i,j]}')
-            if dists[i,j] > 2:
-                bp[i] = -1
-            elif bp[j] != i:
-                bpj = bp[j]
-                logger.warning( " ".join([str(_x) for _x in ["Bad pair", i, j, bp[i], bp[j], dists[i,j], dists[j,i], dists[bpj,j], dists[j,bpj]]]) )
-
-        for i,j in enumerate(bp):
-            if j == -1: continue
-            if bp[j] != i:
-                bpj = bp[j]
-                logger.warning( " ".join([str(_x) for _x in ["Bad pair2", i, j, bp[i], bp[j], dists[i,j], dists[j,i], dists[bpj,j], dists[j,bpj]]]) )
-                raise Exception
-
-        if sequence is not None:
-            seq = sequence
-            bp_seq = sequence[bp]
-            bp_seq[bp==-1] = 'X'
-            bad_bps = np.where( (bp >= 0) &
-                                (((seq == 'C') & (bp_seq != 'G')) |
-                                 ((seq == 'G') & (bp_seq != 'C')) |
-                                 ((seq == 'T') & (bp_seq != 'A')) | 
-                                 ((seq == 'U') & (bp_seq != 'A')) |
-                                 ((seq == 'A') & ((bp_seq != 'T') | (bp_seq != 'U')))
-                                 ) )[0]
-            bp[bp[bad_bps]] = -1
-            bp[bad_bps] = -1
-            
-        return bp
-
-    def _get_stack():
-        dists = distance_matrix( r + 3.5*normal_dir + 2.1*perp_dir -1*base_dir, r ) + np.eye(len(r))*1000
-        stack = np.array([np.argmin(da) for da in dists])
-        for i,j in enumerate(stack):
-            if dists[i,j] > 8:
-                stack[i] = -1
-            elif i < 10:
-                ## development info
-                # devlogger.info([i,j,dists[i,j]])
-                # dr = r[j] - (r[i] - normal_dir[i]*3.4 + perp_dir[i]*1 + base_dir[i]*1)
-                dr = r[j] - r[i]
-                # devlogger.info([normal_dir[i].dot(dr), perp_dir[i].dot(dr), base_dir[i].dot(dr)])
-        return np.array(stack)
-
-    seq = top_data[1]
-    bp = _get_bp(seq)
-    stack = _get_stack()
-      
-    three_prime = len(r) - top_data[2] -1
-    five_prime = len(r) - top_data[3] -1
-    three_prime[three_prime >= len(r)] = -1
-    five_prime[five_prime >= len(r)] = -1
-
-    def _debug_write_bonds():
-        from ..arbdmodel import ParticleType, PointParticle, ArbdModel, Group
-        bond = tuple()
-        b_t = ParticleType('BASE')
-        p_t = ParticleType('PHOS')
-
-        parts = []
-        for i,(r0,r_bp,three_prime0,bp0,stack0,seq0) in enumerate(zip(r,basepair_pos, three_prime, bp, stack, seq)):
-            p = PointParticle(p_t, name='PHOS', position = r0, resid=i)
-            b = PointParticle(b_t, name=seq0, position = 0.5*(r0+r_bp), resid=i)
-            parts.extend((p,b))
-
-        model = ArbdModel(parts)
-        model.writePdb('test.pdb')
-
-        for i,(r0,r_bp,three_prime0,bp0,stack0) in enumerate(zip(r,basepair_pos, three_prime, bp, stack)):
-            model.add_bond(parts[2*i],parts[2*i+1],bond)
-            j = three_prime0
-            if j >= 0:
-                model.add_bond(parts[2*i],parts[2*j],bond)
-            j = bp0
-            if j >= 0:
-                model.add_bond(parts[2*i+1],parts[2*j+1],bond)
-        model.writePsf('test.psf')
-
-        model.bonds = []
-        for i,(r0,r_bp,three_prime0,bp0,stack0) in enumerate(zip(r,basepair_pos, three_prime, bp, stack)):
-            j = stack0
-            if j >= 0:
-                model.add_bond(parts[2*i],parts[2*j],bond)
-        model.writePsf('test.stack.psf')
-    ## _debug_write_bonds()
-
-    logger.info(f'mrdna_model_from_oxdna: num_bp, num_ss_nt, num_stacked: {np.sum(bp>=0)//2} {np.sum(bp<0)} {np.sum(stack >= 0)}')
-
-    if coordinate_file != idealized_coordinate_file:
-        conf_data = conf_data[::-1,:]
-
-        r = conf_data[:,:3] * 8.518
-        base_dir = conf_data[:,3:6]
-        basepair_pos = r + base_dir*10.0
-        normal_dir = -conf_data[:,6:9]
-        perp_dir = np.cross(base_dir, normal_dir)
-        orientation = np.array([np.array(o).T.dot(_yrot) for o in zip(perp_dir,-base_dir,-normal_dir)])
-    
-    model = model_from_basepair_stack_3prime( r, bp, stack, three_prime, seq, orientation, **model_parameters )
-
-    """
-    model.DEBUG = True
-    model.generate_bead_model(1,1,False,True,one_bead_per_monomer=True)
-    for seg in model.segments:
-        for bead in seg.beads:
-            bead.position = bead.position + np.random.standard_normal(3)
-    
-    simulate( model, output_name='test', directory='test4' )
-    """
-    return model
-
-if __name__ == "__main__":
-    mrdna_model_from_oxdna("0-from-collab/nanopore.oxdna","0-from-collab/nanopore.top")
-    # mrdna_model_from_oxdna("2-oxdna.manual/output/from_mrdna-oxdna-min.last.conf","0-from-collab/nanopore.top")
diff --git a/mrdna/readers/.ipynb_checkpoints/test-checkpoint.ipynb b/mrdna/readers/.ipynb_checkpoints/test-checkpoint.ipynb
index 8e5ae43..2b75bca 100644
--- a/mrdna/readers/.ipynb_checkpoints/test-checkpoint.ipynb
+++ b/mrdna/readers/.ipynb_checkpoints/test-checkpoint.ipynb
@@ -2,97 +2,765 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 20,
-   "id": "ef4ed889-492f-4ba3-8c1d-a0fc607b1f57",
-   "metadata": {},
+   "execution_count": 124,
+   "id": "767c8226",
+   "metadata": {
+    "scrolled": true
+   },
    "outputs": [
     {
      "data": {
-      "text/html": [
-       "<div>\n",
-       "<style scoped>\n",
-       "    .dataframe tbody tr th:only-of-type {\n",
-       "        vertical-align: middle;\n",
-       "    }\n",
-       "\n",
-       "    .dataframe tbody tr th {\n",
-       "        vertical-align: top;\n",
-       "    }\n",
-       "\n",
-       "    .dataframe thead th {\n",
-       "        text-align: right;\n",
-       "    }\n",
-       "</style>\n",
-       "<table border=\"1\" class=\"dataframe\">\n",
-       "  <thead>\n",
-       "    <tr style=\"text-align: right;\">\n",
-       "      <th></th>\n",
-       "      <th>name</th>\n",
-       "      <th>vstrands</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>0</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 12, 'col': 16, 'num': 0, 'scaf': [[-1,...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>1</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 12, 'col': 15, 'num': 1, 'scaf': [[-1,...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>2</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 13, 'col': 15, 'num': 2, 'scaf': [[-1,...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>3</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 13, 'col': 16, 'num': 3, 'scaf': [[-1,...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>4</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 13, 'col': 17, 'num': 4, 'scaf': [[-1,...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>5</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 12, 'col': 17, 'num': 5, 'scaf': [[5, ...</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
       "text/plain": [
-       "        name                                           vstrands\n",
-       "0  test.json  {'row': 12, 'col': 16, 'num': 0, 'scaf': [[-1,...\n",
-       "1  test.json  {'row': 12, 'col': 15, 'num': 1, 'scaf': [[-1,...\n",
-       "2  test.json  {'row': 13, 'col': 15, 'num': 2, 'scaf': [[-1,...\n",
-       "3  test.json  {'row': 13, 'col': 16, 'num': 3, 'scaf': [[-1,...\n",
-       "4  test.json  {'row': 13, 'col': 17, 'num': 4, 'scaf': [[-1,...\n",
-       "5  test.json  {'row': 12, 'col': 17, 'num': 5, 'scaf': [[5, ..."
+       "dict_keys(['row', 'col', 'num', 'scaf', 'stap', 'loop', 'skip', 'scafLoop', 'stapLoop', 'stap_colors'])"
       ]
      },
-     "execution_count": 20,
+     "execution_count": 124,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
     "import pandas as pd\n",
-    "\n",
-    "\n",
+    "import pickle\n",
+    "import numpy as np\n",
     "df=pd.read_json(\"test.json\")\n",
-    "df"
+    "df[\"vstrands\"][0].keys()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 164,
+   "id": "bf2d37ca",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[[-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [0, 3, -1, -1],\n",
+       " [0, 4, 0, 2],\n",
+       " [0, 5, 0, 3],\n",
+       " [0, 6, 0, 4],\n",
+       " [0, 7, 0, 5],\n",
+       " [0, 8, 0, 6],\n",
+       " [0, 9, 0, 7],\n",
+       " [0, 10, 0, 8],\n",
+       " [0, 11, 0, 9],\n",
+       " [0, 12, 0, 10],\n",
+       " [0, 13, 0, 11],\n",
+       " [0, 14, 0, 12],\n",
+       " [0, 15, 0, 13],\n",
+       " [0, 16, 0, 14],\n",
+       " [0, 17, 0, 15],\n",
+       " [0, 18, 0, 16],\n",
+       " [0, 19, 0, 17],\n",
+       " [0, 20, 0, 18],\n",
+       " [1, 20, 0, 19],\n",
+       " [0, 22, 1, 21],\n",
+       " [0, 23, 0, 21],\n",
+       " [-1, -1, 0, 22],\n",
+       " [0, 25, -1, -1],\n",
+       " [0, 26, 0, 24],\n",
+       " [0, 27, 0, 25],\n",
+       " [5, 27, 0, 26],\n",
+       " [0, 29, 5, 28],\n",
+       " [0, 30, 0, 28],\n",
+       " [0, 31, 0, 29],\n",
+       " [0, 32, 0, 30],\n",
+       " [0, 33, 0, 31],\n",
+       " [0, 34, 0, 32],\n",
+       " [0, 35, 0, 33],\n",
+       " [0, 36, 0, 34],\n",
+       " [0, 37, 0, 35],\n",
+       " [0, 38, 0, 36],\n",
+       " [-1, -1, 0, 37],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1]]"
+      ]
+     },
+     "execution_count": 164,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "df[\"vstrands\"][0][\"stap\"]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 65,
+   "id": "4ce8f67f",
+   "metadata": {},
+   "outputs": [
+    {
+     "ename": "UnicodeDecodeError",
+     "evalue": "'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mUnicodeDecodeError\u001b[0m                        Traceback (most recent call last)",
+      "\u001b[0;32m<ipython-input-65-71f198107f5e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"test.virt2nuc\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\"r\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mpickle\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mload\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+      "\u001b[0;32m/data/server1/cmaffeo2/miniconda3/lib/python3.8/codecs.py\u001b[0m in \u001b[0;36mdecode\u001b[0;34m(self, input, final)\u001b[0m\n\u001b[1;32m    320\u001b[0m         \u001b[0;31m# decode input (taking the buffer into account)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    321\u001b[0m         \u001b[0mdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuffer\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0minput\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 322\u001b[0;31m         \u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconsumed\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_buffer_decode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0merrors\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfinal\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    323\u001b[0m         \u001b[0;31m# keep undecoded input until the next call\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    324\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuffer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mconsumed\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;31mUnicodeDecodeError\u001b[0m: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte"
+     ]
+    }
+   ],
+   "source": [
+    "f=open(\"test.virt2nuc\",\"r\")\n",
+    "pickle.load(f)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 119,
+   "id": "625c831b",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "210"
+      ]
+     },
+     "execution_count": 119,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "vh_vb,pattern=pd.read_pickle(\"test.virt2nuc\")\n",
+    "len(vh_vb._scaf)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 66,
+   "id": "6a4129c2",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{0: (12, 16), 1: (12, 15), 2: (13, 15), 3: (13, 16), 4: (13, 17), 5: (12, 17)}"
+      ]
+     },
+     "execution_count": 66,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "pattern"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 141,
+   "id": "f85af2e4",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(0, 40)\n",
+      "(0, 41)\n"
+     ]
+    },
+    {
+     "ename": "AttributeError",
+     "evalue": "'NoneType' object has no attribute 'append'",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
+      "\u001b[0;32m<ipython-input-141-a0e59df19136>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ms\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdecode_vh_vb\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"test.virt2nuc\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-140-99891f72666f>\u001b[0m in \u001b[0;36mdecode_vh_vb\u001b[0;34m(virt2nuc)\u001b[0m\n\u001b[1;32m     21\u001b[0m     \u001b[0mscafs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvh_vb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_scaf\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     22\u001b[0m     \u001b[0mstaps\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvh_vb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stap\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 23\u001b[0;31m     \u001b[0mscaf_strands\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfind_segs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mscafs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     24\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     25\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0mvh_list\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-140-99891f72666f>\u001b[0m in \u001b[0;36mfind_segs\u001b[0;34m(vir2nuc_scaf)\u001b[0m\n\u001b[1;32m      8\u001b[0m             \u001b[0mb\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvir2nuc_scaf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      9\u001b[0m             \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m             \u001b[0moligos\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0moligo\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0moligos\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0moligo\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvir2nuc_scaf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     11\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0moligos\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     12\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;31mAttributeError\u001b[0m: 'NoneType' object has no attribute 'append'"
+     ]
+    }
+   ],
+   "source": [
+    "s=decode_vh_vb(\"test.virt2nuc\")[0]\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 165,
+   "id": "aefe656e",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class strands():\n",
+    "    def __init__(self):\n",
+    "        self.row=0 \n",
+    "        self.col=0\n",
+    "        self.num=0\n",
+    "        self.scaf=[]\n",
+    "        self.stap=[]\n",
+    "        self.loop=[]\n",
+    "        self.skip=[]\n",
+    "        self.scafLoop=[]\n",
+    "        self.stapLoop=[]\n",
+    "        self.stap_colors=[]\n",
+    "        self.scaf_contact={}\n",
+    "        self.stap_connect={}\n",
+    "    def to_dict(self):\n",
+    "        d={}\n",
+    "        d['row']=self.row\n",
+    "        d['col']=self.col\n",
+    "        d['num']=self.num\n",
+    "        d['scaf']=self.scaf\n",
+    "        d['stap']=self.stap\n",
+    "        d['loop']=self.loop\n",
+    "        d['skip']=self.skip\n",
+    "        d['scafLoop']=self.scafLoop\n",
+    "        d['stapLoop']=self.stapLoop\n",
+    "        d['stap_colors']=self.stap_colors\n",
+    "        return d\n",
+    "    \n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 160,
+   "id": "e154a8c3",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def find_segs(vir2nuc_scaf):\n",
+    "    oligos={}\n",
+    "    for i in range(len(vir2nuc_scaf)):\n",
+    "        oligo,ox_ind=list(vir2nuc_scaf.values())[i]\n",
+    "        if oligo not in oligos.keys():\n",
+    "            oligos[oligo]=[]\n",
+    "        oligos[oligo].append(list(vir2nuc_scaf.keys())[i])\n",
+    "    return oligos\n",
+    "    \n",
+    "def decode_vh_vb(virt2nuc):\n",
+    "    vh_list=[]\n",
+    "    vh_vb,pattern=pd.read_pickle(virt2nuc)\n",
+    "    for i in pattern.keys():\n",
+    "        s=strands()\n",
+    "        s.row,s.col=pattern[i]\n",
+    "        s.num=i\n",
+    "        vh_list.append(s)\n",
+    "    scafs=vh_vb._scaf\n",
+    "    staps=vh_vb._stap\n",
+    "    scaf_strands=find_segs(scafs)\n",
+    "    scaf_oligos=list(scaf_strands.keys())\n",
+    "    for i in scaf_oligos:\n",
+    "        bases=len(scaf_oligos)\n",
+    "        vh0,vb0=scaf_oligos[i][0]\n",
+    "        vh1,vb1=scaf_oligos[i][1]\n",
+    "        if vb0>vb1:#53\n",
+    "            scaf_contact\n",
+    "        else: #35\n",
+    "            \n",
+    "            \n",
+    "    return vh_list"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 163,
+   "id": "09619e4e",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{0: [(0, 39), (0, 40), (0, 41)],\n",
+       " 1: [(1, 41), (1, 40), (1, 39)],\n",
+       " 2: [(2, 39), (2, 40), (2, 41)],\n",
+       " 4: [(3, 41), (3, 40), (3, 39), (3, 38), (3, 37)],\n",
+       " 5: [(4, 0), (4, 1), (4, 2), (4, 3)],\n",
+       " 6: [(5, 3), (5, 2), (5, 1), (5, 0)],\n",
+       " 7: [(5, 22),\n",
+       "  (5, 21),\n",
+       "  (5, 20),\n",
+       "  (5, 19),\n",
+       "  (5, 18),\n",
+       "  (5, 17),\n",
+       "  (5, 16),\n",
+       "  (5, 15),\n",
+       "  (5, 14),\n",
+       "  (5, 13),\n",
+       "  (5, 12),\n",
+       "  (5, 11),\n",
+       "  (5, 10),\n",
+       "  (5, 9),\n",
+       "  (4, 9),\n",
+       "  (4, 10),\n",
+       "  (4, 11),\n",
+       "  (4, 12),\n",
+       "  (4, 13),\n",
+       "  (4, 14),\n",
+       "  (4, 15),\n",
+       "  (3, 15),\n",
+       "  (3, 14),\n",
+       "  (3, 13),\n",
+       "  (3, 12),\n",
+       "  (3, 11),\n",
+       "  (3, 10),\n",
+       "  (3, 9),\n",
+       "  (3, 8),\n",
+       "  (3, 7),\n",
+       "  (3, 6),\n",
+       "  (3, 5),\n",
+       "  (3, 4),\n",
+       "  (3, 3),\n",
+       "  (3, 2),\n",
+       "  (2, 2),\n",
+       "  (2, 3),\n",
+       "  (2, 4),\n",
+       "  (2, 5),\n",
+       "  (2, 6),\n",
+       "  (2, 7),\n",
+       "  (2, 8),\n",
+       "  (2, 9),\n",
+       "  (2, 10),\n",
+       "  (2, 11),\n",
+       "  (2, 12),\n",
+       "  (2, 13),\n",
+       "  (2, 14),\n",
+       "  (2, 15),\n",
+       "  (2, 16),\n",
+       "  (2, 17),\n",
+       "  (2, 18),\n",
+       "  (1, 18),\n",
+       "  (1, 17),\n",
+       "  (1, 16),\n",
+       "  (1, 15),\n",
+       "  (1, 14),\n",
+       "  (1, 13),\n",
+       "  (1, 12),\n",
+       "  (1, 11),\n",
+       "  (1, 10),\n",
+       "  (1, 9),\n",
+       "  (1, 8),\n",
+       "  (1, 7),\n",
+       "  (1, 6),\n",
+       "  (1, 5),\n",
+       "  (0, 5),\n",
+       "  (0, 6),\n",
+       "  (0, 7),\n",
+       "  (0, 8),\n",
+       "  (0, 9),\n",
+       "  (0, 10),\n",
+       "  (0, 11),\n",
+       "  (0, 12),\n",
+       "  (0, 13),\n",
+       "  (0, 14),\n",
+       "  (0, 15),\n",
+       "  (0, 16),\n",
+       "  (0, 17),\n",
+       "  (0, 18),\n",
+       "  (0, 19),\n",
+       "  (0, 20),\n",
+       "  (0, 21),\n",
+       "  (0, 22),\n",
+       "  (0, 23),\n",
+       "  (0, 24),\n",
+       "  (0, 25),\n",
+       "  (0, 26),\n",
+       "  (0, 27),\n",
+       "  (0, 28),\n",
+       "  (0, 29),\n",
+       "  (0, 30),\n",
+       "  (0, 31),\n",
+       "  (0, 32),\n",
+       "  (0, 33),\n",
+       "  (0, 34),\n",
+       "  (0, 35),\n",
+       "  (0, 36),\n",
+       "  (1, 36),\n",
+       "  (1, 35),\n",
+       "  (1, 34),\n",
+       "  (1, 33),\n",
+       "  (1, 32),\n",
+       "  (1, 31),\n",
+       "  (1, 30),\n",
+       "  (1, 29),\n",
+       "  (1, 28),\n",
+       "  (1, 27),\n",
+       "  (1, 26),\n",
+       "  (1, 25),\n",
+       "  (1, 24),\n",
+       "  (1, 23),\n",
+       "  (1, 22),\n",
+       "  (1, 21),\n",
+       "  (1, 20),\n",
+       "  (1, 19),\n",
+       "  (2, 19),\n",
+       "  (2, 20),\n",
+       "  (2, 21),\n",
+       "  (2, 22),\n",
+       "  (2, 23),\n",
+       "  (2, 24),\n",
+       "  (2, 25),\n",
+       "  (2, 26),\n",
+       "  (2, 27),\n",
+       "  (2, 28),\n",
+       "  (2, 29),\n",
+       "  (2, 30),\n",
+       "  (2, 31),\n",
+       "  (2, 32),\n",
+       "  (3, 32),\n",
+       "  (3, 31),\n",
+       "  (3, 30),\n",
+       "  (3, 29),\n",
+       "  (3, 28),\n",
+       "  (3, 27),\n",
+       "  (3, 26),\n",
+       "  (3, 25),\n",
+       "  (3, 24),\n",
+       "  (3, 23),\n",
+       "  (3, 22),\n",
+       "  (3, 21),\n",
+       "  (3, 20),\n",
+       "  (3, 19),\n",
+       "  (3, 18),\n",
+       "  (3, 17),\n",
+       "  (3, 16),\n",
+       "  (4, 16),\n",
+       "  (4, 17),\n",
+       "  (4, 18),\n",
+       "  (4, 19),\n",
+       "  (4, 20),\n",
+       "  (4, 21),\n",
+       "  (4, 22),\n",
+       "  (4, 23),\n",
+       "  (4, 24),\n",
+       "  (4, 25),\n",
+       "  (4, 26),\n",
+       "  (4, 27),\n",
+       "  (4, 28),\n",
+       "  (4, 29),\n",
+       "  (4, 30),\n",
+       "  (4, 31),\n",
+       "  (4, 32),\n",
+       "  (4, 33),\n",
+       "  (4, 34),\n",
+       "  (4, 35),\n",
+       "  (4, 36),\n",
+       "  (4, 37),\n",
+       "  (4, 38),\n",
+       "  (4, 39),\n",
+       "  (5, 39),\n",
+       "  (5, 38),\n",
+       "  (5, 37),\n",
+       "  (5, 36),\n",
+       "  (5, 35),\n",
+       "  (5, 34),\n",
+       "  (5, 33),\n",
+       "  (5, 32),\n",
+       "  (5, 31),\n",
+       "  (5, 30),\n",
+       "  (5, 29),\n",
+       "  (5, 28),\n",
+       "  (5, 27),\n",
+       "  (5, 26),\n",
+       "  (5, 25),\n",
+       "  (5, 24),\n",
+       "  (5, 23)]}"
+      ]
+     },
+     "execution_count": 163,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "scafs=vh_vb._scaf\n",
+    "s=list(scafs.values())\n",
+    "len(scafs)\n",
+    "find_segs(scafs)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 157,
+   "id": "88d989b9",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[(1, 2)]"
+      ]
+     },
+     "execution_count": 157,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "oligos[0]=[]\n",
+    "L=[]\n",
+    "L.append((1,2))\n",
+    "L"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 152,
+   "id": "2909c273",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "(0, 39)"
+      ]
+     },
+     "execution_count": 152,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "list(scafs.keys())[0]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 62,
+   "id": "422e2b48",
+   "metadata": {
+    "scrolled": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{(2, 34): (3, [43]),\n",
+       " (2, 33): (3, [42]),\n",
+       " (2, 32): (3, [41]),\n",
+       " (2, 31): (3, [40]),\n",
+       " (2, 30): (3, [39]),\n",
+       " (2, 29): (3, [38]),\n",
+       " (2, 28): (3, [37]),\n",
+       " (2, 27): (3, [36]),\n",
+       " (2, 26): (3, [35]),\n",
+       " (2, 25): (3, [34]),\n",
+       " (2, 24): (3, [33]),\n",
+       " (2, 23): (3, [32]),\n",
+       " (2, 22): (3, [31]),\n",
+       " (2, 21): (3, [30]),\n",
+       " (2, 20): (3, [29]),\n",
+       " (2, 19): (3, [28]),\n",
+       " (2, 18): (3, [27]),\n",
+       " (2, 17): (3, [26]),\n",
+       " (2, 16): (3, [25]),\n",
+       " (2, 15): (3, [24]),\n",
+       " (2, 14): (3, [23]),\n",
+       " (2, 13): (3, [22]),\n",
+       " (2, 12): (3, [21]),\n",
+       " (2, 11): (3, [20]),\n",
+       " (2, 10): (3, [19]),\n",
+       " (2, 9): (3, [18]),\n",
+       " (2, 8): (3, [17]),\n",
+       " (2, 7): (3, [16]),\n",
+       " (2, 6): (3, [15]),\n",
+       " (2, 5): (3, [14]),\n",
+       " (2, 4): (3, [13]),\n",
+       " (2, 3): (3, [12]),\n",
+       " (2, 2): (3, [11]),\n",
+       " (2, 1): (3, [10]),\n",
+       " (2, 0): (3, [9]),\n",
+       " (1, 3): (8, [281]),\n",
+       " (1, 4): (8, [280]),\n",
+       " (1, 5): (8, [279]),\n",
+       " (1, 6): (8, [278]),\n",
+       " (1, 7): (8, [277]),\n",
+       " (1, 8): (8, [276]),\n",
+       " (1, 9): (8, [275]),\n",
+       " (1, 10): (8, [274]),\n",
+       " (1, 11): (8, [273]),\n",
+       " (1, 12): (8, [272]),\n",
+       " (1, 13): (8, [271]),\n",
+       " (1, 14): (8, [270]),\n",
+       " (1, 15): (8, [269]),\n",
+       " (1, 16): (8, [268]),\n",
+       " (1, 17): (8, [267]),\n",
+       " (1, 18): (8, [266]),\n",
+       " (1, 19): (8, [265]),\n",
+       " (1, 20): (8, [264]),\n",
+       " (0, 20): (8, [263]),\n",
+       " (0, 19): (8, [262]),\n",
+       " (0, 18): (8, [261]),\n",
+       " (0, 17): (8, [260]),\n",
+       " (0, 16): (8, [259]),\n",
+       " (0, 15): (8, [258]),\n",
+       " (0, 14): (8, [257]),\n",
+       " (0, 13): (8, [256]),\n",
+       " (0, 12): (8, [255]),\n",
+       " (0, 11): (8, [254]),\n",
+       " (0, 10): (8, [253]),\n",
+       " (0, 9): (8, [252]),\n",
+       " (0, 8): (8, [251]),\n",
+       " (0, 7): (8, [250]),\n",
+       " (0, 6): (8, [249]),\n",
+       " (0, 5): (8, [248]),\n",
+       " (0, 4): (8, [247]),\n",
+       " (0, 3): (8, [246]),\n",
+       " (0, 2): (8, [245]),\n",
+       " (0, 23): (9, [302]),\n",
+       " (0, 22): (9, [301]),\n",
+       " (0, 21): (9, [300]),\n",
+       " (1, 21): (9, [299]),\n",
+       " (1, 22): (9, [298]),\n",
+       " (1, 23): (9, [297]),\n",
+       " (1, 24): (9, [296]),\n",
+       " (1, 25): (9, [295]),\n",
+       " (1, 26): (9, [294]),\n",
+       " (1, 27): (9, [293]),\n",
+       " (1, 28): (9, [292]),\n",
+       " (1, 29): (9, [291]),\n",
+       " (1, 30): (9, [290]),\n",
+       " (1, 31): (9, [289]),\n",
+       " (1, 32): (9, [288]),\n",
+       " (1, 33): (9, [287]),\n",
+       " (1, 34): (9, [286]),\n",
+       " (1, 35): (9, [285]),\n",
+       " (1, 36): (9, [284]),\n",
+       " (1, 37): (9, [283]),\n",
+       " (1, 38): (9, [282]),\n",
+       " (5, 9): (10, [325]),\n",
+       " (5, 10): (10, [324]),\n",
+       " (5, 11): (10, [323]),\n",
+       " (5, 12): (10, [322]),\n",
+       " (5, 13): (10, [321]),\n",
+       " (5, 14): (10, [320]),\n",
+       " (5, 15): (10, [319]),\n",
+       " (5, 16): (10, [318]),\n",
+       " (5, 17): (10, [317]),\n",
+       " (5, 18): (10, [316]),\n",
+       " (5, 19): (10, [315]),\n",
+       " (5, 20): (10, [314]),\n",
+       " (5, 21): (10, [313]),\n",
+       " (5, 22): (10, [312]),\n",
+       " (5, 23): (10, [311]),\n",
+       " (5, 24): (10, [310]),\n",
+       " (5, 25): (10, [309]),\n",
+       " (5, 26): (10, [308]),\n",
+       " (5, 27): (10, [307]),\n",
+       " (0, 27): (10, [306]),\n",
+       " (0, 26): (10, [305]),\n",
+       " (0, 25): (10, [304]),\n",
+       " (0, 24): (10, [303]),\n",
+       " (0, 38): (11, [348]),\n",
+       " (0, 37): (11, [347]),\n",
+       " (0, 36): (11, [346]),\n",
+       " (0, 35): (11, [345]),\n",
+       " (0, 34): (11, [344]),\n",
+       " (0, 33): (11, [343]),\n",
+       " (0, 32): (11, [342]),\n",
+       " (0, 31): (11, [341]),\n",
+       " (0, 30): (11, [340]),\n",
+       " (0, 29): (11, [339]),\n",
+       " (0, 28): (11, [338]),\n",
+       " (5, 28): (11, [337]),\n",
+       " (5, 29): (11, [336]),\n",
+       " (5, 30): (11, [335]),\n",
+       " (5, 31): (11, [334]),\n",
+       " (5, 32): (11, [333]),\n",
+       " (5, 33): (11, [332]),\n",
+       " (5, 34): (11, [331]),\n",
+       " (5, 35): (11, [330]),\n",
+       " (5, 36): (11, [329]),\n",
+       " (5, 37): (11, [328]),\n",
+       " (5, 38): (11, [327]),\n",
+       " (5, 39): (11, [326]),\n",
+       " (3, 0): (12, [381]),\n",
+       " (3, 1): (12, [380]),\n",
+       " (3, 2): (12, [379]),\n",
+       " (3, 3): (12, [378]),\n",
+       " (3, 4): (12, [377]),\n",
+       " (3, 5): (12, [376]),\n",
+       " (3, 6): (12, [375]),\n",
+       " (3, 7): (12, [374]),\n",
+       " (3, 8): (12, [373]),\n",
+       " (3, 9): (12, [372]),\n",
+       " (3, 10): (12, [371]),\n",
+       " (3, 11): (12, [370]),\n",
+       " (3, 12): (12, [369]),\n",
+       " (3, 13): (12, [368]),\n",
+       " (3, 14): (12, [367]),\n",
+       " (3, 15): (12, [366]),\n",
+       " (3, 16): (12, [365]),\n",
+       " (3, 17): (12, [364]),\n",
+       " (3, 18): (12, [363]),\n",
+       " (3, 19): (12, [362]),\n",
+       " (3, 20): (12, [361]),\n",
+       " (4, 20): (12, [360]),\n",
+       " (4, 19): (12, [359]),\n",
+       " (4, 18): (12, [358]),\n",
+       " (4, 17): (12, [357]),\n",
+       " (4, 16): (12, [356]),\n",
+       " (4, 15): (12, [355]),\n",
+       " (4, 14): (12, [354]),\n",
+       " (4, 13): (12, [353]),\n",
+       " (4, 12): (12, [352]),\n",
+       " (4, 11): (12, [351]),\n",
+       " (4, 10): (12, [350]),\n",
+       " (4, 9): (12, [349]),\n",
+       " (4, 39): (13, [414]),\n",
+       " (4, 38): (13, [413]),\n",
+       " (4, 37): (13, [412]),\n",
+       " (4, 36): (13, [411]),\n",
+       " (4, 35): (13, [410]),\n",
+       " (4, 34): (13, [409]),\n",
+       " (4, 33): (13, [408]),\n",
+       " (4, 32): (13, [407]),\n",
+       " (4, 31): (13, [406]),\n",
+       " (4, 30): (13, [405]),\n",
+       " (4, 29): (13, [404]),\n",
+       " (4, 28): (13, [403]),\n",
+       " (4, 27): (13, [402]),\n",
+       " (4, 26): (13, [401]),\n",
+       " (4, 25): (13, [400]),\n",
+       " (4, 24): (13, [399]),\n",
+       " (4, 23): (13, [398]),\n",
+       " (4, 22): (13, [397]),\n",
+       " (4, 21): (13, [396]),\n",
+       " (3, 21): (13, [395]),\n",
+       " (3, 22): (13, [394]),\n",
+       " (3, 23): (13, [393]),\n",
+       " (3, 24): (13, [392]),\n",
+       " (3, 25): (13, [391]),\n",
+       " (3, 26): (13, [390]),\n",
+       " (3, 27): (13, [389]),\n",
+       " (3, 28): (13, [388]),\n",
+       " (3, 29): (13, [387]),\n",
+       " (3, 30): (13, [386]),\n",
+       " (3, 31): (13, [385]),\n",
+       " (3, 32): (13, [384]),\n",
+       " (3, 33): (13, [383]),\n",
+       " (3, 34): (13, [382])}"
+      ]
+     },
+     "execution_count": 62,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s=vh_vb.__dict__\n",
+    "scafs=s[\"_scaf\"]\n",
+    "staps=s[\"_stap\"]\n",
+    "staps"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
-   "id": "051eb3b8-2bf1-4482-9815-19937f66e09d",
+   "execution_count": 3,
+   "id": "69c011ff",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -217,8 +885,8 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 43,
-   "id": "6e88e214-c870-47d1-9a47-504caa411530",
+   "execution_count": 4,
+   "id": "f2693e7a",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -238,30 +906,215 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 57,
-   "id": "326f70c5-6a80-4802-847a-ae0de82f0eda",
+   "execution_count": 20,
+   "id": "a4594752",
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'{\\n\"stapLoop\":[],\\n\"skip\":[],\\n\"loop\":[],\\n\"stap_colors\":[],\\n\"row\":0,\\n\"col\":0,\\n\"num\":0,\\n\"scafLoop\":[],\\n\"stap\":[[5, 1, -1, -1],[5, 2, 5, 0],[5, 3, 5, 1],[-1, -1, 5, 2],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[5, 10, 4, 9],[5, 11, 5, 9],[5, 12, 5, 10],[5, 13, 5, 11],[5, 14, 5, 12],[5, 15, 5, 13],[5, 16, 5, 14],[5, 17, 5, 15],[5, 18, 5, 16],[5, 19, 5, 17],[5, 20, 5, 18],[5, 21, 5, 19],[5, 22, 5, 20],[-1, -1, 5, 21],[5, 24, -1, -1],[5, 25, 5, 23],[5, 26, 5, 24],[5, 27, 5, 25],[5, 28, 5, 26],[5, 29, 5, 27],[5, 30, 5, 28],[5, 31, 5, 29],[5, 32, 5, 30],[5, 33, 5, 31],[5, 34, 5, 32],[5, 35, 5, 33],[5, 36, 5, 34],[5, 37, 5, 35],[5, 38, 5, 36],[5, 39, 5, 37],[4, 39, 5, 38],[-1, -1, -1, -1],[-1, -1, -1, -1]],\\n\"scaf\":[[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, 5, 10],[5, 9, 5, 11],[5, 10, 5, 12],[5, 11, 5, 13],[5, 12, 5, 14],[5, 13, 5, 15],[5, 14, 5, 16],[5, 15, 5, 17],[5, 16, 5, 18],[5, 17, 5, 19],[5, 18, 5, 20],[5, 19, 5, 21],[5, 20, 5, 22],[5, 21, 5, 23],[5, 22, 5, 24],[5, 23, 5, 25],[5, 24, 5, 26],[5, 25, 5, 27],[5, 26, 0, 27],[0, 28, 5, 29],[5, 28, 5, 30],[5, 29, 5, 31],[5, 30, 5, 32],[5, 31, 5, 33],[5, 32, 5, 34],[5, 33, 5, 35],[5, 34, 5, 36],[5, 35, 5, 37],[5, 36, 5, 38],[5, 37, 5, 39],[5, 38, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1]]\\n}'"
+       "['__class__',\n",
+       " '__delattr__',\n",
+       " '__dict__',\n",
+       " '__dir__',\n",
+       " '__doc__',\n",
+       " '__eq__',\n",
+       " '__format__',\n",
+       " '__ge__',\n",
+       " '__getattribute__',\n",
+       " '__gt__',\n",
+       " '__hash__',\n",
+       " '__init__',\n",
+       " '__init_subclass__',\n",
+       " '__le__',\n",
+       " '__lt__',\n",
+       " '__module__',\n",
+       " '__ne__',\n",
+       " '__new__',\n",
+       " '__reduce__',\n",
+       " '__reduce_ex__',\n",
+       " '__repr__',\n",
+       " '__setattr__',\n",
+       " '__sizeof__',\n",
+       " '__str__',\n",
+       " '__subclasshook__',\n",
+       " '__weakref__',\n",
+       " 'add_square',\n",
+       " 'cad_index',\n",
+       " 'col',\n",
+       " 'get_length',\n",
+       " 'len',\n",
+       " 'loop',\n",
+       " 'num',\n",
+       " 'row',\n",
+       " 'scaf',\n",
+       " 'scafLoop',\n",
+       " 'skip',\n",
+       " 'skiploop_bases',\n",
+       " 'stap',\n",
+       " 'stapLoop',\n",
+       " 'stap_colors']"
       ]
      },
-     "execution_count": 57,
+     "execution_count": 20,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
     "s0=cadsys.vhelices[0]\n",
-    "s0.__str__()"
+    "dir(s0)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 25,
+   "id": "ca071163",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[[-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, 5, 10],\n",
+       " [5, 9, 5, 11],\n",
+       " [5, 10, 5, 12],\n",
+       " [5, 11, 5, 13],\n",
+       " [5, 12, 5, 14],\n",
+       " [5, 13, 5, 15],\n",
+       " [5, 14, 5, 16],\n",
+       " [5, 15, 5, 17],\n",
+       " [5, 16, 5, 18],\n",
+       " [5, 17, 5, 19],\n",
+       " [5, 18, 5, 20],\n",
+       " [5, 19, 5, 21],\n",
+       " [5, 20, 5, 22],\n",
+       " [5, 21, 5, 23],\n",
+       " [5, 22, 5, 24],\n",
+       " [5, 23, 5, 25],\n",
+       " [5, 24, 5, 26],\n",
+       " [5, 25, 5, 27],\n",
+       " [5, 26, 0, 27],\n",
+       " [0, 28, 5, 29],\n",
+       " [5, 28, 5, 30],\n",
+       " [5, 29, 5, 31],\n",
+       " [5, 30, 5, 32],\n",
+       " [5, 31, 5, 33],\n",
+       " [5, 32, 5, 34],\n",
+       " [5, 33, 5, 35],\n",
+       " [5, 34, 5, 36],\n",
+       " [5, 35, 5, 37],\n",
+       " [5, 36, 5, 38],\n",
+       " [5, 37, 5, 39],\n",
+       " [5, 38, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1]]"
+      ]
+     },
+     "execution_count": 25,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s0.scaf"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e5913163",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "for s in s0.scaf:\n",
+    "    if s[0]==-1 and s[1]==-1:\n",
+    "        pass\n",
+    "    elif s[2]==len(s0.scaf) and abs(s[3])==1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "id": "3eefca8f",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[-1, -1, -1, -1]"
+      ]
+     },
+     "execution_count": 13,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s0.scaf[0]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "268d5c04",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['__class__',\n",
+       " '__delattr__',\n",
+       " '__dict__',\n",
+       " '__dir__',\n",
+       " '__doc__',\n",
+       " '__eq__',\n",
+       " '__format__',\n",
+       " '__ge__',\n",
+       " '__getattribute__',\n",
+       " '__gt__',\n",
+       " '__hash__',\n",
+       " '__init__',\n",
+       " '__init_subclass__',\n",
+       " '__le__',\n",
+       " '__lt__',\n",
+       " '__module__',\n",
+       " '__ne__',\n",
+       " '__new__',\n",
+       " '__reduce__',\n",
+       " '__reduce_ex__',\n",
+       " '__repr__',\n",
+       " '__setattr__',\n",
+       " '__sizeof__',\n",
+       " '__str__',\n",
+       " '__subclasshook__',\n",
+       " '__weakref__',\n",
+       " 'add_vhelix',\n",
+       " 'bbox',\n",
+       " 'vhelices']"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "dir(cadsys)"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": 36,
-   "id": "7b552911-d7de-4079-ab4d-e859f2281f36",
+   "id": "d3d42e33",
    "metadata": {},
    "outputs": [
     {
@@ -323,7 +1176,7 @@
   {
    "cell_type": "code",
    "execution_count": 1,
-   "id": "94113dfa",
+   "id": "2cc3f477",
    "metadata": {},
    "outputs": [
     {
@@ -349,7 +1202,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "ec7f1e22-6a95-41f9-8c23-7603cc165837",
+   "id": "5d50f58a",
    "metadata": {},
    "outputs": [],
    "source": []
@@ -357,7 +1210,7 @@
   {
    "cell_type": "code",
    "execution_count": 3,
-   "id": "40d7cdcf",
+   "id": "3b40b71b",
    "metadata": {},
    "outputs": [
     {
@@ -377,7 +1230,7 @@
   {
    "cell_type": "code",
    "execution_count": 13,
-   "id": "4b3748a8",
+   "id": "6915bad6",
    "metadata": {},
    "outputs": [
     {
@@ -398,7 +1251,7 @@
   {
    "cell_type": "code",
    "execution_count": 15,
-   "id": "aa8a8cd9",
+   "id": "1c16c59d",
    "metadata": {},
    "outputs": [
     {
@@ -468,7 +1321,7 @@
   {
    "cell_type": "code",
    "execution_count": 16,
-   "id": "e0cab15d",
+   "id": "c61d9586",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -479,7 +1332,7 @@
   {
    "cell_type": "code",
    "execution_count": 26,
-   "id": "9811bf9a",
+   "id": "aeca0546",
    "metadata": {},
    "outputs": [
     {
@@ -588,7 +1441,7 @@
   {
    "cell_type": "code",
    "execution_count": 25,
-   "id": "86403b4b",
+   "id": "90a54834",
    "metadata": {},
    "outputs": [
     {
@@ -609,7 +1462,7 @@
   {
    "cell_type": "code",
    "execution_count": 10,
-   "id": "5c7cea80",
+   "id": "de00fb7e",
    "metadata": {},
    "outputs": [
     {
@@ -640,7 +1493,7 @@
   {
    "cell_type": "code",
    "execution_count": 1,
-   "id": "136dcf08",
+   "id": "716ff2ed",
    "metadata": {},
    "outputs": [
     {
@@ -1137,7 +1990,7 @@
   {
    "cell_type": "code",
    "execution_count": 3,
-   "id": "88f7d20e",
+   "id": "766d0ecd",
    "metadata": {},
    "outputs": [
     {
@@ -1171,7 +2024,7 @@
   {
    "cell_type": "code",
    "execution_count": 4,
-   "id": "69d29f1e",
+   "id": "05456be4",
    "metadata": {},
    "outputs": [
     {
@@ -1191,7 +2044,7 @@
   {
    "cell_type": "code",
    "execution_count": 5,
-   "id": "e103e8b4",
+   "id": "cd1a5604",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -1201,7 +2054,7 @@
   {
    "cell_type": "code",
    "execution_count": 6,
-   "id": "a30b582d",
+   "id": "4346f1fc",
    "metadata": {},
    "outputs": [
     {
@@ -1222,7 +2075,7 @@
   {
    "cell_type": "code",
    "execution_count": 7,
-   "id": "dcd8bf8a",
+   "id": "294094f9",
    "metadata": {},
    "outputs": [
     {
@@ -1249,7 +2102,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "bf20c9ef",
+   "id": "b3d29c52",
    "metadata": {},
    "outputs": [],
    "source": []
@@ -1257,7 +2110,7 @@
  ],
  "metadata": {
   "kernelspec": {
-   "display_name": "Python 3 (ipykernel)",
+   "display_name": "Python 3",
    "language": "python",
    "name": "python3"
   },
@@ -1271,7 +2124,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.19"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/mrdna/readers/.segmentmodel_from_cadnano.py.swp b/mrdna/readers/.segmentmodel_from_cadnano.py.swp
new file mode 100644
index 0000000000000000000000000000000000000000..7123f88b4445178a630adc7268e37e691a15e980
GIT binary patch
literal 16384
zcmeHOZ-^vE74I00G5<+Ig5T<9h3VPr>HU|xoQtcjcbCf=Zui)`%O%-e+n(;4nacHa
zcdBc4cXA#Q6^)4aMNLE{elQY<|30W7Br%Ey62*KIA|#@M3K2!npvD+~ulnE2?A~!9
z@q^M0zwPO&datTpy?XWD>)zJ%ol8gA0ejlOb)8{6`rF6bPd#wCarUnbBNpL61Y(w|
zE_A6@CunX(^7PEDcHA8#!b@xs1R{(?VspQr(@y!Wa;Fk5H@Q48m2;o!Nk4S6zmmH?
zmkAnmdOTFU$mfC6mQl~~T(k-!J09fhs(U4YN&>G*0#_Szvom_DPt^9X8?Hb3ny9PB
zl>{mYR1&BpP)VSYKqY}n0+j?R3H)zMK*g6CAI22klug6S?w5?+U(K$&vT}c{{@+>s
zN>={FSp6$meNJ~})<NFSzq0xdW^~b5{iRv?-P!%wvHGmIx>XXWBv479l0YSaN&=Mx
zDhX5)s3cHHpprl(fl30qNWeuveiO={qIeqb|MU3&57!#T^T0E}6TsJiF9BZ!jsSnT
z#xQ;a{1A8=h=Ez)2H>Tu4Pz5n1MUIt25tr34!nAmVf-EV74U7~Tfj$vyMRl9$F4Mt
zGr&5q09*n5<_g33HSkT~LqHq219(4R12+Sg06%$~VSEZ$1sHH6a077ea>Iy#n}8?Z
zY8WAKJ@CiNFfX7B90yi`cK|m7zk7>e`~o-!JP0UY5@-O|0>6K=VSE?(4)9Une&9X8
zpOL8e9`G3O5U>io8+ZW;mgj+|fG2^+fX@J1z)4^qa0^feUdCFy2>bw`b$Jpv&&7tW
zu;06V=@46Bu`89`;cCfW?)Q$m+h&99Wiv+Jly7@HR`bO(mG7VhnI<2jRdO&7;bvFD
zgSNdL;d73}Q4xCfg{REMuJ!a0$Icd-*a<|UP`9>GQYz_&{w@`p-J!y=ISnL|q9eit
zjIv+lK(q1Y6=-s%EByIfP<INc`fhML55)G0=3=6{u{J-u!P=2zcwizd<SIz6iP<<?
z^iTYE6DyTt#IcOx#2V^dcig4!j-iT6C3vzJ`f1<bY!G37X_@B_JV^NH(n(h&oGnLc
zsTT*FzMA3wVJRbN)=<bqSy~(AJHbw@99m(n?=uhI*)Xgi5B0BOP@sfu3DsqbtM6Mn
zvAVc=H;W??DzpsSqSKeI5>c2K`LINr=}D5>nRVUNQG=M*8*E{L9V5~cc(e<4<s1qg
zngNz3UzMZu@lPoqvtfHtJb-Wt3ax)yj1JVL!)fiu9(U77YT^}*(_cH<>F<w-VOCRg
znon6Pbn#V^jJC0cwij}2B@%ihRXXp(RNyA15JotiPirogJ4tnf;i$Ikveid8?=s#I
zjs-WLw^{xTmP0Fq4ew-MX(c8tghi!|A?qNy>dTN}VS;jq`Uz6y{ea7RV3*VuHot>C
z;I!O?Pl^!o#@aO5w7qY#*O3v-OEJNTlv_#PJRkkuVR|xu2c`=yqg{fTisj_o{%L!v
z70aR(dp%dZhp*qHlMdg}ldf-+=I!;cX7yBdb?XfpDy>qYS3vTZyXp;NObhy7V7yk>
z8`uq;SSYVMG~8}%F)X1)3u<L5X0c3(u+G|EX!DX8<<#=pLFBEac0>49X<llzS|MUz
zNbZr%vtVID57x5F85X&putapi#Kr-jRl1<S`Nf2)C$MKiGLca0F_mCG???`9cemU@
zLAb?P9~PZDfVJI(K}WaxabF!4+GmN<_SsczI_FRjuZm7ru`W92K0CC$$Yi8kg)Tfy
z@-+4uXW9UO73}?7y&!C6TMGj{c&aGfJ5)MU49T$DR#%R)gNx{6d1cn#SBh<diP&%1
z35Si4uE&RtGgPIPky;d;5Vs>-v6`NkgVP&x)(1>2J$~t+Wcg}nON3*_Nmoqot<(Tz
zwjXPV(^{L6VROWGy(TA5Z@IFQlt<(7^wU#)`q+*mLZKWd>p&||ZuQFjr;8mNq&VqC
zk2_eT;X}Nv_GFYK+Fu$HN?DClQo6ZvW9`FK<#zDOM*x*x!|&WjvG6+~M<v1G!+kww
zTeHK-Borr~rJ)-W5w%16(kM-&`vZmKM9|T<J9F~2#<*UH>GAW+)3)tW?x`5E19j&S
zqfeJo$#m<$RSKtt_B1eDhqNLqGt>6@n(O9Ngl2Tpx(DsZ>x+A?54uLH+NcH)vBeB8
za1-pQ^qXWoSaW!uq<6-|1h_VtC#2U8TuGZbQL^u;B(KV(h`o)yoOGjp;IkH|{q3E`
z_I0(oU<WeZi`9Th-XTk1mRgkVWwJD67qFsaG>Gdq?QVQ7jc2)|u95feNBveXXof;}
zmyL!h$uXSQRwTf1V(tkyV7*9*wjO(0?YXeN<@7K&3`FZ+jTT~`-V3!{NVo^V5Ou;K
zN?0Z~EVpz%i?ZeG?FU6>y?&qs99z9?B=V3%<VC%f2)Pe2YjbAX`crWm--yF2xv#HH
zbY^RMGjrsB;f9*Ld8Xx>DmO~QBeB?VL5|CDJuB{Kbrw5BG8-?>xw;s6IuI|4Bncxm
zcl231&FY{owXl+S-t3GNk)6i!F1Dh+THF?iVHCtE`%VzGa)$Ifua6Qd86^1=yv=w(
z^9|#?h-~cyYfeHJBOkMxXMNRf9-tC~;{WFnpKc(grT9O8zy4{&_@{t9z@HG){|tB(
z_#E(Afa3iPU=E<TzX4naJck(n9PoYMD}Vq_0w(|qxDj|9asETV=Ya=+R}kaB0Q?wu
z7&rx71zZWdjJW=v0ObIl0looz6`(vo46FgS0u1;EV*M9^M}SWN9|t}F+zFfnt^xjr
z9KcV3uLGY19t6$;61W3+7hnSh@GNo!KL;KGJ_Z~BY=H6xF9N>=o&(MSUjQBe@HvIi
z0$kuW;4tuBU=Q#TWc)PnWq{<p4pdhqfl31ZrxGBqf}8-xWIuEgfwN58cuEMV$cqA#
z!Pr}@c5l>b3cqGC`VT3Kb>jZQG)rBhl%C4ry3o1d+?zz9(-r|Y+rv%3Nw=_jbS|59
zYBpuslMS1G)vb2JMmXA!&6!~;9MYjOYp3wvTR0gQ+>0}3Yc`Tz-~#@6Q_6z1$-$t5
zC*wU?&m1UNc_as%(1q*kP`;<`I6YT{j#GypG=a<z^?^yj%buXgY2R|%nz3d#sCp1?
z_5z#!9Pjp(A8m#3j*Esmvttf5I>a~O^dVq481=yyV;teJ1cyCO5@jg}eI%E@V|qeU
ze3H8gaFtV^!D0|>P?Rr>Jf*@I&A{!#D|Iw1h|J>)x4B5zT?AKB5;$J)I9)hA<gE1K
znF9tDL%8|yD2!Z=LXK1-3wT%zTW8s(v)oInF+`aSE_KY-rZ;p<mh&Rwe0g{22EJq3
z6?vD`SA(VQa>^dAyFpYF5LgJ$4r$@^k^YuK$vxzv)4azbv6MQS<>C<i$d!BKDWzr&
zJ<l1FKdycKG#aBv)cTzAm?QZrQ*RsEM=2u;I#;osNU8PiqWF>=e!a(ZHzkQxtiS?^
ze|$abC+Zd}#+fYxNr?ExaOT|(cU<Xp#U?iy?Gx;DoluD6faO7IrmVw3jWH~Ve5)?5
zE-x(~ffE<H@I=Yc_qpN{=>_=3X+)x(WtMSbl!zV5{f;Uy^)TEeq*w1^jstSB%k%(Z
z3heO?guB3IN8_e(>g2w@D|ty;63(QA<2lbU2I$2m86hpR#bp*K7y6>dpyx-q<|9)0
zl(5WNjd7y2(rd6YGRzh!lR2r)?kY$%_RegP@EthXR-TI6fYgvcoHX}O%^+`?YS{4F
zK?WDiX@OxU4-=E|O*<rI)qF5@{dxuwec2YB1ls&&D^S*;_(IV!?S&;opd2ZJT!oO*
zVJ5<esLedSzulgmd1r(95i&_+8DKnhta&(1<I)JzPIFyC5KEzMUsCERl9W6P2GDxE
z3FuH*hq#m%DIE+v-LW!LFFk#lD8@~<1jefnN&3R$uug3wU@~hfVK4w^ub<{E5N9i#
zKGczm<QzqD`J^;62JNIcDt}qR5PYjHEUQB9#?Ceh$r46Sciv!o7Fedcx&WhEi*?Q;
z*5)JfNEeUMK+VQRsYu17*laQSY=_!(fQ!i9oJ||q>CMD6EH-AUNEc9!UJqrH%+!5+
zBbEKlowvWa*U_KegqrinON3nXBvg9sk&jZh%*wK9>)n`+;C$A3bZ3%jF6P2;Wu6d;
z2nNDMqK(!Y39Fr(E~{XB7g(^jwjS0-7!k7x+Ay&AcG7Q|vSzMtHRj=k$@=<CZ5}o~
z*vWK^#9B`#iA+;jwe^{cqB=87b>;$8U8Uk=erigmgeY;?hEc?Ou-+8>l|;XTo4RFs
wZf^hF+!Q5!@lW@iX5ijGXp(@MB5cM31#{ly+sNW5s-@R#$a^F00~>4n2cRed(*OVf

literal 0
HcmV?d00001

diff --git a/mrdna/readers/cadnano_segments.py b/mrdna/readers/cadnano_segments.py
index b39bd2e..47cf148 100644
--- a/mrdna/readers/cadnano_segments.py
+++ b/mrdna/readers/cadnano_segments.py
@@ -17,166 +17,7 @@ from ..model.dna_sequence import m13 as m13seq
 ##   - helices that should be stacked across an empty region (crossovers from and end in the helix to another end in the helix)
 ##   - circular constructs
 
-def combineRegionLists(loHi1,loHi2,intersect=False):
-
-    """Combines two lists of (lo,hi) pairs specifying integer
-    regions a single list of regions.  """
-
-    ## Validate input
-    for l in (loHi1,loHi2):
-        ## Assert each region in lists is sorted
-        for pair in l:
-            assert(len(pair) == 2)
-            assert(pair[0] <= pair[1])
-
-    if len(loHi1) == 0:
-        if intersect:
-            return []
-        else:
-            return loHi2
-    if len(loHi2) == 0:
-        if intersect:
-            return []
-        else:
-            return loHi1
-
-    ## Break input into lists of compact regions
-    compactRegions1,compactRegions2 = [[],[]]
-    for compactRegions,loHi in zip(
-            [compactRegions1,compactRegions2],
-            [loHi1,loHi2]):
-        tmp = []
-        lastHi = loHi[0][0]-1
-        for lo,hi in loHi:
-            if lo-1 != lastHi:
-                compactRegions.append(tmp)
-                tmp = []
-            tmp.append((lo,hi))
-            lastHi = hi
-        if len(tmp) > 0:
-            compactRegions.append(tmp)
-
-    ## Build result
-    result = []
-    region = []
-    i,j = [0,0]
-    compactRegions1.append([[1e10]])
-    compactRegions2.append([[1e10]])
-    while i < len(compactRegions1)-1 or j < len(compactRegions2)-1:
-        cr1 = compactRegions1[i]
-        cr2 = compactRegions2[j]
-
-        ## initialize region
-        if len(region) == 0:
-            if cr1[0][0] <= cr2[0][0]:
-                region = cr1
-                i += 1
-                continue
-            else:
-                region = cr2
-                j += 1
-                continue
-
-        if region[-1][-1] >= cr1[0][0]:
-            region = combineCompactRegionLists(region, cr1, intersect=False)
-            i+=1
-        elif region[-1][-1] >= cr2[0][0]:
-            region = combineCompactRegionLists(region, cr2, intersect=False)
-            j+=1
-        else:
-            result.extend(region)
-            region = []
-
-    assert( len(region) > 0 )
-    result.extend(region)
-    result = sorted(result)
-
-    # print("loHi1:",loHi1)
-    # print("loHi2:",loHi2)
-    # print(result,"\n")
-
-    if intersect:
-        lo = max( [loHi1[0][0], loHi2[0][0]] )
-        hi = min( [loHi1[-1][1], loHi2[-1][1]] )
-        result = [r for r in result if r[0] >= lo and r[1] <= hi]
-
-    return result
-
-def combineCompactRegionLists(loHi1,loHi2,intersect=False):
-
-    """Combines two lists of (lo,hi) pairs specifying regions within a
-    compact integer set into a single list of regions.
-
-    examples:
-    loHi1 = [[0,4],[5,7]]
-    loHi2 = [[2,4],[5,9]]
-    out = [(0, 1), (2, 4), (5, 7), (8, 9)]
-
-    loHi1 = [[0,3],[5,7]]
-    loHi2 = [[2,4],[5,9]]
-    out = [(0, 1), (2, 3), (4, 4), (5, 7), (8, 9)]
-    """
-
-    ## Validate input
-    for l in (loHi1,loHi2):
-        ## Assert each region in lists is sorted
-        for pair in l:
-            assert(len(pair) == 2)
-            assert(pair[0] <= pair[1])
-        ## Assert lists are compact
-        for pair1,pair2 in zip(l[::2],l[1::2]):
-            assert(pair1[1]+1 == pair2[0])
-
-    if len(loHi1) == 0:
-        if intersect:
-            return []
-        else:
-            return loHi2
-    if len(loHi2) == 0:
-        if intersect:
-            return []
-        else:
-            return loHi1
 
-    ## Find the ends of the region
-    lo = min( [loHi1[0][0], loHi2[0][0]] )
-    hi = max( [loHi1[-1][1], loHi2[-1][1]] )
-
-    ## Make a list of indices where each region will be split
-    splitAfter = []
-    for l,h in loHi2:
-        if l != lo:
-            splitAfter.append(l-1)
-        if h != hi:
-            splitAfter.append(h)
-
-    for l,h in loHi1:
-        if l != lo:
-            splitAfter.append(l-1)
-        if h != hi:
-            splitAfter.append(h)
-    splitAfter = sorted(list(set(splitAfter)))
-
-    # print("splitAfter:",splitAfter)
-
-    split=[]
-    last = -2
-    for s in splitAfter:
-        split.append(s)
-        last = s
-
-    # print("split:",split)
-    returnList = [(i+1,j) if i != j else (i,j) for i,j in zip([lo-1]+split,split+[hi])]
-
-    if intersect:
-        lo = max( [loHi1[0][0], loHi2[0][0]] )
-        hi = min( [loHi1[-1][1], loHi2[-1][1]] )
-        returnList = [r for r in returnList if r[0] >= lo and r[1] <= hi]
-
-    # print("loHi1:",loHi1)
-    # print("loHi2:",loHi2)
-    # print(returnList,"\n")
-    return returnList
 
 class cadnano_part(SegmentModel):
     def __init__(self, part, 
@@ -700,6 +541,166 @@ def read_model(json_data, sequence=None, fill_sequence='T', **kwargs):
 # pynvml.nvmlShutdown()
 # gpus = [0,1,2]
 # print(gpus)
+def combineRegionLists(loHi1,loHi2,intersect=False):
+
+    """Combines two lists of (lo,hi) pairs specifying integer
+    regions a single list of regions.  """
+
+    ## Validate input
+    for l in (loHi1,loHi2):
+        ## Assert each region in lists is sorted
+        for pair in l:
+            assert(len(pair) == 2)
+            assert(pair[0] <= pair[1])
+
+    if len(loHi1) == 0:
+        if intersect:
+            return []
+        else:
+            return loHi2
+    if len(loHi2) == 0:
+        if intersect:
+            return []
+        else:
+            return loHi1
+
+    ## Break input into lists of compact regions
+    compactRegions1,compactRegions2 = [[],[]]
+    for compactRegions,loHi in zip(
+            [compactRegions1,compactRegions2],
+            [loHi1,loHi2]):
+        tmp = []
+        lastHi = loHi[0][0]-1
+        for lo,hi in loHi:
+            if lo-1 != lastHi:
+                compactRegions.append(tmp)
+                tmp = []
+            tmp.append((lo,hi))
+            lastHi = hi
+        if len(tmp) > 0:
+            compactRegions.append(tmp)
+
+    ## Build result
+    result = []
+    region = []
+    i,j = [0,0]
+    compactRegions1.append([[1e10]])
+    compactRegions2.append([[1e10]])
+    while i < len(compactRegions1)-1 or j < len(compactRegions2)-1:
+        cr1 = compactRegions1[i]
+        cr2 = compactRegions2[j]
+
+        ## initialize region
+        if len(region) == 0:
+            if cr1[0][0] <= cr2[0][0]:
+                region = cr1
+                i += 1
+                continue
+            else:
+                region = cr2
+                j += 1
+                continue
+
+        if region[-1][-1] >= cr1[0][0]:
+            region = combineCompactRegionLists(region, cr1, intersect=False)
+            i+=1
+        elif region[-1][-1] >= cr2[0][0]:
+            region = combineCompactRegionLists(region, cr2, intersect=False)
+            j+=1
+        else:
+            result.extend(region)
+            region = []
+
+    assert( len(region) > 0 )
+    result.extend(region)
+    result = sorted(result)
+
+    # print("loHi1:",loHi1)
+    # print("loHi2:",loHi2)
+    # print(result,"\n")
+
+    if intersect:
+        lo = max( [loHi1[0][0], loHi2[0][0]] )
+        hi = min( [loHi1[-1][1], loHi2[-1][1]] )
+        result = [r for r in result if r[0] >= lo and r[1] <= hi]
+
+    return result
+
+def combineCompactRegionLists(loHi1,loHi2,intersect=False):
+
+    """Combines two lists of (lo,hi) pairs specifying regions within a
+    compact integer set into a single list of regions.
+
+    examples:
+    loHi1 = [[0,4],[5,7]]
+    loHi2 = [[2,4],[5,9]]
+    out = [(0, 1), (2, 4), (5, 7), (8, 9)]
+
+    loHi1 = [[0,3],[5,7]]
+    loHi2 = [[2,4],[5,9]]
+    out = [(0, 1), (2, 3), (4, 4), (5, 7), (8, 9)]
+    """
+
+    ## Validate input
+    for l in (loHi1,loHi2):
+        ## Assert each region in lists is sorted
+        for pair in l:
+            assert(len(pair) == 2)
+            assert(pair[0] <= pair[1])
+        ## Assert lists are compact
+        for pair1,pair2 in zip(l[::2],l[1::2]):
+            assert(pair1[1]+1 == pair2[0])
+
+    if len(loHi1) == 0:
+        if intersect:
+            return []
+        else:
+            return loHi2
+    if len(loHi2) == 0:
+        if intersect:
+            return []
+        else:
+            return loHi1
+
+    ## Find the ends of the region
+    lo = min( [loHi1[0][0], loHi2[0][0]] )
+    hi = max( [loHi1[-1][1], loHi2[-1][1]] )
+
+    ## Make a list of indices where each region will be split
+    splitAfter = []
+    for l,h in loHi2:
+        if l != lo:
+            splitAfter.append(l-1)
+        if h != hi:
+            splitAfter.append(h)
+
+    for l,h in loHi1:
+        if l != lo:
+            splitAfter.append(l-1)
+        if h != hi:
+            splitAfter.append(h)
+    splitAfter = sorted(list(set(splitAfter)))
+
+    # print("splitAfter:",splitAfter)
+
+    split=[]
+    last = -2
+    for s in splitAfter:
+        split.append(s)
+        last = s
+
+    # print("split:",split)
+    returnList = [(i+1,j) if i != j else (i,j) for i,j in zip([lo-1]+split,split+[hi])]
+
+    if intersect:
+        lo = max( [loHi1[0][0], loHi2[0][0]] )
+        hi = min( [loHi1[-1][1], loHi2[-1][1]] )
+        returnList = [r for r in returnList if r[0] >= lo and r[1] <= hi]
+
+    # print("loHi1:",loHi1)
+    # print("loHi2:",loHi2)
+    # print(returnList,"\n")
+    return returnList
 
 if __name__ == '__main__':
     loHi1 = [[0,4],[5,7]]
diff --git a/mrdna/readers/libs b/mrdna/readers/libs
new file mode 120000
index 0000000..8266af3
--- /dev/null
+++ b/mrdna/readers/libs
@@ -0,0 +1 @@
+/home/pinyili2/server5/tacoxDNA/src/libs/
\ No newline at end of file
diff --git a/mrdna/readers/list.pdb b/mrdna/readers/list.pdb
index e402a34..a986d3d 100644
--- a/mrdna/readers/list.pdb
+++ b/mrdna/readers/list.pdb
@@ -1,8 +1,8 @@
 CRYST1 5000.000 5000.000 5000.000  90.00  90.00  90.00 P 1           1
-ATOM      1 DNA  DNA A 1       0.50000 0.00000 5.10000  0.00  0.00   0     0
-ATOM      2 DNA  DNA A 2       0.50000 0.00000 11.9000  0.00  0.00   0     0
-ATOM      3 DNA  DNA A 3       0.50000 0.00000 18.7000  0.00  0.00   0     0
-ATOM      4 NAS  NAS A 4       0.00000 0.00000-1.70000  0.00  0.00   0     1
-ATOM      5 NAS  NAS A 5       0.00000 0.00000 1.70000  0.00  0.00   0     1
-ATOM      6 NAS  NAS A 6       0.00000 0.00000 5.10000  0.00  0.00   0     1
-ATOM      7 NAS  NAS A 7       0.00000 0.00000 20.4000  0.00  0.00   0     2
+ATOM      1 DNA  DNA A 1       0.50000 0.00000 8.50000  0.00  0.00   0     0
+ATOM      2 DNA  DNA A 2       0.50000 0.00000 15.3000  0.00  0.00   0     1
+ATOM      3 DNA  DNA A 3       0.50000 0.00000 15.3000  0.00  0.00   0     1
+ATOM      4 NAS  NAS A 4       0.00000 0.00000-1.70000  0.00  0.00   0     2
+ATOM      5 NAS  NAS A 5       0.00000 0.00000 1.70000  0.00  0.00   0     2
+ATOM      6 NAS  NAS A 6       0.00000 0.00000 5.10000  0.00  0.00   0     2
+ATOM      7 NAS  NAS A 7       0.00000 0.00000 20.4000  0.00  0.00   0     3
diff --git a/mrdna/readers/list.psf b/mrdna/readers/list.psf
index 89e10e7..828fb57 100644
--- a/mrdna/readers/list.psf
+++ b/mrdna/readers/list.psf
@@ -3,20 +3,20 @@ PSF NAMD
        0 !NTITLE
 
        7 !NATOM
-         1 0        1        DNA      DNA      D000   0.000000      150.0000 0
-         2 0        2        DNA      DNA      D001   0.000000      300.0000 0
-         3 0        3        DNA      DNA      D001   0.000000      300.0000 0
-         4 1        4        NAS      NAS      S000   0.000000      150.0000 0
-         5 1        5        NAS      NAS      S000   0.000000      150.0000 0
-         6 1        6        NAS      NAS      S001   0.000000       75.0000 0
-         7 2        7        NAS      NAS      S000   0.000000      150.0000 0
+         1 0        1        DNA      DNA      D000   0.000000      225.0000 0
+         2 1        2        DNA      DNA      D001   0.000000      300.0000 0
+         3 1        3        DNA      DNA      D002   0.000000      375.0000 0
+         4 2        4        NAS      NAS      S000   0.000000      150.0000 0
+         5 2        5        NAS      NAS      S000   0.000000      150.0000 0
+         6 2        6        NAS      NAS      S001   0.000000       75.0000 0
+         7 3        7        NAS      NAS      S000   0.000000      150.0000 0
 
        7 !NBOND
-       4       7        3       7        1       2        1       6
-       2       3        4       5        5       6 
+       1       6        4       5        5       6        4       7
+       1       3        2       3        2       7 
 
        3 !NTHETA
-       5       4       7        4       5       6        1       2       3
+       4       5       6        5       4       7        1       3       2
 
        0 !NPHI
 
diff --git a/mrdna/readers/test.ipynb b/mrdna/readers/test.ipynb
index 8e5ae43..2b75bca 100644
--- a/mrdna/readers/test.ipynb
+++ b/mrdna/readers/test.ipynb
@@ -2,97 +2,765 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 20,
-   "id": "ef4ed889-492f-4ba3-8c1d-a0fc607b1f57",
-   "metadata": {},
+   "execution_count": 124,
+   "id": "767c8226",
+   "metadata": {
+    "scrolled": true
+   },
    "outputs": [
     {
      "data": {
-      "text/html": [
-       "<div>\n",
-       "<style scoped>\n",
-       "    .dataframe tbody tr th:only-of-type {\n",
-       "        vertical-align: middle;\n",
-       "    }\n",
-       "\n",
-       "    .dataframe tbody tr th {\n",
-       "        vertical-align: top;\n",
-       "    }\n",
-       "\n",
-       "    .dataframe thead th {\n",
-       "        text-align: right;\n",
-       "    }\n",
-       "</style>\n",
-       "<table border=\"1\" class=\"dataframe\">\n",
-       "  <thead>\n",
-       "    <tr style=\"text-align: right;\">\n",
-       "      <th></th>\n",
-       "      <th>name</th>\n",
-       "      <th>vstrands</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>0</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 12, 'col': 16, 'num': 0, 'scaf': [[-1,...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>1</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 12, 'col': 15, 'num': 1, 'scaf': [[-1,...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>2</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 13, 'col': 15, 'num': 2, 'scaf': [[-1,...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>3</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 13, 'col': 16, 'num': 3, 'scaf': [[-1,...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>4</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 13, 'col': 17, 'num': 4, 'scaf': [[-1,...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>5</th>\n",
-       "      <td>test.json</td>\n",
-       "      <td>{'row': 12, 'col': 17, 'num': 5, 'scaf': [[5, ...</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
       "text/plain": [
-       "        name                                           vstrands\n",
-       "0  test.json  {'row': 12, 'col': 16, 'num': 0, 'scaf': [[-1,...\n",
-       "1  test.json  {'row': 12, 'col': 15, 'num': 1, 'scaf': [[-1,...\n",
-       "2  test.json  {'row': 13, 'col': 15, 'num': 2, 'scaf': [[-1,...\n",
-       "3  test.json  {'row': 13, 'col': 16, 'num': 3, 'scaf': [[-1,...\n",
-       "4  test.json  {'row': 13, 'col': 17, 'num': 4, 'scaf': [[-1,...\n",
-       "5  test.json  {'row': 12, 'col': 17, 'num': 5, 'scaf': [[5, ..."
+       "dict_keys(['row', 'col', 'num', 'scaf', 'stap', 'loop', 'skip', 'scafLoop', 'stapLoop', 'stap_colors'])"
       ]
      },
-     "execution_count": 20,
+     "execution_count": 124,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
     "import pandas as pd\n",
-    "\n",
-    "\n",
+    "import pickle\n",
+    "import numpy as np\n",
     "df=pd.read_json(\"test.json\")\n",
-    "df"
+    "df[\"vstrands\"][0].keys()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 164,
+   "id": "bf2d37ca",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[[-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [0, 3, -1, -1],\n",
+       " [0, 4, 0, 2],\n",
+       " [0, 5, 0, 3],\n",
+       " [0, 6, 0, 4],\n",
+       " [0, 7, 0, 5],\n",
+       " [0, 8, 0, 6],\n",
+       " [0, 9, 0, 7],\n",
+       " [0, 10, 0, 8],\n",
+       " [0, 11, 0, 9],\n",
+       " [0, 12, 0, 10],\n",
+       " [0, 13, 0, 11],\n",
+       " [0, 14, 0, 12],\n",
+       " [0, 15, 0, 13],\n",
+       " [0, 16, 0, 14],\n",
+       " [0, 17, 0, 15],\n",
+       " [0, 18, 0, 16],\n",
+       " [0, 19, 0, 17],\n",
+       " [0, 20, 0, 18],\n",
+       " [1, 20, 0, 19],\n",
+       " [0, 22, 1, 21],\n",
+       " [0, 23, 0, 21],\n",
+       " [-1, -1, 0, 22],\n",
+       " [0, 25, -1, -1],\n",
+       " [0, 26, 0, 24],\n",
+       " [0, 27, 0, 25],\n",
+       " [5, 27, 0, 26],\n",
+       " [0, 29, 5, 28],\n",
+       " [0, 30, 0, 28],\n",
+       " [0, 31, 0, 29],\n",
+       " [0, 32, 0, 30],\n",
+       " [0, 33, 0, 31],\n",
+       " [0, 34, 0, 32],\n",
+       " [0, 35, 0, 33],\n",
+       " [0, 36, 0, 34],\n",
+       " [0, 37, 0, 35],\n",
+       " [0, 38, 0, 36],\n",
+       " [-1, -1, 0, 37],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1]]"
+      ]
+     },
+     "execution_count": 164,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "df[\"vstrands\"][0][\"stap\"]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 65,
+   "id": "4ce8f67f",
+   "metadata": {},
+   "outputs": [
+    {
+     "ename": "UnicodeDecodeError",
+     "evalue": "'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mUnicodeDecodeError\u001b[0m                        Traceback (most recent call last)",
+      "\u001b[0;32m<ipython-input-65-71f198107f5e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"test.virt2nuc\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\"r\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mpickle\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mload\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+      "\u001b[0;32m/data/server1/cmaffeo2/miniconda3/lib/python3.8/codecs.py\u001b[0m in \u001b[0;36mdecode\u001b[0;34m(self, input, final)\u001b[0m\n\u001b[1;32m    320\u001b[0m         \u001b[0;31m# decode input (taking the buffer into account)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    321\u001b[0m         \u001b[0mdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuffer\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0minput\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 322\u001b[0;31m         \u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconsumed\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_buffer_decode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0merrors\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfinal\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    323\u001b[0m         \u001b[0;31m# keep undecoded input until the next call\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    324\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuffer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mconsumed\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;31mUnicodeDecodeError\u001b[0m: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte"
+     ]
+    }
+   ],
+   "source": [
+    "f=open(\"test.virt2nuc\",\"r\")\n",
+    "pickle.load(f)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 119,
+   "id": "625c831b",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "210"
+      ]
+     },
+     "execution_count": 119,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "vh_vb,pattern=pd.read_pickle(\"test.virt2nuc\")\n",
+    "len(vh_vb._scaf)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 66,
+   "id": "6a4129c2",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{0: (12, 16), 1: (12, 15), 2: (13, 15), 3: (13, 16), 4: (13, 17), 5: (12, 17)}"
+      ]
+     },
+     "execution_count": 66,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "pattern"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 141,
+   "id": "f85af2e4",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(0, 40)\n",
+      "(0, 41)\n"
+     ]
+    },
+    {
+     "ename": "AttributeError",
+     "evalue": "'NoneType' object has no attribute 'append'",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
+      "\u001b[0;32m<ipython-input-141-a0e59df19136>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ms\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdecode_vh_vb\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"test.virt2nuc\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-140-99891f72666f>\u001b[0m in \u001b[0;36mdecode_vh_vb\u001b[0;34m(virt2nuc)\u001b[0m\n\u001b[1;32m     21\u001b[0m     \u001b[0mscafs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvh_vb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_scaf\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     22\u001b[0m     \u001b[0mstaps\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvh_vb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stap\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 23\u001b[0;31m     \u001b[0mscaf_strands\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfind_segs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mscafs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     24\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     25\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0mvh_list\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-140-99891f72666f>\u001b[0m in \u001b[0;36mfind_segs\u001b[0;34m(vir2nuc_scaf)\u001b[0m\n\u001b[1;32m      8\u001b[0m             \u001b[0mb\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvir2nuc_scaf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      9\u001b[0m             \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m             \u001b[0moligos\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0moligo\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0moligos\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0moligo\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvir2nuc_scaf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     11\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0moligos\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     12\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;31mAttributeError\u001b[0m: 'NoneType' object has no attribute 'append'"
+     ]
+    }
+   ],
+   "source": [
+    "s=decode_vh_vb(\"test.virt2nuc\")[0]\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 165,
+   "id": "aefe656e",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class strands():\n",
+    "    def __init__(self):\n",
+    "        self.row=0 \n",
+    "        self.col=0\n",
+    "        self.num=0\n",
+    "        self.scaf=[]\n",
+    "        self.stap=[]\n",
+    "        self.loop=[]\n",
+    "        self.skip=[]\n",
+    "        self.scafLoop=[]\n",
+    "        self.stapLoop=[]\n",
+    "        self.stap_colors=[]\n",
+    "        self.scaf_contact={}\n",
+    "        self.stap_connect={}\n",
+    "    def to_dict(self):\n",
+    "        d={}\n",
+    "        d['row']=self.row\n",
+    "        d['col']=self.col\n",
+    "        d['num']=self.num\n",
+    "        d['scaf']=self.scaf\n",
+    "        d['stap']=self.stap\n",
+    "        d['loop']=self.loop\n",
+    "        d['skip']=self.skip\n",
+    "        d['scafLoop']=self.scafLoop\n",
+    "        d['stapLoop']=self.stapLoop\n",
+    "        d['stap_colors']=self.stap_colors\n",
+    "        return d\n",
+    "    \n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 160,
+   "id": "e154a8c3",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def find_segs(vir2nuc_scaf):\n",
+    "    oligos={}\n",
+    "    for i in range(len(vir2nuc_scaf)):\n",
+    "        oligo,ox_ind=list(vir2nuc_scaf.values())[i]\n",
+    "        if oligo not in oligos.keys():\n",
+    "            oligos[oligo]=[]\n",
+    "        oligos[oligo].append(list(vir2nuc_scaf.keys())[i])\n",
+    "    return oligos\n",
+    "    \n",
+    "def decode_vh_vb(virt2nuc):\n",
+    "    vh_list=[]\n",
+    "    vh_vb,pattern=pd.read_pickle(virt2nuc)\n",
+    "    for i in pattern.keys():\n",
+    "        s=strands()\n",
+    "        s.row,s.col=pattern[i]\n",
+    "        s.num=i\n",
+    "        vh_list.append(s)\n",
+    "    scafs=vh_vb._scaf\n",
+    "    staps=vh_vb._stap\n",
+    "    scaf_strands=find_segs(scafs)\n",
+    "    scaf_oligos=list(scaf_strands.keys())\n",
+    "    for i in scaf_oligos:\n",
+    "        bases=len(scaf_oligos)\n",
+    "        vh0,vb0=scaf_oligos[i][0]\n",
+    "        vh1,vb1=scaf_oligos[i][1]\n",
+    "        if vb0>vb1:#53\n",
+    "            scaf_contact\n",
+    "        else: #35\n",
+    "            \n",
+    "            \n",
+    "    return vh_list"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 163,
+   "id": "09619e4e",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{0: [(0, 39), (0, 40), (0, 41)],\n",
+       " 1: [(1, 41), (1, 40), (1, 39)],\n",
+       " 2: [(2, 39), (2, 40), (2, 41)],\n",
+       " 4: [(3, 41), (3, 40), (3, 39), (3, 38), (3, 37)],\n",
+       " 5: [(4, 0), (4, 1), (4, 2), (4, 3)],\n",
+       " 6: [(5, 3), (5, 2), (5, 1), (5, 0)],\n",
+       " 7: [(5, 22),\n",
+       "  (5, 21),\n",
+       "  (5, 20),\n",
+       "  (5, 19),\n",
+       "  (5, 18),\n",
+       "  (5, 17),\n",
+       "  (5, 16),\n",
+       "  (5, 15),\n",
+       "  (5, 14),\n",
+       "  (5, 13),\n",
+       "  (5, 12),\n",
+       "  (5, 11),\n",
+       "  (5, 10),\n",
+       "  (5, 9),\n",
+       "  (4, 9),\n",
+       "  (4, 10),\n",
+       "  (4, 11),\n",
+       "  (4, 12),\n",
+       "  (4, 13),\n",
+       "  (4, 14),\n",
+       "  (4, 15),\n",
+       "  (3, 15),\n",
+       "  (3, 14),\n",
+       "  (3, 13),\n",
+       "  (3, 12),\n",
+       "  (3, 11),\n",
+       "  (3, 10),\n",
+       "  (3, 9),\n",
+       "  (3, 8),\n",
+       "  (3, 7),\n",
+       "  (3, 6),\n",
+       "  (3, 5),\n",
+       "  (3, 4),\n",
+       "  (3, 3),\n",
+       "  (3, 2),\n",
+       "  (2, 2),\n",
+       "  (2, 3),\n",
+       "  (2, 4),\n",
+       "  (2, 5),\n",
+       "  (2, 6),\n",
+       "  (2, 7),\n",
+       "  (2, 8),\n",
+       "  (2, 9),\n",
+       "  (2, 10),\n",
+       "  (2, 11),\n",
+       "  (2, 12),\n",
+       "  (2, 13),\n",
+       "  (2, 14),\n",
+       "  (2, 15),\n",
+       "  (2, 16),\n",
+       "  (2, 17),\n",
+       "  (2, 18),\n",
+       "  (1, 18),\n",
+       "  (1, 17),\n",
+       "  (1, 16),\n",
+       "  (1, 15),\n",
+       "  (1, 14),\n",
+       "  (1, 13),\n",
+       "  (1, 12),\n",
+       "  (1, 11),\n",
+       "  (1, 10),\n",
+       "  (1, 9),\n",
+       "  (1, 8),\n",
+       "  (1, 7),\n",
+       "  (1, 6),\n",
+       "  (1, 5),\n",
+       "  (0, 5),\n",
+       "  (0, 6),\n",
+       "  (0, 7),\n",
+       "  (0, 8),\n",
+       "  (0, 9),\n",
+       "  (0, 10),\n",
+       "  (0, 11),\n",
+       "  (0, 12),\n",
+       "  (0, 13),\n",
+       "  (0, 14),\n",
+       "  (0, 15),\n",
+       "  (0, 16),\n",
+       "  (0, 17),\n",
+       "  (0, 18),\n",
+       "  (0, 19),\n",
+       "  (0, 20),\n",
+       "  (0, 21),\n",
+       "  (0, 22),\n",
+       "  (0, 23),\n",
+       "  (0, 24),\n",
+       "  (0, 25),\n",
+       "  (0, 26),\n",
+       "  (0, 27),\n",
+       "  (0, 28),\n",
+       "  (0, 29),\n",
+       "  (0, 30),\n",
+       "  (0, 31),\n",
+       "  (0, 32),\n",
+       "  (0, 33),\n",
+       "  (0, 34),\n",
+       "  (0, 35),\n",
+       "  (0, 36),\n",
+       "  (1, 36),\n",
+       "  (1, 35),\n",
+       "  (1, 34),\n",
+       "  (1, 33),\n",
+       "  (1, 32),\n",
+       "  (1, 31),\n",
+       "  (1, 30),\n",
+       "  (1, 29),\n",
+       "  (1, 28),\n",
+       "  (1, 27),\n",
+       "  (1, 26),\n",
+       "  (1, 25),\n",
+       "  (1, 24),\n",
+       "  (1, 23),\n",
+       "  (1, 22),\n",
+       "  (1, 21),\n",
+       "  (1, 20),\n",
+       "  (1, 19),\n",
+       "  (2, 19),\n",
+       "  (2, 20),\n",
+       "  (2, 21),\n",
+       "  (2, 22),\n",
+       "  (2, 23),\n",
+       "  (2, 24),\n",
+       "  (2, 25),\n",
+       "  (2, 26),\n",
+       "  (2, 27),\n",
+       "  (2, 28),\n",
+       "  (2, 29),\n",
+       "  (2, 30),\n",
+       "  (2, 31),\n",
+       "  (2, 32),\n",
+       "  (3, 32),\n",
+       "  (3, 31),\n",
+       "  (3, 30),\n",
+       "  (3, 29),\n",
+       "  (3, 28),\n",
+       "  (3, 27),\n",
+       "  (3, 26),\n",
+       "  (3, 25),\n",
+       "  (3, 24),\n",
+       "  (3, 23),\n",
+       "  (3, 22),\n",
+       "  (3, 21),\n",
+       "  (3, 20),\n",
+       "  (3, 19),\n",
+       "  (3, 18),\n",
+       "  (3, 17),\n",
+       "  (3, 16),\n",
+       "  (4, 16),\n",
+       "  (4, 17),\n",
+       "  (4, 18),\n",
+       "  (4, 19),\n",
+       "  (4, 20),\n",
+       "  (4, 21),\n",
+       "  (4, 22),\n",
+       "  (4, 23),\n",
+       "  (4, 24),\n",
+       "  (4, 25),\n",
+       "  (4, 26),\n",
+       "  (4, 27),\n",
+       "  (4, 28),\n",
+       "  (4, 29),\n",
+       "  (4, 30),\n",
+       "  (4, 31),\n",
+       "  (4, 32),\n",
+       "  (4, 33),\n",
+       "  (4, 34),\n",
+       "  (4, 35),\n",
+       "  (4, 36),\n",
+       "  (4, 37),\n",
+       "  (4, 38),\n",
+       "  (4, 39),\n",
+       "  (5, 39),\n",
+       "  (5, 38),\n",
+       "  (5, 37),\n",
+       "  (5, 36),\n",
+       "  (5, 35),\n",
+       "  (5, 34),\n",
+       "  (5, 33),\n",
+       "  (5, 32),\n",
+       "  (5, 31),\n",
+       "  (5, 30),\n",
+       "  (5, 29),\n",
+       "  (5, 28),\n",
+       "  (5, 27),\n",
+       "  (5, 26),\n",
+       "  (5, 25),\n",
+       "  (5, 24),\n",
+       "  (5, 23)]}"
+      ]
+     },
+     "execution_count": 163,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "scafs=vh_vb._scaf\n",
+    "s=list(scafs.values())\n",
+    "len(scafs)\n",
+    "find_segs(scafs)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 157,
+   "id": "88d989b9",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[(1, 2)]"
+      ]
+     },
+     "execution_count": 157,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "oligos[0]=[]\n",
+    "L=[]\n",
+    "L.append((1,2))\n",
+    "L"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 152,
+   "id": "2909c273",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "(0, 39)"
+      ]
+     },
+     "execution_count": 152,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "list(scafs.keys())[0]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 62,
+   "id": "422e2b48",
+   "metadata": {
+    "scrolled": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{(2, 34): (3, [43]),\n",
+       " (2, 33): (3, [42]),\n",
+       " (2, 32): (3, [41]),\n",
+       " (2, 31): (3, [40]),\n",
+       " (2, 30): (3, [39]),\n",
+       " (2, 29): (3, [38]),\n",
+       " (2, 28): (3, [37]),\n",
+       " (2, 27): (3, [36]),\n",
+       " (2, 26): (3, [35]),\n",
+       " (2, 25): (3, [34]),\n",
+       " (2, 24): (3, [33]),\n",
+       " (2, 23): (3, [32]),\n",
+       " (2, 22): (3, [31]),\n",
+       " (2, 21): (3, [30]),\n",
+       " (2, 20): (3, [29]),\n",
+       " (2, 19): (3, [28]),\n",
+       " (2, 18): (3, [27]),\n",
+       " (2, 17): (3, [26]),\n",
+       " (2, 16): (3, [25]),\n",
+       " (2, 15): (3, [24]),\n",
+       " (2, 14): (3, [23]),\n",
+       " (2, 13): (3, [22]),\n",
+       " (2, 12): (3, [21]),\n",
+       " (2, 11): (3, [20]),\n",
+       " (2, 10): (3, [19]),\n",
+       " (2, 9): (3, [18]),\n",
+       " (2, 8): (3, [17]),\n",
+       " (2, 7): (3, [16]),\n",
+       " (2, 6): (3, [15]),\n",
+       " (2, 5): (3, [14]),\n",
+       " (2, 4): (3, [13]),\n",
+       " (2, 3): (3, [12]),\n",
+       " (2, 2): (3, [11]),\n",
+       " (2, 1): (3, [10]),\n",
+       " (2, 0): (3, [9]),\n",
+       " (1, 3): (8, [281]),\n",
+       " (1, 4): (8, [280]),\n",
+       " (1, 5): (8, [279]),\n",
+       " (1, 6): (8, [278]),\n",
+       " (1, 7): (8, [277]),\n",
+       " (1, 8): (8, [276]),\n",
+       " (1, 9): (8, [275]),\n",
+       " (1, 10): (8, [274]),\n",
+       " (1, 11): (8, [273]),\n",
+       " (1, 12): (8, [272]),\n",
+       " (1, 13): (8, [271]),\n",
+       " (1, 14): (8, [270]),\n",
+       " (1, 15): (8, [269]),\n",
+       " (1, 16): (8, [268]),\n",
+       " (1, 17): (8, [267]),\n",
+       " (1, 18): (8, [266]),\n",
+       " (1, 19): (8, [265]),\n",
+       " (1, 20): (8, [264]),\n",
+       " (0, 20): (8, [263]),\n",
+       " (0, 19): (8, [262]),\n",
+       " (0, 18): (8, [261]),\n",
+       " (0, 17): (8, [260]),\n",
+       " (0, 16): (8, [259]),\n",
+       " (0, 15): (8, [258]),\n",
+       " (0, 14): (8, [257]),\n",
+       " (0, 13): (8, [256]),\n",
+       " (0, 12): (8, [255]),\n",
+       " (0, 11): (8, [254]),\n",
+       " (0, 10): (8, [253]),\n",
+       " (0, 9): (8, [252]),\n",
+       " (0, 8): (8, [251]),\n",
+       " (0, 7): (8, [250]),\n",
+       " (0, 6): (8, [249]),\n",
+       " (0, 5): (8, [248]),\n",
+       " (0, 4): (8, [247]),\n",
+       " (0, 3): (8, [246]),\n",
+       " (0, 2): (8, [245]),\n",
+       " (0, 23): (9, [302]),\n",
+       " (0, 22): (9, [301]),\n",
+       " (0, 21): (9, [300]),\n",
+       " (1, 21): (9, [299]),\n",
+       " (1, 22): (9, [298]),\n",
+       " (1, 23): (9, [297]),\n",
+       " (1, 24): (9, [296]),\n",
+       " (1, 25): (9, [295]),\n",
+       " (1, 26): (9, [294]),\n",
+       " (1, 27): (9, [293]),\n",
+       " (1, 28): (9, [292]),\n",
+       " (1, 29): (9, [291]),\n",
+       " (1, 30): (9, [290]),\n",
+       " (1, 31): (9, [289]),\n",
+       " (1, 32): (9, [288]),\n",
+       " (1, 33): (9, [287]),\n",
+       " (1, 34): (9, [286]),\n",
+       " (1, 35): (9, [285]),\n",
+       " (1, 36): (9, [284]),\n",
+       " (1, 37): (9, [283]),\n",
+       " (1, 38): (9, [282]),\n",
+       " (5, 9): (10, [325]),\n",
+       " (5, 10): (10, [324]),\n",
+       " (5, 11): (10, [323]),\n",
+       " (5, 12): (10, [322]),\n",
+       " (5, 13): (10, [321]),\n",
+       " (5, 14): (10, [320]),\n",
+       " (5, 15): (10, [319]),\n",
+       " (5, 16): (10, [318]),\n",
+       " (5, 17): (10, [317]),\n",
+       " (5, 18): (10, [316]),\n",
+       " (5, 19): (10, [315]),\n",
+       " (5, 20): (10, [314]),\n",
+       " (5, 21): (10, [313]),\n",
+       " (5, 22): (10, [312]),\n",
+       " (5, 23): (10, [311]),\n",
+       " (5, 24): (10, [310]),\n",
+       " (5, 25): (10, [309]),\n",
+       " (5, 26): (10, [308]),\n",
+       " (5, 27): (10, [307]),\n",
+       " (0, 27): (10, [306]),\n",
+       " (0, 26): (10, [305]),\n",
+       " (0, 25): (10, [304]),\n",
+       " (0, 24): (10, [303]),\n",
+       " (0, 38): (11, [348]),\n",
+       " (0, 37): (11, [347]),\n",
+       " (0, 36): (11, [346]),\n",
+       " (0, 35): (11, [345]),\n",
+       " (0, 34): (11, [344]),\n",
+       " (0, 33): (11, [343]),\n",
+       " (0, 32): (11, [342]),\n",
+       " (0, 31): (11, [341]),\n",
+       " (0, 30): (11, [340]),\n",
+       " (0, 29): (11, [339]),\n",
+       " (0, 28): (11, [338]),\n",
+       " (5, 28): (11, [337]),\n",
+       " (5, 29): (11, [336]),\n",
+       " (5, 30): (11, [335]),\n",
+       " (5, 31): (11, [334]),\n",
+       " (5, 32): (11, [333]),\n",
+       " (5, 33): (11, [332]),\n",
+       " (5, 34): (11, [331]),\n",
+       " (5, 35): (11, [330]),\n",
+       " (5, 36): (11, [329]),\n",
+       " (5, 37): (11, [328]),\n",
+       " (5, 38): (11, [327]),\n",
+       " (5, 39): (11, [326]),\n",
+       " (3, 0): (12, [381]),\n",
+       " (3, 1): (12, [380]),\n",
+       " (3, 2): (12, [379]),\n",
+       " (3, 3): (12, [378]),\n",
+       " (3, 4): (12, [377]),\n",
+       " (3, 5): (12, [376]),\n",
+       " (3, 6): (12, [375]),\n",
+       " (3, 7): (12, [374]),\n",
+       " (3, 8): (12, [373]),\n",
+       " (3, 9): (12, [372]),\n",
+       " (3, 10): (12, [371]),\n",
+       " (3, 11): (12, [370]),\n",
+       " (3, 12): (12, [369]),\n",
+       " (3, 13): (12, [368]),\n",
+       " (3, 14): (12, [367]),\n",
+       " (3, 15): (12, [366]),\n",
+       " (3, 16): (12, [365]),\n",
+       " (3, 17): (12, [364]),\n",
+       " (3, 18): (12, [363]),\n",
+       " (3, 19): (12, [362]),\n",
+       " (3, 20): (12, [361]),\n",
+       " (4, 20): (12, [360]),\n",
+       " (4, 19): (12, [359]),\n",
+       " (4, 18): (12, [358]),\n",
+       " (4, 17): (12, [357]),\n",
+       " (4, 16): (12, [356]),\n",
+       " (4, 15): (12, [355]),\n",
+       " (4, 14): (12, [354]),\n",
+       " (4, 13): (12, [353]),\n",
+       " (4, 12): (12, [352]),\n",
+       " (4, 11): (12, [351]),\n",
+       " (4, 10): (12, [350]),\n",
+       " (4, 9): (12, [349]),\n",
+       " (4, 39): (13, [414]),\n",
+       " (4, 38): (13, [413]),\n",
+       " (4, 37): (13, [412]),\n",
+       " (4, 36): (13, [411]),\n",
+       " (4, 35): (13, [410]),\n",
+       " (4, 34): (13, [409]),\n",
+       " (4, 33): (13, [408]),\n",
+       " (4, 32): (13, [407]),\n",
+       " (4, 31): (13, [406]),\n",
+       " (4, 30): (13, [405]),\n",
+       " (4, 29): (13, [404]),\n",
+       " (4, 28): (13, [403]),\n",
+       " (4, 27): (13, [402]),\n",
+       " (4, 26): (13, [401]),\n",
+       " (4, 25): (13, [400]),\n",
+       " (4, 24): (13, [399]),\n",
+       " (4, 23): (13, [398]),\n",
+       " (4, 22): (13, [397]),\n",
+       " (4, 21): (13, [396]),\n",
+       " (3, 21): (13, [395]),\n",
+       " (3, 22): (13, [394]),\n",
+       " (3, 23): (13, [393]),\n",
+       " (3, 24): (13, [392]),\n",
+       " (3, 25): (13, [391]),\n",
+       " (3, 26): (13, [390]),\n",
+       " (3, 27): (13, [389]),\n",
+       " (3, 28): (13, [388]),\n",
+       " (3, 29): (13, [387]),\n",
+       " (3, 30): (13, [386]),\n",
+       " (3, 31): (13, [385]),\n",
+       " (3, 32): (13, [384]),\n",
+       " (3, 33): (13, [383]),\n",
+       " (3, 34): (13, [382])}"
+      ]
+     },
+     "execution_count": 62,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s=vh_vb.__dict__\n",
+    "scafs=s[\"_scaf\"]\n",
+    "staps=s[\"_stap\"]\n",
+    "staps"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
-   "id": "051eb3b8-2bf1-4482-9815-19937f66e09d",
+   "execution_count": 3,
+   "id": "69c011ff",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -217,8 +885,8 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 43,
-   "id": "6e88e214-c870-47d1-9a47-504caa411530",
+   "execution_count": 4,
+   "id": "f2693e7a",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -238,30 +906,215 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 57,
-   "id": "326f70c5-6a80-4802-847a-ae0de82f0eda",
+   "execution_count": 20,
+   "id": "a4594752",
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'{\\n\"stapLoop\":[],\\n\"skip\":[],\\n\"loop\":[],\\n\"stap_colors\":[],\\n\"row\":0,\\n\"col\":0,\\n\"num\":0,\\n\"scafLoop\":[],\\n\"stap\":[[5, 1, -1, -1],[5, 2, 5, 0],[5, 3, 5, 1],[-1, -1, 5, 2],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[5, 10, 4, 9],[5, 11, 5, 9],[5, 12, 5, 10],[5, 13, 5, 11],[5, 14, 5, 12],[5, 15, 5, 13],[5, 16, 5, 14],[5, 17, 5, 15],[5, 18, 5, 16],[5, 19, 5, 17],[5, 20, 5, 18],[5, 21, 5, 19],[5, 22, 5, 20],[-1, -1, 5, 21],[5, 24, -1, -1],[5, 25, 5, 23],[5, 26, 5, 24],[5, 27, 5, 25],[5, 28, 5, 26],[5, 29, 5, 27],[5, 30, 5, 28],[5, 31, 5, 29],[5, 32, 5, 30],[5, 33, 5, 31],[5, 34, 5, 32],[5, 35, 5, 33],[5, 36, 5, 34],[5, 37, 5, 35],[5, 38, 5, 36],[5, 39, 5, 37],[4, 39, 5, 38],[-1, -1, -1, -1],[-1, -1, -1, -1]],\\n\"scaf\":[[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1],[-1, -1, 5, 10],[5, 9, 5, 11],[5, 10, 5, 12],[5, 11, 5, 13],[5, 12, 5, 14],[5, 13, 5, 15],[5, 14, 5, 16],[5, 15, 5, 17],[5, 16, 5, 18],[5, 17, 5, 19],[5, 18, 5, 20],[5, 19, 5, 21],[5, 20, 5, 22],[5, 21, 5, 23],[5, 22, 5, 24],[5, 23, 5, 25],[5, 24, 5, 26],[5, 25, 5, 27],[5, 26, 0, 27],[0, 28, 5, 29],[5, 28, 5, 30],[5, 29, 5, 31],[5, 30, 5, 32],[5, 31, 5, 33],[5, 32, 5, 34],[5, 33, 5, 35],[5, 34, 5, 36],[5, 35, 5, 37],[5, 36, 5, 38],[5, 37, 5, 39],[5, 38, -1, -1],[-1, -1, -1, -1],[-1, -1, -1, -1]]\\n}'"
+       "['__class__',\n",
+       " '__delattr__',\n",
+       " '__dict__',\n",
+       " '__dir__',\n",
+       " '__doc__',\n",
+       " '__eq__',\n",
+       " '__format__',\n",
+       " '__ge__',\n",
+       " '__getattribute__',\n",
+       " '__gt__',\n",
+       " '__hash__',\n",
+       " '__init__',\n",
+       " '__init_subclass__',\n",
+       " '__le__',\n",
+       " '__lt__',\n",
+       " '__module__',\n",
+       " '__ne__',\n",
+       " '__new__',\n",
+       " '__reduce__',\n",
+       " '__reduce_ex__',\n",
+       " '__repr__',\n",
+       " '__setattr__',\n",
+       " '__sizeof__',\n",
+       " '__str__',\n",
+       " '__subclasshook__',\n",
+       " '__weakref__',\n",
+       " 'add_square',\n",
+       " 'cad_index',\n",
+       " 'col',\n",
+       " 'get_length',\n",
+       " 'len',\n",
+       " 'loop',\n",
+       " 'num',\n",
+       " 'row',\n",
+       " 'scaf',\n",
+       " 'scafLoop',\n",
+       " 'skip',\n",
+       " 'skiploop_bases',\n",
+       " 'stap',\n",
+       " 'stapLoop',\n",
+       " 'stap_colors']"
       ]
      },
-     "execution_count": 57,
+     "execution_count": 20,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
     "s0=cadsys.vhelices[0]\n",
-    "s0.__str__()"
+    "dir(s0)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 25,
+   "id": "ca071163",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[[-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, 5, 10],\n",
+       " [5, 9, 5, 11],\n",
+       " [5, 10, 5, 12],\n",
+       " [5, 11, 5, 13],\n",
+       " [5, 12, 5, 14],\n",
+       " [5, 13, 5, 15],\n",
+       " [5, 14, 5, 16],\n",
+       " [5, 15, 5, 17],\n",
+       " [5, 16, 5, 18],\n",
+       " [5, 17, 5, 19],\n",
+       " [5, 18, 5, 20],\n",
+       " [5, 19, 5, 21],\n",
+       " [5, 20, 5, 22],\n",
+       " [5, 21, 5, 23],\n",
+       " [5, 22, 5, 24],\n",
+       " [5, 23, 5, 25],\n",
+       " [5, 24, 5, 26],\n",
+       " [5, 25, 5, 27],\n",
+       " [5, 26, 0, 27],\n",
+       " [0, 28, 5, 29],\n",
+       " [5, 28, 5, 30],\n",
+       " [5, 29, 5, 31],\n",
+       " [5, 30, 5, 32],\n",
+       " [5, 31, 5, 33],\n",
+       " [5, 32, 5, 34],\n",
+       " [5, 33, 5, 35],\n",
+       " [5, 34, 5, 36],\n",
+       " [5, 35, 5, 37],\n",
+       " [5, 36, 5, 38],\n",
+       " [5, 37, 5, 39],\n",
+       " [5, 38, -1, -1],\n",
+       " [-1, -1, -1, -1],\n",
+       " [-1, -1, -1, -1]]"
+      ]
+     },
+     "execution_count": 25,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s0.scaf"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e5913163",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "for s in s0.scaf:\n",
+    "    if s[0]==-1 and s[1]==-1:\n",
+    "        pass\n",
+    "    elif s[2]==len(s0.scaf) and abs(s[3])==1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "id": "3eefca8f",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[-1, -1, -1, -1]"
+      ]
+     },
+     "execution_count": 13,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s0.scaf[0]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "268d5c04",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['__class__',\n",
+       " '__delattr__',\n",
+       " '__dict__',\n",
+       " '__dir__',\n",
+       " '__doc__',\n",
+       " '__eq__',\n",
+       " '__format__',\n",
+       " '__ge__',\n",
+       " '__getattribute__',\n",
+       " '__gt__',\n",
+       " '__hash__',\n",
+       " '__init__',\n",
+       " '__init_subclass__',\n",
+       " '__le__',\n",
+       " '__lt__',\n",
+       " '__module__',\n",
+       " '__ne__',\n",
+       " '__new__',\n",
+       " '__reduce__',\n",
+       " '__reduce_ex__',\n",
+       " '__repr__',\n",
+       " '__setattr__',\n",
+       " '__sizeof__',\n",
+       " '__str__',\n",
+       " '__subclasshook__',\n",
+       " '__weakref__',\n",
+       " 'add_vhelix',\n",
+       " 'bbox',\n",
+       " 'vhelices']"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "dir(cadsys)"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": 36,
-   "id": "7b552911-d7de-4079-ab4d-e859f2281f36",
+   "id": "d3d42e33",
    "metadata": {},
    "outputs": [
     {
@@ -323,7 +1176,7 @@
   {
    "cell_type": "code",
    "execution_count": 1,
-   "id": "94113dfa",
+   "id": "2cc3f477",
    "metadata": {},
    "outputs": [
     {
@@ -349,7 +1202,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "ec7f1e22-6a95-41f9-8c23-7603cc165837",
+   "id": "5d50f58a",
    "metadata": {},
    "outputs": [],
    "source": []
@@ -357,7 +1210,7 @@
   {
    "cell_type": "code",
    "execution_count": 3,
-   "id": "40d7cdcf",
+   "id": "3b40b71b",
    "metadata": {},
    "outputs": [
     {
@@ -377,7 +1230,7 @@
   {
    "cell_type": "code",
    "execution_count": 13,
-   "id": "4b3748a8",
+   "id": "6915bad6",
    "metadata": {},
    "outputs": [
     {
@@ -398,7 +1251,7 @@
   {
    "cell_type": "code",
    "execution_count": 15,
-   "id": "aa8a8cd9",
+   "id": "1c16c59d",
    "metadata": {},
    "outputs": [
     {
@@ -468,7 +1321,7 @@
   {
    "cell_type": "code",
    "execution_count": 16,
-   "id": "e0cab15d",
+   "id": "c61d9586",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -479,7 +1332,7 @@
   {
    "cell_type": "code",
    "execution_count": 26,
-   "id": "9811bf9a",
+   "id": "aeca0546",
    "metadata": {},
    "outputs": [
     {
@@ -588,7 +1441,7 @@
   {
    "cell_type": "code",
    "execution_count": 25,
-   "id": "86403b4b",
+   "id": "90a54834",
    "metadata": {},
    "outputs": [
     {
@@ -609,7 +1462,7 @@
   {
    "cell_type": "code",
    "execution_count": 10,
-   "id": "5c7cea80",
+   "id": "de00fb7e",
    "metadata": {},
    "outputs": [
     {
@@ -640,7 +1493,7 @@
   {
    "cell_type": "code",
    "execution_count": 1,
-   "id": "136dcf08",
+   "id": "716ff2ed",
    "metadata": {},
    "outputs": [
     {
@@ -1137,7 +1990,7 @@
   {
    "cell_type": "code",
    "execution_count": 3,
-   "id": "88f7d20e",
+   "id": "766d0ecd",
    "metadata": {},
    "outputs": [
     {
@@ -1171,7 +2024,7 @@
   {
    "cell_type": "code",
    "execution_count": 4,
-   "id": "69d29f1e",
+   "id": "05456be4",
    "metadata": {},
    "outputs": [
     {
@@ -1191,7 +2044,7 @@
   {
    "cell_type": "code",
    "execution_count": 5,
-   "id": "e103e8b4",
+   "id": "cd1a5604",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -1201,7 +2054,7 @@
   {
    "cell_type": "code",
    "execution_count": 6,
-   "id": "a30b582d",
+   "id": "4346f1fc",
    "metadata": {},
    "outputs": [
     {
@@ -1222,7 +2075,7 @@
   {
    "cell_type": "code",
    "execution_count": 7,
-   "id": "dcd8bf8a",
+   "id": "294094f9",
    "metadata": {},
    "outputs": [
     {
@@ -1249,7 +2102,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "bf20c9ef",
+   "id": "b3d29c52",
    "metadata": {},
    "outputs": [],
    "source": []
@@ -1257,7 +2110,7 @@
  ],
  "metadata": {
   "kernelspec": {
-   "display_name": "Python 3 (ipykernel)",
+   "display_name": "Python 3",
    "language": "python",
    "name": "python3"
   },
@@ -1271,7 +2124,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.19"
+   "version": "3.8.18"
   }
  },
  "nbformat": 4,
diff --git a/mrdna/readers/test.json.oxdna b/mrdna/readers/test.json.oxdna
new file mode 100644
index 0000000..22b3082
--- /dev/null
+++ b/mrdna/readers/test.json.oxdna
@@ -0,0 +1,418 @@
+t = 0
+b = 59.840000 59.840000 59.840000
+E = 0.000000 0.000000 0.000000
+35.75312434114018 45.470817422524235 15.980277060342809 -0.698813111225147 0.7153042957929386 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.46830708232107 45.31526274652053 15.590514205212497 -0.22411767985996922 0.97456208913244 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.144150399289146 45.330773162168974 15.200751350082184 0.31614345852657033 0.9487113963850442 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.37179933844421 47.722103913305695 15.200751350082177 -0.41054607281573 -0.9118398555094973 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.02080474653338 47.76580016075659 15.59051420521249 0.17444491370231707 -0.9846669345943282 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.70618382801968 47.60418257747576 15.980277060342802 0.6988131112251446 -0.7153042957929399 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.54475956148986 49.29581742252423 15.980277060342809 -0.6988131112251457 0.7153042957929381 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.25994230267075 49.140262746520534 15.590514205212497 -0.22411767985996822 0.9745620891324388 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.93578561963883 49.15577316216897 15.200751350082184 0.3161434585265706 0.9487113963850426 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.561656122283225 49.93021208599539 1.1102230246251565e-16 0.9396926207859077 -0.34202014332566855 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.53985546526863 49.59441044543136 0.38976285513031234 0.9760270491435681 0.21764925761439552 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.72845682719759 49.27513424787104 0.7795257102606246 0.6616914459286316 0.7497762535482672 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.06023949562461 49.12855657418608 1.1692885653909368 0.1087203318836026 0.9940723763565297 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.41586177015792 49.199953712414455 1.5590514205212491 -0.4839834590052442 0.875077145975895 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.66535877056129 49.463233032303364 1.9488142756515614 -0.8998117930108621 0.43627827949438 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.71754990973771 49.82217709268453 2.3385771307818737 -0.9867970249715624 -0.1619618211408862 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.55336153668667 50.14560704127664 2.7283399859121857 -0.7131497365531624 -0.701011735461079 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.23279754814879 50.31532292958451 3.118102841042498 -0.1788764223233551 -0.983871549307528 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.873010505596895 50.269300788139226 3.50786569617281 0.42076864859646335 -0.9071679802320541 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.605487335594205 50.024359760536335 3.897628551303122 0.8666405986009411 -0.4989329342272377 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.52799642679254 49.67001541876616 4.287391406433434 0.995792113270385 0.09164096872305229 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.66885742450945 49.335765612762266 4.6771542615637465 0.7610237837422053 0.6487239787295487 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.97659159974164 49.14376449066761 5.066917116694059 0.24813349168855076 0.9687258488873137 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.33873514441879 49.164180331089035 5.4566799718243715 -0.3554390827733704 0.934699448184936 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.62293993025211 49.3895520089922 5.846442826954684 -0.829113725828891 0.5590799850129974 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.72534114449366 49.73751572091242 6.2362056820849965 -0.9997824162314877 -0.0208595348540425 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.60851548017426 50.08090546689761 6.625968537215309 -0.8050729756991452 -0.5931757781626982 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.315157769870716 50.29422683783102 7.0157313923456215 -0.31614345852657166 -0.9487113963850422 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.96154078962503 50.30217125564545 7.405494247475934 0.27321817521622777 -0.9619520927424158 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.663494595457585 50.10785396657858 7.7952571026062465 0.7699618321619808 -0.6380899442976392 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.527898468248125 49.778909544261076 8.185019957736559 0.9959553775110749 -0.08984924043513565 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.60243355924406 49.43100831848251 8.574782812866871 0.8717302258511888 0.4899861358624689 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.86089027809679 49.1864866074467 8.964545667997184 0.44096902776330643 0.89752232092215 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.21238465816112 49.13132825838522 9.354308523127496 -0.14485493901058039 0.9894529026913003 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.53331688103983 49.28492920566787 9.744071378257809 -0.6797419771417614 0.7334513238868737 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.710834034380895 49.59327706597775 10.133834233388122 -0.9756038993768755 0.21953822337040532 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.68251381740292 49.947944104195734 10.523597088518434 -0.9284035377469173 -0.37157350699290564 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.45831477816237 50.22421486539137 10.913359943648747 -0.5547384723459938 -0.8320247756522829 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.11707448023534 50.32494123611259 11.303122798779059 0.013995357532388293 -0.9999020601876663 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.77878698681533 50.214703699476466 11.692885653909372 0.5778078465657451 -0.8161728324607816 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.56240803410816 49.93226628780204 12.082648509039684 0.9384394344110165 -0.3454438130034033 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.54402532301732 49.57694556138582 12.472411364169997 0.9690772862290773 0.24675739769029417 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.72846019219666 49.275131278219355 12.862174219300309 0.6616858375968585 0.7497812029677342 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.99195475891848 49.14004425137888 13.251937074430622 0.22252822639381867 0.9749262477018558 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.903691545284474 50.812209696221935 14.421225639821552 -0.949758451465636 0.3129838396300944 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.89799649202623 51.20426324808372 14.810988494951864 -0.940266696035234 -0.34043874680621233 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.651376243239824 51.50908594088658 15.200751350082177 -0.5292329480578937 -0.8484765681443127 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.269150264687134 51.59650288706118 15.59051420521249 0.10781034952992652 -0.9941714784353024 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.91454860767 51.42918257747576 15.980277060342802 0.6988131112251446 -0.7153042957929399 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.53622185501599 50.32497020491614 1.1692885653909366 0.009965665065707063 -0.999950341526917 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.89729099547497 50.208643748578005 0.7795257102606244 -0.5918162356992592 -0.8060729142966898 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.11642014453254 49.89899041875694 0.3897628551303122 -0.9570314841285477 -0.2899840312615668 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.10601682652696 49.519787914004596 0.0 -0.9396926207859083 0.3420201433256689 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.978385681583866 47.3802120859954 -6.994405055138486e-15 0.9396926207859071 -0.34202014332567066 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.96198410287354 47.02219928837079 0.38976285513030523 0.9670285853031227 0.25466785271533593 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.152594615545105 46.71870331227512 0.7795257102606175 0.6493443975171795 0.7604944795414692 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.48221047283636 46.57800661128557 1.1692885653909297 0.09998463536509283 0.9949889811907007 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.10169102725237 46.76762948059299 8.964545667997177 0.7341837113383977 0.6789508656783465 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.43003882334065 46.58557690142296 9.35430852312749 0.18693738452460512 0.982371830961729 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.802303014340836 46.63430870702736 9.744071378257802 -0.43350293380903776 0.9011521549543988 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.07272622749144 46.89474430860247 10.133834233388114 -0.8842082890600417 0.46709281899587546 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.135426194136286 47.264912015137256 10.523597088518427 -0.9887082334681243 -0.1498533585620988 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.020186128118674 47.537671283901446 10.91335994364874 -0.7966414567721041 -0.6044521398357525 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.7224838684437 47.7472745660514 11.303122798779052 -0.30047102398048187 -0.9537909434190078 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.358397458084355 47.74615336345558 11.692885653909364 0.30633965995176865 -0.9519222724259765 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.061991777392166 47.5347205283589 12.082648509039677 0.8003491277720788 -0.5995342139315094 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.9424101258336 47.19083042976032 12.47241136416999 0.9996518803696997 -0.026384049600539805 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.043685181784674 46.84111120760385 12.862174219300302 0.8308601204512335 0.5564813206602373 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.328525170896356 46.61433741743736 13.251937074430614 0.3561268052650998 0.9344376376043901 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.69204554386096 46.594012316126516 13.641699929560927 -0.24974048300923346 0.9683128064558036 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.000389848143634 46.78762006731445 14.03146278469124 -0.7636476568136992 0.6456332211425824 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.14001871208826 47.12386990249232 14.421225639821552 -0.9963624300547468 0.08521682917945145 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.05951761868531 47.47894700012684 14.810988494951864 -0.862193941049832 -0.5065783335447329 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.788528897744854 47.722103913305695 15.200751350082177 -0.4105460728157302 -0.9118398555094974 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.35251517893947 49.15577316216897 15.200751350082184 0.3161434585265723 0.9487113963850428 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.05978072285229 49.36825018419948 14.810988494951872 0.8040342186718706 0.5945830263341821 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.94237925725375 49.71038589199235 14.421225639821559 0.9997033280027812 0.024356846679402966 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.04297967519406 50.057833013986254 14.031462784691247 0.8320359647689195 -0.5547216899771032 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.32501932856643 50.28431387542317 13.641699929560934 0.36196987581497586 -0.932189792371967 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.6859925140194 50.307515298990474 13.251937074430622 -0.23965209993997283 -0.9708588316508024 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.99470558617922 50.11900485962635 12.862174219300309 -0.7541738868730156 -0.656674766043928 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.13895853977307 49.78729560131259 12.472411364169997 -0.9945954761960902 -0.1038260021876607 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.066323461591374 49.43294536201656 12.082648509039684 -0.8735370125599315 0.48675772997238537 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.803199156511305 49.18474071510651 11.692885653909372 -0.43499650409315727 0.9004321414891471 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.445216652434766 49.13289022381953 11.303122798779059 0.16164100270108034 0.9868496269674467 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.12248264864715 49.29623865347475 10.913359943648747 0.6995310090137751 0.714602244208741 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.952292978050366 49.61541794900278 10.523597088518434 0.9831804600084086 0.1826367516620167 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.99650210571371 49.97442421594371 10.133834233388122 0.9094985805695084 -0.4157070265728599 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.23904247634309 50.24277867423829 9.744071378257809 0.5052646295205465 -0.862964457063826 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.59176417560833 50.32294942662999 9.354308523127496 -0.0826048692548616 -0.9965823777166574 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.92647251372671 50.18579887043116 8.964545667997184 -0.6404520994521539 -0.7679981173852753 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.12151965428168 49.88117359302802 8.574782812866871 -0.9655306670437727 -0.2602893217133695 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.10601682652696 49.519787914004596 8.185019957736559 -0.9396926207859078 0.34202014332566855 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.9614891207905 49.29581742252423 7.7952571026062465 -0.6988131112251442 0.7153042957929394 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.62457907283371 49.13068199171375 7.405494247475934 -0.13729636463049855 0.9905300138104085 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.25545515803796 49.19795476814721 7.0157313923456215 0.4779101600290868 0.878408719754632 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.99846337651171 49.47132871560961 6.625968537215309 0.9062297959061728 0.42278547398397615 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.95410042932779 49.84390088290122 6.2362056820849965 0.9801680412127042 -0.1981681381687017 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.903691545284474 50.812209696221935 6.236205682084989 -0.9497584514656364 0.31298383963009474 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.89799649202623 51.20426324808372 6.625968537215302 -0.9402666960352346 -0.34043874680621233 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.651376243239824 51.50908594088658 7.015731392345614 -0.529232948057894 -0.848476568144313 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.269150264687134 51.59650288706118 7.405494247475927 0.10781034952992641 -0.9941714784353027 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.91454860767 51.42918257747576 7.795257102606239 0.6988131112251448 -0.7153042957929402 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.77002090193354 51.20521208599539 8.185019957736552 0.9396926207859086 -0.34202014332566905 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.75503829969941 50.84190928883274 8.574782812866864 0.9646636245094727 0.26348451861209515 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.95262479483279 50.53666679877471 8.964545667997177 0.6353527992871647 0.7722220020421358 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.29021488046445 50.40158780381572 9.35430852312749 0.07270265656773878 0.9973536603071118 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.64382540854896 50.486281340899176 9.744071378257802 -0.5166482235731272 0.8561977651680319 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.88358957221053 50.759642908460506 10.133834233388114 -0.9162551630090682 0.4005951525658119 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.921451717375014 51.12127788846031 10.523597088518427 -0.9793587382832112 -0.20212981410053477 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.74350661356013 51.438372418252655 10.91335994364874 -0.6827835652584018 -0.7306206970877747 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.415106281127954 51.59447053628857 11.303122798779052 -0.13544967787143963 -0.9907842271476283 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.05685884444895 51.532243734114246 11.692885653909364 0.4616293832602298 -0.887072890190417 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.80033405888354 51.27454539266335 12.082648509039677 0.8891706925359069 -0.45757565443893056 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.739743075231864 50.916017662221144 12.47241136416999 0.9901556652887118 0.1399705629647472 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.70691806649222 49.87305443861417 12.472411364169997 -0.9690772862290773 -0.24675739769029442 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.688535355401385 49.51773371219795 12.082648509039684 -0.9384394344110167 0.3454438130034032 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.47215640269422 49.23529630052352 11.692885653909372 -0.5778078465657454 0.8161728324607816 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.133868909274206 49.125058763887395 11.303122798779059 -0.013995357532388508 0.9999020601876665 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.792628611347176 49.22578513460862 10.913359943648747 0.5547384723459938 0.8320247756522834 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.56842957210662 49.50205589580425 10.523597088518434 0.9284035377469175 0.37157350699290603 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.54010935512865 49.85672293402224 10.133834233388122 0.975603899376876 -0.21953822337040513 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.71762650846971 50.16507079433212 9.744071378257809 0.6797419771417619 -0.7334513238868738 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.038558731348424 50.31867174161477 9.354308523127496 0.14485493901058083 -0.9894529026913006 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.390053111412755 50.263513392553286 8.964545667997184 -0.4409690277633063 -0.8975223209221506 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.64850983026549 50.01899168151748 8.574782812866871 -0.8717302258511891 -0.48998613586246953 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.72304492126142 49.67109045573891 8.185019957736559 -0.9959553775110754 0.08984924043513537 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.58744879405196 49.34214603342141 7.7952571026062465 -0.7699618321619813 0.6380899442976393 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.28940259988451 49.14782874435454 7.405494247475934 -0.2732181752162281 0.9619520927424162 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.003175332971274 47.76240411974595 7.405494247475927 0.20382726963916054 -0.979006866243259 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.70618382801968 47.60418257747576 7.795257102606239 0.6988131112251441 -0.7153042957929415 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.561656122283225 47.3802120859954 8.185019957736552 0.9396926207859086 -0.34202014332567054 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.54287034033203 47.03155781016456 8.574782812866864 0.9710022573712378 0.23907031639239995 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.72138041884882 46.731479717784296 8.964545667997177 0.6734854598432604 0.7392004703595051 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.036734559574256 46.58159817927482 9.35430852312749 0.1478952253008619 0.9890030345419617 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.3821392130697 46.63267004043474 9.744071378257802 -0.42777919719154794 0.9038832659420994 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.64062433145644 46.86739999853817 10.133834233388114 -0.8585877278361184 0.5126666691030467 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.724654855876246 47.20629759461164 10.523597088518427 -0.9986386018691278 -0.05216265768607625 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.60577415042341 47.53459637244927 10.91335994364874 -0.8005040927810596 -0.5993272874154603 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.324240739897604 47.741119127651594 11.303122798779052 -0.3312817419047254 -0.9435318794193293 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.9753949046784 47.75592766940504 11.692885653909364 0.250127983460613 -0.9682127823417371 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.6773720365011 47.57400713812279 12.082648509039677 0.7468327637561277 -0.665011896871315 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.531096511476065 47.25696426966917 12.47241136416999 0.9906253054645159 -0.1366071161152857 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.58610401186037 46.9121644950751 12.862174219300302 0.8989461381573378 0.4380591748748209 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.82376644481124 46.656373022147406 13.251937074430614 0.5028420832392227 0.8643782964209819 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.16360027925893 46.57621271636439 13.641699929560927 -0.0635476408402601 0.9979788060593457 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.49052200522787 46.698829577962364 14.03146278469124 -0.6084171841218246 0.7936173700627209 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.914904022067645 46.32952951048622 14.031462784691247 0.698220753895744 -0.7158825174770369 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.223036316716545 46.48968069754418 13.641699929560934 0.18466692948090307 -0.982801162573639 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.568284790967226 46.45229882026053 13.251937074430622 -0.3907471942702333 -0.9204980337675588 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.83499704282989 46.22990617553499 12.862174219300309 -0.8352676140413408 -0.5498436258916594 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.93382897705554 45.89700053950747 12.472411364169997 -0.9999875044174222 0.004999100820881119 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.83167356656375 45.565099672035075 12.082648509039684 -0.8297284869310981 0.5581672132748681 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.562751146796316 45.34538475249591 11.692885653909372 -0.3815244539853757 0.9243587458401432 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.217146181884516 45.31145656436295 11.303122798779059 0.194483820867627 0.9809057260617507 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.91063049216267 45.47468047705963 10.913359943648747 0.7053433037373743 0.7088658715672859 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.75707863214423 45.73462046260012 10.523597088518434 0.9612630704347677 0.27563256233312594 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.767015285439065 46.09675807413966 10.133834233388122 0.9447019816100349 -0.3279301235660959 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.983593510155735 46.387165132161385 9.744071378257809 0.5837382737489281 -0.8119418869356497 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.327857075365664 46.49997020491615 9.354308523127496 0.009965665065708895 -0.9999503415269181 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.73085134196227 46.34986575212896 8.964545667997184 -0.6616914459286316 -0.7497762535482694 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.915283399860776 46.048052264008795 8.574782812866871 -0.9690782090928103 -0.24675377334799437 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.89765204687664 45.6947879140046 8.185019957736559 -0.9396926207859098 0.3420201433256676 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.75312434114018 45.470817422524235 7.7952571026062465 -0.6988131112251464 0.7153042957929394 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.443179652897975 45.31004740078793 7.405494247475934 -0.1822386308214769 0.9832543320201113 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.096206289175896 45.34906271221858 7.0157313923456215 0.39605030871532604 0.9182288129690206 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.82970553594819 45.57465096144207 6.625968537215309 0.8402182307614929 0.542248397596552 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.73392691808171 45.91041749643064 6.2362056820849965 0.9998492605389716 -0.017362494051069266 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.84130552121939 46.24265618359222 5.846442826954684 0.8208849219761715 -0.5710936393203626 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.115477966283805 46.45885558235652 5.4566799718243715 0.3639308468688105 -0.9314259705942023 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.463596737465124 46.485800541251535 5.066917116694059 -0.21626710510005798 -0.9763342354192246 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.76777266065848 46.31436624652578 4.6771542615637465 -0.7232269770889836 -0.6906104108763002 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.924997649726585 46.002608307619354 4.287391406433434 -0.9852686255358258 -0.17101384603226139 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.882028025660155 45.6561024331147 3.8976285513031215 -0.9136525854251036 0.4064959448088318 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.65341529763405 45.392191595438206 3.5078656961728094 -0.532631372048263 0.8463473409363237 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.316578346581935 45.30024825383827 3.1181028410424974 0.028763546371929072 0.9995862436028773 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.98558579865914 45.4114086913969 2.7283399859121853 0.5804177929099155 0.8143188476718337 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.77252709384925 45.688028824365155 2.3385771307818732 0.9355156342597376 0.3532852927247344 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.74955379887374 46.03643223619778 1.9488142756515612 0.9738044592189148 -0.22738706032964418 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.689456945467334 46.97025470218174 1.9488142756515543 -0.9399754178542725 0.34124216303042976 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.706795481020585 47.32353503129424 2.3385771307818666 -0.9688729771096851 -0.24755838549040554 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.52211170301771 47.62519629479281 2.7283399859121786 -0.6610666804382285 -0.7503271579880219 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.199587131275905 47.77040482200707 3.1181028410424907 -0.12352572753522689 -0.9923413700117988 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.85130587744064 47.70869757786266 3.5078656961728027 0.4569430288568943 -0.8894959631044361 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.59830304506407 47.46151913510843 3.897628551303115 0.878614416151166 -0.4775318918473894 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.52850247063894 47.114769231629154 4.287391406433427 0.9949487068597191 0.10038461395141074 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.66616133040001 46.78895079433278 4.677154261563739 0.7655172739246101 0.6434153427787022 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.9634402584251 46.597292622826274 5.066917116694052 0.270052393882779 0.9628456286228764 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.31702853832863 46.60639998621173 5.456679971824364 -0.31926140595642977 0.9476666896471171 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.60404676273024 46.813107883047614 5.846442826954677 -0.7976251132924458 0.6031535282539717 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.72475002681733 47.14558094630491 6.236205682084989 -0.9987972201042699 0.0490317561584791 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.637191392857865 47.48827775307748 6.625968537215302 -0.8528661635051552 -0.5221295884624808 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.37179933844421 47.722103913305695 7.015731392345614 -0.41054607281573186 -0.9118398555094976 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.93578561963883 49.15577316216897 7.0157313923456215 0.31614345852657155 0.9487113963850426 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.64242790933528 49.36909453310238 6.625968537215309 0.8050729756991453 0.5931757781626985 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.52560224501588 49.71248427908757 6.2362056820849965 0.9997824162314881 0.020859534854042683 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.628003459257435 50.06044799100779 5.846442826954684 0.8291137258288914 -0.5590799850129975 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.91220824509075 50.28581966891095 5.4566799718243715 0.35543908277337066 -0.9346994481849364 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.274351789767906 50.30623550933238 5.066917116694059 -0.24813349168855076 -0.9687258488873143 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.5820859650001 50.11423438723772 4.6771542615637465 -0.7610237837422056 -0.6487239787295491 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.722946962717 49.779984581233826 4.287391406433434 -0.9957921132703855 -0.09164096872305239 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.64545605391534 49.425640239463654 3.8976285513031215 -0.8666405986009417 0.498932934227238 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.37793288391265 49.18069921186076 3.5078656961728094 -0.42076864859646357 0.9071679802320547 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.018145841360756 49.13467707041548 3.1181028410424974 0.17887642232335527 0.9838715493075285 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.69758185282287 49.30439295872335 2.7283399859121853 0.7131497365531628 0.7010117354610793 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.53339347977183 49.62782290731546 2.3385771307818732 0.986797024971563 0.16196182114088625 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.58558461894825 49.986766967696624 1.9488142756515612 0.8998117930108627 -0.43627827949438025 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.83508161935163 50.25004628758553 1.559051420521249 0.4839834590052444 -0.8750771459758956 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.19070389388494 50.32144342581391 1.1692885653909366 -0.1087203318836028 -0.9940723763565303 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.522486562311954 50.17486575212895 0.7795257102606244 -0.6616914459286322 -0.7497762535482676 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.89332624760205 50.59262948059298 0.7795257102606175 0.734183711338398 0.6789508656783477 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.19856423748157 50.41544767392669 1.1692885653909297 0.2254537282058689 0.9742538767888357 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.550607782731156 50.44052685508005 1.559051420521242 -0.3612855138767731 0.9324552415332317 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.82764627368986 50.659189374974396 1.9488142756515543 -0.8230163321412801 0.5680177083759936 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.933821604340416 50.99577580108286 2.3385771307818666 -0.9999752165588751 0.007040331528562871 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.83239604171764 51.33382384252944 2.7283399859121786 -0.8309326121875789 -0.5563730708824142 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.55846385124692 51.55636547482132 3.1181028410424907 -0.3743789614030465 -0.9272757913688772 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.20680832771453 51.58639905350227 3.5078656961728027 0.2117135778175938 -0.9773317558371235 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.89910582136219 51.41353265808747 3.897628551303115 0.7245510884048345 -0.6892210968124601 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.741824496139344 51.09757980113668 4.287391406433427 0.9866866304429135 -0.16263300189448104 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.789385273469485 50.74786335093885 4.677154261563739 0.9074186682260024 0.42022774843523736 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.025331645739556 50.48538871884688 5.066917116694052 0.5141747144425598 0.8576854685885222 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.3680237935541 50.40097476913788 5.456679971824364 -0.05697886524835066 0.9983753847701831 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.698886784878184 50.52382957796236 5.846442826954677 -0.6084171841218244 0.7936173700627215 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.12326880171797 50.15452951048622 5.846442826954684 0.6982207538957413 -0.715882517477038 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.44195440092028 50.31656619953856 5.4566799718243715 0.16707808855855577 -0.9859436658976103 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.796232199713685 50.2685699390584 5.066917116694059 -0.42338490943045864 -0.9059498984306813 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.06031744046244 50.02758158797758 4.6771542615637465 -0.8635269773450485 -0.504302646629307 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.140447832343085 49.6791629891126 4.287391406433434 -0.9970776304794546 0.07639501814566135 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.00817343591179 49.34701861720978 3.8976285513031215 -0.7766203030939662 0.6299689713170291 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.710457687639014 49.14907485507426 3.5078656961728094 -0.2804273893060022 0.9598752415428892 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.43753651542219 47.76580055220593 3.5078656961728027 0.17444123105537201 -0.9846675870098931 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.1213514548646 47.60265108034594 3.897628551303115 0.7014163319846831 -0.7127518005765765 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.95315441830607 47.28912197550729 4.287391406433427 0.9817447262489032 -0.190203292512157 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.99209037179067 46.93546291056728 4.677154261563739 0.9168514704412498 0.39922848238786407 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.22446783957149 46.6660348957734 5.066917116694052 0.5295556908065372 0.84827517371099 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.568573387675414 46.5755798547193 5.456679971824364 -0.04395355603333001 0.9990335754678239 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.90340541360927 46.6959054841464 5.846442826954677 -0.6020069325897589 0.7984908597559954 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.11122326504336 46.98470036518365 6.236205682084989 -0.9483700183132395 0.3171660580272505 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.118949674875275 47.340412390956054 6.625968537215302 -0.9612473680330986 -0.27568731826009024 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.92386772099687 47.637958646114775 7.015731392345614 -0.6361107782357527 -0.7715977435246326 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.594576207370615 47.772709682258224 7.405494247475927 -0.08729158885867166 -0.996182803763711 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.24686751530431 47.697281516765905 7.795257102606239 0.4922228979185057 -0.8704691946098426 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.003010260263906 47.43819778155244 8.185019957736552 0.8986516563191761 -0.43866296925407455 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.948754639542244 47.086562927892984 8.574782812866864 0.9890776908552785 0.14739512017834894 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.93682160684791 45.450134247871034 0.7795257102606246 0.6616914459286328 0.7497762535482688 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.339815873444515 45.300029795083844 1.1692885653909368 -0.009965665065707693 0.9999503415269184 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.7397384608735 45.45813624568086 1.5590514205212491 -0.6765033107806757 0.7364395905318962 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.91811914993644 45.763567763802214 1.9488142756515614 -0.9738044592189159 0.22738706032964426 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.89514585496093 46.11197117563484 2.3385771307818737 -0.9355156342597385 -0.3532852927247349 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.68208715015104 46.3885913086031 2.7283399859121857 -0.5804177929099159 -0.8143188476718345 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.351094602228244 46.49975174616173 3.118102841042498 -0.028763546371928978 -0.9995862436028781 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.01425765117613 46.40780840456179 3.50786569617281 0.5326313720482635 -0.8463473409363242 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.78564492315002 46.1438975668853 3.897628551303122 0.9136525854251042 -0.406495944808832 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.742675299083594 45.79739169238064 4.287391406433434 0.9852686255358262 0.17101384603226139 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.8999002881517 45.48563375347422 4.6771542615637465 0.7232269770889839 0.6906104108763003 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.204076211345054 45.31419945874846 5.066917116694059 0.2162671051000581 0.9763342354192247 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.55219498252637 45.34114441764348 5.4566799718243715 -0.36393084686881044 0.9314259705942024 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.82636742759079 45.55734381640778 5.846442826954684 -0.8208849219761714 0.5710936393203627 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.93374603072847 45.88958250356936 6.2362056820849965 -0.9998492605389714 0.01736249405106932 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.837967412861985 46.22534903855793 6.625968537215309 -0.8402182307614928 -0.5422483975965517 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.57146665963428 46.450937287781414 7.0157313923456215 -0.39605030871532604 -0.9182288129690204 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.224493295912204 46.48995259921207 7.405494247475934 0.18223863082147676 -0.983254332020111 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.91454860767 46.32918257747576 7.7952571026062465 0.6988131112251461 -0.7153042957929392 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.54475956148986 46.74581742252423 7.795257102606239 -0.6988131112251437 0.715304295792941 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.24776805653827 46.58759588025404 7.405494247475927 -0.20382726963916048 0.9790068662432584 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.87914405106533 46.6278960866943 7.015731392345614 0.4105460728157315 0.911839855509497 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.61375199665168 46.86172224692251 6.625968537215302 0.8528661635051547 0.5221295884624804 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.52619336269221 47.204419053695084 6.236205682084989 0.9987972201042691 -0.04903175615847916 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.6468966267793 47.53689211695238 5.846442826954677 0.7976251132924452 -0.6031535282539714 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.933914851180916 47.74360001378827 5.456679971824364 0.3192614059564296 -0.9476666896471165 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.28750313108444 47.75270737717372 5.066917116694052 -0.2700523938827789 -0.9628456286228758 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.584782059109536 47.56104920566722 4.677154261563739 -0.7655172739246098 -0.6434153427787018 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.7224409188706 47.23523076837084 4.287391406433427 -0.9949487068597188 -0.10038461395141068 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.65264034444547 46.88848086489156 3.897628551303115 -0.8786144161511658 0.4775318918473893 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.39963751206891 46.641302422137336 3.5078656961728027 -0.4569430288568942 0.889495963104436 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.05135625823364 46.57959517799292 3.1181028410424907 0.12352572753522682 0.9923413700117987 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.72883168649184 46.72480370520719 2.7283399859121786 0.6610666804382285 0.7503271579880219 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.54414790848896 47.02646496870575 2.3385771307818666 0.9688729771096852 0.24755838549040565 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.56148644404221 47.37974529781825 1.9488142756515543 0.9399754178542727 -0.34124216303042976 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.77482234552896 47.66187270809475 1.559051420521242 0.5844155820430217 -0.8114545134912474 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.18546247597383 47.77199338871442 1.1692885653909297 -0.09998463536509268 -0.9949889811907016 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.57633060772338 46.9332479234133 14.810988494951864 0.91523514505232 0.4029201276445009 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.55561662387539 47.362790303778056 14.421225639821552 0.9497584514656373 -0.31298383963009424 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.76042138428168 47.65117042203763 14.03146278469124 0.6084171841218254 -0.7936173700627215 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.087343110250615 47.773787283635606 13.641699929560927 0.06354764084026046 -0.9979788060593466 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.4271769446983 47.69362697785259 13.251937074430614 -0.5028420832392229 -0.8643782964209826 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.66483937764917 47.43783550492489 12.862174219300302 -0.8989461381573381 -0.43805917487482143 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.71984687803348 47.093035730330826 12.47241136416999 -0.9906253054645163 0.13660711611528548 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.57357135300845 46.77599286187721 12.082648509039677 -0.7468327637561283 0.665011896871315 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.27554848483114 46.594072330594955 11.692885653909364 -0.2501279834606135 0.9682127823417374 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.92670264961194 46.6088808723484 11.303122798779052 0.3312817419047251 0.9435318794193296 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.64516923908614 46.81540362755072 10.91335994364874 0.8005040927810594 0.5993272874154606 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.5262885336333 47.14370240538835 10.523597088518427 0.9986386018691277 0.05216265768607663 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.6103190580531 47.482600001461826 10.133834233388114 0.8585877278361184 -0.5126666691030463 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+32.868804176439845 47.717329959565255 9.744071378257802 0.4277791971915481 -0.903883265942099 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.21420882993529 47.768401820725174 9.35430852312749 -0.1478952253008616 -0.9890030345419614 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.52956297066073 47.6185202822157 8.964545667997177 -0.6734854598432599 -0.7392004703595049 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.708073049177514 47.31844218983544 8.574782812866864 -0.9710022573712371 -0.23907031639239987 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+33.68928726722632 46.9697879140046 8.185019957736552 -0.939692620785908 0.34202014332567027 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.77002090193354 46.1052120859954 8.185019957736559 0.9396926207859094 -0.34202014332566755 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.7523895489494 45.7519477359912 8.574782812866871 0.9690782090928098 0.24675377334799425 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.93682160684791 45.450134247871034 8.964545667997184 0.6616914459286314 0.749776253548269 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.339815873444515 45.300029795083844 9.354308523127496 -0.00996566506570883 0.9999503415269176 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.68407943865444 45.41283486783861 9.744071378257809 -0.5837382737489277 0.8119418869356495 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.90065766337111 45.70324192586034 10.133834233388122 -0.9447019816100346 0.327930123566096 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.91059431666595 46.06537953739987 10.523597088518434 -0.9612630704347676 -0.2756325623331256 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.94897631397454 47.08508798486274 10.523597088518427 0.9887082334681232 0.1498533585620983 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.01167628061939 47.455255691397525 10.133834233388114 0.8842082890600406 -0.4670928189958753 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.28209949376999 47.715691292972636 9.744071378257802 0.43350293380903704 -0.901152154954398 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.654363684770175 47.76442309857703 9.35430852312749 -0.18693738452460523 -0.9823718309617279 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.982711480858455 47.58237051940701 8.964545667997177 -0.7341837113383971 -0.6789508656783456 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.13564786856858 47.263437072107 8.574782812866864 -0.9890776908552774 -0.1473951201783485 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.08139224784692 46.911802218447555 8.185019957736552 -0.898651656319175 0.43866296925407433 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.83753499280652 46.65271848323409 7.795257102606239 -0.49222289791850493 0.8704691946098418 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.48982630074021 46.57729031774177 7.405494247475927 0.08729158885867185 0.9961828037637099 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.16053478711396 46.71204135388522 7.015731392345614 0.6361107782357522 0.7715977435246316 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.96545283323555 47.00958760904394 6.625968537215302 0.9612473680330977 0.27568731826008974 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.97317924306747 47.365299634816346 6.236205682084989 0.9483700183132386 -0.31716605802725045 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.180997094501556 47.65409451585359 5.846442826954677 0.6020069325897583 -0.798490859755995 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.51582912043541 47.77442014528069 5.456679971824364 0.04395355603332979 -0.9990335754678232 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.85993466853934 47.683965104226594 5.066917116694052 -0.5295556908065371 -0.8482751737109895 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.09231213632016 47.41453708943271 4.677154261563739 -0.9168514704412495 -0.39922848238786374 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.13124808980476 47.0608780244927 4.287391406433427 -0.9817447262489029 0.19020329251215712 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.963051053246225 46.74734891965405 3.897628551303115 -0.7014163319846829 0.7127518005765764 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.64686599268864 46.58419944779406 3.5078656961728027 -0.17444123105537196 0.9846675870098929 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.29587361036597 46.6278960866943 15.200751350082177 0.41054607281572997 0.9118398555094962 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.024884889425515 46.87105299987316 14.810988494951864 0.8621939410498312 0.5065783335447321 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.944383796022564 47.22613009750767 14.421225639821552 0.9963624300547456 -0.08521682917945166 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.08401265996719 47.562379932685545 14.03146278469124 0.7636476568136981 -0.6456332211425818 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.39235696424987 47.75598768387348 13.641699929560927 0.24974048300923288 -0.9683128064558025 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.75587733721447 47.73566258256263 13.251937074430614 -0.35612680526509966 -0.9344376376043889 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.04071732632615 47.50888879239614 12.862174219300302 -0.8308601204512325 -0.5564813206602364 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.14199238227723 47.159169570239676 12.47241136416999 -0.9996518803696983 0.026384049600540017 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.02241073071866 46.81527947164109 12.082648509039677 -0.8003491277720776 0.5995342139315087 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.72600505002647 46.60384663654441 11.692885653909364 -0.30633965995176815 0.9519222724259752 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.361918639667124 46.60272543394859 11.303122798779052 0.3004710239804816 0.9537909434190064 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.06421637999215 46.81232871609855 10.91335994364874 0.7966414567721031 0.6044521398357515 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.75704245664751 46.32531952294037 10.913359943648747 -0.7053433037373744 -0.7088658715672855 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.45052676692566 46.48854343563705 11.303122798779059 -0.19448382086762733 -0.9809057260617506 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.10492180201386 46.45461524750409 11.692885653909372 0.38152445398537543 -0.9243587458401433 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.83599938224643 46.23490032796492 12.082648509039684 0.829728486931098 -0.5581672132748683 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.73384397175464 45.90299946049253 12.472411364169997 0.9999875044174223 -0.004999100820881356 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.83267590598028 45.570093824465005 12.862174219300309 0.8352676140413411 0.5498436258916592 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.09938815784295 45.34770117973946 13.251937074430622 0.3907471942702337 0.9204980337675589 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.44463663209363 45.31031930245582 13.641699929560934 -0.18466692948090288 0.9828011625736394 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.75276892674253 45.47047048951378 14.031462784691247 -0.6982207538957441 0.7158825174770374 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.921937299132715 45.781099117098776 14.421225639821559 -0.9801680412127061 0.19816813816869952 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.85308406024647 46.200635900381 14.810988494951872 -0.8654126430689731 -0.5010598339683353 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.37394482047181 50.30092514492573 3.50786569617281 0.28042738930600236 -0.9598752415428897 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.076229072199034 50.10298138279021 3.897628551303122 0.7766203030939668 -0.6299689713170294 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.94395467576774 49.77083701088739 4.287391406433434 0.9970776304794553 -0.07639501814566131 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.024085067648386 49.42241841202241 4.6771542615637465 0.8635269773450491 0.5043026466293076 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.28817030839714 49.18143006094159 5.066917116694059 0.42338490943045887 0.9059498984306823 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.642448107190546 49.133433800461425 5.4566799718243715 -0.16707808855855616 0.9859436658976114 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.96113370639286 49.29547048951377 5.846442826954684 -0.6982207538957423 0.7158825174770388 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.13030207878304 49.60609911709877 6.2362056820849965 -0.9801680412127054 0.19816813816870182 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.08593913159912 49.97867128439038 6.625968537215309 -0.9062297959061739 -0.42278547398397665 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.828947350072866 50.252045231852776 7.0157313923456215 -0.4779101600290874 -0.8784087197546331 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.459823435277116 50.31931800828624 7.405494247475934 0.13729636463049874 -0.9905300138104098 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.122913387320324 50.15418257747576 7.7952571026062465 0.6988131112251452 -0.7153042957929404 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.75312434114018 50.57081742252423 7.795257102606239 -0.6988131112251456 0.715304295792941 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.398522684123044 50.40349711293881 7.405494247475927 -0.10781034952992662 0.994171478435304 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.016296705570355 50.49091405911341 7.015731392345614 0.5292329480578946 0.8484765681443142 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.76967645678395 50.795736751916266 6.625968537215302 0.9402666960352357 0.34043874680621294 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.763981403525705 51.18779030377805 6.236205682084989 0.9497584514656378 -0.312983839630095 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.968786163931995 51.476170422037626 5.846442826954677 0.6084171841218253 -0.7936173700627224 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.29964915525608 51.599025230862104 5.456679971824364 0.0569788652483509 -0.9983753847701842 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.64234130307062 51.51461128115311 5.066917116694052 -0.5141747144425602 -0.8576854685885232 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.878287675340694 51.252136649061136 4.677154261563739 -0.9074186682260033 -0.4202277484352379 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.92584845267084 50.902420198863304 4.287391406433427 -0.9866866304429145 0.16263300189448113 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.76856712744799 50.58646734191252 3.897628551303115 -0.7245510884048352 0.6892210968124607 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.460864621095645 50.413600946497716 3.5078656961728027 -0.21171357781759406 0.9773317558371242 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.10920909756326 50.443634525178666 3.1181028410424907 0.37437896140304666 0.9272757913688778 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.83527690709254 50.666176157470545 2.7283399859121786 0.8309326121875794 0.5563730708824145 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.73385134446976 51.00422419891713 2.3385771307818666 0.9999752165588757 -0.007040331528562828 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.84002667512032 51.34081062502559 1.9488142756515543 0.8230163321412806 -0.568017708375994 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.11706516607902 51.559473144919934 1.559051420521242 0.3612855138767732 -0.932455241533232 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.46910871132861 51.58455232607329 1.1692885653909297 -0.225453728205869 -0.9742538767888359 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.77434670120813 51.407370519407 0.7795257102606175 -0.7341837113383981 -0.6789508656783477 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.92728308891826 51.088437072107006 0.38976285513030523 -0.9890776908552794 -0.1473951201783497 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.89765204687664 50.794787914004594 -6.994405055138486e-15 -0.939692620785909 0.34202014332566966 -0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.54700693371559 51.56085502162087 13.251937074430614 -0.35528409885083634 -0.9347583693681234 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.793152391868695 51.38604259863979 12.862174219300302 -0.7655265291060067 -0.643404331066332 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.927929873578314 51.08398233777884 12.47241136416999 -0.9901556652887139 -0.13997056296474736 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.867338889926636 50.72545460733664 12.082648509039677 -0.8891706925359086 0.45757565443893156 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.610814104361225 50.46775626588574 11.692885653909364 -0.4616293832602306 0.8870728901904188 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.252566667682224 50.40552946371142 11.303122798779052 0.13544967787144002 0.9907842271476301 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.92416633525005 50.56162758174733 10.91335994364874 0.6827835652584031 0.7306206970877759 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.746221231435165 50.87872211153967 10.523597088518427 0.9793587382832128 0.202129814100535 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+34.784083376599646 51.24035709153948 10.133834233388114 0.9162551630090695 -0.4005951525658127 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.023847540261215 51.51371865910081 9.744071378257802 0.5166482235731279 -0.8561977651680331 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.37745806834573 51.59841219618426 9.35430852312749 -0.07270265656773893 -0.9973536603071131 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.71504815397739 51.463333201225275 8.964545667997177 -0.6353527992871655 -0.7722220020421366 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.91263464911077 51.15809071116725 8.574782812866864 -0.9646636245094738 -0.26348451861209543 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+35.89765204687664 50.794787914004594 8.185019957736552 -0.9396926207859096 0.34202014332566943 0.0 -0.0 -0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.978385681583866 49.93021208599539 8.185019957736559 0.9396926207859091 -0.34202014332566905 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.96288285382915 49.56882640697197 8.574782812866871 0.9655306670437741 0.2602893217133698 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.15792999438412 49.26420112956883 8.964545667997184 0.6404520994521548 0.7679981173852763 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.492638332502494 49.12705057337 9.354308523127496 0.08260486925486167 0.9965823777166585 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.84536003176774 49.2072213257617 9.744071378257809 -0.5052646295205471 0.862964457063827 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.08790040239712 49.475575784056275 10.133834233388122 -0.9094985805695094 0.4157070265728603 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.13210953006046 49.834582050997206 10.523597088518434 -0.9831804600084095 -0.182636751662017 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.96191985946368 50.153761346525236 10.913359943648747 -0.6995310090137755 -0.7146022442087416 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.63918585567606 50.317109776180466 11.303122798779059 -0.16164100270108037 -0.9868496269674475 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.281203351599515 50.26525928489348 11.692885653909372 0.4349965040931576 -0.9004321414891476 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.01807904651945 50.01705463798343 12.082648509039684 0.8735370125599321 -0.48675772997238564 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+36.945443968337756 49.662704398687396 12.472411364169997 0.9945954761960909 0.10382600218766079 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.089696921931605 49.33099514037364 12.862174219300309 0.754173886873016 0.6566747660439285 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.39840999409143 49.142484701009515 13.251937074430622 0.23965209993997297 0.970858831650803 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.7593831795444 49.165686124576816 13.641699929560934 -0.361969875814976 0.9321897923719674 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.041422832916766 49.392166986013734 14.031462784691247 -0.8320359647689198 0.5547216899771034 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.14202325085708 49.739614108007636 14.421225639821559 -0.9997033280027814 -0.024356846679403014 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+38.02462178525854 50.08174981580051 14.810988494951872 -0.8040342186718707 -0.5945830263341823 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
+37.73188732917136 50.29422683783102 15.200751350082184 -0.3161434585265723 -0.9487113963850429 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0
diff --git a/mrdna/readers/test.json.top b/mrdna/readers/test.json.top
new file mode 100644
index 0000000..ccbe1c9
--- /dev/null
+++ b/mrdna/readers/test.json.top
@@ -0,0 +1,416 @@
+415 14
+1 T -1 1
+1 T 0 2
+1 T 1 -1
+2 A -1 4
+2 A 3 5
+2 C 4 -1
+3 A -1 7
+3 C 6 8
+3 A 7 -1
+4 A -1 10
+4 T 9 11
+4 C 10 12
+4 C 11 13
+4 G 12 14
+4 G 13 15
+4 A 14 16
+4 G 15 17
+4 C 16 18
+4 A 17 19
+4 C 18 20
+4 C 19 21
+4 G 20 22
+4 T 21 23
+4 G 22 24
+4 A 23 25
+4 C 24 26
+4 T 25 27
+4 T 26 28
+4 T 27 29
+4 C 28 30
+4 A 29 31
+4 C 30 32
+4 A 31 33
+4 A 32 34
+4 C 33 35
+4 T 34 36
+4 T 35 37
+4 T 36 38
+4 C 37 39
+4 G 38 40
+4 G 39 41
+4 A 40 42
+4 G 41 43
+4 C 42 -1
+5 C -1 45
+5 G 44 46
+5 C 45 47
+5 C 46 48
+5 G 47 -1
+6 G -1 50
+6 A 49 51
+6 C 50 52
+6 T 51 -1
+7 C -1 54
+7 T 53 55
+7 A 54 56
+7 T 55 -1
+8 C -1 58
+8 C 57 59
+8 C 58 60
+8 A 59 61
+8 A 60 62
+8 G 61 63
+8 G 62 64
+8 C 63 65
+8 A 64 66
+8 T 65 67
+8 T 66 68
+8 G 67 69
+8 T 68 70
+8 G 69 71
+8 G 70 72
+8 T 71 73
+8 C 72 74
+8 C 73 75
+8 T 74 76
+8 G 75 77
+8 G 76 78
+8 A 77 79
+8 T 78 80
+8 T 79 81
+8 G 80 82
+8 A 81 83
+8 C 82 84
+8 C 83 85
+8 T 84 86
+8 T 85 87
+8 C 86 88
+8 A 87 89
+8 C 88 90
+8 A 89 91
+8 G 90 92
+8 T 91 93
+8 A 92 94
+8 T 93 95
+8 C 94 96
+8 T 95 97
+8 C 96 98
+8 T 97 99
+8 A 98 100
+8 A 99 101
+8 T 100 102
+8 C 101 103
+8 C 102 104
+8 T 103 105
+8 A 104 106
+8 G 105 107
+8 T 106 108
+8 T 107 109
+8 A 108 110
+8 T 109 111
+8 G 110 112
+8 G 111 113
+8 A 112 114
+8 G 113 115
+8 T 114 116
+8 C 115 117
+8 C 116 118
+8 G 117 119
+8 A 118 120
+8 A 119 121
+8 A 120 122
+8 G 121 123
+8 T 122 124
+8 T 123 125
+8 G 124 126
+8 T 125 127
+8 G 126 128
+8 A 127 129
+8 G 128 130
+8 A 129 131
+8 C 130 132
+8 A 131 133
+8 A 132 134
+8 A 133 135
+8 C 134 136
+8 G 135 137
+8 C 136 138
+8 C 137 139
+8 T 138 140
+8 A 139 141
+8 C 140 142
+8 C 141 143
+8 C 142 144
+8 C 143 145
+8 A 144 146
+8 T 145 147
+8 T 146 148
+8 A 147 149
+8 C 148 150
+8 A 149 151
+8 C 150 152
+8 A 151 153
+8 G 152 154
+8 G 153 155
+8 C 154 156
+8 A 155 157
+8 T 156 158
+8 C 157 159
+8 G 158 160
+8 G 159 161
+8 G 160 162
+8 G 161 163
+8 G 162 164
+8 T 163 165
+8 T 164 166
+8 G 165 167
+8 T 166 168
+8 C 167 169
+8 T 168 170
+8 T 169 171
+8 G 170 172
+8 T 171 173
+8 C 172 174
+8 T 173 175
+8 C 174 176
+8 A 175 177
+8 G 176 178
+8 T 177 179
+8 C 178 180
+8 G 179 181
+8 T 180 182
+8 G 181 183
+8 G 182 184
+8 C 183 185
+8 T 184 186
+8 C 185 187
+8 C 186 188
+8 T 187 189
+8 T 188 190
+8 G 189 191
+8 T 190 192
+8 T 191 193
+8 A 192 194
+8 A 193 195
+8 G 194 196
+8 T 195 197
+8 C 196 198
+8 A 197 199
+8 C 198 200
+8 G 199 201
+8 G 200 202
+8 T 201 203
+8 G 202 204
+8 C 203 205
+8 T 204 206
+8 C 205 207
+8 C 206 208
+8 G 207 209
+8 G 208 210
+8 T 209 211
+8 G 210 212
+8 G 211 213
+8 C 212 214
+8 G 213 215
+8 A 214 216
+8 G 215 217
+8 T 216 218
+8 T 217 219
+8 C 218 220
+8 T 219 221
+8 T 220 222
+8 G 221 223
+8 A 222 224
+8 T 223 225
+8 T 224 226
+8 C 225 227
+8 C 226 228
+8 A 227 229
+8 T 228 230
+8 A 229 231
+8 T 230 232
+8 T 231 233
+8 C 232 234
+8 A 233 235
+8 C 234 236
+8 T 235 237
+8 T 236 238
+8 G 237 239
+8 T 238 240
+8 G 239 241
+8 C 240 242
+8 G 241 243
+8 C 242 244
+8 T 243 -1
+9 A -1 246
+9 C 245 247
+9 G 246 248
+9 A 247 249
+9 C 248 250
+9 T 249 251
+9 G 250 252
+9 A 251 253
+9 G 252 254
+9 A 253 255
+9 C 254 256
+9 A 255 257
+9 A 256 258
+9 G 257 259
+9 A 258 260
+9 C 259 261
+9 A 260 262
+9 A 261 263
+9 C 262 264
+9 T 263 265
+9 C 264 266
+9 A 265 267
+9 A 266 268
+9 C 267 269
+9 A 268 270
+9 A 269 271
+9 G 270 272
+9 G 271 273
+9 A 272 274
+9 G 273 275
+9 C 274 276
+9 C 275 277
+9 A 276 278
+9 C 277 279
+9 G 278 280
+9 A 279 281
+9 C 280 -1
+10 C -1 283
+10 G 282 284
+10 A 283 285
+10 T 284 286
+10 G 285 287
+10 G 286 288
+10 G 287 289
+10 G 288 290
+10 T 289 291
+10 A 290 292
+10 G 291 293
+10 G 292 294
+10 C 293 295
+10 G 294 296
+10 T 295 297
+10 T 296 298
+10 T 297 299
+10 G 298 300
+10 C 299 301
+10 C 300 302
+10 C 301 -1
+11 C -1 304
+11 G 303 305
+11 A 304 306
+11 T 305 307
+11 T 306 308
+11 T 307 309
+11 G 308 310
+11 G 309 311
+11 G 310 312
+11 A 311 313
+11 G 312 314
+11 C 313 315
+11 G 314 316
+11 C 315 317
+11 A 316 318
+11 C 317 319
+11 A 318 320
+11 A 319 321
+11 G 320 322
+11 T 321 323
+11 G 322 324
+11 A 323 325
+11 A 324 -1
+12 G -1 327
+12 A 326 328
+12 C 327 329
+12 C 328 330
+12 A 329 331
+12 C 330 332
+12 A 331 333
+12 A 332 334
+12 T 333 335
+12 G 334 336
+12 C 335 337
+12 C 336 338
+12 G 337 339
+12 C 338 340
+12 C 339 341
+12 T 340 342
+12 G 341 343
+12 T 342 344
+12 G 343 345
+12 T 344 346
+12 A 345 347
+12 T 346 348
+12 G 347 -1
+13 T -1 350
+13 A 349 351
+13 T 350 352
+13 G 351 353
+13 G 352 354
+13 A 353 355
+13 A 354 356
+13 G 355 357
+13 A 356 358
+13 G 357 359
+13 A 358 360
+13 T 359 361
+13 G 360 362
+13 A 361 363
+13 T 362 364
+13 T 363 365
+13 A 364 366
+13 T 365 367
+13 C 366 368
+13 A 367 369
+13 A 368 370
+13 G 369 371
+13 A 370 372
+13 A 371 373
+13 C 372 374
+13 T 373 375
+13 C 374 376
+13 G 375 377
+13 C 376 378
+13 C 377 379
+13 A 378 380
+13 A 379 381
+13 G 380 -1
+14 G -1 383
+14 C 382 384
+14 C 383 385
+14 T 384 386
+14 C 385 387
+14 C 386 388
+14 A 387 389
+14 T 388 390
+14 A 389 391
+14 A 390 392
+14 C 391 393
+14 T 392 394
+14 A 393 395
+14 G 394 396
+14 A 395 397
+14 C 396 398
+14 T 397 399
+14 G 398 400
+14 T 399 401
+14 G 400 402
+14 A 401 403
+14 A 402 404
+14 G 403 405
+14 G 404 406
+14 T 405 407
+14 C 406 408
+14 A 407 409
+14 A 408 410
+14 T 409 411
+14 C 410 412
+14 C 411 413
+14 A 412 414
+14 G 413 -1
diff --git a/mrdna/readers/test.virt2nuc b/mrdna/readers/test.virt2nuc
new file mode 100644
index 0000000000000000000000000000000000000000..a426be27a24d0091ddfa79f6dea5bb125b0f90f5
GIT binary patch
literal 6565
zcmX}xbzoH27KQPd$pj7VPH-yJ-Cb^}drQ+0LP?t@lq8f2EmWwb%21*5+}+*X-Cz6M
z-Tn35Z`N9mKbZWOGw1HJ_de&|3ES$scF(Fb{|ry=?O8jps;hHdUuR!`$IxI;??7XC
z_T~-Uy**nxHm~g*=<XQo@8}!q>h10y>{-{{*x6XQy|J~iVz{+qpsRB|KNgi@`Hn_W
zS<@(Lo%~R&FstH9vjVFHtd@gYMFzvV$W*We)|xZdN{$j43`dGg1xLV^=FIhy`-%*P
z`-sd8SBcBay~U;GUa($N%D-F7!3T;}^8m4C?k~2O`@z-%jwnBSsK{V=h*&ib7P%1b
z9wbgLIkM!R#cAfB#Hr>V#VO_=#L4FG#YyJx#EIr_#R=wb#PQ~@#c}4Z#5VJn;#l(+
z;u!Pi;%M_{uwH~e6*KrJVy61Bm<#<#Oc*~D6XXxXEaCgGr3k+#X7F=jrg~P)g}y5$
zjPHmE^4nsT@GWta7x+zar1=eTg!y%`)%==RH@_;<DwO*xBCP_y3~NRBB{74)C}yfJ
zh`G?`#f0%WF+qM-%o08$W`Um;v;0qqNzNz5r0x@968mv6Y5$m*qI^_L6MjTYi+)&4
z1Ahosi|~VD27f@zRPPsaq4$Xi<Go^ne2<tVyj#oy-z8@G?-Y}qcZf;d+r=dIZDP{?
zRxw3+3#=63o5c)%lbEUADCR<M5EI7h#RT~}F-v%@m<7H@%<^9?CONMXle$-mN$e}c
zr2XY$it;isN6<^f98fP2b9}v6%;EMTafZA7h2l)}1>!988F9Axv^d9nN}OvxDb6!@
zi}TGV#0BQ#;zIK=vE6)BTx9MN7n==niMbP2i|`RKgC7<%)k9*tKl`AVFdh&S<o#ln
zFf3+)_la5ly<(DckC@cmEhe#diAnnoF-5skOv&yLQ_$PRl>0U@&9EKTig25l!MBQ;
z>J~8<+A1cDo5ciqlb9vkC}x2-h*|y?G0C}JOzJj^N$ilAv=53Y$^dLB!cAfZUngd&
zjbbj;FD8sWF+pA{W(mDw7I=-A<zFo(IXz-hw?Rx|uM(5?^<s+BEoM8f6SLX7#2f`{
zVZ8`D#SFeu%v2p>E_8*MFxH3(@^UdtxJ=9fFBP-=OT;ASVlk<^NK9fc6qEJ~#1!Rx
zF(o@sOhL~TQ|@!bc5m3T#cb!Z#BBC6#T*5z#ijo28R9at5SN>$!`9|QFOLDIi5YyV
zn5j+?bD@*PgmIFXAWszAeW4S?Ebw?S%Rf#`a*h>~x?{v7_GmF_KT1qdjuca}Bg7Q+
za53dRtmF{iECxF_HosZa3gT}mQ?Vx_Yel=che-UqyHX^6xI!d;xLhQDxJ)E|xKt#5
zxI`p=xL729xJV>^*e()3Tqx4aaDhmx!}%f`0nQWICUCCECW3QBwiui(vH{^NksCLh
zDRNtfGemCsaJtAN0h}iCzyPO;JWjwVA`csIvdE(doFwv~0w;<*#=r?84>@qWSU1Os
zEoPfoGslWmbBtIqN5g9Ki`A$#jn%WNGE?K3Hdn?oYy!j6ZQ{n$Y?g(m+N>H+u}KP^
zY?CuQ$tI<EqD{u}1e=23@iz6s<7~=_+ia?h$J#Ul9%Iuhc(hF`;ZaRjig=`*@gwZa
z*J|f_bvyC2*on7hXFXLr>#f+%NAW!6sT59E@n6x|EdC=p*~Py_*P{5B=u#E`6kW;U
zAEFCg{9SY(6n_(Gu`(^iUqxCB{zYW7jxLk7%0aVR@!mGu74Ow_wTSn$Gky;{^R2Ww
z8~FSRo1+6Sw>eqxGMj@3FSR+B@DiJ23oo`g)$k&lLl3vxoQZg$-EJ?iIZ=6kzRe8-
z&$GFo;JG%p8$8G6ZiHty-P-(qKc@6aHf6>q+H?Uv!KO*@@it9_kF#kqe5_3q;$v)@
z6d!HV#P}$iCdWtGYyy0Q%_hNz+te2yW>a5$s7-zGAvX2J2iw#aA7oQse4tHz@c~U&
zig<rJ<M*>O-@bOPw~tN!$CmS5Zc`t8nN9uhr8f1&m)O)FUu@GK_#&JB!57-}7rwxz
z|M2-X{fW=B>0f+q)2&5(j-Bym+nMhyJJ&nYPCTpa#CwLF^%Qp2d%B%`oMtCqr`pNq
zDK^hy#D8+rEzREqww2y$SIhVD%{IpizRBkF!8h6*PWT3!vkPyrIoj~`HYXq6Y;!Q;
zA)9j(58CWEJYcim@Ftu6hOe{PZ+N54e#8AX`wjQm>^FR^&3?nZHv0`<W3%7z)i(PL
z_cUE^-lXsbJL9jiGv9hU*Xy<u&pJEtcG+3aT086Qw3Cl3?c}S&PCl=&lkYV){V}eL
z{~4S9!B5-t7k<j7|L~JG{fT$m^e=wGroZvyHvNwuv)Lc`QJejPciHSO+_2eyc&E+z
zgCDUufAGUL=MR3!=KR4A+MI{@0h{v@-*0oC;^C%Sn)gq9pPljd+L`YjJJ-A0PCR$n
ziFb#c_1tM^y?5Bj$L)6Vb(@`hZnu-~ZFcH$tDSn?f`^7jm;X7^(bYfHH&{OM47Uvo
xZtCn?_y2zwTC4vcX={FWt`=?0-%{6#an0A3@|AY3m#?&WYx#cpI<%v)>VIEH!IJ<0

literal 0
HcmV?d00001

diff --git a/mrdna/readers/test2.ipynb b/mrdna/readers/test2.ipynb
new file mode 100644
index 0000000..2fcb4e5
--- /dev/null
+++ b/mrdna/readers/test2.ipynb
@@ -0,0 +1,973 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "9ea65628",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "             _\n",
+      " _____ ___ _| |___ ___\n",
+      "|     |  _| . |   | .'|\n",
+      "|_|_|_|_| |___|_|_|__,|  v1.0a.dev74  \n",
+      "it/its\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "\n",
+    "\n",
+    "from mrdna.readers.cadnano_segments import *\n",
+    "from cadnano.document import Document\n",
+    "import cadnano"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 27,
+   "id": "f07e1b32",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Found cadnano version 2 file\n"
+     ]
+    }
+   ],
+   "source": [
+    "json_data=read_json_file(\"test.json\")\n",
+    "part=decode_cadnano_part(json_data)\n",
+    "model=cadnano_part(part)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 28,
+   "id": "a4d48fe0",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Found cadnano version 2 file\n"
+     ]
+    }
+   ],
+   "source": [
+    "doc=Document()\n",
+    "cadnano.fileio.v2decode.decode(doc, json_data)\n",
+    "parts = [p for p in doc.getParts()]\n",
+    "part=parts[0]\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 29,
+   "id": "03d8b6e7",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Oligo_(5.1[22])_2224\t188\t'None\n",
+      "Oligo_(4.1[39])_7104\t33\t'None\n",
+      "Oligo_(2.1[34])_8976\t35\t'None\n",
+      "Oligo_(5.0[9])_4592\t23\t'None\n",
+      "Oligo_(0.0[39])_2544\t3\t'None\n",
+      "Oligo_(3.1[41])_5568\t5\t'None\n",
+      "Oligo_(1.0[3])_3184\t37\t'None\n",
+      "Oligo_(0.1[38])_5296\t23\t'None\n",
+      "Oligo_(4.0[0])_8128\t4\t'None\n",
+      "Oligo_(3.0[0])_6400\t33\t'None\n",
+      "Oligo_(2.0[39])_8208\t3\t'None\n",
+      "Oligo_(1.1[41])_1888\t3\t'None\n",
+      "Oligo_(0.1[23])_3888\t21\t'None\n",
+      "Oligo_(5.1[3])_1120\t4\t'None\n",
+      "VH0\n",
+      "\t <fwd_StrandSet(0)> \t [(5, 36), (39, 41)] \n",
+      "\t\t\t\t ['#0066cc', '#0066cc']\n",
+      "\t <rev_StrandSet(0)> \t [(2, 20), (21, 23), (24, 27), (28, 38)] \n",
+      "\t\t\t\t ['#cc0000', '#b8056c', '#f74308', '#1700de']\n",
+      "VH1\n",
+      "\t <fwd_StrandSet(1)> \t [(3, 20), (21, 38)] \n",
+      "\t\t\t\t ['#cc0000', '#b8056c']\n",
+      "\t <rev_StrandSet(1)> \t [(5, 18), (19, 36), (39, 41)] \n",
+      "\t\t\t\t ['#0066cc', '#0066cc', '#0066cc']\n",
+      "VH2\n",
+      "\t <fwd_StrandSet(2)> \t [(2, 18), (19, 32), (39, 41)] \n",
+      "\t\t\t\t ['#0066cc', '#0066cc', '#0066cc']\n",
+      "\t <rev_StrandSet(2)> \t [(0, 34)] \n",
+      "\t\t\t\t ['#888888']\n",
+      "VH3\n",
+      "\t <fwd_StrandSet(3)> \t [(0, 20), (21, 34)] \n",
+      "\t\t\t\t ['#cc0000', '#888888']\n",
+      "\t <rev_StrandSet(3)> \t [(2, 15), (16, 32), (37, 41)] \n",
+      "\t\t\t\t ['#0066cc', '#0066cc', '#0066cc']\n",
+      "VH4\n",
+      "\t <fwd_StrandSet(4)> \t [(0, 3), (9, 15), (16, 39)] \n",
+      "\t\t\t\t ['#0066cc', '#0066cc', '#0066cc']\n",
+      "\t <rev_StrandSet(4)> \t [(9, 20), (21, 39)] \n",
+      "\t\t\t\t ['#cc0000', '#888888']\n",
+      "VH5\n",
+      "\t <fwd_StrandSet(5)> \t [(9, 27), (28, 39)] \n",
+      "\t\t\t\t ['#f74308', '#1700de']\n",
+      "\t <rev_StrandSet(5)> \t [(0, 3), (9, 22), (23, 39)] \n",
+      "\t\t\t\t ['#0066cc', '#0066cc', '#0066cc']\n"
+     ]
+    }
+   ],
+   "source": [
+    "part.__dict__.keys()\n",
+    "\n",
+    "oligos = part.oligos()\n",
+    "for oligo in oligos:\n",
+    "    print(\"{0}\\t{1}\\t\\'{2}\".format(oligo,\n",
+    "                                          oligo.length(),\n",
+    "                                          oligo.sequence()))\n",
+    "\n",
+    "vhs = list(part.getIdNums())  # convert set to list\n",
+    "for vh_id in vhs:         # display first 3 vhs\n",
+    "    fwd_ss, rev_ss = part.getStrandSets(vh_id)\n",
+    "    print('VH{0}'.format(vh_id))\n",
+    "    print('\\t', fwd_ss, '\\t', [s.idxs() for s in fwd_ss.strands()], '\\n\\t\\t\\t\\t',\n",
+    "          [s.getColor() for s in fwd_ss.strands()])\n",
+    "    print('\\t', rev_ss, '\\t', [s.idxs() for s in rev_ss.strands()], '\\n\\t\\t\\t\\t',\n",
+    "          [s.getColor() for s in rev_ss.strands()])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "884f07ed",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "id": "1e934f2b",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "strands5 = [o.strand5p() for o in part.oligos()]\n",
+    "strands3 = [o.strand3p() for o in part.oligos()]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 35,
+   "id": "e5b59a91",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'_part': NucleicAcidPart_-1_7520,\n",
+       " '_strand5p': <rev_StrandSet(4)>.<Strand(21, 39)>,\n",
+       " '_is_circular': False,\n",
+       " '_props': {'name': 'oligo7104',\n",
+       "  'color': '#888888',\n",
+       "  'length': 33,\n",
+       "  'is_visible': True}}"
+      ]
+     },
+     "execution_count": 35,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "L=[o for o in part.oligos()]\n",
+    "\n",
+    "L[1].__dict__"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 36,
+   "id": "78ecf1e1",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['__class__',\n",
+       " '__delattr__',\n",
+       " '__dict__',\n",
+       " '__dir__',\n",
+       " '__doc__',\n",
+       " '__eq__',\n",
+       " '__format__',\n",
+       " '__ge__',\n",
+       " '__getattribute__',\n",
+       " '__gt__',\n",
+       " '__hash__',\n",
+       " '__init__',\n",
+       " '__init_subclass__',\n",
+       " '__le__',\n",
+       " '__lt__',\n",
+       " '__module__',\n",
+       " '__ne__',\n",
+       " '__new__',\n",
+       " '__reduce__',\n",
+       " '__reduce_ex__',\n",
+       " '__repr__',\n",
+       " '__setattr__',\n",
+       " '__sizeof__',\n",
+       " '__slots__',\n",
+       " '__str__',\n",
+       " '__subclasshook__',\n",
+       " '__weakref__',\n",
+       " '_decrementLength',\n",
+       " '_incrementLength',\n",
+       " '_is_circular',\n",
+       " '_parent',\n",
+       " '_part',\n",
+       " '_props',\n",
+       " '_setColor',\n",
+       " '_setLength',\n",
+       " '_setLoop',\n",
+       " '_setProperty',\n",
+       " '_signals',\n",
+       " '_strand5p',\n",
+       " '_strandMergeUpdate',\n",
+       " '_strandSplitUpdate',\n",
+       " 'addToPart',\n",
+       " 'applyAbstractSequences',\n",
+       " 'applyColor',\n",
+       " 'applySequence',\n",
+       " 'applySequenceCMD',\n",
+       " 'clearAbstractSequences',\n",
+       " 'connect',\n",
+       " 'deleteLater',\n",
+       " 'destroy',\n",
+       " 'disconnect',\n",
+       " 'displayAbstractSequences',\n",
+       " 'dump',\n",
+       " 'editable_properties',\n",
+       " 'getAbsolutePositionAtLength',\n",
+       " 'getColor',\n",
+       " 'getModelProperties',\n",
+       " 'getName',\n",
+       " 'getNumberOfBasesToEachXover',\n",
+       " 'getOutlineProperties',\n",
+       " 'getProperty',\n",
+       " 'getStrandLengths',\n",
+       " 'isCircular',\n",
+       " 'length',\n",
+       " 'locString',\n",
+       " 'oligoPropertyChangedSignal',\n",
+       " 'oligoRemovedSignal',\n",
+       " 'oligoSelectedChangedSignal',\n",
+       " 'oligoSequenceAddedSignal',\n",
+       " 'oligoSequenceClearedSignal',\n",
+       " 'parent',\n",
+       " 'part',\n",
+       " 'refreshLength',\n",
+       " 'remove',\n",
+       " 'removeFromPart',\n",
+       " 'sequence',\n",
+       " 'sequenceExport',\n",
+       " 'setParent',\n",
+       " 'setPart',\n",
+       " 'setProperty',\n",
+       " 'setStrand5p',\n",
+       " 'shallowCopy',\n",
+       " 'shouldHighlight',\n",
+       " 'signals',\n",
+       " 'splitAtAbsoluteLengths',\n",
+       " 'strand3p',\n",
+       " 'strand5p',\n",
+       " 'undoStack']"
+      ]
+     },
+     "execution_count": 36,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "dir(L[0])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "680d09ca",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'name': 'NaPart1',\n",
+       " 'color': '#0066cc',\n",
+       " 'is_visible': True,\n",
+       " 'active_phos': None,\n",
+       " 'crossover_span_angle': 45,\n",
+       " 'max_vhelix_length': 42,\n",
+       " 'neighbor_active_angle': '',\n",
+       " 'grid_type': <GridEnum.HONEYCOMB: 2>,\n",
+       " 'virtual_helix_order': [0, 1, 2, 3, 4, 5],\n",
+       " 'is_lattice': True,\n",
+       " <GridEnum.HONEYCOMB: 2>: <GridEnum.NONE: 0>}"
+      ]
+     },
+     "execution_count": 10,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "part.getModelProperties()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "190a91a3",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "             _\n",
+      " _____ ___ _| |___ ___\n",
+      "|     |  _| . |   | .'|\n",
+      "|_|_|_|_| |___|_|_|__,|  v1.0a.dev74  \n",
+      "it/its\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "import pdb\n",
+    "import numpy as np\n",
+    "import os,sys\n",
+    "import scipy\n",
+    "\n",
+    "from mrdna import logger, devlogger\n",
+    "from mrdna.segmentmodel import SegmentModel, SingleStrandedSegment, DoubleStrandedSegment\n",
+    "from mrdna.arbdmodel.coords import quaternion_from_matrix, rotationAboutAxis, quaternion_slerp\n",
+    "from mrdna import get_resource_path\n",
+    "\n",
+    "ref_stack_position = np.array((-2.41851735, -0.259761333, 3.39999978))\n",
+    "\n",
+    "def _three_prime_list_to_five_prime(three_prime):\n",
+    "    five_prime = -np.ones(three_prime.shape, dtype=int)\n",
+    "    has_three_prime = np.where(three_prime >= 0)[0]\n",
+    "    five_prime[three_prime[has_three_prime]] = has_three_prime\n",
+    "    return five_prime  \n",
+    "def _primes_list_to_strands(three_prime, five_prime):\n",
+    "    five_prime_ends = np.where(five_prime < 0)[0]\n",
+    "    strands = []\n",
+    "    strand_is_circular = []\n",
+    "    \n",
+    "    idx_to_strand = -np.ones(three_prime.shape, dtype=int)\n",
+    "\n",
+    "    def build_strand(nt_idx, conditional):\n",
+    "        strand = [nt_idx]\n",
+    "        idx_to_strand[nt_idx] = len(strands)\n",
+    "        while conditional(nt_idx):\n",
+    "            nt_idx = three_prime[nt_idx]\n",
+    "            strand.append(nt_idx)\n",
+    "            idx_to_strand[nt_idx] = len(strands)\n",
+    "        strands.append( np.array(strand, dtype=int) )\n",
+    "\n",
+    "    for nt_idx in five_prime_ends:\n",
+    "        build_strand(nt_idx,\n",
+    "                     lambda nt: three_prime[nt] >= 0)\n",
+    "        strand_is_circular.append(False)\n",
+    "\n",
+    "    while True:\n",
+    "        ## print(\"WARNING: working on circular strand {}\".format(len(strands)))\n",
+    "        ids = np.where(idx_to_strand < 0)[0]\n",
+    "        if len(ids) == 0: break\n",
+    "        build_strand(ids[0],\n",
+    "                     lambda nt: three_prime[nt] >= 0 and \\\n",
+    "                     idx_to_strand[three_prime[nt]] < 0)\n",
+    "        strand_is_circular.append(True)\n",
+    "\n",
+    "    return strands, strand_is_circular\n",
+    "\n",
+    "def find_stacks(centers, transforms):\n",
+    "\n",
+    "    ## Find orientation and center of each nucleotide\n",
+    "    expected_stack_positions = []\n",
+    "    for R,c in zip(transforms,centers):\n",
+    "        expected_stack_positions.append( c + ref_stack_position.dot(R) )\n",
+    "\n",
+    "    expected_stack_positions = np.array(expected_stack_positions, dtype=np.float32)\n",
+    "\n",
+    "    dists = scipy.spatial.distance_matrix(expected_stack_positions, centers)\n",
+    "    dists = dists + 5*np.eye(len(dists))\n",
+    "    idx1, idx2 = np.where(dists < 3.5)\n",
+    "\n",
+    "    ## Convert distances to stacks\n",
+    "    stacks_above = -np.ones(len(centers), dtype=int)\n",
+    "    _z = np.array((0,0,1))\n",
+    "    for i in np.unique(idx1):\n",
+    "        js = idx2[ idx1 == i ]\n",
+    "        with np.errstate(divide='ignore',invalid='ignore'):\n",
+    "            angles = [np.arccos( transforms[j].T.dot( transforms[i].dot(_z) ).dot( _z ) ) for j in js]\n",
+    "        angles = np.array( angles )\n",
+    "        tmp = np.argmin(dists[i][js] + 1.0*angles)\n",
+    "        j = js[tmp]\n",
+    "        stacks_above[i] = j\n",
+    "\n",
+    "    return stacks_above\n",
+    "\n",
+    "def basepairs_and_stacks_to_helixmap(basepairs,stacks_above):\n",
+    "\n",
+    "    helixmap = -np.ones(basepairs.shape, dtype=int)\n",
+    "    helixrank = -np.ones(basepairs.shape)\n",
+    "    is_fwd = np.ones(basepairs.shape, dtype=int)\n",
+    "    \n",
+    "    ## Remove stacks with nts lacking a basepairs\n",
+    "    nobp = np.where(basepairs < 0)[0]\n",
+    "    stacks_above[nobp] = -1\n",
+    "    stacks_with_nobp = np.in1d(stacks_above, nobp)\n",
+    "    stacks_above[stacks_with_nobp] = -1\n",
+    "\n",
+    "    end_ids = np.where( (stacks_above < 0)*(basepairs >= 0) )[0]\n",
+    "\n",
+    "    hid = 0\n",
+    "    for end in end_ids:\n",
+    "        if helixmap[end] >= 0:\n",
+    "            continue\n",
+    "        rank = 0\n",
+    "        nt = basepairs[end]\n",
+    "        bp = basepairs[nt]\n",
+    "        assert( bp == end )\n",
+    "        if helixmap[nt] >= 0 or helixmap[bp] >= 0:\n",
+    "            logger.warning(f'Ill-formed helix: problematic basepair or stacking data near nucleotide {nt} or {bp}... skipping')\n",
+    "            continue\n",
+    "        # assert(helixmap[nt] == -1)\n",
+    "        # assert(helixmap[bp] == -1)\n",
+    "        helixmap[nt] = helixmap[bp] = hid\n",
+    "        helixrank[nt] = helixrank[bp] = rank\n",
+    "        is_fwd[bp] = 0\n",
+    "        rank +=1\n",
+    "\n",
+    "        _tmp = [(nt,bp)]\n",
+    "        \n",
+    "        while stacks_above[nt] >= 0:\n",
+    "            nt = stacks_above[nt]\n",
+    "            if basepairs[nt] < 0: break\n",
+    "            bp = basepairs[nt]\n",
+    "            if helixmap[nt] >= 0 or helixmap[bp] >= 0:\n",
+    "                logger.warning(f'Ill-formed helix: problematic basepair or stacking data near nucleotide {nt} or {bp}... skipping')\n",
+    "                break\n",
+    "            helixmap[nt] = helixmap[bp] = hid\n",
+    "            helixrank[nt] = helixrank[bp] = rank\n",
+    "            is_fwd[bp] = 0\n",
+    "            _tmp.append((nt,bp))\n",
+    "            rank +=1\n",
+    "\n",
+    "        hid += 1\n",
+    "\n",
+    "    ## Create \"helix\" for each circular segment\n",
+    "    intrahelical = []\n",
+    "    processed = set()\n",
+    "    unclaimed_bases = np.where( (basepairs >= 0)*(helixmap == -1) )[0]\n",
+    "    for nt0 in unclaimed_bases:\n",
+    "        if nt0 in processed: continue\n",
+    "\n",
+    "        nt = nt0\n",
+    "        all_nts = [nt]\n",
+    "\n",
+    "        rank = 0\n",
+    "        nt = nt0\n",
+    "        bp = basepairs[nt]\n",
+    "        if helixmap[nt] >= 0 or helixmap[bp] >= 0:\n",
+    "            logger.warning(f'Ill-formed cylic helix: problematic basepair or stacking data near nucleotide {nt} or {bp}... skipping')\n",
+    "            continue\n",
+    "        helixmap[nt] = helixmap[bp] = hid\n",
+    "        helixrank[nt] = helixrank[bp] = rank\n",
+    "        is_fwd[bp] = 0\n",
+    "        rank +=1\n",
+    "        processed.add(nt)\n",
+    "        processed.add(bp)\n",
+    "\n",
+    "        counter = 0\n",
+    "        while stacks_above[nt] >= 0:\n",
+    "            lastnt = nt\n",
+    "            nt = stacks_above[nt]\n",
+    "            bp = basepairs[nt]\n",
+    "            if nt == nt0 or nt == basepairs[nt0]:\n",
+    "                intrahelical.append((lastnt,nt0))\n",
+    "                break\n",
+    "                \n",
+    "            assert( bp >= 0 )\n",
+    "            if helixmap[nt] >= 0 or helixmap[bp] >= 0:\n",
+    "                logger.warning(f'Ill-formed cyclic helix: problematic basepair or stacking data near nucleotide {nt} or {bp}... skipping')\n",
+    "                break\n",
+    "            \n",
+    "            helixmap[nt] = helixmap[bp] = hid\n",
+    "            helixrank[nt] = helixrank[bp] = rank\n",
+    "            is_fwd[bp] = 0\n",
+    "            processed.add(nt)\n",
+    "            processed.add(bp)\n",
+    "            rank +=1\n",
+    "        hid += 1\n",
+    "\n",
+    "    return helixmap, helixrank, is_fwd, intrahelical\n",
+    "\n",
+    "\n",
+    "def set_splines(seg, coordinate, hid, hmap, hrank, fwd, basepair, orientation=None):\n",
+    "    maxrank = np.max( hrank[hmap==hid] )\n",
+    "    if maxrank == 0:\n",
+    "        ids = np.where((hmap == hid))[0]\n",
+    "        pos = np.mean( [coordinate[r,:] for r in ids ], axis=0 )\n",
+    "        coords = [pos,pos]\n",
+    "        contours = [0,1]\n",
+    "        if orientation is not None:\n",
+    "            ids = np.where((hmap == hid) * fwd)[0]\n",
+    "            assert( len(ids) == 1 )\n",
+    "            q = quaternion_from_matrix( orientation[ids[0]] )\n",
+    "            quats = [q, q]\n",
+    "            coords[-1] = pos + orientation[ids[0]].dot(np.array((0,0,1)))\n",
+    "\n",
+    "    else:\n",
+    "        coords,contours,quats = [[],[],[]]\n",
+    "        last_q = None\n",
+    "        for rank in range(int(maxrank)+1):\n",
+    "            ids = np.where((hmap == hid) * (hrank == rank))[0]\n",
+    "                \n",
+    "            coords.append(np.mean( [coordinate[r,:] for r in ids ], axis=0 ))\n",
+    "            contours.append( float(rank+0.5)/(maxrank+1) )\n",
+    "            if orientation is not None:\n",
+    "                ids = np.where((hmap == hid) * (hrank == rank) * fwd)[0]\n",
+    "                assert(len(ids) == 1)\n",
+    "                q = quaternion_from_matrix( orientation[ids[0]] )\n",
+    "\n",
+    "                if last_q is not None and last_q.dot(q) < 0:\n",
+    "                    q = -q\n",
+    "\n",
+    "                ## Average quaterion with reverse direction\n",
+    "                bp = basepair[ids[0]]\n",
+    "                if bp >= 0:\n",
+    "                    bp_o = orientation[bp].dot(rotationAboutAxis(np.array((1,0,0)),180))\n",
+    "                    q2 = quaternion_from_matrix( bp_o )\n",
+    "                    if q.dot(q2) < 0:\n",
+    "                        q2 = -q2\n",
+    "\n",
+    "                    ## probably good enough, but slerp is better: q = (q + q2)*0.5\n",
+    "                    q = quaternion_slerp(q,q2,0.5)\n",
+    "\n",
+    "                quats.append(q)\n",
+    "                last_q = q\n",
+    "\n",
+    "    coords = np.array(coords)\n",
+    "    seg.set_splines(contours,coords)\n",
+    "    if orientation is not None:\n",
+    "        quats = np.array(quats)\n",
+    "        seg.set_orientation_splines(contours,quats)\n",
+    "\n",
+    "    seg.start_position = coords[0,:]\n",
+    "    seg.end_position = coords[-1,:]\n",
+    "\n",
+    "\n",
+    "def model_from_basepair_stack_3prime(coordinate, basepair, stack, three_prime,\n",
+    "                                     sequence=None, orientation=None,\n",
+    "                                     max_basepairs_per_bead = 5,\n",
+    "                                     max_nucleotides_per_bead = 5,\n",
+    "                                     local_twist = False,\n",
+    "                                     dimensions=(5000,5000,5000),\n",
+    "                                     **model_parameters):\n",
+    "    \"\"\" \n",
+    "    Creates a SegmentModel object from lists of each nucleotide's\n",
+    "    basepair, its stack (on 3' side) and its 3'-connected nucleotide\n",
+    "\n",
+    "    The first argument should be an N-by-3 numpy array containing the\n",
+    "    coordinate of each nucleotide, where N is the number of\n",
+    "    nucleotides. The following three arguments should be integer lists\n",
+    "    where the i-th element corresponds to the i-th nucleotide; the\n",
+    "    list element should the integer index of the corresponding\n",
+    "    basepaired / stacked / phosphodiester-bonded nucleotide. If there\n",
+    "    is no such nucleotide, the value should be -1.\n",
+    "\n",
+    "    Args:\n",
+    "        basepair:  List of each nucleotide's basepair's index\n",
+    "        stack:  List containing index of the nucleotide stacked on the 3' of each nucleotide\n",
+    "        three_prime:  List of each nucleotide's the 3' end of each nucleotide\n",
+    "\n",
+    "    Returns:\n",
+    "        SegmentModel\n",
+    "    \"\"\"\n",
+    "\n",
+    "    \"\"\" Validate Input \"\"\"\n",
+    "    inputs = (basepair,three_prime)\n",
+    "    try:\n",
+    "        basepair,three_prime = [np.array(a,dtype=int) for a in inputs]\n",
+    "    except:\n",
+    "        raise TypeError(\"One or more of the input lists could not be converted into a numpy array\")\n",
+    "    inputs = (basepair,three_prime)\n",
+    "    coordinate = np.array(coordinate)\n",
+    "\n",
+    "    if np.any( [len(a.shape) > 1 for a in inputs] ):\n",
+    "        raise ValueError(\"One or more of the input lists has the wrong dimensionality\")\n",
+    "\n",
+    "    if len(coordinate.shape) != 2:\n",
+    "        raise ValueError(\"Coordinate array has the wrong dimensionality\")\n",
+    "\n",
+    "    inputs = (coordinate,basepair,three_prime)\n",
+    "    if not np.all(np.diff([len(a) for a in inputs]) == 0):\n",
+    "        raise ValueError(\"Inputs are not the same length\")\n",
+    "        \n",
+    "    num_nt = len(basepair)\n",
+    "    if sequence is not None and len(sequence) != num_nt:\n",
+    "        raise ValueError(\"The 'sequence' parameter is the wrong length {} != {}\".format(len(sequence),num_nt))\n",
+    "\n",
+    "    if orientation is not None:\n",
+    "        orientation = np.array(orientation)\n",
+    "        if len(orientation.shape) != 3:\n",
+    "            raise ValueError(\"The 'orientation' array has the wrong dimensionality (should be Nx3x3)\")\n",
+    "        if orientation.shape != (num_nt,3,3):\n",
+    "            raise ValueError(\"The 'orientation' array is not properly formatted\")\n",
+    "\n",
+    "    if stack is None:\n",
+    "        if orientation is not None:\n",
+    "            stack = find_stacks(coordinate, orientation)\n",
+    "        else:\n",
+    "            ## Guess stacking based on 3' connectivity\n",
+    "            stack = np.array(three_prime,dtype=int) # Assume nts on 3' ends are stacked\n",
+    "            _stack_below = _three_prime_list_to_five_prime(stack)\n",
+    "            _has_bp = (basepair >= 0)\n",
+    "            _nostack = np.where( (stack == -1)*_has_bp )[0]\n",
+    "            _has_stack_below = _stack_below[basepair[_nostack]] >= 0\n",
+    "            _nostack2 = _nostack[_has_stack_below]\n",
+    "            stack[_nostack2] = basepair[_stack_below[basepair[_nostack2]]]\n",
+    "\n",
+    "    else:\n",
+    "        try:\n",
+    "            stack = np.array(stack,dtype=int)\n",
+    "        except:\n",
+    "            raise TypeError(\"The 'stack' array could not be converted into a numpy integer array\")\n",
+    "\n",
+    "        if len(stack.shape) != 1:\n",
+    "            raise ValueError(\"The 'stack' array has the wrong dimensionality\")\n",
+    "\n",
+    "        if len(stack) != num_nt:\n",
+    "            raise ValueError(\"The length of the 'stack' array does not match other inputs\")\n",
+    "\n",
+    "    bps = basepair              # alias\n",
+    "\n",
+    "    \"\"\" Fix stacks: require that the stack of a bp of a base's stack is its bp \"\"\"\n",
+    "    _has_bp =  (bps >= 0)\n",
+    "    _has_stack = (stack >= 0)\n",
+    "    _stack_has_basepair = (bps[stack] >= 0) * _has_stack\n",
+    "    stack = np.where( (stack[bps[stack]] == bps) * _has_bp * _has_stack * _has_bp,\n",
+    "                      stack, -np.ones(len(stack),dtype=int) )\n",
+    "\n",
+    "    five_prime = _three_prime_list_to_five_prime(three_prime)\n",
+    "\n",
+    "    \"\"\" Build map of dsDNA helices and strands \"\"\"\n",
+    "    hmap,hrank,fwd,intrahelical = basepairs_and_stacks_to_helixmap(bps,stack)\n",
+    "    double_stranded_helices = np.unique(hmap[hmap >= 0])    \n",
+    "    strands, strand_is_circular = _primes_list_to_strands(three_prime, five_prime)\n",
+    "\n",
+    "    \"\"\" Add ssDNA to hmap \"\"\"\n",
+    "    if len(double_stranded_helices) > 0:\n",
+    "        hid = double_stranded_helices[-1]+1\n",
+    "    else:\n",
+    "        hid = 0\n",
+    "    ss_residues = hmap < 0\n",
+    "    #\n",
+    "    if np.any(bps[ss_residues] != -1):\n",
+    "        logger.warning(f'{np.sum(bps[ss_residues] != -1)} ssDNA nucleotides appear to have basepairs... ignoring')\n",
+    "    \n",
+    "    for s,c in zip(strands, strand_is_circular):\n",
+    "        strand_segment_ends = [i for i in np.where( np.diff(hmap[s]) != 0 )[0]] + [len(s)-1]\n",
+    "        seg_start = 0\n",
+    "        for i in strand_segment_ends:\n",
+    "            if hmap[s[i]] < 0:\n",
+    "                ## Found single-stranded segment\n",
+    "                ids = s[seg_start:i+1]\n",
+    "                assert( np.all(hmap[ids] == -1) )\n",
+    "                hmap[ids] = hid\n",
+    "                hrank[ids] = np.arange(i+1-seg_start)\n",
+    "                hid+=1\n",
+    "            seg_start = i+1\n",
+    "\n",
+    "    if len(double_stranded_helices) > 0:\n",
+    "        single_stranded_helices = np.arange(double_stranded_helices[-1]+1,hid)\n",
+    "    else:\n",
+    "        single_stranded_helices = np.arange(hid)\n",
+    "\n",
+    "    ## Create double-stranded segments\n",
+    "    doubleSegments = []\n",
+    "    for hid in double_stranded_helices:\n",
+    "        seg = DoubleStrandedSegment(name=str(hid),\n",
+    "                                    num_bp = np.sum(hmap==hid)//2)\n",
+    "        set_splines(seg, coordinate, hid, hmap, hrank, fwd, basepair, orientation)\n",
+    "\n",
+    "        assert(hid == len(doubleSegments))\n",
+    "        doubleSegments.append(seg)\n",
+    "\n",
+    "    ## Create single-stranded segments\n",
+    "    singleSegments = []\n",
+    "    for hid in single_stranded_helices:\n",
+    "        seg = SingleStrandedSegment(name=str(hid),\n",
+    "                                    num_nt = np.sum(hmap==hid))\n",
+    "        set_splines(seg, coordinate, hid, hmap, hrank, fwd, basepair, orientation)\n",
+    "\n",
+    "        assert(hid == len(doubleSegments) + len(singleSegments))\n",
+    "        singleSegments.append(seg)\n",
+    "\n",
+    "    ## Find crossovers and 5prime/3prime ends\n",
+    "    crossovers,prime5,prime3 = [[],[],[]]\n",
+    "    for s,c in zip(strands,strand_is_circular):\n",
+    "        tmp = np.where(np.diff(hmap[s]) != 0)[0]\n",
+    "        for i in tmp:\n",
+    "            crossovers.append( (s[i],s[i+1]) )\n",
+    "        if c:\n",
+    "            if hmap[s[-1]] != hmap[s[0]]:\n",
+    "                crossovers.append( (s[-1],s[0]) )\n",
+    "        else:\n",
+    "            prime5.append(s[0])\n",
+    "            prime3.append(s[-1])\n",
+    "\n",
+    "    ## Add connections\n",
+    "    allSegments = doubleSegments+singleSegments\n",
+    "\n",
+    "    for r1,r2 in crossovers:\n",
+    "        seg1,seg2 = [allSegments[hmap[i]] for i in (r1,r2)]\n",
+    "        nt1,nt2 = [hrank[i] for i in (r1,r2)]\n",
+    "        f1,f2 = [fwd[i] for i in (r1,r2)]\n",
+    "\n",
+    "        ## Handle connections at the ends\n",
+    "        is_terminal1 = (nt1,f1) in ((0,0),(seg1.num_nt-1,1))\n",
+    "        is_terminal2 = (nt2,f2) in ((0,1),(seg2.num_nt-1,0))\n",
+    "\n",
+    "        print(seg1,seg2, r1, r2, is_terminal1, is_terminal2)\n",
+    "        if is_terminal1 or is_terminal2:\n",
+    "            \"\"\" Ensure that we don't have three-way dsDNA junctions \"\"\"\n",
+    "            if is_terminal1 and (bps[r1] >= 0) and (five_prime[bps[r1]] >= 0) and (three_prime[r1] >= 0):\n",
+    "                if (bps[five_prime[bps[r1]]] >= 0) and (bps[three_prime[r1]] >= 0):\n",
+    "                    # is_terminal1 = (three_prime[r1] == bps[five_prime[bps[r1]]])\n",
+    "                    is_terminal1 = hmap[five_prime[bps[r1]]] == hmap[three_prime[r1]]\n",
+    "            if is_terminal2 and (bps[r2] >= 0) and (three_prime[bps[r2]] >= 0) and (five_prime[r2] >= 0):\n",
+    "                if (bps[three_prime[bps[r2]]] >= 0) and (bps[five_prime[r2]] >= 0):\n",
+    "                    # is_terminal2 = (five_prime[r2] == bps[three_prime[bps[r2]]])\n",
+    "                    is_terminal2 = hmap[three_prime[bps[r2]]] == hmap[five_prime[r2]]\n",
+    "                \n",
+    "            \"\"\" Place connection \"\"\"\n",
+    "            if is_terminal1 and is_terminal2:\n",
+    "                end1 = seg1.end3 if f1 else seg1.start3\n",
+    "                end2 = seg2.start5 if f2 else seg2.end5\n",
+    "                seg1._connect_ends( end1, end2, type_='intrahelical')\n",
+    "            else:\n",
+    "                seg1.add_crossover(nt1,seg2,nt2,[f1,f2],type_=\"terminal_crossover\")\n",
+    "        else:\n",
+    "            seg1.add_crossover(nt1,seg2,nt2,[f1,f2])\n",
+    "\n",
+    "    ## Add 5prime/3prime ends\n",
+    "    for r in prime5:\n",
+    "        seg = allSegments[hmap[r]]\n",
+    "        seg.add_5prime(hrank[r],fwd[r])\n",
+    "    for r in prime3:\n",
+    "        seg = allSegments[hmap[r]]\n",
+    "        seg.add_3prime(hrank[r],fwd[r])\n",
+    "\n",
+    "    ## Add intrahelical connections to circular helical sections\n",
+    "    for nt0,nt1 in intrahelical:\n",
+    "        seg = allSegments[hmap[nt0]]\n",
+    "        assert( seg is allSegments[hmap[nt1]] )\n",
+    "        if three_prime[nt0] >= 0:\n",
+    "            if hmap[nt0] == hmap[three_prime[nt0]]:\n",
+    "                seg.connect_end3(seg.start5)\n",
+    "\n",
+    "        bp0,bp1 = [bps[nt] for nt in (nt0,nt1)]\n",
+    "        if three_prime[bp1] >= 0:\n",
+    "            if hmap[bp1] == hmap[three_prime[bp1]]:\n",
+    "                seg.connect_start3(seg.end5)\n",
+    "\n",
+    "    ## Assign sequence\n",
+    "    if sequence is not None:\n",
+    "        for hid in range(len(allSegments)):\n",
+    "            resids = np.where( (hmap==hid)*(fwd==1) )[0]\n",
+    "            s = allSegments[hid]\n",
+    "            s.sequence = [sequence[r] for r in sorted(resids,key=lambda x: hrank[x])]\n",
+    "\n",
+    "\n",
+    "    ## Build model\n",
+    "    model = SegmentModel( allSegments,\n",
+    "                          max_basepairs_per_bead = max_basepairs_per_bead,\n",
+    "                          max_nucleotides_per_bead = max_nucleotides_per_bead,\n",
+    "                          local_twist = local_twist,\n",
+    "                          dimensions = dimensions,\n",
+    "                          **model_parameters )\n",
+    "\n",
+    "\n",
+    "    model._reader_list_coordinates = coordinate\n",
+    "    model._reader_list_basepair = basepair\n",
+    "    model._reader_list_stack = stack\n",
+    "    model._reader_list_three_prime = three_prime\n",
+    "    model._reader_list_five_prime = five_prime\n",
+    "    model._reader_list_sequence = sequence\n",
+    "    model._reader_list_orientation = orientation\n",
+    "    model._reader_list_hmap = hmap\n",
+    "    model._reader_list_fwd = fwd\n",
+    "    model._reader_list_hrank = hrank\n",
+    "\n",
+    "    if sequence is None:\n",
+    "        for s in model.segments:\n",
+    "            s.randomize_unset_sequence()\n",
+    "\n",
+    "    return model\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "ba82a4ed",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "<DoubleStrandedSegment'> 1[1]> <DoubleStrandedSegment'> 0[1]> 5 3 True True\n",
+      "<SingleStrandedSegment'> 2[2]> <DoubleStrandedSegment'> 0[1]> 1 2 True True\n",
+      "<DoubleStrandedSegment'> 0[1]> <DoubleStrandedSegment'> 1[1]> 2 4 True True\n",
+      "<DoubleStrandedSegment'> 1[1]> <SingleStrandedSegment'> 3[1]> 4 6 True True\n",
+      "<SingleStrandedSegment'> 3[1]> <SingleStrandedSegment'> 2[2]> 6 0 True True\n"
+     ]
+    }
+   ],
+   "source": [
+    "coordinate = [(0,0,3.4*i) for i in range(7)]\n",
+    "three_prime = [ 1, 2, 4,-1, 6, 3, 0]\n",
+    "basepair    = [-1,-1, 3, 2, 5, 4,-1]\n",
+    "stack       = [-1,-1, -1,-1,-1, -1,-1]\n",
+    "for i in [3,5]:\n",
+    "    coordinate[i] = (1,0,3.4*i)\n",
+    "\n",
+    "model = model_from_basepair_stack_3prime(coordinate, basepair, stack, three_prime,\n",
+    "                                             max_basepairs_per_bead=1,\n",
+    "                                             max_nucleotides_per_bead=1,\n",
+    "                                             local_twist=False)\n",
+    "model.writePsf(\"list.psf\")\n",
+    "model.writePdb(\"list.pdb\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "79e8a471",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[[<SegmentParticle DNA on <DoubleStrandedSegment'> 0[1]>[1.00]>], [<SegmentParticle DNA on <DoubleStrandedSegment'> 1[1]>[0.00]>, <SegmentParticle DNA on <DoubleStrandedSegment'> 1[1]>[1.00]>], [<SegmentParticle NAS on <SingleStrandedSegment'> 2[2]>[0.00]>, <SegmentParticle NAS on <SingleStrandedSegment'> 2[2]>[0.50]>, <SegmentParticle NAS on <SingleStrandedSegment'> 2[2]>[1.00]>], [<SegmentParticle NAS on <SingleStrandedSegment'> 3[1]>[0.50]>]]\n",
+      "[[<Connection <Location 1.end3[0,on_fwd_strand]>--intrahelical--<Location 0.end5[0,on_fwd_strand]>]>, <Connection <Location 2.end3[1,on_fwd_strand]>--sscrossover--<Location 0.end5[0,on_rev_strand]>]>, <Connection <Location 0.end3[0,on_rev_strand]>--intrahelical--<Location 1.end5[0,on_rev_strand]>]>], [<Connection <Location 1.end3[0,on_fwd_strand]>--intrahelical--<Location 0.end5[0,on_fwd_strand]>]>, <Connection <Location 0.end3[0,on_rev_strand]>--intrahelical--<Location 1.end5[0,on_rev_strand]>]>, <Connection <Location 1.end3[0,on_rev_strand]>--intrahelical--<Location 3.end5[0,on_fwd_strand]>]>], [<Connection <Location 2.end3[1,on_fwd_strand]>--sscrossover--<Location 0.end5[0,on_rev_strand]>]>, <Connection <Location 3.end3[0,on_fwd_strand]>--intrahelical--<Location 2.end5[0,on_fwd_strand]>]>], [<Connection <Location 1.end3[0,on_rev_strand]>--intrahelical--<Location 3.end5[0,on_fwd_strand]>]>, <Connection <Location 3.end3[0,on_fwd_strand]>--intrahelical--<Location 2.end5[0,on_fwd_strand]>]>]]\n"
+     ]
+    }
+   ],
+   "source": [
+    "print([i.children for i in model.children])\n",
+    "print([i.connections for i in model.children])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "71b7ffdc",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "s=model.children[0]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "f7c95c63",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'0'"
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s.segname"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "e905bb35",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[(0, 0, 0.0),\n",
+       " (0, 0, 3.4),\n",
+       " (0, 0, 6.8),\n",
+       " (1, 0, 10.2),\n",
+       " (0, 0, 13.6),\n",
+       " (1, 0, 17.0),\n",
+       " (0, 0, 20.4)]"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "coordinate"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "8964b3a5",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.8.18"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
-- 
GitLab