]>
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; | |
321 | if (off != 0) return off; | |
322 | ||
323 | const char* lidN = "FMD1_lid_mat0"; | |
324 | TGeoMatrix* lidM = static_cast<TGeoMatrix*>(gGeoManager->GetListOfMatrices() | |
325 | ->FindObject(lidN)); | |
326 | if (!lidM) { | |
327 | Error("getFMD1Offset", "Couldn't find FMD1 lid transformation %s", lidN); | |
328 | return 0; | |
329 | } | |
330 | ||
331 | const Double_t* lidT = lidM->GetTranslation(); | |
332 | Double_t lidZ = lidT[2]; | |
333 | off = lidZ-3.3; | |
334 | ||
335 | return off; | |
336 | } | |
337 | } | |
338 | ||
f567c3ce | 339 | //____________________________________________________________________ |
340 | Bool_t | |
341 | AliFMDSurveyToAlignObjs::GetFMD1Plane(Double_t* rot, Double_t* trans) const | |
342 | { | |
09b6c804 | 343 | // |
344 | // Get the FMD1 plane from the survey points | |
345 | // | |
346 | // Parameters: | |
347 | // rot Rotation matrix (direction cosines) | |
348 | // trans Translation | |
349 | // | |
350 | // Return: | |
351 | // @c true on success, @c false otherwise. | |
352 | // | |
f567c3ce | 353 | |
354 | // The possile survey points | |
9956d453 | 355 | TVector3 icb, ict, ocb, oct, eicb, eict, eocb, eoct; |
f567c3ce | 356 | Int_t missing = 0; |
9956d453 | 357 | if (!GetPoint("V0L_ICB", icb, eicb)) missing++; |
358 | if (!GetPoint("V0L_ICT", ict, eict)) missing++; | |
359 | if (!GetPoint("V0L_OCB", ocb, eocb)) missing++; | |
360 | if (!GetPoint("V0L_OCT", oct, eoct)) missing++; | |
f567c3ce | 361 | |
362 | // Check that we have enough points | |
363 | if (missing > 1) { | |
364 | AliWarning(Form("Only got %d survey points - no good for FMD1 plane", | |
365 | 4-missing)); | |
366 | return kFALSE; | |
367 | } | |
f567c3ce | 368 | #if 0 |
9956d453 | 369 | TObjArray points; |
370 | TObjArray errors; | |
371 | points.Add(&icb); errors.Add(&eicb); | |
372 | points.Add(&ict); errors.Add(&eict); | |
373 | points.Add(&oct); errors.Add(&eoct); | |
374 | points.Add(&ocb); errors.Add(&eocb); | |
375 | ||
376 | Bool_t ret = FitPlane(points, errors, 0, trans, rot); | |
377 | if (!ret) { | |
378 | Warning("GetFMD1Plane", "fit to plane failed"); | |
379 | } | |
380 | for (Int_t i = 0; i < 4; i++) { | |
381 | TVector3* v = static_cast<TVector3*>(points.At(i)); | |
382 | TVector3* e = static_cast<TVector3*>(errors.At(i)); | |
383 | Info("GetFMD1Plane", "p%d=(%8f,%8f,%8f)+/-(%8f,%8f,%8f)", | |
384 | i, v->X(), v->Y(), v->Z(), e->X(), e->Y(), e->Z()); | |
f567c3ce | 385 | } |
f567c3ce | 386 | #else |
9956d453 | 387 | Double_t off = getFMD1Offset(); |
388 | Info("GetFMD1Plane", "Lid offset is %f", off); | |
f567c3ce | 389 | |
4c01505b | 390 | // if (!CalculatePlane(ocb, icb, ict, off, trans, rot)) return kFALSE; |
9956d453 | 391 | // Bool_t ret = CalculatePlane(ocb, icb, oct, off, trans, rot); |
392 | Bool_t ret = CalculatePlane(oct, ocb, ict, off, trans, rot); | |
393 | #endif | |
4c01505b | 394 | PrintRotation("FMD1 rotation:", rot); |
395 | PrintVector("FMD1 translation:", trans); | |
f567c3ce | 396 | |
9956d453 | 397 | return ret; |
f567c3ce | 398 | } |
399 | ||
400 | //____________________________________________________________________ | |
401 | Bool_t | |
402 | AliFMDSurveyToAlignObjs::DoFMD1() | |
403 | { | |
09b6c804 | 404 | // |
405 | // Do the FMD1 analysis. We have 4 survey targets on V0-A on the | |
406 | // C-side. These are | |
407 | // | |
408 | // - V0A_ICT In-side, C-side, top. | |
409 | // - V0A_ICB In-side, C-side, bottom. | |
410 | // - V0A_OCT Out-side, C-side, top. | |
411 | // - V0A_OCB Out-side, C-side, bottom. | |
412 | // | |
413 | // These 4 survey targets sit 3.3mm over the V0-A C-side surface, or | |
414 | // 3.3mm over the back surface of FMD1. | |
415 | // | |
416 | // Since these are really sitting on a plane, we can use the method | |
417 | // proposed by the CORE offline. | |
418 | // | |
419 | // Return: | |
420 | // @c true on success, @c false otherwise. | |
421 | // | |
422 | ||
f567c3ce | 423 | // Do the FMD1 stuff |
424 | Double_t rot[9], trans[3]; | |
425 | if (!GetFMD1Plane(rot, trans)) return kFALSE; | |
426 | // const char* path = "/ALIC_1/F1MT_1/FMD1_lid_0"; | |
4c01505b | 427 | |
428 | #if 0 | |
f567c3ce | 429 | // TGeoHMatrix delta; |
4c01505b | 430 | Double_t gRot[9], gTrans[3]; |
431 | TVector3 ocb(-127, -220, 324.67); | |
432 | TVector3 oct(-127, +220, 324.67); | |
433 | TVector3 icb(+127, -220, 324.67); | |
434 | TVector3 ict(+127, +220, 324.67); | |
435 | if (!CalculatePlane(ocb, icb, oct, 0, gTrans, gRot)) { | |
436 | Warning("DoFMD1", "Failed to make reference plane"); | |
437 | return kFALSE; | |
438 | } | |
439 | PrintRotation("FMD1 ref rotation:", gRot); | |
440 | PrintVector("FMD1 ref translation:", gTrans); | |
441 | TGeoRotation ggRot; ggRot.SetMatrix(gRot); | |
442 | TGeoCombiTrans global(gTrans[0], gTrans[1], gTrans[2], &ggRot); | |
443 | #endif | |
9956d453 | 444 | Double_t off = getFMD1Offset(); |
445 | Info("DoFMD1", "Lid offset is %f", off); | |
4c01505b | 446 | |
9956d453 | 447 | TGeoTranslation global(0,0,324.670-off); |
f567c3ce | 448 | if (!MakeDelta(&global, rot, trans, fFMD1Delta)) |
449 | return kFALSE; | |
b2e6f0b0 | 450 | |
f567c3ce | 451 | // PrintRotation("FMD1 delta rotation:", fFMD1Delta.GetRotationMatrix()); |
452 | // PrintVector("FMD1 delta translation:", fFMD1Delta.GetTranslation()); | |
453 | ||
454 | return kTRUE; | |
455 | } | |
456 | ||
457 | //____________________________________________________________________ | |
458 | Bool_t | |
459 | AliFMDSurveyToAlignObjs::GetFMD2Plane(Double_t* rot, Double_t* trans) const | |
460 | { | |
09b6c804 | 461 | // |
462 | // Get the surveyed plane corresponding to the backside of FMD2. | |
463 | // The plane is done as a best fit of the plane equation to at least | |
464 | // 4 of the available survey points. | |
465 | // | |
466 | // Parameters: | |
467 | // rot Rotation matrix (direction cosines) | |
468 | // trans Translation vector. | |
469 | // | |
470 | // Return: | |
471 | // @c true on success, @c false otherwise | |
472 | // | |
f567c3ce | 473 | |
474 | // The possible survey points | |
475 | const char* names[] = { "FMD2_ITOP", "FMD2_OTOP", | |
476 | "FMD2_IBOTM", "FMD2_OBOTM", | |
477 | "FMD2_IBOT", "FMD2_OBOT", | |
478 | 0 }; | |
479 | const char** name = names; | |
480 | ||
481 | TObjArray points; | |
482 | TObjArray errors; | |
b2e6f0b0 | 483 | |
f567c3ce | 484 | // Loop and fill graph |
9956d453 | 485 | int i = 0; |
f567c3ce | 486 | while (*name) { |
487 | TVector3 p, e; | |
9956d453 | 488 | if (!GetPoint(*name, p, e)) { |
489 | name++; | |
490 | i++; | |
491 | continue; | |
492 | } | |
f567c3ce | 493 | |
9956d453 | 494 | if (i == 5) { |
495 | Warning("GetFMD2plane", "Setting error on %d, %s to 0.4", i, *name); | |
496 | e.SetXYZ(0.4, 0.4, 0.4); // OBOT | |
497 | } | |
f567c3ce | 498 | points.Add(new TVector3(p)); |
499 | errors.Add(new TVector3(e)); | |
9956d453 | 500 | name++; |
501 | i++; | |
f567c3ce | 502 | } |
503 | if (points.GetEntries() < 4) { | |
504 | AliWarning(Form("Only got %d survey points - no good for FMD2 plane", | |
505 | points.GetEntries())); | |
506 | return kFALSE; | |
507 | } | |
508 | ||
509 | return FitPlane(points, errors, 0, trans, rot); | |
510 | } | |
511 | ||
512 | #define M(I,J) rot[(J-1) * 3 + (I-1)] | |
513 | //____________________________________________________________________ | |
514 | Bool_t | |
515 | AliFMDSurveyToAlignObjs::DoFMD2() | |
516 | { | |
09b6c804 | 517 | // |
518 | // Do the FMD2 calculations. We have 6 survey points of which only | |
519 | // 5 are normally surveyed. These are all sittings | |
520 | // | |
521 | // - FMD2_ITOP - In-side, top | |
522 | // - FMD2_IBOTM - In-side, middle bottom | |
523 | // - FMD2_IBOT - In-side, bottom | |
524 | // - FMD2_OTOP - Out-side, top | |
525 | // - FMD2_OBOTM - Out-side, middle bottom | |
526 | // - FMD2_OBOT - Out-side, bottom | |
527 | // | |
528 | // The nominal coordinates of these retro-fitted survey stickers | |
529 | // isn't known. Also, these stickers are put on a thin (0.3mm | |
530 | // thick) carbon cover which flexes quite easily. This means, that | |
531 | // to rotations and xy-translation obtained from the survey data | |
532 | // cannot be used, and left is only the z-translation. | |
533 | // | |
534 | // Further more, since FMD2 to is attached to the ITS SPD thermal | |
535 | // screen, it is questionable if the FMD2 survey will ever be used. | |
536 | // | |
537 | // Return: | |
538 | // @c true on success, @c false otherwise. | |
539 | // | |
540 | ||
f567c3ce | 541 | // Do the FMD2 stuff |
542 | Double_t rot[9], trans[3]; | |
543 | if (!GetFMD2Plane(rot, trans)) return kFALSE; | |
4c01505b | 544 | PrintRotation("FMD2 rotation:", rot); |
545 | PrintVector("FMD2 translation:", trans); | |
f567c3ce | 546 | |
4c01505b | 547 | #if 0 |
f567c3ce | 548 | for (int i = 0; i < 3; i++) { |
549 | for (int j = 0; j < 3; j++) { | |
550 | rot[i*3+j] = (i == j ? 1 : 0); | |
551 | } | |
552 | } | |
4c01505b | 553 | #endif |
f567c3ce | 554 | trans[0] = trans[1] = 0; |
555 | trans[2] += 0.015; | |
556 | // PrintRotation("FMD2 rotation:", rot); | |
557 | // PrintVector("FMD2 translation:", trans); | |
b2e6f0b0 | 558 | |
f567c3ce | 559 | // TGeoHMatrix delta; |
560 | if (!MakeDelta("/ALIC_1/F2MT_2/FMD2_support_0/FMD2_back_cover_2", | |
561 | rot, trans, fFMD2Delta)) return kFALSE; | |
b2e6f0b0 | 562 | |
f567c3ce | 563 | // PrintRotation("FMD2 delta rotation:", fFMD2Delta.GetRotationMatrix()); |
564 | // PrintVector("FMD2 delta translation:", fFMD2Delta.GetTranslation()); | |
565 | ||
b2e6f0b0 | 566 | return kTRUE; |
567 | } | |
568 | ||
569 | //____________________________________________________________________ | |
570 | void | |
571 | AliFMDSurveyToAlignObjs::Run() | |
572 | { | |
09b6c804 | 573 | // |
574 | // Run the task. | |
575 | // | |
576 | // | |
577 | ||
b2e6f0b0 | 578 | AliFMDGeometry* geom = AliFMDGeometry::Instance(); |
579 | geom->Init(); | |
580 | geom->InitTransformations(); | |
581 | ||
f567c3ce | 582 | DoFMD1(); |
b2e6f0b0 | 583 | DoFMD2(); |
584 | } | |
585 | ||
4c01505b | 586 | //____________________________________________________________________ |
587 | void | |
588 | AliFMDSurveyToAlignObjs::Run(const char** files) | |
589 | { | |
590 | // | |
591 | // Run the task. | |
592 | // | |
593 | // | |
594 | ||
595 | AliFMDGeometry* geom = AliFMDGeometry::Instance(); | |
596 | geom->Init(); | |
597 | geom->InitTransformations(); | |
598 | ||
599 | const char** file = files; | |
600 | while (*file) { | |
601 | if ((*file)[0] == '\0') { | |
602 | Warning("Run", "no file specified"); | |
603 | file++; | |
604 | continue; | |
605 | } | |
606 | if (!LoadSurveyFromLocalFile(*file)) { | |
607 | Warning("Run", "Failed to load %s", *file); | |
608 | file++; | |
609 | continue; | |
610 | } | |
611 | TString sDet(fSurveyObj->GetDetector()); | |
612 | Int_t d = Int_t(sDet[sDet.Length()-1] - '0'); | |
613 | Info("Run", "Making alignment for %s (%d)", sDet.Data(), d); | |
614 | Bool_t ret = true; | |
615 | switch (d) { | |
616 | case 1: ret = DoFMD1(); break; | |
617 | case 2: ret = DoFMD2(); break; | |
618 | default: | |
619 | Warning("Run", "Do not know how to deal with %s", sDet.Data()); | |
620 | break; | |
621 | } | |
622 | if (!ret) { | |
623 | Warning("Run", "Calculation for %s failed", sDet.Data()); | |
624 | } | |
625 | file++; | |
626 | } | |
627 | CreateAlignObjs(); | |
9956d453 | 628 | GetAlignObjArray()->Print(); |
4c01505b | 629 | FillDefaultAlignObjs(); |
630 | } | |
631 | ||
632 | //____________________________________________________________________ | |
633 | AliAlignObjParams* | |
634 | AliFMDSurveyToAlignObjs::CreateDefaultAlignObj(const TString& path, | |
635 | Int_t id) | |
636 | { | |
637 | Int_t nAlign = fAlignObjArray->GetEntries(); | |
638 | AliAlignObjParams* obj = | |
639 | new ((*fAlignObjArray)[nAlign]) AliAlignObjParams(path.Data(), | |
640 | id,0,0,0,0,0,0,kTRUE); | |
641 | if (!obj) { | |
642 | AliError(Form("Failed to create alignment object for %s", path.Data())); | |
643 | return 0; | |
644 | } | |
645 | if (!obj->SetLocalPars(0, 0, 0, 0, 0, 0)) { | |
646 | AliError(Form("Failed to set local transforms on %s", path.Data())); | |
647 | return obj; | |
648 | } | |
649 | return obj; | |
650 | } | |
651 | ||
652 | //____________________________________________________________________ | |
653 | AliAlignObjParams* | |
654 | AliFMDSurveyToAlignObjs::FindAlignObj(const TString& path) const | |
655 | { | |
656 | AliAlignObjParams* p = 0; | |
657 | for (int i = 0; i < fAlignObjArray->GetEntries(); i++) { | |
658 | p = static_cast<AliAlignObjParams*>(fAlignObjArray->At(i)); | |
659 | if (path.EqualTo(p->GetSymName())) return p; | |
660 | } | |
661 | return 0; | |
662 | } | |
663 | ||
664 | //____________________________________________________________________ | |
665 | Bool_t | |
666 | AliFMDSurveyToAlignObjs::FillDefaultAlignObjs() | |
667 | { | |
668 | for (int d = 1; d <= 3; d++) { | |
669 | const char sides[] = { 'T', 'B', 0 }; | |
670 | const char* side = sides; | |
671 | while (*side) { | |
672 | TString path = TString::Format("FMD/FMD%d_%c", d, *side); | |
673 | AliAlignObjParams* p = FindAlignObj(path); | |
9956d453 | 674 | if (!p) p = CreateDefaultAlignObj(path, 0); |
675 | ||
4c01505b | 676 | const char halves[] = { 'I', d == 1 ? '\0' : 'O', 0 }; |
677 | const char* half = halves; | |
678 | while (*half) { | |
679 | int nsec = *half == 'I' ? 10 : 20; | |
680 | int start = *side == 'T' ? 0 : nsec/2; | |
681 | int end = *side == 'T' ? nsec/2 : nsec; | |
682 | for (int s=start; s < end; s++) { | |
683 | path = TString::Format("FMD/FMD%d_%c/FMD%c_%02d", | |
684 | d, *side, *half, s); | |
685 | CreateDefaultAlignObj(path, 0); | |
686 | } | |
687 | half++; | |
688 | } | |
689 | side++; | |
690 | } | |
691 | ||
692 | } | |
693 | return true; | |
694 | } | |
695 | ||
f567c3ce | 696 | //____________________________________________________________________ |
697 | Bool_t | |
698 | AliFMDSurveyToAlignObjs::CreateAlignObjs() | |
699 | { | |
09b6c804 | 700 | // |
701 | // | |
702 | // Method to create the alignment objects | |
703 | // | |
704 | // Return: | |
705 | // @c true on success, @c false otherwise | |
706 | // | |
f567c3ce | 707 | TClonesArray& array = *fAlignObjArray; |
708 | Int_t n = array.GetEntriesFast(); | |
709 | ||
710 | if (!fFMD1Delta.IsIdentity()) { | |
4c01505b | 711 | new (array[n++]) AliAlignObjParams("FMD/FMD1_T", 0, fFMD1Delta, kTRUE); |
712 | new (array[n++]) AliAlignObjParams("FMD/FMD1_B", 0, fFMD1Delta, kTRUE); | |
f567c3ce | 713 | } |
714 | if (!fFMD2Delta.IsIdentity()) { | |
4c01505b | 715 | new (array[n++]) AliAlignObjParams("FMD/FMD2_T", 0, fFMD2Delta, kTRUE); |
716 | new (array[n++]) AliAlignObjParams("FMD/FMD2_B", 0, fFMD2Delta, kTRUE); | |
f567c3ce | 717 | } |
718 | // array.Print(); | |
719 | ||
720 | return kTRUE; | |
721 | } | |
722 | ||
b2e6f0b0 | 723 | //____________________________________________________________________ |
724 | void | |
725 | AliFMDSurveyToAlignObjs::PrintVector(const char* text, const TVector3& v) | |
726 | { | |
09b6c804 | 727 | // |
728 | // Service member function to print a vector | |
729 | // | |
730 | // Parameters: | |
731 | // text Prefix text | |
732 | // v Vector | |
733 | // | |
b2e6f0b0 | 734 | Double_t va[] = { v.X(), v.Y(), v.Z() }; |
735 | PrintVector(text, va); | |
736 | } | |
737 | //____________________________________________________________________ | |
738 | void | |
739 | AliFMDSurveyToAlignObjs::PrintVector(const char* text, const Double_t* v) | |
740 | { | |
09b6c804 | 741 | // |
742 | // Service member function to print a vector | |
743 | // | |
744 | // Parameters: | |
745 | // text Prefix text | |
746 | // v Vector (array of 3 doubles) | |
747 | // | |
b2e6f0b0 | 748 | std::cout << text |
749 | << std::setw(15) << v[0] | |
750 | << std::setw(15) << v[1] | |
751 | << std::setw(15) << v[2] | |
752 | << std::endl; | |
753 | } | |
754 | ||
755 | ||
756 | //____________________________________________________________________ | |
757 | void | |
758 | AliFMDSurveyToAlignObjs::PrintRotation(const char* text, const Double_t* rot) | |
759 | { | |
09b6c804 | 760 | // |
761 | // Service member function to print a rotation matrix | |
762 | // | |
763 | // Parameters: | |
764 | // text Prefix text | |
765 | // v Matrix (array of 9 doubles) | |
766 | // | |
767 | ||
b2e6f0b0 | 768 | std::cout << text << std::endl; |
769 | for (size_t i = 0; i < 3; i++) { | |
770 | for (size_t j = 0; j < 3; j++) | |
771 | std::cout << std::setw(15) << rot[i * 3 + j]; | |
772 | std::cout << std::endl; | |
773 | } | |
774 | } | |
775 | ||
776 | //____________________________________________________________________ | |
777 | // | |
778 | // EOF | |
779 | // |