]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EVE/EveDet/AliEveListAnalyser.cxx
new class "List Analyser" by Ben Hess
[u/mrichter/AliRoot.git] / EVE / EveDet / AliEveListAnalyser.cxx
1 // Author: Benjamin Hess   06/11/2009
2
3 /*************************************************************************
4  * Copyright (C) 2009, Alexandru Bercuci, Benjamin Hess.                 *
5  * All rights reserved.                                                  *
6  *************************************************************************/
7
8 // TODO: Documentation
9 //////////////////////////////////////////////////////////////////////////
10 //                                                                      //
11 // AliEveListAnalyser                                           //
12 //                                                                      //
13 // An AliEveListAnalyser is, in principal, a TEveElementList    //
14 // with some sophisticated features. You can add macros to this list,   //
15 // which then can be applied to the list of tracks (these tracks can be //
16 // added to the list in the same way as for the TEveElementList).       //
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 // be removed. 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 // With ApplySTSelectionMacros(...) or ApplyProcessMacros(...)          //
28 // respectively you can apply the macros to the track list via          //
29 // iterators (same style like for RemoveSelectedMacros(...)(cf. above)).//
30 // Selection macros (de-)select macros according to a selection rule    //
31 // by setting the rnr-state of the tracks.                              //
32 // If multiple selection macros are applied, a track is selected, if    //
33 // all selection macros select the track.                               //
34 // Process macros create data or histograms, which will be stored in    //
35 // a temporary file. The editor of this class will access this file     //
36 // and draw all the stuff within it's DrawHistos() function. The file   //
37 // will be deleted by the destructor.                                   //
38 //                                                                      //
39 // Currently, the following macro types are supported:                  //
40 // Selection macros:                                                    //
41 // Bool_t YourMacro(const AliTRDtrackV1*);                              //
42 // Bool_t YourMacro(const AliTRDtrackV1*, const AliTRDtrackV1*);        //
43 //                                                                      //
44 // Process macros:                                                      //
45 // void YourMacro(const AliTRDtrackV1*, Double_t*&, Int_t&);            //
46 // void YourMacro(const AliTRDtrackV1*, const AliTRDtrackV1*,           //
47 //                Double_t*&, Int_t&);                                  //
48 // TH1* YourMacro(const AliTRDtrackV1*);                                //
49 // TH1* YourMacro(const AliTRDtrackV1*, const AliTRDtrackV1*);          //
50 //                                                                      //
51 // The macros which take 2 tracks are applied to all track pairs        //
52 // (whereby BOTH tracks of the pair have to be selected by the single   //
53 // track selection macros and have to be unequal, otherwise they will   //
54 // be skipped) that have been selected by ALL correlated tracks         //
55 // selection macros. The selection macros with 2 tracks do NOT affect   //
56 // process macros that process only a single track!                     //
57 //////////////////////////////////////////////////////////////////////////
58
59
60 // Uncomment to display debugging infos
61 //#define AliEveListAnalyser_DEBUG
62
63 #include <TFile.h>
64 #include <TFunction.h>
65 #include <TMethodArg.h>
66 #include <TH1.h>
67 #include <TList.h>
68 #include <TMap.h>
69 #include <TObjString.h>
70 #include <TROOT.h>
71 #include <TSystem.h>
72 #include <TTree.h>
73 #include <TTreeStream.h>
74 #include <TMethodCall.h>
75
76 #include <AliTRDReconstructor.h>
77
78 #include <EveDet/AliEveListAnalyser.h>
79 #include <EveDet/AliEveListAnalyserEditor.h>
80
81 // TODO: Are these files required?
82 //#include <../PWG1/TRD/AliTRDrecoTask.h>
83 //#include <../PWG1/TRD/macros/AliTRDperformanceTrain.h>
84
85 ClassImp(AliEveListAnalyser)
86
87 ///////////////////////////////////////////////////////////
88 /////////////   AliEveListAnalyser ////////////////
89 ///////////////////////////////////////////////////////////
90 AliEveListAnalyser::AliEveListAnalyser(const Text_t* n, const Text_t* t, Bool_t doColor):
91   TEveElementList(n, t, doColor),
92   fEditor(0x0),
93   fDataFromMacroList(0x0),
94   fMacroList(0x0),
95   fDataTree(0x0),
96   fHistoDataSelected(0),
97   fMacroListSelected(0),
98   fSelectedTab(1)                               // Standard tab: "Apply macros" (index 1)
99
100
101 // TODO: Old version with style tab
102 /*
103   fSelectedTab(1),                              // Standard tab: "Apply macros" (index 1)
104   fSelectedStyle(0)
105 */
106
107 {
108   // Creates the AliEveListAnalyser.
109
110   // Only accept childs of type TEveElement
111   SetChildClass(TEveElement::Class());
112
113   // Allocate memory for the lists and declare them as owners of their contents
114   fDataFromMacroList = new TList();
115   fDataFromMacroList->TCollection::SetOwner(kTRUE);
116
117   fMacroList = new TMap();
118   // Set map to owner of it's objects to delete them, if they are removed from the map
119   fMacroList->SetOwnerKeyValue(kTRUE, kTRUE);
120
121   // Set the build directory for AClic
122   if(gSystem->AccessPathName(Form("%s/.QArec" , gSystem->Getenv("HOME")))) gSystem->Exec("mkdir $HOME/.QArec");
123   gSystem->SetBuildDir(Form("%s/.QArec", gSystem->Getenv("HOME")));
124
125   AddStandardContent();
126 }
127
128 //______________________________________________________
129 AliEveListAnalyser::~AliEveListAnalyser()
130 {
131   // Frees allocated memory (lists etc.).
132
133   // Let the editor know that the list will be destroyed -> The editor will save the data
134   if (fEditor != 0)
135   {
136     fEditor->SaveMacroList(fMacroList);
137     fEditor = 0;
138   }
139
140   if (fDataFromMacroList != 0)
141   {
142     fDataFromMacroList->Delete();
143     delete fDataFromMacroList;
144     fDataFromMacroList = 0;
145   } 
146   if (fDataTree != 0)
147   {
148     delete fDataTree;
149     fDataTree = 0;
150   } 
151   if (fMacroList != 0)
152   {
153     fMacroList->DeleteAll();
154     delete fMacroList;
155     fMacroList = 0;
156   }
157   // Note: gSystem->AccessPathName(...) returns kTRUE, if the access FAILED!
158   if(!gSystem->AccessPathName(Form("/tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")))) 
159     gSystem->Exec(Form("rm /tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")));
160 }
161
162 //______________________________________________________
163 Int_t AliEveListAnalyser::AddMacro(const Char_t* path, const Char_t* nameC, Bool_t forceReload)
164 {
165   // Checks, if the file exists and if the signature is correct.
166   // If these criteria are fullfilled, the library for this macro is built
167   // and the macro is added to the corresponding list.
168   // Supported macro types:
169   // Selection macros:                                                    
170   // Bool_t YourMacro(const TObject*)
171   // Bool_t YourMacro(const TObject*, const TObject*)
172   //
173   // Process macros:                                                      
174   // void YourMacro(const TObject*, Double_t*&, Int_t&)             
175   // void YourMacro(const TObject*, const TObject*, Double_t*&, Int_t&)                                   
176   // TH1* YourMacro(const TObject*)                                 
177   // TH1* YourMacro(const TObject*, const TObject*)                              
178
179   Char_t pathname[fkMaxMacroPathNameLength];
180   memset(pathname, '\0', sizeof(Char_t) * fkMaxMacroPathNameLength);
181
182   // Expand the path and create the pathname
183   Char_t* systemPath = gSystem->ExpandPathName(path);
184   sprintf(pathname, "%s/%s", systemPath, nameC);
185   delete systemPath;
186   systemPath = 0;
187
188   // Delete ".C" from filename
189   Char_t name[fkMaxMacroNameLength];
190   memset(name, '\0', sizeof(Char_t) * fkMaxMacroNameLength);
191   
192   for (UInt_t ind = 0; ind < fkMaxMacroNameLength && ind < strlen(nameC) - 2; ind++)  name[ind] = nameC[ind];
193
194   // Check, if files exists
195   FILE* fp = 0x0;
196   if((fp = fopen(pathname, "rb"))){
197     fclose(fp);
198     fp = 0x0;
199   } else  return NOT_EXIST_ERROR;
200   
201   // Clean up root, load the desired macro and then check the type of the macro
202   // A.B. gROOT->Reset();
203  
204   gROOT->ProcessLineSync(Form(".L %s+%c", pathname, forceReload ? '+' : ' '));
205
206   TClass* objectType;
207
208   objectType = GetMacroObjectType(name);
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   AliEveListAnalyserMacroType type = GetMacroType(name, objectType->GetName(), kFALSE);
216
217   // Clean up again
218   // A.B. gROOT->Reset();
219  
220   // Has not the correct signature!
221   if (type == kUnknown) return SIGNATURE_ERROR;
222
223   // Only add macro, if it is not already in the list
224   Int_t returnValue = WARNING;
225   if(fMacroList->GetValue(name) == 0) 
226   {
227     returnValue = AddMacroFast(path, name, type, objectType) ? SUCCESS : ERROR;
228   }
229
230   return returnValue;
231 }
232
233 //______________________________________________________
234 Bool_t AliEveListAnalyser::AddMacroFast(const Char_t* path, const Char_t* name, AliEveListAnalyserMacroType type, TClass* objectType)
235 {
236   // Adds a macro (path/name) to the corresponding list. No checks are performed (file exists, 
237   // macro already in list/map, signature correct),  no libraries are created!
238   // You can use this function only, if the macro has been added successfully before 
239   // (and then maybe was removed). The function is very fast. On success kTRUE is returned, otherwise: kFALSE;
240
241   Bool_t success = kFALSE;
242
243   switch (type)
244   {
245     case kSingleObjectSelect:
246     case kCorrelObjectSelect:
247     case kSingleObjectAnalyse:
248     case kSingleObjectHisto:
249     case kCorrelObjectAnalyse:
250     case kCorrelObjectHisto:
251       fMacroList->Add(new TObjString(name), new TGeneralMacroData(name, path, type, objectType));
252
253       // We do not know, where the element has been inserted - deselect this list
254       fMacroListSelected = 0;
255     
256       success = kTRUE;
257
258 #ifdef AliEveListAnalyser_DEBUG
259       // Successfull add will only be displayed in debug mode
260       printf("AliEveListAnalyser::AddMacroFast: Added macro \"%s/%s\" with object type \"%s\" to the corresponding list\n", path, name,
261              objectType->GetName());
262 #endif
263
264       break;
265
266     default:
267       // Error will always be displayed
268       printf("AliEveListAnalyser::AddMacroFast: ERROR: Could not add macro \"%s/%s\" with object type \"%s\" to the corresponding list\n", 
269              path, name, objectType->GetName());
270
271       success = kFALSE;
272
273       break;
274   }
275
276   return success;
277 }
278
279 //______________________________________________________
280 void AliEveListAnalyser::AddStandardContent()
281 {
282   // Adds standard macros to the macro list.
283
284   // Add your standard macros here, e.g.: 
285   // To add a macro use:
286   // AddMacro("$(ALICE_ROOT)/myFolder", "myMacroName.C");
287   // -> If the file does not exist, nothing happens. So if you want to handle this,
288   // use the return value of AddMacro (NOT_EXIST_ERROR is returned, if file does not exist)
289   // (-> You can also check for other return values (see AddMacro(...)))
290 /*
291   const Char_t *libs[] = {"libANALYSIS.so", "libANALYSISalice.so", "libTENDER.so", "libPWG1.so"};
292   Int_t nlibs = static_cast<Int_t>(sizeof(libs)/sizeof(Char_t *));
293   for(Int_t ilib=0; ilib<nlibs; ilib++){
294     if(gSystem->Load(libs[ilib]) >= 0) continue;
295     AliError(Form("Fail loading %s.", libs[ilib]));
296     return;
297   }
298
299   AliTRDrecoTask *task = 0x0;
300   TList *fPlots = 0x0;
301   for(Int_t it=2; it<NTRDQATASKS; it++){
302     TClass c(fgkTRDtaskClassName[it]);
303     task = (AliTRDrecoTask*)c.New();
304     task->SetMCdata(kFALSE);
305     if(!(fPlots = task->GetPlotFunctors())){
306       //AliWarning(Form("No Plot functors defined for task \"%s\"", fgkTRDtaskClassName[it]));
307       delete task;
308       continue;
309     }
310     if(!(task->Histos())){
311       //AliWarning(Form("No Ref Histograms defined for task \"%s\"", fgkTRDtaskClassName[it]));
312       delete task;
313       continue;
314     }
315
316     // export task to CINT and add functions
317     gROOT->ProcessLine(Form("%s* %s = (%s*)0x%lx;", fgkTRDtaskClassName[it], task->GetName(), fgkTRDtaskClassName[it], (void*)task));
318     TIter iter(fPlots); TMethodCall *m = 0x0;
319     while((m = dynamic_cast<TMethodCall*>(iter()))){
320       AddMacroFast("", Form("%s->%s", task->GetName(), m->GetMethodName()), kSingleTrackHisto);
321     }
322   }
323 */
324 }
325
326 //______________________________________________________
327 Bool_t AliEveListAnalyser::ApplyProcessMacros(const TList* selIterator, const TList* procIterator)
328 {
329   // Uses the procIterator (for the selected process macros) to apply the selected macros to the data.
330   // Returns kTRUE on success, otherwise kFALSE. If there no process macros selected, kTRUE is returned 
331   // (this is no error!).
332   // The single object process macros are applied to all selected objects.
333   // The selIterator (for the selected selection macros) will be used to apply the correlated objects selection
334   // macros to all object pairs (whereby BOTH objects have to be selected, otherwise they will be skipped).
335   // All object pairs that have been selected by ALL correlated objects selection macros will be processed by
336   // the correlated objects process macros.
337
338   // No process macros need to be processed
339   if (procIterator->GetEntries() <= 0)  return kTRUE;
340
341   // Clear root
342   // A.B. gROOT->Reset();
343   
344   // Clear old data and re-allocate
345   if (fDataTree == 0x0){ 
346     TDirectory *cwd = gDirectory;
347     fDataTree = new TTreeSRedirector(Form("/tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")));
348     cwd->cd();
349   }
350   if (!fDataTree){
351     Error("Apply process macros", Form("File \"/tmp/ListAnalyserMacroData_%s.root\" could not be accessed properly!", 
352           gSystem->Getenv("USER")));
353     return kFALSE;
354   }
355   
356   if (fDataFromMacroList != 0) {
357     fDataFromMacroList->Delete();
358     delete fDataFromMacroList;
359   }
360   fDataFromMacroList = new TList();
361   fDataFromMacroList->TCollection::SetOwner(kTRUE);
362
363   fHistoDataSelected = 0;
364
365
366   TGeneralMacroData* macro = 0;
367
368   Char_t** procCmds = 0;
369   AliEveListAnalyserMacroType* mProcType = 0;
370   if (procIterator->GetEntries() > 0) {
371     procCmds = new Char_t*[procIterator->GetEntries()];
372     mProcType = new AliEveListAnalyserMacroType[procIterator->GetEntries()];
373   }
374
375   Char_t** selCmds  = 0;
376   AliEveListAnalyserMacroType* mSelType = 0;
377   if (selIterator->GetEntries() > 0) {
378     selCmds = new Char_t*[selIterator->GetEntries()];
379     mSelType = new AliEveListAnalyserMacroType[selIterator->GetEntries()];
380   }
381   
382   Bool_t selectedByCorrSelMacro = kFALSE;
383
384   AliEveListAnalyserMacroType macroType = kUnknown;
385   Int_t numHistoMacros = 0;
386   TH1** histos = 0;
387
388   TEveElement* object1 = 0;
389   TEveElement* object2 = 0;
390
391   // Collect the commands for each process macro and add them to "data-from-list"
392   for (Int_t i = 0; i < procIterator->GetEntries(); i++){
393     procCmds[i] = new Char_t[(fkMaxMacroPathNameLength + fkMaxApplyCommandLength)];
394     memset(procCmds[i], '\0', sizeof(Char_t) * (fkMaxMacroNameLength + fkMaxApplyCommandLength));
395
396     macro = (TGeneralMacroData*)fMacroList->GetValue(procIterator->At(i)->GetTitle());
397
398     if (!macro){
399       Error("Apply process macros", 
400         Form("Macro list is corrupted: Macro \"%s\" is not registered!", 
401         procIterator->At(i)->GetTitle()));
402       continue;
403     }
404
405 #ifdef AliEveListAnalyser_DEBUG
406     printf("AliEveListAnalyser: Checking process macro: %s\n", macro->GetName());
407 #endif 
408            
409     // Find the type of the process macro
410     macroType = macro->GetType();
411     if (macroType == kSingleObjectHisto || macroType == kCorrelObjectHisto){
412       mProcType[i] = macroType;
413       numHistoMacros++;
414       // Create the command 
415       sprintf(procCmds[i], macro->GetCmd());
416
417       // Add to "data-from-list" -> Mark as a histo macro with the substring "(histo macro)"
418       fDataFromMacroList->Add(new TObjString(Form("%s (histo macro)", macro->GetName())));
419     } else if (macroType == kSingleObjectAnalyse || macroType == kCorrelObjectAnalyse) {
420       mProcType[i] = macroType;
421       // Create the command 
422       sprintf(procCmds[i], macro->GetCmd());
423
424       // Add to "data-from-list"
425       fDataFromMacroList->Add(new TObjString(macro->GetName()));
426     } else {
427       Error("Apply process macros", 
428         Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a process macro!", 
429         macro->GetPath(), macro->GetName()));
430       mProcType[i] = kUnknown;
431     } 
432   }  
433
434   // Collect the commands for each selection macro and add them to "data-from-list"
435   for (Int_t i = 0; i < selIterator->GetEntries(); i++){
436     selCmds[i] = new Char_t[(fkMaxMacroPathNameLength + fkMaxApplyCommandLength)];
437     memset(selCmds[i], '\0', sizeof(Char_t) * (fkMaxMacroNameLength + fkMaxApplyCommandLength));
438
439     macro = (TGeneralMacroData*)fMacroList->GetValue(selIterator->At(i)->GetTitle());
440
441     if (!macro){
442       Error("Apply process macros", 
443         Form("Macro list is corrupted: Macro \"%s\" is not registered!", 
444         selIterator->At(i)->GetTitle()));
445       continue;
446     }
447
448 #ifdef AliEveListAnalyser_DEBUG
449     printf("AliEveListAnalyser: Checking selection macro: %s\n", macro->GetName());
450 #endif
451        
452     // Find the type of the process macro
453     macroType = macro->GetType();
454
455     // Single Object select macro
456     if (macroType == kSingleObjectSelect) {
457       // Has already been processed by ApplySTSelectionMacros(...)
458       mSelType[i] = macroType;         
459     }
460     // Correlated Objects select macro
461     else if (macroType == kCorrelObjectSelect) {
462       mSelType[i] = macroType;  
463  
464       // Create the command
465       sprintf(selCmds[i], macro->GetCmd());
466     } else {
467       Error("Apply process macros", 
468         Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a selection macro!", 
469         macro->GetPath(), macro->GetName()));
470       mSelType[i] = kUnknown;
471     } 
472   }  
473
474   // Allocate memory for the histograms
475   if (numHistoMacros > 0)  histos = new TH1*[numHistoMacros];
476   for (Int_t i = 0; i < numHistoMacros; i++)  histos[i] = 0x0;
477
478
479   //////////////////////////////////
480   // WALK THROUGH THE LIST OF OBJECTS
481   //////////////////////////////////     
482   for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter){
483     if(!(object1 = dynamic_cast<TEveElement*>(*iter))) continue;
484
485     // Skip objects that have not been selected
486     if (!object1->GetRnrState())  continue;
487     
488     // Cast to the "real" object behind
489     gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object1));
490     gROOT->ProcessLineSync("TObject* automaticObject_1 = (TObject*)automaticEveElement->GetUserData();");
491
492     // Collect data for each macro
493     for (Int_t i = 0, histoIndex = 0; i < procIterator->GetEntries(); i++){
494       // Single object histo
495       if (mProcType[i] == kSingleObjectHisto){
496         histos[histoIndex++] = (TH1*)gROOT->ProcessLineSync(procCmds[i]);
497        // Correlated Objects histo
498       } else if (mProcType[i] == kCorrelObjectHisto) {
499         // Loop over all pairs behind the current one - together with the other loop this will be a loop
500         // over all pairs. We have a pair of objects, if and only if both objects of the pair are selected (Rnr-state)
501         // and are not equal.
502         // The correlated objects process macro will be applied to all pairs that will be additionally selected by
503         // all correlated objects selection macros.
504         TEveElement::List_i iter2 = iter;
505         iter2++;
506         for ( ; iter2 != this->EndChildren(); ++iter2)
507         {
508           if(!(object2 = dynamic_cast<TEveElement*>(*iter2))) continue;
509
510           // Skip objects that have not been selected
511           if (!object2->GetRnrState())  continue;
512       
513           // Cast to the "real" object behind
514           gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object2));
515           gROOT->ProcessLineSync("TObject* automaticObject_2 = (TObject*)automaticEveElement->GetUserData();");
516
517           // Select object by default (so it will be processed, if there are no correlated objects selection macros!)
518           selectedByCorrSelMacro = kTRUE;
519           for (Int_t j = 0; j < selIterator->GetEntries(); j++){
520             if (mSelType[j] == kCorrelObjectSelect){
521               selectedByCorrSelMacro = (Bool_t)gROOT->ProcessLineSync(selCmds[j]);
522               if (!selectedByCorrSelMacro)  break;
523             }
524           }       
525
526           // If the pair has not been selected by the correlated objects selection macros, skip it!
527           if (!selectedByCorrSelMacro) continue;
528           
529           histos[histoIndex] = (TH1*)gROOT->ProcessLineSync(procCmds[i]);
530         }
531         histoIndex++;
532       }
533       // Single object analyse
534       else if (mProcType[i] == kSingleObjectAnalyse) {
535         // Create data pointers in CINT, execute the macro and get the data
536         gROOT->ProcessLineSync("Double_t* results = 0;");
537         gROOT->ProcessLineSync("Int_t n = 0;");
538         gROOT->ProcessLineSync(procCmds[i]);
539         Double_t* results = (Double_t*)gROOT->ProcessLineSync("results;");
540         Int_t nResults = (Int_t)gROOT->ProcessLineSync("n;");
541         
542         if (results == 0) {
543           Error("Apply macros", Form("Error reading data from macro \"%s\"", procIterator->At(i)->GetTitle()));
544           continue;
545         }
546         for (Int_t resInd = 0; resInd < nResults; resInd++){
547           (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << results[resInd] << (Char_t*)"\n";   
548         }
549
550         delete results;
551         results = 0;
552       }
553       // Correlated objects analyse
554       else if (mProcType[i] == kCorrelObjectAnalyse){
555         // Loop over all pairs behind the current one - together with the other loop this will be a loop
556         // over all pairs. We have a pair of objects, if and only if both objects of the pair are selected (Rnr-state)
557         // and are not equal.
558         // The correlated objects process macro will be applied to all pairs that will be additionally selected by
559         // all correlated objects selection macros.
560         TEveElement::List_i iter2 = iter;
561         iter2++;
562
563         for ( ; iter2 != this->EndChildren(); ++iter2) {
564           if(!(object2 = dynamic_cast<TEveElement*>(*iter2))) continue;
565  
566           // Skip objects that have not been selected
567           if (!object2->GetRnrState())  continue;
568     
569           // Cast to the "real" object behind
570           gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object2));
571           gROOT->ProcessLineSync("TObject* automaticObject_2 = (TObject*)automaticEveElement->GetUserData();");
572
573           // Select object by default (so it will be processed, if there are no correlated objects selection macros!)
574           selectedByCorrSelMacro = kTRUE;
575           for (Int_t j = 0; j < selIterator->GetEntries(); j++) {
576             if (mSelType[j] == kCorrelObjectSelect) {
577               selectedByCorrSelMacro = (Bool_t)gROOT->ProcessLineSync(selCmds[j]);
578               if (!selectedByCorrSelMacro)  break;
579             }
580           }       
581
582           // If the pair has not been selected by the correlated objects selection macros, skip it!
583           if (!selectedByCorrSelMacro) continue;
584           
585           // Create data pointers in CINT, execute the macro and get the data
586           gROOT->ProcessLineSync("Double_t* results = 0;");
587           gROOT->ProcessLineSync("Int_t n = 0;");
588           gROOT->ProcessLineSync(procCmds[i]);
589           Double_t* results = (Double_t*)gROOT->ProcessLineSync("results;");
590           Int_t nResults = (Int_t)gROOT->ProcessLineSync("n;");
591      
592           if (results == 0) {
593             Error("Apply macros", Form("Error reading data from macro \"%s\"", procIterator->At(i)->GetTitle()));
594             continue;
595           }
596           for (Int_t resInd = 0; resInd < nResults; resInd++) {
597             (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << results[resInd] << (Char_t*)"\n";   
598           }
599
600           delete results;
601           results = 0;
602         }
603       }
604     }
605   }    
606
607   for (Int_t i = 0, histoIndex = 0; i < procIterator->GetEntries() && histoIndex < numHistoMacros; i++) {
608     if (mProcType[i] == kSingleObjectHisto || mProcType[i] == kCorrelObjectHisto) {
609       // Might be empty (e.g. no objects have been selected)!
610       if (histos[histoIndex]) {
611         (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << histos[histoIndex] << (Char_t*)"\n";
612       }
613       histoIndex++;
614     }
615   }
616
617   if (fDataTree != 0) delete fDataTree;
618   fDataTree = 0;
619
620   if (procCmds != 0)  delete [] procCmds;
621   procCmds = 0;
622   if (mProcType != 0)  delete mProcType;
623   mProcType = 0;
624
625   if (selCmds != 0)  delete [] selCmds;
626   selCmds = 0;
627   if (mSelType != 0)  delete mSelType;
628   mSelType = 0;
629
630   if (histos != 0)  delete [] histos;
631   histos = 0;
632
633   // Clear root
634   // A.B. gROOT->Reset();
635   
636   // If there is data, select the first data set
637   if (procIterator->GetEntries() > 0) SETBIT(fHistoDataSelected, 0);
638
639   // Now the data is stored in "/tmp/ListAnalyserMacroData_$USER.root"
640   // The editor will access this file to display the data
641   return kTRUE;
642 }
643
644 //______________________________________________________
645 void AliEveListAnalyser::ApplySTSelectionMacros(const TList* iterator)
646 {
647   // Uses the iterator (for the selected selection macros) to apply the selected macros to the data.
648   // The rnr-states of the objects are set according to the result of the macro calls (kTRUE, if all
649   // macros return kTRUE for this object, otherwise: kFALSE).
650   // "ST" stands for "single object". This means that only single object selection macros are applied.
651   // Correlated objects selection macros will be used inside the call of ApplyProcessMacros(...)!
652
653   TGeneralMacroData* macro = 0;
654   AliEveListAnalyserMacroType macroType = kUnknown;
655   TEveElement* object1 = 0;
656   Bool_t selectedByMacro = kFALSE;
657
658   // Clear root
659   // A.B. gROOT->Reset();
660
661   // Select all objecs at first. A object is then deselected, if at least one selection macro
662   // returns kFALSE for this object.
663   // Enable all objects (Note: EnableListElements(..) will call "ElementChanged", which will cause unforeseen behaviour!)
664   for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter) ((TEveElement*)(*iter))->SetRnrState(kTRUE);
665   SetRnrState(kTRUE);
666   
667   for (Int_t i = 0; i < iterator->GetEntries(); i++){
668     macro = (TGeneralMacroData*)fMacroList->GetValue(iterator->At(i)->GetTitle());
669
670     if (!macro){
671       Error("Apply selection macros", 
672             Form("Macro list is corrupted: Macro \"%s\" is not registered!", iterator->At(i)->GetTitle()));
673       continue;
674     }
675
676 #ifdef AliEveListAnalyser_DEBUG
677     printf("AliEveListAnalyser: Applying selection macro: %s\n", macro->GetName());
678 #endif
679     
680     // Determine macro type
681     macroType = macro->GetType();
682
683     // Single object select macro
684     if (macroType == kSingleObjectSelect){
685       // Walk through the list of objects
686       for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter)
687       {
688         object1 = dynamic_cast<TEveElement*>(*iter);
689
690         if (!object1) continue;
691
692         // If the object has already been deselected, nothing is to do here
693         if (!object1->GetRnrState()) continue;
694
695         // Cast to the "real" object behind
696         gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object1));
697         gROOT->ProcessLineSync("TObject* automaticObject_1 = (TObject*)automaticEveElement->GetUserData();");
698
699         selectedByMacro = (Bool_t)gROOT->ProcessLineSync(macro->GetCmd());
700         object1->SetRnrState(selectedByMacro && object1->GetRnrState());               
701       }
702     }
703     // Correlated objects select macro
704     else if (macroType == kCorrelObjectSelect){
705       // Will be processed in ApplyProcessMacros(...)
706       continue;
707     } else {
708       Error("Apply selection macros", 
709         Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a selection macro!", 
710         macro->GetPath(), macro->GetName()));
711     } 
712   }
713
714   // Clear root
715   // A.B. gROOT->Reset();  
716 }
717
718 // TODO -> Type checking
719 //______________________________________________________
720 AliEveListAnalyser::AliEveListAnalyserMacroType AliEveListAnalyser::GetMacroType(const Char_t* name, const Char_t* objectType, Bool_t UseList) const
721 {
722   // Returns the type of the corresponding macro, that accepts pointers of the class "objectType" as a parametre. 
723   // If "UseList" is kTRUE, the type will be looked up in the internal list (very fast). But if this list
724   // does not exist, you have to use kFALSE for this parameter. Then the type will be determined by the
725   // prototype! NOTE: It is assumed that the macro has been compiled! If not, the return value is not
726   // predictable, but normally will be kUnknown.
727   // Note: AddMacro(Fast) will update the internal list and RemoveMacros respectively.
728
729   AliEveListAnalyserMacroType type = kUnknown;
730
731   TString* typeStr = 0;
732   
733   if (objectType != 0) 
734   {
735     typeStr = new TString(objectType);
736     // Remove white-spaces
737     typeStr->ReplaceAll(" ", "");
738   }
739   else
740   {
741     typeStr = new TString("TObject");
742   }
743
744   TString* mangled1Str = new TString();
745   TString* mangled2Str = new TString();
746   TString* mangled3Str = new TString();
747   TString* mangled4Str = new TString();
748   TString* mangledArg1Str = new TString();
749   TString* mangledArg2Str = new TString();
750
751   // We want "const 'OBJECTTYPE'*"
752   mangled1Str->Append("const ").Append(*typeStr).Append("*");
753
754   // We want "const 'OBJECTTYPE'*, Double_t*&, Int_t&"
755   mangled2Str->Append("const ").Append(*typeStr).Append("*, Double_t*&, Int_t&");
756
757   // We want "const 'OBJECTTYPE'*, const 'OBJECTTYPE'*"
758   mangled3Str->Append("const ").Append(*typeStr).Append("*, const ").Append(*typeStr).Append("*");
759
760   // We want "const 'OBJECTTYPE'*, const 'OBJECTTYPE'*, Double_t*&, Int_t&"
761   mangled4Str->Append("const ").Append(*typeStr).Append("*, const ").Append(*typeStr).Append("*, Double_t*&, Int_t&");
762
763   // We want "oPconstsP'OBJECTTYPE'mUsP"
764   mangledArg1Str->Append("oPconstsP").Append(*typeStr).Append("mUsP");
765
766   // We want "cOconstsP'OBJECTTYPE'mUsP"
767   mangledArg2Str->Append("cOconstsP").Append(*typeStr).Append("mUsP");  
768   
769   // Re-do the check of the macro type
770   if (!UseList){
771     // Single object select macro or single object histo macro?
772     TFunction* f = gROOT->GetGlobalFunctionWithPrototype(name, mangled1Str->Data(), kTRUE);
773
774     if (f != 0x0)
775     {
776       // Some additional check (is the parameter EXACTLY of the desired type?)
777       if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0)
778       {
779         // Single object select macro?
780         if (!strcmp(f->GetReturnTypeName(), "Bool_t")) 
781         { 
782           type = kSingleObjectSelect;     
783         }
784         // single object histo macro?
785         else if (!strcmp(f->GetReturnTypeName(), "TH1*"))
786         {
787           type = kSingleObjectHisto;
788         }
789       }
790     }
791     // Single object analyse macro?
792     else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled2Str->Data(), kTRUE)) 
793              != 0x0)
794     {
795       if (!strcmp(f->GetReturnTypeName(), "void"))
796       {
797         // Some additional check (are the parameters EXACTLY of the desired type?)
798         if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 &&
799             strstr(f->GetMangledName(), "cODouble_tmUaNsP") != 0x0 &&
800             strstr(f->GetMangledName(), "cOInt_taNsP") != 0x0)
801         {
802           type = kSingleObjectAnalyse;
803         }
804       }
805     }    
806     // Correlated objects select macro or correlated objects histo macro?
807     else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled3Str->Data(), kTRUE)) 
808              != 0x0)
809     {
810       // Some additional check (is the parameter EXACTLY of the desired type?)
811       if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 &&
812           strstr(f->GetMangledName(), mangledArg2Str->Data()) != 0x0)
813       {
814         // Correlated objects select macro?
815         if (!strcmp(f->GetReturnTypeName(), "Bool_t")) 
816         { 
817           type = kCorrelObjectSelect;     
818         }
819         // Correlated objects histo macro?
820         else if (!strcmp(f->GetReturnTypeName(), "TH1*"))
821         {
822           type = kCorrelObjectHisto;
823         }
824       }
825     }    
826     // Correlated objects analyse macro?
827     else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled4Str->Data(), kTRUE)) 
828              != 0x0)
829     {
830       if (!strcmp(f->GetReturnTypeName(), "void"))
831       {
832         // Some additional check (is the parameter EXACTLY of the desired type?)
833         if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 &&
834             strstr(f->GetMangledName(), mangledArg2Str->Data()) != 0x0 &&
835             strstr(f->GetMangledName(), "cODouble_tmUaNsP") != 0x0 &&
836             strstr(f->GetMangledName(), "cOInt_taNsP") != 0x0)
837         {
838           type = kCorrelObjectAnalyse;
839         }
840       }
841     }    
842   }
843   // Use list to look up the macro type
844   else
845   {
846     TGeneralMacroData* macro = 0;
847     macro = (TGeneralMacroData*)fMacroList->GetValue(name);
848     if (macro == 0)  return kUnknown; 
849     
850     type = macro->GetType();
851     switch (type)
852     {
853       case kSingleObjectSelect:
854       case kSingleObjectAnalyse:
855       case kSingleObjectHisto:
856       case kCorrelObjectSelect:
857       case kCorrelObjectAnalyse:
858       case kCorrelObjectHisto:      
859         break;
860     default:
861       type = kUnknown;
862       break;
863     }
864   }
865
866   // Clean up
867   if (mangled1Str != 0)
868   {
869     mangled1Str->Clear();
870     delete mangled1Str;
871     mangled1Str = 0;
872   }
873   if (mangled2Str != 0)
874   {
875     mangled2Str->Clear();
876     delete mangled2Str;
877     mangled2Str = 0;
878   }
879   if (mangled3Str != 0)
880   {
881     mangled3Str->Clear();
882     delete mangled3Str;
883     mangled3Str = 0;
884   }
885   if (mangled4Str != 0)
886   {
887     mangled4Str->Clear();
888     delete mangled4Str;
889     mangled4Str = 0;
890   }
891   if (mangledArg1Str != 0)
892   {
893     mangledArg1Str->Clear();
894     delete mangledArg1Str;
895     mangledArg1Str = 0;
896   }
897   if (mangledArg2Str != 0)
898   {
899     mangledArg2Str->Clear();
900     delete mangledArg2Str;
901     mangledArg2Str = 0;
902   }
903   if (typeStr != 0)
904   {
905     typeStr->Clear();
906     delete typeStr;
907     typeStr = 0;
908   }
909
910
911   return type;
912 }
913
914 // TODO: IMPLEMENTATION + DOCUMENTATION
915 //______________________________________________________
916 TClass* AliEveListAnalyser::GetMacroObjectType(const Char_t* name) const
917 {
918   TFunction* f = gROOT->GetGlobalFunction(name, 0 , kTRUE);
919   TMethodArg* m = 0;
920   TList* list = 0;
921
922   if (f)
923   {
924     list = f->GetListOfMethodArgs();
925     
926     if (!list->IsEmpty())
927     {
928       m = (TMethodArg*)list->At(0);
929
930       if (m)  return TClass::GetClass(m->GetTypeName());
931     }
932   }  
933
934   // Error
935   return 0x0;
936 }
937
938 //______________________________________________________
939 void AliEveListAnalyser::RemoveSelectedMacros(const TList* iterator) 
940 {
941   // Uses the iterator (for the selected macros) to remove the selected macros from 
942   // the corresponding list.
943    
944   TObject* key = 0;
945   TPair*   entry = 0;
946   for (Int_t i = 0; i < iterator->GetEntries(); i++)
947   {
948     entry = (TPair*)fMacroList->FindObject(iterator->At(i)->GetTitle());
949
950     if (entry == 0)
951     {
952       Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Macro \"%s\" not found in list!", 
953                                                                      iterator->At(i)->GetTitle()));
954       continue;
955     }
956     key = entry->Key();
957
958     if (key == 0)   
959     {
960       Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Key for macro \"%s\" not found in list!", 
961                                                                      iterator->At(i)->GetTitle()));
962       continue;
963     }
964
965     // Key and value will be deleted, too, since fMacroList is the owner of them
966     Bool_t rem = fMacroList->DeleteEntry(key);
967
968     if (rem)
969     {
970 #ifdef AliEveListAnalyser_DEBUG
971     printf("AliEveListAnalyser::RemoveSelectedMacros(): Removed macro: %s\n", iterator->At(i)->GetTitle());
972 #endif
973     }
974     else
975     {
976       Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Macro \"%s\" could not be removed from the list!", 
977                                                                      iterator->At(i)->GetTitle()));
978     }
979   }
980 }