StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StiPxlDetectorBuilder.cxx
1 /* $Id: StiPxlDetectorBuilder.cxx,v 1.118 2017/11/01 21:13:14 smirnovd Exp $ */
2 
3 #include <assert.h>
4 #include <sstream>
5 #include <string>
6 
7 #include "TGeoVolume.h"
8 #include "TGeoMatrix.h"
9 #include "TVector3.h"
10 
11 #include "Sti/StiPlanarShape.h"
12 #include "Sti/StiCylindricalShape.h"
13 #include "Sti/StiMaterial.h"
14 #include "Sti/StiPlacement.h"
15 #include "Sti/StiDetector.h"
16 #include "Sti/Base/Factory.h"
17 #include "Sti/StiToolkit.h"
19 #include "StiPxl/StiPxlDetectorBuilder.h"
21 #include "StiPxl/StiPxlHitErrorCalculator.h"
22 #include "tables/St_HitError_Table.h"
23 #include "StEvent/StEvent.h"
24 #include "StEvent/StEventTypes.h"
25 #include "StPxlDbMaker/StPxlDb.h"
26 #include "StPxlDbMaker/StPxlDbMaker.h"
27 #include "StPxlUtil/StPxlConstants.h"
28 #include "StBFChain/StBFChain.h"
29 
30 
31 
41 StiPxlDetectorBuilder::StiPxlDetectorBuilder(bool active, bool buildIdealGeom) :
42  StiDetectorBuilder("Pixel", active), mBuildIdealGeom(buildIdealGeom), mPxlDb(0)
43 {
44  setGroupId(kPxlId);
45 }
46 
47 
52 {
53  if (!gGeoManager)
54  throw runtime_error("StiPxlDetectorBuilder::StiPxlDetectorBuilder() "
55  "- Cannot build Sti geometry due to missing global object of TGeoManager class. "
56  "Make sure STAR geometry is properly loaded with BFC AgML option");
57 
58  SetCurrentDetectorBuilder(this);
59 
60  // Access the (survey) geometry if requested by the user
61  if (!mBuildIdealGeom) {
62  TObjectSet *pxlDbDataSet = (TObjectSet*) source.GetDataSet("pxl_db");
63 
64  if (!pxlDbDataSet) {
65  LOG_ERROR << "StiPxlDetectorBuilder::buildDetectors() - PXL geometry was requested from "
66  "DB but no StPxlDb object found. Check for pxlDb option in BFC chain" << endm;
67  exit(EXIT_FAILURE);
68  }
69 
70  mPxlDb = (StPxlDb*) pxlDbDataSet->GetObject();
71  assert(mPxlDb);
72 
73  LOG_INFO << "StiPxlDetectorBuilder::buildDetectors() - Will build PXL geometry from DB tables" << endm;
74  }
75 
76  // Gas material must be defined. Here we use air properties
77  const TGeoMaterial* geoMat = gGeoManager->GetMaterial("AIR");
78 
79  _gasMat = geoMat ? add(new StiMaterial(geoMat->GetName(), geoMat->GetZ(), geoMat->GetA(), geoMat->GetDensity(), geoMat->GetRadLen()))
80  : add(new StiMaterial("AIR", 7.3, 14.61, 0.001205, 30420.));
81 
82  if (StiVMCToolKit::GetVMC()) {
84  buildInactiveVolumes();
85  }
86 }
87 
88 
96 {
97  // Define silicon material used in manual construction of sensitive layers in this builder
98  const TGeoMaterial* geoMat = gGeoManager->GetMaterial("SILICON");
99 
100  StiMaterial* silicon = geoMat ? add(new StiMaterial(geoMat->GetName(), geoMat->GetZ(), geoMat->GetA(), geoMat->GetDensity(), geoMat->GetRadLen()))
101  : add(new StiMaterial("SILICON", 14, 28.0855, 2.33, 9.36) );
102 
103  // Use the "middle" sensor on the ladder to extract alignment corrections from DB
104  int iSensor = floor(kNumberOfPxlSensorsPerLadder/2);
105 
106  for (int iSector = 1; iSector <= kNumberOfPxlSectors; ++iSector)
107  {
108  for (int iLadder = 1; iLadder <= kNumberOfPxlLaddersPerSector; ++iLadder)
109  {
110  std::string geoPath( formTGeoPath(iSector, iLadder, iSensor) );
111 
112  if ( geoPath.empty() ) {
113  LOG_WARN << "StiPxlDetectorBuilder::useVMCGeometry() - Cannot find path to PLAC (PXL sensitive) node. Skipping to next ladder..." << endm;
114  continue;
115  }
116 
117  TGeoVolume* sensorVol = gGeoManager->GetCurrentNode()->GetVolume();
118  TGeoHMatrix sensorMatrix( *gGeoManager->MakePhysicalNode(geoPath.c_str())->GetMatrix() );
119 
120  // Temporarily save the translation for this sensor in Z so, we can center
121  // the newly built sensors at Z=0 (in ideal geometry) later
122  double idealOffsetZ = sensorMatrix.GetTranslation()[2];
123 
124  if (!mBuildIdealGeom) {
125  const TGeoHMatrix* sensorMatrixDb = mPxlDb->geoHMatrixSensorOnGlobal(iSector, iLadder, iSensor);
126 
127  if (!sensorMatrixDb) {
128  LOG_WARN << "StiPxlDetectorBuilder::useVMCGeometry() - Cannot get PXL sensor position matrix. Skipping to next ladder..." << endm;
129  continue;
130  }
131 
132  sensorMatrix = *sensorMatrixDb;
133  }
134 
135  // Update the global translation in Z so that the new volumes are centered at Z=0
136  sensorMatrix.SetDz(sensorMatrix.GetTranslation()[2] - idealOffsetZ);
137 
138  TGeoBBox *sensorBBox = (TGeoBBox*) sensorVol->GetShape();
139 
140  // Split the ladder in two halves
141  for (int iLadderHalf = 1; iLadderHalf <= 2; iLadderHalf++) {
142  // Create new Sti shape based on the sensor geometry
143  std::string halfLadderName(geoPath + (iLadderHalf == 1 ? "_HALF1" : "_HALF2") );
144  double sensorLength = kNumberOfPxlSensorsPerLadder * (sensorBBox->GetDZ() + 0.02); // halfDepth + 0.02 ~= (dead edge + sensor gap)/2
145  StiShape *stiShape = new StiPlanarShape(halfLadderName.c_str(), sensorLength, 2*sensorBBox->GetDY(), sensorBBox->GetDX()/2);
146 
147  TVector3 offset((iLadderHalf == 1 ? -sensorBBox->GetDX()/2 : sensorBBox->GetDX()/2), 0, 0);
148  StiPlacement *pPlacement= new StiPlacement(sensorMatrix, offset);
149 
150  // Build final detector object
151  StiDetector *stiDetector = getDetectorFactory()->getInstance();
152  StiIsActiveFunctor* isActive = _active ? new StiPxlIsActiveFunctor :
153  static_cast<StiIsActiveFunctor*>(new StiNeverActiveFunctor);
154 
155  stiDetector->setProperties(halfLadderName, isActive, stiShape, pPlacement, getGasMat(), silicon);
156  stiDetector->setHitErrorCalculator(StiPxlHitErrorCalculator::instance());
157 
158  // Convert geo sensor id to Sti indices. We do not check the validity
159  // of returned values because the input is valid a priori in this case
160  int stiRow, stiSensor;
161  convertSensor2StiId(iSector, iLadder, iLadderHalf, stiRow, stiSensor);
162 
163  // Add created sensitive PXL layer to Sti
164  add(stiRow, stiSensor, stiDetector);
165  }
166  }
167  }
168 }
169 
170 
184 const StiDetector* StiPxlDetectorBuilder::getActiveDetector(int sector, int ladder, int sensorHalf) const
185 {
186  int stiRow, stiSensor;
187  convertSensor2StiId(sector, ladder, sensorHalf, stiRow, stiSensor);
188 
189  return stiRow < 0 ? 0 : getDetector(stiRow, stiSensor);
190 }
191 
192 
198 std::string StiPxlDetectorBuilder::formTGeoPath(int sector, int ladder, int sensor)
199 {
200  const std::string tgeoPathToMother("/HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1");
201 
202  std::ostringstream geoPath;
203 
204  geoPath << tgeoPathToMother << "/PXLA_" << sector
205  << "/LADR_" << ladder
206  << "/PXSI_" << sensor
207  << "/PLAC_1";
208 
209  bool found = gGeoManager->cd( geoPath.str().c_str() );
210 
211  // Look for ladders staged in the mother volume
212  if ( !found )
213  {
214  geoPath.str("");
215  geoPath << tgeoPathToMother << "/LADR_" << 4*(sector - 1) + ladder
216  << "/PXSI_" << sensor
217  << "/PLAC_1";
218  found = gGeoManager->cd( geoPath.str().c_str() );
219  }
220 
221  // Look for sensors staged in the mother volume
222  if ( !found )
223  {
224  geoPath.str("");
225  geoPath << tgeoPathToMother << "/PXSI_" << 40*(sector - 1) + 10*(ladder - 1) + sensor
226  << "/PLAC_1";
227  found = gGeoManager->cd( geoPath.str().c_str() );
228  }
229 
230  return found ? geoPath.str() : "";
231 }
232 
233 
235 void StiPxlDetectorBuilder::buildInactiveVolumes()
236 {
237  // Build average inactive volumes
238  const VolumeMap_t pxlVolumes[] = {
239  {"DTUH", "Dtube part of pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
240 
241  // Planar components of the pixel sector support .../PSUP_\d/...
242  {"PSHA", "Detail in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
243  {"PSHC", "Detail in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
244  {"PSHE", "Detail in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
245  {"PSHG", "Detail in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
246  {"PSAL", "Long tube in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
247  {"PSAK", "Short tube in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
248  {"PSCL", "Plane in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
249  {"PSCK", "Detail in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
250  {"PSAB", "Detail in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
251  {"PSAE", "Detail in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
252  {"PSMD", "Detail in half pixel support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1", "", ""},
253 
254  // The following are the largest planar components of the central pixel
255  // sector support .../PXLA_\d/...
256  {"PXRB", "Pixel sector support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
257  {"PXTR", "Pixel sector support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
258  {"PXTM", "Pixel sector support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
259  {"PXTL", "Pixel sector support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
260  {"PXLB", "Pixel sector support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
261  {"PXIB", "Pixel sector support", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
262 
263  // Inactive material close to silicon layers
264  { "DRIV", "Driver Board", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
265  { "GLUA", "Glu layer A", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
266  { "GLUB", "Glu layer B", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
267  { "GLUC", "Glu layer C", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
268  { "ALCA", "Aluminium cable", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
269  { "CFBK", "Carbon Fiber Backing", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PXMO_1", "", ""},
270 
271  // These are the components of the pixel support tube (PSTM)
272  { "APTS1", "Tube shell", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PSTM_1/APTS_1", "", ""},
273  { "PITN1", "Pixel insertion TubeNaked", "HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/PSTM_1/PITN_1", "", ""}
274  };
275 
276  int nPxlVolumes = sizeof(pxlVolumes) / sizeof(VolumeMap_t);
277 
278  for (int i = 0; i < nPxlVolumes; i++) {
279 
280  if (! gGeoManager->cd(pxlVolumes[i].path) ) {
281  LOG_WARN << "StiPxlDetectorBuilder::buildInactiveVolumes() - Cannot find path to '"
282  << pxlVolumes[i].name << "' node. Skipping to next node..." << endm;
283  continue;
284  }
285 
286  TGeoNode *geoNode = gGeoManager->GetCurrentNode();
287 
288  if (!geoNode) continue;
289 
290  StiVMCToolKit::LoopOverNodes(geoNode, pxlVolumes[i].path, pxlVolumes[i].name, MakeAverageVolume);
291  }
292 }
293 
294 
327 void StiPxlDetectorBuilder::convertSensor2StiId(int sector, int ladder, int sensorHalf, int& stiRow, int& stiSensor)
328 {
329  // Check validity of input values
330  if (sector < 1 || sector > kNumberOfPxlSectors ||
331  ladder < 1 || ladder > kNumberOfPxlLaddersPerSector ||
332  sensorHalf < 1 || sensorHalf > 2)
333  {
334  stiRow = stiSensor = -1;
335  return;
336  }
337 
338  if (ladder == 1) {
339  stiRow = sensorHalf == 1 ? 0 : 1;
340  stiSensor = (sector - 1);
341  } else { // ladder = 2, 3, 4
342  stiRow = sensorHalf == 1 ? 2 : 3;
343  stiSensor = (sector - 1) * (kNumberOfPxlLaddersPerSector - 1) + (ladder - 2);
344  }
345 }
void setProperties(std::string name, StiIsActiveFunctor *activeFunctor, StiShape *shape, StiPlacement *placement, StiMaterial *gas, StiMaterial *material)
virtual void buildDetectors(StMaker &source)
virtual Abstract * getInstance()=0
Get a pointer to instance of objects served by this factory.
StiPxlDetectorBuilder(bool active, bool buildIdealGeom=true)
const StiDetector * getActiveDetector(int sector, int ladder, int sensorHalf) const
function object for determine a detector&#39;s active regions
Abstract interface for a STI toolkit.
function object for determine a Pixel padrow&#39;s active regions
virtual TObject * GetObject() const
The depricated method (left here for the sake of the backward compatibility)
Definition: TObjectSet.h:56
Class implements an object which is never active.