Skip to content

Commit f50543c

Browse files
Merge pull request #15 from KrisThielemans/petsird_v0.7
petsird v0.7
2 parents d699ae0 + b8a7e1e commit f50543c

File tree

8 files changed

+62
-204
lines changed

8 files changed

+62
-204
lines changed

.clang-format

Lines changed: 0 additions & 37 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 0 additions & 61 deletions
This file was deleted.

.github/workflows/python-app.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
steps:
2+
- uses: actions/checkout@v4
3+
- name: Set up Python
4+
uses: actions/setup-python@v5
5+
with:
6+
python-version: '3.x'
7+
cache: 'pip'
8+
- name: Install dependencies
9+
run: |
10+
python -m pip install --upgrade pip
11+
pip install -r requirements.txt
12+
- name: Test on generated file
13+
shell: bash
14+
run: |
15+
set -ex
16+
python -m petsird.helpers.generator | python python/main.py -o test.ply
17+
# minimal test if readable output
18+
test -r test.ply

.gitmodules

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +0,0 @@
1-
[submodule "PETSIRD"]
2-
path = PETSIRD
3-
url = https://github.com/ETSInitiative/PETSIRD
4-
branch=main

PETSIRD

Lines changed: 0 additions & 1 deletion
This file was deleted.

environment.yml

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
1-
name: petsird
1+
name: petsird-visualisation
22
channels:
33
- conda-forge
4-
- defaults
54
dependencies:
6-
- bash-completion>=2.11
7-
- cmake>=3.21.3
8-
- fmt>=8.1.1
9-
- compilers
10-
- h5py>=3.7.0
11-
- hdf5>=1.12.1
12-
- howardhinnant_date>=3.0.1
5+
- petsird=0.7
136
- ipykernel>=6.19.2
14-
- ninja>=1.11.0
15-
- nlohmann_json>=3.11.2
16-
- numpy>=1.24.3
17-
- python>=3.11.3
187
- matplotlib
19-
- shellcheck>=0.8.0
20-
- xtensor-fftw>=0.2.5
21-
- xtensor>=0.24.2
8+
- trimesh
9+
- scipy

python/main.py

Lines changed: 36 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import numpy as np
2727
import numpy.typing as npt
2828
import petsird
29+
import petsird.helpers.geometry
2930
import trimesh
3031
import argparse
3132

@@ -39,59 +40,6 @@
3940
#########################################################################################
4041
# Methods
4142
#########################################################################################
42-
def transform_to_mat44(
43-
transform: petsird.RigidTransformation,
44-
) -> npt.NDArray[np.float32]:
45-
return np.vstack([transform.matrix, [0, 0, 0, 1]])
46-
47-
48-
def mat44_to_transform(mat: npt.NDArray[np.float32]) -> petsird.RigidTransformation:
49-
return petsird.RigidTransformation(matrix=mat[0:3, :])
50-
51-
52-
def coordinate_to_homogeneous(coord: petsird.Coordinate) -> npt.NDArray[np.float32]:
53-
return np.hstack([coord.c, 1])
54-
55-
56-
def homogeneous_to_coordinate(
57-
hom_coord: npt.NDArray[np.float32],
58-
) -> petsird.Coordinate:
59-
return petsird.Coordinate(c=hom_coord[0:3])
60-
61-
62-
def mult_transforms(
63-
transforms: list[petsird.RigidTransformation],
64-
) -> petsird.RigidTransformation:
65-
"""multiply rigid transformations"""
66-
mat = np.array(
67-
((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)),
68-
dtype="float32",
69-
)
70-
71-
for t in reversed(transforms):
72-
mat = np.matmul(transform_to_mat44(t), mat)
73-
return mat44_to_transform(mat)
74-
75-
76-
def mult_transforms_coord(
77-
transforms: list[petsird.RigidTransformation], coord: petsird.Coordinate
78-
) -> petsird.Coordinate:
79-
"""apply list of transformations to coordinate"""
80-
# TODO better to multiply with coordinates in sequence, as first multiplying the matrices
81-
hom = np.matmul(
82-
transform_to_mat44(mult_transforms(transforms)),
83-
coordinate_to_homogeneous(coord),
84-
)
85-
return homogeneous_to_coordinate(hom)
86-
87-
88-
def transform_BoxShape(
89-
transform: petsird.RigidTransformation, box_shape: petsird.BoxShape
90-
) -> petsird.BoxShape:
91-
return petsird.BoxShape(
92-
corners=[mult_transforms_coord([transform], c) for c in box_shape.corners]
93-
)
94-
9543

9644
def create_box_from_vertices(vertices):
9745
# Define faces using the indices of vertices that make up each face
@@ -120,43 +68,42 @@ def extract_detector_eff(show_det_eff, header):
12068
if not show_det_eff:
12169
return None
12270

123-
if header.scanner.detection_efficiencies.det_el_efficiencies is None:
71+
eff = header.scanner.detection_efficiencies.detection_bin_efficiencies
72+
if eff is None:
12473
raise ValueError(
12574
"The scanner detection efficiencies are not defined. Correct this or remove the show_det_eff flag."
12675
)
127-
return header.scanner.detection_efficiencies.det_el_efficiencies
76+
return eff
12877

