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