catm-python-lib
Loading...
Searching...
No Matches
catmviewer.py
Go to the documentation of this file.
1"""!
2@file catmviewer.py
3@version 1
4@author Fumitaka ENDO
5@date 2025-01-28T13:22:04+09:00
6@brief analysis utilities related to CAT-M
7"""
8import numpy as np
9import matplotlib
10import matplotlib.pyplot as plt
11from mpl_toolkits.mplot3d import Axes3D
12from mpl_toolkits.mplot3d.art3d import Poly3DCollection
13from matplotlib.gridspec import GridSpec
14
15
16def find_nearest_index(array, value):
17 """!
18 @brief find index of nearest point
19 @param array reference array for sorting index
20 @param reference value
21 @return index value
22 """
23 array = np.array(array)
24 index = np.abs(array - value).argmin()
25 return index
26
27def calculate_track_dipole_magnet_analytical_solution(v0=np.array([1,0,0]), x0=np.array([0,0,0]), omega=1, t=0):
28 """!
29 @brief analytical solution for equation of moyion in uniform magnetic field
30 @param v0 initial vector [m] (numpy.array([x,y,z]))
31 @param x0 initial position [m] (numpy.array([x,y,z]))
32 @param omega cyclotron frequency (qB/m [C][T][m]^-1)
33 @param t list of time, which you want to calculate the position
34 @return list of 3 component : [x1,x2,..,x3],[y1,y2,..,y3], [z1,z2,..,z3]
35 """
36 x = v0[0]/omega * np.sin( omega * t ) + v0[2]/omega * ( 1.0 - np.cos( omega * t ) ) + x0[0]
37 y = v0[1] * t + x0[1]
38 z = v0[2]/omega * np.sin( omega * t ) - v0[0]/omega * ( 1.0 - np.cos( omega * t ) ) + x0[2]
39
40 return x,y,z
41
42def calculate_unit_vector(v=np.array([-0.2, 0.01, 0.01])):
43 """!
44 @brief calculate and return unit vector
45 @param v vector (np.array([-x, y, z]))
46 @return unit vector of input vector
47 """
48 uv = v/np.linalg.norm(v)
49 return uv
50
51def calculate_extrapolated_position(position, direction, target_value, direction_to_extrapolate=2):
52 """!
53 @brief calculate and return extrapolated_position
54 @param position reference position
55 @param direction refarence vector
56 @param target_value extrapolated value
57 @param direction_to_extrapolate extrapolated axis
58 @return extrapolated position (np.array([x, y, z]))
59 """
60 x0, y0, z0 = position
61 vx, vy, vz = direction
62
63 # extrapolate along X
64 if direction_to_extrapolate == 0:
65 if vx == 0:
66 raise ValueError("can not be changed due to the X component of vector is zero")
67 t = (target_value - x0) / vx
68 y_target = y0 + t * vy
69 z_target = z0 + t * vz
70 return np.array([target_value, y_target, z_target])
71
72 # extrapolate along Y
73 elif direction_to_extrapolate == 1:
74 if vy == 0:
75 raise ValueError("can not be changed due to the Y component of vector is zero")
76 t = (target_value - y0) / vy
77 x_target = x0 + t * vx
78 z_target = z0 + t * vz
79 return np.array([x_target, target_value, z_target])
80
81 # extrapolate along Z
82 elif direction_to_extrapolate == 2:
83 if vz == 0:
84 raise ValueError("can not be changed due to the Z component of vector is zero")
85 t = (target_value - z0) / vz
86 x_target = x0 + t * vx
87 y_target = y0 + t * vy
88 return np.array([x_target, y_target, target_value])
89
90 else:
91 raise ValueError("extrapolation direction must be specified as 0 (x), 1 (y), or 2 (z).")
92
93def plot_3d_trajectory(x=[], y=[], z=[], u=[], v=[], w=[],
94 x_lim=None, y_lim=None, z_lim=None,
95 bpad=None, rpad=None, spad=None,
96 bid=None, rid=None, sid=None,
97 anaflag=-1, showflag=True, savepath=None, user_colors=['#B844A0','#36797A','#36797A','#B844A0']
98 ):
99 """!
100 @brief plot 3 disimensional trajectories
101 @param x point data list : [[x1,x2,..x3],[x1,x2,..x3],[x1,x2,..x3]]
102 @param y point data list : [[y1,y2,..y3],[y1,y2,..y3],[y1,y2,..y3]]
103 @param z point data list : [[z1,z2,..z3],[z1,z2,..z3],[z1,z2,..z3]]
104 @param u line data list : [[x1,x2,..x3],[x1,x2,..x3],[x1,x2,..x3]]
105 @param v line data list : [[y1,y2,..y3],[y1,y2,..y3],[y1,y2,..y3]]
106 @param w line data list : [[z1,z2,..z3],[z1,z2,..z3],[z1,z2,..z3]]
107 @param x_lim draw range for X
108 @param y_lim draw range for Y
109 @param z_lim draw range for Z
110 @param bpad beam tpc pad info (TReadoutPadArray)
111 @param rpad recoil tpc pad info (TReadoutPadArray)
112 @param spad silicon pad info (TReadoutPadArray)
113 @param bid beam tpc hit id
114 @param rid recoil tpc hit id
115 @param sid silicon hit id
116 @param anaflag analysis flag (-1:tpc, 1:si)
117 @param showflag draw flag (default : True)
118 @param savepath save path
119 @param user_colors color set
120 @return None
121 """
122 fig = plt.figure(figsize=(8, 6))
123 ax = fig.add_subplot(111, projection='3d')
124
125 # Label
126 ax.set_xlabel('Z position [mm]')
127 ax.set_ylabel('X position [mm]')
128 ax.set_zlabel('Y Position [mm]')
129 ax.xaxis.pane.set_edgecolor('k')
130 ax.yaxis.pane.set_edgecolor('k')
131 ax.zaxis.pane.set_edgecolor('k')
132 ax.xaxis.pane.set_facecolor('w')
133 ax.yaxis.pane.set_facecolor('w')
134 ax.zaxis.pane.set_facecolor('w')
135 ax.grid(False)
136
137 if x_lim:
138 ax.set_xlim(x_lim)
139 if y_lim:
140 ax.set_ylim(y_lim)
141 if z_lim:
142 ax.set_zlim(z_lim)
143 if x_lim and y_lim and z_lim:
144 ax.set_box_aspect([abs(x_lim[0]-x_lim[1]),abs(y_lim[0]-y_lim[1]),abs(z_lim[0]-z_lim[1])])
145
146 # XZ projection all
147 if bpad != None:
148 for i in range(len(bpad.pads)):
149 tri = [[bpad.pads[i][0][2],bpad.pads[i][0][0],bpad.pads[i][0][1]],[bpad.pads[i][1][2],bpad.pads[i][1][0],bpad.pads[i][1][1]],[bpad.pads[i][2][2],bpad.pads[i][2][0],bpad.pads[i][2][1]]]
150 triangle = Poly3DCollection([np.array(tri)], color='gray', alpha=0.3, edgecolor='gray')
151 ax.add_collection3d(triangle)
152
153 if rpad != None:
154 for i in range(len(rpad.pads)):
155 tri = [[rpad.pads[i][0][2],rpad.pads[i][0][0],rpad.pads[i][0][1]],[rpad.pads[i][1][2],rpad.pads[i][1][0],rpad.pads[i][1][1]],[rpad.pads[i][2][2],rpad.pads[i][2][0],rpad.pads[i][2][1]]]
156 triangle = Poly3DCollection([np.array(tri)], color='gray', alpha=0.3, edgecolor='gray')
157 ax.add_collection3d(triangle)
158
159 if spad != None:
160 for i in range(len(spad.pads)):
161 rec = [[spad.pads[i][0][2],spad.pads[i][0][0],spad.pads[i][0][1]],[spad.pads[i][1][2],spad.pads[i][1][0],spad.pads[i][1][1]],[spad.pads[i][2][2],spad.pads[i][2][0],spad.pads[i][2][1]],[spad.pads[i][3][2],spad.pads[i][3][0],spad.pads[i][3][1]]]
162 rectangle = Poly3DCollection([np.array(rec)], color='gray', alpha=0.3, edgecolor='gray')
163 ax.add_collection3d(rectangle)
164
165 # XZ projection hit
166 if bpad != None:
167 for j in range(len(bid)):
168 i = int(bid[j])
169 tri = [[bpad.pads[i][0][2],bpad.pads[i][0][0],bpad.pads[i][0][1]],[bpad.pads[i][1][2],bpad.pads[i][1][0],bpad.pads[i][1][1]],[bpad.pads[i][2][2],bpad.pads[i][2][0],bpad.pads[i][2][1]]]
170 triangle = Poly3DCollection([np.array(tri)], color=user_colors[1])
171 ax.add_collection3d(triangle)
172
173 if rpad != None:
174 for j in range(len(rid)):
175 i = int(rid[j])
176 tri = [[rpad.pads[i][0][2],rpad.pads[i][0][0],rpad.pads[i][0][1]],[rpad.pads[i][1][2],rpad.pads[i][1][0],rpad.pads[i][1][1]],[rpad.pads[i][2][2],rpad.pads[i][2][0],rpad.pads[i][2][1]]]
177 triangle = Poly3DCollection([np.array(tri)], color=user_colors[0])
178 ax.add_collection3d(triangle)
179
180 if anaflag ==1:
181 if spad != None:
182 for j in range(len(sid)):
183 i = int(sid[j])
184 rec = [[spad.pads[i][0][2],spad.pads[i][0][0],spad.pads[i][0][1]],[spad.pads[i][1][2],spad.pads[i][1][0],spad.pads[i][1][1]],[spad.pads[i][2][2],spad.pads[i][2][0],spad.pads[i][2][1]],[spad.pads[i][3][2],spad.pads[i][3][0],spad.pads[i][3][1]]]
185 rectangle = Poly3DCollection([np.array(rec)], color=user_colors[0])
186 ax.add_collection3d(rectangle)
187
188 # XZ Projection line
189 for i in range(len(u)-1):
190 ax.plot(u[i], v[i], w[i]-w[i]-99. ,c=user_colors[i],lw=1, linestyle=(0, (5, 1, 1, 1)))
191
192 # plot track
193 label_titles = ['Hit Pattern (RecoilTPC&SSD)','Hit Pattern (BeamTPC)']
194 for i in range(len(x)):
195 ax.scatter(x[i], y[i], z[i],c=user_colors[i],label=label_titles[i])
196
197 label_titles = ['Track (Recoil Particle)','','Track (Beam Particle)','']
198
199 if anaflag == 1:
200 for i in range(len(u)):
201 ax.plot(u[i], v[i], w[i],c=user_colors[i],label=label_titles[i])
202 else:
203 for i in range(len(u)-1):
204 ax.plot(u[i], v[i], w[i],c=user_colors[i],label=label_titles[i])
205
206 ax.legend(loc="upper right", bbox_to_anchor=(1.05, 0.95))
207
208 ax.view_init(50, 230)
209 plt.tight_layout()
210
211 if showflag == True:
212 plt.show()
213
214 if savepath:
215 fig.savefig(savepath)
216
217 plt.close(fig)
218
219
220def plot_2d_trajectory(x=[], y=[], z=[], u=[], v=[], w=[],
221 x_lim=None, y_lim=None, z_lim=None,
222 bpad=None, rpad=None, spad=None,
223 bid=None, rid=None, sid=None,
224 anaflag=-1, showflag=True, savepath=None, user_colors=['#B844A0','#36797A','#36797A','#B844A0']
225 ):
226 """!
227 @brief plot 3 disimensional trajectories
228 @param x point data list : [[x1,x2,..x3],[x1,x2,..x3],[x1,x2,..x3]]
229 @param y point data list : [[y1,y2,..y3],[y1,y2,..y3],[y1,y2,..y3]]
230 @param z point data list : [[z1,z2,..z3],[z1,z2,..z3],[z1,z2,..z3]]
231 @param u line data list : [[x1,x2,..x3],[x1,x2,..x3],[x1,x2,..x3]]
232 @param v line data list : [[y1,y2,..y3],[y1,y2,..y3],[y1,y2,..y3]]
233 @param w line data list : [[z1,z2,..z3],[z1,z2,..z3],[z1,z2,..z3]]
234 @param x_lim draw range for X
235 @param y_lim draw range for Y
236 @param z_lim draw range for Z
237 @param bpad beam tpc pad info (TReadoutPadArray)
238 @param rpad recoil tpc pad info (TReadoutPadArray)
239 @param spad silicon pad info (TReadoutPadArray)
240 @param bid beam tpc hit id
241 @param rid recoil tpc hit id
242 @param sid silicon hit id
243 @param anaflag analysis flag (-1:tpc, 1:si)
244 @param showflag draw flag (default : True)
245 @param savepath save path
246 @param user_colors color set
247 @return None
248 """
249 fig = plt.figure(figsize=(12, 10))
250
251 gs = GridSpec(2, 3, height_ratios=[5, 0.375], width_ratios=[0.5, 2, 0.5])
252 ax1 = fig.add_subplot(gs[0, 1])
253 ax2 = fig.add_subplot(gs[1, 1], sharex=ax1)
254 axl = fig.add_subplot(gs[0, 0], sharey=ax1)
255 axr = fig.add_subplot(gs[0, 2], sharey=ax1)
256
257 #top
258 for i in range(len(rpad.pads)):
259 xs = [vertex[0] for vertex in rpad.pads[i]]
260 ys = [vertex[2] for vertex in rpad.pads[i]]
261 ax1.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
262
263 k=0
264 for j in range(len(rid)):
265 i = int(rid[j])
266 xs = [vertex[0] for vertex in rpad.pads[i]]
267 ys = [vertex[2] for vertex in rpad.pads[i]]
268 if k==0:
269 ax1.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[3], lw=0.5, zorder=0, label="Hit Pattern (RecoilTPC&SSD)")
270 else:
271 ax1.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[3], lw=0.5, zorder=0)
272 k=k+1
273
274 ax1.set_aspect('equal') # アスペクト比を等しく設定
275 ax1.set_xlim(-160, 160) # X軸の範囲を固定
276 ax1.set_ylim(-170, 230)
277
278 if len(v) >= 2:
279 ax1.plot(v[0],u[0], lw=2, color=user_colors[0], alpha=0.5, label="Track (Recoil Particle)")
280 ax1.plot(v[1],u[1], lw=2, color=user_colors[1], alpha=0.5, label="Track (Beam Particle)")
281
282 if anaflag ==1:
283 ax1.plot(v[3],u[3], lw=2, color=user_colors[0], alpha=0.5)
284 ax1.legend(loc='upper right')
285
286 # bottom
287 for i in range(len(bpad.pads)):
288 xs = [vertex[0] for vertex in bpad.pads[i]]
289 ys = [vertex[2] for vertex in bpad.pads[i]]
290 ax2.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
291
292 k=0
293 for j in range(len(bid)):
294 i = int(bid[j])
295 xs = [vertex[0] for vertex in bpad.pads[i]]
296 ys = [vertex[2] for vertex in bpad.pads[i]]
297 if k == 0:
298 ax2.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[2], lw=0.5, zorder=0, label="Hit Pattern (BeamTPC)")
299 else:
300 ax2.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[2], lw=0.5, zorder=0)
301 k=k+1
302
303 if len(v) >= 2:
304 ax2.plot(v[2],u[2], lw=2, color=user_colors[1], alpha=0.5, label="Track (Beam Particle)")
305
306 ax2.set_xlabel('X position [mm]')
307 ax2.set_ylim(-255 -15 , -255 +15)
308 ax2.set_aspect('equal')
309 ax2.legend(loc='lower right')
310
311 # left
312 for i in range(len(spad.pads)):
313 if spad.ids[i] < 48:
314 zos = [vertex[2] for vertex in spad.pads[i]]
315
316 if spad.ids[i] < 24:
317 ys = [min(zos), min(zos), max(zos), max(zos)]
318 xs = [-255, -255-8, -255-8, -255]
319 axl.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
320 else:
321 ys = [min(zos), min(zos), max(zos), max(zos)]
322 xs = [-255, -255+8, -255+8, -255]
323 axl.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
324
325 if anaflag ==1:
326 for j in range(len(sid)):
327 i = int(sid[j])
328 if i < 48:
329 zos = [vertex[2] for vertex in spad.pads[i]]
330 if spad.ids[i] < 24:
331 ys = [min(zos), min(zos), max(zos), max(zos)]
332 xs = [-255, -255-8, -255-8, -255]
333 axl.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[3], lw=0.5, zorder=0)
334 else:
335 ys = [min(zos), min(zos), max(zos), max(zos)]
336 xs = [-255, -255+8, -255+8, -255]
337 axl.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[3], lw=0.5, zorder=0)
338
339 axl.plot(v[3],u[3], lw=2, color=user_colors[3], alpha=0.5)
340
341 axl.set_aspect('equal')
342 axl.set_ylabel('Z position [mm]')
343 axl.set_xlim(-255 -15 , -255 +15)
344
345 # right
346 for i in range(len(spad.pads)):
347 if spad.ids[i] >= 48:
348 zos = [vertex[2] for vertex in spad.pads[i]]
349
350 if spad.ids[i] < 72:
351 ys = [min(zos), min(zos), max(zos), max(zos)]
352 xs = [255, 255-8, 255-8, 255]
353 axr.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
354 else:
355 ys = [min(zos), min(zos), max(zos), max(zos)]
356 xs = [255, 255+8, 255+8, 255]
357 axr.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
358
359 if anaflag ==1:
360 for j in range(len(sid)):
361 i = int(sid[j])
362 if i >= 48:
363 zos = [vertex[2] for vertex in spad.pads[i]]
364 if spad.ids[i] < 24:
365 ys = [min(zos), min(zos), max(zos), max(zos)]
366 xs = [255, 255-8, 255-8, 255]
367 axr.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[3], lw=0.5, zorder=0)
368 else:
369 ys = [min(zos), min(zos), max(zos), max(zos)]
370 xs = [255, 255+8, 255+8, 255]
371 axr.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[3], lw=0.5, zorder=0)
372
373 axr.plot(v[3],u[3], lw=2, color=user_colors[3], alpha=0.5)
374
375 axr.set_aspect('equal')
376 axr.set_xlim(255 -15 , 255 +15)
377
378 plt.tight_layout()
379
380 if showflag == True:
381 plt.show()
382
383 if savepath:
384 fig.savefig(savepath)
385
386 plt.close(fig)
387
388def plot_2d_categories( x_lim=None, y_lim=None, z_lim=None,
389 bpad=None, rpad=None, spad=None,
390 bid=None, rid=None, sid=None,
391 blabel=None, rlabel=None, slabel=None,
392 showflag=True, savepath=None,
393 user_colors=[['#B844A0'],['#36797A'],["#5CA3EF"]],
394 legendFlag=False,
395 title_name="Map file checker (Cobo, AsAd, AGET, Channel), [-1] = all"
396 ):
397 """!
398 @brief plot categories with 2 disimension
399 @param x_lim draw range for X
400 @param y_lim draw range for Y
401 @param z_lim draw range for Z
402 @param bpad beam tpc pad info (TReadoutPadArray)
403 @param rpad recoil tpc pad info (TReadoutPadArray)
404 @param spad silicon pad info (TReadoutPadArray)
405 @param bid beam tpc categories list ([ [1,2,...], [3,6...] ])
406 @param rid recoil tpc categories list ([ [1,2,...], [3,6...] ])
407 @param sid silicon hit categories list ([ [1,2,...], [3,6...] ])
408 @param showflag draw flag (default : True)
409 @param savepath save path
410 @param user_colors color set
411 @param title_name plot title
412 @return None
413 """
414 fig = plt.figure(figsize=(12, 10))
415
416 gs = GridSpec(2, 3, height_ratios=[5, 0.375], width_ratios=[0.5, 2, 0.5])
417 ax1 = fig.add_subplot(gs[0, 1])
418 ax2 = fig.add_subplot(gs[1, 1], sharex=ax1)
419 axl = fig.add_subplot(gs[0, 0], sharey=ax1)
420 axr = fig.add_subplot(gs[0, 2], sharey=ax1)
421
422 #top
423 for i in range(len(rpad.pads)):
424 xs = [vertex[0] for vertex in rpad.pads[i]]
425 ys = [vertex[2] for vertex in rpad.pads[i]]
426 ax1.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
427
428 for j in range(len(rid)):
429 k=0
430 for jj in range(len(rid[j])):
431 i = int(rid[j][jj])
432 xs = [vertex[0] for vertex in rpad.pads[i]]
433 ys = [vertex[2] for vertex in rpad.pads[i]]
434 if k==0:
435 ax1.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[0][j], lw=0.5, zorder=0, label=rlabel[j])
436 else:
437 ax1.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[0][j], lw=0.5, zorder=0)
438 k=k+1
439
440 ax1.set_aspect('equal') # アスペクト比を等しく設定
441 ax1.set_xlim(-160, 160) # X軸の範囲を固定
442 ax1.set_ylim(-170, 230)
443
444 # bottom
445 for i in range(len(bpad.pads)):
446 xs = [vertex[0] for vertex in bpad.pads[i]]
447 ys = [vertex[2] for vertex in bpad.pads[i]]
448 ax2.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
449
450 for j in range(len(bid)):
451 k=0
452 for jj in range(len(bid[j])):
453 i = int(bid[j][jj])
454 xs = [vertex[0] for vertex in bpad.pads[i]]
455 ys = [vertex[2] for vertex in bpad.pads[i]]
456 if k==0:
457 ax2.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[1][j], lw=0.5, zorder=0, label=blabel[j])
458 else:
459 ax2.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[1][j], lw=0.5, zorder=0)
460 k=k+1
461
462 ax2.set_xlabel('X position [mm]')
463 ax2.set_ylim(-255 -15 , -255 +15)
464 ax2.set_aspect('equal')
465
466 # left
467 for i in range(len(spad.pads)):
468 if spad.ids[i] < 48:
469 zos = [vertex[2] for vertex in spad.pads[i]]
470
471 if spad.ids[i] < 24:
472 ys = [min(zos), min(zos), max(zos), max(zos)]
473 xs = [-255, -255-8, -255-8, -255]
474 axl.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
475 else:
476 ys = [min(zos), min(zos), max(zos), max(zos)]
477 xs = [-255, -255+8, -255+8, -255]
478 axl.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
479
480 for j in range(len(sid)):
481 k=0
482 for jj in range(len(sid[j])):
483 i = int(sid[j][jj])
484 if spad.ids[i] < 48:
485 zos = [vertex[2] for vertex in spad.pads[i]]
486
487 if spad.ids[i] < 24:
488 ys = [min(zos), min(zos), max(zos), max(zos)]
489 xs = [-255, -255-8, -255-8, -255]
490 else:
491 ys = [min(zos), min(zos), max(zos), max(zos)]
492 xs = [-255, -255+8, -255+8, -255]
493
494 if k==0:
495 axl.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[2][j], lw=0.5, zorder=0, label=slabel[j])
496 else:
497 axl.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[2][j], lw=0.5, zorder=0)
498 k=k+1
499
500 axl.set_aspect('equal')
501 axl.set_ylabel('Z position [mm]')
502 axl.set_xlim(-255 -15 , -255 +15)
503
504 # right
505 for i in range(len(spad.pads)):
506 if spad.ids[i] >= 48:
507 zos = [vertex[2] for vertex in spad.pads[i]]
508
509 if spad.ids[i] < 72:
510 ys = [min(zos), min(zos), max(zos), max(zos)]
511 xs = [255, 255-8, 255-8, 255]
512 axr.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
513 else:
514 ys = [min(zos), min(zos), max(zos), max(zos)]
515 xs = [255, 255+8, 255+8, 255]
516 axr.fill(xs, ys, edgecolor='#a9a9a9', facecolor='#d3d3d3', lw=0.5, zorder=-2)
517
518 for j in range(len(sid)):
519 k=0
520 for jj in range(len(sid[j])):
521 i = int(sid[j][jj])
522 if spad.ids[i] >= 48:
523 zos = [vertex[2] for vertex in spad.pads[i]]
524 if spad.ids[i] < 72:
525 ys = [min(zos), min(zos), max(zos), max(zos)]
526 xs = [255, 255-8, 255-8, 255]
527 else:
528 ys = [min(zos), min(zos), max(zos), max(zos)]
529 xs = [255, 255+8, 255+8, 255]
530
531 if k==0:
532 axr.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[2][j], lw=0.5, zorder=0, label=slabel[j])
533 else:
534 axr.fill(xs, ys, edgecolor='#a9a9a9', facecolor=user_colors[2][j], lw=0.5, zorder=0)
535 k=k+1
536
537 axr.set_aspect('equal')
538 axr.set_xlim(255 -15 , 255 +15)
539
540 if legendFlag:
541 handles, labels = [], []
542 for ax in [ax1, ax2, axl, axr]:
543 h, l = ax.get_legend_handles_labels()
544 handles.extend(h)
545 labels.extend(l)
546
547 seen = set()
548 unique_handles_labels = []
549 for h, l in zip(handles, labels):
550 if l not in seen:
551 unique_handles_labels.append((h, l))
552 seen.add(l)
553
554 unique_handles, unique_labels = zip(*unique_handles_labels)
555 fig.legend(unique_handles, unique_labels, loc='upper center', bbox_to_anchor=(0.5, 0.95), ncol=4, fontsize=10)
556
557 fig.suptitle(title_name)
558 plt.tight_layout()
559
560 if showflag == True:
561 plt.show()
562
563 if savepath:
564 fig.savefig(savepath)
565
566 plt.close(fig)
567
568def check_catm_view():
569 """!
570 @brief plot catm readpad using matplotlib
571 """
572
573 import catmlib.readoutpad.catm as catpad
574
575 beamtpc = catpad.get_beam_tpc_array()
576 recoiltpc = catpad.get_recoil_tpc_array()
577 ssd = catpad.get_ssd_array()
578
579 x_range = (260, -260)
580 y_range = (-100, 100)
581 z_range = (-270, 220)
582
583 bid, rid, sid = [], [], []
584 rlabel, blabel, slabel = [], [], []
585 user_colors=[ [], [], [] ]
586
587 plot_2d_categories( z_range, x_range, y_range, beamtpc, recoiltpc, ssd, bid, rid, sid, blabel, rlabel, slabel, True, None, user_colors, False, "catm readpad view at XZ plane")