Skip to content

Commit

Permalink
Merge pull request #544 from UC-Davis-molecular-computing/dev
Browse files Browse the repository at this point in the history
v0.13.3
  • Loading branch information
UnHumbleBen authored Dec 9, 2020
2 parents a57200d + bce0d3d commit 3e1802b
Show file tree
Hide file tree
Showing 31 changed files with 735 additions and 519 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ jobs:
run: |
echo "done!"
- uses: "marvinpinto/action-automatic-releases@v1.1.0"
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "latest"
prerelease: false
title: "Development Build [TODO: Replace label and number with version number]"
title: "Development Build [TODO: Replace label and title with version number]"
files: |
LICENSE.txt
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,8 @@ This refers to the menu at the top of the whole app. At the top of the side view
* **DNA sequences:**
Exports a file containing DNA sequences. A few defaults are available, but it is not very configurable. For more advanced control, the Python scripting package can be used to customize how DNA sequences are exported.

By default the DNA sequences will be output in the same order strands appear in the `.sc` file. A few defaults are available to output them in another order based on their 5' or 3' ends' helix index and case offset.

* Help

* This contains links to various web sites associated with scadnano, which contain its documentation.
Expand Down Expand Up @@ -513,7 +515,7 @@ In both the side menu and the main menu, hovering the cursor over a most menu it
There are different edit modes available, shown on the right side of the screen. Currently most of them are mutually exclusive, so selecting one will unselect the others. However, a few can be on simultaneously. Each edit mode has a keyboard shortcut that can be used to toggle it, shown in parentheses in the application's display.

* **(s)elect:**
This is similar to the Select edit mode in cadnano. It allows one to select one or more items and delete, move, or copy/paste them. Which are allowed to be selected depends on the "Select Mode", shown below the Edit modes. Some of these are mutually exclusive as well.
This is similar to the Select edit mode in cadnano. It allows one to select one or more items and delete, move, or copy/paste them. Which are allowed to be selected depends on the "Select Mode", shown when in select edit mode or rope select edit mode. Some of the select modes are mutually exclusive as well.

A single item can be selected by clicking. Multiple items can be selected by pressing Shift (to add to the selection) or Ctrl (to toggle whether an item is selected) and clicking multiple items. Ctrl+A will select all selectable items in the design. If Shift or Ctrl is pressed while in select mode, one can use the mouse/touchpad to click+drag to select multiple items by drawing a rectangular box. See also "rope select" mode, described below, for a more flexible way to select many items by drawing an arbitrary polygon (useful for selecting many items lined up diagonally, for instance).

Expand Down Expand Up @@ -556,12 +558,10 @@ There are different edit modes available, shown on the right side of the screen.
- **scaffold/staple:**
In the case of a DNA origami design---one in which at least one strand is marked as a *scaffold*---all non-scaffold strands are called *staples*. This option allows one to select only scaffold strands/strand parts, only staples, or both. The option is not shown in a non-origami design.

It is also possible to select helices in the side view. As currently implemented, the delete key does not delete them. Instead, they can be deleted by picking the "helix" edit mode and clicking on them.

Regardless of the current select mode, it is always possible to select helices in the side view. Pressing delete will delete those helices. You can also delete a helix by clicking on the helix in the side view while in pencil mode (see below).
Regardless of the current select mode, it is always possible to select helices in the side view by holding Shift or Ctrl and dragging a selection box. Pressing delete will delete the selected helices. You can also delete a helix by clicking on the helix in the side view while in pencil edit mode.

* **(r)ope select:**
This is similar to select mode, but it allows one to draw a general polygon (a "rope"), rather than just a rectangle. This is useful, for example, for selecting many objects along a diagonal, where a rectangle containing all of them would also contain many objects off the diagonal that are not intended to be selected.
This is similar to select mode, but when holding Shift or Ctrl, it allows one to draw a general polygon (a "rope"), rather than just a rectangle. This is useful, for example, for selecting many objects along a diagonal, where a rectangle containing all of them would also contain many objects off the diagonal that are not intended to be selected.

