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