CbmRoot
Loading...
Searching...
No Matches
CbmTrdGeoFactory.cxx
Go to the documentation of this file.
1/* Copyright (C) 2024 National Institute of Physics and Nuclear Engineering - Horia Hulubei, Bucharest
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Alexandru Bercuci [committer] */
4
11#include "CbmTrdGeoFactory.h"
12
13// #include "CbmTrdConstructionDB.h"
14#include "CbmTrdAddress.h"
15
16#include <Logger.h> // for LOG, Logger
17
18#include <TGeoBBox.h>
19#include <TGeoCompositeShape.h>
20#include <TGeoManager.h>
21#include <TGeoMatrix.h>
22#include <TGeoMedium.h>
23#include <TGeoVolume.h>
24#include <TROOT.h>
25
26#include <cassert>
27using namespace cbm::trd;
28using namespace cbm::trd::geo;
29
30const char* ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kNparts] = {"Radiator", "Window",
31 "Volume", "BackPanel", "FEB"};
32//________________________________________________________________________________________
33const TGeoMedium* cbm::trd::geo::GetMaterial(const char* mname)
34{
35 if (fMaterial.find(mname) == fMaterial.end()) {
36 LOG(error) << "GetMaterial(" << mname << ") failed.";
37 return nullptr;
38 }
39 return fMaterial.at(mname);
40}
41
42//__________________________________________________________________
43bool cbm::trd::geo::ReadModuleInfo(const char* modTxt, info_t& info)
44{
45 // parse module info
46 string modName = modTxt;
47 auto posstart = modName.find("module") + 6;
48 uint ndigits = 0;
49 auto partoftype = modName.at(posstart);
50 while (std::isdigit(partoftype) && (ndigits + posstart) < modName.size()) {
51 partoftype = modName.at(posstart + ndigits);
52 ++ndigits;
53 }
54 info.type = stoi(modName.substr(posstart, ndigits)); // 6th element+ module type
55
56 posstart += ndigits;
57 int modCopyNo = stoi(modName.substr(posstart, string::npos));
58 if ((modCopyNo / 100000000) < 0) {
59 LOG(warning) << modTxt << " Module in ancient (< 2013) format. Ask expert.";
60 return false;
61 }
62
63 // >= 2014 format has 9 digits
64 // In TGeoManager numbering starts with 1, so we have to subtract 1.
65 // int modCopy = ((modCopyNo / 1000000) % 100); // from module copy number
66 info.id = (modCopyNo % 1000) - 1;
67 info.superId = ((modCopyNo / 1000) % 100) - 1;
68 info.rotation = ((modCopyNo / 100000) % 10); // from module copy number
69 info.address = CbmTrdAddress::GetAddress(info.superId, info.id, 0, 0, 0);
70 return true;
71}
72
73//__________________________________________________________________
74bool cbm::trd::geo::ReadFebInfo(const char* febTxt, info_t& info)
75{
76 // parse FEB info
77 string febName = febTxt;
78 auto posstart = febName.find("FEB") + 3;
79 try {
80 info.type = stoi(febName.substr(posstart, 2));
81 info.superType = info.type / 10;
82 if (info.superType < 0 || info.superType > 2) throw eException::invalid_type;
83 info.type = info.type % 10;
84
85 int febNo = stoi(febName.substr(posstart + 3, string::npos));
86 info.id = febNo % 100;
87 if (info.superType == 0 && info.id >= faspFeb[info.type].nmax) throw eException::invalid_id;
88 info.superId = (febNo / 100) % 1000;
89 info.rotation = (febNo / 100000) % 10;
90 if (info.rotation > 1) throw eException::invalid_id;
91 }
92 catch (invalid_argument a) { // syntax exceptions
93 LOG(error) << "FEB name does not follow syntax rules : \"FEBxy_identifier\", \"x\" = superType, \"y\" = Type. "
94 "Couldn't initialize.";
95 return false;
96 }
97 catch (eException e) { // TRD exceptions
98 LOG(error) << "FEB name does not follow syntax rules";
99 switch (e) {
100 case eException::invalid_type: LOG(info) << " : Family type not recognized"; break;
101 case eException::invalid_id: LOG(info) << " : Local id not recognized"; break;
102 default: LOG(info) << " : Un-identified violation."; break;
103 }
104 return false;
105 }
106
107 return true;
108}
109
110//__________________________________________________________________
112{
122 int modInfo = 0; //info.id + info.superId * 100;
123 return modInfo;
124}
125
126//__________________________________________________________________
128{
138 if (info == nullptr) {
139 LOG(error) << "WriteFebInfo : Info for FEB is missing";
140 return -1;
141 }
142 if (info->id < 0 || info->superId < 0 || info->rotation < 0) {
143 LOG(warning) << "WriteFebInfo : Info for FEB is incomplete : id=" << info->id << " superId=" << info->superId
144 << " rotatation=" << info->rotation;
145 return -1;
146 }
147 int febInfo = info->id + 100 * info->superId + 100000 * info->rotation;
148 return febInfo;
149}
150
151//________________________________________________________________________________________
152ChamberBuilder::ChamberBuilder(int typ) : FairTask(Form("module%d", typ))
153{
154 fChmbTyp = typ;
155
156 fMaterial["air"] = nullptr;
157 fMaterial["TRDpefoam20"] = nullptr;
158 fMaterial["TRDG10"] = nullptr;
159 fMaterial["TRDkapton"] = nullptr;
160 fMaterial["TRDgas"] = nullptr;
161 fMaterial["TRDcopper"] = nullptr;
162 fMaterial["TRDaramide"] = nullptr;
163 fMaterial["TRDcarbon"] = nullptr;
164 fMaterial["aluminium"] = nullptr;
165 fMaterial["polypropylene"] = nullptr;
166 fMaterial["silicon"] = nullptr;
167
168 fComponent[(int) eGeoPart::kRadiator] = nullptr;
172 fComponent[(int) eGeoPart::kFEB] = nullptr;
173}
174
175//________________________________________________________________________________________
177{
179 if (HasFEB()) fComponent[(int) eGeoPart::kFEB] = new FEB;
180 switch (fChmbTyp) {
181 case 1:
182 LOG(info) << "Init for TRD2D.";
183 SetFEE(fConfig, (bool) eAsic::kFasp);
186 sizeX = sizeY = 57;
187 break;
193 LOG(info) << "Init for TRD1D type " << fChmbTyp << ".";
194 break;
195 default: LOG(fatal) << "Unknown TRD chamber type " << fChmbTyp << ". Abort."; break;
196 }
197
198 // Activate materials od the TRD geometry
199 TGeoManager* gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
200 assert(gGeoMan);
201 for (auto& imat : fMaterial) {
202 imat.second = gGeoMan->GetMedium(imat.first.data());
203 assert(imat.second);
204 }
205
206 // Instantiate the construction data base of the TRD system
207 // if (!gDB) {
208 // assert((gDB = ConstructionDB::Instantiate()));
209 // }
210
211 // Init sub-components
212 for (auto icomp : fComponent) {
213 if (!icomp) continue;
214 auto status = icomp->Init();
215 if (status != kSUCCESS) return status;
216 }
217 return kSUCCESS;
218}
219
220//________________________________________________________________________________________
221void ChamberBuilder::Exec(Option_t*)
222{
223 // estimate total module height and define center
224 int idx(0);
225 double vh[(int) eGeoPart::kNparts];
226 bool kAdd(true);
227 double hOffset(0.), hTot(0.);
228 for (auto icomp : fComponent) {
229 if (!icomp) continue;
230 vh[idx] = icomp->GetHeight();
231 hTot += vh[idx];
232 if (kAdd) {
233 if (idx == (int) eGeoPart::kVolume) {
234 hOffset += vh[idx] / 2;
235 kAdd = false;
236 }
237 else
238 hOffset += vh[idx];
239 }
240 idx++;
241 }
242 // add global z offset
243 hOffset = hTot / 2;
244 fVol = new TGeoVolume(Form("module%d", fChmbTyp), new TGeoBBox("", sizeX / 2, sizeY / 2, hTot / 2),
246 fVol->SetLineColor(kGreen);
247 fVol->SetTransparency(80);
248
249 // Stack-up all sub-components
250 idx = 0;
251 double hh(-hTot / 2);
252 info_t infoFeb;
253 for (auto icomp : fComponent) {
254 if (!icomp) continue;
255 hh += 0.5 * vh[idx];
256 switch (idx) {
257 case (int) eGeoPart::kFEB: { // special case for feb multiple placement.
258 // FEB characteristics and identification stored in geometry
259 auto vFeb = new TGeoVolume(icomp->GetName(), new TGeoBBox("", sizeX / 2, sizeY / 2, vh[idx] / 2));
260 for (int ifeb(0), jfeb(0); ifeb < Nfebs; ifeb++) {
261 infoFeb.id = ifeb;
262 infoFeb.superId = 0; // gDB.GetFebId(imod, ifeb);
263 infoFeb.rotation = 0; // gDB.GetFebRot(imod, ifeb);
264 if ((jfeb = WriteFebInfo(&infoFeb)) < 0) continue;
265 vFeb->AddNode(icomp->fVol, jfeb, new TGeoTranslation("", feb_pos[ifeb][0], feb_pos[ifeb][1], 0.));
266 }
267 fVol->AddNode(vFeb, 1, new TGeoTranslation("", 0, 0, hh));
268 } break;
269 default: fVol->AddNode(icomp->fVol, 1, new TGeoTranslation("", 0., 0., hh)); break;
270 }
271
272 hh += 0.5 * vh[idx++];
273 }
274}
275//________________________________________________________________________________________
277{
278 if (!fVol) return 0.;
279 double zlo, zhi;
280 fVol->GetShape()->GetAxisRange(3., zlo, zhi);
281 return 0.5 * (zlo + zhi);
282}
283// double ChamberBuilder::Component::GetHeight() const
284// {
285// if (!fVol) return 0.;
286// double zlo, zhi, hh = fVol->GetShape()->GetAxisRange(2, zlo, zhi);
287// return hh;
288// }
289
290//________________________________________________________________________________________
292
294{
295 const double hc_size_x = activeAreaX;
296 const double hc_size_y = 2 * 0.3 + activeAreaY;
297 const double win_size_x = hc_size_x + 2 * WIN_FrameX_thickness;
298 const double win_size_y = hc_size_y + 2 * WIN_FrameY_thickness;
299
300 // Carbon fiber layers
301 TGeoBBox* winIn_C = new TGeoBBox("winIn_C", win_size_x / 2., win_size_y / 2., winIn_C_thickness / 2.);
302 TGeoVolume* vol_winIn_C =
303 new TGeoVolume("winIn_C", winIn_C, cbm::trd::geo::GetMaterial("TRDcarbon") /*carbonVolMed*/);
304 vol_winIn_C->SetLineColor(kBlack); //kGray);
305 fHeight = winIn_C_thickness;
306
307 // Honeycomb layer
308 TGeoBBox* winIn_HC = new TGeoBBox("winIn_HC", hc_size_x / 2., hc_size_y / 2., winIn_HC_thickness / 2.);
309 TGeoVolume* vol_winIn_HC = new TGeoVolume("winIn_HC", winIn_HC, cbm::trd::geo::GetMaterial("TRDaramide"));
310 vol_winIn_HC->SetLineColor(kOrange);
311 fHeight += winIn_HC_thickness;
312
313 // framex
314 TGeoBBox* winIn_fx = new TGeoBBox("winIn_fx", (hc_size_x + 2 * WIN_FrameX_thickness) / 2, WIN_FrameY_thickness / 2,
315 winIn_HC_thickness / 2.);
316 TGeoVolume* vol_winIn_fx = new TGeoVolume("winIn_fx", winIn_fx, /*frameVolMed*/ cbm::trd::geo::GetMaterial("TRDG10"));
317 vol_winIn_fx->SetLineColor(kBlue);
318 TGeoBBox* winIn_xout = new TGeoBBox("winIn_xout", hc_size_x / 2 + 2 * WIN_FrameX_thickness, WIN_OutY_thickness / 2,
319 winIn_HC_thickness / 2.);
320 TGeoVolume* vol_winIn_xout =
321 new TGeoVolume("winIn_xout", winIn_xout, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
322 vol_winIn_xout->SetLineColor(kBlue + 2);
323
324 // framey
325 TGeoBBox* winIn_fy = new TGeoBBox("winIn_fy", WIN_FrameX_thickness / 2, hc_size_y / 2, winIn_HC_thickness / 2.);
326 TGeoVolume* vol_winIn_fy = new TGeoVolume("winIn_fy", winIn_fy, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
327 vol_winIn_fy->SetLineColor(kCyan);
328 TGeoBBox* winIn_k =
329 new TGeoBBox("winIn_k", WIN_FrameX_thickness / 2, hc_size_y / 2 + WIN_FrameY_thickness, winIn_HC_thickness / 2.);
330 TGeoVolume* vol_winIn_k = new TGeoVolume("winIn_k", winIn_k, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
331 vol_winIn_k->SetLineColor(kViolet);
332 TGeoBBox* winIn_yout =
333 new TGeoBBox("winIn_yout", WIN_OutX_thickness / 2, hc_size_y / 2 + WIN_FrameY_thickness + WIN_OutY_thickness,
334 winIn_HC_thickness / 2.);
335 TGeoVolume* vol_winIn_yout =
336 new TGeoVolume("winIn_yout", winIn_yout, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
337 vol_winIn_yout->SetLineColor(kViolet + 5);
338
339 // Add up all sub-components
340 fVol =
341 new TGeoVolume(GetName(), new TGeoBBox("", sizeX / 2, sizeY / 2, fHeight / 2), cbm::trd::geo::GetMaterial("air"));
342 fVol->SetLineColor(kOrange);
343 fVol->SetTransparency(50);
344
345 double x, y;
346 fHeight = -fHeight / 2 + winIn_HC_thickness / 2;
347 fVol->AddNode(vol_winIn_HC, 1, new TGeoTranslation("", 0., 0., fHeight));
348 y = (hc_size_y + WIN_FrameY_thickness) / 2.;
349 fVol->AddNode(vol_winIn_fx, 1, new TGeoTranslation("", 0., y, fHeight));
350 fVol->AddNode(vol_winIn_fx, 2, new TGeoTranslation("", 0., -y, fHeight));
351 y += 0.5 * (WIN_FrameY_thickness + WIN_OutY_thickness);
352 fVol->AddNode(vol_winIn_xout, 1, new TGeoTranslation("", 0., y, fHeight));
353 fVol->AddNode(vol_winIn_xout, 2, new TGeoTranslation("", 0., -y, fHeight));
354 x = (hc_size_x + WIN_FrameX_thickness) / 2.;
355 fVol->AddNode(vol_winIn_fy, 1, new TGeoTranslation("", x, 0., fHeight));
356 fVol->AddNode(vol_winIn_fy, 2, new TGeoTranslation("", -x, 0., fHeight));
357 x += WIN_FrameX_thickness;
358 fVol->AddNode(vol_winIn_k, 1, new TGeoTranslation("", x, 0., fHeight));
359 fVol->AddNode(vol_winIn_k, 2, new TGeoTranslation("", -x, 0., fHeight));
360 x += 0.5 * (WIN_FrameX_thickness + WIN_OutX_thickness);
361 fVol->AddNode(vol_winIn_yout, 1, new TGeoTranslation("", x, 0., fHeight));
362 fVol->AddNode(vol_winIn_yout, 2, new TGeoTranslation("", -x, 0., fHeight));
363
364 fHeight += 0.5 * (winIn_HC_thickness + winIn_C_thickness);
365 fVol->AddNode(vol_winIn_C, 1, new TGeoTranslation("", 0., 0., fHeight));
366 fHeight += 0.5 * winIn_C_thickness;
367 fHeight *= 2;
368 return kSUCCESS;
369}
370
371//________________________________________________________________________________________
373
375{
376 // Gas. The volume has to be defined only for pads (read-out) area. Take care in the DigiPara definition
377 TGeoBBox* gas = new TGeoBBox("trd_gas", 0.5 * activeAreaX, 0.5 * activeAreaY, 0.5 * gas_thickness);
378 TGeoVolume* vol_gas = new TGeoVolume("gas", gas, cbm::trd::geo::GetMaterial("TRDgas") /*gasVolMed*/);
379 vol_gas->SetLineColor(kRed);
380 //vol_gas->SetTransparency(80);
381 TGeoBBox* gas_ext = new TGeoBBox("trd_gas_dstr", 0.5 * activeAreaX, 0.5 * gas_extra, 0.5 * gas_thickness);
382 TGeoVolume* vol_gas_ext = new TGeoVolume("gas_ext", gas_ext, cbm::trd::geo::GetMaterial("TRDgas") /*gasVolMed*/);
383 vol_gas_ext->SetLineColor(kMagenta);
384 //vol_gas_ext->SetTransparency(80);
385 fHeight = gas_thickness;
386
387 const double gas_size_x = activeAreaX;
388 const double gas_size_y = activeAreaY + 2 * gas_extra;
389
390 // framex
391 auto* gas_xin = new TGeoBBox("gas_xin", gas_size_x / 2 + cathode_width, WIN_OutY_thickness / 2, gas_thickness / 2.);
392 auto* vol_gas_xin = new TGeoVolume("gas_xin", gas_xin, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
393 vol_gas_xin->SetLineColor(kViolet + 5);
394 auto* gas_xout = new TGeoBBox("gas_xout", gas_size_x / 2 + cathode_width, WIN_OutY_thickness / 2,
395 (gas_thickness /*+ ridge_height*/) / 2.);
396 TGeoVolume* vol_gas_xout = new TGeoVolume("gas_xout", gas_xout, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
397 vol_gas_xout->SetLineColor(kViolet + 5);
398 // framey
399 TGeoBBox* gas_k = new TGeoBBox("gas_k", cathode_width / 2, gas_size_y / 2, ledge_thickness / 2.);
400 TGeoVolume* vol_gas_k = new TGeoVolume("gas_k", gas_k, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
401 vol_gas_k->SetLineColor(kViolet);
402 TGeoBBox* gas_a = new TGeoBBox("gas_a", anode_width / 2, gas_size_y / 2, ledge_thickness / 2.);
403 TGeoVolume* vol_gas_a = new TGeoVolume("gas_a", gas_a, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
404 vol_gas_a->SetLineColor(kViolet + 2);
405 TGeoBBox* gas_d = new TGeoBBox("gas_d", dist_width / 2, gas_size_y / 2, ledge_thickness / 2.);
406 TGeoVolume* vol_gas_d = new TGeoVolume("gas_d", gas_d, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
407 vol_gas_d->SetLineColor(kViolet + 4);
408 TGeoBBox* gas_yout = new TGeoBBox("gas_yout", WIN_OutX_thickness / 2, 2 * WIN_OutY_thickness + gas_size_y / 2,
409 (gas_thickness /*+ ridge_height*/) / 2.);
410 TGeoVolume* vol_gas_yout = new TGeoVolume("gas_yout", gas_yout, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
411 vol_gas_yout->SetLineColor(kViolet + 5);
412
413 // Add up all sub-components
414 fVol =
415 new TGeoVolume(GetName(), new TGeoBBox("", sizeX / 2, sizeY / 2, fHeight / 2), cbm::trd::geo::GetMaterial("air"));
416 fVol->SetLineColor(kYellow);
417 fVol->SetTransparency(50);
418
419 double x, y;
420 fHeight = 0.;
421 fVol->AddNode(vol_gas, 0, new TGeoTranslation("", 0., 0., fHeight));
422 x = 0.5 * (gas_size_x + cathode_width);
423 fVol->AddNode(vol_gas_k, 1, new TGeoTranslation("", x, 0., fHeight - ledge_thickness));
424 fVol->AddNode(vol_gas_k, 2, new TGeoTranslation("", -x, 0., fHeight - ledge_thickness));
425 x = 0.5 * (gas_size_x + anode_width);
426 fVol->AddNode(vol_gas_a, 1, new TGeoTranslation("", x, 0., fHeight));
427 fVol->AddNode(vol_gas_a, 2, new TGeoTranslation("", -x, 0., fHeight));
428 x = 0.5 * (gas_size_x + dist_width);
429 fVol->AddNode(vol_gas_d, 1, new TGeoTranslation("", x, 0., fHeight + ledge_thickness));
430 fVol->AddNode(vol_gas_d, 2, new TGeoTranslation("", -x, 0., fHeight + ledge_thickness));
431 x = 0.5 * gas_size_x + cathode_width + 0.5 * WIN_OutX_thickness;
432 fVol->AddNode(vol_gas_yout, 1, new TGeoTranslation("", x, 0., fHeight /* + ridge_height / 2*/));
433 fVol->AddNode(vol_gas_yout, 2, new TGeoTranslation("", -x, 0., fHeight /* + ridge_height / 2*/));
434 y = 0.5 * (activeAreaY + gas_extra);
435 fVol->AddNode(vol_gas_ext, 0, new TGeoTranslation("", 0., y, fHeight));
436 fVol->AddNode(vol_gas_ext, 1, new TGeoTranslation("", 0., -y, fHeight));
437 y += 0.5 * (gas_extra + WIN_OutY_thickness);
438 fVol->AddNode(vol_gas_xin, 1, new TGeoTranslation("", 0, y, fHeight));
439 fVol->AddNode(vol_gas_xin, 2, new TGeoTranslation("", 0, -y, fHeight));
440 y += WIN_OutY_thickness;
441 fVol->AddNode(vol_gas_xout, 1, new TGeoTranslation("", 0, y, fHeight /* + ridge_height / 2*/));
442 fVol->AddNode(vol_gas_xout, 2, new TGeoTranslation("", 0, -y, fHeight /* + ridge_height / 2*/));
443 fHeight += gas_thickness;
444 return kSUCCESS;
445}
446
447//________________________________________________________________________________________
450{
451 const double hc_size_x = activeAreaX;
452 const double hc_size_y = activeAreaY - 2 * BKP_OutY_correct;
453 const double bkp_size_x = hc_size_x + 2 * BKP_Frame_width;
454 const double bkp_size_y = hc_size_y + 2 * BKP_Frame_width;
455
456 // Pad Copper
457 TGeoBBox* pp = new TGeoBBox("pp_cu", activeAreaX / 2., activeAreaY / 2., pp_pads_thickness / 2.);
458 TGeoVolume* vol_pp = new TGeoVolume("pp_cu", pp, /*padcopperVolMed*/ cbm::trd::geo::GetMaterial("TRDcopper"));
459 vol_pp->SetLineColor(kBlue);
460 fHeight = pp_pads_thickness;
461
462 // Pad Plane
463 TGeoBBox* pp_PCB = new TGeoBBox("pp_pcb", bkp_size_x / 2., bkp_size_y / 2., pp_pcb_thickness / 2.);
464 TGeoVolume* vol_pp_PCB = new TGeoVolume("pp_pcb2d", pp_PCB, /*padpcbVolMed*/ cbm::trd::geo::GetMaterial("TRDG10"));
465 vol_pp_PCB->SetLineColor(kGreen);
466 fHeight += pp_pcb_thickness;
467
468 // Perforated BackPanel structure
469 auto vol_bp = new TGeoVolumeAssembly("bkp_int");
470 auto vol_bp_ASIC = new TGeoVolumeAssembly("");
471 // HC : 3 components (HC, PCB, Cu) with 2 sizes
472 Color_t bp_col[3] = {kOrange, kGray, kRed + 2};
473 const char* matName[3] = {"TRDaramide", "TRDG10", "TRDcopper"};
474 // build one BP unit
475 double dxHC[2] = {hc_unitx / 2., (hc_unitx - hc_holex) / 4.}, dyHC[2] = {(hc_unity - hc_holey) / 4., hc_holey / 2.},
476 hHCx((hc_unitx + hc_holex) / 4.), hHCy((hc_unity + hc_holey) / 4.), hHC(0.),
477 hHCz[] = {hc_thickness, cu_pcb_thickness, cu_thickness};
478 for (int ibpz(0); ibpz < 3; ibpz++) {
479 hHC += 0.5 * hHCz[ibpz];
480 for (int ibpy(-1), jbp(0); ibpy < 2; ibpy += 2) {
481 auto bpShp = new TGeoBBox("", dxHC[0], dyHC[0], hHCz[ibpz] / 2.);
482 auto vol_cmp = new TGeoVolume("", bpShp, cbm::trd::geo::GetMaterial(matName[ibpz]));
483 vol_cmp->SetLineColor(bp_col[ibpz]);
484 vol_bp_ASIC->AddNode(vol_cmp, jbp++, new TGeoTranslation("", 0., ibpy * hHCy, hHC));
485 }
486 for (int ibpx(-1), jbp(0); ibpx < 2; ibpx += 2) {
487 auto bpShp = new TGeoBBox("", dxHC[1], dyHC[1], hHCz[ibpz] / 2.);
488 auto vol_cmp = new TGeoVolume("", bpShp, cbm::trd::geo::GetMaterial(matName[ibpz]));
489 vol_cmp->SetLineColor(bp_col[ibpz]);
490 vol_bp_ASIC->AddNode(vol_cmp, jbp++, new TGeoTranslation("", ibpx * hHCx, 0., hHC));
491 }
492 hHC += 0.5 * hHCz[ibpz];
493 }
494 // build BP plate
495 for (Int_t c(0), ifc(0); c < 9; c++) {
496 for (Int_t r(0); r < 10; r++) {
497 vol_bp->AddNode(vol_bp_ASIC, ifc++, new TGeoTranslation("", (c - 4) * hc_unitx, hc_unity * (0.5 + r), 0.));
498 vol_bp->AddNode(vol_bp_ASIC, ifc++, new TGeoTranslation("", (c - 4) * hc_unitx, -hc_unity * (r + 0.5), 0.));
499 }
500 }
501 fHeight += hHC;
502
503 // framex
504 auto xoutBd =
505 new TGeoBBox("", hc_size_x / 2, (BKP_OutY_thickness - BKP_OutY_correct) / 2, (hHC - BKP_Frame_closure) / 2.);
506 auto xvolBd = new TGeoVolume("", xoutBd, cbm::trd::geo::GetMaterial("TRDG10"));
507 auto xoutFc = new TGeoBBox("", hc_size_x / 2, (BKP_Frame_width - BKP_OutY_correct) / 2, BKP_Frame_closure / 2.);
508 auto xvolFc = new TGeoVolume("", xoutFc, cbm::trd::geo::GetMaterial("TRDG10"));
509 auto vol_bkp_xout = new TGeoVolumeAssembly("bkp_xout");
510 vol_bkp_xout->AddNode(
511 xvolFc, 1, new TGeoTranslation("", 0, (BKP_Frame_width - BKP_OutY_thickness) / 2, (BKP_Frame_closure - hHC) / 2));
512 vol_bkp_xout->AddNode(xvolBd, 1, new TGeoTranslation("", 0., 0., BKP_Frame_closure / 2));
513 vol_bkp_xout->SetLineColor(kViolet + 2);
514
515 // framey
516 auto youtBd =
517 new TGeoBBox("", BKP_OutX_thickness / 2, hc_size_y / 2 + BKP_OutY_thickness, (hHC - BKP_Frame_closure) / 2.);
518 auto yvolBd = new TGeoVolume("", youtBd, cbm::trd::geo::GetMaterial("TRDG10"));
519 auto youtFc = new TGeoBBox("", BKP_Frame_width / 2, hc_size_y / 2 + BKP_Frame_width, BKP_Frame_closure / 2.);
520 auto yvolFc = new TGeoVolume("", youtFc, cbm::trd::geo::GetMaterial("TRDG10"));
521 auto vol_bkp_yout = new TGeoVolumeAssembly("bkp_yout");
522 vol_bkp_yout->AddNode(yvolFc, 1,
523 new TGeoTranslation("t_bkp_yout_fc", (BKP_Frame_width - BKP_OutX_thickness) / 2, 0.,
524 (BKP_Frame_closure - hHC) / 2));
525 vol_bkp_yout->AddNode(yvolBd, 1, new TGeoTranslation("t_bkp_yout_bd", 0., 0., BKP_Frame_closure / 2));
526 vol_bkp_yout->SetLineColor(kViolet + 2);
527
528 // Add up all components
529 fVol = new TGeoVolume(GetName(), new TGeoBBox("", bkp_size_x / 2, bkp_size_y / 2, fHeight / 2),
531 fVol->SetLineColor(kOrange);
532 fVol->SetTransparency(50);
533
534 double x, y;
535 fHeight = -fHeight / 2 + 0.5 * pp_pads_thickness;
536 fVol->AddNode(vol_pp, 1, new TGeoTranslation("", 0., 0., fHeight));
537 fHeight += 0.5 * (pp_pads_thickness + pp_pcb_thickness);
538 fVol->AddNode(vol_pp_PCB, 1, new TGeoTranslation("", 0., 0., fHeight));
539 fHeight += 0.5 * pp_pcb_thickness;
540 fVol->AddNode(vol_bp, 1, new TGeoTranslation("", 0., 0., fHeight));
541 fHeight += 0.5 * hHC;
542
543 x = 0.5 * (hc_size_x + BKP_OutX_thickness);
544 auto* fy_tra = new TGeoTranslation("", x, 0., fHeight);
545 fVol->AddNode(vol_bkp_yout, 1, fy_tra);
546 auto* fy_rot = new TGeoRotation();
547 fy_rot->RotateZ(180.);
548 auto* fy_mat = new TGeoHMatrix("");
549 (*fy_mat) = (*fy_rot) * (*fy_tra);
550 fVol->AddNode(vol_bkp_yout, 2, fy_mat);
551 y = 0.5 * (hc_size_y + BKP_OutY_thickness + BKP_OutY_correct);
552 fy_tra = new TGeoTranslation("", 0., y, fHeight);
553 fVol->AddNode(vol_bkp_xout, 1, fy_tra);
554 fy_mat = new TGeoHMatrix("");
555 (*fy_mat) = (*fy_rot) * (*fy_tra);
556 fVol->AddNode(vol_bkp_xout, 2, fy_mat);
557 fHeight += 0.5 * hHC;
558 fHeight *= 2;
559 return kSUCCESS;
560}
561
562//________________________________________________________________________________________
564
566{
567 // Create the FASPRO FEBs out of all CU/PCB layers
568 fHeight = FASPRO_zspace;
569
570 TString scu = "", spcb = "";
571 TGeoTranslation* tr(nullptr);
572 double FASPRO_thickness(0.);
573 for (int ily(0); ily < FASPRO_Nly; ily++) {
574 // effective Cu layer thickness = h [um * 10-4] * coverage [% * 10-2]
575 double lyThickEff = FASPRO_ly_cu[ily][0] * FASPRO_ly_cu[ily][1] * 1.e-6;
576 new TGeoBBox(Form("faspro_ly%02d", ily), FASPRO_length / 2., FASPRO_width / 2., lyThickEff / 2.);
577 FASPRO_thickness += lyThickEff / 2;
578 tr = new TGeoTranslation(Form("t_faspro_ly%02d", ily), 0., 0., FASPRO_thickness);
579 tr->RegisterYourself();
580 scu += Form("%cfaspro_ly%02d:t_faspro_ly%02d", (ily ? '+' : ' '), ily, ily);
581 FASPRO_thickness += lyThickEff / 2;
582 if (ily == FASPRO_Nly - 1) break; // skip for FR4
583 // the FEB dielectric made of PCB
584 double lyThickPcb = 1.e-4 * FASPRO_ly_pcb[ily] / 2.;
585 new TGeoBBox(Form("faspro_ly%02d_pcb", ily), FASPRO_length / 2., FASPRO_width / 2., lyThickPcb);
586 FASPRO_thickness += lyThickPcb;
587 tr = new TGeoTranslation(Form("t_faspro_ly%02d_pcb", ily), 0., 0., FASPRO_thickness);
588 tr->RegisterYourself();
589 spcb += Form("%cfaspro_ly%02d_pcb:t_faspro_ly%02d_pcb", (ily ? '+' : ' '), ily, ily);
590 FASPRO_thickness += lyThickPcb;
591 }
592 for (int ihole(0); ihole < FASPRO_Nfasp; ihole++) {
593 new TGeoBBox(Form("faspro_hole%d", ihole), FASPRO_hole_x / 2., FASPRO_hole_y / 2., 1.e-4 + FASPRO_thickness / 2.);
594 tr =
595 new TGeoTranslation(Form("t_faspro_hole%d", ihole), HOLE_pos[ihole][0], HOLE_pos[ihole][1], FASPRO_thickness / 2);
596 tr->RegisterYourself();
597 scu += Form("-faspro_hole%d:t_faspro_hole%d", ihole, ihole);
598 spcb += Form("-faspro_hole%d:t_faspro_hole%d", ihole, ihole);
599 }
600 auto faspro_cu = new TGeoCompositeShape("faspro_cu", scu.Data());
601 auto vol_faspro_cu = new TGeoVolume("faspro_cu", faspro_cu, cbm::trd::geo::GetMaterial("TRDcopper"));
602 vol_faspro_cu->SetLineColor(kRed - 3); //vol_faspro_cu->SetTransparency(50);
603 auto faspro_pcb = new TGeoCompositeShape("faspro_pcb", spcb.Data());
604 auto vol_faspro_pcb = new TGeoVolume("faspro_pcb", faspro_pcb,
605 cbm::trd::geo::GetMaterial("TRDG10") /*febVolMed*/); // the FEB made of PCB
606 vol_faspro_pcb->SetLineColor(kGreen + 3);
607 //vol_faspro_pcb->SetTransparency(50);
608 fHeight += FASPRO_thickness;
609
610 // create FASP ASIC
611 auto fasp = new TGeoBBox("fasp", FASP_x / 2., FASP_y / 2., FASP_z / 2.);
612 auto vol_fasp = new TGeoVolume("fasp", fasp, cbm::trd::geo::GetMaterial("silicon"));
613 vol_fasp->SetLineColor(kBlack);
614 // create ADC ASIC
615 auto adc = new TGeoBBox("adc", ADC_x / 2., ADC_y / 2., ADC_z / 2.);
616 auto vol_adc = new TGeoVolume("adc", adc, cbm::trd::geo::GetMaterial("silicon"));
617 vol_adc->SetLineColor(kBlack);
618 // create FPGA ASIC
619 auto fpga = new TGeoBBox("fpga", FPGA_x / 2., FPGA_y / 2., FPGA_z / 2.);
620 auto vol_fpga = new TGeoVolume("fpga", fpga, cbm::trd::geo::GetMaterial("silicon"));
621 vol_fpga->SetLineColor(kBlack);
622 // create DCDC ASIC
623 auto dcdc = new TGeoBBox("dcdc", DCDC_x / 2., DCDC_y / 2., DCDC_z / 2.);
624 auto vol_dcdc = new TGeoVolume("dcdc", dcdc, cbm::trd::geo::GetMaterial("silicon"));
625 vol_dcdc->SetLineColor(kBlack);
626 // create FC Coonector
627 auto connFc = new TGeoBBox("connFc", ConnFC_x / 2., ConnFC_y / 2., ConnFC_z / 2.);
628 auto vol_conn_fc = new TGeoVolume("connFc", connFc, cbm::trd::geo::GetMaterial("polypropylene"));
629 vol_conn_fc->SetLineColor(kYellow);
630 // create BRIDGE Coonector
631 auto connBrg = new TGeoBBox("connBrg", ConnBRG_x / 2., ConnBRG_y / 2., ConnBRG_z / 2.);
632 auto vol_conn_brg = new TGeoVolume("connBrg", connBrg, cbm::trd::geo::GetMaterial("polypropylene"));
633 vol_conn_brg->SetLineColor(kYellow + 2);
634 fHeight += ConnBRG_z;
635
636 // Init volume:
637 // FEB family FASPRO
638 // FEB type v1 (12 FASPs)
639 int fType = 1;
640 fVol = new TGeoVolumeAssembly(Form("%s1%d", GetName(), fType));
641 fVol->SetLineColor(kGreen);
642 fVol->SetTransparency(50);
643
644 // Add up all components
645 fHeight = -0.5 * fHeight + FASPRO_zspace;
646 fVol->AddNode(vol_faspro_cu, 1, new TGeoTranslation("", 0., 0., fHeight));
647 fVol->AddNode(vol_faspro_pcb, 1, new TGeoTranslation("", 0., 0., fHeight));
648 // add FASPs on the back side of the FEB
649 info_t infoAsic;
650 for (int ifasp(0), jfasp(0); ifasp < faspFeb[fType].nasic; ifasp++) {
651 vol_fasp->SetTitle(Form("%x", 0xff /*gDB->GetASICMask*/));
652 // if ((jfasp = WriteAsicInfo(&infoAsic)) < 0) continue;
653 fVol->AddNode(vol_fasp, jfasp,
654 new TGeoTranslation("", FASP_pos[ifasp][0], FASP_pos[ifasp][1], fHeight - FASP_z / 2));
655 }
656 fHeight += FASPRO_thickness;
657 // add ADCs, FPGAs and DCDC converters on the tob side of the FEB
658 for (int iadc(0); iadc < FASPRO_Nadc; iadc++)
659 fVol->AddNode(vol_adc, iadc + 1, new TGeoTranslation("", ADC_pos[iadc][0], ADC_pos[iadc][1], fHeight + ADC_z / 2));
660 for (int ifpga(0); ifpga < FASPRO_Nfpga; ifpga++)
661 fVol->AddNode(vol_fpga, ifpga + 1,
662 new TGeoTranslation("", FPGA_pos[ifpga][0], FPGA_pos[ifpga][1], fHeight + FPGA_z / 2));
663 for (int idcdc(0); idcdc < FASPRO_Ndcdc; idcdc++)
664 fVol->AddNode(vol_dcdc, idcdc + 1,
665 new TGeoTranslation("", DCDC_pos[idcdc][0], DCDC_pos[idcdc][1], fHeight + DCDC_z / 2));
666 // add connectors to the FEB
667 for (int ifasp(0); ifasp < FASPRO_Nfasp; ifasp++)
668 fVol->AddNode(vol_conn_fc, ifasp + 1,
669 new TGeoTranslation("", ConnFC_pos[ifasp][0], ConnFC_pos[ifasp][1], fHeight + ConnFC_z / 2));
670 for (int iconn(0); iconn < 2; iconn++)
671 fVol->AddNode(vol_conn_brg, iconn + 1,
672 new TGeoTranslation("", ConnBRG_pos[iconn][0], ConnBRG_pos[iconn][1], fHeight + ConnBRG_z / 2));
673 fHeight += ConnBRG_z;
674 fHeight *= 2;
675 return kSUCCESS;
676}
677
678//________________________________________________________________________________________
680
682{
683 TGeoBBox* trd_radiator = new TGeoBBox("trd_radiator", sizeX / 2., sizeY / 2., radiator_thickness / 2.);
684 fVol = new TGeoVolume("Radiator", trd_radiator, cbm::trd::geo::GetMaterial("TRDpefoam20") /*radVolMed*/);
685 fVol->SetLineColor(kRed);
686 //trdmod1_radvol->SetTransparency(50); // set transparency for the TRD radiator
687
688 fHeight = radiator_thickness;
689 return kSUCCESS;
690}
691/* clang-format off */
692// NamespaceImp(cbm::trd::geo)
700 /* clang-format on */
ClassImp(CbmConverterManager)
Helper class to convert unique channel ID back and forth.
Builder class for the TRD chamber geometry.
static uint32_t GetAddress(int32_t layerId, int32_t moduleId, int32_t sectorId, int32_t rowId, int32_t columnId)
Return address from system ID, layer, module, sector, column and row IDs.
Inner class describing the back panel of composed of.
static const char * fgName[(int) eGeoPart::kNparts]
Inner class describing the geometry of the TRD Front End Electronics (FEE):
virtual InitStatus Init()
Init task.
virtual InitStatus Init()
Init task.
virtual InitStatus Init()
Init task.
Window()
Constructor of entrance window for the TRD chamber.
virtual InitStatus Init()
Init task.
Generic Chamber builder.
array< Component *,(int) eGeoPart::kNparts > fComponent
chamber type [1, 3, 5, 7]
ChamberBuilder(int typ=1)
Constructor for the chamber. Adds all elements according to config.
short fChmbTyp
bit map of the setter flags
virtual void Exec(Option_t *)
Executed task.
static const int Nfebs
list of chamber component builders
virtual InitStatus Init()
Init task.
const double feb_pos[Nfebs][2]
const TGeoMedium * GetMaterial(const char *mname)
material mapping (name, value)
bool ReadModuleInfo(const char *modTxt, info_t &info)
Identify information related to the module encrypted in the geoManager path. Based on legacy function...
bool ReadFebInfo(const char *febTxt, info_t &info)
Identify information related to one FEB encrypted in the geoManager path.
int WriteFebInfo(info_t *info)
Put up information related to the FEB and store it in the geoManager path.
static double sizeX
static double sizeY
int WriteModuleInfo(info_t *info)
Put up information related to the module and store it in the geoManager path. Based on legacy version...
static double activeAreaY
static map< const string, const TGeoMedium * > fMaterial
active area
static double activeAreaX
total area
static constexpr FEB faspFeb[2]
Definition CbmTrdDefs.h:158
@ k1d
rectangular 1D case
@ k2d
triangular 2D case
@ kSpadic
SPADIC type definition.
@ kFasp
FASP ASIC definition.
void SetPP(uint16_t config, bool twod=true)
Define the pad-plane type of the chamber.
void SetFEE(uint16_t config, bool fasp=true)
Define the read-out FEE type of the module.
int nmax
max no of febs on the module
Definition CbmTrdDefs.h:80
Information to be storred in the geoManager path. Based on legacy class CbmTrdGeoHandler.
int id
global addressing of element
int type
global (wrt setup) id of element
int superType
version of element wrt superType family
int superId
local (wrt installation) id of element
int rotation
global type wrt TRD design