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