EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CbmRich.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CbmRich.cxx
1 
2 
3 #include "CbmRich.h"
4 
5 #include "CbmGeoRichPar.h"
6 #include "CbmGeoRich.h"
7 #include "CbmRichPoint.h"
8 
9 #include "CbmDetectorList.h"
10 #include "FairGeoInterface.h"
11 #include "FairGeoLoader.h"
12 #include "FairGeoNode.h"
13 #include "FairGeoRootBuilder.h"
14 #include "CbmStack.h"
15 #include "FairRootManager.h"
16 #include "FairVolume.h"
17 #include "FairRuntimeDb.h"
18 #include "FairRun.h"
19 
20 #include "TObjArray.h"
21 #include "TClonesArray.h"
22 #include "TGeoMCGeometry.h"
23 #include "TGeoManager.h"
24 #include "TLorentzVector.h"
25 #include "TParticle.h"
26 #include "TParticlePDG.h"
27 #include "TVirtualMC.h"
28 #include "TGeoMatrix.h"
29 #include "TGeoNode.h"
30 
31 #include "FairGeoMedia.h"
32 #include "FairGeoBuilder.h"
33 
34 #include "TGDMLParse.h"
35 
36 #include <iostream>
37 
38 using std::cout;
39 using std::endl;
40 
41 
42 std::map<TString, Int_t> CbmRich::fFixedMats;
43 Bool_t CbmRich::fIsFirstGDML = kTRUE;
44 
46  FairDetector("RICH", kTRUE, kRICH),
47  fPosIndex(0),
48 
49  fRichPoints(NULL),
50  fRichRefPlanePoints(NULL),
51  fRichMirrorPoints(NULL),
52  fRotation(),
53  fPositionRotation(),
54  mScale(1.0)
55 {
56  fRichPoints = new TClonesArray("CbmRichPoint");
57  fRichRefPlanePoints = new TClonesArray("CbmRichPoint");
58  fRichMirrorPoints = new TClonesArray("CbmRichPoint");
59  fPosIndex = 0;
60 
61  fVerboseLevel = 1;
62 }
63 
65  const char* name,
66  Bool_t active,
67  Double_t px,
68  Double_t py,
69  Double_t pz,
70  Double_t rx,
71  Double_t ry,
72  Double_t rz):
73  FairDetector(name, active, kRICH),
74  fPosIndex(0),
75  fRichPoints(new TClonesArray("CbmRichPoint")),
76  fRichRefPlanePoints(new TClonesArray("CbmRichPoint")),
77  fRichMirrorPoints(new TClonesArray("CbmRichPoint")),
78 
79  fRotation(new TGeoRotation("", rx, ry, rz)),
80  fPositionRotation(new TGeoCombiTrans(px, py, pz, fRotation)),
81  mScale(1.0)
82 {
83  fVerboseLevel = 1;
84 }
85 
87 {
88  if (NULL != fRichPoints) {
89  fRichPoints->Delete();
90  delete fRichPoints;
91  }
92  if (NULL != fRichRefPlanePoints) {
93  fRichRefPlanePoints->Delete();
94  delete fRichRefPlanePoints;
95  }
96 
97  if (NULL != fRichMirrorPoints) {
98  fRichMirrorPoints->Delete();
99  delete fRichMirrorPoints;
100  }
101 }
102 
104 {
105  //return;
107  FairRun* sim = FairRun::Instance();
108  FairRuntimeDb* rtdb=sim->GetRuntimeDb();
109  CbmGeoRichPar *par=(CbmGeoRichPar*)(rtdb->getContainer("CbmGeoRichPar"));
110  TObjArray *fSensNodes = par->GetGeoSensitiveNodes();
111 }
112 
113 
114 Bool_t CbmRich::CheckIfSensitive(std::string name)
115 {
116  TString volName = name;
117  if ( volName.Contains("rich1d")){
118  return kTRUE;
119  }
120  return kFALSE;
121 }
122 
123 
125  FairVolume* vol)
126 {
127  Int_t pdgCode = gMC->TrackPid();
128  Int_t iVol = vol->getMCid();
129  TString volName = TString(vol->GetName());
130  // cout << volName << endl;
131  //Treat photodetectors : All particles
132  if (volName.Contains("rich1d") || volName.Contains("RICH_PMT") ){
133  if (gMC->IsTrackEntering()){
134 
135  TParticle* part = gMC->GetStack()->GetCurrentTrack();
136  Double_t charge = part->GetPDG()->Charge() / 3. ;
137  Int_t trackID = gMC->GetStack()->GetCurrentTrackNumber();
138  Double_t time = gMC->TrackTime() * 1.0e09;
139  Double_t length = gMC->TrackLength();
140  Double_t eLoss = gMC->Edep();
141  TLorentzVector tPos, tMom;
142  gMC->TrackPosition(tPos);
143  gMC->TrackMomentum(tMom);
144 
145  //printf("%4d: %d\n", trackID, pdgCode);
146  if ( pdgCode == 50000050) { // Cherenkovs only
147  AddHit(trackID, pdgCode, iVol, TVector3(tPos.X(), tPos.Y(), tPos.Z()), TVector3(tMom.Px(), tMom.Py(), tMom.Pz()), time, length, eLoss);
148 
149  // Increment number of RichPoints for this track
150  CbmStack* stack = (CbmStack*) gMC->GetStack();
151  stack->AddPoint(kRICH);
152  return kTRUE;
153  } else {
154  if (charge == 0.) {
155  return kFALSE; // no neutrals
156  } else { // charged particles
157  AddHit(trackID, pdgCode, iVol, TVector3(tPos.X(), tPos.Y(), tPos.Z()), TVector3(tMom.Px(), tMom.Py(), tMom.Pz()), time, length, eLoss);
158 
159  // Increment number of RichPoints for this track
160  CbmStack* stack = (CbmStack*) gMC->GetStack();
161  stack->AddPoint(kRICH);
162  return kTRUE;
163  }
164  }
165  }
166  }
167 
168  // Treat imaginary plane in front of the mirrors: Only charged particles at entrance
169  if (volName == "rich1gas2") {
170  // Collecting points of tracks and imaginary plane intersection
171  if ( gMC->IsTrackEntering() ) {
172  TParticle* part = gMC->GetStack()->GetCurrentTrack();
173  Double_t charge = part->GetPDG()->Charge() / 3. ;
174  if (charge == 0.) {
175  return kFALSE; // no neutrals
176  } else {
177  Int_t trackID = gMC->GetStack()->GetCurrentTrackNumber();
178  Double_t time = gMC->TrackTime() * 1.0e09;
179  Double_t length = gMC->TrackLength();
180  Double_t eLoss = gMC->Edep();
181  TLorentzVector tPos, tMom;
182 
183  gMC->TrackPosition(tPos);
184  gMC->TrackMomentum(tMom);
185 
186  AddRefPlaneHit(trackID, iVol, TVector3(tPos.X(), tPos.Y(), tPos.Z()), TVector3(tMom.Px(), tMom.Py(), tMom.Pz()), time, length, eLoss);
187 
188  //Increment number of RefPlanePoints for this track
189  CbmStack* stack = (CbmStack*) gMC->GetStack();
190  stack->AddPoint(kREF);
191  return kTRUE;
192  }
193  }
194  }
195 
196  // Treat mirror points
197  if (volName.Contains("rich1mgl") || volName.Contains("rich1mglLU") || volName.Contains("rich1mglRU") ) {
198 
199  // Collecting points of tracks and imaginary plane intersection
200  if (gMC->IsTrackEntering()) {
201  TParticle* part = gMC->GetStack()->GetCurrentTrack();
202  Double_t charge = part->GetPDG()->Charge() / 3.;
203  if (charge == 0.) {
204  return kFALSE; // no neutrals
205  } else {
206 
207  Int_t trackID = gMC->GetStack()->GetCurrentTrackNumber();
208 
209  Double_t time = gMC->TrackTime() * 1.0e09;
210  Double_t length = gMC->TrackLength();
211  Double_t eLoss = gMC->Edep();
212  TLorentzVector tPos, tMom;
213 
214  gMC->TrackPosition(tPos);
215  gMC->TrackMomentum(tMom);
216 
217  // check number of STS points
218  //UInt_t points = gMC->GetStack()->GetCurrentTrack()->GetMother(1);
219  //Int_t nStsPoints = (points & 15);
220 
221  //if (nStsPoints > 0) { // store only particles with STSpoints (at least 1)
222  AddMirrorHit(trackID, iVol, TVector3(tPos.X(), tPos.Y(), tPos.Z()), TVector3(tMom.Px(), tMom.Py(), tMom.Pz()), time, length, eLoss);
223  return kTRUE;
224  //}
225  }
226  }
227  }
228 
229 
230  return kFALSE;
231 }
232 
234 {
235  if (fVerboseLevel) Print();
236  Reset();
237 }
238 
240 {
241  FairRootManager::Instance()->Register("RichPoint","Rich", fRichPoints, kTRUE);
242  FairRootManager::Instance()->Register("RefPlanePoint","RichRefPlane", fRichRefPlanePoints, kTRUE);
243  FairRootManager::Instance()->Register("RichMirrorPoint","RichMirror", fRichMirrorPoints, kFALSE);
244 }
245 
247  Int_t iColl) const
248 {
249  if (iColl == 0) return fRichPoints;
250  if (iColl == 1) return fRichRefPlanePoints;
251  if (iColl == 2) return fRichMirrorPoints;
252  return NULL;
253 }
254 
255 void CbmRich::Print() const
256 {
257  Int_t nHits = fRichPoints->GetEntriesFast();
258  cout << "-I- CbmRich: " << nHits << " points registered in this event." << endl;
259 
260  if (fVerboseLevel > 1) for (Int_t i=0; i<nHits; i++) (*fRichPoints)[i]->Print();
261 }
262 
264 {
265  fRichPoints->Delete();
266  fRichRefPlanePoints->Delete();
267  fRichMirrorPoints->Delete();
268  fPosIndex = 0;
269 }
270 
272  TClonesArray* cl1,
273  TClonesArray* cl2,
274  Int_t offset )
275 {
276  Int_t nEntries = cl1->GetEntriesFast();
277  cout << "-I- CbmRich: " << nEntries << " entries to add." << endl;
278  TClonesArray& clref = *cl2;
279  CbmRichPoint* oldpoint = NULL;
280  for (Int_t i=0; i< nEntries ; i++ ) {
281  oldpoint = (CbmRichPoint*) cl1->At(i);
282  Int_t index = oldpoint->GetTrackID() + offset;
283  oldpoint->SetTrackID(index);
284  new (clref[fPosIndex]) CbmRichPoint(*oldpoint);
285  fPosIndex++;
286  }
287  cout << "-I- CbmRich: " << cl2->GetEntriesFast() << " merged entries." << endl;
288 }
289 
291 {
292  cout<< "CbmRich::ConstructOpGeometry() " <<endl;
293 }
294 
296 {
297  TString fileName = GetGeometryFileName();
298  if ( fileName.EndsWith(".root") ) {
299  cout << "Constructing RICH geometry from ROOT file: " << fileName.Data() << endl;
301  } else if ( fileName.EndsWith(".geo") ) {
302  cout << "-I- Constructing RICH geometry from ASCII file: " << fileName.Data() << endl;
304  } else if (fileName.EndsWith(".gdml") ) {
305  cout << "-I- Constructing RICH geometry from GDML file: " << fileName.Data() << endl;
307  } else {
308  Fatal("CbmRich::ConstructGeometry", "Geometry format of RICH geometry file is not supported");
309  }
310 }
311 
313 {
315  FairGeoInterface* geoFace = geoLoad->getGeoInterface();
316  CbmGeoRich* richGeo = new CbmGeoRich();
317  richGeo->setGeomFile(GetGeometryFileName());
318  geoFace->addGeoModule(richGeo);
319 
320  Bool_t rc = geoFace->readSet(richGeo);
321  if (rc) richGeo->create(geoLoad->getGeoBuilder());
322  TList* volList = richGeo->getListOfVolumes();
323 
324  // store geo parameter
325  FairRun *fRun = FairRun::Instance();
327  CbmGeoRichPar* par=(CbmGeoRichPar*)(rtdb->getContainer("CbmGeoRichPar"));
328  TObjArray *fSensNodes = par->GetGeoSensitiveNodes();
329  TObjArray *fPassNodes = par->GetGeoPassiveNodes();
330 
331  TListIter iter(volList);
332  FairGeoNode* node = NULL;
333  FairGeoVolume *aVol=NULL;
334 
335  while( (node = (FairGeoNode*)iter.Next()) ) {
336  aVol = dynamic_cast<FairGeoVolume*> ( node );
337  if ( node->isSensitive() ) {
338  fSensNodes->AddLast( aVol );
339  }else{
340  fPassNodes->AddLast( aVol );
341  }
342  }
343  par->setChanged();
344  par->setInputVersion(fRun->GetRunId(),1);
345 
346  ProcessNodes ( volList );
347 
348  // add support structure for mirrors
349  TGeoMaterial * matAl = new TGeoMaterial("Al", 26.98, 13, 2.7);
350  TGeoMedium * Al = new TGeoMedium("Al",1, matAl);
351  TGeoVolume * volume = gGeoManager->MakeTube("grid", Al, 1.3, 1.5, 180);
352 
353  gGeoManager->Matrix(123456, 180, 0, 90, 90 , 90 , 0);//z rotation
354  gGeoManager->Matrix(123457, 90, 0, 180, 0, 90, 90);// y rotation
355 
356  Double_t * buf = 0;
357  for (Int_t i = 0; i< 11; i++) {
358  if (i == 5) continue;
359  gGeoManager->Node("grid", 2*i+1, "rich1gas3", 36*i - 180, 0, 40, 123457, kTRUE, buf, 0);
360  gGeoManager->Node("grid", 2*i+2, "rich1gas3", 0, 36*i - 180, 48, 123456, kTRUE, buf, 0);
361  }
362 }
363 
364 #define _RICH_GAS_VOLUME_ ("RICH_gas_1")
365 #define _AEROGEL_MEDIUM_ ("Aerogel")
366 
367 TGeoVolume *CbmRich::GetGasVolume(TGeoVolume *current)
368 {
369  // Hardcoded to the moment;
370  if (!strcmp(current->GetName(), _RICH_GAS_VOLUME_)) return current;
371 
372  for (unsigned nd=0; nd<current->GetNdaughters(); nd++) {
373  TGeoNode *node = current->GetNode(nd);
374  TGeoVolume *volume = node->GetVolume();
375 
376  if (!strcmp(volume->GetName(), _RICH_GAS_VOLUME_)) return volume;
377 
378  TGeoVolume *ret = GetGasVolume(volume);
379  if (ret) return ret;
380  } //for nd
381 
382  return 0;
383 } // CbmRich::GetGasVolume()
384 
385 #include <assert.h>
386 #include <TGeoBBox.h>
387 //#include <EicMediaHub.h>
388 
389 //
390 // NB: one needs to re-define GetScale() function in TGDMLParse as
391 //
392 // protected:
393 // virtual TString GetScale(const char* unit);
394 //
395 // and recompile (make install) ROOT to have this working;
396 //
397 
398 class EicGDMLParse: public TGDMLParse
399 {
400 public:
401  EicGDMLParse(): mScale(1.0) {};
403 
404  TGeoVolume *GDMLReadFile(const char* filename, double scale = 1.0) {
405  mScale = scale;
406 
407  return TGDMLParse::GDMLReadFile(filename);
408  };
409 
410  TString GetScale(const char* unit) {
411  double extraScale = 0.0;
412 
413  // Well, same quality code as original TGDMLParse.cxx, sorry;
414  if (strcmp(unit, "mm") == 0)
415  extraScale = 0.1;
416  else if (strcmp(unit, "milimeter") == 0)
417  extraScale = 0.1;
418  else if (strcmp(unit, "cm") == 0)
419  extraScale = 1.0;
420  else if (strcmp(unit, "centimeter") == 0)
421  extraScale = 1.0;
422  else if (strcmp(unit, "m") == 0)
423  extraScale = 100.0;
424  else if (strcmp(unit, "meter") == 0)
425  extraScale = 100.0;
426  else if (strcmp(unit, "km") == 0)
427  extraScale = 100000.0;
428  else if (strcmp(unit, "kilometer") == 0)
429  extraScale = 100000.0;
430 
431  if (extraScale)
432  // Pattern found -> proceed and return;
433  return TString::Format("%f", extraScale * mScale);
434  else
435  // Perhaps angular units, etc -> fall back to the original TGDMLParse call;
436  //return TGDMLParse::GetScale(unit);
437  assert(0);
438  };
439 
440 private:
441  double mScale;
442 };
443 
444 void CbmRich::ConstructGdmlGeometry(TGeoMatrix* geoMatrix)
445 {
446  TFile *old = gFile;
447  //@@@TGDMLParse parser;
449  TGeoVolume* gdmlTop;
450  gdmlTop = parser.GDMLReadFile(GetGeometryFileName(), mScale);
451  //gdmlTop = parser.GDMLReadFile(GetGeometryFileName().Data());
452  gGeoManager->GetTopVolume()->AddNode(gdmlTop,1,geoMatrix);
453  //gGeoManager->GetTopVolume()->AddNode(gdmlTop,1, new TGeoScale(0.5, 0.5, 0.5));
454  ExpandNodeForGdml(gGeoManager->GetTopVolume()->GetNode(gGeoManager->GetTopVolume()->GetNdaughters()-1));
455  fIsFirstGDML = 0;
456  gFile = old;
457 
458  // Hardcode colors, sorry; this crap should disappear from the distribution eventually anyway
459  // and be replaced by a proper RICH geometry and other stuff;
460  {
461  // Set up colors and transparency values;
462  TIter next( gGeoManager->GetListOfVolumes() );
463 
464  TGeoVolume *volume;
465 
466  while ((volume=(TGeoVolume*)next())) {
467  TString name = volume->GetName();
468 
469  if (name.BeginsWith("RICH_pipe"))
470  volume->SetVisibility(kFALSE);
471  else if (name.BeginsWith("RICH_gas") || name.EqualTo("RICH_small_frame_container"))
472  volume->SetVisibility(kFALSE);
473  else if (name.BeginsWith("RICH_PMT")) {
474  volume->SetLineColor(kRed);
475  volume->SetFillColor(kRed);
476  volume->SetFillStyle(4000+40);
477  }
478  else if (name.BeginsWith("RICH_covering")) {
479  volume->SetLineColor(kMagenta);
480  volume->SetFillColor(kMagenta);
481  volume->SetFillStyle(4000+40);
482  }
483  else if (name.BeginsWith("RICH_main_frame_trap_pillar")) {
484  volume->SetLineColor(kMagenta);
485  volume->SetFillColor(kMagenta);
486  volume->SetFillStyle(4000+70);
487  }
488  else if (name.BeginsWith("RICH_mirror_support_belt_pillar")) {
489  volume->SetLineColor(kBlack);
490  volume->SetFillColor(kBlack);
491  volume->SetFillStyle(4000+50);
492  }
493  else if (name.BeginsWith("RICH_mirror")) {
494  volume->SetLineColor(kGray);
495  volume->SetFillColor(kGray);
496  //volume->SetTransparency(40);
497  } //if
498  } //while
499  }
500 
501  // Add aerogel volume by hand; not really possible with the present CBM design;
502 #if _LATER_
503  //EicMediaHub *mediaHub = new EicMediaHub((char *)"Aerogel");
504  //assert(mediaHub);
505  //mediaHub->Init();
506  //assert(mediaHub->fSingleMedium);
507 
508  // Not the most economic way, but GDML file have very few nodes in
509  // the tree, so overhead is small;
510  TGeoVolume *gasVolume = GetGasVolume(gdmlTop);
511  assert(gasVolume);
512  TGeoBBox *aerogel = new TGeoBBox("Aerogel", 10., 10., 2.5);
513  TGeoMedium *medium = gGeoManager->GetMedium(_AEROGEL_MEDIUM_);
514  //assert(medium);
515  if (!medium) {
517  FairGeoInterface *geoFace = geoLoad->getGeoInterface();
518 
519  FairGeoMedia *Media = geoFace->getMedia();
520  FairGeoBuilder *geobuild = geoLoad->getGeoBuilder();
521 
522  FairGeoMedium *fmedium = Media->getMedium(_AEROGEL_MEDIUM_);
523  // Would mean no such medium in media.geo file;
524  assert(fmedium);
525 
526  geobuild->createMedium(fmedium);
527 
528  // Should not happen;
529  medium = gGeoManager->GetMedium(_AEROGEL_MEDIUM_);
530  assert(medium);
531  }
532 
533  TGeoVolume *vaerogel = new TGeoVolume("Aerogel", aerogel, /*mediaHub->fSingleMedium*/medium);
534  gasVolume->AddNode(vaerogel, 0, 0, 0);
535  vaerogel->RegisterYourself();
536 #endif
537 }
538 
539 void CbmRich::ExpandNodeForGdml(TGeoNode* node)
540 {
541  TGeoVolume* curVol = node->GetVolume();
542 
544  if (!curVol->IsAssembly()) {
545  TString curMedName = node->GetMedium()->GetName();
546  TGeoMedium* curMedInGeoManager = gGeoManager->GetMedium(curMedName);
547  Int_t matIndToDel = gGeoManager->GetMaterialIndex(curMedName);
548 
549  if (curMedName.BeginsWith("G4_")) {
550  curMedName.Remove(0, 3);
551  }
552 
553  Int_t nmed;
554 
556  FairGeoInterface* geoFace = geoLoad->getGeoInterface();
557  FairGeoMedia* geoMediaBase = geoFace->getMedia();
558  FairGeoBuilder* geobuild = geoLoad->getGeoBuilder();
559  FairGeoMedium* curMedInGeo;
560 
561  if (curMedInGeoManager == 0) {
562  std::cout << "[ExpandNodeForGDML] New medium found in gmdl - it is not in gGeoManager list." << std::endl;
566  } else {
569 
570  curMedInGeo = geoMediaBase->getMedium(curMedName);
571  if (curMedInGeo == 0)
572  {
573  printf("Q: %s!\n", curMedName.Data());
574  std::cout << "[ExpandNodeForGDML] Media not found in Geo file." << std::endl;
578  }
579  else
580  {
581  if (fFixedMats.find(curMedName) == fFixedMats.end()) {
582  nmed = geobuild->createMedium(curMedInGeo);
583  fFixedMats[curMedName] = gGeoManager->GetListOfMedia()->GetEntries();
584  }
585  node->GetVolume()->SetMedium(gGeoManager->GetMedium(curMedName));
586  gGeoManager->SetAllIndex();
587  }
588  }
589 
591  if (curMedInGeo->getSensitivityFlag()) {
592  AddSensitiveVolume(curVol);
593  }
594  }
595 
597  if (curVol->GetNdaughters() != 0)
598  {
599  TObjArray* NodeChildList = curVol->GetNodes();
600  TGeoNode* curNodeChild;
601  for (Int_t j=0; j<NodeChildList->GetEntriesFast(); j++)
602  {
603  curNodeChild = (TGeoNode*)NodeChildList->At(j);
604  ExpandNodeForGdml(curNodeChild);
605  }
606  }
607 }
608 
610  Int_t trackID,
611  Int_t pdg,
612  Int_t detID,
613  TVector3 pos,
614  TVector3 mom,
615  Double_t time,
616  Double_t length,
617  Double_t eLoss)
618 {
619  TClonesArray& clref = *fRichPoints;
620  Int_t size = clref.GetEntriesFast();
621  //printf("%d\n", trackID);
622  return new(clref[size]) CbmRichPoint(trackID, pdg, detID, pos, mom, time,length, eLoss);
623 }
624 
626  Int_t trackID,
627  Int_t detID,
628  TVector3 pos,
629  TVector3 mom,
630  Double_t time,
631  Double_t length,
632  Double_t eLoss)
633 {
634  TClonesArray& clref = *fRichRefPlanePoints;
635  Int_t tsize = clref.GetEntriesFast();
636  return new(clref[tsize]) CbmRichPoint(trackID, 0, detID, pos, mom, time,length, eLoss);
637 }
638 
640  Int_t trackID,
641  Int_t detID,
642  TVector3 pos,
643  TVector3 mom,
644  Double_t time,
645  Double_t length,
646  Double_t eLoss)
647 {
648  TClonesArray& clref = *fRichMirrorPoints;
649  Int_t tsize = clref.GetEntriesFast();
650  return new(clref[tsize]) CbmRichPoint(trackID, 0, detID, pos, mom, time,length, eLoss);
651 }
652