Skip to content

Commit 60d75c6

Browse files
jeromekellehermergify[bot]
authored andcommitted
Improve error handling on weighted stats
1 parent e20a0a2 commit 60d75c6

File tree

7 files changed

+188
-34
lines changed

7 files changed

+188
-34
lines changed

c/tests/test_stats.c

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,16 @@ verify_window_errors(tsk_treeseq_t *ts, tsk_flags_t mode)
345345
ts, 1, W, 1, general_stat_error, NULL, 2, windows, options, sigma);
346346
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_BAD_WINDOWS);
347347

348+
windows[0] = -1;
349+
ret = tsk_treeseq_general_stat(
350+
ts, 1, W, 1, general_stat_error, NULL, 2, windows, options, sigma);
351+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_BAD_WINDOWS);
352+
353+
windows[1] = -1;
354+
ret = tsk_treeseq_general_stat(
355+
ts, 1, W, 1, general_stat_error, NULL, 1, windows, options, sigma);
356+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_BAD_WINDOWS);
357+
348358
windows[0] = 10;
349359
ret = tsk_treeseq_general_stat(
350360
ts, 1, W, 1, general_stat_error, NULL, 2, windows, options, sigma);
@@ -438,11 +448,10 @@ verify_node_general_stat_errors(tsk_treeseq_t *ts)
438448
static void
439449
verify_one_way_weighted_func_errors(tsk_treeseq_t *ts, one_way_weighted_method *method)
440450
{
441-
// we don't have any specific errors for this function
442-
// but we might add some in the future
443451
int ret;
444452
tsk_size_t num_samples = tsk_treeseq_get_num_samples(ts);
445453
double *weights = tsk_malloc(num_samples * sizeof(double));
454+
double bad_windows[] = { 0, -1 };
446455
double result;
447456
tsk_size_t j;
448457

@@ -451,7 +460,10 @@ verify_one_way_weighted_func_errors(tsk_treeseq_t *ts, one_way_weighted_method *
451460
}
452461

453462
ret = method(ts, 0, weights, 0, NULL, 0, &result);
454-
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_BAD_STATE_DIMS);
463+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_INSUFFICIENT_WEIGHTS);
464+
465+
ret = method(ts, 1, weights, 1, bad_windows, 0, &result);
466+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_BAD_WINDOWS);
455467

456468
free(weights);
457469
}
@@ -460,12 +472,11 @@ static void
460472
verify_one_way_weighted_covariate_func_errors(
461473
tsk_treeseq_t *ts, one_way_covariates_method *method)
462474
{
463-
// we don't have any specific errors for this function
464-
// but we might add some in the future
465475
int ret;
466476
tsk_size_t num_samples = tsk_treeseq_get_num_samples(ts);
467477
double *weights = tsk_malloc(num_samples * sizeof(double));
468478
double *covariates = NULL;
479+
double bad_windows[] = { 0, -1 };
469480
double result;
470481
tsk_size_t j;
471482

@@ -474,7 +485,10 @@ verify_one_way_weighted_covariate_func_errors(
474485
}
475486

476487
ret = method(ts, 0, weights, 0, covariates, 0, NULL, 0, &result);
477-
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_BAD_STATE_DIMS);
488+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_INSUFFICIENT_WEIGHTS);
489+
490+
ret = method(ts, 1, weights, 0, covariates, 1, bad_windows, 0, &result);
491+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_BAD_WINDOWS);
478492

479493
free(weights);
480494
}
@@ -558,6 +572,28 @@ verify_two_way_stat_func_errors(tsk_treeseq_t *ts, general_sample_stat_method *m
558572
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_BAD_SAMPLE_SET_INDEX);
559573
}
560574

