]>
Commit | Line | Data |
---|---|---|
09b6c804 | 1 | // |
2 | // Class to take survey data and | |
3 | // transform that to alignment objects. | |
4 | // | |
5 | // FMD | |
6 | // | |
b2e6f0b0 | 7 | #include "AliFMDSurveyToAlignObjs.h" |
f567c3ce | 8 | #include "AliLog.h" |
b2e6f0b0 | 9 | #include "AliSurveyPoint.h" |
10 | #include <TGraph2DErrors.h> | |
11 | #include <TF2.h> | |
12 | #include <TVector3.h> | |
13 | #include <iostream> | |
14 | #include <iomanip> | |
15 | #include <TMath.h> | |
16 | #include <TRotation.h> | |
17 | #include <TGeoMatrix.h> | |
18 | #include <TGeoManager.h> | |
19 | #include <TGeoPhysicalNode.h> | |
20 | #include "AliFMDGeometry.h" | |
21 | ||
faf80567 | 22 | //____________________________________________________________________ |
23 | Double_t | |
24 | AliFMDSurveyToAlignObjs::GetUnitFactor() const | |
25 | { | |
26 | // Returns the conversion factor from the measured values to | |
27 | // centimeters. | |
f567c3ce | 28 | if (!fSurveyObj) return 0; |
faf80567 | 29 | TString units(fSurveyObj->GetUnits()); |
30 | if (units.CompareTo("mm", TString::kIgnoreCase) == 0) return .1; | |
31 | else if (units.CompareTo("cm", TString::kIgnoreCase) == 0) return 1.; | |
32 | else if (units.CompareTo("m", TString::kIgnoreCase) == 0) return 100.; | |
33 | return 1; | |
34 | } | |
35 | ||
b2e6f0b0 | 36 | //____________________________________________________________________ |
37 | Bool_t | |
faf80567 | 38 | AliFMDSurveyToAlignObjs::GetPoint(const char* name, |
39 | TVector3& point, | |
40 | TVector3& error) const | |
b2e6f0b0 | 41 | { |
faf80567 | 42 | // Get named point. On return, point will contain the point |
43 | // coordinates in centimeters, and error will contain the | |
44 | // meassurement errors in centimeters too. If no point is found, | |
45 | // returns false, otherwise true. | |
f567c3ce | 46 | if (!fSurveyPoints) return kFALSE; |
47 | ||
faf80567 | 48 | Double_t unit = GetUnitFactor(); |
f567c3ce | 49 | if (unit == 0) return kFALSE; |
50 | ||
faf80567 | 51 | TObject* obj = fSurveyPoints->FindObject(name); |
52 | if (!obj) return kFALSE; | |
53 | ||
f567c3ce | 54 | AliSurveyPoint* p = static_cast<AliSurveyPoint*>(obj); |
55 | point.SetXYZ(unit * p->GetX(), | |
56 | unit * p->GetY(), | |
57 | unit * p->GetZ()); | |
58 | error.SetXYZ(unit * p->GetPrecisionX(), | |
59 | unit * p->GetPrecisionY(), | |
60 | unit * p->GetPrecisionZ()); | |
61 | return kTRUE; | |
faf80567 | 62 | } |
b2e6f0b0 | 63 | |
faf80567 | 64 | //____________________________________________________________________ |
65 | Bool_t | |
66 | AliFMDSurveyToAlignObjs::CalculatePlane(const TVector3& a, | |
67 | const TVector3& b, | |
68 | const TVector3& c, | |
f567c3ce | 69 | Double_t depth, |
faf80567 | 70 | Double_t* trans, |
71 | Double_t* rot) const | |
72 | { | |
09b6c804 | 73 | // |
74 | // Calculate the plane translation and rotation from 3 survey points | |
75 | // | |
76 | // Parameters: | |
77 | // a 1st Survey point | |
78 | // b 2nd Survey point | |
79 | // c 3rd Survey point | |
80 | // trans Translation vector | |
81 | // rot Rotation matrix (direction cosines) | |
82 | // | |
83 | // Return: | |
84 | // | |
85 | // | |
86 | ||
faf80567 | 87 | // Vector a->b, b->c, and normal to plane defined by these two |
88 | // vectors. | |
4c01505b | 89 | TVector3 ab(b-a), bc(c-a); |
b2e6f0b0 | 90 | |
faf80567 | 91 | // Normal vector to the plane of the fiducial marks obtained |
92 | // as cross product of the two vectors on the plane d0^d1 | |
93 | TVector3 nn(ab.Cross(bc)); | |
94 | if (nn.Mag() < 1e-8) { | |
f567c3ce | 95 | Info("CalculatePlane", "Normal vector is null vector"); |
faf80567 | 96 | return kFALSE; |
97 | } | |
b2e6f0b0 | 98 | |
faf80567 | 99 | // We express the plane in Hessian normal form. |
100 | // | |
101 | // n x = -p, | |
102 | // | |
103 | // where n is the normalised normal vector given by | |
104 | // | |
105 | // n_x = a / l, n_y = b / l, n_z = c / l, p = d / l | |
106 | // | |
107 | // with l = sqrt(a^2+b^2+c^2) and a, b, c, and d are from the | |
108 | // normal plane equation | |
109 | // | |
110 | // ax + by + cz + d = 0 | |
111 | // | |
112 | // Normalize | |
113 | TVector3 n(nn.Unit()); | |
f567c3ce | 114 | // Double_t p = - (n * a); |
faf80567 | 115 | |
116 | // The center of the square with the fiducial marks as the | |
117 | // corners. The mid-point of one diagonal - md. Used to get the | |
118 | // center of the surveyd box. | |
4c01505b | 119 | // TVector3 md(a + c); |
120 | // md *= 1/2.; | |
121 | TVector3 md(c + b); | |
122 | md *= 1./2; | |
f567c3ce | 123 | |
faf80567 | 124 | // The center of the box. |
f567c3ce | 125 | TVector3 orig(md - depth * n); |
faf80567 | 126 | trans[0] = orig[0]; |
127 | trans[1] = orig[1]; | |
128 | trans[2] = orig[2]; | |
129 | ||
130 | // Normalize the spanning vectors | |
131 | TVector3 uab(ab.Unit()); | |
132 | TVector3 ubc(bc.Unit()); | |
133 | ||
134 | for (size_t i = 0; i < 3; i++) { | |
4c01505b | 135 | // rot[i * 3 + 0] = ubc[i]; |
136 | // rot[i * 3 + 1] = uab[i]; | |
137 | rot[i * 3 + 0] = uab[i]; | |
138 | rot[i * 3 + 1] = ubc[i]; | |
faf80567 | 139 | rot[i * 3 + 2] = n[i]; |
140 | } | |
141 | return kTRUE; | |
142 | } | |
143 | ||
faf80567 | 144 | //____________________________________________________________________ |
f567c3ce | 145 | Bool_t |
146 | AliFMDSurveyToAlignObjs::FitPlane(const TObjArray& points, | |
147 | const TObjArray& errors, | |
148 | Double_t /* depth */, | |
149 | Double_t* trans, | |
150 | Double_t* rot) const | |
faf80567 | 151 | { |
09b6c804 | 152 | // |
153 | // Calculate the plane rotation and translation by doing a fit of | |
154 | // the plane equation to the surveyed points. At least 4 points | |
155 | // must be passed in the @a points array with corresponding errors | |
156 | // in the array @a errors. The arrays are assumed to contain | |
157 | // TVector3 objects. | |
158 | // | |
159 | // Parameters: | |
160 | // points Array surveyed positions | |
161 | // errors Array of errors corresponding to @a points | |
162 | // depth Survey targets depth (perpendicular to the plane) | |
163 | // trans On return, translation of the plane | |
164 | // rot On return, rotation (direction cosines) of the plane | |
165 | // | |
166 | // Return: | |
167 | // @c true on success, @c false otherwise | |
168 | // | |
169 | ||
f567c3ce | 170 | Int_t nPoints = points.GetEntries(); |
171 | if (nPoints < 4) { | |
172 | AliError(Form("Cannot fit a plane equation to less than 4 survey points, " | |
173 | "got only %d", nPoints)); | |
faf80567 | 174 | return kFALSE; |
175 | } | |
f567c3ce | 176 | |
faf80567 | 177 | TGraph2DErrors g; |
b2e6f0b0 | 178 | // Loop and fill graph |
f567c3ce | 179 | for (int i = 0; i < nPoints; i++) { |
180 | TVector3* p = static_cast<TVector3*>(points.At(i)); | |
181 | TVector3* e = static_cast<TVector3*>(errors.At(i)); | |
b2e6f0b0 | 182 | |
f567c3ce | 183 | if (!p || !e) continue; |
184 | ||
185 | g.SetPoint(i, p->X(), p->Y(), p->Z()); | |
186 | g.SetPointError(i, e->X(), e->Y(), e->Z()); | |
187 | } | |
188 | ||
b2e6f0b0 | 189 | // Check that we have enough points |
190 | if (g.GetN() < 4) { | |
f567c3ce | 191 | AliError(Form("Only got %d survey points - no good for plane fit", |
192 | g.GetN())); | |
b2e6f0b0 | 193 | return kFALSE; |
194 | } | |
195 | ||
196 | // Next, declare fitting function and fit to graph. | |
197 | // Fit to the plane equation: | |
198 | // | |
199 | // ax + by + cz + d = 0 | |
200 | // | |
201 | // or | |
202 | // | |
203 | // z = - ax/c - by/c - d/c | |
204 | // | |
f567c3ce | 205 | TF2 f("plane", "-[0]*x-[1]*y-[2]", |
206 | g.GetXmin(), g.GetXmax(), g.GetYmin(), g.GetYmax()); | |
b2e6f0b0 | 207 | g.Fit(&f, "Q"); |
f567c3ce | 208 | |
b2e6f0b0 | 209 | // Now, extract the normal and offset |
210 | TVector3 nv(f.GetParameter(0), f.GetParameter(1), 1); | |
211 | TVector3 n(nv.Unit()); | |
212 | Double_t p = -f.GetParameter(2); | |
f567c3ce | 213 | |
b2e6f0b0 | 214 | // Create two vectors spanning the plane |
215 | TVector3 a(1, 0, f.Eval(1, 0)-p); | |
216 | TVector3 b(0, -1, f.Eval(0, -1)-p); | |
217 | TVector3 ua(a.Unit()); | |
218 | TVector3 ub(b.Unit()); | |
f567c3ce | 219 | // Double_t angAb = ua.Angle(ub); |
faf80567 | 220 | // PrintVector("ua: ", ua); |
221 | // PrintVector("ub: ", ub); | |
222 | // std::cout << "Angle: " << angAb * 180 / TMath::Pi() << std::endl; | |
f567c3ce | 223 | |
b2e6f0b0 | 224 | for (size_t i = 0; i < 3; i++) { |
225 | rot[i * 3 + 0] = ua[i]; | |
226 | rot[i * 3 + 1] = ub[i]; | |
227 | rot[i * 3 + 2] = n[i]; | |
228 | } | |
f567c3ce | 229 | |
b2e6f0b0 | 230 | // The intersection of the plane is given by (0, 0, -d/c) |
231 | trans[0] = 0; | |
232 | trans[1] = 0; | |
233 | trans[2] = p; | |
f567c3ce | 234 | |
b2e6f0b0 | 235 | return kTRUE; |
236 | } | |
237 | ||
f567c3ce | 238 | |
b2e6f0b0 | 239 | //____________________________________________________________________ |
240 | Bool_t | |
f567c3ce | 241 | AliFMDSurveyToAlignObjs::MakeDelta(const char* path, |
09b6c804 | 242 | const Double_t* rot, |
243 | const Double_t* trans, | |
f567c3ce | 244 | TGeoHMatrix& delta) const |
b2e6f0b0 | 245 | { |
09b6c804 | 246 | // |
247 | // Create a delta transform from a global rotation matrix and | |
248 | // translation. | |
249 | // | |
250 | // Parameters: | |
251 | // path Path of element to transform. | |
252 | // rot Rotation matrix (direction cosines) | |
253 | // trans Translation | |
254 | // delta On return, the delta transform | |
255 | // | |
256 | // Return: | |
257 | // Newly | |
258 | // | |
f567c3ce | 259 | if (!gGeoManager) return kFALSE; |
260 | if (!gGeoManager->cd(path)) return kFALSE; | |
b2e6f0b0 | 261 | |
b2e6f0b0 | 262 | |
f567c3ce | 263 | TGeoMatrix* global = gGeoManager->GetCurrentMatrix(); |
264 | #if 0 | |
265 | PrintRotation(Form("%s rot:", global->GetName()),global->GetRotationMatrix()); | |
266 | PrintVector(Form("%s trans:", global->GetName()),global->GetTranslation()); | |
267 | #endif | |
b2e6f0b0 | 268 | |
f567c3ce | 269 | return MakeDelta(global, rot, trans, delta); |
270 | } | |
271 | ||
272 | //____________________________________________________________________ | |
273 | Bool_t | |
09b6c804 | 274 | AliFMDSurveyToAlignObjs::MakeDelta(const TGeoMatrix* global, |
275 | const Double_t* rot, | |
276 | const Double_t* trans, | |
f567c3ce | 277 | TGeoHMatrix& delta) const |
278 | { | |
09b6c804 | 279 | // |
280 | // Create a delta transform from a global rotation matrix and | |
281 | // translation. | |
282 | // | |
283 | // Parameters: | |
284 | // global Global matrix of element to transform. | |
285 | // rot Rotation matrix (direction cosines) | |
286 | // trans Translation | |
287 | // delta On return, the delta transform | |
288 | // | |
289 | // Return: | |
290 | // Newly | |
291 | // | |
b2e6f0b0 | 292 | TGeoHMatrix* geoM = new TGeoHMatrix; |
b2e6f0b0 | 293 | geoM->SetTranslation(trans); |
f567c3ce | 294 | geoM->SetRotation(rot); |
295 | ||
296 | delta = global->Inverse(); | |
297 | delta.MultiplyLeft(geoM); | |
298 | ||
299 | return true; | |
300 | } | |
301 | ||
302 | //____________________________________________________________________ | |
303 | Bool_t | |
304 | AliFMDSurveyToAlignObjs::GetFMD1Plane(Double_t* rot, Double_t* trans) const | |
305 | { | |
09b6c804 | 306 | // |
307 | // Get the FMD1 plane from the survey points | |
308 | // | |
309 | // Parameters: | |
310 | // rot Rotation matrix (direction cosines) | |
311 | // trans Translation | |
312 | // | |
313 | // Return: | |
314 | // @c true on success, @c false otherwise. | |
315 | // | |
f567c3ce | 316 | |
317 | // The possile survey points | |
318 | TVector3 icb, ict, ocb, oct, dummy; | |
319 | Int_t missing = 0; | |
320 | if (!GetPoint("V0L_ICB", icb, dummy)) missing++; | |
321 | if (!GetPoint("V0L_ICT", ict, dummy)) missing++; | |
322 | if (!GetPoint("V0L_OCB", ocb, dummy)) missing++; | |
323 | if (!GetPoint("V0L_OCT", oct, dummy)) missing++; | |
324 | ||
325 | // Check that we have enough points | |
326 | if (missing > 1) { | |
327 | AliWarning(Form("Only got %d survey points - no good for FMD1 plane", | |
328 | 4-missing)); | |
329 | return kFALSE; | |
330 | } | |
331 | ||
332 | #if 0 | |
333 | const char* lidN = "FMD1_lid_mat0"; | |
334 | TGeoMatrix* lidM = static_cast<TGeoMatrix*>(gGeoManager->GetListOfMatrices() | |
335 | ->FindObject(lidN)); | |
336 | if (!lidM) { | |
337 | AliError(Form("Couldn't find FMD1 lid transformation %s", lidN)); | |
338 | return kFALSE; | |
339 | } | |
340 | ||
341 | const Double_t* lidT = lidM->GetTranslation(); | |
342 | Double_t lidZ = lidT[2]; | |
343 | Double_t off = lidZ-3.3; | |
344 | #else | |
345 | Double_t off = 0; | |
b2e6f0b0 | 346 | #endif |
f567c3ce | 347 | |
4c01505b | 348 | // if (!CalculatePlane(ocb, icb, ict, off, trans, rot)) return kFALSE; |
349 | if (!CalculatePlane(ocb, icb, oct, off, trans, rot)) return kFALSE; | |
350 | PrintRotation("FMD1 rotation:", rot); | |
351 | PrintVector("FMD1 translation:", trans); | |
f567c3ce | 352 | |
353 | return kTRUE; | |
354 | } | |
355 | ||
356 | //____________________________________________________________________ | |
357 | Bool_t | |
358 | AliFMDSurveyToAlignObjs::DoFMD1() | |
359 | { | |
09b6c804 | 360 | // |
361 | // Do the FMD1 analysis. We have 4 survey targets on V0-A on the | |
362 | // C-side. These are | |
363 | // | |
364 | // - V0A_ICT In-side, C-side, top. | |
365 | // - V0A_ICB In-side, C-side, bottom. | |
366 | // - V0A_OCT Out-side, C-side, top. | |
367 | // - V0A_OCB Out-side, C-side, bottom. | |
368 | // | |
369 | // These 4 survey targets sit 3.3mm over the V0-A C-side surface, or | |
370 | // 3.3mm over the back surface of FMD1. | |
371 | // | |
372 | // Since these are really sitting on a plane, we can use the method | |
373 | // proposed by the CORE offline. | |
374 | // | |
375 | // Return: | |
376 | // @c true on success, @c false otherwise. | |
377 | // | |
378 | ||
f567c3ce | 379 | // Do the FMD1 stuff |
380 | Double_t rot[9], trans[3]; | |
381 | if (!GetFMD1Plane(rot, trans)) return kFALSE; | |
382 | // const char* path = "/ALIC_1/F1MT_1/FMD1_lid_0"; | |
4c01505b | 383 | |
384 | #if 0 | |
f567c3ce | 385 | // TGeoHMatrix delta; |
4c01505b | 386 | Double_t gRot[9], gTrans[3]; |
387 | TVector3 ocb(-127, -220, 324.67); | |
388 | TVector3 oct(-127, +220, 324.67); | |
389 | TVector3 icb(+127, -220, 324.67); | |
390 | TVector3 ict(+127, +220, 324.67); | |
391 | if (!CalculatePlane(ocb, icb, oct, 0, gTrans, gRot)) { | |
392 | Warning("DoFMD1", "Failed to make reference plane"); | |
393 | return kFALSE; | |
394 | } | |
395 | PrintRotation("FMD1 ref rotation:", gRot); | |
396 | PrintVector("FMD1 ref translation:", gTrans); | |
397 | TGeoRotation ggRot; ggRot.SetMatrix(gRot); | |
398 | TGeoCombiTrans global(gTrans[0], gTrans[1], gTrans[2], &ggRot); | |
399 | #endif | |
400 | ||
f567c3ce | 401 | TGeoTranslation global(0,0,324.670); |
402 | if (!MakeDelta(&global, rot, trans, fFMD1Delta)) | |
403 | return kFALSE; | |
b2e6f0b0 | 404 | |
f567c3ce | 405 | // PrintRotation("FMD1 delta rotation:", fFMD1Delta.GetRotationMatrix()); |
406 | // PrintVector("FMD1 delta translation:", fFMD1Delta.GetTranslation()); | |
407 | ||
408 | return kTRUE; | |
409 | } | |
410 | ||
411 | //____________________________________________________________________ | |
412 | Bool_t | |
413 | AliFMDSurveyToAlignObjs::GetFMD2Plane(Double_t* rot, Double_t* trans) const | |
414 | { | |
09b6c804 | 415 | // |
416 | // Get the surveyed plane corresponding to the backside of FMD2. | |
417 | // The plane is done as a best fit of the plane equation to at least | |
418 | // 4 of the available survey points. | |
419 | // | |
420 | // Parameters: | |
421 | // rot Rotation matrix (direction cosines) | |
422 | // trans Translation vector. | |
423 | // | |
424 | // Return: | |
425 | // @c true on success, @c false otherwise | |
426 | // | |
f567c3ce | 427 | |
428 | // The possible survey points | |
429 | const char* names[] = { "FMD2_ITOP", "FMD2_OTOP", | |
430 | "FMD2_IBOTM", "FMD2_OBOTM", | |
431 | "FMD2_IBOT", "FMD2_OBOT", | |
432 | 0 }; | |
433 | const char** name = names; | |
434 | ||
435 | TObjArray points; | |
436 | TObjArray errors; | |
b2e6f0b0 | 437 | |
f567c3ce | 438 | // Loop and fill graph |
439 | while (*name) { | |
440 | TVector3 p, e; | |
441 | if (!GetPoint(*name++, p, e)) continue; | |
442 | ||
443 | points.Add(new TVector3(p)); | |
444 | errors.Add(new TVector3(e)); | |
445 | } | |
446 | if (points.GetEntries() < 4) { | |
447 | AliWarning(Form("Only got %d survey points - no good for FMD2 plane", | |
448 | points.GetEntries())); | |
449 | return kFALSE; | |
450 | } | |
451 | ||
452 | return FitPlane(points, errors, 0, trans, rot); | |
453 | } | |
454 | ||
455 | #define M(I,J) rot[(J-1) * 3 + (I-1)] | |
456 | //____________________________________________________________________ | |
457 | Bool_t | |
458 | AliFMDSurveyToAlignObjs::DoFMD2() | |
459 | { | |
09b6c804 | 460 | // |
461 | // Do the FMD2 calculations. We have 6 survey points of which only | |
462 | // 5 are normally surveyed. These are all sittings | |
463 | // | |
464 | // - FMD2_ITOP - In-side, top | |
465 | // - FMD2_IBOTM - In-side, middle bottom | |
466 | // - FMD2_IBOT - In-side, bottom | |
467 | // - FMD2_OTOP - Out-side, top | |
468 | // - FMD2_OBOTM - Out-side, middle bottom | |
469 | // - FMD2_OBOT - Out-side, bottom | |
470 | // | |
471 | // The nominal coordinates of these retro-fitted survey stickers | |
472 | // isn't known. Also, these stickers are put on a thin (0.3mm | |
473 | // thick) carbon cover which flexes quite easily. This means, that | |
474 | // to rotations and xy-translation obtained from the survey data | |
475 | // cannot be used, and left is only the z-translation. | |
476 | // | |
477 | // Further more, since FMD2 to is attached to the ITS SPD thermal | |
478 | // screen, it is questionable if the FMD2 survey will ever be used. | |
479 | // | |
480 | // Return: | |
481 | // @c true on success, @c false otherwise. | |
482 | // | |
483 | ||
f567c3ce | 484 | // Do the FMD2 stuff |
485 | Double_t rot[9], trans[3]; | |
486 | if (!GetFMD2Plane(rot, trans)) return kFALSE; | |
4c01505b | 487 | PrintRotation("FMD2 rotation:", rot); |
488 | PrintVector("FMD2 translation:", trans); | |
f567c3ce | 489 | |
4c01505b | 490 | #if 0 |
f567c3ce | 491 | for (int i = 0; i < 3; i++) { |
492 | for (int j = 0; j < 3; j++) { | |
493 | rot[i*3+j] = (i == j ? 1 : 0); | |
494 | } | |
495 | } | |
4c01505b | 496 | #endif |
f567c3ce | 497 | trans[0] = trans[1] = 0; |
498 | trans[2] += 0.015; | |
499 | // PrintRotation("FMD2 rotation:", rot); | |
500 | // PrintVector("FMD2 translation:", trans); | |
b2e6f0b0 | 501 | |
f567c3ce | 502 | // TGeoHMatrix delta; |
503 | if (!MakeDelta("/ALIC_1/F2MT_2/FMD2_support_0/FMD2_back_cover_2", | |
504 | rot, trans, fFMD2Delta)) return kFALSE; | |
b2e6f0b0 | 505 | |
f567c3ce | 506 | // PrintRotation("FMD2 delta rotation:", fFMD2Delta.GetRotationMatrix()); |
507 | // PrintVector("FMD2 delta translation:", fFMD2Delta.GetTranslation()); | |
508 | ||
b2e6f0b0 | 509 | return kTRUE; |
510 | } | |
511 | ||
512 | //____________________________________________________________________ | |
513 | void | |
514 | AliFMDSurveyToAlignObjs::Run() | |
515 | { | |
09b6c804 | 516 | // |
517 | // Run the task. | |
518 | // | |
519 | // | |
520 | ||
b2e6f0b0 | 521 | AliFMDGeometry* geom = AliFMDGeometry::Instance(); |
522 | geom->Init(); | |
523 | geom->InitTransformations(); | |
524 | ||
f567c3ce | 525 | DoFMD1(); |
b2e6f0b0 | 526 | DoFMD2(); |
527 | } | |
528 | ||
4c01505b | 529 | //____________________________________________________________________ |
530 | void | |
531 | AliFMDSurveyToAlignObjs::Run(const char** files) | |
532 | { | |
533 | // | |
534 | // Run the task. | |
535 | // | |
536 | // | |
537 | ||
538 | AliFMDGeometry* geom = AliFMDGeometry::Instance(); | |
539 | geom->Init(); | |
540 | geom->InitTransformations(); | |
541 | ||
542 | const char** file = files; | |
543 | while (*file) { | |
544 | if ((*file)[0] == '\0') { | |
545 | Warning("Run", "no file specified"); | |
546 | file++; | |
547 | continue; | |
548 | } | |
549 | if (!LoadSurveyFromLocalFile(*file)) { | |
550 | Warning("Run", "Failed to load %s", *file); | |
551 | file++; | |
552 | continue; | |
553 | } | |
554 | TString sDet(fSurveyObj->GetDetector()); | |
555 | Int_t d = Int_t(sDet[sDet.Length()-1] - '0'); | |
556 | Info("Run", "Making alignment for %s (%d)", sDet.Data(), d); | |
557 | Bool_t ret = true; | |
558 | switch (d) { | |
559 | case 1: ret = DoFMD1(); break; | |
560 | case 2: ret = DoFMD2(); break; | |
561 | default: | |
562 | Warning("Run", "Do not know how to deal with %s", sDet.Data()); | |
563 | break; | |
564 | } | |
565 | if (!ret) { | |
566 | Warning("Run", "Calculation for %s failed", sDet.Data()); | |
567 | } | |
568 | file++; | |
569 | } | |
570 | CreateAlignObjs(); | |
571 | FillDefaultAlignObjs(); | |
572 | } | |
573 | ||
574 | //____________________________________________________________________ | |
575 | AliAlignObjParams* | |
576 | AliFMDSurveyToAlignObjs::CreateDefaultAlignObj(const TString& path, | |
577 | Int_t id) | |
578 | { | |
579 | Int_t nAlign = fAlignObjArray->GetEntries(); | |
580 | AliAlignObjParams* obj = | |
581 | new ((*fAlignObjArray)[nAlign]) AliAlignObjParams(path.Data(), | |
582 | id,0,0,0,0,0,0,kTRUE); | |
583 | if (!obj) { | |
584 | AliError(Form("Failed to create alignment object for %s", path.Data())); | |
585 | return 0; | |
586 | } | |
587 | if (!obj->SetLocalPars(0, 0, 0, 0, 0, 0)) { | |
588 | AliError(Form("Failed to set local transforms on %s", path.Data())); | |
589 | return obj; | |
590 | } | |
591 | return obj; | |
592 | } | |
593 | ||
594 | //____________________________________________________________________ | |
595 | AliAlignObjParams* | |
596 | AliFMDSurveyToAlignObjs::FindAlignObj(const TString& path) const | |
597 | { | |
598 | AliAlignObjParams* p = 0; | |
599 | for (int i = 0; i < fAlignObjArray->GetEntries(); i++) { | |
600 | p = static_cast<AliAlignObjParams*>(fAlignObjArray->At(i)); | |
601 | if (path.EqualTo(p->GetSymName())) return p; | |
602 | } | |
603 | return 0; | |
604 | } | |
605 | ||
606 | //____________________________________________________________________ | |
607 | Bool_t | |
608 | AliFMDSurveyToAlignObjs::FillDefaultAlignObjs() | |
609 | { | |
610 | for (int d = 1; d <= 3; d++) { | |
611 | const char sides[] = { 'T', 'B', 0 }; | |
612 | const char* side = sides; | |
613 | while (*side) { | |
614 | TString path = TString::Format("FMD/FMD%d_%c", d, *side); | |
615 | AliAlignObjParams* p = FindAlignObj(path); | |
616 | if (!p) | |
617 | p = CreateDefaultAlignObj(path, 0); | |
618 | else | |
619 | Info("FillDefaultAlignObjs", "Alignment object %s exists", path.Data()); | |
620 | const char halves[] = { 'I', d == 1 ? '\0' : 'O', 0 }; | |
621 | const char* half = halves; | |
622 | while (*half) { | |
623 | int nsec = *half == 'I' ? 10 : 20; | |
624 | int start = *side == 'T' ? 0 : nsec/2; | |
625 | int end = *side == 'T' ? nsec/2 : nsec; | |
626 | for (int s=start; s < end; s++) { | |
627 | path = TString::Format("FMD/FMD%d_%c/FMD%c_%02d", | |
628 | d, *side, *half, s); | |
629 | CreateDefaultAlignObj(path, 0); | |
630 | } | |
631 | half++; | |
632 | } | |
633 | side++; | |
634 | } | |
635 | ||
636 | } | |
637 | return true; | |
638 | } | |
639 | ||
f567c3ce | 640 | //____________________________________________________________________ |
641 | Bool_t | |
642 | AliFMDSurveyToAlignObjs::CreateAlignObjs() | |
643 | { | |
09b6c804 | 644 | // |
645 | // | |
646 | // Method to create the alignment objects | |
647 | // | |
648 | // Return: | |
649 | // @c true on success, @c false otherwise | |
650 | // | |
f567c3ce | 651 | TClonesArray& array = *fAlignObjArray; |
652 | Int_t n = array.GetEntriesFast(); | |
653 | ||
654 | if (!fFMD1Delta.IsIdentity()) { | |
4c01505b | 655 | new (array[n++]) AliAlignObjParams("FMD/FMD1_T", 0, fFMD1Delta, kTRUE); |
656 | new (array[n++]) AliAlignObjParams("FMD/FMD1_B", 0, fFMD1Delta, kTRUE); | |
f567c3ce | 657 | } |
658 | if (!fFMD2Delta.IsIdentity()) { | |
4c01505b | 659 | new (array[n++]) AliAlignObjParams("FMD/FMD2_T", 0, fFMD2Delta, kTRUE); |
660 | new (array[n++]) AliAlignObjParams("FMD/FMD2_B", 0, fFMD2Delta, kTRUE); | |
f567c3ce | 661 | } |
662 | // array.Print(); | |
663 | ||
664 | return kTRUE; | |
665 | } | |
666 | ||
b2e6f0b0 | 667 | //____________________________________________________________________ |
668 | void | |
669 | AliFMDSurveyToAlignObjs::PrintVector(const char* text, const TVector3& v) | |
670 | { | |
09b6c804 | 671 | // |
672 | // Service member function to print a vector | |
673 | // | |
674 | // Parameters: | |
675 | // text Prefix text | |
676 | // v Vector | |
677 | // | |
b2e6f0b0 | 678 | Double_t va[] = { v.X(), v.Y(), v.Z() }; |
679 | PrintVector(text, va); | |
680 | } | |
681 | //____________________________________________________________________ | |
682 | void | |
683 | AliFMDSurveyToAlignObjs::PrintVector(const char* text, const Double_t* v) | |
684 | { | |
09b6c804 | 685 | // |
686 | // Service member function to print a vector | |
687 | // | |
688 | // Parameters: | |
689 | // text Prefix text | |
690 | // v Vector (array of 3 doubles) | |
691 | // | |
b2e6f0b0 | 692 | std::cout << text |
693 | << std::setw(15) << v[0] | |
694 | << std::setw(15) << v[1] | |
695 | << std::setw(15) << v[2] | |
696 | << std::endl; | |
697 | } | |
698 | ||
699 | ||
700 | //____________________________________________________________________ | |
701 | void | |
702 | AliFMDSurveyToAlignObjs::PrintRotation(const char* text, const Double_t* rot) | |
703 | { | |
09b6c804 | 704 | // |
705 | // Service member function to print a rotation matrix | |
706 | // | |
707 | // Parameters: | |
708 | // text Prefix text | |
709 | // v Matrix (array of 9 doubles) | |
710 | // | |
711 | ||
b2e6f0b0 | 712 | std::cout << text << std::endl; |
713 | for (size_t i = 0; i < 3; i++) { | |
714 | for (size_t j = 0; j < 3; j++) | |
715 | std::cout << std::setw(15) << rot[i * 3 + j]; | |
716 | std::cout << std::endl; | |
717 | } | |
718 | } | |
719 | ||
720 | //____________________________________________________________________ | |
721 | // | |
722 | // EOF | |
723 | // |