1 /**************************************************************************
2 * Copyright(c) 2007-2009, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
17 /* $Id: AliITSUv11.cxx */
20 //========================================================================
22 // Geometry for the Upgrade of the Inner Tracking System
24 // Mario Sitta (sitta@to.infn.it)
26 //========================================================================
30 // $Log: AliITSUv11.cxx,v $
32 #include <TClonesArray.h>
33 #include <TGeoGlobalMagField.h>
34 #include <TGeoManager.h>
35 #include <TGeoMatrix.h>
36 #include <TGeoPhysicalNode.h>
37 #include <TGeoVolume.h>
39 #include <TLorentzVector.h>
41 #include <TVirtualMC.h>
44 #include "AliITSUHit.h"
49 #include "AliTrackReference.h"
50 #include "AliITSv11Geometry.h"
51 #include "AliITSUv11Layer.h"
52 #include "AliITSUv11.h"
53 #include "AliITSUGeomTGeo.h"
54 #include "AliGeomManager.h"
59 //______________________________________________________________________
60 AliITSUv11::AliITSUv11()
74 // Standard default constructor
83 //______________________________________________________________________
84 AliITSUv11::AliITSUv11(const char *title,const Int_t nlay)
99 // Standard constructor for the Upgrade geometry.
101 // const char * name Ignored, set to "ITS"
102 // const char * title Arbitrary title
103 // const Int_t nlay Number of layers
105 fLayerName = new TString[fNLayers];
107 for (Int_t j=0; j<fNLayers; j++) fLayerName[j].Form("%s%d",AliITSUGeomTGeo::GetITSSensorPattern(),j); // See AliITSUv11Layer
109 fLayTurbo = new Bool_t[fNLayers];
110 fLayPhi0 = new Double_t[fNLayers];
111 fLayRadii = new Double_t[fNLayers];
112 fLayZLength = new Double_t[fNLayers];
113 fLaddPerLay = new Int_t[fNLayers];
114 fModPerLadd = new Int_t[fNLayers];
115 fLadThick = new Double_t[fNLayers];
116 fLadWidth = new Double_t[fNLayers];
117 fLadTilt = new Double_t[fNLayers];
118 fDetThick = new Double_t[fNLayers];
119 fDetTypeID = new UInt_t[fNLayers];
121 fUpGeom = new AliITSUv11Layer*[fNLayers];
123 if (fNLayers > 0) { // if not, we'll Fatal-ize in CreateGeometry
124 for (Int_t j=0; j<fNLayers; j++) {
138 //______________________________________________________________________
139 AliITSUv11::~AliITSUv11() {
140 // Standard destructor
150 delete [] fLayZLength;
151 delete [] fLaddPerLay;
152 delete [] fModPerLadd;
157 delete [] fDetTypeID;
162 //______________________________________________________________________
163 void AliITSUv11::SetT2Lmatrix(Int_t uid, Double_t yShift,
164 Bool_t yFlip, Bool_t yRot180) const {
167 // Creates the TGeo Local to Tracking transformation matrix
168 // and sends it to the corresponding TGeoPNEntry
170 // This function is used in AddAlignableVolumes()
172 TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(uid);
173 TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
174 Double_t *gtrans = globMatrix->GetTranslation(), rotMatrix[9];
175 memcpy(&rotMatrix[0], globMatrix->GetRotationMatrix(), 9*sizeof(Double_t));
176 Double_t al = TMath::ATan2(rotMatrix[1], yRot180 ? -rotMatrix[0] : rotMatrix[0]);
177 Double_t xShift = gtrans[0]*TMath::Cos(al)+gtrans[1]*TMath::Sin(al);
178 Double_t zShift = -gtrans[2];
179 TGeoHMatrix *matLtoT = new TGeoHMatrix;
180 matLtoT->SetDx( xShift ); // translation
181 matLtoT->SetDy( yShift );
182 matLtoT->SetDz( zShift );
183 rotMatrix[0]= 0; rotMatrix[1]= 1; rotMatrix[2]= 0; // + rotation
184 rotMatrix[3]= 1; rotMatrix[4]= 0; rotMatrix[5]= 0;
185 rotMatrix[6]= 0; rotMatrix[7]= 0; rotMatrix[8]=-1;
186 if (yFlip) rotMatrix[3] = rotMatrix[1] = -1; // flipping in y
188 if (yRot180) { // rotation of pi around the axis perpendicular to the wafer
189 if (yFlip) matLtoT->SetDx( -xShift ); // flipping in y (for SPD1)
190 matLtoT->SetDy( -yShift );
191 matLtoT->SetDz( -zShift );
194 if (yFlip) rotMatrix[3] = 1; // flipping in y (for SPD1)
196 // printf("UID:%d xS:%f ZS:%f\n",uid,xShift,zShift);
197 // globMatrix->Print();
201 rot.SetMatrix(rotMatrix);
202 matLtoT->MultiplyLeft(&rot);
203 TGeoHMatrix *matTtoL = new TGeoHMatrix(matLtoT->Inverse());
205 alignableEntry->SetMatrix(matTtoL);
208 //______________________________________________________________________
209 void AliITSUv11::AddAlignableVolumes() const{
210 // Creates entries for alignable volumes associating the symbolic volume
211 // name with the corresponding volume path.
213 // Records in the alignable entries the transformation matrices converting
214 // TGeo local coordinates (in the RS of alignable volumes) to the tracking
216 // For this, this function has to run before the misalignment because we
217 // are using the ideal positions in the AliITSgeom object.
225 AliInfo("Add ITS alignable volumes");
227 if (!gGeoManager) { AliFatal("TGeoManager doesn't exist !"); return; }
230 pth = Form("ALIC_1/%s_2",AliITSUGeomTGeo::GetITSVolPattern());
231 // RS: to be checked with MS
232 if( !gGeoManager->SetAlignableEntry("ITS",pth.Data()) )
233 AliFatal(Form("Unable to set alignable entry ! %s :: %s","ITS",pth.Data()));
237 for (int lr=0; lr<fNLayers; lr++) {
239 pth = Form("ALIC_1/%s_2/%s%d_1",AliITSUGeomTGeo::GetITSVolPattern(),AliITSUGeomTGeo::GetITSLayerPattern(),lr);
240 snm = Form("ITS/%s%d",AliITSUGeomTGeo::GetITSLayerPattern(),lr);
241 //printf("SetAlignable: %s %s\n",snm.Data(),pth.Data());
242 gGeoManager->SetAlignableEntry(snm.Data(),pth.Data());
244 for (int ld=0; ld<fLaddPerLay[lr]; ld++) {
246 TString pthL = Form("%s/%s%d_%d",pth.Data(),AliITSUGeomTGeo::GetITSLadderPattern(),lr,ld);
247 TString snmL = Form("%s/%s%d",snm.Data(),AliITSUGeomTGeo::GetITSLadderPattern(),ld);
248 //printf("SetAlignable: %s %s\n",snmL.Data(),pthL.Data());
249 gGeoManager->SetAlignableEntry(snmL.Data(),pthL.Data());
251 for (int md=0; md<fModPerLadd[lr]; md++) {
253 TString pthM = Form("%s/%s%d_%d",pthL.Data(),AliITSUGeomTGeo::GetITSModulePattern(),lr,md);
254 TString snmM = Form("%s/%s%d",snmL.Data(),AliITSUGeomTGeo::GetITSModulePattern(),md);
256 // RS: Attention, this is a hack: AliGeomManager cannot accomodate all ITSU modules w/o
257 // conflicts with TPC. For this reason we define the UID of the module to be simply its ID
258 // int modUID = AliGeomManager::LayerToVolUID(lr+1,modNum++); // here modNum would be module within the layer
259 int modUID = AliITSUGeomTGeo::ModuleVolUID( modNum++ );
261 gGeoManager->SetAlignableEntry(snmM.Data(),pthM.Data(),modUID);
263 double yshift = -(fUpGeom[lr]->GetSensorThick()-fUpGeom[lr]->GetLadderThick())/2;
264 // SetT2Lmatrix(modUID,yshift, kTRUE,kTRUE); // RS: do we need here special matrix, ask MS
265 // SetT2Lmatrix(modUID,yshift, kTRUE,kFALSE); // RS: do we need here special matrix, ask MS
267 // RS: to clarify: in order to get reasonable tracking frame X,phi with STANDARD SetT2Lmatrix
268 // the yRot180 must be true.
269 SetT2Lmatrix(modUID,yshift, kTRUE,kTRUE); // RS: do we need here special matrix, ask MS
277 //______________________________________________________________________
278 void AliITSUv11::CreateGeometry() {
280 // Create the geometry and insert it in the mother volume ITSV
281 TGeoManager *geoManager = gGeoManager;
283 TGeoVolume *vALIC = geoManager->GetVolume("ALIC");
285 new TGeoVolumeAssembly(AliITSUGeomTGeo::GetITSVolPattern());
286 TGeoVolume *vITSV = geoManager->GetVolume(AliITSUGeomTGeo::GetITSVolPattern());
287 vALIC->AddNode(vITSV, 2, 0); // Copy number is 2 to cheat AliGeoManager::CheckSymNamesLUT
290 const Int_t kLength=100;
291 Char_t vstrng[kLength] = "xxxRS"; //?
292 vITSV->SetTitle(vstrng);
294 // Check that we have all needed parameters
295 if (fNLayers <= 0) AliFatal(Form("Wrong number of layers (%d)",fNLayers));
297 for (Int_t j=0; j<fNLayers; j++) {
298 if (fLayRadii[j] <= 0) AliFatal(Form("Wrong layer radius for layer %d (%f)",j,fLayRadii[j]));
299 if (fLayZLength[j] <= 0) AliFatal(Form("Wrong layer length for layer %d (%f)",j,fLayZLength[j]));
300 if (fLaddPerLay[j] <= 0) AliFatal(Form("Wrong number of ladders for layer %d (%d)",j,fLaddPerLay[j]));
301 if (fModPerLadd[j] <= 0) AliFatal(Form("Wrong number of modules for layer %d (%d)",j,fModPerLadd[j]));
302 if (fLadThick[j] < 0) AliFatal(Form("Wrong ladder thickness for layer %d (%f)",j,fLadThick[j]));
303 if (fLayTurbo[j] && fLadWidth[j] <= 0) AliFatal(Form("Wrong ladder width for layer %d (%f)",j,fLadWidth[j]));
304 if (fDetThick[j] < 0) AliFatal(Form("Wrong module thickness for layer %d (%f)",j,fDetThick[j]));
307 if (fLayRadii[j]<=fLayRadii[j-1]) AliFatal(Form("Layer %d radius (%f) is smaller than layer %d radius (%f)",
308 j,fLayRadii[j],j-1,fLayRadii[j-1]));
311 if (fLadThick[j] == 0) AliInfo(Form("Ladder thickness for layer %d not set, using default",j));
312 if (fDetThick[j] == 0) AliInfo(Form("Module thickness for layer %d not set, using default",j));
314 } // for (Int_t j=0; j<fNLayers; j++)
316 // Now create the actual geometry
317 for (Int_t j=0; j<fNLayers; j++) {
319 fUpGeom[j] = new AliITSUv11Layer(j,kTRUE,kFALSE);
320 fUpGeom[j]->SetLadderWidth(fLadWidth[j]);
321 fUpGeom[j]->SetLadderTilt(fLadTilt[j]);
323 else fUpGeom[j] = new AliITSUv11Layer(j,kFALSE);
325 fUpGeom[j]->SetPhi0(fLayPhi0[j]);
326 fUpGeom[j]->SetRadius(fLayRadii[j]);
327 fUpGeom[j]->SetZLength(fLayZLength[j]);
328 fUpGeom[j]->SetNLadders(fLaddPerLay[j]);
329 fUpGeom[j]->SetNModules(fModPerLadd[j]);
330 fUpGeom[j]->SetDetType(fDetTypeID[j]);
332 if (fLadThick[j] != 0) fUpGeom[j]->SetLadderThick(fLadThick[j]);
333 if (fDetThick[j] != 0) fUpGeom[j]->SetSensorThick(fDetThick[j]);
334 fUpGeom[j]->CreateLayer(vITSV);
339 //______________________________________________________________________
340 void AliITSUv11::CreateMaterials() {
341 // Create ITS materials
342 // This function defines the default materials used in the Geant
343 // Monte Carlo simulations for the geometries AliITSv1, AliITSv3,
345 // In general it is automatically replaced by
346 // the CreateMaterials routine defined in AliITSv?. Should the function
347 // CreateMaterials not exist for the geometry version you are using this
348 // one is used. See the definition found in AliITSv5 or the other routine
349 // for a complete definition.
357 Int_t ifield = ((AliMagF*)TGeoGlobalMagField::Instance()->GetField())->Integ();
358 Float_t fieldm = ((AliMagF*)TGeoGlobalMagField::Instance()->GetField())->Max();
360 Float_t tmaxfd = 0.1; // 1.0; // Degree
361 Float_t stemax = 1.0; // cm
362 Float_t deemax = 0.1; // 30.0; // Fraction of particle's energy 0<deemax<=1
363 Float_t epsil = 1.0E-4; // 1.0; // cm
364 Float_t stmin = 0.0; // cm "Default value used"
366 Float_t tmaxfdSi = 0.1; // .10000E+01; // Degree
367 Float_t stemaxSi = 0.0075; // .10000E+01; // cm
368 Float_t deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
369 Float_t epsilSi = 1.0E-4;// .10000E+01;
370 Float_t stminSi = 0.0; // cm "Default value used"
372 Float_t tmaxfdAir = 0.1; // .10000E+01; // Degree
373 Float_t stemaxAir = .10000E+01; // cm
374 Float_t deemaxAir = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
375 Float_t epsilAir = 1.0E-4;// .10000E+01;
376 Float_t stminAir = 0.0; // cm "Default value used"
379 Float_t aAir[4]={12.0107,14.0067,15.9994,39.948};
380 Float_t zAir[4]={6.,7.,8.,18.};
381 Float_t wAir[4]={0.000124,0.755267,0.231781,0.012827};
382 Float_t dAir = 1.20479E-3;
385 AliMaterial(1,"SI$",0.28086E+02,0.14000E+02,0.23300E+01,0.93600E+01,0.99900E+03);
386 AliMedium(1,"SI$",1,0,ifield,fieldm,tmaxfdSi,stemaxSi,deemaxSi,epsilSi,stminSi);
388 AliMixture(5,"AIR$",aAir,zAir,dAir,4,wAir);
389 AliMedium(5,"AIR$",5,0,ifield,fieldm,tmaxfdAir,stemaxAir,deemaxAir,epsilAir,stminAir);
391 AliMaterial(8,"BERILLIUM$",9.01, 4., 1.848, 35.3, 36.7);// From AliPIPEv3
392 AliMedium(8,"BERILLIUM$",8,0,ifield,fieldm,tmaxfd,stemax,deemax,epsil,stmin);
396 //______________________________________________________________________
397 void AliITSUv11::DefineLayer(const Int_t nlay, const double phi0, const Double_t r,
398 const Double_t zlen, const Int_t nladd,
399 const Int_t nmod, const Double_t lthick,
400 const Double_t dthick, const UInt_t dettypeID)
402 // Sets the layer parameters
408 // nladd number of ladders
409 // nmod number of modules per ladder
410 // lthick ladder thickness (if omitted, defaults to 0)
411 // dthick detector thickness (if omitted, defaults to 0)
417 if (nlay >= fNLayers || nlay < 0) {
418 AliError(Form("Wrong layer number (%d)",nlay));
422 fLayTurbo[nlay] = kFALSE;
423 fLayPhi0[nlay] = phi0;
425 fLayZLength[nlay] = zlen;
426 fLaddPerLay[nlay] = nladd;
427 fModPerLadd[nlay] = nmod;
428 fLadThick[nlay] = lthick;
429 fDetThick[nlay] = dthick;
430 fDetTypeID[nlay] = dettypeID;
434 //______________________________________________________________________
435 void AliITSUv11::DefineLayerTurbo(Int_t nlay, Double_t phi0, Double_t r, Double_t zlen, Int_t nladd,
436 Int_t nmod, Double_t width, Double_t tilt,
437 Double_t lthick,Double_t dthick,
440 // Sets the layer parameters for a "turbo" layer
441 // (i.e. a layer whose ladders overlap in phi)
444 // phi0 phi of 1st ladder
447 // nladd number of ladders
448 // nmod number of modules per ladder
449 // width ladder width
450 // tilt layer tilt angle (degrees)
451 // lthick ladder thickness (if omitted, defaults to 0)
452 // dthick detector thickness (if omitted, defaults to 0)
458 if (nlay >= fNLayers || nlay < 0) {
459 AliError(Form("Wrong layer number (%d)",nlay));
463 fLayTurbo[nlay] = kTRUE;
464 fLayPhi0[nlay] = phi0;
466 fLayZLength[nlay] = zlen;
467 fLaddPerLay[nlay] = nladd;
468 fModPerLadd[nlay] = nmod;
469 fLadThick[nlay] = lthick;
470 fLadWidth[nlay] = width;
471 fLadTilt[nlay] = tilt;
472 fDetThick[nlay] = dthick;
473 fDetTypeID[nlay] = dettypeID;
477 //______________________________________________________________________
478 void AliITSUv11::GetLayerParameters(Int_t nlay, Double_t &phi0,
479 Double_t &r, Double_t &zlen,
480 Int_t &nladd, Int_t &nmod,
481 Double_t &width, Double_t &tilt,
482 Double_t <hick, Double_t &dthick) const
484 // Gets the layer parameters
488 // phi0 phi of 1st ladder
491 // nladd number of ladders
492 // nmod number of modules per ladder
493 // width ladder width
494 // tilt ladder tilt angle
495 // lthick ladder thickness
496 // dthick detector thickness
500 if (nlay >= fNLayers || nlay < 0) {
501 AliError(Form("Wrong layer number (%d)",nlay));
505 phi0 = fLayPhi0[nlay];
507 zlen = fLayZLength[nlay];
508 nladd = fLaddPerLay[nlay];
509 nmod = fModPerLadd[nlay];
510 width = fLadWidth[nlay];
511 tilt = fLadTilt[nlay];
512 lthick = fLadThick[nlay];
513 dthick = fDetThick[nlay];
516 //______________________________________________________________________
517 void AliITSUv11::Init()
519 // Initialise the ITS after it has been created.
520 UpdateInternalGeometry();
525 //______________________________________________________________________
526 Bool_t AliITSUv11::IsLayerTurbo(Int_t nlay)
528 // Returns true if the layer is a "turbo" layer
529 if ( nlay < 0 || nlay > fNLayers ) {
530 AliError(Form("Wrong layer number %d",nlay));
533 else return fUpGeom[nlay]->IsTurbo();
536 //______________________________________________________________________
537 void AliITSUv11::SetDefaults()
539 // sets the default segmentation, response, digit and raw cluster classes
542 //______________________________________________________________________
543 void AliITSUv11::StepManager()
545 // Called for every step in the ITS, then calles the AliITSUHit class
546 // creator with the information to be recoreded about that hit.
547 // The value of the macro ALIITSPRINTGEOM if set to 1 will allow the
548 // printing of information to a file which can be used to create a .det
549 // file read in by the routine CreateGeometry(). If set to 0 or any other
550 // value except 1, the default behavior, then no such file is created nor
551 // it the extra variables and the like used in the printing allocated.
558 if(!(this->IsActive())) return;
559 if(!(gMC->TrackCharge())) return;
562 Int_t id = gMC->CurrentVolID(copy);
564 Bool_t notSens = kFALSE;
565 while ((lay<fNLayers) && (notSens = (id!=fIdSens[lay]))) ++lay;
566 //printf("R: %.1f | Lay: %d NotSens: %d\n",positionRS.Pt(), lay, notSens);
570 if(gMC->IsTrackExiting()) {
571 AddTrackReference(gAlice->GetMCApp()->GetCurrentTrackNumber(), AliTrackReference::kITS);
572 } // if Outer ITS mother Volume
574 static TLorentzVector position, momentum; // Saves on calls to construtors
575 static AliITSUHit hit;// Saves on calls to constructors
577 TClonesArray &lhits = *(Hits());
578 Int_t cpn0, cpn1, mod, status = 0;
581 if(gMC->IsTrackInside()) status += 1;
582 if(gMC->IsTrackEntering()) status += 2;
583 if(gMC->IsTrackExiting()) status += 4;
584 if(gMC->IsTrackOut()) status += 8;
585 if(gMC->IsTrackDisappeared()) status += 16;
586 if(gMC->IsTrackStop()) status += 32;
587 if(gMC->IsTrackAlive()) status += 64;
590 // retrieve the indices with the volume path
592 if (lay < 0 || lay >= fNLayers) {
593 AliError(Form("Invalid value: lay=%d. Not an ITS sensitive volume",lay));
594 return; // not an ITS sensitive volume.
597 gMC->CurrentVolOffID(1,cpn1);
598 gMC->CurrentVolOffID(2,cpn0);
601 mod = fGeomTGeo->GetModuleIndex(lay,cpn0,cpn1);
602 //RS2DEL fInitGeom.DecodeDetector(mod,lay+1,cpn0,cpn1,copy);
604 // Fill hit structure.
607 hit.SetTrack(gAlice->GetMCApp()->GetCurrentTrackNumber());
608 gMC->TrackPosition(position);
609 gMC->TrackMomentum(momentum);
610 hit.SetPosition(position);
611 hit.SetTime(gMC->TrackTime());
612 hit.SetMomentum(momentum);
613 hit.SetStatus(status);
614 hit.SetEdep(gMC->Edep());
615 hit.SetShunt(GetIshunt());
616 if(gMC->IsTrackEntering()){
617 hit.SetStartPosition(position);
618 hit.SetStartTime(gMC->TrackTime());
619 hit.SetStartStatus(status);
620 return; // don't save entering hit.
621 } // end if IsEntering
622 // Fill hit structure with this new hit.
623 //Info("StepManager","Calling Copy Constructor");
624 new(lhits[fNhits++]) AliITSUHit(hit); // Use Copy Construtor.
625 // Save old position... for next hit.
626 hit.SetStartPosition(position);
627 hit.SetStartTime(gMC->TrackTime());
628 hit.SetStartStatus(status);
633 //______________________________________________________________________
634 void AliITSUv11::SetLayerDetTypeID(Int_t lr, UInt_t id)
637 if (!fDetTypeID || fNLayers<=lr) AliFatal(Form("Number of layers %d, %d is manipulated",fNLayers,lr));
641 //______________________________________________________________________
642 Int_t AliITSUv11::GetLayerDetTypeID(Int_t lr)
645 if (!fDetTypeID || fNLayers<=lr) AliFatal(Form("Number of layers %d, %d is manipulated",fNLayers,lr));
646 return fDetTypeID[lr];