Skip to content

Commit c9bc0fb

Browse files
Merge pull request #1027 from UC-Davis-molecular-computing/984-replace-tuples-with-records-2
Fixes #984 - Replace Tuples with Records
2 parents a0db9e0 + a5136a4 commit c9bc0fb

31 files changed

Lines changed: 248 additions & 346 deletions

lib/src/middleware/helices_positions_set_based_on_crossovers.dart

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import '../state/domain.dart';
1212
import '../state/geometry.dart';
1313
import '../state/helix.dart';
1414
import '../state/position3d.dart';
15-
import 'package:tuple/tuple.dart';
1615

1716
import '../state/address.dart';
1817
import '../actions/actions.dart' as actions;
@@ -60,7 +59,7 @@ List<actions.UndoableAction> get_helix_position_and_roll_actions(AppState state)
6059
var group = state.design.groups[group_name]!;
6160
var geometry = group.geometry ?? state.design.geometry;
6261
List<Helix> helices = _get_helices_to_process(state, group);
63-
List<Tuple2<Address, Address>>? addresses = _get_addresses_to_process(state, helices);
62+
List<(Address, Address)>? addresses = _get_addresses_to_process(state, helices);
6463
if (addresses == null) {
6564
continue;
6665
}
@@ -100,17 +99,17 @@ List<Helix> _get_helices_to_process(AppState state, HelixGroup group) {
10099
/// on the two helices it connects.
101100
/// returns null if two such crossovers are selected
102101
/// if none are selected, finds the first (one with lowest offset on helix earlier in order in [helices])
103-
List<Tuple2<Address, Address>>? _get_addresses_to_process(AppState state, List<Helix> helices) {
102+
List<(Address, Address)>? _get_addresses_to_process(AppState state, List<Helix> helices) {
104103
var design = state.design;
105104
var selected_crossovers = state.ui_state.selectables_store.selected_crossovers;
106105
var addresses_of_selected_crossovers_by_prev_helix_idx =
107106
_get_addresses_of_selected_crossovers_by_prev_helix_idx(selected_crossovers, helices, design);
108107

109-
List<Tuple2<Address, Address>> addresses = [];
108+
List<(Address, Address)> addresses = [];
110109
for (int i = 0; i < helices.length - 1; i++) {
111110
var helix_top = helices[i];
112111
var helix_bot = helices[i + 1];
113-
var helix_idx_top_bot = Tuple2<int, int>(helix_top.idx, helix_bot.idx);
112+
(int, int) helix_idx_top_bot = (helix_top.idx, helix_bot.idx);
114113
var addresses_crossovers_this_helices_pair =
115114
addresses_of_selected_crossovers_by_prev_helix_idx[helix_idx_top_bot]!;
116115

@@ -126,12 +125,11 @@ Please select only one, or select none to default to the first crossover between
126125
return null;
127126
} else if (addresses_crossovers_this_helices_pair.length == 1) {
128127
// first try selected crossovers between this pair of helices
129-
address_top = addresses_crossovers_this_helices_pair.first.item1;
130-
address_bot = addresses_crossovers_this_helices_pair.first.item2;
128+
(address_top, address_bot) = addresses_crossovers_this_helices_pair.first;
131129
} else {
132130
// otherwise if none are selected, find the addresses of first crossover between this pair of helices
133131
// using boolean scaffold/staple settings from user to possible ignore one of those types
134-
Tuple2<Address, Address>? address_top_bot;
132+
(Address, Address)? address_top_bot;
135133
bool use_scaffold = state.ui_state.default_crossover_type_scaffold_for_setting_helix_rolls;
136134
bool use_staple = state.ui_state.default_crossover_type_staple_for_setting_helix_rolls;
137135

@@ -151,50 +149,49 @@ Please select only one, or select none to default to the first crossover between
151149
util.async_alert(msg);
152150
return null;
153151
}
154-
address_top = address_top_bot.item1;
155-
address_bot = address_top_bot.item2;
152+
(address_top, address_bot) = address_top_bot;
156153
}
157-
addresses.add(Tuple2<Address, Address>(address_top, address_bot));
154+
addresses.add((address_top, address_bot));
158155
}
159156
return addresses;
160157
}
161158

