cardiac-geometriesx 0.0.1__tar.gz → 0.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.

Potentially problematic release.


This version of cardiac-geometriesx might be problematic. Click here for more details.

Files changed (22) hide show
  1. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/PKG-INFO +1 -3
  2. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/pyproject.toml +2 -4
  3. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometries/mesh.py +5 -5
  4. cardiac_geometriesx-0.0.3/src/cardiac_geometries/utils.py +123 -0
  5. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometriesx.egg-info/PKG-INFO +1 -3
  6. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometriesx.egg-info/requires.txt +0 -2
  7. cardiac_geometriesx-0.0.1/src/cardiac_geometries/utils.py +0 -173
  8. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/README.md +0 -0
  9. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/setup.cfg +0 -0
  10. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometries/__init__.py +0 -0
  11. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometries/cli.py +0 -0
  12. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometries/fibers/__init__.py +0 -0
  13. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometries/fibers/lv_ellipsoid.py +0 -0
  14. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometries/fibers/slab.py +0 -0
  15. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometries/fibers/utils.py +0 -0
  16. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometries/geometry.py +0 -0
  17. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometriesx.egg-info/SOURCES.txt +0 -0
  18. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometriesx.egg-info/dependency_links.txt +0 -0
  19. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometriesx.egg-info/entry_points.txt +0 -0
  20. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometriesx.egg-info/not-zip-safe +0 -0
  21. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/src/cardiac_geometriesx.egg-info/top_level.txt +0 -0
  22. {cardiac_geometriesx-0.0.1 → cardiac_geometriesx-0.0.3}/tests/test_cli.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cardiac-geometriesx
3
- Version: 0.0.1
3
+ Version: 0.0.3
4
4
  Summary: A python library for cardiac geometries
5
5
  Author-email: Henrik Finsberg <henriknf@simula.no>
6
6
  License: MIT
@@ -12,8 +12,6 @@ Classifier: Programming Language :: Python :: 3 :: Only
12
12
  Requires-Python: >=3.8
13
13
  Description-Content-Type: text/markdown
14
14
  Requires-Dist: fenics-dolfinx>=0.8.0
15
- Requires-Dist: meshio
16
- Requires-Dist: h5py
17
15
  Requires-Dist: structlog
18
16
  Requires-Dist: cardiac-geometries-core
19
17
  Requires-Dist: rich-click
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cardiac-geometriesx"
7
- version = "0.0.1"
7
+ version = "0.0.3"
8
8
  description = "A python library for cardiac geometries"
9
9
  authors = [{name = "Henrik Finsberg", email = "henriknf@simula.no"}]
10
10
  license = {text = "MIT"}
@@ -18,8 +18,6 @@ urls = {Homepage = "https://github.com/finsberg/cardiac-geometriesx" }
18
18
  requires-python = ">=3.8"
19
19
  dependencies = [
20
20
  "fenics-dolfinx>=0.8.0",
21
- "meshio",
22
- "h5py",
23
21
  "structlog",
24
22
  "cardiac-geometries-core",
25
23
  "rich-click",
@@ -136,7 +134,7 @@ tag = true
136
134
  sign_tags = false
137
135
  tag_name = "v{new_version}"
138
136
  tag_message = "Bump version: {current_version} → {new_version}"
139
- current_version = "0.0.1"
137
+ current_version = "0.0.3"
140
138
 
141
139
 
142
140
  [[tool.bumpversion.files]]
@@ -166,7 +166,7 @@ def biv_ellipsoid(
166
166
  c_epi_rv=c_epi_rv,
167
167
  )
168
168
  comm.barrier()
169
- geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
169
+ geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name)
170
170
 
171
171
  if comm.rank == 0:
172
172
  with open(outdir / "markers.json", "w") as f:
@@ -367,7 +367,7 @@ def biv_ellipsoid_torso(
367
367
  )
368
368
  comm.barrier()
369
369
 
370
- geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
370
+ geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name)
371
371
 
372
372
  if comm.rank == 0:
373
373
  with open(outdir / "markers.json", "w") as f:
@@ -500,7 +500,7 @@ def lv_ellipsoid(
500
500
  )
501
501
  comm.barrier()
502
502
 
503
- geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
503
+ geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name)
504
504
 
505
505
  # if aha:
506
506
  # from .aha import lv_aha
@@ -618,7 +618,7 @@ def slab(
618
618
  cgc.slab(mesh_name=mesh_name.as_posix(), lx=lx, ly=ly, lz=lz, dx=dx)
619
619
  comm.barrier()
620
620
 
621
- geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
621
+ geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name)
622
622
 
623
623
  if comm.rank == 0:
624
624
  with open(outdir / "markers.json", "w") as f:
