Releases: UC-Davis-molecular-computing/scadnano-python-package
v 0.20.1
Added back wc
(deprecated) so as not to break existing scripts.
Commits
- 9cf18fe: changed some refs from
wc
torc
(David Doty) #314 - 5ec6b80: Update scadnano.py (David Doty) #314
- 85f153c: Update scadnano.py (David Doty) #314
- 5327c48: Update scadnano.py (David Doty) #314
- bd8df31: Update scadnano.py (David Doty) #314
- c2f87e6: minor (Dave Doty) #314
- 314e848: Update scadnano.py (David Doty) #314
- 05acbbf: added back
wc
(deprecated) and bumped version (David Doty) #314 - 4eba568: Update run_unit_tests.yml (David Doty) #314
v0.20.0
Release notes
BREAKING CHANGE: Minimum Python version is 3.9
The minimum Python version has been changed to 3.9. Technically there is not yet any part of the scadnano package that actually depends on 3.9 features; mainly this is done because support is being dropped for older Python versions in other tools, for example the unit tests that are run whenever we update the github repo no longer support older Python versions.
As of version 0.20.0, you can still install scadnano with Python version 3.7 or 3.8 by using the option --ignore-requires-python
with pip: pip install scadnano --ignore-requires-python
https://stackoverflow.com/questions/75726452/can-i-force-the-install-of-a-package-that-requires-a-newer-python-version-than-t However, future versions of scadnano may use newer features of Python, so it is advisable to upgrade to the latest Python version now for maximum future compatibility.
BREAKING CHANGE: parameter only_strands_with_idt
changed to only_strands_with_vendor_fields
Version 0.19.0 changed some names of fields and classes from IDT-specific names to the more generic "vendor fields". However, the parameter only_strands_with_idt
in a few methods was not at that time changed to only_strands_with_vendor_fields
; now that parameter name has been changed as well in version 0.20.0.
HelixGroups custom geometry
See also UC-Davis-molecular-computing/scadnano#993 (comment).
There is a new optional field HelixGroup.geometry
, which overrides the Geometry
parameters of the Design.geometry
field. For instance, the following code:
import scadnano as sc
def create_design() -> sc.Design:
group0 = sc.HelixGroup(grid=sc.square)
group1 = sc.HelixGroup(grid=sc.square,
# NOTE: here's the custom geometry for helix 1
geometry=sc.Geometry(bases_per_turn=18),
position=sc.Position3D(0, 3, 0))
groups = {"group 0": group0, "group 1": group1}
helices = [sc.Helix(idx=idx, max_offset=40, group=group) for idx, group in
[(0, "group 0"), (1, "group 1")]]
design = sc.Design(helices=helices, groups=groups, strands=[])
design.draw_strand(0, 0).move(40)
design.draw_strand(0, 40).move(-40)
design.draw_strand(1, 0).move(40)
design.draw_strand(1, 40).move(-40)
return design
if __name__ == '__main__':
d = create_design()
d.write_scadnano_file(directory='output_designs')
produces this design with helix 0 having 10.5 base pairs per turn, and helix 1 having 18 base pairs per turn:

