1d7e8999a83b97a00032018294b1128358b6f232
[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 static const char* kRingFormat         = "FRG%c";
77 static const char* kVirtualFormat      = "FV%c%c";
78 static const char* kActiveFormat       = "FAC%c";
79 static const char* kSectorFormat       = "FSE%c";
80 static const char* kStripFormat        = "FST%c";
81 static const char* kPrintboardFormat   = "FP%c%c";
82
83
84 //____________________________________________________________________
85 ClassImp(AliFMDRing);
86
87 //____________________________________________________________________
88 AliFMDRing::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)
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
110
111 //____________________________________________________________________
112 void 
113 AliFMDRing::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 //____________________________________________________________________
123 AliFMDRing::~AliFMDRing() 
124 {
125   // Destructor - deletes shape and rotation matricies 
126   if (fShape) delete fShape;
127   if (fRotMatricies) delete fRotMatricies;
128 }
129
130
131 //____________________________________________________________________
132 void 
133 AliFMDRing::Browse(TBrowser* /* b */)
134 {
135   // DebugGuard guard("AliFMDRing::Browse");
136   AliDebug(10, "AliFMDRing::Browse");
137 }
138
139   
140 //____________________________________________________________________
141 void 
142 AliFMDRing::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 //____________________________________________________________________
175 bool
176 AliFMDRing::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 //____________________________________________________________________
203 void
204 AliFMDRing::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 //____________________________________________________________________
258 void 
259 AliFMDRing::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   // 
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)
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;
314   name                = Form(kRingFormat, fId);
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;
321   name                = Form(kVirtualFormat, 'F', fId);
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;
326   name                =  Form(kVirtualFormat, 'B', fId);
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;
332   name                =  Form(kActiveFormat, fId);
333   fActiveId           =  gMC->Gsvolu(name.Data(), "TUBS", vacuumId , pars, 5);
334
335   if (fDetailed) {
336     // Virtual sector volumes 
337     name2               = name;
338     name                = Form(kSectorFormat, fId);
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;
344     name                = Form(kStripFormat, fId);
345     gMC->Gsdvt2(name.Data(), name2.Data(), dStrip, 1,stripOff, siId, fNStrips);
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;
356   name                = Form(kPrintboardFormat, 'T', fId);
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;
363   name                = Form(kPrintboardFormat, 'B', fId);
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++) {
387     TString  name2    = Form(kRingFormat, fId);
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 
396     name = Form(kVirtualFormat, (isFront ? 'F' : 'B'), fId);
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. 
407     name  = Form(kActiveFormat, fId);
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
412     name = Form(kPrintboardFormat, 'T', fId);
413     dz   =  w / 2 - fSiThickness - fPrintboardThickness / 2;
414     gMC->Gspos(name.Data(), id, name2.Data(), 
415                fLowR + pbBotL + pbTopL / 2, 0, dz, pbRotId, "ONLY");
416     name = Form(kPrintboardFormat, fId);
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);
424     name  = (isFront ? "FLL" : "FSL");
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 //____________________________________________________________________
433 void 
434 AliFMDRing::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;
454   name = Form(kRingFormat, fId);
455   gMC->Gspos(name.Data(), baseId, mother, 0., 0., z - offsetZ, idRotId, "");
456 }
457
458 //____________________________________________________________________
459 void 
460 AliFMDRing::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) {
486     TString name(Form(kActiveFormat, fId));
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));
526     TString name(Form("FAC%c_%d_%d", fId, n, i));
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 //____________________________________________________________________
540 void 
541 AliFMDRing::Gsatt() 
542 {
543   // Set drawing attributes for the RING 
544   // 
545   // DebugGuard guard("AliFMDRing::Gsatt");
546   AliDebug(10, "AliFMDRing::Gsatt");
547   TString name;
548   name = Form(kRingFormat,fId);
549   gMC->Gsatt(name.Data(), "SEEN", 0);
550
551   name = Form(kVirtualFormat, 'T', fId);
552   gMC->Gsatt(name.Data(), "SEEN", 0);
553
554   name = Form(kVirtualFormat, 'B', fId);
555   gMC->Gsatt(name.Data(), "SEEN", 0);
556
557   name = Form(kActiveFormat,fId);
558   gMC->Gsatt(name.Data(), "SEEN", 1);
559
560   name = Form(kPrintboardFormat, 'T', fId);
561   gMC->Gsatt(name.Data(), "SEEN", 1);
562
563   name = Form(kPrintboardFormat, 'B',fId);
564   gMC->Gsatt(name.Data(), "SEEN", 1);
565 }
566
567 //
568 // EOF
569 //