StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StiPixelDetectorBuilder.cxx
1 // 12/12/2012 : modification of the builder to take into account the new geometry path names
2 // backward compatibility with upgr15 geometry is lost
3 /*
4  * $Id: StiPixelDetectorBuilder.cxx,v 1.32 2014/08/22 17:47:53 perev Exp $
5  *
6  * $Log: StiPixelDetectorBuilder.cxx,v $
7  * Revision 1.32 2014/08/22 17:47:53 perev
8  * Remove never used input file
9  *
10  * Revision 1.31 2014/01/30 16:50:59 didenko
11  * get back to previous revision
12  *
13  * Revision 1.29 2013/03/11 17:24:08 bouchet
14  * StiRnD for Y2013
15  *
16  * Revision 1.28 2012/12/18 20:52:32 bouchet
17  * update for DEV13 geometry
18  *
19  * Revision 1.27 2011/04/22 22:00:18 fisyak
20  * warn off
21  *
22  * Revision 1.26 2010/08/25 21:57:41 fisyak
23  * Get rid off access to specfic detector tracking parameters which usage has been disable since 2008/06/11
24  *
25  * Revision 1.25 2009/03/16 13:51:00 fisyak
26  * Move out all Sti Chairs into StDetectorDb
27  *
28  * Revision 1.24 2009/02/09 02:47:19 andrewar
29  * UPGR15 update. Will break backward compatibility with older geometries.
30  *
31  * Revision 1.23 2008/04/03 20:04:20 fisyak
32  * Straighten out DB access via chairs
33  *
34  * Revision 1.22 2007/10/20 00:16:27 fisyak
35  * Active hit errors from DB
36  *
37  * Revision 1.21 2007/10/16 19:50:24 fisyak
38  * rename Hft => Pxl, remove Hpd, Igt and Fst
39  *
40  * Revision 1.20 2007/05/16 15:02:57 andrewar
41  * Removed couts in favor of LOG_INFO.
42  *
43  * Revision 1.19 2007/05/03 06:14:56 andrewar
44  * Geometry fix to conform to StiHit:setGlobal() test.
45  *
46  * Revision 1.18 2007/03/30 02:14:19 andrewar
47  * Removed some debug output.
48  *
49  * Revision 1.17 2006/11/30 16:37:19 andrewar
50  * Removed call to dbase for tracking parameter loading for the review. Dynamic
51  * access will be debugged and restored after the STAR review. Hit errors are
52  * forced to 60um.
53  *
54  * Revision 1.16 2006/11/29 04:02:01 andrewar
55  * Make use of pre-existing STAR DB inteface.
56  *
57  * Revision 1.15 2006/11/29 00:44:04 andrewar
58  * Added call to get tracking parameters from DBase.
59  *
60  * Revision 1.14 2006/11/17 15:39:03 wleight
61  * Changes to make PXL hits work with UPGR05 geometry
62  *
63  * Revision 1.13 2006/04/19 19:49:47 andrewar
64  * Added call to setLayerAngle, needed for detector container sort.
65  *
66  * Revision 1.12 2006/02/23 00:22:54 andrewar
67  * Set Detector Id to kPxlId, corrected Ist*pars -> Pixel*pars
68  *
69  * Revision 1.11 2006/02/17 21:39:32 andrewar
70  * Added calls to StiDetector::setKey(key,val)
71  *
72  *
73  */
74 
75 /*
76  numbering should be the following :
77  hardware : sector ladder ITTF : layer ladder
78  1 1 1 0
79  1 2 1 1
80  1 3 1 2
81  1 4 0 0
82 
83  2 1 1 3
84  2 2 1 4
85  2 3 1 5
86  2 4 0 1
87  (...)
88  10 1 1 27
89  10 2 1 28
90  10 3 1 29
91  10 4 0 9
92 */
93 
94 #include <stdio.h>
95 #include <stdexcept>
96 #include "Sti/StiPlanarShape.h"
97 #include "Sti/StiCylindricalShape.h"
98 #include "Sti/StiMaterial.h"
99 #include "Sti/StiPlacement.h"
100 #include "Sti/StiDetector.h"
101 #include "Sti/Base/Factory.h"
102 #include "Sti/StiToolkit.h"
103 #include "StiPixelIsActiveFunctor.h"
105 //#include "Sti/StiElossCalculator.h"
106 #include "StiPixelDetectorBuilder.h"
107 #include "StiPixelIsActiveFunctor.h"
108 #include "StDetectorDbMaker/StiPixelHitErrorCalculator.h"
109 #include "TDataSetIter.h"
110 #include "tables/St_HitError_Table.h"
111 #include "StEvent.h"
112 #include "StEventTypes.h"
113 
114 StiPixelDetectorBuilder::StiPixelDetectorBuilder(bool active)
115  : StiDetectorBuilder("Pixel",active)
116 {
117  //Parameterized hit error calculator. Given a track (dip, cross, pt, etc)
118  //returns average error once you actually want to do tracking, the results
119  //depend strongly on the numbers below.
120 }
121 
122 StiPixelDetectorBuilder::~StiPixelDetectorBuilder()
123 {}
124 
127 {
128 
129  char name[50];
130  LOG_INFO << "StiPixelDetectorBuilder::buildDetectors() -I- Started" << endm;
131 
132 
133  unsigned int nRows=2;
134 
135  // 2 real rows, but we have detector elements and support elements.
136  setNRows(nRows);
137 
138  if (StiVMCToolKit::GetVMC()) {useVMCGeometry(); return;}
139 
140  //_gas is the gas that the pixel detector lives in
141  _gasMat = add(new StiMaterial("PixelAir",7.3, 14.61, 0.001205, 30420.*0.001205, 7.3*12.e-9));
142  //_fcMaterial is the (average) material that makes up the detector elements. Here I use ~silicon
143  //StiMaterial * material = add(new StiMaterial("PixelSi", 14., 28.0855, 2.33, 21.82, 14.*12.*1e-9) );
144  _siMat = add(new StiMaterial("PixelSi", 14., 28.0855, 2.33, 21.82, 14.*12.*1e-9) );
145  _hybridMat = add(new StiMaterial("PixelHyb", 14., 28.0855, 2.33, 21.82, 14.*12.*1e-9) );
146 
147  //Instantiate energy loss detector for si material
148  //const static double I2Ar = (15.8*18) * (15.8*18) * 1e-18; // GeV**2
149  //double ionization = material->getIonization();
150 // double ionization = _siMat->getIonization();
151 
152 // StiElossCalculator * siElossCalculator = new StiElossCalculator(_siMat->getZOverA(),
153 // ionization*ionization,
154 // _siMat->getA(),
155 // _siMat->getZ(),
156 // _siMat->getDensity());
157  StiPlanarShape *pShape;
158  for (unsigned int row=0; row<nRows; row++)
159  {
160  pShape = new StiPlanarShape;
161  if (!pShape) throw runtime_error("StiPixelDetectorBuilder::buildDetectors() - FATAL - pShape==0||ifcShape==0");
162  sprintf(name, "Pixel/Layer_%d", row);
163  pShape->setName(name);
164  pShape->setThickness(0.0280); //cm
165  pShape->setHalfDepth( 20./2. );
166  pShape->setHalfWidth(1.0);
167  for(unsigned int sector = 0; sector<24; sector++)
168  {
169  StiPlacement *pPlacement = new StiPlacement;
170  pPlacement->setZcenter(0.);
171  double phi = phiForPixelSector(sector) + psiForPixelSector(sector);
172  double r = radiusForPixelSector(sector)* cos(psiForPixelSector(sector)) - 0.0040; // note 40 microns offset
173  double dY = radiusForPixelSector(sector)*sin(psiForPixelSector(sector));
174  /*printf(" sector: %g phi: %g radius: %g normal: %g dY: %g\n",sector
175  ,phi*180/3.1415
176  << " radius:"<<radiusForPixelSector(sector)
177  << " normal r:"<<r
178  << " dY:"<<dY<<endl;*/
179  pPlacement->setNormalRep(phi, r, dY);
180  pPlacement->setLayerRadius(r);
181  pPlacement->setLayerAngle(phi);
182  pPlacement->setRegion(StiPlacement::kMidRapidity);
183  sprintf(name, "Pixel/Layer_%d/Ladder_%d", row, sector);
184  StiDetector *pDetector = _detectorFactory->getInstance();
185  pDetector->setName(name);
186  pDetector->setIsOn(true);
187  pDetector->setIsActive(new StiPixelIsActiveFunctor);
188  pDetector->setIsContinuousMedium(true);
189  pDetector->setIsDiscreteScatterer(false);
190  pDetector->setMaterial(_siMat);
191  pDetector->setGas(_gasMat);
192  pDetector->setGroupId(kPxlId);
193  pDetector->setShape(pShape);
194  pDetector->setPlacement(pPlacement);
195  pDetector->setHitErrorCalculator(StiPixelHitErrorCalculator::instance());
196 // pDetector->setElossCalculator(siElossCalculator);
197  if (sector<18)
198  {
199  pDetector->setKey(1,1);
200  pDetector->setKey(2,sector);
201  add(1,sector,pDetector);
202  }
203  else
204  {
205  pDetector->setKey(1,0);
206  pDetector->setKey(2,sector-18);
207  add(0,(sector-18),pDetector);
208  }
209 
210  //cout << "Setting detector: " << name << " with key values: "
211  // << pDetector->getKey(1) << " " << pDetector->getKey(2) << endl;
212  }
213  }
214  LOG_INFO << " -I- Done" << endl;
215 }
216 
217 void StiPixelDetectorBuilder::useVMCGeometry() {
218  LOG_INFO << "StiPixelDetectorBuilder::buildDetectors() -I- Use VMC geometry"
219  << endm;
220  SetCurrentDetectorBuilder(this);
221 
222  // Build materials. In the Pixel detector we have two: Air for the mother volume,
223  // silicon for both the detector and the ladder support. This will be updated with
224  // more detailed support structures at the appropriate time.
225  struct Material_t {
226  const Char_t *name;
227  StiMaterial **p;
228  };
229  Material_t map[] = {
230  {"AIR", &_gasMat},
231  {"SILICON", &_siMat},
232  {"SILICON", &_hybridMat}
233  };
234  Int_t M = sizeof(map)/sizeof(Material_t);
235  for (Int_t i = 0; i < M; i++)
236  {
237  const TGeoMaterial *mat = gGeoManager->GetMaterial(map[i].name);
238  if (! mat) continue;
239  Double_t PotI = StiVMCToolKit::GetPotI(mat);
240  *map[i].p = add(new StiMaterial(mat->GetName(),
241  mat->GetZ(),
242  mat->GetA(),
243  mat->GetDensity(),
244  mat->GetDensity()*mat->GetRadLen(),
245  PotI));
246  }
247 
248  //
249  // Build volumes. Will be done from GEANT tables.
250  //
251 
252  // Set volume name tree. Inactive volumes only here. Active volumes are declared in ::AverageVolume, called
253  // through loop over StiDetectorBuilder::AverageVolume
254  const VolumeMap_t PxlVolumes[] =
255  {
256  {"PLAC","Active ladder volume", "HALL_1/CAVE_1/IDSM_1/PXMO_1","",""}
257  //{"PXSI","InActive ladder volume", "HALL_1/CAVE_1/IDSM_1/PXMO_1","",""}
258  //{"SIFR","InActive ladder volume", "HALL_1/CAVE_1/IDSM_1/PXMO_1","",""}
259  };
260 
261  Int_t NoPxlVols = sizeof(PxlVolumes)/sizeof(VolumeMap_t);
262  gGeoManager->RestoreMasterVolume();
263  gGeoManager->CdTop();
264  for (Int_t i = 0; i < NoPxlVols; i++) {
265  gGeoManager->cd(PxlVolumes[i].path);
266  TGeoNode *nodeT = gGeoManager->GetCurrentNode();
267  if (! nodeT) continue;;
268  LOG_DEBUG <<" current node : " << i <<"/" << NoPxlVols <<" path is : " << PxlVolumes[i].name << endm;
269  StiVMCToolKit::LoopOverNodes(nodeT, PxlVolumes[i].path, PxlVolumes[i].name, MakeAverageVolume);
270  }
271 }
272 
273 void StiPixelDetectorBuilder::AverageVolume(TGeoPhysicalNode *nodeP)
274 {
275  // Handle pathalogical input
276  if (!nodeP)
277  {
278  LOG_INFO << "StiPixelDetectorBuilder::AverageVolume -E- no TGeoPhysicalNode. "
279  << " Perhaps Pixel is turned on in tracking, but not present in simulation. Returning."
280  << endm;
281 
282  return;
283  }
284 
285  // Note:
286  // Volumes are currently all planes. I am coding this routine appropriately. Other
287  // GEANT shapes (cylinder/sphere) are handled differently, and would require adding cases
288  // if such are added to the PXL geometry.
289  // AAR - Oct 31, 2006
290 
291  TString nameP(nodeP->GetName());
292 
293  TString temp=nameP;
294  temp.ReplaceAll("HALL_1/CAVE_1/IDSM_1/PXMO_1/","");
295  int q=temp.Index("_");
296  temp.Replace(0,q+1,"");
297  TString numsec=temp(0,2);
298  int sector=numsec.Atoi();
299 
300  q=temp.Index("_");
301  temp.Replace(0,q+1,"");
302  TString numlad=temp(0,2);
303  if(!numlad.IsDigit()) numlad=temp(0,1);
304  int ladder=numlad.Atoi();
305 
306  q=temp.Index("_");
307  temp.Replace(0,q+1,"");
308  TString numsens=temp(0,2);
309  if(!numsens.IsDigit()) numsens=temp(0,1);
310  int sensor=numsens.Atoi();
311 
312  if(sensor!=1) return;
313 
314  // Check whether this is an active volume
315  Bool_t ActiveVolume = kFALSE;
316  if (nodeP->GetVolume()->GetMedium()->GetParam(0) == 1) {
317  ActiveVolume = kTRUE;
318  LOG_DEBUG <<" this node is active " << endm;
319  }
320 
321  //Material definitions
322  TGeoMaterial *matP = nodeP->GetVolume()->GetMaterial();
323  Double_t PotI = StiVMCToolKit::GetPotI(matP);
324  static StiMaterial *matS = 0;
325  if (! matS) matS = add(new StiMaterial(matP->GetName(),
326  matP->GetZ(),
327  matP->GetA(),
328  matP->GetDensity(),
329  matP->GetDensity()*matP->GetRadLen(),
330  PotI));
331 // Double_t ionization = matS->getIonization();
332 // StiElossCalculator *ElossCalculator = new StiElossCalculator(matS->getZOverA(),
333 // ionization*ionization,
334 // matS->getA(),
335 // matS->getZ(),
336 // matS->getDensity());
337 
338 // Extract volume geometry for this node
339  TGeoBBox *box = (TGeoBBox *) nodeP->GetShape();
340  StiShape *sh = new StiPlanarShape(nodeP->GetVolume()->GetName(), // Name
341  10*box->GetDZ(), // halfDepth
342  box->GetDY(), // thickness
343  box->GetDX()); // halfWidth
344  add(sh);
345 
346  // position information
347  TGeoHMatrix *hmat = nodeP->GetMatrix(); if (debug()) hmat->Print("");
348  Double_t *xyz = hmat->GetTranslation();
349  Double_t *rot = hmat->GetRotationMatrix();
350  //StThreeVectorD centerVector(xyz[0],xyz[1],0.0);
351  StThreeVectorD centerVector(xyz[0],xyz[1],xyz[2]);
352  StThreeVectorD normalVector(rot[1],rot[4],rot[7]);
353 
354  Double_t prod = centerVector*normalVector;
355  if (prod < 0) normalVector *= -1;
356  // Normalize normal vector, just in case....
357  normalVector /= normalVector.magnitude();
358 
359  // Volume positioning
360  StiPlacement *pPlacement = new StiPlacement;
361  Double_t phi = centerVector.phi();
362  Double_t phiD = normalVector.phi();
363  Double_t r = centerVector.perp();
364  pPlacement->setZcenter(0);
365  pPlacement->setLayerRadius(r);
366 
367  //if(nameP.Contains("PLAC"))
368  pPlacement->setLayerAngle(phi);
369  pPlacement->setRegion(StiPlacement::kMidRapidity);
370  pPlacement->setNormalRep(phiD, r*TMath::Cos(phi-phiD), r*TMath::Sin(phi-phiD));
371  assert(pPlacement);
372 
373  //Build final detector object
374 
375  StiDetector *p =getDetectorFactory()->getInstance();
376  if ( !p )
377  {
378  LOG_INFO <<"StiPixelDetectorBuilder::AverageVolume() -E- StiDetector pointer invalid." <<endm;
379  return;
380  }
381  p->setName(nameP.Data());
382 
383  p->setIsOn(false);
384  if (ActiveVolume) {
385  p->setIsActive(new StiPixelIsActiveFunctor);
386  }
387  else {
388  p->setIsActive(new StiNeverActiveFunctor);
389  }
390  //layer=layer+10;
391  //if(nameP.Contains("SIFL")) {layer=layer+10;}
392  //if(nameP.Contains("SIFR")) {layer=layer+20;}
393  //}
394 
395  p->setIsContinuousMedium(false);
396  p->setIsDiscreteScatterer(true);
397  p->setShape(sh);
398  p->setPlacement(pPlacement);
399  p->setGas(GetCurrentDetectorBuilder()->getGasMat());
400  if(!p->getGas()) LOG_INFO <<"gas not there!"<<endm;
401  p->setMaterial(matS);
402 // p->setElossCalculator(ElossCalculator);
403  p->setHitErrorCalculator(StiPixelHitErrorCalculator::instance());
404 
405  Int_t ROW = 0;
406  Int_t SECTOR = 0;
407 
408  /* numbering is :
409  ladder = 0-1- ...9 for inner layer --> ROW =0
410  ladder = 0-1-2 for sector 0 of outer layer, then 3-4-5 for the second sector until 29 for the last sectro
411  ladder=4 is the inner ladder
412  */
413  if(ladder==4)
414  {
415  ROW =0 ;
416  SECTOR = sector-1;
417  }
418  else {
419  ROW = 1;
420  SECTOR = (sector-1)*3 + (ladder -1);
421  }
422  p->setKey(1, ROW);
423  p->setKey(2, SECTOR);
424  add(ROW,SECTOR, p);
425 
426  // Whole bunch of debugging information
427 
428  Float_t rad2deg = 180.0/3.1415927;
429  LOG_DEBUG << "===>NEW:PIXEL:pDetector:Name = " << p->getName() << endm;
430  LOG_DEBUG << "===>NEW:PIXEL:pPlacement:NormalRefAngle = " << pPlacement->getNormalRefAngle()*rad2deg << endm;
431  LOG_DEBUG << "===>NEW:PIXEL:pPlacement:NormalRadius = " << pPlacement->getNormalRadius() << endm;
432  LOG_DEBUG << "===>NEW:PIXEL:pPlacement:NormalYoffset = " << pPlacement->getNormalYoffset() << endm;
433  LOG_DEBUG << "===>NEW:PIXEL:pPlacement:CenterRefAngle = " << pPlacement->getCenterRefAngle()*rad2deg << endm;
434  LOG_DEBUG << "===>NEW:PIXEL:pPlacement:CenterRadius = " << pPlacement->getCenterRadius() << endm;
435  LOG_DEBUG << "===>NEW:PIXEL:pPlacement:CenterOrientation = " << pPlacement->getCenterOrientation()*rad2deg << endm;
436  LOG_DEBUG << "===>NEW:PIXEL:pPlacement:LayerRadius = " << pPlacement->getLayerRadius() << endm;
437  LOG_DEBUG << "===>NEW:PIXEL:pPlacement:LayerAngle = " << pPlacement->getLayerAngle()*rad2deg << endm;
438  LOG_DEBUG << "===>NEW:PIXEL:pPlacement:Zcenter = " << pPlacement->getZcenter() << endm;
439  LOG_DEBUG << "===>NEW:PIXEL:pDetector:sector = " << sector << endm;
440  LOG_DEBUG << "===>NEW:PIXEL:pDetector:Ladder = " << ladder << endm;
441  LOG_DEBUG << "===>NEW:PIXEL:pDetector:sensor = " << sensor << endm;
442  LOG_DEBUG << "===>NEW:PIXEL:pDetector:row/sector (ITTF) = " << ROW <<" / " << SECTOR << endm;
443  LOG_DEBUG << "===>NEW:PIXEL:pDetector:Active? = " << p->isActive() << endm;
444 
445 }
virtual void buildDetectors(StMaker &source)
Build all detector components of the Pixel detector.
virtual Abstract * getInstance()=0
Get a pointer to instance of objects served by this factory.
function object for determine a Pixel padrow&#39;s active regions
virtual void setNRows(UInt_t nRows)
Abstract interface for a STI toolkit.
double phiForPixelSector(unsigned int iSector) const
returns the azimuthal angle [-pi, pi) for tpc sector [1-24]
void setName(const string &newName)
Set the name of the object.
Definition: Named.cxx:15
const string & getName() const
Get the name of the object.
Definition: Named.cxx:22
Class implements an object which is never active.