示例#1
0
/* Create Ntuples with material properties along straight lines from the model
 * and from the surfaces.
 */
int main(int argc, char** argv) {
  
  if(argc < 2) {

    std::cout << " usage: ./material_ntuples ILDEx.xml " << std::endl ;
    return 1;
  }
  
  std::string inFile = argv[1] ;

  std::vector<int> thetasDeg ; // ={ 85 , 20 }  --- C++11
  thetasDeg.push_back( 90 ) ;
  thetasDeg.push_back( 85 ) ;
  thetasDeg.push_back( 60 ) ;
  thetasDeg.push_back( 45 ) ;
  thetasDeg.push_back( 30 ) ;
  thetasDeg.push_back( 20 ) ;
  thetasDeg.push_back( 15 ) ;
  thetasDeg.push_back( 10 ) ;
  thetasDeg.push_back( 7 ) ;

  std::vector<int> phisDeg ; //= { 42  } ;
  phisDeg.push_back(  0 ) ;
  phisDeg.push_back(  7 ) ;
  phisDeg.push_back( 12 ) ;
  phisDeg.push_back( 17 ) ;
  phisDeg.push_back( 25 ) ;
  phisDeg.push_back( 30 ) ;
  phisDeg.push_back( 42 ) ;
  phisDeg.push_back( 60 ) ;
  phisDeg.push_back( 71 ) ;
  phisDeg.push_back( 85 ) ;

  //----------------
  std::string varNames =  "theta:phi:epx:epy:epz:x0:lambda:eloss" ;

  TFile *ofile = new TFile( "material_ntuples.root", "RECREATE");
  TNtuple* surfTuple = new TNtuple( "surfTuple" , "material properties from surfaces", varNames.c_str() ) ;
  TNtuple* matTuple  = new TNtuple( "matTuple" , "material properties from detailed model", varNames.c_str() ) ;

  //----------------


  for( unsigned i=0,N= thetasDeg.size() ; i<N ; ++i ){
    for( unsigned j=0,M= phisDeg.size()   ; j<M ; ++j ){
      
      
      double theta = thetasDeg[i] / 180. * M_PI  ;
      double phi = phisDeg[j] / 180. * M_PI ;
      
      
      aidaTT::Vector3D dirVec( 1. , phi , theta,  aidaTT::Vector3D::spherical ) ;
      
      // create an (almost) straight track in that direction
      double omega = 1.e-9 ;
      double tanl  = tan( 0.5*M_PI - theta ) ;
      double phi0  = phi ;
      double d0    = 0. ;
      double z0    = 0. ;
      
      
      aidaTT::Vector3D p0(0.,0.,0.) ; // start point
      aidaTT::Vector3D p1  ; // end point
   
      aidaTT::trackParameters tP( aidaTT::Vector5(omega, tanl, phi0 , d0 , z0 ), p0 )  ;
      
      
      std::cout << " --- theta, phi :       " <<  thetasDeg[i] <<" , " <<  phisDeg[j]  << std::endl ;
      
      const aidaTT::IGeometry& geom = aidaTT::IGeometry::instance( inFile ) ;
      
      const aidaTT::SurfaceVec& surfaces = geom.getSurfaces() ;
      
      // create a trajectory w/o fitter or propagation
      aidaTT::trajectory traj( tP, 0, 0, &geom ) ;
      
      
      aidaTT::IntersectionVec intersections = traj.getIntersectionsWithSurfaces( surfaces ) ;
      
      double X0_tot = 0. ;
      
      // ============================ loop over surface intersections ====================
      for(unsigned ii=0,NN=intersections.size() ; ii<NN ; ++ii){
	
	
	const aidaTT::ISurface* surf = intersections[ii].second ;
	
	double s =  0;
	aidaTT::Vector3D xx ;
	bool intersects = aidaTT::intersectWithSurface(  surf , 
							 tP.parameters() , tP.referencePoint() ,
							 s, xx, 0 , true ) ; 
	
	//----------------- get X0 --------------------------------------------
	const dd4hep::rec::IMaterial& material_inn = surf->innerMaterial();
	const dd4hep::rec::IMaterial& material_out = surf->outerMaterial();
	
	const double r_i = surf->innerThickness();
	const double r_o = surf->outerThickness();
	
	const double X0_o = material_out.radiationLength();
	const double X0_i = material_inn.radiationLength();
	
	double r_tot = r_i + r_o ;
	
	//calculation of effective radiation length of the surface
	double X0_eff = ( r_i/X0_i + r_o/X0_o ) / r_tot ; 
	
	//calculation of the path of the particle inside the material
	//compute path as projection of (straight) track to surface normal:
	
	const aidaTT::Vector3D& up = dirVec.unit() ;
	
        // need to get the normal at crossing point 
	const aidaTT::Vector3D& n = surf->normal( xx ) ;
	
	double cosTrk = std::fabs( up * n )  ;
	
	double path = r_i + r_o ;
	
	path = path/cosTrk ; 
	
	double X_X0 = path * X0_eff ;
	
	//--------------------------------------------------------------------
	
	X0_tot += X_X0 ;
	
	//"theta:phi:epx:epy:epz:x0:lambda:eloss"
	surfTuple->Fill( float(thetasDeg[i]) , float(phisDeg[j]) , xx.x() , xx.y() , xx.z() , X0_tot , 0., 0.  ) ; 

	p1 = xx ; // save last crossing point
      }


      aidaTT::Vector3D end ;
      aidaTT::Vector3D direction = ( p1 -p0 ).unit() ;


      dd4hep::Detector& thedetector = dd4hep::Detector::getInstance();
      const dd4hep::DetElement& world = thedetector.world() ;
      MaterialManager matMgr( world.volume() ) ;

      const MaterialVec& materials = matMgr.materialsBetween(  p0, p1 );
      double sum_x0 = 0;
      double sum_lambda = 0;
      double path_length = 0;


      for( unsigned k=0,K=materials.size();k<K;++k){
	TGeoMaterial* mat =  materials[k].first->GetMaterial();
	double length = materials[k].second;
	double nx0 = length / mat->GetRadLen();
	sum_x0 += nx0;
	double nLambda = length / mat->GetIntLen();
	sum_lambda += nLambda;
	path_length += length;
	end = path_length * direction;

	// ::printf(fmt, i+1, mat->GetName(), mat->GetZ(), mat->GetA(),
	// 	 mat->GetDensity(), mat->GetRadLen(), mat->GetIntLen(), 
	// 	 length, path_length, sum_x0, sum_lambda, end[0], end[1], end[2]);
	// //mat->Print();

	//"theta:phi:epx:epy:epz:x0:lambda:eloss"
	matTuple->Fill( float(thetasDeg[i]) , float(phisDeg[j]) , end.x() , end.y() , end.z() , sum_x0 , sum_lambda, 0.  ) ; 
      }




    } // phi
  } //theta

  ofile->Write("surfTuple");

  return 0;
}
示例#2
0
void MUONChamberMaterialBudget(const char* geoFilename = "geometry.root", Int_t segmentationLevel = 1)
{
  /// Draw the local chamber thickness over x0 (x/x0) used in the computation of Multiple Coulomb Scattering effets.
  /// Compute <x> and <x/x0> in a limited area (displayed on the histograms) to avoid edge effets.
  /// The resolution can be changed by changing the sementation level: resolution = 1 cm / segmentationLevel.
  
  const char* chamberName[10] = {"SC01", "SC02", "SC03", "SC04", "SC05", "SC06", "SC07", "SC08", "SC09", "SC10"};
  Double_t OneOverX0MeanCh[10] = {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
  Double_t totalLengthCh[10] = {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
  Double_t OneOverX0Mean = 0.;
  Double_t totalLength = 0.;
  
  // Import TGeo geometry
  if (!gGeoManager) {
    TGeoManager::Import(geoFilename);
    if (!gGeoManager) {
      cout<<"getting geometry from file geometry.root failed"<<endl;
      return;
    }
  }
  
  // z intervals where to find the stations
  Double_t zIn[5] =  {-510., -600.,  -800., -1150., -1350.};
  Double_t zOut[5] = {-600., -800., -1150., -1350., -1470.};
  
  // transverse area where to compute locally x and x/x0
  Double_t xIn0[5] = {0., 0., 0., 0., 0.};
  Double_t yIn0[5] = {0., 0., 0., 0., 0.};
  Int_t ixMax[5] = {90, 120, 165, 250, 260};
  Int_t iyMax[5] = {90, 120, 180, 250, 270};
  
  // transverse area where to compute <x> and <x/x0> for each chamber
  Double_t xIn0ForMean[5] = { 5.,  5.,  35.,  40.,  40.};
  Double_t yIn0ForMean[5] = {20., 25.,   0.,   0.,   0.};
  Int_t ixMaxForMean[5] = {  50,  65,   85,  120,  160 };
  Int_t iyMaxForMean[5] = {  60,  70,  110,  150,  150 };
  
  // define output histograms
  gStyle->SetPalette(1);
  TFile *f = TFile::Open("MaterialBudget.root","RECREATE");
  TH2F* hXOverX0[10];
  TBox* bXOverX0[10];
  for (Int_t i=0; i<10; i++) {
    Int_t st = i/2;
    hXOverX0[i] = new TH2F(Form("hXOverX0_%d",i+1), Form("x/x0 on ch %d (%%)",i+1),
			   segmentationLevel*ixMax[st], xIn0[st], xIn0[st]+ixMax[st],
			   segmentationLevel*iyMax[st], yIn0[st], yIn0[st]+iyMax[st]);
    hXOverX0[i]->SetOption("COLZ");
    hXOverX0[i]->SetStats(kFALSE);
    bXOverX0[i] = new TBox(xIn0ForMean[st], yIn0ForMean[st],
			   xIn0ForMean[st]+ixMaxForMean[st], yIn0ForMean[st]+iyMaxForMean[st]);
    bXOverX0[i]->SetLineStyle(2);
    bXOverX0[i]->SetLineWidth(2);
    bXOverX0[i]->SetFillStyle(0);
    hXOverX0[i]->GetListOfFunctions()->Add(bXOverX0[i]);
  }
  
  // loop over stations
  for (Int_t ist=0; ist<5; ist++) {
    
    Int_t nPoints = 0;
    
    // loop over position in non bending direction (by step of 1cm)
    for (Int_t ix=0; ix<segmentationLevel*ixMax[ist]; ix++) {
      
      Double_t xIn = xIn0[ist] + ((Double_t)ix+0.5) / ((Double_t)segmentationLevel);
      
      // loop over position in bending direction (by step of 1cm)
      for (Int_t iy=0; iy<segmentationLevel*iyMax[ist]; iy++) {
	Int_t permilDone = 1000 * (ix * segmentationLevel*iyMax[ist] + iy + 1) /
	                   (segmentationLevel*segmentationLevel*ixMax[ist]*iyMax[ist]);
	if (permilDone%10 == 0) cout<<"\rStation "<<ist+1<<": processing... "<<permilDone/10<<"%"<<flush;
	
	Double_t yIn = yIn0[ist] + ((Double_t)iy+0.5) / ((Double_t)segmentationLevel);
	
	// Initialize starting point and direction
	Double_t trackXYZIn[3] = {xIn, yIn, zIn[ist]};
	Double_t trackXYZOut[3] = {1.000001*xIn, 1.000001*yIn, zOut[ist]};
	Double_t pathLength = TMath::Sqrt((trackXYZOut[0] - trackXYZIn[0])*(trackXYZOut[0] - trackXYZIn[0])+
					  (trackXYZOut[1] - trackXYZIn[1])*(trackXYZOut[1] - trackXYZIn[1])+
					  (trackXYZOut[2] - trackXYZIn[2])*(trackXYZOut[2] - trackXYZIn[2]));
	Double_t b[3];
	b[0] = (trackXYZOut[0] - trackXYZIn[0]) / pathLength;
	b[1] = (trackXYZOut[1] - trackXYZIn[1]) / pathLength;
	b[2] = (trackXYZOut[2] - trackXYZIn[2]) / pathLength;
	TGeoNode *currentnode = gGeoManager->InitTrack(trackXYZIn, b);
	if (!currentnode) break;
	
	Bool_t OK = kTRUE;
	Double_t x0 = 0.;  // radiation-length (cm-1)
	Double_t localOneOverX0MeanCh[10] = {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
	Double_t localTotalLengthCh[10] = {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
	Double_t localPathLength = 0.;
	Double_t remainingPathLength = pathLength;
	do {
	  // Get material properties
	  TGeoMaterial *material = currentnode->GetVolume()->GetMedium()->GetMaterial();
	  TString currentNodePath(gGeoManager->GetPath());
	  x0 = material->GetRadLen();
	  
	  // Get path length within this material
	  gGeoManager->FindNextBoundary(remainingPathLength);
	  localPathLength = gGeoManager->GetStep() + 1.e-6;
	  
	  // Check if boundary within remaining path length.
	  // If so, make sure to cross the boundary to prepare the next step
	  if (localPathLength >= remainingPathLength) localPathLength = remainingPathLength;
	  else {
	    currentnode = gGeoManager->Step();
	    if (!currentnode) { OK = kFALSE; break; }
	    if (!gGeoManager->IsEntering()) {
	      // make another small step to try to enter in new slice
	      gGeoManager->SetStep(0.001);
	      currentnode = gGeoManager->Step();
	      if (!gGeoManager->IsEntering() || !currentnode) { OK = kFALSE; break; }
	      localPathLength += 0.001;
	    }
	  }
	  remainingPathLength -= localPathLength;

	  // check if entering a chamber of the current station or go to next step
	  Int_t chId;
	  if (currentNodePath.Contains(chamberName[2*ist])) chId = 2*ist;
	  else if (currentNodePath.Contains(chamberName[2*ist+1])) chId = 2*ist+1;
	  else continue;
	  
	  // add current material budget
	  localOneOverX0MeanCh[chId] += localPathLength / x0;
	  localTotalLengthCh[chId] += localPathLength;
	  
	} while (remainingPathLength > TGeoShape::Tolerance());
	
	// account for the local material characteristic if computed successfully
	if (OK) {
	  
	  // fill histograms in the full space
	  hXOverX0[2*ist]->Fill(xIn,yIn,100.*localOneOverX0MeanCh[2*ist]);
	  hXOverX0[2*ist+1]->Fill(xIn,yIn,100.*localOneOverX0MeanCh[2*ist+1]);
	  
	  // computation of <x> and <x/x0> in a limited chamber region
	  if (xIn > xIn0ForMean[ist] && xIn < xIn0ForMean[ist]+1.*ixMaxForMean[ist] &&
	      yIn > yIn0ForMean[ist] && yIn < yIn0ForMean[ist]+1.*iyMaxForMean[ist]) {
	    nPoints++;
	    OneOverX0MeanCh[2*ist] += localOneOverX0MeanCh[2*ist];
	    OneOverX0MeanCh[2*ist+1] += localOneOverX0MeanCh[2*ist+1];
	    totalLengthCh[2*ist] += localTotalLengthCh[2*ist];
	    totalLengthCh[2*ist+1] += localTotalLengthCh[2*ist+1];
	  }
	  
	}
	
      }
      
    }
    cout<<"\rStation "<<ist+1<<": processing... 100%"<<endl;
    
    // normalize <x> and <x/x0> to the number of data points
    for (Int_t i=2*ist; i<=2*ist+1; i++) {
      OneOverX0MeanCh[i] /= (Double_t) nPoints;
      totalLengthCh[i] /= (Double_t) nPoints;
    }
    
  }
  
  // print results
  cout<<endl<<endl;
  cout<<"chamber   thickness (cm)    x/x0 (%)"<<endl;
  cout<<"------------------------------------"<<endl;
  for (Int_t i=0; i<10; i++) {
    printf("  %2d          %4.2f            %4.2f\n",i+1,totalLengthCh[i],100.*OneOverX0MeanCh[i]);
    totalLength += totalLengthCh[i];
    OneOverX0Mean += OneOverX0MeanCh[i];
  }
  cout<<"------------------------------------"<<endl;
  printf("  tot         %4.1f            %4.1f\n",totalLength,100.*OneOverX0Mean);
  cout<<endl;
  
  // save histograms
  f->Write();
  f->Close();
  
}