int main() { TGeoNode *node = NULL; TGeoVolume *vol = NULL; LMCgeomN *g = new LMCgeomN("Telescope"); TObjArray *oa = g->GetGeoManager()->GetListOfNodes(); for (int i=0; i<oa->GetEntries(); i++) { node = (TGeoNode*)oa->At(i); vol = node->GetVolume(); cout << "= " << node->GetName() << " " << vol->GetName() <<endl; TObjArray *vnodes = vol->GetNodes(); cout << vnodes->GetEntries() << endl; for (int j=0; j<vnodes->GetEntries(); j++) { node = (TGeoNode*)vnodes->At(j); cout << "== " << node->GetName() << endl; vol = node->GetVolume(); TObjArray *vnodes1 = vol->GetNodes(); for (int k=0; k<vnodes1->GetEntries(); k++) { node = (TGeoNode*)vnodes1->At(k); cout << "=== " << node->GetName() << endl; vol = node->GetVolume(); TObjArray *vnodes2 = vol->GetNodes(); if(!vnodes2) continue; for (int q=0; q<vnodes2->GetEntries(); q++) { node = (TGeoNode*)vnodes2->At(q); cout << "==== " << node->GetName() << endl; } } } } return 0; }
void KVSpectroDetector::UpdateVolumeAndNodeNames(){ // Update the names of Volumes and the names of the Nodes of this // detector. // The name of the volume representing the detector (returned // by GetAbsGeoVolume()) is DET_<detector name>. // The name of the active volumes is ACTIVE_<detector name>_<material name>. // The name of the other volumes is <detector name>_<material name>. GetAbsGeoVolume()->SetName( Form("DET_%s", GetName() ) ); TObjArray *nodes = GetAbsGeoVolume()->GetNodes(); TGeoNode *node = NULL; TGeoVolume *vol = NULL; TIter next( nodes ); while( (node = (TGeoNode *)next()) ){ TString name, nname; vol = node->GetVolume(); name.Form("%s_%s", GetName(), vol->GetMaterial()->GetName()); if( GetActiveVolumes()->Contains( vol ) ) name.Prepend("ACTIVE_"); vol->SetName( name.Data() ); nname = name; Int_t i=0; while( nodes->FindObject( nname.Data() ) ) nname.Form("%s_%d",name.Data(), ++i); node->SetName( nname.Data() ); node->SetNumber( i ); } }
void update_evegeonodes(TEveElement* el, Bool_t top) { TEveGeoNode *en = dynamic_cast<TEveGeoNode*>(el); if (en && !top) { TGeoNode *n = en->GetNode(); en->SetRnrSelfChildren(n->IsVisible(), n->IsVisDaughters()); en->SetMainColor(n->GetVolume()->GetLineColor()); en->SetMainTransparency(n->GetVolume()->GetTransparency()); } for (TEveElement::List_i i = el->BeginChildren(); i != el->EndChildren(); ++i) { update_evegeonodes(*i, kFALSE); } }
void printNodeTree(TObjArray *nodeList, Int_t level) { TIter nextNode(nodeList); TGeoNode *node; while( (node=(TGeoNode *)nextNode())!=NULL ) { for(int k=0;k<level;k++) cerr << "\t"; cerr << node->GetVolume()->GetName() << endl; printNodeTree(node->GetNodes(),level+1); } }
double EUTelGeometryTelescopeGeoDescription::FindRad(Eigen::Vector3d const & startPt, Eigen::Vector3d const & endPt) { Eigen::Vector3d track = endPt-startPt; double length = track.norm(); track.normalize(); double snext; Eigen::Vector3d point; Eigen::Vector3d direction; double epsil = 0.00001; double rad = 0.; double propagatedDistance = 0; bool reachedEnd = false; TGeoMedium* med; gGeoManager->InitTrack(startPt(0), startPt(1), startPt(2), track(0), track(1), track(2)); TGeoNode* nextnode = gGeoManager->GetCurrentNode(); while(nextnode && !reachedEnd) { med = nullptr; if (nextnode) med = nextnode->GetVolume()->GetMedium(); nextnode = gGeoManager->FindNextBoundaryAndStep(length); snext = gGeoManager->GetStep(); if( propagatedDistance+snext >= length ) { snext = length - propagatedDistance; reachedEnd = true; } //snext gets very small at a transition into a next node, in this case we need to manually propagate a small (epsil) //step into the direction of propagation. This introduces a small systematic error, depending on the size of epsil as if(snext < 1.e-8) { const double * currDir = gGeoManager->GetCurrentDirection(); const double * currPt = gGeoManager->GetCurrentPoint(); direction(0) = currDir[0]; direction(1) = currDir[1]; direction(2) = currDir[2]; point(0) = currPt[0]; point(1) = currPt[1]; point(2) = currPt[2]; point = point + epsil*direction; gGeoManager->CdTop(); nextnode = gGeoManager->FindNode(point(0),point(1),point(2)); snext = epsil; } if(med) { //ROOT returns the rad length in cm while we use mm, therefore factor of 10 double radlen = med->GetMaterial()->GetRadLen(); if (radlen > 1.e-5 && radlen < 1.e10) { rad += snext/(radlen*10); } } propagatedDistance += snext; } return rad; }
TGeoNode * findNode(TObjArray *nodeList,const char *name) { TIter nextNode(nodeList); TGeoNode *node; while( (node=(TGeoNode *)nextNode())!=NULL ) { if(strcmp(node->GetVolume()->GetName(),name)==0) return node; if( (node=findNode(node->GetNodes(),name))!= NULL ) return node; } return NULL; }
//________________________________________________________________________________ void StarMCHits::Step() { // static Int_t Idevt0 = -1; static Double_t Gold = 0; #if 0 if (Debug() && gMC->IsA()->InheritsFrom("TGeant3TGeo")) { TGeant3TGeo *geant3 = (TGeant3TGeo *)gMC; geant3->Gdebug(); } #endif // cout << "Call StarMCHits::Step" << endl; TGeoNode *nodeT = gGeoManager->GetCurrentNode(); assert(nodeT); TGeoVolume *volT = nodeT->GetVolume(); assert(volT); const TGeoMedium *med = volT->GetMedium(); /* fParams[0] = isvol; fParams[1] = ifield; fParams[2] = fieldm; fParams[3] = tmaxfd; fParams[4] = stemax; fParams[5] = deemax; fParams[6] = epsil; fParams[7] = stmin; */ Int_t Isvol = (Int_t) med->GetParam(0); fCurrentDetector = 0; if (Isvol <= 0) return; fCurrentDetector = (StarVMCDetector *) fVolUserInfo->At(volT->GetNumber()); if (! fCurrentDetector) { volT = nodeT->GetMotherVolume(); fCurrentDetector = (StarVMCDetector *) fVolUserInfo->At(volT->GetNumber()); if (! fCurrentDetector) { TString path(gGeoManager->GetPath()); TObjArray *obj = path.Tokenize("_/"); Int_t N = obj->GetEntries(); for (Int_t i = N-2; i >= 0; i -= 2) { TObjString *o = (TObjString *) obj->At(i); const Char_t *name = o->GetName(); volT = gGeoManager->GetVolume(name); assert (volT); fCurrentDetector = (StarVMCDetector *) fVolUserInfo->At(volT->GetNumber()); if (fCurrentDetector) break; } delete obj; } } if (Isvol && ! fCurrentDetector && Debug()) { cout << "Active medium:" << med->GetName() << "\t for volume " << volT->GetName() << " has no detector description" << endl; } // Int_t Idevt = gMC->CurrentEvent(); gMC->TrackPosition(fHit.Current.Global.xyzT); gMC->TrackMomentum(fHit.Current.Global.pxyzE); TGeoHMatrix *matrixC = gGeoManager->GetCurrentMatrix(); fHit.Current.Global2Local(matrixC); if (gMC->IsTrackEntering()) { fHit.Detector= fCurrentDetector; fHit.Entry = fHit.Current; fHit.Sleng = gMC->TrackLength(); fHit.Charge = (Int_t) gMC->TrackCharge(); fHit.Mass = gMC->TrackMass(); fHit.AdEstep = fHit.AStep = 0; return; } Double_t GeKin = fHit.Current.Global.pxyzE.E() - fHit.Mass; fHit.Sleng = gMC->TrackLength(); if (fHit.Sleng == 0.) Gold = GeKin; Double_t dEstep = gMC->Edep(); Double_t Step = gMC->TrackStep(); fHit.iPart = gMC->TrackPid(); fHit.iTrack = StarVMCApplication::Instance()->GetStack()->GetCurrentTrackId(); // GetCurrentTrackNumber() + 1 to be consistent with g2t // - - - - - - - - - - - - - energy correction - - - - - - - - - - if (gMC->IsTrackStop() && TMath::Abs(fHit.iPart) == kElectron) { TArrayI proc; Int_t Nproc = gMC->StepProcesses(proc); Int_t Mec = 0; for (Int_t i = 0; i < Nproc; i++) if (proc[i] == kPAnnihilation || proc[i] == kPStop) Mec = proc[i]; Int_t Ngkine = gMC->NSecondaries(); if (fHit.iPart == kElectron && Ngkine == 0 && Mec == kPStop) dEstep = Gold; else { if (fHit.iPart == kPositron && Ngkine < 2 && Mec == kPAnnihilation) { dEstep = Gold + 2*fHit.Mass; if (Ngkine == 1) { TLorentzVector x; TLorentzVector p; Int_t IpartSec; gMC->GetSecondary(0,IpartSec,x,p); dEstep -= p.E(); } } } } // - - - - - - - - - - - - - - - - user - - - - - - - - - - - - - - - // user step // - - - - - - - - - - - - - - - sensitive - - - - - - - - - - - - - fHit.AdEstep += dEstep; fHit.AStep += Step; if (fHit.AdEstep == 0) return; if (! gMC->IsTrackExiting() && ! gMC->IsTrackStop()) return; fHit.Exit = fHit.Current; fHit.Middle = fHit.Entry; fHit.Middle += fHit.Exit; fHit.Middle *= 0.5; if (! fCurrentDetector) return; fHit.VolumeId = fCurrentDetector->GetVolumeId(gGeoManager->GetPath()); FillG2Table(); }
dunedphase10kt_geo(TString volName="") { gSystem->Load("libGeom"); gSystem->Load("libGdml"); std::string geofile = "dunedphase10kt_v2.gdml"; TGeoManager::Import(geofile.c_str()); //TList* mat = gGeoManager->GetListOfMaterials(); //TIter next(mat); TGeoIterator next(gGeoManager->GetTopVolume()); TGeoNode *node = 0; //gGeoManager->GetVolume("volCryostat")->SetLineColor(kMagenta); //gGeoManager->GetVolume("volCryostat")->SetVisibility(1); //gGeoManager->GetVolume("volCryostat")->SetTransparency(85); gGeoManager->GetVolume("volSteelShell")->SetLineColor(19); gGeoManager->GetVolume("volSteelShell")->SetVisibility(1); gGeoManager->GetVolume("volSteelShell")->SetTransparency(85); gGeoManager->GetVolume("volGaseousArgon")->SetLineColor(kYellow); gGeoManager->GetVolume("volGaseousArgon")->SetVisibility(1); gGeoManager->GetVolume("volGaseousArgon")->SetTransparency(85); while ( (node=(TGeoNode*)next()) ){ const char* nm = node->GetName(); if( (strncmp(nm, "volCathode", 10) == 0) ){ node->GetVolume()->SetLineColor(kOrange+3); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(30); } if( (strncmp(nm, "volTPCActive", 12) == 0) ){ node->GetVolume()->SetLineColor(kGreen-7); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(80); } if( (strncmp(nm, "volAPAFrame", 11) == 0) ){ node->GetVolume()->SetLineColor(kGray); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(20); } if( (strncmp(nm, "volG10Board", 11) == 0) ){ node->GetVolume()->SetLineColor(kMagenta-10); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(40); } if( (strncmp(nm, "volTPCPlane", 11) == 0) ){ node->GetVolume()->SetLineColor(kBlue-9); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(50); } if( (strncmp(nm, "volTPCInner", 11) == 0) ){ node->GetVolume()->SetLineColor(kWhite); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(100); } if( (strncmp(nm, "volTPCOuter", 11) == 0) ){ node->GetVolume()->SetLineColor(kWhite); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(100); } if( (strncmp(nm, "volOpDetSensitive", 17) == 0) ){ node->GetVolume()->SetLineColor(kRed-4); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(10); } if( (strncmp(nm, "volWorld", 8) == 0) ){ node->GetVolume()->SetLineColor(kOrange-7); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(100); } if( (strncmp(nm, "volFoamPadding", 14) == 0) ){ node->GetVolume()->SetLineColor(kCyan); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(85); } if( (strncmp(nm, "volSteelSupport", 15) == 0) ){ node->GetVolume()->SetLineColor(kBlue); node->GetVolume()->SetVisibility(1); node->GetVolume()->SetTransparency(85); } } gGeoManager->GetTopNode(); //gGeoManager->CheckOverlaps(1e-5); //gGeoManager->PrintOverlaps(); //gGeoManager->SetMaxVisNodes(70000); //gGeoManager->GetTopVolume()->Draw("ogl"); gGeoManager->FindVolumeFast("volWorld")->Draw("ogl"); //gGeoManager->FindVolumeFast("volTPCPlaneUInner")->Draw("ogl"); //if ( ! volName.IsNull() ) gGeoManager->FindVolumeFast(volName)->Draw("ogl"); //gGeoManager->FindVolumeFast("volCryostat")->Draw("X3D"); size_t lastindex = geofile.find_last_of("."); std::string basename = geofile.substr(0, lastindex); TFile *tf = new TFile(Form("%s.root",basename.c_str()), "RECREATE"); gGeoManager->Write(); tf->Close(); }
/** * Calculate effective radiation length traversed by particle traveling between two points * along straight line. * * Calculation is done according to the eq. (27.23) * @see http://pdg.lbl.gov/2006/reviews/passagerpp.pdf * * @param globalPosStart starting point in the global coordinate system * @param globalPosFinish ending point in the global coordinate system * @param skipBoundaryVolumes if true subtract rad length of the volumes containing start and finish points * * @return radiation length in units of X0 */ float EUTelGeometryTelescopeGeoDescription::findRadLengthIntegral( const double globalPosStart[], const double globalPosFinish[], bool skipBoundaryPonitsVolumes ) { streamlog_out(DEBUG1) << "EUTelGeometryTelescopeGeoDescription::findRadLengthIntegral()" << std::endl; float rad = 0.; // integral of radiation length in units of X0 const double mm2cm = 0.1; /* TGeo uses cm and grams as internal units e.g. in radiation length and density. Telescope/LCIO uses mm. Therefore this routine is full of annoying conversion factors */ const double stepLenght2 = ( globalPosFinish[0] - globalPosStart[0] )*( globalPosFinish[0] - globalPosStart[0] ) + ( globalPosFinish[1] - globalPosStart[1] )*( globalPosFinish[1] - globalPosStart[1] ) + ( globalPosFinish[2] - globalPosStart[2] )*( globalPosFinish[2] - globalPosStart[2] ); const double stepLenght = TMath::Sqrt( stepLenght2 ); // don't need conversion factor to for calculation of directions const double xp = ( globalPosFinish[0] - globalPosStart[0] )/stepLenght; const double yp = ( globalPosFinish[1] - globalPosStart[1] )/stepLenght; const double zp = ( globalPosFinish[2] - globalPosStart[2] )/stepLenght; streamlog_out(DEBUG0) << "Start point (x,y,z):" << globalPosStart[0] << "," << globalPosStart[1] << "," << globalPosStart[2] << std::endl; streamlog_out(DEBUG0) << "Finish point (x,y,z):" << globalPosFinish[0] << "," << globalPosFinish[1] << "," << globalPosFinish[2] << std::endl; streamlog_out(DEBUG0) << "Direction (nx,ny,nz):" << xp << "," << yp << "," << zp << std::endl; double snext; double pt[3], loc[3]; double epsil = 1.E-7; double lastrad = 0.; int ismall = 0; int nbound = 0; float length = 0.; TGeoMedium *med; TGeoShape *shape; // Get starting node gGeoManager->InitTrack( globalPosStart[0]/*mm*/, globalPosStart[1]/*mm*/, globalPosStart[2]/*mm*/, xp, yp, zp ); TGeoNode *nextnode = gGeoManager->GetCurrentNode( ); double currentStep = stepLenght /*mm*/; // Loop over all, encountered during the propagation, volumes while ( nextnode ) { med = NULL; // Check if current point is inside silicon sensor. Radiation length of silicon sensors is accounted in thin scatterers of GBL. bool isBoundaryVolume = false; if ( gGeoManager->IsSameLocation( globalPosStart[0], globalPosStart[1], globalPosStart[2] ) || gGeoManager->IsSameLocation( globalPosFinish[0], globalPosFinish[1], globalPosFinish[2] ) ) isBoundaryVolume = true; if ( nextnode ) med = nextnode->GetVolume()->GetMedium(); else return 0.; shape = nextnode->GetVolume()->GetShape(); // make a step to the next intersection point if ( currentStep > 1.e-9 /*mm*/ ) nextnode = gGeoManager->FindNextBoundaryAndStep( currentStep /*mm*/ ); else return rad; snext = gGeoManager->GetStep() /*mm*/; // Small steps treatment if ( snext < 1.e-8 /*mm*/ ) { ismall++; // Terminate calculation if too many small steps done if ( ismall > 3 ) { streamlog_out( WARNING1 ) << "ERROR: Small steps in: " << gGeoManager->GetPath() << " shape=" << shape->ClassName() << endl; return rad; } // increase step size (epsilon) and advance along the particle direction memcpy( pt, gGeoManager->GetCurrentPoint(), 3 * sizeof (double) ); const double *dir = gGeoManager->GetCurrentDirection(); for ( Int_t i = 0; i < 3; i++ ) pt[i] += epsil * dir[i]; snext = epsil; length += snext; // Ignore start and finish volumes if required if ( skipBoundaryPonitsVolumes && isBoundaryVolume ) { rad += 0.; } else { rad += lastrad*snext; } gGeoManager->CdTop( ); nextnode = gGeoManager->FindNode( pt[0], pt[1], pt[2] ); // Check if particle is crossed the boundary if ( gGeoManager->IsOutside() ) return rad; // leave if not TGeoMatrix *mat = gGeoManager->GetCurrentMatrix(); mat->MasterToLocal( pt, loc ); if ( !gGeoManager->GetCurrentVolume()->Contains( loc ) ) { gGeoManager->CdUp(); nextnode = gGeoManager->GetCurrentNode(); // move to new volume } continue; } else { ismall = 0; } // Normal steps case nbound++; length += snext; currentStep -= snext; if ( med ) { double radlen = med->GetMaterial()->GetRadLen() /*cm*/; if ( radlen > 1.e-9 && radlen < 1.e10 ) { lastrad = 1. / radlen * mm2cm; // Ignore start and finish volumes if required if ( skipBoundaryPonitsVolumes && isBoundaryVolume ) { rad += 0.; } else { rad += lastrad*snext; } } else { lastrad = 0.; } streamlog_out( DEBUG0 ) << "STEP #" << nbound << std::endl; streamlog_out( DEBUG0 ) << " step[mm]=" << snext << " length[mm]=" << length << " rad[X0]=" << snext * mm2cm / radlen << " " << med->GetName( ) << " rho[g/cm^3]=" << med->GetMaterial()->GetDensity() <<" radlen[cm]=" << radlen << " Boundary:" << (isBoundaryVolume?"yes":"no") << std::endl; } } streamlog_out(DEBUG1) << "--------EUTelGeometryTelescopeGeoDescription::findRadLengthIntegral()--------" << std::endl; return rad; }
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(); }
//____________________________________________________________________________ void get_mass(Double_t length_unit, Double_t density_unit) { //tables of Z and A const Int_t lcin_Z = 150; const Int_t lcin_A = 300; // calc unit conversion factors Double_t density_unit_to_SI = density_unit / units::kg_m3; Double_t length_unit_to_SI = length_unit / units::m; Double_t volume_unit_to_SI = TMath::Power(length_unit_to_SI, 3.); #ifdef _debug_ cout << "Input density unit --> kg/m^3 : x" << density_unit_to_SI << endl; cout << "Input length unit --> m : x" << length_unit_to_SI << endl; #endif // get materials in geometry TList *matlist = gGeoManager->GetListOfMaterials(); if (!matlist ) { cout << "Null list of materials!" << endl; return; } else { #ifdef _debug_ matlist->Print(); #endif } int max_idx = 0; // number of mixtures in geometry Int_t nmat = matlist->GetEntries(); for( Int_t imat = 0; imat < nmat; imat++ ) { Int_t idx = gGeoManager->GetMaterial(imat)->GetIndex(); max_idx = TMath::Max(max_idx, idx); } //check if material index is unique Int_t * checkindex = new Int_t[max_idx+1]; for( Int_t i = 0; i<max_idx+1; i++ ) checkindex[i] = 0; for( Int_t imat = 0; imat < nmat; imat++ ) { if( !checkindex[imat] ) checkindex[imat] = 1; else { cout << "material index is not unique" << endl; return; } } #ifdef _debug_ cout << "max_idx = " << max_idx << endl; cout << "nmat = " << nmat << endl; #endif TGeoVolume * topvol = gGeoManager->GetTopVolume(); //get top volume if (!topvol) { cout << "volume does not exist" << endl; return; } TGeoIterator NodeIter(topvol); TGeoNode *node; NodeIter.SetType(0); // include all daughters Double_t * volume = new Double_t[max_idx+1]; Double_t * mass = new Double_t[max_idx+1]; for( Int_t i = 0; i<max_idx+1; i++ ){ volume[i]=0.; mass[i]=0.; } // IMPORTANT! force empty arrays, allows repated calls without ending ROOT session volume[ topvol->GetMaterial()->GetIndex() ] = topvol->Capacity() * volume_unit_to_SI; //iterator does not include topvolume while ( (node=NodeIter()) ) { Int_t momidx = node->GetMotherVolume()->GetMaterial()->GetIndex() ; Int_t idx = node->GetVolume() ->GetMaterial()->GetIndex() ; Double_t node_vol = node->GetVolume()->Capacity() * volume_unit_to_SI; volume[ momidx ] -= node_vol; //substract subvolume from mother volume[ idx ] += node_vol; } Double_t larr_MassIsotopes[lcin_Z][lcin_A] = {0.}; //[Z][A], no map in pure ROOT Double_t larr_VolumeIsotopes[lcin_Z][lcin_A] = {0.}; //[Z][A], no map in pure ROOT for( Int_t i=0; i<gGeoManager->GetListOfMaterials()->GetEntries(); i++ ) { TGeoMaterial *lgeo_Mat = gGeoManager->GetMaterial(i); Int_t idx = gGeoManager->GetMaterial(i)->GetIndex(); if( lgeo_Mat->IsMixture() ) { TGeoMixture * lgeo_Mix = dynamic_cast <TGeoMixture*> ( lgeo_Mat ); Int_t lint_Nelements = lgeo_Mix->GetNelements(); for ( Int_t j=0; j<lint_Nelements; j++) { Int_t lint_Z = TMath::Nint( (Double_t) lgeo_Mix->GetZmixt()[j] ); Int_t lint_A = TMath::Nint( (Double_t) lgeo_Mix->GetAmixt()[j] ); Double_t ldou_Fraction = lgeo_Mix->GetWmixt()[j]; Double_t ldou_Density = lgeo_Mix->GetDensity() * density_unit_to_SI; larr_MassIsotopes[ lint_Z ][ lint_A ] += volume[idx] * ldou_Fraction * ldou_Density; larr_VolumeIsotopes[ lint_Z ][ lint_A ] += volume[idx] * ldou_Fraction; } } } // // print out volume/mass for each `material' // Double_t ldou_MinimumVolume = 1e-20; cout << endl << " Geometry: \"" << gFileName << "\"" << endl << " TopVolume: \"" << topvol->GetName() << "\"" << endl; cout <<endl << "materials:" << endl; cout << setw(5) << "index" << setw(15) << "name" << setprecision(6) << setw(14) << "volume (m^3)" << setw(14) << "mass (kg)" << setw(14) << "mass (%)" << endl; double total_mass_materials = 0; for( Int_t i=0; i<gGeoManager->GetListOfMaterials()->GetEntries(); i++ ) { Int_t idx = gGeoManager->GetMaterial(i)->GetIndex(); Double_t density = gGeoManager->GetMaterial(i)->GetDensity() * density_unit_to_SI; Double_t mass_material = density * volume[idx]; if ( volume[idx] > ldou_MinimumVolume ) { total_mass_materials += mass_material; } } for( Int_t i=0; i<gGeoManager->GetListOfMaterials()->GetEntries(); i++ ) { Int_t idx = gGeoManager->GetMaterial(i)->GetIndex(); Double_t density = gGeoManager->GetMaterial(i)->GetDensity() * density_unit_to_SI; mass[idx] = density * volume[idx]; if( volume[idx] > ldou_MinimumVolume ) { cout << setw(5) << i << setw(15) << gGeoManager->GetMaterial(i)->GetName() << setprecision(6) << setw(14) << volume[idx] << setw(14) << mass[idx] << setw(14) << mass[idx]*100./total_mass_materials << endl; } } // // print out mass contribution for each nuclear target // PDGLibrary* pdglib = PDGLibrary::Instance(); cout <<endl << "isotopes:" << endl; cout << setw(4) << "Z" << setw(4) << "A" << setw(14) << "PDG isotope" << setw(5) << " " << setprecision(6) << setw(14) << "volume (m^3)" << setw(14) << "mass (kg)" << setw(10) << "mass (%)" << endl; double total_mass_isotopes = 0; for( Int_t i=0; i<lcin_Z; i++ ) { for( Int_t j=0; j<lcin_A; j++ ) { if( larr_VolumeIsotopes[ i ][ j ] > ldou_MinimumVolume ) { total_mass_isotopes += larr_MassIsotopes[ i ][ j ]; } } } for( Int_t i=0; i<lcin_Z; i++ ) { for( Int_t j=0; j<lcin_A; j++ ) { if( larr_VolumeIsotopes[ i ][ j ] > ldou_MinimumVolume ) { int pdgcode = 1000000000 + i*10000 + j*10; cout << setw(4) << i << setw(4)<< j << setw(14) << pdgcode << setw(5) << pdglib->Find(pdgcode)->GetName() << setprecision(6) << setw(14) << larr_VolumeIsotopes[ i ][ j ] << setw(14) << larr_MassIsotopes[ i ][ j ] << setw(10) << larr_MassIsotopes[ i ][ j ]*100.0/total_mass_isotopes << endl; } else if ( larr_VolumeIsotopes[ i ][ j ] < -ldou_MinimumVolume ) { cout << "negative volume, check geometry " << larr_VolumeIsotopes[ i ][ j ] << endl; } } } cout << endl << " mass totals: " << total_mass_materials << " " << total_mass_isotopes << endl << endl; delete [] volume; delete [] mass; }