@@ -716,7 +716,7 @@ def slab_in_bath(
716
716
  dx=dx,
717
717
  )
718
718
 
719
- geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name, unlink=False)
719
+ geometry = utils.gmsh2dolfin(comm=comm, msh_file=mesh_name)
720
720
 
721
721
  if comm.rank == 0:
722
722
  with open(outdir / "markers.json", "w") as f:
@@ -0,0 +1,123 @@
1
+ from pathlib import Path
2
+ import tempfile
3
+ from typing import NamedTuple, Iterable
4
+ from enum import Enum
5
+
6
+ import numpy as np
7
+ from mpi4py import MPI
8
+ from structlog import get_logger
9
+ import basix
10
+ import dolfinx
11
+
12
+
13
+ logger = get_logger()
14
+
15
+
16
+ def element2array(el: basix.finite_element.FiniteElement) -> np.ndarray:
17
+ return np.array(
18
+ [int(el.family), int(el.cell_type), int(el.degree), int(el.discontinuous)],
19
+ dtype=np.uint8,
20
+ )
21
+
22
+
23
+ def number2Enum(num: int, enum: Iterable) -> Enum:
24
+ for e in enum:
25
+ if int(e) == num:
26
+ return e
27
+ raise ValueError(f"Invalid value {num} for enum {enum}")
28
+
29
+
30
+ def array2element(arr: np.ndarray) -> basix.finite_element.FiniteElement:
31
+ family = number2Enum(arr[0], basix.ElementFamily)
32
+ cell_type = number2Enum(arr[1], basix.CellType)
33
+ degree = int(arr[2])
34
+ discontinuous = bool(arr[3])
35
+ # TODO: Shape is hardcoded to (3,) for now, but this should also be stored
36
+ return basix.ufl.element(
37
+ family=family,
38
+ cell=cell_type,
39
+ degree=degree,
40
+ discontinuous=discontinuous,
41
+ shape=(3,),
42
+ )
43
+
44
+
45
+ def handle_mesh_name(mesh_name: str = "") -> Path:
46
+ if mesh_name == "":
47
+ fd, mesh_name = tempfile.mkstemp(suffix=".msh")
48
+ return Path(mesh_name).with_suffix(".msh")
49
+
50
+
51
+ def json_serial(obj):
52
+ if isinstance(obj, (np.ndarray)):
53
+ return obj.tolist()
54
+ else:
55
+ try:
56
+ return str(obj)
57
+ except Exception:
58
+ raise TypeError("Type %s not serializable" % type(obj))
59
+
60
+
61
+ class GMshGeometry(NamedTuple):
62
+ mesh: dolfinx.mesh.Mesh
63
+ cfun: dolfinx.mesh.MeshTags | None
64
+ ffun: dolfinx.mesh.MeshTags | None
65
+ efun: dolfinx.mesh.MeshTags | None
66
+ vfun: dolfinx.mesh.MeshTags | None
67
+ markers: dict[str, tuple[int, int]]
68
+
69
+
70
+ def read_ffun(mesh, filename: str | Path) -> dolfinx.mesh.MeshTags | None:
71
+ mesh.topology.create_connectivity(mesh.topology.dim - 1, mesh.topology.dim)
72
+ with dolfinx.io.XDMFFile(mesh.comm, filename, "r") as xdmf:
73
+ ffun = xdmf.read_meshtags(mesh, name="Facet tags")
74
+
75
+ return ffun
76
+
77
+
78
+ def read_mesh(comm, filename: str | Path) -> tuple[dolfinx.mesh.Mesh, dolfinx.mesh.MeshTags | None]:
79
+ with dolfinx.io.XDMFFile(comm, filename, "r") as xdmf:
80
+ mesh = xdmf.read_mesh(name="Mesh")
81
+ cfun = xdmf.read_meshtags(mesh, name="Cell tags")
82
+ return mesh, cfun
83
+
84
+
85
+ def gmsh2dolfin(comm: MPI.Intracomm, msh_file, rank: int = 0) -> GMshGeometry:
86
+ logger.debug(f"Convert file {msh_file} to dolfin")
87
+ outdir = Path(msh_file).parent
88
+
89
+ import gmsh
90
+
91
+ # We could make this work in parallel in the future
92
+
93
+ if comm.rank == rank:
94
+ gmsh.initialize()
95
+ gmsh.model.add("Mesh from file")
96
+ gmsh.merge(str(msh_file))
97
+ mesh, ct, ft = dolfinx.io.gmshio.model_to_mesh(gmsh.model, comm, 0)
98
+ markers = {gmsh.model.getPhysicalName(*v): v for v in gmsh.model.getPhysicalGroups()}
99
+ gmsh.finalize()
100
+ else:
101
+ mesh, ct, ft = dolfinx.io.gmshio.model_to_mesh(gmsh.model, comm, 0)
102
+ markers = {}
103
+ mesh.name = "Mesh"
104
+ ct.name = "Cell tags"
105
+ ft.name = "Facet tags"
106
+
107
+ markers = comm.bcast(markers, root=rank)
108
+
109
+ # Save tags to xdmf
110
+ with dolfinx.io.XDMFFile(comm, outdir / "mesh.xdmf", "w") as xdmf:
111
+ xdmf.write_mesh(mesh)
112
+ mesh.topology.create_connectivity(2, 3)
113
+ xdmf.write_meshtags(
114
+ ct, mesh.geometry, geometry_xpath=f"/Xdmf/Domain/Grid[@Name='{mesh.name}']/Geometry"
115
+ )
116
+ xdmf.write_meshtags(
117
+ ft, mesh.geometry, geometry_xpath=f"/Xdmf/Domain/Grid[@Name='{mesh.name}']/Geometry"
118
+ )
119
+
120
+ vfun = None
121
+ efun = None
122
+
123
+ return GMshGeometry(mesh, ct, ft, efun, vfun, markers)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cardiac-geometriesx
3
- Version: 0.0.1
3
+ Version: 0.0.3
4
4
  Summary: A python library for cardiac geometries
