FairShip
Loading...
Searching...
No Matches
strawtubes.cxx
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-3.0-or-later
2// SPDX-FileCopyrightText: Copyright CERN for the benefit of the SHiP
3// Collaboration
4
5// Construction of SST tracker stations
6// Last update: 15 Aug 2025
7// Contact: W.-C. Marty Lee <wei-chieh.lee@desy.de>
8
9#include "strawtubes.h"
10
11#include <array>
12#include <iostream>
13#include <sstream>
14
15#include "FairGeoBuilder.h"
16#include "FairGeoInterface.h"
17#include "FairGeoLoader.h"
18#include "FairGeoMedia.h"
19#include "FairGeoNode.h"
20#include "FairGeoVolume.h"
21#include "FairLogger.h"
22#include "FairRootManager.h"
23#include "FairRun.h"
24#include "FairRuntimeDb.h"
25#include "FairVolume.h"
26#include "ShipDetectorList.h"
27#include "ShipGeoUtil.h"
28#include "ShipStack.h"
29#include "TClonesArray.h"
30#include "TGeoBBox.h"
31#include "TGeoCompositeShape.h"
32#include "TGeoManager.h"
33#include "TGeoMaterial.h"
34#include "TGeoMedium.h"
35#include "TGeoTube.h"
36#include "TMath.h"
37#include "TParticle.h"
38#include "TVector3.h"
39#include "TVirtualMC.h"
40#include "strawtubesPoint.h"
41using std::cout;
42using std::endl;
43
45 : Detector("strawtubes", kTRUE, kStraw), fMedium("air") {}
46
47strawtubes::strawtubes(std::string medium)
48 : Detector("strawtubes", kTRUE, kStraw), fMedium(medium) {}
49
50strawtubes::strawtubes(const char* name, Bool_t active)
51 : Detector(name, active, kStraw) {}
52
53Bool_t strawtubes::ProcessHits(FairVolume* vol) {
55 // Set parameters at entrance of volume. Reset ELoss.
56 if (gMC->IsTrackEntering()) {
57 fELoss = 0.;
58 fTime = gMC->TrackTime() * 1.0e09;
59 fLength = gMC->TrackLength();
60 gMC->TrackPosition(fPos);
61 gMC->TrackMomentum(fMom);
62 }
63 // Sum energy loss for all steps in the active volume
64 fELoss += gMC->Edep();
65
66 // Create strawtubesPoint at exit of active volume
67 if (gMC->IsTrackExiting() || gMC->IsTrackStop() ||
68 gMC->IsTrackDisappeared()) {
69 if (fELoss == 0.) {
70 return kFALSE;
71 }
72 TParticle* p = gMC->GetStack()->GetCurrentTrack();
73 Int_t pdgCode = p->GetPdgCode();
74 fTrackID = gMC->GetStack()->GetCurrentTrackNumber();
75 fEventID = gMC->CurrentEvent();
76 Int_t straw_uniqueId;
77 gMC->CurrentVolID(straw_uniqueId);
78 if (fVolumeID == straw_uniqueId) {
79 // std::cout << pdgCode<< " same volume again ? "<< straw_uniqueId << "
80 // exit:" << gMC->IsTrackExiting() << " stop:" << gMC->IsTrackStop() << "
81 // disappeared:" << gMC->IsTrackDisappeared()<< std::endl;
82 return kTRUE;
83 }
84 fVolumeID = straw_uniqueId;
85 // # d = |pq . u x v|/|u x v|
86 TVector3 bot, top;
87 StrawEndPoints(straw_uniqueId, bot, top);
88 TLorentzVector Pos;
89 gMC->TrackPosition(Pos);
90 Double_t xmean = (fPos.X() + Pos.X()) / 2.;
91 Double_t ymean = (fPos.Y() + Pos.Y()) / 2.;
92 Double_t zmean = (fPos.Z() + Pos.Z()) / 2.;
93 TVector3 pq = TVector3(top.x() - xmean, top.y() - ymean, top.z() - zmean);
94 TVector3 u =
95 TVector3(bot.x() - top.x(), bot.y() - top.y(), bot.z() - top.z());
96 TVector3 v =
97 TVector3(fPos.X() - Pos.X(), fPos.Y() - Pos.Y(), fPos.Z() - Pos.Z());
98 TVector3 uCrossv = u.Cross(v);
99 Double_t dist2Wire = fabs(pq.Dot(uCrossv)) / (uCrossv.Mag() + 1E-8);
100 Double_t deltaTrackLength = gMC->TrackLength() - fLength;
101 AddHit(fEventID, fTrackID, straw_uniqueId, TVector3(xmean, ymean, zmean),
102 TVector3(fMom.Px(), fMom.Py(), fMom.Pz()), fTime, deltaTrackLength,
103 fELoss, pdgCode, dist2Wire);
104 if (dist2Wire > f_inner_straw_diameter / 2) {
105 std::cout << "addhit " << dist2Wire << " straw id " << straw_uniqueId
106 << " pdgcode " << pdgCode << " dot prod " << pq.Dot(uCrossv)
107 << std::endl;
108 std::cout << " exit:" << gMC->IsTrackExiting()
109 << " stop:" << gMC->IsTrackStop()
110 << " disappeared:" << gMC->IsTrackDisappeared() << std::endl;
111 std::cout << " entry:" << fPos.X() << " " << fPos.Y() << " " << fPos.Z()
112 << std::endl;
113 std::cout << " exit:" << Pos.X() << " " << Pos.Y() << " " << Pos.Z()
114 << std::endl;
115 std::cout << " mean:" << xmean << " " << ymean << " " << zmean
116 << std::endl;
117 std::cout << " bot:" << bot.x() << " " << bot.y() << " " << bot.z()
118 << std::endl;
119 std::cout << " top:" << top.x() << " " << top.y() << " " << top.z()
120 << std::endl;
121 pq.Print();
122 u.Print();
123 v.Print();
124 uCrossv.Print();
125 }
126 // Increment number of strawtubes det points in TParticle
127 ShipStack* stack = dynamic_cast<ShipStack*>(gMC->GetStack());
128 stack->AddPoint(kStraw);
129 }
130 return kTRUE;
131}
132
133void strawtubes::SetzPositions(Double_t z1, Double_t z2, Double_t z3,
134 Double_t z4) {
135 f_T1_z = z1;
136 f_T2_z = z2;
137 f_T3_z = z3;
138 f_T4_z = z4;
139}
140
141void strawtubes::SetApertureArea(Double_t width, Double_t height) {
142 f_aperture_width = width;
143 f_aperture_height = height;
144}
145
146void strawtubes::SetStrawDiameter(Double_t outer_straw_diameter,
147 Double_t wall_thickness) {
148 f_outer_straw_diameter = outer_straw_diameter;
150 outer_straw_diameter - 2 * wall_thickness;
151}
152
153void strawtubes::SetStrawPitch(Double_t straw_pitch, Double_t layer_offset) {
154 f_straw_pitch = straw_pitch;
155 f_offset_layer = layer_offset;
156}
157
158void strawtubes::SetDeltazLayer(Double_t delta_z_layer) {
159 f_delta_z_layer = delta_z_layer;
160}
161
162void strawtubes::SetStereoAngle(Double_t stereo_angle) {
163 f_view_angle = stereo_angle;
164}
165
166void strawtubes::SetWireThickness(Double_t wire_thickness) {
167 f_wire_thickness = wire_thickness;
168}
169
170void strawtubes::SetDeltazView(Double_t delta_z_view) {
171 f_delta_z_view = delta_z_view;
172}
173
174void strawtubes::SetFrameMaterial(TString frame_material) {
175 f_frame_material = frame_material;
176}
177
178void strawtubes::SetStationEnvelope(Double_t x, Double_t y, Double_t z) {
179 f_station_width = x;
180 f_station_height = y;
181 f_station_length = z;
182}
183
189 TGeoVolume* top = gGeoManager->GetTopVolume();
190 ShipGeo::InitMedium("mylar");
191 TGeoMedium* mylar = gGeoManager->GetMedium("mylar");
192 ShipGeo::InitMedium("STTmix8020_1bar");
193 TGeoMedium* sttmix8020_1bar = gGeoManager->GetMedium("STTmix8020_1bar");
194 ShipGeo::InitMedium("tungsten");
195 TGeoMedium* tungsten = gGeoManager->GetMedium("tungsten");
197 TGeoMedium* FrameMatPtr = gGeoManager->GetMedium(f_frame_material);
199 TGeoMedium* med = gGeoManager->GetMedium(fMedium.c_str());
200
201 gGeoManager->SetVisLevel(4);
202 gGeoManager->SetTopVisible();
203
204 // Epsilon to avoid overlapping volumes
205 Double_t eps = 0.0001;
206 // Straw (half) length
207 Double_t straw_length = f_aperture_width + 2. * eps;
208 // Width of frame: standard HEA 500 I-beam width
209 Double_t frame_width = 49.;
210 // Offset due to floor space limitation
211 Double_t floor_offset = 14.;
212
213 Double_t rmin, rmax, T_station_z;
214
215 // Arguments of boxes are half-lengths
216 [[maybe_unused]] TGeoBBox* detbox1 = new TGeoBBox(
217 "detbox1", f_aperture_width + frame_width,
218 f_aperture_height + frame_width - floor_offset / 2., f_station_length);
219 [[maybe_unused]] TGeoBBox* detbox2 = new TGeoBBox(
220 "detbox2", straw_length + eps,
222 TMath::Tan(f_view_angle * TMath::Pi() / 180.0) * straw_length * 2 +
223 f_offset_layer / TMath::Cos(f_view_angle * TMath::Pi() / 180.0) + eps,
224 f_station_length + eps);
225 TGeoTranslation* move_up =
226 new TGeoTranslation("move_up", 0, floor_offset / 2., 0);
227 move_up->RegisterYourself();
228
229 // Composite shape to create frame
230 TGeoCompositeShape* detcomp1 =
231 new TGeoCompositeShape("detcomp1", "(detbox1:move_up)-detbox2");
232
233 // Volume: straw
234 rmin = f_inner_straw_diameter / 2.;
235 rmax = f_outer_straw_diameter / 2.;
236 // Third argument is half-length of tube
237 TGeoTube* straw_tube = new TGeoTube("straw", rmin, rmax, straw_length);
238 TGeoVolume* straw = new TGeoVolume("straw", straw_tube, mylar);
239 straw->SetLineColor(4);
240 straw->SetVisibility(kTRUE);
241
242 // Volume: gas
243 rmin = f_wire_thickness / 2. + eps;
244 rmax = f_inner_straw_diameter / 2. - eps;
245 TGeoTube* gas_tube = new TGeoTube("gas", rmin, rmax, straw_length - 2. * eps);
246 TGeoVolume* gas = new TGeoVolume("gas", gas_tube, sttmix8020_1bar);
247 gas->SetLineColor(5);
248 // Only the gas is sensitive
249 AddSensitiveVolume(gas);
250
251 // Volume: wire
252 rmin = 0.;
253 rmax = f_wire_thickness / 2.;
254 TGeoTube* wire_tube =
255 new TGeoTube("wire", rmin, rmax, straw_length - 4. * eps);
256 TGeoVolume* wire = new TGeoVolume("wire", wire_tube, tungsten);
257 wire->SetLineColor(6);
258
259 // Tracking stations
260 // statnb = station number; vnb = view number; lnb = layer number; snb = straw
261 // number
262
263 // Station box to contain all components
264 TGeoBBox* statbox =
265 new TGeoBBox("statbox", f_station_width,
266 f_station_height - floor_offset / 2., f_station_length);
267
268 f_frame_material.ToLower();
269
270 for (Int_t statnb = 1; statnb < 5; statnb++) {
271 // Tracking station loop
272 TString nmstation = "Tr";
273 std::stringstream ss;
274 ss << statnb;
275 nmstation = nmstation + ss.str();
276 switch (statnb) {
277 case 1:
278 T_station_z = f_T1_z;
279 break;
280 case 2:
281 T_station_z = f_T2_z;
282 break;
283 case 3:
284 T_station_z = f_T3_z;
285 break;
286 case 4:
287 T_station_z = f_T4_z;
288 break;
289 default:
290 T_station_z = f_T1_z;
291 }
292
293 TGeoVolume* vol = new TGeoVolume(nmstation, statbox, med);
294 // z-translate the station to its (absolute) position
295 top->AddNode(vol, statnb,
296 new TGeoTranslation(0, floor_offset / 2., T_station_z));
297
298 TGeoVolume* statframe =
299 new TGeoVolume(nmstation + "_frame", detcomp1, FrameMatPtr);
300 vol->AddNode(statframe, statnb * 1e6,
301 new TGeoTranslation(0, -floor_offset / 2., 0));
302 statframe->SetLineColor(kRed);
303
304 for (Int_t vnb = 0; vnb < 4; vnb++) {
305 // View loop
306 const Double_t angle = [&] {
307 switch (vnb) {
308 case 1:
309 return f_view_angle;
310 case 2:
311 return -f_view_angle;
312 default:
313 return 0.;
314 }
315 }();
316 const TString nmview = [&] {
317 switch (vnb) {
318 case 0:
319 return nmstation + "_y1";
320 case 1:
321 return nmstation + "_u";
322 case 2:
323 return nmstation + "_v";
324 case 3:
325 return nmstation + "_y2";
326 default:
327 return nmstation + "_y1";
328 }
329 }();
330
331 // Adjustments in the stereo views
332 // stereo_growth: extension of stereo views beyond aperture
333 // stereo_pitch: straw pitch in stereo views
334 // offset_layer: layer offset in stereo views
335 // straws_per_layer: number of straws in one layer with stereo extension
336 // If angle == 0., all numbers return the case of non-stereo views.
337 const Double_t stereo_growth =
338 TMath::Tan(TMath::Abs(angle) * TMath::Pi() / 180.0) * straw_length;
339 const Double_t stereo_pitch =
340 f_straw_pitch / TMath::Cos(TMath::Abs(angle) * TMath::Pi() / 180.0);
341 const Double_t offset_layer =
342 f_offset_layer / TMath::Cos(TMath::Abs(angle) * TMath::Pi() / 180.0);
343 const Int_t straws_per_layer =
344 std::ceil(2 * (f_aperture_height + stereo_growth) / stereo_pitch);
345
346 for (Int_t lnb = 0; lnb < 2; lnb++) {
347 // Layer loop
348 TString nmlayer = nmview + "_layer_";
349 nmlayer += lnb;
350 TGeoBBox* layer = new TGeoBBox(
351 "layer box", straw_length + eps / 4,
352 f_aperture_height + stereo_growth * 2 + offset_layer + eps / 4,
353 f_outer_straw_diameter / 2. + eps / 4);
354 TGeoVolume* layerbox = new TGeoVolume(nmlayer, layer, med);
355
356 // The layer box sits in the viewframe.
357 // Hence, z-translate the layer w.r.t. the view
358 vol->AddNode(
359 layerbox, statnb * 1e6 + vnb * 1e5 + lnb * 1e4,
360 new TGeoTranslation(0, -floor_offset / 2.,
361 (vnb - 3. / 2.) * f_delta_z_view +
362 (lnb - 1. / 2.) * f_delta_z_layer));
363
364 TGeoRotation r6s;
365 TGeoTranslation t6s;
366 for (Int_t snb = 1; snb <= straws_per_layer; snb++) {
367 // Straw loop
368 // y-translate the straw to its position
369 t6s.SetTranslation(0,
370 f_aperture_height + stereo_growth -
371 (snb - 1. / 2.) * stereo_pitch +
372 lnb * offset_layer,
373 0);
374 // Rotate the straw with stereo angle
375 r6s.SetAngles(90 + angle, 90, 0);
376 TGeoCombiTrans c6s(t6s, r6s);
377 TGeoHMatrix* h6s = new TGeoHMatrix(c6s);
378 layerbox->AddNode(
379 straw, statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 1e3 + snb, h6s);
380 layerbox->AddNode(
381 gas, statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 2e3 + snb, h6s);
382 layerbox->AddNode(
383 wire, statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 3e3 + snb, h6s);
384 // End of straw loop
385 }
386
387 if (lnb == 1) {
388 // Add one more straw at the bottom of the second layer to cover
389 // aperture entirely
390 t6s.SetTranslation(0,
391 f_aperture_height + stereo_growth -
392 (straws_per_layer - 1. / 2.) * stereo_pitch -
393 lnb * offset_layer,
394 0);
395 r6s.SetAngles(90 + angle, 90, 0);
396 TGeoCombiTrans c6s(t6s, r6s);
397 TGeoHMatrix* h6s = new TGeoHMatrix(c6s);
398 layerbox->AddNode(
399 straw,
400 statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 1e3 + straws_per_layer + 1,
401 h6s);
402 layerbox->AddNode(
403 gas,
404 statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 2e3 + straws_per_layer + 1,
405 h6s);
406 layerbox->AddNode(
407 wire,
408 statnb * 1e6 + vnb * 1e5 + lnb * 1e4 + 3e3 + straws_per_layer + 1,
409 h6s);
410 }
411 // End of layer loop
412 }
413 // End of view loop
414 }
415 // End of tracking station loop
416 }
417}
418// ----- Public method StrawDecode -------------------------------------------
419// ----- returns station, view, layer, straw number in a tuple
420// -----------------------------------
421std::array<Int_t, 4> strawtubes::StrawDecode(Int_t detID) {
422 Int_t statnb, vnb, lnb, snb;
423 statnb = detID / 1e6;
424 vnb = (detID - statnb * 1e6) / 1e5;
425 lnb = (detID - statnb * 1e6 - vnb * 1e5) / 1e4;
426 snb = detID - statnb * 1e6 - vnb * 1e5 - lnb * 1e4 - 2e3;
427
428 if (statnb < 1 || statnb > 4 || vnb < 0 || vnb > 3 || lnb < 0 || lnb > 1 ||
429 snb < 1 || snb > 317) {
430 LOG(warning) << "Invalid strawtubes detID:";
431 LOG(warning) << detID << " -> station: " << statnb << ", view: " << vnb
432 << ", layer: " << lnb << ", straw: " << snb;
433 LOG(warning) << "strawtubes detID is 7-digit!";
434 return {0, -1, -1, 0};
435 } else {
436 return {statnb, vnb, lnb, snb};
437 }
438}
439// ----- Public method StrawEndPoints
440// -------------------------------------------
441// ----- returns top (left) and bottom (right) coordinates of straw
442// -----------------------------------
443void strawtubes::StrawEndPoints(Int_t fDetectorID, TVector3& vbot,
444 TVector3& vtop)
445// method to get end points from TGeoNavigator
446{
447 const auto [statnb, vnb, lnb, snb] = StrawDecode(fDetectorID);
448 TString stat = "Tr";
449 stat += statnb;
450 stat += "_";
451 stat += statnb;
452 const TString view = [&] {
453 switch (vnb) {
454 case 1:
455 return TString("_u");
456 case 2:
457 return TString("_v");
458 case 3:
459 return TString("_y2");
460 default:
461 return TString("_y1");
462 }
463 }();
464 TGeoNavigator* nav = gGeoManager->GetCurrentNavigator();
465 TString prefix = "Tr";
466 prefix += statnb;
467 prefix += view;
468 prefix += "_";
469 TString layer = prefix + "layer_";
470 layer += lnb;
471 layer += "_";
472 layer += statnb;
473 layer += vnb;
474 layer += lnb;
475 layer += "0000";
476 TString wire = "wire_";
477 wire += fDetectorID + 1e3;
478 TString path = "/";
479 path += stat;
480 path += "/";
481 path += layer;
482 path += "/";
483 path += wire;
484 Bool_t rc = nav->cd(path);
485 if (!rc) {
486 LOG(warning) << "strawtubes::StrawDecode, TGeoNavigator failed" << path;
487 return;
488 }
489 TGeoNode* W = nav->GetCurrentNode();
490 TGeoTube* S = dynamic_cast<TGeoTube*>(W->GetVolume()->GetShape());
491 Double_t top[3] = {0, 0, S->GetDZ()};
492 Double_t bot[3] = {0, 0, -S->GetDZ()};
493 Double_t Gtop[3], Gbot[3];
494 nav->LocalToMaster(top, Gtop);
495 nav->LocalToMaster(bot, Gbot);
496 vtop.SetXYZ(Gtop[0], Gtop[1], Gtop[2]);
497 vbot.SetXYZ(Gbot[0], Gbot[1], Gbot[2]);
498}
@ kStraw
Definition: diagrams_e.h:4
Int_t fVolumeID
track index
Definition: Detector.h:86
TLorentzVector fPos
volume id
Definition: Detector.h:87
Double_t fTime
momentum at entrance
Definition: Detector.h:89
strawtubesPoint * AddHit(Args &&... args)
Definition: Detector.h:38
TLorentzVector fMom
position at entrance
Definition: Detector.h:88
void SetDeltazView(Double_t delta_z_view)
Definition: strawtubes.cxx:170
std::string fMedium
spatial resolution
Definition: strawtubes.h:84
Double_t f_aperture_width
z-position of tracking station 4
Definition: strawtubes.h:68
Double_t f_inner_straw_diameter
Aperture height (y)
Definition: strawtubes.h:70
Double_t f_station_length
Station envelope height (y)
Definition: strawtubes.h:81
Bool_t ProcessHits(FairVolume *v=0) override
Definition: strawtubes.cxx:53
void SetDeltazLayer(Double_t delta_z_layer)
Definition: strawtubes.cxx:158
Double_t f_wire_thickness
Stereo view angle.
Definition: strawtubes.h:76
Double_t f_T2_z
z-position of tracking station 1
Definition: strawtubes.h:65
TString f_frame_material
Sense wire thickness.
Definition: strawtubes.h:77
static void StrawEndPoints(Int_t detID, TVector3 &top, TVector3 &bot)
Definition: strawtubes.cxx:443
void SetStrawDiameter(Double_t outer_straw_diameter, Double_t wall_thickness)
Definition: strawtubes.cxx:146
void SetzPositions(Double_t z1, Double_t z2, Double_t z3, Double_t z4)
Definition: strawtubes.cxx:133
Double_t f_straw_pitch
Outer Straw diameter.
Definition: strawtubes.h:72
Double_t f_T3_z
z-position of tracking station 2
Definition: strawtubes.h:66
Double_t f_aperture_height
Aperture width (x)
Definition: strawtubes.h:69
Double_t f_delta_z_view
Structure frame material.
Definition: strawtubes.h:78
void SetStrawPitch(Double_t straw_pitch, Double_t layer_offset)
Definition: strawtubes.cxx:153
Double_t f_station_height
Station envelope width (x)
Definition: strawtubes.h:80
void ConstructGeometry() override
Definition: strawtubes.cxx:184
Double_t f_T1_z
Definition: strawtubes.h:64
Double_t f_view_angle
Distance (z) between layers.
Definition: strawtubes.h:75
Double_t f_outer_straw_diameter
Inner Straw diameter.
Definition: strawtubes.h:71
void SetFrameMaterial(TString frame_material)
Definition: strawtubes.cxx:174
Double_t f_station_width
Distance (z) between stereo views.
Definition: strawtubes.h:79
void SetStereoAngle(Double_t stereo_angle)
Definition: strawtubes.cxx:162
void SetWireThickness(Double_t wire_thickness)
Definition: strawtubes.cxx:166
void SetApertureArea(Double_t width, Double_t height)
Definition: strawtubes.cxx:141
void SetStationEnvelope(Double_t x, Double_t y, Double_t z)
Definition: strawtubes.cxx:178
static std::array< Int_t, 4 > StrawDecode(Int_t detID)
Definition: strawtubes.cxx:421
Double_t f_offset_layer
Distance (y) between straws in a layer.
Definition: strawtubes.h:73
Double_t f_T4_z
z-position of tracking station 3
Definition: strawtubes.h:67
Double_t f_delta_z_layer
Offset (y) of straws between layers.
Definition: strawtubes.h:74
Int_t InitMedium(const char *name)
Definition: ShipGeoUtil.h:20