The interpretation of Shift and Ctrl are similar (Shift means add all items inside the polygon to the selected items; Ctrl means toggle them). First, press and hold either Shift or Ctrl. While holding down the Shift or Ctrl key, click several points to define a polygon.

Expand Down Expand Up @@ -637,8 +637,14 @@ There are different edit modes available, shown on the right side of the screen.

## Assigning DNA
Right-clicking on a strand allows one to assign a DNA sequence to a strand (or remove it if assigned).

There are two options for assigning DNA sequences to a strand, both available via the right-click context menu on a strand:
*assign DNA* and *assign DNA complement from bound strands*.
The first option requires you to specify a DNA sequence. The second infers the DNA sequence from the complement of other DNA sequences already present in the design.

*assign DNA*:
By default any strands bound to the assigned strand will have their sequences assigned to be the complement of the relevant region.
Disabling this allows one to create intentional mismatches.
Disabling this allows one to create intentional mismatches, for instance.

It is possible to assign DNA to a strand that already has DNA assigned to it. It will replace the previous DNA sequence.
However, be careful in automatically assigning DNA complements to strands bound to this one.
Expand All @@ -653,6 +659,9 @@ Any bases on *s1* not bound to *s2* (for instance, those bound to *s3*), after *
Upon subsequently assigning a DNA sequence to *s3*, the complementary portions of *s1* (which have a `?`) will be overwritten with the appropriate DNA sequence, even if the warning is enabled.
Thus the warning only concerns a concrete DNA base, one of `A`, `C`, `G`, or `T`, if it already exists and is about to be overwritten with a different base.

*assign DNA complement from bound strands*:
The above description indicates how to assign a specific DNA sequence to a particular strand while automatically assigning the complementary DNA sequence to strands bound to it. But in some circumstances, you might have some strand(s) that already have DNA sequences assigned, and through some modification of the design, new strand(s) come to be bound to them that were not present in the design at the time the DNA sequence was assigned. This feature allows you to select that new strand (or many strands if you like), and tell it to receive the appropriate complementary DNA sequence. It is equivalent to iterating over each strand bound to the selected strand(s), selecting "Assign DNA" from the context menu, and selecting the option "assign complement to bound strands".

[TODO: make a figure showing this]


Expand Down
20 changes: 19 additions & 1 deletion lib/src/actions/actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:color/color.dart';
import 'package:js/js.dart';
import 'package:built_collection/built_collection.dart';
import 'package:scadnano/src/state/domains_move.dart';
import 'package:scadnano/src/state/export_dna_format_strand_order.dart';
import 'package:scadnano/src/state/geometry.dart';
import 'package:scadnano/src/state/helix_group_move.dart';
import 'package:tuple/tuple.dart';
Expand Down Expand Up @@ -1542,8 +1543,25 @@ abstract class ExportDNA with BuiltJsonSerializable implements Action, Built<Exp

ExportDNAFormat get export_dna_format;

@nullable
StrandOrder get strand_order;

bool get column_major;

/************************ begin BuiltValue boilerplate ************************/
factory ExportDNA({bool include_scaffold, ExportDNAFormat export_dna_format}) = _$ExportDNA._;
factory ExportDNA(
{bool include_scaffold,
ExportDNAFormat export_dna_format,
StrandOrder strand_order = null,
bool column_major = true}) {
return ExportDNA.from((b) => b
..include_scaffold = include_scaffold
..export_dna_format = export_dna_format
..strand_order = strand_order
..column_major = column_major);
}

factory ExportDNA.from([void Function(ExportDNABuilder) updates]) = _$ExportDNA;

ExportDNA._();

Expand Down
14 changes: 10 additions & 4 deletions lib/src/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ import 'dart:html';
import 'package:color/color.dart';
import 'package:platform_detect/platform_detect.dart';

import 'state/geometry.dart';
import 'state/grid.dart';

// WARNING: Do not modify line below, except for the version string
// (and also add new version string to scadnano_versions_to_link).
const String CURRENT_VERSION = "0.13.2";
const String CURRENT_VERSION = "0.13.3";
const String INITIAL_VERSION = "0.1.0";

