/************************************************************************** * Copyright(c) 2007-2009, ALICE Experiment at CERN, All rights reserved. * * * * Author: The ALICE Off-line Project. * * Contributors are mentioned in the code where appropriate. * * * * Permission to use, copy, modify and distribute this software and its * * documentation strictly for non-commercial purposes is hereby granted * * without fee, provided that the above copyright notice appears in all * * copies and that both the copyright notice and this permission notice * * appear in the supporting documentation. The authors make no claims * * about the suitability of this software for any purpose. It is * * provided "as is" without express or implied warranty. * **************************************************************************/ /* $Id: AliITSUv0.cxx */ //======================================================================== // // Geometry for the Upgrade of the Inner Tracking System // // Mario Sitta (sitta@to.infn.it) // Chinorat Kobdaj (kobdaj@g.sut.ac.th) // //======================================================================== // $Log: AliITSUv0.cxx,v $ #include #include #include #include #include #include #include #include #include #include #include #include "AliITSU.h" #include "AliITSUHit.h" #include "AliLog.h" #include "AliMC.h" #include "AliMagF.h" #include "AliRun.h" #include "AliTrackReference.h" #include "AliITSv11Geometry.h" #include "AliITSUv0Layer.h" #include "AliITSUv0.h" #include "AliITSUGeomTGeo.h" #include "AliGeomManager.h" using namespace TMath; ClassImp(AliITSUv0) //______________________________________________________________________ AliITSUv0::AliITSUv0() : fNWrapVol(0) ,fWrapRMin(0) ,fWrapRMax(0) ,fWrapZSpan(0) ,fLay2WrapV(0) ,fLayTurbo(0) ,fLayPhi0(0) ,fLayRadii(0) ,fLayZLength(0) ,fStavPerLay(0) ,fModPerStav(0) ,fStaThick(0) ,fStaWidth(0) ,fStaTilt(0) ,fDetThick(0) ,fChipTypeID(0) ,fBuildLevel(0) ,fUpGeom(0) ,fStaveModel(kModel0) { // Standard default constructor // Inputs: // none. // Outputs: // none. // Return: // none. } //______________________________________________________________________ AliITSUv0::AliITSUv0(const char *title, Int_t nlay) :AliITSU(title,nlay) ,fNWrapVol(0) ,fWrapRMin(0) ,fWrapRMax(0) ,fWrapZSpan(0) ,fLay2WrapV(0) ,fLayTurbo(0) ,fLayPhi0(0) ,fLayRadii(0) ,fLayZLength(0) ,fStavPerLay(0) ,fModPerStav(0) ,fStaThick(0) ,fStaWidth(0) ,fStaTilt(0) ,fDetThick(0) ,fChipTypeID(0) ,fBuildLevel(0) ,fUpGeom(0) ,fStaveModel(kModel0) { // Standard constructor for the Upgrade geometry. // Inputs: // const char * name Ignored, set to "ITS" // const char * title Arbitrary title // const Int_t nlay Number of layers // fLayerName = new TString[fNLayers]; // for (Int_t j=0; j 0) { // if not, we'll Fatal-ize in CreateGeometry for (Int_t j=0; jSetAlignableEntry(AliITSUGeomTGeo::ComposeSymNameITS(),pth.Data()) ) AliFatal(Form("Unable to set alignable entry ! %s :: %s","ITS",pth.Data())); // int chipNum = 0; // for (int lr=0; lrSetAlignableEntry(AliITSUGeomTGeo::ComposeSymNameLayer(lr),pth.Data()) ) { AliFatal(Form("Unable to set alignable entry ! %s :: %s",AliITSUGeomTGeo::ComposeSymNameLayer(lr),pth.Data())); } // for (int ld=0; ldSetAlignableEntry(AliITSUGeomTGeo::ComposeSymNameStave(lr,ld),pthL.Data()) ) { AliFatal(Form("Unable to set alignable entry ! %s :: %s",AliITSUGeomTGeo::ComposeSymNameStave(lr,ld),pthL.Data())); } // for (int md=0; mdSetAlignableEntry(AliITSUGeomTGeo::ComposeSymNameChip(lr,ld,-1,-1,md),pthM.Data(),modUID) ) { AliFatal(Form("Unable to set alignable entry ! %s :: %s",AliITSUGeomTGeo::ComposeSymNameChip(lr,ld,-1,-1,md),pthM.Data())); } // } } } // } //______________________________________________________________________ void AliITSUv0::SetNWrapVolumes(Int_t n) { // book arrays for wrapper volumes if (fNWrapVol) AliFatal(Form("%d wrapper volumes already defined",fNWrapVol)); if (n<1) return; fNWrapVol = n; fWrapRMin = new Double_t[fNWrapVol]; fWrapRMax = new Double_t[fNWrapVol]; fWrapZSpan= new Double_t[fNWrapVol]; for (int i=fNWrapVol;i--;) fWrapRMin[i]=fWrapRMax[i]=fWrapZSpan[i]=-1; // } //______________________________________________________________________ void AliITSUv0::DefineWrapVolume(Int_t id, Double_t rmin,Double_t rmax, Double_t zspan) { // set parameters of id-th wrapper volume if (id>=fNWrapVol||id<0) AliFatal(Form("id=%d of wrapper volume is not in 0-%d range",id,fNWrapVol-1)); fWrapRMin[id] = rmin; fWrapRMax[id] = rmax; fWrapZSpan[id] = zspan; } //______________________________________________________________________ void AliITSUv0::CreateGeometry() { // Create the geometry and insert it in the mother volume ITSV TGeoManager *geoManager = gGeoManager; TGeoVolume *vALIC = geoManager->GetVolume("ALIC"); new TGeoVolumeAssembly(AliITSUGeomTGeo::GetITSVolPattern()); TGeoVolume *vITSV = geoManager->GetVolume(AliITSUGeomTGeo::GetITSVolPattern()); vITSV->SetUniqueID(AliITSUGeomTGeo::GetUIDShift()); // store modID -> midUUID bitshift vALIC->AddNode(vITSV, 2, 0); // Copy number is 2 to cheat AliGeoManager::CheckSymNamesLUT // const Int_t kLength=100; Char_t vstrng[kLength] = "xxxRS"; //? vITSV->SetTitle(vstrng); // // Check that we have all needed parameters if (fNLayers <= 0) AliFatal(Form("Wrong number of layers (%d)",fNLayers)); // for (Int_t j=0; j 0) { if (fLayRadii[j]<=fLayRadii[j-1]) AliFatal(Form("Layer %d radius (%f) is smaller than layer %d radius (%f)", j,fLayRadii[j],j-1,fLayRadii[j-1])); } // if (j > 0) if (fStaThick[j] == 0) AliInfo(Form("Stave thickness for layer %d not set, using default",j)); if (fDetThick[j] == 0) AliInfo(Form("Chip thickness for layer %d not set, using default",j)); } // for (Int_t j=0; jAddNode(wrapVols[id], 1, 0); } } // fLay2WrapV = new Int_t[fNLayers]; // Now create the actual geometry for (Int_t j=0; jSetStaveWidth(fStaWidth[j]); fUpGeom[j]->SetStaveTilt(fStaTilt[j]); } else fUpGeom[j] = new AliITSUv0Layer(j,kFALSE); // fUpGeom[j]->SetPhi0(fLayPhi0[j]); fUpGeom[j]->SetRadius(fLayRadii[j]); fUpGeom[j]->SetZLength(fLayZLength[j]); fUpGeom[j]->SetNStaves(fStavPerLay[j]); fUpGeom[j]->SetNChips(fModPerStav[j]); fUpGeom[j]->SetChipType(fChipTypeID[j]); fUpGeom[j]->SetBuildLevel(fBuildLevel[j]); fUpGeom[j]->SetStaveModel(fStaveModel); AliDebug(1,Form("fBuildLevel: %d\n",fBuildLevel[j])); // if (fStaThick[j] != 0) fUpGeom[j]->SetStaveThick(fStaThick[j]); if (fDetThick[j] != 0) fUpGeom[j]->SetSensorThick(fDetThick[j]); // for (int iw=0;iwfWrapRMin[iw] && fLayRadii[j]=fWrapZSpan[iw]) AliFatal(Form("ZSpan %.3f of wrapper volume %d is less than ZSpan %.3f of layer %d", fWrapZSpan[iw],iw,fLayZLength[j],j)); dest = wrapVols[iw]; fLay2WrapV[j] = iw; break; } } fUpGeom[j]->CreateLayer(dest); } delete[] wrapVols; // delete pointer only, not the volumes // } //______________________________________________________________________ void AliITSUv0::CreateMaterials() { // Create ITS materials // This function defines the default materials used in the Geant // Monte Carlo simulations for the geometries AliITSv1, AliITSv3, // AliITSv11Hybrid. // In general it is automatically replaced by // the CreateMaterials routine defined in AliITSv?. Should the function // CreateMaterials not exist for the geometry version you are using this // one is used. See the definition found in AliITSv5 or the other routine // for a complete definition. // Inputs: // none. // Outputs: // none. // Return: // none. Int_t ifield = ((AliMagF*)TGeoGlobalMagField::Instance()->GetField())->Integ(); Float_t fieldm = ((AliMagF*)TGeoGlobalMagField::Instance()->GetField())->Max(); Float_t tmaxfd = 0.1; // 1.0; // Degree Float_t stemax = 1.0; // cm Float_t deemax = 0.1; // 30.0; // Fraction of particle's energy 0= fNLayers || nlay < 0) { AliError(Form("Wrong layer number (%d)",nlay)); return; } fLayTurbo[nlay] = kFALSE; fLayPhi0[nlay] = phi0; fLayRadii[nlay] = r; fLayZLength[nlay] = zlen; fStavPerLay[nlay] = nstav; fModPerStav[nlay] = nmod; fStaThick[nlay] = lthick; fDetThick[nlay] = dthick; fChipTypeID[nlay] = dettypeID; } //______________________________________________________________________ void AliITSUv0::DefineLayerTurbo(Int_t nlay, Double_t phi0, Double_t r, Double_t zlen, Int_t nstav, Int_t nmod, Double_t width, Double_t tilt, Double_t lthick,Double_t dthick, UInt_t dettypeID, Int_t buildLevel) { // Sets the layer parameters for a "turbo" layer // (i.e. a layer whose staves overlap in phi) // Inputs: // nlay layer number // phi0 phi of 1st stave // r layer radius // zlen layer length // nstav number of staves // nmod number of chips per stave // width stave width // tilt layer tilt angle (degrees) // lthick stave thickness (if omitted, defaults to 0) // dthick detector thickness (if omitted, defaults to 0) // dettypeID ?? // buildLevel (if 0, all geometry is build, used for material budget studies) // Outputs: // none. // Return: // none. if (nlay >= fNLayers || nlay < 0) { AliError(Form("Wrong layer number (%d)",nlay)); return; } fLayTurbo[nlay] = kTRUE; fLayPhi0[nlay] = phi0; fLayRadii[nlay] = r; fLayZLength[nlay] = zlen; fStavPerLay[nlay] = nstav; fModPerStav[nlay] = nmod; fStaThick[nlay] = lthick; fStaWidth[nlay] = width; fStaTilt[nlay] = tilt; fDetThick[nlay] = dthick; fChipTypeID[nlay] = dettypeID; fBuildLevel[nlay] = buildLevel; } //______________________________________________________________________ void AliITSUv0::GetLayerParameters(Int_t nlay, Double_t &phi0, Double_t &r, Double_t &zlen, Int_t &nstav, Int_t &nmod, Double_t &width, Double_t &tilt, Double_t <hick, Double_t &dthick, UInt_t &dettype) const { // Gets the layer parameters // Inputs: // nlay layer number // Outputs: // phi0 phi of 1st stave // r layer radius // zlen layer length // nstav number of staves // nmod number of chips per stave // width stave width // tilt stave tilt angle // lthick stave thickness // dthick detector thickness // dettype detector type // Return: // none. if (nlay >= fNLayers || nlay < 0) { AliError(Form("Wrong layer number (%d)",nlay)); return; } phi0 = fLayPhi0[nlay]; r = fLayRadii[nlay]; zlen = fLayZLength[nlay]; nstav = fStavPerLay[nlay]; nmod = fModPerStav[nlay]; width = fStaWidth[nlay]; tilt = fStaTilt[nlay]; lthick = fStaThick[nlay]; dthick = fDetThick[nlay]; dettype= fChipTypeID[nlay]; } //______________________________________________________________________ TGeoVolume* AliITSUv0::CreateWrapperVolume(Int_t id) { // Creates an air-filled wrapper cylindrical volume // Inputs: // volume id // Outputs: // the wrapper volume if (fWrapRMin[id]<0 || fWrapRMax[id]<0 || fWrapZSpan[id]<0) AliFatal(Form("Wrapper volume %d was requested but not defined",id)); // Now create the actual shape and volume // TGeoTube *tube = new TGeoTube(fWrapRMin[id], fWrapRMax[id], fWrapZSpan[id]/2.); TGeoMedium *medAir = gGeoManager->GetMedium("ITS_AIR$"); char volnam[30]; snprintf(volnam, 29, "%s%d", AliITSUGeomTGeo::GetITSWrapVolPattern(),id); TGeoVolume *wrapper = new TGeoVolume(volnam, tube, medAir); return wrapper; } //______________________________________________________________________ void AliITSUv0::Init() { // Initialise the ITS after it has been created. UpdateInternalGeometry(); AliITSU::Init(); // } //______________________________________________________________________ Bool_t AliITSUv0::IsLayerTurbo(Int_t nlay) { // Returns true if the layer is a "turbo" layer if ( nlay < 0 || nlay > fNLayers ) { AliError(Form("Wrong layer number %d",nlay)); return kFALSE; } else return fUpGeom[nlay]->IsTurbo(); } //______________________________________________________________________ void AliITSUv0::SetDefaults() { // sets the default segmentation, response, digit and raw cluster classes } //______________________________________________________________________ void AliITSUv0::StepManager() { // Called for every step in the ITS, then calles the AliITSUHit class // creator with the information to be recoreded about that hit. // The value of the macro ALIITSPRINTGEOM if set to 1 will allow the // printing of information to a file which can be used to create a .det // file read in by the routine CreateGeometry(). If set to 0 or any other // value except 1, the default behavior, then no such file is created nor // it the extra variables and the like used in the printing allocated. // Inputs: // none. // Outputs: // none. // Return: // none. if(!(this->IsActive())) return; if(!(TVirtualMC::GetMC()->TrackCharge())) return; // Int_t copy, lay = 0; Int_t id = TVirtualMC::GetMC()->CurrentVolID(copy); Bool_t notSens = kFALSE; while ((layIsTrackExiting()) { AddTrackReference(gAlice->GetMCApp()->GetCurrentTrackNumber(), AliTrackReference::kITS); } // if Outer ITS mother Volume static TLorentzVector position, momentum; // Saves on calls to construtors static AliITSUHit hit;// Saves on calls to constructors TClonesArray &lhits = *(Hits()); Int_t cpn0, cpn1, mod, status = 0; // // Track status if(TVirtualMC::GetMC()->IsTrackInside()) status += 1; if(TVirtualMC::GetMC()->IsTrackEntering()) status += 2; if(TVirtualMC::GetMC()->IsTrackExiting()) status += 4; if(TVirtualMC::GetMC()->IsTrackOut()) status += 8; if(TVirtualMC::GetMC()->IsTrackDisappeared()) status += 16; if(TVirtualMC::GetMC()->IsTrackStop()) status += 32; if(TVirtualMC::GetMC()->IsTrackAlive()) status += 64; // // retrieve the indices with the volume path // if (lay < 0 || lay >= fNLayers) { AliError(Form("Invalid value: lay=%d. Not an ITS sensitive volume",lay)); return; // not an ITS sensitive volume. } else { copy = 1; TVirtualMC::GetMC()->CurrentVolOffID(1,cpn1); TVirtualMC::GetMC()->CurrentVolOffID(2,cpn0); } // mod = fGeomTGeo->GetChipIndex(lay,cpn0,cpn1); //RS2DEL fInitGeom.DecodeDetector(mod,lay+1,cpn0,cpn1,copy); // // Fill hit structure. // hit.SetChip(mod); hit.SetTrack(gAlice->GetMCApp()->GetCurrentTrackNumber()); TVirtualMC::GetMC()->TrackPosition(position); TVirtualMC::GetMC()->TrackMomentum(momentum); hit.SetPosition(position); hit.SetTime(TVirtualMC::GetMC()->TrackTime()); hit.SetMomentum(momentum); hit.SetStatus(status); hit.SetEdep(TVirtualMC::GetMC()->Edep()); hit.SetShunt(GetIshunt()); if(TVirtualMC::GetMC()->IsTrackEntering()){ hit.SetStartPosition(position); hit.SetStartTime(TVirtualMC::GetMC()->TrackTime()); hit.SetStartStatus(status); return; // don't save entering hit. } // end if IsEntering // Fill hit structure with this new hit. //Info("StepManager","Calling Copy Constructor"); new(lhits[fNhits++]) AliITSUHit(hit); // Use Copy Construtor. // Save old position... for next hit. hit.SetStartPosition(position); hit.SetStartTime(TVirtualMC::GetMC()->TrackTime()); hit.SetStartStatus(status); return; } //______________________________________________________________________ void AliITSUv0::SetLayerChipTypeID(Int_t lr, UInt_t id) { // set det type if (!fChipTypeID || fNLayers<=lr) AliFatal(Form("Number of layers %d, %d is manipulated",fNLayers,lr)); fChipTypeID[lr] = id; } //______________________________________________________________________ Int_t AliITSUv0::GetLayerChipTypeID(Int_t lr) { // set det type if (!fChipTypeID || fNLayers<=lr) AliFatal(Form("Number of layers %d, %d is manipulated",fNLayers,lr)); return fChipTypeID[lr]; }