GeneralBrokenLines V03-01-03
using EIGEN
exampleDc.cpp
Go to the documentation of this file.
1/*
2 * exampleDc.cpp
3 *
4 * Created on: 6 Nov 2018
5 * Author: kleinwrt
6 */
7
30#include <time.h>
31#include "exampleDc.h"
32#include "GblTrajectory.h"
33
34using namespace gbl;
35using namespace Eigen;
36
38
90void exampleDc() {
91
92 // detector layers (ordered in Z):
93 // name, position (x,y,z), thickness (X/X_0), xz-angle, stereo-angle, resolution
94 double thickness[12];
95 thickness[0] = 0.0025; // gas, wire, wall
96 for (unsigned int iLayer = 1; iLayer < 11; ++iLayer)
97 thickness[iLayer] = 0.0005; // gas, wire
98 thickness[11] = 0.0025; // gas, wire, wall
99 // list of layers
100 std::vector<GblDetectorLayer> layers;
101 const double theta(25.), cosTheta(cos(theta / 180. * M_PI)), sinTheta(
102 sin(theta / 180. * M_PI));
103 // 1. chamber at distance of 200 cm
104 double dist = 200.;
105 for (unsigned int iLayer = 0; iLayer < 6; ++iLayer) {
106 layers.push_back(
107 CreateLayerDc("CH1+", 100, dist * sinTheta, 0.0, dist * cosTheta,
108 thickness[iLayer], theta, 6., 0.030)); // +6 deg stereo layers
109 dist += 2.;
110 }
111 for (unsigned int iLayer = 6; iLayer < 12; ++iLayer) {
112 layers.push_back(
113 CreateLayerDc("CH1-", 100, dist * sinTheta, 0.0, dist * cosTheta,
114 thickness[iLayer], theta, -6., 0.030)); // -6 deg stereo layers
115 dist += 2.;
116 }
117 // 2. chamber at distance of 300 cm
118 dist = 300.;
119 for (unsigned int iLayer = 0; iLayer < 6; ++iLayer) {
120 layers.push_back(
121 CreateLayerDc("CH2+", 200, dist * sinTheta, 0.0, dist * cosTheta,
122 thickness[iLayer], theta, 6., 0.030)); // +6 deg stereo layers
123 dist += 2.;
124 }
125 for (unsigned int iLayer = 6; iLayer < 12; ++iLayer) {
126 layers.push_back(
127 CreateLayerDc("CH2-", 200, dist * sinTheta, 0.0, dist * cosTheta,
128 thickness[iLayer], theta, -6., 0.030)); // -6 deg stereo layers
129 dist += 2.;
130 }
131 // 3. chamber at distance of 400 cm
132 dist = 400.;
133 for (unsigned int iLayer = 0; iLayer < 6; ++iLayer) {
134 layers.push_back(
135 CreateLayerDc("CH3+", 300, dist * sinTheta, 0.0, dist * cosTheta,
136 thickness[iLayer], theta, 6., 0.030)); // +6 deg stereo layers
137 dist += 2.;
138 }
139 for (unsigned int iLayer = 6; iLayer < 12; ++iLayer) {
140 layers.push_back(
141 CreateLayerDc("CH3-", 300, dist * sinTheta, 0.0, dist * cosTheta,
142 thickness[iLayer], theta, -6., 0.030)); // -6 deg stereo layers
143 dist += 2.;
144 }
145
146 /* print layers
147 for (unsigned int iLayer = 0; iLayer < layers.size(); ++iLayer) {
148 layers[iLayer].print();
149 } */
150
151 // Alignment with MillePede-II requires for alignables with a single 1D measurements to fix the unmeasured
152 // direction with a (linear equality) constraint (unless alignment equal to measurement system).
153 std::cout
154 << "! MillePede-II: constraints for alignables with SINGLE 1D measurements"
155 << std::endl;
156 for (unsigned int iLayer = 0; iLayer < layers.size(); ++iLayer) {
157 // count number of measurements per alignable
158 unsigned int numMeas = 0;
159 for (unsigned int jLayer = 0; jLayer < layers.size(); ++jLayer) {
160 if (layers[iLayer].getLayerID() == layers[jLayer].getLayerID())
161 numMeas++;
162 }
163 // alignable with single measurement
164 if (numMeas == 1)
165 layers[iLayer].printMP2Constraint();
166 }
167 std::cout << "! End of lines to be added to MillePede-II steering file"
168 << std::endl;
169 std::cout << std::endl;
170
171 unsigned int nTry = 10000; //: number of tries
172 std::cout << " GblDc $Id$ " << nTry << ", " << layers.size() << std::endl;
173 srand(4711);
174 clock_t startTime = clock();
175
176 double qbyp = 0.2; // 5 GeV
177 // const double bfac = 0.003; // B*c for 1 T
178 const double bfac = 0.; // B*c for 0 T
179
180 MilleBinary mille; // for producing MillePede-II binary file
181
182 double Chi2Sum = 0.;
183 int NdfSum = 0;
184 double LostSum = 0.;
185 int numFit = 0;
186
187 for (unsigned int iTry = 0; iTry < nTry; ++iTry) {
188
189 // helix parameter for track generation
190 const double genDca = 0.1 * unrm(); // normal
191 const double genZ0 = 0.1 * unrm(); // normal
192 const double genPhi0 = 0.52 * (2. * unif() - 1.); // uniform, [-30..30] deg
193 const double genDzds = 10. * unif() + 1.2; // uniform, lambda ~ [50..85] deg
194 const double genCurv = bfac * qbyp * sqrt(1. + genDzds * genDzds);
195
196 //
197 // generate hits
198 //
199 std::vector<Vector2d> hits;
200 double curv(genCurv), phi0(genPhi0), dca(genDca), dzds(genDzds), z0(
201 genZ0);
202 const double cosLambda = 1. / sqrt(1. + dzds * dzds);
203 for (unsigned int iLayer = 0; iLayer < layers.size(); ++iLayer) {
204 // local constant (Bfield) helix
205 GblSimpleHelix hlx = GblSimpleHelix(curv, phi0, dca, dzds, z0);
206 // prediction from local helix
207 GblHelixPrediction pred = layers[iLayer].intersectWithHelix(hlx);
208 // std::cout << " layer " << iLayer << " arc-length " << pred.getArcLength() << std::endl;
209 Vector2d meas = pred.getMeasPred();
210 // smear according to resolution
211 Vector2d sigma = layers[iLayer].getResolution();
212 meas[0] += sigma[0] * unrm();
213 meas[1] += sigma[1] * unrm();
214 // save hit
215 hits.push_back(meas);
216 // scatter at intersection point
217 Vector3d measPos = pred.getPosition();
218 double radlen = layers[iLayer].getRadiationLength()
219 / fabs(pred.getCosIncidence());
220 double errMs = gblMultipleScatteringError(qbyp, radlen); // simple model
221 // move to intersection point
222 hlx.moveToXY(measPos[0], measPos[1], phi0, dca, z0); // update phi0, dca, z0
223 phi0 += unrm() * errMs / cosLambda; // scattering for phi
224 dzds += unrm() * errMs / (cosLambda * cosLambda); // scattering for dzds
225 GblSimpleHelix newhlx = GblSimpleHelix(curv, phi0, dca, dzds, z0); // after scattering
226 // move back
227 newhlx.moveToXY(-measPos[0], -measPos[1], phi0, dca, z0); // update phi0, dca, z0
228 }
229
230 //
231 // fit track with GBL
232 //
233 // seed (with true parameters)
234 double seedCurv(genCurv), seedPhi0(genPhi0), seedDca(genDca), seedDzds(
235 genDzds), seedZ0(genZ0);
236 GblSimpleHelix seed = GblSimpleHelix(seedCurv, seedPhi0, seedDca,
237 seedDzds, seedZ0);
238 // (previous) arc-length
239 double sOld = 0.;
240 const double cosLambdaSeed = 1. / sqrt(1. + (seedDzds * seedDzds));
241 // list of points on trajectory
242 std::vector<GblPoint> listOfPoints;
243 for (unsigned int iLayer = 0; iLayer < layers.size(); ++iLayer) {
244 // std::cout << " hit " << iLayer << " " << hits[iLayer].transpose() << std::endl;
245 GblDetectorLayer &layer = layers[iLayer];
246 // prediction from seeding helix
247 GblHelixPrediction pred = layer.intersectWithHelix(seed);
248 double sArc = pred.getArcLength(); // arc-length
249 Vector2d measPrediction = pred.getMeasPred(); // measurement prediction
250 Vector2d measPrecision = layer.getPrecision(); // measurement precision
251 // residuals
252 Vector2d res(hits[iLayer][0] - measPrediction[0],
253 hits[iLayer][1] - measPrediction[1]);
254 // transformation global system to local (curvilinear) (u,v) (matrix from row vectors)
255 Matrix<double, 2, 3> transG2l = pred.getCurvilinearDirs();
256 // transformation measurement system to global system
257 Matrix3d transM2g = layer.getMeasSystemDirs().inverse();
258 // projection matrix (measurement plane to local (u,v))
259 Matrix2d proM2l = transG2l * transM2g.block<3, 2>(0, 0);// skip measurement normal
260 // projection matrix (local (u,v) to measurement plane)
261 Matrix2d proL2m = proM2l.inverse();
262 // propagation
263 Matrix5d jacPointToPoint = gblSimpleJacobian(
264 (sArc - sOld) / cosLambdaSeed, cosLambdaSeed, bfac);
265 sOld = sArc;
266 // point with (independent) measurements (in measurement system)
267 GblPoint point(jacPointToPoint);
268 point.addMeasurement(proL2m, res, measPrecision);
269 // global labels and parameters for rigid body alignment
270 std::vector<int> labGlobal(6);
271 Vector3d pos = pred.getPosition();
272 Vector3d dir = pred.getDirection();
273 // Chamber alignment in global system (as common system for both stereo orientations)
274 for (int p = 0; p < 6; p++)
275 labGlobal[p] = layer.getRigidBodyGlobalLabel(p);; // chamber alignment
276 Matrix<double, 2, 6> derGlobal = layer.getRigidBodyDerGlobal(pos,
277 dir).block<2, 6>(0, 0);
278 point.addGlobals(labGlobal, derGlobal);
279 // add scatterer to point
280 double radlen = layer.getRadiationLength()
281 / fabs(pred.getCosIncidence());
282 double errMs = gblMultipleScatteringError(qbyp, radlen);// simple model
283 if (errMs > 0.) {
284 Vector2d scat(0., 0.);
285 Vector2d scatPrec(1. / (errMs * errMs), 1. / (errMs * errMs)); // scattering precision matrix is diagonal in curvilinear system
286 point.addScatterer(scat, scatPrec);
287 }
288 // add point to trajectory
289 listOfPoints.push_back(point);
290 }
291 // create trajectory
292 GblTrajectory traj(listOfPoints, bfac != 0.);
293 // fit trajectory
294 double Chi2;
295 int Ndf;
296 double lostWeight;
297 unsigned int ierr = traj.fit(Chi2, Ndf, lostWeight);
298 //std::cout << " Fit " << iTry << ": "<< Chi2 << ", " << Ndf << ", " << lostWeight << std::endl;
299 // successfully fitted?
300 if (!ierr) {
301 // write to MP binary file
302 traj.milleOut(mille);
303 // update statistics
304 Chi2Sum += Chi2;
305 NdfSum += Ndf;
306 LostSum += lostWeight;
307 numFit++;
308 }
309 }
310 clock_t endTime = clock();
311 double diff = endTime - startTime;
312 double cps = CLOCKS_PER_SEC;
313 std::cout << " Time elapsed " << diff / cps << " s" << std::endl;
314 std::cout << " Chi2/Ndf = " << Chi2Sum / NdfSum << std::endl;
315 std::cout << " Tracks fitted " << numFit << std::endl;
316 if (LostSum > 0.)
317 std::cout << " Weight lost " << LostSum << std::endl;
318}
319
320namespace gbl {
321
323
335GblDetectorLayer CreateLayerDc(const std::string aName, unsigned int layer,
336 double xPos, double yPos, double zPos, double thickness, double xzAngle,
337 double stereoAngle, double uRes) {
338 Vector3d aCenter(xPos, yPos, zPos);
339 Vector2d aResolution(uRes, 0.);
340 Vector2d aPrecision(1. / (uRes * uRes), 0.);
341 Matrix3d measTrafo;
342 const double cosXz = cos(xzAngle / 180. * M_PI);
343 const double sinXz = sin(xzAngle / 180. * M_PI);
344 const double cosSt = cos(stereoAngle / 180. * M_PI);
345 const double sinSt = sin(stereoAngle / 180. * M_PI);
346 measTrafo << cosSt * cosXz, sinSt, -cosSt * sinXz, -sinSt * cosXz, cosSt, sinSt
347 * sinXz, sinXz, 0., cosXz; // U,V,N
348 Matrix3d alignTrafo;
349 alignTrafo << cosXz, 0., -sinXz, 0., 1., 0., sinXz, 0., cosXz; // I,J,K
350 return GblDetectorLayer(aName, layer, 1, thickness, aCenter, aResolution,
351 aPrecision, measTrafo, alignTrafo);
352}
353
354}
GblTrajectory definition.
Detector layer.
Definition: GblUtilities.h:107
unsigned int getRigidBodyGlobalLabel(const unsigned int aPar) const
Get global label.
GblHelixPrediction intersectWithHelix(GblSimpleHelix hlx) const
Intersect with helix.
double getRadiationLength() const
Get radiation length.
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 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
void moveToXY(double xPos, double yPos, double &newPhi0, double &newDca, double &newZ0) const
Move to new reference point (X,Y)
GBL trajectory.
Definition: GblTrajectory.h:50
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 exampleDc()
Drift chamber example.
Definition: exampleDc.cpp:90
Definitions for exampleDc.
Namespace for the general broken lines package.
double unrm()
unit normal distribution, Box-Muller method, polar form
double gblMultipleScatteringError(double qbyp, double xbyx0)
Multiple scattering error.
GblDetectorLayer CreateLayerDc(const std::string aName, unsigned int layer, double xPos, double yPos, double zPos, double thickness, double xzAngle, double stereoAngle, double uRes)
Create a drift chamber layer with 1D measurement.
Definition: exampleDc.cpp:335
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