Example #1
0
def read_tom_strands_from_file(filename, box=20):
    infile = open(filename, 'r')
    mysys = base.System([box, box, box])
    for line in infile.readlines():
        if len(line) > 2:
            strand = read_tom_strand_from_string(line, box)
            mysys.add_strand(strand, check_overlap=False)

    return mysys
Example #2
0
def double_strands():
    g = gen.StrandGenerator()
    s = base.System([30, 30, 30])
    s.add_strands(g.generate(10))
    s.add_strands(g.generate(10))
    s.add_strands(g.generate(25, dir=[0, 1, 0], start_position=[0, 0, 7], double=False))
    s.add_strands(g.generate(25, dir=[1, 1, 1], start_position=[-10, -10, -10]))
    s.print_crepy_output ("prova.mgl")
    s.print_lorenzo_output ("generated.dat", "generated.top")
Example #3
0
def read_strands():
    # prendiamo le sequenze da un file; ogni riga uno strand; se e' un
    # double strand, ci deve essere DOUBLE davanti
    double = gen.StrandGenerator()
    try:
        infile = open ("caca.sqs", "r")
    except IOError:
        base.Logger.die("caca.sqs not found")

    if len(sys.argv) > 1:
        side = float(sys.argv[1])
    else: side = 50

    lines = infile.readlines()
    nlines = len(lines)
    print >> sys.stderr, "Found %i lines" % (nlines)
    s = base.System(np.array ([float(side), float(side), float(side)], np.float64))
    i = 1 
    for line in lines:
        line = line.upper().strip()
        # skip empty lines
        if len(line) == 0: continue
        if line[:6] == 'DOUBLE':
            line = line[6:]
            line = line.split()[-1]
            seq = [base.base_to_number[x] for x in line]
            length = len(line)
            print >> sys.stderr, "Adding duplex of %i bases" % (length)
            cdm = np.random.random_sample(3) * s._box
            axis = np.random.random_sample(3)
            axis /= np.sqrt(np.dot(axis, axis))
            axis = np.array ([1.,0.,0])
            cdm = np.array ([0.,0.,0.])
            while not s.add_strands(double.generate(len(line), sequence=seq, dir=axis, start_pos=cdm)):
                cdm = np.random.random_sample(3) * s._box
                axis = np.random.random_sample(3)
                axis /= np.sqrt(np.dot(axis, axis))
                print >> sys.stderr, "  riprovo %i" % (i)
            print >> sys.stderr, "  done %i" % (i)
        else:
            seq = [base.base_to_number[x] for x in line]
            cdm = np.random.random_sample(3) * s._box
            axis = np.random.random_sample(3)
            axis /= np.sqrt(np.dot(axis, axis))
            print >> sys.stderr, "Adding single strand of %i bases" % (len(line))
            while not s.add_strand(double.generate(len(line), sequence=seq, dir=axis, start_pos=cdm, double=False)):
                cdm = np.random.random_sample(3) * s._box
                axis = np.random.random_sample(3)
                axis /= np.sqrt(np.dot(axis, axis))
                print >> sys.stderr, "  riprovo %i" % (i)
            print >> sys.stderr, "  done %i" % (i)
        #print >> sys.stderr, "Added strand..."
        i += 1

    s.print_crepy_output("prova.mgl")
    s.print_lorenzo_output("prova.conf", "prova.top")
Example #4
0
def process_sequence_file(fname, box):
    s = base.System([box, box, box])
    fin = open(fname, 'r')
    for line in fin.readlines():
        vals = line.split()
        if (vals[0] == 'DOUBLE'):
            seq = vals[1].strip()
            track = [base.base_to_number[x] for x in seq]
            print >> sys.stderr, 'Adding duplex 3\'-', seq, '-5\''
            do_strands(s, track, True)
        else:
            seq = vals[0].strip()
            track = [base.base_to_number[x] for x in seq]
            do_strands(s, track, False)
            print >> sys.stderr, 'Adding sequence 3\'-', seq, '-5\''
    s.print_lorenzo_output(prefix + ".conf", prefix + ".top")
    return s