Commits
- 3600d1a: changed idt references to vendor_fields (David Doty) #313
- e8905fa: fixes #304: Typo in
set_dna_sequence
comment (David Doty) #313 - d9cd906: closes #306: allow per-helix-group geometry (David Doty) #307
- c597888: removed xlwt from environment.yml (David Doty) #307
- d6a52bd: Update run_unit_tests.yml (David Doty) #307
- efce159: fixed group-specific geometry in oxdna/oxview export (David Doty) #313
- 0c435bf: Update scadnano.py (David Doty) #313
- 2795055: fixed issue 309 by rotating helix position by group's orientation before adding to helix group's offset (DanielHader) #312
- cf75e42: Update scadnano.py (David Doty) #312
- b7afcd2: removed assignment of
None
toDesign.helices
andDesign.groups
since constructor sets them anyway (David Doty) #313 - abc8435: made
StrandBuilder
a dataclass and added documentation for fields (David Doty) #313 - c4f64ba: bumped minimum Python version to 3.9 and bumped version to 0.20.0 (David Doty) #313
v0.19.4
Release notes
Changed type of Design.to_oxview_format
from dict
to str
to keep convention with similar other methods such as Design.to_oxdna_format
.
This is a breaking change, although the minor version number did not change. The method Design.to_oxview_json
has the same functionality that Design.to_oxview_format
, namely that it returns a JSON-serializable dict. Calling json.dumps
on this dict produces the same output as Design.to_oxview_format
.
v0.19.3
Release notes
Mostly fixes this bug with oxView export: #297.
We jumped straight from v0.19.0 to v0.19.3 due to some testing that happened in the dev branch.
Commits
- a78b395: bumped version (David Doty) #299
- 5cf25e3: changed parameter type of
Strand.set_domains
to allowExtension
's (David Doty) #299 - 1128beb: added the required build section (RayBipse) #292
- dcede52: Removed python.version (RayBipse) #293
- 3d20590: Removed python.version and added back tools.python (RayBipse) #294
- 4380042: Changed to use mamba and added python version requirement to environment.yml (RayBipse) #295
- 21aa34a: Added pip packages used to environment.yml (RayBipse) #296
- e5572ad: fixes #297: fix oxView export exception on Loopouts (David Doty) #298
- a220c32: Update scadnano.py (David Doty) #299
v0.19.0
Release notes
BREAKING CHANGE: Renamed IDT-specific fields
Some names related to the DNA synthesis company IDT have been renamed to be more general. You will have to rename these in your own code for it to run:
- class
IDTFields
-->VendorFields
- field
Modification.idt_text
-->Modification.vendor_code
- field
Strand.idt
-->Strand.vendor_fields
Additionally, some keys in the JSON format for .sc
files have changed as well. Scadnano (both the web interface and the Python package) should be able to read files with the old keys and convert them to the new keys upon saving. However, if you are manually editing the .sc
file then use the new keys.
Some IDT-specific methods remain, such as Design.write_idt_plate_excel_file
. These use the values in Strand.vendor_fields
and Modification.vendor_code
, but since the file format actually is specific to IDT, the method name is unchanged.
Although currently there are no methods for exporting to file formats recognized by other synthesis companies, in the meantime it should be straightforward to use the values in VendorFields
to write custom code for such exports.
Field Modification.id
removed
Previously, scadnano used Modification.id
as a unique identifier for modifications.
The field id
has been removed. Now, the field vendor_code
is used as a unique identifier for the modification, where id
was previously used.
Previously, if no id
was specified, but vendor_code
/idt_text
was, then id
was set to the latter. Such code should continue to work unmodified. But code referencing id
should now refer to vendor_code
instead. Additionally, if a script used the same vendor_code
for different Modifications, then this will break. Each Modification should now have a unique vendor_code
field.
Note that some vendors such as Eurofins use the same code for 5'/3' modifications (see issue #283). For this reason, the modifications internally are stored in a way that encodes their location (5', 3', internal). But for any two modifications of the same "location" (both 5' modifications, both 3' modifications, or both internal modifications) the vendor_code
must be unique to the type of modification.
Commits
- 99e16d2: bumped version (David Doty) #285
- bd12d4d: Update scadnano.py (David Doty) #285
- dbc1058: Update scadnano.py (David Doty) #285
- ddc8eee: Update README.md (David Doty) #285
- 34211de: Update scadnano.py (David Doty) #285
- 3ed8158: Update scadnano.py (David Doty) #285
- 0bd7995: Update scadnano.py (David Doty) #285
- d012f17: Update scadnano.py (David Doty) #285
- 1c39fbc: closes #279: rename IDTFields to VendorFields (David Doty) #280
- 5fefd41: re-ran examples to alter changed name of IDT fields (David Doty) #280
- f679027: fixed docstrings (David Doty) #280
- 65630f4: fixed docstrings (David Doty) #280
- 3bb1373: Update scadnano.py (David Doty) #285
- 6356689: closes #281: remove field
Modification.id
(David Doty) #282 - 4c52f52: Update scadnano.py (David Doty) #285
- 032ebde: Update scadnano.py (David Doty) #285
- 4795224: Update scadnano.py (David Doty) #285
- b72a5c7: Update scadnano.py (David Doty) #285
- db9ec53: Update scadnano.py (David Doty) #285
- 41d93e3: removed
Position3D.clone()
, which is unnecessary sincePosition3D
is frozen (David Doty) #285 - 6465434: Update scadnano.py (David Doty) #285
- fc30862: Update scadnano.py (David Doty) #285
- 37fa350: fixes #283: deal with non-unique Modification vendor codes (David Doty) #284
- 09ad91b: Update scadnano.py (David Doty) #285
- 82661bb: Update scadnano.py (David Doty) #285
v0.18.3
Release notes
Custom delimiter between DNA sequences of domains
A custom delimiter string to go in between DNA sequences of different domains on a strand can be specified, e.g., a space (which is ignored by IDT), so that the exported IDT sequences might look like this for a 3-domain strand:
ST0[8]0[15];/5Biosg/ ACGTCGT ACGTC ACGTAC;25nm;STD
See
https://scadnano-python-package.readthedocs.io/en/latest/#scadnano.Strand.vendor_dna_sequence
https://scadnano-python-package.readthedocs.io/en/latest/#scadnano.Design.to_idt_bulk_input_format
https://scadnano-python-package.readthedocs.io/en/latest/#scadnano.Design.write_idt_bulk_input_file
Commits
- 301edc4: bumped version (David Doty) #278
- 315c0f3: fixes #276: customize delimiter between domains in exported DNA sequences (David Doty) #277
- 5d8b61d: updated unit test to test for non-default delimiter (David Doty) #277
- 96b5e0d: removed delimiters between internal modifications and rest of sequence (David Doty) #277
- 93431b4: Update scadnano.py (David Doty) #277
- 19975dd: added unit test for internal modification that goes between bases (David Doty) #278
v0.18.2
Bug fixes related to relaxing helix rolls.
Commits
- 8165951: bumped version (David Doty) #275
- 3f5bb6e: fixed one unit test (David Doty) #275
- a37b35a: Update scadnano.py (David Doty) #275
- 0837366: Update scadnano.py (David Doty) #275
- caf20e1: fixed bug in calculating minimum strain angle for helices with no crossovers (David Doty) #275
- e832e53: Update scadnano_tests.py (David Doty) #275
- 25fa92f: fixes #268: ignore loopouts when relaxing Helix rolls (David Doty) #269
- 9ea350b: fixed bug with relaxing roll starting from non-0 roll (David Doty) #275
- 7d938b5: cleaned up unit test (David Doty) #275
- 15c1514: Update scadnano.py (David Doty) #275
- 770366a: fixes #270: ignore "same helix" crossovers when relaxing helix rolls; also ensures domains on helix are stored in increasing order of start offsets (David Doty) #272
- 888565c: added new example (David Doty) #272
- 832c503: Update scadnano_tests.py (David Doty) #275
- d84419f: added unit test for relaxing helix rolls with intrahelix crossovers and fixed bug in relax code that didn't account for that case (David Doty) #275
- d3a6d7d: change parameter name (David Doty) #275
- a2d4e52: fixes #273: deal with inter-group crossovers when relaxing helix rolls (David Doty) #274
- 27568e4: Update scadnano_tests.py (David Doty) #275
- 1dedd8b: fixed relax helix rolls to ignore intergroup crossovers (David Doty) #275
- 51fbc9c: Update tutorial.md (David Doty) #275
- 5189e8d: Update scadnano.py (David Doty) #275
v0.18.1
Release notes
automatically set Helix rolls based on crossover locations ("relax" the rolls)
In this design, the crossovers are well placed relative to each other, but the helix rolls need to be rotated. As the slice bar shows, with the default roll of 0, the crossovers do not point at the helices they connect to:
By calling Design.relax_helix_rolls
, the helix rolls are set to minimize "strain" in the crossovers:
Formally, the strain is defined as the square of the angular distance between the "ideal" angle for the crossover (i.e., the relative angle of the other helix to which it is connecting) and the crossover's current angle. The roll is set so as to minimize this total strain across all crossovers in each helix.
The reason to minimize the sum of the squared angular distances is that, if we model each crossover as an angular spring exerting a rotational force on the helix proportional to its displacement from the "ideal" angle (pointing directly at the other helix), this minimizes the total energy stored in the springs.
Commits
- 2b11342: bumped version (David Doty) #267
- 49867e3: Merge branch 'dev' into 257-automatically-set-helix-rolls-based-on-crossover-locations-relax-the-rolls (David Doty) #264
- 123e001: closes #257: automatically set Helix rolls based on crossover locations (relax the rolls) (David Doty) #264
- 5208be3: fixed some unit tests (David Doty) #264
- c370a1f: Update scadnano.py (David Doty) #264
- c26dbe6: fixed dependencies (David Doty) #266
- 62c5dd5: changed unit test versions for openpyxl and tabulate to versions matching what is in Anaconda package repository (David Doty) #266
- 7b963c5: added instructions for installing openpyxl and tabulate to README (David Doty) #266
- f45d3f0: fixes #234: export new Excel format (David Doty) #266
- 3da4763: added openpyxl to tests_require (David Doty) #266
- c177ef0: added openpyxl installation to docs-check GitHub action (David Doty) #266
- 50899e3: Merge branch 'dev' into 257-automatically-set-helix-rolls-based-on-crossover-locations-relax-the-rolls (David Doty) #264
v0.18.0
Release notes
BREAKING CHANGE: label type is now str
Strands, domains, loopouts, and extensions have a field label
. Previously the declared type was arbitrary, though at runtime it was required to be JSON-serializable.
Now we have changed the type of label
field in Strand
, Domain
, Loopout
, and Extension
to str
instead of an arbitrary object.
This is a breaking change because existing code using non-string labels will have to be altered to change the data to a string before storing and change it back to structured data when reading.
If you would like to store "structured data" (e.g., lists or dicts) in the label, you can serialize to a string and deserialize back to structured data manually using the json
package.
Before, this was possible:
from typing import List
# previously was possible, now is not supported
nums = [1, 2, 3]
strand.label = nums # stores strand.label as the list [1, 2, 3]; would be a mypy type error now
# and to get the structured data back out:
nums: List[int] = strand.label # would be a mypy type error now
Now this is necessary to store a list of int
's in the label:
import json
from typing import List
nums = [1, 2, 3]
strand.label = json.dumps(nums) # stores strand.label as the string '[1, 2, 3]'
# and to get the structured data back out:
nums: List[int] = json.loads(strand.label) # nums is now the list [1, 2, 3]
added p8634 variant of M13
There is a variant of M13 mentioned in a few papers (e.g., https://doi.org/10.1038/s41565-022-01283-1) called "p8634". It can be obtained from Tilibit (though not listed on their website). This sequence is now available as a predefined sequence. See https://scadnano-python-package.readthedocs.io/en/latest/#scadnano.M13Variant.p8634
Commits
- d955eda: bumped version (David Doty) #258
- 2f58b2b: updated docstrings (David Doty) #258
- 0a482a7: Update scadnano.py (David Doty) #258
- c55411e: Update scadnano.py (David Doty) #258
- fca673a: added test generated by GitHub Copilot (David Doty) #258
- 3e84a38: changed docstring for
Design.base_pairs
(David Doty) #258 - fc2176b: added examples (David Doty) #258
- 7b0603b: changed to LR newlines (David Doty) #258
- 01c43e3: added p8634 variant of M13 (David Doty) #258
- 0678d55: formatting (David Doty) #258
- e8211db: fixed PyCharm warnings (David Doty) #258
- 602575d: closes #261: change
label
type tostr
(David Doty) #262 - a292757: removed all string type hints and replaced with forward references (not supported in Python 3.6) (David Doty) #262
v0.17.7
Release notes
new method Design.base_pairs()
This method returns a dict mapping helix idx's where base pairs exist to a list of offsets where those base pairs are.
Domain/Extension/Loopout colors
Individual Domain
's, Extension
's, and Loopout
's now have a color
field. If specified, then this overrides the field Strand.color
when displayed in the web interface. There is also a new method StrandBuilder.with_domain_color()
:
helices = [sc.Helix(max_offset=100) for _ in range(4)]
design = sc.Design(helices=helices, grid=sc.square)
red = sc.Color(255, 0, 0)
dark_red = sc.Color(150, 0, 0)
green = sc.Color(0, 255, 0)
dark_green = sc.Color(0, 150, 0)
blue = sc.Color(0, 0, 255)
dark_blue = sc.Color(0, 0, 150)
black = sc.Color(0, 0, 0)
design.draw_strand(0, 0) \
.extension_5p(num_bases=5).with_domain_color(red) \
.move(8).with_domain_color(green) \
.loopout(1, 5).with_domain_color(dark_blue) \
.move(-8).with_domain_color(dark_red) \
.cross(2) \
.move(8).with_domain_color(dark_green) \
.cross(3) \
.move(-8) \
.extension_3p(num_bases=5).with_domain_color(black) \
.with_color(blue)
Commits
- 5586c9f: bumped version (David Doty) #256
- 6463865: closes #252: add method
Design.base_pairs()
(David Doty) #254 - fec6f43: changed return type of
Design.base_pairs()
to dict and addedallow_mismatches
parameter (David Doty) #254 - e795627: fixed unit tests after updating
with_sequence
andwith_domain_sequence
to default to not assigning complement (David Doty) #254 - 6b6001a: removed unused _popleft() function (David Doty) #254
- e55609d: Update scadnano.py (David Doty) #256
- afc44b8: don't put Helix idx in base_pairs dict if Helix has no base pairs (David Doty) #256
- 1049cdc: fixed base pair calculation to allow for deletions/insertions/wildcards/None if DNA sequence is not assigned (David Doty) #256
- e6c0737: added unit test for no base pairs (David Doty) #256
- f81b8ff: Update scadnano_tests.py (David Doty) #256
- 7b83a43: fixed bug in
Design.base_pairs()
when no reverse domains on helix (David Doty) #256 - 5312a59: Update scadnano_tests.py (David Doty) #256
- 1b7e605: closes #238: Domain colors (David Doty) #255
- fea3b32: added example with domain colors (David Doty) #256