12978

130-
def set_detector_color(det_mesh, detector_efficiencies, mod_i, num_det_in_module, det_i, random_color):
79+
def set_detector_color(det_mesh, detector_efficiencies, type_of_module, num_modules, mod_i, num_det_in_module, det_i, random_color):
13180
if random_color == True:
13281
color = np.random.randint(0, 255, size=3)
13382
elif detector_efficiencies is not None:
134-
color = (crystal_color * detector_efficiencies[mod_i * num_det_in_module + det_i])
83+
eff = np.reshape(detector_efficiencies[type_of_module], shape=(num_modules, num_det_in_module, -1))
84+
color = (crystal_color * np.mean(eff[mod_i, det_i, :]))
13585
else:
13686
color = crystal_color
13787

13888
f_color = np.array([color[0], color[1], color[2], 50]).astype(
13989
np.uint8
14090
)
141-
14291
det_mesh.visual.face_colors = f_color
14392

14493
return det_mesh
14594

14695

14796

14897
def set_module_color(
149-
module_mesh, detector_efficiencies, mod_i, num_det_in_module, det_el, random_color
98+
module_mesh, detector_efficiencies, type_of_module, num_modules, mod_i, num_det_in_module, random_color
15099
):
151100
if random_color == True:
152101
color = np.random.randint(0, 255, size=3)
153102
elif detector_efficiencies is not None:
154-
# Mean of the detector efficiency in the current module
103+
# Mean of the detector efficiencies in the current module
104+
eff = np.reshape(detector_efficiencies[type_of_module], shape=(num_modules, num_det_in_module, -1))
155105
color = crystal_color * np.mean(
156-
detector_efficiencies.reshape((-1, len(det_el) * num_det_in_module))[
157-
mod_i, :
158-
]
159-
)
106+
eff[mod_i, :, :])
160107
else:
161108
color = crystal_color
162109

@@ -177,8 +124,10 @@ def create_mesh(header, modules_only=False, show_det_eff=False, random_color=Fal
177124
shapes = []
178125
# draw all crystals
179126
module_count = 0
180-
for rep_module in header.scanner.scanner_geometry.replicated_modules:
181-
det_el = (
127+
for type_of_module in range(len(header.scanner.scanner_geometry.replicated_modules)):
128+
rep_module = header.scanner.scanner_geometry.replicated_modules[type_of_module]
129+
num_modules = len(rep_module.transforms)
130+
det_els = (
182131
rep_module.object.detecting_elements
183132
) # Get all the detecting elements modules
184133
for mod_i in range(len(rep_module.transforms)):
@@ -188,36 +137,38 @@ def create_mesh(header, modules_only=False, show_det_eff=False, random_color=Fal
188137

189138
vertices = [] # If showing modules only
190139
mod_transform = rep_module.transforms[mod_i]
191-
for rep_volume in det_el:
192-
num_det_in_module = len(rep_volume.transforms)
193-
for det_i in range(num_det_in_module):
194-
transform = rep_volume.transforms[det_i]
195-
box: petsird.BoxShape = transform_BoxShape(
196-
mult_transforms([mod_transform, transform]),
197-
rep_volume.object.shape,
198-
)
199-
corners = []
200-
for boxcorner in box.corners:
201-
corners.append(boxcorner.c)
202-
203-
if not modules_only:
204-
det_mesh = create_box_from_vertices(corners)
140+
num_det_in_module = len(det_els.transforms)
141+
for det_i in range(num_det_in_module):
142+
transform = det_els.transforms[det_i]
143+
box: petsird.BoxShape = petsird.helpers.geometry.transform_BoxShape(
144+
petsird.helpers.geometry.mult_transforms(
145+
[mod_transform, transform]),
146+
det_els.object.shape,
147+
)
148+
corners = []
149+
for boxcorner in box.corners:
150+
corners.append(boxcorner.c)
151+
152+
if not modules_only:
153+
det_mesh = create_box_from_vertices(corners)
205154

206-
det_mesh = set_detector_color(det_mesh, detector_efficiencies, mod_i, num_det_in_module, det_i, random_color)
155+
det_mesh = set_detector_color(det_mesh, detector_efficiencies, type_of_module, num_modules, mod_i, num_det_in_module, det_i, random_color)
207156

208-
shapes.append(det_mesh)
209-
else:
210-
vertices.append(corners)
157+
shapes.append(det_mesh)
158+
else:
159+
vertices.append(corners)
211160
if modules_only:
212161
vertices_reshaped = np.array(vertices).reshape((-1, 3))
213162
module_mesh = trimesh.convex.convex_hull(vertices_reshaped)
214163

215164
module_mesh = set_module_color(
216165
module_mesh,
217166
detector_efficiencies,
167+
type_of_module,
168+
num_modules,
218169
mod_i,
219170
num_det_in_module,
220-
det_el, random_color
171+
random_color
221172
)
222173

223174
shapes.append(module_mesh)

requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
petsird==0.7
2+
matplotlib
3+
trimesh
4+
scipy

0 commit comments

Comments
 (0)