Fixed a few problems
[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
42403906 76static const char* kRingFormat = "FRG%c";
77static const char* kVirtualFormat = "FV%c%c";
78static const char* kActiveFormat = "FAC%c";
79static const char* kSectorFormat = "FSE%c";
80static const char* kStripFormat = "FST%c";
81static const char* kPrintboardFormat = "FP%c%c";
82
83
84//____________________________________________________________________
4347b38f 85ClassImp(AliFMDRing);
86
87//____________________________________________________________________
4347b38f 88AliFMDRing::AliFMDRing(Char_t id, Bool_t detailed)
89 : fId(id),
90 fDetailed(detailed),
91 fWaferRadius(0),
92 fSiThickness(0),
93 fLowR(0),
94 fHighR(0),
95 fTheta(0),
96 fNStrips(0),
97 fShape(0),
98 fRotMatricies(0)
42403906 99{
100 // Construct a alifmdring.
101 //
102 // id Id of the ring (either 'i' or 'o').
103 // lowr Lower radius of ring (in centimeters).
104 // highr Upper radius of ring (in centimeters).
105 // r Radius of the silicon wafers (in centimeters).
106 // theta Opening angle of the silicon wafers.
107 // strips Number of strips.
108}
109
4347b38f 110
111//____________________________________________________________________
112void
113AliFMDRing::Init()
114{
115 // Initialize the ring object.
116 // DebugGuard guard("AliFMDRing::Init");
117 AliDebug(10, "AliFMDRing::Init");
118 fPolygon.Clear();
119 SetupCoordinates();
120}
121
122//____________________________________________________________________
123AliFMDRing::~AliFMDRing()
124{
42403906 125 // Destructor - deletes shape and rotation matricies
4347b38f 126 if (fShape) delete fShape;
127 if (fRotMatricies) delete fRotMatricies;
128}
129
130
131//____________________________________________________________________
132void
133AliFMDRing::Browse(TBrowser* /* b */)
134{
135 // DebugGuard guard("AliFMDRing::Browse");
136 AliDebug(10, "AliFMDRing::Browse");
137}
138
139
140//____________________________________________________________________
141void
142AliFMDRing::SetupCoordinates()
143{
144 // Calculates the parameters of the polygon shape.
145 //
146 // DebugGuard guard("AliFMDRing::SetupCoordinates");
147 AliDebug(10, "AliFMDRing::SetupCoordinates");
148 // Get out immediately if we have already done all this
149 if (fPolygon.GetNVerticies() > 1) return;
150
151 double tan_theta = TMath::Tan(fTheta * TMath::Pi() / 180.);
152 double tan_theta2 = TMath::Power(tan_theta,2);
153 double r2 = TMath::Power(fWaferRadius,2);
154 double y_A = tan_theta * fLowR;
155 double lr2 = TMath::Power(fLowR, 2);
156 double hr2 = TMath::Power(fHighR,2);
157 double x_D = fLowR + TMath::Sqrt(r2 - tan_theta2 * lr2);
158 double x_D2 = TMath::Power(x_D,2);
159 //double x_D_2 = fLowR - TMath::Sqrt(r2 - tan_theta2 * lr2);
160 double y_B = sqrt(r2 - hr2 + 2 * fHighR * x_D - x_D2);
161 double x_C = ((x_D + TMath::Sqrt(-tan_theta2 * x_D2 + r2
162 + r2 * tan_theta2))
163 / (1 + tan_theta2));
164 double y_C = tan_theta * x_C;
165
166 fPolygon.AddVertex(fLowR, -y_A);
167 fPolygon.AddVertex(x_C, -y_C);
168 fPolygon.AddVertex(fHighR, -y_B);
169 fPolygon.AddVertex(fHighR, y_B);
170 fPolygon.AddVertex(x_C, y_C);
171 fPolygon.AddVertex(fLowR, y_A);
172}
173
174//____________________________________________________________________
175bool
176AliFMDRing::IsWithin(size_t moduleNo, double x, double y) const
177{
178 // Checks if a point (x,y) is inside the module with number moduleNo
179 //
180 // DebugGuard guard("AliFMDRing::IsWithin");
181 AliDebug(10, "AliFMDRing::IsWithin");
182 bool ret = false;
183 double r2 = x * x + y * y;
184 if (r2 < fHighR * fHighR && r2 > fLowR * fLowR) {
185 // double point_angle = TMath::ATan2(y, x);
186 // int n_modules = 360 / Int_t(fTheta * 2);
187 double m_angle = (.5 + moduleNo) * 2 * fTheta;
188 double m_radians = TMath::Pi() * m_angle / 180.;
189
190 // Rotate the point.
191 double xr = x * TMath::Cos(-m_radians) - y * TMath::Sin(-m_radians);
192 double yr = x * TMath::Sin(-m_radians) + y * TMath::Cos(-m_radians);
193
194 ret = fPolygon.Contains(xr,yr);
195 }
196 return ret;
197}
198
199
200
201
202//____________________________________________________________________
203void
204AliFMDRing::Draw(Option_t* option) const
205{
206 // Draw a the shape of the ring into a 2D histogram. Useful for
207 // superimposing the actual shape of the ring onto a scatter plot of
208 // hits in the detector.
209 //
210 // DebugGuard guard("AliFMDRing::Draw");
211 AliDebug(10, "AliFMDRing::Draw");
212 // The unrotated coordinates of the polygon verticies
213 if (fPolygon.GetNVerticies() < 1) return;
214
215 TVector2 v[6];
216 for (size_t i = 0; i < fPolygon.GetNVerticies(); i++)
217 v[i] = fPolygon.GetVertex(i);
218
219 Int_t nModules = 360 / Int_t(fTheta * 2);
220 Double_t dTheta = fTheta * 2;
221
222 TString opt(option);
223 if (opt.Contains("B", TString::kIgnoreCase)) {
224 opt.Remove(opt.Index("B", 1, TString::kIgnoreCase),1);
225 TH1* null = new TH2F("null", "Null",
226 100, -fHighR * 1.1, fHighR * 1.1,
227 100, -fHighR * 1.1, fHighR * 1.1);
228 null->SetStats(0);
229 null->Draw(opt.Data());
230 }
231
232 for (int i = 0; i < nModules; i++) {
233 Double_t theta = (i + .5) * dTheta;
234 AliFMDPolygon p;
235 for (int j = 0; j < 6; j++) {
236 TVector2 vr(v[j].Rotate(TMath::Pi() * theta / 180.));
237 if (!p.AddVertex(vr.X(),vr.Y())) {
238 // std::cerr << "Draw of polygon " << i << " failed" << std::endl;
239 break;
240 }
241 }
242 p.Draw(opt.Data(), Form("MOD%c_%d", fId, i));
243 }
244 if (opt.Contains("0", TString::kIgnoreCase)) {
245 TArc* arcH = new TArc(0,0, fHighR);
246 arcH->SetLineStyle(2);
247 arcH->SetLineColor(4);
248 arcH->Draw();
249
250 TArc* arcL = new TArc(0,0, fLowR);
251 arcL->SetLineStyle(2);
252 arcL->SetLineColor(4);
253 arcL->Draw();
254 }
255}
256
257//____________________________________________________________________
258void
259AliFMDRing::SetupGeometry(Int_t vacuumId, Int_t siId, Int_t pcbId,
260 Int_t pbRotId, Int_t idRotId)
261{
262 // Setup the geometry of the ring. It defines the volumes
263 // RNGI or RNGO which can later be positioned in a sub-detector
264 // volume.
265 //
266 // The hieracy of the RNGx volume is
267 //
42403906 268 // FRGx // Ring volume
269 // FVFx // Container of hybrid + legs
270 // FACx // Active volume (si sensor approx)
271 // FSEx // Section division
272 // FSTx // Strip division
273 // FPTx // Print board (bottom)
274 // FPBx // Print board (top)
275 // FLL // Support leg (long version)
276 // FVBx // Container of hybrid + legs
277 // FACx // Active volume (si sensor approx)
278 // FSEx // Section division
279 // FSTx // Strip division
280 // FPTx // Print board (bottom)
281 // FPBx // Print board (top)
282 // FSL // Support leg (long version)
4347b38f 283 //
284 // Parameters:
285 //
286 // vacuumId Medium of inactive virtual volumes
287 // siId Medium of Silicon sensor (active)
288 // pcbId Medium of print boards
289 // pbRotId Print board rotation matrix
290 // idRotId Identity rotation matrix
291 //
292 // DebugGuard guard("AliFMDRing::SetupGeometry");
293 AliDebug(10, "AliFMDRing::SetupGeometry");
294
295 const TVector2& bCorner = fPolygon.GetVertex(3); // Third corner
296 const TVector2& aCorner = fPolygon.GetVertex(5); // First corner
297 const TVector2& cCorner = fPolygon.GetVertex(4); // Second corner
298 TString name;
299 TString name2;
300 Double_t dStrip = (bCorner.Mod() - aCorner.Mod()) / fNStrips;
301 Double_t stripOff = aCorner.Mod();
302 Double_t rmin = fLowR;
303 Double_t rmax = bCorner.Mod();
304 Double_t pars[10];
305 fRingDepth = (fSiThickness
306 + fPrintboardThickness
307 + fLegLength
308 + fModuleSpacing);
309
310 // Ring virtual volume
311 pars[0] = rmin;
312 pars[1] = fHighR;
313 pars[2] = fRingDepth / 2;
42403906 314 name = Form(kRingFormat, fId);
4347b38f 315 fRingId = gMC->Gsvolu(name.Data(), "TUBE", vacuumId, pars, 3);
316
317 // Virtual volume for modules with long legs
318 pars[1] = rmax;
319 pars[3] = -fTheta;
320 pars[4] = fTheta;
42403906 321 name = Form(kVirtualFormat, 'F', fId);
4347b38f 322 fVirtualFrontId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5);
323
324 // Virtual volume for modules with long legs
325 pars[2] = (fRingDepth - fModuleSpacing) / 2;
42403906 326 name = Form(kVirtualFormat, 'B', fId);
4347b38f 327 fVirtualBackId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5);
328
329 // Virtual mother volume for silicon
330 pars[2] = fSiThickness/2;
331 name2 = name;
42403906 332 name = Form(kActiveFormat, fId);
4347b38f 333 fActiveId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId , pars, 5);
334
335 if (fDetailed) {
336 // Virtual sector volumes
337 name2 = name;
42403906 338 name = Form(kSectorFormat, fId);
4347b38f 339 gMC->Gsdvn2(name.Data(), name2.Data(), 2, 2, -fTheta, vacuumId);
340 fSectionId = gMC->VolId(name.Data());
341
342 // Active strip volumes
343 name2 = name;
42403906 344 name = Form(kStripFormat, fId);
345 gMC->Gsdvt2(name.Data(), name2.Data(), dStrip, 1,stripOff, siId, fNStrips);
4347b38f 346 fStripId = gMC->VolId(name.Data());
347 }
348
349 // Print-board on back of module
350 pars[4] = TMath::Tan(TMath::Pi() * fTheta / 180) * fBondingWidth;
351 // Top of the print board
352 pars[0] = cCorner.Y() - pars[4];
353 pars[1] = bCorner.Y() - pars[4];
354 pars[2] = fPrintboardThickness / 2; // PCB half thickness
355 pars[3] = (bCorner.X() - cCorner.X()) / 2;
42403906 356 name = Form(kPrintboardFormat, 'T', fId);
4347b38f 357 fPrintboardTopId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4);
358
359 // Bottom of the print board
360 pars[0] = aCorner.Y() - pars[4];
361 pars[1] = cCorner.Y() - pars[4];
362 pars[3] = (cCorner.X() - aCorner.X()) / 2;
42403906 363 name = Form(kPrintboardFormat, 'B', fId);
4347b38f 364 fPrintboardBottomId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4);
365
366 // Define rotation matricies
367 Int_t nModules = 360 / Int_t(fTheta * 2);
368 Double_t dTheta = fTheta * 2;
369 fRotations.Set(nModules);
370 for (int i = 0; i < nModules; i++) {
371 Double_t theta = (i + .5) * dTheta;
372 Int_t idrot = 0;
373 // Rotation matrix for virtual module volumes
374 gMC->Matrix(idrot, 90, theta, 90, fmod(90 + theta, 360), 0, 0);
375 fRotations[i] = idrot;
376 }
377
378
379 // Int_t nModules = 360 / Int_t(fTheta * 2);
380 // Double_t dTheta = fTheta * 2;
381 Double_t pbTopL = (bCorner.X() - cCorner.X());
382 Double_t pbBotL = (cCorner.X() - aCorner.X());
383 Double_t yoffset = ((TMath::Tan(TMath::Pi() * fTheta / 180)
384 * fBondingWidth));
385
386 for (int i = 0; i < nModules; i++) {
42403906 387 TString name2 = Form(kRingFormat, fId);
4347b38f 388
389 Int_t id = i;
390 // Double_t theta = (i + .5) * dTheta;
391 Bool_t isFront = (i % 2 == 1);
392 Double_t dz = 0;
393 Double_t w = fRingDepth - (isFront ? 0 : fModuleSpacing);
394
395 // Place virtual module volume
42403906 396 name = Form(kVirtualFormat, (isFront ? 'F' : 'B'), fId);
4347b38f 397 dz = (w - fRingDepth) / 2;
398 gMC->Gspos(name.Data(), id, name2.Data(), 0., 0., dz,fRotations[i]);
399
400 // We only need to place the children once, they are copied when
401 // we place the other virtual volumes.
402 if (i > 1) continue;
403 name2 = name;
404
405 // Place active silicon wafer - this is put so that the front of
406 // the silicon is on the edge of the virtual volume.
42403906 407 name = Form(kActiveFormat, fId);
4347b38f 408 dz = (w - fSiThickness) / 2;
409 gMC->Gspos(name.Data(), id, name2.Data(),0.,0.,dz,idRotId);
410
411 // Place print board. This is put immediately behind the silicon
42403906 412 name = Form(kPrintboardFormat, 'T', fId);
4347b38f 413 dz = w / 2 - fSiThickness - fPrintboardThickness / 2;
414 gMC->Gspos(name.Data(), id, name2.Data(),
415 fLowR + pbBotL + pbTopL / 2, 0, dz, pbRotId, "ONLY");
afddaa11 416 name = Form(kPrintboardFormat, 'B', fId);
4347b38f 417 gMC->Gspos(name.Data(), id, name2.Data(),
418 fLowR + pbBotL / 2, 0, dz, pbRotId, "ONLY");
419
420 // Support legs
421 // This is put immediately behind the pringboard.
422 dz = (w / 2 - fSiThickness - fPrintboardThickness
423 - (fLegLength + (isFront ? fModuleSpacing : 0)) /2);
42403906 424 name = (isFront ? "FLL" : "FSL");
4347b38f 425 gMC->Gspos(name.Data(), id*10 + 1, name2.Data(),
426 aCorner.X() + fLegOffset + fLegRadius, 0., dz, idRotId, "");
427 Double_t y = cCorner.Y() - yoffset - fLegOffset - fLegRadius;
428 gMC->Gspos(name.Data(),id*10+2,name2.Data(),cCorner.X(), y,dz,idRotId,"");
429 gMC->Gspos(name.Data(),id*10+3,name2.Data(),cCorner.X(), -y,dz ,idRotId,"");
430 }
431}
432//____________________________________________________________________
433void
434AliFMDRing::Geometry(const char* mother, Int_t baseId, Double_t z,
435 Int_t /* pbRotId */, Int_t idRotId)
436{
437 // Positions a RNGx volume inside a mother.
438 //
439 // Parameters
440 //
441 // mother Mother volume to position the RNGx volume in
442 // baseId Base copy number
443 // z Z coordinate where the front of the active silicon
444 // should be in the mother volume, so we need to
445 // subtract half the ring width.
446 // idRotId Identity rotation matrix
447 //
448 // DebugGuard guard("AliFMDRing::Geometry");
449 AliDebug(10, "AliFMDRing::Geometry");
450 TString name;
451 Double_t offsetZ = (fSiThickness
452 + fPrintboardThickness
453 + fLegLength + fModuleSpacing) / 2;
42403906 454 name = Form(kRingFormat, fId);
4347b38f 455 gMC->Gspos(name.Data(), baseId, mother, 0., 0., z - offsetZ, idRotId, "");
456}
457
458//____________________________________________________________________
459void
460AliFMDRing::SimpleGeometry(TList* nodes,
461 TNode* mother,
462 Int_t colour,
463 Double_t z,
464 Int_t n)
465{
466 // Make a simple geometry of the ring for event display.
467 //
468 // The simple geometry is made from ROOT TNode and TShape objects.
469 // Note, that we cache the TShape and TRotMatrix objects used for
470 // this.
471 //
472 // Parameters
473 //
474 // nodes List of nodes to register all create nodes in
475 // mother Mother node to put the ring in.
476 // colour Colour of the nodes
477 // z Z position of the node in the mother volume
478 // n Detector number
479 //
480 // DebugGuard guard("AliFMDRing::SimpleGeometry");
481 AliDebug(10, "AliFMDRing::SimpleGeometry");
482 SetupCoordinates();
483
484 // If the shape hasn't been defined yet, we define it here.
485 if (!fShape) {
42403906 486 TString name(Form(kActiveFormat, fId));
4347b38f 487 TString title(Form("Shape of modules in %c Rings", fId));
488 Int_t n = fPolygon.GetNVerticies();
489 TXTRU* shape = new TXTRU(name.Data(), title.Data(), "void", n, 2);
490 for (Int_t i = 0; i < n; i++) {
491 const TVector2& v = fPolygon.GetVertex(i);
492 shape->DefineVertex(i, v.X(), v.Y());
493 }
494 shape->DefineSection(0, - fSiThickness / 2, 1, 0, 0);
495 shape->DefineSection(1, + fSiThickness / 2, 1, 0, 0);
496 fShape = shape;
497 fShape->SetLineColor(colour);
498 }
499
500 Int_t nModules = 360 / Int_t(fTheta * 2);
501 Double_t dTheta = fTheta * 2;
502
503 // If the roation matricies hasn't been defined yet, we do so here
504 if (!fRotMatricies) {
505 fRotMatricies = new TObjArray(nModules);
506 for (int i = 0; i < nModules; i++) {
507 Double_t theta = (i + .5) * dTheta;
508 TString name(Form("FMD_ring_%c_rot", fId));
509 TString title(Form("FMD Ring %c Rotation", fId));
510 TRotMatrix* rot =
511 new TRotMatrix(name.Data(), title.Data(),
512 90, theta, 90, fmod(90 + theta, 360), 0, 0);
513 fRotMatricies->AddAt(rot, i);
514 }
515 }
516
517 Double_t offsetZ = (fSiThickness
518 + fPrintboardThickness
519 + fLegLength + fModuleSpacing) / 2;
520
521 // Make all the nodes
522 for (int i = 0; i < nModules; i++) {
523 Bool_t isFront = (i % 2 == 1);
524 mother->cd();
525 TRotMatrix* rot = static_cast<TRotMatrix*>(fRotMatricies->At(i));
42403906 526 TString name(Form("FAC%c_%d_%d", fId, n, i));
4347b38f 527 TString title(Form("Active FMD%d volume in %c Ring", n, fId));
528 TNode* node = new TNode(name.Data(), title.Data(), fShape,
529 0, 0,
530 z - offsetZ + (isFront ? fModuleSpacing : 0),
531 rot);
532 node->SetLineColor(colour);
533 nodes->Add(node);
534 }
535}
536
537
538
539//____________________________________________________________________
540void
541AliFMDRing::Gsatt()
542{
543 // Set drawing attributes for the RING
544 //
545 // DebugGuard guard("AliFMDRing::Gsatt");
546 AliDebug(10, "AliFMDRing::Gsatt");
547 TString name;
42403906 548 name = Form(kRingFormat,fId);
4347b38f 549 gMC->Gsatt(name.Data(), "SEEN", 0);
550
42403906 551 name = Form(kVirtualFormat, 'T', fId);
4347b38f 552 gMC->Gsatt(name.Data(), "SEEN", 0);
553
42403906 554 name = Form(kVirtualFormat, 'B', fId);
4347b38f 555 gMC->Gsatt(name.Data(), "SEEN", 0);
556
42403906 557 name = Form(kActiveFormat,fId);
4347b38f 558 gMC->Gsatt(name.Data(), "SEEN", 1);
559
42403906 560 name = Form(kPrintboardFormat, 'T', fId);
4347b38f 561 gMC->Gsatt(name.Data(), "SEEN", 1);
562
42403906 563 name = Form(kPrintboardFormat, 'B',fId);
4347b38f 564 gMC->Gsatt(name.Data(), "SEEN", 1);
565}
566
567//
568// EOF
569//