scadnano documentation¶
scadnano¶
The scadnano
Python module is a library for describing synthetic DNA nanostructures
(e.g., DNA origami).
Installation instructions are at the
GitHub repository.
The scadnano project is developed and maintained by the UC Davis Molecular Computing group. Note that cadnano is a separate project, developed and maintained by the Douglas lab at UCSF.
This module is used to write Python scripts creating files readable by scadnano, a web application useful for displaying and manually editing synthetic DNA nanostructures. The purpose of this module is to help automate some of the task of creating DNA designs, as well as making large-scale changes to them that are easier to describe programmatically than to do by hand in scadnano.
If you find scadnano useful in a scientific project, please cite its associated paper:
This document describes the API for the scadnano Python package, see the repository for additional documentation, such as installation instructions. There is separate documentation for the scadnano web interface.
This library uses typing hints from the Python typing library. (https://docs.python.org/3/library/typing.html) Each function and method indicate intended types of the parameters. However, due to Python’s design, these types are not enforced at runtime. It is suggested to use a static analysis tool such as that provided by an IDE such as PyCharm (https://www.jetbrains.com/pycharm/) to see warnings when the typing rules are violated. Such warnings probably indicate an erroneous usage.
Most of the classes in this module are Python dataclasses
(https://docs.python.org/3/library/dataclasses.html)
whose fields show up in the documentation.
Their types are listed in parentheses after the name of the class;
for example Color
has int
fields Color.r
, Color.g
, Color.b
.
In general it is safe to read these fields directly, but not to write to them directly.
Setter methods (named set_<fieldname>
) are provided for fields where it makes sense to set it to another
value than it had originally.
However, due to Python naming conventions for dataclass fields and property setters,
it is not straightforward to enforce that the fields cannot be written,
so the user must take care not to set them.
-
class
scadnano.
Color
(r: Union[int, NoneType] = None, g: Union[int, NoneType] = None, b: Union[int, NoneType] = None, hex_string: dataclasses.InitVar = None)¶ -
r
: Optional[int] = None¶ Red component: 0-255.
Optional if
Color.hex
is given.
-
g
: Optional[int] = None¶ Green component: 0-255.
Optional if
Color.hex
is given.
-
b
: Optional[int] = None¶ Blue component: 0-255.
Optional if
Color.hex
is given.
-
-
class
scadnano.
ColorCycler
¶ Calling
next(color_cycler)
on a ColorCycler namedcolor_cycler
returns a the nextColor
from a fixed size list, cycling after reaching the end of the list.To choose new colors, set
color_cycler.colors
to a new list ofColor
’s.-
property
colors
¶ The colors that are cycled through when calling
next()
on someColorCycler
.
-
property
-
scadnano.
default_scaffold_color
= Color(r=0, g=102, b=204)¶ Default color for scaffold strand(s).
-
scadnano.
default_strand_color
= Color(r=0, g=0, b=0)¶ Default color for non-scaffold strand(s).
-
class
scadnano.
Grid
(value)¶ Represents default patterns for laying out helices in the side view. Each
Grid
exceptGrid.none
has an interpretation of a “grid position”, which is a 2D integer coordinate (h, v). (scadnano also allows a 3rd coordinate (h, v, b) specifying a “base offset” at which to position the start of theHelix
, which is not relevant for the side view but will eventually be supported to adjust the main view.)-
square
= 'square'¶ Square lattice. Increasing h moves right and increasing v moves down. (i.e., “computer screen coordinates” rather than Cartesian coordinates where positive y is up.)
-
hex
= 'hex'¶ Hexagonal lattice. Uses the “odd-q horizontal layout” coordinate system described here: https://www.redblobgames.com/grids/hexagons/. Incrementing v moves down. Incrementing h moves down and to the right if h is even, and moves up and to the right if h is odd.
-
honeycomb
= 'honeycomb'¶ Honeycomb lattice. This consists of all the hex lattice positions except where honeycomb lattice disallows grid positions (h, v) with v even and h a multiple of 3 or v odd and h = 1 + a multiple of 3.
However, we use the same convention as cadnano for encoding hex coordinates see misc/cadnano-format-specs/v2.txt. That convention is different from simply excluding coordinates from the hex lattice.
-
none
= 'none'¶ No fixed grid.
-
-
scadnano.
DNA_base_wildcard
= '?'¶ Symbol to insert when a DNA sequence has been assigned to a strand through complementarity, but some regions of the strand are not bound to the strand that was just assigned. Also used in case the DNA sequence assigned to a strand is too short; the sequence is padded with
DNA_base_wildcard
to make its length the same as the length of the strand.
-
class
scadnano.
M13Variant
(value)¶ Variants of M13mp18 viral genome. “Standard” variant is p7249. Other variants are longer.
-
p7249
= 'p7249'¶ “Standard” variant of M13mp18; 7249 bases long, available from, for example
https://www.tilibit.com/collections/scaffold-dna/products/single-stranded-scaffold-dna-type-p7249
https://www.neb.com/products/n4040-m13mp18-single-stranded-dna
-
p7560
= 'p7560'¶ Variant of M13mp18 that is 7560 bases long. Available from, for example
https://www.tilibit.com/collections/scaffold-dna/products/single-stranded-scaffold-dna-type-p7560
-
p8064
= 'p8064'¶ Variant of M13mp18 that is 8064 bases long. Available from, for example
https://www.tilibit.com/collections/scaffold-dna/products/single-stranded-scaffold-dna-type-p8064
-
-
scadnano.
m13
(rotation: int = 5587, variant: scadnano.M13Variant = <M13Variant.p7249: 'p7249'>) → str¶ The M13mp18 DNA sequence (commonly called simply M13).
By default, starts from cyclic rotation 5587 (with 0-based indexing; commonly this is called rotation 5588, which assumes that indexing begins at 1), as defined in GenBank.
By default, returns the “standard” variant of consisting of 7249 bases, sold by companies such as Tilibit. and New England Biolabs
The actual M13 DNA strand itself is circular, so assigning this sequence to the scaffold
Strand
in aDesign
means that the “5’ end” of the scaffoldStrand
(which is a fiction since the actual circular DNA strand has no endpoint) will have the sequence starting at position 5587 starting at the displayed 5’ in scadnano, assigned until the displayed 3’ end. Assuming the displayed scaffoldStrand
has length \(n < 7249\), then a loopout of length \(7249 - n\) consisting of the undisplayed bases will be present in the actual DNA structure. For a more detailed discussion of why this particular rotation of M13 is chosen, see Supplementary Note S8 in [Folding DNA to create nanoscale shapes and patterns. Paul W. K. Rothemund, Nature 440:297-302 (2006)].- Parameters
rotation – rotation of circular strand. Valid values are 0 through length-1.
variant – variant of M13 strand to use
- Returns
M13 strand sequence
-
class
scadnano.
Modification
(display_text: str, id: str = 'WARNING: no id assigned to modification', idt_text: Optional[str] = None)¶ Base class of modifications (to DNA sequences, e.g., biotin or Cy3). Use
Modification3Prime
,Modification5Prime
, orModificationInternal
to instantiate.-
display_text
: str¶ Short text to display in the web interface as an “icon” visually representing the modification, e.g.,
'B'
for biotin or'Cy3'
for Cy3.
-
id
: str = 'WARNING: no id assigned to modification'¶ Representation as a string; used to write in
Strand
json representation, while the full description of the modification is written under a global key in theDesign
. If not specified, butModification.idt_text
is specified, then it will be set equal to that.
-
idt_text
: Optional[str] = None¶ IDT text string specifying this modification (e.g., ‘/5Biosg/’ for 5’ biotin). optional
-
-
class
scadnano.
Modification5Prime
(display_text: str, id: str = 'WARNING: no id assigned to modification', idt_text: Optional[str] = None)¶ 5’ modification of DNA sequence, e.g., biotin or Cy3.
-
class
scadnano.
Modification3Prime
(display_text: str, id: str = 'WARNING: no id assigned to modification', idt_text: Optional[str] = None)¶ 3’ modification of DNA sequence, e.g., biotin or Cy3.
-
class
scadnano.
ModificationInternal
(display_text: str, id: str = 'WARNING: no id assigned to modification', idt_text: Optional[str] = None, allowed_bases: Optional[FrozenSet[str]] = None)¶ Internal modification of DNA sequence, e.g., biotin or Cy3.
-
allowed_bases
: Optional[FrozenSet[str]] = None¶ If None, then this is an internal modification that goes between bases. If instead it is a list of bases, then this is an internal modification that attaches to a base, and this lists the allowed bases for this internal modification to be placed at. For example, internal biotins for IDT must be at a T. If any base is allowed, it should be
['A','C','G','T']
.
-
-
class
scadnano.
Position3D
(x: float = 0, y: float = 0, z: float = 0)¶ Position (x,y,z) in 3D space.
-
x
: float = 0¶ x-coordinate of position. Increasing x moves right in the side view and out of the screen in the main view.
-
y
: float = 0¶ y-coordinate of position. Increasing y moves down in the side and main views, i.e., “screen coordinates”. (though this can be rotated to Cartesian coordinates, where y goes up, by selecting “invert y/z axes” in the View menu of scadnano.)
-
z
: float = 0¶ z-coordinate of position. Increasing z moves right in the main view and into the screen in the side view.
-
-
class
scadnano.
HelixGroup
(position: scadnano.Position3D = Position3D(x=0, y=0, z=0), pitch: float = 0, yaw: float = 0, roll: float = 0, helices_view_order: Optional[List[int]] = None, grid: scadnano.Grid = <Grid.none: 'none'>)¶ Represents a set of properties to apply to a specific group of
Helix
’s in theDesign
.A
HelixGroup
is useful for grouping together helices that should all be in parallel, as part of a design where different groups are not parallel. In particular, eachHelixGroup
can be given its own 3D position and pitch/yaw/roll orientation angles. EachHelixGroup
does not actually contain its helices; they are associated through the field Helix.group, which is a string representing a key in the dictgroups
specified in the constructor forDesign
.If there are
HelixGroup
’s explicitly specified, then the fieldDesign.grid
is ignored. EachHelixGroup
has its own grid, and the fieldsHelix.position
orHelix.grid_position
are considered relative to the origin of thatHelixGroup
(i.e., the valueHelixGroup.position
). Although it is possible to assign aHelix
in aHelixGroup
a non-zeroHelix.pitch
orHelix.yaw
, the most common use case is that all helices in a group are parallel, so they all have these angles equal to 0 (since they are unrotated relative to each other along the pitch and yaw planes).-
position
: scadnano.Position3D = Position3D(x=0, y=0, z=0)¶ The “origin” of this
HelixGroup
.
-
pitch
: float = 0¶ Same meaning as
Helix.pitch
, applied to everyHelix
in the group.
-
roll
: float = 0¶ Same meaning as
Helix.roll
, applied to everyHelix
in the group.
-
helices_view_order
: Optional[List[int]] = None¶ Same meaning as
Design.helices_view_order
, applied to only theHelix
’s in the group.
-
grid
: scadnano.Grid = 'none'¶ Same meaning as
Design.grid
, enforced only on theHelix
’s in the group.
-
helices_view_order_inverse
(idx: int) → int¶ Given a
Helix.idx
in thisHelixGroup
, return its view order.- Parameters
idx – index of
Helix
in thisHelixGroup
- Returns
view order of the
Helix
- Raises
ValueError – if idx is not the index of a
Helix
in thisHelixGroup
-
-
class
scadnano.
Helix
(max_offset: Optional[int] = None, min_offset: int = 0, major_tick_start: Optional[int] = None, major_tick_distance: Optional[int] = None, major_tick_periodic_distances: Optional[List[int]] = None, major_ticks: Optional[List[int]] = None, grid_position: Optional[Tuple[int, int]] = None, position: Optional[scadnano.Position3D] = None, pitch: float = 0, roll: float = 0, yaw: float = 0, idx: Optional[int] = None, group: str = 'default_group', _domains: List[scadnano.Domain] = <factory>)¶ Represents a “helix” where
Domain
’s could go. Technically aHelix
can contain noDomain
’s. More commonly, some partial regions of it may have only 1 or 0Domain
’s. So it is best thought of as a “potential” double-helix.It has a 1-dimensional integer coordinate system given by “offsets”, integers between
Helix.min_offset
(inclusive) andHelix.max_offset
(exclusive). At any valid offset for thisHelix
, at most twoDomain
’s may share that offset on thisHelix
, and if there are exactly two, then one must haveDomain.forward
=true
and the other must haveDomain.forward
=false
.Once part of a
Design
, aHelix
has an index (accessible viaHelix.idx()
once theDesign
is created) representing its order in the list of allHelix
’s. This index is how aDomain
is associated to theHelix
via the integer indexDomain.helix
.-
max_offset
: Optional[int] = None¶ Maximum offset (exclusive) of
Domain
that can be drawn on thisHelix
.Optional field. If unspecified, it is calculated when the
Design
is instantiated as the largestDomain.end
offset of anyDomain
in the design.
-
min_offset
: int = 0¶ Minimum offset (inclusive) of
Domain
that can be drawn on thisHelix
.Optional field. Default value 0.
-
major_tick_start
: Optional[int] = None¶ Offset of first major tick when not specifying
Helix.major_ticks
. Used in combination with eitherHelix.major_tick_distance
orHelix.major_tick_periodic_distances
.Optional field. If not specified, is initialized to value
Helix.min_offset
.
-
major_tick_distance
: Optional[int] = None¶ Distance between major ticks (bold) delimiting boundaries between bases. Major ticks will appear in the visual interface at positions
Optional field. If 0 then no major ticks are drawn. If not specified then the default value is assumed. If the grid is
Grid.square
then the default value is 8. If the grid isGrid.hex
orGrid.honeycomb
then the default value is 7.
-
major_tick_periodic_distances
: Optional[List[int]] = None¶ Periodic distances between major ticks. For example, setting
Helix.major_tick_periodic_distances
= [2, 3] andHelix.major_tick_start
= 10 means that major ticks will appear at 12, 15, 17, 20, 22, 25, 27, 30, …Optional field.
Helix.major_tick_distance
is equivalent to the settingHelix.major_tick_periodic_distances
= [Helix.major_tick_distance
].
-
major_ticks
: Optional[List[int]] = None¶ If not
None
, overridesHelix.major_tick_distance
to specify a list of offsets at which to put major ticks.
-
grid_position
: Optional[Tuple[int, int]] = None¶ (h,v) position of this helix in the side view grid, if
Grid.square
,Grid.hex
, orGrid.honeycomb
is used in theDesign
containing this helix. h and v are in units of “helices”: incrementing h moves right one helix in the grid and incrementing v moves down one helix in the grid. In the case of the hexagonal lattice, The convention is that incrementing v moves down and to the right if h is even, and moves down and to the left if h is odd. This is the “odd-q” coordinate system here: https://www.redblobgames.com/grids/hexagons/) However, the default y position in the main view for helices does not otherwise depend on grid_position. The default is to list the y-coordinates in order by helix idx.Default is h = 0, v = index of
Helix
inDesign.helices
.In the case of the honeycomb lattice, we use the same convention as cadnano for encoding hex coordinates, see misc/cadnano-format-specs/v2.txt. That convention is different from simply excluding coordinates from the hex lattice.
-
position
: Optional[scadnano.Position3D] = None¶ Position (x,y,z) of this
Helix
in 3D space.Must be None if
Helix.grid_position
is specified.
-
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. See https://en.wikipedia.org/wiki/Aircraft_principal_axes 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. See https://en.wikipedia.org/wiki/Aircraft_principal_axes Units are degrees.
-
yaw
: float = 0¶ Third angle for orientation besides
Helix.pitch
andHelix.roll
. Not visually displayed in scadnano, but here to support more general 3D applications. See https://en.wikipedia.org/wiki/Aircraft_principal_axes Units are degrees.
-
idx
: Optional[int] = None¶ Index of this
Helix
.Optional if no other
Helix
specifies a value for idx. Default is the order of theHelix
is listed in constructor forDesign
.
-
group
: str = 'default_group'¶ Name of the
HelixGroup
to which thisHelix
belongs.
-
calculate_major_ticks
(grid: scadnano.Grid) → List[int]¶ Calculates full list of major tick marks, whether using default_major_tick_distance (from
Design
),Helix.major_tick_distance
, orHelix.major_ticks
. They are used in reverse order to determine precedence. (e.g.,Helix.major_ticks
overridesHelix.major_tick_distance
, which overrides default_major_tick_distance fromDesign
.
-
-
class
scadnano.
Domain
(helix: int, forward: bool, start: int, end: int, deletions: List[int] = <factory>, insertions: List[Tuple[int, int]] = <factory>, name: Optional[str] = None, label: Optional[DomainLabel] = None)¶ A maximal portion of a
Strand
that is continguous on a singleHelix
. AStrand
contains a list ofDomain
’s (and also potentiallyLoopout
’s).-
forward
: bool¶ Whether the strand “points” forward (i.e., its 3’ end has a larger offset than its 5’ end). If
Domain.forward
isTrue
, thenDomain.start
is the 5’ end of theDomain
andDomain.end
is the 3’ end of theDomain
. IfDomain.forward
isFalse
, these roles are reversed.
-
start
: int¶ The smallest offset position of any base on this Domain (3’ end if
Domain.forward
=False
, 5’ end ifDomain.forward
=True
).
-
end
: int¶ 1 plus the largest offset position of any base on this Domain (5’ end if
Domain.forward
=False
, 3’ end ifDomain.forward
=True
). Note that the set of base offsets occupied by this Domain is {start, start+1, …, end-1}, i.e., inclusive forStrand.start
but exclusive forStrand.end
, the same convention used in Python for slices of lists and strings. (e.g.,"abcdef"[1:3] == "bc"
)Some methods (such as
Domain.dna_sequence_in()
) use the convention of being inclusive on both ends and are marked with the word “INCLUSIVE”. (Such a convention is easier to reason about when there are insertions and deletions.)
-
deletions
: List[int]¶ List of positions of deletions on this Domain.
-
insertions
: List[Tuple[int, int]]¶ List of (position,num_insertions) pairs on this Domain.
This is the number of extra bases in addition to the base already at this position. The total number of bases at this offset is num_insertions+1.
-
name
: Optional[str] = None¶ Optional name to give this
Domain
.This is used to interoperate with the dsd DNA sequence design package.
-
label
: Optional[DomainLabel] = None¶ Generic “label” object to associate to this
Domain
.Useful for associating extra information with the
Domain
that will be serialized, for example, for DNA sequence design. It must be an object (e.g., a dict or primitive type such as str or int) that is naturally JSON serializable. (Calling json.dumps on the object should succeed without having to specify a custom encoder.)
-
strand
() → scadnano.Strand¶
-
contains_offset
(offset: int) → bool¶ Indicates if offset is the offset of a base on this
Domain
.Note that offsets refer to visual portions of the displayed grid for the Helix. If for example, this Domain starts at position 0 and ends at 10, and it has 5 deletions, then it contains the offset 7 even though there is no base 7 positions from the start.
-
dna_length
() → int¶ Number of bases in this Domain.
-
dna_length_in
(left: int, right: int) → int¶ Number of bases in this Domain between offsets left and right (INCLUSIVE).
-
visual_length
() → int¶ Distance between
Domain.start
offset andDomain.end
offset.This can be more or less than the
Domain.dna_length()
due to insertions and deletions.
-
dna_sequence
() → Optional[str]¶ Return DNA sequence of this Domain, or
None
if no DNA sequence has been assigned to thisDomain
’sStrand
.
-
dna_sequence_in
(offset_left: int, offset_right: int) → Optional[str]¶ Return DNA sequence of this Domain in the interval of offsets given by [offset_left, offset_right], INCLUSIVE, or
None
if no DNA sequence has been assigned to thisDomain
’sStrand
.WARNING: This is inclusive on both ends, unlike other parts of this API where the right endpoint is exclusive. This is to make the notion well-defined when one of the endpoints is on an offset with a deletion or insertion.
-
get_seq_start_idx
() → int¶ Starting DNA subsequence index for first base of this
Domain
on its ParentStrand
’s DNA sequence.
-
domain_offset_to_strand_dna_idx
(offset: int, offset_closer_to_5p: bool) → int¶ Convert from offset on this
Domain
’sHelix
to string index on the parentStrand
’s DNA sequence.If offset_closer_to_5p is
True
, (this only matters if offset contains an insertion) then the only leftmost string index corresponding to this offset is included, otherwise up to the rightmost string index (including all insertions) is included.
-
overlaps
(other: scadnano.Domain) → bool¶ Indicates if this
Domain
’s set of offsets (the set \(\{x \in \mathbb{N} \mid\)self.start
\(\leq x \leq\)self.end
\(\}\)) has nonempty intersection with those of other, and they appear on the same helix, and they point in opposite directions.
-
overlaps_illegally
(other: scadnano.Domain) → bool¶ Indicates if this
Domain
’s set of offsets (the set \(\{x \in \mathbb{N} \mid\)self.start
\(\leq x \leq\)self.end
\(\}\)) has nonempty intersection with those of other, and they appear on the same helix, and they point in the same direction.
-
compute_overlap
(other: scadnano.Domain) → Tuple[int, int]¶ Return [left,right) offset indicating overlap between this Domain and other.
Return
(-1,-1)
if they do not overlap (different helices, or non-overlapping regions of the same helix).
-
insertion_offsets
() → List[int]¶ Return offsets of insertions (but not their lengths).
-
-
class
scadnano.
Loopout
(length: int, name: Optional[str] = None, label: Optional[DomainLabel] = None)¶ Represents a single-stranded loopout on a
Strand
.One could think of a
Loopout
as a type ofDomain
, but none of the fields ofDomain
make sense forLoopout
, so they are not related to each other in the type hierarchy. It is interpreted that aLoopout
is a single-stranded region bridging twoDomain
’s that are connected toHelix
’s. It is illegal for two consecutiveDomain
’s to both beLoopout
’s, or for aLoopout
to occur on either end of theStrand
(i.e., eachStrand
must begin and end with aDomain
).For example, one use of a loopout is to describe a hairpin (a.k.a., stem-loop). The following creates a
Strand
that represents a hairpin with a stem length of 10 and a loop length of 5.import scadnano as sc domain_f = sc.Domain(helix=0, forward=True, start=0, end=10) loop = sc.Loopout(length=5) domain_r = sc.Domain(helix=0, forward=False, start=0, end=10) hairpin = sc.Strand([domain_f, loop, domain_r])
It can also be created with chained method calls
import scadnano as sc design = sc.Design(helices=[sc.Helix(max_offset=10)]) design.strand(0,0).move(10).loopout(0,5).move(-10)
-
name
: Optional[str] = None¶ Optional name to give this
Loopout
.This is used to interoperate with the dsd DNA sequence design package.
-
label
: Optional[DomainLabel] = None¶ Generic “label” object to associate to this
Loopout
.Useful for associating extra information with the
Loopout
that will be serialized, for example, for DNA sequence design. It must be an object (e.g., a dict or primitive type such as str or int) that is naturally JSON serializable. (Calling json.dumps on the object should succeed without having to specify a custom encoder.)
-
strand
() → scadnano.Strand¶
-
dna_length
() → int¶ Length of this
Loopout
; same as fieldLoopout.length
.
-
-
scadnano.
wc
(seq: str) → str¶ Return reverse Watson-Crick complement of seq.
-
class
scadnano.
IDTFields
(scale: str = '25nm', purification: str = 'STD', plate: Optional[str] = None, well: Optional[str] = None)¶ Data required when ordering DNA strands from the synthesis company IDT (Integrated DNA Technologies). This data is used when automatically generating files used to order DNA from IDT.
When exporting to IDT files via
Design.write_idt_plate_excel_file()
orDesign.write_idt_bulk_input_file()
, the fieldStrand.name
is used for the name if it exists, otherwise a reasonable default is chosen.-
scale
: str = '25nm'¶ Synthesis scale at which to synthesize the strand (third field in IDT bulk input: https://www.idtdna.com/site/order/oligoentry). Choices supplied by IDT at the time this was written:
"25nm"
,"100nm"
,"250nm"
,"1um"
,"5um"
,"10um"
,"4nmU"
,"20nmU"
,"PU"
,"25nmS"
.Optional field.
-
purification
: str = 'STD'¶ Purification options (fourth field in IDT bulk input: https://www.idtdna.com/site/order/oligoentry). Choices supplied by IDT at the time this was written:
"STD"
,"PAGE"
,"HPLC"
,"IEHPLC"
,"RNASE"
,"DUALHPLC"
,"PAGEHPLC"
.Optional field.
-
plate
: Optional[str] = None¶ Name of plate in case this strand will be ordered on a 96-well or 384-well plate.
Optional field, but non-optional if
IDTField.well
is notNone
.
-
well
: Optional[str] = None¶ Well position on plate in case this strand will be ordered on a 96-well or 384-well plate.
Optional field, but non-optional if
IDTField.plate
is notNone
.
-
-
class
scadnano.
StrandBuilder
(design: scadnano.Design[StrandLabel, DomainLabel], helix: int, offset: int)¶ Represents a
Strand
that is being built in an existingDesign
.This is an intermediate object created when using chained method building by calling
Design.strand()
, for exampledesign.strand(0, 0).to(10).cross(1).to(5).with_modification_5p(mod.biotin_5p).as_scaffold()
StrandBuilder
should generally not be created directly. Although it is convenient to use chained method calls, it is also sometimes useful to assign theStrandBuilder
object into a variable and then call the methods on that variable. For example, this code is equivalent to the above line:strand_builder = design.strand(0, 0) strand_builder.to(10) strand_builder.cross(1) strand_builder.to(5) strand_builder.with_modification_5p(mod.biotin_5p) strand_builder.as_scaffold()
-
cross
(helix: int, offset: Optional[int] = None, move: Optional[int] = None) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Add crossover. To have any effect, must be followed by call to
StrandBuilder.to()
orStrandBuilder.move()
.- Parameters
helix –
Helix
to crossover tooffset – new offset on helix. If not specified, defaults to current offset. (i.e., a “vertical” crossover) Mutually excusive with move.
move – Relative distance to new offset on helix from current offset. If not specified, defaults to using parameter offset. Mutually excusive with offset.
- Returns
self
-
loopout
(helix: int, length: int, offset: Optional[int] = None, move: Optional[int] = None) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Like
StrandBuilder.cross()
, but creates aLoopout
instead of a crossover.- Parameters
helix –
Helix
to crossover tolength – length of
Loopout
to addoffset – new offset on helix. If not specified, defaults to current offset. (i.e., a “vertical” loopout) Mutually excusive with move.
move – Relative distance to new offset on helix from current offset. If not specified, defaults to using parameter offset. Mutually excusive with offset.
- Returns
self
-
move
(delta: int) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Extends this
StrandBuilder
on the current helix to offset given by the current offset plus delta, which adds a newDomain
to theStrand
being built. This is a “relative move”, whereasStrandBuilder.to()
andStrandBuilder.update_to()
are “absolute moves”.This updates the underlying
Design
with a newDomain
, and ifStrandBuilder.loopout()
was last called on thisStrandBuilder
, also a newLoopout
.If two instances of
StrandBuilder.move()
are chained together, this creates two domains on the same helix. The two offsets must move in the same direction. In other words, if we call.move(o1).move(o2)
, theno1
ando2
must be either both negative or both positive.- Parameters
delta – Distance to new offset to extend to, compared to current offset. If less than current offset, the new
Domain
is reverse, otherwise it is forward.- Returns
self
-
to
(offset: int) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Extends this
StrandBuilder
on the current helix to offset offset, which adds a newDomain
to theStrand
being built. This is an “absolute move”, whereasStrandBuilder.move()
is a “relative move”.This updates the underlying
Design
with a newDomain
, and ifStrandBuilder.loopout()
was last called on thisStrandBuilder
, also a newLoopout
.If two instances of
StrandBuilder.to()
are chained together, this creates two domains on the same helix. The two offsets must move in the same direction. In other words, if the starting offset iss
, and we call.to(o1).to(o2)
, then eithers < o1 < o2
oro2 < o1 < s
must be true.To simply change the current offset after calling
StrandBuilder.to()
, without creating a new Domain, callStrandBuilder.update_to()
instead.- Parameters
offset – new offset to extend to. If less than current offset, the new
Domain
is reverse, otherwise it is forward.- Returns
self
-
update_to
(offset: int) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Like
StrandBuilder.to()
, but changes the current offset without creating a newDomain
. So unlikeStrandBuilder.to()
, several consecutive calls toStrandBuilder.update_to()
are equivalent to only making the final call. This is an “absolute move”, whereasStrandBuilder.move()
is a “relative move”.If
StrandBuilder.cross()
orStrandBuilder.loopout()
was just called, thenStrandBuilder.to()
andStrandBuilder.update_to()
have the same effect.- Parameters
offset – new offset to extend to. If less than offset of the last call to
StrandBuilder.cross()
orStrandBuilder.loopout()
, the newDomain
is reverse, otherwise it is forward.- Returns
self
-
as_circular
() → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Makes
Strand
being built circular.- Returns
self
-
as_scaffold
() → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Makes
Strand
being built a scaffold.- Returns
self
-
with_idt
(scale: str = '25nm', purification: str = 'STD', plate: Optional[str] = None, well: Optional[str] = None) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Gives
IDTFields
value toStrand
being built. Only a name is required; other fields are given reasonable default values.- Parameters
scale – see
IDTFields.scale
purification – see
IDTFields.purification
plate – see
IDTFields.plate
well – see
IDTFields.well
- Returns
self
-
with_modification_5p
(mod: scadnano.Modification5Prime) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Sets Strand being built to have given 5’ modification.
- Parameters
mod – 5’ modification
- Returns
self
-
with_modification_3p
(mod: scadnano.Modification3Prime) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Sets Strand being built to have given 3’ modification.
- Parameters
mod – 3’ modification
- Returns
self
-
with_modification_internal
(idx: int, mod: scadnano.ModificationInternal, warn_on_no_dna: bool) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Sets Strand being built to have given internal modification.
- Parameters
idx – idx along DNA sequence of internal modification
mod – internal modification
warn_on_no_dna – whether to print warning to screen if DNA has not been assigned
- Returns
self
-
with_color
(color: scadnano.Color) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Sets Strand being built to have given color.
- Parameters
color – color to set for Strand
- Returns
self
-
with_sequence
(sequence: str, assign_complement: bool = True) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Assigns sequence as DNA sequence of the
Strand
being built. This should be done after theStrand
’s structure is done being built, e.g.,design.strand(0, 0).to(10).cross(1).to(5).with_sequence('AAAAAAAAAACGCGC')
- Parameters
sequence – the DNA sequence to assign to the
Strand
assign_complement – whether to automatically assign the complement to existing
Strand
’s bound to thisStrand
. This has the same meaning as the parameter assign_complement inDesign.assign_dna()
.
- Returns
self
-
with_domain_sequence
(sequence: str, assign_complement: bool = True) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Assigns sequence as DNA sequence of the most recently created
Domain
in theStrand
being built. This should be called immediately after aDomain
is created via a call toStrandBuilder.to()
,StrandBuilder.update_to()
, orStrandBuilder.loopout()
, e.g.,design.strand(0, 5).to(8).with_domain_sequence('AAA')\ .cross(1).to(5).with_domain_sequence('TTT')\ .loopout(2, 4).with_domain_sequence('CCCC')\ .to(10).with_domain_sequence('GGGGG')
- Parameters
sequence – the DNA sequence to assign to the
Domain
assign_complement – whether to automatically assign the complement to existing
Strand
’s bound to thisStrand
. This has the same meaning as the parameter assign_complement inDesign.assign_dna()
.
- Returns
self
-
with_name
(name: str) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Assigns name as name of the
Strand
being built.design.strand(0, 0).to(10).cross(1).to(5).with_name('scaffold')
- Parameters
name – name to assign to the
Strand
- Returns
self
-
with_label
(label: StrandLabel) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Assigns label as label of the
Strand
being built.design.strand(0, 0).to(10).cross(1).to(5).with_label('scaffold')
- Parameters
label – label to assign to the
Strand
- Returns
self
-
with_domain_name
(name: str) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Assigns name as of the most recently created
Domain
orLoopout
in theStrand
being built. This should be called immediately after aDomain
is created via a call toStrandBuilder.to()
,StrandBuilder.update_to()
, orStrandBuilder.loopout()
, e.g.,design.strand(0, 0).to(10).with_domain_name('dom1*').cross(1).to(5).with_domain_name('dom1')
-
with_domain_label
(label: DomainLabel) → scadnano.StrandBuilder[StrandLabel, DomainLabel]¶ Assigns label as label of the most recently created
Domain
orLoopout
in theStrand
being built. This should be called immediately after aDomain
is created via a call toStrandBuilder.to()
,StrandBuilder.update_to()
, orStrandBuilder.loopout()
, e.g.,design.strand(0, 5).to(8).with_domain_label('domain 1')\ .cross(1).to(5).with_domain_label('domain 2')\ .loopout(2, 4).with_domain_label('domain 3')\ .to(10).with_domain_label('domain 4')
-
-
class
scadnano.
Strand
(domains: List[Union[scadnano.Domain[DomainLabel], scadnano.Loopout[DomainLabel]]], circular: bool = False, dna_sequence: Optional[str] = None, color: Optional[scadnano.Color] = None, idt: Optional[scadnano.IDTFields] = None, is_scaffold: bool = False, modification_5p: Optional[scadnano.Modification5Prime] = None, modification_3p: Optional[scadnano.Modification3Prime] = None, modifications_int: Dict[int, scadnano.ModificationInternal] = <factory>, name: Optional[str] = None, label: Optional[StrandLabel] = None)¶ Represents a single strand of DNA.
Each maximal portion that is continguous on a single
Helix
is aDomain
. Crossovers from oneHelix
to another are implicitly from the 3’ end of one of this Strand’sDomain
’s to the 5’ end of the nextDomain
.A portion of the
Strand
not associated to anyHelix
is represented by aLoopout
. TwoLoopout
’s cannot occur consecutively on aStrand
, nor can aStrand
contain only aLoopout
but noDomain
.One can set the strand to be a scaffold in the constructor:
import scadnano as sc scaffold_domains = [ ... ] scaffold_strand = sc.Strand(domains=scaffold_domains, is_scaffold=True)
or by calling
Strand.set_scaffold()
on theStrand
object:import scadnano as sc scaffold_domains = [ ... ] scaffold_strand = sc.Strand(domains=scaffold_domains) scaffold_strand.set_scaffold()
Both will give the strand the same color that cadnano uses for the scaffold.
-
domains
: List[Union[scadnano.Domain[DomainLabel], scadnano.Loopout[DomainLabel]]]¶ Domain
’s (orLoopout
’s) composing this Strand. EachDomain
is contiguous on a singleHelix
and could be either single-stranded or double-stranded, whereas eachLoopout
is single-stranded and has no associatedHelix
.
-
circular
: bool = False¶ If True, this
Strand
is circular and has no 5’ or 3’ end. Although there is still a first and lastDomain
, 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 ofStrand.domains
should result in a functionally equivalentStrand
. It is illegal to have aModification5Prime
orModification3Prime
on a circularStrand
.
-
dna_sequence
: Optional[str] = None¶ Do not assign directly to this field. Always use
Design.assign_dna
(for complementarity checking) orStrand.set_dna_sequence
(without complementarity checking, to allow mismatches).
-
color
: Optional[scadnano.Color] = None¶ Color to show this strand in the main view. If not specified in the constructor, a color is assigned by cycling through a list of defaults given by
ColorCycler.colors()
-
idt
: Optional[scadnano.IDTFields] = None¶ Fields used when ordering strands from the synthesis company IDT (Integrated DNA Technologies, Coralville, IA). If present (i.e., not equal to
None
) then the methodDesign.write_idt_bulk_input_file()
can be called to automatically generate an text file for ordering strands in test tubes: https://www.idtdna.com/site/order/oligoentry, as can the methodDesign.write_idt_plate_excel_file()
for writing a Microsoft Excel file that can be uploaded to IDT’s website for describing DNA sequences to be ordered in 96-well or 384-well plates.
-
is_scaffold
: bool = False¶ Indicates whether this
Strand
is a scaffold for a DNA origami. If anyStrand
in aDesign
is a scaffold, then the design is considered a DNA origami design.
-
modification_5p
: Optional[scadnano.Modification5Prime] = None¶ 5’ modification; None if there is no 5’ modification. Illegal to have if
Strand.circular
is True.
-
modification_3p
: Optional[scadnano.Modification3Prime] = None¶ 3’ modification; None if there is no 3’ modification. Illegal to have if
Strand.circular
is True.
-
modifications_int
: Dict[int, scadnano.ModificationInternal]¶ Modification
’s to the DNA sequence (e.g., biotin, Cy3/Cy5 fluorphores). Maps offset to modification. If the internal modification is attached to a base (e.g., internal biotin, /iBiodT/ from IDT), then the offset is that of the base. If it goes between two bases (e.g., internal Cy3, /iCy3/ from IDT), then the offset is that of the previous base, e.g., to put a Cy3 between bases at offsets 3 and 4, the offset should be 3. So for an internal modified base on a sequence of length n, the allowed offsets are 0,…,n-1, and for an internal modification that goes between bases, the allowed offsets are 0,…,n-2.
-
name
: Optional[str] = None¶ Optional name to give the strand. If specified it is shown on mouseover in the scadnano web interface.
This is used to interoperate with the dsd DNA sequence design package.
-
label
: Optional[StrandLabel] = None¶ Generic “label” object to associate to this
Strand
.Useful for associating extra information with the Strand that will be serialized, for example, for DNA sequence design. It must be an object (e.g., a dict or primitive type such as str or int) that is naturally JSON serializable. (Calling
json.dumps
on the object should succeed without having to specify a custom encoder.)
-
rotate_domains
(rotation: int, forward: bool = True) → None¶ “Rotates” the strand by replacing domains with a circular rotation, e.g., if the domains are
A, B, C, D, E, F
then
strand.rotate_domains(2)
makes theStrand
have the same domains, but in this order:E, F, A, B, C, D
and
strand.rotate_domains(2, forward=False)
makesC, D, E, F, A, B
- Parameters
rotation – Amount to rotate domains.
forward – Whether to move domains forward (wrapping off 3’ end back to 5’ end) or backward (wrapping off 5’ end back to 3’ end).
-
set_scaffold
(is_scaf: bool = True) → None¶ Sets this
Strand
as a scaffold. Alters color to default scaffold color.If is_scaf ==
False
, sets this strand as not a scaffold, and leaves the color alone.
-
set_color
(color: scadnano.Color) → None¶ Sets color of this
Strand
.
-
set_circular
(circular: bool = True) → None¶ Sets this to be a circular
Strand
(or non-circular if optional parameter is False).- Parameters
circular – whether to make this
Strand
circular (True) or linear (False)- Raises
StrandError – if this
Strand
has a 5’ or 3’ modification
-
set_linear
() → None¶ Makes this a linear (non-circular)
Strand
. Equivalent to calling self.set_circular(False).
-
set_domains
(domains: Iterable[Union[scadnano.Domain[DomainLabel], scadnano.Loopout[DomainLabel]]]) → None¶ Sets the
Domain
’s/Loopout
’s of thisStrand
to be domains, which can contain a mix ofDomain
’s andLoopout
’s, just like the fieldStrand.domains
.
-
idt_export_name
(unique_names: bool = False) → str¶ - Parameters
unique_names – If True and default name is used, enforces that strand names must be unique by encoding the forward/reverse Boolean into the name. If False (the default), uses cadnano’s exact naming convention, which allows two strands to have the same default name, if they begin and end at the same (helix,offset) pair (but point in opposite directions at each). Has no effect if
Strand.idt
orStrand.name
are defined; if those are used, they must be explicitly set to be unique.- Returns
If
Strand.name
is not None, returnStrand.name
, otherwise return the result ofStrand.default_export_name()
with parameter unique_names.
-
default_export_name
(unique_names: bool = False) → str¶ Returns a default name to use when exporting the DNA sequence. Uses cadnano’s naming convention of, for example ‘ST2[5]4[10]’ to indicate a strand that starts at helix 2, offset 5, and ends at helix 4, offset 10. Note that this naming convention is not unique: two strands in the system could share this name. To ensure it is unique, set the parameter unique_names to True, which will modify the name with forward/reverse information from the first domain that uniquely identifies the strand, e.g., ‘ST2[5]F4[10]’ or ‘ST2[5]R4[10]’.
If the strand is a scaffold (i.e., if
Strand.is_scaffold
is True), then the name will begin with ‘SCAF’ instead of ‘ST’.- Parameters
unique_names – If True, enforces that strand names must be unique by encoding the forward/reverse Boolean into the name. If False (the default), uses cadnano’s exact naming convention, which allows two strands to have the same default name, if they begin and end at the same (helix,offset) pair (but point in opposite directions at each).
- Returns
default name to export (used, for example, by idt DNA export methods
Design.write_idt_plate_excel_file()
andDesign.write_idt_bulk_input_file()
ifStrand.name
andStrand.idt.name
are both not set)
-
set_modification_5p
(mod: Optional[scadnano.Modification5Prime] = None) → None¶ Sets 5’ modification to be mod. mod cannot be non-None if
Strand.circular
is True.
-
set_modification_3p
(mod: Optional[scadnano.Modification3Prime] = None) → None¶ Sets 3’ modification to be mod. mod cannot be non-None if
Strand.circular
is True.
-
remove_modification_5p
() → None¶ Removes 5’ modification.
-
remove_modification_3p
() → None¶ Removes 3’ modification.
-
set_modification_internal
(idx: int, mod: scadnano.ModificationInternal, warn_on_no_dna: bool = True) → None¶ Adds internal modification mod at given DNA index idx.
-
remove_modification_internal
(idx: int) → None¶ Removes internal modification at given DNA index idx.
-
first_domain
() → scadnano.Domain¶ First domain on this
Strand
.
-
last_domain
() → scadnano.Domain¶ Last domain on this
Strand
.
-
set_dna_sequence
(sequence: str) → None¶ Set this
Strand
’s DNA sequence to seq WITHOUT checking for complementarity with overlappingStrand
’s or automatically assigning their sequences. To assign a sequence to aStrand
and have the overlappingStrand
’s automatically have the appropriate Watson-Crick complements assigned, useDesign.assign_dna
.All whitespace in sequence is removed, and lowercase bases ‘a’, ‘c’, ‘g’, ‘t’ are converted to uppercase.
sequence, after all whitespace is removed, must be exactly the same length as
Strand.dna_length()
. Wildcard symbols (DNA_case_wildcard
) are allowed to leave part of the DNA unassigned.
-
bound_domains
() → List[scadnano.Domain]¶
-
overlaps
(other: scadnano.Strand) → bool¶ Indicates whether self overlaps other_strand, meaning that the set of offsets occupied by self has nonempty intersection with those occupied by other_strand.
-
assign_dna_complement_from
(other: scadnano.Strand) → None¶ Assuming a DNA sequence has been assigned to other, assign its Watson-Crick complement to the portions of this Strand that are bound to other.
Generally this is not called directly; use
Design.assign_dna()
to assign a DNA sequence to aStrand
. The methodDesign.assign_dna()
will calculate which otherStrand
’s need to be assigned viaStrand.assign_dna_complement_from()
.However, it is permitted to assign the field
Strand.dna_sequence
directly via the methodStrand.set_dna_sequence()
. This is used, for instance, to assign a DNA sequence to aStrand
bound to anotherStrand
with an assigned DNA sequence where they overlap. In this case no error checking about sequence complementarity is done. This can be used to intentionally assign mismatching DNA sequences toStrand
’s that are bound on aHelix
.
-
dna_index_start_domain
(domain: Union[scadnano.Domain, scadnano.Loopout]) → int¶ Returns index in DNA sequence of domain, e.g., if there are five domains
012 3 45 678 9 AAA-C-GG-TTT-ACGT
Then their indices, respectively in order, are 0, 3, 4, 6, 9.
- Parameters
domain –
- any
to find the start DNA index of
- Returns
index (within DNA sequence string) of substring of DNA starting with given
Domain
-
first_bound_domain
() → scadnano.Domain¶ First
Domain
(i.e., not aLoopout
) on thisStrand
.Currently the first and last strand must not be
Loopout
’s, so this should return the same domain asStrand.first_domain()
, but in case an initial or finalLoopout
is supported in the future, this method is provided.
-
last_bound_domain
() → scadnano.Domain¶ Last
Domain
(i.e., not aLoopout
) on thisStrand
.Currently the first and last strand must not be
Loopout
’s, so this should return the same domain asStrand.first_domain()
, but in case an initial or finalLoopout
is supported in the future, this method is provided.
-
reverse
() → None¶ Reverses “polarity” of this
Strand
.Does NOT check whether this keeps the
Design
legal, so be cautious in calling this method directly. To reverse everyStrand
, calledDesign.reverse_all()
. If the design was legal before, it will be legal after calling that method.
-
no_modifications_version
() → scadnano.Strand¶ - Returns
version of this
Strand
with no DNA modifications.
-
-
class
scadnano.
StrandOrder
(value)¶ Which part of a
Strand
to use for sorting in the key function returned bystrand_order_key_function()
.-
five_prime
= 0¶ 5’ end of the strand
-
three_prime
= 1¶ 3’ end of the strand
-
five_or_three_prime
= 2¶ Either 5’ end or 3’ end is used, whichever is first according to the sort order.
-
top_left_domain
= 3¶ The start offset of the “top-left”
Domain
of theStrand
: theDomain
whoseDomain.helix
is minimal, and, among all suchDomain
’s, the one with minimalDomain.start
.
-
-
scadnano.
strand_order_key_function
(*, column_major: bool = True, strand_order: scadnano.StrandOrder) → Callable[[scadnano.Strand], Any]¶ Returns a key function indicating a sorted order for
Strand
’s. Useful as a parameter forDesign.()
.- Parameters
column_major – If true, column major order is used: ordered by base offset first, then by helix. Otherwise row-major order is used: ordered by helix first, then by base offset.
strand_order – Which part of the strand to use as a key for the sorted order. See
StrandOrder
for definitions.
- Returns
A key function that can be passed to
Design.()
to specify a sorted order for theStrand
’s.
-
exception
scadnano.
IllegalDesignError
(the_cause: str)¶ Indicates that some aspect of the
Design
object is illegal.
-
exception
scadnano.
StrandError
(strand: scadnano.Strand, the_cause: str)¶ Indicates that the
Design
is illegal due to some specificStrand
. Information about theStrand
is embedded in the error message when this exception is raised that helps to identify whichStrand
caused the problem.
-
class
scadnano.
PlateType
(value)¶ Represents two different types of plates in which DNA sequences can be ordered.
-
wells96
= 96¶ 96-well plate.
-
wells384
= 384¶ 384-well plate.
-
-
class
scadnano.
Geometry
(rise_per_base_pair: float = 0.332, helix_radius: float = 1.0, bases_per_turn: float = 10.5, minor_groove_angle: float = 150.0, inter_helix_gap: float = 1.0)¶ Parameters controlling some geometric visualization/physical aspects of Design.
-
rise_per_base_pair
: float = 0.332¶ Distance in nanometers between two adjacent base pairs along the length of a DNA double helix.
-
helix_radius
: float = 1.0¶ Radius of a DNA helix in nanometers.
-
bases_per_turn
: float = 10.5¶ Number of DNA base pairs in a full turn of DNA.
-
minor_groove_angle
: float = 150.0¶ Minor groove angle in degrees.
-
inter_helix_gap
: float = 1.0¶ Gap between helices in nanometers (due to electrostatic repulsion; needed to display to scale).
-
-
class
scadnano.
Design
(*, helices: Optional[Union[List[scadnano.Helix], Dict[int, scadnano.Helix]]] = None, groups: Optional[Dict[str, scadnano.HelixGroup]] = None, strands: Optional[List[scadnano.Strand]] = None, grid: Optional[scadnano.Grid] = None, helices_view_order: Optional[List[int]] = None, geometry: Optional[scadnano.Geometry] = None)¶ Object representing the entire design of the DNA structure.
-
automatically_assign_color
: bool = True¶ If automatically_assign_color =
False
, then for anyStrand
such that Strand.color =None
, do not automatically assign aColor
to it. In this case color will be set to its default ofNone
and will not be written to the JSON withDesign.write_scadnano_file()
orDesign.to_json()
.
-
strands
: List[scadnano.Strand[StrandLabel, DomainLabel]]¶ All of the
Strand
’s in thisDesign
.Required field.
-
geometry
: scadnano.Geometry¶ Controls some geometric/physical aspects of this
Design
.
-
groups
: Dict[str, scadnano.HelixGroup] = None¶ HelixGroup
’s in thisDesign
.
-
helices
: Dict[int, scadnano.Helix] = None¶ All of the
Helix
’s in thisDesign
. This is a dictionary mapping index to theHelix
with that index; if helices have indices 0, 1, …, num_helices-1, then this can be used as a list of Helices.Optional field. If not specified, then the number of helices will be just large enough to store the largest index
Domain.helix
stored in anyDomain
inDesign.strands
.
-
property
helices_view_order
¶ Return helices_view_order of this
Design
if noHelixGroup
’s are being used, otherwise raise a ValueError.- Returns
helices_view_order of this
Design
-
property
grid
¶ Return grid of this
Design
if noHelixGroup
’s are being used, otherwise raise a ValueError.- Returns
grid of this
Design
-
set_grid
(grid: scadnano.Grid) → None¶ Sets the grid of the default
HelixGroup
, if the default is being used, otherwise raises an exception.- Parameters
grid – new grid to set for the (only)
HelixGroup
in thisDesign
- Raises
IllegalDesignError – if there is more than one
HelixGroup
in thisDesign
-
helices_idxs_in_group
(group_name: str) → List[int]¶ Indexes of
Helix
’s in this group. Must be associated with aDesign
for this to work.- Parameters
group_name – name of group
- Returns
list of indices of
Helix
’s in thisHelixGroup
-
static
from_scadnano_file
(filename: str) → scadnano.Design¶ Loads a
Design
from the file with the given name.- Parameters
filename – name of the file with the design. Should be a JSON file ending in .dna
- Returns
Design described in the file
-
static
from_scadnano_json_str
(json_str: str) → scadnano.Design¶ Loads a
Design
from the given JSON string.- Parameters
json_str – JSON description of the
Design
- Returns
Design described in the JSON string
-
static
from_scadnano_json_map
(json_map: dict) → scadnano.Design¶ Loads a
Design
from the given JSON object (i.e., Python object obtained by calling json.loads(json_str) from a string representing contents of a JSON file.
-
static
from_cadnano_v2
(directory: Optional[str] = None, filename: Optional[str] = None, json_dict: Optional[dict] = None) → scadnano.Design¶ Creates a Design from a cadnano v2 file.
-
strand
(helix: int, offset: int) → scadnano.StrandBuilder¶ Used for chained method building by calling
Design.strand()
to build theStrand
domain by domain, in order from 5’ to 3’. For exampledesign.strand(0, 7).to(10).cross(1).to(5).cross(2).to(15)
This creates a
Strand
in thisDesign
equivalent todesign.add_strand(Strand([ sc.Domain(0, True, 7, 10), sc.Domain(1, False, 5, 10), sc.Domain(2, True, 5, 15), ]))
Loopouts can also be included:
design.strand(0, 7).to(10).cross(1).to(5).loopout(2, 3).to(15)
This creates a
Strand
in thisDesign
equivalent todesign.add_strand(Strand([ sc.Domain(0, True, 7, 10), sc.Domain(1, False, 5, 10), sc.Loopout(3), sc.Domain(2, True, 5, 15), ]))
Each call to
Design.strand()
,StrandBuilder.cross()
,StrandBuilder.loopout()
,StrandBuilder.to()
StrandBuilder.update_to()
, returns aStrandBuilder
object.Each call to
StrandBuilder.to()
,StrandBuilder.update_to()
, orStrandBuilder.loopout()
modifies theDesign
by replacing the Strand with an updated version.See the documentation for
StrandBuilder
for the methods available to call in this way.- Parameters
helix – starting
Helix
offset – starting offset on helix
- Returns
StrandBuilder
object representing the partially completedStrand
-
assign_m13_to_scaffold
(rotation: int = 5587, variant: scadnano.M13Variant = <M13Variant.p7249: 'p7249'>) → None¶ Assigns the scaffold to be the sequence of M13:
m13()
with the given rotation andM13Variant
.Raises
IllegalDesignError
if the number of scaffolds is not exactly 1.
-
to_cadnano_v2
() → Dict[str, Any]¶ Converts the design to the cadnano v2 format. Please see the spec misc/cadnano-format-specs/v2.txt for more info on that format.
-
set_helices_view_order
(helices_view_order: List[int]) → None¶ Sets helices_view_order.
- Parameters
helices_view_order – new view order of helices
-
strands_starting_on_helix
(helix: int) → List[scadnano.Strand]¶ Return list of
Strand
’s that begin (have their 5’ end) on theHelix
with index helix.
-
strands_ending_on_helix
(helix: int) → List[scadnano.Strand]¶ Return list of
Strand
’s that finish (have their 3’ end) on theHelix
with index helix.
-
domain_at
(helix: int, offset: int, forward: bool) → Optional[scadnano.Domain]¶ Return
Domain
that overlaps offset on helix with idx helix and hasDomain.forward
=True
, orNone
if there is no suchDomain
.- Parameters
helix – TODO
offset – TODO
forward – TODO
- Returns
TODO
-
domains_at
(helix: int, offset: int) → List[scadnano.Domain]¶ Return list of
Domain
’s that overlap offset on helix with idx helix.If constructed properly, this list should have 0, 1, or 2 elements.
-
add_strand
(strand: scadnano.Strand) → None¶ Add strand to this design.
-
remove_strand
(strand: scadnano.Strand) → None¶ Remove strand from this design.
-
append_domain
(strand: scadnano.Strand, domain: Union[scadnano.Domain, scadnano.Loopout]) → None¶ Same as
Design.insert_domain
, but inserts at end.
-
insert_domain
(strand: scadnano.Strand, order: int, domain: Union[scadnano.Domain, scadnano.Loopout]) → None¶ Insert Domain into strand at index given by order. Uses same indexing as Python lists, e.g.,
design.insert_domain(strand, domain, 0)
insertsdomain
as the new firstDomain
.
-
remove_domain
(strand: scadnano.Strand, domain: Union[scadnano.Domain, scadnano.Loopout]) → None¶ Remove Domain from strand.
-
to_json
(suppress_indent: bool = True) → str¶ Return string representing this Design, suitable for reading by scadnano if written to a JSON file ending in extension .sc
-
add_deletion
(helix: int, offset: int) → None¶ Adds a deletion to every
scadnano.Strand
at the given helix and base offset.
-
add_insertion
(helix: int, offset: int, length: int) → None¶ Adds an insertion with the given length to every
scadnano.Strand
at the given helix and base offset, with the given length.
-
set_start
(domain: scadnano.Domain, start: int) → None¶ Sets
Domain.start
to start.
-
set_end
(domain: scadnano.Domain, end: int) → None¶ Sets
Domain.end
to end.
-
move_strand_offsets
(delta: int) → None¶ Moves all strands backward (if delta < 0) or forward (if delta > 0) by delta.
-
move_strands_on_helices
(delta: int) → None¶ Moves all strands up (if delta < 0) or down (if delta > 0) by the number of helices given by delta.
-
assign_dna
(strand: scadnano.Strand, sequence: str, assign_complement: bool = True, domain: Optional[Union[scadnano.Domain, scadnano.Loopout]] = None, check_length: bool = False) → None¶ Assigns sequence as DNA sequence of strand.
If any
scadnano.Strand
is bound to strand, it is assigned the reverse Watson-Crick complement of the relevant portion, and any remaining portions of the other strand that have not already been assigned a DNA sequence are assigned to be the symbolDNA_base_wildcard
.Before assigning, sequence is first forced to be the same length as strand as follows: If sequence is longer, it is truncated. If sequence is shorter, it is padded with
DNA_base_wildcard
’s. This can be disabled by setting check_length to True, in which case the method raises anIllegalDesignError
if the lengths do not match.All whitespace in sequence is removed, and lowercase bases ‘a’, ‘c’, ‘g’, ‘t’ are converted to uppercase.
- Parameters
strand –
Strand
to assign DNA sequence tosequence – string of DNA bases to assign
assign_complement – Whether to assign the complement DNA sequence to any
Strand
that is bound to this one (default True)domain –
Domain
on strand to assign. IfNone
, then the wholeStrand
is given a DNA sequence. Otherwise, only domain is assigned, and the rest of theDomain
’s on strand are left alone (either keeping their DNA sequence, or being assignedDNA_base_wildcard
if no DNA sequence was previously assigned.) If domain is specified, thenlen(sequence)
must be least than or equal to the number of bases on domain. (i.e.,domain.dna_length()
)check_length – If True, raises
IllegalDesignError
if length ofStrand
orDomain
being assigned to does not match the length of the DNA sequence.
- Raises
IllegalDesignError – If check_length is True and the length of
Strand
orDomain
being assigned to does not match the length of the DNA sequence.
-
to_idt_bulk_input_format
(delimiter: str = ',', key: Optional[Callable[[scadnano.Strand], Any]] = None, warn_duplicate_name: bool = False, only_strands_with_idt: bool = False, export_scaffold: bool = False, export_non_modified_strand_version: bool = False) → str¶ Called by
Design.write_idt_bulk_input_file()
to determine what string to write to the file. This function can be used to get the string directly without creating a file.Parameters have the same meaning as in
Design.write_idt_bulk_input_file()
.- Returns
string that is written to the file in the method
Design.write_idt_bulk_input_file()
.
-
write_idt_bulk_input_file
(*, directory: str = '.', filename: Optional[str] = None, key: Optional[Callable[[scadnano.Strand], Any]] = None, extension: Optional[str] = None, delimiter: str = ',', warn_duplicate_name: bool = True, only_strands_with_idt: bool = False, export_scaffold: bool = False, export_non_modified_strand_version: bool = False) → None¶ Write
.idt
text file encoding the strands of thisDesign
with the fieldStrand.idt
, suitable for pasting into the “Bulk Input” field of IDT (Integrated DNA Technologies, Coralville, IA, https://www.idtdna.com/), with the output file having the same name as the running script but with.py
changed to.idt
, unless filename is explicitly specified. For instance, if the script is namedmy_origami.py
, then the sequences will be written tomy_origami.idt
. If filename is not specified but extension is, then that extension is used instead ofidt
. At least one of filename or extension must beNone
.The string written is that returned by
Design.to_idt_bulk_input_format()
.- Parameters
directory – specifies a directory in which to place the file, either absolute or relative to the current working directory. Default is the current working directory.
filename – optinoal custom filename to use (instead of currently running script)
key –
key function used to determine order in which to output strand sequences. Some useful defaults are provided by
strand_order_key_function()
extension – alternate filename extension to use (instead of idt)
delimiter – is the symbol to delimit the four IDT fields name,sequence,scale,purification.
warn_duplicate_name – if
True
prints a warning when two differentStrand
’s have the sameIDTField.name
and the sameStrand.dna_sequence
. AnIllegalDesignError
is raised (regardless of the value of this parameter) if two differentStrand
’s have the same name but different sequences, IDT scales, or IDT purifications.only_strands_with_idt – If False (the default), all non-scaffold sequences are output, with reasonable default values chosen if the field
Strand.idt
is missing. (though scaffold is included if export_scaffold is True). If True, then strands lacking the fieldStrand.idt
will not be exported.export_scaffold – If False (the default), scaffold sequences are not exported. If True, scaffold sequences on strands output according to only_strands_with_idt (i.e., scaffolds will be exported, unless they lack the field
Strand.idt
and only_strands_with_idt is True).export_non_modified_strand_version – For any
Strand
with aModification
, also export a version of theStrand
without any modifications. The name for thisStrand
is the original name with ‘_nomods’ appended to it.
-
write_idt_plate_excel_file
(*, directory: str = '.', filename: Optional[str] = None, key: Optional[Callable[[scadnano.Strand], Any]] = None, warn_duplicate_name: bool = False, only_strands_with_idt: bool = False, export_scaffold: bool = False, use_default_plates: bool = True, warn_using_default_plates: bool = True, plate_type: scadnano.PlateType = <PlateType.wells96: 96>, export_non_modified_strand_version: bool = False) → None¶ Write
.xls
(Microsoft Excel) file encoding the strands of thisDesign
with the fieldStrand.idt
, suitable for uploading to IDT (Integrated DNA Technologies, Coralville, IA, https://www.idtdna.com/) to describe a 96-well or 384-well plate (https://www.idtdna.com/site/order/plate/index/dna/), with the output file having the same name as the running script but with.py
changed to.xls
, unless filename is explicitly specified. For instance, if the script is namedmy_origami.py
, then the sequences will be written tomy_origami.xls
.- Parameters
directory – specifies a directory in which to place the file, either absolute or relative to the current working directory. Default is the current working directory.
filename – custom filename if default (explained above) is not desired
key –
key function used to determine order in which to output strand sequences. Some useful defaults are provided by
strand_order_key_function()
warn_duplicate_name – if
True
prints a warning when two differentStrand
’s have the sameIDTField.name
and the sameStrand.dna_sequence
. AnIllegalDesignError
is raised (regardless of the value of this parameter) if two differentStrand
’s have the same name but different sequences, IDT scales, or IDT purifications.only_strands_with_idt – If False (the default), all non-scaffold sequences are output, with reasonable default values chosen if the field
Strand.idt
is missing. (though scaffold is included if export_scaffold is True). If True, then strands lacking the fieldStrand.idt
will not be exported. If False, then use_default_plates must be True.export_scaffold – If False (the default), scaffold sequences are not exported. If True, scaffold sequences on strands output according to only_strands_with_idt (i.e., scaffolds will be exported, unless they lack the field
Strand.idt
and only_strands_with_idt is True).use_default_plates – Use default values for plate and well (ignoring those in idt fields, which may be None). If False, each Strand to export must have the field
Strand.idt
, so in particular the parameter only_strands_with_idt must be True.warn_using_default_plates – specifies whether, if use_default_plates is True, to print a warning for strands whose
Strand.idt
has the fieldsIDTFields.plate
andIDTFields.well
, since use_default_plates directs these fields to be ignored.plate_type – a
PlateType
specifying whether to use a 96-well plate or a 384-well plate if the use_default_plates parameter isTrue
. Ignored if use_default_plates isFalse
, because in that case the wells are explicitly set by the user, who is free to use coordinates for either plate type.export_non_modified_strand_version – For any
Strand
with aModification
, also export a version of theStrand
without any modifications. The name for thisStrand
is the original name with ‘_nomods’ appended to it.
-
write_scadnano_file
(directory: str = '.', filename: Optional[str] = None, extension: Optional[str] = None) → None¶ Write
.sc
file representing thisDesign
, suitable for reading by scadnano, with the output file having the same name as the running script but with.py
changed to.sc
, unless filename is explicitly specified. For instance, if the script is namedmy_origami.py
, then the design will be written tomy_origami.sc
. If extension is specified (but filename is not), then the design will be written tomy_origami.<extension>
directory specifies a directory in which to place the file, either absolute or relative to the current working directory. Default is the current working directory.
The string written is that returned by
Design.to_json()
.- Parameters
directory – directory in which to put file (default: current working directory)
filename – filename (default: name of script with
.py
replaced by.sc
). Mutually exclusive with extensionextension – extension for filename (default:
.sc
) Mutually exclusive with filename
-
export_cadnano_v2
(directory: str = '.', filename: Optional[str] = None) → None¶ Write
.json
file representing thisDesign
, suitable for reading by cadnano v2, with the output file having the same name as the running script but with.py
changed to.json
, unless filename is explicitly specified. For instance, if the script is namedmy_origami.py
, then the design will be written tomy_origami.json
.directory specifies a directory in which to place the file, either absolute or relative to the current working directory. Default is the current working directory.
The string written is that returned by
Design.to_cadnano_v2()
.
-
add_nick
(helix: int, offset: int, forward: bool, new_color: bool = True) → None¶ Add nick to
Domain
onHelix
with index helix, in direction given by forward, at offset offset. The twoDomain
’s created by this nick will have 5’/3’ ends at offsets offset and offset-1.For example, if there is a
Domain
withDomain.helix
=0
,Domain.forward
=True
,Domain.start
=0
,Domain.end
=10
, then callingadd_nick(helix=0, offset=5, forward=True)
will split it into twoDomain
’s, with one domains having the fieldsDomain.helix
=0
,Domain.forward
=True
,Domain.start
=0
,Domain.end
=5
, (recall thatDomain.end
is exclusive, meaning that the largest offset on thisDomain
is 4 =offset-1
) and the other domain having the fieldsDomain.helix
=0
,Domain.forward
=True
,Domain.start
=5
,Domain.end
=10
.If the
Strand
is circular, then it will be made linear with the 5’ and 3’ ends at the nick position, modified in place. Otherwise, thisStrand
will be deleted from the design, and two newStrand
’s will be added.- Parameters
helix – index of helix where nick will occur
offset – offset to nick (nick will be between offset and offset-1)
forward – forward or reverse
Domain
on helix at offset?new_color – whether to assign a new color to one of the
Strand
’s resulting from the nick. If False, bothStrand
’s created have the same color as the original If True, oneStrand
keeps the same color as the original and the other is assigned a new color
-
ligate
(helix: int, offset: int, forward: bool) → None¶ Reverse operation of
Design.add_nick()
. “Ligates” a nick between two adjacentDomain
’s in the same direction on aHelix
with index helix, in direction given by forward, at offset offset.For example, if there are a
Domain
’s withDomain.helix
=0
,Domain.forward
=True
,Domain.start
=0
,Domain.end
=5
, (recall thatDomain.end
is exclusive, meaning that the largest offset on thisDomain
is 4 =offset-1
) and the other domain having the fieldsDomain.helix
=0
,Domain.forward
=True
,Domain.start
=5
,Domain.end
=10
. then callingligate(helix=0, offset=5, forward=True)
will combine them into oneDomain
, having the fieldsDomain.helix
=0
,Domain.forward
=True
,Domain.start
=0
,Domain.end
=10
.If the
Domain
’s are on the sameStrand
(i.e., they are the 5’ and 3’ ends of thatStrand
, which is necessarily linear), then theStrand
is made is circular in place, Otherwise, the twoStrand
’s of eachDomain
will be joined into one, replacing the previous strand on the 5’-most side of the nick (i.e., the one whose 3’ end terminated at the nick), and deleting the other strand.- Parameters
helix – index of helix where nick will be ligated
offset – offset to ligate (nick to ligate must be between offset and offset-1)
forward – forward or reverse
Domain
on helix at offset?
-
add_half_crossover
(helix: int, helix2: int, offset: int, forward: bool, offset2: Optional[int] = None, forward2: Optional[bool] = None) → None¶ Add a half crossover from helix helix at offset offset to helix2, on the strand with
Strand.forward
= forward.Unlike
Design.add_full_crossover()
, which automatically adds a nick between the two half-crossovers, to call this method, there must already be nicks adjacent to the given offsets on the given helices. (either on the left or right side)If the crossover is within a
Strand
, i.e., between its 5’ and ‘ ends, theStrand
will simply be made circular, modifying it in place. Otherwise, the old twoStrand
’s will be deleted, and a newStrand
added.- Parameters
helix – index of one helix of half crossover
helix2 – index of other helix of half crossover
offset – offset on helix at which to add half crossover
forward – direction of
Strand
on helix to which to add half crossoveroffset2 – offset on helix2 at which to add half crossover. If not specified, defaults to offset
forward2 – direction of
Strand
on helix2 to which to add half crossover. If not specified, defaults to the negation of forward
-
add_full_crossover
(helix: int, helix2: int, offset: int, forward: bool, offset2: Optional[int] = None, forward2: Optional[bool] = None) → None¶ Adds two half-crossovers, one at offset and another at offset-1. Other arguments have the same meaning as in
Design.add_half_crossover()
. A nick is automatically added on helix helix between offset and offset-1 if one is not already present, and similarly for offset2 on helix helix2.- Parameters
helix – index of one helix of half crossover
helix2 – index of other helix of half crossover
offset – offset on helix at which to add half crossover
forward – direction of
Strand
on helix to which to add half crossoveroffset2 – offset on helix2 at which to add half crossover. If not specified, defaults to offset
forward2 – direction of
Strand
on helix2 to which to add half crossover. If not specified, defaults to the negation of forward
-
inline_deletions_insertions
() → None¶ Converts deletions and insertions by “inlining” them. Insertions and deletions are removed, and their domains have their lengths altered. Also, major tick marks on the helices will be shifted to preserve their adjacency to bases already present. For example, if there are major tick marks at 0, 8, 18, 24, and a deletion between 0 and 8:
0 8 18 24 30 |--X---|---------|-----|------
then the domain is shortened by 1, the tick marks become 0, 7, 15, 23, and the helix’s maximum offset is shrunk by 1:
0 7 17 23 29 |-----|---------|-----|------
Similarly, if there are insertions (in the example below, the “2” represents an insertion of length 2, which represents 3 total bases), they are expanded
0 8 18 24 30 |--2---|---------|-----|------
then the domain is lengthened by 3:
0 10 20 26 32 |--------|---------|-----|------
And it works if there are both insertions and deletions:
0 8 18 24 30 |--2---|---------|--X--|------
then the domain is lengthened by 3:
0 10 20 25 31 |--------|---------|----|------
We assume that a major tick mark appears just to the LEFT of the offset it encodes, so the minimum and maximum offsets for tick marks are respectively the helix’s minimum offset and 1 plus its maximum offset, the latter being just to the right of the last offset on the helix.
-
reverse_all
() → None¶ Reverses “polarity” of every
Strand
in thisDesign
.No attempt is made to make any assigned DNA sequences match by reversing or rearranging them. Every
Strand
keeps the same DNA sequence it had before (unreversed), if one was assigned. It is recommended to assign/reassign DNA sequences after doing this operation.
-
origami_rectangle¶
The origami_rectangle
module defines the function origami_rectangle.create()
for creating a DNA origami rectangle
using the scadnano
module.
-
class
origami_rectangle.
NickPattern
(value)¶ Represents options for where to place nicks between staples.
-
staggered
= 1¶ A nick appears in a given helix and column if the parity of the helix and column match (both even or both odd).
-
staggered_opposite
= 2¶ A nick appears in a given helix and column if the parity of the helix and column don’t match (one is even and the other is odd).
CURRENTLY UNSUPPORTED.
-
even
= 3¶ A nick appears in every column and only even-index helices.
CURRENTLY UNSUPPORTED.
-
odd
= 4¶ A nick appears in every column and only odd-index helices.
CURRENTLY UNSUPPORTED.
-
-
origami_rectangle.
staggered
= <NickPattern.staggered: 1>¶ Convenience reference defined so one can type
origami_rectangle.staggered
instead oforigami_rectangle.NickPattern.staggered
.
-
origami_rectangle.
staggered_opposite
= <NickPattern.staggered_opposite: 2>¶ Convenience reference defined so one can type
origami_rectangle.staggered_opposite
instead oforigami_rectangle.NickPattern.staggered_opposite
.CURRENTLY UNSUPPORTED.
-
origami_rectangle.
even
= <NickPattern.even: 3>¶ Convenience reference defined so one can type
origami_rectangle.even
instead oforigami_rectangle.NickPattern.even
.CURRENTLY UNSUPPORTED.
-
origami_rectangle.
odd
= <NickPattern.odd: 4>¶ Convenience reference defined so one can type
origami_rectangle.odd
instead oforigami_rectangle.NickPattern.odd
.CURRENTLY UNSUPPORTED.
-
origami_rectangle.
create
(*, num_helices: int, num_cols: int, assign_seq: bool = True, seam_left_column: int = -1, nick_pattern: origami_rectangle.NickPattern = <NickPattern.staggered: 1>, twist_correction_deletion_spacing: int = 0, twist_correction_start_col: int = 1, twist_correction_deletion_offset: int = -1, num_flanking_columns: int = 1, num_flanking_helices: int = 0, custom_scaffold: Optional[str] = None, edge_staples: bool = True, scaffold_nick_offset: int = -1) → scadnano.Design¶ Creates a DNA origami rectangle with a given number of helices and “columns” (16-base-wide region in each helix). The columns include the 16-base regions on the end where potential “edge staples” go, as well as the two-column-wide “seam” region in the middle.
Below is an example diagram of the staples created by this function.
Consider for example the function call
create(num_helices=8, num_cols=10, nick_pattern=origami_rectangle.staggered)
. The scaffold strand resulting from this call is shown below:# C0 # C1 # C2 # C3 # C4 # C5 # C6 # C7 # C8 # C9 # H0 +--------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------+ | | H1 +--------------- ---------------- ---------------- ---------------- ---------------+ +--------------- ---------------- ---------------- ---------------- ---------------+ | | H2 +--------------- ---------------- ---------------- ---------------- ---------------+ +--------------- ---------------- ---------------- ---------------- ---------------+ | | H3 +--------------- ---------------- ---------------- ---------------- ---------------+ +--------------- ---------------- ---------------- ---------------- ---------------+ | | H4 +--------------- ---------------- ---------------- ---------------- ---------------+ +--------------- ---------------- ---------------- ---------------- ---------------+ | | H5 +--------------- ---------------- ---------------- ---------------- ---------------+ +--------------- ---------------- ---------------- ---------------- ---------------+ | | H6 +--------------- ---------------- ---------------- ---------------- ---------------+ +--------------- ---------------- ---------------- ---------------- ---------------+ | | H7 +--------------- ---------------- ---------------- ---------------- ---------------] <--------------- ---------------- ---------------- ---------------- ---------------+
Helix indices are labelled
H0
,H1
, … and column indices are labeledC0
,C1
, … Each single symbol-
,+
,<
,>
,[
,]
,+
represents one DNA base, so each column is 16 bases wide. The#
is a visual delimiter between columns and does not represent any bases, nor do spaces between the base-representing symbols. The 5’ end of a strand is indicated with[
or]
and the 3’ end is indicated with>
or<
. A crossover is indicated with+ | +
Below are the staples resulting from this same call.
# C0 # C1 # C2 # C3 # C4 # C5 # C6 # C7 # C8 # C9 # H0 <--------------+ +--------------- -------]<------+ +--------------- -------]<------+ +--------------- -------]<------+ +--------------- -------]<------+ +--------------] | | | | | | | | H1 [--------------+ +------>[------+ +--------------+ +------>[------+ +--------------+ +------>[------+ +--------------+ +------>[------+ +--------------+ +--------------> | | | | | | | | H2 <--------------+ +--------------+ +------]<------+ +--------------+ +------]<------+ +--------------+ +------]<------+ +--------------+ +------]<------+ +--------------] | | | | | | | | H3 [--------------+ +------>[------+ +--------------+ +------>[------+ +--------------+ +------>[------+ +--------------+ +------>[------+ +--------------+ +--------------> | | | | | | | | H4 <--------------+ +--------------+ +------]<------+ +--------------+ +------]<------+ +--------------+ +------]<------+ +--------------+ +------]<------+ +--------------] | | | | | | | | H5 [--------------+ +------>[------+ +--------------+ +------>[------+ +--------------+ +------>[------+ +--------------+ +------>[------+ +--------------+ +--------------> | | | | | | | | H6 <--------------+ +--------------+ +------]<------+ +--------------+ +------]<------+ +--------------+ +------]<------+ +--------------+ +------]<------+ +--------------] | | | | | | | | H7 [--------------+ +------>[------- ---------------+ +------>[------- ---------------+ +------>[------- ---------------+ +------>[------- ---------------+ +-------------->
The seam crosses columns
C4
andC5
. The left and right edge staples respectively are in columnsC0
andC9
.Prints warning if number of bases exceeds 7249 (length of standard M13 scaffold strand), but does not otherwise cause an error.
Here’s an example of using
origami_rectangle.create
to create a design for a 16-helix rectangle and write it to a file readable by scadnano. (By default the output file name is the same as the script callingDesign.write_scadnano_file()
but with the extension.py
changed to.dna
.)import origami_rectangle as rect # XXX: ensure num_cols is even since we divide it by 2 design = rect.create(num_helices=16, num_cols=24, nick_pattern=rect.staggered) design.write_scadnano_file()
However, we caution that
create()
is not intended to be very extensible for creating many different types of DNA origami. It is more intended as an example whose source code can be an efficient reference to learn thescadnano
API.- Parameters
num_helices – number of helices. must be even.
num_cols – number of “columns” as defined above. must be even and at least 4.
assign_seq – whether to assign a DNA sequence to the scaffold. If True, uses custom_scaffold if it is not None, or M13 otherwise.
seam_left_column – specifies the location of the seam. (i.e., scaffold crossovers in the middle of the origami.) If positive, the seam occupies two columns, and seam_left_column specifies the column on the left. To make the crossover geometry work out, a nonnegative seam_left_column must be even, greater than 0, and less than num_helices - 2. If negative, it is calculated automatically to be roughly in the middle.
nick_pattern – describes whether nicks between staples should be “staggered” or not. See
origami_rectangle.NickPattern
for details.twist_correction_deletion_spacing – If twist_correction_deletion_spacing > 0, adds deletions between crossovers in one out of every twist_correction_deletion_spacing columns. See this paper for an explanation of twist correction in DNA origami: Programmable molecular recognition based on the geometry of DNA nanostructures, Sungwook Woo and Paul W. K. Rothemund, Nature Chemistry, volume 3, pages 620–627 (2011) https://doi.org/10.1038/nchem.1070
twist_correction_start_col – ignored if twist_correction_deletion_spacing <= 0, otherwise it indicates the column at which to put the first deletions. Default = 1.
twist_correction_deletion_offset – the relative offset of the deletion, relative to the left side of the column.
num_flanking_columns – the number of empty columns on the helix on each side of the origami.
num_flanking_helices – the number of empty helices above and below the origami.
custom_scaffold – the scaffold sequence to use. If set to
None
, the standard 7249-base M13 is used:scadnano.m13()
.edge_staples – indicates whether to include the edge staples. (Leaving them out prevents multiple origami rectangles from polymerizing in solution due to base stacking interactions on the left and right edges of the origami rectangle.)
scaffold_nick_offset – the position of the “nick” on the scaffold (the M13 scaffold is circular, so for such a scaffold this really represents where any unused and undepicted bases of the scaffold will form a loop-out). If negative (default value) then it will be chosen to be along the origami seam.
- Returns
a
Design
representing a DNA origami rectangle
Interoperability - cadnano v2¶
Scadnano provides function to convert design to and from cadnano v2:
DNADesign.from_cadnano_v2()
will create a scadnano DNADesign from acadnanov2
json file.DNADesign.export_cadnano_v2()
will produce acadnanov2
json file from a scadnano design.
Important
All cadnanov2
designs can be imported to scadnano. However not all scadnano designs can be imported
to cadnanov2, to be importable to cadnanov2
a scadnano design need to comply with the following points:
The design cannot feature any
Loopout
as it is not a concept that exists incadnanov2
.Following
cadnanov2
conventions, helices with even number must have their scaffold going forward and helices with odd number backward.
Also note that maximum helices offsets can be altered in a scadnano
to cadnanov2
conversion as cadnanov2
needs max offsets to be a multiple of 21 in the hex grid and 32 in the rectangular grid.
The conversion algorithm will choose the lowest multiple of 21 or 32 which fits the entire design.
The cadnanov2
json format does not embed sequences hence they will be lost after conversion.