Skill Tracer
Skills › Scientific Agent Skills › gtars › python-api.md

python-api.md

288 lines · skills/gtars/references/python-api.md at 5f2bc03

Open on GitHub
1# Python API (`gtars==0.10.0`)
2
3Research and runtime verification date: **2026-10-01**. The PyPI package requires
4Python 3.10+ and contains a native PyO3 extension.
5

Python API (gtars==0.10.0)

Research and runtime verification date: 2026-10-01. The PyPI package requires Python 3.10+ and contains a native PyO3 extension.

Raw lines 1 to 5
6## Import surface
7
8Public functionality is grouped into submodules:
9
10```python
11import gtars
12from gtars.models import Region, RegionSet
13from gtars.genomic_distributions import consensus
14from gtars.tokenizers import Tokenizer, tokenize_fragment_file
15from gtars.refget import RefgetStore, digest_fasta, digest_sequence
16```
18`gtars.__version__` is `0.10.0`. `Region`, `RegionSet`, `Tokenizer`, and
19`RefgetStore` are not documented as top-level classes. Python 0.10.0 does not
20export Python `uniwig`, `igd`, `scoring`, `fragsplit`, or `bbcache` submodules.

Import surface

Public functionality is grouped into submodules:

import gtars
from gtars.models import Region, RegionSet
from gtars.genomic_distributions import consensus
from gtars.tokenizers import Tokenizer, tokenize_fragment_file
from gtars.refget import RefgetStore, digest_fasta, digest_sequence

gtars.__version__ is 0.10.0. Region, RegionSet, Tokenizer, and RefgetStore are not documented as top-level classes. Python 0.10.0 does not export Python uniwig, igd, scoring, fragsplit, or bbcache submodules.

Raw lines 6 to 21
22## Verified signatures
24The installed 0.10.0 wheel reported:
26```text
27Region(chr, start, end, rest)
28RegionSet(path)
29RegionSet.from_regions(regions, strands=None)
30RegionSet.from_vectors(chrs, starts, ends, strands=None)
31RegionSet.count_overlaps(self, other)
32RegionSet.coverage(self, other)
33Tokenizer(path)
34Tokenizer.from_bed(path)
35Tokenizer.from_pretrained(path)
36tokenize_fragment_file(file, tokenizer)
37consensus(region_sets)
38RefgetStore.open_local(path)
39RefgetStore.open_remote(cache_path, remote_url)
40RefgetStore.get_substring(self, seq_digest, start, end)
41```
43The shipped `.pyi` stubs omit some runtime methods (`from_vectors`, `disjoin`,
44`strands`, and several refget load methods). The tagged PyO3 source and the
45installed runtime are authoritative for those omissions.

Verified signatures

The installed 0.10.0 wheel reported:

Region(chr, start, end, rest)
RegionSet(path)
RegionSet.from_regions(regions, strands=None)
RegionSet.from_vectors(chrs, starts, ends, strands=None)
RegionSet.count_overlaps(self, other)
RegionSet.coverage(self, other)
Tokenizer(path)
Tokenizer.from_bed(path)
Tokenizer.from_pretrained(path)
tokenize_fragment_file(file, tokenizer)
consensus(region_sets)
RefgetStore.open_local(path)
RefgetStore.open_remote(cache_path, remote_url)
RefgetStore.get_substring(self, seq_digest, start, end)

The shipped .pyi stubs omit some runtime methods (from_vectors, disjoin, strands, and several refget load methods). The tagged PyO3 source and the installed runtime are authoritative for those omissions.

Raw lines 22 to 46
47## `Region`
49```python
50from gtars.models import Region
52region = Region(
53 chr="chr1",
54 start=100,
55 end=200,
56 rest="peak_001\t500\t+",
58assert len(region) == 100
59assert (region.chr, region.start, region.end) == ("chr1", 100, 200)
60```
62`start` and `end` are Rust `u32`. Validate `0 <= start < end <= contig_length`
63before construction. The constructor does not itself prove assembly or contig
64compatibility. Equality compares only chromosome/start/end; trailing `rest`
65content is not part of equality.

