void EUTelGeometryTelescopeGeoDescription::translateSiPlane2TGeo(TGeoVolume* pvolumeWorld, int SensorId ) { double xc, yc, zc; // volume center position double alpha, beta, gamma; double rotRef1, rotRef2, rotRef3, rotRef4; std::stringstream strId; strId << SensorId; // Get sensor center position xc = siPlaneXPosition( SensorId ); yc = siPlaneYPosition( SensorId ); zc = siPlaneZPosition( SensorId ); // Get sensor orientation alpha = siPlaneXRotation( SensorId ); // in degrees ! beta = siPlaneYRotation( SensorId ); // gamma = siPlaneZRotation( SensorId ); // rotRef1 = siPlaneRotation1( SensorId ); rotRef2 = siPlaneRotation2( SensorId ); rotRef3 = siPlaneRotation3( SensorId ); rotRef4 = siPlaneRotation4( SensorId ); //We must check that the input is correct. Since this is a combination of initial rotations and reflections the determinate must be 1 or -1 float determinant = rotRef1*rotRef4 - rotRef2*rotRef3 ; if(determinant==1 or determinant==-1) { streamlog_out(DEBUG5) << "SensorID: " << SensorId << ". Determinant = " <<determinant <<" This is the correct determinate for this transformation." << std::endl; } else { streamlog_out(ERROR5) << "SensorID: " << SensorId << ". Determinant = " <<determinant << std::endl; throw(lcio::Exception("The initial rotation and reflection matrix does not have determinant of 1 or -1. Gear file input must be wrong.")); } //Create spatial TGeoTranslation object. std::string stTranslationName = "matrixTranslationSensor"; stTranslationName.append( strId.str() ); TGeoTranslation* pMatrixTrans = new TGeoTranslation( stTranslationName.c_str(), xc, yc, zc ); //ALL clsses deriving from TGeoMatrix are not owned by the ROOT geometry manager, invoking RegisterYourself() transfers //ownership and thus ROOT will clean up pMatrixTrans->RegisterYourself(); //Create TGeoRotation object. //Translations are of course just positional changes in the global frame. //Note that each subsequent rotation is using the new coordinate system of the last transformation all the way back to the global frame. //The way to think about this is that each rotation is the multiplication of the last rotation matrix by a new one. //The order is: //Integer Z rotation and reflections. //Z rotations specified by in degrees. //X rotations //Y rotations TGeoRotation* pMatrixRotRefCombined = new TGeoRotation(); //We have to ensure that we retain a right handed coordinate system, i.e. if we only flip the x or y axis, we have to also flip the z-axis. If we flip both we have to flip twice. double integerRotationsAndReflections[9]={rotRef1,rotRef2,0,rotRef3,rotRef4,0,0,0, determinant}; pMatrixRotRefCombined->SetMatrix(integerRotationsAndReflections); std::cout << "Rotating plane " << SensorId << " to gamma: " << gamma << std::endl; pMatrixRotRefCombined->RotateZ(gamma);//Z Rotation (degrees)//This will again rotate a vector around z axis usign the right hand rule. pMatrixRotRefCombined->RotateX(alpha);//X Rotations (degrees)//This will rotate a vector usign the right hand rule round the x-axis pMatrixRotRefCombined->RotateY(beta);//Y Rotations (degrees)//Same again for Y axis pMatrixRotRefCombined->RegisterYourself();//We must allow the matrix to be used by the TGeo manager. // Combined translation and orientation TGeoCombiTrans* combi = new TGeoCombiTrans( *pMatrixTrans, *pMatrixRotRefCombined ); //This is to print to screen the rotation and translation matrices used to transform from local to global frame. streamlog_out(MESSAGE9) << "THESE MATRICES ARE USED TO TAKE A POINT IN THE LOCAL FRAME AND MOVE IT TO THE GLOBAL FRAME." << std::endl; streamlog_out(MESSAGE9) << "SensorID: " << SensorId << " Rotation/Reflection matrix for this object." << std::endl; const double* rotationMatrix = combi->GetRotationMatrix(); streamlog_out(MESSAGE9) << std::setw(10) <<rotationMatrix[0]<<" "<<rotationMatrix[1]<<" "<<rotationMatrix[2]<< std::endl; streamlog_out(MESSAGE9) << std::setw(10) <<rotationMatrix[3]<<" "<<rotationMatrix[4]<<" "<<rotationMatrix[5]<< std::endl; streamlog_out(MESSAGE9) << std::setw(10) <<rotationMatrix[6]<<" "<<rotationMatrix[7]<<" "<<rotationMatrix[8]<< std::endl; //streamlog_out(MESSAGE9) << std::setw(10) <<rotationMatrix[0] << std::setw(10) <<rotationMatrix[1]<< std::setw(10) <<rotationMatrix[2]<< std::setw(10)<< std::endl<< std::endl; //streamlog_out(MESSAGE9) << std::setw(10) <<rotationMatrix[3] << std::setw(10) <<rotationMatrix[4]<< std::setw(10) <<rotationMatrix[5]<< std::setw(10)<< std::endl<< std::endl; //streamlog_out(MESSAGE9) << std::setw(10) <<rotationMatrix[6] << std::setw(10) <<rotationMatrix[7]<< std::setw(10) <<rotationMatrix[8]<< std::setw(10)<< std::endl<< std::endl; const double* translationMatrix = combi->GetTranslation(); streamlog_out(MESSAGE9) << "SensorID: " << SensorId << " Translation vector for this object." << std::endl; streamlog_out(MESSAGE9) << std::setw(10) <<translationMatrix[0] << std::setw(10) <<translationMatrix[1]<< std::setw(10) <<translationMatrix[2]<< std::setw(10)<< std::endl; combi->RegisterYourself(); // Construct object medium. Required for radiation length determination // assume SILICON, though all information except of radiation length is ignored double a = 28.085500; double z = 14.000000; double density = 2.330000; double radl = siPlaneRadLength( SensorId ); double absl = 45.753206; std::string stMatName = "materialSensor"; stMatName.append( strId.str() ); TGeoMaterial* pMat = new TGeoMaterial( stMatName.c_str(), a, z, density, -radl, absl ); pMat->SetIndex( 1 ); // Medium: medium_Sensor_SILICON int numed = 0; // medium number double par[8]; par[0] = 0.000000; // isvol par[1] = 0.000000; // ifield par[2] = 0.000000; // fieldm par[3] = 0.000000; // tmaxfd par[4] = 0.000000; // stemax par[5] = 0.000000; // deemax par[6] = 0.000000; // epsil par[7] = 0.000000; // stmin std::string stMedName = "mediumSensor"; stMedName.append( strId.str() ); TGeoMedium* pMed = new TGeoMedium( stMedName.c_str(), numed, pMat, par ); // Construct object shape // Shape: Box type: TGeoBBox // TGeo requires half-width of box side Double_t dx = siPlaneXSize( SensorId ) / 2.; Double_t dy = siPlaneYSize( SensorId ) / 2.; Double_t dz = siPlaneZSize( SensorId ) / 2.; TGeoShape *pBoxSensor = new TGeoBBox( "BoxSensor", dx, dy, dz ); std::cout << "Box for sensor: " << SensorId << " is: " << dx << "|" << dy << "|" << dz << '\n'; // Geometry navigation package requires following names for objects that have an ID name:ID std::string stVolName = "volume_SensorID:"; stVolName.append( strId.str() ); _planePath.insert( std::make_pair(SensorId, "/volume_World_1/"+stVolName+"_1") ); TGeoVolume* pvolumeSensor = new TGeoVolume( stVolName.c_str(), pBoxSensor, pMed ); pvolumeSensor->SetVisLeaves( kTRUE ); pvolumeWorld->AddNode(pvolumeSensor, 1/*(SensorId)*/, combi); //this line tells the pixel geometry manager to load the pixel geometry into the plane streamlog_out(DEBUG1) << " sensorID: " << SensorId << " " << stVolName << std::endl; std::string name = geoLibName(SensorId); if( name == "CAST" ) { _pixGeoMgr->addCastedPlane( SensorId, siPlaneXNpixels(SensorId), siPlaneYNpixels(SensorId), siPlaneXSize(SensorId), siPlaneYSize(SensorId), siPlaneZSize(SensorId), siPlaneRadLength(SensorId), stVolName); } else { _pixGeoMgr->addPlane( SensorId, name, stVolName); updatePlaneInfo(SensorId); } }
TGeoCombiTrans* GetGlobalPosition(TGeoCombiTrans *fRef) { if (fLocalTrans == kTRUE ) { if ( ( fThetaX == 0 ) && ( fThetaY==0 ) && ( fThetaZ == 0 ) && ( fX == 0 ) && ( fY == 0 ) && ( fZ == 0 ) ) return fRef; // X axis Double_t xAxis[3] = { 1. , 0. , 0. }; Double_t yAxis[3] = { 0. , 1. , 0. }; Double_t zAxis[3] = { 0. , 0. , 1. }; // Reference Rotation fRefRot = fRef->GetRotation(); if (fRefRot) { Double_t mX[3] = {0.,0.,0.}; Double_t mY[3] = {0.,0.,0.}; Double_t mZ[3] = {0.,0.,0.}; fRefRot->LocalToMasterVect(xAxis,mX); fRefRot->LocalToMasterVect(yAxis,mY); fRefRot->LocalToMasterVect(zAxis,mZ); Double_t a[4]={ mX[0],mX[1],mX[2], fThetaX }; Double_t b[4]={ mY[0],mY[1],mY[2], fThetaY }; Double_t c[4]={ mZ[0],mZ[1],mZ[2], fThetaZ }; ROOT::Math::AxisAngle aX(a,a+4); ROOT::Math::AxisAngle aY(b,b+4); ROOT::Math::AxisAngle aZ(c,c+4); ROOT::Math::Rotation3D fMatX( aX ); ROOT::Math::Rotation3D fMatY( aY ); ROOT::Math::Rotation3D fMatZ( aZ ); ROOT::Math::Rotation3D fRotXYZ = (fMatZ * (fMatY * fMatX)); //cout << fRotXYZ << endl; Double_t fRotable[9]={0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}; fRotXYZ.GetComponents( fRotable[0],fRotable[3],fRotable[6], fRotable[1],fRotable[4],fRotable[7], fRotable[2],fRotable[5],fRotable[8] ); TGeoRotation *pRot = new TGeoRotation(); pRot->SetMatrix(fRotable); TGeoCombiTrans *pTmp = new TGeoCombiTrans(*fGlobalTrans,*pRot); // ne peut pas etre applique ici // il faut differencier trans et rot dans la multi. TGeoRotation rot_id; rot_id.SetAngles(0.0,0.0,0.0); TGeoCombiTrans c1; c1.SetRotation(rot_id); const Double_t *t = pTmp->GetTranslation(); c1.SetTranslation(t[0],t[1],t[2]); TGeoCombiTrans c2; c2.SetRotation(rot_id); const Double_t *tt = fRefRot->GetTranslation(); c2.SetTranslation(tt[0],tt[1],tt[2]); TGeoCombiTrans cc = c1 * c2 ; TGeoCombiTrans c3; c3.SetRotation(pTmp->GetRotation()); TGeoCombiTrans c4; c4.SetRotation(fRefRot); TGeoCombiTrans ccc = c3 * c4; TGeoCombiTrans pGlobal; pGlobal.SetRotation(ccc.GetRotation()); const Double_t *allt = cc.GetTranslation(); pGlobal.SetTranslation(allt[0],allt[1],allt[2]); return ( new TGeoCombiTrans( pGlobal ) ); }else{ cout << "-E- R3BDetector::GetGlobalPosition() \ No. Ref. Transformation defined ! " << endl; cout << "-E- R3BDetector::GetGlobalPosition() \ cannot create Local Transformation " << endl; return NULL; } //! fRefRot } else { // Lab Transf. if ( ( fPhi == 0 ) && ( fTheta==0 ) && ( fPsi == 0 )
/** * Initialise ROOT geometry objects from GEAR objects * * @param geomName name of ROOT geometry object * @param dumpRoot dump automatically generated ROOT geometry file for further inspection */ void EUTelGeometryTelescopeGeoDescription::initializeTGeoDescription( std::string& geomName, bool dumpRoot = false ) { // #ifdef USE_TGEO // get access to ROOT's geometry manager if( _isGeoInitialized ) { streamlog_out( WARNING3 ) << "EUTelGeometryTelescopeGeoDescription: Geometry already initialized, using old initialization" << std::endl; return; } else { _geoManager = new TGeoManager("Telescope", "v0.1"); } if( !_geoManager ) { streamlog_out( ERROR3 ) << "Can't instantiate ROOT TGeoManager " << std::endl; return; } // Create top world volume containing telescope/DUT geometry // Create air mixture // see http://pdg.lbl.gov/2013/AtomicNuclearProperties/HTML_PAGES/104.html double air_density = 1.2e-3; // g/cm^3 double air_radlen = 36.62; // g/cm^2 TGeoMixture* pMatAir = new TGeoMixture("AIR",3,air_density); pMatAir->DefineElement(0, 14.007, 7., 0.755267 ); //Nitrogen pMatAir->DefineElement(1, 15.999, 8., 0.231781 ); //Oxygen pMatAir->DefineElement(2, 39.948, 18., 0.012827 ); //Argon pMatAir->DefineElement(3, 12.011, 6., 0.000124 ); //Carbon pMatAir->SetRadLen( air_radlen ); // Medium: medium_World_AIR TGeoMedium* pMedAir = new TGeoMedium("medium_World_AIR", 3, pMatAir ); // The World is the 10 x 10m x 10m box filled with air mixture Double_t dx,dy,dz; dx = 5000.000000; // [mm] dy = 5000.000000; // [mm] dz = 5000.000000; // [mm] TGeoShape *pBoxWorld = new TGeoBBox("Box_World", dx,dy,dz); // Volume: volume_World TGeoVolume* pvolumeWorld = new TGeoVolume("volume_World",pBoxWorld, pMedAir); pvolumeWorld->SetLineColor(4); pvolumeWorld->SetLineWidth(3); pvolumeWorld->SetVisLeaves(kTRUE); // Set top volume of geometry gGeoManager->SetTopVolume( pvolumeWorld ); // Iterate over registered GEAR objects and construct their TGeo representation const Double_t PI = 3.141592653589793; const Double_t DEG = 180./PI; double xc, yc, zc; // volume center position double alpha, beta, gamma; IntVec::const_iterator itrPlaneId; for ( itrPlaneId = _sensorIDVec.begin(); itrPlaneId != _sensorIDVec.end(); ++itrPlaneId ) { std::stringstream strId; strId << *itrPlaneId; // Get sensor center position xc = siPlaneXPosition( *itrPlaneId ); yc = siPlaneYPosition( *itrPlaneId ); zc = siPlaneZPosition( *itrPlaneId ); // Get sensor orientation alpha = siPlaneXRotation( *itrPlaneId ); // [rad] beta = siPlaneYRotation( *itrPlaneId ); // [rad] gamma = siPlaneZRotation( *itrPlaneId ); // [rad] // Spatial translations of the sensor center string stTranslationName = "matrixTranslationSensor"; stTranslationName.append( strId.str() ); TGeoTranslation* pMatrixTrans = new TGeoTranslation( stTranslationName.c_str(), xc, yc, zc ); //ALL clsses deriving from TGeoMatrix are not owned by the ROOT geometry manager, invoking RegisterYourself() transfers //ownership and thus ROOT will clean up pMatrixTrans->RegisterYourself(); // Spatial rotation around sensor center // TGeoRotation requires Euler angles in degrees string stRotationName = "matrixRotationSensorX"; stRotationName.append( strId.str() ); TGeoRotation* pMatrixRotX = new TGeoRotation( stRotationName.c_str(), 0., alpha*DEG, 0.); // around X axis stRotationName = "matrixRotationSensorY"; stRotationName.append( strId.str() ); TGeoRotation* pMatrixRotY = new TGeoRotation( stRotationName.c_str(), 90., beta*DEG, 0.); // around Y axis (combination of rotation around Z axis and new X axis) stRotationName = "matrixRotationSensorBackY"; stRotationName.append( strId.str() ); TGeoRotation* pMatrixRotY1 = new TGeoRotation( stRotationName.c_str(), -90., 0., 0.); // restoration of original orientation (valid in small angle approximataion ~< 15 deg) stRotationName = "matrixRotationSensorZ"; stRotationName.append( strId.str() ); TGeoRotation* pMatrixRotZ = new TGeoRotation( stRotationName.c_str(), 0. , 0., gamma*DEG); // around Z axis // Combined rotation in several steps TGeoRotation* pMatrixRot = new TGeoRotation( *pMatrixRotX ); pMatrixRot->MultiplyBy( pMatrixRotY ); pMatrixRot->MultiplyBy( pMatrixRotY1 ); pMatrixRot->MultiplyBy( pMatrixRotZ ); pMatrixRot->RegisterYourself(); pMatrixRotX->RegisterYourself(); pMatrixRotY->RegisterYourself(); pMatrixRotY1->RegisterYourself(); pMatrixRotZ->RegisterYourself(); // Combined translation and orientation TGeoCombiTrans* combi = new TGeoCombiTrans( *pMatrixTrans, *pMatrixRot ); combi->RegisterYourself(); // Construction of sensor objects // Construct object medium. Required for radiation length determination // assume SILICON, though all information except of radiation length is ignored double a = 28.085500; double z = 14.000000; double density = 2.330000; double radl = siPlaneMediumRadLen( *itrPlaneId ); double absl = 45.753206; string stMatName = "materialSensor"; stMatName.append( strId.str() ); TGeoMaterial* pMat = new TGeoMaterial( stMatName.c_str(), a, z, density, radl, absl ); pMat->SetIndex( 1 ); // Medium: medium_Sensor_SILICON int numed = 0; // medium number double par[8]; par[0] = 0.000000; // isvol par[1] = 0.000000; // ifield par[2] = 0.000000; // fieldm par[3] = 0.000000; // tmaxfd par[4] = 0.000000; // stemax par[5] = 0.000000; // deemax par[6] = 0.000000; // epsil par[7] = 0.000000; // stmin string stMedName = "mediumSensor"; stMedName.append( strId.str() ); TGeoMedium* pMed = new TGeoMedium( stMedName.c_str(), numed, pMat, par ); // Construct object shape // Shape: Box type: TGeoBBox // TGeo requires half-width of box side dx = siPlaneXSize( *itrPlaneId ) / 2.; dy = siPlaneYSize( *itrPlaneId ) / 2.; dz = siPlaneZSize( *itrPlaneId ) / 2.; TGeoShape *pBoxSensor = new TGeoBBox( "BoxSensor", dx, dy, dz ); // Volume: volume_Sensor1 // Geometry navigation package requires following names for objects that have an ID // name:ID string stVolName = "volume_SensorID:"; stVolName.append( strId.str() ); _planePath.insert( std::make_pair(*itrPlaneId, "/volume_World_1/"+stVolName+"_1") ); TGeoVolume* pvolumeSensor = new TGeoVolume( stVolName.c_str(), pBoxSensor, pMed ); pvolumeSensor->SetVisLeaves( kTRUE ); pvolumeWorld->AddNode(pvolumeSensor, 1/*(*itrPlaneId)*/, combi); //this line tells the pixel geometry manager to load the pixel geometry into the plane _pixGeoMgr->addPlane( *itrPlaneId, geoLibName( *itrPlaneId), stVolName); } // loop over sensorID _geoManager->CloseGeometry(); _isGeoInitialized = true; // Dump ROOT TGeo object into file if ( dumpRoot ) _geoManager->Export( geomName.c_str() ); // #endif //USE_TGEO return; }