def generate_vhelices_origami_he(vhelix_direction, vhelix_perp, h, sequence_file, single_strand_system, vhelix_counter):
    g = gen.StrandGenerator()
    # 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
        if modi == 0:
            helix_angles[i] = 32.571 * np.pi/180
        elif modi == 1:
            helix_angles[i] = 36 * np.pi/180
        elif modi in (1,2,3):
            helix_angles[i] = 42 * np.pi/180
        elif modi in (5,6,7):
            helix_angles[i] = 29.143 * np.pi/180
        elif modi == 8:
            helix_angles[i] = 32 * np.pi/180
        elif modi in (9,10):
            helix_angles[i] = 44 * np.pi/180
        elif modi in (12,13,14):
            helix_angles[i] = 28.571 * np.pi/180
        elif modi in (16,17):
            helix_angles[i] = 41.5 * np.pi/180
        elif modi in (19,20):
            helix_angles[i] = 28.476 * np.pi/180
        else:
            helix_angles[i] = 720./21 * (np.pi/180.) 

    # make sure it's periodic
    sum = 0
    for i in range(20):
        sum += helix_angles[i]

    for i in range(len(helix_angles)):
        if i % 21 == 20:
            helix_angles[i] = 720. * np.pi/180 - sum

    # make the virtual helices
    if h.num % 2 == 0:
        pos = np.array([h.col * np.sqrt(3)*DIST_HEXAGONAL/2, h.row * 3*DIST_HEXAGONAL/2, 0])
        dir = vhelix_direction
        perp = vhelix_perp
        rot = 0.
        strands = g.generate_or_sq(h.len, start_pos=pos, dir=dir, perp=perp, double=True, rot=rot, angle = helix_angles)

    else:
        pos = np.array([h.col * np.sqrt(3)*DIST_HEXAGONAL/2, h.row * 3*DIST_HEXAGONAL/2 + DIST_HEXAGONAL/2, (h.len-1)*base.BASE_BASE])
        dir = -vhelix_direction
        perp = -vhelix_perp
        if base.MM_GROOVING:
            rot = -np.sum(helix_angles) % (2*np.pi) - 0.07
        else:
            rot = -np.sum(helix_angles) % (2*np.pi)
        angles = np.flipud(helix_angles)
        strands = g.generate_or_sq(h.len, start_pos=pos, dir=dir, perp=perp, double=True, rot=rot, angle=angles)

    return (strands[0], strands[1]), helix_angles, pos, rot, dir, perp
예제 #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")
예제 #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")
예제 #4
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")
예제 #5
0
            ret.num = map(int, re.findall(r'(\d+)', line))[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)):
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()
def insert_loop_skip(strands, start_pos, dir, perp, rot, helix_angles, vhelix, nodes, use_seq, seqs):
    # return a double strand which is a copy of the double strand in the first argument, but with skips and loops

    # strand is generated right to left i.e. opposite direction to even vhelix
    g = gen.StrandGenerator()
    length_change = []
    length_change_total = 0
    new_nodes = vh_nodes()
    new_angle = []
    helix_angles_new = np.array(range(len(helix_angles)), dtype = float)
    for i in range(len(helix_angles)):
        helix_angles_new[i] = helix_angles[i]

    if vhelix.num % 2 == 1:
        reverse_nodes = vh_nodes()
        for i in range(len(nodes.begin)):
            reverse_nodes.add_begin(nodes.begin[i])
            reverse_nodes.add_end(nodes.end[i])
        reverse_nodes.begin.reverse()
        reverse_nodes.end.reverse()

    for i in range(len(nodes.begin)):
        # ltr: left to right; looking at the strand left to right (low to high square index), the beginning/end of the effective strand is here (before skips/loops)
        # gs: generated strand; the index of the nucleotide (BEFORE skips/loops are applied) on the generated strand corresponding to the beginning/end of the effective strand
        if vhelix.num % 2 == 0:
            begin_ltr = nodes.begin[i]
            end_ltr = nodes.end[i]
            begin_gs =  nodes.begin[i]
            end_gs = nodes.end[i]
        else:
            begin_ltr = reverse_nodes.end[i]
            end_ltr = reverse_nodes.begin[i]
            begin_gs = vhelix.len - reverse_nodes.begin[i] - 1
            end_gs = vhelix.len - reverse_nodes.end[i] - 1

        # check for zero length effective strand
        if end_gs - begin_gs != 0:
            # get length change for this effective strand
            length_change.append(0)
            for j in vhelix.skip[begin_ltr:end_ltr+1]:
                length_change[i] -= int(j)
            for j in vhelix.loop[begin_ltr:end_ltr+1]:
                length_change[i] += int(j)
            # get new pitch angles for this effective strand
            new_angle.append(sum(helix_angles[begin_gs:end_gs]) / (end_gs - begin_gs + length_change[i]))
            helix_angles_new[begin_gs:end_gs] = new_angle[i]
            # adjust beginning/end indices according to length change
            begin_gs += length_change_total
            end_gs += length_change_total + length_change[i]
            new_nodes.add_begin(begin_gs)
            new_nodes.add_end(end_gs) # begin_gs > end_gs.....
        else:
            length_change.append(0)
            new_angle.append(sum(helix_angles)/len(helix_angles)) # append an average angle
            new_nodes.add_begin(begin_gs)
            new_nodes.add_end(end_gs)
        length_change_total += length_change[i]

    # adjust the new helix angle array according to skips/loops
    deleted = 0
    inserted = 0
    deleted_this_iteration = 0
    inserted_this_iteration = 0
    for i in range(len(nodes.begin)):
        deleted += deleted_this_iteration
        inserted += inserted_this_iteration
        deleted_this_iteration = 0
        inserted_this_iteration = 0
        if vhelix.num % 2 == 0:
            begin_ltr = nodes.begin[i]
            end_ltr = nodes.end[i]
            begin_gs =  nodes.begin[i]
            end_gs = nodes.end[i]
        else:
            begin_ltr = reverse_nodes.end[i]
            end_ltr = reverse_nodes.begin[i]
            begin_gs = vhelix.len - reverse_nodes.begin[i] - 1
            end_gs = vhelix.len - reverse_nodes.end[i] - 1
        for j in vhelix.skip[begin_ltr:end_ltr+1]:
            if j == 1:
                helix_angles_new = np.delete(helix_angles_new, begin_gs - deleted + inserted)
                deleted_this_iteration += 1
        for j in vhelix.loop[begin_ltr:end_ltr+1]:
            for k in range(j):
                helix_angles_new = np.insert(helix_angles_new, begin_gs - deleted + inserted, new_angle[i])
                inserted_this_iteration += 1

    new_strands = g.generate_or_sq(len(helix_angles_new)+1, start_pos=start_pos, dir=dir, perp=perp, double=True, rot=rot, angle = helix_angles_new, length_change=length_change, region_begin = new_nodes.begin, region_end = new_nodes.end)
    if use_seq:
        try:
            sequence = [x for x in seqs[vhelix.cad_index]]
        except IndexError:
            base.Logger.die("sequence file contains too few rows compared to the number of virtual helices in the cadnano file, dying")
        if vhelix.num % 2 == 1:
            sequence.reverse()
        if new_strands[0].get_length() != len(sequence):
            base.Logger.log("Cannot change sequence: lengths don't match; virtual helix %s, sequence length %s, virtual helix length %s - are skips/loops accounted for?" % (vhelix.num, len(sequence), new_strands[0].get_length()), base.Logger.WARNING)
        else:
            new_strands[0].set_sequence(sequence)
        sequence2 = [3-s for s in sequence]
        sequence2.reverse()
        if new_strands[0].get_length() != len(sequence):
            base.Logger.log("Cannot change sequence: lengths don't match; virtual helix %s, sequence length %s, virtual helix length %s - are skips/loops accounted for?" % (vhelix.num, len(sequence), new_strands[0].get_length()), base.Logger.WARNING)
        else:
            new_strands[1].set_sequence(sequence2)

    return new_strands
