5 #include "StDbUtilities/StTpcLocalCoordinate.hh"
6 #include "StDbUtilities/StTpcCoordinateTransform.hh"
7 #include "StTpcDb/StTpcDb.h"
8 #include "Sti/StiPlanarShape.h"
9 #include "Sti/StiCylindricalShape.h"
10 #include "Sti/StiMaterial.h"
11 #include "Sti/StiPlacement.h"
12 #include "Sti/StiDetector.h"
13 #include "Sti/Base/Factory.h"
16 #include "StDetectorDbMaker/StiTpcInnerHitErrorCalculator.h"
17 #include "StDetectorDbMaker/StiTpcOuterHitErrorCalculator.h"
18 #include "StiTpcDetectorBuilder.h"
20 #include "StDetectorDbMaker/StDetectorDbTpcRDOMasks.h"
21 #include "StDetectorDbMaker/St_tpcPadConfigC.h"
22 #include "StDbUtilities/StCoordinates.hh"
23 #include "StTpcDb/StTpcDb.h"
24 #include "StMatrixD.hh"
25 #include "StDetectorDbMaker/St_tpcAnodeHVavgC.h"
26 #include "StDetectorDbMaker/St_tpcPadGainT0BC.h"
29 std::set<StiTpcDetectorBuilder::StiLayer> StiTpcDetectorBuilder::sStiLayers{};
32 StiTpcDetectorBuilder::StiTpcDetectorBuilder(Bool_t active,
bool active_iTpc)
35 StiTpcDetectorBuilder::~StiTpcDetectorBuilder() {}
47 cout <<
"StiTpcDetectorBuilder::buildDetectors() -I- Started" << endl;
50 cout <<
"StiTpcDetectorBuilder::buildDetectors() -I- Done" << endl;
53 void StiTpcDetectorBuilder::useVMCGeometry()
57 if (debug>1) StiVMCToolKit::SetDebug(1);
58 cout <<
"StiTpcDetectorBuilder::buildDetectors() -I- Use VMC geometry" << endl;
59 SetCurrentDetectorBuilder(
this);
62 TGeoVolume *volT = gGeoManager->GetVolume(
"TPAD");
63 if (! volT) volT = gGeoManager->GetVolume(
"tpad");
65 TGeoMaterial *mat = volT->GetMaterial();
67 if (debug>1) mat->Print();
68 Double_t PotI = StiVMCToolKit::GetPotI(mat);
69 if (debug>1) cout <<
"PotI " << PotI << endl;
74 mat->GetDensity()*mat->GetRadLen(),
78 StiTpcDetectorBuilder::buildStiLayerMap();
80 for(
const StiLayer& stiLayer : sStiLayers)
83 StiDetector* pDetector = constructTpcPadrowDetector(stiLayer, pShape);
85 add(stiLayer.sti_padrow_id, stiLayer.sti_sector_id, pDetector);
86 if (debug>1) cout << *pDetector << endl;
91 {
"TIFC",
"Inner Field Cage",
"HALL_1/CAVE_1/TPCE_1/TIFC_1",
"",
""},
92 {
"TOFC",
"Inner Field Cage",
"HALL_1/CAVE_1/TPCE_1/TOFC_1",
"",
""},
93 {
"TIFC",
"Inner Field Cage",
"HALL_1/CAVE_1/TpcRefSys_1/TPCE_1/TIFC_1",
"",
""},
94 {
"TOFC",
"Inner Field Cage",
"HALL_1/CAVE_1/TpcRefSys_1/TPCE_1/TOFC_1",
"",
""},
97 TString check_path(
"HALL_1/CAVE_1/TpcRefSys_1/TPCE_1");
98 bool newRefSystem = gGeoManager->cd(check_path) ?
true :
false;
100 for (Int_t i = 0; i < 4; i++) {
101 TString path = TpcVolumes[i].path;
103 if ( newRefSystem && !path.Contains(
"TpcRefSys"))
continue;
104 if (!newRefSystem && path.Contains(
"TpcRefSys"))
continue;
105 if (!gGeoManager->cd(path)) {
106 LOG_WARN <<
"Skipping non-existing geometry path " << path << endm;
110 TGeoNode *nodeT = gGeoManager->GetCurrentNode();
111 StiVMCToolKit::LoopOverNodes(nodeT, path, TpcVolumes[i].name, MakeAverageVolume);
118 int tpc_sector_id = stiLayer.tpc_sector();
119 int tpc_padrow_id = stiLayer.tpc_padrow();
123 UInt_t nRows = tpcPadCfg.numberOfRows(tpc_sector_id);
124 UInt_t nInnerPadrows = tpcPadCfg.numberOfInnerRows(tpc_sector_id);
127 float fRadius = tpcPadCfg.radialDistanceAtRow(tpc_sector_id, tpc_padrow_id);
134 Double_t dZ = pShape->getHalfDepth()*0.5;
141 local2GlobalRotation = unit;
142 for (Int_t i = 0; i < 3; i++) {
144 #ifndef TPC_IDEAL_GEOM
147 transform(dirLS[i],dirLSA);
148 transform(dirLSA,dirL);
150 transform(dirL,dirG);
153 transform(dirLS[i],dirG);
155 local2GlobalRotation(i+1,1) = dirG.position().x();
156 local2GlobalRotation(i+1,2) = dirG.position().y();
157 local2GlobalRotation(i+1,3) = dirG.position().z();
160 Double_t y = transform.yFromRow(tpc_sector_id, tpc_padrow_id);
162 #ifndef TPC_IDEAL_GEOM
164 transform(lsCoord,lsCoordA);
166 transform(lsCoordA, gCoord);
169 transform(lsCoord, gCoord);
172 StThreeVectorD centerVector(gCoord.position().x(),gCoord.position().y(),gCoord.position().z());
174 local2GlobalRotation(2,2),
175 local2GlobalRotation(2,3));
176 Double_t prod = centerVector*normalVector;
177 if (prod < 0) normalVector *= -1;
178 Double_t phi = centerVector.phi();
179 Double_t phiD = normalVector.phi();
180 Double_t r = centerVector.perp();
184 if ( stiLayer.represents_only(StiLayer::West) ) zc = 2*dZ;
185 if ( stiLayer.represents_only(StiLayer::East) ) zc = -2*dZ;
187 pPlacement->setZcenter(zc);
188 pPlacement->setLayerRadius(fRadius);
189 pPlacement->setLayerAngle(phi);
190 pPlacement->setRegion(StiPlacement::kMidRapidity);
191 pPlacement->setNormalRep(phiD, r*TMath::Cos(phi-phiD), r*TMath::Sin(phi-phiD));
192 TString name = Form(
"Tpc/Padrow_%d/Sector_%d", stiLayer.sti_padrow_id, stiLayer.sti_sector_id);
195 pDetector->
setName(name.Data());
196 pDetector->setIsOn(kTRUE);
201 int tpc_sector_id_west = stiLayer.tpc_sector(StiLayer::West);
202 int tpc_sector_id_east = stiLayer.tpc_sector(StiLayer::East);
204 Int_t iRdo = s_pRdoMasks->rdoForPadrow(tpc_padrow_id);
205 Bool_t west = tpc_sector_id_west > 0 && s_pRdoMasks->isOn(tpc_sector_id_west, iRdo);
206 Bool_t east = tpc_sector_id_east > 0 && s_pRdoMasks->isOn(tpc_sector_id_east, iRdo);
209 west = St_tpcAnodeHVavgC::instance()->livePadrow(tpc_sector_id_west,tpc_padrow_id) &&
210 St_tpcPadGainT0BC::instance()->livePadrow(tpc_sector_id_west,tpc_padrow_id);
213 east = St_tpcAnodeHVavgC::instance()->livePadrow(tpc_sector_id_east,tpc_padrow_id) &&
214 St_tpcPadGainT0BC::instance()->livePadrow(tpc_sector_id_east,tpc_padrow_id);
220 if ( tpcPadCfg.isiTpcPadRow(tpc_sector_id, tpc_padrow_id) ) {
222 pDetector->setGroupId(kTpcId);
224 new StiTpcIsActiveFunctor(false,west,east);
227 pDetector->setGroupId(kTpcId);
231 pDetector->setIsActive(activator);
232 pDetector->setIsContinuousMedium(kTRUE);
233 pDetector->setIsDiscreteScatterer(kFALSE);
234 pDetector->setMaterial(_gasMat);
235 pDetector->setGas(_gasMat);
236 pDetector->setShape(pShape);
237 pDetector->setPlacement(pPlacement);
239 if (tpc_padrow_id <= nInnerPadrows)
240 pDetector->setHitErrorCalculator(StiTpcInnerHitErrorCalculator::instance());
242 pDetector->setHitErrorCalculator(StiTpcOuterHitErrorCalculator::instance());
244 pDetector->setKey(1,stiLayer.sti_padrow_id);
245 pDetector->setKey(2,stiLayer.sti_sector_id);
251 StiPlanarShape* StiTpcDetectorBuilder::constructTpcPadrowShape(StiLayer stiLayer)
const
253 int tpc_sector_id = stiLayer.tpc_sector();
254 int tpc_padrow_id = stiLayer.tpc_padrow();
257 UInt_t nInnerPadrows = tpcPadCfg.numberOfInnerRows(tpc_sector_id);
259 TString name = Form(
"Tpc/Padrow_%d/Sector_%d", stiLayer.sti_padrow_id, stiLayer.sti_sector_id);
263 throw runtime_error(
"StiTpcDetectorBuilder::buildDetectors() - FATAL - pShape==0||ofcShape==0");
266 if(tpc_padrow_id <= nInnerPadrows) {
267 pShape->setThickness(tpcPadCfg.innerSectorPadLength(tpc_sector_id));
268 dZ = tpcPadCfg.innerSectorPadPlaneZ(tpc_sector_id);
271 pShape->setThickness(tpcPadCfg.outerSectorPadLength(tpc_sector_id));
272 dZ = tpcPadCfg.outerSectorPadPlaneZ(tpc_sector_id);
276 if ( stiLayer.represents_only(StiLayer::West) ||
277 stiLayer.represents_only(StiLayer::East) )
285 pShape->setHalfDepth(dZ*2);
286 pShape->setHalfWidth(tpcPadCfg.PadPitchAtRow(tpc_sector_id, tpc_padrow_id) *
287 tpcPadCfg.numberOfPadsAtRow(tpc_sector_id, tpc_padrow_id) / 2.);
290 if (StiVMCToolKit::Debug()>1) cout << *pShape << endl;
297 double StiTpcDetectorBuilder::StiLayer::radial_distance()
const
304 delta = represents_only(StiLayer::East) ? +0.1 : (represents_only(StiLayer::West) ? -0.1 : 0);
306 return tpcPadCfg.radialDistanceAtRow(tpc_sector(), tpc_padrow()) + delta;
311 bool StiTpcDetectorBuilder::StiLayer::operator< (
const StiLayer& other)
const
313 double radius = radial_distance();
314 double radius_other = other.radial_distance();
317 ( radius < radius_other ) ||
318 ( radius == radius_other && sti_sector_id < other.sti_sector_id );
329 double radius = tpcPadCfg.radialDistanceAtRow(stiLayer.tpc_sector(), stiLayer.tpc_padrow());
331 os << radius <<
",\t" << stiLayer.radial_distance() <<
";\t"
334 << stiLayer.sti_sector_id <<
",\t" << stiLayer.sti_padrow_id;
341 std::pair<int, int> StiTpcDetectorBuilder::toStiLayer(
const int tpc_sector,
const int tpc_padrow)
343 auto find_tpc_sector = [tpc_sector, tpc_padrow](
const StiLayer& sl)
345 StiLayer::TpcHalf half = (tpc_sector <= 12 ? StiLayer::West : StiLayer::East);
346 return sl.tpc_sector_id[half] == tpc_sector && sl.tpc_padrow_id[half] == tpc_padrow;
349 auto stiLayerIter = std::find_if(sStiLayers.begin(), sStiLayers.end(), find_tpc_sector);
351 return stiLayerIter != sStiLayers.end() ?
352 std::make_pair(stiLayerIter->sti_sector_id, stiLayerIter->sti_padrow_id) :
353 std::pair<int, int>(-1, -1);
358 void StiTpcDetectorBuilder::buildStiLayerMap()
364 for(
int sector = 1; sector <= 24; sector++)
366 for(
int row = 1; row <= tpcPadCfg.numberOfRows(sector); row++)
368 std::set<StiLayer>::iterator stiLayerIter;
370 std::tie(stiLayerIter, inserted) = sStiLayers.insert( StiLayer(sector, row) );
372 if (!inserted) stiLayerIter->update_tpc_id(sector, row);
378 auto prevStiLayer = sStiLayers.begin();
379 auto currStiLayer = sStiLayers.begin();
381 for ( ; currStiLayer != sStiLayers.end(); ++currStiLayer)
383 currStiLayer->sti_padrow_id = prevStiLayer->sti_padrow_id;
385 if (currStiLayer->radial_distance() != prevStiLayer->radial_distance())
386 currStiLayer->sti_padrow_id++;
388 prevStiLayer = currStiLayer;
int tpc_sector_id[2]
East and/or West if available.
int tpc_padrow_id[2]
East and/or West if available.
function object for determine a TPC padrow's active regions
virtual Abstract * getInstance()=0
Get a pointer to instance of objects served by this factory.
virtual void buildDetectors(StMaker &s)
function object for determine a detector's active regions
bool sti_split_in_half
Split Sti layer in East and West halves.
bool _active_iTpc
Option to use iTPC hits in Sti tracking. By default hits are not used in Sti tracking.
void setName(const string &newName)
Set the name of the object.