StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StiIstDetectorBuilder.cxx
1 #include <assert.h>
2 #include <sstream>
3 #include <string>
4 
5 #include "TGeoVolume.h"
6 #include "TGeoMatrix.h"
7 #include "TVector3.h"
8 
9 #include "StMessMgr.h"
10 #include "StThreeVectorD.hh"
11 
12 #include "Sti/Base/Factory.h"
13 #include "Sti/StiPlanarShape.h"
14 #include "Sti/StiCylindricalShape.h"
15 #include "Sti/StiMaterial.h"
16 #include "Sti/StiPlacement.h"
17 #include "Sti/StiDetector.h"
18 #include "Sti/StiToolkit.h"
19 #include "Sti/StiIsActiveFunctor.h"
21 #include "StiIst/StiIstIsActiveFunctor.h"
22 #include "StiIst/StiIstDetectorBuilder.h"
23 #include "tables/St_HitError_Table.h"
24 #include "StEvent/StEvent.h"
25 #include "StEvent/StEnumerations.h"
26 #include "StEvent/StEventTypes.h"
27 #include "StDetectorDbMaker/StiIst1HitErrorCalculator.h"
28 #include "StIstDbMaker/StIstDb.h"
29 #include "StIstUtil/StIstConsts.h"
30 #include "StBFChain/StBFChain.h"
31 
32 
33 using namespace StIstConsts;
34 
35 
45 StiIstDetectorBuilder::StiIstDetectorBuilder(bool active, bool buildIdealGeom) :
46  StiDetectorBuilder("Ist", active), mBuildIdealGeom(buildIdealGeom), mIstDb(0)
47 {
48  setGroupId(kIstId);
49 }
50 
51 
56 {
57  if (!gGeoManager)
58  throw runtime_error("StiIstDetectorBuilder::StiIstDetectorBuilder() "
59  "- Cannot build Sti geometry due to missing global object of TGeoManager class. "
60  "Make sure STAR geometry is properly loaded with BFC AgML option");
61 
62  SetCurrentDetectorBuilder(this);
63 
64  if (!mBuildIdealGeom) {
65  TObjectSet *istDbDataSet = (TObjectSet *) source.GetDataSet("ist_db");
66 
67  if (!istDbDataSet) {
68  LOG_ERROR << "StiIstDetectorBuilder::buildDetectors() - IST geometry was requested from "
69  "DB but no StIstDb object found. Check for istDb option in BFC chain" << endm;
70  exit(EXIT_FAILURE);
71  }
72 
73  mIstDb = (StIstDb *) istDbDataSet->GetObject();
74  assert(mIstDb);
75 
76  LOG_INFO << "StiIstDetectorBuilder::buildDetectors() - Will build IST geometry from DB tables" << endm;
77  }
78 
79  // Gas material must be defined. Here we use air properties
80  const TGeoMaterial* geoMat = gGeoManager->GetMaterial("AIR");
81 
82  _gasMat = geoMat ? add(new StiMaterial(geoMat->GetName(), geoMat->GetZ(), geoMat->GetA(), geoMat->GetDensity(), geoMat->GetRadLen()))
83  : add(new StiMaterial("AIR", 7.3, 14.61, 0.001205, 30420.));
84 
85  if (StiVMCToolKit::GetVMC()) {
88  }
89 }
90 
91 
99 {
100  // Define silicon material used in manual construction of sensitive layers in this builder
101  const TGeoMaterial* geoMat = gGeoManager->GetMaterial("SILICON");
102 
103  StiMaterial* silicon = geoMat ? add(new StiMaterial(geoMat->GetName(), geoMat->GetZ(), geoMat->GetA(), geoMat->GetDensity(), geoMat->GetRadLen()))
104  : add(new StiMaterial("SILICON", 14, 28.0855, 2.33, 9.36) );
105 
106  // Use the "middle" sensor on the ladder to extract alignment corrections from DB
107  int iSensor = floor(kIstNumSensorsPerLadder/2);
108 
109  for (int iLadder = 1; iLadder <= kIstNumLadders; ++iLadder)
110  {
111  std::string geoPath( formTGeoPath(iLadder, iSensor) );
112 
113  if ( geoPath.empty() )
114  {
115  LOG_WARN << "StiIstDetectorBuilder::useVMCGeometry() - Cannot find path to IBSS (IST sensitive) node. Skipping to next ladder..." << endm;
116  continue;
117  }
118 
119  TGeoVolume* sensorVol = gGeoManager->GetCurrentNode()->GetVolume();
120  TGeoHMatrix sensorMatrix( *gGeoManager->MakePhysicalNode(geoPath.c_str())->GetMatrix() );
121 
122  // Temporarily save the translation for this sensor in Z so, we can center
123  // the newly built sensors at Z=0 (in ideal geometry) later
124  double idealOffsetZ = sensorMatrix.GetTranslation()[2];
125 
126  if (!mBuildIdealGeom) {
127  const TGeoHMatrix* sensorMatrixDb = mIstDb->getHMatrixSensorOnGlobal(iLadder, iSensor);
128 
129  if (!sensorMatrixDb) {
130  LOG_WARN << "StiIstDetectorBuilder::useVMCGeometry() - Cannot get IST sensor position matrix. Skipping to next ladder..." << endm;
131  continue;
132  }
133 
134  sensorMatrix = *sensorMatrixDb;
135  }
136 
137  // Update the global translation in Z so that the new volumes are centered at Z=0
138  sensorMatrix.SetDz(sensorMatrix.GetTranslation()[2] - idealOffsetZ);
139 
140  TGeoBBox *sensorBBox = (TGeoBBox*) sensorVol->GetShape();
141 
142  // Split the ladder in two halves
143  for (int iLadderHalf = 1; iLadderHalf <= 2; iLadderHalf++)
144  {
145  // Create new Sti shape based on the sensor geometry
146  std::string halfLadderName(geoPath + (iLadderHalf == 1 ? "_HALF1" : "_HALF2") );
147 
148  // IBSS shape : DX =1.9008cm ; DY = .015cm ; DZ = 3.765 cm
149  double sensorLength = kIstNumSensorsPerLadder * (sensorBBox->GetDZ() + 0.10); // halfDepth + deadedge 0.16/2 + sensor gap 0.04/2
150  StiShape *stiShape = new StiPlanarShape(halfLadderName.c_str(), sensorLength, 2*sensorBBox->GetDY(), sensorBBox->GetDX()/2);
151 
152  TVector3 offset((iLadderHalf == 1 ? -sensorBBox->GetDX()/2 : sensorBBox->GetDX()/2), 0, 0);
153  StiPlacement *pPlacement= new StiPlacement(sensorMatrix, offset);
154 
155  // Build final detector object
156  StiDetector *stiDetector = getDetectorFactory()->getInstance();
157  StiIsActiveFunctor* isActive = _active ? new StiIstIsActiveFunctor :
158  static_cast<StiIsActiveFunctor*>(new StiNeverActiveFunctor);
159 
160  stiDetector->setProperties(halfLadderName, isActive, stiShape, pPlacement, getGasMat(), silicon);
161  stiDetector->setHitErrorCalculator(StiIst1HitErrorCalculator::instance());
162 
163  // Add created sensitive IST layer to Sti
164  add(iLadderHalf-1, iLadder-1, stiDetector);
165  }
166  }
167 }
168 
169 
183 const StiDetector* StiIstDetectorBuilder::getActiveDetector(int ladder, int sensorHalf) const
184 {
185  if (ladder < 1 || ladder > kIstNumLadders || sensorHalf < 1 || sensorHalf > 2)
186  return 0;
187  else
188  return getDetector(sensorHalf-1, ladder-1);
189 }
190 
191 
198 {
199  // Prepare shapes for each ladder
200  StiShape *digiBoardShape = new StiPlanarShape("IBAM_DIGI_BOARD", 5.830, 2*0.0823, 1.9355);
201  StiShape *connectorShape = new StiPlanarShape("IBAM_CONNECTOR", 1.125, 2*0.3050, 3.0500);
202  StiShape *cfBackingShape = new StiPlanarShape("IBAM_CF_BACKING", 27.800, 2*0.3050, 3.0500); // Carbon fiber backing
203 
204  // StiMaterial(const string &name, double z, double a, double density, double X0)
205  StiMaterial* digiBoardMaterial = new StiMaterial("IBAM_DIGI_BOARD", 9.01, 18.01, 1.70, 18.2086);
206  StiMaterial* alumConnectorMaterial = new StiMaterial("IBAM_ALUM_CONNECTOR", 13.00, 26.98, 1.05*2.70, 8.8751);
207  StiMaterial* gtenConnectorMaterial = new StiMaterial("IBAM_GTEN_CONNECTOR", 9.01, 18.02, 1.10*1.70, 18.2086);
208  StiMaterial* cfBackingMaterial = new StiMaterial("IBAM_CF_BACKING", 6.34, 12.71, 0.19, 1096.0000);
209 
210  // Volumes offsets
211  TVector3 digiBoardOffset (2.11591, -2.087862, -25.4911);
212  TVector3 alumConnectorOffset(0.47779, -0.352065, -29.3221);
213  TVector3 gtenConnectorOffset(0.47779, -0.352065, 28.8080);
214  TVector3 cfBackingOffset (0.47779, -0.352065, -0.5141);
215 
216  // We use position of sensitive IST volumes to place new inactive volumes
217  int stiRow = getNRows(); // Put volumes in the same (and next available) Sti row
218  // Use the "middle" sensor on the ladder to extract alignment corrections from DB
219  int iSensor = floor(kIstNumSensorsPerLadder/2);
220 
221  for (int iLadder = 1; iLadder <= kIstNumLadders; ++iLadder)
222  {
223  std::ostringstream geoPath, ssPfx;
224  geoPath << "/HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/IBMO_1/IBAM_" << iLadder << "/IBLM_" << iSensor << "/IBSS_1";
225  ssPfx << "/HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/IBMO_1/IBAM_" << iLadder << "/";
226 
227  // Save first part of geoPath to reuse in new detector names
228  std::string pfx(ssPfx.str());
229 
230  bool isAvail = gGeoManager->cd(geoPath.str().c_str());
231 
232  if (!isAvail) {
233  LOG_WARN << "StiIstDetectorBuilder::useVMCGeometry() - Cannot find path to IBSS (IST sensitive) node. Skipping to next ladder..." << endm;
234  continue;
235  }
236 
237  TGeoHMatrix transMatrix( *gGeoManager->MakePhysicalNode(geoPath.str().c_str())->GetMatrix() );
238 
239  // Temporarily save the translation for this sensor in Z so, we can center
240  // the newly built sensors at Z=0 (in ideal geometry) later
241  double idealOffsetZ = transMatrix.GetTranslation()[2];
242 
243  if (!mBuildIdealGeom) {
244  const TGeoHMatrix* transMatrixDb = mIstDb->getHMatrixSensorOnGlobal(iLadder, iSensor);
245 
246  if (!transMatrixDb) {
247  LOG_WARN << "StiIstDetectorBuilder::useVMCGeometry() - Cannot get IST sensor position matrix. Skipping to next ladder..." << endm;
248  continue;
249  }
250 
251  transMatrix = *transMatrixDb;
252  }
253 
254  // Update the global translation in Z so that the new volumes are centered at Z=0
255  transMatrix.SetDz(transMatrix.GetTranslation()[2] - idealOffsetZ);
256 
257  StiPlacement *cfBackingPlacement = new StiPlacement(transMatrix, cfBackingOffset);
258  StiPlacement *alumConnectorPlacement = new StiPlacement(transMatrix, alumConnectorOffset);
259  StiPlacement *gtenConnectorPlacement = new StiPlacement(transMatrix, gtenConnectorOffset);
260  StiPlacement *digiBoardPlacement = new StiPlacement(transMatrix, digiBoardOffset);
261 
262  StiDetector *stiDetector = getDetectorFactory()->getInstance();
263  stiDetector->setProperties(pfx+"IBAM_CF_BACKING", new StiNeverActiveFunctor, cfBackingShape, cfBackingPlacement, getGasMat(), cfBackingMaterial);
264  add(stiRow, iLadder-1, stiDetector);
265 
266  stiDetector = getDetectorFactory()->getInstance();
267  stiDetector->setProperties(pfx+"IBAM_ALUM_CONNECTOR", new StiNeverActiveFunctor, connectorShape, alumConnectorPlacement, getGasMat(), alumConnectorMaterial);
268  add(stiRow+1, iLadder-1, stiDetector);
269 
270  stiDetector = getDetectorFactory()->getInstance();
271  stiDetector->setProperties(pfx+"IBAM_GTEN_CONNECTOR", new StiNeverActiveFunctor, connectorShape, gtenConnectorPlacement, getGasMat(), gtenConnectorMaterial);
272  add(stiRow+2, iLadder-1, stiDetector);
273 
274  stiDetector = getDetectorFactory()->getInstance();
275  stiDetector->setProperties(pfx+"IBAM_DIGI_BOARD", new StiNeverActiveFunctor, digiBoardShape, digiBoardPlacement, getGasMat(), digiBoardMaterial);
276  add(stiRow+3, iLadder-1, stiDetector);
277  }
278 
279  std::string pfx("/HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/IBMO_1/");
280 
281  // Implement plastic brackets as a thin cylinder on east and west sides
282  StiCylindricalShape* ibamBracketShape = new StiCylindricalShape("IBAM_BRACKET", 0.635, 0.2, 12, 2*M_PI);
283  StiPlacement* ibamBracketEastPlacement = new StiPlacement(0, 11.9, 0, 29.34);
284  StiPlacement* ibamBracketWestPlacement = new StiPlacement(0, 11.9, 0, -29.6);
285  StiMaterial* ibamBracketMaterial = new StiMaterial("IBAM_BRACKET", 6.089, 12.149, 24*0.2601, 160);
286 
287  StiDetector* stiDetector = getDetectorFactory()->getInstance();
288  stiDetector->setProperties(pfx+"IBAM_BRACKET_EAST", new StiNeverActiveFunctor, ibamBracketShape, ibamBracketEastPlacement, getGasMat(), ibamBracketMaterial);
289  add(getNRows(), 0, stiDetector);
290 
291  stiDetector = getDetectorFactory()->getInstance();
292  stiDetector->setProperties(pfx+"IBAM_BRACKET_WEST", new StiNeverActiveFunctor, ibamBracketShape, ibamBracketWestPlacement, getGasMat(), ibamBracketMaterial);
293  add(getNRows(), 0, stiDetector);
294 
295  // Implement cooling line and cablings in transition area
296  StiCylindricalShape* icctShape = new StiCylindricalShape("ICCT", 4.35720/2., 22.384-19.115, 22.384, 2*M_PI);
297  StiPlacement* icctPlacement = new StiPlacement(0, (22.384+19.115)/2., 0, -57.4);
298  StiMaterial* icctMaterial = new StiMaterial("ICCT", 26.8, 56.9, 0.673, 17.9);
299 
300  stiDetector = getDetectorFactory()->getInstance();
301  stiDetector->setProperties(pfx+"ICCT", new StiNeverActiveFunctor, icctShape, icctPlacement, getGasMat(), icctMaterial);
302  add(getNRows(), 0, stiDetector);
303 }
304 
305 
311 std::string StiIstDetectorBuilder::formTGeoPath(int ladder, int sensor)
312 {
313  const std::string tgeoPathToMother("/HALL_1/CAVE_1/TpcRefSys_1/IDSM_1/IBMO_1");
314 
315  std::ostringstream geoPath;
316 
317  geoPath << tgeoPathToMother << "/IBAM_" << ladder
318  << "/IBLM_" << sensor
319  << "/IBSS_1";
320 
321  bool found = gGeoManager->cd( geoPath.str().c_str() );
322 
323  // Look for sensors staged in the mother volume
324  if ( !found )
325  {
326  geoPath.str("");
327  geoPath << tgeoPathToMother << "/IBSS_" << (ladder - 1)*6 + sensor;
328  found = gGeoManager->cd( geoPath.str().c_str() );
329  }
330 
331  return found ? geoPath.str() : "";
332 }
virtual void buildDetectors(StMaker &source)
void setProperties(std::string name, StiIsActiveFunctor *activeFunctor, StiShape *shape, StiPlacement *placement, StiMaterial *gas, StiMaterial *material)
const StiDetector * getActiveDetector(int ladder, int sensorHalf) const
function object for determine a Ist padrow&#39;s active regions
const int kIstNumLadders
24 IST Ladders
static std::string formTGeoPath(int ladder, int sensor)
Returns a TGeo path to the sensor in the given ladder.
StiIstDetectorBuilder(bool active, bool buildIdealGeom=true)
virtual Abstract * getInstance()=0
Get a pointer to instance of objects served by this factory.
function object for determine a detector&#39;s active regions
Abstract interface for a STI toolkit.
const int kIstNumSensorsPerLadder
6 sensor per one IST Ladder
virtual TObject * GetObject() const
The depricated method (left here for the sake of the backward compatibility)
Definition: TObjectSet.h:56
static const TGeoHMatrix * getHMatrixSensorOnGlobal(int ladder, int sensor)
Definition: StIstDb.cxx:136
Class implements an object which is never active.