Belle II Software  release-08-01-10
plotVXDAlignmentPayload.py
1 #!/usr/bin/env python3
2 
3 
10 
11 import numpy as np
12 import pandas as pd
13 import math
14 from pylab import savefig, subplot
15 import matplotlib.pyplot as plt
16 from matplotlib import ticker
17 import matplotlib as mpl
18 import sys
19 
20 
21 import ROOT
22 from ROOT import Belle2
23 if len(sys.argv) < 2:
24  sys.exit("No input .root file specified!")
25 
26 inputroot = sys.argv[1]
27 file = ROOT.TFile(inputroot, "OPEN")
28 vxd = file.Get("VXDAlignment")
29 
30 fileName = inputroot + '.txt'
31 text_file = open(fileName, "w")
32 text_file.write("layer ladder sensor param value\n")
33 for entry in vxd.getMap():
34  element_parameter = entry.first
35  value = entry.second
36  element = element_parameter.first
37  param = element_parameter.second
38  vxdid = Belle2.VxdID(element)
39  layer = vxdid.getLayerNumber()
40  ladder = vxdid.getLadderNumber()
41  sensor = vxdid.getSensorNumber()
42  if sensor != 0:
43  text_file.write("{} {} {} {} {}\n".format(layer, ladder, sensor, param, value))
44 text_file.close()
45 
46 # set to True, if automatic scaling is to be used, otherwise the values in the unit_scale dict will be used.
47 autoscale = True
48 
49 # datafile structure
50 components = {'value'}
51 comp_map = {'value': 0}
52 parameters = {'du', 'dv', 'dw', 'alpha', 'beta', 'gamma', 'P_20', 'P_11', 'P_02', 'P_30', 'P_21', 'P_12', 'P_03'}
53 param_map = {1: 'du', 2: 'dv', 3: 'dw', 4: 'alpha', 5: 'beta', 6: 'gamma',
54  31: 'P_20', 32: 'P_11', 33: 'P_02',
55  41: 'P_30', 42: 'P_21', 43: 'P_12', 44: 'P_03'}
56 param_nums = {u: v for (v, u) in param_map.items()}
57 layers = {1, 2, 3, 4, 5, 6}
58 
59 n_data = 10 # number of independent samples
60 
61 # OK, we could make a dataframe for this, but then - why?
62 layer_phi0 = {
63  1: 0.0,
64  2: 0.0,
65  3: 33.624 * np.pi / 180,
66  4: 8 * np.pi / 180,
67  5: -8 * np.pi / 180,
68  6: -4 * np.pi / 180,
69 }
70 layer_nladders = {
71  1: 8,
72  2: 12,
73  3: 7,
74  4: 10,
75  5: 12,
76  6: 16,
77 }
78 layer_nsensors = {
79  1: 2,
80  2: 2,
81  3: 2,
82  4: 3,
83  5: 4,
84  6: 5,
85 }
86 
87 # If you want to use preset scales, enter them here and set autoscale to False.
88 unit_scale = {'value': {'shift': (-10.0,
89  10.,
90  plt.cm.bwr,
91  ' [um]'),
92  'rotation': (-1.0,
93  1.0,
94  plt.cm.bwr,
95  ' [mrad]'),
96  'surface': (-10.0,
97  10.,
98  plt.cm.bwr,
99  ' [um]')}}
100 
101 # Read data into a pandas DataFrame
102 print('reading from file ' + fileName)
103 
104 dataframe = pd.read_table(
105  fileName,
106  sep=' ',
107  skipinitialspace=True,
108  skiprows=1,
109  names=[
110  'layer',
111  'ladder',
112  'sensor',
113  'parameter',
114  'value'])
115 
116 # Scale things properly
117 scale = np.where((dataframe.parameter < 4) | (dataframe.parameter > 6), 1.0e4, 1.0e3)
118 for colname in ['value']:
119  dataframe[colname] *= scale
120 
121 # If bias is average of 10 samples, scale t_mille by sqrt(10)
122 # dataframe['t_mille'] *= np.sqrt(10)
123 
124 # Calculate and print scales.
125 # Maxima can be calculated for series of columns
126 data_columns = ['value']
127 min_shift = dataframe[data_columns][dataframe.parameter < 4].min().min()
128 max_shift = dataframe[data_columns][dataframe.parameter < 4].max().max()
129 min_shift = min(min_shift, -max_shift)
130 max_shift = max(-min_shift, max_shift)
131 min_rot = dataframe[data_columns][(3 < dataframe.parameter) & (dataframe.parameter < 7)].min().min()
132 max_rot = dataframe[data_columns][(3 < dataframe.parameter) & (dataframe.parameter < 7)].max().max()
133 min_rot = min(min_rot, -max_rot)
134 max_rot = max(-min_rot, max_rot)
135 min_sur2 = dataframe[data_columns][(30 < dataframe.parameter) & (dataframe.parameter < 34)].min().min()
136 max_sur2 = dataframe[data_columns][(30 < dataframe.parameter) & (dataframe.parameter < 34)].max().max()
137 min_sur2 = min(min_sur2, -max_sur2)
138 max_sur2 = max(-min_sur2, max_sur2)
139 min_sur3 = dataframe[data_columns][(40 < dataframe.parameter) & (dataframe.parameter < 45)].min().min()
140 max_sur3 = dataframe[data_columns][(40 < dataframe.parameter) & (dataframe.parameter < 45)].max().max()
141 min_sur3 = min(min_sur3, -max_sur3)
142 max_sur3 = max(-min_sur3, max_sur3)
143 
144 if math.isnan(min_rot):
145  min_rot = 0.
146 if math.isnan(max_rot):
147  max_rot = 0.
148 if math.isnan(min_shift):
149  min_shift = 0.
150 if math.isnan(max_shift):
151  max_shift = 0.
152 if math.isnan(min_sur2):
153  min_sur2 = 0.
154 if math.isnan(max_sur2):
155  max_sur2 = 0.
156 if math.isnan(min_sur3):
157  min_sur3 = 0.
158 if math.isnan(max_sur3):
159  max_sur3 = 0.
160 
161 print('Symmetrized scales for value: ')
162 print('Shifts: ' + str(min_shift) + ' to ' + str(max_shift))
163 print('Rotations: ' + str(min_rot) + ' to ' + str(max_rot))
164 print('Surface^2 ' + str(min_sur2) + ' to ' + str(max_sur2))
165 print('Surface^3 ' + str(min_sur3) + ' to ' + str(max_sur3))
166 
167 if autoscale:
168  unit_scale['value']['shift'] = (min_shift, max_shift, plt.cm.bwr, ' [um]')
169  unit_scale['value']['rotation'] = (min_rot, max_rot, plt.cm.bwr, ' [mrad]')
170  unit_scale['value']['surface2'] = (min_sur2, max_sur2, plt.cm.bwr, ' [um]')
171  unit_scale['value']['surface3'] = (min_sur3, max_sur3, plt.cm.bwr, ' [um]')
172 
173 fig = plt.figure(figsize=(10, 6.5))
174 for value in components:
175  for shiftrot, i_params in zip(['shift', 'rotation'], [[1, 2, 3], [4, 5, 6]]):
176  cmin, cmax, cmap, unit = unit_scale[value][shiftrot]
177  for i_param in i_params:
178  parameter = param_map[i_param]
179  # Make a subframe
180  val_param = dataframe[['layer', 'ladder', 'sensor', value]][dataframe['parameter'] == i_param]
181  val_param[value] = val_param[value]
182  # Here comes the real thing
183  ax = subplot(2, 3, i_param, projection='polar')
184  layer_gap = 24
185  bottom = 24 # starts at this, increases by sensor height in layers and layer_gap in between.
186  for layer in layers:
187  ladder_width = 2 * np.pi / layer_nladders[layer]
188  ladder_angles = np.linspace(layer_phi0[layer], layer_phi0[layer] + 2 * np.pi, layer_nladders[layer], endpoint=False)
189 
190  for sensor in range(1, 1 + layer_nsensors[layer]):
191  height = (layer > 3 and sensor == 1) * 10.0 + 28.0 / (1.0 + 0.3 * layer + 0.5 * sensor)
192  content = height * np.ones(layer_nladders[layer])
193  bars = ax.bar(
194  ladder_angles,
195  content,
196  width=ladder_width,
197  bottom=bottom,
198  label=str(sensor + 1),
199  align='center',
200  # edgecolor='k',
201  )
202  bottom += height
203  for (ladder, bar) in zip(range(1, 1 + layer_nladders[layer]), bars):
204  cond = (val_param.layer == layer) & (val_param.ladder == ladder) & (val_param.sensor == sensor)
205  try:
206  c = float(val_param[value][cond])
207  except BaseException:
208  c = 0.
209  if (cmax - cmin) > 0.:
210  color_value = (c - cmin) / (cmax - cmin)
211  else:
212  color_value = 0.
213  bar.set_facecolor(cmap(color_value))
214  bar.set_linewidth(0.2)
215 
216  label_r = bottom + 8
217  for i in range(layer_nladders[layer]):
218  ax.text(
219  ladder_angles[i],
220  label_r,
221  str(i + 1),
222  ha='center',
223  va='center',
224  fontsize=6,
225  # color='k',
226  )
227  bottom += layer_gap * (1 + 0.5 * (layer == 2))
228 
229  ax.grid(False)
230  ax.axis('off')
231 
232  plt.title(parameter)
233 
234  # if we are done with shifts/rotations, collect some data
235  # for the colorbar
236  if shiftrot == 'shift':
237  par_shifts = (cmap, cmin, cmax, unit)
238  elif shiftrot == 'rotation':
239  par_rots = (cmap, cmin, cmax, unit)
240 
241  # Plot colorbars after rings are in place
242  axb1 = fig.add_axes([0.01, 0.55, 0.02, 0.33])
243  cmap, cmin, cmax, unit = par_shifts
244  norm1 = mpl.colors.Normalize(vmin=cmin, vmax=cmax)
245  cb1 = mpl.colorbar.ColorbarBase(axb1, cmap=cmap, norm=norm1, orientation='vertical')
246  cb1.set_label('Shifts ' + unit)
247  cb1.locator = ticker.MaxNLocator(nbins=11)
248  cb1.update_ticks()
249  # rotations
250  axb2 = fig.add_axes([0.01, 0.11, 0.02, 0.33])
251  cmap, cmin, cmax, unit = par_rots
252  norm2 = mpl.colors.Normalize(vmin=cmin, vmax=cmax)
253  cb2 = mpl.colorbar.ColorbarBase(axb2, cmap=cmap, norm=norm2, orientation='vertical')
254  cb2.set_label('Rotations ' + unit)
255  cb2.locator = ticker.MaxNLocator(nbins=11)
256  cb2.update_ticks()
257 
258  fig.suptitle(value, fontsize=20, x=0.01, y=0.95, horizontalalignment='left')
259  figname = inputroot + '.rigid.png'
260  savefig(figname)
261  print('Saved figure ' + figname)
262 
263 fig = plt.figure(figsize=(14, 6.5))
264 for value in components:
265  for shiftrot, i_params in zip(['surface2', 'surface3'], [[31, 32, 33], [41, 42, 43, 44]]):
266  cmin, cmax, cmap, unit = unit_scale[value][shiftrot]
267  for i_param in i_params:
268  parameter = param_map[i_param]
269  # Make a subframe
270  val_param = dataframe[['layer', 'ladder', 'sensor', value]][dataframe['parameter'] == i_param]
271  val_param[value] = val_param[value]
272  # Here comes the real thing
273  if shiftrot == 'surface2':
274  ax = subplot(2, 4, i_param-30, projection='polar')
275  if shiftrot == 'surface3':
276  ax = subplot(2, 4, i_param-36, projection='polar')
277  layer_gap = 24
278  bottom = 24 # starts at this, increases by sensor height in layers and layer_gap in between.
279  for layer in layers:
280  ladder_width = 2 * np.pi / layer_nladders[layer]
281  ladder_angles = np.linspace(layer_phi0[layer], layer_phi0[layer] + 2 * np.pi, layer_nladders[layer], endpoint=False)
282 
283  for sensor in range(1, 1 + layer_nsensors[layer]):
284  height = (layer > 3 and sensor == 1) * 10.0 + 28.0 / (1.0 + 0.3 * layer + 0.5 * sensor)
285  content = height * np.ones(layer_nladders[layer])
286  bars = ax.bar(
287  ladder_angles,
288  content,
289  width=ladder_width,
290  bottom=bottom,
291  label=str(sensor + 1),
292  align='center',
293  # edgecolor='k',
294  )
295  bottom += height
296  for (ladder, bar) in zip(range(1, 1 + layer_nladders[layer]), bars):
297  cond = (val_param.layer == layer) & (val_param.ladder == ladder) & (val_param.sensor == sensor)
298  try:
299  c = float(val_param[value][cond])
300  except BaseException:
301  c = 0.
302  if (cmax - cmin) > 0.:
303  color_value = (c - cmin) / (cmax - cmin)
304  else:
305  color_value = 0.
306  bar.set_facecolor(cmap(color_value))
307  bar.set_linewidth(0.2)
308 
309  label_r = bottom + 8
310  for i in range(layer_nladders[layer]):
311  ax.text(
312  ladder_angles[i],
313  label_r,
314  str(i + 1),
315  ha='center',
316  va='center',
317  fontsize=6,
318  color='k',
319  )
320  bottom += layer_gap * (1 + 0.5 * (layer == 2))
321 
322  ax.grid(False)
323  ax.axis('off')
324 
325  plt.title(parameter)
326 
327  # if we are done with shifts/rotations, collect some data
328  # for the colorbar
329  if shiftrot == 'surface2':
330  par_sur2 = (cmap, cmin, cmax, unit)
331  elif shiftrot == 'surface3':
332  par_sur3 = (cmap, cmin, cmax, unit)
333 
334  # Plot colorbars after rings are in place
335  axb1 = fig.add_axes([0.01, 0.55, 0.02, 0.33])
336  cmap, cmin, cmax, unit = par_sur2
337  norm1 = mpl.colors.Normalize(vmin=cmin, vmax=cmax)
338  cb1 = mpl.colorbar.ColorbarBase(axb1, cmap=cmap, norm=norm1, orientation='vertical')
339  cb1.set_label('Quadratic parameters ' + unit)
340  cb1.locator = ticker.MaxNLocator(nbins=11)
341  cb1.update_ticks()
342  # rotations
343  axb2 = fig.add_axes([0.01, 0.11, 0.02, 0.33])
344  cmap, cmin, cmax, unit = par_sur3
345  norm2 = mpl.colors.Normalize(vmin=cmin, vmax=cmax)
346  cb2 = mpl.colorbar.ColorbarBase(axb2, cmap=cmap, norm=norm2, orientation='vertical')
347  cb2.set_label('Cubic parameters ' + unit)
348  cb2.locator = ticker.MaxNLocator(nbins=11)
349  cb2.update_ticks()
350 
351  fig.suptitle(value, fontsize=20, x=0.01, y=0.95, horizontalalignment='left')
352 
353  figname = inputroot + '.surface.png'
354  savefig(figname)
355  print('Saved figure ' + figname)
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33