telometer 2.0.2__tar.gz → 2.0.3__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.
- {telometer-2.0.2 → telometer-2.0.3}/LICENSE.txt +3 -1
- telometer-2.0.3/PKG-INFO +155 -0
- telometer-2.0.3/README.md +108 -0
- {telometer-2.0.2 → telometer-2.0.3}/pyproject.toml +1 -1
- {telometer-2.0.2 → telometer-2.0.3}/telometer/__init__.py +1 -1
- {telometer-2.0.2 → telometer-2.0.3}/telometer/telometer.py +59 -4
- telometer-2.0.3/telometer.egg-info/PKG-INFO +155 -0
- {telometer-2.0.2 → telometer-2.0.3}/telometer.egg-info/SOURCES.txt +1 -0
- telometer-2.0.2/PKG-INFO +0 -48
- telometer-2.0.2/README.md +0 -3
- telometer-2.0.2/telometer.egg-info/PKG-INFO +0 -48
- {telometer-2.0.2 → telometer-2.0.3}/setup.cfg +0 -0
- {telometer-2.0.2 → telometer-2.0.3}/telometer/telometer_variant_support.py +0 -0
- {telometer-2.0.2 → telometer-2.0.3}/telometer/variant_support_v2.py +0 -0
- {telometer-2.0.2 → telometer-2.0.3}/telometer.egg-info/dependency_links.txt +0 -0
- {telometer-2.0.2 → telometer-2.0.3}/telometer.egg-info/entry_points.txt +0 -0
- {telometer-2.0.2 → telometer-2.0.3}/telometer.egg-info/requires.txt +0 -0
- {telometer-2.0.2 → telometer-2.0.3}/telometer.egg-info/top_level.txt +0 -0
telometer-2.0.3/PKG-INFO
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: telometer
|
|
3
|
+
Version: 2.0.3
|
|
4
|
+
Summary: Quantitative digital telomere measurement from nanopore long reads
|
|
5
|
+
Author-email: "Santiago E. Sanchez" <santy.esanchez@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2023 santiago-es
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Classifier: Development Status :: 4 - Beta
|
|
29
|
+
Classifier: Intended Audience :: Science/Research
|
|
30
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
31
|
+
Classifier: Operating System :: OS Independent
|
|
32
|
+
Classifier: Programming Language :: Python :: 3
|
|
33
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
39
|
+
Requires-Python: >=3.8
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
License-File: LICENSE.txt
|
|
42
|
+
Requires-Dist: numpy
|
|
43
|
+
Requires-Dist: pandas
|
|
44
|
+
Requires-Dist: pysam
|
|
45
|
+
Requires-Dist: regex
|
|
46
|
+
Requires-Dist: scipy
|
|
47
|
+
|
|
48
|
+
# Telometer 2.0.3
|
|
49
|
+
|
|
50
|
+
A tool for measuring chromosome-specific telomeres from long-read alignments.
|
|
51
|
+
|
|
52
|
+
[Telometer Github](https://github.com/santiago-es/Telometer)
|
|
53
|
+
|
|
54
|
+
Version 2.0.3 simplifies the main variant-output table and adds individual tract lengths and a fractional first-tract position. Telomere measurement, alignment selection, variant-tract qualification, and enrichment accounting are unchanged from the uploaded 2.0.2 baseline.
|
|
55
|
+
|
|
56
|
+
## Install and run
|
|
57
|
+
|
|
58
|
+
The distribution retains its Python **>=3.8** declaration and unpinned numpy, pandas, pysam, regex, and scipy dependencies. Validation for this revision uses **Python 3.11.13**; this does not establish compatibility with older interpreters or every platform/dependency combination. The standalone bundle includes the previously tested dependency pins in `requirements.txt`.
|
|
59
|
+
|
|
60
|
+
In an activated Python environment, install a downloaded release file:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
uv pip install ./telometer-2.0.3-py3-none-any.whl
|
|
64
|
+
# Or build/install the source distribution:
|
|
65
|
+
uv pip install ./telometer-2.0.3.tar.gz
|
|
66
|
+
|
|
67
|
+
telometer --version
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The version command prints `Telometer v2.0.3`. Run on a sorted BAM aligned to a confirmed compatible reference:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# WGS; use -m 1000 for telomere capture libraries.
|
|
74
|
+
telometer -b sample.sorted.bam -o telomeres.tsv -m 4000 -g 20 -t 2 -l 1
|
|
75
|
+
|
|
76
|
+
# Optional variant motif and independently optional enrichment:
|
|
77
|
+
telometer -b sample.sorted.bam -o telomeres_variants.tsv -m 4000 -g 20 -t 2 -l 1 \
|
|
78
|
+
--variant-motif TGCGGT --min-variant-units 2 -e
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`TGCGGT` is an example, not an inferred or default motif. Both optional features are off unless requested. `-e` / `--enrichment` is a Boolean switch with no value. The existing minimum-length default is 1000 bp; the gap default is 20. `-l` is a nominal batch-size setting in GiB, **not a total-memory limit**. With enrichment enabled, memory also scales with the number of unique read IDs. Choose resources using a representative subset.
|
|
82
|
+
|
|
83
|
+
The console entry point is `telometer.telometer:run_telometer`. Package-context alternatives are `python -m telometer.telometer` and `from telometer.telometer import process_bam_file`. There is no `python -m telometer` launcher or root-level function re-export in this package.
|
|
84
|
+
|
|
85
|
+
For the standalone ZIP, extract **all five files together**, install its requirements, and invoke `python telometer.py`. Its two helper modules must remain adjacent to the caller. The separate drop-in package module uses relative imports and is not a self-contained standalone script.
|
|
86
|
+
|
|
87
|
+
## Main TSV
|
|
88
|
+
|
|
89
|
+
With variant mode and enrichment both enabled, columns are exactly:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
chromosome
|
|
93
|
+
reference_start
|
|
94
|
+
reference_end
|
|
95
|
+
telomere_length
|
|
96
|
+
read_id
|
|
97
|
+
mapping_quality
|
|
98
|
+
read_length
|
|
99
|
+
arm
|
|
100
|
+
direction
|
|
101
|
+
variant_motif
|
|
102
|
+
variant_present
|
|
103
|
+
variant_tract_count
|
|
104
|
+
pre_variant_bp
|
|
105
|
+
telomeres_per_gb
|
|
106
|
+
variant_tract_lengths
|
|
107
|
+
percent_pre_variant
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Without `-e`, `telomeres_per_gb` is omitted. Without variant mode, all variant-specific columns are omitted. The four mode widths are **9 / 10 / 15 / 16** for neither / enrichment only / variants only / both. Empty tables retain the appropriate headers. Missing values in the main TSV are the literal **`NA`**; genuine zeros are preserved. Main row order may vary across worker runs, so compare by read ID.
|
|
111
|
+
|
|
112
|
+
### Individual tract lengths
|
|
113
|
+
|
|
114
|
+
`variant_tract_lengths` contains integer base-pair spans, separated by commas without spaces, in the existing companion `tract_id` order (increasing original-read query coordinates). There is one entry per qualifying tract. These are spans, not six-base repeat counts or merged/union coverage. Separately counted overlapping tracts remain separate, and lengths are not rounded to multiples of six. Reads without qualifying tracts have `NA`.
|
|
115
|
+
|
|
116
|
+
### Fractional first-tract position
|
|
117
|
+
|
|
118
|
+
`percent_pre_variant` is a **0–1 fraction**, not a 0–100 percentage. It describes the first qualifying tract's position from the called telomere's subtelomeric-facing end toward its distal end. In the existing original-orientation coordinate frame, let `T0` and `T1` be the selected telomere boundaries:
|
|
119
|
+
|
|
120
|
+
- Right-terminal telomere: `(minimum tract start - T0) / telomere_length`.
|
|
121
|
+
- Left-terminal telomere: `(T1 - maximum tract end) / telomere_length`.
|
|
122
|
+
|
|
123
|
+
The coordinate frame includes consistent recorded hard-clip offsets. No qualifying tract or an ambiguous/unidentifiable terminal side gives `NA`. A tract at the proximal boundary gives a genuine zero. The lengths list stays in query-coordinate order even when the proximal-first tract is its last entry.
|
|
124
|
+
|
|
125
|
+
Unlike the unchanged `pre_variant_bp`, the new fraction **does not require a supported alignment/repeat-free-flank anchor**. It can therefore be numeric when `pre_variant_bp` is `NA`. It measures position within the called telomere interval, not a verified physical subtelomeric junction or historical telomere length. Detection and tract-support thresholds are unchanged.
|
|
126
|
+
|
|
127
|
+
## Companion table and enrichment
|
|
128
|
+
|
|
129
|
+
Variant mode still writes `<output_stem>_variant_tracts.tsv` with its unchanged 20-column schema, per-tract values, and missing-value formatting. The eight removed main-table coverage/diagnostic fields are not used to change calls or suppress internal diagnostics. Use a fresh output stem to avoid confusing an old companion with a new variant-disabled run.
|
|
130
|
+
|
|
131
|
+
Enrichment remains:
|
|
132
|
+
|
|
133
|
+
`final measured unique read-ID count * 1,000,000,000 / nonredundant recorded read bases in the BAM`
|
|
134
|
+
|
|
135
|
+
Each QNAME contributes one consistent recorded full length before filtering; repeated alignments do not multiply bases. Query-consuming CIGAR operations and recorded hard clips determine full length when available. Unresolved/conflicting lengths, unusable IDs, or paired-end input can make the aggregate unavailable; valid measurements are still written with `NA` enrichment. Positive recorded bases with zero calls give rate zero; an empty/zero-base BAM has unavailable rate. The sample-wide value is repeated on measured rows, not calculated independently per read. Preserve the console log for sample totals when the output has no rows.
|
|
136
|
+
|
|
137
|
+
The BAM cannot recover reads removed upstream or trimming that is absent from its metadata. This rate is not necessarily total instrument yield or a fold-enrichment comparison. Software regression checks are not independent biological validation of variant status, telomere boundaries, or positional interpretation.
|
|
138
|
+
|
|
139
|
+
## Build and manual publication
|
|
140
|
+
|
|
141
|
+
The supplied flat layout and `setuptools>=61,<76` backend policy are retained. Build in an activated environment:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
uv pip install "build==1.5.0"
|
|
145
|
+
python -m build
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Use current Twine and packaging when checking metadata:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
uv pip install --upgrade "twine>=6.1.0" "packaging>=24.2"
|
|
152
|
+
python -m twine check --strict dist/telometer-2.0.3-py3-none-any.whl dist/telometer-2.0.3.tar.gz
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Publishing is a separate maintainer action; these files do not update GitHub or PyPI automatically. The release is MIT licensed under the restored Telometer notice in `LICENSE.txt`.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Telometer 2.0.3
|
|
2
|
+
|
|
3
|
+
A tool for measuring chromosome-specific telomeres from long-read alignments.
|
|
4
|
+
|
|
5
|
+
[Telometer Github](https://github.com/santiago-es/Telometer)
|
|
6
|
+
|
|
7
|
+
Version 2.0.3 simplifies the main variant-output table and adds individual tract lengths and a fractional first-tract position. Telomere measurement, alignment selection, variant-tract qualification, and enrichment accounting are unchanged from the uploaded 2.0.2 baseline.
|
|
8
|
+
|
|
9
|
+
## Install and run
|
|
10
|
+
|
|
11
|
+
The distribution retains its Python **>=3.8** declaration and unpinned numpy, pandas, pysam, regex, and scipy dependencies. Validation for this revision uses **Python 3.11.13**; this does not establish compatibility with older interpreters or every platform/dependency combination. The standalone bundle includes the previously tested dependency pins in `requirements.txt`.
|
|
12
|
+
|
|
13
|
+
In an activated Python environment, install a downloaded release file:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv pip install ./telometer-2.0.3-py3-none-any.whl
|
|
17
|
+
# Or build/install the source distribution:
|
|
18
|
+
uv pip install ./telometer-2.0.3.tar.gz
|
|
19
|
+
|
|
20
|
+
telometer --version
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The version command prints `Telometer v2.0.3`. Run on a sorted BAM aligned to a confirmed compatible reference:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# WGS; use -m 1000 for telomere capture libraries.
|
|
27
|
+
telometer -b sample.sorted.bam -o telomeres.tsv -m 4000 -g 20 -t 2 -l 1
|
|
28
|
+
|
|
29
|
+
# Optional variant motif and independently optional enrichment:
|
|
30
|
+
telometer -b sample.sorted.bam -o telomeres_variants.tsv -m 4000 -g 20 -t 2 -l 1 \
|
|
31
|
+
--variant-motif TGCGGT --min-variant-units 2 -e
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`TGCGGT` is an example, not an inferred or default motif. Both optional features are off unless requested. `-e` / `--enrichment` is a Boolean switch with no value. The existing minimum-length default is 1000 bp; the gap default is 20. `-l` is a nominal batch-size setting in GiB, **not a total-memory limit**. With enrichment enabled, memory also scales with the number of unique read IDs. Choose resources using a representative subset.
|
|
35
|
+
|
|
36
|
+
The console entry point is `telometer.telometer:run_telometer`. Package-context alternatives are `python -m telometer.telometer` and `from telometer.telometer import process_bam_file`. There is no `python -m telometer` launcher or root-level function re-export in this package.
|
|
37
|
+
|
|
38
|
+
For the standalone ZIP, extract **all five files together**, install its requirements, and invoke `python telometer.py`. Its two helper modules must remain adjacent to the caller. The separate drop-in package module uses relative imports and is not a self-contained standalone script.
|
|
39
|
+
|
|
40
|
+
## Main TSV
|
|
41
|
+
|
|
42
|
+
With variant mode and enrichment both enabled, columns are exactly:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
chromosome
|
|
46
|
+
reference_start
|
|
47
|
+
reference_end
|
|
48
|
+
telomere_length
|
|
49
|
+
read_id
|
|
50
|
+
mapping_quality
|
|
51
|
+
read_length
|
|
52
|
+
arm
|
|
53
|
+
direction
|
|
54
|
+
variant_motif
|
|
55
|
+
variant_present
|
|
56
|
+
variant_tract_count
|
|
57
|
+
pre_variant_bp
|
|
58
|
+
telomeres_per_gb
|
|
59
|
+
variant_tract_lengths
|
|
60
|
+
percent_pre_variant
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Without `-e`, `telomeres_per_gb` is omitted. Without variant mode, all variant-specific columns are omitted. The four mode widths are **9 / 10 / 15 / 16** for neither / enrichment only / variants only / both. Empty tables retain the appropriate headers. Missing values in the main TSV are the literal **`NA`**; genuine zeros are preserved. Main row order may vary across worker runs, so compare by read ID.
|
|
64
|
+
|
|
65
|
+
### Individual tract lengths
|
|
66
|
+
|
|
67
|
+
`variant_tract_lengths` contains integer base-pair spans, separated by commas without spaces, in the existing companion `tract_id` order (increasing original-read query coordinates). There is one entry per qualifying tract. These are spans, not six-base repeat counts or merged/union coverage. Separately counted overlapping tracts remain separate, and lengths are not rounded to multiples of six. Reads without qualifying tracts have `NA`.
|
|
68
|
+
|
|
69
|
+
### Fractional first-tract position
|
|
70
|
+
|
|
71
|
+
`percent_pre_variant` is a **0–1 fraction**, not a 0–100 percentage. It describes the first qualifying tract's position from the called telomere's subtelomeric-facing end toward its distal end. In the existing original-orientation coordinate frame, let `T0` and `T1` be the selected telomere boundaries:
|
|
72
|
+
|
|
73
|
+
- Right-terminal telomere: `(minimum tract start - T0) / telomere_length`.
|
|
74
|
+
- Left-terminal telomere: `(T1 - maximum tract end) / telomere_length`.
|
|
75
|
+
|
|
76
|
+
The coordinate frame includes consistent recorded hard-clip offsets. No qualifying tract or an ambiguous/unidentifiable terminal side gives `NA`. A tract at the proximal boundary gives a genuine zero. The lengths list stays in query-coordinate order even when the proximal-first tract is its last entry.
|
|
77
|
+
|
|
78
|
+
Unlike the unchanged `pre_variant_bp`, the new fraction **does not require a supported alignment/repeat-free-flank anchor**. It can therefore be numeric when `pre_variant_bp` is `NA`. It measures position within the called telomere interval, not a verified physical subtelomeric junction or historical telomere length. Detection and tract-support thresholds are unchanged.
|
|
79
|
+
|
|
80
|
+
## Companion table and enrichment
|
|
81
|
+
|
|
82
|
+
Variant mode still writes `<output_stem>_variant_tracts.tsv` with its unchanged 20-column schema, per-tract values, and missing-value formatting. The eight removed main-table coverage/diagnostic fields are not used to change calls or suppress internal diagnostics. Use a fresh output stem to avoid confusing an old companion with a new variant-disabled run.
|
|
83
|
+
|
|
84
|
+
Enrichment remains:
|
|
85
|
+
|
|
86
|
+
`final measured unique read-ID count * 1,000,000,000 / nonredundant recorded read bases in the BAM`
|
|
87
|
+
|
|
88
|
+
Each QNAME contributes one consistent recorded full length before filtering; repeated alignments do not multiply bases. Query-consuming CIGAR operations and recorded hard clips determine full length when available. Unresolved/conflicting lengths, unusable IDs, or paired-end input can make the aggregate unavailable; valid measurements are still written with `NA` enrichment. Positive recorded bases with zero calls give rate zero; an empty/zero-base BAM has unavailable rate. The sample-wide value is repeated on measured rows, not calculated independently per read. Preserve the console log for sample totals when the output has no rows.
|
|
89
|
+
|
|
90
|
+
The BAM cannot recover reads removed upstream or trimming that is absent from its metadata. This rate is not necessarily total instrument yield or a fold-enrichment comparison. Software regression checks are not independent biological validation of variant status, telomere boundaries, or positional interpretation.
|
|
91
|
+
|
|
92
|
+
## Build and manual publication
|
|
93
|
+
|
|
94
|
+
The supplied flat layout and `setuptools>=61,<76` backend policy are retained. Build in an activated environment:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
uv pip install "build==1.5.0"
|
|
98
|
+
python -m build
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Use current Twine and packaging when checking metadata:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
uv pip install --upgrade "twine>=6.1.0" "packaging>=24.2"
|
|
105
|
+
python -m twine check --strict dist/telometer-2.0.3-py3-none-any.whl dist/telometer-2.0.3.tar.gz
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Publishing is a separate maintainer action; these files do not update GitHub or PyPI automatically. The release is MIT licensed under the restored Telometer notice in `LICENSE.txt`.
|
|
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "telometer"
|
|
11
|
-
version = "2.0.
|
|
11
|
+
version = "2.0.3"
|
|
12
12
|
description = "Quantitative digital telomere measurement from nanopore long reads"
|
|
13
13
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
14
14
|
requires-python = ">=3.8"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
# Telometer v2.0
|
|
2
|
+
# Telometer v2.0.3
|
|
3
3
|
|
|
4
4
|
# Created by: Santiago E Sanchez
|
|
5
5
|
# Artandi Lab, Stanford University, 2024
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
# Simple Usage: telometer -b sorted_t2t.bam -o output.tsv
|
|
10
10
|
|
|
11
|
-
__version__ = "2.0.
|
|
11
|
+
__version__ = "2.0.3"
|
|
12
12
|
|
|
13
13
|
import pysam
|
|
14
14
|
from pathlib import Path
|
|
@@ -354,6 +354,56 @@ class EnrichmentCounter:
|
|
|
354
354
|
'warning': 'Enrichment unavailable: ' + '; '.join(reasons) if reasons else None}
|
|
355
355
|
|
|
356
356
|
|
|
357
|
+
_MAIN_VARIANT_COLUMNS = ['variant_motif', 'variant_present', 'variant_tract_count', 'pre_variant_bp']
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def _variant_output_fields(read_result):
|
|
361
|
+
"""Format existing winning tracts without changing calls or anchor checks.
|
|
362
|
+
|
|
363
|
+
The fraction uses the called telomere's proximal-facing boundary, independently
|
|
364
|
+
of whether the original pre_variant_bp proxy passes its stricter anchor gates.
|
|
365
|
+
All coordinates already share the original-read frame and hard-clip offset.
|
|
366
|
+
"""
|
|
367
|
+
tracts = read_result['_variant_tracts']
|
|
368
|
+
if (len(tracts) != read_result['variant_tract_count'] or
|
|
369
|
+
bool(tracts) != read_result['variant_present']):
|
|
370
|
+
raise ValueError('Variant tract count/presence disagrees with the existing tract rows')
|
|
371
|
+
if not tracts:
|
|
372
|
+
return None, None
|
|
373
|
+
|
|
374
|
+
details = read_result['_variant_details']
|
|
375
|
+
start, end = details['query_start_forward'], details['query_end_forward']
|
|
376
|
+
telomere_length = read_result['telomere_length']
|
|
377
|
+
if not 0 <= start < end or telomere_length <= 0 or end-start != telomere_length:
|
|
378
|
+
raise ValueError('Inconsistent called-telomere coordinates for variant output')
|
|
379
|
+
|
|
380
|
+
lengths = []
|
|
381
|
+
previous_start = None
|
|
382
|
+
for index, tract in enumerate(tracts, 1):
|
|
383
|
+
tract_start, tract_end = tract['query_start_forward'], tract['query_end_forward']
|
|
384
|
+
span = tract['span_bp']
|
|
385
|
+
if (not isinstance(span, int) or isinstance(span, bool) or
|
|
386
|
+
not start <= tract_start < tract_end <= end or span != tract_end-tract_start):
|
|
387
|
+
raise ValueError('Inconsistent variant tract coordinates or base-pair span')
|
|
388
|
+
if tract['tract_id'] != index or (previous_start is not None and tract_start < previous_start):
|
|
389
|
+
raise ValueError('Variant tract rows are not in their existing tract-ID/query order')
|
|
390
|
+
lengths.append(str(span))
|
|
391
|
+
previous_start = tract_start
|
|
392
|
+
|
|
393
|
+
length_list = ','.join(lengths)
|
|
394
|
+
side = details['telomeric_query_side']
|
|
395
|
+
if side == 'right':
|
|
396
|
+
distance = min(tract['query_start_forward'] for tract in tracts)-start
|
|
397
|
+
elif side == 'left':
|
|
398
|
+
distance = end-max(tract['query_end_forward'] for tract in tracts)
|
|
399
|
+
else:
|
|
400
|
+
return length_list, None
|
|
401
|
+
fraction = distance / telomere_length
|
|
402
|
+
if not 0 <= fraction <= 1:
|
|
403
|
+
raise ValueError('Variant fractional position lies outside the called telomere')
|
|
404
|
+
return length_list, fraction
|
|
405
|
+
|
|
406
|
+
|
|
357
407
|
def process_bam_file(bam_file_path, output_file_path, max_gap_length=20, min_read_len=1000, num_processes=8, memory_limit_gb=8,
|
|
358
408
|
variant_motif=None, min_variant_units=None, enrichment=False):
|
|
359
409
|
variant_motif, min_variant_units = validate_variant_options(variant_motif, min_variant_units)
|
|
@@ -447,11 +497,16 @@ def process_bam_file(bam_file_path, output_file_path, max_gap_length=20, min_rea
|
|
|
447
497
|
bam_file.close()
|
|
448
498
|
|
|
449
499
|
enrichment_summary = enrichment_counter.summarize(len(read_results)) if enrichment_counter is not None else None
|
|
450
|
-
|
|
500
|
+
output_records = list(read_results.values())
|
|
501
|
+
results_df = pd.DataFrame(output_records, columns=BASE_COLUMNS + (_MAIN_VARIANT_COLUMNS if variant_motif is not None else []))
|
|
451
502
|
if enrichment_summary is not None:
|
|
452
503
|
rate = enrichment_summary['telomeres_per_gb']
|
|
453
504
|
results_df['telomeres_per_gb'] = rate if rate is not None else np.nan
|
|
454
|
-
|
|
505
|
+
if variant_motif is not None:
|
|
506
|
+
variant_output = [_variant_output_fields(result) for result in output_records]
|
|
507
|
+
results_df['variant_tract_lengths'] = [fields[0] for fields in variant_output]
|
|
508
|
+
results_df['percent_pre_variant'] = [fields[1] for fields in variant_output]
|
|
509
|
+
results_df.to_csv(output_file_path, sep='\t', index=False, na_rep='NA')
|
|
455
510
|
if variant_motif is not None:
|
|
456
511
|
tract_rows = [tract for result in read_results.values() for tract in result['_variant_tracts']]
|
|
457
512
|
tract_path = Path(output_file_path).with_name(Path(output_file_path).stem + '_variant_tracts.tsv')
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: telometer
|
|
3
|
+
Version: 2.0.3
|
|
4
|
+
Summary: Quantitative digital telomere measurement from nanopore long reads
|
|
5
|
+
Author-email: "Santiago E. Sanchez" <santy.esanchez@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2023 santiago-es
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Classifier: Development Status :: 4 - Beta
|
|
29
|
+
Classifier: Intended Audience :: Science/Research
|
|
30
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
31
|
+
Classifier: Operating System :: OS Independent
|
|
32
|
+
Classifier: Programming Language :: Python :: 3
|
|
33
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
39
|
+
Requires-Python: >=3.8
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
License-File: LICENSE.txt
|
|
42
|
+
Requires-Dist: numpy
|
|
43
|
+
Requires-Dist: pandas
|
|
44
|
+
Requires-Dist: pysam
|
|
45
|
+
Requires-Dist: regex
|
|
46
|
+
Requires-Dist: scipy
|
|
47
|
+
|
|
48
|
+
# Telometer 2.0.3
|
|
49
|
+
|
|
50
|
+
A tool for measuring chromosome-specific telomeres from long-read alignments.
|
|
51
|
+
|
|
52
|
+
[Telometer Github](https://github.com/santiago-es/Telometer)
|
|
53
|
+
|
|
54
|
+
Version 2.0.3 simplifies the main variant-output table and adds individual tract lengths and a fractional first-tract position. Telomere measurement, alignment selection, variant-tract qualification, and enrichment accounting are unchanged from the uploaded 2.0.2 baseline.
|
|
55
|
+
|
|
56
|
+
## Install and run
|
|
57
|
+
|
|
58
|
+
The distribution retains its Python **>=3.8** declaration and unpinned numpy, pandas, pysam, regex, and scipy dependencies. Validation for this revision uses **Python 3.11.13**; this does not establish compatibility with older interpreters or every platform/dependency combination. The standalone bundle includes the previously tested dependency pins in `requirements.txt`.
|
|
59
|
+
|
|
60
|
+
In an activated Python environment, install a downloaded release file:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
uv pip install ./telometer-2.0.3-py3-none-any.whl
|
|
64
|
+
# Or build/install the source distribution:
|
|
65
|
+
uv pip install ./telometer-2.0.3.tar.gz
|
|
66
|
+
|
|
67
|
+
telometer --version
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The version command prints `Telometer v2.0.3`. Run on a sorted BAM aligned to a confirmed compatible reference:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# WGS; use -m 1000 for telomere capture libraries.
|
|
74
|
+
telometer -b sample.sorted.bam -o telomeres.tsv -m 4000 -g 20 -t 2 -l 1
|
|
75
|
+
|
|
76
|
+
# Optional variant motif and independently optional enrichment:
|
|
77
|
+
telometer -b sample.sorted.bam -o telomeres_variants.tsv -m 4000 -g 20 -t 2 -l 1 \
|
|
78
|
+
--variant-motif TGCGGT --min-variant-units 2 -e
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`TGCGGT` is an example, not an inferred or default motif. Both optional features are off unless requested. `-e` / `--enrichment` is a Boolean switch with no value. The existing minimum-length default is 1000 bp; the gap default is 20. `-l` is a nominal batch-size setting in GiB, **not a total-memory limit**. With enrichment enabled, memory also scales with the number of unique read IDs. Choose resources using a representative subset.
|
|
82
|
+
|
|
83
|
+
The console entry point is `telometer.telometer:run_telometer`. Package-context alternatives are `python -m telometer.telometer` and `from telometer.telometer import process_bam_file`. There is no `python -m telometer` launcher or root-level function re-export in this package.
|
|
84
|
+
|
|
85
|
+
For the standalone ZIP, extract **all five files together**, install its requirements, and invoke `python telometer.py`. Its two helper modules must remain adjacent to the caller. The separate drop-in package module uses relative imports and is not a self-contained standalone script.
|
|
86
|
+
|
|
87
|
+
## Main TSV
|
|
88
|
+
|
|
89
|
+
With variant mode and enrichment both enabled, columns are exactly:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
chromosome
|
|
93
|
+
reference_start
|
|
94
|
+
reference_end
|
|
95
|
+
telomere_length
|
|
96
|
+
read_id
|
|
97
|
+
mapping_quality
|
|
98
|
+
read_length
|
|
99
|
+
arm
|
|
100
|
+
direction
|
|
101
|
+
variant_motif
|
|
102
|
+
variant_present
|
|
103
|
+
variant_tract_count
|
|
104
|
+
pre_variant_bp
|
|
105
|
+
telomeres_per_gb
|
|
106
|
+
variant_tract_lengths
|
|
107
|
+
percent_pre_variant
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Without `-e`, `telomeres_per_gb` is omitted. Without variant mode, all variant-specific columns are omitted. The four mode widths are **9 / 10 / 15 / 16** for neither / enrichment only / variants only / both. Empty tables retain the appropriate headers. Missing values in the main TSV are the literal **`NA`**; genuine zeros are preserved. Main row order may vary across worker runs, so compare by read ID.
|
|
111
|
+
|
|
112
|
+
### Individual tract lengths
|
|
113
|
+
|
|
114
|
+
`variant_tract_lengths` contains integer base-pair spans, separated by commas without spaces, in the existing companion `tract_id` order (increasing original-read query coordinates). There is one entry per qualifying tract. These are spans, not six-base repeat counts or merged/union coverage. Separately counted overlapping tracts remain separate, and lengths are not rounded to multiples of six. Reads without qualifying tracts have `NA`.
|
|
115
|
+
|
|
116
|
+
### Fractional first-tract position
|
|
117
|
+
|
|
118
|
+
`percent_pre_variant` is a **0–1 fraction**, not a 0–100 percentage. It describes the first qualifying tract's position from the called telomere's subtelomeric-facing end toward its distal end. In the existing original-orientation coordinate frame, let `T0` and `T1` be the selected telomere boundaries:
|
|
119
|
+
|
|
120
|
+
- Right-terminal telomere: `(minimum tract start - T0) / telomere_length`.
|
|
121
|
+
- Left-terminal telomere: `(T1 - maximum tract end) / telomere_length`.
|
|
122
|
+
|
|
123
|
+
The coordinate frame includes consistent recorded hard-clip offsets. No qualifying tract or an ambiguous/unidentifiable terminal side gives `NA`. A tract at the proximal boundary gives a genuine zero. The lengths list stays in query-coordinate order even when the proximal-first tract is its last entry.
|
|
124
|
+
|
|
125
|
+
Unlike the unchanged `pre_variant_bp`, the new fraction **does not require a supported alignment/repeat-free-flank anchor**. It can therefore be numeric when `pre_variant_bp` is `NA`. It measures position within the called telomere interval, not a verified physical subtelomeric junction or historical telomere length. Detection and tract-support thresholds are unchanged.
|
|
126
|
+
|
|
127
|
+
## Companion table and enrichment
|
|
128
|
+
|
|
129
|
+
Variant mode still writes `<output_stem>_variant_tracts.tsv` with its unchanged 20-column schema, per-tract values, and missing-value formatting. The eight removed main-table coverage/diagnostic fields are not used to change calls or suppress internal diagnostics. Use a fresh output stem to avoid confusing an old companion with a new variant-disabled run.
|
|
130
|
+
|
|
131
|
+
Enrichment remains:
|
|
132
|
+
|
|
133
|
+
`final measured unique read-ID count * 1,000,000,000 / nonredundant recorded read bases in the BAM`
|
|
134
|
+
|
|
135
|
+
Each QNAME contributes one consistent recorded full length before filtering; repeated alignments do not multiply bases. Query-consuming CIGAR operations and recorded hard clips determine full length when available. Unresolved/conflicting lengths, unusable IDs, or paired-end input can make the aggregate unavailable; valid measurements are still written with `NA` enrichment. Positive recorded bases with zero calls give rate zero; an empty/zero-base BAM has unavailable rate. The sample-wide value is repeated on measured rows, not calculated independently per read. Preserve the console log for sample totals when the output has no rows.
|
|
136
|
+
|
|
137
|
+
The BAM cannot recover reads removed upstream or trimming that is absent from its metadata. This rate is not necessarily total instrument yield or a fold-enrichment comparison. Software regression checks are not independent biological validation of variant status, telomere boundaries, or positional interpretation.
|
|
138
|
+
|
|
139
|
+
## Build and manual publication
|
|
140
|
+
|
|
141
|
+
The supplied flat layout and `setuptools>=61,<76` backend policy are retained. Build in an activated environment:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
uv pip install "build==1.5.0"
|
|
145
|
+
python -m build
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Use current Twine and packaging when checking metadata:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
uv pip install --upgrade "twine>=6.1.0" "packaging>=24.2"
|
|
152
|
+
python -m twine check --strict dist/telometer-2.0.3-py3-none-any.whl dist/telometer-2.0.3.tar.gz
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Publishing is a separate maintainer action; these files do not update GitHub or PyPI automatically. The release is MIT licensed under the restored Telometer notice in `LICENSE.txt`.
|
telometer-2.0.2/PKG-INFO
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: telometer
|
|
3
|
-
Version: 2.0.2
|
|
4
|
-
Summary: Quantitative digital telomere measurement from nanopore long reads
|
|
5
|
-
Author-email: "Santiago E. Sanchez" <santy.esanchez@gmail.com>
|
|
6
|
-
License: Copyright (c) 2024 The Python Packaging Authority
|
|
7
|
-
|
|
8
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
10
|
-
in the Software without restriction, including without limitation the rights
|
|
11
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
13
|
-
furnished to do so, subject to the following conditions:
|
|
14
|
-
|
|
15
|
-
The above copyright notice and this permission notice shall be included in all
|
|
16
|
-
copies or substantial portions of the Software.
|
|
17
|
-
|
|
18
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
-
SOFTWARE.
|
|
25
|
-
|
|
26
|
-
Classifier: Development Status :: 4 - Beta
|
|
27
|
-
Classifier: Intended Audience :: Science/Research
|
|
28
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
29
|
-
Classifier: Operating System :: OS Independent
|
|
30
|
-
Classifier: Programming Language :: Python :: 3
|
|
31
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
32
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
33
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
34
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
35
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
36
|
-
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
37
|
-
Requires-Python: >=3.8
|
|
38
|
-
Description-Content-Type: text/markdown
|
|
39
|
-
License-File: LICENSE.txt
|
|
40
|
-
Requires-Dist: numpy
|
|
41
|
-
Requires-Dist: pandas
|
|
42
|
-
Requires-Dist: pysam
|
|
43
|
-
Requires-Dist: regex
|
|
44
|
-
Requires-Dist: scipy
|
|
45
|
-
|
|
46
|
-
A simple tool for measuring chromosome-specific telomeres from long-read alignments.
|
|
47
|
-
|
|
48
|
-
[Telometer Github](https://github.com/santiago-es/Telometer)
|
telometer-2.0.2/README.md
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: telometer
|
|
3
|
-
Version: 2.0.2
|
|
4
|
-
Summary: Quantitative digital telomere measurement from nanopore long reads
|
|
5
|
-
Author-email: "Santiago E. Sanchez" <santy.esanchez@gmail.com>
|
|
6
|
-
License: Copyright (c) 2024 The Python Packaging Authority
|
|
7
|
-
|
|
8
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
10
|
-
in the Software without restriction, including without limitation the rights
|
|
11
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
13
|
-
furnished to do so, subject to the following conditions:
|
|
14
|
-
|
|
15
|
-
The above copyright notice and this permission notice shall be included in all
|
|
16
|
-
copies or substantial portions of the Software.
|
|
17
|
-
|
|
18
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
-
SOFTWARE.
|
|
25
|
-
|
|
26
|
-
Classifier: Development Status :: 4 - Beta
|
|
27
|
-
Classifier: Intended Audience :: Science/Research
|
|
28
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
29
|
-
Classifier: Operating System :: OS Independent
|
|
30
|
-
Classifier: Programming Language :: Python :: 3
|
|
31
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
32
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
33
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
34
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
35
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
36
|
-
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
37
|
-
Requires-Python: >=3.8
|
|
38
|
-
Description-Content-Type: text/markdown
|
|
39
|
-
License-File: LICENSE.txt
|
|
40
|
-
Requires-Dist: numpy
|
|
41
|
-
Requires-Dist: pandas
|
|
42
|
-
Requires-Dist: pysam
|
|
43
|
-
Requires-Dist: regex
|
|
44
|
-
Requires-Dist: scipy
|
|
45
|
-
|
|
46
|
-
A simple tool for measuring chromosome-specific telomeres from long-read alignments.
|
|
47
|
-
|
|
48
|
-
[Telometer Github](https://github.com/santiago-es/Telometer)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|