void fw_simGeo_set_material_titles(Double_t fraction=0, Bool_t long_names=false) { TGeoMaterial *m; TIter it(FWGeometryTableViewManager_GetGeoManager()->GetListOfMaterials()); while ((m = (TGeoMaterial*) it()) != 0) { TString tit(":"); TGeoMixture *mix = dynamic_cast<TGeoMixture*>(m); if (mix == 0) { TGeoElement *e = m->GetBaseElement(); tit += long_names ? e->GetTitle() : e->GetName(); tit += ":"; } else { Double_t *ww = mix->GetWmixt(); for (Int_t i = 0; i < mix->GetNelements(); ++i) { if (ww[i] >= fraction) { TGeoElement *e = mix->GetElement(i); tit += long_names ? e->GetTitle() : e->GetName(); tit += ":"; } } } if (tit == ":") tit += ":"; m->SetTitle(tit); } }
void fw_simGeo_fix_materials() { Int_t base_element_offset = TGeoMaterial::Class()->GetDataMemberOffset("fElement"); TString vacuum("materials:Vacuum"); TGeoMaterial *m; TIter it(FWGeometryTableViewManager_GetGeoManager()->GetListOfMaterials()); while ((m = (TGeoMaterial*) it()) != 0) { // Fixes if (vacuum == m->GetName()) { m->SetZ(0); } TGeoMixture *mix = dynamic_cast<TGeoMixture*>(m); if (mix == 0) { if ( ! m->GetBaseElement()) { *(TGeoElement**)(((char*)m) + base_element_offset) = g_element_table->GetElement(m->GetZ()); } } } }
void KVGeoImport::AddLayer(KVDetector *det, TGeoVolume *vol) { // Add an absorber layer to the detector // Volumes representing 'active' layers in detectors must have names // which begin with "ACTIVE_" TString vnom = vol->GetName(); // exclude dead zone layers if(vnom.BeginsWith("DEADZONE")) return; TGeoMaterial* material = vol->GetMaterial(); KVIonRangeTableMaterial* irmat = fRangeTable->GetMaterial(material); if(!irmat){ Warning("AddLayer", "Unknown material %s/%s used in layer %s of detector %s", material->GetName(), material->GetTitle(), vol->GetName(), det->GetName()); return; } TGeoBBox* sh = dynamic_cast<TGeoBBox*>(vol->GetShape()); if(!sh) { Warning("AddLayer", "Unknown shape class %s used in layer %s of detector %s", vol->GetShape()->ClassName(), vol->GetName(), det->GetName()); return; // just in case - for now, all shapes derive from TGeoBBox... } Double_t width = 2.*sh->GetDZ(); // thickness in centimetres KVMaterial* absorber; if( irmat->IsGas() ){ Double_t p = material->GetPressure(); Double_t T = material->GetTemperature(); absorber = new KVMaterial(irmat->GetType(), width, p, T); } else absorber = new KVMaterial(irmat->GetType(), width); det->AddAbsorber(absorber); if(vnom.BeginsWith("ACTIVE_")) det->SetActiveLayer( det->GetListOfAbsorbers()->GetEntries()-1 ); }
void fw_simGeo_set_volume_color_by_material(const char* material_re, Bool_t use_names, Color_t color, Char_t transparency=-1) { // Note: material_re is a perl regexp! // If you want exact match, enclose in begin / end meta characters (^ / $): // set_volume_color_by_material("^materials:Silicon$", kRed); TPMERegexp re(material_re, "o"); TGeoMaterial *m; TIter it(FWGeometryTableViewManager_GetGeoManager()->GetListOfMaterials()); while ((m = (TGeoMaterial*) it()) != 0) { if (re.Match(use_names ? m->GetName() : m->GetTitle())) { if (transparency != -1) { m->SetTransparency(transparency); } TGeoVolume *v; TIter it2(FWGeometryTableViewManager_GetGeoManager()->GetListOfVolumes()); while ((v = (TGeoVolume*) it2()) != 0) { if (v->GetMaterial() == m) { v->SetLineColor(color); } } } } }
TGeoMaterial* KVIonRangeTableMaterial::GetTGeoMaterial() const { // Create and return pointer to a TGeoMaterial or TGeoMixture (for compound materials) // with the properties of this material. // gGeoManager must exist. TGeoMaterial* gmat = 0x0; if (!gGeoManager) return gmat; if (IsCompound()) { gmat = new TGeoMixture(GetTitle(), GetComposition()->GetEntries(), GetDensity()); TIter next(GetComposition()); KVNameValueList* nvl; while ((nvl = (KVNameValueList*)next())) { KVNucleus n(nvl->GetIntValue("Z"), nvl->GetIntValue("A")); TGeoElement* gel = gGeoManager->GetElementTable()->FindElement(n.GetSymbol("EL")); float poids = nvl->GetDoubleValue("NormWeight"); ((TGeoMixture*)gmat)->AddElement(gel, poids); } } else { gmat = new TGeoMaterial(GetTitle(), GetMass(), GetZ(), GetDensity()); } // set state of material if (IsGas()) gmat->SetState(TGeoMaterial::kMatStateGas); else gmat->SetState(TGeoMaterial::kMatStateSolid); return gmat; }
void set_volume_color_by_material(const char* material_re, Color_t color, Char_t transparency=-1) { // Note: material_re is a perl regexp! // If you want exact match, enclose in begin / end meta characters (^ / $): // set_volume_color_by_material("^materials:Silicon$", kRed); TPMERegexp re(material_re, "o"); TGeoMaterial *m; TIter it(gGeoManager->GetListOfMaterials()); while ((m = (TGeoMaterial*) it()) != 0) { if (re.Match(m->GetName())) { if (transparency != -1) { m->SetTransparency(transparency); } TGeoVolume *v; TIter it2(gGeoManager->GetListOfVolumes()); while ((v = (TGeoVolume*) it2()) != 0) { if (v->GetMaterial() == m) { v->SetLineColor(color); } } } } full_update(); }
void KVSpectroDetector::AddAbsorberLayer( TGeoVolume *vol, Bool_t active){ // Add an absorber layer to the detector made from the shape of the // volume. // If active = kTRUE the layer is set active. TGeoMaterial* material = vol->GetMaterial(); KVIonRangeTableMaterial* irmat = KVMaterial::GetRangeTable()->GetMaterial(material); if(!irmat){ Warning("AddAbsorberLayer", "Unknown material %s/%s used in layer %s of detector %s", material->GetName(), material->GetTitle(), vol->GetName(), GetName()); return; } TGeoBBox* sh = dynamic_cast<TGeoBBox*>(vol->GetShape()); if(!sh) { Warning("AddAbsorberLayer", "Unknown shape class %s used in layer %s of detector %s", vol->GetShape()->ClassName(), vol->GetName(), GetName()); return; // just in case - for now, all shapes derive from TGeoBBox... } Double_t width = 2.*sh->GetDZ(); // thickness in centimetres KVMaterial* absorber; if( irmat->IsGas() ){ Double_t p = material->GetPressure(); Double_t T = material->GetTemperature(); absorber = new KVMaterial(irmat->GetType(), width, p, T); } else absorber = new KVMaterial(irmat->GetType(), width); KVDetector::AddAbsorber(absorber); ClearHits(); if( active ) SetActiveLayer( GetListOfAbsorbers()->GetEntries()-1 ); }
void KVFAZIA::Build(Int_t) { // Build the combined INDRA & FAZIA arrays GetGeometryParameters(); GenerateCorrespondanceFile(); if (!gGeoManager) { new TGeoManager("FAZIA", Form("FAZIA geometry for dataset %s", gDataSet->GetName())); TGeoMaterial* matVacuum = gGeoManager->GetMaterial("Vacuum"); if (!matVacuum) { matVacuum = new TGeoMaterial("Vacuum", 0, 0, 0); matVacuum->SetTitle("Vacuum"); } TGeoMedium* Vacuum = gGeoManager->GetMedium("Vacuum"); if (!Vacuum) Vacuum = new TGeoMedium("Vacuum", 1, matVacuum); TGeoVolume* top = gGeoManager->MakeBox("WORLD", Vacuum, 500, 500, 500); gGeoManager->SetTopVolume(top); } BuildFAZIA(); if (fBuildTarget) BuildTarget(); KVGeoImport imp(gGeoManager, KVMaterial::GetRangeTable(), this, kTRUE); imp.SetDetectorPlugin(ClassName()); imp.SetNameCorrespondanceList(fCorrespondanceFile.Data()); // any additional structure name formatting definitions DefineStructureFormats(imp); // the following parameters are optimized for a 12-block compact // geometry placed at 80cm with rings 1-5 of INDRA removed. // make sure that the expected number of detectors get imported! imp.ImportGeometry(fImport_dTheta, fImport_dPhi, fImport_ThetaMin, fImport_PhiMin, fImport_ThetaMax, fImport_PhiMax); /* KVFAZIADetector* det=0; TIter next_d(GetDetectors()); while ( det = (KVFAZIADetector* )next_d() ){ printf("%s %s %d %d %d\n",det->GetName(),det->GetFAZIAType(),det->GetBlockNumber(),det->GetQuartetNumber(),det->GetTelescopeNumber()); } */ SetIdentifications(); SortIDTelescopes(); KVDetector* det = GetDetector("SI2-T1-Q1-B001"); det->GetIDTelescopes()->ls(); SetDetectorThicknesses(); SetBit(kIsBuilt); }
void fw_simGeo_dump_materials(Bool_t dump_components=false) { TGeoMaterial *m; TIter it(FWGeometryTableViewManager_GetGeoManager()->GetListOfMaterials()); while ((m = (TGeoMaterial*) it()) != 0) { TGeoMixture *mix = dynamic_cast<TGeoMixture*>(m); printf("%-50s | %-40s | %2d | %.3f\n", m->GetName(), m->GetTitle(), mix ? mix->GetNelements() : 0, m->GetZ()); if (dump_components) { if (mix == 0) { printf(" %4d %6s %s\n", m->GetBaseElement()->Z(), m->GetBaseElement()->GetName(), m->GetBaseElement()->GetTitle()); } else { Double_t *ww = mix->GetWmixt(); for (Int_t i = 0; i < mix->GetNelements(); ++i) { TGeoElement *e = mix->GetElement(i); printf(" %4d %-4s %f\n", e->Z(), e->GetName(), ww[i]); } } } } }
void visibility_volume_by_material(const char* material_re, Bool_t vis_state) { TPMERegexp re(material_re, "o"); TGeoMaterial *m; TIter it(gGeoManager->GetListOfMaterials()); while ((m = (TGeoMaterial*) it()) != 0) { if (re.Match(m->GetName())) { TGeoVolume *v; TIter it2(gGeoManager->GetListOfVolumes()); while ((v = (TGeoVolume*) it2()) != 0) { if (v->GetMaterial() == m) { v->SetVisibility(vis_state); } } } } full_update(); }
void AliITSMaterialsTGeo(TString gfile="geometry.root"){ // Macro to print out the ITS material definitions as found // in the TGeo geometry file. // retrives geometry if(!gGeoManager) gGeoManager = new TGeoManager(); TGeoManager::Import(gfile.Data()); if (!gGeoManager) { cout<<"geometry not found\n"; return; } // end if TList *medlist=gGeoManager->GetListOfMedia(); TGeoMedium *med; TGeoMaterial *mat; Int_t imed,nmed,i; printf("imed Id Med_Name Mat_Name "); for(i=0;i<20;i++) printf(" par[%2d] ",i); printf("\n"); imed=0; do{ med = (TGeoMedium*)(medlist->At(imed)); if(!med) continue; /*if((((med->GetName())[0]=='I')&& // Only ITS. ((med->GetName())[1]=='T')&& ((med->GetName())[2]=='S')&& ((med->GetName())[3]=='_')))*/{ mat = med->GetMaterial(); if(mat) printf("%4d %4d %30s %30s",imed,med->GetId(),med->GetName(),mat->GetName()); else printf("%4d %4d %30s %30s",imed,med->GetId(),med->GetName(),"No Material"); for(i=0;i<20;i++) printf(" %12g",med->GetParam(i)); printf("\n"); imed++; } }while(med!=medlist->Last()); }
/* 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; }
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); } }
/** * 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; }
void KVVAMOSReconGeoNavigator::ParticleEntersNewVolume(KVNucleus* nuc) { // Overrides method in KVGeoNavigator base class. // Every time a particle enters a new volume, we check the material to see // if it is known (i.e. contained in the range table fRangeTable). // If so, then we calculate the step through the material (STEP) of the nucleus // and the distance (DPATH in cm) between the intersection point at the focal plane // and the point at the entrance of the volume if it is the first active volume of a detector. // DPATH has the sign + if the volume is behind the focal plane or - if it // is at the front of it. // KVVAMOSReconNuc* rnuc = (KVVAMOSReconNuc*)nuc; // stop the propagation if the current volume is the stopping detector // of the nucleus but after the process of this volume if (rnuc->GetStoppingDetector()) { TGeoVolume* stopVol = (TGeoVolume*)((KVVAMOSDetector*)rnuc->GetStoppingDetector())->GetActiveVolumes()->Last(); if (GetCurrentVolume() == stopVol) SetStopPropagation(); } if (fDoNothing) return; TGeoMaterial* material = GetCurrentVolume()->GetMaterial(); KVIonRangeTableMaterial* irmat = 0; // skip the process if the current material is unkown if ((irmat = fRangeTable->GetMaterial(material))) { KVString dname; Bool_t multi; TString absorber_name; Bool_t is_active = kFALSE; if (GetCurrentDetectorNameAndVolume(dname, multi)) { is_active = kTRUE; if (multi) { absorber_name.Form("%s/%s", dname.Data(), GetCurrentNode()->GetName()); is_active = absorber_name.Contains("ACTIVE_"); } else absorber_name = dname; } else absorber_name = irmat->GetName(); // Coordinates of the vector between the intersection point at the // focal plane and the point at the entrance of the current detector Double_t X = GetEntryPoint().X() - fOrigine.X(); Double_t Y = GetEntryPoint().Y() - fOrigine.Y(); Double_t Z = GetEntryPoint().Z() - fOrigine.Z(); // Norm of this vector. The signe gives an infomation about the detector position // (1: behind; -1: in front of) with respect to the focal plane. Double_t Delta = TMath::Sign(1., Z) * TMath::Sqrt(X * X + Y * Y + Z * Z); if ((fCalib & kECalib) || (fCalib & kTCalib)) { if (fE > 1e-3) { // velocity before material Double_t Vi = nuc->GetVelocity().Mag(); // energy lost in the material Double_t DE = irmat->GetLinearDeltaEOfIon( nuc->GetZ(), nuc->GetA(), fE, GetStepSize(), 0., material->GetTemperature(), material->GetPressure()); fE -= DE; nuc->SetEnergy(fE); //set flag to say that particle has been slowed down nuc->SetIsDetected(); // velocity after material Double_t Vf = nuc->GetVelocity().Mag(); if (fCalib & kTCalib) { //from current start point to the entrance point fTOF += (Delta - fStartPath) / Vi; fStartPath = Delta; //nuc->GetParameters()->SetValue(Form("TOF:%s",absorber_name.Data()), fTOF); if (is_active) nuc->GetParameters()->SetValue(Form("TOF:%s", dname.Data()), fTOF); else if ((fCalib & kFullTCalib) == kFullTCalib) nuc->GetParameters()->SetValue(Form("TOF:%s", absorber_name.Data()), fTOF); // from the entrance to the exit of the material Double_t step = GetStepSize(); fTOF += CalculateLinearDeltaT(Vi, Vf, step); fStartPath += step; } if (fCalib & kECalib) { if (is_active) nuc->GetParameters()->SetValue(Form("DE:%s", dname.Data()), DE); else if ((fCalib & kFullECalib) == kFullECalib) nuc->GetParameters()->SetValue(Form("DE:%s", absorber_name.Data()), DE); } } } if (is_active) nuc->GetParameters()->SetValue(Form("DPATH:%s", dname.Data()), Delta); else if ((fCalib & kFullTCalib) == kFullTCalib) nuc->GetParameters()->SetValue(Form("DPATH:%s", absorber_name.Data()), Delta); nuc->GetParameters()->SetValue(Form("STEP:%s", absorber_name.Data()), GetStepSize()); } }
TGeoMedium* KVMaterial::GetGeoMedium(const Char_t* med_name) { // By default, return pointer to TGeoMedium corresponding to this KVMaterial. // If argument "med_name" is given and corresponds to the name of an already existing // medium, we return a pointer to this medium, or 0x0 if it does not exist. // med_name = "Vacuum" is a special case: if the "Vacuum" does not exist, we create it. // // Instance of geometry manager class TGeoManager must be created before calling this // method, otherwise 0x0 will be returned. // If the required TGeoMedium is not already available in the TGeoManager, we create // a new TGeoMedium corresponding to the properties of this KVMaterial. // The name of the TGeoMedium (and associated TGeoMaterial) is the name of the KVMaterial. if (!gGeoManager) return NULL; if (strcmp(med_name, "")) { TGeoMedium* gmed = gGeoManager->GetMedium(med_name); if (gmed) return gmed; else if (!strcmp(med_name, "Vacuum")) { // create material TGeoMaterial* gmat = new TGeoMaterial("Vacuum", 0, 0, 0); gmat->SetTitle("Vacuum"); gmed = new TGeoMedium("Vacuum", 0, gmat); gmed->SetTitle("Vacuum"); return gmed; } return NULL; } // if object is a KVDetector, we return medium corresponding to the active layer if (GetActiveLayer()) return GetActiveLayer()->GetGeoMedium(); // for gaseous materials, the TGeoMedium/Material name is of the form // gasname_pressure // e.g. C3F8_37.5 for C3F8 gas at 37.5 torr // each gas with different pressure has to have a separate TGeoMaterial/Medium TString medName; if (IsGas()) medName.Form("%s_%f", GetName(), GetPressure()); else medName = GetName(); TGeoMedium* gmed = gGeoManager->GetMedium(medName); if (gmed) return gmed; TGeoMaterial* gmat = gGeoManager->GetMaterial(medName); if (!gmat) { // create material gmat = GetRangeTable()->GetTGeoMaterial(GetName()); gmat->SetPressure(GetPressure()); gmat->SetTemperature(GetTemperature()); gmat->SetTransparency(0); gmat->SetName(medName); gmat->SetTitle(GetName()); } // create medium static Int_t numed = 1; // static counter variable used to number media gmed = new TGeoMedium(medName, numed, gmat); numed += 1; return gmed; }
TGeoMedium* KVSpectroDetector::GetGeoMedium(const Char_t* mat_name){ // By default, return pointer to TGeoMedium corresponding to this KVMaterial. // If argument "mat_name" is given, a pointer to a medium is return for this material. // mat_name = "Vacuum" is a special case: if the "Vacuum" does not exist, we create it. // // Instance of geometry manager class TGeoManager must be created before calling this // method, otherwise 0x0 will be returned. // If the required TGeoMedium is not already available in the TGeoManager, we create // a new TGeoMedium corresponding to the material given in argument. if( !gGeoManager ) return NULL; TString medName, matName; if( !strcmp(mat_name,"") ){ // for gaseous materials, the TGeoMedium/Material name is of the form // gasname_pressure // e.g. C3F8_37.5 for C3F8 gas at 37.5 torr // each gas with different pressure has to have a separate TGeoMaterial/Medium matName = GetName(); KVIonRangeTableMaterial* irmat = KVMaterial::GetRangeTable()->GetMaterial(matName.Data()); if(irmat->IsGas()) medName.Form("%s_%f", matName.Data(), GetPressure()); else medName = GetName(); } else{ matName = mat_name; medName = mat_name; } TGeoMedium* gmed = gGeoManager->GetMedium( medName); if( gmed ) return gmed; TGeoMaterial *gmat = gGeoManager->GetMaterial( medName); if( !gmat ){ if( !strcmp(matName.Data(), "Vacuum") ){ // create material gmat = new TGeoMaterial("Vacuum",0,0,0 ); } else{ // create material gmat = GetRangeTable()->GetTGeoMaterial(matName.Data()); if(!gmat){ Error("GetGeoMedium","Material %s is nowhere to be found in %s" ,matName.Data(),GetRangeTable()->GetName()); return NULL; } gmat->SetPressure( GetPressure() ); gmat->SetTemperature( GetTemperature() ); gmat->SetTransparency(0); } } // For the moment the names of material and medium do not // depend on the temperature of the material. gmat->SetName(medName); gmat->SetTitle(matName); // create medium TGeoMedium* lastmed = (TGeoMedium*)gGeoManager->GetListOfMedia()->Last(); Int_t numed = (lastmed ? lastmed->GetId()+1 : 0); // static counter variable used to number media gmed = new TGeoMedium( medName, numed, gmat ); numed+=1; return gmed; }
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(); }