4
4
* * Constant population size
5
5
* * Poisson number of crossovers per parent, per mating.
6
6
* * Overlapping generations supported.
7
- * * Simplifcation includes unary nodes for later "recapitation".
7
+ * * Simplifcation keeps input roots for later "recapitation".
8
8
*
9
9
* On the rust side:
10
10
*
11
- * * Runtime errors from all dependencies propagate to main.
11
+ * * Runtime errors are handled when they occur.
12
+ * We do this because stable rust does not have
13
+ * support for back traces.
12
14
* * No "unsafe" tskit C code is called directly.
13
15
* * By default, clap doesn't allow argument values to start
14
16
* with a hyphen ('-'). This is handy, as it automatically
@@ -21,7 +23,6 @@ use rand::rngs::StdRng;
21
23
use rand:: Rng ;
22
24
use rand:: SeedableRng ;
23
25
use rand_distr:: { Exp , Uniform } ;
24
- use std:: error:: Error ;
25
26
26
27
struct SimParams {
27
28
pub popsize : u32 ,
@@ -200,24 +201,15 @@ fn death_and_parents(
200
201
}
201
202
}
202
203
203
- fn mendel (
204
- pnodes : & mut ( tskit:: tsk_id_t , tskit:: tsk_id_t ) ,
205
- rng : & mut StdRng ,
206
- ) -> Result < ( ) , Box < dyn Error > > {
204
+ fn mendel ( pnodes : & mut ( tskit:: tsk_id_t , tskit:: tsk_id_t ) , rng : & mut StdRng ) {
207
205
let x: f64 = rng. gen ( ) ;
208
206
match x. partial_cmp ( & 0.5 ) {
209
207
Some ( std:: cmp:: Ordering :: Less ) => {
210
208
std:: mem:: swap ( & mut pnodes. 0 , & mut pnodes. 1 ) ;
211
209
}
212
210
Some ( _) => ( ) ,
213
- None => {
214
- return Err ( Box :: new ( tskit:: TskitError :: ValueError {
215
- got : String :: from ( "None" ) ,
216
- expected : String :: from ( "Some(std::cmp::Ordering)" ) ,
217
- } ) ) ;
218
- }
211
+ None => panic ! ( "Unexpected None" ) ,
219
212
}
220
- Ok ( ( ) )
221
213
}
222
214
223
215
fn crossover_and_record_edges_details (
@@ -226,40 +218,52 @@ fn crossover_and_record_edges_details(
226
218
params : & SimParams ,
227
219
tables : & mut tskit:: TableCollection ,
228
220
rng : & mut StdRng ,
229
- ) -> Result < ( ) , Box < dyn Error > > {
221
+ ) {
230
222
if params. xovers == 0.0 {
231
- let _ = tables. add_edge ( 0. , tables. sequence_length ( ) , parent. node0 , offspring_node) ?;
223
+ match tables. add_edge ( 0. , tables. sequence_length ( ) , parent. node0 , offspring_node) {
224
+ Ok ( _) => ( ) ,
225
+ Err ( e) => panic ! ( "{}" , e) ,
226
+ }
232
227
} else {
233
228
let mut pnodes = ( parent. node0 , parent. node1 ) ;
234
- mendel ( & mut pnodes, rng) ? ;
229
+ mendel ( & mut pnodes, rng) ;
235
230
236
231
let mut p0 = parent. node0 ;
237
232
let mut p1 = parent. node1 ;
238
233
239
- let exp = Exp :: new ( params. xovers / tables. sequence_length ( ) ) ?;
234
+ let exp = match Exp :: new ( params. xovers / tables. sequence_length ( ) ) {
235
+ Ok ( e) => e,
236
+ Err ( e) => panic ! ( "{}" , e) ,
237
+ } ;
240
238
let mut current_pos = 0.0 ;
241
239
loop {
242
240
let next_length = rng. sample ( exp) ;
243
241
match ( current_pos + next_length) . partial_cmp ( & tables. sequence_length ( ) ) {
244
242
Some ( std:: cmp:: Ordering :: Less ) => {
245
- tables. add_edge ( current_pos, current_pos + next_length, p0, offspring_node) ?;
243
+ match tables. add_edge (
244
+ current_pos,
245
+ current_pos + next_length,
246
+ p0,
247
+ offspring_node,
248
+ ) {
249
+ Ok ( _) => ( ) ,
250
+ Err ( e) => panic ! ( "{}" , e) ,
251
+ }
246
252
std:: mem:: swap ( & mut p0, & mut p1) ;
247
253
current_pos += next_length;
248
254
}
249
255
Some ( _) => {
250
- tables. add_edge ( current_pos, tables. sequence_length ( ) , p0, offspring_node) ?;
256
+ match tables. add_edge ( current_pos, tables. sequence_length ( ) , p0, offspring_node)
257
+ {
258
+ Ok ( _) => ( ) ,
259
+ Err ( e) => panic ! ( "{}" , e) ,
260
+ }
251
261
break ;
252
262
}
253
- None => {
254
- return Err ( Box :: new ( tskit:: TskitError :: ValueError {
255
- got : String :: from ( "None" ) ,
256
- expected : String :: from ( "Some(std::cmp::Ordering)" ) ,
257
- } ) ) ;
258
- }
263
+ None => panic ! ( "Unexpected None" ) ,
259
264
}
260
265
}
261
266
}
262
- Ok ( ( ) )
263
267
}
264
268
265
269
fn crossover_and_record_edges (
@@ -268,9 +272,9 @@ fn crossover_and_record_edges(
268
272
params : & SimParams ,
269
273
tables : & mut tskit:: TableCollection ,
270
274
rng : & mut StdRng ,
271
- ) -> Result < ( ) , Box < dyn Error > > {
272
- crossover_and_record_edges_details ( parents. parent0 , offspring_nodes. 0 , params, tables, rng) ? ;
273
- crossover_and_record_edges_details ( parents. parent1 , offspring_nodes. 1 , params, tables, rng)
275
+ ) {
276
+ crossover_and_record_edges_details ( parents. parent0 , offspring_nodes. 0 , params, tables, rng) ;
277
+ crossover_and_record_edges_details ( parents. parent1 , offspring_nodes. 1 , params, tables, rng) ;
274
278
}
275
279
276
280
fn births (
@@ -280,70 +284,85 @@ fn births(
280
284
tables : & mut tskit:: TableCollection ,
281
285
alive : & mut [ Diploid ] ,
282
286
rng : & mut StdRng ,
283
- ) -> Result < ( ) , Box < dyn Error > > {
287
+ ) {
284
288
for p in parents {
285
289
// Register the two nodes for our offspring
286
- let offspring_node_0 = tables. add_node (
290
+ let node0 = match tables. add_node (
287
291
0 , // flags
288
292
birth_time as f64 , // time
289
293
tskit:: TSK_NULL , // population
290
294
// individual
291
295
tskit:: TSK_NULL ,
292
- ) ?;
293
- let offspring_node_1 =
294
- tables. add_node ( 0 , birth_time as f64 , tskit:: TSK_NULL , tskit:: TSK_NULL ) ?;
296
+ ) {
297
+ Ok ( x) => x,
298
+ Err ( e) => panic ! ( "{}" , e) ,
299
+ } ;
300
+ let node1 = match tables. add_node ( 0 , birth_time as f64 , tskit:: TSK_NULL , tskit:: TSK_NULL ) {
301
+ Ok ( x) => x,
302
+ Err ( e) => panic ! ( "{}" , e) ,
303
+ } ;
295
304
296
305
// Replace a dead individual
297
306
// with our newborn.
298
- alive[ p. index ] = Diploid {
299
- node0 : offspring_node_0,
300
- node1 : offspring_node_1,
301
- } ;
307
+ alive[ p. index ] = Diploid { node0, node1 } ;
302
308
303
- crossover_and_record_edges ( p, ( offspring_node_0 , offspring_node_1 ) , params, tables, rng) ? ;
309
+ crossover_and_record_edges ( p, ( node0 , node1 ) , params, tables, rng) ;
304
310
}
305
- Ok ( ( ) )
306
311
}
307
312
308
- fn simplify (
309
- alive : & mut [ Diploid ] ,
310
- tables : & mut tskit:: TableCollection ,
311
- ) -> Result < ( ) , Box < dyn Error > > {
313
+ fn simplify ( alive : & mut [ Diploid ] , tables : & mut tskit:: TableCollection ) {
312
314
let mut samples = vec ! [ ] ;
313
315
for a in alive. iter ( ) {
314
316
assert ! ( a. node0 != a. node1) ;
315
317
samples. push ( a. node0 ) ;
316
318
samples. push ( a. node1 ) ;
317
319
}
318
320
319
- tables. full_sort ( tskit:: TableSortOptions :: default ( ) ) ?;
321
+ match tables. full_sort ( tskit:: TableSortOptions :: default ( ) ) {
322
+ Ok ( _) => ( ) ,
323
+ Err ( e) => panic ! ( "{}" , e) ,
324
+ }
320
325
321
- match tables. simplify ( & samples, tskit:: SimplificationOptions :: KEEP_UNARY , true ) ? {
322
- Some ( idmap) => {
323
- for a in alive. iter_mut ( ) {
324
- a. node0 = idmap[ a. node0 as usize ] ;
325
- assert ! ( a. node0 != tskit:: TSK_NULL ) ;
326
- a. node1 = idmap[ a. node1 as usize ] ;
327
- assert ! ( a. node1 != tskit:: TSK_NULL ) ;
326
+ match tables. simplify (
327
+ & samples,
328
+ tskit:: SimplificationOptions :: KEEP_INPUT_ROOTS ,
329
+ true ,
330
+ ) {
331
+ Ok ( x) => match x {
332
+ Some ( idmap) => {
333
+ for a in alive. iter_mut ( ) {
334
+ a. node0 = idmap[ a. node0 as usize ] ;
335
+ assert ! ( a. node0 != tskit:: TSK_NULL ) ;
336
+ a. node1 = idmap[ a. node1 as usize ] ;
337
+ assert ! ( a. node1 != tskit:: TSK_NULL ) ;
338
+ }
328
339
}
329
- Ok ( ( ) )
330
- }
331
- None => Err ( Box :: new ( tskit:: TskitError :: ValueError {
332
- got : String :: from ( "None" ) ,
333
- expected : String :: from ( "Some(idmap) from simplification function" ) ,
334
- } ) ) ,
335
- }
340
+ None => panic ! ( "Unexpected None" ) ,
341
+ } ,
342
+ Err ( e) => panic ! ( "{}" , e) ,
343
+ } ;
336
344
}
337
345
338
- fn runsim ( params : & SimParams ) -> Result < tskit:: TableCollection , Box < dyn std:: error:: Error > > {
339
- let mut tables = tskit:: TableCollection :: new ( params. genome_length ) ?;
346
+ fn runsim ( params : & SimParams ) -> tskit:: TableCollection {
347
+ let mut tables = match tskit:: TableCollection :: new ( params. genome_length ) {
348
+ Ok ( x) => x,
349
+ Err ( e) => panic ! ( "{}" , e) ,
350
+ } ;
340
351
341
352
let mut rng = StdRng :: seed_from_u64 ( params. seed ) ;
342
353
343
354
let mut alive: Vec < Diploid > = vec ! [ ] ;
344
355
for _ in 0 ..params. popsize {
345
- let node0 = tables. add_node ( 0 , params. nsteps as f64 , tskit:: TSK_NULL , tskit:: TSK_NULL ) ?;
346
- let node1 = tables. add_node ( 0 , params. nsteps as f64 , tskit:: TSK_NULL , tskit:: TSK_NULL ) ?;
356
+ let node0 = match tables. add_node ( 0 , params. nsteps as f64 , tskit:: TSK_NULL , tskit:: TSK_NULL )
357
+ {
358
+ Ok ( x) => x,
359
+ Err ( e) => panic ! ( "{}" , e) ,
360
+ } ;
361
+ let node1 = match tables. add_node ( 0 , params. nsteps as f64 , tskit:: TSK_NULL , tskit:: TSK_NULL )
362
+ {
363
+ Ok ( x) => x,
364
+ Err ( e) => panic ! ( "{}" , e) ,
365
+ } ;
347
366
alive. push ( Diploid { node0, node1 } ) ;
348
367
}
349
368
@@ -353,32 +372,29 @@ fn runsim(params: &SimParams) -> Result<tskit::TableCollection, Box<dyn std::err
353
372
for step in ( 0 ..params. nsteps ) . rev ( ) {
354
373
parents. clear ( ) ;
355
374
death_and_parents ( & alive, & params, & mut parents, & mut rng) ;
356
- births ( & parents, & params, step, & mut tables, & mut alive, & mut rng) ? ;
375
+ births ( & parents, & params, step, & mut tables, & mut alive, & mut rng) ;
357
376
let remainder = step % params. simplification_interval ;
358
377
match step < params. nsteps && remainder == 0 {
359
378
true => {
360
- simplify ( & mut alive, & mut tables) ? ;
379
+ simplify ( & mut alive, & mut tables) ;
361
380
simplified = true ;
362
381
}
363
382
false => simplified = false ,
364
383
}
365
384
}
366
385
367
386
if !simplified {
368
- simplify ( & mut alive, & mut tables) ? ;
387
+ simplify ( & mut alive, & mut tables) ;
369
388
}
370
389
371
- Ok ( tables)
390
+ tables
372
391
}
373
392
374
393
fn main ( ) {
375
394
let params = SimParams :: new ( ) ;
376
395
params. validate ( ) . unwrap ( ) ;
377
396
378
- let tables = match runsim ( & params) {
379
- Ok ( t) => t,
380
- Err ( e) => panic ! ( "{}" , e) ,
381
- } ;
397
+ let tables = runsim ( & params) ;
382
398
let treeseq = tables
383
399
. tree_sequence ( tskit:: TreeSequenceFlags :: BUILD_INDEXES )
384
400
. unwrap ( ) ;
@@ -392,7 +408,7 @@ fn main() {
392
408
fn test_bad_genome_length ( ) {
393
409
let mut params = SimParams :: new ( ) ;
394
410
params. genome_length = -1.0 ;
395
- let _tables = runsim ( & params) . unwrap ( ) ;
411
+ let _tables = runsim ( & params) ;
396
412
}
397
413
398
414
#[ test]
@@ -401,10 +417,7 @@ fn test_nonoverlapping_generations() {
401
417
params. nsteps = 100 ;
402
418
params. xovers = 1e-3 ;
403
419
params. validate ( ) . unwrap ( ) ;
404
- match runsim ( & params) {
405
- Ok ( _) => ( ) ,
406
- Err ( e) => panic ! ( "{}" , e) ,
407
- }
420
+ runsim ( & params) ;
408
421
}
409
422
410
423
#[ test]
@@ -415,8 +428,5 @@ fn test_overlapping_generations() {
415
428
params. psurvival = 0.25 ;
416
429
params. seed = 616161 ;
417
430
params. validate ( ) . unwrap ( ) ;
418
- match runsim ( & params) {
419
- Ok ( _) => ( ) ,
420
- Err ( e) => panic ! ( "{}" , e) ,
421
- }
431
+ runsim ( & params) ;
422
432
}
0 commit comments