5
5
  Author-email: Henrik Finsberg <henriknf@simula.no>
6
6
  License: MIT
@@ -12,8 +12,6 @@ Classifier: Programming Language :: Python :: 3 :: Only
12
12
  Requires-Python: >=3.8
13
13
  Description-Content-Type: text/markdown
14
14
  Requires-Dist: fenics-dolfinx>=0.8.0
15
- Requires-Dist: meshio
16
- Requires-Dist: h5py
17
15
  Requires-Dist: structlog
18
16
  Requires-Dist: cardiac-geometries-core
19
17
  Requires-Dist: rich-click
@@ -1,6 +1,4 @@
1
1
  fenics-dolfinx>=0.8.0
2
- meshio
3
- h5py
4
2
  structlog
5
3
  cardiac-geometries-core
6
4
  rich-click
@@ -1,173 +0,0 @@
1
- from pathlib import Path
2
- import tempfile
3
- from typing import NamedTuple, Iterable
4
- from enum import Enum
5
-
6
- import numpy as np
7
- from mpi4py import MPI
8
- from structlog import get_logger
9
- import basix
10
- import dolfinx
11
- import meshio
12
-
13
-
14
- logger = get_logger()
15
-
16
-
17
- def element2array(el: basix.finite_element.FiniteElement) -> np.ndarray:
18
- return np.array(
19
- [int(el.family), int(el.cell_type), int(el.degree), int(el.discontinuous)],
20
- dtype=np.uint8,
21
- )
22
-
23
-
24
- def number2Enum(num: int, enum: Iterable) -> Enum:
25
- for e in enum:
26
- if int(e) == num:
27
- return e
28
- raise ValueError(f"Invalid value {num} for enum {enum}")
29
-
30
-
31
- def array2element(arr: np.ndarray) -> basix.finite_element.FiniteElement:
32
- family = number2Enum(arr[0], basix.ElementFamily)
33
- cell_type = number2Enum(arr[1], basix.CellType)
34
- degree = int(arr[2])
35
- discontinuous = bool(arr[3])
36
- # TODO: Shape is hardcoded to (3,) for now, but this should also be stored
37
- return basix.ufl.element(
38
- family=family,
39
- cell=cell_type,
40
- degree=degree,
41
- discontinuous=discontinuous,
42
- shape=(3,),
43
- )
44
-
45
-
46
- def handle_mesh_name(mesh_name: str = "") -> Path:
47
- if mesh_name == "":
48
- fd, mesh_name = tempfile.mkstemp(suffix=".msh")
49
- return Path(mesh_name).with_suffix(".msh")
50
-
51
-
52
- def json_serial(obj):
53
- if isinstance(obj, (np.ndarray)):
54
- return obj.tolist()
55
- else:
56
- try:
57
- return str(obj)
58
- except Exception:
59
- raise TypeError("Type %s not serializable" % type(obj))
60
-
61
-
62
- class GMshGeometry(NamedTuple):
63
- mesh: dolfinx.mesh.Mesh
64
- cfun: dolfinx.mesh.MeshTags | None
65
- ffun: dolfinx.mesh.MeshTags | None
66
- efun: dolfinx.mesh.MeshTags | None
67
- vfun: dolfinx.mesh.MeshTags | None
68
- markers: dict[str, tuple[int, int]]
69
-
70
-
71
- def create_mesh(mesh, cell_type):
72
- # From http://jsdokken.com/converted_files/tutorial_pygmsh.html
73
- cells = mesh.get_cells_type(cell_type)
74
- if cells.size == 0:
75
- return None
76
-
77
- cells = mesh.get_cells_type(cell_type)
78
- cell_data = mesh.get_cell_data("gmsh:physical", cell_type)
79
- out_mesh = meshio.Mesh(
80
- points=mesh.points,
81
- cells={cell_type: cells},
82
- cell_data={"name_to_read": [cell_data]},
83
- )
84
- return out_mesh
85
-
86
-
87
- def read_ffun(mesh, filename: str | Path) -> dolfinx.mesh.MeshTags | None:
88
- mesh.topology.create_connectivity(mesh.topology.dim - 1, mesh.topology.dim)
89
- with dolfinx.io.XDMFFile(mesh.comm, filename, "r") as xdmf:
90
- ffun = xdmf.read_meshtags(mesh, name="Grid")
91
- ffun.name = "Facet tags"
92
- return ffun
93
-
94
-
95
- def read_mesh(comm, filename: str | Path) -> tuple[dolfinx.mesh.Mesh, dolfinx.mesh.MeshTags | None]:
96
- with dolfinx.io.XDMFFile(comm, filename, "r") as xdmf:
97
- mesh = xdmf.read_mesh(name="Grid")
98
- cfun = xdmf.read_meshtags(mesh, name="Grid")
99
- return mesh, cfun
100
-
101
-
102
- def gmsh2dolfin(comm: MPI.Intracomm, msh_file, unlink: bool = False) -> GMshGeometry:
103
- logger.debug(f"Convert file {msh_file} to dolfin")
104
- outdir = Path(msh_file).parent
105
-
106
- vertex_mesh_name = outdir / "vertex_mesh.xdmf"
107
- line_mesh_name = outdir / "line_mesh.xdmf"
108
- triangle_mesh_name = outdir / "triangle_mesh.xdmf"
109
- tetra_mesh_name = outdir / "mesh.xdmf"
110
-
111
- if comm.rank == 0:
112
- msh = meshio.gmsh.read(msh_file)
113
- vertex_mesh = create_mesh(msh, "vertex")
114
- line_mesh = create_mesh(msh, "line")
115
- triangle_mesh = create_mesh(msh, "triangle")
116
- tetra_mesh = create_mesh(msh, "tetra")
117
-
118
- if vertex_mesh is not None:
119
- meshio.write(vertex_mesh_name, vertex_mesh)
120
-
121
- if line_mesh is not None:
122
- meshio.write(line_mesh_name, line_mesh)
123
-
124
- if triangle_mesh is not None:
125
- meshio.write(triangle_mesh_name, triangle_mesh)
126
-
127
- if tetra_mesh is not None:
128
- meshio.write(
129
- tetra_mesh_name,
130
- tetra_mesh,
131
- )
132
- markers = msh.field_data
133
- else:
134
- markers = {}
135
- # Broadcast markers
136
- markers = comm.bcast(markers, root=0)
137
- comm.barrier()
138
-
139
- mesh, cfun = read_mesh(comm, tetra_mesh_name)
140
-
141
- if triangle_mesh_name.is_file():
142
- ffun = read_ffun(mesh, triangle_mesh_name)
143
- else:
144
- ffun = None
145
-
146
- if line_mesh_name.is_file():
147
- mesh.topology.create_connectivity(mesh.topology.dim - 2, mesh.topology.dim)
148
- with dolfinx.io.XDMFFile(comm, line_mesh_name, "r") as xdmf:
149
- efun = xdmf.read_meshtags(mesh, name="Grid")
150
- else:
151
- efun = None
152
-
153
- if vertex_mesh_name.is_file():
154
- mesh.topology.create_connectivity(mesh.topology.dim - 3, mesh.topology.dim)
155
- with dolfinx.io.XDMFFile(comm, vertex_mesh_name, "r") as xdmf:
156
- vfun = xdmf.read_meshtags(mesh, name="Grid")
157
- else:
158
- vfun = None
159
-
160
- if unlink:
161
- # Wait for all processes to finish reading
162
- comm.barrier()
163
- if comm.rank == 0:
164
- vertex_mesh_name.unlink(missing_ok=True)
165
- line_mesh_name.unlink(missing_ok=True)
166
- triangle_mesh_name.unlink(missing_ok=True)
167
- tetra_mesh_name.unlink(missing_ok=True)
168
- vertex_mesh_name.with_suffix(".h5").unlink(missing_ok=True)
169
- line_mesh_name.with_suffix(".h5").unlink(missing_ok=True)
170
- triangle_mesh_name.with_suffix(".h5").unlink(missing_ok=True)
171
- tetra_mesh_name.with_suffix(".h5").unlink(missing_ok=True)
172
-
173
- return GMshGeometry(mesh, cfun, ffun, efun, vfun, markers)