Example #5
0
    def _read(self, only_strand_ends=False, skip=False):
        timeline = self._conf.readline()
        time = 0.
        if len(timeline) == 0:
            return False
        else:
            time = float(timeline.split()[2])

        box = np.array([float(x) for x in self._conf.readline().split()[2:]])
        [E_tot, E_pot, E_kin] = [float(x) for x in self._conf.readline().split()[2:5]]

        if skip:
            for tl in self._top_lines:
                self._conf.readline()

            return False

        system = base.System(box, time=time, E_pot=E_pot, E_kin=E_kin)
        base.Nucleotide.index = 0
        base.Strand.index = 0
        s = False
        strandid_current = 0
        for tl in self._top_lines:
            tls = tl.split()
            n3 = int(tls[2])
            n5 = int(tls[3])
            strandid = int(tls[0])
            if (len(tls[1]) == 1):
                b = base.base_to_number[tls[1]]
                bb = b
            else:
                try:
                    tmp = int(tls[1])
                except:
                    raise ValueError ("problems in topology file with specific base pairing")

                if tmp > 0:
                    b = tmp % 4
                else:
                    b = (3 - ((3 - tmp) % 4))
                bb = tmp

            if strandid != strandid_current:
                # check for circular strand
                if n3 != -1:
                    iscircular = True
                else:
                    iscircular = False

                if s:
                    system.add_strand(s, self._check_overlap)
                s = base.Strand()
                if iscircular:
                    s.make_circular()
                strandid_current = strandid

            ls = self._conf.readline().split()
            cm = [float(x) for x in ls[0:3]]
            a1 = [float(x) for x in ls[3:6]]
            a3 = [float(x) for x in ls[6:9]]
            v = [float(x) for x in ls[9:12]]
            L = [float(x) for x in ls[12:15]]
            if not only_strand_ends or n3 == -1 or n5 == -1:
                s.add_nucleotide(base.Nucleotide(cm, a1, a3, b, bb, v, L, n3))

        system.add_strand(s, self._check_overlap)

        return system
Example #6
0
def read_strands(filename='caca.sqs', box_side=50):
    """
    The main() function for this script
    Reads a text file with the following format:
    - Each line contains the sequence for a single strand (A,C,T,G)
	      the nucleotides can be specified by (case insensitive) letter (A, C, G, T), 
			random (X), strong (S) and weak (W).
    - Options:
        - DOUBLE
        - CIRCULAR
        - DOUBLE CIRCULAR
        - DELTALK = ???

    Ex: Two ssDNA (single stranded DNA)
    ATATATA
    GCGCGCG

    Ex: Two strands, one double stranded, the other single stranded.
    DOUBLE AGGGCT
    CCTGTA

	 Ex: One dsDNA that frays only on one side:
	 DOUBLE SSXXXXXXWW

	 Ex: One dsDNA that frays very little but has TATA in the middle:
	 DOUBLE SSXXXXTATAXXXXSS

    Ex: Two strands, one double stranded circular, the other single stranded circular.
    DOUBLE CIRCULAR AGAGGTAGGAGGATTTGCTTGAGCTTCGAGAGCTTCGAGATTCGATCAGGGCT
    CIRCULAR CCTGTAAGGAGATCGGAGAGATTCGAGAGGATCTGAGAGCTTAGCT
    """
    # we read the sequences from a file; each line is a strand;
    # prepending DOUBLE tells us to generate a double strand
    # prepending CIRCULAR tells us to generate a (topologically) closed strand

    # Check filename
    try:
        infile = open(filename, "r")
    except IOError:
        base.Logger.die("%s not found" % filename)

    # Check box_side
    if box_side > 1:
        pass
    else:
        base.Logger.log("Invalid box size (%f). Using default box size." %
                        box_side,
                        level=base.Logger.WARNING)
        box_side = 50

    double = gen.StrandGenerator()
    lines = infile.readlines()
    nlines = len(lines)
    print(sys.stdout, "Found %i lines" % (nlines))

    box = np.array(
        [float(box_side), float(box_side),
         float(box_side)], np.float64)
    s = base.System(box)
    i = 1
    for line in lines:
        line = line.upper().strip()
        # skip empty lines
        if len(line) == 0: continue

        # Set flags
        bool_double = False
        bool_circular = False
        bool_rw = False
        type_strand = 'single strand'
        type_circular = 'linear'
        if line.find('DOUBLE') >= 0:
            bool_double = True
            type_strand = 'duplex'
        if line.find('CIRCULAR') >= 0:
            bool_circular = True
            type_circular = 'circular'
        if line.find('RW') >= 0:
            bool_rw = True


#        if line.find('DELTALK') >= 0:
#            DLKline = line.split()
#            DLK = DLKline[-1]

# Parse input and output structures in lorenzo format
        raw_seq = line.split()[-1]

        import random
        raw_seq2 = ""
        for x in raw_seq:
            if x in ['x', 'X']:
                raw_seq2 += random.choice(['A', 'C', 'G', 'T'])
            elif x in ['s', 'S']:
                raw_seq2 += random.choice(['C', 'G'])
            elif x in ['w', 'W']:
                raw_seq2 += random.choice(['A', 'T'])
            else:
                raw_seq2 += x

        seq = [base.base_to_number[x] for x in raw_seq2]
        length = len(raw_seq)
        print(
            sys.stdout,
            "Adding %s %s of %i bases" % (type_circular, type_strand, length))
        cdm = np.random.random_sample(3) * s._box
        axis = np.random.random_sample(3)
        axis /= np.sqrt(np.dot(axis, axis))
        success = False
        while not success:
            if not bool_rw:
                success = s.add_strands(double.generate(len(seq), sequence=seq, dir=axis, \
                   start_pos=cdm, double=bool_double, circular=bool_circular), check_overlap=True)
            else:
                success = s.add_strands(
                    double.generate_rw(sequence=seq, start_pos=cdm))

            cdm = np.random.random_sample(3) * s._box
            axis = np.random.random_sample(3)
            axis /= np.sqrt(np.dot(axis, axis))
            print(sys.stdout, "  try again with %i" % (i))
        print(sys.stdout, "  done %i" % (i))
        i += 1

    s.print_lorenzo_output("generated.dat", "generated.top")
