2626import numpy as np
2727import numpy .typing as npt
2828import petsird
29+ import petsird .helpers .geometry
2930import trimesh
3031import argparse
3132
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
9644def 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
14897def 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 )
0 commit comments