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