]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EVE/EveDet/AliEveListAnalyser.cxx
fix user histogram management and style (Ben)
[u/mrichter/AliRoot.git] / EVE / EveDet / AliEveListAnalyser.cxx
1 // Author: Benjamin Hess   29/01/2010
2
3 /*************************************************************************
4  * Copyright (C) 2009-2010, Alexandru Bercuci, Benjamin Hess.            *
5  * All rights reserved.                                                  *
6  *************************************************************************/
7
8 //////////////////////////////////////////////////////////////////////////
9 //                                                                      //
10 // AliEveListAnalyser                                                   //
11 //                                                                      //
12 // An AliEveListAnalyser is, in principal, a TEveElementList with some  //
13 // sophisticated features. You can add macros to this list, which then  //
14 // can be applied to the list of analysis objects (these objects can be //
15 // added to the list in the same way as for the TEveElementList, but    //
16 // also "by clicking" (cf. AliEveListAnaLyserEditor)).                  //
17 // In general, please use AddMacro(...) for this purpose.               //
18 // Macros that are no longer needed can be removed from the list via    //
19 // RemoveSelectedMacros(...). This function takes an iterator of the    //
20 // list of macros that are to be removed.                               //
21 // An entry looks like:                                                 //
22 // The data for each macro consists of path, name, type and the command //
23 // that will be used to apply the macro. This stuff is stored in a map  //
24 // which takes the macro name for the key and the above mentioned data  //
25 // in a TGeneralMacroData-object for the value.                         //
26 // You can get the macro type via GetMacroType(...).                    //
27 // To find the type of objects the macro will deal with (corresponds to //
28 // "YourObjectType" in the examples below) please use                   //
29 // GetMacroObjectType(...).                                             //
30 // With ApplySOSelectionMacros(...) or ApplyProcessMacros(...)          //
31 // respectively you can apply the macros to the track list via          //
32 // iterators (same style like for RemoveSelectedMacros(...)(cf. above)).//
33 // Selection macros (de-)select macros according to a selection rule    //
34 // by setting the rnr-state of the tracks.                              //
35 // If multiple selection macros are applied, a track is selected, if    //
36 // all selection macros select the track.                               //
37 // Process macros create data or histograms, which will be stored in    //
38 // a temporary file. The editor of this class will access this file     //
39 // and draw all the stuff within it's DrawHistos() function. The file   //
40 // will be deleted by the destructor.                                   //
41 //                                                                      //
42 // Currently, the following macro types are supported:                  //
43 // Selection macros:                                                    //
44 // Bool_t YourMacro(const YourObjectType*);                             //
45 // Bool_t YourMacro(const YourObjectType*, const YourObjectType2*);     //
46 //                                                                      //
47 // Process macros:                                                      //
48 // void YourMacro(const YourObjectType*, Double_t*&, Int_t&);           //
49 // void YourMacro(const YourObjectType*, const YourObjectType2*,        //
50 //                Double_t*&, Int_t&);                                  //
51 // TH1* YourMacro(const YourObjectType*);                               //
52 // TH1* YourMacro(const YourObjectType*, const YourObjectType2*);       //
53 //                                                                      //
54 // The macros which take 2 tracks are applied to all track pairs        //
55 // (whereby BOTH tracks of the pair have to be selected by the single   //
56 // track selection macros and have to be unequal, otherwise they will   //
57 // be skipped) that have been selected by ALL correlated tracks         //
58 // selection macros. The selection macros with 2 tracks do NOT affect   //
59 // process macros that process only a single track!                     //
60 //////////////////////////////////////////////////////////////////////////
61
62
63 // Uncomment to display debugging infos
64 //#define AliEveListAnalyser_DEBUG
65
66 #include <TEveManager.h>
67 #include <TEveSelection.h>
68 #include <TFile.h>
69 #include <TFunction.h>
70 #include <TH1.h>
71 #include <TList.h>
72 #include <TMap.h>
73 #include <TMethodArg.h>
74 #include <TMethodCall.h>
75 #include <TObjString.h>
76 #include <TQObject.h>
77 #include <TROOT.h>
78 #include <TSystem.h>
79 #include <TTree.h>
80 #include <TTreeStream.h>
81
82 #include <AliTRDReconstructor.h>
83
84 #include <EveDet/AliEveListAnalyser.h>
85 #include <EveDet/AliEveListAnalyserEditor.h>
86
87 ClassImp(AliEveListAnalyser)
88
89 ///////////////////////////////////////////////////////////
90 /////////////   AliEveListAnalyser ////////////////////////
91 ///////////////////////////////////////////////////////////
92 AliEveListAnalyser::AliEveListAnalyser(const Text_t* n, const Text_t* t, Bool_t doColor):
93   TEveElementList(n, t, doColor),
94   fConnected(kFALSE),
95   fDataFromMacroList(0x0),
96   fEditor(0x0),
97   fMacroList(0x0),
98   fDataTree(0x0),
99   fHistoDataSelected(0),
100   fMacroListSelected(0),
101   fSelectedTab(2)                               // Standard tab: "Apply macros" (index 2)
102 {
103   // Creates the AliEveListAnalyser.
104
105   // Only accept childs of type TEveElement
106   SetChildClass(TEveElement::Class());
107
108   // Allocate memory for the lists and declare them as owners of their contents
109   fDataFromMacroList = new TList();
110   fDataFromMacroList->TCollection::SetOwner(kTRUE);
111
112   fMacroList = new TMap();
113   // Set map to owner of it's objects to delete them, if they are removed from the map
114   fMacroList->SetOwnerKeyValue(kTRUE, kTRUE);
115
116   // Set the build directory for AClic
117   if(gSystem->AccessPathName(Form("%s/.QArec" , gSystem->Getenv("HOME")))) gSystem->Exec("mkdir $HOME/.QArec");
118   gSystem->SetBuildDir(Form("%s/.QArec", gSystem->Getenv("HOME")));
119
120   AddStandardContent();
121 }
122
123 //______________________________________________________
124 AliEveListAnalyser::~AliEveListAnalyser()
125 {
126   // Frees allocated memory (lists etc.).
127
128   // Stop adding objects
129   StopAddingObjects();
130
131   // Let the editor know that the list will be destroyed -> The editor will save the data
132   if (fEditor != 0)
133   {
134     fEditor->SaveMacroList(fMacroList);
135     fEditor = 0;
136   }
137
138   if (fDataFromMacroList != 0)
139   {
140     fDataFromMacroList->Delete();
141     delete fDataFromMacroList;
142     fDataFromMacroList = 0;
143   } 
144   if (fDataTree != 0)
145   {
146     delete fDataTree;
147     fDataTree = 0;
148   } 
149   if (fMacroList != 0)
150   {
151     fMacroList->DeleteAll();
152     delete fMacroList;
153     fMacroList = 0;
154   }
155   // Note: gSystem->AccessPathName(...) returns kTRUE, if the access FAILED!
156   if(!gSystem->AccessPathName(Form("/tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")))) 
157     gSystem->Exec(Form("rm /tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")));
158 }
159
160 //______________________________________________________
161 Int_t AliEveListAnalyser::AddMacro(const Char_t* path, const Char_t* nameC, Bool_t forceReload)
162 {
163   // Checks, if the file exists and if the signature is correct.
164   // If these criteria are fullfilled, the library for this macro is built
165   // and the macro is added to the corresponding list.
166   // Supported macro types:
167   // Selection macros:                                                    
168   // Bool_t YourMacro(const YourObjectType*)
169   // Bool_t YourMacro(const YourObjectType*, const YourObjectType2*)
170   //
171   // Process macros:                                                      
172   // void YourMacro(const YourObjectType*, Double_t*&, Int_t&)             
173   // void YourMacro(const YourObjectType*, const YourObjectType2*, Double_t*&, Int_t&)                                   
174   // TH1* YourMacro(const YourObjectType*)                                 
175   // TH1* YourMacro(const YourObjectType*, const YourObjectType2*)                              
176
177   Char_t pathname[fkMaxMacroPathNameLength];
178   memset(pathname, '\0', sizeof(Char_t) * fkMaxMacroPathNameLength);
179
180   // Expand the path and create the pathname
181   Char_t* systemPath = gSystem->ExpandPathName(path);
182   sprintf(pathname, "%s/%s", systemPath, nameC);
183   delete systemPath;
184   systemPath = 0;
185
186   // Delete ".C" from filename
187   Char_t name[fkMaxMacroNameLength];
188   memset(name, '\0', sizeof(Char_t) * fkMaxMacroNameLength);
189   
190   for (UInt_t ind = 0; ind < fkMaxMacroNameLength && ind < strlen(nameC) - 2; ind++)  name[ind] = nameC[ind];
191
192   // Check, if files exists
193   FILE* fp = 0x0;
194   if((fp = fopen(pathname, "rb"))){
195     fclose(fp);
196     fp = 0x0;
197   } else  return NOT_EXIST_ERROR;
198   
199   // Clean up root, load the desired macro and then check the type of the macro
200   // A.B. gROOT->Reset();
201  
202   gROOT->ProcessLineSync(Form(".L %s+%c", pathname, forceReload ? '+' : ' '));
203
204   TClass* objectType;
205   TClass* objectType2;
206
207   objectType = GetMacroObjectType(name, 1);
208   objectType2 = GetMacroObjectType(name, 2);
209
210   // We need this line... otherwise, in some cases, there will be problems concerning ACLIC
211   gROOT->ProcessLineSync(Form(".L %s", pathname));
212
213   if (!objectType)  return UNKNOWN_OBJECT_TYPE_ERROR;
214
215   // This might be a macro dealing with only 1 object... test this afterwards!
216   Bool_t testSecondObj = kFALSE;
217   if (!objectType2) 
218   {
219     objectType2 = TObject::Class();
220     testSecondObj = kTRUE;
221   }
222   AliEveListAnalyserMacroType type = GetMacroType(name, objectType->GetName(), objectType2->GetName(), kFALSE);
223
224   if (testSecondObj)
225   {
226     switch (type)
227     {
228     case AliEveListAnalyser::kCorrelObjectSelect:
229     case AliEveListAnalyser::kCorrelObjectAnalyse:
230     case AliEveListAnalyser::kCorrelObjectHisto:
231       // There must be a second type -> Error!
232       return UNKNOWN_OBJECT_TYPE_ERROR;
233       break;
234     default:
235       // Ok, single object macro!
236       break;
237     }
238   }
239
240
241   // Clean up again
242   // A.B. gROOT->Reset();
243  
244   // Has not the correct signature!
245   if (type == kUnknown) return SIGNATURE_ERROR;
246
247   // Only add macro, if it is not already in the list
248   Int_t returnValue = WARNING;
249   if(fMacroList->GetValue(name) == 0) 
250   {
251     returnValue = AddMacroFast(path, name, type, objectType, objectType2) ? SUCCESS : ERROR;
252   }
253
254   return returnValue;
255 }
256
257 //______________________________________________________
258 Bool_t AliEveListAnalyser::AddMacroFast(const Char_t* path, const Char_t* name, AliEveListAnalyserMacroType type, 
259                                         TClass* objectType, TClass* objectType2)
260 {
261   // Adds a macro (path/name) to the corresponding list. No checks are performed (file exists, 
262   // macro already in list/map, signature correct),  no libraries are created!
263   // You can use this function only, if the macro has been added successfully before 
264   // (and then maybe was removed). The function is very fast. On success kTRUE is returned, otherwise: kFALSE;
265   // Note: If your macro takes only 1 pointer as a parameter, just use "0x0" for objectType2!
266
267   Bool_t success = kFALSE;
268
269   switch (type)
270   {
271     case kSingleObjectSelect:
272     case kCorrelObjectSelect:
273     case kSingleObjectAnalyse:
274     case kSingleObjectHisto:
275     case kCorrelObjectAnalyse:
276     case kCorrelObjectHisto:
277       fMacroList->Add(new TObjString(name), new TGeneralMacroData(name, path, type, objectType, objectType2));
278
279       // We do not know, where the element has been inserted - deselect this list
280       fMacroListSelected = 0;
281     
282       success = kTRUE;
283
284 #ifdef AliEveListAnalyser_DEBUG
285       // Successfull add will only be displayed in debug mode
286       printf("AliEveListAnalyser::AddMacroFast: Added macro \"%s/%s\" with object types \"%s\" and \"%s\" to the corresponding list\n", 
287              path, name, objectType->GetName(), objectType2->GetName());
288 #endif
289
290       break;
291
292     default:
293       // Error will always be displayed
294       printf("AliEveListAnalyser::AddMacroFast: ERROR: Could not add macro \"%s/%s\" with object types \"%s\" and \"%s\" to the corresponding list\n", path, name, objectType->GetName(), objectType2->GetName());
295
296       success = kFALSE;
297
298       break;
299   }
300
301   return success;
302 }
303
304
305 //______________________________________________________
306 Int_t AliEveListAnalyser::AddPrimSelectedObject(TEveElement* el)
307 {
308   // Adds the TEveElement el to the list. If it is already in the list, it is removed.
309   // If the list is the only parent of the clicked object, the object is moved outside the list in the browser (not deleted!).
310   // If you want to delete the object, just select it there and choose "Destroy" in the menu.
311   // This function is designed to be used together with a signal:
312   // It adds the (primarily) selected objects in the viewer to the list (objects that are already in the list are removed!).
313   // Returns "ERROR" (cf. defines) on error, "WARNING" if the element does not contain any user data and else "SUCCESS" (i.e.
314   // the element has been added successfully or the element is the list itself and therefore ignored, or the element is ignored 
315   // because it has been added via secondary selection).
316  
317   if (!el)
318   {
319     Error("AliEveListAnalyser::AddPrimSelectedObject", "Zero pointer!\n");
320
321     return ERROR;
322   }
323
324   // If the clicked element is the list itself, just do nothing.
325   if (el == this)  return SUCCESS;
326
327   if (!this->HasChild(el))
328   {
329
330     // Ignore objects that do not have any user data, since these cannot be used in the analysis!
331     if (el->GetUserData() == 0x0)
332     {
333       Warning("AddPrimSelectedObject", "Selected object does not contain any \"user data\" and therefore is ignored!");
334
335       return WARNING;
336     }
337
338     // Element clicked that is not in the list (and is not the list itself!) -> Add this element to the list
339     this->AddElement(el);
340     this->SetTitle(Form("Objects %d", this->NumChildren()));
341     gEve->Redraw3D();
342   }
343   else
344   {
345     // Element clicked that is already in the list. Remove it. But: Only take care of objects that have been added
346     // via primary selection (name does not start with "[sec")
347     if (TString(el->GetElementName()).BeginsWith("[sec:"))  return SUCCESS;
348
349
350     // Element is a child of this list. So, if there are only 2 parents, we know them: list + eve selection. In this case,
351     // the element needs to be destroyed. If there are more parents, just remove the element from the list.
352     // Since the elements editor will be opened, the element is not deleted, but "moved" outside the list (in the browser).
353     if (el->NumParents() > 2) 
354     {
355       this->RemoveElement(el);
356     }
357     else
358     {
359       // There must be at least 2 parents!
360       if (el->NumParents() <= 1)  return ERROR;
361
362       TEveElement* listObj = 0x0;
363       listObj = this->FindChild(el->GetElementName());
364       if (!listObj)  return ERROR;
365
366       gEve->AddElement(listObj, 0);
367       // Alternatively: Switch on that the element is NOT destroyed, instead of adding it outside the list. Warning: Memory leaks possible.
368       //listObj->SetDestroyOnZeroRefCnt(kFALSE);
369       this->RemoveElement(listObj);
370       //gEve->RemoveElement(listObj, 0);
371     }
372   } 
373
374   this->SetTitle(Form("Objects %d", this->NumChildren()));
375   gEve->Redraw3D();
376
377   return SUCCESS;
378 }
379
380
381 /*
382 //______________________________________________________
383 void AliEveListAnalyser::AddPrimSelectedObjects()
384 {
385   // Adds the (primarily) selected objects in the viewer to the list (objects that are already in the list are ignored).
386   // Hold the CTRL-key for multiple selection.
387
388   TEveSelection* eveSel = gEve->GetSelection();
389   if (!eveSel)
390   {
391     Error("AliEveListAnalyser::AddPrimSelectedObjects", "Failed to get the selection!\n");
392     return;
393   }
394   
395   TEveElement* elem = 0x0;
396   Bool_t changedSomething = kFALSE;
397
398   for (TEveElement::List_i iter = eveSel->BeginChildren(); iter != eveSel->EndChildren(); ++iter)
399   {
400     if(!(elem = dynamic_cast<TEveElement*>(*iter))) continue;
401
402     if (!this->HasChild(elem) && elem != this)
403     {
404       // Element clicked that is not in the list (and is not the list itself!) -> Add this element to list
405       this->AddElement(elem);
406       this->SetTitle(Form("Objects %d", this->NumChildren()));
407       changedSomething = kTRUE;
408     }
409   }
410
411   if (changedSomething) gEve->Redraw3D();
412 }
413 */
414
415 //______________________________________________________
416 void AliEveListAnalyser::AddSecSelectedSingleObjectToList(Int_t pointId)
417 {
418   // This function adds the selected object (secondary selection in the viewer) to the list
419   // of analysis objects. If the object is already in the list, it will be removed from it.
420   // This function is used to add single objects of a TEvePointset, e.g. single clusters.
421
422   TEvePointSet* ps = dynamic_cast<TEvePointSet*>((TQObject*) gTQSender);
423   if (!ps)
424   {
425     Error("AliEveListAnalyser::AddSecSelectedSingleObjectToList", "Zero pointer!\n");
426     return;
427   }
428
429   // Check, if object is already there. If so, remove it!
430   
431   // 1st possibility: Object of the list clicked. But: Only take care of objects that have been added
432   // via secondary selection (name starts with "[sec"). Note: HasChild will also return kTRUE, if e.g.
433   // the whole TEvePointSet of clusters is in the last (but maybe another point of it has been clicked!)
434
435   if (this->HasChild(ps))
436   {
437     if (TString(ps->GetName()).BeginsWith("[sec:"))
438     {
439       // I don't know why, but you get a crash, if you try this->RemoveElement(ps) (in some cases).
440       // So, use this way instead.
441       TEveElement* listObj = this->FindChild(ps->GetName());
442       if (listObj)
443       {
444         listObj->SetUserData(0x0);
445         this->RemoveElement(listObj);
446         this->SetTitle(Form("Objects %d", this->NumChildren()));
447       }
448
449       return;
450     }
451   }
452
453   TObject* obj = ps->GetPointId(pointId);
454   if (obj)
455   {
456     // 2nd possibility: Same object clicked again
457     TEveElement* listObj = 0x0;
458     listObj = this->FindChild(Form("[sec:%d] %s%d", obj->GetUniqueID(), obj->GetName(), pointId));
459     if (listObj)
460     {
461       listObj->SetUserData(0x0);
462       this->RemoveElement(listObj); 
463       this->SetTitle(Form("Objects %d", this->NumChildren()));
464       return;
465     }
466
467     // Object clicked that is not in the list -> Add this object to list
468     TEvePointSet* newPS = new TEvePointSet(Form("[sec:%d] %s%d", obj->GetUniqueID(), obj->GetName(), pointId));
469     Double_t x = 0, y = 0, z = 0;
470     ps->GetPoint(pointId, x, y, z);
471     newPS->SetPoint(0, x, y, z);
472     newPS->SetUserData(obj);
473     // Choose yellow for the added points and inherit style and size for the marker
474     newPS->SetMarkerColor(5);
475     newPS->SetMarkerStyle(ps->GetMarkerStyle());
476     newPS->SetMarkerSize(ps->GetMarkerSize());
477     // Own points -> Will be cleared, if this object is removed
478     newPS->SetOwnIds(kTRUE);
479
480     this->AddElement(newPS);
481     this->SetTitle(Form("Objects %d", this->NumChildren()));
482     gEve->Redraw3D();
483   }
484   else
485   {
486     Error("AliEveListAnalyser::AddSecSelectedSingleObjectToList", "Selected object is NULL and therefore ignored!");
487   }
488 }
489
490 //______________________________________________________
491 void AliEveListAnalyser::AddStandardContent()
492 {
493   // Adds standard macros to the macro list.
494
495   // Add your standard macros here, e.g.: 
496   // To add a macro use:
497   // AddMacro("$(ALICE_ROOT)/myFolder", "myMacroName.C");
498   // -> If the file does not exist, nothing happens. So if you want to handle this,
499   // use the return value of AddMacro (NOT_EXIST_ERROR is returned, if file does not exist)
500   // (-> You can also check for other return values (see AddMacro(...)))
501
502 }
503
504 //______________________________________________________
505 Bool_t AliEveListAnalyser::ApplyProcessMacros(const TList* selIterator, const TList* procIterator)
506 {
507   // Uses the procIterator (for the selected process macros) to apply the selected macros to the data.
508   // Returns kTRUE on success, otherwise kFALSE. If there no process macros selected, kTRUE is returned 
509   // (this is no error!).
510   // The single object process macros are applied to all selected objects.
511   // The selIterator (for the selected selection macros) will be used to apply the correlated objects selection
512   // macros to all object pairs (whereby BOTH objects have to be selected, otherwise they will be skipped).
513   // All object pairs that have been selected by ALL correlated objects selection macros will be processed by
514   // the correlated objects process macros.
515
516   // No process macros need to be processed
517   if (procIterator->GetEntries() <= 0)  return kTRUE;
518
519   // Clear root
520   // A.B. gROOT->Reset();
521   
522   // Clear old data and re-allocate
523   if (fDataTree == 0x0){ 
524     TDirectory *cwd = gDirectory;
525     fDataTree = new TTreeSRedirector(Form("/tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")));
526     cwd->cd();
527   }
528   if (!fDataTree){
529     Error("Apply process macros", Form("File \"/tmp/ListAnalyserMacroData_%s.root\" could not be accessed properly!", 
530           gSystem->Getenv("USER")));
531     return kFALSE;
532   }
533   
534   if (fDataFromMacroList != 0) {
535     fDataFromMacroList->Delete();
536     delete fDataFromMacroList;
537   }
538   fDataFromMacroList = new TList();
539   fDataFromMacroList->TCollection::SetOwner(kTRUE);
540
541   fHistoDataSelected = 0;
542
543
544   TGeneralMacroData* macro = 0;
545
546   Char_t** procCmds = 0;
547   AliEveListAnalyserMacroType* mProcType = 0;
548   if (procIterator->GetEntries() > 0) {
549     procCmds = new Char_t*[procIterator->GetEntries()];
550     mProcType = new AliEveListAnalyserMacroType[procIterator->GetEntries()];
551   }
552   
553   TClass** mProcObjectType = 0;
554   TClass** mProcObjectType2 = 0;
555   if (procIterator->GetEntries() > 0) {
556     mProcObjectType = new TClass*[procIterator->GetEntries()];
557     mProcObjectType2 = new TClass*[procIterator->GetEntries()];
558   }
559
560   Char_t** selCmds  = 0;
561   AliEveListAnalyserMacroType* mSelType = 0;
562   if (selIterator->GetEntries() > 0) {
563     selCmds = new Char_t*[selIterator->GetEntries()];
564     mSelType = new AliEveListAnalyserMacroType[selIterator->GetEntries()];
565   }
566
567   TClass** mSelObjectType = 0;
568   TClass** mSelObjectType2 = 0;
569   if (selIterator->GetEntries() > 0) {
570     mSelObjectType = new TClass*[selIterator->GetEntries()];
571     mSelObjectType2 = new TClass*[selIterator->GetEntries()];
572   }
573   
574   Bool_t selectedByCorrSelMacro = kFALSE;
575
576   AliEveListAnalyserMacroType macroType = kUnknown;
577   Int_t numHistoMacros = 0;
578   TH1** histos = 0;
579
580   TEveElement* object1 = 0;
581   TEveElement* object2 = 0;
582   TH1* returnedHist = 0x0;
583
584   // Collect the commands for each process macro and add them to "data-from-list"
585   for (Int_t i = 0; i < procIterator->GetEntries(); i++){
586     procCmds[i] = new Char_t[(fkMaxMacroPathNameLength + fkMaxApplyCommandLength)];
587     memset(procCmds[i], '\0', sizeof(Char_t) * (fkMaxMacroNameLength + fkMaxApplyCommandLength));
588
589     macro = (TGeneralMacroData*)fMacroList->GetValue(procIterator->At(i)->GetTitle());
590
591     if (!macro){
592       Error("Apply process macros", 
593         Form("Macro list is corrupted: Macro \"%s\" is not registered!", 
594         procIterator->At(i)->GetTitle()));
595       continue;
596     }
597
598 #ifdef AliEveListAnalyser_DEBUG
599     printf("AliEveListAnalyser: Checking process macro: %s\n", macro->GetName());
600 #endif 
601            
602     // Find the object types of the macro
603     mProcObjectType[i] = macro->GetObjectType();
604     mProcObjectType2[i] = macro->GetObjectType2();
605
606     // Find the type of the process macro
607     macroType = macro->GetType();
608     if (macroType == kSingleObjectHisto || macroType == kCorrelObjectHisto){
609       mProcType[i] = macroType;
610       numHistoMacros++;
611       // Create the command 
612       sprintf(procCmds[i], macro->GetCmd());
613
614       // Add to "data-from-list" -> Mark as a histo macro with the substring "(histo macro)"
615       fDataFromMacroList->Add(new TObjString(Form("%s (histo macro)", macro->GetName())));
616     } else if (macroType == kSingleObjectAnalyse || macroType == kCorrelObjectAnalyse) {
617       mProcType[i] = macroType;
618       // Create the command 
619       sprintf(procCmds[i], macro->GetCmd());
620
621       // Add to "data-from-list"
622       fDataFromMacroList->Add(new TObjString(macro->GetName()));
623     } else {
624       Error("Apply process macros", 
625         Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a process macro!", 
626         macro->GetPath(), macro->GetName()));
627       mProcType[i] = kUnknown;
628     } 
629   }  
630
631   // Collect the commands for each selection macro and add them to "data-from-list"
632   for (Int_t i = 0; i < selIterator->GetEntries(); i++){
633     selCmds[i] = new Char_t[(fkMaxMacroPathNameLength + fkMaxApplyCommandLength)];
634     memset(selCmds[i], '\0', sizeof(Char_t) * (fkMaxMacroNameLength + fkMaxApplyCommandLength));
635
636     macro = (TGeneralMacroData*)fMacroList->GetValue(selIterator->At(i)->GetTitle());
637
638     if (!macro){
639       Error("Apply process macros", 
640         Form("Macro list is corrupted: Macro \"%s\" is not registered!", 
641         selIterator->At(i)->GetTitle()));
642       continue;
643     }
644
645 #ifdef AliEveListAnalyser_DEBUG
646     printf("AliEveListAnalyser: Checking selection macro: %s\n", macro->GetName());
647 #endif
648
649     // Find the object types of the macro
650     mSelObjectType[i] = macro->GetObjectType();
651     mSelObjectType2[i] = macro->GetObjectType2();
652        
653     // Find the type of the process macro
654     macroType = macro->GetType();
655
656     // Single Object select macro
657     if (macroType == kSingleObjectSelect) {
658       // Has already been processed by ApplySOSelectionMacros(...)
659       mSelType[i] = macroType;         
660     }
661     // Correlated Objects select macro
662     else if (macroType == kCorrelObjectSelect) {
663       mSelType[i] = macroType;  
664  
665       // Create the command
666       sprintf(selCmds[i], macro->GetCmd());
667     } else {
668       Error("Apply process macros", 
669         Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a selection macro!", 
670         macro->GetPath(), macro->GetName()));
671       mSelType[i] = kUnknown;
672     } 
673   }  
674
675   // Allocate memory for the histograms
676   if (numHistoMacros > 0)  histos = new TH1*[numHistoMacros];
677   for (Int_t i = 0; i < numHistoMacros; i++)  histos[i] = 0x0;
678
679   Bool_t secondBeforeFirstObject = kTRUE;
680   
681
682   //////////////////////////////////////
683   // WALK THROUGH THE LIST OF OBJECTS //
684   //////////////////////////////////////     
685   for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter){
686     if(!(object1 = dynamic_cast<TEveElement*>(*iter))) continue;
687
688     // Skip objects that have not been selected
689     if (!object1->GetRnrState())  continue;
690     
691     // Cast to the "real" object behind
692     gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object1));
693     gROOT->ProcessLineSync("TObject* automaticObject_1 = (TObject*)automaticEveElement->GetUserData();");
694
695     // Collect data for each macro
696     for (Int_t i = 0, histoIndex = 0; i < procIterator->GetEntries(); i++){
697       // Find the type of the object and relate it to the macro object type
698       // Only apply macro to this object, if...
699       // ... the macro takes objects of exactly this type.
700       // ... the macro object type is a child of this object's type.
701       // Otherwise: Continue
702
703       // Finally, via procCmds[i], the automatic objects are casted to the correct type and analysed by each macro!
704       if (((TObject*)object1->GetUserData())->IsA() != mProcObjectType[i] && 
705           !((TObject*)object1->GetUserData())->InheritsFrom(mProcObjectType[i]))  continue;
706
707         
708       // Single object histo
709       if (mProcType[i] == kSingleObjectHisto){
710         returnedHist = (TH1*)gROOT->ProcessLineSync(procCmds[i]);
711         if (returnedHist)
712         {
713           if (!histos[histoIndex])  histos[histoIndex] = returnedHist;
714           else  
715           {
716             histos[histoIndex]->Add((const TH1*)returnedHist);
717             delete returnedHist;
718             returnedHist = 0;
719           }
720         }
721         histoIndex++;
722        // Correlated Objects histo
723       } else if (mProcType[i] == kCorrelObjectHisto) {
724         // To get all pairs, do the second loop over all objects.
725         // But: If a macro takes 2 pointers of the same type, we must take care that one gets the same pair, when we exchange the objects
726         // (this is not true, if we have different types - even if they inherit from the same classes!).
727         // Thus: If the latter case occurs, we ignore an object pair, if the second object is BEFORE the first object in the list.
728         // Since then the pair has already been taken into account.
729         // Furthermore, we have a pair of objects, if and only if both objects of the pair are selected (Rnr-state)
730         // and are not equal.
731         // The correlated objects process macro will be applied to all pairs that will be additionally selected by
732         // all correlated objects selection macros.
733
734         secondBeforeFirstObject = kTRUE;
735         for (TEveElement::List_i iter2 = this->BeginChildren(); iter2 != this->EndChildren(); ++iter2)
736         {
737           // If the objects are the same, it is not a pair -> continue. From now on: 2nd object BEHIND the 1st object in the list!
738           if (iter == iter2)
739           {
740             secondBeforeFirstObject = kFALSE;
741             continue;
742           }
743           if(!(object2 = dynamic_cast<TEveElement*>(*iter2))) continue;
744
745           // Skip objects that have not been selected
746           if (!object2->GetRnrState())  continue;
747
748           // Same check of the macro object type as before
749           if (((TObject*)object2->GetUserData())->IsA() != mProcObjectType2[i] && 
750               !((TObject*)object2->GetUserData())->InheritsFrom(mProcObjectType2[i]))  continue;
751           // Do not process object pairs twice
752           if (secondBeforeFirstObject)
753           {
754             if (mProcObjectType[i] == mProcObjectType2[i]) continue;
755           }
756       
757           // Cast to the "real" object behind
758           gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object2));
759           gROOT->ProcessLineSync("TObject* automaticObject_2 = (TObject*)automaticEveElement->GetUserData();");
760
761           // Select object by default (so it will be processed, if there are no correlated objects selection macros!)
762           selectedByCorrSelMacro = kTRUE;
763           for (Int_t j = 0; j < selIterator->GetEntries(); j++){
764             if (mSelType[j] == kCorrelObjectSelect){
765           // Check, whether the macro can deal with both objects. If not, skip it.
766           // Note: Again, via selCmds[i], the automatic objects are casted to the correct type!
767           if (((TObject*)object1->GetUserData())->IsA() != mSelObjectType[j] && 
768               !((TObject*)object1->GetUserData())->InheritsFrom(mSelObjectType[j]))  continue;
769           if (((TObject*)object2->GetUserData())->IsA() != mSelObjectType2[j] && 
770               !((TObject*)object2->GetUserData())->InheritsFrom(mSelObjectType2[j]))  continue;
771
772               selectedByCorrSelMacro = (Bool_t)gROOT->ProcessLineSync(selCmds[j]);
773               if (!selectedByCorrSelMacro)  break;
774             }
775           }       
776
777           // If the pair has not been selected by the correlated objects selection macros, skip it!
778           if (!selectedByCorrSelMacro) continue;
779
780           returnedHist = (TH1*)gROOT->ProcessLineSync(procCmds[i]);
781           if (returnedHist)
782           {
783             if (!histos[histoIndex])  histos[histoIndex] = returnedHist;
784             else  
785             {
786               histos[histoIndex]->Add((const TH1*)returnedHist);
787
788               delete returnedHist;
789               returnedHist = 0;
790             }
791           }
792         }
793         histoIndex++;
794       }
795       // Single object analyse
796       else if (mProcType[i] == kSingleObjectAnalyse) {
797         // Create data pointers in CINT, execute the macro and get the data
798         gROOT->ProcessLineSync("Double_t* results = 0;");
799         gROOT->ProcessLineSync("Int_t n = 0;");
800         gROOT->ProcessLineSync(procCmds[i]);
801         Double_t* results = (Double_t*)gROOT->ProcessLineSync("results;");
802         Int_t nResults = (Int_t)gROOT->ProcessLineSync("n;");
803         
804         if (results == 0) {
805           Error("Apply macros", Form("Error reading data from macro \"%s\"", procIterator->At(i)->GetTitle()));
806           continue;
807         }
808         for (Int_t resInd = 0; resInd < nResults; resInd++){
809           (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << results[resInd] << (Char_t*)"\n";   
810         }
811
812         delete results;
813         results = 0;
814       }
815       // Correlated objects analyse
816       else if (mProcType[i] == kCorrelObjectAnalyse){
817         // To get all pairs, do the second loop over all objects.
818         // But: If a macro takes 2 pointers of the same type, we must take care that one gets the same pair, when we exchange the objects
819         // (this is not true, if we have different types - even if they inherit from the same classes!).
820         // Thus: If the latter case occurs, we ignore an object pair, if the second object is BEFORE the first object in the list.
821         // Since then the pair has already been taken into account.
822         // Furthermore, we have a pair of objects, if and only if both objects of the pair are selected (Rnr-state)
823         // and are not equal.
824         // The correlated objects process macro will be applied to all pairs that will be additionally selected by
825         // all correlated objects selection macros.
826
827         secondBeforeFirstObject = kTRUE;
828         for (TEveElement::List_i iter2 = this->BeginChildren(); iter2 != this->EndChildren(); ++iter2)
829         {
830           // If the objects are the same, it is not a pair -> continue. From now on: 2nd object BEHIND the 1st object in the list!
831           if (iter == iter2)
832           {
833             secondBeforeFirstObject = kFALSE;
834             continue;
835           }
836           if(!(object2 = dynamic_cast<TEveElement*>(*iter2))) continue;
837  
838           // Skip objects that have not been selected
839           if (!object2->GetRnrState())  continue;
840
841           // Same check of the macro object type as before
842           if (((TObject*)object2->GetUserData())->IsA() != mProcObjectType2[i] && 
843               !((TObject*)object2->GetUserData())->InheritsFrom(mProcObjectType2[i]))  continue;
844           // Do not process object pairs twice
845           if (secondBeforeFirstObject)
846           {
847             if (mProcObjectType[i] == mProcObjectType2[i]) continue;
848           }
849     
850           // Cast to the "real" object behind
851           gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object2));
852           gROOT->ProcessLineSync("TObject* automaticObject_2 = (TObject*)automaticEveElement->GetUserData();");
853
854           // Select object by default (so it will be processed, if there are no correlated objects selection macros!)
855           selectedByCorrSelMacro = kTRUE;
856           for (Int_t j = 0; j < selIterator->GetEntries(); j++) {
857             if (mSelType[j] == kCorrelObjectSelect) {
858               // Check, whether the macro can deal with both objects. If not, skip it.
859               // Note: Again, via selCmds[i], the automatic objects are casted to the correct type! 
860               if (((TObject*)object1->GetUserData())->IsA() != mSelObjectType[j] && 
861                   !((TObject*)object1->GetUserData())->InheritsFrom(mSelObjectType[j]))  continue;
862               if (((TObject*)object2->GetUserData())->IsA() != mSelObjectType2[j] && 
863                   !((TObject*)object2->GetUserData())->InheritsFrom(mSelObjectType2[j]))  continue;
864
865               selectedByCorrSelMacro = (Bool_t)gROOT->ProcessLineSync(selCmds[j]);
866               if (!selectedByCorrSelMacro)  break;
867             }
868           }       
869
870           // If the pair has not been selected by the correlated objects selection macros, skip it!
871           if (!selectedByCorrSelMacro) continue;
872           
873           // Create data pointers in CINT, execute the macro and get the data
874           gROOT->ProcessLineSync("Double_t* results = 0;");
875           gROOT->ProcessLineSync("Int_t n = 0;");
876           gROOT->ProcessLineSync(procCmds[i]);
877           Double_t* results = (Double_t*)gROOT->ProcessLineSync("results;");
878           Int_t nResults = (Int_t)gROOT->ProcessLineSync("n;");
879      
880           if (results == 0) {
881             Error("Apply macros", Form("Error reading data from macro \"%s\"", procIterator->At(i)->GetTitle()));
882             continue;
883           }
884           for (Int_t resInd = 0; resInd < nResults; resInd++) {
885             (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << results[resInd] << (Char_t*)"\n";   
886           }
887
888           delete results;
889           results = 0;
890         }
891       }
892     }
893   }    
894
895   for (Int_t i = 0, histoIndex = 0; i < procIterator->GetEntries() && histoIndex < numHistoMacros; i++) {
896     if (mProcType[i] == kSingleObjectHisto || mProcType[i] == kCorrelObjectHisto) {
897       // Might be empty (e.g. no objects have been selected)!
898       if (histos[histoIndex]) {
899         (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << histos[histoIndex] << (Char_t*)"\n";
900       }
901       histoIndex++;
902     }
903   }
904
905   if (fDataTree != 0) delete fDataTree;
906   fDataTree = 0;
907
908   if (procCmds != 0)  delete [] procCmds;
909   procCmds = 0;
910   if (mProcObjectType != 0) delete mProcObjectType;
911   mProcObjectType = 0;
912   if (mProcObjectType2 != 0) delete mProcObjectType2;
913   mProcObjectType2 = 0;
914   if (mProcType != 0)  delete [] mProcType;
915   mProcType = 0;
916
917   if (selCmds != 0)  delete [] selCmds;
918   selCmds = 0;
919   if (mSelObjectType != 0)  delete mSelObjectType;
920   mSelObjectType = 0;
921   if (mSelObjectType2 != 0)  delete mSelObjectType2;
922   mSelObjectType2 = 0;
923   if (mSelType != 0)  delete [] mSelType;
924   mSelType = 0;
925
926   if (histos != 0)  delete [] histos;
927   histos = 0;
928
929   // Clear root
930   // A.B. gROOT->Reset();
931   
932   // If there is data, select the first data set
933   if (procIterator->GetEntries() > 0) SETBIT(fHistoDataSelected, 0);
934
935   // Now the data is stored in "/tmp/ListAnalyserMacroData_$USER.root"
936   // The editor will access this file to display the data
937   return kTRUE;
938 }
939
940 //______________________________________________________
941 void AliEveListAnalyser::ApplySOSelectionMacros(const TList* iterator)
942 {
943   // Uses the iterator (for the selected selection macros) to apply the selected macros to the data.
944   // The rnr-states of the objects are set according to the result of the macro calls (kTRUE, if all
945   // macros return kTRUE for this object, otherwise: kFALSE).
946   // "SO" stands for "single object". This means that only single object selection macros are applied.
947   // Correlated objects selection macros will be used inside the call of ApplyProcessMacros(...)!
948
949   TGeneralMacroData* macro = 0;
950   AliEveListAnalyserMacroType macroType = kUnknown;
951   TEveElement* object1 = 0;
952   Bool_t selectedByMacro = kFALSE;
953
954   // Clear root
955   // A.B. gROOT->Reset();
956
957   // Select all objecs at first. A object is then deselected, if at least one selection macro
958   // returns kFALSE for this object.
959   // Enable all objects (Note: EnableListElements(..) will call "ElementChanged", which will cause unforeseen behaviour!)
960   for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter) ((TEveElement*)(*iter))->SetRnrState(kTRUE);
961   SetRnrState(kTRUE);
962   
963   for (Int_t i = 0; i < iterator->GetEntries(); i++){
964     macro = (TGeneralMacroData*)fMacroList->GetValue(iterator->At(i)->GetTitle());
965
966     if (!macro){
967       Error("Apply selection macros", 
968             Form("Macro list is corrupted: Macro \"%s\" is not registered!", iterator->At(i)->GetTitle()));
969       continue;
970     }
971
972 #ifdef AliEveListAnalyser_DEBUG
973     printf("AliEveListAnalyser: Applying selection macro: %s\n", macro->GetName());
974 #endif
975     
976     // Determine macro type
977     macroType = macro->GetType();
978
979     // Single object select macro
980     if (macroType == kSingleObjectSelect){
981       // Walk through the list of objects
982       for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter)
983       {
984         object1 = dynamic_cast<TEveElement*>(*iter);
985
986         if (!object1) continue;
987
988         // If the object has already been deselected, nothing is to do here
989         if (!object1->GetRnrState()) continue;
990
991         // Find the type of the object and relate it to the macro object type
992         // Only apply macro to this object, if...
993         // ... the macro takes objects of exactly this type.
994         // ... the macro object type is a child of this object's type.
995         // Otherwise: Continue
996         if (((TObject*)object1->GetUserData())->IsA() != macro->GetObjectType() && 
997             !((TObject*)object1->GetUserData())->InheritsFrom(macro->GetObjectType()))  continue;
998
999         // Cast to the "real" object behind
1000         gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object1));
1001         gROOT->ProcessLineSync("TObject* automaticObject_1 = (TObject*)automaticEveElement->GetUserData();");
1002
1003         // GetCmd() will cast the automatic objects to the correct type for each macro!
1004         selectedByMacro = (Bool_t)gROOT->ProcessLineSync(macro->GetCmd());
1005         object1->SetRnrState(selectedByMacro && object1->GetRnrState());               
1006       }
1007     }
1008     // Correlated objects select macro
1009     else if (macroType == kCorrelObjectSelect){
1010       // Will be processed in ApplyProcessMacros(...)
1011       continue;
1012     } else {
1013       Error("Apply selection macros", 
1014         Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a selection macro!", 
1015         macro->GetPath(), macro->GetName()));
1016     } 
1017   }
1018
1019   // Clear root
1020   // A.B. gROOT->Reset();  
1021 }
1022
1023 //______________________________________________________
1024 TClass* AliEveListAnalyser::GetMacroObjectType(const Char_t* name, Int_t argNum) const
1025 {
1026   // Returns the type of object (of argument argNum) the macro with name "name" is dealing with; 
1027   // e.g. if you have the signature:
1028   // void MyMacro(const AliTRDtrackV1* track, Double_t* &results, Int_t& nResults)
1029   // the call 'GetMacroObjectType("MyMacro")' yields the AliTRDtrackV1-class.
1030   // If the macro is not found (or there is an error), 0x0 is returned.
1031
1032   if (argNum - 1 < 0) return 0x0;
1033
1034   TFunction* f = gROOT->GetGlobalFunction(name, 0 , kTRUE);
1035   TMethodArg* m = 0;
1036   TList* list = 0;
1037
1038   if (f)
1039   {
1040     list = f->GetListOfMethodArgs();
1041     
1042     if (!list->IsEmpty())
1043     {
1044       m = (TMethodArg*)list->At(argNum - 1);
1045
1046       if (m)  return TClass::GetClass(m->GetTypeName());
1047     }
1048   }  
1049
1050   // Error
1051   return 0x0;
1052 }
1053
1054 //______________________________________________________
1055 AliEveListAnalyser::AliEveListAnalyserMacroType AliEveListAnalyser::GetMacroType(const Char_t* name, const Char_t* objectType, 
1056                                                                                  const Char_t* objectType2, Bool_t UseList) const
1057 {
1058   // Returns the type of the corresponding macro, that accepts pointers of the classes "objectType" (first pointer) and
1059   // objectType2" (second pointer) as parametres. 
1060   // If "UseList" is kTRUE, the type will be looked up in the internal list (very fast). But if this list
1061   // does not exist, you have to use kFALSE for this parameter. Then the type will be determined by the
1062   // prototype! NOTE: It is assumed that the macro has been compiled! If not, the return value is not
1063   // predictable, but normally will be kUnknown.
1064   // Note: AddMacro(Fast) will update the internal list and RemoveMacros respectively.
1065
1066   AliEveListAnalyserMacroType type = kUnknown;
1067
1068   TString* typeStr = 0;
1069   TString* typeStr2 = 0;
1070   
1071   if (objectType != 0) 
1072   {
1073     typeStr = new TString(objectType);
1074     // Remove white-spaces
1075     typeStr->ReplaceAll(" ", "");
1076   }
1077   else
1078   {
1079     typeStr = new TString("TObject");
1080   }
1081   if (objectType2 != 0) 
1082   {
1083     typeStr2 = new TString(objectType2);
1084     // Remove white-spaces
1085     typeStr2->ReplaceAll(" ", "");
1086   }
1087   else
1088   {
1089     typeStr2 = new TString("TObject");
1090   }
1091
1092   TString* mangled1Str = new TString();
1093   TString* mangled2Str = new TString();
1094   TString* mangled3Str = new TString();
1095   TString* mangled4Str = new TString();
1096   TString* mangledArg1Str = new TString();
1097   TString* mangledArg2Str = new TString();
1098
1099   // We want "const 'OBJECTTYPE'*"
1100   mangled1Str->Append("const ").Append(*typeStr).Append("*");
1101
1102   // We want "const 'OBJECTTYPE'*, Double_t*&, Int_t&"
1103   mangled2Str->Append("const ").Append(*typeStr).Append("*, Double_t*&, Int_t&");
1104
1105   // We want "const 'OBJECTTYPE'*, const 'OBJECTTYPE2'*"
1106   mangled3Str->Append("const ").Append(*typeStr).Append("*, const ").Append(*typeStr2).Append("*");
1107
1108   // We want "const 'OBJECTTYPE'*, const 'OBJECTTYPE2'*, Double_t*&, Int_t&"
1109   mangled4Str->Append("const ").Append(*typeStr).Append("*, const ").Append(*typeStr2).Append("*, Double_t*&, Int_t&");
1110
1111   // We want "oPconstsP'OBJECTTYPE'mUsP"
1112   mangledArg1Str->Append("oPconstsP").Append(*typeStr).Append("mUsP");
1113
1114   // We want "cOconstsP'OBJECTTYPE2'mUsP"
1115   mangledArg2Str->Append("cOconstsP").Append(*typeStr2).Append("mUsP");  
1116   
1117   // Re-do the check of the macro type
1118   if (!UseList){
1119     // Single object select macro or single object histo macro?
1120     TFunction* f = gROOT->GetGlobalFunctionWithPrototype(name, mangled1Str->Data(), kTRUE);
1121
1122     if (f != 0x0)
1123     {
1124       // Some additional check (is the parameter EXACTLY of the desired type?)
1125       if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0)
1126       {
1127         // Single object select macro?
1128         if (!strcmp(f->GetReturnTypeName(), "Bool_t")) 
1129         { 
1130           type = kSingleObjectSelect;     
1131         }
1132         // single object histo macro?
1133         else if (!strcmp(f->GetReturnTypeName(), "TH1*"))
1134         {
1135           type = kSingleObjectHisto;
1136         }
1137       }
1138     }
1139     // Single object analyse macro?
1140     else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled2Str->Data(), kTRUE)) 
1141              != 0x0)
1142     {
1143       if (!strcmp(f->GetReturnTypeName(), "void"))
1144       {
1145         // Some additional check (are the parameters EXACTLY of the desired type?)
1146         if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 &&
1147             strstr(f->GetMangledName(), "cODouble_tmUaNsP") != 0x0 &&
1148             strstr(f->GetMangledName(), "cOInt_taNsP") != 0x0)
1149         {
1150           type = kSingleObjectAnalyse;
1151         }
1152       }
1153     }    
1154     // Correlated objects select macro or correlated objects histo macro?
1155     else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled3Str->Data(), kTRUE)) 
1156              != 0x0)
1157     {
1158       // Some additional check (is the parameter EXACTLY of the desired type?)
1159       if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 &&
1160           strstr(f->GetMangledName(), mangledArg2Str->Data()) != 0x0)
1161       {
1162         // Correlated objects select macro?
1163         if (!strcmp(f->GetReturnTypeName(), "Bool_t")) 
1164         { 
1165           type = kCorrelObjectSelect;     
1166         }
1167         // Correlated objects histo macro?
1168         else if (!strcmp(f->GetReturnTypeName(), "TH1*"))
1169         {
1170           type = kCorrelObjectHisto;
1171         }
1172       }
1173     }    
1174     // Correlated objects analyse macro?
1175     else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled4Str->Data(), kTRUE)) 
1176              != 0x0)
1177     {
1178       if (!strcmp(f->GetReturnTypeName(), "void"))
1179       {
1180         // Some additional check (is the parameter EXACTLY of the desired type?)
1181         if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 &&
1182             strstr(f->GetMangledName(), mangledArg2Str->Data()) != 0x0 &&
1183             strstr(f->GetMangledName(), "cODouble_tmUaNsP") != 0x0 &&
1184             strstr(f->GetMangledName(), "cOInt_taNsP") != 0x0)
1185         {
1186           type = kCorrelObjectAnalyse;
1187         }
1188       }
1189     }    
1190   }
1191   // Use list to look up the macro type
1192   else
1193   {
1194     TGeneralMacroData* macro = 0;
1195     macro = (TGeneralMacroData*)fMacroList->GetValue(name);
1196     if (macro == 0)  return kUnknown; 
1197     
1198     type = macro->GetType();
1199     switch (type)
1200     {
1201       case kSingleObjectSelect:
1202       case kSingleObjectAnalyse:
1203       case kSingleObjectHisto:
1204       case kCorrelObjectSelect:
1205       case kCorrelObjectAnalyse:
1206       case kCorrelObjectHisto:      
1207         break;
1208     default:
1209       type = kUnknown;
1210       break;
1211     }
1212   }
1213
1214   // Clean up
1215   if (mangled1Str != 0)
1216   {
1217     mangled1Str->Clear();
1218     delete mangled1Str;
1219     mangled1Str = 0;
1220   }
1221   if (mangled2Str != 0)
1222   {
1223     mangled2Str->Clear();
1224     delete mangled2Str;
1225     mangled2Str = 0;
1226   }
1227   if (mangled3Str != 0)
1228   {
1229     mangled3Str->Clear();
1230     delete mangled3Str;
1231     mangled3Str = 0;
1232   }
1233   if (mangled4Str != 0)
1234   {
1235     mangled4Str->Clear();
1236     delete mangled4Str;
1237     mangled4Str = 0;
1238   }
1239   if (mangledArg1Str != 0)
1240   {
1241     mangledArg1Str->Clear();
1242     delete mangledArg1Str;
1243     mangledArg1Str = 0;
1244   }
1245   if (mangledArg2Str != 0)
1246   {
1247     mangledArg2Str->Clear();
1248     delete mangledArg2Str;
1249     mangledArg2Str = 0;
1250   }
1251   if (typeStr != 0)
1252   {
1253     typeStr->Clear();
1254     delete typeStr;
1255     typeStr = 0;
1256   }
1257   if (typeStr2 != 0)
1258   {
1259     typeStr2->Clear();
1260     delete typeStr2;
1261     typeStr2 = 0;
1262   }
1263
1264
1265   return type;
1266 }
1267
1268
1269 /*
1270 //______________________________________________________
1271 void AliEveListAnalyser::RemovePrimSelectedObjects()
1272 {
1273   // Removes the (primarily) selected objects in the viewer from the list (objects that are already in the list are ignored).
1274   // Hold the CTRL-key for multiple selection.
1275
1276   TEveSelection* eveSel = gEve->GetSelection();
1277
1278   if (!eveSel)
1279   {
1280     Error("AliEveListAnalyser::RemovePrimSelectedObjects", "Failed to get the selection!\n");
1281     return;
1282   }
1283   
1284   TEveElement* elem = 0x0;
1285   Bool_t changedSomething = kFALSE;
1286
1287   for (TEveElement::List_i iter = eveSel->BeginChildren(); iter != eveSel->EndChildren(); ++iter)
1288   {
1289     if(!(elem = dynamic_cast<TEveElement*>(*iter))) continue;
1290
1291     // Check, if element is already there. If so, remove it!
1292     if (this->HasChild(elem) && elem != this)
1293     {
1294       this->RemoveElement(elem);
1295       this->SetTitle(Form("Objects %d", this->NumChildren()));
1296       changedSomething = kTRUE;
1297     }
1298   }
1299
1300   if (changedSomething) gEve->Redraw3D();
1301 }
1302 */
1303
1304 //______________________________________________________
1305 void AliEveListAnalyser::RemoveSelectedMacros(const TList* iterator) 
1306 {
1307   // Uses the iterator (for the selected macros) to remove the selected macros from 
1308   // the corresponding list.
1309    
1310   TObject* key = 0;
1311   TPair*   entry = 0;
1312   for (Int_t i = 0; i < iterator->GetEntries(); i++)
1313   {
1314     entry = (TPair*)fMacroList->FindObject(iterator->At(i)->GetTitle());
1315
1316     if (entry == 0)
1317     {
1318       Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Macro \"%s\" not found in list!", 
1319                                                                      iterator->At(i)->GetTitle()));
1320       continue;
1321     }
1322     key = entry->Key();
1323
1324     if (key == 0)   
1325     {
1326       Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Key for macro \"%s\" not found in list!", 
1327                                                                      iterator->At(i)->GetTitle()));
1328       continue;
1329     }
1330
1331     // Key and value will be deleted, too, since fMacroList is the owner of them
1332     Bool_t rem = fMacroList->DeleteEntry(key);
1333
1334     if (rem)
1335     {
1336 #ifdef AliEveListAnalyser_DEBUG
1337     printf("AliEveListAnalyser::RemoveSelectedMacros(): Removed macro: %s\n", iterator->At(i)->GetTitle());
1338 #endif
1339     }
1340     else
1341     {
1342       Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Macro \"%s\" could not be removed from the list!", 
1343                                                                      iterator->At(i)->GetTitle()));
1344     }
1345   }
1346 }
1347
1348 //______________________________________________________
1349 void AliEveListAnalyser::ResetObjectList()
1350 {
1351   // Removes all objects from the list.
1352
1353   RemoveElements();
1354   this->SetTitle(Form("Objects %d", this->NumChildren()));
1355 }
1356
1357 //______________________________________________________
1358 Bool_t AliEveListAnalyser::StartAddingObjects()
1359
1360   // Starts adding objects for the analysis. Returns kTRUE on success.
1361
1362   if (fConnected == kFALSE)
1363   {
1364     fConnected = TQObject::Connect("TEvePointSet", "PointSelected(Int_t)", "AliEveListAnalyser", this, "AddSecSelectedSingleObjectToList(Int_t)");
1365     if (fConnected)  fConnected = TQObject::Connect(gEve->GetSelection(), "SelectionAdded(TEveElement*)", "AliEveListAnalyser", this, "AddPrimSelectedObject(TEveElement*)");
1366
1367     if (fConnected) return kTRUE;
1368     
1369     Error("AliEveListAnalyser::StartAddingObjects", "Connection failed!");
1370     
1371     // Connection of 2nd signal failed, but first connection succeeded -> Disconnect 1st signal.
1372     TQObject::Disconnect("TEvePointSet", "PointSelected(Int_t)", this, "AddObjectToList(Int_t)");
1373   }
1374
1375   return kFALSE;
1376 }
1377
1378 //______________________________________________________
1379 Bool_t AliEveListAnalyser::StopAddingObjects()
1380 {
1381   // Stops adding objects for the analysis. Returns kTRUE on success.
1382
1383   if (fConnected)
1384   {
1385     Bool_t dis1 = kFALSE, dis2 = kFALSE;
1386     dis1 = TQObject::Disconnect("TEvePointSet", "PointSelected(Int_t)", this, "AddSecSelectedSingleObjectToList(Int_t)");
1387     dis2 = TQObject::Disconnect(gEve->GetSelection(), "SelectionAdded(TEveElement*)", this, "AddPrimSelectedObject(TEveElement*)");
1388
1389     if (dis1 || dis2) fConnected = kFALSE;
1390     if (dis1 && dis2) return kTRUE;
1391     else
1392     {
1393       Error("AliEveListAnalyser::StopAddingObjects", "Disconnection failed!");
1394
1395       return kFALSE;
1396     }
1397   }
1398
1399   return kTRUE;
1400 }