Region

from gtars.models import Region

region = Region(
    chr="chr1",
    start=100,
    end=200,
    rest="peak_001\t500\t+",
)
assert len(region) == 100
assert (region.chr, region.start, region.end) == ("chr1", 100, 200)

start and end are Rust u32. Validate 0 <= start < end <= contig_length before construction. The constructor does not itself prove assembly or contig compatibility. Equality compares only chromosome/start/end; trailing rest content is not part of equality.

Raw lines 47 to 66
67## `RegionSet` constructors

RegionSet constructors

Raw lines 67 to 68
69### Local file
71```python
72from pathlib import Path
73from gtars.models import RegionSet
75path = Path("reviewed-input.bed.gz")
76if not path.is_file() or path.is_symlink():
77 raise ValueError("expected a reviewed local regular file")
78regions = RegionSet(str(path))
79```
81The Python build enables `gtars-core`'s HTTP feature. If the supplied string is
82not an existing local file, core code attempts to open it as a URL. Therefore,
83checking `is_file()` before construction is a security boundary, not just an
84error-message improvement.
86File parsing:
88- accepts tab-separated BED-like input and `.gz`;
89- skips `browser`, `track`, and `#` lines;
90- treats a first row with a nonnumeric second field as a column header;
91- requires at least three columns;
92- stores columns 4+ as one tab-joined `Region.rest` string;
93- rejects an empty region set;
94- sorts in memory by lexicographic chromosome then numeric start.
96The original file is not rewritten, but input row order is not preserved in the
97object.

Local file

from pathlib import Path
from gtars.models import RegionSet

path = Path("reviewed-input.bed.gz")
if not path.is_file() or path.is_symlink():
    raise ValueError("expected a reviewed local regular file")
regions = RegionSet(str(path))

The Python build enables gtars-core's HTTP feature. If the supplied string is not an existing local file, core code attempts to open it as a URL. Therefore, checking is_file() before construction is a security boundary, not just an error-message improvement.

File parsing:

  • accepts tab-separated BED-like input and .gz;
  • skips browser, track, and # lines;
  • treats a first row with a nonnumeric second field as a column header;
  • requires at least three columns;
  • stores columns 4+ as one tab-joined Region.rest string;
  • rejects an empty region set;
  • sorts in memory by lexicographic chromosome then numeric start.

The original file is not rewritten, but input row order is not preserved in the object.

Raw lines 69 to 98
99### In-memory regions
101```python
102from gtars.models import Region, RegionSet
104regions = RegionSet.from_regions(
105 [
106 Region("chr1", 100, 200, None),
107 Region("chr2", 300, 450, None),
108 ],
109 strands=["+", "-"],
112same = RegionSet.from_vectors(
113 ["chr1", "chr2"],
114 [100, 300],
115 [200, 450],
116 strands=["+", "-"],
118```
120All coordinate vectors, and the optional strand vector, must have equal length.
121When strands are omitted, the separate strand vector contains `"*"`.

In-memory regions

from gtars.models import Region, RegionSet

regions = RegionSet.from_regions(
    [
        Region("chr1", 100, 200, None),
        Region("chr2", 300, 450, None),
    ],
    strands=["+", "-"],
)

same = RegionSet.from_vectors(
    ["chr1", "chr2"],
    [100, 300],
    [200, 450],
    strands=["+", "-"],
)

All coordinate vectors, and the optional strand vector, must have equal length. When strands are omitted, the separate strand vector contains "*".

