--- /dev/null
+void PMDSurveyPointsGen_v1(){
+
+ // Macro to generate survey points in the format of AliSurveyObj
+ // by giving some finite rotation and translation.
+
+ 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<<endl<<"Origin of sector-1 in the global RS: "<<
+ g_vect_1[0]<<" "<<g_vect_1[1]<<" "<<g_vect_1[2]<<" "<<endl;
+
+
+ TGeoHMatrix *g3_2 = AliGeomManager::GetMatrix("PMD/Sector2");
+ TGeoNode* n3_2 = gGeoManager->GetCurrentNode();
+ TGeoHMatrix* l3_2 = n3_2->GetMatrix();
+ g3_2->LocalToMaster(l_vect,g_vect_2);
+
+ cout<<endl<<"Origin of sector-2 in the global RS: "<<
+ g_vect_2[0]<<" "<<g_vect_2[1]<<" "<<g_vect_2[2]<<" "<<endl;
+
+
+ TGeoHMatrix *g3_3 = AliGeomManager::GetMatrix("PMD/Sector3");
+ TGeoNode* n3_3 = gGeoManager->GetCurrentNode();
+ TGeoHMatrix* l3_3 = n3_3->GetMatrix();
+ g3_3->LocalToMaster(l_vect,g_vect_3);
+
+ cout<<endl<<"Origin of the sector-3 in the global RS: "<<
+ g_vect_3[0]<<" "<<g_vect_3[1]<<" "<<g_vect_3[2]<<" "<<endl;
+
+
+ TGeoHMatrix *g3_4 = AliGeomManager::GetMatrix("PMD/Sector4");
+ TGeoNode* n3_4 = gGeoManager->GetCurrentNode();
+ TGeoHMatrix* l3_4 = n3_4->GetMatrix();
+ g3_4->LocalToMaster(l_vect,g_vect_4);
+
+ cout<<endl<<"Origin of the sector-4 in the global RS: "<<
+ g_vect_4[0]<<" "<<g_vect_4[1]<<" "<<g_vect_4[2]<<" "<<endl;
+
+
+
+ // Hereafter the four ideal fiducial marks on the PMD
+ // are expressed in local coordinates.
+ //All the coordinates are expressed in cm here.
+ const Double_t zsize = 2.3;
+ const Double_t zoffset = 0.0;
+ const Double_t zdepth = zsize + zoffset + g_vect_1[2];
+
+ // Coordinates of four Ideal fudicial marks on the sector-1 of the PMD in
+ //global frame of reference.
+
+ Double_t A1[3] = {12.025, 37.85, zdepth};// Fiducial mark # 19
+ Double_t B1[3] = {74.275, 37.85, zdepth};// Fiducial mark # 20
+ Double_t C1[3] = {74.275, 87.05, zdepth};// Fiducial mark # 18
+ Double_t D1[3] = {12.025, 87.05, zdepth};// Fiducial mark # 17
+
+ // Coordinates of four Ideal fudicial marks on the sector-2 of the PMD in
+ //global frame of reference.
+
+ Double_t A2[3] = {-74.275, -87.05, zdepth};// Fiducial mark # 15
+ Double_t B2[3] = {-12.025, -87.05, zdepth};// Fiducial mark # 16
+ Double_t C2[3] = {-12.025, -37.85, zdepth};// Fiducial mark # 14
+ Double_t D2[3] = {-74.275, -37.85, zdepth};// Fiducial mark # 13
+
+ // Coordinates of four Ideal fudicial marks on the sector-3 of the PMD in
+ //global frame of reference.
+
+ Double_t A3[3] = {-74.275, 11.15, zdepth};// Fiducial mark # 11
+ Double_t B3[3] = {7.725, 11.15, zdepth}; // Fiducial mark # 12
+ Double_t C3[3] = {7.725, 87.05, zdepth}; // Fiducial mark # 06
+ Double_t D3[3] = {-74.25, 87.05, zdepth}; // Fiducial mark # 05
+
+ // Coordinates of four Ideal fudicial marks on the sector-4 of the PMD in
+ //global frame of reference.
+
+ Double_t A4[3] = {-7.725, -87.05, zdepth};// Fiducial mark # 27
+ Double_t B4[3] = {74.275, -87.05, zdepth};// Fiducial mark # 28
+ Double_t C4[3] = {74.275, -11.15, zdepth};// Fiducial mark # 22
+ Double_t D4[3] = {-7.725, -11.15, zdepth};// Fiducial mark # 21
+
+ // Let's misalign the sector-1 for testing purpose only.
+ for (Int_t i = 0; i < 3; i++)
+ {
+ // To convert the coordinates of fiducial marks in local RS as those are
+ // given above in global RS.
+ A1[i] = A1[i] - g_vect_1[i];
+ B1[i] = B1[i] - g_vect_1[i];
+ C1[i] = C1[i] - g_vect_1[i];
+ D1[i] = D1[i] - g_vect_1[i];
+
+ }
+
+
+ // ^ local y
+ // |
+ // D-------------|-------------C
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // ------------------|------------------> local x
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // | | |
+ // A-------------|-------------B
+ //
+ // local z exiting the plane of the screen
+
+ Double_t gA1[3], gB1[3], gC1[3], gD1[3];
+
+ g3_1->LocalToMaster(A1,gA1);
+ g3_1->LocalToMaster(B1,gB1);
+ g3_1->LocalToMaster(C1,gC1);
+ g3_1->LocalToMaster(D1,gD1);
+
+ /*
+ cout<<endl<<"Ideal fiducial marks coordinates in the global RS:1\n"<<
+ "A1 "<<gA1[0]<<" "<<gA1[1]<<" "<<gA1[2]<<" "<<endl<<
+ "B1 "<<gB1[0]<<" "<<gB1[1]<<" "<<gB1[2]<<" "<<endl<<
+ "C1 "<<gC1[0]<<" "<<gC1[1]<<" "<<gC1[2]<<" "<<endl<<
+ "D1 "<<gD1[0]<<" "<<gD1[1]<<" "<<gD1[2]<<" "<<endl;
+ */
+
+ // We apply a delta transformation to the surveyed vol. to represent
+ // its real position, given below by ng3 and nl3, which differs from its
+ // ideal position saved above in g3 and l3
+
+ TGeoPhysicalNode* pn3_1 = gGeoManager->MakePhysicalNode("ALIC_1/EPM1_1");
+
+ Double_t dphi_1 = 0.; // tilt around Z
+ Double_t dtheta_1 = 0.; // tilt around X
+ Double_t dpsi_1 = 0.; // tilt around new Z
+
+ Double_t dx_1 = 2.; // shift along X
+ Double_t dy_1 = 3.; // shift along Y
+ Double_t dz_1 = 4.; // shift along Z
+
+ TGeoRotation* rrot_1 = new TGeoRotation("rot",dphi_1,dtheta_1,dpsi_1);
+ TGeoCombiTrans localdelta_1 = *(new TGeoCombiTrans(dx_1,dy_1,dz_1, rrot_1));
+
+ // new local matrix, representing real position
+ TGeoHMatrix nlocal_1 = *l3_1 * localdelta_1;
+ TGeoHMatrix* nl3_1 = new TGeoHMatrix(nlocal_1);
+ pn3_1->Align(nl3_1);
+
+ // Let's get the global matrix for later comparison
+ TGeoHMatrix* ng3_1 = pn3_1->GetMatrix(); //"real" global matrix,what survey sees
+ printf("\n\n************ real global matrix for Sector-1 **************\n");
+ ng3_1->Print();
+
+ Double_t ngA1[3], ngB1[3], ngC1[3], ngD1[3];
+ ng3_1->LocalToMaster(A1,ngA1);
+ ng3_1->LocalToMaster(B1,ngB1);
+ ng3_1->LocalToMaster(C1,ngC1);
+ ng3_1->LocalToMaster(D1,ngD1);
+
+ cout<<endl<<"Fiducial marks coordinates in the global RS given by survey:1\n"<<
+ "A1 "<<ngA1[0]<<" "<<ngA1[1]<<" "<<ngA1[2]<<" "<<endl<<
+ "B1 "<<ngB1[0]<<" "<<ngB1[1]<<" "<<ngB1[2]<<" "<<endl<<
+ "C1 "<<ngC1[0]<<" "<<ngC1[1]<<" "<<ngC1[2]<<" "<<endl<<
+ "D1 "<<ngD1[0]<<" "<<ngD1[1]<<" "<<ngD1[2]<<" "<<endl;
+
+
+ // Let's misalign the sector-2.
+ for (Int_t i = 0; i < 3; i++)
+ {
+ // To convert the coordinates of fiducial marks in local RS as those are
+ // given above in global RS.
+ A2[i] = A2[i] - g_vect_2[i];
+ B2[i] = B2[i] - g_vect_2[i];
+ C2[i] = C2[i] - g_vect_2[i];
+ D2[i] = D2[i] - g_vect_2[i];
+
+ }
+
+ Double_t gA2[3], gB2[3], gC2[3], gD2[3];
+
+ g3_2->LocalToMaster(A2,gA2);
+ g3_2->LocalToMaster(B2,gB2);
+ g3_2->LocalToMaster(C2,gC2);
+ g3_2->LocalToMaster(D2,gD2);
+
+ /*
+ cout<<endl<<"Ideal fiducial marks coordinates in the global RS:2\n"<<
+ "A2 "<<gA2[0]<<" "<<gA2[1]<<" "<<gA2[2]<<" "<<endl<<
+ "B2 "<<gB2[0]<<" "<<gB2[1]<<" "<<gB2[2]<<" "<<endl<<
+ "C2 "<<gC2[0]<<" "<<gC2[1]<<" "<<gC2[2]<<" "<<endl<<
+ "D2 "<<gD2[0]<<" "<<gD2[1]<<" "<<gD2[2]<<" "<<endl;
+ */
+
+ // We apply a delta transformation to the surveyed vol. to represent
+ // its real position, given below by ng3 and nl3, which differs from its
+ // ideal position saved above in g3 and l3
+
+ TGeoPhysicalNode* pn3_2 = gGeoManager->MakePhysicalNode("ALIC_1/EPM2_1");
+
+ Double_t dphi_2 = 0.; // tilt around Z
+ Double_t dtheta_2 = 0.; // tilt around X
+ Double_t dpsi_2 = 0.; // tilt around new Z
+
+ Double_t dx_2 = 2.; // shift along X
+ Double_t dy_2 = 3.; // shift along Y
+ Double_t dz_2 = 4.; // shift along Z
+
+ TGeoRotation* rrot_2 = new TGeoRotation("rot",dphi_2,dtheta_2,dpsi_2);
+ TGeoCombiTrans localdelta_2 = *(new TGeoCombiTrans(dx_2,dy_2,dz_2, rrot_2));
+
+ // new local matrix, representing real position
+ TGeoHMatrix nlocal_2 = *l3_2 * localdelta_2;
+ TGeoHMatrix* nl3_2 = new TGeoHMatrix(nlocal_2);
+ pn3_2->Align(nl3_2);
+
+ // Let's get the global matrix for later comparison
+ TGeoHMatrix* ng3_2 = pn3_2->GetMatrix(); //real global matrix
+ printf("\n\n************ real global matrix for Sector-2 **************\n");
+ ng3_2->Print();
+
+ Double_t ngA2[3], ngB2[3], ngC2[3], ngD2[3];
+ ng3_2->LocalToMaster(A2,ngA2);
+ ng3_2->LocalToMaster(B2,ngB2);
+ ng3_2->LocalToMaster(C2,ngC2);
+ ng3_2->LocalToMaster(D2,ngD2);
+
+ cout<<endl<<"Fiducial marks coordinates in the global RS given by survey:2\n"<<
+ "A2 "<<ngA2[0]<<" "<<ngA2[1]<<" "<<ngA2[2]<<" "<<endl<<
+ "B2 "<<ngB2[0]<<" "<<ngB2[1]<<" "<<ngB2[2]<<" "<<endl<<
+ "C2 "<<ngC2[0]<<" "<<ngC2[1]<<" "<<ngC2[2]<<" "<<endl<<
+ "D2 "<<ngD2[0]<<" "<<ngD2[1]<<" "<<ngD2[2]<<" "<<endl;
+
+// Let's misalign the sector-3.
+ for (Int_t i = 0; i < 3; i++)
+ {
+ // To convert the coordinates of fiducial marks in local RS as those are
+ // given above in global RS.
+ A3[i] = A3[i] - g_vect_3[i];
+ B3[i] = B3[i] - g_vect_3[i];
+ C3[i] = C3[i] - g_vect_3[i];
+ D3[i] = D3[i] - g_vect_3[i];
+ }
+
+ Double_t gA3[3], gB3[3], gC3[3], gD3[3];
+
+ g3_3->LocalToMaster(A3,gA3);
+ g3_3->LocalToMaster(B3,gB3);
+ g3_3->LocalToMaster(C3,gC3);
+ g3_3->LocalToMaster(D3,gD3);
+
+ /*
+ cout<<endl<<"Ideal fiducial marks coordinates in the global RS:3\n"<<
+ "A3 "<<gA3[0]<<" "<<gA3[1]<<" "<<gA3[2]<<" "<<endl<<
+ "B3 "<<gB3[0]<<" "<<gB3[1]<<" "<<gB3[2]<<" "<<endl<<
+ "C3 "<<gC3[0]<<" "<<gC3[1]<<" "<<gC3[2]<<" "<<endl<<
+ "D3 "<<gD3[0]<<" "<<gD3[1]<<" "<<gD3[2]<<" "<<endl;
+ */
+
+ // We apply a delta transformation to the surveyed vol. to represent
+ // its real position, given below by ng3 and nl3, which differs from its
+ // ideal position saved above in g3 and l3
+
+ TGeoPhysicalNode* pn3_3 = gGeoManager->MakePhysicalNode("ALIC_1/EPM3_1");
+
+ Double_t dphi_3 = 0.; // tilt around Z
+ Double_t dtheta_3 = 0.; // tilt around X
+ Double_t dpsi_3 = 0.; // tilt around new Z
+
+ Double_t dx_3 = 2.; // shift along X
+ Double_t dy_3 = 3.; // shift along Y
+ Double_t dz_3 = 4 ; // shift along Z
+
+ TGeoRotation* rrot_3 = new TGeoRotation("rot",dphi_3,dtheta_3,dpsi_3);
+ TGeoCombiTrans localdelta_3 = *(new TGeoCombiTrans(dx_3,dy_3,dz_3, rrot_3));
+
+ // new local matrix, representing real position
+ TGeoHMatrix nlocal_3 = *l3_3 * localdelta_3;
+ TGeoHMatrix* nl3_3 = new TGeoHMatrix(nlocal_3);
+ pn3_3->Align(nl3_3);
+
+ // Let's get the global matrix for later comparison
+ TGeoHMatrix* ng3_3 = pn3_3->GetMatrix(); //"real" global matrix,what survey sees
+ printf("\n\n************ real global matrix for Sector-3 **************\n");
+ ng3_3->Print();
+
+ Double_t ngA3[3], ngB3[3], ngC3[3], ngD3[3];
+ ng3_3->LocalToMaster(A3,ngA3);
+ ng3_3->LocalToMaster(B3,ngB3);
+ ng3_3->LocalToMaster(C3,ngC3);
+ ng3_3->LocalToMaster(D3,ngD3);
+
+ cout<<endl<<"Fiducial marks coordinates in the global RS given by survey:3\n"<<
+ "A3 "<<ngA3[0]<<" "<<ngA3[1]<<" "<<ngA3[2]<<" "<<endl<<
+ "B3 "<<ngB3[0]<<" "<<ngB3[1]<<" "<<ngB3[2]<<" "<<endl<<
+ "C3 "<<ngC3[0]<<" "<<ngC3[1]<<" "<<ngC3[2]<<" "<<endl<<
+ "D3 "<<ngD3[0]<<" "<<ngD3[1]<<" "<<ngD3[2]<<" "<<endl;
+
+ // Let's misalign the sector-4.
+ for (Int_t i = 0; i < 3; i++)
+ {
+ // To convert the coordinates of fiducial marks in local RS as those are
+ // given above in global RS.
+ A4[i] = A4[i] - g_vect_4[i];
+ B4[i] = B4[i] - g_vect_4[i];
+ C4[i] = C4[i] - g_vect_4[i];
+ D4[i] = D4[i] - g_vect_4[i];
+
+ }
+
+ Double_t gA4[3], gB4[3], gC4[3], gD4[3];
+
+ g3_4->LocalToMaster(A4,gA4);
+ g3_4->LocalToMaster(B4,gB4);
+ g3_4->LocalToMaster(C4,gC4);
+ g3_4->LocalToMaster(D4,gD4);
+
+ /*
+ cout<<endl<<"Ideal fiducial marks coordinates in the global RS:4\n"<<
+ "A4 "<<gA4[0]<<" "<<gA4[1]<<" "<<gA4[2]<<" "<<endl<<
+ "B4 "<<gB4[0]<<" "<<gB4[1]<<" "<<gB4[2]<<" "<<endl<<
+ "C4 "<<gC4[0]<<" "<<gC4[1]<<" "<<gC4[2]<<" "<<endl<<
+ "D4 "<<gD4[0]<<" "<<gD4[1]<<" "<<gD4[2]<<" "<<endl;
+ */
+
+ // We apply a delta transformation to the surveyed vol. to represent
+ // its real position, given below by ng3 and nl3, which differs from its
+ // ideal position saved above in g3 and l3
+
+ TGeoPhysicalNode* pn3_4 = gGeoManager->MakePhysicalNode("ALIC_1/EPM4_1");
+
+ Double_t dphi_4 = 0.; // tilt around Z
+ Double_t dtheta_4 = 0.; // tilt around X
+ Double_t dpsi_4 = 0.; // tilt around new Z
+
+ Double_t dx_4 = 2.; // shift along X
+ Double_t dy_4 = 3.; // shift along Y
+ Double_t dz_4 = 4.; // shift along Z
+
+
+ TGeoRotation* rrot_4 = new TGeoRotation("rot",dphi_4,dtheta_4,dpsi_4);
+ TGeoCombiTrans localdelta_4 = *(new TGeoCombiTrans(dx_4,dy_4,dz_4, rrot_4));
+
+ // new local matrix, representing real position
+ TGeoHMatrix nlocal_4 = *l3_4 * localdelta_4;
+ TGeoHMatrix* nl3_4 = new TGeoHMatrix(nlocal_4);
+ pn3_4->Align(nl3_4);
+
+ // Let's get the global matrix for later comparison
+ TGeoHMatrix* ng3_4 = pn3_4->GetMatrix(); //"real" global matrix,what survey sees
+ printf("\n\n************ real global matrix for Sector-4 **************\n");
+ ng3_4->Print();
+
+ Double_t ngA4[3], ngB4[3], ngC4[3], ngD4[3];
+ ng3_4->LocalToMaster(A4,ngA4);
+ ng3_4->LocalToMaster(B4,ngB4);
+ ng3_4->LocalToMaster(C4,ngC4);
+ ng3_4->LocalToMaster(D4,ngD4);
+
+ cout<<endl<<"Fiducial marks coordinates in the global RS given by survey:4\n"<<
+ "A4 "<<ngA4[0]<<" "<<ngA4[1]<<" "<<ngA4[2]<<" "<<endl<<
+ "B4 "<<ngB4[0]<<" "<<ngB4[1]<<" "<<ngB4[2]<<" "<<endl<<
+ "C4 "<<ngC4[0]<<" "<<ngC4[1]<<" "<<ngC4[2]<<" "<<endl<<
+ "D4 "<<ngD4[0]<<" "<<ngD4[1]<<" "<<ngD4[2]<<" "<<endl;
+
+
+ Double_t ngP1[4][3], ngP2[4][3],ngP3[4][3], ngP4[4][3];
+
+ for(Int_t i=0;i<4;i++)
+ {
+ for (Int_t j=0; j<3; j++)
+ {
+ ngP1[0][j] = ngA1[j];
+ ngP1[1][j] = ngB1[j];
+ ngP1[2][j] = ngC1[j];
+ ngP1[3][j] = ngD1[j];
+
+ ngP2[0][j] = ngA2[j];
+ ngP2[1][j] = ngB2[j];
+ ngP2[2][j] = ngC2[j];
+ ngP2[3][j] = ngD2[j];
+
+ ngP3[0][j] = ngA3[j];
+ ngP3[1][j] = ngB3[j];
+ ngP3[2][j] = ngC3[j];
+ ngP3[3][j] = ngD3[j];
+
+ ngP4[0][j] = ngA4[j];
+ ngP4[1][j] = ngB4[j];
+ ngP4[2][j] = ngC4[j];
+ ngP4[3][j] = ngD4[j];
+
+ }
+ }
+
+ Float_t xx, yy, zz;
+ Char_t seqno[6], PType[1], TUsed[1];
+ Int_t precision;
+
+ ofstream ftw;
+ ftw.open("PMDGenSurveyPoints_v1.txt");
+
+ ifstream ftr;
+ ftr.open("Survey_Points_PMD01.txt",ios::in);
+
+ Int_t nline = 0;
+ const int Nrow=70;
+ TString CommentLine[Nrow];
+ TString tmp, tmp1;
+ char line[80];
+ Int_t surseq1[4] = {19, 20, 18, 17};
+ Int_t surseq2[4] = {15, 16, 14, 13};
+ Int_t surseq3[4] = {11, 12, 06, 05};
+ Int_t surseq4[4] = {27, 28, 22, 21};
+
+ while (nline<Nrow)
+ {
+ ftr.getline(line,80, '\n');
+ tmp = line;
+ tmp1 = tmp(0,60);
+ CommentLine[nline] = Strip(tmp1);
+
+ ftw<<CommentLine[nline]<<endl;
+
+ if (nline >= 40 && nline < 68)
+ {
+ ftr>>seqno>>xx>>yy>>zz>>PType>>TUsed>>precision;
+
+ // cout<<seqno<<"\t"<<xx<<"\t"<<yy<<"\t"<<zz<<"\t"<<PType<<"\t"<<TUsed<<
+ //"\t"<<precision<<endl;
+
+ Int_t i= (nline-40)+1;
+ for (Int_t j=0;j<4;j++)
+ {
+ if (surseq1[j] == i)
+ {
+ xx = ngP1[j][0]*10.0;
+ yy = ngP1[j][1]*10.0;
+ zz = ngP1[j][2]*10.0;
+ cout<<seqno<<"\t"<<xx<<"\t"<<yy<<"\t"<<zz<<"\t"<<PType<<
+ "\t"<<TUsed<< "\t"<<precision<<endl;
+ }
+ else if (surseq2[j] == i)
+ {
+ xx = ngP2[j][0]*10.0;
+ yy = ngP2[j][1]*10.0;
+ zz = ngP2[j][2]*10.0;
+ cout<<seqno<<"\t"<<xx<<"\t"<<yy<<"\t"<<zz<<"\t"<<PType<<
+ "\t"<<TUsed<< "\t"<<precision<<endl;
+ }
+ else if (surseq3[j] == i)
+ {
+ xx = ngP3[j][0]*10.0;
+ yy = ngP3[j][1]*10.0;
+ zz = ngP3[j][2]*10.0;
+ cout<<seqno<<"\t"<<xx<<"\t"<<yy<<"\t"<<zz<<"\t"<<PType<<
+ "\t"<<TUsed<< "\t"<<precision<<endl;
+ }
+ else if (surseq4[j] == i)
+ {
+ xx = ngP4[j][0]*10.0;
+ yy = ngP4[j][1]*10.0;
+ zz = ngP4[j][2]*10.0;
+ cout<<seqno<<"\t"<<xx<<"\t"<<yy<<"\t"<<zz<<"\t"<<PType<<
+ "\t"<<TUsed<< "\t"<<precision<<endl;
+ }
+ }
+ ftw<<seqno<<"\t"<<xx<<"\t"<<yy<<"\t"<<zz<<"\t"<<PType<<"\t"<<TUsed<<
+ "\t"<<precision<<endl;
+
+ }
+
+ //cout << "CommentLine [" << nline<< "]: " << CommentLine[nline] <<endl;
+ nline++;
+ }
+}
--- /dev/null
+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<<endl<<"Origin of sector-1 in the global RS: "<<
+ g_vect_1[0]<<" "<<g_vect_1[1]<<" "<<g_vect_1[2]<<" "<<endl;
+
+
+ TGeoHMatrix *g3_2 = AliGeomManager::GetMatrix("PMD/Sector2");
+ TGeoNode* n3_2 = gGeoManager->GetCurrentNode();
+ TGeoHMatrix* l3_2 = n3_2->GetMatrix();
+ g3_2->LocalToMaster(l_vect,g_vect_2);
+
+ cout<<endl<<"Origin of sector-2 in the global RS: "<<
+ g_vect_2[0]<<" "<<g_vect_2[1]<<" "<<g_vect_2[2]<<" "<<endl;
+
+
+ TGeoHMatrix *g3_3 = AliGeomManager::GetMatrix("PMD/Sector3");
+ TGeoNode* n3_3 = gGeoManager->GetCurrentNode();
+ TGeoHMatrix* l3_3 = n3_3->GetMatrix();
+ g3_3->LocalToMaster(l_vect,g_vect_3);
+
+ cout<<endl<<"Origin of the sector-3 in the global RS: "<<
+ g_vect_3[0]<<" "<<g_vect_3[1]<<" "<<g_vect_3[2]<<" "<<endl;
+
+
+ TGeoHMatrix *g3_4 = AliGeomManager::GetMatrix("PMD/Sector4");
+ TGeoNode* n3_4 = gGeoManager->GetCurrentNode();
+ TGeoHMatrix* l3_4 = n3_4->GetMatrix();
+ g3_4->LocalToMaster(l_vect,g_vect_4);
+
+ cout<<endl<<"Origin of the sector-4 in the global RS: "<<
+ g_vect_4[0]<<" "<<g_vect_4[1]<<" "<<g_vect_4[2]<<" "<<endl;
+
+
+ // From the coordinates of fiducial marks derive back the
+ // new global position of the surveyed volume.
+ // What follows is the actual survey-to-alignment procedure which assumes,
+ // 4 fiducial marks at the corners of a rectangle lying on a plane parallel
+ // to a surface of the detector at a certain offset and with x and y sides
+ // parallel to the detector's x and y axes.
+ // It needs as input of four points and the offset from the origin (zdepth).
+ // The algorithm can be easily modified for different placement and/or
+ // cardinality of the fiducial marks.
+
+ // Now specify the path of the module to be misaligned
+ // as followed for the PMD geometry in Geant.
+
+ /*
+ Y|
+ |
+ _____________ D(3)|_____________C(2)
+ | | | | |
+ | 1 | 3 | | |
+ | |________| | |
+ |____|___| | | |
+ | | 2 | | |
+ | 4 | | |_____________|_______
+ |________|____| A(0) B(1) X
+
+ //
+ // Misalignment Matrix is set for sector-1, sector-2, sector-3 and
+ // sector-4 even though sectors 1 and 4 and sectors 2 and 3
+ // will be mounted on the same steel plate.
+ */
+
+// All the units are in milimeter in survey data file.
+
+// Retrieval of real survey data from ALICE Survey Data Depot :
+
+ AliSurveyObj *so = new AliSurveyObj();
+ //so->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 : "<<plane1[0]
+ <<" "<<plane1[1]<<" "<<plane1[2]<<endl;
+ cout<<"Unit vector normal to sector-2 : "<<plane2[0]
+ <<" "<<plane2[1]<<" "<<plane2[2]<<endl;
+ cout<<"Unit vector normal to sector-3 : "<<plane3[0]
+ <<" "<<plane3[1]<<" "<<plane3[2]<<endl;
+ cout<<"Unit vector normal to sector-4 : "<<plane4[0]
+ <<" "<<plane4[1]<<" "<<plane4[2]<<endl;
+
+ // The center of the sector with fiducial marks as corners,
+ // is the middle point of one diagonal.
+
+ Double_t orig1[kNDIM1], md1[kNDIM1];
+ Double_t orig2[kNDIM1], md2[kNDIM1];
+ Double_t orig3[kNDIM1], md3[kNDIM1];
+ Double_t orig4[kNDIM1], md4[kNDIM1];
+
+ for(i = 0; i < kNDIM1; i++)
+ {
+ md1[i] = (nga1[0][i] + nga1[1][i]) * 0.5;
+ md2[i] = (nga2[2][i] + nga2[3][i]) * 0.5;
+ md3[i] = (nga3[0][i] + nga3[2][i]) * 0.5;
+ md4[i] = (nga4[0][i] + nga4[2][i]) * 0.5;
+ }
+
+ const Double_t kZdepth = 23.;//(Zdepth+zoffset) is the distance
+ //from surface to centre of the PMD.
+
+ for(i = 0; i < kNDIM1; i++)
+ {
+ orig1[i] = md1[i] - plane1[i]*kZdepth;
+ orig2[i] = md2[i] - plane2[i]*kZdepth;
+ orig3[i] = md3[i] - plane3[i]*kZdepth;
+ orig4[i] = md4[i] - plane4[i]*kZdepth;
+ }
+
+ Double_t PMDorig1[kNDIM1];
+ Double_t PMDorig2[kNDIM1];
+ for(i = 0; i < kNDIM1; i++)
+ {
+ PMDorig1[i] = (orig1[i] + orig2[i]) * 0.5;
+ PMDorig2[i] = (orig3[i] + orig4[i]) * 0.5;
+ }
+
+ // Get x,y local directions needed to write the global rotation matrix
+ // for the surveyed volume by normalising vectors ab1 and bc1
+
+ Double_t sx1 = TMath::Sqrt(ab1[0]*ab1[0] + ab1[1]*ab1[1] +
+ ab1[2]*ab1[2]);
+ if(sx1 > 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();
+}
--- /dev/null
+> Title:
+
+Alignment of the PMD.
+
+> Date:
+
+11.01.2008
+
+> Subdetector:
+
+PMD
+
+> Report URL:
+
+https://edms.cern.ch/document/000000
+
+> Version:
+
+1
+
+> General Observations:
+
+ This will be documented later by surveyer.
+
+> Coordinate System:
+
+ALICEPH
+
+> Units:
+
+mm
+
+> Nr Columns:
+
+7
+
+> Column Names:
+
+Point Name,XPH,YPH,ZPH,Point Type,Target Used,Precision(mm)
+
+> Data:
+PMD_01 -544.50 906.5 3638.0 M Y 1
+PMD_02 17.50 906.5 3638.0 M Y 1
+PMD_03 186.50 906.5 3638.0 M Y 1
+PMD_04 544.50 906.5 3638.0 M Y 1
+PMD_05 -742.75 870.5 3638.0 M Y 1
+PMD_06 77.25 870.5 3638.0 M Y 1
+PMD_07 -742.75 617.5 3638.0 M Y 1
+PMD_08 77.25 617.5 3638.0 M Y 1
+PMD_09 -742.75 364.5 3638.0 M Y 1
+PMD_10 77.25 364.5 3638.0 M Y 1
+PMD_11 -742.75 111.5 3638.0 M Y 1
+PMD_12 77.25 111.5 3638.0 M Y 1
+PMD_13 -742.75 -378.5 3638.0 M Y 1
+PMD_14 -120.25 -378.5 3638.0 M Y 1
+PMD_15 -742.75 -870.5 3638.0 M Y 1
+PMD_16 -120.25 -870.5 3638.0 M Y 1
+PMD_17 120.25 870.5 3638.0 M Y 1
+PMD_18 742.75 870.5 3638.0 M Y 1
+PMD_19 120.25 378.5 3638.0 M Y 1
+PMD_20 742.75 378.5 3638.0 M Y 1
+PMD_21 -77.25 -111.5 3638.0 M Y 1
+PMD_22 742.75 -111.5 3638.0 M Y 1
+PMD_23 -77.25 -364.5 3638.0 M Y 1
+PMD_24 742.75 -364.5 3638.0 M Y 1
+PMD_25 -77.25 -617.5 3638.0 M Y 1
+PMD_26 742.75 -617.5 3638.0 M Y 1
+PMD_27 -77.25 -870.5 3638.0 M Y 1
+PMD_28 742.75 -870.5 3638.0 M Y 1