diff --git a/examples/circular.py b/examples/circular.py
new file mode 100644
index 0000000..2116836
--- /dev/null
+++ b/examples/circular.py
@@ -0,0 +1,18 @@
+import scadnano as sc
+import modifications as mod
+import dataclasses
+
+def create_design():
+    helices = [sc.Helix(max_offset=30) for _ in range(2)]
+    design = sc.Design(helices=helices, grid=sc.square)
+
+    design.strand(0,0).move(10).cross(1).move(-10).as_circular()
+    design.strand(0,10).move(10).loopout(1, 5).move(-10).as_circular()
+    design.strand(0,20).move(10).cross(1).move(-10)
+
+    return design
+
+
+if __name__ == '__main__':
+    design = create_design()
+    design.write_scadnano_file(directory='output_designs')
diff --git a/examples/output_designs/circular.sc b/examples/output_designs/circular.sc
new file mode 100644
index 0000000..82f0bd4
--- /dev/null
+++ b/examples/output_designs/circular.sc
@@ -0,0 +1,34 @@
+{
+  "version": "0.13.0",
+  "grid": "square",
+  "helices": [
+    {"grid_position": [0, 0]},
+    {"grid_position": [0, 1]}
+  ],
+  "strands": [
+    {
+      "circular": true,
+      "color": "#f74308",
+      "domains": [
+        {"helix": 0, "forward": true, "start": 0, "end": 10},
+        {"helix": 1, "forward": false, "start": 0, "end": 10}
+      ]
+    },
+    {
+      "circular": true,
+      "color": "#57bb00",
+      "domains": [
+        {"helix": 0, "forward": true, "start": 10, "end": 20},
+        {"loopout": 5},
+        {"helix": 1, "forward": false, "start": 10, "end": 20}
+      ]
+    },
+    {
+      "color": "#888888",
+      "domains": [
+        {"helix": 0, "forward": true, "start": 20, "end": 30},
+        {"helix": 1, "forward": false, "start": 20, "end": 30}
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/scadnano/scadnano.py b/scadnano/scadnano.py
index a0b0459..185c419 100644
--- a/scadnano/scadnano.py
+++ b/scadnano/scadnano.py
@@ -44,7 +44,7 @@ so the user must take care not to set them.
 # commented out for now to support Py3.6, which does not support this feature
 # from __future__ import annotations
 
-__version__ = "0.13.0"  # version line; WARNING: do not remove or change this line or comment
+__version__ = "0.13.1"  # version line; WARNING: do not remove or change this line or comment
 
 import dataclasses
 from abc import abstractmethod, ABC, ABCMeta
@@ -749,6 +749,7 @@ position_origin_key = 'origin'
 
 # Strand keys
 strand_name_key = 'name'
+circular_key = 'circular'
 color_key = 'color'
 dna_sequence_key = 'sequence'
 legacy_dna_sequence_keys = ['dna_sequence']  # support legacy names for these ideas
@@ -2201,6 +2202,17 @@ class StrandBuilder(Generic[StrandLabel, DomainLabel]):
 
         return self
 
+    def as_circular(self) -> 'StrandBuilder[StrandLabel, DomainLabel]':
+        """
+        Makes :any:`Strand` being built circular.
+
+        :return: self
+        """
+        if self._strand is None:
+            raise ValueError('no Strand created yet; make at least one domain first')
+        self._strand.set_circular()
+        return self
+
     # remove quotes when Py3.6 support dropped
     def as_scaffold(self) -> 'StrandBuilder[StrandLabel, DomainLabel]':
         """
@@ -2477,6 +2489,13 @@ class Strand(_JSONSerializable, Generic[StrandLabel, DomainLabel]):
     and could be either single-stranded or double-stranded, 
     whereas each :any:`Loopout` is single-stranded and has no associated :any:`Helix`."""
 
+    circular: bool = False
+    """If True, this :any:`Strand` is circular and has no 5' or 3' end. Although there is still a 
+    first and last :any:`Domain`, we interpret there to be a crossover from the 3' end of the last domain
+    to the 5' end of the first domain, and any circular permutation of :py:data:`Strand.domains` 
+    should result in a functionally equivalent :any:`Strand`. It is illegal to have a 
+    :any:`Modification5Prime` or :any:`Modification3Prime` on a circular :any:`Strand`."""
+
     dna_sequence: Optional[str] = None
     """Do not assign directly to this field. Always use :any:`Design.assign_dna` 
     (for complementarity checking) or :any:`Strand.set_dna_sequence` 
@@ -2509,10 +2528,16 @@ class Strand(_JSONSerializable, Generic[StrandLabel, DomainLabel]):
     :any:`Design` is a scaffold, then the design is considered a DNA origami design."""
 
     modification_5p: Optional[Modification5Prime] = None
-    """5' modification; None if there is no 5' modification."""
+    """
+    5' modification; None if there is no 5' modification. 
+    Illegal to have if :py:data:`Strand.circular` is True.
+    """
 
     modification_3p: Optional[Modification3Prime] = None
-    """3' modification; None if there is no 5' modification."""
+    """
+    3' modification; None if there is no 3' modification. 
+    Illegal to have if :py:data:`Strand.circular` is True.
+    """
 
     modifications_int: Dict[int, ModificationInternal] = field(default_factory=dict)
     """:any:`Modification`'s to the DNA sequence (e.g., biotin, Cy3/Cy5 fluorphores). Maps offset to 
@@ -2574,6 +2599,8 @@ class Strand(_JSONSerializable, Generic[StrandLabel, DomainLabel]):
         dct: Dict[str, Any] = OrderedDict()
         if self.name is not None:
             dct[strand_name_key] = self.name
+        if self.circular:
+            dct[circular_key] = self.circular
         if self.color is not None:
             dct[color_key] = self.color.to_json_serializable(suppress_indent)
         if self.dna_sequence is not None:
@@ -2617,6 +2644,7 @@ class Strand(_JSONSerializable, Generic[StrandLabel, DomainLabel]):
             raise IllegalDesignError('Loopout at end of Strand not supported')
 
         is_scaffold = json_map.get(is_scaffold_key, False)
+        circular = json_map.get(circular_key, False)
 
         dna_sequence = optional_field(None, json_map, dna_sequence_key, *legacy_dna_sequence_keys)
 
@@ -2638,6 +2666,7 @@ class Strand(_JSONSerializable, Generic[StrandLabel, DomainLabel]):
         return Strand(
             domains=domains,
             dna_sequence=dna_sequence,
+            circular=circular,
             color=color,
             idt=idt,
             is_scaffold=is_scaffold,
@@ -2699,6 +2728,28 @@ class Strand(_JSONSerializable, Generic[StrandLabel, DomainLabel]):
         """Sets color of this :any:`Strand`."""
         self.color = color
 
+    def set_circular(self, circular: bool = True) -> None:
+        """
+        Sets this to be a circular :any:`Strand` (or non-circular if optional parameter is False.
+
+        :param circular:
+            whether to make this :any:`Strand` circular (True) or linear (False)
+        :raises StrandError:
+            if this :any:`Strand` has a 5' or 3' modification
+        """
+        if circular and self.modification_5p is not None:
+            raise StrandError(self, "cannot have a 5' modification on a circular strand")
+        if circular and self.modification_3p is not None:
+            raise StrandError(self, "cannot have a 3' modification on a circular strand")
+        self.circular = circular
+
+    def set_linear(self) -> None:
+        """
+        Makes this a linear (non-circular) :any:`Strand`. Equivalent to calling
+        `self.set_circular(False)`.
+        """
+        self.set_circular(False)
+
     def set_default_idt(self, use_default_idt: bool = True, skip_scaffold: bool = True,
                         unique_names: bool = False) -> None:
         """
@@ -2744,11 +2795,15 @@ class Strand(_JSONSerializable, Generic[StrandLabel, DomainLabel]):
             self.idt = None
 
     def set_modification_5p(self, mod: Modification5Prime = None) -> None:
-        """Sets 5' modification to be `mod`."""
+        """Sets 5' modification to be `mod`. `mod` cannot be non-None if :any:`Strand.circular` is True."""
+        if self.circular and mod is not None:
+            raise StrandError(self, "cannot have a 5' modification on a circular strand")
         self.modification_5p = mod
 
     def set_modification_3p(self, mod: Modification3Prime = None) -> None:
-        """Sets 3' modification to be `mod`."""
+        """Sets 3' modification to be `mod`. `mod` cannot be non-None if :any:`Strand.circular` is True."""
+        if self.circular and mod is not None:
+            raise StrandError(self, "cannot have a 3' modification on a circular strand")
         self.modification_3p = mod
 
     def remove_modification_5p(self) -> None:

diff --git a/tests/scadnano_tests.py b/tests/scadnano_tests.py
index fc584bd..bf58fc1 100644
--- a/tests/scadnano_tests.py
+++ b/tests/scadnano_tests.py
@@ -3601,6 +3601,46 @@ def set_colors_black(*strands) -> None:
         strand.set_color(sc.Color(r=0, g=0, b=0))
 
 
+class TestCircularStrands(unittest.TestCase):
+
+    def setUp(self) -> None:
+        helices = [sc.Helix(max_offset=10) for _ in range(2)]
+        self.design = sc.Design(helices=helices, strands=[])
+        self.design.strand(0, 0).move(10).cross(1).move(-10)
+        self.strand = self.design.strands[0]
+        r'''
+        0  [--------\
+                    |
+        1  <--------/
+        '''
+
+    def test_can_add_internal_mod_to_circular_strand(self) -> None:
+        self.strand.set_circular()
+        self.assertEqual(True, self.strand.circular)
+        self.strand.set_modification_internal(2, mod.biotin_int)
+        self.assertEqual(1, len(self.strand.modifications_int))
+
+    def test_cannot_make_strand_circular_if_5p_mod(self) -> None:
+        self.strand.set_modification_5p(mod.biotin_5p)
+        with self.assertRaises(sc.StrandError):
+            self.strand.set_circular(True)
+
+    def test_cannot_make_strand_circular_if_3p_mod(self) -> None:
+        self.strand.set_modification_3p(mod.biotin_3p)
+        with self.assertRaises(sc.StrandError):
+            self.strand.set_circular(True)
+
+    def test_add_5p_mod_to_circular_strand(self) -> None:
+        self.strand.set_circular(True)
+        with self.assertRaises(sc.StrandError):
+            self.strand.set_modification_5p(mod.biotin_5p)
+
+    def test_add_3p_mod_to_circular_strand(self) -> None:
+        self.strand.set_circular(True)
+        with self.assertRaises(sc.StrandError):
+            self.strand.set_modification_3p(mod.biotin_3p)
+
+
 class TestAddStrand(unittest.TestCase):
 
     def test_add_strand__with_loopout(self) -> None:

circular Strands
Add a Boolean field `Strand.circular` and draw a crossover from last substrand to first. Any equivalent cyclic permutation of the substrands should display in the same way.

Even if one doesn't wish the final design to have circular strands, this will help to avoid the problem that sometimes an intermediate design temporarily creates a circular `Strand`, even though subsequent edits make it linear again. Currently such designs are simply not allowed.

See https://github.com/UC-Davis-molecular-computing/scadnano/issues/5.
tests/scadnano_tests.py::TestCircularStrands::test_add_3p_mod_to_circular_strand tests/scadnano_tests.py::TestCircularStrands::test_add_5p_mod_to_circular_strand tests/scadnano_tests.py::TestCircularStrands::test_can_add_internal_mod_to_circular_strand tests/scadnano_tests.py::TestCircularStrands::test_cannot_make_strand_circular_if_3p_mod tests/scadnano_tests.py::TestCircularStrands::test_cannot_make_strand_circular_if_5p_mod
tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__0_0_to_10_cross_1_to_5 tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__0_0_to_10_cross_1_to_5__reverse tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__call_to_then_update_to_legally tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__call_to_twice_decrease_increase_reverse tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__call_to_twice_increase_decrease_forward tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__call_to_twice_legally tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__call_update_to_twice_legally tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__h0_off0_to_off10_cross_h1_to_off5_loopout_length3_h2_to_off15 tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__loopouts_with_labels tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__loopouts_with_labels_to_json tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__multiple_strands tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__multiple_strands_other_order tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__multiple_strands_overlap_error tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__multiple_strands_overlap_no_error tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__two_forward_paranemic_crossovers tests/scadnano_tests.py::TestCreateStrandChainedMethods::test_strand__two_reverse_paranemic_crossovers tests/scadnano_tests.py::TestCreateHelix::test_helix_constructor_no_max_offset_with_major_ticks tests/scadnano_tests.py::TestM13::test_p7249 tests/scadnano_tests.py::TestM13::test_p7560 tests/scadnano_tests.py::TestM13::test_p8064 tests/scadnano_tests.py::TestModifications::test_Cy3 tests/scadnano_tests.py::TestModifications::test_biotin tests/scadnano_tests.py::TestModifications::test_mod_illegal_exceptions_raised tests/scadnano_tests.py::TestModifications::test_to_json_serializable tests/scadnano_tests.py::TestImportCadnanoV2::test_32_helix_rectangle tests/scadnano_tests.py::TestImportCadnanoV2::test_Nature09_monolith tests/scadnano_tests.py::TestImportCadnanoV2::test_Science09_prot120_98_v3 tests/scadnano_tests.py::TestImportCadnanoV2::test_helices_order tests/scadnano_tests.py::TestImportCadnanoV2::test_huge_hex tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__col_major_3p tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__col_major_5p tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__col_major_5p_or_3p tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__col_major_top_left_domain_start tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__duplicate_names_different_purifications tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__duplicate_names_different_scales tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__duplicate_names_different_sequences tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__duplicate_names_same_sequence tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__row_major_3p tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__row_major_5p tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__row_major_5p_or_3p tests/scadnano_tests.py::TestExportDNASequences::test_to_idt_bulk_input_format__row_major_top_left_domain_start tests/scadnano_tests.py::TestExportCadnanoV2::test_16_helix_origami_rectangle_no_twist tests/scadnano_tests.py::TestExportCadnanoV2::test_2_staple_2_helix_origami_deletions_insertions tests/scadnano_tests.py::TestExportCadnanoV2::test_2_staple_2_helix_origami_extremely_simple tests/scadnano_tests.py::TestExportCadnanoV2::test_2_staple_2_helix_origami_extremely_simple_2 tests/scadnano_tests.py::TestExportCadnanoV2::test_6_helix_bundle_honeycomb tests/scadnano_tests.py::TestExportCadnanoV2::test_6_helix_origami_rectangle tests/scadnano_tests.py::TestExportCadnanoV2::test_bad_cases tests/scadnano_tests.py::TestExportCadnanoV2::test_export_design_with_helix_group tests/scadnano_tests.py::TestExportCadnanoV2::test_export_design_with_helix_group_not_same_grid tests/scadnano_tests.py::TestDesignFromJson::test_from_json__from_and_to_file_contents tests/scadnano_tests.py::TestDesignFromJson::test_from_json__helices_non_default_error_if_some_have_idx_not_others tests/scadnano_tests.py::TestDesignFromJson::test_from_json__helices_non_default_error_if_some_have_idx_not_others_mixed_default tests/scadnano_tests.py::TestDesignFromJson::test_from_json__helices_non_default_indices tests/scadnano_tests.py::TestDesignFromJson::test_from_json__helices_non_default_indices_mixed_with_default tests/scadnano_tests.py::TestDesignFromJson::test_from_json__three_strands tests/scadnano_tests.py::TestStrandReversePolarity::test_reverse_all__one_strand tests/scadnano_tests.py::TestStrandReversePolarity::test_reverse_all__three_strands tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__deletions_insertions_in_multiple_domains tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__deletions_insertions_in_multiple_domains_two_strands tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__one_deletion tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__one_deletion_left_of_major_tick tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__one_deletion_on_major_tick tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__one_deletion_one_insertion tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__one_deletion_right_of_major_tick tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__one_insertion tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__one_insertion_left_of_major_tick tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__one_insertion_on_major_tick tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__one_insertion_right_of_major_tick tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__two_deletions tests/scadnano_tests.py::TestInlineInsDel::test_inline_deletions_insertions__two_insertions tests/scadnano_tests.py::TestNickAndCrossover::test_add_full_crossover__small_design_H0_forward tests/scadnano_tests.py::TestNickAndCrossover::test_add_full_crossover__small_design_H0_reverse tests/scadnano_tests.py::TestNickAndCrossover::test_add_full_crossover__small_design_illegal tests/scadnano_tests.py::TestNickAndCrossover::test_add_full_crossover__small_design_illegal_only_one_helix_has_domain tests/scadnano_tests.py::TestNickAndCrossover::test_add_half_crossover__small_design_H0_reverse_0 tests/scadnano_tests.py::TestNickAndCrossover::test_add_half_crossover__small_design_H0_reverse_15 tests/scadnano_tests.py::TestNickAndCrossover::test_add_half_crossover__small_design_H0_reverse_8 tests/scadnano_tests.py::TestNickAndCrossover::test_add_half_crossover__small_design_illegal tests/scadnano_tests.py::TestNickAndCrossover::test_add_nick__6_helix_rectangle tests/scadnano_tests.py::TestNickAndCrossover::test_add_nick__small_design_H0_forward tests/scadnano_tests.py::TestNickAndCrossover::test_add_nick__small_design_H0_reverse tests/scadnano_tests.py::TestNickAndCrossover::test_add_nick__small_design_H1_forward tests/scadnano_tests.py::TestNickAndCrossover::test_add_nick__small_design_H1_reverse tests/scadnano_tests.py::TestNickAndCrossover::test_add_nick__small_design_no_nicks_added tests/scadnano_tests.py::TestNickAndCrossover::test_add_nick__twice_on_same_domain tests/scadnano_tests.py::TestNickAndCrossover::test_add_nick_then_add_crossovers__6_helix_rectangle tests/scadnano_tests.py::TestAutocalculatedData::test_helix_max_offset tests/scadnano_tests.py::TestAutocalculatedData::test_helix_min_max_offsets tests/scadnano_tests.py::TestAutocalculatedData::test_helix_min_max_offsets_illegal_autocalculated tests/scadnano_tests.py::TestAutocalculatedData::test_helix_min_max_offsets_illegal_explicitly_specified tests/scadnano_tests.py::TestSetHelixIdx::test_set_helix_idx tests/scadnano_tests.py::TestHelixGroups::test_JSON_bad_no_groups_but_helices_reference_groups tests/scadnano_tests.py::TestHelixGroups::test_JSON_bad_uses_groups_and_top_level_grid tests/scadnano_tests.py::TestHelixGroups::test_JSON_bad_uses_groups_and_top_level_helices_view_order tests/scadnano_tests.py::TestHelixGroups::test_helix_groups tests/scadnano_tests.py::TestHelixGroups::test_helix_groups_fail_nonexistent tests/scadnano_tests.py::TestHelixGroups::test_helix_groups_to_from_JSON tests/scadnano_tests.py::TestNames::test_strand_domain_names_json tests/scadnano_tests.py::TestNames::test_strand_names_can_be_nonunique tests/scadnano_tests.py::TestJSON::test_Helix_major_tick_periodic_distances tests/scadnano_tests.py::TestJSON::test_Helix_major_tick_start_default_min_offset tests/scadnano_tests.py::TestJSON::test_NoIndent_on_helix_without_position_or_major_ticks_present tests/scadnano_tests.py::TestJSON::test_color_specified_with_integer tests/scadnano_tests.py::TestJSON::test_default_helices_view_order_with_nondefault_helix_idxs_in_default_order tests/scadnano_tests.py::TestJSON::test_default_helices_view_order_with_nondefault_helix_idxs_in_nondefault_order tests/scadnano_tests.py::TestJSON::test_domain_labels tests/scadnano_tests.py::TestJSON::test_error_when_domain_end_missing tests/scadnano_tests.py::TestJSON::test_error_when_domain_forward_and_right_missing tests/scadnano_tests.py::TestJSON::test_error_when_domain_helix_missing tests/scadnano_tests.py::TestJSON::test_error_when_domain_start_missing tests/scadnano_tests.py::TestJSON::test_error_when_grid_missing tests/scadnano_tests.py::TestJSON::test_error_when_strands_missing tests/scadnano_tests.py::TestJSON::test_json_tristan_example_issue_32 tests/scadnano_tests.py::TestJSON::test_lack_of_NoIndent_on_helix_if_position_or_major_ticks_present tests/scadnano_tests.py::TestJSON::test_legacy_dna_sequence_key tests/scadnano_tests.py::TestJSON::test_legacy_right_key tests/scadnano_tests.py::TestJSON::test_legacy_substrands_key tests/scadnano_tests.py::TestJSON::test_nondefault_geometry tests/scadnano_tests.py::TestJSON::test_nondefault_geometry_some_default tests/scadnano_tests.py::TestJSON::test_position_specified_with_origin_keyword tests/scadnano_tests.py::TestJSON::test_strand_idt tests/scadnano_tests.py::TestJSON::test_strand_labels tests/scadnano_tests.py::TestJSON::test_to_json__hairpin tests/scadnano_tests.py::TestJSON::test_to_json__roll tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_assign_dna__conflicting_sequences_directly_assigned tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_assign_dna__conflicting_sequences_indirectly_assigned tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_consecutive_domains_loopout tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_four_legally_leapfrogging_strands tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_helices_not_specified_in_Design_constructor tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_major_tick_just_inside_range tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_major_tick_outside_range tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_overlapping_caught_in_strange_counterexample tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_singleton_loopout tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_strand_offset_beyond_maxbases tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_strand_references_nonexistent_helix tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_strands_and_helices_not_specified_in_Design_constructor tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_strands_not_specified_in_Design_constructor tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_two_illegally_overlapping_strands tests/scadnano_tests.py::TestIllegalStructuresPrevented::test_two_nonconsecutive_illegally_overlapping_strands tests/scadnano_tests.py::TestInsertRemoveDomains::test_3_helix_before_design tests/scadnano_tests.py::TestInsertRemoveDomains::test_append_domain_with_sequence tests/scadnano_tests.py::TestInsertRemoveDomains::test_insert_domain_with_sequence tests/scadnano_tests.py::TestInsertRemoveDomains::test_remove_first_domain_with_sequence tests/scadnano_tests.py::TestInsertRemoveDomains::test_remove_last_domain_with_sequence tests/scadnano_tests.py::TestInsertRemoveDomains::test_remove_middle_domain_with_sequence tests/scadnano_tests.py::TestLabels::test_with_domain_label tests/scadnano_tests.py::TestLabels::test_with_domain_label__and__with_label tests/scadnano_tests.py::TestLabels::test_with_label__dict tests/scadnano_tests.py::TestLabels::test_with_label__str tests/scadnano_tests.py::TestAddStrand::test_add_strand__illegal_overlapping_domains tests/scadnano_tests.py::TestAddStrand::test_add_strand__with_loopout tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__2helix_with_deletions tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__adapter_assigned_from_scaffold_and_tiles tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__adapter_assigned_from_scaffold_and_tiles_with_deletions tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__adapter_assigned_from_scaffold_and_tiles_with_insertions tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__assign_from_strand_multi_other_single tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__assign_seq_with_wildcards tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__assign_to_strand_multi_other_single tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__dna_sequence_shorter_than_complementary_strand_left_strand_longer tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__dna_sequence_shorter_than_complementary_strand_right_strand_longer tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__dna_sequence_with_uncomplemented_domain_on_different_helix tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__dna_sequence_with_uncomplemented_domain_on_different_helix_wildcards_both_ends tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__from_strand_with_loopout tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__hairpin tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__one_helix_with_one_bottom_strand_and_three_top_strands tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__one_strand_assigned_by_complement_from_two_other_strands tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__other_strand_fully_defined_already tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__other_strand_fully_defined_already_and_other_extends_beyond tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__other_strand_fully_defined_already_and_self_extends_beyond tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__to_strand_with_loopout tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__two_equal_length_strands_on_one_helix tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__two_helices_with_multiple_domain_intersections tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__upper_left_edge_staple_of_16H_origami_rectangle tests/scadnano_tests.py::TestAssignDNA::test_assign_dna__wildcards_simple tests/scadnano_tests.py::TestAssignDNAToDomains::test_assign_dna__domain_sequence_too_long_error tests/scadnano_tests.py::TestAssignDNAToDomains::test_assign_dna__to_individual_domains__wildcards_multiple_overlaps tests/scadnano_tests.py::TestAssignDNAToDomains::test_assign_dna__wildcards_multiple_overlaps tests/scadnano_tests.py::TestAssignDNAToDomains::test_method_chaining_with_domain_sequence tests/scadnano_tests.py::TestSubstrandDNASequenceIn::test_dna_sequence_in__right_then_left tests/scadnano_tests.py::TestSubstrandDNASequenceIn::test_dna_sequence_in__right_then_left_deletions tests/scadnano_tests.py::TestSubstrandDNASequenceIn::test_dna_sequence_in__right_then_left_deletions_and_insertions tests/scadnano_tests.py::TestSubstrandDNASequenceIn::test_dna_sequence_in__right_then_left_insertions