pedview 1.0.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.
- pedview-1.0.0/LICENSE +21 -0
- pedview-1.0.0/PKG-INFO +138 -0
- pedview-1.0.0/README.md +113 -0
- pedview-1.0.0/pyproject.toml +43 -0
- pedview-1.0.0/setup.cfg +4 -0
- pedview-1.0.0/src/pedview/__init__.py +5 -0
- pedview-1.0.0/src/pedview/__main__.py +3 -0
- pedview-1.0.0/src/pedview/cli.py +199 -0
- pedview-1.0.0/src/pedview/insights.py +301 -0
- pedview-1.0.0/src/pedview/layout.py +1105 -0
- pedview-1.0.0/src/pedview/models.py +134 -0
- pedview-1.0.0/src/pedview/parser.py +428 -0
- pedview-1.0.0/src/pedview/phenotypes.py +89 -0
- pedview-1.0.0/src/pedview/relatedness.py +52 -0
- pedview-1.0.0/src/pedview/render.py +3740 -0
- pedview-1.0.0/src/pedview/segregation.py +132 -0
- pedview-1.0.0/src/pedview/validate.py +154 -0
- pedview-1.0.0/src/pedview.egg-info/PKG-INFO +138 -0
- pedview-1.0.0/src/pedview.egg-info/SOURCES.txt +20 -0
- pedview-1.0.0/src/pedview.egg-info/dependency_links.txt +1 -0
- pedview-1.0.0/src/pedview.egg-info/entry_points.txt +2 -0
- pedview-1.0.0/src/pedview.egg-info/top_level.txt +1 -0
pedview-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dongkun Lee, and Mark Angier
|
|
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.
|
pedview-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pedview
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Command-line pedigree visualization for genetics workflows
|
|
5
|
+
Author: Dongkun Lee, Mark Angier
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/DKunLee/Pedview
|
|
8
|
+
Project-URL: Repository, https://github.com/DKunLee/Pedview
|
|
9
|
+
Project-URL: Issues, https://github.com/DKunLee/Pedview/issues
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# pedview
|
|
27
|
+
|
|
28
|
+
[](https://pypi.org/project/pedview/)
|
|
29
|
+
[](https://pypi.org/project/pedview/)
|
|
30
|
+
[](https://opensource.org/licenses/MIT)
|
|
31
|
+
|
|
32
|
+
A lightweight command-line tool for visualizing family pedigrees in genetics and clinical research workflows.
|
|
33
|
+
|
|
34
|
+
`pedview` reads standard pedigree files and generates self-contained, interactive HTML reports with publication-ready SVG diagrams. It has **zero external runtime dependencies** (built purely on Python standard library) and runs completely offline.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- **Zero Runtime Dependencies**: Pure Python standard library (`math`, `html`, `dataclasses`, `pathlib`, `argparse`).
|
|
41
|
+
- **Flexible Input**: Auto-detects standard 6-column PLINK `.fam`/`.ped` files and extended headered pedigree files.
|
|
42
|
+
- **Clinical & Research Attributes**: Visualizes affected status, proband indicators, carriers, deceased status, age labels, and genotype calls.
|
|
43
|
+
- **Layered Graph Engine**: Sugiyama-style layout with barycenter crossing reduction, twin handling, and consanguinity loop routing.
|
|
44
|
+
- **Interactive Standalone HTML**: Produces a single offline HTML report with pan/zoom navigation, individual detail drawer, and search.
|
|
45
|
+
- **Publication Exports**: One-click download for vector SVG, journal-styled SVG, and high-resolution PNG.
|
|
46
|
+
- **Mendelian Quality Control**: Automated parent-child relationship validation and Wright's inbreeding coefficient calculations ($f_a$).
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install pedview
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Or install from source:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/DKunLee/Pedview.git
|
|
60
|
+
cd Pedview
|
|
61
|
+
pip install .
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Quickstart
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# 1. Validate pedigree format, integrity, and relationships
|
|
70
|
+
pedview validate <input.ped>
|
|
71
|
+
|
|
72
|
+
# 2. Preview family and cohort summaries directly in the terminal
|
|
73
|
+
pedview preview <input.ped>
|
|
74
|
+
|
|
75
|
+
# 3. Build a standalone interactive HTML report
|
|
76
|
+
pedview build <input.ped> -o <output_report.html>
|
|
77
|
+
|
|
78
|
+
# 4. Render a single family from a multi-family cohort
|
|
79
|
+
pedview build <input.ped> --family <family_id> -o <family_report.html>
|
|
80
|
+
|
|
81
|
+
# 5. Highlight a candidate variant and set ancestor inbreeding coefficient
|
|
82
|
+
pedview build <input.ped> --variant-name "<variant_name>" --ancestor-inbreeding 0.02 -o <output_report.html>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Supported Formats
|
|
88
|
+
|
|
89
|
+
### 1. Standard Headerless PLINK `.fam` / `.ped` (6 Columns)
|
|
90
|
+
```text
|
|
91
|
+
FAM01 101 0 0 1 1
|
|
92
|
+
FAM01 102 0 0 2 1
|
|
93
|
+
FAM01 201 101 102 1 2
|
|
94
|
+
FAM01 202 101 102 2 1
|
|
95
|
+
```
|
|
96
|
+
- **Sex**: `1` = Male, `2` = Female, `0` = Unknown.
|
|
97
|
+
- **Phenotype**: `1` = Unaffected, `2` = Affected, `0` / `-9` = Unknown.
|
|
98
|
+
- **Missing Parents**: `0`, `.`, `-9`, `NA`.
|
|
99
|
+
|
|
100
|
+
### 2. Headered Extended Pedigree (Tab- or Space-delimited)
|
|
101
|
+
```text
|
|
102
|
+
famid id fid mid sex affected proband deceased age genotype
|
|
103
|
+
FAM01 101 0 0 1 unaffected 0 1 72y 0/0
|
|
104
|
+
FAM01 102 0 0 2 unaffected 0 0 68y 0/1
|
|
105
|
+
FAM01 201 101 102 1 affected 1 0 14y 0/1
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Common column header aliases are resolved automatically:
|
|
109
|
+
- **Family**: `famid`, `family_id`, `family`, `pedigree`, `fid`
|
|
110
|
+
- **Individual**: `id`, `iid`, `individual_id`, `sample_id`
|
|
111
|
+
- **Father**: `fid`, `pat`, `pid`, `father`, `father_id`
|
|
112
|
+
- **Mother**: `mid`, `mat`, `mother`, `mother_id`
|
|
113
|
+
- **Sex**: `sex`, `gender`
|
|
114
|
+
- **Phenotype**: `affected`, `phenotype`, `affection`
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## CLI Reference
|
|
119
|
+
|
|
120
|
+
| Command | Description | Example |
|
|
121
|
+
| :--- | :--- | :--- |
|
|
122
|
+
| `validate` | Validates file format, parent references, sex codes, and loops | `pedview validate <input.ped>` |
|
|
123
|
+
| `preview` | Prints terminal summary of families, founders, and generations | `pedview preview <input.ped>` |
|
|
124
|
+
| `build` | Generates interactive HTML report | `pedview build <input.ped> -o <output_report.html>` |
|
|
125
|
+
|
|
126
|
+
### Build Options
|
|
127
|
+
|
|
128
|
+
- `-o, --output`: Output file path (defaults to `<input>.html`).
|
|
129
|
+
- `--family`: Filter report to a specific family ID (`<family_id>`).
|
|
130
|
+
- `--title`: Custom title for the HTML report (`"<title>"`).
|
|
131
|
+
- `--variant-name`: Candidate variant annotation label (e.g. `"<variant_name>"`).
|
|
132
|
+
- `--ancestor-inbreeding`: Global Wright ancestor inbreeding coefficient ($f_a$). Defaults to `0.0`.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
This project is licensed under the [MIT License](LICENSE).
|
pedview-1.0.0/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# pedview
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/pedview/)
|
|
4
|
+
[](https://pypi.org/project/pedview/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
A lightweight command-line tool for visualizing family pedigrees in genetics and clinical research workflows.
|
|
8
|
+
|
|
9
|
+
`pedview` reads standard pedigree files and generates self-contained, interactive HTML reports with publication-ready SVG diagrams. It has **zero external runtime dependencies** (built purely on Python standard library) and runs completely offline.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Zero Runtime Dependencies**: Pure Python standard library (`math`, `html`, `dataclasses`, `pathlib`, `argparse`).
|
|
16
|
+
- **Flexible Input**: Auto-detects standard 6-column PLINK `.fam`/`.ped` files and extended headered pedigree files.
|
|
17
|
+
- **Clinical & Research Attributes**: Visualizes affected status, proband indicators, carriers, deceased status, age labels, and genotype calls.
|
|
18
|
+
- **Layered Graph Engine**: Sugiyama-style layout with barycenter crossing reduction, twin handling, and consanguinity loop routing.
|
|
19
|
+
- **Interactive Standalone HTML**: Produces a single offline HTML report with pan/zoom navigation, individual detail drawer, and search.
|
|
20
|
+
- **Publication Exports**: One-click download for vector SVG, journal-styled SVG, and high-resolution PNG.
|
|
21
|
+
- **Mendelian Quality Control**: Automated parent-child relationship validation and Wright's inbreeding coefficient calculations ($f_a$).
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install pedview
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or install from source:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
git clone https://github.com/DKunLee/Pedview.git
|
|
35
|
+
cd Pedview
|
|
36
|
+
pip install .
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Quickstart
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# 1. Validate pedigree format, integrity, and relationships
|
|
45
|
+
pedview validate <input.ped>
|
|
46
|
+
|
|
47
|
+
# 2. Preview family and cohort summaries directly in the terminal
|
|
48
|
+
pedview preview <input.ped>
|
|
49
|
+
|
|
50
|
+
# 3. Build a standalone interactive HTML report
|
|
51
|
+
pedview build <input.ped> -o <output_report.html>
|
|
52
|
+
|
|
53
|
+
# 4. Render a single family from a multi-family cohort
|
|
54
|
+
pedview build <input.ped> --family <family_id> -o <family_report.html>
|
|
55
|
+
|
|
56
|
+
# 5. Highlight a candidate variant and set ancestor inbreeding coefficient
|
|
57
|
+
pedview build <input.ped> --variant-name "<variant_name>" --ancestor-inbreeding 0.02 -o <output_report.html>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Supported Formats
|
|
63
|
+
|
|
64
|
+
### 1. Standard Headerless PLINK `.fam` / `.ped` (6 Columns)
|
|
65
|
+
```text
|
|
66
|
+
FAM01 101 0 0 1 1
|
|
67
|
+
FAM01 102 0 0 2 1
|
|
68
|
+
FAM01 201 101 102 1 2
|
|
69
|
+
FAM01 202 101 102 2 1
|
|
70
|
+
```
|
|
71
|
+
- **Sex**: `1` = Male, `2` = Female, `0` = Unknown.
|
|
72
|
+
- **Phenotype**: `1` = Unaffected, `2` = Affected, `0` / `-9` = Unknown.
|
|
73
|
+
- **Missing Parents**: `0`, `.`, `-9`, `NA`.
|
|
74
|
+
|
|
75
|
+
### 2. Headered Extended Pedigree (Tab- or Space-delimited)
|
|
76
|
+
```text
|
|
77
|
+
famid id fid mid sex affected proband deceased age genotype
|
|
78
|
+
FAM01 101 0 0 1 unaffected 0 1 72y 0/0
|
|
79
|
+
FAM01 102 0 0 2 unaffected 0 0 68y 0/1
|
|
80
|
+
FAM01 201 101 102 1 affected 1 0 14y 0/1
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Common column header aliases are resolved automatically:
|
|
84
|
+
- **Family**: `famid`, `family_id`, `family`, `pedigree`, `fid`
|
|
85
|
+
- **Individual**: `id`, `iid`, `individual_id`, `sample_id`
|
|
86
|
+
- **Father**: `fid`, `pat`, `pid`, `father`, `father_id`
|
|
87
|
+
- **Mother**: `mid`, `mat`, `mother`, `mother_id`
|
|
88
|
+
- **Sex**: `sex`, `gender`
|
|
89
|
+
- **Phenotype**: `affected`, `phenotype`, `affection`
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## CLI Reference
|
|
94
|
+
|
|
95
|
+
| Command | Description | Example |
|
|
96
|
+
| :--- | :--- | :--- |
|
|
97
|
+
| `validate` | Validates file format, parent references, sex codes, and loops | `pedview validate <input.ped>` |
|
|
98
|
+
| `preview` | Prints terminal summary of families, founders, and generations | `pedview preview <input.ped>` |
|
|
99
|
+
| `build` | Generates interactive HTML report | `pedview build <input.ped> -o <output_report.html>` |
|
|
100
|
+
|
|
101
|
+
### Build Options
|
|
102
|
+
|
|
103
|
+
- `-o, --output`: Output file path (defaults to `<input>.html`).
|
|
104
|
+
- `--family`: Filter report to a specific family ID (`<family_id>`).
|
|
105
|
+
- `--title`: Custom title for the HTML report (`"<title>"`).
|
|
106
|
+
- `--variant-name`: Candidate variant annotation label (e.g. `"<variant_name>"`).
|
|
107
|
+
- `--ancestor-inbreeding`: Global Wright ancestor inbreeding coefficient ($f_a$). Defaults to `0.0`.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
This project is licensed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pedview"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Command-line pedigree visualization for genetics workflows"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Dongkun Lee" },
|
|
14
|
+
{ name = "Mark Angier" }
|
|
15
|
+
]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Science/Research",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
28
|
+
]
|
|
29
|
+
dependencies = []
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/DKunLee/Pedview"
|
|
33
|
+
Repository = "https://github.com/DKunLee/Pedview"
|
|
34
|
+
Issues = "https://github.com/DKunLee/Pedview/issues"
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
pedview = "pedview.cli:main"
|
|
38
|
+
|
|
39
|
+
[tool.setuptools]
|
|
40
|
+
package-dir = {"" = "src"}
|
|
41
|
+
|
|
42
|
+
[tool.setuptools.packages.find]
|
|
43
|
+
where = ["src"]
|
pedview-1.0.0/setup.cfg
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from .layout import build_family_layout
|
|
8
|
+
from .parser import PedigreeFormatError, parse_pedigree
|
|
9
|
+
from .render import render_report
|
|
10
|
+
from .validate import summarize_pedigree, validate_pedigree
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
14
|
+
parser = argparse.ArgumentParser(
|
|
15
|
+
prog="pedview",
|
|
16
|
+
description="Build interactive pedigree reports from pedigree-style family files.",
|
|
17
|
+
)
|
|
18
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
19
|
+
|
|
20
|
+
validate_parser = subparsers.add_parser(
|
|
21
|
+
"validate", help="Validate a pedigree file."
|
|
22
|
+
)
|
|
23
|
+
validate_parser.add_argument(
|
|
24
|
+
"input_path", help="Path to a pedigree file (.ped, .fam)."
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
preview_parser = subparsers.add_parser(
|
|
28
|
+
"preview", help="Summarize pedigree contents."
|
|
29
|
+
)
|
|
30
|
+
preview_parser.add_argument(
|
|
31
|
+
"input_path", help="Path to a pedigree file (.ped, .fam)."
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
build_parser_ = subparsers.add_parser(
|
|
35
|
+
"build", help="Generate a standalone HTML report."
|
|
36
|
+
)
|
|
37
|
+
build_parser_.add_argument(
|
|
38
|
+
"input_path", help="Path to a pedigree file (.ped, .fam)."
|
|
39
|
+
)
|
|
40
|
+
build_parser_.add_argument(
|
|
41
|
+
"-o",
|
|
42
|
+
"--output",
|
|
43
|
+
help="Path to the output HTML file. Defaults to <input>.html.",
|
|
44
|
+
)
|
|
45
|
+
build_parser_.add_argument(
|
|
46
|
+
"--family",
|
|
47
|
+
help="Optional family ID filter. Only render the requested family.",
|
|
48
|
+
)
|
|
49
|
+
build_parser_.add_argument(
|
|
50
|
+
"--title",
|
|
51
|
+
help="Optional report title. Defaults to a title derived from the input filename.",
|
|
52
|
+
)
|
|
53
|
+
build_parser_.add_argument(
|
|
54
|
+
"--ancestor-inbreeding",
|
|
55
|
+
type=float,
|
|
56
|
+
help="Global Wright ancestor inbreeding coefficient (f_a). Defaults to 0.0 when omitted.",
|
|
57
|
+
)
|
|
58
|
+
build_parser_.add_argument(
|
|
59
|
+
"--variant-name",
|
|
60
|
+
help="Optional label or name of the candidate variant being analyzed (e.g. SCN1A:c.1234G>A).",
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
return parser
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def main(argv: list[str] | None = None) -> int:
|
|
67
|
+
parser = build_parser()
|
|
68
|
+
args = parser.parse_args(argv)
|
|
69
|
+
|
|
70
|
+
if args.command == "validate":
|
|
71
|
+
return run_validate(args.input_path)
|
|
72
|
+
if args.command == "preview":
|
|
73
|
+
return run_preview(args.input_path)
|
|
74
|
+
if args.command == "build":
|
|
75
|
+
return run_build(
|
|
76
|
+
args.input_path,
|
|
77
|
+
args.output,
|
|
78
|
+
args.family,
|
|
79
|
+
args.title,
|
|
80
|
+
args.ancestor_inbreeding,
|
|
81
|
+
args.variant_name,
|
|
82
|
+
)
|
|
83
|
+
parser.error("Unknown command.")
|
|
84
|
+
return 2
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def run_validate(input_path: str) -> int:
|
|
88
|
+
pedigree, messages = load_with_messages(input_path)
|
|
89
|
+
print_validation_result(pedigree.source_path, messages)
|
|
90
|
+
return 1 if any(message.severity == "error" for message in messages) else 0
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def run_preview(input_path: str) -> int:
|
|
94
|
+
pedigree, messages = load_with_messages(input_path)
|
|
95
|
+
summaries = summarize_pedigree(pedigree)
|
|
96
|
+
print(f"Source: {pedigree.source_path}")
|
|
97
|
+
print(f"Families: {len(summaries)}")
|
|
98
|
+
print(f"Individuals: {pedigree.people_count()}")
|
|
99
|
+
for summary in summaries:
|
|
100
|
+
print(
|
|
101
|
+
f"- {summary.family_id}: {summary.people_count} individuals, "
|
|
102
|
+
f"{summary.founders_count} founders, "
|
|
103
|
+
f"{summary.relationship_count} parent references, "
|
|
104
|
+
f"{summary.generation_count} generations"
|
|
105
|
+
)
|
|
106
|
+
if messages:
|
|
107
|
+
print()
|
|
108
|
+
print_validation_messages(messages)
|
|
109
|
+
return 1 if any(message.severity == "error" for message in messages) else 0
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def run_build(
|
|
113
|
+
input_path: str,
|
|
114
|
+
output_path: str | None,
|
|
115
|
+
family_filter: str | None,
|
|
116
|
+
title: str | None,
|
|
117
|
+
ancestor_inbreeding: float | None,
|
|
118
|
+
variant_name: str | None = None,
|
|
119
|
+
) -> int:
|
|
120
|
+
pedigree, messages = load_with_messages(input_path)
|
|
121
|
+
if family_filter:
|
|
122
|
+
if family_filter not in pedigree.families:
|
|
123
|
+
print(
|
|
124
|
+
f"Family '{family_filter}' was not found in the input.", file=sys.stderr
|
|
125
|
+
)
|
|
126
|
+
return 1
|
|
127
|
+
pedigree.families = {family_filter: pedigree.families[family_filter]}
|
|
128
|
+
if any(message.severity == "error" for message in messages):
|
|
129
|
+
print_validation_result(pedigree.source_path, messages)
|
|
130
|
+
return 1
|
|
131
|
+
|
|
132
|
+
summaries = summarize_pedigree(pedigree)
|
|
133
|
+
family_layouts = {
|
|
134
|
+
summary.family_id: build_family_layout(pedigree.families[summary.family_id])
|
|
135
|
+
for summary in summaries
|
|
136
|
+
}
|
|
137
|
+
ancestor_inbreeding_value = (
|
|
138
|
+
ancestor_inbreeding if ancestor_inbreeding is not None else 0.0
|
|
139
|
+
)
|
|
140
|
+
output = (
|
|
141
|
+
Path(output_path)
|
|
142
|
+
if output_path
|
|
143
|
+
else default_output_path(input_path, family_filter)
|
|
144
|
+
)
|
|
145
|
+
report_title = title or f"pedview report: {Path(input_path).stem}"
|
|
146
|
+
html = render_report(
|
|
147
|
+
pedigree=pedigree,
|
|
148
|
+
family_layouts=family_layouts,
|
|
149
|
+
family_summaries=summaries,
|
|
150
|
+
messages=[message for message in messages if message.severity == "warning"],
|
|
151
|
+
title=report_title,
|
|
152
|
+
ancestor_inbreeding=ancestor_inbreeding_value,
|
|
153
|
+
used_default_ancestor_inbreeding=ancestor_inbreeding is None,
|
|
154
|
+
variant_name=variant_name,
|
|
155
|
+
)
|
|
156
|
+
output.write_text(html, encoding="utf-8")
|
|
157
|
+
if ancestor_inbreeding is None:
|
|
158
|
+
print(
|
|
159
|
+
"Using Wright ancestor inbreeding coefficient f_a = 0.0 (default). "
|
|
160
|
+
"Pass --ancestor-inbreeding to override."
|
|
161
|
+
)
|
|
162
|
+
else:
|
|
163
|
+
print(
|
|
164
|
+
f"Using Wright ancestor inbreeding coefficient f_a = {ancestor_inbreeding_value:.4f}."
|
|
165
|
+
)
|
|
166
|
+
print(f"Wrote {output}")
|
|
167
|
+
return 0
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def load_with_messages(input_path: str):
|
|
171
|
+
try:
|
|
172
|
+
pedigree = parse_pedigree(input_path)
|
|
173
|
+
except PedigreeFormatError as exc:
|
|
174
|
+
print(f"[ERROR] {exc}", file=sys.stderr)
|
|
175
|
+
raise SystemExit(1) from exc
|
|
176
|
+
messages = [*pedigree.messages, *validate_pedigree(pedigree)]
|
|
177
|
+
return pedigree, messages
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def default_output_path(input_path: str, family_filter: str | None) -> Path:
|
|
181
|
+
input_file = Path(input_path)
|
|
182
|
+
suffix = f".{family_filter}" if family_filter else ""
|
|
183
|
+
return input_file.with_suffix(f"{suffix}.html")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def print_validation_result(source_path: str, messages) -> None:
|
|
187
|
+
print(f"Validation result for {source_path}")
|
|
188
|
+
if not messages:
|
|
189
|
+
print("No validation issues found.")
|
|
190
|
+
return
|
|
191
|
+
print_validation_messages(messages)
|
|
192
|
+
error_count = sum(message.severity == "error" for message in messages)
|
|
193
|
+
warning_count = sum(message.severity == "warning" for message in messages)
|
|
194
|
+
print(f"{error_count} error(s), {warning_count} warning(s)")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def print_validation_messages(messages) -> None:
|
|
198
|
+
for message in messages:
|
|
199
|
+
print(message.format_for_cli())
|