Example #7
0
def tetramers():
    g = gen.TetramerGenerator()
    s = base.System([20, 20, 20])
    s.add_strands(g.generate())
    s.print_crepy_output("tetramer.mgl")
    s.print_lorenzo_output("tetramer.dat", "tetramer.top")
Example #8
0
        elif line.startswith('"col"'):
            ret.col = map(int, re.findall(r'(\d+)', line))[0]
        else:
            pass  #print >> sys.stderr, "Unknown line... Passing"

    return ret


cadsys = parse_cadnano('dummy.json')
side = cadsys.bbox()
vhelix_direction = np.array([0, 0, 1])
vhelix_perp = np.array([1, 0, 0])
R = get_rotation_matrix(vhelix_direction, np.pi * 160. / 180)
vhelix_perp = np.dot(R, vhelix_perp)
g = gen.StrandGenerator()
slice_sys = base.System([side, side, side])
final_sys = base.System([side, side, side])
strand_number = -1
partner_list_scaf = []
partner_list_stap = []
found_partner = False
join_list_scaf = []
join_list_stap = []
for h in cadsys.vhelices:
    # generate helix angles
    helix_angles = np.zeros(h.len - 1, dtype=float)

    av_angle = 720. / 21 * np.pi / 180

    for i in range(len(helix_angles)):
        modi = i % 21
Example #9
0
checkboard = [[1 for i in range(width)] for i in range(height)]
checkboard[0] = [0, 1, 1, 0]

# major index on heigth
# each height step is a dsDNA
# each width step is a 16bp turn
print >> sys.stderr, "#(stderr) Will generate a %d nucleotide system" % (
    width * height * 32)

print checkboard

# for each row, we print out a dsDNA
box = np.max([2.5 * height, 17 * width])
box = 50

s = base.System([box, box, box])

g = gen.StrandGenerator()