162159
// "First" refers to having the lowest offset on helix h1.
163-
Tuple2<Address, Address>? _first_crossover_addresses_between_helices(
160+
(Address, Address)? _first_crossover_addresses_between_helices(
164161
Helix helix_top,
165162
Helix helix_bot,
166163
Design design, {
167164
required bool use_scaffold,
168165
required bool use_staple,
169166
}) {
170-
BuiltList<Tuple2<Address, Crossover>> address_crossovers_on_top =
167+
BuiltList<(Address, Crossover)> address_crossovers_on_top =
171168
design.address_crossover_pairs_by_helix_idx[helix_top.idx]!;
172-
BuiltList<Tuple2<Address, Crossover>> address_crossovers_on_bot =
169+
BuiltList<(Address, Crossover)> address_crossovers_on_bot =
173170
design.address_crossover_pairs_by_helix_idx[helix_bot.idx]!;
174171

175172
// if not using scaffold or crossovers when finding leftmost, filter those out
176173
if (!use_scaffold) {
177174
address_crossovers_on_bot =
178175
address_crossovers_on_bot
179-
.where((address_crossover) => !address_crossover.item2.is_scaffold)
176+
.where((address_crossover) => !address_crossover.$2.is_scaffold)
180177
.toBuiltList();
181178
}
182179
if (!use_staple) {
183180
address_crossovers_on_bot =
184181
address_crossovers_on_bot
185-
.where((address_crossover) => address_crossover.item2.is_scaffold)
182+
.where((address_crossover) => address_crossover.$2.is_scaffold)
186183
.toBuiltList();
187184
}
188185

189186
// find first crossover on h1 that also goes to h2
190-
for (Tuple2<Address, Crossover> address_crossover_top in address_crossovers_on_top) {
191-
Crossover crossover_top = address_crossover_top.item2;
187+
for ((Address, Crossover) address_crossover_top in address_crossovers_on_top) {
188+
Crossover crossover_top = address_crossover_top.$2;
192189
for (var address_crossover_bot in address_crossovers_on_bot) {
193-
var crossover_bot = address_crossover_bot.item2;
190+
var crossover_bot = address_crossover_bot.$2;
194191
if (crossover_bot == crossover_top) {
195-
Address address_top = address_crossover_top.item1;
196-
Address address_bot = address_crossover_bot.item1;
197-
return Tuple2<Address, Address>(address_top, address_bot);
192+
Address address_top = address_crossover_top.$1;
193+
Address address_bot = address_crossover_bot.$1;
194+
return (address_top, address_bot);
198195
}
199196
}
200197
}
@@ -213,20 +210,20 @@ Tuple2<Address, Address>? _first_crossover_addresses_between_helices(
213210
// (7,5): [... (offset,crossover) pairs between 5 and 7, offset is where crossover touches helix 7]
214211
// }
215212
// Sorts each list by the offset on its first helix (first meaning first in order in helices)
216-
Map<Tuple2<int, int>, List<Tuple2<Address, Address>>> _get_addresses_of_selected_crossovers_by_prev_helix_idx(
213+
Map<(int, int), List<(Address, Address)>> _get_addresses_of_selected_crossovers_by_prev_helix_idx(
217214
BuiltSet<Crossover> selected_crossovers,
218215
List<Helix> helices,
219216
Design design,
220217
) {
221218
// this is essentially what we return, but each crossover also carries with it the start offset of
222219
// the helix earlier in the ordering, which helps to sort the lists of crossovers before returning
223-
Map<Tuple2<int, int>, List<Tuple2<Address, Address>>> addresses_top_bot_crossovers = {};
220+
Map<(int, int), List<(Address, Address)>> addresses_top_bot_crossovers = {};
224221

225222
// initialize internal map to have empty lists
226223
for (int i = 0; i < helices.length - 1; i++) {
227224
int idx1 = helices[i].idx;
228225
int idx2 = helices[i + 1].idx;
229-
var pair_idxs = Tuple2<int, int>(idx1, idx2);
226+
(int, int) pair_idxs = (idx1, idx2);
230227
addresses_top_bot_crossovers[pair_idxs] = [];
231228
}
232229

@@ -240,8 +237,8 @@ Map<Tuple2<int, int>, List<Tuple2<Address, Address>>> _get_addresses_of_selected
240237
var next_dom = strand.substrands[crossover.next_domain_idx] as Domain;
241238
var prev_idx = prev_dom.helix;
242239
var next_idx = next_dom.helix;
243-
var pair_idxs = Tuple2<int, int>(prev_idx, next_idx);
244-
var pair_idxs_rev = Tuple2<int, int>(next_idx, prev_idx);
240+
(int, int) pair_idxs = (prev_idx, next_idx);
241+
(int, int) pair_idxs_rev = (next_idx, prev_idx);
245242

246243
if (addresses_top_bot_crossovers.containsKey(pair_idxs) ||
247244
addresses_top_bot_crossovers.containsKey(pair_idxs_rev)) {
@@ -280,7 +277,7 @@ Map<Tuple2<int, int>, List<Tuple2<Address, Address>>> _get_addresses_of_selected
280277
}
281278
var address_top = Address(helix_idx: dom_top.helix, offset: offset_top, forward: dom_top.forward);
282279
var address_bot = Address(helix_idx: dom_bot.helix, offset: offset_bot, forward: dom_bot.forward);
283-
addresses_top_bot_crossovers[pair_idxs]!.add(Tuple2<Address, Address>(address_top, address_bot));
280+
addresses_top_bot_crossovers[pair_idxs]!.add((address_top, address_bot));
284281
}
285282
}
286283

@@ -307,7 +304,7 @@ List<RollXY> _calculate_rolls_and_positions(
307304
Design design,
308305
Geometry geometry,
309306
List<Helix> helices,
310-
List<Tuple2<Address, Address>> addresses,
307+
List<(Address, Address)> addresses,
311308
double first_roll,
312309
) {
313310
assert(helices.length == addresses.length + 1);
@@ -317,8 +314,8 @@ List<RollXY> _calculate_rolls_and_positions(
317314
List<RollXY> rollxys = [RollXY(roll: first_roll, x: x, y: y)];
318315

319316
for (int i = 0; i < addresses.length; i++) {
320-
var address_top = addresses[i].item1;
321-
var address_bot = addresses[i].item2;
317+
var (address_top, address_bot) = addresses[i];
318+
322319
var roll = rollxys[i].roll;
323320
var x = rollxys[i].x;
324321
var y = rollxys[i].y;

lib/src/middleware/oxdna_export.dart

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import 'package:scadnano/src/state/grid.dart';
1515
import 'package:scadnano/src/state/loopout.dart';
1616
import 'package:scadnano/src/state/position3d.dart';
1717
import 'package:scadnano/src/state/strand.dart';
18-
import 'package:tuple/tuple.dart';
1918
import '../state/app_state.dart';
2019
import '../actions/actions.dart' as actions;
2120
import '../state/helix.dart';
@@ -41,9 +40,7 @@ First select some strands, or choose Export🡒oxDNA to export all strands in th
4140
}
4241

4342
if (action is actions.OxdnaExport) {
44-
Tuple2<String, String> dat_top = to_oxdna_format(state.design, strands_to_export);
45-
String dat = dat_top.item1;
46-
String top = dat_top.item2;
43+
var (dat, top) = to_oxdna_format(state.design, strands_to_export); // (String, String)
4744

4845
String default_filename = state.ui_state.loaded_filename;
4946
String default_filename_dat = path.setExtension(default_filename, '.dat');
@@ -152,11 +149,9 @@ String to_oxview_format(Design design, List<Strand> strands_to_export) {
152149
);
153150
for (int helix in base_pairs_map.keys) {
154151
for (var offset_dom_strands in base_pairs_map[helix]!) {
155-
int offset = offset_dom_strands.item1;
156-
Domain domain1 = offset_dom_strands.item2;
157-
Domain domain2 = offset_dom_strands.item3;
158-
Strand sc_strand1 = offset_dom_strands.item4;
159-
Strand sc_strand2 = offset_dom_strands.item5;
152+
// (int, Domain, Domain, Strand, Strand)
153+
var (offset, domain1, domain2, sc_strand1, sc_strand2) = offset_dom_strands;
154+
160155
Map<String, dynamic> oxv_strand1 = oxview_strand_map[sc_strand1.id];
161156
Map<String, dynamic> oxv_strand2 = oxview_strand_map[sc_strand2.id];
162157
int d1 = sc_strand1.domain_offset_to_strand_dna_idx(domain1, offset, false);
@@ -195,10 +190,9 @@ String to_oxview_format(Design design, List<Strand> strands_to_export) {
195190
return content;
196191
}
197192

198-
Tuple2<String, String> to_oxdna_format(Design design, [List<Strand>? strands_to_export = null]) {
193+
(String, String) to_oxdna_format(Design design, [List<Strand>? strands_to_export = null]) {
199194
OxdnaSystem system = convert_design_to_oxdna_system(design, strands_to_export);
200-
Tuple2<String, String> dat_top = system.oxdna_output();
201-
return dat_top;
195+
return system.oxdna_output();
202196
}
203197

204198
class OxdnaVector {
@@ -320,7 +314,7 @@ class OxdnaSystem {
320314
}
321315
}
322316

323-
Tuple2<String, String> oxdna_output() {
317+
(String, String) oxdna_output() {
324318
OxdnaVector bbox = compute_bounding_box();
325319

326320
List<String> dat_list = ['t = 0', 'b = ${bbox.x} ${bbox.y} ${bbox.z}', 'E = 0 0 0'];
@@ -358,14 +352,14 @@ class OxdnaSystem {
358352

359353
top = '${nuc_count} ${strand_count}\n' + top;
360354

361-
return Tuple2<String, String>(dat, top);
355+
return (dat, top);
362356
}
363357
}
364358

365359
const NM_TO_OX_UNITS = 1.0 / 0.8518;
366360

367361
// returns the origin, forward, and normal vectors of a helix
368-
Tuple3<OxdnaVector, OxdnaVector, OxdnaVector> oxdna_get_helix_vectors(Design design, Helix helix) {
362+
(OxdnaVector, OxdnaVector, OxdnaVector) oxdna_get_helix_vectors(Design design, Helix helix) {
369363
/*
370364
TODO: document functions/methods with docstrings
371365
:param helix:
@@ -426,7 +420,7 @@ Tuple3<OxdnaVector, OxdnaVector, OxdnaVector> oxdna_get_helix_vectors(Design des
426420

427421
var origin = (position_in_helix_group_rotated + helix_group_offset) * NM_TO_OX_UNITS;
428422

429-
return Tuple3<OxdnaVector, OxdnaVector, OxdnaVector>(origin, forward, normal);
423+
return (origin, forward, normal);
430424
}
431425

432426
OxdnaSystem convert_design_to_oxdna_system(Design design, [List<Strand>? strands_to_export = null]) {
@@ -472,7 +466,7 @@ OxdnaSystem convert_design_to_oxdna_system(Design design, [List<Strand>? strands
472466
};
473467

474468
for (var strand in strands_to_export) {
475-
List<Tuple2<OxdnaStrand, bool>> strand_domains = [];
469+
List<(OxdnaStrand, bool)> strand_domains = [];
476470
for (int ss_idx = 0; ss_idx < strand.substrands.length; ss_idx++) {
477471
var domain = strand.substrands[ss_idx];
478472
var ox_strand = OxdnaStrand();
@@ -487,10 +481,7 @@ OxdnaSystem convert_design_to_oxdna_system(Design design, [List<Strand>? strands
487481
var group = design.groups[helix.group]!;
488482
var geometry = group.geometry ?? design.geometry;
489483
var step_rot = -360 / geometry.bases_per_turn;
490-
var origin_forward_normal = helix_vectors[helix.idx]!;
491-
var origin = origin_forward_normal.item1;
492-
var forward = origin_forward_normal.item2;
493-
var normal = origin_forward_normal.item3;
484+
var (origin, forward, normal) = helix_vectors[helix.idx]!; // (OxdnaVector, OxdnaVector, OxdnaVector)
494485

495486
if (!domain.forward) {
496487
normal = normal.rotate(-geometry.minor_groove_angle, forward);
@@ -545,7 +536,7 @@ OxdnaSystem convert_design_to_oxdna_system(Design design, [List<Strand>? strands
545536
if (!domain.forward) {
546537
ox_strand.nucleotides = List<OxdnaNucleotide>.from(ox_strand.nucleotides.reversed);
547538
}
548-
strand_domains.add(Tuple2<OxdnaStrand, bool>(ox_strand, false));
539+
strand_domains.add((ox_strand, false));
549540
// because we need to know the positions of nucleotides before and after the loopout
550541
// we temporarily store domain strands with a boolean that is true if it's a loopout
551542
// handle loopouts
@@ -560,7 +551,7 @@ OxdnaSystem convert_design_to_oxdna_system(Design design, [List<Strand>? strands
560551
var nuc = OxdnaNucleotide(center, normal, forward, base);
561552
ox_strand.nucleotides.add(nuc);
562553
}
563-
strand_domains.add(Tuple2<OxdnaStrand, bool>(ox_strand, true));
554+
strand_domains.add((ox_strand, true));
564555
} else if (domain is Extension) {
565556
bool is_5p = ss_idx == 0;
566557
var helix = design.helices[domain.adjacent_domain.helix]!;
@@ -575,7 +566,7 @@ OxdnaSystem convert_design_to_oxdna_system(Design design, [List<Strand>? strands
575566
mod_map: mod_map,
576567
);
577568
ox_strand.nucleotides.addAll(nucleotides);
578-
strand_domains.add(Tuple2<OxdnaStrand, bool>(ox_strand, false));
569+
strand_domains.add((ox_strand, false));
579570
} else {
580571
throw AssertionError('unreachable');
581572
}
@@ -584,12 +575,11 @@ OxdnaSystem convert_design_to_oxdna_system(Design design, [List<Strand>? strands
584575
var sstrand = OxdnaStrand();
585576
// process loopouts and join strands
586577
for (int i = 0; i < strand_domains.length; i++) {
587-
var dstrand_is_loopout = strand_domains[i];
588-
var dstrand = dstrand_is_loopout.item1;
589-
var is_loopout = dstrand_is_loopout.item2;
578+
var (dstrand, is_loopout) = strand_domains[i]; // (OxdnaStrand, bool)
579+
590580
if (is_loopout) {
591-
var prev_nuc = strand_domains[i - 1].item1.nucleotides.last;
592-
var next_nuc = strand_domains[i + 1].item1.nucleotides.first;
581+
var prev_nuc = strand_domains[i - 1].$1.nucleotides.last;
582+
var next_nuc = strand_domains[i + 1].$1.nucleotides.first;
593583

594584
int strand_length = dstrand.nucleotides.length;
595585

@@ -618,7 +608,7 @@ List<OxdnaNucleotide> _compute_extension_nucleotides({
618608
required Geometry geometry,
619609
required Strand strand,
620610
required bool is_5p,
621-
required Map<int, Tuple3<OxdnaVector, OxdnaVector, OxdnaVector>> helix_vectors,
611+
required Map<int, (OxdnaVector, OxdnaVector, OxdnaVector)> helix_vectors,
622612
required Map<int, List<int>> mod_map,
623613
}) {
624614
var step_rot = -360 / geometry.bases_per_turn;
@@ -628,9 +618,8 @@ List<OxdnaNucleotide> _compute_extension_nucleotides({
628618
var offset = is_5p ? adj_dom.offset_5p : adj_dom.offset_3p; // offset of attached end of domain
629619

630620
var origin_forward_normal = helix_vectors[adj_dom.helix]!;
631-
var origin_ = origin_forward_normal.item1;
632-
var forward = origin_forward_normal.item2;
633-
var normal = origin_forward_normal.item3;
621+
622+
var (origin_, forward, normal) = origin_forward_normal; // (OxdnaVector, OxdnaVector, OxdnaVector)
634623

635624
if (!adj_dom.forward) {
636625
normal = normal.rotate(-geometry.minor_groove_angle, forward);

lib/src/middleware/oxview_update_view.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import 'package:scadnano/src/state/grid.dart';
1717
import 'package:scadnano/src/state/loopout.dart';
1818
import 'package:scadnano/src/state/position3d.dart';
1919
import 'package:scadnano/src/state/strand.dart';
20-
import 'package:tuple/tuple.dart';
2120
import '../state/app_state.dart';
2221
import '../actions/actions.dart' as actions;
2322
import '../state/helix.dart';
@@ -67,9 +66,7 @@ void update_oxview_view(Design design, [IFrameElement? frame = null]) {
6766
List<Strand> strands_to_export = design.strands.toList();
6867

6968
// String content = to_oxview_format(design, strands_to_export);
70-
Tuple2<String, String> dat_top = to_oxdna_format(design, strands_to_export);
71-
String dat = dat_top.item1;
72-
String top = dat_top.item2;
69+
var (dat, top) = to_oxdna_format(design, strands_to_export); // (String, String)
7370

7471
Blob blob_dat = new Blob([dat], blob_type_to_string(BlobType.text));
7572
Blob blob_top = new Blob([top], blob_type_to_string(BlobType.text));

lib/src/middleware/reselect_moved_dna_extension_ends.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import 'package:react/react.dart';
22
import 'package:redux/redux.dart';
33
import 'package:built_collection/built_collection.dart';
44
import 'package:scadnano/src/state/extension.dart';
5-
import 'package:tuple/tuple.dart';
65

76
import '../state/domain.dart';
87
import '../state/dna_end.dart';

lib/src/middleware/selections_intersect_box_compute.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import 'dart:svg' as svg;
55
import 'package:built_collection/built_collection.dart';
66
import 'package:redux/redux.dart';
77
import 'package:scadnano/src/state/selection_rope.dart';
8-
import 'package:tuple/tuple.dart';
98

109
import '../state/select_mode.dart';
1110
import '../state/selection_box.dart';

lib/src/middleware/system_clipboard.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,7 @@ bool paste_is_impossible_from_clipboard(String clipboard_content, bool in_browse
127127
var strands_and_helices_view_order = parse_strands_and_helices_view_order_from_clipboard(clipboard_content);
128128
if (strands_and_helices_view_order == null) return true;
129129

130-
List<Strand> strands = strands_and_helices_view_order.item1;
131-
List<int>? helices_view_order = strands_and_helices_view_order.item2;
130+
var (strands, helices_view_order) = strands_and_helices_view_order; // (List<Strand>, List<int>?)
132131

133132
if (strands.isEmpty) return true;
134133

0 commit comments

Comments
 (0)