]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDRing.cxx
6feac4741c1ae09523e67cdd7e9d0357a5df6027
[u/mrichter/AliRoot.git] / FMD / AliFMDRing.cxx
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
76 ClassImp(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. 
87 AliFMDRing::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 //____________________________________________________________________
101 void 
102 AliFMDRing::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 //____________________________________________________________________
112 AliFMDRing::~AliFMDRing() 
113 {
114   if (fShape) delete fShape;
115   if (fRotMatricies) delete fRotMatricies;
116 }
117
118
119 //____________________________________________________________________
120 void 
121 AliFMDRing::Browse(TBrowser* /* b */)
122 {
123   // DebugGuard guard("AliFMDRing::Browse");
124   AliDebug(10, "AliFMDRing::Browse");
125 }
126
127   
128 //____________________________________________________________________
129 void 
130 AliFMDRing::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 //____________________________________________________________________
163 bool
164 AliFMDRing::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 //____________________________________________________________________
191 void
192 AliFMDRing::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 //____________________________________________________________________
246 void 
247 AliFMDRing::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 //____________________________________________________________________
422 void 
423 AliFMDRing::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 //____________________________________________________________________
448 void 
449 AliFMDRing::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 //____________________________________________________________________
529 void 
530 AliFMDRing::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 //