streampile 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,171 @@
1
+ .DS_Store
2
+
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ share/python-wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+ MANIFEST
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+ cover/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # pyenv
88
+ # For a library or package, you might want to ignore these files since the code is
89
+ # intended to run in multiple environments; otherwise, check them in:
90
+ .python-version
91
+
92
+ # pipenv
93
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
95
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
96
+ # install all needed dependencies.
97
+ #Pipfile.lock
98
+
99
+ # poetry
100
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
101
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
102
+ # commonly ignored for libraries.
103
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
104
+ #poetry.lock
105
+
106
+ # pdm
107
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
108
+ #pdm.lock
109
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
110
+ # in version control.
111
+ # https://pdm.fming.dev/#use-with-ide
112
+ .pdm.toml
113
+
114
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
115
+ __pypackages__/
116
+
117
+ # Celery stuff
118
+ celerybeat-schedule
119
+ celerybeat.pid
120
+
121
+ # SageMath parsed files
122
+ *.sage.py
123
+
124
+ # Environments
125
+ .env
126
+ .venv
127
+ env/
128
+ venv/
129
+ ENV/
130
+ env.bak/
131
+ venv.bak/
132
+
133
+ # Spyder project settings
134
+ .spyderproject
135
+ .spyproject
136
+
137
+ # Rope project settings
138
+ .ropeproject
139
+
140
+ # mkdocs documentation
141
+ /site
142
+
143
+ # mypy
144
+ .mypy_cache/
145
+ .dmypy.json
146
+ dmypy.json
147
+
148
+ # Pyre type checker
149
+ .pyre/
150
+
151
+ # pytype static type analyzer
152
+ .pytype/
153
+
154
+ # Cython debug symbols
155
+ cython_debug/
156
+
157
+ # PyCharm
158
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
159
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
160
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
161
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
162
+ .idea/
163
+
164
+ # VS Code
165
+ .vscode/
166
+
167
+ # Jupyter notebook files
168
+ *.ipynb
169
+
170
+ # Benchmark scratch files
171
+ benchmarks/out/
@@ -0,0 +1,66 @@
1
+ # Developer Documentation
2
+
3
+ ## Local Setup
4
+
5
+ Install [uv](https://docs.astral.sh/uv/), then install the library and its development tools with:
6
+
7
+ ```console
8
+ uv sync --locked
9
+ ```
10
+
11
+ ## Local Testing
12
+
13
+ To ensure all tests pass, run:
14
+
15
+ ```console
16
+ uv run poe check-tests
17
+ ```
18
+
19
+ The tests run the examples in the README too, so keep them working.
20
+
21
+ ## Local Linting and Formatting
22
+
23
+ To check the lockfile, project metadata, format, lint, and types of all the code, and run every test, run:
24
+
25
+ ```console
26
+ uv run poe check-all
27
+ ```
28
+
29
+ To fix what can be fixed automatically, run:
30
+
31
+ ```console
32
+ uv run poe fix-all
33
+ ```
34
+
35
+ ## Benchmarks
36
+
37
+ See [`benchmarks/README.md`](benchmarks/README.md) for how to run them and recent results.
38
+
39
+ ## Locking
40
+
41
+ `[tool.uv]` in `pyproject.toml` ignores releases younger than a week, and `uv.lock` records that setting.
42
+ Lock with the uv version pinned as `UV_VERSION` in [`tests.yml`](.github/workflows/tests.yml), and keep any user-level uv configuration out of the lock, or CI will find the lockfile stale:
43
+
44
+ ```console
45
+ XDG_CONFIG_HOME="$(mktemp -d)" uvx uv@0.12.20 lock
46
+ ```
47
+
48
+ ## Commits
49
+
50
+ Commit titles follow [Conventional Commits](https://www.conventionalcommits.org), which group the release notes that [git-cliff](https://git-cliff.org) generates from `pyproject.toml`.
51
+
52
+ ## Releasing
53
+
54
+ Releases are published to PyPI by the [`publish_streampile.yml`](.github/workflows/publish_streampile.yml) workflow with PyPI Trusted Publishing, so no API token is stored in GitHub.
55
+
56
+ To release:
57
+
58
+ 1. Merge a pull request titled `chore(release): bump to X.Y.Z` that sets the version in `pyproject.toml`.
59
+ 2. Tag the merge commit on `main` and push the tag:
60
+
61
+ ```console
62
+ git tag X.Y.Z
63
+ git push origin X.Y.Z
64
+ ```
65
+
66
+ 3. The workflow checks that the tag is on `main` and matches the version, runs the tests, builds the sdist and wheel, checks that each installs and imports on every supported Python, publishes to PyPI, and creates a GitHub release with notes generated by git-cliff.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright © 2026 Clint Valentine
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,12 @@
1
+ streampile
2
+ Copyright © 2026 Clint Valentine
3
+
4
+ The forward-only, coordinate-advancing design of StreamingPileupBuilder follows
5
+ StreamingPileupBuilder in fgbio (https://github.com/fulcrumgenomics/fgbio), which
6
+ is distributed under the MIT License:
7
+
8
+ Copyright (c) 2015-2026 Fulcrum Genomics LLC
9
+
10
+ Pileup entries follow the conventions of htslib (https://github.com/samtools/htslib)
11
+ and pysam (https://github.com/pysam-developers/pysam), both distributed under the
12
+ MIT License.
@@ -0,0 +1,184 @@
1
+ Metadata-Version: 2.5
2
+ Name: streampile
3
+ Version: 0.1.0
4
+ Summary: Forward-only pileups streamed from coordinate-sorted SAM, BAM, and CRAM records.
5
+ Project-URL: homepage, https://github.com/clintval/streampile
6
+ Project-URL: repository, https://github.com/clintval/streampile
7
+ Project-URL: Bug Tracker, https://github.com/clintval/streampile/issues
8
+ Author-email: Clint Valentine <valentine.clint@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ License-File: NOTICE
12
+ Keywords: BAM,HTS,NGS,SAM,bioinformatics,genomics,pileup
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Natural Language :: English
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.11
27
+ Requires-Dist: bedspec>=4.0.0
28
+ Requires-Dist: pybgzf>=0.1.2
29
+ Requires-Dist: pysam>=0.23
30
+ Requires-Dist: typeline>=2.4.0
31
+ Requires-Dist: typing-extensions>=4.12
32
+ Description-Content-Type: text/markdown
33
+
34
+ # streampile
35
+
36
+ [![Build Status](https://github.com/clintval/streampile/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/clintval/streampile/actions/workflows/tests.yml?query=branch%3Amain)
37
+ [![Python Versions](https://img.shields.io/badge/python-3.11_|_3.12_|_3.13_|_3.14-blue)](https://github.com/clintval/streampile)
38
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/clintval/streampile/blob/main/LICENSE)
39
+ [![basedpyright](https://img.shields.io/badge/basedpyright-checked-42b983)](https://docs.basedpyright.com/latest/)
40
+ [![mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
41
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://docs.astral.sh/uv/)
42
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://docs.astral.sh/ruff/)
43
+
44
+ Forward-only pileups streamed from coordinate-sorted BAM and CRAM records, and a table of the alleles at every base.
45
+
46
+ ## Installation
47
+
48
+ ```console
49
+ pip install streampile
50
+ ```
51
+
52
+ ## Quickstart
53
+
54
+ ### Building Pileups
55
+
56
+ A `StreamingPileupBuilder` reads records once and piles them up at the 0-based positions you ask for, moving forward only.
57
+
58
+ ```pycon
59
+ >>> from pysam import AlignmentFile
60
+ >>> from streampile import StreamingPileupBuilder
61
+ >>>
62
+ >>> with (
63
+ ... AlignmentFile("tests/data/reads.bam") as reads,
64
+ ... StreamingPileupBuilder(reads, min_base_quality=30) as builder,
65
+ ... ):
66
+ ... first = builder.pileup("chr1", 10)
67
+ ... second = builder.pileup("chr1", 12)
68
+ >>>
69
+ >>> first.filtered_depth, first.bases
70
+ (4, ['A', 'T', 'G', 'A'])
71
+ >>> second.filtered_depth, second.bases
72
+ (3, ['G', 'G', 'G'])
73
+
74
+ ```
75
+
76
+ Filter reads with `read_filter`, and count each template once with `without_overlaps()`:
77
+
78
+ ```pycon
79
+ >>> with (
80
+ ... AlignmentFile("tests/data/reads.bam") as reads,
81
+ ... StreamingPileupBuilder(reads, read_filter=lambda read: read.is_paired) as builder,
82
+ ... ):
83
+ ... pileup = builder.pileup("chr1", 50)
84
+ >>>
85
+ >>> pileup.bases, pileup.without_overlaps().bases
86
+ (['T', 'T'], ['T'])
87
+
88
+ ```
89
+
90
+ Pass `tap=writer.write` to receive every record, in input order, once the builder has moved past it.
91
+
92
+ ### Sweeping a Territory
93
+
94
+ `columns` yields the pileup at every position of a span.
95
+
96
+ ```pycon
97
+ >>> with AlignmentFile("tests/data/reads.bam") as reads, StreamingPileupBuilder(reads) as builder:
98
+ ... sum(pileup.unfiltered_depth for pileup in builder.columns("chr1", 0, 20))
99
+ 73
100
+
101
+ ```
102
+
103
+ ### Tabulating Alleles
104
+
105
+ `tabulate` counts the reads of every allele at every base of a [bedspec](https://github.com/clintval/bedspec) `Territory`.
106
+ Alleles are normalized VCF alleles at 1-based positions, so they match a VCF by `CHROM`, `POS`, `REF`, and `ALT`.
107
+
108
+ ```pycon
109
+ >>> from bedspec import Bed3
110
+ >>> from bedspec import Territory
111
+ >>> from pysam import FastaFile
112
+ >>> from streampile import tabulate
113
+ >>>
114
+ >>> territory = Territory([Bed3("chr1", start=9, end=12)])
115
+ >>> with (
116
+ ... AlignmentFile("tests/data/reads.bam") as reads,
117
+ ... FastaFile("tests/data/reference.fa") as reference,
118
+ ... ):
119
+ ... bases = list(tabulate(reads, reference, territory, min_base_quality=30))
120
+ >>>
121
+ >>> for base in bases:
122
+ ... print(base.pos, base.ref, base.depth, base.alts, base.alt_reads)
123
+ 10 A 4 () ()
124
+ 11 A 4 ('T', 'GG') (1, 1)
125
+ 12 C 4 () ()
126
+
127
+ ```
128
+
129
+ Each base also splits its reads by strand and counts no-calls apart from its depth.
130
+
131
+ ### Reading a Table
132
+
133
+ ```pycon
134
+ >>> from streampile import TabulationReader
135
+ >>>
136
+ >>> for base in TabulationReader.from_path("tests/data/counts.tsv"):
137
+ ... print(base.pos, base.depth, base.alts, base.alt_reads)
138
+ 21 5 () ()
139
+ 22 5 () ()
140
+ 23 4 ('C',) (1,)
141
+ 24 4 () ()
142
+
143
+ ```
144
+
145
+ ## Command Line
146
+
147
+ ```console
148
+ streampile tabulate \
149
+ --bam tests/data/reads.bam \
150
+ --ref tests/data/reference.fa \
151
+ --intervals tests/data/territory.bed \
152
+ --min-base-quality 30 \
153
+ --min-mapping-quality 20 \
154
+ --out counts.tsv
155
+ ```
156
+
157
+ ```text
158
+ ##streampile-tabulation=1
159
+ ##streampile-version=0.1.0
160
+ ##bam=tests/data/reads.bam
161
+ ##reference=tests/data/reference.fa
162
+ ##territory=tests/data/territory.bed
163
+ ##min_base_quality=30
164
+ ##min_mapping_quality=20
165
+ ##exclude_flags=0xf00
166
+ #contig pos ref depth no_calls ref_reads ref_fwd ref_rev alt_refs alts alt_reads alt_fwd alt_rev
167
+ chr1 21 T 5 0 5 3 2
168
+ chr1 22 G 5 0 5 3 2
169
+ chr1 23 C 4 0 3 2 1 CA C 1 0 1
170
+ chr1 24 A 4 0 3 2 1
171
+ ```
172
+
173
+ Write to a `.gz` path with `--index tbi` to compress and index the table, then read a region back:
174
+
175
+ ```python
176
+ for base in TabulationReader.query("counts.tsv.gz", "chr1", 20, 24):
177
+ print(base.pos, base.depth, base.alts)
178
+ ```
179
+
180
+ ## Development and Testing
181
+
182
+ See the [contributing guide](https://github.com/clintval/streampile/blob/main/CONTRIBUTING.md) for more information.
183
+
184
+ The streaming design follows the `StreamingPileupBuilder` of [fgbio](https://github.com/fulcrumgenomics/fgbio); see [NOTICE](https://github.com/clintval/streampile/blob/main/NOTICE).
@@ -0,0 +1,151 @@
1
+ # streampile
2
+
3
+ [![Build Status](https://github.com/clintval/streampile/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/clintval/streampile/actions/workflows/tests.yml?query=branch%3Amain)
4
+ [![Python Versions](https://img.shields.io/badge/python-3.11_|_3.12_|_3.13_|_3.14-blue)](https://github.com/clintval/streampile)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/clintval/streampile/blob/main/LICENSE)
6
+ [![basedpyright](https://img.shields.io/badge/basedpyright-checked-42b983)](https://docs.basedpyright.com/latest/)
7
+ [![mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
8
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://docs.astral.sh/uv/)
9
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://docs.astral.sh/ruff/)
10
+
11
+ Forward-only pileups streamed from coordinate-sorted BAM and CRAM records, and a table of the alleles at every base.
12
+
13
+ ## Installation
14
+
15
+ ```console
16
+ pip install streampile
17
+ ```
18
+
19
+ ## Quickstart
20
+
21
+ ### Building Pileups
22
+
23
+ A `StreamingPileupBuilder` reads records once and piles them up at the 0-based positions you ask for, moving forward only.
24
+
25
+ ```pycon
26
+ >>> from pysam import AlignmentFile
27
+ >>> from streampile import StreamingPileupBuilder
28
+ >>>
29
+ >>> with (
30
+ ... AlignmentFile("tests/data/reads.bam") as reads,
31
+ ... StreamingPileupBuilder(reads, min_base_quality=30) as builder,
32
+ ... ):
33
+ ... first = builder.pileup("chr1", 10)
34
+ ... second = builder.pileup("chr1", 12)
35
+ >>>
36
+ >>> first.filtered_depth, first.bases
37
+ (4, ['A', 'T', 'G', 'A'])
38
+ >>> second.filtered_depth, second.bases
39
+ (3, ['G', 'G', 'G'])
40
+
41
+ ```
42
+
43
+ Filter reads with `read_filter`, and count each template once with `without_overlaps()`:
44
+
45
+ ```pycon
46
+ >>> with (
47
+ ... AlignmentFile("tests/data/reads.bam") as reads,
48
+ ... StreamingPileupBuilder(reads, read_filter=lambda read: read.is_paired) as builder,
49
+ ... ):
50
+ ... pileup = builder.pileup("chr1", 50)
51
+ >>>
52
+ >>> pileup.bases, pileup.without_overlaps().bases
53
+ (['T', 'T'], ['T'])
54
+
55
+ ```
56
+
57
+ Pass `tap=writer.write` to receive every record, in input order, once the builder has moved past it.
58
+
59
+ ### Sweeping a Territory
60
+
61
+ `columns` yields the pileup at every position of a span.
62
+
63
+ ```pycon
64
+ >>> with AlignmentFile("tests/data/reads.bam") as reads, StreamingPileupBuilder(reads) as builder:
65
+ ... sum(pileup.unfiltered_depth for pileup in builder.columns("chr1", 0, 20))
66
+ 73
67
+
68
+ ```
69
+
70
+ ### Tabulating Alleles
71
+
72
+ `tabulate` counts the reads of every allele at every base of a [bedspec](https://github.com/clintval/bedspec) `Territory`.
73
+ Alleles are normalized VCF alleles at 1-based positions, so they match a VCF by `CHROM`, `POS`, `REF`, and `ALT`.
74
+
75
+ ```pycon
76
+ >>> from bedspec import Bed3
77
+ >>> from bedspec import Territory
78
+ >>> from pysam import FastaFile
79
+ >>> from streampile import tabulate
80
+ >>>
81
+ >>> territory = Territory([Bed3("chr1", start=9, end=12)])
82
+ >>> with (
83
+ ... AlignmentFile("tests/data/reads.bam") as reads,
84
+ ... FastaFile("tests/data/reference.fa") as reference,
85
+ ... ):
86
+ ... bases = list(tabulate(reads, reference, territory, min_base_quality=30))
87
+ >>>
88
+ >>> for base in bases:
89
+ ... print(base.pos, base.ref, base.depth, base.alts, base.alt_reads)
90
+ 10 A 4 () ()
91
+ 11 A 4 ('T', 'GG') (1, 1)
92
+ 12 C 4 () ()
93
+
94
+ ```
95
+
96
+ Each base also splits its reads by strand and counts no-calls apart from its depth.
97
+
98
+ ### Reading a Table
99
+
100
+ ```pycon
101
+ >>> from streampile import TabulationReader
102
+ >>>
103
+ >>> for base in TabulationReader.from_path("tests/data/counts.tsv"):
104
+ ... print(base.pos, base.depth, base.alts, base.alt_reads)
105
+ 21 5 () ()
106
+ 22 5 () ()
107
+ 23 4 ('C',) (1,)
108
+ 24 4 () ()
109
+
110
+ ```
111
+
112
+ ## Command Line
113
+
114
+ ```console
115
+ streampile tabulate \
116
+ --bam tests/data/reads.bam \
117
+ --ref tests/data/reference.fa \
118
+ --intervals tests/data/territory.bed \
119
+ --min-base-quality 30 \
120
+ --min-mapping-quality 20 \
121
+ --out counts.tsv
122
+ ```
123
+
124
+ ```text
125
+ ##streampile-tabulation=1
126
+ ##streampile-version=0.1.0
127
+ ##bam=tests/data/reads.bam
128
+ ##reference=tests/data/reference.fa
129
+ ##territory=tests/data/territory.bed
130
+ ##min_base_quality=30
131
+ ##min_mapping_quality=20
132
+ ##exclude_flags=0xf00
133
+ #contig pos ref depth no_calls ref_reads ref_fwd ref_rev alt_refs alts alt_reads alt_fwd alt_rev
134
+ chr1 21 T 5 0 5 3 2
135
+ chr1 22 G 5 0 5 3 2
136
+ chr1 23 C 4 0 3 2 1 CA C 1 0 1
137
+ chr1 24 A 4 0 3 2 1
138
+ ```
139
+
140
+ Write to a `.gz` path with `--index tbi` to compress and index the table, then read a region back:
141
+
142
+ ```python
143
+ for base in TabulationReader.query("counts.tsv.gz", "chr1", 20, 24):
144
+ print(base.pos, base.depth, base.alts)
145
+ ```
146
+
147
+ ## Development and Testing
148
+
149
+ See the [contributing guide](https://github.com/clintval/streampile/blob/main/CONTRIBUTING.md) for more information.
150
+
151
+ The streaming design follows the `StreamingPileupBuilder` of [fgbio](https://github.com/fulcrumgenomics/fgbio); see [NOTICE](https://github.com/clintval/streampile/blob/main/NOTICE).