Raw lines 99 to 122
123## Properties and mutability
125```python
126n = len(regions)
127first = regions[0] # negative indices are supported
128identifier = regions.identifier
129file_digest = regions.file_digest
130header = regions.header
131strands = regions.strands
133regions.sort() # in-place; returns None; see strand caveat below
134regions.to_bed("out.bed")
135regions.to_bed_gz("out.bed.gz")
136regions.to_bigbed("out.bb", "assembly.chrom.sizes")
137```
139- `identifier` is an MD5-like identifier over sorted first-three-column content.
140- `file_digest` includes retained trailing columns. Neither value substitutes for
141 an independently recorded SHA-256 provenance hash.
142- `path` raises `ValueError` for a set created from regions/vectors.
143- `sort()` reorders regions but does not reorder the separate `strands` vector
144 in 0.10.0. Sort `(region, strand)` pairs before construction, or maintain the
145 association externally; otherwise strand-dependent annotations can be silently
146 reassigned. File loading already sets this vector to `"*"`.
147- Writers overwrite/create the specified output; check output policy first.
148- `to_bigbed` needs chromosome sizes matching every contig and bound.

Properties and mutability

n = len(regions)
first = regions[0]       # negative indices are supported
identifier = regions.identifier
file_digest = regions.file_digest
header = regions.header
strands = regions.strands

regions.sort()           # in-place; returns None; see strand caveat below
regions.to_bed("out.bed")
regions.to_bed_gz("out.bed.gz")
regions.to_bigbed("out.bb", "assembly.chrom.sizes")
  • identifier is an MD5-like identifier over sorted first-three-column content.
  • file_digest includes retained trailing columns. Neither value substitutes for an independently recorded SHA-256 provenance hash.
  • path raises ValueError for a set created from regions/vectors.
  • sort() reorders regions but does not reorder the separate strands vector in 0.10.0. Sort (region, strand) pairs before construction, or maintain the association externally; otherwise strand-dependent annotations can be silently reassigned. File loading already sets this vector to "*".
  • Writers overwrite/create the specified output; check output policy first.
  • to_bigbed needs chromosome sizes matching every contig and bound.
Raw lines 123 to 149
150## Interval statistics and structural operations
152The following methods are current:
154```python
155widths = regions.widths() # list[int]
156same_widths = regions.region_widths() # alias
157mean_width = regions.mean_region_width() # runtime returns float
158length = regions.get_nucleotide_length()
159max_ends = regions.get_max_end_per_chr()
160stats = regions.chromosome_statistics()
162reduced = regions.reduce()
163disjoint = regions.disjoin()
164trimmed = regions.trim({"chr1": 248956422})
165gaps = regions.gaps({"chr1": 248956422})
166clusters = regions.cluster(max_gap=100)
167```
169`reduce()` merges overlapping **and adjacent** ranges. `trim()` drops unknown
170contigs and clamps bounds. These transformations do not perform liftover and can
171drop the separate strand vector.
173`promoters(upstream, downstream)` is relative to each region's start in the
174current implementation; it is not a safe substitute for a strand-aware TSS
175workflow. Establish strand and TSS semantics independently.
177`neighbor_distances()` and `nearest_neighbors()` can return fewer values than
178input regions because singletons on a chromosome are skipped; results are not
179row-aligned.
181`distribution(n_bins=250, chrom_sizes=None)` uses observed maximum ends when
182chromosome sizes are absent, making results non-comparable across files. Supply
183the exact assembly dictionary. Unknown/out-of-bounds regions are skipped when
184sizes are supplied, so summed counts may be lower than input count.

Interval statistics and structural operations

The following methods are current:

widths = regions.widths()                 # list[int]
same_widths = regions.region_widths()     # alias
mean_width = regions.mean_region_width()  # runtime returns float
length = regions.get_nucleotide_length()
max_ends = regions.get_max_end_per_chr()
stats = regions.chromosome_statistics()

reduced = regions.reduce()
disjoint = regions.disjoin()
trimmed = regions.trim({"chr1": 248956422})
gaps = regions.gaps({"chr1": 248956422})
clusters = regions.cluster(max_gap=100)

reduce() merges overlapping and adjacent ranges. trim() drops unknown contigs and clamps bounds. These transformations do not perform liftover and can drop the separate strand vector.

promoters(upstream, downstream) is relative to each region's start in the current implementation; it is not a safe substitute for a strand-aware TSS workflow. Establish strand and TSS semantics independently.

