Main changes:
[u/mrichter/AliRoot.git] / MUON / MUONCheckDI.C
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 // Macro for checking AliMUONDataInterface and AliMUONMCDataInterface.
20 // By Bruce Becker, DAPNIA/SPhN/CEA Saclay
21 //
22 // Modified to updated versions of data interfaces.
23 //  Artur Szostak <artursz@iafrica.com> (University of Cape Town)
24 //
25
26 #if !defined(__CINT__) || defined(__MAKECINT__)
27 #include <Rtypes.h>
28 #include <Riostream.h>
29 #include <TObjArray.h>
30 #include <TIterator.h>
31 #include "AliMUONHit.h"
32 #include "AliMUONVDigit.h"
33 #include "AliMUONVCluster.h"
34 #include "AliMUONTrack.h"
35 #include "AliMUONLocalTrigger.h"
36 #include "AliMUONRegionalTrigger.h"
37 #include "AliMUONGlobalTrigger.h"
38 #include "AliMUONTriggerTrack.h"
39 #include "AliMUONMCDataInterface.h"
40 #include "AliMUONDataInterface.h"
41 #include "AliMUONVDigitStore.h"
42 #include "AliMUONVClusterStore.h"
43 #include "AliMUONVTrackStore.h"
44 #include "AliMUONVTriggerStore.h"
45 #include "AliMUONVTriggerTrackStore.h"
46 #include "AliMpConstants.h"
47 #include "AliMpDEManager.h"
48 #include <cstdlib>
49 #endif
50
51
52 /**
53  * This routine implements a the comparison functionality which is missing for
54  * classes like AliMUONTrack and the various AliMUONxxxTrigger classes.
55  * A result of -1 is returned if a < b, 0 if a == b and +1 if a > b.
56  */
57 Int_t Compare(const TObject* a, const TObject* b)
58 {
59         int result = -999;
60         if (a->IsA() == AliMUONTrack::Class() && b->IsA() == AliMUONTrack::Class())
61         {
62                 const AliMUONTrack* ta = static_cast<const AliMUONTrack*>(a);
63                 const AliMUONTrack* tb = static_cast<const AliMUONTrack*>(b);
64                 if (ta->GetNClusters() < tb->GetNClusters()) return -1;
65                 if (ta->GetNClusters() > tb->GetNClusters()) return 1;
66                 if (ta->GetMatchTrigger() < tb->GetMatchTrigger()) return -1;
67                 if (ta->GetMatchTrigger() > tb->GetMatchTrigger()) return 1;
68                 if (ta->GetLoTrgNum() < tb->GetLoTrgNum()) return -1;
69                 if (ta->GetLoTrgNum() > tb->GetLoTrgNum()) return 1;
70                 if (ta->GetChi2MatchTrigger() < tb->GetChi2MatchTrigger()) return -1;
71                 if (ta->GetChi2MatchTrigger() > tb->GetChi2MatchTrigger()) return 1;
72                 const AliMUONTrackParam* tpa = static_cast<const AliMUONTrackParam*>(ta->GetTrackParamAtCluster()->First());
73                 const AliMUONTrackParam* tpb = static_cast<const AliMUONTrackParam*>(tb->GetTrackParamAtCluster()->First());
74                 if (tpa->GetNonBendingCoor() < tpb->GetNonBendingCoor()) return -1;
75                 if (tpa->GetNonBendingCoor() > tpb->GetNonBendingCoor()) return 1;
76                 if (tpa->GetNonBendingSlope() < tpb->GetNonBendingSlope()) return -1;
77                 if (tpa->GetNonBendingSlope() > tpb->GetNonBendingSlope()) return 1;
78                 if (tpa->GetBendingCoor() < tpb->GetBendingCoor()) return -1;
79                 if (tpa->GetBendingCoor() > tpb->GetBendingCoor()) return 1;
80                 if (tpa->GetBendingSlope() < tpb->GetBendingSlope()) return -1;
81                 if (tpa->GetBendingSlope() > tpb->GetBendingSlope()) return 1;
82                 if (tpa->GetInverseBendingMomentum() < tpb->GetInverseBendingMomentum()) return -1;
83                 if (tpa->GetInverseBendingMomentum() > tpb->GetInverseBendingMomentum()) return 1;
84                 if (tpa->GetCharge() < tpb->GetCharge()) return -1;
85                 if (tpa->GetCharge() > tpb->GetCharge()) return 1;
86                 return 0;
87         }
88         else if (a->IsA() == AliMUONLocalTrigger::Class() && b->IsA() == AliMUONLocalTrigger::Class())
89         {
90                 result = memcmp(a, b, sizeof(AliMUONLocalTrigger));
91         }
92         else if (a->IsA() == AliMUONRegionalTrigger::Class() && b->IsA() == AliMUONRegionalTrigger::Class())
93         {
94                 result = memcmp(a, b, sizeof(AliMUONRegionalTrigger));
95         }
96         else if (a->IsA() == AliMUONGlobalTrigger::Class() && b->IsA() == AliMUONGlobalTrigger::Class())
97         {
98                 result = memcmp(a, b, sizeof(AliMUONGlobalTrigger));
99         }
100         else if (a->IsA() == AliMUONTriggerTrack::Class() && b->IsA() == AliMUONTriggerTrack::Class())
101         {
102                 const AliMUONTriggerTrack* ta = static_cast<const AliMUONTriggerTrack*>(a);
103                 const AliMUONTriggerTrack* tb = static_cast<const AliMUONTriggerTrack*>(b);
104                 if (ta->GetX11() < tb->GetX11()) return -1;
105                 if (ta->GetX11() > tb->GetX11()) return 1;
106                 if (ta->GetY11() < tb->GetY11()) return -1;
107                 if (ta->GetY11() > tb->GetY11()) return 1;
108                 if (ta->GetThetax() < tb->GetThetax()) return -1;
109                 if (ta->GetThetax() > tb->GetThetax()) return 1;
110                 if (ta->GetThetay() < tb->GetThetay()) return -1;
111                 if (ta->GetThetay() > tb->GetThetay()) return 1;
112                 if (ta->GetLoTrgNum() < tb->GetLoTrgNum()) return -1;
113                 if (ta->GetLoTrgNum() > tb->GetLoTrgNum()) return 1;
114                 if (ta->GetGTPattern() < tb->GetGTPattern()) return -1;
115                 if (ta->GetGTPattern() > tb->GetGTPattern()) return 1;
116                 return 0;
117         }
118         else
119         {
120                 result = memcmp(a, b, sizeof(TObject));
121         }
122         
123         if (result < 0) return -1;
124         if (result > 0) return 1;
125         return 0;
126 }
127
128 /**
129  * This method fills internal arrays with local and regional triggers returned
130  * by AliMUONMCDataInterface. For each set of interface methods available in
131  * AliMUONMCDataInterface a TObjArray is created for local and another for regional
132  * triggers. These arrays are filled with copies of the trigger objects.
133  * The global trigger object is also copied out using the 2 different methods.
134  * The arrays and objects are then compared to each other. The arrays and objects
135  * should contain the same information if everything is working correctly with
136  * AliMUONMCDataInterface. If not then the difference is printed together with an
137  * error message and kFALSE is returned.
138  */
139 bool SimTriggersOk()
140 {
141         AliMUONMCDataInterface data;
142         for (Int_t event = 0; event < data.NumberOfEvents(); event++)
143         {
144                 TObjArray localsFromStore, regionalsFromStore;
145                 localsFromStore.SetOwner(kTRUE);
146                 regionalsFromStore.SetOwner(kTRUE);
147                 AliMUONVTriggerStore* store = data.TriggerStore(event);
148                 AliMUONGlobalTrigger* globalFromStore = static_cast<AliMUONGlobalTrigger*>(store->Global()->Clone());
149                 TIter nextLocal(store->CreateLocalIterator());
150                 AliMUONLocalTrigger* localTrig;
151                 while ( (localTrig = static_cast<AliMUONLocalTrigger*>( nextLocal() )) != NULL )
152                 {
153                         localsFromStore.Add(localTrig->Clone());
154                 }
155                 TIter nextRegional(store->CreateRegionalIterator());
156                 AliMUONRegionalTrigger* regionalTrig;
157                 while ( (regionalTrig = static_cast<AliMUONRegionalTrigger*>( nextRegional() )) != NULL )
158                 {
159                         regionalsFromStore.Add(regionalTrig->Clone());
160                 }
161                 
162                 TObjArray localsByIndex, regionalsByIndex;
163                 localsByIndex.SetOwner(kTRUE);
164                 regionalsByIndex.SetOwner(kTRUE);
165                 data.GetEvent(event);
166                 AliMUONGlobalTrigger* globalByMethod = static_cast<AliMUONGlobalTrigger*>(data.GlobalTrigger()->Clone());
167                 Int_t nlocals = data.NumberOfLocalTriggers();
168                 for (Int_t i = 0; i < nlocals; i++)
169                 {
170                         localTrig = data.LocalTrigger(i);
171                         localsByIndex.Add(localTrig->Clone());
172                 }
173                 Int_t nregionals = data.NumberOfRegionalTriggers();
174                 for (Int_t i = 0; i < nregionals; i++)
175                 {
176                         regionalTrig = data.RegionalTrigger(i);
177                         regionalsByIndex.Add(regionalTrig->Clone());
178                 }
179                 
180                 // Now check that all the lists of local, regional and global triggers
181                 // contain the same results.
182                 // They must. If they do not then something is wrong with the implementation
183                 // of AliMUONMCDataInterface.
184                 if (Compare(globalFromStore, globalByMethod) != 0)
185                 {
186                         Error(  "SimTriggersOk",
187                                 "The AliMUONMCDataInterface does not return identical global"
188                                   " triggers through all its user interface methods."
189                         );
190                         globalFromStore->Print();
191                         globalByMethod->Print();
192                         return false;
193                 }
194                 delete globalFromStore;
195                 delete globalByMethod;
196                 if (localsFromStore.GetEntriesFast() != localsByIndex.GetEntriesFast())
197                 {
198                         Error(  "SimTriggersOk",
199                                 "The AliMUONMCDataInterface does not return all the local triggers"
200                                   " correctly through all its user interface methods. We got the"
201                                   " following numbers of local triggers: %d and %d",
202                                 localsFromStore.GetEntriesFast(),
203                                 localsByIndex.GetEntriesFast()
204                         );
205                         return false;
206                 }
207                 if (regionalsFromStore.GetEntriesFast() != regionalsByIndex.GetEntriesFast())
208                 {
209                         Error(  "SimTriggersOk",
210                                 "The AliMUONMCDataInterface does not return all the regional triggers"
211                                   " correctly through all its user interface methods. We got the"
212                                   " following numbers of regional triggers: %d and %d",
213                                 regionalsFromStore.GetEntriesFast(),
214                                 regionalsByIndex.GetEntriesFast()
215                         );
216                         return false;
217                 }
218                 for (Int_t i = 0; i < localsFromStore.GetEntriesFast(); i++)
219                 {
220                         if (Compare(localsFromStore[i], localsByIndex[i]) != 0)
221                         {
222                                 Error(  "SimTriggersOk",
223                                         "The AliMUONMCDataInterface does not return identical local"
224                                           " triggers through all its user interface methods. The"
225                                           " incorrect local trigger has index %d.",
226                                         i
227                                 );
228                                 localsFromStore[i]->Print();
229                                 localsByIndex[i]->Print();
230                                 return false;
231                         }
232                 }
233                 for (Int_t i = 0; i < regionalsFromStore.GetEntriesFast(); i++)
234                 {
235                         if (Compare(regionalsFromStore[i], regionalsByIndex[i]) != 0)
236                         {
237                                 Error(  "SimTriggersOk",
238                                         "The AliMUONMCDataInterface does not return identical regional"
239                                           " triggers through all its user interface methods. The"
240                                           " incorrect regional trigger has index %d.",
241                                         i
242                                 );
243                                 regionalsFromStore[i]->Print();
244                                 regionalsByIndex[i]->Print();
245                                 return false;
246                         }
247                 }
248         }
249         return true;
250 }
251
252 /**
253  * This method fills internal arrays with digits returned by the AliMUONDataInterface.
254  * For each set of interface methods available a TObjArray is filled with copies of 
255  * the digits. These arrays are sorted and then compared to each other. The arrays
256  * should contain the same digit information if everything is working correctly with
257  * AliMUONDataInterface. If not then the difference is printed together with an
258  * error message and kFALSE is returned.
259  */
260 bool RecDigitsOk()
261 {
262         AliMUONDataInterface data;
263         for (Int_t event = 0; event < data.NumberOfEvents(); event++)
264         {
265                 TObjArray digitsFromStore;
266                 digitsFromStore.SetOwner(kTRUE);
267                 AliMUONVDigitStore* store = data.DigitStore(event);
268                 TIter next(store->CreateIterator());
269                 AliMUONVDigit* digit;
270                 while ( (digit = static_cast<AliMUONVDigit*>( next() )) != NULL )
271                 {
272                         digitsFromStore.Add(digit->Clone());
273                 }
274                 digitsFromStore.Sort();
275                 
276                 TObjArray digitsByDetElem;
277                 digitsByDetElem.SetOwner(kTRUE);
278                 data.GetEvent(event);
279                 for (Int_t detElem = 0; detElem < 1500; detElem++)
280                 {
281                         if (! AliMpDEManager::IsValidDetElemId(detElem)) continue;
282                         Int_t ndigits = data.NumberOfDigits(detElem);
283                         for (Int_t i = 0; i < ndigits; i++)
284                         {
285                                 AliMUONVDigit* digit = data.Digit(detElem, i);
286                                 digitsByDetElem.Add(digit->Clone());
287                         }
288                 }
289                 digitsByDetElem.Sort();
290                 
291                 TObjArray digitsByChamber;
292                 digitsByChamber.SetOwner(kTRUE);
293                 data.GetEvent(event);
294                 for (Int_t chamber = 0; chamber < AliMpConstants::NofChambers(); chamber++)
295                 for (Int_t cathode = 0; cathode < 2; cathode++)
296                 {
297                         Int_t ndigits = data.NumberOfDigits(chamber, cathode);
298                         for (Int_t i = 0; i < ndigits; i++)
299                         {
300                                 AliMUONVDigit* digit = data.Digit(chamber, cathode, i);
301                                 digitsByChamber.Add(digit->Clone());
302                         }
303                 }
304                 digitsByChamber.Sort();
305                 
306                 // Now check that all the lists of digits contain the same results.
307                 // They must. If they do not then something is wrong with the implementation
308                 // of AliMUONDataInterface.
309                 if (digitsFromStore.GetEntriesFast() != digitsByDetElem.GetEntriesFast()
310                     || digitsFromStore.GetEntriesFast() != digitsByChamber.GetEntriesFast())
311                 {
312                         Error(  "RecDigitsOk",
313                                 "The AliMUONDataInterface does not return all the digits correctly"
314                                   " through all its user interface methods. We got the following"
315                                   " numbers of digits: %d, %d and %d",
316                                 digitsFromStore.GetEntriesFast(),
317                                 digitsByDetElem.GetEntriesFast(),
318                                 digitsByChamber.GetEntriesFast()
319                         );
320                         return false;
321                 }
322                 for (Int_t i = 0; i < digitsFromStore.GetEntriesFast(); i++)
323                 {
324                         if (digitsFromStore[i]->Compare(digitsByDetElem[i]) != 0
325                             || digitsFromStore[i]->Compare(digitsByChamber[i]) != 0)
326                         {
327                                 Error(  "RecDigitsOk",
328                                         "The AliMUONDataInterface does not return identical digits"
329                                           " through all its user interface methods. The incorrect"
330                                           " digit has index %d after sorting.",
331                                         i
332                                 );
333                                 digitsFromStore[i]->Print();
334                                 digitsByChamber[i]->Print();
335                                 digitsByDetElem[i]->Print();
336                                 return false;
337                         }
338                 }
339         }
340         return true;
341 }
342
343 /**
344  * This method fills internal arrays with raw clusters returned by AliMUONDataInterface.
345  * For each set of interface methods available in AliMUONDataInterface a TObjArray is
346  * filled with copies of the raw clusters. These arrays are sorted and then compared
347  * to each other. The arrays should contain the same information if everything is
348  * working correctly with AliMUONDataInterface. If not then the difference is printed
349  * together with an error message and kFALSE is returned.
350  */
351 bool RawClustersOk()
352 {
353         AliMUONDataInterface data;
354         for (Int_t event = 0; event < data.NumberOfEvents(); event++)
355         {
356                 TObjArray clustersFromStore;
357                 clustersFromStore.SetOwner(kTRUE);
358                 AliMUONVClusterStore* store = data.ClusterStore(event);
359                 TIter next(store->CreateIterator());
360                 AliMUONVCluster* cluster;
361                 while ( (cluster = static_cast<AliMUONVCluster*>( next() )) != NULL )
362                 {
363                         clustersFromStore.Add(cluster->Clone());
364                 }
365                 clustersFromStore.Sort();
366                 
367                 TObjArray clustersByChamber;
368                 clustersByChamber.SetOwner(kTRUE);
369                 data.GetEvent(event);
370                 for (Int_t chamber = 0; chamber < AliMpConstants::NofChambers(); chamber++)
371                 {
372                         Int_t nclusters = data.NumberOfRawClusters(chamber);
373                         for (Int_t i = 0; i < nclusters; i++)
374                         {
375                                 AliMUONVCluster* cluster = data.RawCluster(chamber, i);
376                                 clustersByChamber.Add(cluster->Clone());
377                         }
378                 }
379                 clustersByChamber.Sort();
380                 
381                 // Now check that all the lists of clusters contain the same results.
382                 // They must. If they do not then something is wrong with the implementation
383                 // of AliMUONDataInterface.
384                 if (clustersFromStore.GetEntriesFast() != clustersByChamber.GetEntriesFast())
385                 {
386                         Error(  "RawClustersOk",
387                                 "The AliMUONDataInterface does not return all the clusters correctly"
388                                   " through all its user interface methods. We got the following"
389                                   " numbers of clusters: %d and %d",
390                                 clustersFromStore.GetEntriesFast(),
391                                 clustersByChamber.GetEntriesFast()
392                         );
393                         return false;
394                 }
395                 for (Int_t i = 0; i < clustersFromStore.GetEntriesFast(); i++)
396                 {
397                         if (clustersFromStore[i]->Compare(clustersByChamber[i]) != 0)
398                         {
399                                 Error(  "RawClustersOk",
400                                         "The AliMUONDataInterface does not return identical clusters"
401                                           " through all its user interface methods. The incorrect"
402                                           " cluster has index %d after sorting.",
403                                         i
404                                 );
405                                 clustersFromStore[i]->Print();
406                                 clustersByChamber[i]->Print();
407                                 return false;
408                         }
409                 }
410         }
411         return true;
412 }
413
414 /**
415  * This method fills internal arrays with tracks returned by AliMUONDataInterface.
416  * For each set of interface methods available in AliMUONDataInterface a TObjArray is
417  * filled with copies of the raw clusters. These arrays are then compared to each
418  * other. The arrays should contain the same information if everything is working
419  * correctly with AliMUONDataInterface. If not then the difference is printed
420  * together with an error message and kFALSE is returned.
421  */
422 bool TracksOk()
423 {
424         AliMUONDataInterface data;
425         for (Int_t event = 0; event < data.NumberOfEvents(); event++)
426         {
427                 TObjArray tracksFromStore;
428                 tracksFromStore.SetOwner(kTRUE);
429                 AliMUONVTrackStore* store = data.TrackStore(event);
430                 TIter next(store->CreateIterator());
431                 AliMUONTrack* track;
432                 while ( (track = static_cast<AliMUONTrack*>( next() )) != NULL )
433                 {
434                         tracksFromStore.Add(track->Clone());
435                 }
436                 
437                 TObjArray tracksByIndex;
438                 tracksByIndex.SetOwner(kTRUE);
439                 data.GetEvent(event);
440                 Int_t ntracks = data.NumberOfTracks();
441                 for (Int_t i = 0; i < ntracks; i++)
442                 {
443                         AliMUONTrack* track = data.Track(i);
444                         tracksByIndex.Add(track->Clone());
445                 }
446                 
447                 // Now check that all the lists of tracks contain the same results.
448                 // They must. If they do not then something is wrong with the implementation
449                 // of AliMUONDataInterface.
450                 if (tracksFromStore.GetEntriesFast() != tracksByIndex.GetEntriesFast())
451                 {
452                         Error(  "TracksOk",
453                                 "The AliMUONDataInterface does not return all the tracks correctly"
454                                   " through all its user interface methods. We got the following"
455                                   " numbers of tracks: %d and %d",
456                                 tracksFromStore.GetEntriesFast(),
457                                 tracksByIndex.GetEntriesFast()
458                         );
459                         return false;
460                 }
461                 for (Int_t i = 0; i < tracksFromStore.GetEntriesFast(); i++)
462                 {
463                         if (Compare(tracksFromStore[i], tracksByIndex[i]) != 0)
464                         {
465                                 Error(  "TracksOk",
466                                         "The AliMUONDataInterface does not return identical tracks"
467                                           " through all its user interface methods. The incorrect"
468                                           " track has index %d.",
469                                         i
470                                 );
471                                 tracksFromStore[i]->Print();
472                                 tracksByIndex[i]->Print();
473                                 return false;
474                         }
475                 }
476         }
477         return true;
478 }
479
480 /**
481  * This method fills internal arrays with local and regional triggers returned
482  * by AliMUONDataInterface. For each set of interface methods available in
483  * AliMUONDataInterface a TObjArray is created for local and another for regional
484  * triggers. These arrays are filled with copies of the trigger objects.
485  * The global trigger object is also copied out using the 2 different methods.
486  * The arrays and objects are then compared to each other. The arrays and objects
487  * should contain the same information if everything is working correctly with
488  * AliMUONDataInterface. If not then the difference is printed together with an
489  * error message and kFALSE is returned.
490  */
491 bool TriggersOk()
492 {
493         AliMUONDataInterface data;
494         for (Int_t event = 0; event < data.NumberOfEvents(); event++)
495         {
496                 TObjArray localsFromStore, regionalsFromStore;
497                 localsFromStore.SetOwner(kTRUE);
498                 regionalsFromStore.SetOwner(kTRUE);
499                 AliMUONVTriggerStore* store = data.TriggerStore(event);
500                 AliMUONGlobalTrigger* globalFromStore = static_cast<AliMUONGlobalTrigger*>(store->Global()->Clone());
501                 TIter nextLocal(store->CreateLocalIterator());
502                 AliMUONLocalTrigger* localTrig;
503                 while ( (localTrig = static_cast<AliMUONLocalTrigger*>( nextLocal() )) != NULL )
504                 {
505                         localsFromStore.Add(localTrig->Clone());
506                 }
507                 TIter nextRegional(store->CreateRegionalIterator());
508                 AliMUONRegionalTrigger* regionalTrig;
509                 while ( (regionalTrig = static_cast<AliMUONRegionalTrigger*>( nextRegional() )) != NULL )
510                 {
511                         regionalsFromStore.Add(regionalTrig->Clone());
512                 }
513                 
514                 TObjArray localsByIndex, regionalsByIndex;
515                 localsByIndex.SetOwner(kTRUE);
516                 regionalsByIndex.SetOwner(kTRUE);
517                 data.GetEvent(event);
518                 AliMUONGlobalTrigger* globalByMethod = static_cast<AliMUONGlobalTrigger*>(data.GlobalTrigger()->Clone());
519                 Int_t nlocals = data.NumberOfLocalTriggers();
520                 for (Int_t i = 0; i < nlocals; i++)
521                 {
522                         localTrig = data.LocalTrigger(i);
523                         localsByIndex.Add(localTrig->Clone());
524                 }
525                 Int_t nregionals = data.NumberOfRegionalTriggers();
526                 for (Int_t i = 0; i < nregionals; i++)
527                 {
528                         regionalTrig = data.RegionalTrigger(i);
529                         regionalsByIndex.Add(regionalTrig->Clone());
530                 }
531                 
532                 // Now check that all the lists of local, regional and global triggers
533                 // contain the same results.
534                 // They must. If they do not then something is wrong with the implementation
535                 // of AliMUONDataInterface.
536                 if (Compare(globalFromStore, globalByMethod) != 0)
537                 {
538                         Error(  "TriggersOk",
539                                 "The AliMUONDataInterface does not return identical global"
540                                   " triggers through all its user interface methods."
541                         );
542                         globalFromStore->Print();
543                         globalByMethod->Print();
544                         return false;
545                 }
546                 delete globalFromStore;
547                 delete globalByMethod;
548                 if (localsFromStore.GetEntriesFast() != localsByIndex.GetEntriesFast())
549                 {
550                         Error(  "TriggersOk",
551                                 "The AliMUONDataInterface does not return all the local triggers"
552                                   " correctly through all its user interface methods. We got the"
553                                   " following numbers of local triggers: %d and %d",
554                                 localsFromStore.GetEntriesFast(),
555                                 localsByIndex.GetEntriesFast()
556                         );
557                         return false;
558                 }
559                 if (regionalsFromStore.GetEntriesFast() != regionalsByIndex.GetEntriesFast())
560                 {
561                         Error(  "TriggersOk",
562                                 "The AliMUONDataInterface does not return all the regional triggers"
563                                   " correctly through all its user interface methods. We got the"
564                                   " following numbers of regional triggers: %d and %d",
565                                 regionalsFromStore.GetEntriesFast(),
566                                 regionalsByIndex.GetEntriesFast()
567                         );
568                         return false;
569                 }
570                 for (Int_t i = 0; i < localsFromStore.GetEntriesFast(); i++)
571                 {
572                         if (Compare(localsFromStore[i], localsByIndex[i]) != 0)
573                         {
574                                 Error(  "TriggersOk",
575                                         "The AliMUONDataInterface does not return identical local"
576                                           " triggers through all its user interface methods. The"
577                                           " incorrect local trigger has index %d.",
578                                         i
579                                 );
580                                 localsFromStore[i]->Print();
581                                 localsByIndex[i]->Print();
582                                 return false;
583                         }
584                 }
585                 for (Int_t i = 0; i < regionalsFromStore.GetEntriesFast(); i++)
586                 {
587                         if (Compare(regionalsFromStore[i], regionalsByIndex[i]) != 0)
588                         {
589                                 Error(  "TriggersOk",
590                                         "The AliMUONDataInterface does not return identical regional"
591                                           " triggers through all its user interface methods. The"
592                                           " incorrect regional trigger has index %d.",
593                                         i
594                                 );
595                                 regionalsFromStore[i]->Print();
596                                 regionalsByIndex[i]->Print();
597                                 return false;
598                         }
599                 }
600         }
601         return true;
602 }
603
604 /**
605  * This method fills internal arrays with trigger tracks returned by AliMUONDataInterface.
606  * For each set of interface methods available in AliMUONDataInterface a TObjArray is
607  * filled with copies of the trigger tracks. These arrays are then compared to each
608  * other. The arrays should contain the same information if everything is working
609  * correctly with AliMUONDataInterface. If not then the difference is printed
610  * together with an error message and kFALSE is returned.
611  */
612 bool TriggerTracksOk()
613 {
614         AliMUONDataInterface data;
615         for (Int_t event = 0; event < data.NumberOfEvents(); event++)
616         {
617                 TObjArray tracksFromStore;
618                 tracksFromStore.SetOwner(kTRUE);
619                 AliMUONVTriggerTrackStore* store = data.TriggerTrackStore(event);
620                 TIter next(store->CreateIterator());
621                 AliMUONTriggerTrack* track;
622                 while ( (track = static_cast<AliMUONTriggerTrack*>( next() )) != NULL )
623                 {
624                         tracksFromStore.Add(track->Clone());
625                 }
626                 
627                 TObjArray tracksByIndex;
628                 tracksByIndex.SetOwner(kTRUE);
629                 data.GetEvent(event);
630                 Int_t ntracks = data.NumberOfTriggerTracks();
631                 for (Int_t i = 0; i < ntracks; i++)
632                 {
633                         AliMUONTriggerTrack* track = data.TriggerTrack(i);
634                         tracksByIndex.Add(track->Clone());
635                 }
636                 
637                 // Now check that all the lists of trigger tracks contain the same results.
638                 // They must. If they do not then something is wrong with the implementation
639                 // of AliMUONDataInterface.
640                 if (tracksFromStore.GetEntriesFast() != tracksByIndex.GetEntriesFast())
641                 {
642                         Error(  "TriggerTracksOk",
643                                 "The AliMUONDataInterface does not return all the trigger tracks"
644                                   " correctly through all its user interface methods. We got the"
645                                   " following numbers of tracks: %d and %d",
646                                 tracksFromStore.GetEntriesFast(),
647                                 tracksByIndex.GetEntriesFast()
648                         );
649                         return false;
650                 }
651                 for (Int_t i = 0; i < tracksFromStore.GetEntriesFast(); i++)
652                 {
653                         if (Compare(tracksFromStore[i], tracksByIndex[i]) != 0)
654                         {
655                                 Error(  "TriggerTracksOk",
656                                         "The AliMUONDataInterface does not return identical trigger"
657                                           " tracks through all its user interface methods. The"
658                                           " incorrect track has index %d.",
659                                         i
660                                 );
661                                 tracksFromStore[i]->Print();
662                                 tracksByIndex[i]->Print();
663                                 return false;
664                         }
665                 }
666         }
667         return true;
668 }
669
670 /**
671  * This method performs a check of the AliMUONDataInterface and AliMUONMCDataInterface
672  * classes. Basically there are at least 2 ways to fetch data using these interfaces:
673  * The expert way using the store objects returned by these interface classes or
674  * the much slower but easier way of using the NumberOfxxx and Digit(...),
675  * RawCluster(...), Track(...) etc. methods to fetch individual data objects.
676  * The MUONCheckDI will check that all these various ways of fetching data results
677  * in the same information being returned. If yes then kTRUE is returned and a
678  * confirmation message is printed, if not then kFALSE is returned with the failure
679  * reason printed to screen.
680  */
681 bool MUONCheckDI()
682 {
683         // TODO: complete checking AliMUONMCDataInterface.
684         //cout << "Checking simulated triggers..." << endl;
685         //if (! SimTriggersOk()) return false;
686         //cout << "Simulated triggers look OK." << endl;
687         
688         cout << "Checking reconstructed digits..." << endl;
689         if (! RecDigitsOk()) return false;
690         cout << "Reconstructed digits look OK." << endl;
691         
692         cout << "Checking raw clusters..." << endl;
693         if (! RawClustersOk()) return false;
694         cout << "Raw clusters look OK." << endl;
695
696         cout << "Checking reconstructed tracks..." << endl;
697         if (! TracksOk()) return false;
698         cout << "Reconstructed tracks look OK." << endl;
699
700         cout << "Checking reconstructed triggers..." << endl;
701         if (! TriggersOk()) return false;
702         cout << "Reconstructed triggers look OK." << endl;
703
704         cout << "Checking reconstructed trigger tracks..." << endl;
705         if (! TriggerTracksOk()) return false;
706         cout << "Reconstructed trigger tracks look OK." << endl;
707         
708         return true;
709 }