#include <TClonesArray.h>
#include <TGeoGlobalMagField.h>
#include <TGeoManager.h>
#include <TGeoMatrix.h>
#include <TGeoPhysicalNode.h>
#include <TGeoVolume.h>
#include <TGeoTube.h>
#include <TGeoXtru.h>
#include <TLorentzVector.h>
#include <TString.h>
#include <TVirtualMC.h>
#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)
{
}
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)
{
fLayerName = new TString[fNLayers];
for (Int_t j=0; j<fNLayers; j++)
fLayerName[j].Form("%s%d",AliITSUGeomTGeo::GetITSSensorPattern(),j);
fLayTurbo = new Bool_t[fNLayers];
fLayPhi0 = new Double_t[fNLayers];
fLayRadii = new Double_t[fNLayers];
fLayZLength = new Double_t[fNLayers];
fStavPerLay = new Int_t[fNLayers];
fModPerStav = new Int_t[fNLayers];
fStaThick = new Double_t[fNLayers];
fStaWidth = new Double_t[fNLayers];
fStaTilt = new Double_t[fNLayers];
fDetThick = new Double_t[fNLayers];
fChipTypeID = new UInt_t[fNLayers];
fBuildLevel = new Int_t[fNLayers];
fUpGeom = new AliITSUv0Layer*[fNLayers];
if (fNLayers > 0) {
for (Int_t j=0; j<fNLayers; j++) {
fLayPhi0[j] = 0;
fLayRadii[j] = 0.;
fLayZLength[j] = 0.;
fStavPerLay[j] = 0;
fModPerStav[j] = 0;
fStaWidth[j] = 0.;
fDetThick[j] = 0.;
fChipTypeID[j] = 0;
fBuildLevel[j] = 0;
fUpGeom[j] = 0;
}
}
}
AliITSUv0::~AliITSUv0() {
delete [] fLayTurbo;
delete [] fLayPhi0;
delete [] fLayRadii;
delete [] fLayZLength;
delete [] fStavPerLay;
delete [] fModPerStav;
delete [] fStaThick;
delete [] fStaWidth;
delete [] fStaTilt;
delete [] fDetThick;
delete [] fChipTypeID;
delete [] fBuildLevel;
delete [] fUpGeom;
delete [] fWrapRMin;
delete [] fWrapRMax;
delete [] fWrapZSpan;
delete [] fLay2WrapV;
}
void AliITSUv0::AddAlignableVolumes() const{
AliInfo("Add ITS alignable volumes");
if (!gGeoManager) { AliFatal("TGeoManager doesn't exist !"); return; }
TString pth;
pth = Form("ALIC_1/%s_2",AliITSUGeomTGeo::GetITSVolPattern());
if( !gGeoManager->SetAlignableEntry(AliITSUGeomTGeo::ComposeSymNameITS(),pth.Data()) )
AliFatal(Form("Unable to set alignable entry ! %s :: %s","ITS",pth.Data()));
int chipNum = 0;
for (int lr=0; lr<fNLayers; lr++) {
TString wrpV = fLay2WrapV[lr]!=-1 ? Form("%s%d_1/",AliITSUGeomTGeo::GetITSWrapVolPattern(),fLay2WrapV[lr]) : "";
pth = Form("ALIC_1/%s_2/%s%s%d_1",AliITSUGeomTGeo::GetITSVolPattern(),wrpV.Data(),AliITSUGeomTGeo::GetITSLayerPattern(),lr);
if( !gGeoManager->SetAlignableEntry(AliITSUGeomTGeo::ComposeSymNameLayer(lr),pth.Data()) ) {
AliFatal(Form("Unable to set alignable entry ! %s :: %s",AliITSUGeomTGeo::ComposeSymNameLayer(lr),pth.Data()));
}
for (int ld=0; ld<fStavPerLay[lr]; ld++) {
TString pthL = Form("%s/%s%d_%d",pth.Data(),AliITSUGeomTGeo::GetITSStavePattern(),lr,ld);
if ( !gGeoManager->SetAlignableEntry(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; md<fModPerStav[lr]; md++) {
TString pthM = Form("%s/%s%d_%d",pthL.Data(),AliITSUGeomTGeo::GetITSChipPattern(),lr,md);
int modUID = AliITSUGeomTGeo::ChipVolUID( chipNum++ );
if ( !gGeoManager->SetAlignableEntry(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)
{
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)
{
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() {
TGeoManager *geoManager = gGeoManager;
TGeoVolume *vALIC = geoManager->GetVolume("ALIC");
new TGeoVolumeAssembly(AliITSUGeomTGeo::GetITSVolPattern());
TGeoVolume *vITSV = geoManager->GetVolume(AliITSUGeomTGeo::GetITSVolPattern());
vITSV->SetUniqueID(AliITSUGeomTGeo::GetUIDShift());
vALIC->AddNode(vITSV, 2, 0);
const Int_t kLength=100;
Char_t vstrng[kLength] = "xxxRS";
vITSV->SetTitle(vstrng);
if (fNLayers <= 0) AliFatal(Form("Wrong number of layers (%d)",fNLayers));
for (Int_t j=0; j<fNLayers; j++) {
if (fLayRadii[j] <= 0) AliFatal(Form("Wrong layer radius for layer %d (%f)",j,fLayRadii[j]));
if (fLayZLength[j] <= 0) AliFatal(Form("Wrong layer length for layer %d (%f)",j,fLayZLength[j]));
if (fStavPerLay[j] <= 0) AliFatal(Form("Wrong number of staves for layer %d (%d)",j,fStavPerLay[j]));
if (fModPerStav[j] <= 0) AliFatal(Form("Wrong number of chips for layer %d (%d)",j,fModPerStav[j]));
if (fStaThick[j] < 0) AliFatal(Form("Wrong stave thickness for layer %d (%f)",j,fStaThick[j]));
if (fLayTurbo[j] && fStaWidth[j] <= 0) AliFatal(Form("Wrong stave width for layer %d (%f)",j,fStaWidth[j]));
if (fDetThick[j] < 0) AliFatal(Form("Wrong chip thickness for layer %d (%f)",j,fDetThick[j]));
if (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 (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));
}
TGeoVolume **wrapVols = 0;
if (fNWrapVol) {
wrapVols = new TGeoVolume*[fNWrapVol];
for (int id=0;id<fNWrapVol;id++) {
wrapVols[id] = CreateWrapperVolume(id);
vITSV->AddNode(wrapVols[id], 1, 0);
}
}
fLay2WrapV = new Int_t[fNLayers];
for (Int_t j=0; j<fNLayers; j++) {
TGeoVolume* dest = vITSV;
if (fLayTurbo[j]) {
fUpGeom[j] = new AliITSUv0Layer(j,kTRUE,kFALSE);
fUpGeom[j]->SetStaveWidth(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;iw<fNWrapVol;iw++) {
if (fLayRadii[j]>fWrapRMin[iw] && fLayRadii[j]<fWrapRMax[iw]) {
AliInfo(Form("Will embed layer %d in wrapper volume %d",j,iw));
if (fLayZLength[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;
}
void AliITSUv0::CreateMaterials() {
Int_t ifield = ((AliMagF*)TGeoGlobalMagField::Instance()->GetField())->Integ();
Float_t fieldm = ((AliMagF*)TGeoGlobalMagField::Instance()->GetField())->Max();
Float_t tmaxfd = 0.1;
Float_t stemax = 1.0;
Float_t deemax = 0.1;
Float_t epsil = 1.0E-4;
Float_t stmin = 0.0;
Float_t tmaxfdSi = 0.1;
Float_t stemaxSi = 0.0075;
Float_t deemaxSi = 0.1;
Float_t epsilSi = 1.0E-4;
Float_t stminSi = 0.0;
Float_t tmaxfdAir = 0.1;
Float_t stemaxAir = .10000E+01;
Float_t deemaxAir = 0.1;
Float_t epsilAir = 1.0E-4;
Float_t stminAir = 0.0;
Float_t aAir[4]={12.0107,14.0067,15.9994,39.948};
Float_t zAir[4]={6.,7.,8.,18.};
Float_t wAir[4]={0.000124,0.755267,0.231781,0.012827};
Float_t dAir = 1.20479E-3;
Float_t aWater[2]={1.00794,15.9994};
Float_t zWater[2]={1.,8.};
Float_t wWater[2]={0.111894,0.888106};
Float_t dWater = 1.0;
Float_t aKapton[4]={1.00794,12.0107, 14.010,15.9994};
Float_t zKapton[4]={1.,6.,7.,8.};
Float_t wKapton[4]={0.026362,0.69113,0.07327,0.209235};
Float_t dKapton = 1.42;
AliMixture(1,"AIR$",aAir,zAir,dAir,4,wAir);
AliMedium(1, "AIR$",1,0,ifield,fieldm,tmaxfdAir,stemaxAir,deemaxAir,epsilAir,stminAir);
AliMixture(2,"WATER$",aWater,zWater,dWater,2,wWater);
AliMedium(2, "WATER$",2,0,ifield,fieldm,tmaxfd,stemax,deemax,epsil,stmin);
AliMaterial(3,"SI$",0.28086E+02,0.14000E+02,0.23300E+01,0.93600E+01,0.99900E+03);
AliMedium(3, "SI$",3,0,ifield,fieldm,tmaxfdSi,stemaxSi,deemaxSi,epsilSi,stminSi);
AliMaterial(4,"BERILLIUM$",9.01, 4., 1.848, 35.3, 36.7);
AliMedium(4, "BERILLIUM$",4,0,ifield,fieldm,tmaxfd,stemax,deemax,epsil,stmin);
AliMaterial(5,"COPPER$",0.63546E+02,0.29000E+02,0.89600E+01,0.14300E+01,0.99900E+03);
AliMedium(5, "COPPER$",5,0,ifield,fieldm,tmaxfd,stemax,deemax,epsil,stmin);
AliMaterial(6,"CARBON$",12.0107,6,2.210/1.3,999,999);
AliMedium(6, "CARBON$",6,0,ifield,fieldm,tmaxfdSi,stemaxSi,deemaxSi,epsilSi,stminSi);
AliMixture(7,"KAPTON(POLYCH2)$", aKapton, zKapton, dKapton, 4, wKapton);
AliMedium(7, "KAPTON(POLYCH2)$",7,0,ifield,fieldm,tmaxfd,stemax,deemax,epsil,stmin);
AliMaterial(7,"GLUE$",12.011,6,1.93/2.015,999,999);
AliMedium(7, "GLUE$",7,0,ifield,fieldm,tmaxfd,stemax,deemax,epsil,stmin);
AliMaterial(8,"K13D2U2k$",12.0107,6,1.643,999,999);
AliMedium(8, "K13D2U2k$",8,0,ifield,fieldm,tmaxfdSi,stemaxSi,deemaxSi,epsilSi,stminSi);
AliMaterial(9,"M60J3K$",12.0107,6,2.21,999,999);
AliMedium(9, "M60J3K$",9,0,ifield,fieldm,tmaxfdSi,stemaxSi,deemaxSi,epsilSi,stminSi);
AliMaterial(10,"M55J6K$",12.0107,6,1.63,999,999);
AliMedium(10, "M55J6K$",10,0,ifield,fieldm,tmaxfdSi,stemaxSi,deemaxSi,epsilSi,stminSi);
AliMaterial(11,"T300$",12.0107,6,1.725,999,999);
AliMedium(11, "T300$",11,0,ifield,fieldm,tmaxfdSi,stemaxSi,deemaxSi,epsilSi,stminSi);
AliMaterial(12,"FGS003$",12.0107,6,1.6,999,999);
AliMedium(12, "FGS003$",12,0,ifield,fieldm,tmaxfdSi,stemaxSi,deemaxSi,epsilSi,stminSi);
AliMaterial(13,"CarbonFleece$",12.0107,6,0.4,999,999);
AliMedium(13, "CarbonFleece$",13,0,ifield,fieldm,tmaxfdSi,stemaxSi,deemaxSi,epsilSi,stminSi);
Float_t aFCm[5]={12.0107,1.00794,14.0067,15.9994,26.981538};
Float_t zFCm[5]={6.,1.,7.,8.,13.};
Float_t wFCm[5]={0.520088819984,0.01983871336,0.0551367996,0.157399667056, 0.247536};
Float_t dFCm = 2.595;
AliMixture(14,"FLEXCABLE$",aFCm,zFCm,dFCm,5,wFCm);
AliMedium(14, "FLEXCABLE$",14,0,ifield,fieldm,tmaxfd,stemax,deemax,epsil,stmin);
}
void AliITSUv0::DefineLayer(Int_t nlay, double phi0, Double_t r,
Double_t zlen, Int_t nstav,
Int_t nmod, Double_t lthick,
Double_t dthick, UInt_t dettypeID)
{
if (nlay >= 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)
{
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
{
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)
{
if (fWrapRMin[id]<0 || fWrapRMax[id]<0 || fWrapZSpan[id]<0) AliFatal(Form("Wrapper volume %d was requested but not defined",id));
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()
{
UpdateInternalGeometry();
AliITSU::Init();
}
Bool_t AliITSUv0::IsLayerTurbo(Int_t nlay)
{
if ( nlay < 0 || nlay > fNLayers ) {
AliError(Form("Wrong layer number %d",nlay));
return kFALSE;
}
else return fUpGeom[nlay]->IsTurbo();
}
void AliITSUv0::SetDefaults()
{
}
void AliITSUv0::StepManager()
{
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 ((lay<fNLayers) && (notSens = (id!=fIdSens[lay]))) ++lay;
if (notSens) return;
if(TVirtualMC::GetMC()->IsTrackExiting()) {
AddTrackReference(gAlice->GetMCApp()->GetCurrentTrackNumber(), AliTrackReference::kITS);
}
static TLorentzVector position, momentum;
static AliITSUHit hit;
TClonesArray &lhits = *(Hits());
Int_t cpn0, cpn1, mod, status = 0;
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;
if (lay < 0 || lay >= fNLayers) {
AliError(Form("Invalid value: lay=%d. Not an ITS sensitive volume",lay));
return;
} else {
copy = 1;
TVirtualMC::GetMC()->CurrentVolOffID(1,cpn1);
TVirtualMC::GetMC()->CurrentVolOffID(2,cpn0);
}
mod = fGeomTGeo->GetChipIndex(lay,cpn0,cpn1);
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;
}
new(lhits[fNhits++]) AliITSUHit(hit);
hit.SetStartPosition(position);
hit.SetStartTime(TVirtualMC::GetMC()->TrackTime());
hit.SetStartStatus(status);
return;
}
void AliITSUv0::SetLayerChipTypeID(Int_t lr, UInt_t id)
{
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)
{
if (!fChipTypeID || fNLayers<=lr) AliFatal(Form("Number of layers %d, %d is manipulated",fNLayers,lr));
return fChipTypeID[lr];
}