Belle II Software development
CreateSensorDisplacements.py
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4
11
12'''
13For SectorMaps running on data it significantly improves performance if the SectorMap is trained
14on the Geometry as it is in data. This script reads alignment data from a GT and compares the aligned
15Geometry with the not aligned Geomtry. The differences are written are written out in xml file
16format which can be directly used to create new Geometry payloads for SVD and PXD.
17Note you need to provide one or more global tags (or local DB) which contain the default geometry
18and alignement payloads to be used. Be careful that the IOVs do need to match (e.g. by editing the DB
19txt file for a local DB). See for example svd/scripts/dbImporters/create_SVDGeometryPar_payload.py
20'''
21
22import basf2
23from ROOT import Belle2
24import ROOT
25
26import argparse
27
28
29parser = argparse.ArgumentParser(description='Script that produces a xml file with \
30 sensor displacements to be used to create a DB payload. ')
31
32
33parser.add_argument(
34 '--localDB',
35 type=str,
36 default='',
37 dest="localDB",
38 help="The txt file defining a local DB (optional)."
39)
40
41parser.add_argument(
42 '--listOfGT',
43 nargs="*",
44 default=[],
45 dest="listOfGT",
46 help="List of global tag names separated by space (optional)."
47)
48
49parser.add_argument(
50 '--expNum',
51 type=int,
52 default='0',
53 dest="expNum",
54 help="The experiment number needed to pick correct IOV. (optional)."
55)
56
57parser.add_argument(
58 '--runNum',
59 type=int,
60 default='0',
61 dest="runNum",
62 help="The run number needed to pick correct IOV. (optional)"
63)
64
65args = parser.parse_args()
66
67
68if not args.localDB == '':
69 basf2.B2INFO('Prepending local DB: ' + args.localDB)
70 basf2.conditions.prepend_testing_payloads(args.localDB)
71
72
73for aGT in args.listOfGT:
74 basf2.B2INFO('Prepending global tag: ' + aGT)
75 basf2.conditions.prepend_globaltag(aGT)
76
77
78class Reader(basf2.Module):
79 """ Module to create misalignment (first reads real sensor positions, then applies misalignment and creates a xml file
80 suited for creating a DB payload). The DB payload itself is created by using the Geometry module by setting the
81 createPayloads to True.
82 """
83
84 def __init__(self):
85 ''' Init '''
86
87
88 self.sensors = dict()
89
90 super().__init__()
91
92 def event(self):
93 ''' event function '''
94 maxDiff = 0.0
95
96 for sensor in Belle2.VXD.GeoCache.getInstance().getListOfSensors():
97
98 info = Belle2.VXD.GeoCache.getInstance().get(sensor)
99
100 center = ROOT.TVector3(0., 0., 0.)
101
102 centerN = info.pointToGlobal(center, False)
103 centerA = info.pointToGlobal(center, True)
104
105 centerDiff = centerA - centerN
106
107 centerDiff = info.vectorToLocal(centerDiff, reco=False)
108
109 # it is easy to run without alignment (e.g. specifying wrong IOV or tag) try to catch that by
110 # checking that the displacementa are not 0
111 if (maxDiff < centerDiff.R()):
112 maxDiff = centerDiff.R()
113
114 # for now do not use rotations for sensors
115 phi = 0
116 psi = 0
117 theta = 0
118
119 self.sensors[f"{sensor.getLayerNumber()}.{sensor.getLadderNumber()}.{sensor.getSensorNumber()}"] = [
120 centerDiff.X(), centerDiff.Y(), centerDiff.Z(), phi, theta, psi]
121
122 if (maxDiff < 1e-9):
123 basf2.B2ERROR(f"Max occured displacements are smaller then 1e-9! Are you sure alignments constants \
124 are loaded correctly? max={maxDiff} cm")
125
126
127# reading displacements from the DB into a dictionary
128reader = Reader()
129
130path = basf2.create_path()
131path.add_module("EventInfoSetter", expList=[args.expNum], runList=[args.runNum], evtNumList=[1])
132path.add_module("Gearbox")
133path.add_module("Geometry")
134path.add_module(reader)
135basf2.process(path)
136
137sensors = reader.sensors
138
139
140allladders = [8, 12, 7, 10, 12, 16]
141allsensors = [2, 2, 2, 3, 4, 5]
142
143
144def a(xml, txt):
145 ''' Writes a single line into the xml file
146 @param xml the opened xml file to be written to
147 @param txt the line to be written
148 '''
149 xml.writelines([txt + "\n"])
150
151
152def c(xml, name, alig=None):
153 '''
154 Creates displacement information in the correct format to be written to the xml file.
155 @param the open xml file to be written to
156 @param name The name of the sensor which information is written
157 @param alig
158 '''
159 if alig is None:
160 alig = [0., 0., 0., 0., 0., 0.]
161 a(xml, "<Align component=\"" + name + "\">")
162 a(xml, f"<du unit=\"cm\" >{alig[0]}</du> <dv unit=\"cm\" > {alig[1]}</dv> <dw unit=\"cm\" >{alig[2]}</dw>")
163 a(xml, f"<alpha unit=\"rad\">{alig[3]}</alpha> <beta unit=\"rad\">{alig[4]}</beta> <gamma unit=\"rad\">{alig[5]}</gamma>")
164 a(xml, "</Align>")
165
166
167# write the PXD displacement into xml format
168with open("PXD-Alignment.xml", "w") as xml:
169
170 # write header
171 a(xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
172 a(xml, "<Alignment>")
173
174 # write global and halfshell displacements (none)
175 c(xml, "PXD")
176 c(xml, "PXD.Ying")
177 c(xml, "PXD.Yang")
178
179 # write displacement data for each sensor
180 for layer in [1, 2]:
181 c(xml, f"{layer}")
182 for ladder in range(1, allladders[layer - 1] + 1):
183 c(xml, f"{layer}.{ladder}")
184 for sensor in range(1, allsensors[layer - 1] + 1):
185 if f"{layer}.{ladder}.{sensor}" in sensors:
186 c(xml, f"{layer}.{ladder}.{sensor}", [v for v in sensors[f"{layer}.{ladder}.{sensor}"]])
187
188 # write outro
189 a(xml, "</Alignment>")
190
191
192# write all data for the SVD
193with open("SVD-Alignment.xml", "w") as xml:
194
195 # write header
196 a(xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
197 a(xml, "<Alignment>")
198
199 # write global and half shell displacement (none)
200 c(xml, "SVD")
201 c(xml, "SVD.Pat")
202 c(xml, "SVD.Mat")
203
204 # write displacement for each sensor
205 for layer in [3, 4, 5, 6]:
206 c(xml, f"{layer}")
207 for ladder in range(1, allladders[layer - 1] + 1):
208 c(xml, f"{layer}.{ladder}")
209 for sensor in range(1, allsensors[layer - 1] + 1):
210 if f"{layer}.{ladder}.{sensor}" in sensors:
211 c(xml, f"{layer}.{ladder}.{sensor}", [v for v in sensors[f"{layer}.{ladder}.{sensor}"]])
212
213 # write outro
214 a(xml, "</Alignment>")
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
sensors
dictionary to map the displacements for each sensor