Skip to content

Commit b3f2716

Browse files
committed
Added a skip_aggregate_stats parameter to Dataset.delete_samples() in the Python API
This uses the tiledb_vcf_writer_set_skip_aggregate_stats hook in the C API to skip updating allele count and variant stats when deleting samples. Python tests were added to cover this new parameter.
1 parent dee49a7 commit b3f2716

5 files changed

Lines changed: 61 additions & 0 deletions

File tree

apis/python/src/tiledbvcf/binding/libtiledbvcf.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ PYBIND11_MODULE(libtiledbvcf, m) {
131131
"ingest_samples",
132132
&Writer::ingest_samples,
133133
py::call_guard<py::gil_scoped_release>())
134+
.def("set_skip_aggregate_stats", &Writer::set_skip_aggregate_stats)
134135
.def(
135136
"delete_samples",
136137
&Writer::delete_samples,

apis/python/src/tiledbvcf/binding/writer.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,11 @@ void Writer::ingest_samples() {
232232
check_error(writer, tiledb_vcf_writer_store(writer));
233233
}
234234

235+
void Writer::set_skip_aggregate_stats(bool skip) {
236+
auto writer = ptr.get();
237+
check_error(writer, tiledb_vcf_writer_set_skip_aggregate_stats(writer, skip));
238+
}
239+
235240
void Writer::delete_samples(std::vector<std::string> samples_to_delete) {
236241
std::vector<const char*> samples;
237242
for (std::string& sample : samples_to_delete) {

apis/python/src/tiledbvcf/binding/writer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ class Writer {
162162

163163
void ingest_samples();
164164

165+
void set_skip_aggregate_stats(bool skip);
166+
165167
void delete_samples(std::vector<std::string> samples);
166168

167169
/** Returns schema version number of the TileDB VCF dataset */

apis/python/src/tiledbvcf/dataset.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,9 +1111,23 @@ def ingest_samples(
11111111
def delete_samples(
11121112
self,
11131113
sample_uris: List[str] = None,
1114+
skip_aggregate_stats: bool = False,
11141115
):
1116+
"""
1117+
Delete samples from the dataset.
1118+
1119+
Parameters
1120+
----------
1121+
sample_uris
1122+
List of sample names to delete.
1123+
skip_aggregate_stats
1124+
If True, skip updating allele_count and variant_stats arrays
1125+
during deletion.
1126+
"""
11151127
if self.mode != "w":
11161128
raise Exception("Dataset not open in write mode")
1129+
if skip_aggregate_stats:
1130+
self.writer.set_skip_aggregate_stats(True)
11171131
self.writer.delete_samples(sample_uris)
11181132

11191133
def tiledb_stats(self) -> str:

apis/python/tests/test_delete.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,45 @@ def test_delete_samples_nonexistent_raises(tmp_path):
8989
ds.delete_samples(["NONEXISTENT"])
9090

9191

92+
@skip_if_no_bcftools
93+
def test_delete_samples_skip_aggregate_stats(tmp_path, stats_v3_dataset):
94+
"""Verify skip_aggregate_stats skips stats update and records metadata."""
95+
uri = os.path.join(tmp_path, "stats_test")
96+
ds = tiledbvcf.Dataset(uri=uri, mode="w")
97+
ds.delete_samples(["second"], skip_aggregate_stats=True)
98+
99+
# Verify sample is deleted
100+
ds = tiledbvcf.Dataset(uri=uri, mode="r")
101+
sample_names = ds.samples()
102+
assert "second" not in sample_names
103+
assert "third" in sample_names
104+
105+
# Verify skipped_delete_samples metadata on allele_count and variant_stats
106+
for array_name in ["allele_count", "variant_stats"]:
107+
with tiledb.open(os.path.join(uri, array_name), "r") as arr:
108+
meta = arr.meta["skipped_delete_samples"]
109+
assert b"second" in meta
110+
111+
112+
@skip_if_no_bcftools
113+
def test_delete_samples_skip_aggregate_stats_accumulates(
114+
tmp_path, stats_v3_dataset
115+
):
116+
"""Verify skipped_delete_samples metadata accumulates across deletions."""
117+
uri = os.path.join(tmp_path, "stats_test")
118+
119+
ds = tiledbvcf.Dataset(uri=uri, mode="w")
120+
ds.delete_samples(["second"], skip_aggregate_stats=True)
121+
122+
ds = tiledbvcf.Dataset(uri=uri, mode="w")
123+
ds.delete_samples(["fifth"], skip_aggregate_stats=True)
124+
125+
for array_name in ["allele_count", "variant_stats"]:
126+
with tiledb.open(os.path.join(uri, array_name), "r") as arr:
127+
meta = arr.meta["skipped_delete_samples"]
128+
assert meta == b"second,fifth"
129+
130+
92131
def test_delete_samples_read_mode_raises(tmp_path):
93132
"""Verify delete_samples() raises in read mode."""
94133
uri = os.path.join(tmp_path, "dataset")

0 commit comments

Comments
 (0)