SND@LHC Software
Loading...
Searching...
No Matches
DriftTube.cxx
Go to the documentation of this file.
1//
2// DriftTube.cxx
3//
4// S. Ilieva
5// April 2025
6//
7
8#include "DriftTube.h"
9
10#include "DriftTubePoint.h"
11#include "FairGeoBuilder.h"
12#include "FairGeoInterface.h"
13#include "FairGeoLoader.h"
14#include "FairGeoMedia.h"
15#include "FairGeoMedium.h"
16#include "FairGeoNode.h"
17#include "FairGeoTransform.h"
18#include "FairGeoVolume.h"
19#include "FairRootManager.h"
20#include "FairVolume.h"
21#include "ShipDetectorList.h"
22#include "ShipStack.h"
23#include "ShipUnit.h"
24#include "TGeoArb8.h"
25#include "TGeoBBox.h"
26#include "TGeoCompositeShape.h"
27#include "TGeoGlobalMagField.h"
28#include "TGeoManager.h"
29#include "TGeoMaterial.h"
30#include "TGeoMedium.h"
31#include "TGeoSphere.h"
32#include "TGeoTrd1.h"
33#include "TGeoTrd2.h"
34#include "TGeoTube.h"
35#include "TGeoUniformMagField.h"
36#include "TParticle.h"
37#include "TString.h" // for TString
38#include "TVector3.h"
39#include "TVirtualMC.h"
40
41#include <ROOT/TSeq.hxx>
42#include <iosfwd> // for ostream
43#include <iostream> // for operator<<, basic_ostream,etc
44#include <stddef.h> // for NULL
45
46using ROOT::TSeq;
47using namespace ShipUnit;
48
50 : FairDetector("DriftTube", "", kTRUE), fTrackID(-1), fVolumeID(-1), fEntryPoint(), fMom(), fTime(-1.), fLength(-1.),
51 fELoss(-1), fDriftTubePointCollection(new TClonesArray("DriftTubePoint"))
52{
53}
54
55DriftTube::DriftTube(const char *name, Bool_t Active, const char *Title)
56 : FairDetector(name, true, kDriftTube), fTrackID(-1), fVolumeID(-1), fEntryPoint(), fMom(), fTime(-1.), fLength(-1.),
57 fELoss(-1), fDriftTubePointCollection(new TClonesArray("DriftTubePoint"))
58{
59}
60
68
70{
71 FairDetector::Initialize();
72}
73
74// ----- Private method InitMedium
75Int_t DriftTube::InitMedium(const char *name)
76{
77 static FairGeoLoader *geoLoad = FairGeoLoader::Instance();
78 static FairGeoInterface *geoFace = geoLoad->getGeoInterface();
79 static FairGeoMedia *media = geoFace->getMedia();
80 static FairGeoBuilder *geoBuild = geoLoad->getGeoBuilder();
81
82 FairGeoMedium *ShipMedium = media->getMedium(name);
83
84 if (!ShipMedium) {
85 Fatal("InitMedium", "Material %s not defined in media file.", name);
86 return -1111;
87 }
88 TGeoMedium *medium = gGeoManager->GetMedium(name);
89 if (medium != NULL)
90 return ShipMedium->getMediumIndex();
91 return geoBuild->createMedium(ShipMedium);
92}
93
95{
96 // Geometry implementation from D. Centanni
97 // TGeoVolume *top = gGeoManager->GetTopVolume();//FIXME is it needed
98 TGeoVolume *detector = gGeoManager->FindVolumeFast("Detector");
99 if (!detector)
100 LOG(ERROR) << "no Detector volume found ";
101
102 // Materials
103
104 InitMedium("aluminium");
105 TGeoMedium *aluminium = gGeoManager->GetMedium("aluminium");
106 InitMedium("steel");
107 TGeoMedium *steel = gGeoManager->GetMedium("steel");
108 /*InitMedium("gold");
109 TGeoMedium *gold = gGeoManager->GetMedium("gold");
110 InitMedium("mylar");
111 TGeoMedium *mylar = gGeoManager->GetMedium("mylar");*/
112 InitMedium("DTGasMixture");
113 TGeoMedium *DTGasMixture = gGeoManager->GetMedium("DTGasMixture");
114
115 /*Double_t fX = conf_floats["DriftTube/fX"];
116 Double_t fY = conf_floats["DriftTube/fY"];
117 Double_t fZ = conf_floats["DriftTube/fZ"];*/
118 Double_t fCellWidth = conf_floats["DriftTube/cellWidth"]; // drift cell dims
119 Double_t fCellHeight = conf_floats["DriftTube/cellHeight"]; // drift cell dims
120 Double_t fCellLength = conf_floats["DriftTube/cellLength"]; // drift cell dims
121 Double_t fIBeamThickness = conf_floats["DriftTube/IBeamThickness"];
122 Double_t fIBeamWingThickness = conf_floats["DriftTube/IBeamWingThickness"];
123 Double_t fIBeamWingWidth = conf_floats["DriftTube/IBeamWingWidth"];
124 // Plates separating the active layers
125 Double_t fPlateThickness = conf_floats["DriftTube/plateThickness"];
126 Double_t fPlateWidth = conf_floats["DriftTube/plateWidth"];
127 Double_t fPlateLength = conf_floats["DriftTube/plateLength"];
128 // Cover plates
129 Double_t fcoverPlateThickness = conf_floats["DriftTube/coverPlateThickness"];
130 Double_t fcoverPlateWidth = conf_floats["DriftTube/coverPlateWidth"];
131 Double_t fcoverPlateLength = conf_floats["DriftTube/coverPlateLength"];
132 Double_t fAnodeRad = conf_floats["DriftTube/anodeRad"];
133 // Frame
134 Double_t fFrameThickness = conf_floats["DriftTube/frameThickness"];
135 Double_t fFrameWidth = conf_floats["DriftTube/frameWidth"];
136 Double_t fFrameLength = conf_floats["DriftTube/frameLength"];
137 Double_t fFrameHoleThickness = conf_floats["DriftTube/frameHoleThickness"];
138 Double_t fFrameHoleWidth = conf_floats["DriftTube/frameHoleWidth"];
139 Double_t fFrameHoleLength = conf_floats["DriftTube/frameHoleLength"];
140 Double_t fFrameTopThickness = conf_floats["DriftTube/frameTopThickness"];
141 // Side bars
142 Double_t fSideBarThickness = conf_floats["DriftTube/sideBarThickness"];
143 Double_t fSideBarWidth = conf_floats["DriftTube/sideBarWidth"];
144 Double_t fSideBarLength = conf_floats["DriftTube/sideBarLength"];
145 Int_t nPlanes = conf_ints["DriftTube/nPlanes"]; // Number of DT planes
146 Int_t nLayers = conf_ints["DriftTube/nLayers"]; // Number of layers per plane
147 Int_t nCells = conf_ints["DriftTube/nCells"]; // Number of cells per layer
148
149 // position of XX( e.g. left bottom) edges in survey coordinate system converted to physicist friendly coordinate
150 // system
151 std::map<int, TVector3> edge_DriftTube;
152 edge_DriftTube[1] =
153 TVector3(-conf_floats["DriftTube/DT1Dx"], conf_floats["DriftTube/DT1Dz"], conf_floats["DriftTube/DT1Dy"]);
154 edge_DriftTube[2] =
155 TVector3(-conf_floats["DriftTube/DT2Dx"], conf_floats["DriftTube/DT2Dz"], conf_floats["DriftTube/DT2Dy"]);
156 // local position of bottom XX(e.g. horizontal) cell to survey edge
157 std::map<int, TVector3> LocCellDT;
158 LocCellDT[1] =
159 TVector3(-conf_floats["DriftTube/DT1LocX"], conf_floats["DriftTube/DT1LocZ"], conf_floats["DriftTube/DT1LocY"]);
160 LocCellDT[2] =
161 TVector3(-conf_floats["DriftTube/DT2LocX"], conf_floats["DriftTube/DT2LocZ"], conf_floats["DriftTube/DT2LocY"]);
162 // system alignment parameters
163 // Double_t fDriftTubeShiftX = conf_floats["DriftTube/ShiftX"];
164
165 TVector3 displacement;
166
167 // DriftTube layout
168 // Define I-beam
169 TGeoBBox *beam = new TGeoBBox("beam", fIBeamWingWidth / 2, fCellHeight / 2, fCellLength / 2);
170 // Define the half-tube segment for subtraction
171 TGeoTubeSeg *tube =
172 new TGeoTubeSeg("tube", 0., fCellHeight / 2 - fIBeamWingThickness + 1e-4, fCellLength / 2 + 1e-4, 270., 90.);
173 TGeoRotation *rot1 = new TGeoRotation("rot1", 0., 0., 180.);
174 TGeoCombiTrans *transRbeam = new TGeoCombiTrans(fIBeamWingWidth / 2 + 1e-4, 0., 0., rot1);
175 transRbeam->SetName("transRbeam");
176 transRbeam->RegisterYourself();
177 TGeoCompositeShape *IbeamShape = new TGeoCompositeShape("IbeamShape", "beam-(tube:transRbeam)");
178 TGeoVolume *volIbeam = new TGeoVolume("volIbeam", IbeamShape, aluminium);
179 volIbeam->SetLineColor(kGray + 3);
180 // Define the sensitive volume
181 TGeoBBox *cellEnvelope =
182 new TGeoBBox("cellEnvelope", fCellWidth / 2 - 1e-5, fCellHeight / 2 - 1e-5, fCellLength / 2 - 1e-5);
183 TGeoCombiTrans *transR = new TGeoCombiTrans((fCellWidth - fIBeamWingWidth) / 2, 0., 0., rot1);
184 transR->SetName("transR");
185 transR->RegisterYourself();
186 TGeoCombiTrans *transL = new TGeoCombiTrans(TGeoTranslation(-(fCellWidth - fIBeamWingWidth) / 2, 0., 0.),
187 TGeoRotation("rot0", 0., 0., 0.));
188 transL->SetName("transL");
189 transL->RegisterYourself();
190 // Define the anode wire
191 TGeoTube *anode = new TGeoTube("anode", 0., fAnodeRad, fCellLength / 2);
192 TGeoTranslation *t0 = new TGeoTranslation("t0", 0, 0, 0);
193 t0->RegisterYourself();
194 // Subract volumes to create the drift tube cell
195 TGeoCompositeShape *cellShape =
196 new TGeoCompositeShape("cellShape", "cellEnvelope-anode:t0-IbeamShape:transR-IbeamShape:transL");
197 TGeoVolume *volGasCell = new TGeoVolume("volGasCell", cellShape, DTGasMixture);
198 // Make the cell sensitive
199 AddSensitiveVolume(volGasCell);
200 volGasCell->SetLineColor(kBlue - 2);
201 volGasCell->SetTransparency(50);
202
203 // anode as volume
204 TGeoVolume *volAnode = new TGeoVolume("volAnode", anode, steel);
205 volAnode->SetLineColor(kViolet);
206 // The drift cell = gas + anode
207 TGeoVolume *volCell = new TGeoVolumeAssembly("volCell");
208 volCell->AddNode(volGasCell, 1);
209 volCell->AddNode(volAnode, 2);
210
211 TGeoBBox *IbeamBox = dynamic_cast<TGeoBBox *>(volIbeam->GetShape());
212 TGeoBBox *cellBox = dynamic_cast<TGeoBBox *>(volGasCell->GetShape());
213
214 // Define the plates used for covers, support and seperators between layers
215 // Endcap frame
216 TGeoBBox *halfFrameOuterBox = new TGeoBBox("halfFrameOuterBox", fFrameWidth / 2, fFrameLength / 2, fFrameThickness / 2);
217 // Subtract a box to make the frame hollow
218 TGeoBBox *halfFrameHole =
219 new TGeoBBox("halfFrameHole", fFrameHoleWidth / 2, fFrameHoleLength / 2, fFrameHoleThickness / 2 );
220 TGeoBBox *halfFrameTopBox = new TGeoBBox("halfFrameTopBox", fFrameWidth / 2, fFrameLength / 2, fFrameTopThickness / 2);
221 TGeoTranslation *t1 = new TGeoTranslation("t1", 0, 0, fFrameThickness/2 + fFrameTopThickness / 2);
222 t1->RegisterYourself();
223 TGeoCompositeShape *frameShape = new TGeoCompositeShape("frameShape", "halfFrameOuterBox-halfFrameHole:t0+halfFrameTopBox:t1");
224 TGeoVolume *volFrame = new TGeoVolume("volFrame", frameShape, aluminium);
225 volFrame->SetLineColor(kGray + 4);
226 // Side bars
227 TGeoBBox *sideBar = new TGeoBBox("sideBar", fSideBarWidth /2 , fSideBarLength /2, fSideBarThickness /2);
228 TGeoVolume *volSideBar = new TGeoVolume("volSideBar", sideBar, aluminium);
229 volSideBar->SetLineColor(kGray + 5);
230
231 // The seperators between layers
232 TGeoBBox *plate = new TGeoBBox("plate", fPlateWidth / 2, fPlateThickness / 2, fPlateLength / 2);
233 TGeoVolume *volPlate = new TGeoVolume("volPlate", plate, aluminium);
234 volPlate->SetLineColor(kGray);
235 TGeoBBox *coverPlate =
236 new TGeoBBox("coverPlate", fcoverPlateWidth / 2, fcoverPlateThickness / 2, fcoverPlateLength / 2);
237 TGeoVolume *volCoverPlate = new TGeoVolume("volCoverPlate", coverPlate, aluminium);
238 volCoverPlate->SetLineColor(kGray + 2);
239
240
241 double DTlayerBox_x{};
242 // Arrange the DT planes, layers and cells together
243 for (auto &&plane : TSeq(nPlanes)) {
244 TGeoVolumeAssembly *volDTplane = new TGeoVolumeAssembly("volDriftTubePlane");
245 volDTplane->AddNode(volCoverPlate, 1, new TGeoTranslation(fcoverPlateWidth / 2, fcoverPlateThickness / 2, 0.));
246 for (auto &&layer : TSeq(nLayers)) {
247 TGeoVolumeAssembly *volDTlayer = new TGeoVolumeAssembly("volLayer");
248 for (auto &&cell : TSeq(nCells)) {
249 volDTlayer->AddNode(
250 volIbeam, 0,
251 new TGeoTranslation(IbeamBox->GetDX() + cell * (2 * cellBox->GetDX()), fCellHeight / 2, 0.));
252 volDTlayer->AddNode(
253 volCell, int(4e4 + plane * 1e3 + layer * 1e2 + cell),
254 new TGeoTranslation(cellBox->GetDX() + cell * (cellBox->GetDX() * 2), fCellHeight / 2, 0.));
255 volDTlayer->AddNode(
256 volIbeam, 0,
257 new TGeoCombiTrans(-IbeamBox->GetDX() + cellBox->GetDX() * 2 + cell * (cellBox->GetDX() * 2),
258 fCellHeight / 2, 0., rot1));
259 }
260 volDTplane->AddNode(
261 volDTlayer, layer,
262 new TGeoTranslation( -fcoverPlateWidth/ 2 + nCells*(cellBox->GetDX()+IbeamBox->GetDX()) + (layer+1) % 2 * cellBox->GetDX(),
263 fcoverPlateThickness + layer * (fPlateThickness + 2 * IbeamBox->GetDY()), 0));
264 // Add the side bars: one per side of a layer
265 for (auto &&side : TSeq(2)) {
266 volDTplane->AddNode(
267 volSideBar, 0,
268 new TGeoCombiTrans(TGeoTranslation( side* fcoverPlateWidth,
269 fSideBarLength/2 + fcoverPlateThickness + layer * (fPlateThickness + 2 * IbeamBox->GetDY()),
270 0),
271 TGeoRotation("rot_all", 90, 90., 90.)));
272 }
273 if (layer != nLayers - 1) {
274 volDTplane->AddNode(volPlate, 0,
275 new TGeoTranslation( fcoverPlateWidth/ 2,
276 fPlateThickness / 2 + fcoverPlateThickness + 2 * IbeamBox->GetDY() +
277 layer * (fPlateThickness + 2 * IbeamBox->GetDY()),
278 0));
279 }
280 }
281 volDTplane->AddNode(volCoverPlate, 1,
282 new TGeoTranslation( fcoverPlateWidth / 2,
283 fcoverPlateThickness / 2 + fcoverPlateThickness + 2 * IbeamBox->GetDY() +
284 (nLayers - 1) * (fPlateThickness + 2 * IbeamBox->GetDY()),
285 0));
286 // Add the endcap frame
287 volDTplane->AddNode(volFrame, 2,
288 new TGeoTranslation( fcoverPlateWidth / 2,
289 ( 3 * fPlateThickness + 2 * fcoverPlateThickness + nLayers * 2*IbeamBox->GetDY()) / 2,
290 fcoverPlateLength / 2 + fFrameThickness/2 ));
291 volDTplane->AddNode(volFrame, 2,
292 new TGeoTranslation( fcoverPlateWidth / 2,
293 ( 3 * fPlateThickness + 2 * fcoverPlateThickness + nLayers * 2*IbeamBox->GetDY()) / 2,
294 - fcoverPlateLength / 2 - fFrameThickness/2 - fFrameTopThickness ));
295 displacement = edge_DriftTube[plane + 1] + LocCellDT[plane+1];
296 detector->AddNode(volDTplane, plane,
297 new TGeoCombiTrans(TGeoTranslation(displacement.X(), displacement.Y(), displacement.Z()),
298 TGeoRotation("rot3", -(plane + 1) * 90., 90., 0)));
299 // volDriftTube->AddNode(volDTplane, plane, new TGeoCombiTrans( TGeoTranslation(plane*(nCells*cellBox->GetDX()),
300 // -plane*fCellLength/2, plane*(-fcoverPlateThickness/2+nLayers*fCellHeight+(nLayers-1)*fPlateThickness)),
301 // TGeoRotation("rot3", -(plane+1)*90., 90.,0) ));
302 }
303}
304
305Bool_t DriftTube::ProcessHits(FairVolume *vol)
306{
308 // Set parameters at entrance of volume. Reset ELoss.
309 if (gMC->IsTrackEntering()) {
310 fELoss = 0.;
311 fTime = gMC->TrackTime() * 1.0e09;
312 fLength = gMC->TrackLength();
313 gMC->TrackPosition(fEntryPoint);
314 gMC->TrackMomentum(fMom);
315 }
316 // Sum energy loss for all steps in the active volume
317 fELoss += gMC->Edep();
318
319 // Create DriftTubePoint at exit of active volume
320 if (gMC->IsTrackExiting() || gMC->IsTrackStop() || gMC->IsTrackDisappeared()) {
321 if (fELoss == 0.) {
322 return kFALSE;
323 }
324
325 fTrackID = gMC->GetStack()->GetCurrentTrackNumber();
326
327 TParticle *p = gMC->GetStack()->GetCurrentTrack();
328 Int_t pdgCode = p->GetPdgCode();
329 TLorentzVector exit_point;
330 gMC->TrackPosition(exit_point);
331 TLorentzVector Mom;
332 gMC->TrackMomentum(Mom);
333 Int_t detID = 0;
334 gMC->CurrentVolID(detID);
335 fVolumeID = detID;
336 Double_t xmean = (fEntryPoint.X() + exit_point.X()) / 2.;
337 Double_t ymean = (fEntryPoint.Y() + exit_point.Y()) / 2.;
338 Double_t zmean = (fEntryPoint.Z() + exit_point.Z()) / 2.;
339 AddHit(fTrackID, fVolumeID, TVector3(xmean, ymean, zmean), TVector3(fMom.Px(), fMom.Py(), fMom.Pz()), fTime,
340 fLength, fELoss, pdgCode);
341
342 // Increment number of det points in TParticle
343 ShipStack *stack = (ShipStack *)gMC->GetStack();
344 stack->AddPoint(kDriftTube);
345 }
346 return kTRUE;
347}
348
349void DriftTube::GetPosition(Int_t fDetectorID, TVector3 &A, TVector3 &B)
350{
351
352 // Alignment to be added!
353 int plane = int(fDetectorID / 1000) % 10;
354 int layer = int(fDetectorID % 1000) / 100;
355 int cell = int(fDetectorID % 100);
356 double global_pos[3];
357 double local_pos[3] = {0, 0, 0};
358 TString path = TString::Format("/cave_1/"
359 "Detector_0/"
360 "volDriftTube_0/"
361 "volDriftTubePlane_%d/"
362 "volLayer_%d/"
363 "volCell_%d/",
364 plane, layer, cell);
365 TGeoNavigator *nav = gGeoManager->GetCurrentNavigator();
366 if (nav->CheckPath(path)) {
367 nav->cd(path);
368 } else {
369 LOG(FATAL) << path;
370 }
371 // Get the corresponding node
372 TGeoNode *W = nav->GetCurrentNode();
373 TGeoBBox *S = dynamic_cast<TGeoBBox *>(W->GetVolume()->GetShape());
374 Double_t top_pos[3] = {0, 0, -(S->GetDZ())}; // left
375 Double_t bot_pos[3] = {0, 0, S->GetDZ()}; // right
376 Double_t global_top_pos[3], global_bot_pos[3];
377 nav->LocalToMaster(top_pos, global_top_pos);
378 nav->LocalToMaster(bot_pos, global_bot_pos);
379 A.SetXYZ(global_top_pos[0], global_top_pos[1], global_top_pos[2]);
380 B.SetXYZ(global_bot_pos[0], global_bot_pos[1], global_bot_pos[2]);
381}
382
387
389{
396 FairRootManager::Instance()->Register("DriftTubePoint", "DriftTube", fDriftTubePointCollection, kTRUE);
397}
398TClonesArray *DriftTube::GetCollection(Int_t iColl) const
399{
400 if (iColl == 0) {
402 } else {
403 return NULL;
404 }
405}
406
408{
410}
411
412DriftTubePoint *DriftTube::AddHit(Int_t trackID, Int_t detID, TVector3 entrypoint, TVector3 mom, Double_t time,
413 Double_t length, Double_t eLoss, Int_t pdgCode)
414{
415 TClonesArray &clref = *fDriftTubePointCollection;
416 Int_t size = clref.GetEntriesFast();
417 return new (clref[size]) DriftTubePoint(trackID, detID, entrypoint, mom, time, length, eLoss, pdgCode);
418}
@ kDriftTube
Int_t fTrackID
Definition DriftTube.h:80
DriftTubePoint * AddHit(Int_t trackID, Int_t detID, TVector3 pos, TVector3 mom, Double_t time, Double_t length, Double_t eLoss, Int_t pdgCode)
Double32_t fLength
time
Definition DriftTube.h:85
std::map< TString, Int_t > conf_ints
Definition DriftTube.h:91
Double32_t fTime
momentum at entrance
Definition DriftTube.h:84
Double32_t fELoss
length
Definition DriftTube.h:86
TLorentzVector fEntryPoint
volume id
Definition DriftTube.h:82
virtual Bool_t ProcessHits(FairVolume *v=0)
virtual void Initialize()
Definition DriftTube.cxx:69
void GetPosition(Int_t detID, TVector3 &A, TVector3 &B)
virtual ~DriftTube()
Definition DriftTube.cxx:61
Int_t fVolumeID
track index
Definition DriftTube.h:81
virtual void Reset()
TClonesArray * fDriftTubePointCollection
energy loss
Definition DriftTube.h:88
std::map< TString, Float_t > conf_floats
Definition DriftTube.h:90
virtual TClonesArray * GetCollection(Int_t iColl) const
TLorentzVector fMom
position at entrance
Definition DriftTube.h:83
void ConstructGeometry()
Definition DriftTube.cxx:94
virtual void EndOfEvent()
virtual void Register()