Skip to content

Two locus general matrix#3426

Open
lkirk wants to merge 17 commits intotskit-dev:mainfrom
lkirk:two-locus-general-matrix
Open

Two locus general matrix#3426
lkirk wants to merge 17 commits intotskit-dev:mainfrom
lkirk:two-locus-general-matrix

Conversation

@lkirk
Copy link
Contributor

@lkirk lkirk commented Mar 10, 2026

Description

This is the last of the required components for the LD matrix methods. I wanted feedback on the API before I add documentation, but this method is complete and tested. The final things to do are to leak check the cpython code and add some documentation.

This feature enables a user to implement their own two-locus count statistic in python, similar to ts.sample_count_stat. User functions take two arguments, the first is a matrix of haplotype counts and the second is a vector of sample set sizes. For instance, this is how we would implement D with this api:

def D(X, n):
    pAB, pAb, paB = X / n
    pA = pAb + pAB
    pB = paB + pAB
    return pAB - (pA * pB)

Since this API supports multiallelic sites, the user can also pass a normalisation function to control how the data is normalised across multiple alleles. The normalisation function is only run when computing over multiallelic sites. I've set the default to be $1/(n_A n_B)$, which is simply the arithmetic mean of the alleles in a given pair of sites. This will suffice in the majority of cases (the only outlier is $r^2$, for which there is already a python API). We also support computing statistics between sample sets.

The user would use the above summary function like this:

ts.two_locus_count_stat(ts.samples(), D, 1)

Where 1 specifies the length of the output array, we always require 1 dimension -- same as the ts.sample_count_stat function.

PR Checklist:

  • Tests that fully cover new/changed functionality.
  • Documentation including tutorial content if appropriate.
  • Changelogs, if there are API changes.

@codecov
Copy link

codecov bot commented Mar 10, 2026

Codecov Report

❌ Patch coverage is 72.38095% with 58 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.79%. Comparing base (1835ea3) to head (e5a105f).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3426      +/-   ##
==========================================
- Coverage   91.92%   91.79%   -0.13%     
==========================================
  Files          37       37              
  Lines       32153    32352     +199     
  Branches     5143     5144       +1     
==========================================
+ Hits        29556    29699     +143     
- Misses       2264     2320      +56     
  Partials      333      333              
Flag Coverage Δ
C 82.71% <100.00%> (+<0.01%) ⬆️
c-python 77.29% <68.04%> (-0.06%) ⬇️
python-tests 96.40% <100.00%> (+<0.01%) ⬆️
python-tests-no-jit 33.20% <18.75%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Python API 98.70% <100.00%> (+<0.01%) ⬆️
Python C interface 90.65% <68.81%> (-0.59%) ⬇️
C library 88.87% <100.00%> (+0.01%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

PyObject *summary_func;
PyObject *norm_func;
} two_locus_general_stat_params;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that the CPython code coverage is split from the rest of the python tests. I can't test this directly without a small multiallelic test case in test_python_c.py.

out:
return ret;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function now serves as an inner wrapper. The the general stat accepts the summary function params so that the CPython code can pass them directly. All of the specialized stats functions call this function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant