cardiac-geometriesx 0.3.0__py3-none-any.whl → 0.4.0__py3-none-any.whl

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.

@@ -1,3 +1,4 @@
1
+ import json
1
2
  from pathlib import Path
2
3
  from typing import NamedTuple, Sequence
3
4
 
@@ -19,16 +20,21 @@ class Microstructure(NamedTuple):
19
20
  def save_microstructure(
20
21
  mesh: dolfinx.mesh.Mesh, functions: Sequence[dolfinx.fem.Function], outdir: str | Path
21
22
  ) -> None:
22
- from ..utils import element2array
23
+ from ..utils import create_xdmf_pointcloud, element2array
23
24
 
25
+ if len(functions) == 0:
26
+ return
24
27
  # Save for paraview visualization
25
- try:
26
- with dolfinx.io.VTXWriter(
27
- mesh.comm, Path(outdir) / "microstructure-viz.bp", functions, engine="BP4"
28
- ) as file:
29
- file.write(0.0)
30
- except RuntimeError:
31
- pass
28
+ if functions[0].function_space.ufl_element().family_name == "quadrature":
29
+ create_xdmf_pointcloud(us=functions, filename=Path(outdir) / "microstructure-viz.xdmf")
30
+ else:
31
+ try:
32
+ with dolfinx.io.VTXWriter(
33
+ mesh.comm, Path(outdir) / "microstructure-viz.bp", functions, engine="BP4"
34
+ ) as file:
35
+ file.write(0.0)
36
+ except RuntimeError:
37
+ pass
32
38
 
33
39
  # Save with proper function space
34
40
  filename = Path(outdir) / "microstructure.bp"
@@ -43,6 +49,16 @@ def save_microstructure(
43
49
  attributes=attributes,
44
50
  )
45
51
 
52
+ def json_serial(obj):
53
+ if isinstance(obj, (np.ndarray)):
54
+ return obj.tolist()
55
+ raise TypeError("Type %s not serializable" % type(obj))
56
+
57
+ if mesh.comm.rank == 0:
58
+ (Path(outdir) / "microstructure.json").write_text(
59
+ json.dumps(attributes, indent=4, default=json_serial)
60
+ )
61
+
46
62
 
47
63
  def normalize(u):
48
64
  return u / np.linalg.norm(u, axis=0)
@@ -147,13 +147,22 @@ class Geometry:
147
147
  else:
148
148
  markers = {}
149
149
 
150
+ if (folder / "microstructure.json").exists():
151
+ if comm.rank == 0:
152
+ microstructure = json.loads((folder / "microstructure.json").read_text())
153
+ else:
154
+ microstructure = {}
155
+ microstructure = comm.bcast(microstructure, root=0)
156
+ else:
157
+ microstructure = {}
158
+
150
159
  functions = {}
151
160
  microstructure_path = folder / "microstructure.bp"
152
161
  if microstructure_path.exists():
153
- function_space = adios4dolfinx.read_attributes(
154
- comm=MPI.COMM_WORLD, filename=microstructure_path, name="function_space"
155
- )
156
- for name, el in function_space.items():
162
+ # function_space = adios4dolfinx.read_attributes(
163
+ # comm=MPI.COMM_WORLD, filename=microstructure_path, name="function_space"
164
+ # )
165
+ for name, el in microstructure.items():
157
166
  element = utils.array2element(el)
158
167
  V = dolfinx.fem.functionspace(mesh, element)
159
168
  f = dolfinx.fem.Function(V, name=name)
@@ -44,6 +44,7 @@ def biv_ellipsoid(
44
44
  fiber_angle_epi: float = -60,
45
45
  fiber_space: str = "P_1",
46
46
  verbose: bool = False,
47
+ comm: MPI.Comm = MPI.COMM_WORLD,
47
48
  ) -> Geometry:
48
49
  """Create BiV ellipsoidal geometry
49
50
 
@@ -99,6 +100,8 @@ def biv_ellipsoid(
99
100
  Function space for fibers of the form family_degree, by default "P_1"
100
101
  verbose : bool, optional
101
102
  If True print information from gmsh, by default False
103
+ comm : MPI.Comm, optional
104
+ MPI communicator, by default MPI.COMM_WORLD
102
105
 
103
106
  Returns
104
107
  -------
@@ -106,7 +109,6 @@ def biv_ellipsoid(
106
109
  A Geometry with the mesh, markers, markers functions and fibers.
107
110
 
108
111
  """
109
- comm = MPI.COMM_WORLD
110
112
  outdir = Path(outdir)
111
113
  mesh_name = outdir / "biv_ellipsoid.msh"
112
114
  if comm.rank == 0:
@@ -202,17 +204,6 @@ def biv_ellipsoid(
202
204
  save_microstructure(
203
205
  mesh=geometry.mesh, functions=(system.f0, system.s0, system.n0), outdir=outdir
204
206
  )
205
- # from .fibers._biv_ellipsoid import create_biv_fibers
206
-
207
- # create_biv_fibers(
208
- # mesh=geometry.mesh,
209
- # ffun=geometry.marker_functions.ffun,
210
- # markers=geometry.markers,
211
- # fiber_space=fiber_space,
212
- # alpha_endo=fiber_angle_endo,
213
- # alpha_epi=fiber_angle_epi,
214
- # outdir=outdir,
215
- # )
216
207
 
217
208
  geo = Geometry.from_folder(comm=comm, folder=outdir)
218
209
  return geo
@@ -249,6 +240,7 @@ def biv_ellipsoid_torso(
249
240
  fiber_angle_epi: float = -60,
250
241
  fiber_space: str = "P_1",
251
242
  verbose: bool = False,
243
+ comm: MPI.Comm = MPI.COMM_WORLD,
252
244
  ) -> Geometry:
253
245
  """Create BiV ellipsoidal geometry
254
246
 
@@ -316,6 +308,8 @@ def biv_ellipsoid_torso(
316
308
  Function space for fibers of the form family_degree, by default "P_1"
317
309
  verbose : bool, optional
318
310
  If True print information from gmsh, by default False
311
+ comm : MPI.Comm, optional
312
+ MPI communicator, by default MPI.COMM_WORLD
319
313
 
320
314
  Returns
321
315
  -------
@@ -323,7 +317,6 @@ def biv_ellipsoid_torso(
323
317
  A Geometry with the mesh, markers, markers functions and fibers.
324
318
 
325
319
  """
326
- comm = MPI.COMM_WORLD
327
320
  outdir = Path(outdir)
328
321
  mesh_name = outdir / "biv_ellipsoid_torso.msh"
329
322
  if comm.rank == 0:
@@ -445,6 +438,7 @@ def lv_ellipsoid(
445
438
  fiber_space: str = "P_1",
446
439
  aha: bool = True,
447
440
  verbose: bool = False,
441
+ comm: MPI.Comm = MPI.COMM_WORLD,
448
442
  ) -> Geometry:
449
443
  """Create an LV ellipsoidal geometry
450
444
 
@@ -482,6 +476,8 @@ def lv_ellipsoid(
482
476
  If True create 17-segment AHA regions
483
477
  verbose : bool, optional
484
478
  If True print information from gmsh, by default False
479
+ comm : MPI.Comm, optional
480
+ MPI communicator, by default MPI.COMM_WORLD
485
481
 
486
482
  Returns
487
483
  -------
@@ -489,7 +485,7 @@ def lv_ellipsoid(
489
485
  A Geometry with the mesh, markers, markers functions and fibers.
490
486
 
491
487
  """
492
- comm = MPI.COMM_WORLD
488
+
493
489
  outdir = Path(outdir)
494
490
  mesh_name = outdir / "lv_ellipsoid.msh"
495
491
  if comm.rank == 0:
@@ -596,6 +592,7 @@ def slab(
596
592
  fiber_angle_epi: float = -60,
597
593
  fiber_space: str = "P_1",
598
594
  verbose: bool = False,
595
+ comm: MPI.Comm = MPI.COMM_WORLD,
599
596
  ) -> Geometry:
600
597
  """Create slab geometry
601
598
 
@@ -621,6 +618,8 @@ def slab(
621
618
  Function space for fibers of the form family_degree, by default "P_1"
622
619
  verbose : bool, optional
623
620
  If True print information from gmsh, by default False
621
+ comm : MPI.Comm, optional
622
+ MPI communicator, by default MPI.COMM_WORLD
624
623
 
625
624
  Returns
626
625
  -------
@@ -628,7 +627,6 @@ def slab(
628
627
  A Geometry with the mesh, markers, markers functions and fibers.
629
628
 
630
629
  """
631
- comm = MPI.COMM_WORLD
632
630
  outdir = Path(outdir)
633
631
  mesh_name = outdir / "slab.msh"
634
632
  if comm.rank == 0:
@@ -698,6 +696,7 @@ def slab_in_bath(
698
696
  bz: float = 0.1,
699
697
  dx: float = 0.001,
700
698
  verbose: bool = False,
699
+ comm: MPI.Comm = MPI.COMM_WORLD,
701
700
  ) -> Geometry:
702
701
  """Create slab geometry
703
702
 
@@ -721,6 +720,8 @@ def slab_in_bath(
721
720
  Element size, by default 0.001
722
721
  verbose : bool, optional
723
722
  If True print information from gmsh, by default False
723
+ comm : MPI.Comm, optional
724
+ MPI communicator, by default MPI.COMM_WORLD
724
725
 
725
726
  Returns
726
727
  -------
@@ -728,7 +729,6 @@ def slab_in_bath(
728
729
  A Geometry with the mesh, markers, markers functions and fibers.
729
730
 
730
731
  """
731
- comm = MPI.COMM_WORLD
732
732
 
733
733
  outdir = Path(outdir)
734
734
  mesh_name = outdir / "slab_in_bath.msh"
@@ -1,5 +1,6 @@
1
1
  import tempfile
2
2
  import typing
3
+ import xml.etree.ElementTree as ET
3
4
  from enum import Enum
4
5
  from pathlib import Path
5
6
  from typing import Iterable, NamedTuple
@@ -25,6 +26,23 @@ class GMshModel(NamedTuple):
25
26
  vertex_tags: dolfinx.mesh.MeshTags
26
27
 
27
28
 
29
+ def distribute_entity_data(
30
+ mesh: dolfinx.mesh.Mesh,
31
+ tdim: int,
32
+ marked_entities: np.ndarray,
33
+ entity_values: np.ndarray,
34
+ ) -> tuple[np.ndarray, np.ndarray]:
35
+ if dolfinx.__version__ >= "0.9.0":
36
+ local_entities, local_values = dolfinx.io.utils.distribute_entity_data(
37
+ mesh, tdim, marked_entities, entity_values
38
+ )
39
+ else:
40
+ local_entities, local_values = dolfinx.io.utils.distribute_entity_data(
41
+ mesh._cpp_object, tdim, marked_entities, entity_values
42
+ )
43
+ return local_entities, local_values
44
+
45
+
28
46
  # copied from https://github.com/FEniCS/dolfinx/blob/main/python/dolfinx/io/gmshio.py
29
47
  def model_to_mesh(
30
48
  model,
@@ -160,9 +178,10 @@ def model_to_mesh(
160
178
  )
161
179
 
162
180
  # Create MeshTags for cells
163
- local_entities, local_values = dolfinx.io.utils.distribute_entity_data(
164
- mesh._cpp_object, mesh.topology.dim, cells, cell_values
181
+ local_entities, local_values = distribute_entity_data(
182
+ mesh, mesh.topology.dim, cells, cell_values
165
183
  )
184
+
166
185
  mesh.topology.create_connectivity(mesh.topology.dim, 0)
167
186
  adj = dolfinx.cpp.graph.AdjacencyList_int32(local_entities)
168
187
  ct = dolfinx.mesh.meshtags_from_entities(
@@ -188,11 +207,13 @@ def model_to_mesh(
188
207
  gmsh_facet_perm = dolfinx.io.gmshio.cell_perm_array(facet_type, num_facet_nodes)
189
208
  marked_facets = marked_facets[:, gmsh_facet_perm]
190
209
 
191
- local_entities, local_values = dolfinx.io.utils.distribute_entity_data(
192
- mesh._cpp_object, tdim - 1, marked_facets, facet_values
210
+ local_entities, local_values = distribute_entity_data(
211
+ mesh, mesh.topology.dim - 1, marked_facets, facet_values
193
212
  )
213
+
194
214
  mesh.topology.create_connectivity(topology.dim - 1, tdim)
195
215
  adj = dolfinx.cpp.graph.AdjacencyList_int32(local_entities)
216
+
196
217
  ft = dolfinx.io.gmshio.meshtags_from_entities(
197
218
  mesh, tdim - 1, adj, local_values.astype(np.int32, copy=False)
198
219
  )
@@ -210,8 +231,8 @@ def model_to_mesh(
210
231
  gmsh_edge_perm = dolfinx.io.gmshio.cell_perm_array(edge_type, num_edge_nodes)
211
232
  marked_edges = marked_edges[:, gmsh_edge_perm]
212
233
 
213
- local_entities, local_values = dolfinx.io.utils.distribute_entity_data(
214
- mesh._cpp_object, tdim - 2, marked_edges, edge_values
234
+ local_entities, local_values = distribute_entity_data(
235
+ mesh, tdim - 2, marked_edges, edge_values
215
236
  )
216
237
  mesh.topology.create_connectivity(topology.dim - 2, tdim)
217
238
  adj = dolfinx.cpp.graph.AdjacencyList_int32(local_entities)
@@ -232,8 +253,8 @@ def model_to_mesh(
232
253
  gmsh_vertex_perm = dolfinx.io.gmshio.cell_perm_array(vertex_type, num_vertex_nodes)
233
254
  marked_vertices = marked_vertices[:, gmsh_vertex_perm]
234
255
 
235
- local_entities, local_values = dolfinx.io.utils.distribute_entity_data(
236
- mesh._cpp_object, tdim - 3, marked_vertices, vertex_values
256
+ local_entities, local_values = distribute_entity_data(
257
+ mesh, tdim - 3, marked_vertices, vertex_values
237
258
  )
238
259
  mesh.topology.create_connectivity(topology.dim - 3, tdim)
239
260
  adj = dolfinx.cpp.graph.AdjacencyList_int32(local_entities)
@@ -340,6 +361,7 @@ def array2element(arr: np.ndarray) -> basix.finite_element.FiniteElement:
340
361
  degree=degree,
341
362
  discontinuous=discontinuous,
342
363
  shape=(3,),
364
+ lagrange_variant=basix.LagrangeVariant.unset,
343
365
  )
344
366
 
345
367
 
@@ -438,3 +460,88 @@ def gmsh2dolfin(comm: MPI.Intracomm, msh_file, rank: int = 0) -> GMshGeometry:
438
460
  )
439
461
 
440
462
  return GMshGeometry(mesh, ct, ft, et, vt, markers)
463
+
464
+
465
+ def create_xdmf_pointcloud(filename: Path, us: typing.Sequence[dolfinx.fem.Function]) -> None:
466
+ # Adopted from https://gist.github.com/jorgensd/8bae61ad7a0c211570dff0116a68a356
467
+ if len(us) == 0:
468
+ return
469
+
470
+ import adios2
471
+
472
+ u = us[0]
473
+ points = u.function_space.tabulate_dof_coordinates()
474
+ h5name = filename.with_suffix(".h5")
475
+
476
+ bs = u.function_space.dofmap.index_map_bs
477
+ comm = u.function_space.mesh.comm
478
+ num_dofs_global = u.function_space.dofmap.index_map.size_global
479
+ num_dofs_local = u.function_space.dofmap.index_map.size_local
480
+ local_range = np.array(u.function_space.dofmap.index_map.local_range, dtype=np.int64)
481
+
482
+ # Write XDMF on rank 0
483
+ if comm.rank == 0:
484
+ xdmf = ET.Element("XDMF")
485
+ xdmf.attrib["Version"] = "3.0"
486
+ xdmf.attrib["xmlns:xi"] = "http://www.w3.org/2001/XInclude"
487
+ domain = ET.SubElement(xdmf, "Domain")
488
+ grid = ET.SubElement(domain, "Grid")
489
+ grid.attrib["GridType"] = "Uniform"
490
+ grid.attrib["Name"] = "Point Cloud"
491
+ topology = ET.SubElement(grid, "Topology")
492
+ topology.attrib["NumberOfElements"] = str(num_dofs_global)
493
+ topology.attrib["TopologyType"] = "PolyVertex"
494
+ topology.attrib["NodesPerElement"] = "1"
495
+ geometry = ET.SubElement(grid, "Geometry")
496
+ geometry.attrib["GeometryType"] = "XY" if points.shape[1] == 2 else "XYZ"
497
+ for u in us:
498
+ it0 = ET.SubElement(geometry, "DataItem")
499
+ it0.attrib["Dimensions"] = f"{num_dofs_global} {points.shape[1]}"
500
+ it0.attrib["Format"] = "HDF"
501
+ it0.text = f"{h5name.name}:/Step0/Points"
502
+ attrib = ET.SubElement(grid, "Attribute")
503
+ attrib.attrib["Name"] = u.name
504
+ if bs == 1:
505
+ attrib.attrib["AttributeType"] = "Scalar"
506
+ else:
507
+ attrib.attrib["AttributeType"] = "Vector"
508
+ attrib.attrib["Center"] = "Node"
509
+ it1 = ET.SubElement(attrib, "DataItem")
510
+ it1.attrib["Dimensions"] = f"{num_dofs_global} {bs}"
511
+ it1.attrib["Format"] = "HDF"
512
+ it1.text = f"{h5name.name}:/Step0/Values_{u.name}"
513
+ text = [
514
+ '<?xml version="1.0"?>\n<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>\n',
515
+ ET.tostring(xdmf, encoding="unicode"),
516
+ ]
517
+ filename.write_text("".join(text))
518
+ # Create ADIOS2 reader
519
+ # start = time.perf_counter()
520
+ adios = adios2.ADIOS(comm)
521
+ io = adios.DeclareIO("Point cloud writer")
522
+ io.SetEngine("HDF5")
523
+ outfile = io.Open(h5name.as_posix(), adios2.Mode.Write)
524
+ points_out = points[:num_dofs_local, :]
525
+
526
+ pointvar = io.DefineVariable(
527
+ "Points",
528
+ points_out,
529
+ shape=[num_dofs_global, points.shape[1]],
530
+ start=[local_range[0], 0],
531
+ count=[num_dofs_local, points.shape[1]],
532
+ )
533
+ outfile.Put(pointvar, points_out)
534
+ for u in us:
535
+ data = u.x.array[: num_dofs_local * bs].reshape(-1, bs)
536
+
537
+ valuevar = io.DefineVariable(
538
+ f"Values_{u.name}",
539
+ data,
540
+ shape=[num_dofs_global, bs],
541
+ start=[local_range[0], 0],
542
+ count=[num_dofs_local, bs],
543
+ )
544
+ outfile.Put(valuevar, data)
545
+ outfile.PerformPuts()
546
+ outfile.Close()
547
+ assert adios.RemoveIO("Point cloud writer")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cardiac-geometriesx
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: A python library for cardiac geometries
5
5
  Author-email: Henrik Finsberg <henriknf@simula.no>
6
6
  License: MIT
@@ -0,0 +1,16 @@
1
+ cardiac_geometries/__init__.py,sha256=2W_ywAeLjyRk5MqSPAodHa4UN2lOnW1h8tmGLQ3gaJ0,150
2
+ cardiac_geometries/cli.py,sha256=GKcsMNhVFoxWDr-o3jiDCXmTvPgCSEB9Kws8AvYIK4Q,19678
3
+ cardiac_geometries/geometry.py,sha256=s-1BIDKvP9M3uu3Sl8JpGRnTnXZAa9Aq3FfpIIEAxhY,5982
4
+ cardiac_geometries/gui.py,sha256=9WYR850wLrqsUrVUC37E2SaO0OWA_oagSe-YNrsxz3k,8376
5
+ cardiac_geometries/mesh.py,sha256=Ejciny48mnKKN20RrY9DwLY7_Lh1jb6Kldj4CW1wr1o,26909
6
+ cardiac_geometries/utils.py,sha256=fMHlVzwxnk1lJd8XQPy8dgFB9C9ecSnJB2NzMXJGAAQ,20348
7
+ cardiac_geometries/fibers/__init__.py,sha256=WpRrn9Iakl-3m8IGtFkqP0LXGjw5EZHZ8Eg9JCnCdrg,137
8
+ cardiac_geometries/fibers/lv_ellipsoid.py,sha256=KuWnx9yZ5KDyoeoYyDnXLZYb82DRiNveZyNIboD3uJ8,5768
9
+ cardiac_geometries/fibers/slab.py,sha256=5tMvOSqXQ4_nbdUUtho_tQjDrmICxZfN7SXNq4FKdlY,3836
10
+ cardiac_geometries/fibers/utils.py,sha256=x6MNtW6xN5NBGBD0Ubm4eqTDde0j_Vd-nh8agFT_AiU,3161
11
+ cardiac_geometriesx-0.4.0.dist-info/LICENSE,sha256=lo5K2rJPZOSv6luutGHbzzi3IpXNaB9E2UWq60qvNx0,1111
12
+ cardiac_geometriesx-0.4.0.dist-info/METADATA,sha256=rPU1WjGfdSGrlkgnkhIubCY3WzJ7nlMGsLfcuNdU2ME,4163
13
+ cardiac_geometriesx-0.4.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
14
+ cardiac_geometriesx-0.4.0.dist-info/entry_points.txt,sha256=xOBnlc6W-H9oCDYLNz3kpki26OmpfYSoFSrmi_4V-Ec,52
15
+ cardiac_geometriesx-0.4.0.dist-info/top_level.txt,sha256=J0gQxkWR2my5Vf7Qt8buDY8ZOjYdVfIweVunCGXWKNE,19
16
+ cardiac_geometriesx-0.4.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (72.1.0)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,16 +0,0 @@
1
- cardiac_geometries/__init__.py,sha256=2W_ywAeLjyRk5MqSPAodHa4UN2lOnW1h8tmGLQ3gaJ0,150
2
- cardiac_geometries/cli.py,sha256=GKcsMNhVFoxWDr-o3jiDCXmTvPgCSEB9Kws8AvYIK4Q,19678
3
- cardiac_geometries/geometry.py,sha256=iK8lydZEqU3sz0983yucW9IzQ2VqSXSy4D5ubdl9bOs,5636
4
- cardiac_geometries/gui.py,sha256=9WYR850wLrqsUrVUC37E2SaO0OWA_oagSe-YNrsxz3k,8376
5
- cardiac_geometries/mesh.py,sha256=JSm69BTS7WRUldwaQ9-Gnjq_KbX66FTnl2ouFKRtFhA,26825
6
- cardiac_geometries/utils.py,sha256=EwEXAuB4XiJaqlZaGZ1cc6sIBSPJLCx-43As1NUcJrA,16488
7
- cardiac_geometries/fibers/__init__.py,sha256=WpRrn9Iakl-3m8IGtFkqP0LXGjw5EZHZ8Eg9JCnCdrg,137
8
- cardiac_geometries/fibers/lv_ellipsoid.py,sha256=KuWnx9yZ5KDyoeoYyDnXLZYb82DRiNveZyNIboD3uJ8,5768
9
- cardiac_geometries/fibers/slab.py,sha256=5tMvOSqXQ4_nbdUUtho_tQjDrmICxZfN7SXNq4FKdlY,3836
10
- cardiac_geometries/fibers/utils.py,sha256=j1ERqXcdaWCwO2yjbYGlgTt2G1DxZCVzbNHuDhh_QrM,2541
11
- cardiac_geometriesx-0.3.0.dist-info/LICENSE,sha256=lo5K2rJPZOSv6luutGHbzzi3IpXNaB9E2UWq60qvNx0,1111
12
- cardiac_geometriesx-0.3.0.dist-info/METADATA,sha256=xfAjdCgXBkVeMi-R2psGWeh2t2Y0wBPHxcVJ5m6_6MU,4163
13
- cardiac_geometriesx-0.3.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
14
- cardiac_geometriesx-0.3.0.dist-info/entry_points.txt,sha256=xOBnlc6W-H9oCDYLNz3kpki26OmpfYSoFSrmi_4V-Ec,52
15
- cardiac_geometriesx-0.3.0.dist-info/top_level.txt,sha256=J0gQxkWR2my5Vf7Qt8buDY8ZOjYdVfIweVunCGXWKNE,19
16
- cardiac_geometriesx-0.3.0.dist-info/RECORD,,