Esempio n. 1
0
def generate_vhelices_origami_he(vhelix_direction, vhelix_perp, h,
                                 sequence_file, single_strand_system,
                                 vhelix_counter):
    g = cu.StrandGenerator()
    # generate helix angles
    helix_angles = np.zeros(h.len - 1, dtype=float)

    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
    total_sum = 0
    for i in range(20):
        total_sum += helix_angles[i]

    for i in range(len(helix_angles)):
        if i % 21 == 20:
            helix_angles[i] = 720. * np.pi / 180 - total_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
        ])
        direction = vhelix_direction
        perp = vhelix_perp
        rot = 0.
        strands = g.generate_or_sq(h.len,
                                   start_pos=pos,
                                   direction=direction,
                                   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
        ])
        direction = -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,
                                   direction=direction,
                                   perp=perp,
                                   double=True,
                                   rot=rot,
                                   angle=angles)

    return (strands[0], strands[1]), helix_angles, pos, rot, direction, perp
Esempio n. 2
0
def generate_vhelices_origami_sq(vhelix_direction, vhelix_perp, h,
                                 sequence_file, single_strand_system,
                                 vhelix_counter):
    g = cu.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
    total_sum = 0
    for i in range(31):
        total_sum += helix_angles[i]

    for i in range(len(helix_angles)):
        if i % 32 == 31:
            helix_angles[i] = 1080 * np.pi / 180 - total_sum

    # make the virtual helices
    if h.num % 2 == 0:
        pos = np.array([h.col * DIST_SQUARE, h.row * DIST_SQUARE, 0])
        direction = vhelix_direction
        perp = vhelix_perp
        rot = 0.
        angles = helix_angles
        strands = g.generate_or_sq(h.len,
                                   start_pos=pos,
                                   direction=direction,
                                   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
        ])
        direction = -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,
                                   direction=direction,
                                   perp=perp,
                                   double=True,
                                   rot=rot,
                                   angle=angles)

    return (strands[0], strands[1]), helix_angles, pos, rot, direction, perp
Esempio n. 3
0
def insert_loop_skip(strands, start_pos, direction, 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 = cu.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 _ 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,
                                   direction=direction,
                                   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
Esempio n. 4
0
def rpoly_to_oxDNA(opts):
    # Read File
    # 'data' stores helix coordinates + rotaion in quaternion
    data = []

    rev_helix_connections = []  # staple connection information,
    fwd_helix_connections = []  # scaffold connections
    count = 0
    polyFile = open(opts.file_name_in, 'r')

    try:
        for line in polyFile:
            if line.startswith('hb'):
                data.insert(count, line.split(' '))
                count += 1
            elif line.startswith('c'):
                if 'f3' not in line:
                    rev_helix_connections.append([
                        int(re.search('c helix_(.+?) ', line).group(1)),
                        int(re.search('\' helix_(.+?) ', line).group(1))
                    ])  # Extract connection information
                else:
                    fwd_helix_connections.append([
                        int(re.search('c helix_(.+?) ', line).group(1)),
                        int(re.search('\' helix_(.+?) ', line).group(1))
                    ])
    except Exception:
        print('Failed to read the file')

    generator = cu.StrandGenerator()

    staple_fragments = base.System(
        [100, 100, 100]
    )  # temporary system to store staple fragments before later connecting them
    scaffold_fragments = base.System([100, 100, 100])

    # Reads orientation from the "data" and produces rotations from the Quaternian coordinates
    largest_size = 0.0
    for n, i in enumerate(data):

        position = [
            float(i[3]) / 0.84,
            float(i[4]) / 0.84,
            float(i[5]) / 0.84
        ]  # 0.84 scaling is ad hoc solution to get good looking models

        n_bp = int(i[2])

        q = Quaternion(w=float(i[9]),
                       x=float(i[6]),
                       y=float(i[7]),
                       z=float(i[8]))  # find the helix roation Info from file
        vec = q.rotate(np.array([0.0, 0.0,
                                 1.0]))  # use it to figure out direction
        vec2 = q.rotate(
            [0.65, -0.76,
             0.0])  # ad hoc onversion between rpoly rotation and cadnano utils

        new_position = move_along_vector(
            position, vec, n_bp
        )  # rpoly helix coordinates are defined in center of helix, cadnano utils have positions in the base of helix.

        for j in new_position:  # go through every coordinate to find the largest coordinate to figure out box size
            if j > largest_size:
                largest_size = j
            else:
                pass

        # strand 0 is the scaffold and strand 1 is the staple
        new_strands = generator.generate_or_sq(bp=n_bp,
                                               start_pos=new_position,
                                               direction=vec,
                                               perp=vec2)

        fragment1, fragment2 = new_strands[1].cut_in_two(
        )  # cut strand 1 into two equal lengh staple fragments for later connections

        # store the fragments in this system for later connections
        staple_fragments.add_strand(fragment1)
        staple_fragments.add_strand(fragment2)

        scaffold_fragments.add_strand(new_strands[0])

    output_system = base.System(
        [largest_size * 3.0, largest_size * 3.0, largest_size * 3.0])
    for n in rev_helix_connections:  # iterate through staple strand connections and connect the previously generated fragments
        connect_from = n[0] * 2 - 1
        connect_to = n[1] * 2 - 2
        staple_strand = staple_fragments._strands[connect_from].copy()

        staple_strand = staple_strand.append(
            staple_fragments._strands[connect_to].copy())

        output_system.add_strand(staple_strand)

    scaffold_strand = scaffold_fragments._strands[0].copy()
    for n in fwd_helix_connections[:-1]:
        next_segment_adress = n[1] - 1
        next_segment = scaffold_fragments._strands[next_segment_adress].copy()
        scaffold_strand = scaffold_strand.append(next_segment)

    scaffold_strand.make_circular()
    output_system.add_strand(scaffold_strand)

    basename = os.path.basename(opts.file_name_in)
    top_file = basename + ".top"
    conf_file = basename + ".oxdna"

    output_system.print_lorenzo_output(conf_file, top_file)