GeneralBrokenLines V03-01-01
using EIGEN
exampleComposedGeo.cpp
Go to the documentation of this file.
1/*
2 * exampleCdc.cpp
3 *
4 * Created on: 23 Mar 2023
5 * Author: kleinwrt
6 */
7
30#include <time.h>
31
32#include "exampleUtilCdc.h"
33#include "GblTrajectory.h"
34//#include <fstream>
35
36using namespace gbl;
37using namespace Eigen;
38
40
76
77 // detector setup, ~ Belle-II CDC
78 const unsigned int nSuper = 9; // number of super layers
79 double nLayer[nSuper] = { 8, 6, 6, 6, 6, 6, 6, 6, 6 }; // number of layers per super layer
80 double rInner[nSuper] = { 16.80, 25.70, 36.52, 47.69, 58.41, 69.53, 80.25,
81 91.37, 102.00 }; // inner radius of super layer
82 double rOuter[nSuper] = { 23.80, 34.80, 45.57, 56.69, 67.41, 78.53, 89.25,
83 100.37, 111.14 }; // outer radius of super layer
84 double stereo[nSuper] = { 0., 0.068, 0., -0.060, 0., 0.064, 0., -0.072, 0. }; // stereo angle of super layer
85 double zStart[nSuper] = { -35.9, -51.4, -57.5, -59.6, -61.8, -63.9, -66.0,
86 -68.2, -70.2 }; // -Z end of wires per super layer
87 double zEnd[nSuper] = { 67.9, 98.6, 132.9, 144.7, 146.8, 148.9, 151.0,
88 153.2, 155.3 }; // +Z end of wires per super layer
89
90 unsigned int nTry = 1000; //: number of tries
91 std::cout << " GblComposedGeo $Id$ " << nTry << ", " << nSuper << std::endl;
92 srand(4711);
93 clock_t startTime = clock();
94
95 const double bfac = 0.0045; // B*c for 1.5 T
96
97 double beamPos[] = { 0., 0., 0. };
98 double beamSize[] = { 0.005, 0.005, 0.3 };
99 const bool useBeamSpot = true;
100
101 MilleBinary mille; // for producing MillePede-II binary file
102
103 double Chi2Sum = 0.;
104 int NdfSum = 0;
105 double LostSum = 0.;
106 int numFit = 0;
107 unsigned int iEvent = 0;
108
109 // event loop
110 for (unsigned int iTry = 0; iTry < nTry; ++iTry) {
111 unsigned int nTrack;
112 std::vector<std::array<double, 6>> allGenPar; // collect parameters for generation of tracks
113
114 iEvent++;
115 // vertex
116 std::array<double, 3> vtx = { beamPos[0] + beamSize[0] * unrm(),
117 beamPos[1] + beamSize[1] * unrm(), beamPos[2]
118 + beamSize[2] * unrm() };
119 std::cout << " gen(vertex) " << iEvent << ": " << vtx[0] << " "
120 << vtx[1] << " " << vtx[2] << " " << std::endl;
121 // inline generation of track pair
122 nTrack = 2;
123 for (unsigned int iTrack = 0; iTrack < nTrack; ++iTrack) {
124
125 // helix parameter for track generation
126 const double qbyp = 0.2; // 5 GeV
127 const double genPhi0 = M_PI * (2. * unif() - 1.); // uniform, [-30..30] deg
128 const double genDzds = (2. * unif() - 1.); // uniform, lambda ~ [-45..45] deg
129 const double genCurv = bfac * qbyp * sqrt(1. + genDzds * genDzds);
130 // from common vertex
131 const double genDca = sin(genPhi0) * vtx[0] - cos(genPhi0) * vtx[1];
132 const double genZ0 = vtx[2];
133
134 std::cout << " gen(inline) " << iEvent << ": " << genCurv << " "
135 << genPhi0 << " " << genDca << " " << genDzds << " "
136 << genZ0 << std::endl;
137 std::array<double, 6> par = { genCurv, genPhi0, genDca, genDzds,
138 genZ0, 1. };
139 allGenPar.push_back(par);
140 }
141
142 std::vector<std::vector<GblPoint>> listsOfPoints;
143 std::vector<Matrix<double, 2, 3>> listOfTrafos;
144 for (unsigned int iTrack = 0; iTrack < nTrack; ++iTrack) {
145 //
146 // generate hits: (virtual) wires as detector layers at constant radii
147 //
148 std::array<double, 6> genPar = allGenPar[iTrack];
149 double curv(genPar[0]), phi0(genPar[1]), dca(genPar[2]), dzds(
150 genPar[3]), z0(genPar[4]);
151 // local constant (Bfield) helix
152 GblSimpleHelix hlx = GblSimpleHelix(curv, phi0, dca, dzds, z0);
153
154 std::vector<GblDetectorLayer> layers;
155
156 // beam spot (required as first (and common) point for composed trajectory)
157 double sArc = hlx.getArcLengthXY(beamPos[0], beamPos[1]);
158 // add virtual layer
159 layers.push_back(
160 CreateImpactPar("impact", 0, beamPos[0], beamPos[1],
161 beamPos[2], phi0 + sArc * curv, dzds, beamSize[0],
162 beamSize[1], beamSize[2]));
163
164 unsigned int cLayer = 0;
165 for (unsigned int iSuper = 0; iSuper < nSuper; ++iSuper) {
166 double radius = rInner[iSuper];
167 double step = (rOuter[iSuper] - radius) / (nLayer[iSuper] - 1);
168
169 for (unsigned int iLayer = 0; iLayer < nLayer[iSuper];
170 ++iLayer) {
171 // check for |dca| < radius
172 if (fabs(dca) < radius) {
173 // arc length to layer
174 double sArc = hlx.getArcLengthR(radius);
175 if (sArc == 0.)
176 goto theEnd;
177 // phi of position at layer
178 double phiPos = hlx.getPhi(radius);
179 // (virtual) wire position
180 double xPos(cos(phiPos) * radius), yPos(
181 sin(phiPos) * radius), zPos(z0 + sArc * dzds);
182 // add virtual wire
183 if (zPos > zStart[iSuper] and zPos < zEnd[iSuper])
184 layers.push_back(
185 CreateWireCdc("wire", ++cLayer, xPos, yPos,
186 zPos, phi0 + sArc * curv, dzds,
187 stereo[iSuper], 0.015));
188 }
189 // next layer
190 radius += step;
191 }
192 }
193 theEnd:
194
195 //
196 // create GBL trajectory (list of GBL points)
197 //
198 // seed (with true parameters)
199 std::array<double, 6> seedPar = allGenPar[iTrack];
200 // optionally distort seed
201 //seedPar[0] += 0.01 * seedPar[0] * iTrack;
202 //seedPar[1] += 0.001 * iTrack; // different distortions per track
203 //seedPar[2] += 0.001 * iTrack; // different distortions per track
204 double seedCurv(seedPar[0]), seedPhi0(seedPar[1]), seedDca(
205 seedPar[2]), seedDzds(seedPar[3]), seedZ0(seedPar[4]);
206 GblSimpleHelix seed = GblSimpleHelix(seedCurv, seedPhi0, seedDca,
207 seedDzds, seedZ0);
208 // (previous) arc-length
209 double sOld = 0.;
210 const double cosLambdaSeed = 1. / sqrt(1. + (seedDzds * seedDzds));
211 // for multiple scattering (not (yet) implemented)
212 const double qbyp = seedCurv / bfac * cosLambdaSeed;
213
214 // transformations to common POSITION parameters (at vertex) of composed trajectory at first point
215 Matrix<double, 2, 3> innerTrafo = Matrix<double, 2, 3>::Zero();
216 // common parameters (offsets in curvilinear system)
217 innerTrafo(0, 0) = -sin(seedPhi0); // u vs vtx
218 innerTrafo(0, 1) = cos(seedPhi0); // u vs vty
219 innerTrafo(1, 0) = -cos(seedPhi0) * cosLambdaSeed * seedDzds; // v vs vtx
220 innerTrafo(1, 1) = -sin(seedPhi0) * cosLambdaSeed * seedDzds; // v vs vty
221 innerTrafo(1, 2) = cosLambdaSeed; // v vs vtz
222
223 listOfTrafos.push_back(innerTrafo);
224
225 // list of points on trajectory
226 std::vector<GblPoint> listOfPoints;
227 for (unsigned int iLayer = 0; iLayer < layers.size(); ++iLayer) {
228 GblDetectorLayer &layer = layers[iLayer];
229 unsigned int lid = layer.getLayerID(); // layer ID (0 = vertex)
230 // std::cout << " hit " << lid << " " << hits[iLayer].transpose() << std::endl;
231 // prediction from seeding helix
232 GblHelixPrediction pred = layer.intersectWithHelix(seed);
233 double sArc = pred.getArcLength(); // arc-length
234 Vector2d measPrediction = pred.getMeasPred(); // measurement prediction
235 Vector2d measPrecision = layer.getPrecision(); // measurement precision
236 // residuals
237 Vector2d res = measPrediction; // (virtual) wire positioned at measurement
238 // smear u according to resolution
239 Vector2d sigma = layer.getResolution();
240 if (lid > 0) // wire layer?
241 res[0] += sigma[0] * unrm();
242 else
243 std::cout << " impact par " << res[0] << " " << res[1]
244 << " " << seedCurv << " " << seedPhi0 << " "
245 << seedDca << " " << seedDzds << " " << seedZ0
246 << " " << sArc << " " << layers.size() << std::endl;
247 // transformation global system to local (curvilinear) (u,v) (matrix from row vectors)
248 Matrix<double, 2, 3> transG2l = pred.getCurvilinearDirs();
249 // transformation measurement system to global system
250 Matrix3d transM2g = layer.getMeasSystemDirs().inverse();
251 // projection matrix (measurement plane to local (u,v))
252 Matrix2d proM2l = transG2l * transM2g.block<3, 2>(0, 0); // skip measurement normal
253 // projection matrix (local (u,v) to measurement plane)
254 Matrix2d proL2m = proM2l.inverse();
255 // propagation
256 Matrix5d jacPointToPoint = gblSimpleJacobian(
257 (sArc - sOld) / cosLambdaSeed, cosLambdaSeed, bfac);
258 sOld = sArc;
259 // point with (independent) measurements (in measurement system)
260 GblPoint point(jacPointToPoint);
261 if (lid > 0 or (iTrack == 0 and useBeamSpot)) // vertex only for first track (large correlations!)
262 point.addMeasurement(proL2m, res, measPrecision);
263 // global labels and parameters for rigid body alignment
264 if (lid > 0) {
265
266 std::vector<int> labGlobal(6);
267 Vector3d pos = pred.getPosition();
268 Vector3d dir = pred.getDirection();
269 /* Layer alignment in local (measurement) system
270 for (int p = 0; p < 6; p++)
271 labGlobal[p] = (iLayer + 1) * 10 + p + 1;
272 Matrix<double, 2, 6> derGlobal = layer.getRigidBodyDerLocal(pos,
273 dir);
274 */
275 // Chamber alignment in global system
276 unsigned int layerID = layer.getLayerID();
277 for (int p = 0; p < 6; p++)
278 labGlobal[p] = layerID * 1000 + p + 1; // layer alignment
279 Matrix<double, 2, 6> derGlobal =
280 layer.getRigidBodyDerGlobal(pos, dir).block<2, 6>(0,
281 0);
282 point.addGlobals(labGlobal, derGlobal);
283 // add scatterer to point
284 double radlen = layer.getRadiationLength()
285 / fabs(pred.getCosIncidence());
286 double errMs = gblMultipleScatteringError(qbyp, radlen); // simple model
287 if (errMs > 0.) {
288 Vector2d scat(0., 0.);
289 Vector2d scatPrec(1. / (errMs * errMs),
290 1. / (errMs * errMs)); // scattering precision matrix is diagonal in curvilinear system
291 point.addScatterer(scat, scatPrec);
292 }
293 }
294 // add point to trajectory
295 listOfPoints.push_back(point);
296 }
297 listsOfPoints.push_back(listOfPoints);
298 }
299
300 // require 2 decent trajectories for composed trajectory
301 unsigned int nAccepted = 0;
302 for (unsigned int iTrack = 0; iTrack < nTrack; ++iTrack)
303 // sufficient length?
304 if (listsOfPoints[iTrack].size() >= 10)
305 nAccepted++;
306 if (nAccepted != 2)
307 continue;
308
309 // prepare composed trajectory
310 std::vector<std::pair<std::vector<GblPoint>, MatrixXd> > aPointsAndTransList;
311 for (unsigned int iTrack = 0; iTrack < nTrack; ++iTrack) {
312 aPointsAndTransList.push_back(
313 make_pair(listsOfPoints[iTrack], listOfTrafos[iTrack]));
314 }
315 //
316 // fit composed GBL trajectory
317 //
318
319 // create trajectory
320 GblTrajectory traj(aPointsAndTransList);
321 //std::cout << " Trajectory contructed: " << traj.isValid() << std::endl;
322 // fit trajectory
323 double Chi2;
324 int Ndf;
325 double lostWeight;
326 unsigned int ierr = traj.fit(Chi2, Ndf, lostWeight);
327 std::cout << " Fit " << iTry << ": " << Chi2 << ", " << Ndf << ", "
328 << lostWeight << std::endl;
329 traj.printTrajectory();
330 //traj.printData();
331 // successfully fitted?
332 if (!ierr) {
333 // write to MP binary file
334 traj.milleOut(mille);
335 // update statistics
336 Chi2Sum += Chi2;
337 NdfSum += Ndf;
338 LostSum += lostWeight;
339 numFit++;
340 /* look at (track parameter) corrections
341 VectorXd aCorrection(5);
342 MatrixXd aCovariance(5, 5);
343 traj.getResults(1, aCorrection, aCovariance);
344 std::cout << " cor1 " << std::endl << aCorrection << std::endl;
345 std::cout << " cov1 " << std::endl << aCovariance << std::endl;
346 */
347 }
348
349 }
350
351 clock_t endTime = clock();
352 double diff = endTime - startTime;
353 double cps = CLOCKS_PER_SEC;
354 std::cout << " Time elapsed " << diff / cps << " s" << std::endl;
355 std::cout << " Chi2/Ndf = " << Chi2Sum / NdfSum << std::endl;
356 std::cout << " Tracks fitted " << numFit << std::endl;
357 if (LostSum > 0.)
358 std::cout << " Weight lost " << LostSum << std::endl;
359}
360
GblTrajectory definition.
Detector layer.
Definition: GblUtilities.h:107
GblHelixPrediction intersectWithHelix(GblSimpleHelix hlx) const
Intersect with helix.
double getRadiationLength() const
Get radiation length.
unsigned int getLayerID() const
Get layer ID.
Eigen::Matrix3d getMeasSystemDirs() const
Get directions of measurement system.
Eigen::Matrix< double, 3, 6 > getRigidBodyDerGlobal(Eigen::Vector3d &position, Eigen::Vector3d &direction) const
Get rigid body derivatives in global frame.
Eigen::Vector2d getResolution() const
Get resolution.
Eigen::Vector2d getPrecision() const
Get precision.
Prediction on helix.
Definition: GblUtilities.h:49
Eigen::Matrix< double, 2, 3 > getCurvilinearDirs() const
Get curvilinear directions (U,V)
double getArcLength() const
Get arc-length.
const Eigen::Vector2d & getMeasPred() const
Get (measurement) prediction.
double getCosIncidence() const
Get cosine of incidence.
const Eigen::Vector3d & getPosition() const
Get position.
const Eigen::Vector3d & getDirection() const
Get position.
Point on trajectory.
Definition: GblPoint.h:62
void addMeasurement(const Eigen::MatrixBase< Projection > &aProjection, const Eigen::MatrixBase< Residuals > &aResiduals, const Eigen::MatrixBase< Precision > &aPrecision, double minPrecision=0.)
Add a measurement to a point.
Definition: GblPoint.h:238
void addGlobals(const std::vector< int > &aLabels, const Eigen::MatrixBase< Derivative > &aDerivatives)
Add global derivatives to a point.
Definition: GblPoint.h:293
void addScatterer(const Eigen::Vector2d &aResiduals, const Eigen::Matrix2d &aPrecision)
Add a thin scatterer to a point.
Definition: GblPoint.cpp:159
Simple helix.
Definition: GblUtilities.h:78
double getArcLengthR(double aRadius) const
Get (2D) arc length for given radius (to ref. point)
double getPhi(double aRadius) const
Get phi (of point on circle) for given radius (to ref. point)
double getArcLengthXY(double xPos, double yPos) const
Get (2D) arc length for given point.
GBL trajectory.
Definition: GblTrajectory.h:50
void printTrajectory(unsigned int level=0) const
Print GblTrajectory.
void milleOut(MilleBinary &aMille)
Write valid trajectory to Millepede-II binary file.
unsigned int fit(double &Chi2, int &Ndf, double &lostWeight, const std::string &optionList="", unsigned int aLabel=0)
Perform fit of (valid) trajectory.
Millepede-II (binary) record.
Definition: MilleBinary.h:81
void exampleComposedGeo()
Drift chamber example.
Definitions for exampleUtil(ities) for a Cylindrical Drift Chamber.
Namespace for the general broken lines package.
GblDetectorLayer CreateWireCdc(const std::string aName, unsigned int layer, double xPos, double yPos, double zPos, double phi, double tanLambda, double stereoAngle, double uRes)
Create a drift chamber wire with 1D measurement.
double unrm()
unit normal distribution, Box-Muller method, polar form
double gblMultipleScatteringError(double qbyp, double xbyx0)
Multiple scattering error.
GblDetectorLayer CreateImpactPar(const std::string aName, unsigned int layer, double xPos, double yPos, double zPos, double phi, double tanLambda, double xRes, double yRes, double zRes)
Create detector plane for impact parameters as 2D measurement.
double unif()
uniform distribution [0..1]
Matrix5d gblSimpleJacobian(double ds, double cosl, double bfac)
Simple jacobian.
Eigen::Matrix< double, 5, 5 > Matrix5d
Definition: GblData.h:46