]>
Commit | Line | Data |
---|---|---|
0b936dc0 | 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 |