5 Scripts and functions to set the BeamParameters from known configurations
8 from basf2
import B2FATAL, B2INFO
13 beamparameter_defaults = {
32 beamparameter_presets = {
44 "covHER": np.array([0.00513]) ** 2,
45 "covLER": np.array([0.002375]) ** 2,
47 "bunchHER": np.array([10.2e-3, 59e-6, 6.0]) * 1e-1,
48 "bunchLER": np.array([7.75e-3, 59e-6, 5.0]) * 1e-1,
50 "Y1S": (
"SuperKEKB", {
54 "Y2S": (
"SuperKEKB", {
58 "Y3S": (
"SuperKEKB", {
62 "Y4S": (
"SuperKEKB", {
66 "Y5S": (
"SuperKEKB", {
90 "Y1D1": (
"SuperKEKB", {
94 "Y2D1": (
"SuperKEKB", {
98 "Y6S": (
"SuperKEKB", {
102 "Yb10775": (
"SuperKEKB", {
106 "KEKB-Belle": (
None, {
107 "energyHER": 7.998213,
108 "energyLER": 3.499218,
116 "energyHER": 1.02 / 2.,
117 "energyLER": 1.02 / 2.,
122 def __get_4vector(energy, angle):
123 """Calculate an 4vector for electron/positron from energy and angle"""
126 pz = (energy ** 2 - m ** 2) ** .5
127 v = ROOT.Math.PxPyPzEVector(0, 0, pz, energy)
129 angle = math.pi + angle
130 rotationY = ROOT.Math.RotationY(angle)
135 def rot_matrix_y(angle):
136 """Return rotation matrix for a rotation of angle around the y-axis"""
139 return np.matrix([(c, 0, s), (0, 1, 0), (-s, 0, c)])
142 def cov_matrix(beamsize, angle):
143 """Return the covariance matrix for the given bunch size and angle with
144 respect to the z axis"""
146 angle = math.pi + angle
147 rot = rot_matrix_y(angle)
148 cov = np.matrix(np.diag(beamsize ** 2))
149 return rot * cov * rot.T
152 def calculate_beamspot(pos_her, pos_ler, size_her, size_ler, angle_her, angle_ler):
154 Function to calculate position and covariance matrix of the beamspot.
156 This function calculates the mean position and the covariance matrix for the
157 beamspot from the bunch positions, bunch sizes and the angles of the beam
158 with respect to the z-axis. It assumes normal distributed bunch densities and
159 multiplies the PDFs for the two bunches to get a resulting beamspot
161 negative angles are interpreted as "math.pi - abs(angle)"
164 pos_her (list): mean position of the HER bunch (in cm)
165 pos_ler (list): mean position of the LER bunch (in cm)
166 size_her (list): HER bunch size in cm
167 size_ler (list): LER bunch size in cm
168 angle_her (float): angle between HER direction and z-axis
169 angle_her (float): angle between LER direction and z-axis
172 pos (array): array (x, y, z) with the spot center in cm
173 cov (matrix): covariance matrix of the beam spot
176 cov_her = cov_matrix(size_her, angle_her)
177 cov_ler = cov_matrix(size_ler, angle_ler)
179 cov_sum_i = (cov_her + cov_ler).I
182 cov_spot = cov_her * cov_sum_i * cov_ler
183 beampos_spot = np.array(
184 cov_ler * cov_sum_i * np.matrix(pos_her).T +
185 cov_her * cov_sum_i * np.matrix(pos_ler).T
187 return beampos_spot, cov_spot
190 def add_beamparameters(path, name, E_cms=None, **argk):
191 """Add BeamParameter module to a given path
194 path (basf2.Path instance): path to add the module to
195 name (str): name of the beamparameter settings to use
196 E_cms (float): center of mass energy. If not None the beamenergies will
197 be scaled accordingly to achieve E_cms
199 Additional keyword arguments will be passed directly to the module as parameters.
202 values = calculate_beamparameters(name, E_cms)
204 module = path.add_module(
"BeamParameters")
205 module.set_name(
"BeamParameters:%s" % name)
213 def calculate_beamparameters(name, E_cms=None):
214 """Get/calculate the necessary beamparameter values from the given preset name,
215 optionally scale it to achieve the given cms energy
218 name (str): name of the beamparameter settings to use
219 E_cms (float): center of mass energy. If not None the beamenergies will
220 be scaled accordingly to achieve E_cms
222 if name
not in beamparameter_presets:
223 B2FATAL(
"Unknown beamparameter preset: '%s', use one of %s" %
224 (name,
", ".join(sorted(beamparameter_presets.keys()))))
228 values = beamparameter_defaults.copy()
233 def collect_values(preset, name):
234 parent, values = beamparameter_presets[name]
235 if parent
is not None:
236 collect_values(preset, parent)
237 preset.update(values)
239 collect_values(preset, name)
242 for k
in values.keys():
244 if isinstance(preset[k], np.ndarray):
245 values[k] = list(preset[k].flat)
247 values[k] = preset[k]
250 if "bunchHER" in preset
and "bunchLER" in preset:
251 her_size = preset[
"bunchHER"]
252 ler_size = preset[
"bunchLER"]
253 her_angle = values[
"angleXHER"]
254 ler_angle = values[
"angleXLER"]
255 _, cov = calculate_beamspot(
256 [0, 0, 0], [0, 0, 0], her_size, ler_size, her_angle, ler_angle
258 values[
"covVertex"] = list(cov.flat)
260 if E_cms
is not None:
261 ler = __get_4vector(values[
"energyLER"], values[
"angleXLER"])
262 her = __get_4vector(values[
"energyHER"], values[
"angleXHER"])
263 mass = (her + ler).M()
265 B2INFO(
"Scaling beam energies by %g to obtain E_cms = %g GeV" % (scale, E_cms))
266 values[
"energyHER"] *= scale
267 values[
"energyLER"] *= scale
272 if __name__ ==
"__main__":
276 np.set_printoptions(precision=3)
280 values = beamparameter_presets[
"SuperKEKB"][1]
281 beampos_spot, cov_spot = calculate_beamspot(
282 [0, 0, 0], [0, 0, 0],
283 values[
"bunchHER"], values[
"bunchLER"],
284 values[
"angleXHER"], values[
"angleXLER"],
286 print(
"Beamspot position:")
288 print(
"Beamspot covariance:")
290 print(
"Beamspot dimensions (in mm, axes in arbitary order):")
291 print(np.linalg.eig(cov_spot)[0] ** .5 * 10)
295 from matplotlib
import pyplot
as pl
297 cov_her = cov_matrix(values[
"bunchHER"], values[
"angleXHER"])
299 cov_ler = cov_matrix(values[
"bunchLER"], values[
"angleXLER"])
301 points_her = np.random.multivariate_normal([0, 0, 0], cov_her, 1000)
303 points_ler = np.random.multivariate_normal([0, 0, 0], cov_ler, 1000)
305 points_spot = np.random.multivariate_normal(beampos_spot, cov_spot, 1000)
306 pl.scatter(points_her[:, 2], points_her[:, 0], s=5, marker=
".", c=
"b", edgecolors=
"None", label=
"HER")
307 pl.scatter(points_ler[:, 2], points_ler[:, 0], s=5, marker=
".", c=
"r", edgecolors=
"None", label=
"LER")
308 pl.scatter(points_spot[:, 2], points_spot[:, 0], s=5, marker=
".", c=
"g", edgecolors=
"None", label=
"spot")
318 eher = values[
"energyHER"]
320 eler = values[
"energyLER"]
322 aher = values[
"angleXHER"]
324 aler = values[
"angleXLER"]
329 ler = __get_4vector(eher, aher)
331 her = __get_4vector(eler, aler)
333 mass = (her + ler).M()
334 print(
"Nominal CMS Energy: ", mass)
344 for name, energy
in sorted(targets.items()):
346 scale = energy / mass
348 "%s": ("SuperKEKB", { # m(%s) = %.3f GeV
351 }),""" % (name, name, energy, eher * scale, eler * scale))
353 for name, energy
in sorted(targets.items()):
355 scale = (energy - 60e-3) / mass
357 "%s-off": ("%s", { # m(%s) - 60 MeV = %.3f GeV
360 }),""" % (name, name, name, energy - 60e-3, eher * scale, eler * scale))