Formatting changes.
[u/mrichter/AliRoot.git] / MUON / AliMUONGeometryMisAligner.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *      SigmaEffect_thetadegrees                                          * 
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 purpeateose. It is      *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17 //
18 //__________________________________________________________________
19 /// \class AliMUONGeometryMisAligner
20 ///
21 /// This performs the misalignment on an existing muon arm geometry
22 /// based on the standard definition of the detector elements in 
23 /// $ALICE_ROOT/MUON/data
24 ///
25 /// --> User has to specify the magnitude of the alignments, in the Cartesian 
26 /// co-ordiantes (which are used to apply translation misalignments) and in the
27 /// spherical co-ordinates (which are used to apply angular displacements)
28 ///
29 /// --> If the constructor is used with no arguments, user has to set 
30 /// misalignment ranges by hand using the methods : 
31 /// SetApplyMisAlig, SetMaxCartMisAlig, SetMaxAngMisAlig, SetXYAngMisAligFactor
32 /// (last method takes account of the fact that the misalingment is greatest in 
33 /// the XY plane, since the detection elements are fixed to a support structure
34 /// in this plane. Misalignments in the XZ and YZ plane will be very small 
35 /// compared to those in the XY plane, which are small already - of the order 
36 /// of microns)
37 ///
38 /// Note : If the detection elements are allowed to be misaligned in all
39 /// directions, this has consequences for the alignment algorithm
40 /// (AliMUONAlignment), which needs to know the number of free parameters. 
41 /// Eric only allowed 3 :  x,y,theta_xy, but in principle z and the other 
42 /// two angles are alignable as well.
43 ///
44 /// \authors Bruce Becker, Javier Castillo
45
46 #include "AliMUONGeometryMisAligner.h"
47 #include "AliMUONGeometryTransformer.h"
48 #include "AliMUONGeometryModuleTransformer.h"
49 #include "AliMUONGeometryDetElement.h"
50 #include "AliMUONGeometryBuilder.h"
51
52 #include "AliMpExMap.h"
53
54 #include "AliLog.h"
55
56 #include <TGeoMatrix.h>
57 #include <TMath.h>
58 #include <TRandom.h>
59
60 /// \cond CLASSIMP
61 ClassImp(AliMUONGeometryMisAligner)
62 /// \endcond
63
64 //______________________________________________________________________________
65 AliMUONGeometryMisAligner::AliMUONGeometryMisAligner(Double_t cartXMisAligM, Double_t cartXMisAligW, Double_t cartYMisAligM, Double_t cartYMisAligW, Double_t angMisAligM, Double_t angMisAligW)
66   : TObject(),
67     fUseUni(kFALSE),
68     fUseGaus(kTRUE),
69     fCartXMisAligM(cartXMisAligM),
70     fCartXMisAligW(cartXMisAligW), // 0.5 mm. Perhaps this should go into AliMUONConstants.h ? 
71     fCartYMisAligM(cartYMisAligM),
72     fCartYMisAligW(cartYMisAligW), // 0.5 mm. Perhaps this should go into AliMUONConstants.h ? 
73     fAngMisAligM(angMisAligM),
74     fAngMisAligW(angMisAligW),
75     fXYAngMisAligFactor(0.0),
76     fZCartMisAligFactor(0.0),
77     fDisplacementGenerator(0)
78 {
79   /// Standard constructor
80   fDisplacementGenerator = new TRandom(0);
81 }
82
83 //______________________________________________________________________________
84 AliMUONGeometryMisAligner::AliMUONGeometryMisAligner(Double_t cartMisAligM, Double_t cartMisAligW, Double_t angMisAligM, Double_t angMisAligW)
85   : TObject(), 
86     fUseUni(kFALSE),
87     fUseGaus(kTRUE),
88     fCartXMisAligM(cartMisAligM),
89     fCartXMisAligW(cartMisAligW), // 0.5 mm. Perhaps this should go into AliMUONConstants.h ? 
90     fCartYMisAligM(cartMisAligM),
91     fCartYMisAligW(cartMisAligW), // 0.5 mm. Perhaps this should go into AliMUONConstants.h ? 
92     fAngMisAligM(angMisAligM),
93     fAngMisAligW(angMisAligW),
94     fXYAngMisAligFactor(0.0),
95     fZCartMisAligFactor(0.0),
96     fDisplacementGenerator(0)
97 {
98   /// Standard constructor
99   fDisplacementGenerator = new TRandom(0);
100 }
101
102 //______________________________________________________________________________
103 AliMUONGeometryMisAligner::AliMUONGeometryMisAligner(Double_t cartMisAlig, Double_t angMisAlig)
104   : TObject(), 
105     fUseUni(kTRUE),
106     fUseGaus(kFALSE),
107     fCartXMisAligM(0.),
108     fCartXMisAligW(cartMisAlig), // 0.5 mm. Perhaps this should go into AliMUONConstants.h ? 
109     fCartYMisAligM(0.),
110     fCartYMisAligW(cartMisAlig), // 0.5 mm. Perhaps this should go into AliMUONConstants.h ? 
111     fAngMisAligM(0.),
112     fAngMisAligW(angMisAlig),
113     fXYAngMisAligFactor(0.0),
114     fZCartMisAligFactor(0.0),
115     fDisplacementGenerator(0)
116 {
117   /// Standard constructor
118   fDisplacementGenerator = new TRandom(0);
119 }
120
121 //_____________________________________________________________________________
122 AliMUONGeometryMisAligner::AliMUONGeometryMisAligner()
123   : TObject(), 
124     fUseUni(kTRUE),
125     fUseGaus(kFALSE),
126     fCartXMisAligM(0.),
127     fCartXMisAligW(0.),
128     fCartYMisAligM(0.),
129     fCartYMisAligW(0.),
130     fAngMisAligM(0.),
131     fAngMisAligW(0.),
132     fXYAngMisAligFactor(0.0),
133     fZCartMisAligFactor(0.0),
134     fDisplacementGenerator(0)
135 {
136   /// Default constructor
137 }
138
139 //______________________________________________________________________________
140 AliMUONGeometryMisAligner::~AliMUONGeometryMisAligner()
141 {
142 /// Destructor
143
144   if (fDisplacementGenerator) delete fDisplacementGenerator;
145 }
146
147 //_________________________________________________________________________
148 void
149 AliMUONGeometryMisAligner::SetXYAngMisAligFactor(Double_t factor)
150 {
151   /// Set XY angular misalign factor 
152
153   if (TMath::Abs(factor) > 1.0 && factor > 0.)
154     fXYAngMisAligFactor = factor;
155   else
156     AliError(Form("Invalid XY angular misalign factor, %d", factor));
157 }
158
159 //_________________________________________________________________________
160 void AliMUONGeometryMisAligner::SetZCartMisAligFactor(Double_t factor) 
161 {
162   /// Set XY angular misalign factor 
163   if (TMath::Abs(factor)<1.0 && factor>0.)
164     fZCartMisAligFactor = factor;
165   else
166     AliError(Form("Invalid Z cartesian misalign factor, %d", factor));
167 }
168
169 //_________________________________________________________________________
170 void AliMUONGeometryMisAligner::GetUniMisAlign(Double_t cartMisAlig[3], Double_t angMisAlig[3]) const
171 {
172   /// Misalign using uniform distribution
173   /**
174     misalign the centre of the local transformation
175     rotation axes : 
176     fAngMisAlig[1,2,3] = [x,y,z]
177     Assume that misalignment about the x and y axes (misalignment of z plane)
178     is much smaller, since the entire detection plane has to be moved (the 
179     detection elements are on a support structure), while rotation of the x-y
180     plane is more free.
181   */
182   cartMisAlig[0] = fDisplacementGenerator->Uniform(-fCartXMisAligW+fCartXMisAligM, fCartXMisAligM+fCartXMisAligW);
183   cartMisAlig[1] = fDisplacementGenerator->Uniform(-fCartYMisAligW+fCartYMisAligM, fCartYMisAligM+fCartYMisAligW);
184   cartMisAlig[2] = fDisplacementGenerator->Uniform(-fZCartMisAligFactor*(fCartXMisAligW+fCartXMisAligM), fZCartMisAligFactor*(fCartXMisAligM+fCartXMisAligW));  
185  
186   angMisAlig[0] = fDisplacementGenerator->Uniform(-fXYAngMisAligFactor*(fAngMisAligW+fAngMisAligM), fXYAngMisAligFactor*(fAngMisAligM+fAngMisAligW));
187   angMisAlig[1] = fDisplacementGenerator->Uniform(-fXYAngMisAligFactor*(fAngMisAligW+fAngMisAligM), fXYAngMisAligFactor*(fAngMisAligM+fAngMisAligW));
188   angMisAlig[2] = fDisplacementGenerator->Uniform(-fAngMisAligW+fAngMisAligM, fAngMisAligM+fAngMisAligW);       // degrees
189 }
190
191 //_________________________________________________________________________
192 void AliMUONGeometryMisAligner::GetGausMisAlign(Double_t cartMisAlig[3], Double_t angMisAlig[3]) const
193 {
194   /// Misalign using gaussian distribution
195   /**
196     misalign the centre of the local transformation
197     rotation axes : 
198     fAngMisAlig[1,2,3] = [x,y,z]
199     Assume that misalignment about the x and y axes (misalignment of z plane)
200     is much smaller, since the entire detection plane has to be moved (the 
201     detection elements are on a support structure), while rotation of the x-y
202     plane is more free.
203   */
204   cartMisAlig[0] = fDisplacementGenerator->Gaus(fCartXMisAligM, fCartXMisAligW);
205   cartMisAlig[1] = fDisplacementGenerator->Gaus(fCartYMisAligM, fCartYMisAligW);
206   cartMisAlig[2] = fDisplacementGenerator->Gaus(fCartXMisAligM, fZCartMisAligFactor*fCartXMisAligW);
207  
208   angMisAlig[0] = fDisplacementGenerator->Gaus(fAngMisAligM, fXYAngMisAligFactor*fAngMisAligW);
209   angMisAlig[1] = fDisplacementGenerator->Gaus(fAngMisAligM, fXYAngMisAligFactor*fAngMisAligW);
210   angMisAlig[2] = fDisplacementGenerator->Gaus(fAngMisAligM, fAngMisAligW);     // degrees
211 }
212
213 //_________________________________________________________________________
214 TGeoCombiTrans AliMUONGeometryMisAligner::MisAlign(const TGeoCombiTrans & transform) const
215 {
216   /// Misalign given transformation and return the misaligned transformation
217   
218   Double_t cartMisAlig[3] = {0,0,0};
219   Double_t angMisAlig[3] = {0,0,0};
220   const Double_t *trans = transform.GetTranslation();
221   TGeoRotation *rot;
222   // check if the rotation we obtain is not NULL
223   if (transform.GetRotation())
224     {
225       rot = transform.GetRotation();
226     }
227   else
228     {
229       rot = new TGeoRotation("rot");
230     }                   // default constructor.
231
232   if (fUseUni) { 
233     GetUniMisAlign(cartMisAlig,angMisAlig);
234   }
235   else { 
236     if (!fUseGaus) {
237       AliWarning("Neither uniform nor gausian distribution is set! Will use gausian...");
238     } 
239     GetGausMisAlign(cartMisAlig,angMisAlig);
240   }
241
242   TGeoTranslation newTrans(cartMisAlig[0] + trans[0], cartMisAlig[1] + trans[1], cartMisAlig[2] + trans[2]);
243   
244   AliInfo(Form("Rotated by %f about Z axis.", angMisAlig[2]));
245   rot->RotateX(angMisAlig[0]);
246   rot->RotateY(angMisAlig[1]);
247   rot->RotateZ(angMisAlig[2]);
248
249   return TGeoCombiTrans(newTrans, *rot);
250 }
251
252 //______________________________________________________________________
253 AliMUONGeometryTransformer *
254 AliMUONGeometryMisAligner::MisAlign(const AliMUONGeometryTransformer *
255                                  transformer, Bool_t verbose)
256 {
257   /// Takes the internal geometry module transformers, copies them
258   /// and gets the Detection Elements from them.
259   /// Calculates misalignment parameters and applies these
260   /// to the local transform of the Detection Element
261   /// Obtains the global transform by multiplying the module transformer
262   /// transformation with the local transformation 
263   /// Applies the global transform to a new detection element
264   /// Adds the new detection element to a new module transformer
265   /// Adds the new module transformer to a new geometry transformer
266   /// Returns the new geometry transformer
267
268
269   AliMUONGeometryTransformer *newGeometryTransformer =
270     new AliMUONGeometryTransformer(kTRUE);
271   for (Int_t iMt = 0; iMt < transformer->GetNofModuleTransformers(); iMt++)
272     {                           // module transformers
273       
274       const AliMUONGeometryModuleTransformer *kModuleTransformer =
275         transformer->GetModuleTransformer(iMt, true);
276       
277       AliMUONGeometryModuleTransformer *newModuleTransformer =
278         new AliMUONGeometryModuleTransformer(iMt);
279       newGeometryTransformer->AddModuleTransformer(newModuleTransformer);
280
281       TGeoCombiTrans moduleTransform =
282         TGeoCombiTrans(*kModuleTransformer->GetTransformation());
283       TGeoCombiTrans *newModuleTransform = new TGeoCombiTrans(moduleTransform); 
284               // same module transform as the previous one 
285               // no mis align object created
286       newModuleTransformer->SetTransformation(moduleTransform);
287
288       AliMpExMap *detElements = kModuleTransformer->GetDetElementStore();
289
290       if (verbose)
291         AliInfo(Form
292                 ("%i DEs in old GeometryStore  %i",
293                  detElements->GetSize(), iMt));
294
295       for (Int_t iDe = 0; iDe < detElements->GetSize(); iDe++)
296         {                       // detection elements.
297           AliMUONGeometryDetElement *detElement =
298             (AliMUONGeometryDetElement *) detElements->GetObject(iDe);
299           if (!detElement)
300             AliFatal("Detection element not found.");
301
302           /// make a new detection element
303           AliMUONGeometryDetElement *newDetElement =
304             new AliMUONGeometryDetElement(detElement->GetId(),
305                                           detElement->GetVolumePath());
306
307           // local transformation of this detection element.
308           TGeoCombiTrans localTransform
309             = TGeoCombiTrans(*detElement->GetLocalTransformation());
310           TGeoCombiTrans newLocalTransform = MisAlign(localTransform);
311           newDetElement->SetLocalTransformation(newLocalTransform);                                       
312
313           // global transformation
314           TGeoHMatrix newGlobalTransform =
315             AliMUONGeometryBuilder::Multiply(*newModuleTransform,
316                                               newLocalTransform);
317           newDetElement->SetGlobalTransformation(newGlobalTransform);
318           
319           // add this det element to module
320           newModuleTransformer->GetDetElementStore()->Add(newDetElement->GetId(),
321                                                           newDetElement);
322           // Get delta transformation: 
323           // Tdelta = Tnew * Told.inverse
324           TGeoHMatrix  deltaTransform
325             = AliMUONGeometryBuilder::Multiply(
326                 newGlobalTransform, 
327                 detElement->GetGlobalTransformation()->Inverse());
328           
329           // Create mis alignment matrix
330           newGeometryTransformer
331             ->AddMisAlignDetElement(detElement->GetId(), deltaTransform);
332         }
333       if (verbose)
334         AliInfo(Form("Added module transformer %i to the transformer", iMt));
335       newGeometryTransformer->AddModuleTransformer(newModuleTransformer);
336     }
337   return newGeometryTransformer;
338 }
339
340
341
342