1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 // Objects of this class read txt file with survey data
19 // and convert the data into AliAlignObjParams of alignable EMCAL volumes.
20 // AliEMCALSurvey inherits TObject only to use AliLog "functions".
22 // Dummy functions originally written before EMCAL installation and
23 // survey are kept for backward compatibility, but now they are not
26 // Surveyed points on the EMCAL support rails were used with the CATIA
27 // 3D graphics program to determine the positions of the bottom
28 // corners of the active area for each supermodule. These numbers are
29 // read in from file and converted to position of the center and roll,
30 // pitch, yaw angles of each installed SM.
32 // J.L. Klay - Cal Poly
38 #include <TClonesArray.h>
39 #include <TGeoManager.h>
43 #include "AliSurveyObj.h"
44 #include "AliSurveyPoint.h"
46 #include "AliAlignObjParams.h"
47 #include "AliEMCALGeometry.h"
48 #include "AliEMCALSurvey.h"
51 ClassImp(AliEMCALSurvey)
53 //____________________________________________________________________________
54 AliEMCALSurvey::AliEMCALSurvey()
59 //Default constructor.
64 //Coordinates for each SM described in survey reports
66 struct AliEMCALSuperModuleCoords {
67 Double_t fX1; //x coordinate of the center of supermodule
68 Double_t fY1; //y coordinate of the center of supermodule
69 Double_t fZ1; //z coordinate of the center of supermodule
70 Double_t fPsi; //yaw (psi) of supermodule
71 Double_t fTheta; //pitch (theta) of supermodule
72 Double_t fPhi; //roll angle (phi) of supermodule
78 //____________________________________________________________________________
79 AliEMCALSurvey::AliEMCALSurvey(const TString &txtFileName,const SurveyDataType_t type)
84 //Get the geometry object and then attempt to
85 //read survey data from a file, depending on which
86 //method (kSurvey or kDummy) is selected.
88 const AliEMCALGeometry *geom = AliEMCALGeometry::GetInstance();
90 AliError("Cannot obtain AliEMCALGeometry instance.");
94 fNSuperModule = geom->GetNumberOfSuperModules();
96 if(fDataType == kSurvey) {
98 AliSurveyObj *s1 = new AliSurveyObj();
99 s1->FillFromLocalFile(txtFileName);
100 TObjArray* points = s1->GetData();
101 InitSuperModuleData(points);
105 //Use a dummy file that stores x,y,z of the center of each SM
106 //useful for testing...
107 std::ifstream inputFile(txtFileName.Data());
109 AliError(("Cannot open the survey file " + txtFileName).Data());
113 Double_t *xReal = new Double_t[fNSuperModule];
114 Double_t *yReal = new Double_t[fNSuperModule];
115 Double_t *zReal = new Double_t[fNSuperModule];
116 Double_t *psiReal = new Double_t[fNSuperModule];
117 Double_t *thetaReal = new Double_t[fNSuperModule];
118 Double_t *phiReal = new Double_t[fNSuperModule];
120 for (Int_t i = 0; i < fNSuperModule; ++i) {
122 AliError("Error while reading input file.");
131 inputFile>>dummyInt>>xReal[i]>>yReal[i]>>zReal[i]>>psiReal[i]>>thetaReal[i]>>phiReal[i];
134 InitSuperModuleData(xReal, yReal, zReal, psiReal, thetaReal, phiReal);
143 } //kDummy way of doing it
147 //____________________________________________________________________________
148 AliEMCALSurvey::~AliEMCALSurvey()
151 delete [] fSuperModuleData;
154 //____________________________________________________________________________
155 void AliEMCALSurvey::CreateAliAlignObjParams(TClonesArray &array)
157 //Create AliAlignObjParams.
158 const AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance();
160 AliError("Cannot obtain AliEMCALGeometry instance.");
165 AliWarning("Cannot create local transformations for supermodules - gGeoManager does not exist.");
166 AliInfo("Null shifts and rotations will be created instead.");
167 return CreateNullObjects(array, geom);
170 Int_t arrayInd = array.GetEntries(), iIndex = 0;
171 AliGeomManager::ELayerID iLayer = AliGeomManager::kInvalidLayer;
172 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,iIndex);
174 for (Int_t smodnum = 0; smodnum < geom->GetNumberOfSuperModules(); ++smodnum) {
175 TString smodName(TString::Format("EMCAL/FullSupermodule%d", smodnum+1));
176 if(geom->GetKey110DEG() && smodnum >= 10) {
177 smodName = "EMCAL/HalfSupermodule";
178 smodName += (smodnum-10+1);
180 AliEMCALSuperModuleDelta t(GetSuperModuleTransformation(smodnum));
182 ///////////////////////////////
185 // VERY IMPORTANT!!!!
187 // All numbers were calculated in ALICE global c.s., which means
188 // that the last argument in the creation of AliAlignObjParams
189 // MUST BE set to true
190 //////////////////////////////
193 smodName.Data(), volid,
194 t.fXShift, t.fYShift, t.fZShift,
195 -t.fPsi, -t.fTheta, -t.fPhi,
204 //____________________________________________________________________________
205 void AliEMCALSurvey::CreateNullObjects(TClonesArray &array, const AliEMCALGeometry *geom)const
207 //Create null shifts and rotations.
208 Int_t arrayInd = array.GetEntries(), iIndex = 0;
209 AliGeomManager::ELayerID iLayer = AliGeomManager::kInvalidLayer;
210 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,iIndex);
212 for (Int_t smodnum = 0; smodnum < geom->GetNumberOfSuperModules(); ++smodnum) {
213 TString smodName(TString::Format("EMCAL/FullSupermodule%d", smodnum+1));
214 if(geom->GetKey110DEG() && smodnum >= 10) {
215 smodName = "EMCAL/HalfSupermodule";
216 smodName += (smodnum-10+1);
218 new(array[arrayInd]) AliAlignObjParams(smodName.Data(), volid, 0., 0., 0., 0., 0., 0., true);
223 //____________________________________________________________________________
224 AliEMCALSurvey::AliEMCALSuperModuleDelta AliEMCALSurvey::GetSuperModuleTransformation(Int_t supModIndex)const
226 //Supermodule transformation.
227 AliEMCALSuperModuleDelta t = {0., 0., 0., 0., 0., 0.};
228 if (!fSuperModuleData)
231 return fSuperModuleData[supModIndex];
234 //____________________________________________________________________________
235 void AliEMCALSurvey::InitSuperModuleData(const TObjArray *svypts)
237 //This method uses the data points from the EMCAL survey and CATIA program to
238 //create the alignment matrices. Only valid for (installed)
239 //SM, others will have null objects
241 /*--------------------------------------
242 The bottom edges of the strip modules
243 define the active area of the EMCAL, but
244 in software we have a box to hold them which
245 is longer than that. We need to convert
246 info about the position of the corners of the
247 bottom of the active area to the center of
248 the software box that contains the strip
251 View from beam axis up to EMCAL
255 xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxx
259 xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxx
261 <--> = added length <--> = added length
263 * represents the center of the active area
264 % represents the center of the full box (with added length)
266 View from side of topmost SM
271 xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxx
273 xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxx
275 <--> = added length <--> = added length
277 * represents the center of the active area
278 % represents the center of the full box (with added length)
280 -------------------------------------*/
282 AliEMCALGeometry *geom = AliEMCALGeometry::GetInstance();
283 //Center of supermodules
284 Float_t *pars = geom->GetSuperModulesPars();
285 Double_t rpos = (geom->GetEnvelop(0) + geom->GetEnvelop(1))/2.;
286 Double_t phi, phiRad, xpos, ypos, zpos;
288 AliEMCALSuperModuleCoords *idealSM = new AliEMCALSuperModuleCoords[fNSuperModule];
289 for (Int_t smodnum = 0; smodnum < geom->GetNumberOfSuperModules(); ++smodnum) {
290 AliEMCALSuperModuleCoords &smc = idealSM[smodnum];
291 phiRad = geom->GetPhiCenterOfSM(smodnum); //comes in radians
292 phi = phiRad*180./TMath::Pi(); //need degrees for AliAlignObjParams
293 xpos = rpos * TMath::Cos(phiRad);
294 ypos = rpos * TMath::Sin(phiRad);
296 if(geom->GetKey110DEG() && smodnum >= 10) {
297 xpos += (pars[1]/2. * TMath::Sin(phiRad));
298 ypos -= (pars[1]/2. * TMath::Cos(phiRad));
302 smc.fPhi = phi; //degrees
303 smc.fTheta = 0.; //degrees
304 smc.fPsi = 0.; //degrees
311 //printf("PHI OF IDEAL SM = %.2f\n",smc.fPhi);
315 //Real coordinates of center and rotation angles need to be computed
316 //from the survey/CATIA points
319 AliEMCALSuperModuleCoords *realSM = new AliEMCALSuperModuleCoords[fNSuperModule];
320 for (Int_t smodnum = 0; smodnum < geom->GetNumberOfSuperModules(); ++smodnum) {
321 AliEMCALSuperModuleCoords &smc = realSM[smodnum];
322 Double_t zLength = pars[2]*2.; //length of SM in z from software
323 Double_t halfHeight = pars[0]; //half the height of the SM in y direction
325 sprintf(substr,"4096%d",smodnum);
326 //retrieve components of four face points and determine average position of center
329 std::vector<Double_t> xval;
330 std::vector<Double_t> yval;
331 std::vector<Double_t> zval;
333 for(Int_t i = 0; i < svypts->GetEntries(); i++) {
334 AliSurveyPoint* pt = (AliSurveyPoint*)svypts->At(i);
335 TString ptname = pt->GetPointName();
336 if(ptname.Contains(substr)) {
337 //Note: order of values is 00, 01, 10, 11
338 xval.push_back(pt->GetX()*100.); //convert m to cm
339 yval.push_back(pt->GetY()*100.);
340 zval.push_back(pt->GetZ()*100.);
344 //compute center of active area of each SM on bottome face from survey points
345 Double_t activeX = ((xval[0] + (xval[2] - xval[0])/2.) //x00 and x10
346 +(xval[1] + (xval[3] - xval[1])/2.) ) /2.; //x01 and x11
348 // Double_t activeY = ((yval[0] + (yval[2] - yval[0])/2.)
349 // +(yval[1] + (yval[3] - yval[1])/2.) ) /2.;
351 // Double_t activeZ = ((zval[0] + (zval[2] - zval[0])/2.)
352 // +(zval[1] + (zval[3] - zval[1])/2.) ) /2.;
354 //printf("Bottom Center of active area of SM %s: %.2f, %.2f, %.2f\n",substr,activeX,activeY,activeZ);
356 //compute angles for each SM
357 //rotation about each axis
358 //phi = angle in x-y plane
360 Double_t realphi = 0.;
361 //Note: this is phi wrt y axis. To get phi wrt to x, add pi/2
363 realphi = (TMath::ATan((yval[2] - yval[0])/(xval[2] - xval[0]))
364 +TMath::ATan((yval[3] - yval[1])/(xval[3] - xval[1])) )/2.;
366 realphi = (TMath::ATan((yval[0] - yval[2])/(xval[0] - xval[2]))
367 +TMath::ATan((yval[1] - yval[3])/(xval[1] - xval[3])) )/2.;
370 //NOTE: Psi angle is always zero because the two z values being
371 //subtracted are exactly the same, but just in case that could change...
372 //psi = angle in x-z plane
373 Double_t realpsi = (TMath::ATan((zval[0] - zval[2])/(xval[2] - xval[0]))
374 +TMath::ATan((zval[1] - zval[3])/(xval[3] - xval[1])) )/2.;
376 //theta = angle in y-z plane
377 Double_t realtheta = TMath::Pi()/2.
378 - (TMath::ATan((zval[2] - zval[3])/(yval[3] - yval[2]))
379 +TMath::ATan((zval[0] - zval[1])/(yval[1] - yval[0])) )/2.;
381 //printf("Old edge of %s 01: %.2f, %.2f, %.2f\n",substr,xval[1],yval[1],zval[1]);
382 //printf("Old edge of %s 11: %.2f, %.2f, %.2f\n",substr,xval[3],yval[3],zval[3]);
384 //Now calculate the center of the box in z with length added to the 01
385 //and 11 corners, corrected by the theta angle
386 Double_t activeLength = TMath::Abs(((zval[1] - zval[0]) + (zval[3] - zval[2]))/2.);
387 //printf("ACTIVE LENGTH = %.2f\n",activeLength);
389 yval[1] += (zLength - activeLength)*sin(realtheta);
390 yval[3] += (zLength - activeLength)*sin(realtheta);
391 zval[1] += (zLength - activeLength)*cos(realtheta);
392 zval[3] += (zLength - activeLength)*cos(realtheta);
394 yval[1] -= (zLength - activeLength)*sin(realtheta);
395 yval[3] -= (zLength - activeLength)*sin(realtheta);
396 zval[1] -= (zLength - activeLength)*cos(realtheta);
397 zval[3] -= (zLength - activeLength)*cos(realtheta);
400 //printf("New extended edge of %s 01: %.2f, %.2f, %.2f\n",substr,xval[1],yval[1],zval[1]);
401 //printf("New extended edge of %s 11: %.2f, %.2f, %.2f\n",substr,xval[3],yval[3],zval[3]);
403 //Compute the center of the bottom of the box in x,y,z
404 Double_t realX = activeX;
405 Double_t realY = ((yval[0] + (yval[2] - yval[0])/2.)
406 +(yval[1] + (yval[3] - yval[1])/2.) ) /2.;
407 Double_t realZ = ((zval[0] + (zval[2] - zval[0])/2.)
408 +(zval[1] + (zval[3] - zval[1])/2.) ) /2.;
411 //printf("Bottom Center of SM %s Box: %.2f, %.2f, %.2f\n",substr,realX,realY,realZ);
413 //correct the SM centers so that we have the center of the box in
414 //x,y using the phi,theta angles
415 realX += halfHeight*TMath::Cos(TMath::Pi()/2+realphi);
416 realY += halfHeight*(TMath::Sin(TMath::Pi()/2+realphi) + TMath::Sin(realtheta));
417 realZ += halfHeight*TMath::Cos(TMath::Pi()/2-realtheta);
419 //printf("Rotation angles of SM %s: %.4f, %.4f, %.4f\n",substr,realphi*TMath::RadToDeg(),realpsi*TMath::RadToDeg(),realtheta*TMath::RadToDeg());
420 //printf("Middle of SM %s: %.2f, %.2f, %.2f\n\n",substr,realX,realY,realZ);
426 smc.fPhi = 90. + realphi*TMath::RadToDeg();
427 smc.fTheta = 0. + realtheta*TMath::RadToDeg();
428 smc.fPsi = 0. + realpsi*TMath::RadToDeg();
430 }//loop over supermodules
432 fSuperModuleData = new AliEMCALSuperModuleDelta[fNSuperModule];
434 for (Int_t i = 0; i < fNSuperModule; ++i) {
435 const AliEMCALSuperModuleCoords &real = realSM[i];
436 const AliEMCALSuperModuleCoords &ideal = idealSM[i];
437 AliEMCALSuperModuleDelta &t = fSuperModuleData[i];
438 t.fXShift = real.fX1 - ideal.fX1;
439 t.fYShift = real.fY1 - ideal.fY1;
440 t.fZShift = ideal.fZ1 - real.fZ1; //due to z flip for C side
442 t.fZShift *= -1.0; //correct shift for C side
444 t.fPhi = real.fPhi - ideal.fPhi;
445 t.fTheta = real.fTheta - ideal.fTheta;
446 t.fPsi = real.fPsi - ideal.fPsi;
448 printf("===================== SM %d =======================\n",i);
449 printf("real x (%.2f) - ideal x (%.2f) = shift in x (%.2f)\n",real.fX1,ideal.fX1,t.fXShift);
450 printf("real y (%.2f) - ideal y (%.2f) = shift in y (%.2f)\n",real.fY1,ideal.fY1,t.fYShift);
451 printf("real z (%.2f) - ideal z (%.2f) = shift in z (%.2f)\n",real.fZ1,ideal.fZ1,t.fZShift);
452 printf("real theta (%.2f) - ideal theta (%.2f) = shift in theta %.2f\n",real.fTheta,ideal.fTheta,t.fTheta);
453 printf("real psi (%.2f) - ideal psi (%.2f) = shift in psi %.2f\n",real.fPsi,ideal.fPsi,t.fPsi);
454 printf("real phi (%.2f) - ideal phi (%.2f) = shift in phi %.2f\n",real.fPhi,ideal.fPhi,t.fPhi);
455 printf("===================================================\n");
463 //____________________________________________________________________________
464 void AliEMCALSurvey::InitSuperModuleData(const Double_t *xReal, const Double_t *yReal,
465 const Double_t *zReal, const Double_t *psiReal,
466 const Double_t *thetaReal, const Double_t *phiReal)
468 ///////////////////////////////////////
469 //Dummy method just takes the inputted values and applies them
471 //Useful for testing small changes
472 //////////////////////////////////////
473 AliEMCALGeometry *geom = AliEMCALGeometry::GetInstance();
474 //Center of supermodules
475 Float_t *pars = geom->GetSuperModulesPars();
476 Double_t rpos = (geom->GetEnvelop(0) + geom->GetEnvelop(1))/2.;
477 Double_t phi, phiRad, xpos, ypos, zpos;
481 AliEMCALSuperModuleCoords *idealSM = new AliEMCALSuperModuleCoords[fNSuperModule];
482 for (Int_t smodnum = 0; smodnum < geom->GetNumberOfSuperModules(); ++smodnum) {
483 AliEMCALSuperModuleCoords &smc = idealSM[smodnum];
484 phiRad = geom->GetPhiCenterOfSM(smodnum); //comes in radians
485 phi = phiRad*180./TMath::Pi(); //need degrees for AliAlignObjParams
486 xpos = rpos * TMath::Cos(phiRad);
487 ypos = rpos * TMath::Sin(phiRad);
488 if(geom->GetKey110DEG() && smodnum >= 10) {
489 xpos += (pars[1]/2. * TMath::Sin(phiRad));
490 ypos -= (pars[1]/2. * TMath::Cos(phiRad));
495 smc.fPhi = phi; //degrees
496 smc.fTheta = 0.; //degrees
497 smc.fPsi = 0.; //degrees
507 AliEMCALSuperModuleCoords *realSM = new AliEMCALSuperModuleCoords[fNSuperModule];
508 for (Int_t smodnum = 0; smodnum < geom->GetNumberOfSuperModules(); ++smodnum) {
509 AliEMCALSuperModuleCoords &smc = realSM[smodnum];
510 smc.fX1 = xReal[smodnum];
511 smc.fY1 = yReal[smodnum];
512 smc.fZ1 = zReal[smodnum];
513 smc.fTheta = thetaReal[smodnum];
514 smc.fPsi = psiReal[smodnum];
515 smc.fPhi = phiReal[smodnum];
518 fSuperModuleData = new AliEMCALSuperModuleDelta[fNSuperModule];
520 for (Int_t i = 0; i < fNSuperModule; ++i) {
521 const AliEMCALSuperModuleCoords &real = realSM[i];
522 const AliEMCALSuperModuleCoords &ideal = idealSM[i];
523 AliEMCALSuperModuleDelta &t = fSuperModuleData[i];
524 t.fTheta = real.fTheta - ideal.fTheta;
526 t.fPhi = real.fPhi - ideal.fPhi;
527 t.fXShift = real.fX1 - ideal.fX1;
528 t.fYShift = real.fY1 - ideal.fY1;
529 t.fZShift = real.fZ1 - ideal.fZ1;
531 printf("===================== SM %d =======================\n",i);
532 printf("real x (%.2f) - ideal x (%.2f) = shift in x (%.2f)\n",real.fX1,ideal.fX1,t.fXShift);
533 printf("real y (%.2f) - ideal y (%.2f) = shift in y (%.2f)\n",real.fY1,ideal.fY1,t.fYShift);
534 printf("real z (%.2f) - ideal z (%.2f) = shift in z (%.2f)\n",real.fZ1,ideal.fZ1,t.fZShift);
535 printf("real theta (%.2f) - ideal theta (%.2f) = shift in theta %.2f\n",real.fTheta,ideal.fTheta,t.fTheta);
536 printf("real psi (%.2f) - ideal psi (%.2f) = shift in psi %.2f\n",real.fPsi,ideal.fPsi,t.fPsi);
537 printf("real phi (%.2f) - ideal phi (%.2f) = shift in phi %.2f\n",real.fPhi,ideal.fPhi,t.fPhi);
538 printf("===================================================\n");