neighbor_distances() and nearest_neighbors() can return fewer values than input regions because singletons on a chromosome are skipped; results are not row-aligned.

distribution(n_bins=250, chrom_sizes=None) uses observed maximum ends when chromosome sizes are absent, making results non-comparable across files. Supply the exact assembly dictionary. Unknown/out-of-bounds regions are skipped when sizes are supplied, so summed counts may be lower than input count.

Raw lines 150 to 185
186## Pairwise and all-vs-all operations
188```python
189a = RegionSet("a.bed")
190b = RegionSet("b.bed")
192concatenated = a.concat(b) # no merge
193union = a.union(b) # minimal merged set
194difference = a.setdiff(b) # subtract b bases from a
195pairwise = a.pintersect(b) # pair by index, not genomic all-vs-all
196all_pieces = a.intersect_all(b) # every genomic overlap fragment
198jaccard = a.jaccard(b)
199coverage = a.coverage(b)
200coefficient = a.overlap_coefficient(b)
201closest = a.closest(b)
202```
204`coverage` is `covered base pairs in a / merged base pairs in a`, in `[0,1]`.
205Overlaps internal to either input are reduced for these set metrics.
206It is not signal coverage and does not produce WIG/bigWig. `pintersect` depends
207on index position after constructors may have sorted the inputs. It silently
208truncates to the shorter input and emits zero-width intervals for nonoverlapping
209or different-contig pairs. Require equal lengths and explicit row pairing first;
210filter or label misses before applying the strict nonempty-BED contract.
212Overlap query methods are directional:
214```python
215counts = a.count_overlaps(b) # one integer for each region in a
216flags = a.any_overlaps(b) # one bool for each region in a
217indices = a.find_overlaps(b) # indices into b for each region in a
218subset = a.subset_by_overlaps(b) # regions from a having at least one hit
219```

Pairwise and all-vs-all operations

a = RegionSet("a.bed")
b = RegionSet("b.bed")

concatenated = a.concat(b)          # no merge
union = a.union(b)                  # minimal merged set
difference = a.setdiff(b)           # subtract b bases from a
pairwise = a.pintersect(b)          # pair by index, not genomic all-vs-all
all_pieces = a.intersect_all(b)     # every genomic overlap fragment

jaccard = a.jaccard(b)
coverage = a.coverage(b)
coefficient = a.overlap_coefficient(b)
closest = a.closest(b)

coverage is covered base pairs in a / merged base pairs in a, in [0,1]. Overlaps internal to either input are reduced for these set metrics. It is not signal coverage and does not produce WIG/bigWig. pintersect depends on index position after constructors may have sorted the inputs. It silently truncates to the shorter input and emits zero-width intervals for nonoverlapping or different-contig pairs. Require equal lengths and explicit row pairing first; filter or label misses before applying the strict nonempty-BED contract.

Overlap query methods are directional:

counts = a.count_overlaps(b)        # one integer for each region in a
flags = a.any_overlaps(b)           # one bool for each region in a
indices = a.find_overlaps(b)        # indices into b for each region in a
subset = a.subset_by_overlaps(b)    # regions from a having at least one hit
Raw lines 186 to 220
221## Consensus
223```python
224from gtars.genomic_distributions import consensus
226result = consensus([a, b])
227# [{"chr": "chr1", "start": 100, "end": 500, "count": 2}, ...]
228```
230The implementation concatenates all sets, reduces them into merged union
231intervals (including adjacency), then counts how many input sets have at least
232one overlap with each union interval. It does **not** segment a merged interval
233at every support-change boundary. Use this exact meaning when interpreting
234`count`.

Consensus

from gtars.genomic_distributions import consensus

result = consensus([a, b])
# [{"chr": "chr1", "start": 100, "end": 500, "count": 2}, ...]

The implementation concatenates all sets, reduces them into merged union intervals (including adjacency), then counts how many input sets have at least one overlap with each union interval. It does not segment a merged interval at every support-change boundary. Use this exact meaning when interpreting count.

