Belle II Software  release-06-02-00
SVDValidationTTree.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 """
13 <header>
14  <contact> G. Caria, gcaria@student.unimelb.edu.au </contact>
15  <description>
16  This module is used for the SVD validation.
17  It gets information about truehits and clusters, saving
18  in a ttree in a ROOT file.
19  </description>
20 </header>
21 """
22 import math
23 
24 import basf2 as b2
25 
26 # Some ROOT tools
27 import ROOT
28 from ROOT import Belle2
29 from ROOT import gROOT, addressof
30 from ROOT import TVector3
31 
32 # Define a ROOT struct to hold output data in the TTree
33 gROOT.ProcessLine('struct EventData {\
34  int sensor_id;\
35  int layer;\
36  int ladder;\
37  int sensor;\
38  int sensor_type;\
39  int strip_dir;\
40  float strip_pitch;\
41  float cluster_theta;\
42  float cluster_phi;\
43  float cluster_position;\
44  float cluster_positionSigma;\
45  float cluster_clsTime;\
46  float cluster_clsTimeSigma;\
47  float cluster_charge;\
48  float cluster_seedCharge;\
49  float cluster_size;\
50  float cluster_snr;\
51  float cluster_interstripPosition;\
52  float cluster_pull;\
53  float cluster_residual;\
54  float truehit_position;\
55  float truehit_interstripPosition;\
56  float truehit_deposEnergy;\
57  float truehit_lossmomentum;\
58  float truehit_time;\
59  };')
60 
61 from ROOT import EventData # noqa
62 
63 
64 class SVDValidationTTree(b2.Module):
65  '''class to produced the validation ttree '''
66 
67  def __init__(self):
68  """Initialize the module"""
69 
70  super(SVDValidationTTree, self).__init__()
71 
72 
73  self.filefile = ROOT.TFile('../SVDValidationTTree.root', 'recreate')
74 
75  self.treetree = ROOT.TTree('tree', 'Event data of SVD validation events')
76 
77  self.datadata = EventData()
78 
79  # Declare tree branches
80  for key in EventData.__dict__:
81  if '__' not in key:
82  formstring = '/F'
83  if isinstance(self.datadata.__getattribute__(key), int):
84  formstring = '/I'
85  self.treetree.Branch(key, addressof(self.datadata, key), key + formstring)
86 
87  def beginRun(self):
88  """ Does nothing """
89 
90  def event(self):
91  """Find clusters with a truehit and save needed information"""
92 
93  # Start with clusters and use the relation to get the corresponding
94  # digit and truehits
95  clusters = Belle2.PyStoreArray('SVDClusters')
96  for cluster in clusters:
97  cluster_truehits = cluster.getRelationsTo('SVDTrueHits')
98  # We want only clusters with exactly one associated TrueHit
99  if len(cluster_truehits) != 1:
100  continue
101  for truehit in cluster_truehits:
102  sensorInfo = Belle2.VXD.GeoCache.get(cluster.getSensorID())
103  # Let's store some data
104  # Sensor identification
105  sensorID = cluster.getSensorID()
106  self.data.sensor_id = int(sensorID)
107  sensorNum = sensorID.getSensorNumber()
108  self.data.sensor = sensorNum
109  layerNum = sensorID.getLayerNumber()
110  self.data.layer = layerNum
111  if (layerNum == 3):
112  sensorType = 1
113  else:
114  if (sensorNum == 1):
115  sensorType = 0
116  else:
117  sensorType = 1
118  self.data.sensor_type = sensorType
119  ladderNum = sensorID.getLadderNumber()
120  self.data.ladder = ladderNum
121  # Cluster information
122  self.data.cluster_clsTime = cluster.getClsTime()
123  self.data.cluster_clsTimeSigma = cluster.getClsTimeSigma()
124  self.data.cluster_charge = cluster.getCharge()
125  self.data.cluster_seedCharge = cluster.getSeedCharge()
126  self.data.cluster_size = cluster.getSize()
127  self.data.cluster_snr = cluster.getSNR()
128  cluster_position = cluster.getPosition()
129  if cluster.isUCluster():
130  cluster_position = cluster.getPosition(truehit.getV())
131  # Interstrip position calculations
132  if cluster.isUCluster():
133  strip_dir = 0
134  strip_pitch = sensorInfo.getUPitch(truehit.getV())
135  else:
136  strip_dir = 1
137  strip_pitch = sensorInfo.getVPitch(truehit.getU())
138  self.data.strip_dir = strip_dir
139  self.data.strip_pitch = strip_pitch
140  cluster_interstripPosition = cluster_position % strip_pitch / strip_pitch
141  self.data.cluster_interstripPosition = cluster_interstripPosition
142  # theta and phi definitions
143  if cluster.isUCluster():
144  uPos = cluster_position
145  vPos = 0
146  else:
147  uPos = 0
148  vPos = cluster_position
149  localPosition = TVector3(uPos, vPos, 0) # sensor center at (0, 0, 0)
150  globalPosition = sensorInfo.pointToGlobal(localPosition, True)
151  x = globalPosition[0]
152  y = globalPosition[1]
153  z = globalPosition[2]
154  # see https://d2comp.kek.jp/record/242?ln=en for the Belle II
155  # coordinate system and related variables
156  rho = math.sqrt(x * x + y * y)
157  r = math.sqrt(x * x + y * y + z * z)
158  # get theta as arccosine(z/r)
159  thetaRadians = math.acos(z / r)
160  theta = (thetaRadians * 180) / math.pi
161  # get phi as arccosine(x/rho)
162  phiRadians = math.acos(x / rho)
163  if y < 0:
164  phi = 360 - (phiRadians * 180) / math.pi
165  else:
166  phi = (phiRadians * 180) / math.pi
167  self.data.cluster_theta = theta
168  self.data.cluster_phi = phi
169  # Pull calculations
170  clusterPos = cluster_position
171  clusterPosSigma = cluster.getPositionSigma()
172  if cluster.isUCluster():
173  truehitPos = truehit.getU()
174  else:
175  truehitPos = truehit.getV()
176  cluster_residual = clusterPos - truehitPos
177  cluster_pull = cluster_residual / clusterPosSigma
178  self.data.cluster_position = clusterPos
179  self.data.cluster_positionSigma = clusterPosSigma
180  self.data.cluster_residual = cluster_residual
181  self.data.cluster_pull = cluster_pull
182  # Truehit information
183  self.data.truehit_position = truehitPos
184  truehit_interstripPosition = truehitPos % strip_pitch / strip_pitch
185  self.data.truehit_interstripPosition = truehit_interstripPosition
186  self.data.truehit_deposEnergy = truehit.getEnergyDep()
187  self.data.truehit_lossmomentum = truehit.getEntryMomentum().Mag() - truehit.getExitMomentum().Mag()
188  self.data.truehit_time = truehit.getGlobalTime()
189  # Fill tree
190  self.file.cd()
191  self.tree.Fill()
192 
193  def terminate(self):
194  """Close the output file. """
195  self.filefile.cd()
196  self.filefile.Write()
197  self.filefile.Close()
a (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:56
static const SensorInfoBase & get(Belle2::VxdID id)
Return a reference to the SensorInfo of a given SensorID.
Definition: GeoCache.h:139