// scadnano versions that we deploy so that older versions can be used.
final scadnano_older_versions_to_link =[
"0.13.2",
"0.13.1",
"0.13.0",
"0.12.2",
"0.12.1",
Expand Down Expand Up @@ -43,6 +46,8 @@ const String DNA_BASE_WILDCARD = '?';
const default_min_offset = 0;
const default_max_offset = 64;

final default_geometry = Geometry();

const scadnano_css_stylesheet_name_no_ext = r'scadnano-styles';
const scadnano_css_stylesheet_name = r'scadnano-styles.css';

Expand Down Expand Up @@ -320,9 +325,8 @@ const num ZOOM_THRESHOLD = 1;

/////////////////////////////////////////////////////////////
// Backend
const export_url = 'https://dna.hamilton.ie/scadnano-backend/scadnano_to_cadnano_v2';
const import_url = 'https://dna.hamilton.ie/scadnano-backend/cadnano_v2_to_scadnano';

const export_url = 'https://os-interactive.ie/scadnano-backend/scadnano_to_cadnano_v2';
const import_url = 'https://os-interactive.ie/scadnano-backend/cadnano_v2_to_scadnano';

/////////////////////////////////////////////////////////////
// CSS selector classnames
Expand Down Expand Up @@ -365,3 +369,5 @@ const css_selector_deletion_group = 'deletion-group';
const css_selector_selected = 'selected';


const default_idt_scale = "25nm";
const default_idt_purification = "STD";
31 changes: 26 additions & 5 deletions lib/src/middleware/export_dna_sequences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,31 @@ export_dna_sequences_middleware(Store<AppState> store, action, NextDispatcher ne
String filename = 'sequences.' + action.export_dna_format.extension();
util.BlobType blob_type = action.export_dna_format.blob_type();

action.export_dna_format
.export(strands)
.then((content) => util.save_file(filename, content, blob_type: blob_type))
.catchError((e, stackTrace) {
try {
var result = action.export_dna_format
.export(strands, strand_order: action.strand_order, column_major: action.column_major);
// See export comments for why we have this stupid special case
if (result is Future<List<int>>) {
result.then((response) {
List<int> content = response;
util.save_file(filename, content, blob_type: blob_type);
}).catchError((e, stackTrace) {
var cause = "";
if (has_cause(e)) {
cause = e.cause;
} else if (has_message(e)) {
cause = e.message;
}
var msg = cause + '\n\n' + stackTrace.toString();
store.dispatch(actions.ErrorMessageSet(msg));
app.view.design_view.render(store.state);
});
} else {
String content = result;
util.save_file(filename, content, blob_type: blob_type);
}
// .then((content) => util.save_file(filename, content, blob_type: blob_type))
} catch (e, stackTrace) {
var cause = "";
if (has_cause(e)) {
cause = e.cause;
Expand All @@ -32,7 +53,7 @@ export_dna_sequences_middleware(Store<AppState> store, action, NextDispatcher ne
var msg = cause + '\n\n' + stackTrace.toString();
store.dispatch(actions.ErrorMessageSet(msg));
app.view.design_view.render(store.state);
});
}
}
}

Expand Down
30 changes: 9 additions & 21 deletions lib/src/middleware/load_file.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,18 @@ load_file_middleware(Store<AppState> store, action, NextDispatcher next) {

if (action is actions.LoadDNAFile) {
document.title = action.filename;
app?.view?.design_view?.render(store.state);
app?.view?.design_view?.clear_copy_buffer();
var design_view = app?.view?.design_view;
if (design_view != null) {
design_view.render(store.state);

// if moving strands, clear the buffer; otherwise save it to copy into new design
if (design_view.copy_action != null && !design_view.copy_action.copy) {
design_view.clear_copy_buffer();
}
}

// re-center if necessary
if (store.state.ui_state.autofit && store.state.design != null) {
// Point<num> pan_side = Point<num>(50, 50);
// Point<num> pan_main = Point<num>(100, 50);
// if (store.state.design.helices.length > 0) {
// // center at smallest-index helix
// var helices = store.state.design.helices.values.toList();
// var first_helix = helices.first;
// for (var helix in helices) {
// if (first_helix.idx > helix.idx) {
// first_helix = helix;
// }
// }
// pan_main -= first_helix.svg_position;
// pan_side -= util.position3d_to_side_view_svg(first_helix.position3d());
// }
// print('pan_side: $pan_side');
// print('pan_main: $pan_main');

// util.set_pan_side(pan_side);
// util.set_pan_main(pan_main);
util.fit_and_center();
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/middleware/reselect_moved_strands.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ reselect_moved_strands_middleware(Store<AppState> store, action, NextDispatcher
// first collect old addresses while design.end_to_substrand is still valid, convert them to
// their new addresses so we can look them up
for (Strand strand in strands_move.strands_moving) {
Domain old_domain = strand.first_domain();
Domain old_domain = strand.first_domain;
DNAEnd old_5p_end = old_domain.dnaend_5p;
int old_helix_view_order = old_helices_view_order_inverse[old_domain.helix];
int new_helix_view_order = old_helix_view_order + strands_move.delta_view_order;
Expand Down
6 changes: 3 additions & 3 deletions lib/src/reducers/assign_or_remove_dna_reducer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ String compute_dna_complement_from(Strand strand_to, Strand strand_from, bool er
new_dna_sequence =
util.merge_wildcards(strand_to.dna_sequence, new_dna_sequence, constants.DNA_BASE_WILDCARD);
} on ArgumentError {
Domain ss_to = strand_to.first_domain();
Domain ss_from = strand_from.first_domain();
Domain ss_to = strand_to.first_domain;
Domain ss_from = strand_from.first_domain;
var msg = 'strand starting at helix ${ss_to.helix}, offset ${ss_to.offset_5p} has '
'length '
'${strand_to.dna_length()} and already has a partial DNA sequence assignment of length '
Expand All @@ -237,7 +237,7 @@ String merge_sequences_if_necessary(Strand strand, String seq) {
try {
seq = util.merge_wildcards(seq, strand.dna_sequence, constants.DNA_BASE_WILDCARD);
} on ArgumentError {
var first_ss = strand.first_domain();
var first_ss = strand.first_domain;
var msg = 'strand starting at helix ${first_ss.helix}, offset ${first_ss.offset_5p} has '
'length '
'${strand.dna_length()} and already has a DNA sequence assignment of length '
Expand Down
4 changes: 3 additions & 1 deletion lib/src/reducers/strands_reducer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,14 @@ BuiltList<Strand> strands_move_commit_reducer(
if (action.strands_move.allowable && action.strands_move.is_nontrivial) {
var strands_builder = strands.toBuilder();
for (var strand in action.strands_move.strands_moving) {
int strand_idx = strands.indexOf(strand);
Strand new_strand = one_strand_strands_move_commit_reducer(state.design, strand, action.strands_move);
new_strand = new_strand.initialize();
if (action.strands_move.copy) {
strands_builder.add(new_strand);
} else {
// if copying, we might have loaded a new design, so this indexOf is only safe to do
// (i.e., the strand will only be found in the list of all strands) if we are moving
int strand_idx = strands.indexOf(strand);
strands_builder[strand_idx] = new_strand;
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/src/serializers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import 'state/dna_ends_move.dart';
import 'state/edit_mode.dart';
import 'state/example_designs.dart';
import 'state/export_dna_format.dart';
import 'state/export_dna_format_strand_order.dart';
import 'state/geometry.dart';
import 'state/modification.dart';
import 'state/potential_crossover.dart';
Expand Down Expand Up @@ -234,10 +235,10 @@ part 'serializers.g.dart';
DialogFloat,
DialogTextArea,
DialogCheckbox,
DialogSelect,
DialogRadio,
DialogShow,
DialogHide,
StrandOrder,
StrandColorSet,
StrandColorPickerShow,
StrandColorPickerHide,
Expand Down
Loading

0 comments on commit 3e1802b

Please sign in to comment.