]>
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.; | |
9956d453 | 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()); | |
4c01505b | 123 | TVector3 md(c + b); |
124 | md *= 1./2; | |
9956d453 | 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()); | |
f567c3ce | 127 | |
faf80567 | 128 | // The center of the box. |
f567c3ce | 129 | TVector3 orig(md - depth * n); |
9956d453 | 130 | // Info("CalculatePlane", "orig=(%8f,%8f,%8f)", orig.X(),orig.Y(),orig.Z()); |
faf80567 | 131 | trans[0] = orig[0]; |
132 | trans[1] = orig[1]; | |
133 | trans[2] = orig[2]; | |
9956d453 | 134 | //Info("CalculatePlane", "trans=(%8f,%8f,%8f)", trans[0],trans[1],trans[2]); |
faf80567 | 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++) { | |
9956d453 | 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]; | |
faf80567 | 145 | rot[i * 3 + 2] = n[i]; |
146 | } | |
147 | return kTRUE; | |
148 | } | |
149 | ||
faf80567 | 150 | //____________________________________________________________________ |
f567c3ce | 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 | |
faf80567 | 157 | { |
09b6c804 | 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 | ||
f567c3ce | 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)); | |
faf80567 | 180 | return kFALSE; |
181 | } | |
f567c3ce | 182 | |
faf80567 | 183 | TGraph2DErrors g; |
b2e6f0b0 | 184 | // Loop and fill graph |
f567c3ce | 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)); | |
b2e6f0b0 | 188 | |
f567c3ce | 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()); | |
9956d453 | 193 | |
f567c3ce | 194 | } |
195 | ||
b2e6f0b0 | 196 | // Check that we have enough points |
197 | if (g.GetN() < 4) { | |
f567c3ce | 198 | AliError(Form("Only got %d survey points - no good for plane fit", |
199 | g.GetN())); | |
b2e6f0b0 | 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 | // | |
f567c3ce | 212 | TF2 f("plane", "-[0]*x-[1]*y-[2]", |
213 | g.GetXmin(), g.GetXmax(), g.GetYmin(), g.GetYmax()); | |
b2e6f0b0 | 214 | g.Fit(&f, "Q"); |
f567c3ce | 215 | |
b2e6f0b0 | 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); | |
f567c3ce | 220 | |
b2e6f0b0 | 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()); | |
f567c3ce | 226 | // Double_t angAb = ua.Angle(ub); |
faf80567 | 227 | // PrintVector("ua: ", ua); |
228 | // PrintVector("ub: ", ub); | |
229 | // std::cout << "Angle: " << angAb * 180 / TMath::Pi() << std::endl; | |
f567c3ce | 230 | |
b2e6f0b0 | 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 | } | |
f567c3ce | 236 | |
b2e6f0b0 | 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; | |
f567c3ce | 241 | |
b2e6f0b0 | 242 | return kTRUE; |
243 | } | |
244 | ||
f567c3ce | 245 | |
b2e6f0b0 | 246 | //____________________________________________________________________ |
247 | Bool_t | |
f567c3ce | 248 | AliFMDSurveyToAlignObjs::MakeDelta(const char* path, |
09b6c804 | 249 | const Double_t* rot, |
250 | const Double_t* trans, | |
f567c3ce | 251 | TGeoHMatrix& delta) const |
b2e6f0b0 | 252 | { |
09b6c804 | 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 | // | |
f567c3ce | 266 | if (!gGeoManager) return kFALSE; |
267 | if (!gGeoManager->cd(path)) return kFALSE; | |
b2e6f0b0 | 268 | |
b2e6f0b0 | 269 | |
f567c3ce | 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 | |
b2e6f0b0 | 275 | |
f567c3ce | 276 | return MakeDelta(global, rot, trans, delta); |
277 | } | |
278 | ||
279 | //____________________________________________________________________ | |
280 | Bool_t | |
09b6c804 | 281 | AliFMDSurveyToAlignObjs::MakeDelta(const TGeoMatrix* global, |
282 | const Double_t* rot, | |
283 | const Double_t* trans, | |
f567c3ce | 284 | TGeoHMatrix& delta) const |
285 | { | |
09b6c804 | 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 | // | |
b2e6f0b0 | 299 | TGeoHMatrix* geoM = new TGeoHMatrix; |
b2e6f0b0 | 300 | geoM->SetTranslation(trans); |
f567c3ce | 301 | geoM->SetRotation(rot); |
9956d453 | 302 | // Info("MakeDelta", "The HMatrix from survey"); |
303 | // geoM->Print(); | |
304 | // Info("MakeDelta", "The global matrix"); | |
305 | // global->Print(); | |
f567c3ce | 306 | |
307 | delta = global->Inverse(); | |
9956d453 | 308 | // Info("MakeDelta", "The inverse global matrix"); |
309 | // delta.Print(); | |
f567c3ce | 310 | delta.MultiplyLeft(geoM); |
9956d453 | 311 | // Info("MakeDelta", "The delta matrix"); |
312 | // delta.Print(); | |
f567c3ce | 313 | return true; |
314 | } | |
315 | ||
9956d453 | 316 | namespace { |
317 | Double_t getFMD1Offset() | |
318 | { | |
319 | static Double_t off = 0; | |
320 | return off; | |
25c2acf3 | 321 | |
322 | #if 0 | |
9956d453 | 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; | |
25c2acf3 | 338 | #endif |
9956d453 | 339 | } |
340 | } | |
341 | ||
f567c3ce | 342 | //____________________________________________________________________ |
343 | Bool_t | |
344 | AliFMDSurveyToAlignObjs::GetFMD1Plane(Double_t* rot, Double_t* trans) const | |
345 | { | |
09b6c804 | 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 | // | |
f567c3ce | 356 | |
357 | // The possile survey points | |
9956d453 | 358 | TVector3 icb, ict, ocb, oct, eicb, eict, eocb, eoct; |
f567c3ce | 359 | Int_t missing = 0; |
9956d453 | 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++; | |
f567c3ce | 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 | } | |
f567c3ce | 371 | #if 0 |
9956d453 | 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()); | |
f567c3ce | 388 | } |
f567c3ce | 389 | #else |
9956d453 | 390 | Double_t off = getFMD1Offset(); |
391 | Info("GetFMD1Plane", "Lid offset is %f", off); | |
f567c3ce | 392 | |
4c01505b | 393 | // if (!CalculatePlane(ocb, icb, ict, off, trans, rot)) return kFALSE; |
9956d453 | 394 | // Bool_t ret = CalculatePlane(ocb, icb, oct, off, trans, rot); |
395 | Bool_t ret = CalculatePlane(oct, ocb, ict, off, trans, rot); | |
396 | #endif | |
4c01505b | 397 | PrintRotation("FMD1 rotation:", rot); |
398 | PrintVector("FMD1 translation:", trans); | |
f567c3ce | 399 | |
9956d453 | 400 | return ret; |
f567c3ce | 401 | } |
402 | ||
403 | //____________________________________________________________________ | |
404 | Bool_t | |
405 | AliFMDSurveyToAlignObjs::DoFMD1() | |
406 | { | |
09b6c804 | 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 | ||
f567c3ce | 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"; | |
4c01505b | 430 | |
431 | #if 0 | |
f567c3ce | 432 | // TGeoHMatrix delta; |
4c01505b | 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 | |
9956d453 | 447 | Double_t off = getFMD1Offset(); |
448 | Info("DoFMD1", "Lid offset is %f", off); | |
4c01505b | 449 | |
9956d453 | 450 | TGeoTranslation global(0,0,324.670-off); |
f567c3ce | 451 | if (!MakeDelta(&global, rot, trans, fFMD1Delta)) |
452 | return kFALSE; | |
b2e6f0b0 | 453 | |
f567c3ce | 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 | { | |
09b6c804 | 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 | // | |
f567c3ce | 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; | |
b2e6f0b0 | 486 | |
f567c3ce | 487 | // Loop and fill graph |
9956d453 | 488 | int i = 0; |
f567c3ce | 489 | while (*name) { |
490 | TVector3 p, e; | |
9956d453 | 491 | if (!GetPoint(*name, p, e)) { |
492 | name++; | |
493 | i++; | |
494 | continue; | |
495 | } | |
f567c3ce | 496 | |
9956d453 | 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 | } | |
f567c3ce | 501 | points.Add(new TVector3(p)); |
502 | errors.Add(new TVector3(e)); | |
9956d453 | 503 | name++; |
504 | i++; | |
f567c3ce | 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 | { | |
09b6c804 | 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 | ||
f567c3ce | 544 | // Do the FMD2 stuff |
545 | Double_t rot[9], trans[3]; | |
546 | if (!GetFMD2Plane(rot, trans)) return kFALSE; | |
4c01505b | 547 | PrintRotation("FMD2 rotation:", rot); |
548 | PrintVector("FMD2 translation:", trans); | |
f567c3ce | 549 | |
4c01505b | 550 | #if 0 |
f567c3ce | 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 | } | |
4c01505b | 556 | #endif |
f567c3ce | 557 | trans[0] = trans[1] = 0; |
558 | trans[2] += 0.015; | |
559 | // PrintRotation("FMD2 rotation:", rot); | |
560 | // PrintVector("FMD2 translation:", trans); | |
b2e6f0b0 | 561 | |
f567c3ce | 562 | // TGeoHMatrix delta; |
563 | if (!MakeDelta("/ALIC_1/F2MT_2/FMD2_support_0/FMD2_back_cover_2", | |
564 | rot, trans, fFMD2Delta)) return kFALSE; | |
b2e6f0b0 | 565 | |
f567c3ce | 566 | // PrintRotation("FMD2 delta rotation:", fFMD2Delta.GetRotationMatrix()); |
567 | // PrintVector("FMD2 delta translation:", fFMD2Delta.GetTranslation()); | |
568 | ||
b2e6f0b0 | 569 | return kTRUE; |
570 | } | |
571 | ||
572 | //____________________________________________________________________ | |
573 | void | |
574 | AliFMDSurveyToAlignObjs::Run() | |
575 | { | |
09b6c804 | 576 | // |
577 | // Run the task. | |
578 | // | |
579 | // | |
580 | ||
b2e6f0b0 | 581 | AliFMDGeometry* geom = AliFMDGeometry::Instance(); |
582 | geom->Init(); | |
583 | geom->InitTransformations(); | |
584 | ||
f567c3ce | 585 | DoFMD1(); |
b2e6f0b0 | 586 | DoFMD2(); |
587 | } | |
588 | ||
4c01505b | 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(); | |
9956d453 | 631 | GetAlignObjArray()->Print(); |
4c01505b | 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); | |
25c2acf3 | 676 | if (!FindAlignObj(path)) CreateDefaultAlignObj(path, 0); |
9956d453 | 677 | |
4c01505b | 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 | ||
f567c3ce | 698 | //____________________________________________________________________ |
699 | Bool_t | |
700 | AliFMDSurveyToAlignObjs::CreateAlignObjs() | |
701 | { | |
09b6c804 | 702 | // |
703 | // | |
704 | // Method to create the alignment objects | |
705 | // | |
706 | // Return: | |
707 | // @c true on success, @c false otherwise | |
708 | // | |
f567c3ce | 709 | TClonesArray& array = *fAlignObjArray; |
710 | Int_t n = array.GetEntriesFast(); | |
711 | ||
712 | if (!fFMD1Delta.IsIdentity()) { | |
4c01505b | 713 | new (array[n++]) AliAlignObjParams("FMD/FMD1_T", 0, fFMD1Delta, kTRUE); |
714 | new (array[n++]) AliAlignObjParams("FMD/FMD1_B", 0, fFMD1Delta, kTRUE); | |
f567c3ce | 715 | } |
716 | if (!fFMD2Delta.IsIdentity()) { | |
4c01505b | 717 | new (array[n++]) AliAlignObjParams("FMD/FMD2_T", 0, fFMD2Delta, kTRUE); |
718 | new (array[n++]) AliAlignObjParams("FMD/FMD2_B", 0, fFMD2Delta, kTRUE); | |
f567c3ce | 719 | } |
720 | // array.Print(); | |
721 | ||
722 | return kTRUE; | |
723 | } | |
724 | ||
b2e6f0b0 | 725 | //____________________________________________________________________ |
726 | void | |
727 | AliFMDSurveyToAlignObjs::PrintVector(const char* text, const TVector3& v) | |
728 | { | |
09b6c804 | 729 | // |
730 | // Service member function to print a vector | |
731 | // | |
732 | // Parameters: | |
733 | // text Prefix text | |
734 | // v Vector | |
735 | // | |
b2e6f0b0 | 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 | { | |
09b6c804 | 743 | // |
744 | // Service member function to print a vector | |
745 | // | |
746 | // Parameters: | |
747 | // text Prefix text | |
748 | // v Vector (array of 3 doubles) | |
749 | // | |
b2e6f0b0 | 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 | { | |
09b6c804 | 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 | ||
b2e6f0b0 | 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 | // |