Adding classes forgotten in previous commit
[u/mrichter/AliRoot.git] / MUON / AliMUONContourMakerTest.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, 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 /// \class AliMUONContourMakerTest
20 /// 
21 /// Class used to test (and in particular time) the contour creation
22 /// algorithms.
23 ///
24 /// \author Laurent Aphecetche, Subatech
25 ///
26
27 #include "AliMUONContourMakerTest.h"
28
29 #include "AliCodeTimer.h"
30 #include "AliLog.h"
31 #include "AliMUONContour.h"
32 #include "AliMUONContourMaker.h"
33 #include "AliMUONGeometryDetElement.h"
34 #include "AliMUONGeometryTransformer.h"
35 #include "AliMUONManuContourMaker.h"
36 #include "AliMUONPolygon.h"
37 #include "AliMUONSegment.h"
38 #include "AliMpArea.h"
39 #include "AliMpCDB.h"
40 #include "AliMpDDLStore.h"
41 #include "AliMpDEManager.h"
42 #include "AliMpExMap.h"
43 #include <float.h>
44 #include "Riostream.h"
45 #include "TArrow.h"
46 #include "TCanvas.h"
47 #include "TFile.h"
48 #include "TGeoMatrix.h"
49 #include "TLine.h"
50 #include "TObjArray.h"
51 #include "TPolyLine.h"
52 #include "TSystem.h"
53
54 ///\cond CLASSIMP
55 ClassImp(AliMUONContourMakerTest)
56 ///\endcond 
57
58 namespace
59 {
60   //_____________________________________________________________________________
61   void Plot(TPolyLine& line, Bool_t orientation)
62   {
63     if ( !orientation ) 
64     {
65       line.Draw();
66     }
67     else
68     {
69       Double_t* x = line.GetX();
70       Double_t* y = line.GetY();
71       
72       for ( Int_t i = 0; i < line.GetLastPoint(); ++i ) 
73       {
74         Double_t x1 = x[i];
75         Double_t y1 = y[i];
76         Double_t x2 = x[i+1];
77         Double_t y2 = y[i+1];
78         
79         Bool_t horizontal = AliMUONSegment::AreEqual(y1,y2);
80         
81         TLine* a = new TArrow(x1,y1,x2,y2,0.03,"->-");
82         if (horizontal)
83         {
84           a->SetLineStyle(3);
85         }
86         a->Draw();
87       }
88     }
89   }
90 }
91
92 //_____________________________________________________________________________
93 AliMUONContourMakerTest::AliMUONContourMakerTest()
94 {
95   /// ctor
96 }
97
98 //_____________________________________________________________________________
99 AliMUONContourMakerTest::~AliMUONContourMakerTest()
100 {
101   /// dtor
102 }
103
104
105 //______________________________________________________________________________
106 TObjArray*
107 AliMUONContourMakerTest::CreateContourList(const TObjArray& manuContours)
108 {    
109   /// Create an array of maps of contour names
110   ///
111   /// Assyming that key is something like station#/chamber#/de#/buspatch#/manu#
112   /// the idea here is to put one TMap for each level in mapArray :
113   ///
114   /// mapArray[0].key = station0
115   /// mapArray[0].value = map of strings { station0/chamber0, station0/chamber1 }
116   ///
117   /// Then each entry in mapArray will be converted into a contour by
118   /// merging its children (e.g. station0 contour will be made from the merging
119   /// of station0/chamber0 and station0/chamber1 in the example above).
120   ///
121   
122   AliCodeTimerAuto("");
123   
124   TIter next(&manuContours);
125   AliMUONContour* contour;
126   TObjArray* mapArray = new TObjArray;
127
128   while ( ( contour = static_cast<AliMUONContour*>(next()) ) )
129   {
130     // Key is something like station#/chamber#/de#/buspatch#/manu#
131
132     TString key(contour->GetName());
133     TObjArray* s = key.Tokenize("/");
134     for ( Int_t i = 0; i < s->GetLast(); ++i ) 
135     {
136       TMap* m = static_cast<TMap*>(mapArray->At(i));
137       if (!m)
138       {
139         m = new TMap;
140         if ( i > mapArray->GetSize() ) mapArray->Expand(i);
141           mapArray->AddAt(m,i);
142           }
143       TString parent;
144       for ( Int_t k = 0; k <= i; ++k )
145       {
146         TObjString* str = static_cast<TObjString*>(s->At(k));
147         parent += str->String();
148         if ( k < i ) parent += "/";
149           }
150       TString child(parent);
151       child += "/";
152       child += static_cast<TObjString*>(s->At(i+1))->String();
153       
154       TObjArray* ma = static_cast<TObjArray*>(m->GetValue(parent.Data()));
155       if (!ma)
156       {
157         ma = new TObjArray;
158         m->Add(new TObjString(parent.Data()),ma);
159       }
160       TPair* p = static_cast<TPair*>(ma->FindObject(child.Data()));
161       if ( !p ) 
162       {
163         ma->Add(new TObjString(child.Data()));
164       }
165     }
166     delete s;
167   }
168  
169   return mapArray;
170 }
171
172 //_____________________________________________________________________________
173 void 
174 AliMUONContourMakerTest::Exec(const Option_t* opt)
175 {
176   /// Main method
177   /// Generate the geometry transformations, then
178   /// contours for all manus, and then for all the elements
179   /// (bus patches, detection elements, etc...)
180   
181   AliInfo("Resetting all timers before I start...");
182   
183   AliCodeTimer::Instance()->Reset();
184   
185   AliMpCDB::LoadDDLStore2();
186   
187   AliCodeTimer::Instance()->Print();
188   
189   AliInfo("Resetting all timers after loading the mapping...");
190   
191   AliCodeTimer::Instance()->Reset();
192   
193   AliCodeTimerAuto("");
194   
195   AliMpExMap* real(0x0);
196   AliMpExMap* exploded(0x0);
197   
198   GenerateTransformations(real,exploded);
199   
200   TObjArray* manus(0x0);
201   TObjArray* all(0x0);
202   
203   TString sopt(opt);
204   
205   if ( sopt.Contains("MANU") || sopt.Contains("ALL") ) 
206   {
207     AliMUONManuContourMaker manuMaker(exploded);
208     manus = manuMaker.GenerateManuContours(kTRUE);
209   }
210   
211   if ( sopt.Contains("ALL") && manus )
212   {
213     manus->SetOwner(kFALSE);
214     all = GenerateAllContours(*manus);
215     if ( sopt.Contains("SAVE") && all )
216     {
217       TFile f("AliMUONContourMakerTest.all.root","RECREATE");
218       all->Write("ALL",TObject::kSingleKey);
219       f.Close();
220     }
221     
222   }
223   
224   AliCodeTimer::Instance()->Print();
225   
226   delete manus;
227   delete all;
228 }
229
230 //______________________________________________________________________________
231 TObjArray* 
232 AliMUONContourMakerTest::GenerateAllContours(const TObjArray& manuContours)
233 {
234   /// From a map of manu contours, generate the compound contours (bp, de, etc...)
235   /// by merging them.
236   /// Note that manuContours should NOT be the owner of its contours,
237   /// as they are adopted by the array returned by this method.
238   
239   AliCodeTimerAuto("");
240   
241   // Get the list of contours to create
242   TObjArray* mapArray = CreateContourList(manuContours);
243     
244   // Now loop over the mapArray to actually create the contours
245   TIter next2(mapArray,kIterBackward);
246
247   TMap allContourMap;
248   allContourMap.SetOwnerKeyValue(kTRUE,kFALSE); // not owner of contours, as the returned array will be the owner
249   TObjArray* allContourArray = new TObjArray;
250   allContourArray->SetOwner(kTRUE);
251   
252   TIter nextContour(&manuContours);  
253   AliMUONContour* contour(0x0);
254   
255   while ( ( contour = static_cast<AliMUONContour*>(nextContour()) ) )
256   {
257     allContourMap.Add(new TObjString(contour->GetName()),contour);
258     allContourArray->Add(contour);
259   }
260   
261   AliMUONContourMaker maker;
262   
263   for ( Int_t i = mapArray->GetLast(); i >= 1; --i ) 
264     // end at 1 to avoid merging different cathodes together, which
265     // would not work...
266   {
267     TMap* a = static_cast<TMap*>(mapArray->At(i));
268     TIter next3(a);
269     TObjString* str;
270     while ( ( str = static_cast<TObjString*>(next3()) ) )
271     {
272       TObjArray* m = static_cast<TObjArray*>(a->GetValue(str->String().Data()));
273       TIter next4(m);
274       TObjString* k;
275       TObjArray subcontours;
276       subcontours.SetOwner(kFALSE);
277       while ( ( k = static_cast<TObjString*>(next4()) ) )
278       {
279         contour = static_cast<AliMUONContour*>(allContourMap.GetValue(k->String().Data()));
280         if ( contour ) 
281         {
282           subcontours.Add(contour);
283         }
284         else
285         {
286           AliError(Form("Did not find contour %s",k->String().Data()))
287           return allContourArray;
288         }
289       }
290
291       contour = maker.MergeContour(subcontours,str->String().Data());
292         
293       bool error(kFALSE);
294       
295       if (!contour)
296       {
297         error=kTRUE;
298         AliError(Form("ERROR : could not merge into %s",str->String().Data()));
299       }
300       else
301       {
302         if ( contour->Area().IsValid() == kFALSE ) 
303         {
304           error=kTRUE;
305           AliError(Form("ERROR : area of contour %s is invalid",str->String().Data()));
306         }
307       }
308       
309       if ( error ) 
310       {
311         // do it again, but get intermediate results to plot them
312         PrintAsPNG(str->String().Data(),subcontours);
313         if (contour ) 
314         {
315           StdoutToAliError(contour->Area().Print("B"););
316         }
317         AliError(Form("%d subcontours",subcontours.GetLast()+1));
318         StdoutToAliError(subcontours.Print(););
319         // check whether one of the subcontour itself is already invalid ?
320         TIter next(&subcontours);
321         AliMUONContour* cont;
322         while ( ( cont = static_cast<AliMUONContour*>(next()) ) )
323         {
324           if (!cont->IsValid())
325           {
326             AliError(Form("subcontour %s is invalid",cont->GetName()));
327           }
328         }
329         TFile f("subcontour.root","recreate");
330         subcontours.Write("fault",TObject::kSingleKey);
331         f.Close();
332                 
333         return allContourArray;
334       }
335       
336       allContourArray->Add(contour);
337       allContourMap.Add(new TObjString(str->String().Data()),contour);
338     }
339   }
340   
341   return allContourArray;
342 }
343
344 //_____________________________________________________________________________
345 void 
346 AliMUONContourMakerTest::GenerateTransformations(AliMpExMap*& real, AliMpExMap*& exploded)
347 {
348   /// Generate geometric transformations to be used to compute the contours
349   /// (real are, as the name implies, real ones, while the other ones are 
350   /// a bit tweaked to look fine on screen).
351   
352   AliCodeTimerAuto("");
353   
354   AliMUONGeometryTransformer transformer;
355   Bool_t ok = transformer.LoadGeometryData("transform.dat");
356   //  transformer.LoadGeometryData("geometry.root"); //FIXME: add a protection if geometry.root file does not exist
357   if (!ok)
358   {
359     cout << "ERROR : cannot get geometry !" << endl;
360     return;
361   }
362   real = new AliMpExMap;
363   exploded = new AliMpExMap;
364   AliMpDEIterator deIt;
365   deIt.First();
366   while ( !deIt.IsDone() )
367   {
368     Int_t detElemId = deIt.CurrentDEId();
369     const AliMUONGeometryDetElement* de = transformer.GetDetElement(detElemId);
370     
371     real->Add(detElemId,de->GetGlobalTransformation()->Clone());
372     
373     TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(de->GetGlobalTransformation()->Clone());
374     Double_t* translation = matrix->GetTranslation();
375         
376     if ( AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345 ) 
377     {
378       translation[0] *= 1.0;
379       translation[1] *= 1.5; 
380     }
381     else
382     {
383       Double_t shift = 5; // cm
384       Double_t xshift[] = { shift, -shift, -shift, shift };
385       Double_t yshift[] = { shift, shift, -shift, -shift };
386       Int_t ishift = detElemId % 100;
387       
388       translation[0] += xshift[ishift];
389       translation[1] += yshift[ishift];
390     }
391     matrix->SetTranslation(translation);
392     exploded->Add(detElemId,matrix);
393     deIt.Next();
394   }
395 }
396
397 //_____________________________________________________________________________
398 void 
399 AliMUONContourMakerTest::GetBoundingBox(const TObjArray& array, 
400                                         Double_t& xmin, Double_t& ymin, 
401                                         Double_t& xmax, Double_t& ymax,
402                                         Bool_t enlarge) const
403 {
404   /// Get the bounding box of all the contours in array. 
405   /// If enlarge = kTRUE, the bounding box is "enlarged" a bit
406   /// (e.g. to leave some blank around a plot in a canvas)
407   ///
408   
409   xmin=ymin=FLT_MAX;
410   xmax=ymax=-FLT_MAX;
411   TIter next(&array);
412   AliMUONContour* contour;
413   while ( ( contour = static_cast<AliMUONContour*>(next()) ) )
414   {
415     AliMpArea area(contour->Area());
416     xmin = TMath::Min(xmin,area.LeftBorder());
417     xmax = TMath::Max(xmax,area.RightBorder());
418     ymin = TMath::Min(ymin,area.DownBorder());
419     ymax = TMath::Max(ymax,area.UpBorder());
420   }
421
422   if (enlarge)
423   {
424     Double_t xsize = (xmax-xmin);
425     Double_t ysize = (ymax-ymin);
426     Double_t xshift = xsize*0.1;
427     Double_t yshift = ysize*0.1;    
428     xmin -= xshift;
429     ymin -= yshift;
430     xmax = xmin + xsize + xshift*2;
431     ymax = ymin + ysize + yshift*2;
432   }
433 }
434
435 //_____________________________________________________________________________
436 void
437 AliMUONContourMakerTest::PlotSegments(const TObjArray& segments, Int_t lineColor, Int_t lineWidth, Bool_t orientation) const
438 {
439   /// Plot an array of segments 
440   
441   TIter next(&segments);
442   AliMUONSegment* s;
443   while ( ( s = static_cast<AliMUONSegment*>(next()) ) )
444   {
445     TPolyLine* line = new TPolyLine(2);
446     line->SetPoint(0,s->StartX(),s->StartY());
447     line->SetPoint(1,s->EndX(),s->EndY());
448     line->SetLineColor(lineColor);
449     line->SetLineWidth(lineWidth);
450     ::Plot(*line,orientation);
451   }
452 }
453
454 //_____________________________________________________________________________
455 void 
456 AliMUONContourMakerTest::Plot(const AliMUONPolygon& polygon, 
457                               Int_t lineColor, Int_t lineWidth,
458                               Bool_t orientation) const 
459 {
460   /// Plot a polygon
461   TPolyLine* line = new TPolyLine(polygon.NumberOfVertices());
462   for ( Int_t i = 0; i < polygon.NumberOfVertices(); ++i )
463   {
464     line->SetPoint(i,polygon.X(i),polygon.Y(i));
465   }
466   
467   line->SetLineColor(lineColor);
468   line->SetLineWidth(lineWidth);
469   ::Plot(*line,kFALSE);
470   if ( orientation ) ::Plot(*line,kTRUE);
471 }
472
473 //_____________________________________________________________________________
474 void 
475 AliMUONContourMakerTest::Plot(const AliMUONContour& contour, Int_t lineColor, Int_t lineWidth,
476                               Bool_t orientation) const 
477 {
478   /// Plot a contour (i.e. a set of polygons)
479   const TObjArray* polygons = contour.Polygons();
480   TIter next(polygons);
481   AliMUONPolygon* pol;
482   while ( ( pol = static_cast<AliMUONPolygon*>(next()) ) )
483   {
484     Plot(*pol,lineColor,lineWidth,orientation);
485   }
486 }
487
488 //_____________________________________________________________________________
489 void 
490 AliMUONContourMakerTest::PlotContours(const TObjArray& array, Bool_t orientations) const
491 {
492   /// Plot an array of contours
493   TIter next(&array);
494   AliMUONContour* contour;
495   while ( ( contour = static_cast<AliMUONContour*>(next()) ) )
496   {
497     Plot(*contour,5,4,orientations);
498   }
499 }
500
501 //______________________________________________________________________________
502 void 
503 AliMUONContourMakerTest::PrintAsPNG(const char* basename, const TObjArray& contourArray,
504                                     const TObjArray* verticals, const TObjArray* horizontals) const
505 {
506   /// Output contours and segments into a PNG file.
507   TCanvas* c = new TCanvas(basename,basename,0,0,600,600);
508   double xmin,ymin,xmax,ymax;
509   GetBoundingBox(contourArray,xmin,ymin,xmax,ymax,kTRUE);
510   c->Range(xmin,ymin,xmax,ymax);
511   PlotContours(contourArray,kTRUE);
512   c->Modified();
513   c->Update();
514   TString name(Form("%s",basename));
515   name.ReplaceAll("/","_");
516   c->Print(Form("%s.png",name.Data()));
517   if ( verticals || horizontals ) 
518   {
519     c->Clear();
520     if ( verticals ) PlotSegments(*verticals,1);
521     if ( horizontals) PlotSegments(*horizontals,2);
522     c->Modified();
523     c->Update();
524     name = Form("%s",basename);
525     name.ReplaceAll("/","_");
526     c->Print(Form("%s-segments.png",name.Data()));
527   }
528   delete c;
529 }
530