def generate_vhelices_origami_sq(vhelix_direction, vhelix_perp, h, sequence_file, single_strand_system, vhelix_counter):
    g = gen.StrandGenerator()
    # generate helix angles
    helix_angles = np.zeros(h.len-1, dtype=float)
    # hard upper limit on pitch angle seems to be between 54.5 and 55 degrees
    for i in range(len(helix_angles)):
        modi = i %32
        if modi < 2:
            helix_angles[i] = 28 * np.pi/180
        elif modi == 2:
            helix_angles[i] = 36 * np.pi/180
        elif modi == 3:
            helix_angles[i] = 54.375 * np.pi/180
        elif modi == 4:
            helix_angles[i] = 37 * np.pi/180
        elif modi in (5,6):
            helix_angles[i] = 27.6666666666666 * np.pi/180
        elif modi == 7:
            helix_angles[i] = 30.6666666666666 * np.pi/180
        elif modi in (8,9):
            helix_angles[i] = 29.3333333333 * np.pi/180
        elif modi == 10:
            helix_angles[i] = 34.3333333333 * np.pi/180
        elif modi == 11:
            helix_angles[i] = 54.5 * np.pi/180
        elif modi in (12,13):
            helix_angles[i] = (28.91666666666 * np.pi/180)# + 0.25) * np.pi/180
        elif modi in (14,15,16,17):
            helix_angles[i] = 31.16666666666 * np.pi/180
        elif modi == 18:
            helix_angles[i] = 35.5 * np.pi/180
        elif modi == 19:
            helix_angles[i] = 52 * np.pi/180
        elif modi == 20:
            helix_angles[i] = 35.5 * np.pi/180
        elif modi in (21,22):
            helix_angles[i] = 27.5 * np.pi/180
        elif modi == 23:
            helix_angles[i] = 35.5 * np.pi/180
        elif modi >= 24 and modi < 27:
            helix_angles[i] = 30 * np.pi/180
        elif modi == 27:
            helix_angles[i] = 52 * np.pi/180
        elif modi == 28:
            helix_angles[i] = 35.5 * np.pi/180
        else:
            helix_angles[i] = 30.91666666666 * (np.pi/180)

    # make sure the helices are periodic in 32 bases
    sum = 0
    for i in range(31):
        sum += helix_angles[i]

    for i in range(len(helix_angles)):
        if i % 32 == 31:
            helix_angles[i] = 1080 * np.pi/180 - sum
            
    # make the virtual helices
    if h.num % 2 == 0:
        pos = np.array([h.col * DIST_SQUARE, h.row * DIST_SQUARE, 0])
        dir = vhelix_direction
        perp = vhelix_perp
        rot = 0.
        angles = helix_angles
        strands = g.generate_or_sq(h.len, start_pos=pos, dir=dir, perp=perp, double=True, rot=rot, angle = angles)

    else:
        pos = np.array([h.col * DIST_SQUARE, h.row * DIST_SQUARE, (h.len-1)*base.BASE_BASE])
        dir = -vhelix_direction
        perp = -vhelix_perp
        rot = -np.sum(helix_angles) % (2*np.pi)
        angles = np.flipud(helix_angles)
        strands = g.generate_or_sq(h.len, start_pos=pos, dir=dir, perp=perp, double=True, rot=rot, angle = angles)

    return (strands[0], strands[1]), helix_angles, pos, rot, dir, perp