1 /**************************************************************************
2 * Copyright(c) 1998-1999, 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 **************************************************************************/
18 Revision 1.2 2000/06/12 15:36:16 jbarbosa
21 Revision 1.1 2000/06/09 15:00:31 jbarbosa
22 New full version. All parameters configurable.
24 Revision 1.9 2000/05/31 08:19:38 jbarbosa
25 Fixed bug in StepManager
27 Revision 1.8 2000/05/26 17:30:08 jbarbosa
28 Cerenkov angle now stored within cerenkov data structure.
30 Revision 1.7 2000/05/18 10:31:36 jbarbosa
31 Fixed positioning of spacers inside freon.
32 Fixed positioning of proximity gap
34 Fixed cut on neutral particles in the StepManager.
36 Revision 1.6 2000/04/28 11:51:58 morsch
37 Dimensions of arrays hits and Ckov_data corrected.
39 Revision 1.5 2000/04/19 13:28:46 morsch
40 Major changes in geometry (parametrised), materials (updated) and
41 step manager (diagnostics) (JB, AM)
47 //////////////////////////////////////////////////////////
48 // Manager and hits classes for set: RICH full version //
49 //////////////////////////////////////////////////////////
54 #include <TParticle.h>
56 #include "AliRICHv1.h"
57 #include "AliRICHHit.h"
61 #include "AliCallf77.h"
68 //___________________________________________
69 AliRICHv1::AliRICHv1() : AliRICHv0()
72 // Default constructor fo AliRICHvv1 (full version)
77 //___________________________________________
78 AliRICHv1::AliRICHv1(const char *name, const char *title)
79 : AliRICHv0(name,title)
82 // Full version of RICH with hits and diagnostics
88 fChambers = new TObjArray(kNCH);
89 for (i=0; i<kNCH; i++) {
91 (*fChambers)[i] = new AliRICHChamber();
96 void AliRICHv1::Init()
99 printf("*********************************** RICH_INIT ***********************************\n");
101 printf("* AliRICHv1 Configurable version started *\n");
105 AliRICHSegmentation* segmentation;
106 AliRICHGeometry* geometry;
107 AliRICHResponse* response;
111 // Initialize Tracking Chambers
113 for (i=1; i<kNCH; i++) {
115 ( (AliRICHChamber*) (*fChambers)[i])->Init();
119 // Set the chamber (sensitive region) GEANT identifier
121 ((AliRICHChamber*)(*fChambers)[0])->SetGid(1);
122 ((AliRICHChamber*)(*fChambers)[1])->SetGid(2);
123 ((AliRICHChamber*)(*fChambers)[2])->SetGid(3);
124 ((AliRICHChamber*)(*fChambers)[3])->SetGid(4);
125 ((AliRICHChamber*)(*fChambers)[4])->SetGid(5);
126 ((AliRICHChamber*)(*fChambers)[5])->SetGid(6);
127 ((AliRICHChamber*)(*fChambers)[6])->SetGid(7);
129 Float_t pos1[3]={0,471.8999,165.2599};
130 Chamber(0).SetChamberTransform(pos1[0],pos1[1],pos1[2],new TRotMatrix("rot993","rot993",90,0,70.69,90,19.30999,-90));
132 Float_t pos2[3]={171,470,0};
133 Chamber(1).SetChamberTransform(pos2[0],pos2[1],pos2[2],new TRotMatrix("rot994","rot994",90,-20,90,70,0,0));
135 Float_t pos3[3]={0,500,0};
136 Chamber(2).SetChamberTransform(pos3[0],pos3[1],pos3[2],new TRotMatrix("rot995","rot995",90,0,90,90,0,0));
138 Float_t pos4[3]={-171,470,0};
139 Chamber(3).SetChamberTransform(pos4[0],pos4[1],pos4[2], new TRotMatrix("rot996","rot996",90,20,90,110,0,0));
141 Float_t pos5[3]={161.3999,443.3999,-165.3};
142 Chamber(4).SetChamberTransform(pos5[0],pos5[1],pos5[2],new TRotMatrix("rot997","rot997",90,340,108.1999,70,18.2,70));
144 Float_t pos6[3]={0., 471.9, -165.3,};
145 Chamber(5).SetChamberTransform(pos6[0],pos6[1],pos6[2],new TRotMatrix("rot998","rot998",90,0,109.3099,90,19.30999,90));
147 Float_t pos7[3]={-161.399,443.3999,-165.3};
148 Chamber(6).SetChamberTransform(pos7[0],pos7[1],pos7[2],new TRotMatrix("rot999","rot999",90,20,108.1999,110,18.2,110));
150 segmentation=Chamber(0).GetSegmentationModel(0);
151 geometry=Chamber(0).GetGeometryModel();
152 response=Chamber(0).GetResponseModel();
155 printf("* Pads : %3dx%3d *\n",segmentation->Npx(),segmentation->Npy());
156 printf("* Pad size : %5.2f x%5.2f mm2 *\n",segmentation->Dpx(),segmentation->Dpy());
157 printf("* Gap Thickness : %5.1f mm *\n",geometry->GetGapThickness());
158 printf("* Radiator Width : %5.1f mm *\n",geometry->GetQuartzWidth());
159 printf("* Radiator Length : %5.1f mm *\n",geometry->GetQuartzLength());
160 printf("* Freon Thickness : %5.1f mm *\n",geometry->GetFreonThickness());
161 printf("* Charge Slope : %5.1f ADC *\n",response->ChargeSlope());
162 printf("* Feedback Prob. : %5.2f %% *\n",response->AlphaFeedback());
164 printf("* Success! *\n");
166 printf("*********************************************************************************\n");
170 //___________________________________________
171 void AliRICHv1::StepManager()
180 static Float_t hits[18];
181 static Float_t ckovData[19];
182 TLorentzVector position;
183 TLorentzVector momentum;
188 Float_t localTheta,localPhi;
190 Float_t destep, step;
194 static Float_t eloss, xhit, yhit, tlength;
195 const Float_t kBig=1.e10;
197 TClonesArray &lhits = *fHits;
198 TGeant3 *geant3 = (TGeant3*) gMC;
199 TParticle *current = (TParticle*)(*gAlice->Particles())[gAlice->CurrentTrack()];
201 //if (current->Energy()>1)
204 // Only gas gap inside chamber
205 // Tag chambers and record hits when track enters
208 id=gMC->CurrentVolID(copy);
209 Float_t cherenkovLoss=0;
210 //gAlice->KeepTrack(gAlice->CurrentTrack());
212 gMC->TrackPosition(position);
216 ckovData[1] = pos[0]; // X-position for hit
217 ckovData[2] = pos[1]; // Y-position for hit
218 ckovData[3] = pos[2]; // Z-position for hit
219 //ckovData[11] = gAlice->CurrentTrack();
221 //AliRICH *RICH = (AliRICH *) gAlice->GetDetector("RICH");
223 /********************Store production parameters for Cerenkov photons************************/
224 //is it a Cerenkov photon?
225 if (gMC->TrackPid() == 50000050) {
227 //if (gMC->VolId("GAP ")==gMC->CurrentVolID(copy))
229 Float_t ckovEnergy = current->Energy();
230 //energy interval for tracking
231 if (ckovEnergy > 5.6e-09 && ckovEnergy < 7.8e-09 )
232 //if (ckovEnergy > 0)
234 if (gMC->IsTrackEntering()){ //is track entering?
235 if (gMC->VolId("FRE1")==gMC->CurrentVolID(copy) || gMC->VolId("FRE2")==gMC->CurrentVolID(copy))
237 if (geant3->Gctrak()->nstep<1){ //is it the first step?
238 Int_t mother = current->GetFirstMother();
240 //printf("Second Mother:%d\n",current->GetSecondMother());
242 ckovData[10] = mother;
243 ckovData[11] = gAlice->CurrentTrack();
244 ckovData[12] = 1; //Media where photon was produced 1->Freon, 2->Quarz
247 //printf("Index: %d\n",fCkovNumber);
248 } //first step question
251 if (geant3->Gctrak()->nstep<1){ //is it first step?
252 if (gMC->VolId("QUAR")==gMC->CurrentVolID(copy)) //is it in quarz?
256 } //first step question
258 //printf("Before %d\n",fFreonProd);
259 } //track entering question
261 if (ckovData[12] == 1) //was it produced in Freon?
262 //if (fFreonProd == 1)
264 if (gMC->IsTrackEntering()){ //is track entering?
266 if (gMC->VolId("META")==gMC->CurrentVolID(copy)) //is it in gap?
268 //printf("Got in\n");
269 gMC->TrackMomentum(momentum);
274 // Z-position for hit
277 /**************** Photons lost in second grid have to be calculated by hand************/
279 Float_t cophi = TMath::Cos(TMath::ATan2(mom[0], mom[1]));
280 Float_t t = (1. - .025 / cophi) * (1. - .05 / cophi);
282 //printf("grid calculation:%f\n",t);
284 //geant3->StopTrack();
286 AddCerenkov(gAlice->CurrentTrack(),vol,ckovData);
287 //printf("Lost one in grid\n");
289 /**********************************************************************************/
292 if (gMC->VolId("CSI ")==gMC->CurrentVolID(copy)) //is it in csi?
294 gMC->TrackMomentum(momentum);
300 /********* Photons lost by Fresnel reflection have to be calculated by hand********/
301 /***********************Cerenkov phtons (always polarised)*************************/
303 Float_t cophi = TMath::Cos(TMath::ATan2(mom[0], mom[1]));
304 Float_t t = Fresnel(ckovEnergy*1e9,cophi,1);
307 //geant3->StopTrack();
309 AddCerenkov(gAlice->CurrentTrack(),vol,ckovData);
310 //printf("Lost by Fresnel\n");
312 /**********************************************************************************/
317 /********************Evaluation of losses************************/
318 /******************still in the old fashion**********************/
320 Int_t i1 = geant3->Gctrak()->nmec; //number of physics mechanisms acting on the particle
321 for (Int_t i = 0; i < i1; ++i) {
323 if (geant3->Gctrak()->lmec[i] == 106) { //was it reflected
325 if (gMC->VolId("FRE1")==gMC->CurrentVolID(copy) || gMC->VolId("FRE2")==gMC->CurrentVolID(copy))
327 if (gMC->CurrentVolID(copy) == gMC->VolId("QUAR"))
329 //geant3->StopTrack();
330 AddCerenkov(gAlice->CurrentTrack(),vol,ckovData);
331 } //reflection question
335 else if (geant3->Gctrak()->lmec[i] == 101) { //was it absorbed?
337 if (gMC->VolId("FRE1")==gMC->CurrentVolID(copy) || gMC->VolId("FRE2")==gMC->CurrentVolID(copy))
339 if (gMC->CurrentVolID(copy) == gMC->VolId("QUAR"))
341 if (gMC->CurrentVolID(copy) == gMC->VolId("META"))
343 if (gMC->CurrentVolID(copy) == gMC->VolId("GAP "))
346 if (gMC->CurrentVolID(copy) == gMC->VolId("SRIC"))
350 if (gMC->CurrentVolID(copy) == gMC->VolId("CSI ")) {
353 //geant3->StopTrack();
354 AddCerenkov(gAlice->CurrentTrack(),vol,ckovData);
355 //printf("Added cerenkov %d\n",fCkovNumber);
356 } //absorption question
359 // Photon goes out of tracking scope
360 else if (geant3->Gctrak()->lmec[i] == 30) { //is it below energy treshold?
362 //geant3->StopTrack();
363 AddCerenkov(gAlice->CurrentTrack(),vol,ckovData);
364 } // energy treshold question
365 } //number of mechanisms cycle
366 /**********************End of evaluation************************/
367 } //freon production question
368 } //energy interval question
369 //}//inside the proximity gap question
370 } //cerenkov photon question
372 /**************************************End of Production Parameters Storing*********************/
375 /*******************************Treat photons that hit the CsI (Ckovs and Feedbacks)************/
377 if (gMC->TrackPid() == 50000050 || gMC->TrackPid() == 50000051) {
378 //printf("Cerenkov\n");
379 if (gMC->VolId("CSI ")==gMC->CurrentVolID(copy))
382 if (gMC->Edep() > 0.){
383 gMC->TrackPosition(position);
384 gMC->TrackMomentum(momentum);
392 Double_t tc = mom[0]*mom[0]+mom[1]*mom[1];
393 Double_t rt = TMath::Sqrt(tc);
394 theta = Float_t(TMath::ATan2(rt,Double_t(mom[2])))*kRaddeg;
395 phi = Float_t(TMath::ATan2(Double_t(mom[1]),Double_t(mom[0])))*kRaddeg;
396 gMC->Gmtod(pos,localPos,1);
397 gMC->Gmtod(mom,localMom,2);
399 gMC->CurrentVolOffID(2,copy);
403 //Int_t sector=((AliRICHChamber*) (*fChambers)[idvol])
404 //->Sector(localPos[0], localPos[2]);
405 //printf("Sector:%d\n",sector);
407 /*if (gMC->TrackPid() == 50000051){
409 printf("Feedbacks:%d\n",fFeedbacks);
412 ((AliRICHChamber*) (*fChambers)[idvol])
413 ->SigGenInit(localPos[0], localPos[2], localPos[1]);
415 ckovData[0] = gMC->TrackPid(); // particle type
416 ckovData[1] = pos[0]; // X-position for hit
417 ckovData[2] = pos[1]; // Y-position for hit
418 ckovData[3] = pos[2]; // Z-position for hit
419 ckovData[4] = theta; // theta angle of incidence
420 ckovData[5] = phi; // phi angle of incidence
421 ckovData[8] = (Float_t) fNPadHits; // first padhit
422 ckovData[9] = -1; // last pad hit
423 ckovData[13] = 4; // photon was detected
424 ckovData[14] = mom[0];
425 ckovData[15] = mom[1];
426 ckovData[16] = mom[2];
428 destep = gMC->Edep();
429 gMC->SetMaxStep(kBig);
430 cherenkovLoss += destep;
431 ckovData[7]=cherenkovLoss;
433 nPads = MakePadHits(localPos[0],localPos[2],cherenkovLoss,idvol,kCerenkov);
434 if (fNPadHits > (Int_t)ckovData[8]) {
435 ckovData[8]= ckovData[8]+1;
436 ckovData[9]= (Float_t) fNPadHits;
439 ckovData[17] = nPads;
440 //printf("nPads:%d",nPads);
442 //TClonesArray *Hits = RICH->Hits();
443 AliRICHHit *mipHit = (AliRICHHit*) (fHits->UncheckedAt(0));
446 mom[0] = current->Px();
447 mom[1] = current->Py();
448 mom[2] = current->Pz();
449 Float_t mipPx = mipHit->fMomX;
450 Float_t mipPy = mipHit->fMomY;
451 Float_t mipPz = mipHit->fMomZ;
453 Float_t r = mom[0]*mom[0] + mom[1]*mom[1] + mom[2]*mom[2];
454 Float_t rt = TMath::Sqrt(r);
455 Float_t mipR = mipPx*mipPx + mipPy*mipPy + mipPz*mipPz;
456 Float_t mipRt = TMath::Sqrt(mipR);
459 coscerenkov = (mom[0]*mipPx + mom[1]*mipPy + mom[2]*mipPz)/(rt*mipRt);
465 Float_t cherenkov = TMath::ACos(coscerenkov);
466 ckovData[18]=cherenkov;
470 AddHit(gAlice->CurrentTrack(),vol,ckovData);
471 AddCerenkov(gAlice->CurrentTrack(),vol,ckovData);
478 /***********************************************End of photon hits*********************************************/
481 /**********************************************Charged particles treatment*************************************/
483 else if (gMC->TrackCharge())
487 /*if (gMC->IsTrackEntering())
489 hits[13]=20;//is track entering?
491 if (gMC->VolId("FRE1")==gMC->CurrentVolID(copy) || gMC->VolId("FRE2")==gMC->CurrentVolID(copy))
496 if (gMC->VolId("GAP ")== gMC->CurrentVolID(copy)) {
497 // Get current particle id (ipart), track position (pos) and momentum (mom)
499 gMC->CurrentVolOffID(3,copy);
503 //Int_t sector=((AliRICHChamber*) (*fChambers)[idvol])
504 //->Sector(localPos[0], localPos[2]);
505 //printf("Sector:%d\n",sector);
507 gMC->TrackPosition(position);
508 gMC->TrackMomentum(momentum);
516 gMC->Gmtod(pos,localPos,1);
517 gMC->Gmtod(mom,localMom,2);
519 ipart = gMC->TrackPid();
521 // momentum loss and steplength in last step
522 destep = gMC->Edep();
523 step = gMC->TrackStep();
526 // record hits when track enters ...
527 if( gMC->IsTrackEntering()) {
528 // gMC->SetMaxStep(fMaxStepGas);
529 Double_t tc = mom[0]*mom[0]+mom[1]*mom[1];
530 Double_t rt = TMath::Sqrt(tc);
531 theta = Float_t(TMath::ATan2(rt,Double_t(mom[2])))*kRaddeg;
532 phi = Float_t(TMath::ATan2(Double_t(mom[1]),Double_t(mom[0])))*kRaddeg;
535 Double_t localTc = localMom[0]*localMom[0]+localMom[2]*localMom[2];
536 Double_t localRt = TMath::Sqrt(localTc);
537 localTheta = Float_t(TMath::ATan2(localRt,Double_t(localMom[1])))*kRaddeg;
538 localPhi = Float_t(TMath::ATan2(Double_t(localMom[2]),Double_t(localMom[0])))*kRaddeg;
540 hits[0] = Float_t(ipart); // particle type
541 hits[1] = localPos[0]; // X-position for hit
542 hits[2] = localPos[1]; // Y-position for hit
543 hits[3] = localPos[2]; // Z-position for hit
544 hits[4] = localTheta; // theta angle of incidence
545 hits[5] = localPhi; // phi angle of incidence
546 hits[8] = (Float_t) fNPadHits; // first padhit
547 hits[9] = -1; // last pad hit
548 hits[13] = fFreonProd; // did id hit the freon?
557 Chamber(idvol).LocaltoGlobal(localPos,hits+1);
560 //To make chamber coordinates x-y had to pass localPos[0], localPos[2]
563 // Only if not trigger chamber
566 // Initialize hit position (cursor) in the segmentation model
567 ((AliRICHChamber*) (*fChambers)[idvol])
568 ->SigGenInit(localPos[0], localPos[2], localPos[1]);
573 // Calculate the charge induced on a pad (disintegration) in case
575 // Mip left chamber ...
576 if( gMC->IsTrackExiting() || gMC->IsTrackStop() || gMC->IsTrackDisappeared()){
577 gMC->SetMaxStep(kBig);
582 // Only if not trigger chamber
586 if(gMC->TrackPid() == kNeutron)
587 printf("\n\n\n\n\n Neutron Making Pad Hit!!! \n\n\n\n");
588 nPads = MakePadHits(xhit,yhit,eloss,idvol,kMip);
590 //printf("nPads:%d",nPads);
596 if (fNPadHits > (Int_t)hits[8]) {
598 hits[9]= (Float_t) fNPadHits;
602 new(lhits[fNhits++]) AliRICHHit(fIshunt,gAlice->CurrentTrack(),vol,hits);
605 // Check additional signal generation conditions
606 // defined by the segmentation
607 // model (boundary crossing conditions)
609 (((AliRICHChamber*) (*fChambers)[idvol])
610 ->SigGenCond(localPos[0], localPos[2], localPos[1]))
612 ((AliRICHChamber*) (*fChambers)[idvol])
613 ->SigGenInit(localPos[0], localPos[2], localPos[1]);
616 if(gMC->TrackPid() == kNeutron)
617 printf("\n\n\n\n\n Neutron Making Pad Hit!!! \n\n\n\n");
618 nPads = MakePadHits(xhit,yhit,eloss,idvol,kMip);
620 //printf("Npads:%d",NPads);
627 // nothing special happened, add up energy loss
634 /*************************************************End of MIP treatment**************************************/