ukb-atlas 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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Computational Physiology at Simula Research Laboratory
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,146 @@
1
+ Metadata-Version: 2.1
2
+ Name: ukb_atlas
3
+ Version: 0.1.0
4
+ Summary: Generate meshes from UK Biobank data
5
+ Author-email: Henrik Finsberg <henriknf@simula.no>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 Computational Physiology at Simula Research Laboratory
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
+ Requires-Python: >=3.8
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: h5py
32
+ Requires-Dist: meshio
33
+ Requires-Dist: numpy
34
+ Provides-Extra: test
35
+ Requires-Dist: pytest; extra == "test"
36
+ Requires-Dist: pytest-cov; extra == "test"
37
+ Provides-Extra: dev
38
+ Requires-Dist: bump-my-version; extra == "dev"
39
+ Requires-Dist: pre-commit; extra == "dev"
40
+ Provides-Extra: docs
41
+ Requires-Dist: jupyter-book; extra == "docs"
42
+ Requires-Dist: jupytext; extra == "docs"
43
+ Requires-Dist: jupyter; extra == "docs"
44
+ Requires-Dist: pyvista[all]>=0.43.0; extra == "docs"
45
+ Requires-Dist: trame-vuetify; extra == "docs"
46
+ Requires-Dist: ipywidgets; extra == "docs"
47
+
48
+ [![DOI](https://zenodo.org/badge/846706235.svg)](https://doi.org/10.5281/zenodo.13927883)
49
+
50
+ # UK Biobank atlas - mesh generation
51
+
52
+ Generate meshes using the UK Biobank atlas (https://www.cardiacatlas.org/biventricular-modes/)
53
+
54
+ ## Install
55
+ Install with `pip`
56
+ ```
57
+ python3 -m pip install git+https://github.com/ComputationalPhysiology/ukb-atlas
58
+ ```
59
+ or with [`pipx`](https://github.com/pypa/pipx)
60
+ ```
61
+ pipx install git+https://github.com/ComputationalPhysiology/ukb-atlas.git
62
+ ```
63
+
64
+ ## Usage
65
+ ```
66
+ $ ukb-atlas --help
67
+ usage: ukb-atlas [-h] [-a] [-m MODE] [-s STD] [--mesh] [--char_length_max CHAR_LENGTH_MAX] [--char_length_min CHAR_LENGTH_MIN] outdir
68
+
69
+ Generate surfaces and meshes from UK Biobank atlas.
70
+
71
+ positional arguments:
72
+ outdir Directory to save the generated surfaces and meshes.
73
+
74
+ options:
75
+ -h, --help show this help message and exit
76
+ -a, --all Download the PCA atlas derived from all 4,329 subjects from the UK Biobank Study.
77
+ -m MODE, --mode MODE Mode to generate points from. If -1, generate points from the mean shape. If between 0 and the number of modes, generate points from the
78
+ specified mode. By default -1
79
+ -s STD, --std STD Standard deviation to scale the mode by, by default 1.5
80
+ --mesh Create gmsh mesh files from the generated surfaces.
81
+ --char_length_max CHAR_LENGTH_MAX
82
+ Maximum characteristic length of the mesh elements.
83
+ --char_length_min CHAR_LENGTH_MIN
84
+ Minimum characteristic length of the mesh elements.
85
+ ```
86
+ For example, by running the following command
87
+ ```
88
+ ukb-atlas data --mesh
89
+ ```
90
+ The tool will generate the following files
91
+ ```
92
+ data
93
+ ├── AV_ED.stl
94
+ ├── AV_ES.stl
95
+ ├── ED.msh
96
+ ├── EPI_ED.stl
97
+ ├── EPI_ES.stl
98
+ ├── ES.msh
99
+ ├── LV_ED.stl
100
+ ├── LV_ES.stl
101
+ ├── MV_ED.stl
102
+ ├── MV_ES.stl
103
+ ├── PV_ED.stl
104
+ ├── PV_ES.stl
105
+ ├── RVFW_ED.stl
106
+ ├── RVFW_ES.stl
107
+ ├── RV_ED.stl
108
+ ├── RV_ES.stl
109
+ ├── TV_ED.stl
110
+ ├── TV_ES.stl
111
+ ├── UKBRVLV.h5
112
+ └── parameters.json
113
+ ```
114
+ Which are surfaces for both the end diastolic (ED) and the end systolic (ES) shapes, the PCA atlas (`UKBRVLV.h5`) and the parameters used to generate the surfaces.
115
+
116
+ ## Citing
117
+ If you use this tool to create meshes please cite
118
+ ```
119
+ @software{Finsberg_fenics-beat_2024,
120
+ author = {Henrik Finsberg and Lisa R Pankewitz},
121
+ doi = {10.5281/zenodo.13927883},
122
+ title = {UK Biobank atlas - mesh generation},
123
+ url = {https://github.com/ComputationalPhysiology/ukb-atlas},
124
+ version = {0.1.0},
125
+ year = {2024}
126
+ }
127
+ ```
128
+
129
+ The templates used to generate the meshes are described where developed as part of the following publication (so please cite this paper if you use the templates)
130
+ ```
131
+ @article{PANKEWITZ2024103091,
132
+ title = {A universal biventricular coordinate system incorporating valve annuli: Validation in congenital heart disease},
133
+ journal = {Medical Image Analysis},
134
+ volume = {93},
135
+ pages = {103091},
136
+ year = {2024},
137
+ issn = {1361-8415},
138
+ doi = {https://doi.org/10.1016/j.media.2024.103091},
139
+ url = {https://www.sciencedirect.com/science/article/pii/S1361841524000161},
140
+ author = {Lisa R Pankewitz and Kristian G Hustad and Sachin Govil and James C Perry and Sanjeet Hegde and Renxiang Tang and Jeffrey H Omens and Alistair A Young and Andrew D McCulloch and Hermenegild J Arevalo},
141
+ keywords = {Cardiac geometry, Coordinates, Congenital Heart Disease, Mapping},
142
+ }
143
+ ```
144
+
145
+ ## License
146
+ MIT
@@ -0,0 +1,99 @@
1
+ [![DOI](https://zenodo.org/badge/846706235.svg)](https://doi.org/10.5281/zenodo.13927883)
2
+
3
+ # UK Biobank atlas - mesh generation
4
+
5
+ Generate meshes using the UK Biobank atlas (https://www.cardiacatlas.org/biventricular-modes/)
6
+
7
+ ## Install
8
+ Install with `pip`
9
+ ```
10
+ python3 -m pip install git+https://github.com/ComputationalPhysiology/ukb-atlas
11
+ ```
12
+ or with [`pipx`](https://github.com/pypa/pipx)
13
+ ```
14
+ pipx install git+https://github.com/ComputationalPhysiology/ukb-atlas.git
15
+ ```
16
+
17
+ ## Usage
18
+ ```
19
+ $ ukb-atlas --help
20
+ usage: ukb-atlas [-h] [-a] [-m MODE] [-s STD] [--mesh] [--char_length_max CHAR_LENGTH_MAX] [--char_length_min CHAR_LENGTH_MIN] outdir
21
+
22
+ Generate surfaces and meshes from UK Biobank atlas.
23
+
24
+ positional arguments:
25
+ outdir Directory to save the generated surfaces and meshes.
26
+
27
+ options:
28
+ -h, --help show this help message and exit
29
+ -a, --all Download the PCA atlas derived from all 4,329 subjects from the UK Biobank Study.
30
+ -m MODE, --mode MODE Mode to generate points from. If -1, generate points from the mean shape. If between 0 and the number of modes, generate points from the
31
+ specified mode. By default -1
32
+ -s STD, --std STD Standard deviation to scale the mode by, by default 1.5
33
+ --mesh Create gmsh mesh files from the generated surfaces.
34
+ --char_length_max CHAR_LENGTH_MAX
35
+ Maximum characteristic length of the mesh elements.
36
+ --char_length_min CHAR_LENGTH_MIN
37
+ Minimum characteristic length of the mesh elements.
38
+ ```
39
+ For example, by running the following command
40
+ ```
41
+ ukb-atlas data --mesh
42
+ ```
43
+ The tool will generate the following files
44
+ ```
45
+ data
46
+ ├── AV_ED.stl
47
+ ├── AV_ES.stl
48
+ ├── ED.msh
49
+ ├── EPI_ED.stl
50
+ ├── EPI_ES.stl
51
+ ├── ES.msh
52
+ ├── LV_ED.stl
53
+ ├── LV_ES.stl
54
+ ├── MV_ED.stl
55
+ ├── MV_ES.stl
56
+ ├── PV_ED.stl
57
+ ├── PV_ES.stl
58
+ ├── RVFW_ED.stl
59
+ ├── RVFW_ES.stl
60
+ ├── RV_ED.stl
61
+ ├── RV_ES.stl
62
+ ├── TV_ED.stl
63
+ ├── TV_ES.stl
64
+ ├── UKBRVLV.h5
65
+ └── parameters.json
66
+ ```
67
+ Which are surfaces for both the end diastolic (ED) and the end systolic (ES) shapes, the PCA atlas (`UKBRVLV.h5`) and the parameters used to generate the surfaces.
68
+
69
+ ## Citing
70
+ If you use this tool to create meshes please cite
71
+ ```
72
+ @software{Finsberg_fenics-beat_2024,
73
+ author = {Henrik Finsberg and Lisa R Pankewitz},
74
+ doi = {10.5281/zenodo.13927883},
75
+ title = {UK Biobank atlas - mesh generation},
76
+ url = {https://github.com/ComputationalPhysiology/ukb-atlas},
77
+ version = {0.1.0},
78
+ year = {2024}
79
+ }
80
+ ```
81
+
82
+ The templates used to generate the meshes are described where developed as part of the following publication (so please cite this paper if you use the templates)
83
+ ```
84
+ @article{PANKEWITZ2024103091,
85
+ title = {A universal biventricular coordinate system incorporating valve annuli: Validation in congenital heart disease},
86
+ journal = {Medical Image Analysis},
87
+ volume = {93},
88
+ pages = {103091},
89
+ year = {2024},
90
+ issn = {1361-8415},
91
+ doi = {https://doi.org/10.1016/j.media.2024.103091},
92
+ url = {https://www.sciencedirect.com/science/article/pii/S1361841524000161},
93
+ author = {Lisa R Pankewitz and Kristian G Hustad and Sachin Govil and James C Perry and Sanjeet Hegde and Renxiang Tang and Jeffrey H Omens and Alistair A Young and Andrew D McCulloch and Hermenegild J Arevalo},
94
+ keywords = {Cardiac geometry, Coordinates, Congenital Heart Disease, Mapping},
95
+ }
96
+ ```
97
+
98
+ ## License
99
+ MIT
@@ -0,0 +1,121 @@
1
+ [build-system] # Require setuptool version due to https://github.com/pypa/setuptools/issues/2938
2
+ requires = ["setuptools>=61.0.0", "wheel"]
3
+
4
+ [project]
5
+ name = "ukb_atlas"
6
+ version = "0.1.0"
7
+ description = "Generate meshes from UK Biobank data"
8
+ authors = [{name = "Henrik Finsberg", email = "henriknf@simula.no"}]
9
+ license = {file = "LICENSE"}
10
+ requires-python = ">= 3.8"
11
+ readme = "README.md"
12
+ dependencies = [
13
+ "h5py", "meshio", "numpy"
14
+ ]
15
+
16
+ [project.scripts]
17
+ ukb-atlas = "ukb.cli:main"
18
+
19
+ [project.optional-dependencies]
20
+ test = [
21
+ "pytest",
22
+ "pytest-cov",
23
+ ]
24
+ dev = [
25
+ "bump-my-version",
26
+ "pre-commit",
27
+ ]
28
+ docs = [
29
+ "jupyter-book",
30
+ "jupytext",
31
+ "jupyter",
32
+ "pyvista[all]>=0.43.0",
33
+ "trame-vuetify",
34
+ "ipywidgets",
35
+ ]
36
+
37
+
38
+ [tool.setuptools.packages.find]
39
+ where = ["src"]
40
+
41
+ [tool.setuptools.package-data]
42
+ ukb = ["connectivity.txt"]
43
+
44
+ [tool.aliases]
45
+ test = "pytest"
46
+
47
+ [tool.pytest.ini_options]
48
+ testpaths = ["tests"]
49
+
50
+
51
+ [tool.mypy]
52
+ files = ["src/ukb", "tests"]
53
+ ignore_missing_imports = true
54
+
55
+
56
+ [tool.ruff]
57
+
58
+ # Exclude a variety of commonly ignored directories.
59
+ exclude = [
60
+ "examples",
61
+ ".bzr",
62
+ ".direnv",
63
+ ".eggs",
64
+ ".git",
65
+ ".hg",
66
+ ".mypy_cache",
67
+ ".nox",
68
+ ".pants.d",
69
+ ".pytype",
70
+ ".ruff_cache",
71
+ ".svn",
72
+ ".tox",
73
+ ".venv",
74
+ "__pypackages__",
75
+ "_build",
76
+ "buck-out",
77
+ "build",
78
+ "dist",
79
+ "node_modules",
80
+ "venv",
81
+ ]
82
+
83
+ # Same as Black.
84
+ line-length = 100
85
+
86
+ # Assume Python 3.10.
87
+ target-version = "py310"
88
+
89
+ [tool.ruff.lint]
90
+ # Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
91
+ select = ["E", "F"]
92
+ ignore = ["E402", "E741", "E743", "E731"]
93
+
94
+ # Allow autofix for all enabled rules (when `--fix`) is provided.
95
+ fixable = ["A", "B", "C", "D", "E", "F"]
96
+ unfixable = []
97
+
98
+ # Allow unused variables when underscore-prefixed.
99
+ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
100
+
101
+
102
+ [tool.ruff.lint.mccabe]
103
+ # Unlike Flake8, default to a complexity level of 10.
104
+ max-complexity = 10
105
+
106
+
107
+ [tool.bumpversion]
108
+ allow_dirty = false
109
+ commit = true
110
+ message = "Bump version: {current_version} → {new_version}"
111
+ tag = true
112
+ sign_tags = false
113
+ tag_name = "v{new_version}"
114
+ tag_message = "Bump version: {current_version} → {new_version}"
115
+ current_version = "0.1.0"
116
+
117
+
118
+ [[tool.bumpversion.files]]
119
+ filename = "pyproject.toml"
120
+ search = 'version = "{current_version}"'
121
+ replace = 'version = "{new_version}"'
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,4 @@
1
+ from .cli import main
2
+
3
+ if __name__ == "__main__":
4
+ raise SystemExit(main())
@@ -0,0 +1,113 @@
1
+ from typing import NamedTuple
2
+ from pathlib import Path
3
+ import logging
4
+ import h5py
5
+ import numpy as np
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+
10
+ class Points(NamedTuple):
11
+ ED: np.ndarray
12
+ ES: np.ndarray
13
+
14
+
15
+ unwanted_nodes = (5630, 5655, 5696, 5729)
16
+
17
+
18
+ def download_atlas(outdir: Path, all: bool = True) -> Path:
19
+ """Download the UK Biobank atlas from the Cardiac Atlas Project.
20
+
21
+ Parameters
22
+ ----------
23
+ outdir : Path
24
+ Directory to download the atlas to.
25
+ all : bool, optional
26
+ If true, download the PCA atlas derived from all 4,329 subjects
27
+ from the UK Biobank Study. If false, downlaod PCA atlas derived
28
+ from 630 healthy reference subjects from the UK Biobank Study
29
+ (see [1]_) by default False
30
+
31
+ Returns
32
+ -------
33
+ Path
34
+ Path to the downloaded file.
35
+
36
+ References
37
+ ----------
38
+ .. [1] Petersen, Steffen E., et al. "Reference ranges for cardiac
39
+ structure and function using cardiovascular magnetic resonance
40
+ (CMR) in Caucasians from the UK Biobank population cohort.
41
+ " Journal of cardiovascular magnetic resonance 19.1 (2016): 18.
42
+
43
+ """
44
+ from urllib.request import urlretrieve
45
+ import zipfile
46
+
47
+ outdir = Path(outdir)
48
+ outdir.mkdir(exist_ok=True)
49
+
50
+ if all:
51
+ url = "https://www.cardiacatlas.org/share/download.php?id=59&token=CUfi3eWV41LrIL6ZtlMf7bvHEkiiWpVu&download"
52
+ path = outdir / "UKBRVLV_ALL.zip"
53
+ else:
54
+ url = "https://www.cardiacatlas.org/share/download.php?id=60&token=AR3JSoaxJ9Ev9n8QAkvV4BHJUniyttqm&download"
55
+
56
+ path = outdir / "UKBRVLV.zip"
57
+
58
+ if not path.with_suffix(".h5").exists():
59
+ logger.info(f"Downloading {url} to {path}. This may take a while.")
60
+ urlretrieve(url, path)
61
+ with zipfile.ZipFile(path, "r") as zip_ref:
62
+ zip_ref.extractall(outdir)
63
+ path.unlink()
64
+
65
+ logger.info("Done downloading.")
66
+
67
+ return path.with_suffix(".h5")
68
+
69
+
70
+ def generate_points(filename: Path, mode: int = -1, std: float = 1.5) -> Points:
71
+ """Generate points from the UK Biobank atlas.
72
+
73
+ Parameters
74
+ ----------
75
+ filename : Path
76
+ Path to the UK Biobank atlas file.
77
+ mode : int, optional
78
+ Mode to generate points from. If -1, generate points from the mean
79
+ shape. If between 0 and the number of modes, generate points from
80
+ the specified mode. By default -1
81
+ std : float, optional
82
+ Standard deviation to scale the mode by, by default 1.5
83
+
84
+ Returns
85
+ -------
86
+ Points
87
+ Named tuple containing the end-diastolic (ED) and end-systolic (ES)
88
+ points.
89
+ """
90
+ logger.info(f"Generating points from {filename} using mode {mode} and std {std}")
91
+ with h5py.File(filename, "r") as hdf:
92
+ mu = np.transpose(hdf["MU"])
93
+ if mode == -1:
94
+ S = mu
95
+ else:
96
+ if mode < 0 or mode >= hdf["COEFF"].shape[0]:
97
+ raise ValueError(
98
+ f"Mode {mode} is out of bounds. Needs to be between "
99
+ f"0 and {hdf['COEFF'].shape[0] - 1}"
100
+ )
101
+ eigenvalue = hdf["LATENT"][0, mode]
102
+ eigenvector = hdf["COEFF"][mode, :]
103
+ S = np.transpose(hdf["MU"]) + (std * np.sqrt(eigenvalue) * eigenvector)
104
+
105
+ # First half is ED and second half is ES
106
+ N = S.shape[1] // 2
107
+ ed = np.reshape(S[0, :N], (-1, 3))
108
+ es = np.reshape(S[0, N:], (-1, 3))
109
+
110
+ return Points(
111
+ ED=np.delete(ed, unwanted_nodes, axis=0),
112
+ ES=np.delete(es, unwanted_nodes, axis=0),
113
+ )
@@ -0,0 +1,133 @@
1
+ from __future__ import annotations
2
+ import typing
3
+ import json
4
+ import hashlib
5
+ from pathlib import Path
6
+ import logging
7
+ import argparse
8
+
9
+ from . import atlas, surface, mesh
10
+
11
+
12
+ def get_parser() -> argparse.ArgumentParser:
13
+ parser = argparse.ArgumentParser(
14
+ description="Generate surfaces and meshes from UK Biobank atlas."
15
+ )
16
+ parser.add_argument(
17
+ "outdir",
18
+ type=Path,
19
+ help="Directory to save the generated surfaces and meshes.",
20
+ )
21
+ parser.add_argument(
22
+ "--subdir",
23
+ type=Path,
24
+ default=None,
25
+ help="Directory to save the generated surfaces and meshes.",
26
+ )
27
+ parser.add_argument(
28
+ "-a",
29
+ "--all",
30
+ action="store_true",
31
+ help="Download the PCA atlas derived from all 4,329 subjects from the UK Biobank Study.",
32
+ )
33
+ parser.add_argument(
34
+ "-m",
35
+ "--mode",
36
+ type=int,
37
+ default=-1,
38
+ help=(
39
+ "Mode to generate points from. If -1, generate points from the mean "
40
+ "shape. If between 0 and the number of modes, generate points from "
41
+ "the specified mode. By default -1"
42
+ ),
43
+ )
44
+ parser.add_argument(
45
+ "-s",
46
+ "--std",
47
+ type=float,
48
+ default=1.5,
49
+ help="Standard deviation to scale the mode by, by default 1.5",
50
+ )
51
+ parser.add_argument(
52
+ "--mesh",
53
+ action="store_true",
54
+ help="Create gmsh mesh files from the generated surfaces.",
55
+ )
56
+ parser.add_argument(
57
+ "--char_length_max",
58
+ type=float,
59
+ default=5.0,
60
+ help="Maximum characteristic length of the mesh elements.",
61
+ )
62
+ parser.add_argument(
63
+ "--char_length_min",
64
+ type=float,
65
+ default=5.0,
66
+ help="Minimum characteristic length of the mesh elements.",
67
+ )
68
+ parser.add_argument(
69
+ "-v",
70
+ "--verbose",
71
+ action="store_true",
72
+ help="Print verbose output.",
73
+ )
74
+
75
+ return parser
76
+
77
+
78
+ def main(argv: typing.Sequence[str] | None = None) -> int:
79
+ parser = get_parser()
80
+ args = vars(parser.parse_args(argv))
81
+
82
+ logging.basicConfig(level=logging.DEBUG if args["verbose"] else logging.INFO)
83
+
84
+ main_outdir = args["outdir"]
85
+ main_outdir.mkdir(exist_ok=True, parents=True)
86
+
87
+ args_json = json.dumps(
88
+ args,
89
+ indent=4,
90
+ sort_keys=True,
91
+ default=lambda o: str(o),
92
+ )
93
+
94
+ if args["subdir"]:
95
+ outdir = main_outdir / args["subdir"]
96
+ else:
97
+ unique_id = hashlib.md5(args_json.encode()).hexdigest()
98
+ outdir = main_outdir / unique_id
99
+ outdir.mkdir(exist_ok=True, parents=True)
100
+
101
+ (outdir / "parameters.json").write_text(args_json)
102
+
103
+ filename = atlas.download_atlas(main_outdir, args["all"])
104
+
105
+ points = atlas.generate_points(filename=filename, mode=args["mode"], std=args["std"])
106
+
107
+ for case in ["ED", "ES"]:
108
+ epi = surface.get_epi_mesh(
109
+ points=getattr(points, case),
110
+ )
111
+ epi.write(str(outdir / f"EPI_{case}.stl"))
112
+
113
+ for valve in ["MV", "AV", "TV", "PV"]:
114
+ valve_mesh = surface.get_valve_mesh(surface_name=valve, points=getattr(points, case))
115
+ valve_mesh.write(str(outdir / f"{valve}_{case}.stl"))
116
+
117
+ for chamber in ["LV", "RV", "RVFW"]:
118
+ chamber_mesh = surface.get_chamber_mesh(
119
+ surface_name=chamber,
120
+ points=getattr(points, case),
121
+ )
122
+ chamber_mesh.write(str(outdir / f"{chamber}_{case}.stl"))
123
+
124
+ if args["mesh"]:
125
+ mesh.create_mesh(
126
+ outdir=outdir,
127
+ char_length_max=args["char_length_max"],
128
+ char_length_min=args["char_length_min"],
129
+ case=case,
130
+ verbose=args["verbose"],
131
+ )
132
+
133
+ return 0