void PMDSurveyToAlignment_v1(){ // Macro to convert survey data into alignment data. // The position of four fiducial marks, sticked on the // preshower plane of PMD is converted into the // global position. if(!gGeoManager) AliGeomManager::LoadGeometry("geometry.root"); TClonesArray *array = new TClonesArray("AliAlignObjMatrix",10); TClonesArray &mobj = *array; Double_t l_vect[3]={0.,0.,0.}; // a local vector (the origin) Double_t g_vect_1[3]; // vector corresp. to it in global RS for sector-1 Double_t g_vect_2[3]; // vector corresp. to it in global RS for sector-2 Double_t g_vect_3[3]; // vector corresp. to it in global RS for sector-3 Double_t g_vect_4[3]; // vector corresp. to it in global RS for sector-4 //**************** get global matrix ******************* TGeoHMatrix *g3_1 = AliGeomManager::GetMatrix("PMD/Sector1"); TGeoNode* n3_1 = gGeoManager->GetCurrentNode(); TGeoHMatrix* l3_1 = n3_1->GetMatrix();// to get local matrix g3_1->LocalToMaster(l_vect,g_vect_1); // point coordinates in the global RS cout<GetCurrentNode(); TGeoHMatrix* l3_2 = n3_2->GetMatrix(); g3_2->LocalToMaster(l_vect,g_vect_2); cout<GetCurrentNode(); TGeoHMatrix* l3_3 = n3_3->GetMatrix(); g3_3->LocalToMaster(l_vect,g_vect_3); cout<GetCurrentNode(); TGeoHMatrix* l3_4 = n3_4->GetMatrix(); g3_4->LocalToMaster(l_vect,g_vect_4); cout<FillFromLocalFile("Survey_Points_PMD01.txt");//this file will be given //by the surveyer after the installation of PMD. so->FillFromLocalFile("PMDGenSurveyPoints_v1.txt");//This file can be generated by the user. Int_t size = so->GetEntries(); Printf("Title: \"%s\"", so->GetReportTitle().Data()); Printf("Date: \"%s\"", so->GetReportDate().Data()); Printf("Detector: \"%s\"", so->GetDetector().Data()); Printf("URL: \"%s\"", so->GetURL().Data()); Printf("Number: \"%d\"", so->GetReportNumber()); Printf("Version: \"%d\"", so->GetReportVersion()); Printf("Observations: \"%s\"", so->GetObservations().Data()); Printf("Coordinate System: \"%s\"", so->GetCoordSys().Data()); Printf("Measurement Units: \"%s\"", so->GetUnits().Data()); Printf("Nr Columns: \"%d\" \n", so->GetNrColumns()); TObjArray *colNames = so->GetColumnNames(); TObjArray *points = so->GetData(); Printf("Relevant points to be used for alignment procedure (in mm):"); printf("%d \n",points->GetEntries()); Float_t surveyFidX[28]; Float_t surveyFidY[28]; Float_t surveyFidZ[28]; for (Int_t i = 0; i < points->GetEntries(); ++i) { surveyFidX[i] = (((AliSurveyPoint *) points->At(i))->GetX()); surveyFidY[i] = (((AliSurveyPoint *) points->At(i))->GetY()); surveyFidZ[i] = (((AliSurveyPoint *) points->At(i))->GetZ()); } for (Int_t i=0; i < 28; i++) { // printf("%f %f %f\n",surveyFidX[i],surveyFidY[i],surveyFidZ[i]); } const Int_t kNDIM1 = 3; const Int_t kNDIM2 = 4; const Double_t kIdealOrig[kNDIM1] = {0., 0., 3645.}; // Geant values Int_t i; Double_t s1; Double_t ab1[kNDIM1], bc1[kNDIM1], nn1[kNDIM1], plane1[kNDIM1]; Double_t nga1[kNDIM2][kNDIM1]; Double_t s2; Double_t ab2[kNDIM1], bc2[kNDIM1], nn2[kNDIM1], plane2[kNDIM1]; Double_t nga2[kNDIM2][kNDIM1]; Double_t s3; Double_t ab3[kNDIM1], bc3[kNDIM1], nn3[kNDIM1], plane3[kNDIM1]; Double_t nga3[kNDIM2][kNDIM1]; Double_t s4; Double_t ab4[kNDIM1], bc4[kNDIM1], nn4[kNDIM1], plane4[kNDIM1]; Double_t nga4[kNDIM2][kNDIM1]; // These are the sequence of fiducial marks for sector-1,2,3 & 4 - to be // given by the user. Int_t surseq1[kNDIM2] = {19, 20, 18, 17}; Int_t surseq2[kNDIM2] = {15, 16, 14, 13}; Int_t surseq3[kNDIM2] = {11, 12, 06, 05}; Int_t surseq4[kNDIM2] = {27, 28, 22, 21}; for (i = 0; i < 28; i++) { for (Int_t j = 0; j < 4; j++) { if (surseq1[j] == i+1) { nga1[j][0] = surveyFidX[i]; nga1[j][1] = surveyFidY[i]; nga1[j][2] = surveyFidZ[i]; } else if (surseq2[j] == i+1) { nga2[j][0] = surveyFidX[i]; nga2[j][1] = surveyFidY[i]; nga2[j][2] = surveyFidZ[i]; } else if (surseq3[j] == i+1) { nga3[j][0] = surveyFidX[i]; nga3[j][1] = surveyFidY[i]; nga3[j][2] = surveyFidZ[i]; } else if (surseq4[j] == i+1) { nga4[j][0] = surveyFidX[i]; nga4[j][1] = surveyFidY[i]; nga4[j][2] = surveyFidZ[i]; } } } // First vector on the plane of the fiducial marks. for(i = 0; i < kNDIM1; i++) { ab1[i] = nga1[1][i] - nga1[0][i]; ab2[i] = nga2[1][i] - nga2[0][i]; ab3[i] = nga3[1][i] - nga3[0][i]; ab4[i] = nga4[1][i] - nga4[0][i]; } // Second vector on the plane of the fiducial marks. for(i = 0; i < kNDIM1; i++) { bc1[i] = nga1[2][i] - nga1[1][i]; bc2[i] = nga2[2][i] - nga2[1][i]; bc3[i] = nga3[2][i] - nga3[1][i]; bc4[i] = nga4[2][i] - nga4[1][i]; } // Vector normal to the plane of the fiducial marks obtained // as cross product of the two vectors on the sector-1,2,3 and 4. // Vector normal to the sector-1. nn1[0] = ab1[1] * bc1[2] - ab1[2] * bc1[1]; nn1[1] = ab1[2] * bc1[0] - ab1[0] * bc1[2]; nn1[2] = ab1[0] * bc1[1] - ab1[1] * bc1[0]; // Vector normal to the sector-2. nn2[0] = ab2[1] * bc2[2] - ab2[2] * bc2[1]; nn2[1] = ab2[2] * bc2[0] - ab2[0] * bc2[2]; nn2[2] = ab2[0] * bc2[1] - ab2[1] * bc2[0]; // Vector normal to the sector-3. nn3[0] = ab3[1] * bc3[2] - ab3[2] * bc3[1]; nn3[1] = ab3[2] * bc3[0] - ab3[0] * bc3[2]; nn3[2] = ab3[0] * bc3[1] - ab3[1] * bc3[0]; // Vector normal to the sector-4. nn4[0] = ab4[1] * bc4[2] - ab4[2] * bc4[1]; nn4[1] = ab4[2] * bc4[0] - ab4[0] * bc4[2]; nn4[2] = ab4[0] * bc4[1] - ab4[1] * bc4[0]; Double_t sizen1 = TMath::Sqrt( nn1[0]*nn1[0] + nn1[1]*nn1[1] + nn1[2]*nn1[2] ); Double_t sizen2 = TMath::Sqrt( nn2[0]*nn2[0] + nn2[1]*nn2[1] + nn2[2]*nn2[2] ); Double_t sizen3 = TMath::Sqrt( nn3[0]*nn3[0] + nn3[1]*nn3[1] + nn3[2]*nn3[2] ); Double_t sizen4 = TMath::Sqrt( nn4[0]*nn4[0] + nn4[1]*nn4[1] + nn4[2]*nn4[2] ); if(sizen1 > 1.e-8) { s1 = Double_t(1.)/sizen1 ; //normalization factor } else { return 0; } if(sizen2 > 1.e-8) { s2 = Double_t(1.)/sizen2 ; //normalization factor } else { return 0; } if(sizen3 > 1.e-8) { s3 = Double_t(1.)/sizen3 ; //normalization factor } else { return 0; } if(sizen4 > 1.e-8) { s4 = Double_t(1.)/sizen4 ; //normalization factor } else { return 0; } // Plane expressed in the hessian normal form, see: // http://mathworld.wolfram.com/HessianNormalForm.html for(i = 0; i < kNDIM1; i++) { plane1[i] = nn1[i] * s1; plane2[i] = nn2[i] * s2; plane3[i] = nn3[i] * s3; plane4[i] = nn4[i] * s4; } cout<<"Unit vector normal to sector-1 : "< 1.e-8) { for(i = 0; i < 3; i++) { ab1[i] /= sx1; } } Double_t sy1 = TMath::Sqrt(bc1[0]*bc1[0] + bc1[1]*bc1[1] + bc1[2]*bc1[2]); if(sy1 > 1.e-8) { for(i = 0; i < kNDIM1; i++) { bc1[i] /= sy1; } } Double_t sx2 = TMath::Sqrt(ab2[0]*ab2[0] + ab2[1]*ab2[1] + ab2[2]*ab2[2]); if(sx2 > 1.e-8) { for(i = 0; i < kNDIM1; i++) { ab2[i] /= sx2; } } Double_t sy2 = TMath::Sqrt(bc2[0]*bc2[0] + bc2[1]*bc2[1] + bc2[2]*bc2[2]); if(sy2 > 1.e-8) { for(i = 0; i < kNDIM1; i++) { bc2[i] /= sy2; } } Double_t sx3 = TMath::Sqrt(ab3[0]*ab3[0] + ab3[1]*ab3[1] + ab3[2]*ab3[2]); if(sx3 > 1.e-8) { for(i = 0; i < kNDIM1; i++) { ab3[i] /= sx3; } } Double_t sy3 = TMath::Sqrt(bc3[0]*bc3[0] + bc3[1]*bc3[1] + bc3[2]*bc3[2]); if(sy3 > 1.e-8) { for(i = 0; i < kNDIM1; i++) { bc3[i] /= sy3; } } Double_t sx4 = TMath::Sqrt(ab4[0]*ab4[0] + ab4[1]*ab4[1] + ab4[2]*ab4[2]); if(sx4 > 1.e-8) { for(i = 0; i < kNDIM1; i++) { ab4[i] /= sx4; } } Double_t sy4 = TMath::Sqrt(bc4[0]*bc4[0] + bc4[1]*bc4[1] + bc4[2]*bc4[2]); if(sy4 > 1.e-8) { for(i = 0; i < kNDIM1; i++) { bc4[i] /= sy4; } } // The global matrix for the surveyed volume - ng_1 Double_t rot1[9] = { ab1[0], bc1[0], plane1[0], ab1[1], bc1[1], plane1[1], ab1[2], bc1[2], plane1[2]}; TGeoHMatrix ng_1; for(Int_t i=0; i<3; i++) orig1[i]*=0.1;// To convert the surveyed origin //in cm, as in geometry all the distances are in cm. orig1[0]=orig1[0]- 0.321402;//offset in X. orig1[1]=orig1[1]- 0.074998;//offset in Y. ng_1.SetTranslation(orig1); ng_1.SetRotation(rot1); // cout<<"\n** Global Matrix from surveyed fiducial marks for sector-1 **\n"; //ng_1.Print(); Double_t rot2[9] = {ab2[0], bc2[0], plane2[0], ab2[1], bc2[1], plane2[1], ab2[2], bc2[2], plane2[2]}; TGeoHMatrix ng_2; for(Int_t i=0; i<3; i++) orig2[i]*=0.1; orig2[0]=orig2[0]+ 0.321402;//offset in X. orig2[1]=orig2[1]+ 0.074998;//offset in Y. ng_2.SetTranslation(orig2); ng_2.SetRotation(rot2); // cout<<"\n** Global Matrix from surveyed fiducial marks for sector-2 **\n"; // ng_2.Print(); Double_t rot3[9] = {ab3[0], bc3[0], plane3[0], ab3[1], bc3[1], plane3[1], ab3[2], bc3[2], plane3[2]}; TGeoHMatrix ng_3; for(Int_t i=0; i<3; i++) orig3[i]*=0.1; orig3[0]=orig3[0]+ 0.291602;//offset in X orig3[1]=orig3[1]+ 0.100001;//offset in Y ng_3.SetTranslation(orig3); ng_3.SetRotation(rot3); // cout<<"\n** Global Matrix from surveyed fiducial marks for sector-3 **\n"; //ng_3.Print(); Double_t rot4[9] = {ab4[0], bc4[0], plane4[0], ab4[1], bc4[1], plane4[1], ab4[2], bc4[2], plane4[2]}; TGeoHMatrix ng_4; for(Int_t i=0; i<3; i++) orig4[i]*=0.1; orig4[0]=orig4[0]- 0.291602;//offset in X orig4[1]=orig4[1]- 0.100001;//offset in Y ng_4.SetTranslation(orig4); ng_4.SetRotation(rot4); //cout<<"\n** Global Matrix from surveyed fiducial marks for sector-4 **\n"; //ng_4.Print(); // To produce the alignment object for the given volume you would // then do something like this: // Calculate the global delta transformation as ng * g3^-1 TGeoPhysicalNode* pn3_1 = gGeoManager->MakePhysicalNode("ALIC_1/EPM1_1"); TGeoHMatrix gdelta_1 = g3_1->Inverse(); //now equal to the inverse of g3 gdelta_1.MultiplyLeft(&ng_1); Int_t index = 0; Printf("The global delta transformation for sector-1"); gdelta_1.Print(); TGeoPhysicalNode* pn3_2 = gGeoManager->MakePhysicalNode("ALIC_1/EPM2_1"); TGeoHMatrix gdelta_2 = g3_2->Inverse(); gdelta_2.MultiplyLeft(&ng_2); Int_t index = 0; Printf("The global delta transformation for sector-2"); gdelta_2.Print(); TGeoPhysicalNode* pn3_3 = gGeoManager->MakePhysicalNode("ALIC_1/EPM3_1"); TGeoHMatrix gdelta_3 = g3_3->Inverse(); gdelta_3.MultiplyLeft(&ng_3); Int_t index = 0; Printf("The global delta transformation for sector-3"); gdelta_3.Print(); TGeoPhysicalNode* pn3_4 = gGeoManager->MakePhysicalNode("ALIC_1/EPM4_1"); TGeoHMatrix gdelta_4 = g3_4->Inverse(); gdelta_4.MultiplyLeft(&ng_4); Int_t index = 0; Printf("The global delta transformation for sector-4"); gdelta_4.Print(); new(mobj[0]) AliAlignObjMatrix("PMD/Sector1",index,gdelta_1,kTRUE); new(mobj[1]) AliAlignObjMatrix("PMD/Sector2",index,gdelta_2,kTRUE); new(mobj[2]) AliAlignObjMatrix("PMD/Sector3",index,gdelta_3,kTRUE); new(mobj[3]) AliAlignObjMatrix("PMD/Sector4",index,gdelta_4,kTRUE); TString strStorage(gSystem->Getenv("TOCDB")); if(strStorage != TString("kTRUE")){ // save on file TFile f("PMDSurvey.root","RECREATE"); if(!f) cerr<<"cannot open file for output\n"; f.cd(); f.WriteObject(array,"PMDSurveyObjs ","kSingleKey"); f.Close(); }else{ // save in CDB storage AliCDBManager* cdb = AliCDBManager::Instance(); AliCDBStorage* storage = cdb->GetStorage("local://$ALICE_ROOT"); AliCDBMetaData* mda = new AliCDBMetaData(); mda->SetResponsible(" "); mda->SetComment("Alignment objects for PMD survey"); AliCDBId id("PMD/Align/Data",0,AliCDBRunRange::Infinity()); storage->Put(array,id,mda); } array->Delete(); }