for i in range(height):
    for j in range(width):
        if checkboard[i][j] > 0:
            print "#",
            # orientation along positive x if i is odd
            align = [float(pow(-1, i)), 0, 0]
            #align_perp = [0, 0, float (pow (-1, i))]
            align_perp = [0, 1, 0]
            rot = [j * 16, gen.BP]

            # start position of strand
            pos = [
Example #10
0
#!/usr/bin/env python

import base
import generators as gen
import numpy as np

s = gen.StrandGenerator()
str = s.generate(4,
                 double=False,
                 dir=np.array([0, 1, 0]),
                 start_pos=np.array([0, 0, 1]))
syst = base.System([3, 3, 3])
syst.add_strand(str)
syst.print_lorenzo_output("prova.conf", "prova.top")
Example #11
0
    def _read(self, only_strand_ends=False, skip=False):
        try:
            timeline = self._conf.readline()
            time = float(timeline.split()[2])
    
            box = np.array([float(x) for x in self._conf.readline().split()[2:]])
            self._conf.readline()
        except Exception as e:
            raise Exception("The header lines of the configuration file are invalid (caught a '%s' exception)" % e)

        if skip:
            for tl in self._top_lines:
                self._conf.readline()

            return False

        system = base.System(box, time=time)
        base.Nucleotide.index = 0
        base.Strand.index = 0

        s = False
        strandid_current = 0
        for i_line, tl in enumerate(self._top_lines):
            tls = tl.split()
            n3 = int(tls[2])
            n5 = int(tls[3])
            strandid = int(tls[0])
            if (len (tls[1]) == 1):
                b = base.base_to_number[tls[1]]
                bb = b
            else:
                try:
                    tmp = int (tls[1])
                except:
                    raise Exception("The line n. %d in the topology file contains an incorrect specific base pairing" % i_line)

                if tmp > 0:
                    b = tmp % 4
                else:
                    b = (3 - ((3 - tmp) % 4))
                bb = tmp

            if strandid != strandid_current:
                # check for circular strand
                if n3 != -1:
                    iscircular = True
                else:
                    iscircular = False

                if s:
                    system.add_strand(s)
                s = base.Strand()
                if iscircular:
                    s.make_circular()
                strandid_current = strandid

            ls = self._conf.readline().split()
            if len(ls) == 0:
                raise Exception("The %d-th nucleotide line in the configuration file is empty" % i_line)
            elif len(ls) != 15:
                raise Exception("The %d-th nucleotide line in the configuration file is invalid" % i_line)
            cm = [float(x) for x in ls[0:3]]
            a1 = [float(x) for x in ls[3:6]]
            a3 = [float(x) for x in ls[6:9]]
            v = [float(x) for x in ls[9:12]]
            L = [float(x) for x in ls[12:15]]
            if not only_strand_ends or n3 == -1 or n5 == -1:
                s.add_nucleotide(base.Nucleotide(cm, a1, a3, b, bb, v, L, n3))

        system.add_strand(s)
        
        return system
Example #12
0
workdir="../calb-MeOH/"
os.chdir(workdir)
results=workdir+"notebook_results"
if not os.path.exists(results):
    os.makedirs(results)
    
    
#concentrations=['300mM', '600mM']
concentrations=['50mM', '150mM', '300mM', '600mM', '1M', '2.5M', '5.5M']
#concentrations_scalar=[0.3, 0.6]
parameter_scalar={"50mM":0.05, "150mM":0.150, "300mM":0.3, "600mM":0.6, "1M":1, "2.5M":2.5, "5.5M":5.5}
stride=2

project=base.System(workdir=workdir, parent_folder='calb-MeOH', results_folder=results,
                      parameter=parameter_scalar.keys(), parameter_scalar=parameter_scalar.values(), 
                      replicas=10, trajectory='calb.xtc', topology='calb.pdb', protein='calb', ligand='MeOH', timestep=5)

#system.getProperties('protein')


systems=project.create() 

print(systems['protein'])

importlib.reload(base)

selection='resname MeOH'    


#for parameter, v in systems.items():
Example #13
0
import os
import base
import readers
import numpy as np


l = readers.LorenzoReader("prova.conf", "prova.top")
s = l.get_system()
s.map_nucleotides_to_strands()
system = base.System(s._box, s._time)
init = []

break_index = 0

for strand in s._strands:
    break_index = 0
    for i in range(len(strand._nucleotides)-1):
        dr = strand._nucleotides[i].distance(strand._nucleotides[i+1],box=system._box)
        d = np.sqrt(np.dot(dr,dr))
        if d > 0.7525+0.25:
            init.append([strand._nucleotides[i].index,strand._nucleotides[i+1].index,d])
            #if strand.get_slice(break_index, i).N != 0:
            system.add_strand(strand.get_slice(break_index, i+1), check_overlap=False)
            break_index = i+1
        #if strand.get_slice(break_index, strand._last-strand._first).N != 0:
    system.add_strand(strand.get_slice(break_index, strand._last-strand._first+1),check_overlap=False)
    if break_index == 0 and strand._circular==True:
        system._strands[-1]._circular = True

r = 0
while True:
Example #14
0
    strandid2 = s._nucleotide_to_strand[nucid2]
    ligate_list.append(strandid1)
    ligate_list.append(strandid2)
    base.Logger.log(
        "Ligating strand %d and strand %d" % (strandid1, strandid2),
        base.Logger.INFO)
    if (nucid1 != s._strands[strandid1]._last) or (
            nucid2 != s._strands[strandid2]._first):
        base.Logger.die(
            "You should put the 5' nucleotide before the 3' nucleotide in ligate_file."
        )
    new_strand = s._strands[strandid1].append(s._strands[strandid2])
    new_strands.append(new_strand)

if len(set(ligate_list)) != len(ligate_list):
    base.Logger.die(
        "Multiple ligations on one strand detected. This cannot be handled by the script."
    )

new_system = base.System(s._box)
for idx, strand in enumerate(s._strands):
    if idx not in ligate_list:
        new_system.add_strand(strand.copy(), check_overlap=False)

for new_strand in new_strands:
    new_system.add_strand(new_strand.copy(), check_overlap=False)

new_system.print_lorenzo_output('ligated.conf', 'ligated.top')
base.Logger.log("Printed output files ligated.conf and ligated.top",
                base.Logger.INFO)
def main():
    vh_vb2nuc = oru.vhelix_vbase_to_nucleotide()
    vh_vb2nuc_final = oru.vhelix_vbase_to_nucleotide()
    if len(sys.argv) < 3:
        print_usage()

    origami_sq = False
    origami_he = False
    if sys.argv[2] == "sq":
        origami_sq = True
    elif sys.argv[2] == "he":
        origami_he = True
    else:
        print_usage()

    source_file = sys.argv[1]

    nupack = 0
    side = False
    if len(sys.argv) > 3:
        if sys.argv[3] == "nupack":
            # nupack option prints a scaffold pattern file for use (indirectly) in nupack
            nupack = 1
            base.Logger.log("using nupack option; scaffold pattern file will be generated. Assuming a single origami with saturated hydrogen bonds", base.Logger.INFO)
        else:
            # read 4th arg as system size in oxDNA simulation units
            side = float(sys.argv[3])
            base.Logger.log("using side option; system will be in a box of side %s in simulation units" % str(side), base.Logger.INFO)

    cadsys = parse_cadnano (source_file)
    base.Logger.log("using json file %s" % source_file, base.Logger.INFO)

    # define sequences by vhelix
    sequence_file = 0
    single_strand_system = False
    if nupack == 0:
        try:
            sequence_file = open("caca.sqs", "r")
        except:
            base.Logger.log("no sequence file found, using random sequence", base.Logger.INFO)

        sequences = []
        block_seq = True
        if sequence_file:
            base.Logger.log("using sequence file caca.sqs", base.Logger.INFO)
            lines = sequence_file.readlines()
            for line in lines:
                seq = []
                for x in line.replace("\n","").replace(" ",""):
                    if x in ["R","r"]:
                        seq.append(np.random.randint(0, 4))
                    else:
                        try:
                            seq.append(base.base_to_number[x])
                        except KeyError:
                            base.Logger.log("KeyError while converting base to integer; check caca.sqs", base.Logger.CRITICAL)
                            sys.exit()
                sequences.append(seq)
        else:
            for ii in range(len(cadsys.vhelices)):
                seq = []
                for jj in range(cadsys.vhelices[ii].skiploop_bases):
                    seq.append(np.random.randint(0,4))
                sequences.append(seq)

        # check whether we're dealing with a 1 strand system (i.e. NOT double helix) across many vhelices and defined with 1 .sqs line
        if len(sequences) == 1 and len(cadsys.vhelices) > 1:
            base.Logger.log("1 .sqs line detected and more than 1 cadnano virtual helix detected; assuming using sequence from file assuming a single strand system", base.Logger.INFO)
            single_strand_system = True
            block_seq = False

    if nupack:
        staple_to_scaffold = []
        staple_to_vhelix = {}
        staple_to_vhelix_final = {}
        vhelix_to_scaffold = {}
        scaf_count = 0
        vhelix_to_scaffold_final = {}
        record_joined = []

    vhelix_counter = 0
    if not side:
        side = cadsys.bbox()
        if not nupack:
            base.Logger.log("using default box size, a factor %s larger than size of cadnano system" % str(BOX_FACTOR), base.Logger.INFO)
    vhelix_direction_initial = np.array([0,0,1])
    vhelix_perp_initial = np.array([1,0,0])
    if origami_sq:
        vhelix_perp_initial = vhelix_rotation_origami_sq(vhelix_direction_initial, vhelix_perp_initial)
        period = 21
    elif origami_he:
        vhelix_perp_initial = vhelix_rotation_origami_he(vhelix_direction_initial, vhelix_perp_initial)
        period = 32

    g = gen.StrandGenerator ()
    slice_sys = base.System([side,side,side])
    final_sys = base.System([side,side,side])
    strand_number = -1
    partner_list_scaf = []
    partner_list_stap = []
    found_partner = False
    join_list_scaf = []
    join_list_stap = []
    for h in cadsys.vhelices:
        h.cad_index = vhelix_counter
        if origami_sq:
            strands, helix_angles, pos, rot, vhelix_direction, vhelix_perp = generate_vhelices_origami_sq(vhelix_direction_initial, vhelix_perp_initial, h, sequence_file, single_strand_system, vhelix_counter)
        elif origami_he:
            strands, helix_angles, pos, rot, vhelix_direction, vhelix_perp = generate_vhelices_origami_he(vhelix_direction_initial, vhelix_perp_initial, h, sequence_file, single_strand_system, vhelix_counter)

        nodes = build_nodes(h)
        
        # read the scaffold squares and add strands to slice_sys
        i = 0
        for s in h.scaf:
            if s.V_0 == -1 and s.b_0 == -1:
                if s.V_1 == -1 and s.b_0 == -1:
                    pass
                elif s.V_1 == h.num:
                    if h.num % 2 == 0:
                        strand_number += 1
                    begin_helix = i
                    if h.num % 2 == 1:
                        if nupack:
                            vhelix_to_scaffold = add_slice_nupack(h, strand_number, begin_helix, end_helix, vhelix_to_scaffold, 0)
                        else:
                            slice_sys = add_slice(slice_sys, h, begin_helix, end_helix, nodes, strands, pos, vhelix_direction, vhelix_perp, rot, helix_angles, 0, block_seq, sequences)
                            vh_vb2nuc = add_slice_nupack(h, strand_number, begin_helix, end_helix, vh_vb2nuc, 2)
                else:
                    base.Logger.log("unexpected square array", base.Logger.WARNING)
            elif s.V_0 == h.num:
                if s.V_1 == -1 and s.b_1 == -1:
                    if h.num % 2 == 1:
                        strand_number += 1
                    end_helix = i
                    if h.num % 2 == 0:
                        if nupack:
                            vhelix_to_scaffold = add_slice_nupack(h, strand_number, begin_helix, end_helix, vhelix_to_scaffold, 0)
                        else:
                            slice_sys = add_slice(slice_sys, h, begin_helix, end_helix, nodes, strands, pos, vhelix_direction, vhelix_perp, rot, helix_angles, 0, block_seq, sequences)
                            vh_vb2nuc = add_slice_nupack(h, strand_number, begin_helix, end_helix, vh_vb2nuc, 2)
                elif s.V_1 == h.num:
                    pass
                else:
                    if h.num % 2 == 1:
                        strand_number += 1
                    end_helix = i
                    if h.num % 2 == 0 :
                        if nupack:
                            vhelix_to_scaffold = add_slice_nupack(h, strand_number, begin_helix, end_helix, vhelix_to_scaffold, 0)
                        else:
                            slice_sys = add_slice(slice_sys, h, begin_helix, end_helix, nodes, strands, pos, vhelix_direction, vhelix_perp, rot, helix_angles, 0, block_seq, sequences)
                            vh_vb2nuc = add_slice_nupack(h, strand_number, begin_helix, end_helix, vh_vb2nuc, 2)

                    if h.num % 2 == 1:
                        column = i
                    else:
                        column = i
                    for j in range(len(partner_list_scaf)):

                        if [h.num, column] == partner_list_scaf[j]:
                            join_list_scaf[j].insert(0,strand_number)
                            found_partner = True
                    if found_partner == False:
                        join_list_scaf.append([strand_number])
                        partner_list_scaf.append([s.V_1, s.b_1])
                    found_partner = False
            else:
                if s.V_1 == -1 and s.b_1 == -1:
                    base.Logger.log("unexpected square array", base.Logger.WARNING)
                elif s.V_1 == h.num:
                    if h.num % 2 == 0:
                        strand_number += 1
                    begin_helix = i
                    if h.num % 2 == 1:
                        if nupack:
                            vhelix_to_scaffold = add_slice_nupack(h, strand_number, begin_helix, end_helix, vhelix_to_scaffold, 0)
                        else:
                            slice_sys = add_slice(slice_sys, h, begin_helix, end_helix, nodes, strands, pos, vhelix_direction, vhelix_perp, rot, helix_angles, 0, block_seq, sequences)
                            vh_vb2nuc = add_slice_nupack(h, strand_number, begin_helix, end_helix, vh_vb2nuc, 2)

                    for j in range(len(partner_list_scaf)):
                        if h.num % 2 == 1:
                            column = i
                        else:
                            column = i
                        if [h.num, column] == partner_list_scaf[j]:
                            join_list_scaf[j].append(strand_number)
                            found_partner = True
                    if found_partner == False:
                        join_list_scaf.append([strand_number])
                        partner_list_scaf.append([s.V_0, s.b_0])
                    found_partner = False
                else:
                    base.Logger.log("unexpected square array", base.Logger.WARNING)                
            i += 1

        # read the staple squares and add strands to slice_sys
        i = 0
        for s in h.stap:
            if s.V_0 == -1 and s.b_0 == -1:
                if s.V_1 == -1 and s.b_0 == -1:
                    pass
                elif s.V_1 == h.num:
                    if h.num % 2 == 1:
                        strand_number += 1
                    begin_helix = i
                    if h.num % 2 == 0:
                        if nupack:
                            staple_to_vhelix = add_slice_nupack(h, strand_number, begin_helix, end_helix, staple_to_vhelix, 1)
                        else:
                            slice_sys = add_slice(slice_sys, h, begin_helix, end_helix, nodes, strands, pos, vhelix_direction, vhelix_perp, rot, helix_angles, 1, block_seq, sequences)
                            vh_vb2nuc = add_slice_nupack(h, strand_number, begin_helix, end_helix, vh_vb2nuc, 3)
                else:
                    base.Logger.log("unexpected square array", base.Logger.WARNING)
            elif s.V_0 == h.num:
                if s.V_1 == -1 and s.b_1 == -1:
                    if h.num % 2 == 0:
                        strand_number += 1
                    end_helix = i
                    if h.num % 2 == 1:
                        if nupack:
                            staple_to_vhelix = add_slice_nupack(h, strand_number, begin_helix, end_helix, staple_to_vhelix, 1)
                        else:
                            slice_sys = add_slice(slice_sys, h, begin_helix, end_helix, nodes, strands, pos, vhelix_direction, vhelix_perp, rot, helix_angles, 1, block_seq, sequences)
                            vh_vb2nuc = add_slice_nupack(h, strand_number, begin_helix, end_helix, vh_vb2nuc, 3)

                elif s.V_1 == h.num:
                    pass
                else:
                    if h.num % 2 == 0:
                        strand_number += 1
                    end_helix = i
                    if h.num % 2 == 1:
                        if nupack:
                            staple_to_vhelix = add_slice_nupack(h, strand_number, begin_helix, end_helix, staple_to_vhelix, 1)
                        else:
                            slice_sys = add_slice(slice_sys, h, begin_helix, end_helix, nodes, strands, pos, vhelix_direction, vhelix_perp, rot, helix_angles, 1, block_seq, sequences)
                            vh_vb2nuc = add_slice_nupack(h, strand_number, begin_helix, end_helix, vh_vb2nuc, 3)

                    if h.num % 2 == 0:
                        column = i
                    else:
                        column = i
                    for j in range(len(partner_list_stap)):

                        if [h.num, column] == partner_list_stap[j]:
                            join_list_stap[j].insert(0,strand_number)
                            found_partner = True
                    if found_partner == False:
                        join_list_stap.append([strand_number])
                        partner_list_stap.append([s.V_1, s.b_1])
                    found_partner = False
            else:
                if s.V_1 == -1 and s.b_1 == -1:
                    base.Logger.log("unexpected square array", base.Logger.WARNING)
                elif s.V_1 == h.num:
                    if h.num % 2 == 1:
                        strand_number += 1
                    begin_helix = i
                    if h.num % 2 == 0:
                        if nupack:
                            staple_to_vhelix = add_slice_nupack(h, strand_number, begin_helix, end_helix, staple_to_vhelix, 1)
                        else:
                            slice_sys = add_slice(slice_sys, h, begin_helix, end_helix, nodes, strands, pos, vhelix_direction, vhelix_perp, rot, helix_angles, 1, block_seq, sequences)
                            vh_vb2nuc = add_slice_nupack(h, strand_number, begin_helix, end_helix, vh_vb2nuc, 3)

                    for j in range(len(partner_list_stap)):
                        if h.num % 2 == 0:
                            column = i
                        else:
                            column = i
                        if [h.num, column] == partner_list_stap[j]:
                            join_list_stap[j].append(strand_number)
                            found_partner = True
                    if found_partner == False:
                        join_list_stap.append([strand_number])
                        partner_list_stap.append([s.V_0, s.b_0])
                    found_partner = False
                else:
                    base.Logger.log("unexpected square array", base.Logger.WARNING)                
            i += 1
        vhelix_counter += 1

    join_lists = [join_list_scaf, join_list_stap]

    # add strands to final_sys that aren't joined
    join_list_unpacked = []
    for a in range(2):
        for i in join_lists[a]:
            join_list_unpacked.extend(i)
    for i in range(len(slice_sys._strands)):
        if i not in join_list_unpacked:
            final_sys.add_strand(slice_sys._strands[i], check_overlap = False)
            vh_vb2nuc_final.add_strand(i, vh_vb2nuc)

    for a in range(2):
        join_list = join_lists[a]
        all_are_joined = False
        restart = False

        if not nupack:
            # check distance between the backbones we are about to join
            for pair in join_list:
                strand1 = slice_sys._strands[pair[0]]
                strand2 = slice_sys._strands[pair[1]]
                backbone_backbone_dist = strand1._nucleotides[-1].distance(strand2._nucleotides[0], PBC=False)
                absolute_bb_dist = np.sqrt(np.dot(backbone_backbone_dist, backbone_backbone_dist))
                if absolute_bb_dist > 1.0018 or absolute_bb_dist < 0.5525:
                    base.Logger.log("backbone-backbone distance across join the wrong length: %f" % absolute_bb_dist, base.Logger.WARNING)

        # match up all the pairs of joins that involve the same strand
        circular = []
        while all_are_joined == False:
            restart = False
            for i in range(len(join_list)):
                if restart == True:
                    break
                for j in range(len(join_list)):
                    if restart == True:
                        break
                    if join_list[i][0] == join_list[j][-1]:
                        if i != j:
                            join_list[j].extend(join_list[i][1:])
                            join_list.pop(i)
                            restart = True
                            break
                        else:
                            if i not in circular:
                                circular.append(i)

            if restart == False:
                all_are_joined = True

        # add joined strands
        for ii, join in enumerate(join_list):
            if not nupack:
                joined_strand = slice_sys._strands[join[0]]
                if ii in circular:
                    for k in range(1, len(join)-1):
                        joined_strand = joined_strand.append(slice_sys._strands[join[k]])
                    joined_strand.make_circular(check_join_len=True)
                else:
                    for k in range(1, len(join)):
                        joined_strand = joined_strand.append(slice_sys._strands[join[k]])
                    
                final_sys.add_strand(joined_strand, check_overlap = False)

                # This is a bug fix. Ben 12/2/14
                # for a circular strand we need to terminate the strand one element early (so reduce the length
                # of the range by 1), since the final element is just a repeat of the first one.
                if joined_strand._circular:
                    joining_range = range(len(join) - 2)
                else:
                    joining_range = range(len(join) - 1)
                # add joined strands to v2n index
                for k in joining_range:
                    vh_vb2nuc_final.add_strand(join[k], vh_vb2nuc, continue_join = True)
                vh_vb2nuc_final.add_strand(join[k + 1], vh_vb2nuc, continue_join = False)
                    
                if single_strand_system == 1:
                    final_sys._strands[0].set_sequence(sequences[0])
    
            if nupack:
                per_strand_nucleotide_counter = 0
                found_staple = False
                for k in range(len(join)):
                    record_joined.append(join[k])
                    nucleotide_counter = 0
                    for (vhelix,vbase), [scaf_index, scaf_nucleotide] in vhelix_to_scaffold.iteritems():
                        if scaf_index == join[k]:
                            vhelix_to_scaffold_final[(vhelix, vbase)] = [0, scaf_nucleotide + per_strand_nucleotide_counter]
                            nucleotide_counter += 1

                    for (staple_index, staple_nucleotide), [vhelix, vbase] in staple_to_vhelix.iteritems():
                        if staple_index == join[k]:
                            staple_to_vhelix_final[(len(staple_to_scaffold), staple_nucleotide + per_strand_nucleotide_counter)] = [vhelix, vbase]
                            nucleotide_counter += 1
                            found_staple = True

                    per_strand_nucleotide_counter += nucleotide_counter
                    if k == len(join) - 1 and found_staple:
                        staple_to_scaffold.append(range(per_strand_nucleotide_counter))
                        for staple_nucleotide in staple_to_scaffold[-1]:
                            staple_nucleotide = -1

    if sequence_file and single_strand_system:
        if len(final_sys._strands) > 1:
            base.Logger.log("more than one strand detected - sequence file will not be read", base.Logger.WARNING)
            final_sys._strands[0].set_sequence(np.random.randint(0, 4, len(final_sys._strands[0]._nucleotides))) # this line does not work

    ## Fix to reverse the direction of every strand so that the 3' to 5' direction is the same
    ## as in Cadnano. In cadnano the strands point in the 5' to 3' direction, whereas in oxDNA
    ## they point in the 3' to 5' direction. Ben 29/11/13
    rev_sys = base.System(final_sys._box)
    for strand in final_sys._strands:
        reverse_nucs = [nuc for nuc in strand._nucleotides]
        reverse_nucs.reverse()
        rev_strand = base.Strand()
        for nuc in reverse_nucs:
            rev_strand.add_nucleotide(base.Nucleotide(nuc.cm_pos, nuc._a1, -nuc._a3, nuc._base, nuc._btype))
        if strand._circular:
            rev_strand.make_circular(check_join_len=True)
        rev_sys.add_strand(rev_strand, check_overlap = False)
    ## also reverse the vhelix_vbase_to_nucleotide order so it corresponds to the reversed system
    vh_vb2nuc_rev = oru.vhelix_vbase_to_nucleotide()
    # count up the number of nucleotides up to but not including the nucleotides in strand ii
    nnucs_to_here = range(rev_sys._N_strands)
    nuc_total = 0
    for strandii, strand in enumerate(rev_sys._strands):
        nnucs_to_here[strandii] = nuc_total
        nuc_total += len(strand._nucleotides)

    # fill in the _scaf and _stap dicts for the reverse vhelix_vbase_to_nucleotide object
    for vh, vb in vh_vb2nuc_final._scaf.keys():
        strandii, nuciis = vh_vb2nuc_final._scaf[(vh, vb)]
        rev_nuciis = []
        for nucii in nuciis:
            rev_nuciis.append(len(rev_sys._strands[strandii]._nucleotides) - 1 - (nucii - nnucs_to_here[strandii]) + nnucs_to_here[strandii])
        vh_vb2nuc_rev.add_scaf(vh, vb, strandii, rev_nuciis)
    for vh, vb in vh_vb2nuc_final._stap.keys():
        strandii, nuciis = vh_vb2nuc_final._stap[(vh, vb)]
        rev_nuciis = []
        for nucii in nuciis:
            rev_nuciis.append(len(rev_sys._strands[strandii]._nucleotides) - 1 - (nucii - nnucs_to_here[strandii]) + nnucs_to_here[strandii])
        vh_vb2nuc_rev.add_stap(vh, vb, strandii, rev_nuciis)

    # dump spatial arrangement of vhelices to a file
    vhelix_pattern = {}
    for i in range(len(cadsys.vhelices)):
        vhelix_pattern[cadsys.vhelices[i].num] = (cadsys.vhelices[i].row,cadsys.vhelices[i].col)

    fout = open("virt2nuc", "w")
    pickle.dump((vh_vb2nuc_rev, vhelix_pattern), fout)
    #pickle.dump((vh_vb2nuc_final, vhelix_pattern), fout)
    fout.close()

    base.Logger.log("printed index file virt2nuc", base.Logger.INFO)
    
    if nupack == 0:
        #final_sys.print_lorenzo_output ("prova.conf", "prova.top")
        rev_sys.print_lorenzo_output ("prova.conf", "prova.top")
        base.Logger.log("printed lorenzo output files prova.conf, prova.top", base.Logger.INFO)
    else:
        # check for unjoined strands
        if len(vhelix_to_scaffold_final) == 0:
            vhelix_to_scaffold_final = vhelix_to_scaffold

        # get a list of staple indices
        staple_indices = []
        for (staple_index, staple_nucleotide) in staple_to_vhelix.keys():
            if staple_index not in staple_indices:
                staple_indices.append(staple_index)
        for recorded_staple_index in staple_indices:
            if recorded_staple_index not in record_joined:
                nucleotide_counter = 0
                for (staple_index, staple_nucleotide), [vhelix, vbase] in staple_to_vhelix.iteritems():
                    if staple_index == recorded_staple_index:
                        staple_to_vhelix_final[(len(staple_to_scaffold), staple_nucleotide)] = [vhelix, vbase]
                        nucleotide_counter += 1
                staple_to_scaffold.append(range(nucleotide_counter))
                for staple_nucleotide in staple_to_scaffold[-1]:
                    staple_nucleotide = -1


        for key in staple_to_vhelix_final:
            staple, staple_nucleotide = key
            [vhelix, vbase] = staple_to_vhelix_final[key]
            [partner_scaf_index, partner_scaf_nucleotide] = vhelix_to_scaffold_final[(vhelix,vbase)]
            staple_to_scaffold[staple][staple_nucleotide] = partner_scaf_nucleotide

        base.Logger.log("dumping staple to scaffold pattern to output.sts", base.Logger.INFO)
        fout = open("output.sts", "w")
        pickle.dump(staple_to_scaffold, fout)
        fout.close()