Belle II Software  release-06-02-00
PXDHitErrors.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 import math
13 import basf2 as b2
14 
15 # Some ROOT tools
16 import ROOT
17 from ROOT import Belle2
18 
19 
20 class PXDHitErrors(b2.Module):
21 
22  """A simple module to check the reconstruction of PXDTrueHits."""
23 
24  def __init__(self):
25  """Initialize the module"""
26 
27  super(PXDHitErrors, self).__init__()
28 
29  self.filefile = open('PXDHitErrorOutput.txt', 'w')
30 
31  self.vxdid_factorsvxdid_factors = (8192, 256, 32)
32 
33  self.fHistofHisto = ROOT.TFile('PXDPulls.root', 'RECREATE')
34 
35  self.h_pull_uh_pull_u = ROOT.TH1F('h_pull_u', 'Pulls in u', 150, -10, 5)
36 
37  self.h_pull_vh_pull_v = ROOT.TH1F('h_pull_v', 'Pulls in v', 100, -5, 5)
38 
39  def beginRun(self):
40  """ Write legend for file columns """
41 
42  self.filefile.write('vxd.id layer ladder sensor truehit.index cluster.index ')
43  self.filefile.write('truehit.u truehit.v truehit.time truehit.charge theta.u theta.v ')
44  self.filefile.write('u v u.error v.error rho charge seed size u.size v.size u.pull v.pull\n')
45 
46  def event(self):
47  """Find clusters with a truehit and print some stats."""
48 
49  truehits = Belle2.PyStoreArray('PXDTrueHits')
50  # nTruehits = truehits.getEntries()
51  clusters = Belle2.PyStoreArray('PXDClusters')
52  nClusters = clusters.getEntries()
53  # digits = Belle2.PyStoreArray('PXDDigits')
54  # nDigits = digits.getEntries()
55  relClustersToTrueHits = \
56  Belle2.PyRelationArray('PXDClustersToPXDTrueHits')
57  # nClusterRelations = relClustersToTrueHits.getEntries()
58  # relClustersToDigits = Belle2.PyRelationArray('PXDClustersToPXDDigits')
59  # nDigitRelations = relClustersToDigits.getEntries()
60 
61  # Start with clusters and use the relation to get the corresponding
62  # digits and truehits.
63  for cluster_index in range(nClusters):
64  cluster = clusters[cluster_index]
65  cluster_truehits = \
66  relClustersToTrueHits.getToIndices(cluster_index)
67 
68  # Here we ask only for clusters with exactly one TrueHit.
69  # We don't want combined clusters!
70  if len(cluster_truehits) != 1:
71  continue
72 
73  for truehit_index in cluster_truehits:
74  truehit = truehits[truehit_index]
75  # Now let's store some data
76  s = ''
77  # Sesnor identification
78  sensorID = truehit.getRawSensorID()
79  [layer, ladder, sensor] = self.decodedecode(sensorID)
80 
81  s_id = '{sID} {layer} {ladder} {sensor} {indexT:4d} {indexC:4d} '.format(
82  sID=sensorID,
83  layer=layer,
84  ladder=ladder,
85  sensor=sensor,
86  indexT=truehit_index,
87  indexC=cluster_index,
88  )
89  s += s_id
90  # TrueHit information
91  thetaU = math.atan2(truehit.getExitU() - truehit.getEntryU(),
92  0.0075)
93  thetaV = math.atan2(truehit.getExitV() - truehit.getEntryV(),
94  0.0075)
95  s_th = '{uTH:10.5f} {vTH:10.5f} {tTH:10.2f} {eTH:10.7f} '.format(
96  uTH=truehit.getU(), vTH=truehit.getV(), tTH=truehit.getGlobalTime(),
97  eTH=truehit.getEnergyDep()) + '{thetaU:6.3f} {thetaV:6.3f} '.format(thetaU=thetaU, thetaV=thetaV)
98  s += s_th
99  # Cluster information
100  cluster_pull_u = 0
101  cluster_pull_v = 0
102  try:
103  cluster_pull_u = (cluster.getU() - truehit.getU()) \
104  / cluster.getUSigma()
105  cluster_pull_v = (cluster.getV() - truehit.getV()) \
106  / cluster.getVSigma()
107  except ZeroDivisionError:
108  if cluster.getUSigma() < 1.0e-8:
109  b2.B2ERROR('Zero error in u, clsize {cl}.'.format(cl=cluster.getUSize()))
110  else:
111  b2.B2ERROR('Zero error in v, clsize {cl}.'.format(cl=cluster.getVSize()))
112 
113  s_cl = \
114  '{u:10.5f} {v:10.5f} {uEr:10.5f} {vEr:10.5f} {rho:10.4f} '.format(
115  u=cluster.getU(), v=cluster.getV(), uEr=cluster.getUSigma(),
116  vEr=cluster.getVSigma(), rho=cluster.getRho()) \
117  + '{eC:9.1f} {eSeed:9.1f} {size:5d} {uSize:5d} {vSize:5d} '.format(
118  eC=cluster.getCharge(), eSeed=cluster.getSeedCharge(), size=cluster.getSize(),
119  uSize=cluster.getUSize(), vSize=cluster.getVSize()) \
120  + '{uPull:10.3f} {vPull:10.3f}'.format(
121  uPull=cluster_pull_u, vPull=cluster_pull_v)
122  s += s_cl
123  # NO DIGITS by now.
124  s += '\n'
125  self.filefile.write(s)
126  if cluster.getUSize() == 2:
127  self.h_pull_uh_pull_u.Fill(cluster_pull_u)
128  if cluster.getVSize() == 2:
129  self.h_pull_vh_pull_v.Fill(cluster_pull_v)
130 
131  def terminate(self):
132  """ Close the output file."""
133 
134  self.filefile.close()
135  # Save histograms to file
136  self.fHistofHisto.cd()
137  self.h_pull_uh_pull_u.Write()
138  self.h_pull_vh_pull_v.Write()
139  self.fHistofHisto.Flush()
140  self.fHistofHisto.Close()
141 
142  def decode(self, vxdid):
143  """ Utility to decode sensor IDs """
144 
145  result = []
146  for f in self.vxdid_factorsvxdid_factors:
147  result.append(vxdid / f)
148  vxdid = vxdid % f
149 
150  return result
a (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:56
file
Input file object.
Definition: PXDHitErrors.py:29
def decode(self, vxdid)
vxdid_factors
Factors for decoding VXDId's.
Definition: PXDHitErrors.py:31
h_pull_v
Histogram for v pulls.
Definition: PXDHitErrors.py:37
h_pull_u
Histogram for u pulls.
Definition: PXDHitErrors.py:35
fHisto
File to save histograms.
Definition: PXDHitErrors.py:33