575+
static void
576+
verify_two_way_weighted_stat_func_errors(
577+
tsk_treeseq_t *ts, two_way_weighted_method *method)
578+
{
579+
int ret;
580+
tsk_id_t indexes[] = { 0, 0, 0, 1 };
581+
double bad_windows[] = { -1, -1 };
582+
double weights[10];
583+
double result[10];
584+
585+
memset(weights, 0, sizeof(weights));
586+
587+
ret = method(ts, 2, weights, 2, indexes, 0, NULL, result, 0);
588+
CU_ASSERT_EQUAL_FATAL(ret, 0);
589+
590+
ret = method(ts, 0, weights, 2, indexes, 0, NULL, result, 0);
591+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_INSUFFICIENT_WEIGHTS);
592+
593+
ret = method(ts, 2, weights, 2, indexes, 1, bad_windows, result, 0);
594+
CU_ASSERT_EQUAL_FATAL(ret, TSK_ERR_BAD_WINDOWS);
595+
}
596+
561597
static void
562598
verify_three_way_stat_func_errors(tsk_treeseq_t *ts, general_sample_stat_method *method)
563599
{
@@ -1504,32 +1540,54 @@ test_paper_ex_genetic_relatedness(void)
15041540
tsk_treeseq_free(&ts);
15051541
}
15061542

1543+
static void
1544+
test_paper_ex_genetic_relatedness_errors(void)
1545+
{
1546+
tsk_treeseq_t ts;
1547+
1548+
tsk_treeseq_from_text(&ts, 10, paper_ex_nodes, paper_ex_edges, NULL, paper_ex_sites,
1549+
paper_ex_mutations, paper_ex_individuals, NULL, 0);
1550+
verify_two_way_stat_func_errors(&ts, tsk_treeseq_genetic_relatedness);
1551+
tsk_treeseq_free(&ts);
1552+
}
1553+
15071554
static void
15081555
test_paper_ex_genetic_relatedness_weighted(void)
15091556
{
15101557
tsk_treeseq_t ts;
15111558
double weights[] = { 1.2, 0.1, 0.0, 0.0, 3.4, 5.0, 1.0, -1.0 };
15121559
tsk_id_t indexes[] = { 0, 0, 0, 1 };
1513-
double result[2];
1560+
double result[100];
1561+
tsk_size_t num_weights;
15141562
int ret;
15151563

15161564
tsk_treeseq_from_text(&ts, 10, paper_ex_nodes, paper_ex_edges, NULL, paper_ex_sites,
15171565
paper_ex_mutations, paper_ex_individuals, NULL, 0);
15181566

1519-
ret = tsk_treeseq_genetic_relatedness_weighted(
1520-
&ts, 2, weights, 2, indexes, 0, NULL, result, TSK_STAT_SITE);
1521-
CU_ASSERT_EQUAL_FATAL(ret, 0);
1567+
for (num_weights = 1; num_weights < 3; num_weights++) {
1568+
ret = tsk_treeseq_genetic_relatedness_weighted(
1569+
&ts, num_weights, weights, 2, indexes, 0, NULL, result, TSK_STAT_SITE);
1570+
CU_ASSERT_EQUAL_FATAL(ret, 0);
1571+
ret = tsk_treeseq_genetic_relatedness_weighted(
1572+
&ts, num_weights, weights, 2, indexes, 0, NULL, result, TSK_STAT_BRANCH);
1573+
CU_ASSERT_EQUAL_FATAL(ret, 0);
1574+
ret = tsk_treeseq_genetic_relatedness_weighted(
1575+
&ts, num_weights, weights, 2, indexes, 0, NULL, result, TSK_STAT_NODE);
1576+
CU_ASSERT_EQUAL_FATAL(ret, 0);
1577+
}
1578+
15221579
tsk_treeseq_free(&ts);
15231580
}
15241581

15251582
static void
1526-
test_paper_ex_genetic_relatedness_errors(void)
1583+
test_paper_ex_genetic_relatedness_weighted_errors(void)
15271584
{
15281585
tsk_treeseq_t ts;
15291586

15301587
tsk_treeseq_from_text(&ts, 10, paper_ex_nodes, paper_ex_edges, NULL, paper_ex_sites,
15311588
paper_ex_mutations, paper_ex_individuals, NULL, 0);
1532-
verify_two_way_stat_func_errors(&ts, tsk_treeseq_genetic_relatedness);
1589+
verify_two_way_weighted_stat_func_errors(
1590+
&ts, tsk_treeseq_genetic_relatedness_weighted);
15331591
tsk_treeseq_free(&ts);
15341592
}
15351593

