FairShip
Loading...
Searching...
No Matches
convertMisisMap.py
Go to the documentation of this file.
1#!/bin/python
2# SPDX-License-Identifier: LGPL-3.0-or-later
3# SPDX-FileCopyrightText: Copyright CERN for the benefit of the SHiP Collaboration
4
5
6# Python script to convert B field maps from MISIS text files into
7# ROOT files for FairShip. Text files are assumed to contain two
8# preamble lines giving the binning details and variable names, followed
9# by data lines x y z Bx By Bz, where the coordinates are assumed to
10# be in ascending z, y and x, in that order. Need distances in cm
11
12import ROOT
13
14# Struct for the ROOT file TTree data: coord range and field info
15
16ROOT.gROOT.ProcessLine(
17 "struct rangeStruct{\
18 float xMin;\
19 float xMax;\
20 float dx;\
21 float yMin;\
22 float yMax;\
23 float dy;\
24 float zMin;\
25 float zMax;\
26 float dz;\
27};"
28)
29# The field map is assumed to obey the following coordinate bin ordering:
30# z is increased first, y is increased 2nd, x is increased last.
31# So we only store the field components (x,y,z is known from the ordering).
32# For the coordinate bin (iX, iY, iZ), the field bin = (iX*Ny + iY)*Nz + iZ,
33# where Ny and Nz are the number of y and z bins
34
35ROOT.gROOT.ProcessLine(
36 "struct dataStruct{\
37 float Bx;\
38 float By;\
39 float Bz;\
40};"
41)
42
43
44def run(inFileName: str = "BFieldTest.txt", rootFileName: str = "BFieldTest.root") -> None:
45 createRootMap(inFileName, rootFileName)
46
47
48def createRootMap(inFileName, rootFileName) -> None:
49 print(f"Create ROOT map {rootFileName} from {inFileName}")
50
51 # Define ROOT file and its TTree
52 theFile = ROOT.TFile.Open(rootFileName, "recreate")
53
54 rangeTree = ROOT.TTree("Range", "Range")
55 rangeTree.SetDirectory(theFile)
56
57 # Coordinate ranges
58 rStruct = ROOT.rangeStruct()
59 rangeTree.Branch("xMin", ROOT.addressof(rStruct, "xMin"), "xMin/F")
60 rangeTree.Branch("xMax", ROOT.addressof(rStruct, "xMax"), "xMax/F")
61 rangeTree.Branch("dx", ROOT.addressof(rStruct, "dx"), "dx/F")
62 rangeTree.Branch("yMin", ROOT.addressof(rStruct, "yMin"), "yMin/F")
63 rangeTree.Branch("yMax", ROOT.addressof(rStruct, "yMax"), "yMax/F")
64 rangeTree.Branch("dy", ROOT.addressof(rStruct, "dy"), "dy/F")
65 rangeTree.Branch("zMin", ROOT.addressof(rStruct, "zMin"), "zMin/F")
66 rangeTree.Branch("zMax", ROOT.addressof(rStruct, "zMax"), "zMax/F")
67 rangeTree.Branch("dz", ROOT.addressof(rStruct, "dz"), "dz/F")
68
69 dataTree = ROOT.TTree("Data", "Data")
70 dataTree.SetDirectory(theFile)
71
72 # Field components with (x,y,z) coordinate binning ordered such that
73 # z, then y, then x is increased. For the coordinate bin (iX, iY, iZ),
74 # the field bin = (iX*Ny + iY)*Nz + iZ, where Ny and Nz are the number
75 # of y and z bins
76 dStruct = ROOT.dataStruct()
77 dataTree.Branch("Bx", ROOT.addressof(dStruct, "Bx"), "Bx/F")
78 dataTree.Branch("By", ROOT.addressof(dStruct, "By"), "By/F")
79 dataTree.Branch("Bz", ROOT.addressof(dStruct, "Bz"), "Bz/F")
80
81 # mm to cm conversion
82 mm2cm = 0.1
83 # m to cm conversion
84 m2cm = 100.0
85
86 # Open text file and process the information
87 iLine = 0
88
89 # Number of bins initialised by reading first line
90 Nx = 0
91 Ny = 0
92 Nz = 0
93
94 # Field centering coordinates
95 x0 = 0.0
96 y0 = 0.0
97 z0 = 0.0
98
99 with open(inFileName) as f:
100 for line in f:
101 iLine += 1
102
103 # First line contains ranges
104 if iLine == 1:
105 # Remove extraneous, unneeded symbols in the line
106 line = line.replace("[", "")
107 line = line.replace("]", "")
108 line = line.replace("mm", "")
109 sLine = line.split()
110
111 # Bin info line assumed to be formatted as:
112 # Grid Output Min: xMin yMin zMin Max: xMax yMax zMax Grid Size: dx dy dz
113 # These coordinate limits are in mm, but the actual data lines use m
114
115 print(f"sLine = {sLine}")
116 # For each value, convert from mm to cm
117 rStruct.xMin = float(sLine[3]) * mm2cm
118 rStruct.xMax = float(sLine[7]) * mm2cm
119 rStruct.dx = float(sLine[12]) * mm2cm
120 rStruct.yMin = float(sLine[4]) * mm2cm
121 rStruct.yMax = float(sLine[8]) * mm2cm
122 rStruct.dy = float(sLine[13]) * mm2cm
123 rStruct.zMin = float(sLine[5]) * mm2cm
124 rStruct.zMax = float(sLine[9]) * mm2cm
125 rStruct.dz = float(sLine[14]) * mm2cm
126
127 Nx = int(((rStruct.xMax - rStruct.xMin) / rStruct.dx) + 1.0)
128 Ny = int(((rStruct.yMax - rStruct.yMin) / rStruct.dy) + 1.0)
129 Nz = int(((rStruct.zMax - rStruct.zMin) / rStruct.dz) + 1.0)
130
131 print(f"Nx = {Nx}, Ny = {Ny}, Nz = {Nz}")
132
133 # Centre the field map on the local origin (cm)
134 x0 = 0.5 * (rStruct.xMin + rStruct.xMax)
135 y0 = 0.5 * (rStruct.yMin + rStruct.yMax)
136 z0 = 0.5 * (rStruct.zMin + rStruct.zMax)
137
138 print(f"Centering field map using coordinate shift {x0} {y0} {z0} cm")
139
140 # Center coordinate range limits (cm)
141 rStruct.xMin = rStruct.xMin - x0
142 rStruct.xMax = rStruct.xMax - x0
143
144 rStruct.yMin = rStruct.yMin - y0
145 rStruct.yMax = rStruct.yMax - y0
146
147 rStruct.zMin = rStruct.zMin - z0
148 rStruct.zMax = rStruct.zMax - z0
149
150 # Fill info into range tree
151 rangeTree.Fill()
152
153 # Field data values start from line 3
154 elif iLine > 2:
155 sLine = line.split()
156
157 # Bin centre coordinates (m to cm), with origin shift (cm)
158 dStruct.x = float(sLine[0]) * m2cm - x0
159 dStruct.y = float(sLine[1]) * m2cm - y0
160 dStruct.z = float(sLine[2]) * m2cm - z0
161
162 # B field components (Tesla)
163 dStruct.Bx = float(sLine[3])
164 dStruct.By = float(sLine[4])
165 dStruct.Bz = float(sLine[5])
166
167 dataTree.Fill()
168
169 theFile.cd()
170 rangeTree.Write()
171 dataTree.Write()
172 theFile.Close()
173
174
175if __name__ == "__main__":
176 run("BFieldTest.txt", "BFieldTest.root")
None createRootMap(inFileName, rootFileName)
None run(str inFileName="BFieldTest.txt", str rootFileName="BFieldTest.root")
int open(const char *, int)
Opens a file descriptor.