Complete rewrite of the FMD code.
[u/mrichter/AliRoot.git] / FMD / AliFMDRing.cxx
CommitLineData
4347b38f 1/**************************************************************************
2 * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16/* $Id$ */
17
18//////////////////////////////////////////////////////////////////////////////
19//
20// Utility class to help implement collection of FMD modules into
21// rings. This is used by AliFMDSubDetector and AliFMD.
22//
23// The AliFMD object owns the AliFMDRing objects, and the
24// AliFMDSubDetector objects reference these. That is, the AliFMDRing
25// objects are share amoung the AliFMDSubDetector objects.
26//
27// Latest changes by Christian Holm Christensen
28//
29//////////////////////////////////////////////////////////////////////////////
30#ifndef ALIFMDRING_H
31# include "AliFMDRing.h"
32#endif
33#ifndef ALILOG_H
34# include "AliLog.h"
35#endif
36#ifndef ROOT_TMath
37# include <TMath.h>
38#endif
39#ifndef ROOT_TH2
40# include <TH2.h>
41#endif
42#ifndef ROOT_TVirtualMC
43# include <TVirtualMC.h>
44#endif
45#ifndef ROOT_TVector2
46# include <TVector2.h>
47#endif
48#ifndef ROOT_TBrowser
49# include <TBrowser.h>
50#endif
51#ifndef ROOT_TString
52# include <TString.h>
53#endif
54#ifndef ROOT_TArc
55# include <TArc.h>
56#endif
57#ifndef ROOT_TObjArray
58# include <TObjArray.h>
59#endif
60#ifndef ROOT_TXTRU
61# include <TXTRU.h>
62#endif
63#ifndef ROOT_TNode
64# include <TNode.h>
65#endif
66#ifndef ROOT_TRotMatrix
67# include <TRotMatrix.h>
68#endif
69#ifndef ROOT_TList
70# include <TList.h>
71#endif
72#ifndef __IOSTREAM__
73# include <iostream>
74#endif
75
76ClassImp(AliFMDRing);
77
78//____________________________________________________________________
79// Construct a alifmdring.
80//
81// id Id of the ring (either 'i' or 'o').
82// lowr Lower radius of ring (in centimeters).
83// highr Upper radius of ring (in centimeters).
84// r Radius of the silicon wafers (in centimeters).
85// theta Opening angle of the silicon wafers.
86// strips Number of strips.
87AliFMDRing::AliFMDRing(Char_t id, Bool_t detailed)
88 : fId(id),
89 fDetailed(detailed),
90 fWaferRadius(0),
91 fSiThickness(0),
92 fLowR(0),
93 fHighR(0),
94 fTheta(0),
95 fNStrips(0),
96 fShape(0),
97 fRotMatricies(0)
98{}
99
100//____________________________________________________________________
101void
102AliFMDRing::Init()
103{
104 // Initialize the ring object.
105 // DebugGuard guard("AliFMDRing::Init");
106 AliDebug(10, "AliFMDRing::Init");
107 fPolygon.Clear();
108 SetupCoordinates();
109}
110
111//____________________________________________________________________
112AliFMDRing::~AliFMDRing()
113{
114 if (fShape) delete fShape;
115 if (fRotMatricies) delete fRotMatricies;
116}
117
118
119//____________________________________________________________________
120void
121AliFMDRing::Browse(TBrowser* /* b */)
122{
123 // DebugGuard guard("AliFMDRing::Browse");
124 AliDebug(10, "AliFMDRing::Browse");
125}
126
127
128//____________________________________________________________________
129void
130AliFMDRing::SetupCoordinates()
131{
132 // Calculates the parameters of the polygon shape.
133 //
134 // DebugGuard guard("AliFMDRing::SetupCoordinates");
135 AliDebug(10, "AliFMDRing::SetupCoordinates");
136 // Get out immediately if we have already done all this
137 if (fPolygon.GetNVerticies() > 1) return;
138
139 double tan_theta = TMath::Tan(fTheta * TMath::Pi() / 180.);
140 double tan_theta2 = TMath::Power(tan_theta,2);
141 double r2 = TMath::Power(fWaferRadius,2);
142 double y_A = tan_theta * fLowR;
143 double lr2 = TMath::Power(fLowR, 2);
144 double hr2 = TMath::Power(fHighR,2);
145 double x_D = fLowR + TMath::Sqrt(r2 - tan_theta2 * lr2);
146 double x_D2 = TMath::Power(x_D,2);
147 //double x_D_2 = fLowR - TMath::Sqrt(r2 - tan_theta2 * lr2);
148 double y_B = sqrt(r2 - hr2 + 2 * fHighR * x_D - x_D2);
149 double x_C = ((x_D + TMath::Sqrt(-tan_theta2 * x_D2 + r2
150 + r2 * tan_theta2))
151 / (1 + tan_theta2));
152 double y_C = tan_theta * x_C;
153
154 fPolygon.AddVertex(fLowR, -y_A);
155 fPolygon.AddVertex(x_C, -y_C);
156 fPolygon.AddVertex(fHighR, -y_B);
157 fPolygon.AddVertex(fHighR, y_B);
158 fPolygon.AddVertex(x_C, y_C);
159 fPolygon.AddVertex(fLowR, y_A);
160}
161
162//____________________________________________________________________
163bool
164AliFMDRing::IsWithin(size_t moduleNo, double x, double y) const
165{
166 // Checks if a point (x,y) is inside the module with number moduleNo
167 //
168 // DebugGuard guard("AliFMDRing::IsWithin");
169 AliDebug(10, "AliFMDRing::IsWithin");
170 bool ret = false;
171 double r2 = x * x + y * y;
172 if (r2 < fHighR * fHighR && r2 > fLowR * fLowR) {
173 // double point_angle = TMath::ATan2(y, x);
174 // int n_modules = 360 / Int_t(fTheta * 2);
175 double m_angle = (.5 + moduleNo) * 2 * fTheta;
176 double m_radians = TMath::Pi() * m_angle / 180.;
177
178 // Rotate the point.
179 double xr = x * TMath::Cos(-m_radians) - y * TMath::Sin(-m_radians);
180 double yr = x * TMath::Sin(-m_radians) + y * TMath::Cos(-m_radians);
181
182 ret = fPolygon.Contains(xr,yr);
183 }
184 return ret;
185}
186
187
188
189
190//____________________________________________________________________
191void
192AliFMDRing::Draw(Option_t* option) const
193{
194 // Draw a the shape of the ring into a 2D histogram. Useful for
195 // superimposing the actual shape of the ring onto a scatter plot of
196 // hits in the detector.
197 //
198 // DebugGuard guard("AliFMDRing::Draw");
199 AliDebug(10, "AliFMDRing::Draw");
200 // The unrotated coordinates of the polygon verticies
201 if (fPolygon.GetNVerticies() < 1) return;
202
203 TVector2 v[6];
204 for (size_t i = 0; i < fPolygon.GetNVerticies(); i++)
205 v[i] = fPolygon.GetVertex(i);
206
207 Int_t nModules = 360 / Int_t(fTheta * 2);
208 Double_t dTheta = fTheta * 2;
209
210 TString opt(option);
211 if (opt.Contains("B", TString::kIgnoreCase)) {
212 opt.Remove(opt.Index("B", 1, TString::kIgnoreCase),1);
213 TH1* null = new TH2F("null", "Null",
214 100, -fHighR * 1.1, fHighR * 1.1,
215 100, -fHighR * 1.1, fHighR * 1.1);
216 null->SetStats(0);
217 null->Draw(opt.Data());
218 }
219
220 for (int i = 0; i < nModules; i++) {
221 Double_t theta = (i + .5) * dTheta;
222 AliFMDPolygon p;
223 for (int j = 0; j < 6; j++) {
224 TVector2 vr(v[j].Rotate(TMath::Pi() * theta / 180.));
225 if (!p.AddVertex(vr.X(),vr.Y())) {
226 // std::cerr << "Draw of polygon " << i << " failed" << std::endl;
227 break;
228 }
229 }
230 p.Draw(opt.Data(), Form("MOD%c_%d", fId, i));
231 }
232 if (opt.Contains("0", TString::kIgnoreCase)) {
233 TArc* arcH = new TArc(0,0, fHighR);
234 arcH->SetLineStyle(2);
235 arcH->SetLineColor(4);
236 arcH->Draw();
237
238 TArc* arcL = new TArc(0,0, fLowR);
239 arcL->SetLineStyle(2);
240 arcL->SetLineColor(4);
241 arcL->Draw();
242 }
243}
244
245//____________________________________________________________________
246void
247AliFMDRing::SetupGeometry(Int_t vacuumId, Int_t siId, Int_t pcbId,
248 Int_t pbRotId, Int_t idRotId)
249{
250 // Setup the geometry of the ring. It defines the volumes
251 // RNGI or RNGO which can later be positioned in a sub-detector
252 // volume.
253 //
254 // The hieracy of the RNGx volume is
255 //
256 // RNGx // Ring volume
257 // VFx // Container of hybrid + legs
258 // ACTx // Active volume (si sensor approx)
259 // SECx // Section division
260 // STRx // Strip division
261 // PBTx // Print board (bottom)
262 // PTTx // Print board (top)
263 // LLEG // Support leg (long version)
264 // VBx // Container of hybrid + legs
265 // ACTx // Active volume (si sensor approx)
266 // SECx // Section division
267 // STRx // Strip division
268 // PBTx // Print board (bottom)
269 // PTTx // Print board (top)
270 // SLEG // Support leg (long version)
271 //
272 // Parameters:
273 //
274 // vacuumId Medium of inactive virtual volumes
275 // siId Medium of Silicon sensor (active)
276 // pcbId Medium of print boards
277 // pbRotId Print board rotation matrix
278 // idRotId Identity rotation matrix
279 //
280 // DebugGuard guard("AliFMDRing::SetupGeometry");
281 AliDebug(10, "AliFMDRing::SetupGeometry");
282
283 const TVector2& bCorner = fPolygon.GetVertex(3); // Third corner
284 const TVector2& aCorner = fPolygon.GetVertex(5); // First corner
285 const TVector2& cCorner = fPolygon.GetVertex(4); // Second corner
286 TString name;
287 TString name2;
288 Double_t dStrip = (bCorner.Mod() - aCorner.Mod()) / fNStrips;
289 Double_t stripOff = aCorner.Mod();
290 Double_t rmin = fLowR;
291 Double_t rmax = bCorner.Mod();
292 Double_t pars[10];
293 fRingDepth = (fSiThickness
294 + fPrintboardThickness
295 + fLegLength
296 + fModuleSpacing);
297
298 // Ring virtual volume
299 pars[0] = rmin;
300 pars[1] = fHighR;
301 pars[2] = fRingDepth / 2;
302 name = Form("RNG%c", fId);
303 fRingId = gMC->Gsvolu(name.Data(), "TUBE", vacuumId, pars, 3);
304
305 // Virtual volume for modules with long legs
306 pars[1] = rmax;
307 pars[3] = -fTheta;
308 pars[4] = fTheta;
309 name = Form("VF%c", fId);
310 fVirtualFrontId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5);
311
312 // Virtual volume for modules with long legs
313 pars[2] = (fRingDepth - fModuleSpacing) / 2;
314 name = Form("VB%c", fId);
315 fVirtualBackId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5);
316
317 // Virtual mother volume for silicon
318 pars[2] = fSiThickness/2;
319 name2 = name;
320 name = Form("ACT%c",fId);
321 fActiveId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId , pars, 5);
322
323 if (fDetailed) {
324 // Virtual sector volumes
325 name2 = name;
326 name = Form("SEC%c",fId);
327 gMC->Gsdvn2(name.Data(), name2.Data(), 2, 2, -fTheta, vacuumId);
328 fSectionId = gMC->VolId(name.Data());
329
330 // Active strip volumes
331 name2 = name;
332 name = Form("STR%c", fId);
333 gMC->Gsdvt2(name.Data(), name2.Data(), dStrip, 1,
334 stripOff, siId, fNStrips);
335 fStripId = gMC->VolId(name.Data());
336 }
337
338 // Print-board on back of module
339 pars[4] = TMath::Tan(TMath::Pi() * fTheta / 180) * fBondingWidth;
340 // Top of the print board
341 pars[0] = cCorner.Y() - pars[4];
342 pars[1] = bCorner.Y() - pars[4];
343 pars[2] = fPrintboardThickness / 2; // PCB half thickness
344 pars[3] = (bCorner.X() - cCorner.X()) / 2;
345 name = Form("PBT%c", fId);
346 fPrintboardTopId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4);
347
348 // Bottom of the print board
349 pars[0] = aCorner.Y() - pars[4];
350 pars[1] = cCorner.Y() - pars[4];
351 pars[3] = (cCorner.X() - aCorner.X()) / 2;
352 name = Form("PBB%c", fId);
353 fPrintboardBottomId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4);
354
355 // Define rotation matricies
356 Int_t nModules = 360 / Int_t(fTheta * 2);
357 Double_t dTheta = fTheta * 2;
358 fRotations.Set(nModules);
359 for (int i = 0; i < nModules; i++) {
360 Double_t theta = (i + .5) * dTheta;
361 Int_t idrot = 0;
362 // Rotation matrix for virtual module volumes
363 gMC->Matrix(idrot, 90, theta, 90, fmod(90 + theta, 360), 0, 0);
364 fRotations[i] = idrot;
365 }
366
367
368 // Int_t nModules = 360 / Int_t(fTheta * 2);
369 // Double_t dTheta = fTheta * 2;
370 Double_t pbTopL = (bCorner.X() - cCorner.X());
371 Double_t pbBotL = (cCorner.X() - aCorner.X());
372 Double_t yoffset = ((TMath::Tan(TMath::Pi() * fTheta / 180)
373 * fBondingWidth));
374
375 for (int i = 0; i < nModules; i++) {
376 TString name2 = Form("RNG%c", fId);
377
378 Int_t id = i;
379 // Double_t theta = (i + .5) * dTheta;
380 Bool_t isFront = (i % 2 == 1);
381 Double_t dz = 0;
382 Double_t w = fRingDepth - (isFront ? 0 : fModuleSpacing);
383
384 // Place virtual module volume
385 name = Form("V%c%c", (isFront ? 'F' : 'B'), fId);
386 dz = (w - fRingDepth) / 2;
387 gMC->Gspos(name.Data(), id, name2.Data(), 0., 0., dz,fRotations[i]);
388
389 // We only need to place the children once, they are copied when
390 // we place the other virtual volumes.
391 if (i > 1) continue;
392 name2 = name;
393
394 // Place active silicon wafer - this is put so that the front of
395 // the silicon is on the edge of the virtual volume.
396 name = Form("ACT%c", fId);
397 dz = (w - fSiThickness) / 2;
398 gMC->Gspos(name.Data(), id, name2.Data(),0.,0.,dz,idRotId);
399
400 // Place print board. This is put immediately behind the silicon
401 name = Form("PBT%c", fId);
402 dz = w / 2 - fSiThickness - fPrintboardThickness / 2;
403 gMC->Gspos(name.Data(), id, name2.Data(),
404 fLowR + pbBotL + pbTopL / 2, 0, dz, pbRotId, "ONLY");
405 name = Form("PBB%c", fId);
406 gMC->Gspos(name.Data(), id, name2.Data(),
407 fLowR + pbBotL / 2, 0, dz, pbRotId, "ONLY");
408
409 // Support legs
410 // This is put immediately behind the pringboard.
411 dz = (w / 2 - fSiThickness - fPrintboardThickness
412 - (fLegLength + (isFront ? fModuleSpacing : 0)) /2);
413 name = (isFront ? "LLEG" : "SLEG");
414 gMC->Gspos(name.Data(), id*10 + 1, name2.Data(),
415 aCorner.X() + fLegOffset + fLegRadius, 0., dz, idRotId, "");
416 Double_t y = cCorner.Y() - yoffset - fLegOffset - fLegRadius;
417 gMC->Gspos(name.Data(),id*10+2,name2.Data(),cCorner.X(), y,dz,idRotId,"");
418 gMC->Gspos(name.Data(),id*10+3,name2.Data(),cCorner.X(), -y,dz ,idRotId,"");
419 }
420}
421//____________________________________________________________________
422void
423AliFMDRing::Geometry(const char* mother, Int_t baseId, Double_t z,
424 Int_t /* pbRotId */, Int_t idRotId)
425{
426 // Positions a RNGx volume inside a mother.
427 //
428 // Parameters
429 //
430 // mother Mother volume to position the RNGx volume in
431 // baseId Base copy number
432 // z Z coordinate where the front of the active silicon
433 // should be in the mother volume, so we need to
434 // subtract half the ring width.
435 // idRotId Identity rotation matrix
436 //
437 // DebugGuard guard("AliFMDRing::Geometry");
438 AliDebug(10, "AliFMDRing::Geometry");
439 TString name;
440 Double_t offsetZ = (fSiThickness
441 + fPrintboardThickness
442 + fLegLength + fModuleSpacing) / 2;
443 name = Form("RNG%c", fId);
444 gMC->Gspos(name.Data(), baseId, mother, 0., 0., z - offsetZ, idRotId, "");
445}
446
447//____________________________________________________________________
448void
449AliFMDRing::SimpleGeometry(TList* nodes,
450 TNode* mother,
451 Int_t colour,
452 Double_t z,
453 Int_t n)
454{
455 // Make a simple geometry of the ring for event display.
456 //
457 // The simple geometry is made from ROOT TNode and TShape objects.
458 // Note, that we cache the TShape and TRotMatrix objects used for
459 // this.
460 //
461 // Parameters
462 //
463 // nodes List of nodes to register all create nodes in
464 // mother Mother node to put the ring in.
465 // colour Colour of the nodes
466 // z Z position of the node in the mother volume
467 // n Detector number
468 //
469 // DebugGuard guard("AliFMDRing::SimpleGeometry");
470 AliDebug(10, "AliFMDRing::SimpleGeometry");
471 SetupCoordinates();
472
473 // If the shape hasn't been defined yet, we define it here.
474 if (!fShape) {
475 TString name(Form("ACT%c", fId));
476 TString title(Form("Shape of modules in %c Rings", fId));
477 Int_t n = fPolygon.GetNVerticies();
478 TXTRU* shape = new TXTRU(name.Data(), title.Data(), "void", n, 2);
479 for (Int_t i = 0; i < n; i++) {
480 const TVector2& v = fPolygon.GetVertex(i);
481 shape->DefineVertex(i, v.X(), v.Y());
482 }
483 shape->DefineSection(0, - fSiThickness / 2, 1, 0, 0);
484 shape->DefineSection(1, + fSiThickness / 2, 1, 0, 0);
485 fShape = shape;
486 fShape->SetLineColor(colour);
487 }
488
489 Int_t nModules = 360 / Int_t(fTheta * 2);
490 Double_t dTheta = fTheta * 2;
491
492 // If the roation matricies hasn't been defined yet, we do so here
493 if (!fRotMatricies) {
494 fRotMatricies = new TObjArray(nModules);
495 for (int i = 0; i < nModules; i++) {
496 Double_t theta = (i + .5) * dTheta;
497 TString name(Form("FMD_ring_%c_rot", fId));
498 TString title(Form("FMD Ring %c Rotation", fId));
499 TRotMatrix* rot =
500 new TRotMatrix(name.Data(), title.Data(),
501 90, theta, 90, fmod(90 + theta, 360), 0, 0);
502 fRotMatricies->AddAt(rot, i);
503 }
504 }
505
506 Double_t offsetZ = (fSiThickness
507 + fPrintboardThickness
508 + fLegLength + fModuleSpacing) / 2;
509
510 // Make all the nodes
511 for (int i = 0; i < nModules; i++) {
512 Bool_t isFront = (i % 2 == 1);
513 mother->cd();
514 TRotMatrix* rot = static_cast<TRotMatrix*>(fRotMatricies->At(i));
515 TString name(Form("ACT%c_%d_%d", fId, n, i));
516 TString title(Form("Active FMD%d volume in %c Ring", n, fId));
517 TNode* node = new TNode(name.Data(), title.Data(), fShape,
518 0, 0,
519 z - offsetZ + (isFront ? fModuleSpacing : 0),
520 rot);
521 node->SetLineColor(colour);
522 nodes->Add(node);
523 }
524}
525
526
527
528//____________________________________________________________________
529void
530AliFMDRing::Gsatt()
531{
532 // Set drawing attributes for the RING
533 //
534 // DebugGuard guard("AliFMDRing::Gsatt");
535 AliDebug(10, "AliFMDRing::Gsatt");
536 TString name;
537 name = Form("RNG%c",fId);
538 gMC->Gsatt(name.Data(), "SEEN", 0);
539
540 name = Form("VF%c",fId);
541 gMC->Gsatt(name.Data(), "SEEN", 0);
542
543 name = Form("VB%c",fId);
544 gMC->Gsatt(name.Data(), "SEEN", 0);
545
546 name = Form("ACT%c",fId);
547 gMC->Gsatt(name.Data(), "SEEN", 1);
548
549 name = Form("PBT%c",fId);
550 gMC->Gsatt(name.Data(), "SEEN", 1);
551
552 name = Form("PBB%c",fId);
553 gMC->Gsatt(name.Data(), "SEEN", 1);
554}
555
556//
557// EOF
558//