Raw lines 221 to 235
236## Tokenizer and fragment boundary
238`Tokenizer.tokenize()` accepts a `RegionSet` or region objects accepted by the
239native extractor. Despite older prose examples, the verified wheel rejected a
240list of region strings. Use:
242```python
243from gtars.tokenizers import Tokenizer
245tokenizer = Tokenizer.from_bed("local-universe.bed")
246tokens = tokenizer.tokenize(a)
247ids = tokenizer(a)["input_ids"]
248```
250See `tokenizers.md` for special-token, universe-order, remote download, and
251fragment-file behavior.

Tokenizer and fragment boundary

Tokenizer.tokenize() accepts a RegionSet or region objects accepted by the native extractor. Despite older prose examples, the verified wheel rejected a list of region strings. Use:

from gtars.tokenizers import Tokenizer

tokenizer = Tokenizer.from_bed("local-universe.bed")
tokens = tokenizer.tokenize(a)
ids = tokenizer(a)["input_ids"]

See tokenizers.md for special-token, universe-order, remote download, and fragment-file behavior.

Raw lines 236 to 252
253## Error handling
255The package does not export the invented `gtars.FileNotFoundError`,
256`InvalidFormatError`, or `ParseError` classes from the old skill. Validate before
257the call, then catch only the narrow built-in/native errors relevant to the
258operation:
260```python
261try:
262 regions = RegionSet("reviewed-local.bed")
263except (OSError, RuntimeError, ValueError) as exc:
264 raise RuntimeError("Gtars could not load the validated BED") from exc
265```
267Do not use a broad catch to continue past corrupted rows.

Error handling

The package does not export the invented gtars.FileNotFoundError, InvalidFormatError, or ParseError classes from the old skill. Validate before the call, then catch only the narrow built-in/native errors relevant to the operation:

try:
    regions = RegionSet("reviewed-local.bed")
except (OSError, RuntimeError, ValueError) as exc:
    raise RuntimeError("Gtars could not load the validated BED") from exc

Do not use a broad catch to continue past corrupted rows.

Raw lines 253 to 268
269## APIs that are not present
271The 0.10.0 Python surface does not provide:
273- `gtars.RegionSet` or `RegionSet.from_bed`;
274- `total_coverage`, `filter_by_size`, `filter_by_chromosome`, `intersect`,
275 `subtract`, or `symmetric_difference` under the old names;
276- `to_json`, `from_json`, NumPy array getters, `from_arrays`;
277- `stream_bed`, `mmap=True`, `parallel=True`, or `parallel_apply`;
278- global `set_option`, `option_context`, or `set_log_level`;
279- a Python `uniwig` coverage object.

APIs that are not present

The 0.10.0 Python surface does not provide:

  • gtars.RegionSet or RegionSet.from_bed;
  • total_coverage, filter_by_size, filter_by_chromosome, intersect, subtract, or symmetric_difference under the old names;
  • to_json, from_json, NumPy array getters, from_arrays;
  • stream_bed, mmap=True, parallel=True, or parallel_apply;
  • global set_option, option_context, or set_log_level;
  • a Python uniwig coverage object.
Raw lines 269 to 280
281## Official sources (accessed 2026-10-01)
283- [PyPI gtars 0.10.0](https://pypi.org/project/gtars/)
284- [Python 0.10.0 model stubs](https://github.com/databio/gtars/blob/gtars-python-v0.10.0/gtars-python/py_src/gtars/models/__init__.pyi)
285- [Python 0.10.0 Region binding](https://github.com/databio/gtars/blob/gtars-python-v0.10.0/gtars-python/src/models/region.rs)
286- [Python 0.10.0 RegionSet binding](https://github.com/databio/gtars/blob/gtars-python-v0.10.0/gtars-python/src/models/region_set.rs)
287- [Python 0.10.0 genomic-distribution stubs](https://github.com/databio/gtars/blob/gtars-python-v0.10.0/gtars-python/py_src/gtars/genomic_distributions/__init__.pyi)
288- [Gtars model guide](https://docs.bedbase.org/gtars/regionSet/)