@@ -2128,6 +2186,8 @@ main(int argc, char **argv)
21282186
{ "test_paper_ex_genetic_relatedness", test_paper_ex_genetic_relatedness },
21292187
{ "test_paper_ex_genetic_relatedness_weighted",
21302188
test_paper_ex_genetic_relatedness_weighted },
2189+
{ "test_paper_ex_genetic_relatedness_weighted_errors",
2190+
test_paper_ex_genetic_relatedness_weighted_errors },
21312191
{ "test_paper_ex_Y2_errors", test_paper_ex_Y2_errors },
21322192
{ "test_paper_ex_Y2", test_paper_ex_Y2 },
21332193
{ "test_paper_ex_f2_errors", test_paper_ex_f2_errors },

c/tskit/core.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,10 @@ tsk_strerror_internal(int err)
475475
"statistic. "
476476
"(TSK_ERR_STAT_SPAN_NORMALISE_UNSUPPORTED)";
477477
break;
478+
case TSK_ERR_INSUFFICIENT_WEIGHTS:
479+
ret = "Insufficient weights provided (at least 1 required). "
480+
"(TSK_ERR_INSUFFICIENT_WEIGHTS)";
481+
break;
478482

479483
/* Mutation mapping errors */
480484
case TSK_ERR_GENOTYPES_ALL_MISSING:

c/tskit/core.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,10 @@ The TSK_STAT_SPAN_NORMALISE option was passed to a statistic that does
685685
not support it.
686686
*/
687687
#define TSK_ERR_STAT_SPAN_NORMALISE_UNSUPPORTED -912
688+
/**
689+
Insufficient weights were provided.
690+
*/
691+
#define TSK_ERR_INSUFFICIENT_WEIGHTS -913
688692
/** @} */
689693

690694
/**

c/tskit/trees.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2639,6 +2639,10 @@ tsk_treeseq_trait_covariance(const tsk_treeseq_t *self, tsk_size_t num_weights,
26392639
ret = TSK_ERR_NO_MEMORY;
26402640
goto out;
26412641
}
2642+
if (num_weights == 0) {
2643+
ret = TSK_ERR_INSUFFICIENT_WEIGHTS;
2644+
goto out;
2645+
}
26422646

26432647
// center weights
26442648
for (j = 0; j < num_samples; j++) {
@@ -2710,7 +2714,7 @@ tsk_treeseq_trait_correlation(const tsk_treeseq_t *self, tsk_size_t num_weights,
27102714
}
27112715

27122716
if (num_weights < 1) {
2713-
ret = TSK_ERR_BAD_STATE_DIMS;
2717+
ret = TSK_ERR_INSUFFICIENT_WEIGHTS;
27142718
goto out;
27152719
}
27162720

@@ -2823,7 +2827,7 @@ tsk_treeseq_trait_linear_model(const tsk_treeseq_t *self, tsk_size_t num_weights
28232827
}
28242828

28252829
if (num_weights < 1) {
2826-
ret = TSK_ERR_BAD_STATE_DIMS;
2830+
ret = TSK_ERR_INSUFFICIENT_WEIGHTS;
28272831
goto out;
28282832
}
28292833

@@ -3071,6 +3075,10 @@ tsk_treeseq_genetic_relatedness_weighted(const tsk_treeseq_t *self,
30713075
ret = TSK_ERR_NO_MEMORY;
30723076
goto out;
30733077
}
3078+
if (num_weights == 0) {
3079+
ret = TSK_ERR_INSUFFICIENT_WEIGHTS;
3080+
goto out;
3081+
}
30743082

30753083
// Add a column of ones to W
30763084
for (j = 0; j < num_samples; j++) {

python/tests/test_lowlevel.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2153,8 +2153,12 @@ def test_bad_weights(self):
21532153
del params["weights"]
21542154
n = ts.get_num_samples()
21552155

2156+
for bad_weight_type in [None, [None, None]]:
2157+
with pytest.raises(ValueError, match="object of too small depth"):
2158+
f(weights=bad_weight_type, **params)
2159+
21562160
for bad_weight_shape in [(n - 1, 1), (n + 1, 1), (0, 3)]:
2157-
with pytest.raises(ValueError):
2161+
with pytest.raises(ValueError, match="First dimension must be num_samples"):
21582162
f(weights=np.ones(bad_weight_shape), **params)
21592163

21602164
def test_output_dims(self):

0 commit comments

Comments
 (0)