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 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 KVIonRangeTable::SetTemperatureAndPressure(const Char_t*material, Double_t temperature, Double_t pressure) { // Set temperature (in degrees celsius) and pressure (in torr) for a given // material. This has no effect except for gaseous materials, for which T & P // determine the density (in g/cm**3). KVIonRangeTableMaterial* M = GetMaterial(material); if (M) M->SetTemperatureAndPressure(temperature, pressure); }
Double_t KVIonRangeTable::GetZ(const Char_t* material) { // Return atomic number of a material in the range table. // "material" can be either the type or the name of the material. // Prints a warning and returns 0 if material is unknown. KVIonRangeTableMaterial* M = GetMaterial(material); if (!M) { Warning("GetZ", "Material %s is unknown. Returned Z = 0.", material); return 0.0; } return M->GetZ(); }
TObjArray* KVRangeYanez::GetListOfMaterials() { // Create and fill a list of all materials for which range tables exist. // Each entry is a TNamed with the name and type (title) of the material. // User's responsibility to delete list after use (it owns its objects). TObjArray* list = new TObjArray(fMaterials->GetEntries()); list->SetOwner(kTRUE); TIter next(fMaterials); KVIonRangeTableMaterial* mat; while ((mat = (KVIonRangeTableMaterial*)next())) { list->Add(new TNamed(mat->GetName(), mat->GetType())); } return list; }
void KVRangeYanez::AddElementalMaterial(Int_t z, Int_t a) { // Adds a material composed of a single isotope of a chemical element. // If the isotope (a) is not specified, we create a material containing the naturally // occuring isotopes of the given element, weighted according to their abundance. // If the mass is given, the material symbol will be "AX" where X is the symbol for the element // e.g. "48Ca", "124Sn", etc. // and the material name will be "Xxx-A" where Xxx is the name of the element // e.g. "Calcium-48", "Tin-124", etc. // Otherwise, we just use the element symbol and name for naturally-occurring // mixtures of atomic elements ("Ca", "Calcium", etc.). KVIonRangeTableMaterial* mat; if (!a) { mat = MakeNaturallyOccuringElementMixture(z); } else { if (!gNDTManager) { Error("AddElementalMaterial", "Nuclear data tables have not been initialised"); return; } KVElementDensity* ed = (KVElementDensity*)gNDTManager->GetData(z, a, "ElementDensity"); if (!ed) { Error("AddElementalMaterial", "No element found in ElementDensity NDT-table with Z=%d", z); return; } TString state = "solid"; if (ed->IsGas()) state = "gas"; mat = new KVRangeYanezMaterial(this, Form("%s-%d", ed->GetElementName(), a), Form("%d%s", a, ed->GetElementSymbol()), state, ed->GetValue(), z, a); mat->Initialize(); } CheckMaterialsList(); fMaterials->Add(mat); mat->ls(); }
KVIonRangeTableMaterial::KVIonRangeTableMaterial(const KVIonRangeTableMaterial& obj) : KVBase(), fTable(0), fState("unknown"), fComposition(0), fCompound(kFALSE), fMixture(kFALSE), fDens(0.), fZmat(0), fAmat(0), fMoleWt(0), fDeltaE(0), fEres(0), fRange(0), fStopping(0) { // Copy constructor // This ctor is used to make a copy of an existing object (for example // when a method returns an object), and it is always a good idea to // implement it. // If your class allocates memory in its constructor(s) then it is ESSENTIAL :-) obj.Copy(*this); }
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 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()); } }