From abd50b7bb0f1d04ea3cc322048ab5b5cecf03de7 Mon Sep 17 00:00:00 2001 From: David Doty Date: Wed, 3 Jun 2020 17:51:11 -0700 Subject: [PATCH 1/3] updated data model so pitch, roll, yaw are no longer in Helix.position, but are direct fields of Helix --- ...ple_1_helix_origami_position_nondefault.py | 4 +- examples/24_helix_rectangle.dna | 3 +- examples/4_helix_grid_none.py | 8 +- ...elix_origami_barrel_from_algoSST_paper.dna | 2 +- .../16_helix_origami_rectangle.dna | 2 +- .../16_helix_origami_rectangle_idt.dna | 2 +- .../16_helix_origami_rectangle_no_seq.dna | 2 +- ...elix_origami_rectangle_no_seq_no_twist.dna | 2 +- .../16_helix_origami_rectangle_no_twist.dna | 2 +- ...ami_rectangle_seed_tiles_grow_from_top.dna | 2 +- ..._origami_rectangle_shifted_seam_no_seq.dna | 2 +- .../1_staple_1_helix_origami.dna | 2 +- .../1_staple_1_helix_origami_mismatches.dna | 2 +- ...le_1_helix_origami_position_nondefault.dna | 4 +- .../1_staple_1_helix_origami_rotation.dna | 2 +- ...elix_origami_rectangle_twist_corrected.dna | 2 +- ...x_2_strands_multiple_substrands_no_seq.dna | 2 +- .../2_staple_2_helix_modifications.dna | 42 ++++----- .../2_staple_2_helix_origami_6bases_wide.dna | 2 +- .../2_staple_2_helix_origami_deletions.dna | 2 +- ...e_2_helix_origami_deletions_insertions.dna | 2 +- ...elix_origami_deletions_insertions_mods.dna | 2 +- ...ix_origami_deletions_insertions_no_seq.dna | 2 +- .../3_helix_deletions_insertions.dna | 2 +- examples/output_designs/4_helix_grid_none.dna | 11 ++- .../56_helix_origami_rectangle.dna | 2 +- .../64_helix_origami_rectangle.dna | 2 +- .../6_helix_6_col_origami_rectangle.dna | 2 +- .../6_helix_bundle_honeycomb.dna | 2 +- .../6_helix_origami_rectangle.dna | 2 +- ...origami_rectangle_helices_out_of_order.dna | 2 +- .../add_deletions_to_24_helix_rectangle.dna | 4 +- examples/output_designs/empty.dna | 2 +- examples/output_designs/hairpin.dna | 2 +- .../helices_out_of_order_nonconsecutive.dna | 3 +- examples/output_designs/hex_lattice_10x10.dna | 2 +- .../hex_lattice_10x10_with_negative.dna | 2 +- .../honeycomb_lattice_10x10.dna | 2 +- .../honeycomb_lattice_10x10_with_negative.dna | 2 +- .../output_designs/idt-plates-explicit.dna | 2 +- .../output_designs/long_range_crossovers.dna | 2 +- .../output_designs/loopouts_all_types.dna | 2 +- examples/output_designs/many_big_helices.dna | 2 +- .../many_helices_modifications.dna | 26 +++--- examples/output_designs/proposal.dna | 35 +++---- examples/output_designs/sst-motif-3_2.dna | 2 +- examples/output_designs/sst-motif-4_1.dna | 2 +- scadnano/scadnano.py | 93 ++++++++++--------- tests/scadnano_tests.py | 21 +++-- 49 files changed, 176 insertions(+), 152 deletions(-) diff --git a/examples/1_staple_1_helix_origami_position_nondefault.py b/examples/1_staple_1_helix_origami_position_nondefault.py index adb55cb3..721cc572 100644 --- a/examples/1_staple_1_helix_origami_position_nondefault.py +++ b/examples/1_staple_1_helix_origami_position_nondefault.py @@ -1,9 +1,10 @@ import scadnano as sc + def main(): length = 9 helices = [ - sc.Helix(max_offset=length, major_ticks=[2, 5], position3d=sc.Position3D(x=3, y=2, z=1, pitch=90))] + sc.Helix(max_offset=length, major_ticks=[2, 5], position3d=sc.Position3D(x=3, y=2, z=1), pitch=90)] stap_ss = sc.Domain(0, sc.forward, 0, length) scaf_ss = sc.Domain(0, sc.reverse, 0, length) stap = sc.Strand([stap_ss]) @@ -14,6 +15,7 @@ def main(): return design + if not sc.in_browser() and __name__ == '__main__': design = main() design.write_scadnano_file(directory='output_designs') diff --git a/examples/24_helix_rectangle.dna b/examples/24_helix_rectangle.dna index 7eb88a55..12d2acc3 100644 --- a/examples/24_helix_rectangle.dna +++ b/examples/24_helix_rectangle.dna @@ -1,5 +1,6 @@ { - "version": "0.1.0", + "version": "0.7.0", + "grid": "square", "helices": [ {"grid_position": [0, -3], "max_offset": 304}, {"grid_position": [0, -2], "max_offset": 304}, diff --git a/examples/4_helix_grid_none.py b/examples/4_helix_grid_none.py index d22e0d39..e348e6c6 100644 --- a/examples/4_helix_grid_none.py +++ b/examples/4_helix_grid_none.py @@ -4,10 +4,10 @@ def main(): length = 10 helices = [ - sc.Helix(max_offset=length, position3d=(sc.Position3D(x=0, y=0, z=0, pitch=0, roll=0, yaw=0))), - sc.Helix(max_offset=length, position3d=(sc.Position3D(x=3, y=3, z=0, pitch=0, roll=0, yaw=0))), - sc.Helix(max_offset=length, position3d=(sc.Position3D(x=8, y=-3, z=0, pitch=0, roll=0, yaw=0))), - sc.Helix(max_offset=length, position3d=(sc.Position3D(x=11, y=1, z=0, pitch=0, roll=0, yaw=0))), + sc.Helix(max_offset=length, position3d=sc.Position3D(x=0, y=0, z=0), pitch=0, roll=0, yaw=0), + sc.Helix(max_offset=length, position3d=sc.Position3D(x=3, y=3, z=0), pitch=0, roll=0, yaw=0), + sc.Helix(max_offset=length, position3d=sc.Position3D(x=8, y=-3, z=0), pitch=0, roll=0, yaw=0), + sc.Helix(max_offset=length, position3d=sc.Position3D(x=11, y=1, z=0), pitch=0, roll=0, yaw=0), ] stap_ss = sc.Domain(0, sc.forward, 0, length) scaf_ss = sc.Domain(0, sc.reverse, 0, length) diff --git a/examples/output_designs/16_helix_origami_barrel_from_algoSST_paper.dna b/examples/output_designs/16_helix_origami_barrel_from_algoSST_paper.dna index a1274777..91ca1732 100644 --- a/examples/output_designs/16_helix_origami_barrel_from_algoSST_paper.dna +++ b/examples/output_designs/16_helix_origami_barrel_from_algoSST_paper.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 512, "grid_position": [0, 0], "major_ticks": [11, 22, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, 240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344, 352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, 440, 448, 456, 464, 472, 480, 490, 501]}, diff --git a/examples/output_designs/16_helix_origami_rectangle.dna b/examples/output_designs/16_helix_origami_rectangle.dna index 688fd457..07b80469 100644 --- a/examples/output_designs/16_helix_origami_rectangle.dna +++ b/examples/output_designs/16_helix_origami_rectangle.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 448, "grid_position": [0, 0]}, diff --git a/examples/output_designs/16_helix_origami_rectangle_idt.dna b/examples/output_designs/16_helix_origami_rectangle_idt.dna index 260dc6f1..62491357 100644 --- a/examples/output_designs/16_helix_origami_rectangle_idt.dna +++ b/examples/output_designs/16_helix_origami_rectangle_idt.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 448, "grid_position": [0, 0]}, diff --git a/examples/output_designs/16_helix_origami_rectangle_no_seq.dna b/examples/output_designs/16_helix_origami_rectangle_no_seq.dna index 825dd3cb..3898ae55 100644 --- a/examples/output_designs/16_helix_origami_rectangle_no_seq.dna +++ b/examples/output_designs/16_helix_origami_rectangle_no_seq.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 448, "grid_position": [0, 0]}, diff --git a/examples/output_designs/16_helix_origami_rectangle_no_seq_no_twist.dna b/examples/output_designs/16_helix_origami_rectangle_no_seq_no_twist.dna index f62796d0..ed90f672 100644 --- a/examples/output_designs/16_helix_origami_rectangle_no_seq_no_twist.dna +++ b/examples/output_designs/16_helix_origami_rectangle_no_seq_no_twist.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 448, "grid_position": [0, 0]}, diff --git a/examples/output_designs/16_helix_origami_rectangle_no_twist.dna b/examples/output_designs/16_helix_origami_rectangle_no_twist.dna index 64c61946..b1ed408e 100644 --- a/examples/output_designs/16_helix_origami_rectangle_no_twist.dna +++ b/examples/output_designs/16_helix_origami_rectangle_no_twist.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 448, "grid_position": [0, 0]}, diff --git a/examples/output_designs/16_helix_origami_rectangle_seed_tiles_grow_from_top.dna b/examples/output_designs/16_helix_origami_rectangle_seed_tiles_grow_from_top.dna index 9834c9b2..1bfbae30 100644 --- a/examples/output_designs/16_helix_origami_rectangle_seed_tiles_grow_from_top.dna +++ b/examples/output_designs/16_helix_origami_rectangle_seed_tiles_grow_from_top.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 512, "grid_position": [0, 0], "major_ticks": [11, 22, 32, 40, 48, 58, 69, 79, 90, 100, 111, 121, 132, 142, 153, 163, 174, 184, 195, 205, 216, 226, 237, 247, 258, 268, 279, 289, 300, 310, 321, 331, 342, 352, 363, 373, 384, 394, 405, 415, 426, 436, 447, 457, 468, 478]}, diff --git a/examples/output_designs/16_helix_origami_rectangle_shifted_seam_no_seq.dna b/examples/output_designs/16_helix_origami_rectangle_shifted_seam_no_seq.dna index 8b0cac0c..1ca1d9a1 100644 --- a/examples/output_designs/16_helix_origami_rectangle_shifted_seam_no_seq.dna +++ b/examples/output_designs/16_helix_origami_rectangle_shifted_seam_no_seq.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 448, "grid_position": [0, 0]}, diff --git a/examples/output_designs/1_staple_1_helix_origami.dna b/examples/output_designs/1_staple_1_helix_origami.dna index 5c4b1449..5462f4b3 100644 --- a/examples/output_designs/1_staple_1_helix_origami.dna +++ b/examples/output_designs/1_staple_1_helix_origami.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0], "major_ticks": [2, 5]} diff --git a/examples/output_designs/1_staple_1_helix_origami_mismatches.dna b/examples/output_designs/1_staple_1_helix_origami_mismatches.dna index 3bba6e03..d099187d 100644 --- a/examples/output_designs/1_staple_1_helix_origami_mismatches.dna +++ b/examples/output_designs/1_staple_1_helix_origami_mismatches.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]} diff --git a/examples/output_designs/1_staple_1_helix_origami_position_nondefault.dna b/examples/output_designs/1_staple_1_helix_origami_position_nondefault.dna index 98045b16..3e6ebbd2 100644 --- a/examples/output_designs/1_staple_1_helix_origami_position_nondefault.dna +++ b/examples/output_designs/1_staple_1_helix_origami_position_nondefault.dna @@ -1,8 +1,8 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ - {"position": {"x": 3, "y": 2, "z": 1, "pitch": 90, "roll": 0, "yaw": 0}, "major_ticks": [2, 5]} + {"position": {"x": 3, "y": 2, "z": 1}, "pitch": 90, "major_ticks": [2, 5]} ], "strands": [ { diff --git a/examples/output_designs/1_staple_1_helix_origami_rotation.dna b/examples/output_designs/1_staple_1_helix_origami_rotation.dna index 0442ca48..4a76319d 100644 --- a/examples/output_designs/1_staple_1_helix_origami_rotation.dna +++ b/examples/output_designs/1_staple_1_helix_origami_rotation.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0], "rotation": 1.5707963267948966, "rotation_anchor": 2} diff --git a/examples/output_designs/24_helix_origami_rectangle_twist_corrected.dna b/examples/output_designs/24_helix_origami_rectangle_twist_corrected.dna index 13d17128..ef3aeff7 100644 --- a/examples/output_designs/24_helix_origami_rectangle_twist_corrected.dna +++ b/examples/output_designs/24_helix_origami_rectangle_twist_corrected.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 304, "grid_position": [0, 0]}, diff --git a/examples/output_designs/2_helix_2_strands_multiple_substrands_no_seq.dna b/examples/output_designs/2_helix_2_strands_multiple_substrands_no_seq.dna index 863264fe..322cbe67 100644 --- a/examples/output_designs/2_helix_2_strands_multiple_substrands_no_seq.dna +++ b/examples/output_designs/2_helix_2_strands_multiple_substrands_no_seq.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]}, diff --git a/examples/output_designs/2_staple_2_helix_modifications.dna b/examples/output_designs/2_staple_2_helix_modifications.dna index d157613e..5ce36dd0 100644 --- a/examples/output_designs/2_staple_2_helix_modifications.dna +++ b/examples/output_designs/2_staple_2_helix_modifications.dna @@ -1,22 +1,22 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]}, {"grid_position": [0, 1]} ], "modifications_in_design": { - "/5Biosg/": { - "display_text": "B", - "idt_text": "/5Biosg/", + "/3Cy3Sp/": { + "display_text": "Cy3", + "idt_text": "/3Cy3Sp/", "display_connector": false, - "location": "5'" + "location": "3'" }, - "/5Cy5/": { - "display_text": "Cy5", - "idt_text": "/5Cy5/", + "/3Bio/": { + "display_text": "B", + "idt_text": "/3Bio/", "display_connector": false, - "location": "5'" + "location": "3'" }, "/iCy3/": { "display_text": "Cy3", @@ -24,6 +24,12 @@ "display_connector": false, "location": "internal" }, + "/iCy5/": { + "display_text": "Cy5", + "idt_text": "/iCy5/", + "display_connector": false, + "location": "internal" + }, "/iBiodT/": { "display_text": "B", "idt_text": "/iBiodT/", @@ -31,23 +37,17 @@ "location": "internal", "allowed_bases": ["T"] }, - "/iCy5/": { + "/5Cy5/": { "display_text": "Cy5", - "idt_text": "/iCy5/", + "idt_text": "/5Cy5/", "display_connector": false, - "location": "internal" + "location": "5'" }, - "/3Bio/": { + "/5Biosg/": { "display_text": "B", - "idt_text": "/3Bio/", - "display_connector": false, - "location": "3'" - }, - "/3Cy3Sp/": { - "display_text": "Cy3", - "idt_text": "/3Cy3Sp/", + "idt_text": "/5Biosg/", "display_connector": false, - "location": "3'" + "location": "5'" } }, "strands": [ diff --git a/examples/output_designs/2_staple_2_helix_origami_6bases_wide.dna b/examples/output_designs/2_staple_2_helix_origami_6bases_wide.dna index 9b09d229..a3692fdc 100644 --- a/examples/output_designs/2_staple_2_helix_origami_6bases_wide.dna +++ b/examples/output_designs/2_staple_2_helix_origami_6bases_wide.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]}, diff --git a/examples/output_designs/2_staple_2_helix_origami_deletions.dna b/examples/output_designs/2_staple_2_helix_origami_deletions.dna index 68698d6e..4d0ef22e 100644 --- a/examples/output_designs/2_staple_2_helix_origami_deletions.dna +++ b/examples/output_designs/2_staple_2_helix_origami_deletions.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]}, diff --git a/examples/output_designs/2_staple_2_helix_origami_deletions_insertions.dna b/examples/output_designs/2_staple_2_helix_origami_deletions_insertions.dna index 9a7a39ec..65eb4191 100644 --- a/examples/output_designs/2_staple_2_helix_origami_deletions_insertions.dna +++ b/examples/output_designs/2_staple_2_helix_origami_deletions_insertions.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 48, "grid_position": [0, 0]}, diff --git a/examples/output_designs/2_staple_2_helix_origami_deletions_insertions_mods.dna b/examples/output_designs/2_staple_2_helix_origami_deletions_insertions_mods.dna index 55459600..72959011 100644 --- a/examples/output_designs/2_staple_2_helix_origami_deletions_insertions_mods.dna +++ b/examples/output_designs/2_staple_2_helix_origami_deletions_insertions_mods.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 48, "grid_position": [0, 0]}, diff --git a/examples/output_designs/2_staple_2_helix_origami_deletions_insertions_no_seq.dna b/examples/output_designs/2_staple_2_helix_origami_deletions_insertions_no_seq.dna index 90e82b84..b7ba61ef 100644 --- a/examples/output_designs/2_staple_2_helix_origami_deletions_insertions_no_seq.dna +++ b/examples/output_designs/2_staple_2_helix_origami_deletions_insertions_no_seq.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]}, diff --git a/examples/output_designs/3_helix_deletions_insertions.dna b/examples/output_designs/3_helix_deletions_insertions.dna index 03f94d4d..68012cac 100644 --- a/examples/output_designs/3_helix_deletions_insertions.dna +++ b/examples/output_designs/3_helix_deletions_insertions.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 64, "grid_position": [0, 0]}, diff --git a/examples/output_designs/4_helix_grid_none.dna b/examples/output_designs/4_helix_grid_none.dna index dc3525e1..82d20b8a 100644 --- a/examples/output_designs/4_helix_grid_none.dna +++ b/examples/output_designs/4_helix_grid_none.dna @@ -1,10 +1,11 @@ { - "version": "0.7.0", + "version": "0.7.4", + "grid": "none", "helices": [ - {"position": {"x": 0, "y": 0, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 10, "position": {"x": 3, "y": 3, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 10, "position": {"x": 8, "y": -3, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 10, "position": {"x": 11, "y": 1, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}} + {"position": {"x": 0, "y": 0, "z": 0}}, + {"max_offset": 10, "position": {"x": 3, "y": 3, "z": 0}}, + {"max_offset": 10, "position": {"x": 8, "y": -3, "z": 0}}, + {"max_offset": 10, "position": {"x": 11, "y": 1, "z": 0}} ], "strands": [ { diff --git a/examples/output_designs/56_helix_origami_rectangle.dna b/examples/output_designs/56_helix_origami_rectangle.dna index 2f39bc84..682f7c55 100644 --- a/examples/output_designs/56_helix_origami_rectangle.dna +++ b/examples/output_designs/56_helix_origami_rectangle.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 160, "grid_position": [0, 0]}, diff --git a/examples/output_designs/64_helix_origami_rectangle.dna b/examples/output_designs/64_helix_origami_rectangle.dna index d26c8848..0ff2690e 100644 --- a/examples/output_designs/64_helix_origami_rectangle.dna +++ b/examples/output_designs/64_helix_origami_rectangle.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 128, "grid_position": [0, 0]}, diff --git a/examples/output_designs/6_helix_6_col_origami_rectangle.dna b/examples/output_designs/6_helix_6_col_origami_rectangle.dna index 81d39cc3..7a5e2225 100644 --- a/examples/output_designs/6_helix_6_col_origami_rectangle.dna +++ b/examples/output_designs/6_helix_6_col_origami_rectangle.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]}, diff --git a/examples/output_designs/6_helix_bundle_honeycomb.dna b/examples/output_designs/6_helix_bundle_honeycomb.dna index ca015909..b203016a 100644 --- a/examples/output_designs/6_helix_bundle_honeycomb.dna +++ b/examples/output_designs/6_helix_bundle_honeycomb.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "honeycomb", "helices": [ {"max_offset": 1295, "grid_position": [1, 1]}, diff --git a/examples/output_designs/6_helix_origami_rectangle.dna b/examples/output_designs/6_helix_origami_rectangle.dna index 53586717..2874e379 100644 --- a/examples/output_designs/6_helix_origami_rectangle.dna +++ b/examples/output_designs/6_helix_origami_rectangle.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 192, "grid_position": [0, 0]}, diff --git a/examples/output_designs/6_helix_origami_rectangle_helices_out_of_order.dna b/examples/output_designs/6_helix_origami_rectangle_helices_out_of_order.dna index 60ef920f..35463ee1 100644 --- a/examples/output_designs/6_helix_origami_rectangle_helices_out_of_order.dna +++ b/examples/output_designs/6_helix_origami_rectangle_helices_out_of_order.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 192, "grid_position": [0, 0]}, diff --git a/examples/output_designs/add_deletions_to_24_helix_rectangle.dna b/examples/output_designs/add_deletions_to_24_helix_rectangle.dna index 5cfc97d9..73fc5769 100644 --- a/examples/output_designs/add_deletions_to_24_helix_rectangle.dna +++ b/examples/output_designs/add_deletions_to_24_helix_rectangle.dna @@ -1,6 +1,6 @@ { - "version": "0.7.0", - "grid": "square", + "version": "0.7.4", + "grid": "e", "helices": [ {"max_offset": 304, "grid_position": [0, -3]}, {"max_offset": 304, "grid_position": [0, -2]}, diff --git a/examples/output_designs/empty.dna b/examples/output_designs/empty.dna index 7b0696e2..ae74dc6c 100644 --- a/examples/output_designs/empty.dna +++ b/examples/output_designs/empty.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [], "strands": [] diff --git a/examples/output_designs/hairpin.dna b/examples/output_designs/hairpin.dna index f37738af..81af4488 100644 --- a/examples/output_designs/hairpin.dna +++ b/examples/output_designs/hairpin.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]} diff --git a/examples/output_designs/helices_out_of_order_nonconsecutive.dna b/examples/output_designs/helices_out_of_order_nonconsecutive.dna index 2d936bbb..04514dcb 100644 --- a/examples/output_designs/helices_out_of_order_nonconsecutive.dna +++ b/examples/output_designs/helices_out_of_order_nonconsecutive.dna @@ -1,5 +1,6 @@ { - "version": "0.7.0", + "version": "0.7.4", + "grid": "none", "helices": [ {"max_offset": 20, "grid_position": [0, 2], "idx": 2}, {"max_offset": 20, "grid_position": [0, 3], "idx": 3}, diff --git a/examples/output_designs/hex_lattice_10x10.dna b/examples/output_designs/hex_lattice_10x10.dna index 1fc7f3f2..d591ed26 100644 --- a/examples/output_designs/hex_lattice_10x10.dna +++ b/examples/output_designs/hex_lattice_10x10.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "hex", "helices": [ {"max_offset": 16, "grid_position": [0, 0]}, diff --git a/examples/output_designs/hex_lattice_10x10_with_negative.dna b/examples/output_designs/hex_lattice_10x10_with_negative.dna index addbf47d..609ecc54 100644 --- a/examples/output_designs/hex_lattice_10x10_with_negative.dna +++ b/examples/output_designs/hex_lattice_10x10_with_negative.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "hex", "helices": [ {"max_offset": 16, "grid_position": [-4, -4]}, diff --git a/examples/output_designs/honeycomb_lattice_10x10.dna b/examples/output_designs/honeycomb_lattice_10x10.dna index 52d24476..e326db6b 100644 --- a/examples/output_designs/honeycomb_lattice_10x10.dna +++ b/examples/output_designs/honeycomb_lattice_10x10.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "honeycomb", "helices": [ {"max_offset": 16, "grid_position": [0, 0]}, diff --git a/examples/output_designs/honeycomb_lattice_10x10_with_negative.dna b/examples/output_designs/honeycomb_lattice_10x10_with_negative.dna index f4a94f02..9d4fcc89 100644 --- a/examples/output_designs/honeycomb_lattice_10x10_with_negative.dna +++ b/examples/output_designs/honeycomb_lattice_10x10_with_negative.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "honeycomb", "helices": [ {"max_offset": 16, "grid_position": [-4, -4]}, diff --git a/examples/output_designs/idt-plates-explicit.dna b/examples/output_designs/idt-plates-explicit.dna index cd9d69c8..6d1b3b78 100644 --- a/examples/output_designs/idt-plates-explicit.dna +++ b/examples/output_designs/idt-plates-explicit.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]}, diff --git a/examples/output_designs/long_range_crossovers.dna b/examples/output_designs/long_range_crossovers.dna index 5a757810..7b9f0903 100644 --- a/examples/output_designs/long_range_crossovers.dna +++ b/examples/output_designs/long_range_crossovers.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]}, diff --git a/examples/output_designs/loopouts_all_types.dna b/examples/output_designs/loopouts_all_types.dna index cbce5fd9..6c055c7e 100644 --- a/examples/output_designs/loopouts_all_types.dna +++ b/examples/output_designs/loopouts_all_types.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]}, diff --git a/examples/output_designs/many_big_helices.dna b/examples/output_designs/many_big_helices.dna index c4edfafa..dfbcaee3 100644 --- a/examples/output_designs/many_big_helices.dna +++ b/examples/output_designs/many_big_helices.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"max_offset": 2000, "grid_position": [0, 0]}, diff --git a/examples/output_designs/many_helices_modifications.dna b/examples/output_designs/many_helices_modifications.dna index 074374b3..34c5783e 100644 --- a/examples/output_designs/many_helices_modifications.dna +++ b/examples/output_designs/many_helices_modifications.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "helices": [ {"grid_position": [0, 0]}, @@ -12,30 +12,30 @@ {"grid_position": [0, 7]} ], "modifications_in_design": { - "/5Biosg/": { - "display_text": "B", - "idt_text": "/5Biosg/", - "display_connector": false, - "location": "5'" - }, "/3Cy3Sp/": { "display_text": "Cy3", "idt_text": "/3Cy3Sp/", "display_connector": false, "location": "3'" }, - "/iCy3/": { - "display_text": "Cy3", - "idt_text": "/iCy3/", - "display_connector": false, - "location": "internal" - }, "/iBiodT/": { "display_text": "B", "idt_text": "/iBiodT/", "display_connector": false, "location": "internal", "allowed_bases": ["T"] + }, + "/5Biosg/": { + "display_text": "B", + "idt_text": "/5Biosg/", + "display_connector": false, + "location": "5'" + }, + "/iCy3/": { + "display_text": "Cy3", + "idt_text": "/iCy3/", + "display_connector": false, + "location": "internal" } }, "strands": [ diff --git a/examples/output_designs/proposal.dna b/examples/output_designs/proposal.dna index f314e3e5..a42054b5 100644 --- a/examples/output_designs/proposal.dna +++ b/examples/output_designs/proposal.dna @@ -1,22 +1,23 @@ { - "version": "0.7.0", + "version": "0.7.4", + "grid": "none", "helices": [ - {"max_offset": 512, "position": {"x": 0, "y": 0, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": 2.5, "y": 0.0, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": 4.809698831278217, "y": 0.9567085809127245, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": 6.577465784244586, "y": 2.7244755338790934, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": 7.534174365157311, "y": 5.034174365157311, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": 7.534174365157311, "y": 7.534174365157311, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": 6.577465784244587, "y": 9.843873196435528, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": 4.809698831278218, "y": 11.611640149401897, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": 2.500000000000001, "y": 12.568348730314622, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": 8.881784197001252e-16, "y": 12.568348730314622, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": -2.309698831278216, "y": 11.611640149401897, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": -4.077465784244586, "y": 9.843873196435528, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": -5.034174365157312, "y": 7.534174365157312, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": -5.0341743651573125, "y": 5.034174365157312, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": -4.077465784244588, "y": 2.724475533879095, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}}, - {"max_offset": 512, "position": {"x": -2.309698831278218, "y": 0.9567085809127276, "z": 0, "pitch": 0, "roll": 0, "yaw": 0}} + {"max_offset": 512, "position": {"x": 0, "y": 0, "z": 0}}, + {"max_offset": 512, "position": {"x": 2.5, "y": 0.0, "z": 0}}, + {"max_offset": 512, "position": {"x": 4.809698831278217, "y": 0.9567085809127245, "z": 0}}, + {"max_offset": 512, "position": {"x": 6.577465784244586, "y": 2.7244755338790934, "z": 0}}, + {"max_offset": 512, "position": {"x": 7.534174365157311, "y": 5.034174365157311, "z": 0}}, + {"max_offset": 512, "position": {"x": 7.534174365157311, "y": 7.534174365157311, "z": 0}}, + {"max_offset": 512, "position": {"x": 6.577465784244587, "y": 9.843873196435528, "z": 0}}, + {"max_offset": 512, "position": {"x": 4.809698831278218, "y": 11.611640149401897, "z": 0}}, + {"max_offset": 512, "position": {"x": 2.500000000000001, "y": 12.568348730314622, "z": 0}}, + {"max_offset": 512, "position": {"x": 8.881784197001252e-16, "y": 12.568348730314622, "z": 0}}, + {"max_offset": 512, "position": {"x": -2.309698831278216, "y": 11.611640149401897, "z": 0}}, + {"max_offset": 512, "position": {"x": -4.077465784244586, "y": 9.843873196435528, "z": 0}}, + {"max_offset": 512, "position": {"x": -5.034174365157312, "y": 7.534174365157312, "z": 0}}, + {"max_offset": 512, "position": {"x": -5.0341743651573125, "y": 5.034174365157312, "z": 0}}, + {"max_offset": 512, "position": {"x": -4.077465784244588, "y": 2.724475533879095, "z": 0}}, + {"max_offset": 512, "position": {"x": -2.309698831278218, "y": 0.9567085809127276, "z": 0}} ], "helices_view_order": [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], "strands": [ diff --git a/examples/output_designs/sst-motif-3_2.dna b/examples/output_designs/sst-motif-3_2.dna index 41c91b9d..ddfccfa4 100644 --- a/examples/output_designs/sst-motif-3_2.dna +++ b/examples/output_designs/sst-motif-3_2.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "major_tick_distance": 10, "helices": [ diff --git a/examples/output_designs/sst-motif-4_1.dna b/examples/output_designs/sst-motif-4_1.dna index 56e46c36..2f73f61a 100644 --- a/examples/output_designs/sst-motif-4_1.dna +++ b/examples/output_designs/sst-motif-4_1.dna @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.7.4", "grid": "square", "major_tick_distance": 10, "helices": [ diff --git a/scadnano/scadnano.py b/scadnano/scadnano.py index 074873ba..5c9b0210 100644 --- a/scadnano/scadnano.py +++ b/scadnano/scadnano.py @@ -312,13 +312,24 @@ def default_major_tick_distance(grid: Grid) -> int: default_helix_rotation: float = 0.0 default_helix_rotation_anchor: int = 0 +default_pitch: float = 0.0 +default_roll: float = 0.0 +default_yaw: float = 0.0 + base_width_svg: float = 10.0 """Width of a single base in the SVG main view of scadnano.""" base_height_svg: float = 10.0 """Height of a single base in the SVG main view of scadnano.""" -distance_between_helices_svg: float = (base_width_svg * 2.5 / 0.34) +distance_between_helices_nm: float = 2.5 +"""Distance between centers of helices in nanometers. +See :py:data:`distance_between_helices_svg` for explanation of this value.""" + +base_width_nm: float = 0.34 +"""Width of a single DNA base in nanometers.""" + +distance_between_helices_svg: float = base_width_svg * distance_between_helices_nm / base_width_nm """Distance between tops of two consecutive helices (using default positioning rules). This is set to (:const:`base_width_svg` * 2.5/0.34) based on the following calculation, @@ -660,14 +671,15 @@ def m13(rotation: int = 5587, variant: M13Variant = M13Variant.p7249): grid_position_key = 'grid_position' svg_position_key = 'svg_position' position3d_key = 'position' +legacy_position3d_keys = ['origin'] # Position3D keys position_x_key = 'x' position_y_key = 'y' position_z_key = 'z' -position_pitch_key = 'pitch' -position_roll_key = 'roll' -position_yaw_key = 'yaw' +pitch_key = 'pitch' +roll_key = 'roll' +yaw_key = 'yaw' position_origin_key = 'origin' # Strand keys @@ -840,15 +852,6 @@ class Position3D(_JSONSerializable): z: float = 0 """z-coordinate of position""" - pitch: float = 0 - """pitch angle in degrees""" - - roll: float = 0 - """roll angle in degrees""" - - yaw: float = 0 - """yaw angle in degrees""" - def to_json_serializable(self, suppress_indent: bool = True): dct = self.__dict__ # return NoIndent(dct) if suppress_indent else dct @@ -865,10 +868,7 @@ def from_json(json_map: dict) -> Position3D: x = json_map[position_x_key] y = json_map[position_y_key] z = json_map[position_z_key] - pitch = json_map[position_pitch_key] - roll = json_map[position_roll_key] - yaw = json_map[position_yaw_key] - return Position3D(x=x, y=y, z=z, pitch=pitch, roll=roll, yaw=yaw) + return Position3D(x=x, y=y, z=z) def in_browser() -> bool: @@ -986,10 +986,25 @@ class Helix(_JSONSerializable): Default is 0.""" position3d: Position3D = None - """Position (x,y,z) and orientation (pitch,roll,yaw) of this :any:`Helix` in 3D space. + """Position (x,y,z) of this :any:`Helix` in 3D space. Optional if :py:data:`Helix.grid_position` is specified. - Default is pitch, roll, yaw are 0, and x,y,z are determined by grid position h, v, b.""" + Default is x,y,z are determined by grid position h, v, b.""" + + pitch: float = 0 + """Angle in the main view plane; 0 means pointing to the right (min_offset on left, max_offset on right). + Rotation is clockwise in the main view. + Units are degrees.""" + + roll: float = 0 + """Angle around the center of the helix; 0 means pointing straight up in the side view. + Rotation is clockwise in the side view. + Units are degrees.""" + + yaw: float = 0 + """Third angle for orientation besides :py:data:`Helix.pitch` and :py:data:`Helix.roll`. + Not visually displayed in scadnano, but here to support more general 3D applications. + Units are degrees.""" idx: int = None """Index of this :any:`Helix`. @@ -1026,12 +1041,13 @@ def to_json_serializable(self, suppress_indent: bool = True): else: dct[position3d_key] = self.position3d.to_json_serializable(suppress_indent) - # print(f'self.svg_position() = {self.svg_position}') - # print(f'default_svg_position() = {self.default_svg_position()}') - default_x, default_y = self.default_svg_position() - if not (_is_close(self.svg_position[0], default_x) and _is_close(self.svg_position[1], - default_y)): - dct[svg_position_key] = (self.svg_position[0], self.svg_position[1]) + + if not _is_close(self.pitch, default_pitch): + dct[pitch_key] = self.pitch + if not _is_close(self.roll, default_roll): + dct[roll_key] = self.roll + if not _is_close(self.yaw, default_yaw): + dct[yaw_key] = self.yaw if self.major_tick_distance is not None and self.major_tick_distance > 0: dct[major_tick_distance_key] = self.major_tick_distance @@ -1049,9 +1065,6 @@ def to_json_serializable(self, suppress_indent: bool = True): return _NoIndent(dct) if suppress_indent else dct - def default_svg_position(self): - return 0, self.idx * distance_between_helices_svg - def default_grid_position(self): return (0, self.idx, 0) @@ -1080,14 +1093,6 @@ def from_json(json_map: dict) -> Helix: gp_list.append(0) grid_position = tuple(gp_list) - svg_position = None - if svg_position_key in json_map: - sp_list = json_map[grid_position_key] - if len(sp_list) != 2: - raise IllegalDNADesignError("svg_position must have exactly two integers, " - f"but instead it has {len(sp_list)}: {sp_list}") - svg_position = tuple(sp_list) - major_tick_distance = json_map.get(major_tick_distance_key) major_ticks = json_map.get(major_ticks_key) min_offset = json_map.get(min_offset_key) @@ -1096,19 +1101,25 @@ def from_json(json_map: dict) -> Helix: rotation_anchor = json_map.get(rotation_anchor_key, default_helix_rotation_anchor) idx = json_map.get(idx_on_helix_key) - position3d_map = json_map.get(position3d_key) + position3d_map = optional_field(None, json_map, position3d_key, *legacy_position3d_keys) position3d = Position3D.from_json(position3d_map) if position3d_map is not None else None + pitch = json_map.get(pitch_key, default_pitch) + roll = json_map.get(roll_key, default_roll) + yaw = json_map.get(yaw_key, default_yaw) + return Helix( major_tick_distance=major_tick_distance, major_ticks=major_ticks, grid_position=grid_position, - svg_position=svg_position, min_offset=min_offset, max_offset=max_offset, rotation=rotation, rotation_anchor=rotation_anchor, position3d=position3d, + pitch=pitch, + roll=roll, + yaw=yaw, idx=idx, ) @@ -2439,7 +2450,7 @@ def idx_of(helix: Helix, order: int): def __post_init__(self): # XXX: exact order of these calls is important self._set_helices_idxs() - self._set_helices_grid_and_svg_positions() + self._set_helices_grid_positions() self._build_domains_on_helix_lists() self._set_helices_min_max_offsets(update=False) self._check_legal_design() @@ -3025,12 +3036,10 @@ def _set_helices_idxs(self): if helix.idx is None: helix.idx = idx - def _set_helices_grid_and_svg_positions(self): + def _set_helices_grid_positions(self): for idx, helix in self.helices.items(): if helix.grid_position is None: helix.grid_position = helix.default_grid_position() - if helix.svg_position is None: - helix.svg_position = helix.default_svg_position() def _set_helices_min_max_offsets(self, update: bool): """update = whether to overwrite existing Helix.max_offset and Helix.min_offset. diff --git a/tests/scadnano_tests.py b/tests/scadnano_tests.py index 927ddc66..ff9c444c 100644 --- a/tests/scadnano_tests.py +++ b/tests/scadnano_tests.py @@ -2092,11 +2092,11 @@ def test_position_specified_with_origin_keyword(self): json_str = """ { "grid": "none", - "helices": [{"position": { - "origin": { "x": 1, "y": 2, "z": 3}, - "pitch": 4, - "roll": 5, - "yaw": 6} + "helices": [{ + "origin": {"x": 1, "y": 2, "z": 3}, + "pitch": 4, + "roll": 5, + "yaw": 6 }], "strands": [ { @@ -2107,9 +2107,18 @@ def test_position_specified_with_origin_keyword(self): } """ d = sc.DNADesign.from_scadnano_json_str(json_str) - expected_position = sc.Position3D(1,2,3,4,5,6) + expected_position = sc.Position3D(1,2,3) + expected_pitch = 4 + expected_roll = 5 + expected_yaw = 6 actual_position = d.helices[0].position3d + actual_pitch = d.helices[0].pitch + actual_roll = d.helices[0].roll + actual_yaw = d.helices[0].yaw self.assertEqual(expected_position, actual_position) + self.assertEqual(expected_pitch, actual_pitch) + self.assertEqual(expected_roll, actual_roll) + self.assertEqual(expected_yaw, actual_yaw) def test_json_tristan_example_issue_32(self): json_str = """ From c2c394c413ec8acae76d4d5b37191c6c30ec4eba Mon Sep 17 00:00:00 2001 From: David Doty Date: Wed, 3 Jun 2020 17:58:21 -0700 Subject: [PATCH 2/3] removed rotation and rotation_anchor --- ...on.py => 1_staple_1_helix_origami_roll.py} | 40 ++++++++-------- .../1_staple_1_helix_origami_roll.dna | 23 +++++++++ .../2_staple_2_helix_modifications.dna | 46 +++++++++--------- .../many_helices_modifications.dna | 18 +++---- scadnano/scadnano.py | 47 ------------------- tests/scadnano_tests.py | 4 +- 6 files changed, 77 insertions(+), 101 deletions(-) rename examples/{1_staple_1_helix_origami_rotation.py => 1_staple_1_helix_origami_roll.py} (84%) create mode 100644 examples/output_designs/1_staple_1_helix_origami_roll.dna diff --git a/examples/1_staple_1_helix_origami_rotation.py b/examples/1_staple_1_helix_origami_roll.py similarity index 84% rename from examples/1_staple_1_helix_origami_rotation.py rename to examples/1_staple_1_helix_origami_roll.py index f233c4db..f4ee9f9b 100644 --- a/examples/1_staple_1_helix_origami_rotation.py +++ b/examples/1_staple_1_helix_origami_roll.py @@ -1,20 +1,20 @@ -import math - -import scadnano as sc - -def main(): - length = 9 - helices = [sc.Helix(max_offset=length, rotation=math.pi/2, rotation_anchor=2)] - stap_ss = sc.Domain(0, sc.forward, 0, length) - scaf_ss = sc.Domain(0, sc.reverse, 0, length) - stap = sc.Strand([stap_ss]) - scaf = sc.Strand([scaf_ss], color=sc.default_scaffold_color) - strands = [stap, scaf] - design = sc.DNADesign(helices=helices, strands=strands, grid=sc.square) - design.assign_dna(scaf, 'AACT' * (length // 4)) - - return design - -if not sc.in_browser() and __name__ == '__main__': - design = main() - design.write_scadnano_file(directory='output_designs') +import math + +import scadnano as sc + +def main(): + length = 9 + helices = [sc.Helix(max_offset=length, roll=90)] + stap_ss = sc.Domain(0, sc.forward, 0, length) + scaf_ss = sc.Domain(0, sc.reverse, 0, length) + stap = sc.Strand([stap_ss]) + scaf = sc.Strand([scaf_ss], color=sc.default_scaffold_color) + strands = [stap, scaf] + design = sc.DNADesign(helices=helices, strands=strands, grid=sc.square) + design.assign_dna(scaf, 'AACT' * (length // 4)) + + return design + +if not sc.in_browser() and __name__ == '__main__': + design = main() + design.write_scadnano_file(directory='output_designs') diff --git a/examples/output_designs/1_staple_1_helix_origami_roll.dna b/examples/output_designs/1_staple_1_helix_origami_roll.dna new file mode 100644 index 00000000..1c2bb6b4 --- /dev/null +++ b/examples/output_designs/1_staple_1_helix_origami_roll.dna @@ -0,0 +1,23 @@ +{ + "version": "0.7.4", + "grid": "square", + "helices": [ + {"grid_position": [0, 0], "roll": 90} + ], + "strands": [ + { + "color": "#007200", + "sequence": "?AGTTAGTT", + "domains": [ + {"helix": 0, "forward": true, "start": 0, "end": 9} + ] + }, + { + "color": "#0066cc", + "sequence": "AACTAACT?", + "domains": [ + {"helix": 0, "forward": false, "start": 0, "end": 9} + ] + } + ] +} \ No newline at end of file diff --git a/examples/output_designs/2_staple_2_helix_modifications.dna b/examples/output_designs/2_staple_2_helix_modifications.dna index 5ce36dd0..3bb787dc 100644 --- a/examples/output_designs/2_staple_2_helix_modifications.dna +++ b/examples/output_designs/2_staple_2_helix_modifications.dna @@ -6,11 +6,17 @@ {"grid_position": [0, 1]} ], "modifications_in_design": { - "/3Cy3Sp/": { - "display_text": "Cy3", - "idt_text": "/3Cy3Sp/", + "/5Cy5/": { + "display_text": "Cy5", + "idt_text": "/5Cy5/", "display_connector": false, - "location": "3'" + "location": "5'" + }, + "/5Biosg/": { + "display_text": "B", + "idt_text": "/5Biosg/", + "display_connector": false, + "location": "5'" }, "/3Bio/": { "display_text": "B", @@ -18,18 +24,6 @@ "display_connector": false, "location": "3'" }, - "/iCy3/": { - "display_text": "Cy3", - "idt_text": "/iCy3/", - "display_connector": false, - "location": "internal" - }, - "/iCy5/": { - "display_text": "Cy5", - "idt_text": "/iCy5/", - "display_connector": false, - "location": "internal" - }, "/iBiodT/": { "display_text": "B", "idt_text": "/iBiodT/", @@ -37,17 +31,23 @@ "location": "internal", "allowed_bases": ["T"] }, - "/5Cy5/": { + "/3Cy3Sp/": { + "display_text": "Cy3", + "idt_text": "/3Cy3Sp/", + "display_connector": false, + "location": "3'" + }, + "/iCy5/": { "display_text": "Cy5", - "idt_text": "/5Cy5/", + "idt_text": "/iCy5/", "display_connector": false, - "location": "5'" + "location": "internal" }, - "/5Biosg/": { - "display_text": "B", - "idt_text": "/5Biosg/", + "/iCy3/": { + "display_text": "Cy3", + "idt_text": "/iCy3/", "display_connector": false, - "location": "5'" + "location": "internal" } }, "strands": [ diff --git a/examples/output_designs/many_helices_modifications.dna b/examples/output_designs/many_helices_modifications.dna index 34c5783e..7af2dd48 100644 --- a/examples/output_designs/many_helices_modifications.dna +++ b/examples/output_designs/many_helices_modifications.dna @@ -12,11 +12,11 @@ {"grid_position": [0, 7]} ], "modifications_in_design": { - "/3Cy3Sp/": { + "/iCy3/": { "display_text": "Cy3", - "idt_text": "/3Cy3Sp/", + "idt_text": "/iCy3/", "display_connector": false, - "location": "3'" + "location": "internal" }, "/iBiodT/": { "display_text": "B", @@ -25,17 +25,17 @@ "location": "internal", "allowed_bases": ["T"] }, + "/3Cy3Sp/": { + "display_text": "Cy3", + "idt_text": "/3Cy3Sp/", + "display_connector": false, + "location": "3'" + }, "/5Biosg/": { "display_text": "B", "idt_text": "/5Biosg/", "display_connector": false, "location": "5'" - }, - "/iCy3/": { - "display_text": "Cy3", - "idt_text": "/iCy3/", - "display_connector": false, - "location": "internal" } }, "strands": [ diff --git a/scadnano/scadnano.py b/scadnano/scadnano.py index 5c9b0210..11eeae42 100644 --- a/scadnano/scadnano.py +++ b/scadnano/scadnano.py @@ -309,9 +309,6 @@ def default_major_tick_distance(grid: Grid) -> int: return 7 if grid in (Grid.hex, Grid.honeycomb) else 8 -default_helix_rotation: float = 0.0 -default_helix_rotation_anchor: int = 0 - default_pitch: float = 0.0 default_roll: float = 0.0 default_yaw: float = 0.0 @@ -655,8 +652,6 @@ def m13(rotation: int = 5587, variant: M13Variant = M13Variant.p7249): grid_key = 'grid' major_tick_distance_key = 'major_tick_distance' major_ticks_key = 'major_ticks' -rotation_key = 'rotation' -rotation_anchor_key = 'rotation_anchor' helices_key = 'helices' strands_key = 'strands' scaffold_key = 'scaffold' @@ -954,37 +949,6 @@ class Helix(_JSONSerializable): If `grid_position = (h,v,b)` is specified but `position` is omitted, then the default is `x` = b * BASE_WIDTH_SVG, `y` = [index of :any:`Helix`] * :any:`scadnano.distance_between_helices_svg`.""" - rotation: float = 0 - """Rotation angle (in degrees) of backbone of the :any:`Domain` on this :any:`Helix` with - :py:data:`Domain.forward` = ``True``. - - The angle is relative to the offset :py:data:`Helix.rotation_anchor`, and 0 degrees is defined to - be pointing *up* in both the side view and main view. - - A positive rotation angle rotates *clockwise* in the side view. - This violates standard Cartesian coordinate conventions: - https://en.wikipedia.org/wiki/Rotation_matrix, - but it is consistent with SVG rotation conventions: - https://www.w3.org/TR/SVG11/coords.html#ExampleRotateScale. - - For example, a rotation of 90 degrees points right in the side view - and out of the screen in the main view. - - Default is 0 degrees.""" - - rotation_anchor: int = 0 - """Offset on this :any:`Helix` that is the reference point for 0 degrees. - The rotation at offset ``o`` is 360 degrees times the remainder of ``o - rotation_anchor`` - when divided by 10.5. - - For example, if :py:data:`Helix.rotation` = 0 and :py:data:`Helix.rotation_anchor` = 42, then - at offsets of the form :math:`42 + 21k` for integer :math:`k` - (i.e., 42 itself, as well as 21, 0, -21, -42, ..., 63, 84, 105, ...), - the rotation angle is also 0 at those offsets since - they are integer multiples of 21 (hence also multiples of 10.5) from 42. - - Default is 0.""" - position3d: Position3D = None """Position (x,y,z) of this :any:`Helix` in 3D space. @@ -1041,7 +1005,6 @@ def to_json_serializable(self, suppress_indent: bool = True): else: dct[position3d_key] = self.position3d.to_json_serializable(suppress_indent) - if not _is_close(self.pitch, default_pitch): dct[pitch_key] = self.pitch if not _is_close(self.roll, default_roll): @@ -1055,12 +1018,6 @@ def to_json_serializable(self, suppress_indent: bool = True): if self.major_ticks is not None: dct[major_ticks_key] = self.major_ticks - if self.rotation != 0: - dct[rotation_key] = self.rotation - - if self.rotation_anchor != 0: - dct[rotation_anchor_key] = self.rotation_anchor - dct[idx_on_helix_key] = self.idx return _NoIndent(dct) if suppress_indent else dct @@ -1097,8 +1054,6 @@ def from_json(json_map: dict) -> Helix: major_ticks = json_map.get(major_ticks_key) min_offset = json_map.get(min_offset_key) max_offset = json_map.get(max_offset_key) - rotation = json_map.get(rotation_key, default_helix_rotation) - rotation_anchor = json_map.get(rotation_anchor_key, default_helix_rotation_anchor) idx = json_map.get(idx_on_helix_key) position3d_map = optional_field(None, json_map, position3d_key, *legacy_position3d_keys) @@ -1114,8 +1069,6 @@ def from_json(json_map: dict) -> Helix: grid_position=grid_position, min_offset=min_offset, max_offset=max_offset, - rotation=rotation, - rotation_anchor=rotation_anchor, position3d=position3d, pitch=pitch, roll=roll, diff --git a/tests/scadnano_tests.py b/tests/scadnano_tests.py index ff9c444c..0338d309 100644 --- a/tests/scadnano_tests.py +++ b/tests/scadnano_tests.py @@ -2162,8 +2162,8 @@ def test_to_json__hairpin(self): json = design.to_json() # should be no error getting here - def test_to_json__rotation(self): - helix = sc.Helix(rotation=math.pi / 2, rotation_anchor=31) + def test_to_json__roll(self): + helix = sc.Helix(roll=90) ss_f = sc.Domain(helix=0, forward=True, start=0, end=5) ss_r = sc.Domain(helix=0, forward=False, start=0, end=5) strand_f = sc.Strand([ss_f]) From f327b0da5b6457ae7571765d76aaa3f132fe604a Mon Sep 17 00:00:00 2001 From: David Doty Date: Wed, 3 Jun 2020 18:22:04 -0700 Subject: [PATCH 3/3] bumped version to v0.8.0 --- dist/scadnano-0.8.0.tar.gz | Bin 0 -> 56599 bytes ...elix_origami_barrel_from_algoSST_paper.dna | 2 +- .../16_helix_origami_rectangle.dna | 2 +- .../16_helix_origami_rectangle_idt.dna | 2 +- .../16_helix_origami_rectangle_no_seq.dna | 2 +- ...elix_origami_rectangle_no_seq_no_twist.dna | 2 +- .../16_helix_origami_rectangle_no_twist.dna | 2 +- ...ami_rectangle_seed_tiles_grow_from_top.dna | 2 +- ..._origami_rectangle_shifted_seam_no_seq.dna | 2 +- .../1_staple_1_helix_origami.dna | 2 +- .../1_staple_1_helix_origami_mismatches.dna | 2 +- ...le_1_helix_origami_position_nondefault.dna | 2 +- .../1_staple_1_helix_origami_roll.dna | 2 +- ...elix_origami_rectangle_twist_corrected.dna | 2 +- ...x_2_strands_multiple_substrands_no_seq.dna | 2 +- .../2_staple_2_helix_modifications.dna | 38 +++++++++--------- .../2_staple_2_helix_origami_6bases_wide.dna | 2 +- .../2_staple_2_helix_origami_deletions.dna | 2 +- ...e_2_helix_origami_deletions_insertions.dna | 2 +- ...elix_origami_deletions_insertions_mods.dna | 2 +- ...ix_origami_deletions_insertions_no_seq.dna | 2 +- .../3_helix_deletions_insertions.dna | 2 +- examples/output_designs/4_helix_grid_none.dna | 2 +- .../56_helix_origami_rectangle.dna | 2 +- .../64_helix_origami_rectangle.dna | 2 +- .../6_helix_6_col_origami_rectangle.dna | 2 +- .../6_helix_bundle_honeycomb.dna | 2 +- .../6_helix_origami_rectangle.dna | 2 +- ...origami_rectangle_helices_out_of_order.dna | 2 +- .../add_deletions_to_24_helix_rectangle.dna | 2 +- examples/output_designs/empty.dna | 2 +- examples/output_designs/hairpin.dna | 2 +- .../helices_out_of_order_nonconsecutive.dna | 2 +- examples/output_designs/hex_lattice_10x10.dna | 2 +- .../hex_lattice_10x10_with_negative.dna | 2 +- .../honeycomb_lattice_10x10.dna | 2 +- .../honeycomb_lattice_10x10_with_negative.dna | 2 +- .../output_designs/idt-plates-explicit.dna | 2 +- .../output_designs/long_range_crossovers.dna | 2 +- .../output_designs/loopouts_all_types.dna | 2 +- examples/output_designs/many_big_helices.dna | 2 +- .../many_helices_modifications.dna | 14 +++---- examples/output_designs/proposal.dna | 2 +- examples/output_designs/sst-motif-3_2.dna | 2 +- examples/output_designs/sst-motif-4_1.dna | 2 +- scadnano/scadnano.py | 2 +- scadnano/scadnano_version.py | 2 +- setup.py | 2 +- ...st_16_helix_origami_rectangle_no_twist.dna | 2 +- ...e_2_helix_origami_deletions_insertions.dna | 2 +- ...stape_2_helix_origami_extremely_simple.dna | 2 +- ...ape_2_helix_origami_extremely_simple_2.dna | 2 +- .../test_6_helix_origami_rectangle.dna | 2 +- 53 files changed, 76 insertions(+), 76 deletions(-) create mode 100644 dist/scadnano-0.8.0.tar.gz diff --git a/dist/scadnano-0.8.0.tar.gz b/dist/scadnano-0.8.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..1652fcbbe7c624b5ab8135337c7db6f05db7f440 GIT binary patch literal 56599 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