new class "List Analyser" by Ben Hess
authorabercuci <abercuci@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 27 Nov 2009 10:33:58 +0000 (10:33 +0000)
committerabercuci <abercuci@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 27 Nov 2009 10:33:58 +0000 (10:33 +0000)
The class manages a list of TEveElements derived objects and applies
 - selection on elements
 - analysis on elements
The selection/analysis code is provided by user at run time via
compilable macros. The class is a generalization of the TRD similar
class AliEveTRDTrackList used to display/analyse TRD tracks.

A first steering script is provided as alice-macros/ana_list.C
Example for user selection and analysis are provided in
PWG1/TRD/macros/EVE directory

EVE/EveDet/AliEveListAnalyser.cxx [new file with mode: 0644]
EVE/EveDet/AliEveListAnalyser.h [new file with mode: 0644]
EVE/EveDet/AliEveListAnalyserEditor.cxx [new file with mode: 0644]
EVE/EveDet/AliEveListAnalyserEditor.h [new file with mode: 0644]
EVE/EveDet/AliEveTRDTrackList.cxx
EVE/EveDet/AliEveTRDTrackListEditor.cxx
EVE/EveDet/AliEveTRDTrackListEditor.h
EVE/EveDet/EveDetLinkDef.h
EVE/binalieve.pkg

diff --git a/EVE/EveDet/AliEveListAnalyser.cxx b/EVE/EveDet/AliEveListAnalyser.cxx
new file mode 100644 (file)
index 0000000..2c73d94
--- /dev/null
@@ -0,0 +1,980 @@
+// Author: Benjamin Hess   06/11/2009
+
+/*************************************************************************
+ * Copyright (C) 2009, Alexandru Bercuci, Benjamin Hess.                 *
+ * All rights reserved.                                                  *
+ *************************************************************************/
+
+// TODO: Documentation
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// AliEveListAnalyser                                           //
+//                                                                      //
+// An AliEveListAnalyser is, in principal, a TEveElementList    //
+// with some sophisticated features. You can add macros to this list,   //
+// which then can be applied to the list of tracks (these tracks can be //
+// added to the list in the same way as for the TEveElementList).       //
+// In general, please use AddMacro(...) for this purpose.               //
+// Macros that are no longer needed can be removed from the list via    //
+// RemoveSelectedMacros(...).This function takes an iterator of the     //
+// list of macros that are to be removed.                               //
+// be removed. An entry looks like:                                     //
+// The data for each macro consists of path, name, type and the command //
+// that will be used to apply the macro. This stuff is stored in a map  //
+// which takes the macro name for the key and the above mentioned data  //
+// in a TGeneralMacroData-object for the value.                         //
+// You can get the macro type via GetMacroType(...).                    //
+// With ApplySTSelectionMacros(...) or ApplyProcessMacros(...)          //
+// respectively you can apply the macros to the track list via          //
+// iterators (same style like for RemoveSelectedMacros(...)(cf. above)).//
+// Selection macros (de-)select macros according to a selection rule    //
+// by setting the rnr-state of the tracks.                              //
+// If multiple selection macros are applied, a track is selected, if    //
+// all selection macros select the track.                               //
+// Process macros create data or histograms, which will be stored in    //
+// a temporary file. The editor of this class will access this file     //
+// and draw all the stuff within it's DrawHistos() function. The file   //
+// will be deleted by the destructor.                                   //
+//                                                                      //
+// Currently, the following macro types are supported:                  //
+// Selection macros:                                                    //
+// Bool_t YourMacro(const AliTRDtrackV1*);                              //
+// Bool_t YourMacro(const AliTRDtrackV1*, const AliTRDtrackV1*);        //
+//                                                                      //
+// Process macros:                                                      //
+// void YourMacro(const AliTRDtrackV1*, Double_t*&, Int_t&);            //
+// void YourMacro(const AliTRDtrackV1*, const AliTRDtrackV1*,           //
+//                Double_t*&, Int_t&);                                  //
+// TH1* YourMacro(const AliTRDtrackV1*);                                //
+// TH1* YourMacro(const AliTRDtrackV1*, const AliTRDtrackV1*);          //
+//                                                                      //
+// The macros which take 2 tracks are applied to all track pairs        //
+// (whereby BOTH tracks of the pair have to be selected by the single   //
+// track selection macros and have to be unequal, otherwise they will   //
+// be skipped) that have been selected by ALL correlated tracks         //
+// selection macros. The selection macros with 2 tracks do NOT affect   //
+// process macros that process only a single track!                     //
+//////////////////////////////////////////////////////////////////////////
+
+
+// Uncomment to display debugging infos
+//#define AliEveListAnalyser_DEBUG
+
+#include <TFile.h>
+#include <TFunction.h>
+#include <TMethodArg.h>
+#include <TH1.h>
+#include <TList.h>
+#include <TMap.h>
+#include <TObjString.h>
+#include <TROOT.h>
+#include <TSystem.h>
+#include <TTree.h>
+#include <TTreeStream.h>
+#include <TMethodCall.h>
+
+#include <AliTRDReconstructor.h>
+
+#include <EveDet/AliEveListAnalyser.h>
+#include <EveDet/AliEveListAnalyserEditor.h>
+
+// TODO: Are these files required?
+//#include <../PWG1/TRD/AliTRDrecoTask.h>
+//#include <../PWG1/TRD/macros/AliTRDperformanceTrain.h>
+
+ClassImp(AliEveListAnalyser)
+
+///////////////////////////////////////////////////////////
+/////////////   AliEveListAnalyser ////////////////
+///////////////////////////////////////////////////////////
+AliEveListAnalyser::AliEveListAnalyser(const Text_t* n, const Text_t* t, Bool_t doColor):
+  TEveElementList(n, t, doColor),
+  fEditor(0x0),
+  fDataFromMacroList(0x0),
+  fMacroList(0x0),
+  fDataTree(0x0),
+  fHistoDataSelected(0),
+  fMacroListSelected(0),
+  fSelectedTab(1)                               // Standard tab: "Apply macros" (index 1)
+
+
+// TODO: Old version with style tab
+/*
+  fSelectedTab(1),                              // Standard tab: "Apply macros" (index 1)
+  fSelectedStyle(0)
+*/
+
+{
+  // Creates the AliEveListAnalyser.
+
+  // Only accept childs of type TEveElement
+  SetChildClass(TEveElement::Class());
+
+  // Allocate memory for the lists and declare them as owners of their contents
+  fDataFromMacroList = new TList();
+  fDataFromMacroList->TCollection::SetOwner(kTRUE);
+
+  fMacroList = new TMap();
+  // Set map to owner of it's objects to delete them, if they are removed from the map
+  fMacroList->SetOwnerKeyValue(kTRUE, kTRUE);
+
+  // Set the build directory for AClic
+  if(gSystem->AccessPathName(Form("%s/.QArec" , gSystem->Getenv("HOME")))) gSystem->Exec("mkdir $HOME/.QArec");
+  gSystem->SetBuildDir(Form("%s/.QArec", gSystem->Getenv("HOME")));
+
+  AddStandardContent();
+}
+
+//______________________________________________________
+AliEveListAnalyser::~AliEveListAnalyser()
+{
+  // Frees allocated memory (lists etc.).
+
+  // Let the editor know that the list will be destroyed -> The editor will save the data
+  if (fEditor != 0)
+  {
+    fEditor->SaveMacroList(fMacroList);
+    fEditor = 0;
+  }
+
+  if (fDataFromMacroList != 0)
+  {
+    fDataFromMacroList->Delete();
+    delete fDataFromMacroList;
+    fDataFromMacroList = 0;
+  } 
+  if (fDataTree != 0)
+  {
+    delete fDataTree;
+    fDataTree = 0;
+  } 
+  if (fMacroList != 0)
+  {
+    fMacroList->DeleteAll();
+    delete fMacroList;
+    fMacroList = 0;
+  }
+  // Note: gSystem->AccessPathName(...) returns kTRUE, if the access FAILED!
+  if(!gSystem->AccessPathName(Form("/tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")))) 
+    gSystem->Exec(Form("rm /tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")));
+}
+
+//______________________________________________________
+Int_t AliEveListAnalyser::AddMacro(const Char_t* path, const Char_t* nameC, Bool_t forceReload)
+{
+  // Checks, if the file exists and if the signature is correct.
+  // If these criteria are fullfilled, the library for this macro is built
+  // and the macro is added to the corresponding list.
+  // Supported macro types:
+  // Selection macros:                                                    
+  // Bool_t YourMacro(const TObject*)
+  // Bool_t YourMacro(const TObject*, const TObject*)
+  //
+  // Process macros:                                                      
+  // void YourMacro(const TObject*, Double_t*&, Int_t&)             
+  // void YourMacro(const TObject*, const TObject*, Double_t*&, Int_t&)                                   
+  // TH1* YourMacro(const TObject*)                                 
+  // TH1* YourMacro(const TObject*, const TObject*)                              
+
+  Char_t pathname[fkMaxMacroPathNameLength];
+  memset(pathname, '\0', sizeof(Char_t) * fkMaxMacroPathNameLength);
+
+  // Expand the path and create the pathname
+  Char_t* systemPath = gSystem->ExpandPathName(path);
+  sprintf(pathname, "%s/%s", systemPath, nameC);
+  delete systemPath;
+  systemPath = 0;
+
+  // Delete ".C" from filename
+  Char_t name[fkMaxMacroNameLength];
+  memset(name, '\0', sizeof(Char_t) * fkMaxMacroNameLength);
+  
+  for (UInt_t ind = 0; ind < fkMaxMacroNameLength && ind < strlen(nameC) - 2; ind++)  name[ind] = nameC[ind];
+
+  // Check, if files exists
+  FILE* fp = 0x0;
+  if((fp = fopen(pathname, "rb"))){
+    fclose(fp);
+    fp = 0x0;
+  } else  return NOT_EXIST_ERROR;
+  
+  // Clean up root, load the desired macro and then check the type of the macro
+  // A.B. gROOT->Reset();
+  gROOT->ProcessLineSync(Form(".L %s+%c", pathname, forceReload ? '+' : ' '));
+
+  TClass* objectType;
+
+  objectType = GetMacroObjectType(name);
+
+  // We need this line... otherwise, in some cases, there will be problems concerning ACLIC
+  gROOT->ProcessLineSync(Form(".L %s", pathname));
+
+  if (!objectType)  return UNKNOWN_OBJECT_TYPE_ERROR;
+
+  AliEveListAnalyserMacroType type = GetMacroType(name, objectType->GetName(), kFALSE);
+
+  // Clean up again
+  // A.B. gROOT->Reset();
+  // Has not the correct signature!
+  if (type == kUnknown) return SIGNATURE_ERROR;
+
+  // Only add macro, if it is not already in the list
+  Int_t returnValue = WARNING;
+  if(fMacroList->GetValue(name) == 0) 
+  {
+    returnValue = AddMacroFast(path, name, type, objectType) ? SUCCESS : ERROR;
+  }
+
+  return returnValue;
+}
+
+//______________________________________________________
+Bool_t AliEveListAnalyser::AddMacroFast(const Char_t* path, const Char_t* name, AliEveListAnalyserMacroType type, TClass* objectType)
+{
+  // Adds a macro (path/name) to the corresponding list. No checks are performed (file exists, 
+  // macro already in list/map, signature correct),  no libraries are created!
+  // You can use this function only, if the macro has been added successfully before 
+  // (and then maybe was removed). The function is very fast. On success kTRUE is returned, otherwise: kFALSE;
+
+  Bool_t success = kFALSE;
+
+  switch (type)
+  {
+    case kSingleObjectSelect:
+    case kCorrelObjectSelect:
+    case kSingleObjectAnalyse:
+    case kSingleObjectHisto:
+    case kCorrelObjectAnalyse:
+    case kCorrelObjectHisto:
+      fMacroList->Add(new TObjString(name), new TGeneralMacroData(name, path, type, objectType));
+
+      // We do not know, where the element has been inserted - deselect this list
+      fMacroListSelected = 0;
+    
+      success = kTRUE;
+
+#ifdef AliEveListAnalyser_DEBUG
+      // Successfull add will only be displayed in debug mode
+      printf("AliEveListAnalyser::AddMacroFast: Added macro \"%s/%s\" with object type \"%s\" to the corresponding list\n", path, name,
+             objectType->GetName());
+#endif
+
+      break;
+
+    default:
+      // Error will always be displayed
+      printf("AliEveListAnalyser::AddMacroFast: ERROR: Could not add macro \"%s/%s\" with object type \"%s\" to the corresponding list\n", 
+             path, name, objectType->GetName());
+
+      success = kFALSE;
+
+      break;
+  }
+
+  return success;
+}
+
+//______________________________________________________
+void AliEveListAnalyser::AddStandardContent()
+{
+  // Adds standard macros to the macro list.
+
+  // Add your standard macros here, e.g.: 
+  // To add a macro use:
+  // AddMacro("$(ALICE_ROOT)/myFolder", "myMacroName.C");
+  // -> If the file does not exist, nothing happens. So if you want to handle this,
+  // use the return value of AddMacro (NOT_EXIST_ERROR is returned, if file does not exist)
+  // (-> You can also check for other return values (see AddMacro(...)))
+/*
+  const Char_t *libs[] = {"libANALYSIS.so", "libANALYSISalice.so", "libTENDER.so", "libPWG1.so"};
+  Int_t nlibs = static_cast<Int_t>(sizeof(libs)/sizeof(Char_t *));
+  for(Int_t ilib=0; ilib<nlibs; ilib++){
+    if(gSystem->Load(libs[ilib]) >= 0) continue;
+    AliError(Form("Fail loading %s.", libs[ilib]));
+    return;
+  }
+
+  AliTRDrecoTask *task = 0x0;
+  TList *fPlots = 0x0;
+  for(Int_t it=2; it<NTRDQATASKS; it++){
+    TClass c(fgkTRDtaskClassName[it]);
+    task = (AliTRDrecoTask*)c.New();
+    task->SetMCdata(kFALSE);
+    if(!(fPlots = task->GetPlotFunctors())){
+      //AliWarning(Form("No Plot functors defined for task \"%s\"", fgkTRDtaskClassName[it]));
+      delete task;
+      continue;
+    }
+    if(!(task->Histos())){
+      //AliWarning(Form("No Ref Histograms defined for task \"%s\"", fgkTRDtaskClassName[it]));
+      delete task;
+      continue;
+    }
+
+    // export task to CINT and add functions
+    gROOT->ProcessLine(Form("%s* %s = (%s*)0x%lx;", fgkTRDtaskClassName[it], task->GetName(), fgkTRDtaskClassName[it], (void*)task));
+    TIter iter(fPlots); TMethodCall *m = 0x0;
+    while((m = dynamic_cast<TMethodCall*>(iter()))){
+      AddMacroFast("", Form("%s->%s", task->GetName(), m->GetMethodName()), kSingleTrackHisto);
+    }
+  }
+*/
+}
+
+//______________________________________________________
+Bool_t AliEveListAnalyser::ApplyProcessMacros(const TList* selIterator, const TList* procIterator)
+{
+  // Uses the procIterator (for the selected process macros) to apply the selected macros to the data.
+  // Returns kTRUE on success, otherwise kFALSE. If there no process macros selected, kTRUE is returned 
+  // (this is no error!).
+  // The single object process macros are applied to all selected objects.
+  // The selIterator (for the selected selection macros) will be used to apply the correlated objects selection
+  // macros to all object pairs (whereby BOTH objects have to be selected, otherwise they will be skipped).
+  // All object pairs that have been selected by ALL correlated objects selection macros will be processed by
+  // the correlated objects process macros.
+
+  // No process macros need to be processed
+  if (procIterator->GetEntries() <= 0)  return kTRUE;
+
+  // Clear root
+  // A.B. gROOT->Reset();
+  
+  // Clear old data and re-allocate
+  if (fDataTree == 0x0){ 
+    TDirectory *cwd = gDirectory;
+    fDataTree = new TTreeSRedirector(Form("/tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")));
+    cwd->cd();
+  }
+  if (!fDataTree){
+    Error("Apply process macros", Form("File \"/tmp/ListAnalyserMacroData_%s.root\" could not be accessed properly!", 
+          gSystem->Getenv("USER")));
+    return kFALSE;
+  }
+  
+  if (fDataFromMacroList != 0) {
+    fDataFromMacroList->Delete();
+    delete fDataFromMacroList;
+  }
+  fDataFromMacroList = new TList();
+  fDataFromMacroList->TCollection::SetOwner(kTRUE);
+
+  fHistoDataSelected = 0;
+
+
+  TGeneralMacroData* macro = 0;
+
+  Char_t** procCmds = 0;
+  AliEveListAnalyserMacroType* mProcType = 0;
+  if (procIterator->GetEntries() > 0) {
+    procCmds = new Char_t*[procIterator->GetEntries()];
+    mProcType = new AliEveListAnalyserMacroType[procIterator->GetEntries()];
+  }
+
+  Char_t** selCmds  = 0;
+  AliEveListAnalyserMacroType* mSelType = 0;
+  if (selIterator->GetEntries() > 0) {
+    selCmds = new Char_t*[selIterator->GetEntries()];
+    mSelType = new AliEveListAnalyserMacroType[selIterator->GetEntries()];
+  }
+  
+  Bool_t selectedByCorrSelMacro = kFALSE;
+
+  AliEveListAnalyserMacroType macroType = kUnknown;
+  Int_t numHistoMacros = 0;
+  TH1** histos = 0;
+
+  TEveElement* object1 = 0;
+  TEveElement* object2 = 0;
+
+  // Collect the commands for each process macro and add them to "data-from-list"
+  for (Int_t i = 0; i < procIterator->GetEntries(); i++){
+    procCmds[i] = new Char_t[(fkMaxMacroPathNameLength + fkMaxApplyCommandLength)];
+    memset(procCmds[i], '\0', sizeof(Char_t) * (fkMaxMacroNameLength + fkMaxApplyCommandLength));
+
+    macro = (TGeneralMacroData*)fMacroList->GetValue(procIterator->At(i)->GetTitle());
+
+    if (!macro){
+      Error("Apply process macros", 
+        Form("Macro list is corrupted: Macro \"%s\" is not registered!", 
+        procIterator->At(i)->GetTitle()));
+      continue;
+    }
+
+#ifdef AliEveListAnalyser_DEBUG
+    printf("AliEveListAnalyser: Checking process macro: %s\n", macro->GetName());
+#endif 
+           
+    // Find the type of the process macro
+    macroType = macro->GetType();
+    if (macroType == kSingleObjectHisto || macroType == kCorrelObjectHisto){
+      mProcType[i] = macroType;
+      numHistoMacros++;
+      // Create the command 
+      sprintf(procCmds[i], macro->GetCmd());
+
+      // Add to "data-from-list" -> Mark as a histo macro with the substring "(histo macro)"
+      fDataFromMacroList->Add(new TObjString(Form("%s (histo macro)", macro->GetName())));
+    } else if (macroType == kSingleObjectAnalyse || macroType == kCorrelObjectAnalyse) {
+      mProcType[i] = macroType;
+      // Create the command 
+      sprintf(procCmds[i], macro->GetCmd());
+
+      // Add to "data-from-list"
+      fDataFromMacroList->Add(new TObjString(macro->GetName()));
+    } else {
+      Error("Apply process macros", 
+        Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a process macro!", 
+        macro->GetPath(), macro->GetName()));
+      mProcType[i] = kUnknown;
+    } 
+  }  
+
+  // Collect the commands for each selection macro and add them to "data-from-list"
+  for (Int_t i = 0; i < selIterator->GetEntries(); i++){
+    selCmds[i] = new Char_t[(fkMaxMacroPathNameLength + fkMaxApplyCommandLength)];
+    memset(selCmds[i], '\0', sizeof(Char_t) * (fkMaxMacroNameLength + fkMaxApplyCommandLength));
+
+    macro = (TGeneralMacroData*)fMacroList->GetValue(selIterator->At(i)->GetTitle());
+
+    if (!macro){
+      Error("Apply process macros", 
+        Form("Macro list is corrupted: Macro \"%s\" is not registered!", 
+        selIterator->At(i)->GetTitle()));
+      continue;
+    }
+
+#ifdef AliEveListAnalyser_DEBUG
+    printf("AliEveListAnalyser: Checking selection macro: %s\n", macro->GetName());
+#endif
+       
+    // Find the type of the process macro
+    macroType = macro->GetType();
+
+    // Single Object select macro
+    if (macroType == kSingleObjectSelect) {
+      // Has already been processed by ApplySTSelectionMacros(...)
+      mSelType[i] = macroType;         
+    }
+    // Correlated Objects select macro
+    else if (macroType == kCorrelObjectSelect) {
+      mSelType[i] = macroType;  
+      // Create the command
+      sprintf(selCmds[i], macro->GetCmd());
+    } else {
+      Error("Apply process macros", 
+        Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a selection macro!", 
+        macro->GetPath(), macro->GetName()));
+      mSelType[i] = kUnknown;
+    } 
+  }  
+
+  // Allocate memory for the histograms
+  if (numHistoMacros > 0)  histos = new TH1*[numHistoMacros];
+  for (Int_t i = 0; i < numHistoMacros; i++)  histos[i] = 0x0;
+
+
+  //////////////////////////////////
+  // WALK THROUGH THE LIST OF OBJECTS
+  //////////////////////////////////     
+  for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter){
+    if(!(object1 = dynamic_cast<TEveElement*>(*iter))) continue;
+
+    // Skip objects that have not been selected
+    if (!object1->GetRnrState())  continue;
+    
+    // Cast to the "real" object behind
+    gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object1));
+    gROOT->ProcessLineSync("TObject* automaticObject_1 = (TObject*)automaticEveElement->GetUserData();");
+
+    // Collect data for each macro
+    for (Int_t i = 0, histoIndex = 0; i < procIterator->GetEntries(); i++){
+      // Single object histo
+      if (mProcType[i] == kSingleObjectHisto){
+        histos[histoIndex++] = (TH1*)gROOT->ProcessLineSync(procCmds[i]);
+       // Correlated Objects histo
+      } else if (mProcType[i] == kCorrelObjectHisto) {
+        // Loop over all pairs behind the current one - together with the other loop this will be a loop
+        // over all pairs. We have a pair of objects, if and only if both objects of the pair are selected (Rnr-state)
+        // and are not equal.
+        // The correlated objects process macro will be applied to all pairs that will be additionally selected by
+        // all correlated objects selection macros.
+        TEveElement::List_i iter2 = iter;
+        iter2++;
+        for ( ; iter2 != this->EndChildren(); ++iter2)
+        {
+          if(!(object2 = dynamic_cast<TEveElement*>(*iter2))) continue;
+
+          // Skip objects that have not been selected
+          if (!object2->GetRnrState())  continue;
+      
+          // Cast to the "real" object behind
+          gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object2));
+          gROOT->ProcessLineSync("TObject* automaticObject_2 = (TObject*)automaticEveElement->GetUserData();");
+
+          // Select object by default (so it will be processed, if there are no correlated objects selection macros!)
+          selectedByCorrSelMacro = kTRUE;
+          for (Int_t j = 0; j < selIterator->GetEntries(); j++){
+            if (mSelType[j] == kCorrelObjectSelect){
+              selectedByCorrSelMacro = (Bool_t)gROOT->ProcessLineSync(selCmds[j]);
+              if (!selectedByCorrSelMacro)  break;
+            }
+          }       
+
+          // If the pair has not been selected by the correlated objects selection macros, skip it!
+          if (!selectedByCorrSelMacro) continue;
+          
+          histos[histoIndex] = (TH1*)gROOT->ProcessLineSync(procCmds[i]);
+        }
+        histoIndex++;
+      }
+      // Single object analyse
+      else if (mProcType[i] == kSingleObjectAnalyse) {
+        // Create data pointers in CINT, execute the macro and get the data
+        gROOT->ProcessLineSync("Double_t* results = 0;");
+        gROOT->ProcessLineSync("Int_t n = 0;");
+        gROOT->ProcessLineSync(procCmds[i]);
+        Double_t* results = (Double_t*)gROOT->ProcessLineSync("results;");
+        Int_t nResults = (Int_t)gROOT->ProcessLineSync("n;");
+        
+        if (results == 0) {
+          Error("Apply macros", Form("Error reading data from macro \"%s\"", procIterator->At(i)->GetTitle()));
+          continue;
+        }
+        for (Int_t resInd = 0; resInd < nResults; resInd++){
+          (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << results[resInd] << (Char_t*)"\n";   
+        }
+
+        delete results;
+        results = 0;
+      }
+      // Correlated objects analyse
+      else if (mProcType[i] == kCorrelObjectAnalyse){
+        // Loop over all pairs behind the current one - together with the other loop this will be a loop
+        // over all pairs. We have a pair of objects, if and only if both objects of the pair are selected (Rnr-state)
+        // and are not equal.
+        // The correlated objects process macro will be applied to all pairs that will be additionally selected by
+        // all correlated objects selection macros.
+        TEveElement::List_i iter2 = iter;
+        iter2++;
+
+        for ( ; iter2 != this->EndChildren(); ++iter2) {
+          if(!(object2 = dynamic_cast<TEveElement*>(*iter2))) continue;
+          // Skip objects that have not been selected
+          if (!object2->GetRnrState())  continue;
+    
+          // Cast to the "real" object behind
+          gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object2));
+          gROOT->ProcessLineSync("TObject* automaticObject_2 = (TObject*)automaticEveElement->GetUserData();");
+
+          // Select object by default (so it will be processed, if there are no correlated objects selection macros!)
+          selectedByCorrSelMacro = kTRUE;
+          for (Int_t j = 0; j < selIterator->GetEntries(); j++) {
+            if (mSelType[j] == kCorrelObjectSelect) {
+              selectedByCorrSelMacro = (Bool_t)gROOT->ProcessLineSync(selCmds[j]);
+              if (!selectedByCorrSelMacro)  break;
+            }
+          }       
+
+          // If the pair has not been selected by the correlated objects selection macros, skip it!
+          if (!selectedByCorrSelMacro) continue;
+          
+          // Create data pointers in CINT, execute the macro and get the data
+          gROOT->ProcessLineSync("Double_t* results = 0;");
+          gROOT->ProcessLineSync("Int_t n = 0;");
+          gROOT->ProcessLineSync(procCmds[i]);
+          Double_t* results = (Double_t*)gROOT->ProcessLineSync("results;");
+          Int_t nResults = (Int_t)gROOT->ProcessLineSync("n;");
+     
+          if (results == 0) {
+            Error("Apply macros", Form("Error reading data from macro \"%s\"", procIterator->At(i)->GetTitle()));
+            continue;
+          }
+          for (Int_t resInd = 0; resInd < nResults; resInd++) {
+            (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << results[resInd] << (Char_t*)"\n";   
+          }
+
+          delete results;
+          results = 0;
+        }
+      }
+    }
+  }    
+
+  for (Int_t i = 0, histoIndex = 0; i < procIterator->GetEntries() && histoIndex < numHistoMacros; i++) {
+    if (mProcType[i] == kSingleObjectHisto || mProcType[i] == kCorrelObjectHisto) {
+      // Might be empty (e.g. no objects have been selected)!
+      if (histos[histoIndex]) {
+        (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << histos[histoIndex] << (Char_t*)"\n";
+      }
+      histoIndex++;
+    }
+  }
+
+  if (fDataTree != 0) delete fDataTree;
+  fDataTree = 0;
+
+  if (procCmds != 0)  delete [] procCmds;
+  procCmds = 0;
+  if (mProcType != 0)  delete mProcType;
+  mProcType = 0;
+
+  if (selCmds != 0)  delete [] selCmds;
+  selCmds = 0;
+  if (mSelType != 0)  delete mSelType;
+  mSelType = 0;
+
+  if (histos != 0)  delete [] histos;
+  histos = 0;
+
+  // Clear root
+  // A.B. gROOT->Reset();
+  
+  // If there is data, select the first data set
+  if (procIterator->GetEntries() > 0) SETBIT(fHistoDataSelected, 0);
+
+  // Now the data is stored in "/tmp/ListAnalyserMacroData_$USER.root"
+  // The editor will access this file to display the data
+  return kTRUE;
+}
+
+//______________________________________________________
+void AliEveListAnalyser::ApplySTSelectionMacros(const TList* iterator)
+{
+  // Uses the iterator (for the selected selection macros) to apply the selected macros to the data.
+  // The rnr-states of the objects are set according to the result of the macro calls (kTRUE, if all
+  // macros return kTRUE for this object, otherwise: kFALSE).
+  // "ST" stands for "single object". This means that only single object selection macros are applied.
+  // Correlated objects selection macros will be used inside the call of ApplyProcessMacros(...)!
+
+  TGeneralMacroData* macro = 0;
+  AliEveListAnalyserMacroType macroType = kUnknown;
+  TEveElement* object1 = 0;
+  Bool_t selectedByMacro = kFALSE;
+
+  // Clear root
+  // A.B. gROOT->Reset();
+
+  // Select all objecs at first. A object is then deselected, if at least one selection macro
+  // returns kFALSE for this object.
+  // Enable all objects (Note: EnableListElements(..) will call "ElementChanged", which will cause unforeseen behaviour!)
+  for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter) ((TEveElement*)(*iter))->SetRnrState(kTRUE);
+  SetRnrState(kTRUE);
+  
+  for (Int_t i = 0; i < iterator->GetEntries(); i++){
+    macro = (TGeneralMacroData*)fMacroList->GetValue(iterator->At(i)->GetTitle());
+
+    if (!macro){
+      Error("Apply selection macros", 
+            Form("Macro list is corrupted: Macro \"%s\" is not registered!", iterator->At(i)->GetTitle()));
+      continue;
+    }
+
+#ifdef AliEveListAnalyser_DEBUG
+    printf("AliEveListAnalyser: Applying selection macro: %s\n", macro->GetName());
+#endif
+    
+    // Determine macro type
+    macroType = macro->GetType();
+
+    // Single object select macro
+    if (macroType == kSingleObjectSelect){
+      // Walk through the list of objects
+      for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter)
+      {
+        object1 = dynamic_cast<TEveElement*>(*iter);
+
+        if (!object1) continue;
+
+        // If the object has already been deselected, nothing is to do here
+        if (!object1->GetRnrState()) continue;
+
+        // Cast to the "real" object behind
+        gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object1));
+        gROOT->ProcessLineSync("TObject* automaticObject_1 = (TObject*)automaticEveElement->GetUserData();");
+
+        selectedByMacro = (Bool_t)gROOT->ProcessLineSync(macro->GetCmd());
+        object1->SetRnrState(selectedByMacro && object1->GetRnrState());               
+      }
+    }
+    // Correlated objects select macro
+    else if (macroType == kCorrelObjectSelect){
+      // Will be processed in ApplyProcessMacros(...)
+      continue;
+    } else {
+      Error("Apply selection macros", 
+        Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a selection macro!", 
+        macro->GetPath(), macro->GetName()));
+    } 
+  }
+
+  // Clear root
+  // A.B. gROOT->Reset();  
+}
+
+// TODO -> Type checking
+//______________________________________________________
+AliEveListAnalyser::AliEveListAnalyserMacroType AliEveListAnalyser::GetMacroType(const Char_t* name, const Char_t* objectType, Bool_t UseList) const
+{
+  // Returns the type of the corresponding macro, that accepts pointers of the class "objectType" as a parametre. 
+  // If "UseList" is kTRUE, the type will be looked up in the internal list (very fast). But if this list
+  // does not exist, you have to use kFALSE for this parameter. Then the type will be determined by the
+  // prototype! NOTE: It is assumed that the macro has been compiled! If not, the return value is not
+  // predictable, but normally will be kUnknown.
+  // Note: AddMacro(Fast) will update the internal list and RemoveMacros respectively.
+
+  AliEveListAnalyserMacroType type = kUnknown;
+
+  TString* typeStr = 0;
+  
+  if (objectType != 0) 
+  {
+    typeStr = new TString(objectType);
+    // Remove white-spaces
+    typeStr->ReplaceAll(" ", "");
+  }
+  else
+  {
+    typeStr = new TString("TObject");
+  }
+
+  TString* mangled1Str = new TString();
+  TString* mangled2Str = new TString();
+  TString* mangled3Str = new TString();
+  TString* mangled4Str = new TString();
+  TString* mangledArg1Str = new TString();
+  TString* mangledArg2Str = new TString();
+
+  // We want "const 'OBJECTTYPE'*"
+  mangled1Str->Append("const ").Append(*typeStr).Append("*");
+
+  // We want "const 'OBJECTTYPE'*, Double_t*&, Int_t&"
+  mangled2Str->Append("const ").Append(*typeStr).Append("*, Double_t*&, Int_t&");
+
+  // We want "const 'OBJECTTYPE'*, const 'OBJECTTYPE'*"
+  mangled3Str->Append("const ").Append(*typeStr).Append("*, const ").Append(*typeStr).Append("*");
+
+  // We want "const 'OBJECTTYPE'*, const 'OBJECTTYPE'*, Double_t*&, Int_t&"
+  mangled4Str->Append("const ").Append(*typeStr).Append("*, const ").Append(*typeStr).Append("*, Double_t*&, Int_t&");
+
+  // We want "oPconstsP'OBJECTTYPE'mUsP"
+  mangledArg1Str->Append("oPconstsP").Append(*typeStr).Append("mUsP");
+
+  // We want "cOconstsP'OBJECTTYPE'mUsP"
+  mangledArg2Str->Append("cOconstsP").Append(*typeStr).Append("mUsP");  
+  
+  // Re-do the check of the macro type
+  if (!UseList){
+    // Single object select macro or single object histo macro?
+    TFunction* f = gROOT->GetGlobalFunctionWithPrototype(name, mangled1Str->Data(), kTRUE);
+
+    if (f != 0x0)
+    {
+      // Some additional check (is the parameter EXACTLY of the desired type?)
+      if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0)
+      {
+        // Single object select macro?
+        if (!strcmp(f->GetReturnTypeName(), "Bool_t")) 
+        { 
+          type = kSingleObjectSelect;     
+        }
+        // single object histo macro?
+        else if (!strcmp(f->GetReturnTypeName(), "TH1*"))
+        {
+          type = kSingleObjectHisto;
+        }
+      }
+    }
+    // Single object analyse macro?
+    else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled2Str->Data(), kTRUE)) 
+             != 0x0)
+    {
+      if (!strcmp(f->GetReturnTypeName(), "void"))
+      {
+        // Some additional check (are the parameters EXACTLY of the desired type?)
+        if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 &&
+            strstr(f->GetMangledName(), "cODouble_tmUaNsP") != 0x0 &&
+            strstr(f->GetMangledName(), "cOInt_taNsP") != 0x0)
+        {
+          type = kSingleObjectAnalyse;
+        }
+      }
+    }    
+    // Correlated objects select macro or correlated objects histo macro?
+    else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled3Str->Data(), kTRUE)) 
+             != 0x0)
+    {
+      // Some additional check (is the parameter EXACTLY of the desired type?)
+      if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 &&
+          strstr(f->GetMangledName(), mangledArg2Str->Data()) != 0x0)
+      {
+        // Correlated objects select macro?
+        if (!strcmp(f->GetReturnTypeName(), "Bool_t")) 
+        { 
+          type = kCorrelObjectSelect;     
+        }
+        // Correlated objects histo macro?
+        else if (!strcmp(f->GetReturnTypeName(), "TH1*"))
+        {
+          type = kCorrelObjectHisto;
+        }
+      }
+    }    
+    // Correlated objects analyse macro?
+    else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled4Str->Data(), kTRUE)) 
+             != 0x0)
+    {
+      if (!strcmp(f->GetReturnTypeName(), "void"))
+      {
+        // Some additional check (is the parameter EXACTLY of the desired type?)
+        if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 &&
+            strstr(f->GetMangledName(), mangledArg2Str->Data()) != 0x0 &&
+            strstr(f->GetMangledName(), "cODouble_tmUaNsP") != 0x0 &&
+            strstr(f->GetMangledName(), "cOInt_taNsP") != 0x0)
+        {
+          type = kCorrelObjectAnalyse;
+        }
+      }
+    }    
+  }
+  // Use list to look up the macro type
+  else
+  {
+    TGeneralMacroData* macro = 0;
+    macro = (TGeneralMacroData*)fMacroList->GetValue(name);
+    if (macro == 0)  return kUnknown; 
+    
+    type = macro->GetType();
+    switch (type)
+    {
+      case kSingleObjectSelect:
+      case kSingleObjectAnalyse:
+      case kSingleObjectHisto:
+      case kCorrelObjectSelect:
+      case kCorrelObjectAnalyse:
+      case kCorrelObjectHisto:      
+        break;
+    default:
+      type = kUnknown;
+      break;
+    }
+  }
+
+  // Clean up
+  if (mangled1Str != 0)
+  {
+    mangled1Str->Clear();
+    delete mangled1Str;
+    mangled1Str = 0;
+  }
+  if (mangled2Str != 0)
+  {
+    mangled2Str->Clear();
+    delete mangled2Str;
+    mangled2Str = 0;
+  }
+  if (mangled3Str != 0)
+  {
+    mangled3Str->Clear();
+    delete mangled3Str;
+    mangled3Str = 0;
+  }
+  if (mangled4Str != 0)
+  {
+    mangled4Str->Clear();
+    delete mangled4Str;
+    mangled4Str = 0;
+  }
+  if (mangledArg1Str != 0)
+  {
+    mangledArg1Str->Clear();
+    delete mangledArg1Str;
+    mangledArg1Str = 0;
+  }
+  if (mangledArg2Str != 0)
+  {
+    mangledArg2Str->Clear();
+    delete mangledArg2Str;
+    mangledArg2Str = 0;
+  }
+  if (typeStr != 0)
+  {
+    typeStr->Clear();
+    delete typeStr;
+    typeStr = 0;
+  }
+
+
+  return type;
+}
+
+// TODO: IMPLEMENTATION + DOCUMENTATION
+//______________________________________________________
+TClass* AliEveListAnalyser::GetMacroObjectType(const Char_t* name) const
+{
+  TFunction* f = gROOT->GetGlobalFunction(name, 0 , kTRUE);
+  TMethodArg* m = 0;
+  TList* list = 0;
+
+  if (f)
+  {
+    list = f->GetListOfMethodArgs();
+    
+    if (!list->IsEmpty())
+    {
+      m = (TMethodArg*)list->At(0);
+
+      if (m)  return TClass::GetClass(m->GetTypeName());
+    }
+  }  
+
+  // Error
+  return 0x0;
+}
+
+//______________________________________________________
+void AliEveListAnalyser::RemoveSelectedMacros(const TList* iterator) 
+{
+  // Uses the iterator (for the selected macros) to remove the selected macros from 
+  // the corresponding list.
+   
+  TObject* key = 0;
+  TPair*   entry = 0;
+  for (Int_t i = 0; i < iterator->GetEntries(); i++)
+  {
+    entry = (TPair*)fMacroList->FindObject(iterator->At(i)->GetTitle());
+
+    if (entry == 0)
+    {
+      Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Macro \"%s\" not found in list!", 
+                                                                     iterator->At(i)->GetTitle()));
+      continue;
+    }
+    key = entry->Key();
+
+    if (key == 0)   
+    {
+      Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Key for macro \"%s\" not found in list!", 
+                                                                     iterator->At(i)->GetTitle()));
+      continue;
+    }
+
+    // Key and value will be deleted, too, since fMacroList is the owner of them
+    Bool_t rem = fMacroList->DeleteEntry(key);
+
+    if (rem)
+    {
+#ifdef AliEveListAnalyser_DEBUG
+    printf("AliEveListAnalyser::RemoveSelectedMacros(): Removed macro: %s\n", iterator->At(i)->GetTitle());
+#endif
+    }
+    else
+    {
+      Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Macro \"%s\" could not be removed from the list!", 
+                                                                     iterator->At(i)->GetTitle()));
+    }
+  }
+}
diff --git a/EVE/EveDet/AliEveListAnalyser.h b/EVE/EveDet/AliEveListAnalyser.h
new file mode 100644 (file)
index 0000000..1ce0282
--- /dev/null
@@ -0,0 +1,333 @@
+// Author: Benjamin Hess   06/11/2009
+
+/*************************************************************************
+ * Copyright (C) 2009, Alexandru Bercuci, Benjamin Hess.                 *
+ * All rights reserved.                                                  *
+ *************************************************************************/
+
+#ifndef AliEveListAnalyser_H
+#define AliEveListAnalyser_H
+
+// TODO: DOCUMENTATION
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// AliEveTRDTAnalyseObjectList                                          //
+//                                                                      //
+// An AliEveListAnalyser is, in principal, a TEveElementList    //
+// with some sophisticated features. You can add macros to this list,   //
+// which then can be applied to the list of tracks (these tracks can    //
+// be added to the list in the same way as for the TEveElementList).    //
+// In general, please use AddMacro(...) for this purpose.               //
+// Macros that are no longer needed can be removed from the list via    //
+// RemoveSelectedMacros(...).This function takes an iterator of the     //
+// list of macros that are to be removed.                               //
+// be removed. An entry looks like:                                     //
+// The data for each macro consists of path, name, type and the command //
+// that will be used to apply the macro. This stuff is stored in a map  //
+// which takes the macro name for the key and the above mentioned data  //
+// in a TGeneralMacroData-object for the value.                         //
+// You can get the macro type via GetMacroType(...).                    //
+// With ApplySTSelectionMacros(...) or ApplyProcessMacros(...)          //
+// respectively you can apply the macros to the track list via          //
+// iterators (same style like for RemoveSelectedMacros(...)(cf. above)).//
+// Selection macros (de-)select macros according to a selection rule    //
+// by setting the rnr-state of the tracks.                              //
+// If multiple selection macros are applied, a track is selected, if    //
+// all selection macros select the track.                               //
+// Process macros create data or histograms, which will be stored in    //
+// a temporary file. The editor of this class will access this file     //
+// and draw all the stuff within it's DrawHistos() function. The file   //
+// will be deleted by the destructor.                                   //
+//                                                                      //
+// Currently, the following macro types are supported:                  //
+// Selection macros:                                                    //
+// Bool_t YourMacro(const AliTRDtrackV1*);                              //
+// Bool_t YourMacro(const AliTRDtrackV1*, const AliTRDtrackV1*);        //
+//                                                                      //
+// Process macros:                                                      //
+// void YourMacro(const AliTRDtrackV1*, Double_t*&, Int_t&);            //
+// void YourMacro(const AliTRDtrackV1*, const AliTRDtrackV1*,           //
+//                Double_t*&, Int_t&);                                  //
+// TH1* YourMacro(const AliTRDtrackV1*);                                //
+// TH1* YourMacro(const AliTRDtrackV1*, const AliTRDtrackV1*);          //
+//                                                                      //
+// The macros which take 2 tracks are applied to all track pairs        //
+// (whereby BOTH tracks of the pair have to be selected by the single   //
+// track selection macros and have to be unequal, otherwise they will   //
+// be skipped) that have been selected by ALL correlated tracks         //
+// selection macros. The selection macros with 2 tracks do NOT affect   //
+// process macros that process only a single track!                     //
+//////////////////////////////////////////////////////////////////////////
+
+
+#include <TEveElement.h>
+#include <EveDet/AliEveTRDData.h>
+
+#define SIGNATURE_ERROR           -1
+#define NOT_EXIST_ERROR           -2
+#define ERROR                     -3
+#define UNKNOWN_OBJECT_TYPE_ERROR -4
+#define WARNING                   0
+#define SUCCESS                   1
+
+#define MAX_MACRO_NAME_LENGTH     100
+#define MAX_MACRO_PATH_LENGTH     300
+#define MAX_APPLY_COMMAND_LENGTH  120
+
+#define UNSETBIT(n,i)  ((n) &= ~BIT(i))
+
+//class AliEveTRDTrack;
+class AliEveListAnalyserEditor;
+class AliTRDReconstructor;
+class TClass;
+class TFile;
+class TFunction;
+class TH1;
+class TObjString;
+class TList;
+class TMap;
+class TPair;
+class TString;
+class TTreeSRedirector;
+
+class AliEveListAnalyser: public TEveElementList
+{
+  friend class AliEveListAnalyserEditor;
+
+public:
+  
+  enum
+  {
+    // Maximum length (number of characters) for a macro name:
+    fkMaxMacroNameLength = MAX_MACRO_NAME_LENGTH,    
+    // Maximum length (number of characters) for a macro path:
+    fkMaxMacroPathLength = MAX_MACRO_PATH_LENGTH,    
+    // Maximum length (number of characters) for a macro pathname:
+    fkMaxMacroPathNameLength = MAX_MACRO_NAME_LENGTH + MAX_MACRO_PATH_LENGTH,  
+    // Maximum length (number of characters) for "apply macro" commands in addition to the length of the name, path... 
+    fkMaxApplyCommandLength = MAX_APPLY_COMMAND_LENGTH  
+  };
+
+  // Macro types
+  enum AliEveListAnalyserMacroType
+  {
+    kUnknown = 0,
+    kSingleObjectSelect = 1,
+    kSingleObjectAnalyse = 2,
+    kSingleObjectHisto = 3,
+    kCorrelObjectSelect = 4,
+    kCorrelObjectAnalyse = 5,
+    kCorrelObjectHisto = 6
+  };
+  
+
+  AliEveListAnalyser(const Text_t* n = "AliEveListAnalyser", const Text_t* t = "", Bool_t doColor = kFALSE);
+  virtual ~AliEveListAnalyser();
+
+  Int_t AddMacro(const Char_t* path, const Char_t* name, Bool_t forceReload = kFALSE);                      
+  Bool_t AddMacroFast(const Char_t* path, const Char_t* name, AliEveListAnalyserMacroType type, TClass* objectType);        
+  virtual void AddStandardContent();                           
+  Bool_t ApplyProcessMacros(const TList* selIterator, const TList* procIterator);               
+  void ApplySTSelectionMacros(const TList* iterator);
+
+  // Returns the type of the macro of the corresponding entry (i.e. "macro.C (Path: path)"). 
+  // If you have only the name and the path, you can simply use MakeMacroEntry.
+  // If "UseList" is kTRUE, the type will be looked up in the internal list (very fast). But if this list
+  // does not exist, you have to use kFALSE for this parameter. Then the type will be determined by the
+  // prototype! NOTE: It is assumed that the macro has been compiled! If not, the return value is not
+  // predictable, but normally will be kUnknown.
+  // "objectType" gives the class/"type of object" of the pointer(s), the macro accepts as a parametre.
+  // Note: AddMacro(Fast) will update the internal list and RemoveProcess(/Selection)Macros respectively.
+  AliEveListAnalyserMacroType GetMacroType(const Char_t* name, const Char_t* objectType = "TObject", Bool_t UseList = kTRUE) const; 
+  
+  // TODO Documentation
+  TClass* GetMacroObjectType(const Char_t* name) const;
+  void RemoveSelectedMacros(const TList* iterator);                                    
+
+protected:
+  AliEveListAnalyserEditor* fEditor; // Pointer to the editor of this list             
+
+  TList* fDataFromMacroList;         // List of macros that currently have data for histograms
+
+  TMap*  fMacroList;                 // Stores the names, paths, types and commands of all macros added to this list
+
+  TTreeSRedirector *fDataTree;       // Tree containing data for histograms
+
+  Int_t fHistoDataSelected;          // Stores the selection for the data of the histograms
+  Int_t fMacroListSelected;          // Stores the selection of the macro list
+
+  Char_t fSelectedTab;               // Holds the index of the selected tab
+//  UChar_t fSelectedStyle;            // Holds the selected track style
+
+  Char_t GetSelectedTab() const                          // Gets the selected tab
+    { return fSelectedTab;  }
+
+//  UChar_t GetSelectedTrackStyle() const                  // Gets the selected track style
+//    { return fSelectedStyle;  }
+
+  Bool_t HistoDataIsSelected(Int_t index) const          // Is entry in list selected?
+    { return TESTBIT(fHistoDataSelected, index);  }  
+   
+  Bool_t MacroListIsSelected(Int_t index) const          // Is entry in list selected?
+    { return TESTBIT(fMacroListSelected, index);  }     
+
+  void SetHistoDataSelection(Int_t index, Bool_t set)       // Set selection of entry in list
+    { if (set) SETBIT(fHistoDataSelected, index); else UNSETBIT(fHistoDataSelected, index);  }  
+
+  void SetMacroListSelection(Int_t index, Bool_t set)       // Set selection of entry in list
+    { if (set) SETBIT(fMacroListSelected, index); else UNSETBIT(fMacroListSelected, index);  }  
+    
+  void SetSelectedTab(Int_t index)                          // Sets the selected tab
+    { fSelectedTab = (Char_t)index; }  
+
+//  void SetSelectedTrackStyle(UChar_t index)                 // Sets the selected track style
+//    { fSelectedStyle = index;  }
+
+//  void UpdateTrackStyle(AliEveTRDTrack::AliEveTRDTrackState s, UChar_t ss = 0);      
+
+private:
+  AliEveListAnalyser(const AliEveListAnalyser&);            // Not implemented
+  AliEveListAnalyser& operator=(const AliEveListAnalyser&); // Not implemented             
+
+  ClassDef(AliEveListAnalyser, 0);  // Class containing a list of analyse objects
+};
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// TGeneralMacroData                                                    //
+//                                                                      //
+// Stores macro data which will be used by AliEveListAnalyser.          //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+class TGeneralMacroData: public TObject
+{
+public:
+  TGeneralMacroData(const Char_t* name, const Char_t* path,                                                        // Constructor
+             AliEveListAnalyser::AliEveListAnalyserMacroType type = AliEveListAnalyser::kUnknown,
+             TClass* objectType = TObject::Class()):
+    TObject(),
+    fObjectType(0x0),
+    fIsSelected(kFALSE),
+    fType(AliEveListAnalyser::kUnknown)
+    
+  {
+    // The command is automatically set via type.
+
+    SetName(name);
+    SetObjectType(objectType);
+    SetPath(path);
+    SetType(type);
+
+    // Register the commands for each type here
+    switch (type)
+    {
+      case AliEveListAnalyser::kSingleObjectSelect:
+      case AliEveListAnalyser::kSingleObjectHisto:
+        SetCmd(Form("%s(automaticObject_1);", name));
+        break;
+
+      case AliEveListAnalyser::kSingleObjectAnalyse:
+        SetCmd(Form("%s(automaticObject_1, results, n);", name));
+        break;
+
+      case AliEveListAnalyser::kCorrelObjectSelect:
+      case AliEveListAnalyser::kCorrelObjectHisto:
+        SetCmd(Form("%s(automaticObject_1, automaticObject_2);", name));
+        break;
+
+      case AliEveListAnalyser::kCorrelObjectAnalyse:
+        SetCmd(Form("%s(automaticObject_1, automaticObject_2, results, n);", name));
+        break;
+
+      default:
+        SetCmd("");
+        break;
+    }
+  }
+
+  const Char_t* GetCmd() const                // Returns the command that will be used to call this macro
+    { return fCmd;  }
+  const Char_t* GetName() const               // Returns the macro name (without ".C")
+    { return fName;  }
+  TClass* GetObjectType() const               // Returns the object type of the macro parameter
+    { return fObjectType;  }
+  const Char_t* GetPath() const               // Returns the path of the macro
+    { return fPath;  }
+  AliEveListAnalyser::AliEveListAnalyserMacroType GetType() const   // Returns the type of the macro
+    { return fType;  }
+  Bool_t IsProcessMacro() const             // Returns whether the macro is a process type macro or not
+  {
+    switch (fType)
+    {
+      case AliEveListAnalyser::kSingleObjectAnalyse:
+      case AliEveListAnalyser::kSingleObjectHisto:
+      case AliEveListAnalyser::kCorrelObjectAnalyse:
+      case AliEveListAnalyser::kCorrelObjectHisto:
+        return kTRUE;
+        break;
+      default:
+        break;
+    }
+    
+    return kFALSE;
+  }
+
+  Bool_t IsSelected() const                   // Returns whether the macro is selected or not
+    { return fIsSelected; }
+  Bool_t IsSelectionMacro() const             // Returns whether the macro is a selection type macro or not
+  {
+    switch (fType)
+    {
+      case AliEveListAnalyser::kSingleObjectSelect:
+      case AliEveListAnalyser::kCorrelObjectSelect:
+        return kTRUE;
+        break;
+      default:
+        break;
+    }
+    
+    return kFALSE;
+  }
+
+  void SetCmd(const char* newCmd)             // Sets the command that will be used to call this macro
+  { 
+    memset(fCmd, '\0', sizeof(Char_t) * MAX_APPLY_COMMAND_LENGTH);
+    sprintf(fCmd, "%s", newCmd);
+  }
+  void SetName(const char* newName)           // Sets the macro name (please use without ".C")
+  { 
+    memset(fName, '\0', sizeof(Char_t) * MAX_MACRO_NAME_LENGTH);
+    sprintf(fName, "%s", newName);
+  }
+  void SetObjectType(TClass* newObjectType)     // Sets the object type of the macro parameter
+  { 
+    fObjectType = newObjectType;
+  }
+  void SetPath(const char* newPath)           // Sets the path of the macro
+  { 
+    memset(fPath, '\0', sizeof(Char_t) * MAX_MACRO_PATH_LENGTH);
+    sprintf(fPath, "%s", newPath);
+  }
+  void SetSelected(Bool_t selection)          // Sets whether the macro is selected or not
+  {
+    fIsSelected = selection;
+  }
+  void SetType(AliEveListAnalyser::AliEveListAnalyserMacroType newType)  // Sets the type of the macro
+  {
+    fType = newType;
+  }
+
+private:
+  TGeneralMacroData(const TGeneralMacroData&);            // Not implemented
+  TGeneralMacroData& operator=(const TGeneralMacroData&); // Not implemented 
+
+  Char_t fCmd[MAX_APPLY_COMMAND_LENGTH];                  // Command that will be used to call this macro
+  Char_t fName[MAX_MACRO_NAME_LENGTH];                    // Macro name (without ".C"!)
+  TClass* fObjectType;                                    // Type of object of the macro parameter
+  Char_t fPath[MAX_MACRO_PATH_LENGTH];                    // Path of the macro
+  Bool_t fIsSelected;                                     // Is macro selected (e.g. in the editor's list)?
+  AliEveListAnalyser::AliEveListAnalyserMacroType fType;  // Type of the macro  
+};
+
+#endif
diff --git a/EVE/EveDet/AliEveListAnalyserEditor.cxx b/EVE/EveDet/AliEveListAnalyserEditor.cxx
new file mode 100644 (file)
index 0000000..f83599b
--- /dev/null
@@ -0,0 +1,1550 @@
+// Author: Benjamin Hess   06/11/2009
+
+/*************************************************************************
+ * Copyright (C) 2009, Alexandru Bercuci, Benjamin Hess.                 *
+ * All rights reserved.                                                  *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// AliEveListAnalyserEditor                                     //
+//                                                                      //
+// The AliEveListAnalyserEditor provides the graphical          //
+// functionality for the AliEveTRDAnalyseObject. It creates the tabs    //
+// and canvases, when they are needed and, as well, frees allocated     //
+// memory on destruction (or if new events are loaded and thus some     //
+// tabs are closed). The function DrawHistos() accesses the temporary   //
+// file created by the AliEveListAnalyser and draws the desired //
+// data (the file will be created within the call of ApplyMacros()).    //
+// Have a look at this function to learn more about the structure of    //
+// the file and how to access the data.                                 //
+//////////////////////////////////////////////////////////////////////////
+
+#include <EveDet/AliEveTRDData.h>
+#include <EveDet/AliEveListAnalyser.h>
+#include "AliEveListAnalyserEditor.h"
+
+#include <EveBase/AliEveEventManager.h>
+#include <AliTRDReconstructor.h>
+//#include <AliTRDtrackV1.h>
+#include <TCanvas.h>     
+#include <TEveBrowser.h>
+#include <TEveGedEditor.h> 
+#include <TEveMacro.h>
+#include <TEveManager.h>
+#include <TFile.h>
+#include <TG3DLine.h>
+#include <TGButton.h>
+#include <TGButtonGroup.h>
+#include <TGFileDialog.h>
+#include <TGLabel.h>
+#include <TGListBox.h>
+#include <TGMsgBox.h>
+#include <TGTab.h>
+#include <TMap.h>
+#include <TObjString.h>
+#include <TROOT.h>
+#include <TString.h>
+#include <TSystem.h>
+#include <TGTextEntry.h>
+#include <TGTextEdit.h>
+#include <TGComboBox.h>
+#include <TGTextView.h>
+#include <TH1.h>
+#include <TTreeStream.h>
+
+
+ClassImp(AliEveListAnalyserEditor)
+
+///////////////////////////////////////////////////////////
+/////////////   AliEveListAnalyserEditor //////////
+///////////////////////////////////////////////////////////
+AliEveListAnalyserEditor::AliEveListAnalyserEditor(const TGWindow* p, Int_t width, Int_t height,
+                                                  UInt_t options, Pixel_t back) :
+  TGedFrame(p, width, height, options, back),
+  fM(0),
+  fHistoCanvas(0),
+  fHistoCanvasName(0),
+  fInheritedMacroList(0),
+  fInheritSettings(kFALSE),
+//  fStyleFrame(0),
+  fMainFrame(0),
+  fHistoFrame(0),
+  fHistoSubFrame(0),
+  fBrowseFrame(0),
+//  fbgStyleColor(0),
+//  fbgStyleTrack(0),
+//  frbColor(new TGRadioButton*[3]),
+//  frbTrack(new TGRadioButton*[3]),
+  fbBrowse(0),
+  fbNew(0),
+  fbApplyMacros(0),
+  fbRemoveMacros(0),
+  fbDrawHisto(0),
+  fteField(0),
+  ftlMacroList(0),
+  ftlMacroSelList(0),
+  fFileInfo(0),
+  fFileTypes(0),
+  fLabel1(0), fLabel2(0), fLabel3(0), fLabel4(0),
+  fLine1(0), fLine2(0), fLine3(0), fLine4(0),
+// fLine5(0),
+  fCheckButtons(0)
+{
+  // Creates the AliEveListAnalyserEditor.
+
+/*
+  // Style stuff
+  fLine5 = new TGHorizontal3DLine(this, 194, 8);
+  AddFrame(fLine5, new TGLayoutHints(kLHintsLeft  | kLHintsTop, 2, 2, 8, 8));
+  fStyleFrame = new TGHorizontalFrame(this);
+  AddFrame(fStyleFrame);
+
+  // Style - Track model
+  fbgStyleTrack = new TGButtonGroup(fStyleFrame, "Track model");
+  fbgStyleTrack->SetMapSubwindows(kTRUE);
+  fbgStyleTrack->Resize(194, 200);
+  fStyleFrame->AddFrame(fbgStyleTrack);
+
+  frbTrack[0] = new TGRadioButton(fbgStyleTrack, "Rieman", 0);
+  frbTrack[0]->SetToolTipText("Set the track model to \"Rieman\" (i.e. the used fit method)");
+  fbgStyleTrack->AddFrame(frbTrack[0]);
+  frbTrack[1] = new TGRadioButton(fbgStyleTrack, "Kalman", 1);
+  frbTrack[1]->SetToolTipText("Set the track model to \"Kalman\" (i.e. the used fit method)");
+  fbgStyleTrack->AddFrame(frbTrack[1]);
+  frbTrack[2] = new TGRadioButton(fbgStyleTrack, "Line", 2);
+  frbTrack[2]->SetToolTipText("Set the track model to \"Line\" (i.e. the used fit method)");
+  fbgStyleTrack->AddFrame(frbTrack[2]);  
+
+  // Style - Color model
+  fbgStyleColor = new TGButtonGroup(fStyleFrame, "Color model");
+  fbgStyleColor->SetMapSubwindows(kTRUE);
+  fbgStyleColor->Resize(194, 200);
+  fStyleFrame->AddFrame(fbgStyleColor);
+
+  frbColor[0] = new TGRadioButton(fbgStyleColor, "PID LQ", 0);
+  frbColor[0]->SetToolTipText("Set color model to \"PID LQ\" -> 2 dimensional likelihood particle identification");
+  fbgStyleColor->AddFrame(frbColor[0]);
+  frbColor[1] = new TGRadioButton(fbgStyleColor, "PID NN", 1);
+  frbColor[1]->SetToolTipText("Set color model to \"PID NN\" -> Neural network particle identification");
+  fbgStyleColor->AddFrame(frbColor[1]);
+  frbColor[2] = new TGRadioButton(fbgStyleColor, "ESD Source", 2);
+  frbColor[2]->SetToolTipText("Set color model to \"ESD Source\" -> By source (TPC track prolongation or TRD stand alone)");
+  fbgStyleColor->AddFrame(frbColor[2]);  
+*/  
+
+  // Functionality for adding macros  
+  fMainFrame = CreateEditorTabSubFrame("Process");
+   
+  fLabel1 = new TGLabel(fMainFrame,"Add macro(s):");
+  fMainFrame->AddFrame(fLabel1);
+  fBrowseFrame = new TGHorizontalFrame(fMainFrame);
+
+  fteField = new TGTextEntry(fBrowseFrame);
+  fteField->SetToolTipText("Enter the pathname of the macro you want to add here and press \"Enter\"");
+  fteField->Connect("ReturnPressed()","AliEveListAnalyserEditor", this, "HandleMacroPathSet()"); 
+  fBrowseFrame->AddFrame(fteField);
+  
+  fbBrowse = new TGTextButton(fBrowseFrame, "Browse");
+  fbBrowse->SetToolTipText("Browse the macro you want to add");
+  fbBrowse->Connect("Clicked()", "AliEveListAnalyserEditor", this, "BrowseMacros()");
+  fBrowseFrame->AddFrame(fbBrowse);
+  
+  fbNew = new TGTextButton(fBrowseFrame, "New");
+  fbNew->SetToolTipText("Start macro creation wizard");
+  fbNew->Connect("Clicked()", "AliEveListAnalyserEditor", this, "NewMacros()");
+  fBrowseFrame->AddFrame(fbNew);
+  fMainFrame->AddFrame(fBrowseFrame);
+
+  fLine1 = new TGHorizontal3DLine(fMainFrame, 194, 8);
+  fMainFrame->AddFrame(fLine1, new TGLayoutHints(kLHintsLeft  | kLHintsTop, 2, 2, 8, 2));
+  fLabel2 = new TGLabel(fMainFrame,"Selection macros:");
+  fMainFrame->AddFrame(fLabel2);
+
+  ftlMacroSelList = new TGListBox(fMainFrame);
+  ftlMacroSelList->Resize(194, 94);
+  ftlMacroSelList->SetMultipleSelections(kTRUE);
+  fMainFrame->AddFrame(ftlMacroSelList);
+
+  fLine2 = new TGHorizontal3DLine(fMainFrame, 194, 8);
+  fMainFrame->AddFrame(fLine2, new TGLayoutHints(kLHintsLeft  | kLHintsTop, 2, 2, 8, 2));
+  fLabel3 = new TGLabel(fMainFrame,"Process plugins:");
+  fMainFrame->AddFrame(fLabel3);
+
+  ftlMacroList = new TGListBox(fMainFrame);
+  ftlMacroList->Resize(194, 94);
+  ftlMacroList->SetMultipleSelections(kTRUE);
+  fMainFrame->AddFrame(ftlMacroList);
+
+  fLine3 = new TGHorizontal3DLine(fMainFrame, 194, 8);
+  fMainFrame->AddFrame(fLine3, new TGLayoutHints(kLHintsLeft  | kLHintsTop, 2, 2, 8, 2));  
+
+  fbApplyMacros = new TGTextButton(fMainFrame, "Apply plugin(s)");
+  fbApplyMacros->SetToolTipText("Apply all selected macros/class functins to the list of objects -> A data file will be generated");
+  fbApplyMacros->Connect("Clicked()", "AliEveListAnalyserEditor", this, "ApplyMacros()");
+  fbApplyMacros->SetRightMargin(12);
+  fMainFrame->AddFrame(fbApplyMacros);
+
+  fbRemoveMacros = new TGTextButton(fMainFrame, "Remove plugin(s)");
+  fbRemoveMacros->SetToolTipText("Remove the selected macros/class functions from the list(s)");
+  fbRemoveMacros->Connect("Clicked()", "AliEveListAnalyserEditor", this, "RemoveMacros()");
+  fMainFrame->AddFrame(fbRemoveMacros);
+
+  // Stuff for displaying histograms
+  fHistoFrame = CreateEditorTabSubFrame("Results");  
+  fHistoFrame->SetMapSubwindows(kTRUE);
+  fLabel4 = new TGLabel(fHistoFrame,"Data from plugins:");
+  fHistoFrame->AddFrame(fLabel4);
+
+  fHistoSubFrame = new TGVerticalFrame(fHistoFrame);
+  fHistoSubFrame->SetMapSubwindows(kTRUE);
+  fHistoSubFrame->Resize(194, 200);
+  fHistoFrame->AddFrame(fHistoSubFrame);
+
+  fLine4 = new TGHorizontal3DLine(fHistoFrame, 194, 8);
+  fHistoFrame->AddFrame(fLine4, new TGLayoutHints(kLHintsLeft  | kLHintsTop, 2, 2, 8, 2));  
+
+  fbDrawHisto = new TGTextButton(fHistoFrame, "Draw projections");
+  fbDrawHisto->SetToolTipText("Uses the data file created by the last \"Apply selected macro(s)\".\nClick here to display the data histograms of the selected macros.\nSelect multiple macros to create multi-dimensional plots.\nHisto macros cannot be used for multi-dimensional plots!");
+  fbDrawHisto->Connect("Clicked()", "AliEveListAnalyserEditor", this, "DrawHistos()");
+  fHistoFrame->AddFrame(fbDrawHisto);
+
+  // Set up file dialog
+  fFileInfo = new TGFileInfo();
+  fFileInfo->SetMultipleSelection(kTRUE);
+
+  fFileTypes = new Char_t*[6];
+  fFileTypes[0] = (Char_t*)"All files"; fFileTypes[1] = (Char_t*)"*";
+  fFileTypes[2] = (Char_t*)"ROOT macros"; fFileTypes[3] = (Char_t*)"*.C";
+  fFileTypes[4] = 0; fFileTypes[5] = 0;
+  fFileInfo->fFileTypes = (const Char_t**)fFileTypes;
+  fFileInfo->fFileTypeIdx = 2;
+  fFileInfo->fMultipleSelection = kTRUE;
+
+  fHistoCanvasName = new TGString("");
+
+/*
+  // Handle style changed signals:
+  fbgStyleTrack->Connect("Clicked(Int_t)", "AliEveListAnalyserEditor", this, "SetTrackModel(Int_t)");
+  fbgStyleColor->Connect("Clicked(Int_t)", "AliEveListAnalyserEditor", this, "SetTrackColor(Int_t)");
+*/
+
+  // Handle the signal "Selected(Int_t ind)"
+  ftlMacroList->Connect("Selected(Int_t)", "AliEveListAnalyserEditor", this, "UpdateMacroListSelection(Int_t)");
+  ftlMacroSelList->Connect("Selected(Int_t)", "AliEveListAnalyserEditor", this, "UpdateMacroListSelection(Int_t)");
+
+  // Handle the signal "NewEventLoaded"
+  AliEveEventManager::GetMaster()->Connect("NewEventLoaded()", "AliEveListAnalyserEditor", this, "HandleNewEventLoaded()");
+
+  // Handle the signal "Selected" (another tab has been selected)
+  GetGedEditor()->GetTab()->Connect("Selected(Int_t)", "AliEveListAnalyserEditor", this, "HandleTabChangedToIndex(Int_t)");
+}
+
+//______________________________________________________
+AliEveListAnalyserEditor::~AliEveListAnalyserEditor()
+{
+  // Destructor: Closes all tabs created by this object and
+  // frees the corresponding memory.
+
+  if (fFileTypes != 0)
+  {
+    delete [] fFileTypes;
+    fFileTypes = 0;
+  }
+
+  if (fFileInfo != 0)
+  {
+    delete fFileInfo; 
+    fFileInfo = 0;
+  }
+  // Close and delete all tabs that have been created by this class
+  CloseTabs();
+
+  if (fHistoCanvasName != 0)
+  {
+    delete fHistoCanvasName;
+    fHistoCanvasName = 0;
+  }
+  if (fInheritedMacroList != 0)
+  {
+    fInheritedMacroList->Delete();
+    delete fInheritedMacroList;
+    fInheritedMacroList = 0;
+  }
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::AddMacro(const Char_t* name, const Char_t* path)
+{
+  // Adds the macro path/name to the macro list. A warning is provided, if there is
+  // something wrong, e.g. if the macro does not have the correct signature.
+  Int_t result = fM->AddMacro(path, name);
+
+  switch (result)
+  {
+  case SUCCESS:
+    UpdateMacroList();
+    break;
+  case WARNING:
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Warning", "Macro is already in list (won't be added again)!",
+                 kMBIconExclamation, kMBOk);
+    break;
+  case ERROR:
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", "Fail to load the macro (check messages in the terminal)!",
+                 kMBIconExclamation, kMBOk);
+    break;
+  case SIGNATURE_ERROR:
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                 "Macro has not the signature of...\n...a single object selection macro: Bool_t YourMacro(const TObject*)\n...a correlated objects selection macro: Bool_t YourMacro(const TObject*, const TObject*)\n...a single object analyse macro: void YourMacro(const TObject*, Double_t*&, Int_t&)\n...a correlated objects analyse macro: void YourMacro(const TObject*, const TObject*, Double_t*&, Int_t&)\n...a single object histo macro: TH1* YourMacro(const TObject*)\n...a correlated objects histo macro: TH1* YourMacro(const TObject*, const TObject*)", 
+                 kMBIconExclamation, kMBOk);
+    break;               
+  case NOT_EXIST_ERROR:
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                 "File does not exist or you do not have read permission!", kMBIconExclamation, kMBOk);
+    break;
+  case UNKNOWN_OBJECT_TYPE_ERROR:
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                 "Unknown object type of macro parameter!", kMBIconExclamation, kMBOk);
+    break;
+  default:
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                 Form("AliEveListAnalyser::AddMacro exited with unknown return value: %d", result),
+                 kMBIconExclamation, kMBOk);
+    break;
+  }
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::ApplyMacros()
+{
+  // Applies the selected macros and updates the view.
+
+  Bool_t success = kFALSE;
+
+  // First apply the single object selection macros
+  TList* selIterator = new TList();
+  ftlMacroSelList->GetSelectedEntries(selIterator);
+  fM->ApplySTSelectionMacros(selIterator);
+  
+  // Update view
+  gEve->Redraw3D();
+
+  // Now apply the process macros
+  TList* procIterator = new TList();
+  ftlMacroList->GetSelectedEntries(procIterator);
+  success = fM->ApplyProcessMacros(selIterator, procIterator);
+
+  // Update histogram tab (data has to be reloaded)
+  SetModel(fM);
+  Update();
+
+  // AliEveListAnalyser::ApplyProcessMacros() automatically selects a macro -> Draw the histogram for it,
+  // if a process macro has been applied
+  if (success && procIterator->GetEntries() > 0) 
+  {
+    // Set focus on "Histograms" tab
+    GetGedEditor()->GetTab()->SetTab("Results");
+
+    DrawHistos();
+  }
+
+  if (selIterator != 0) delete selIterator;
+  selIterator = 0;  
+  if (procIterator != 0)  delete procIterator;  
+  procIterator = 0;  
+  
+  if (!success)
+  {
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                 "AliEveListAnalyser::ApplyProcessMacros experienced an error (cf. CINT-output)!", 
+                 kMBIconExclamation, kMBOk);  
+  }
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::BrowseMacros()
+{
+  // Creates a file-dialog. The selected files will be added to the macro list
+  // via AddMacro(...).
+
+  new TGFileDialog(gClient->GetRoot(), GetMainFrame(), kFDOpen, fFileInfo);
+  
+  if (fFileInfo->fIniDir != 0 && fFileInfo->fFileNamesList != 0)
+  {       
+    // Extract filenames
+    TObject* iter = fFileInfo->fFileNamesList->First();
+    Char_t* name = 0;
+
+    while (iter != 0)
+    {
+      // NOTE: fileInfo->fFileNamesList will be changed by that, too!
+      name = (Char_t*)strrchr(iter->GetName(), '/');
+      // Delete '"' at the end
+      name[strlen(name)] = '\0';
+              
+      AddMacro(name + 1, fFileInfo->fIniDir); 
+      iter = (TObjString*)fFileInfo->fFileNamesList->After(iter);
+    }
+  }
+
+  // -> The following problem has been fixed (trunk -> Changes according to 03 September 2008):
+  // Some error occurs, when one ends the filedialog with "cancel": fileInfo->fFileNamesList is set to 0x0, but
+  // in the next launch no new memory is allocated. So do this manually.
+  //if (fileInfo->fFileNamesList == 0)  fileInfo->fFileNamesList = new TList();
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::CloseTabs()
+{
+  // Closes + deletes the tabs created by this object
+
+  if (fHistoCanvas != 0)
+  {
+    // Close the created tab, if it exists
+    if (fHistoCanvasName != 0)
+    {
+      if (gEve->GetBrowser()->GetTab(1)->SetTab(fHistoCanvasName->GetString()))
+      {
+        // Now the created tab is the current one and can be deleted
+        gEve->GetBrowser()->GetTab(1)->RemoveTab();
+      }
+    }
+    // With the tab removal, the canvas will be deleted automatically!
+    fHistoCanvas = 0;
+  }
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::DrawHistos()
+{
+  // Accesses the temporary data file created by the last call of ApplyMacros() and draws
+  // histograms according to the selection in the "Histograms"-tab.
+  Int_t nHistograms = GetNSelectedHistograms();
+  if (nHistograms <= 0)
+  {
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                 "No data selected. Please select the data you want to plot!", kMBIconExclamation, kMBOk);
+    return;
+  }
+  if (nHistograms > 3)
+  {
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), 
+                 "Error", "Only histograms with up to 3 dimensions supported. Please select 1,2 or 3 data macros!",
+                 kMBIconExclamation, kMBOk);
+    return;
+  }
+
+  // Check, if a histo macro shall be drawn
+  Int_t indexOfHistoMacro = -1;
+  Int_t selectedChecked = 0;
+  for (Int_t j = 0; j < fM->fDataFromMacroList->GetEntries(); j++)
+  {
+    if (fCheckButtons[j]->TGButton::GetState() == kButtonDown)
+    {
+      selectedChecked++;
+
+      // Histo macro? -> To check this, look for the substring "(histo macro)"
+      if (strstr(fM->fDataFromMacroList->At(j)->GetName(), "(histo macro)") != 0)
+      {
+        // Is also another macro selected?
+        if (nHistograms > 1)
+        {
+          // Histo macros cannot(!) be correlated!
+          new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
+                       "Histo macros (return value \"TH1*\") cannot be combined with other macros", 
+                       kMBIconExclamation, kMBOk);
+          return;        
+        }
+
+        // Mark this histo macro for drawing
+        indexOfHistoMacro = j;
+
+        // Have all selected macros been checked? -> If yes, we are done with this
+        if (selectedChecked == nHistograms)  break;
+      }
+    }
+  }
+
+  TFile* file = new TFile(Form("/tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")), "READ");
+  if (!file)  
+  {
+    Error("Draw histograms", Form("Cannot open file \"/tmp/ListAnalyserMacroData_%s.root\"", 
+                                  gSystem->Getenv("USER")));
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
+                 Form("Cannot open file \"/tmp/ListAnalyserMacroData_%s.root\"", gSystem->Getenv("USER")),
+                 kMBIconExclamation, kMBOk);
+    return;
+  }
+  
+  TTree* t = 0;
+  TTree* tFriend1 = 0;
+  TTree* tFriend2 = 0;
+
+  Int_t indexOfMacro1 = 0;
+  Int_t indexOfMacro2 = 0;
+  Int_t indexOfMacro3 = 0;
+
+  // Variable for the loop below -> Will be set to aborting value, if a histo macro is drawn
+  Int_t i = 0;
+  
+  // Draw histo macro?
+  if (indexOfHistoMacro >= 0)
+  {
+    if ((t = (TTree*)file->Get(Form("ObjectData%d", indexOfHistoMacro))))
+    {
+      SetDrawingToHistoCanvasTab();
+      TH1* myHist = 0;
+      t->SetBranchAddress(Form("Macro%d", indexOfHistoMacro), &myHist);
+      t->GetEntry(0);
+      if (myHist != 0)  myHist->Draw();
+      else
+      {
+        Error("Draw histograms", Form("No histogram for histo macro \"%s\" found!", 
+                                      fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()));
+        new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
+                     Form("No histogram for histo macro \"%s\" found!", 
+                          fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()), kMBIconExclamation, kMBOk);
+               
+      }
+
+      UpdateHistoCanvasTab();    
+    }
+    else
+    {
+      Error("Draw histograms", Form("No data for histo macro \"%s\" found!\nMaybe no objects have been selected.", 
+                                    fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()));
+      new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
+                   Form("No data for histo macro \"%s\" found!\nMaybe no objects have been selected.", 
+                        fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()), kMBIconExclamation, kMBOk);
+    }
+
+    // Skip the loop below
+    i = fM->fDataFromMacroList->GetEntries();
+  }
+
+  // Load the trees in succession and remember the entries -> Plot the analyse macros
+  for ( ; i < fM->fDataFromMacroList->GetEntries(); i++)
+  {
+    if (fCheckButtons[i]->TGButton::GetState() == kButtonDown)
+    {
+      if (t == 0)
+      {
+        indexOfMacro1 = i;
+        if (!(t = (TTree*)file->Get(Form("ObjectData%d", i))))
+        { 
+          Error("Draw histograms", Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
+                                        fM->fDataFromMacroList->At(i)->GetName()));
+          new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
+                       Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
+                            fM->fDataFromMacroList->At(i)->GetName()), kMBIconExclamation, kMBOk);
+          break;   
+        }
+
+        // 1d histogram
+        if (nHistograms == 1) 
+        {
+          SetDrawingToHistoCanvasTab();
+      
+          t->Draw(Form("Macro%d", indexOfMacro1), "1");
+          ((TH1*)gPad->GetPrimitive("htemp"))->SetTitle(Form("%s;%s",
+            fM->fDataFromMacroList->At(indexOfMacro1)->GetName(),
+            fM->fDataFromMacroList->At(indexOfMacro1)->GetName()));
+          UpdateHistoCanvasTab();        
+
+          break;     
+        }
+      }
+      else if (tFriend1 == 0)
+      {
+        indexOfMacro2 = i;
+        if (!(tFriend1 = (TTree*)file->Get(Form("ObjectData%d", i))))
+        { 
+          Error("Draw histograms", Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
+                                        fM->fDataFromMacroList->At(i)->GetName()));
+          new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
+                       Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
+                            fM->fDataFromMacroList->At(i)->GetName()),
+                            kMBIconExclamation, kMBOk);
+          break;   
+        }
+        
+        // 2d histogram
+        if (nHistograms == 2) 
+        {
+          SetDrawingToHistoCanvasTab();
+
+          t->AddFriend(tFriend1);
+          t->Draw(Form("Macro%d:Macro%d", indexOfMacro1, indexOfMacro2), "1");
+          ((TH1*)gPad->GetPrimitive("htemp"))->SetTitle(Form("%s - %s;%s;%s",
+            fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
+            fM->fDataFromMacroList->At(indexOfMacro1)->GetName(),
+            fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
+            fM->fDataFromMacroList->At(indexOfMacro1)->GetName()));
+
+          UpdateHistoCanvasTab();
+          break;     
+        }
+      }    
+      // 3d histogram
+      else
+      {
+        indexOfMacro3 = i;
+        if (!(tFriend2 = (TTree*)file->Get(Form("ObjectData%d", i))))
+        { 
+          Error("Draw histograms", Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
+                                        fM->fDataFromMacroList->At(i)->GetName()));
+          new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
+                       Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
+                            fM->fDataFromMacroList->At(i)->GetName()), kMBIconExclamation, kMBOk);
+          break;   
+        }
+
+        SetDrawingToHistoCanvasTab();
+
+        t->AddFriend(tFriend1);
+        t->AddFriend(tFriend2);
+        t->Draw(Form("Macro%d:Macro%d:Macro%d", indexOfMacro1, indexOfMacro2, indexOfMacro3), "1");
+        ((TH1*)gPad->GetPrimitive("htemp"))->SetTitle(Form("%s - %s - %s;%s;%s;%s",
+            fM->fDataFromMacroList->At(indexOfMacro3)->GetName(),
+            fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
+            fM->fDataFromMacroList->At(indexOfMacro1)->GetName(),
+            fM->fDataFromMacroList->At(indexOfMacro3)->GetName(),
+            fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
+            fM->fDataFromMacroList->At(indexOfMacro1)->GetName()));
+        
+        UpdateHistoCanvasTab();
+        break;     
+      }
+    }
+  }
+
+  if (t != 0) delete t;
+  t = 0;
+  if (tFriend1 != 0)  delete tFriend1;
+  tFriend1 = 0;
+  if (tFriend2 != 0)  delete tFriend2;
+  tFriend2 = 0;
+
+  file->Close("R");
+  delete file;
+  file = 0;
+}
+
+//______________________________________________________
+Int_t AliEveListAnalyserEditor::GetNSelectedHistograms() const
+{
+  // Returns the number of selected macros (or rather: of their selected data) in the "Histograms"-tab
+
+  Int_t count = 0;
+  
+  for (Int_t i = 0; i < fM->fDataFromMacroList->GetEntries(); i++)
+  {
+    if (fCheckButtons[i]->TGButton::GetState() == kButtonDown)  count++;
+  }
+
+  return count;
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::HandleMacroPathSet()
+{
+  // Takes the input of the text field (adding a macro), checks if the macro can be
+  // accessed (and that it exists) and adds the macro to the macro list via AddMacro(...).
+  // You can use environment variables in the text field, e.g. "$ALICE_ROOT/Eve/alice-macro/myMacro.C".
+
+  if (strlen(fteField->GetText()) != 0)
+  {  
+    // Expand the pathname
+    Char_t* systemPath = gSystem->ExpandPathName(fteField->GetText());
+    fteField->SetText(systemPath);
+    delete systemPath;
+    systemPath = 0;
+                               
+    // Check if file exists
+    FILE* fp = NULL;
+
+    fp = fopen(fteField->GetText(), "rb");
+    if (fp != NULL)
+    {
+      fclose(fp);
+
+      // Extract filename
+      Char_t* name = (Char_t*)strrchr(fteField->GetText(), '/');
+
+      // Current path
+      if (name == NULL)
+      {
+        name = new Char_t[AliEveListAnalyser::fkMaxMacroNameLength];
+        memset(name, '\0', sizeof(Char_t) * AliEveListAnalyser::fkMaxMacroNameLength);
+        sprintf(name, "%s", fteField->GetText());
+
+        // Add path to textfield -> Path is "./" -> Use length for the name + 2
+        Char_t pathname[AliEveListAnalyser::fkMaxMacroNameLength + 2];
+        memset(pathname, '\0', sizeof(Char_t) * (AliEveListAnalyser::fkMaxMacroNameLength + 2));
+        sprintf(pathname, "./%s", fteField->GetText());
+        fteField->SetText(pathname);
+
+        AddMacro(name);  
+        if (name != 0)  delete name;
+        name = 0;
+      }
+      // Different path
+      else
+      {
+        // Extract path
+        Char_t* path = new Char_t[AliEveListAnalyser::fkMaxMacroPathLength];
+        memset(path, '\0', sizeof(Char_t) * AliEveListAnalyser::fkMaxMacroPathLength);
+        strncpy(path, fteField->GetText(), strlen(fteField->GetText()) - strlen(name));
+        
+        // Ignore the slash "/" in name
+        AddMacro(name + 1, path);  
+  
+        if (path != 0)  delete path;
+        path = 0;
+      }       
+    }
+    else
+    {
+      new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                   "File does not exist or you do not have read permission!", kMBIconExclamation, kMBOk);
+    }
+  }
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::HandleNewEventLoaded()
+{
+  // Closes the tabs created by this object and sets a flag that will
+  // cause the function SetModel() to inherit the macro lists + style
+  // for the next AliEveListAnalyser from the current one.
+
+//TODO: Old version with style tab....
+  // Inherit the macro list and track style for the next track list!
+
+  // Inherit the macro list for the next analyse object list!
+  fInheritSettings = kTRUE;
+
+  // Close the tabs
+  CloseTabs();
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::HandleTabChangedToIndex(Int_t index)
+{
+  // Saves the current tab in the current AliEveListAnalyser.
+
+  fM->SetSelectedTab(index);
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::InheritMacroList()
+{
+  // The old macro list is possibly stored in the corresponding interior map. This function will 
+  // use this interior map to move the data from the interior map to the newly loaded AliEveListAnalyser. 
+  // Then the interior map will be cleaned up. With this, the settings will be inherited from the previously 
+  // loaded AliEveListAnalyser.
+
+  if (fInheritedMacroList == 0)  return;
+
+  // Clear list  
+  fM->fMacroList->Delete();
+
+  // Store data from interior list in the analyse object list's map
+  TMapIter* iter = (TMapIter*)fInheritedMacroList->MakeIterator();
+  
+  TObject* key = 0;
+  TGeneralMacroData* macro = 0;
+  
+  while ((key = iter->Next()) != 0)
+  {
+    macro = (TGeneralMacroData*)fInheritedMacroList->GetValue(key);
+    if (macro != 0)  fM->fMacroList->Add(new TObjString(key->GetName()), 
+                                         new TGeneralMacroData(macro->GetName(), macro->GetPath(), macro->GetType()));
+    else
+    {
+      Error("AliEveListAnalyserEditor::InheritMacroList", Form("Failed to inherit the macro \"%s\"!", key));
+    }
+  }
+  
+  fInheritedMacroList->Delete();
+  delete fInheritedMacroList;
+  fInheritedMacroList = 0;
+}
+
+/*
+//______________________________________________________
+void AliEveListAnalyserEditor::InheritStyle()
+{
+  // The old styles are stored in the corresponding button groups. This function will replace
+  // the style settings of the newly loaded AliEveListAnalyser with the old styles. With this, the settings
+  // will be inherited from the previously loaded AliEveListAnalyser.
+
+  for (Int_t ind = 0; ind < 3; ind++)
+  {
+    if (fbgStyleTrack->GetButton(ind)->IsOn())
+    {
+      SetTrackModel(ind);
+      break;
+    }
+  }
+  for (Int_t ind = 0; ind < 3; ind++)
+  {
+    if (fbgStyleColor->GetButton(ind)->IsOn())
+    {
+      SetTrackColor(ind);
+      break;
+    }
+  }
+}
+*/
+
+//______________________________________________________
+void AliEveListAnalyserEditor::NewMacros()
+{
+  // Start the macro creation wizard.
+  // thanks to Jacek Otwinowski<J.Otwinowski@GSI.DE> for this suggestion
+
+  AliEveGeneralMacroWizard *wizz = new AliEveGeneralMacroWizard();
+  wizz->Connect("Create(Char_t*)", "AliEveListAnalyserEditor", this, "AddMacro(Char_t*)");
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::RemoveMacros()
+{
+  // Removes the selected macros from the corresponding list.
+
+  TList* iterator = new TList();
+  
+  ftlMacroList->GetSelectedEntries(iterator);
+  fM->RemoveSelectedMacros(iterator);
+
+  if (iterator != 0)  delete iterator;
+
+  iterator = new TList();
+  ftlMacroSelList->GetSelectedEntries(iterator);
+  fM->RemoveSelectedMacros(iterator);
+
+  // Selected macros are deleted from the list -> No selected entries left
+  fM->fMacroListSelected = 0;
+
+  UpdateMacroList();
+
+  if (iterator != 0)  delete iterator;
+  iterator = 0;
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::SetDrawingToHistoCanvasTab()
+{
+  // Sets gPad to the tab with the name of the current AliEveListAnalyser. If this tab does
+  // not exist, it will be created. Otherwise, it is re-used.
+
+  // If the tab with the canvas has been closed, the canvas will be deleted.
+  // So, if there is no tab, set the canvas pointer to zero and recreate it in a new tab.
+  if (fHistoCanvas != 0) 
+  {
+    if (gEve->GetBrowser()->GetTab(1)->SetTab(fHistoCanvasName->GetString()) == 0)
+    {
+      fHistoCanvas = 0;
+    }
+  }
+
+  if (!fHistoCanvas)
+  {
+    fHistoCanvas = gEve->AddCanvasTab(fM->GetName());     
+  }
+                           
+  gPad = fHistoCanvas;
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::SetModel(TObject* obj)
+{  
+  // Sets the model object, updates the related data in the GUI and
+  // inherits settings (cf. Inherit*(...)), if the flag fInheritSettings is set to kTRUE.
+
+  fM = dynamic_cast<AliEveListAnalyser*>(obj);
+
+  if (fM == 0) 
+  {
+    Error("SetModel", "Parameter is zero pointer");
+    return;
+  }
+
+  // Provide a pointer to this editor
+  fM->fEditor = this;
+
+  // If macro list + track style shall be inherited from previously loaded track list, do so
+  if (fInheritSettings)
+  {
+    InheritMacroList();
+    //TODO
+    //InheritStyle();
+
+    fInheritSettings = kFALSE;
+  }
+//TODO
+/*
+  // Select the correct styles
+  Int_t b = 0;
+  UChar_t style = fM->GetSelectedTrackStyle();
+  if (TESTBIT(style, AliEveTRDTrack::kSource)) b = 2;
+  else 
+  {
+    if (TESTBIT(style, AliEveTRDTrack::kPID)) b = 1;
+    else b = 0;
+  } 
+  fbgStyleColor->SetButton(b, kTRUE);
+
+
+  if (TESTBIT(style, AliEveTRDTrack::kTrackCosmics)) b = 2;
+  else
+  {
+    if (TESTBIT(style, AliEveTRDTrack::kTrackModel)) b = 1;
+    else b = 0;
+  }
+  fbgStyleTrack->SetButton(b, kTRUE);
+*/  
+  UpdateMacroList();
+  UpdateHistoList(); 
+
+  // View correct tab
+  GetGedEditor()->GetTab()->SetTab(fM->GetSelectedTab()); 
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::SaveMacroList(TMap* list)
+{
+  // Saves the provided macro list in an interior list. This list will be used by
+  // InheritMacroList() to restore the data in "list". With this method one is able
+  // to inherit the macro list from analyse object list to analyse object list (i.e. from event to event).
+
+  if (fInheritedMacroList != 0)
+  {
+    fInheritedMacroList->Delete();
+    delete fInheritedMacroList;
+  }
+  fInheritedMacroList = new TMap();
+  fInheritedMacroList->SetOwnerKeyValue(kTRUE, kTRUE);
+
+  TMapIter* iter = (TMapIter*)list->MakeIterator();
+  TObject* key = 0;
+  TGeneralMacroData* macro = 0;
+  
+  while ((key = iter->Next()) != 0)
+  {
+    macro = (TGeneralMacroData*)fM->fMacroList->GetValue(key);
+    if (macro != 0) fInheritedMacroList->Add(new TObjString(key->GetName()), 
+                                             new TGeneralMacroData(macro->GetName(), macro->GetPath(), macro->GetType()));
+    else
+    {
+      Error("AliEveListAnalyserEditor::SaveMacroList", Form("Failed to inherit the macro \"%s\"!", key));
+    }
+  }
+}
+
+/*
+//______________________________________________________
+void AliEveListAnalyserEditor::SetTrackColor(Int_t ind)
+{
+  // Sets the color model for the tracks, updates the tracks with this model and
+  // redraws the scene.
+
+  switch(ind)
+  { 
+    case AliTRDpidUtil::kLQ:
+      fM->UpdateTrackStyle(AliEveTRDTrack::kPID, AliTRDpidUtil::kLQ);
+      break;
+    case AliTRDpidUtil::kNN:
+      fM->UpdateTrackStyle(AliEveTRDTrack::kPID, AliTRDpidUtil::kNN);
+      break;
+    default:
+      fM->UpdateTrackStyle(AliEveTRDTrack::kSource);
+      break;
+  }
+
+  gEve->Redraw3D();
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::SetTrackModel(Int_t ind)
+{
+  // Sets the track model for the tracks, updates the tracks with this model and
+  // redraws the scene.
+
+  switch(ind)
+  { 
+    case AliEveTRDTrack::kRieman:
+      fM->UpdateTrackStyle(AliEveTRDTrack::kTrackModel, AliEveTRDTrack::kRieman);
+      break;
+    case AliEveTRDTrack::kKalman:
+      fM->UpdateTrackStyle(AliEveTRDTrack::kTrackModel, AliEveTRDTrack::kKalman);
+      break;
+    default:
+      fM->UpdateTrackStyle(AliEveTRDTrack::kTrackCosmics);
+      break;
+  }
+
+  gEve->Redraw3D();
+}
+*/
+
+//______________________________________________________
+void AliEveListAnalyserEditor::UpdateDataFromMacroListSelection()
+{
+  // Saves the current selection in the "Histograms"-tab to the current
+  // AliEveListAnalyser. This means that the selection is updated and won't
+  // get lost, if another editor is loaded in Eve.
+
+  for (Int_t i = 0; i < fM->fDataFromMacroList->GetEntries(); i++)
+  {
+    fM->SetHistoDataSelection(i, fCheckButtons[i]->IsOn());
+  }
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::UpdateHistoCanvasTab()
+{
+   // Updates the histogram and the corresponding tab (including titles).
+
+  // Update name of the tab (tab has been set to current tab!)
+  fHistoCanvasName->SetString(fM->GetName());  
+
+  // Use a copy of fHistoCanvasName!! -> If the user closes a tab manually, the TGString
+  // will be deleted -> Error might occur, when accessing the pointer   
+  gEve->GetBrowser()->GetTab(1)->GetCurrentTab()->SetText(new TGString(fHistoCanvasName));
+
+  // Switch tabs to force redrawing
+  gEve->GetBrowser()->GetTab(1)->SetTab(0);
+  gEve->GetBrowser()->GetTab(1)->SetTab(fHistoCanvasName->GetString());
+  fHistoCanvas->Update();
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::UpdateHistoList()
+{
+  // Reloads (updates) the buttons in the "Histograms"-tab via
+  // the current AliEveListAnalyser (data).
+
+  fHistoSubFrame->TGCompositeFrame::Cleanup();
+  
+  // Set buttons for histograms
+  if (fCheckButtons != 0) delete fCheckButtons;
+  fCheckButtons = new TGCheckButton*[fM->fDataFromMacroList->GetEntries()];
+  
+  TObjString* iter = (TObjString*)fM->fDataFromMacroList->First();
+  for (Int_t i = 0; i < fM->fDataFromMacroList->GetEntries() && iter != 0; i++)
+  {
+    fCheckButtons[i] = new TGCheckButton(fHistoSubFrame, iter->GetName());
+    fHistoSubFrame->AddFrame(fCheckButtons[i]);
+    
+    fCheckButtons[i]->SetState(kButtonUp, kFALSE);
+    fCheckButtons[i]->MapRaised();
+    fCheckButtons[i]->SetOn(fM->HistoDataIsSelected(i));
+    fCheckButtons[i]->Connect("Clicked()", "AliEveListAnalyserEditor", this, "UpdateDataFromMacroListSelection()");
+            
+    iter = (TObjString*)fM->fDataFromMacroList->After(iter);
+  }  
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::UpdateMacroList()
+{
+  // Reloads (updates) the macro list (selection AND process macros) via
+  // the current AliEveListAnalyser (data).
+
+  ftlMacroList->RemoveAll();
+  ftlMacroSelList->RemoveAll();
+   
+  TMapIter* iter = (TMapIter*)fM->fMacroList->MakeIterator();
+  TObject* key = 0;
+  TGeneralMacroData* macro = 0;
+
+  Int_t ind = 0;
+  while ((key = iter->Next()) != 0)
+  {
+    macro = (TGeneralMacroData*)fM->fMacroList->GetValue(key);
+    if (macro != 0)
+    {
+      if (macro->IsProcessMacro())
+      {
+        ftlMacroList->AddEntry(macro->GetName(), ind);
+        // Select, what has been selected before
+        ftlMacroList->Select(ind, fM->MacroListIsSelected(ind));
+        ind++;
+      }
+      else if (macro->IsSelectionMacro())
+      {
+        ftlMacroSelList->AddEntry(macro->GetName(), ind);
+        // Select, what has been selected before
+        ftlMacroSelList->Select(ind, fM->MacroListIsSelected(ind));
+        ind++;
+      }
+      else
+      {
+        Error("AliEveListAnalyserEditor::UpdateMacroList()", 
+              Form("Macro \"%s/%s.C\" is neither a selection macro nor a process macro!",
+                   macro->GetPath(), macro->GetName()));                                        
+      }
+    }
+    else
+    {
+      Error("AliEveListAnalyserEditor::UpdateMacroList()", 
+              Form("Macro list is corrupted: Macro \"%s\" not found!", key->GetName()));            
+    }     
+  }
+
+  ftlMacroList->SortByName(); 
+  ftlMacroSelList->SortByName(); 
+}
+
+//______________________________________________________
+void AliEveListAnalyserEditor::UpdateMacroListSelection(Int_t ind)
+{
+  // Saves the current selection in the macro listS to the current
+  // AliEveListAnalyser. This means that the selection is updated and won't
+  // get lost, if another editor is loaded in Eve.
+  // NOTE: The indices in BOTH lists will be unique!
+
+  // Toggle selected item
+  fM->SetMacroListSelection(ind, !fM->MacroListIsSelected(ind));
+}
+
+
+/////////////////////////////////////////////////
+ClassImp(AliEveGeneralMacroWizard)
+
+//______________________________________________________
+AliEveGeneralMacroWizard::AliEveGeneralMacroWizard(const TGWindow* p)
+  :TGMainFrame(p ? p : gClient->GetRoot(), 10, 10, kMainFrame | kVerticalFrame)
+  ,fTextName(0x0)
+  ,fTextObjectType(0x0)
+  ,fCombo(0x0)
+  ,fTextEdit(0x0)
+  ,fbCreate(0x0)
+  ,fbCancel(0x0)
+{
+  const Int_t width = 300;
+
+  // horizontal frame
+  TGHorizontalFrame *fFrameName = new TGHorizontalFrame(this, 10, 10, kHorizontalFrame);
+  TGLabel *fLabel = new TGLabel(fFrameName, "Name*");
+  fLabel->SetTextJustify(36);
+  fLabel->SetMargins(0,0,0,0);
+  fLabel->SetWrapLength(-1);
+  fFrameName->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
+
+  fTextName = new TGTextEntry(fFrameName);
+  fTextName->SetMaxLength(255);
+  fTextName->SetAlignment(kTextLeft);
+  fTextName->SetText("");
+  fTextName->SetToolTipText("The name of your macro");
+  fTextName->Resize(width, fTextName->GetDefaultHeight());
+  fFrameName->AddFrame(fTextName, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
+
+  // horizontal frame
+  TGHorizontalFrame *fFrameObjectType = new TGHorizontalFrame(this, 10, 10, kHorizontalFrame);
+  fLabel = new TGLabel(fFrameObjectType, "Object type of macro");
+  fLabel->SetTextJustify(36);
+  fLabel->SetMargins(0,0,0,0);
+  fLabel->SetWrapLength(-1);
+  fFrameObjectType->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
+
+  fTextObjectType = new TGTextEntry(fFrameObjectType);
+  fTextObjectType->SetMaxLength(255);
+  fTextObjectType->SetAlignment(kTextLeft);
+  fTextObjectType->SetText("");
+  // Limit max.length to 80 characters
+  fTextObjectType->SetMaxLength(80);
+  fTextObjectType->SetToolTipText("The type of objects, your macro will work with");
+  fTextObjectType->Resize(width, fTextObjectType->GetDefaultHeight());
+  fFrameObjectType->AddFrame(fTextObjectType, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
+
+  // horizontal frame
+  TGHorizontalFrame *fFrameComment = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
+  fLabel = new TGLabel(fFrameComment, "Comment");
+  fLabel->SetTextJustify(36);
+  fLabel->SetMargins(0,0,0,0);
+  fLabel->SetWrapLength(-1);
+  fFrameComment->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
+
+  fTextEdit = new TGTextEdit(fFrameComment, width, 5*fTextName->GetDefaultHeight());
+  fFrameComment->AddFrame(fTextEdit, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
+
+  // horizontal frame
+  TGHorizontalFrame *fFrameType = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
+  fLabel = new TGLabel(fFrameType, "Type*");
+  fLabel->SetTextJustify(36);
+  fLabel->SetMargins(0,0,0,0);
+  fLabel->SetWrapLength(-1);
+  fFrameType->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
+
+  fCombo = new TGComboBox(fFrameType, -1, kHorizontalFrame | kSunkenFrame | kDoubleBorder | kOwnBackground);
+  fCombo->AddEntry("Single Object Selection", AliEveListAnalyser::kSingleObjectSelect);
+  fCombo->AddEntry("Pair Objects Selection", AliEveListAnalyser::kCorrelObjectSelect);
+  fCombo->AddEntry("Single Object Analyse", AliEveListAnalyser::kSingleObjectAnalyse);
+  fCombo->AddEntry("Single Object Histo", AliEveListAnalyser::kSingleObjectHisto);
+  fCombo->AddEntry("Pair Objects Analyse", AliEveListAnalyser::kCorrelObjectAnalyse);
+  fCombo->AddEntry("Pair Objects Histo", AliEveListAnalyser::kCorrelObjectHisto);
+  fCombo->Select(-1);
+  fCombo->Resize(width, fTextName->GetDefaultHeight());
+  fFrameType->AddFrame(fCombo, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
+
+  // horizontal frame
+  TGHorizontalFrame *fFrameAction = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
+  fbCancel = new TGTextButton(fFrameAction, "Cancel");
+  fbCancel->SetToolTipText("Exit macro creation wizard");
+  fFrameAction->AddFrame(fbCancel, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2)); 
+  fbCreate = new TGTextButton(fFrameAction, "Done");
+  fbCreate->SetToolTipText("Use settings to create the macro");
+  fFrameAction->AddFrame(fbCreate, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2)); 
+
+
+  // horizontal frame
+  TGHorizontalFrame *fFrameText = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
+  fLabel = new TGLabel(fFrameText, "(*) Mandatory fields");
+  fLabel->SetTextJustify(36);
+  fLabel->SetMargins(0,0,0,0);
+  fLabel->SetWrapLength(-1);
+  fFrameText->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
+
+  // put things together  
+  AddFrame(fFrameName, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
+  AddFrame(fFrameObjectType, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
+  AddFrame(fFrameComment, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
+  AddFrame(fFrameType, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
+  AddFrame(fFrameAction, new TGLayoutHints(kLHintsRight | kLHintsTop | kLHintsExpandX,2,2,2,2));
+
+  TGHorizontal3DLine *fLine = new TGHorizontal3DLine(this, 281, 2);
+  AddFrame(fLine, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
+  AddFrame(fFrameText, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
+
+
+  SetWindowName("Macro Wizard");
+  SetMWMHints(kMWMDecorAll,
+              kMWMFuncAll,
+              kMWMInputModeless);
+  MapSubwindows();
+
+  Resize(GetDefaultSize());
+  MapWindow();
+
+  // Do the linking
+  //fCombo->Connect("Selected(Int_t)", "AliEveGeneralMacroWizard", this, "Create(Int_t)");
+  fbCreate->Connect("Clicked()", "AliEveGeneralMacroWizard", this, "HandleCreate()");
+  fbCancel->Connect("Clicked()", "AliEveGeneralMacroWizard", this, "CloseWindow()");
+
+  // Standard choice
+  fCombo->Select(1, kFALSE);
+}  
+
+const Char_t *fGeneralIncludes = 
+// TODO: Remove include files corresponding to a track list
+"#if !defined(__CINT__) || defined(__MAKECINT__)\n"
+"#include <TROOT.h>\n"
+"#include <TH1.h>\n"
+"#include <TRD/AliTRDgeometry.h>\n"
+"#include <TRD/AliTRDcluster.h>\n"
+"#include <TRD/AliTRDseedV1.h>\n"
+"#include <TRD/AliTRDtrackV1.h>\n"
+"#endif\n";
+
+const Char_t *fGeneralMacroTemplate[7] = {
+""
+,"  if (!object) return kFALSE;\n"
+
+,"  n = 0;\n"
+"  r = 0x0;\n"
+"  if (!object) return;\n"
+
+,"  if (!object) return 0x0;\n"
+"  TH1* h = 0x0;\n\n"
+"// Set bins, xmin and xmax here\n"
+"  Int_t n = 1;\n"
+"  Double_t xmin = 0;\n"
+"  Double_t xmax = 100;\n\n" 
+"  if(!(h = (TH1*)gROOT->FindObject(\"h\"))){\n"
+"    h = new TH1(\"h\", \"Title\", n, xmin, xmax);\n"
+"    h->GetXaxis()->SetTitle("");\n"
+"    h->GetYaxis()->SetTitle("");\n"
+"  } else h->Reset();\n"
+
+,"  if (!object) return kFALSE;\n"
+"  if (!object2) return kFALSE;\n"
+
+,"  n = 0;\n"
+"  r = 0x0;\n"
+"  if (!object) return;\n"
+"  if (!object2) return;\n"
+
+,"  if (!object) return 0x0;\n"
+"  if (!object2) return 0x0;\n"
+"  TH1* h = 0x0;\n\n"
+"// Set bins, xmin and xmax here\n"
+"  Int_t n = 1;\n"
+"  Double_t xmin = 0;\n"
+"  Double_t xmax = 100;\n\n" 
+"  if(!(h = (TH1*)gROOT->FindObject(\"h\"))){\n"
+"    h = new TH1(\"h\", \"Title\", n, xmin, xmax);\n"
+"    h->GetXaxis()->SetTitle("");\n"
+"    h->GetYaxis()->SetTitle("");\n"
+"  } else h->Reset();\n"
+};
+
+
+const Char_t *fGeneralMacroTemplate_WithType[7] = {
+""
+,"  if (!object) return kFALSE;\n"
+"  if (object->IsA() != OBJECTTYPE::Class()) return kFALSE;\n\n"
+"  const OBJECTTYPE* myObject = dynamic_cast<const OBJECTTYPE*>(object);\n" 
+"  if (!myObject) return kFALSE;\n"
+
+,"  n = 0;\n"
+"  r = 0x0;\n"
+"  if (!object) return;\n"
+"  if (object->IsA() != OBJECTTYPE::Class()) return;\n\n"
+"  const OBJECTTYPE* myObject = dynamic_cast<const OBJECTTYPE*>(object);\n" 
+"  if (!myObject) return;\n"
+
+,"  if (!object) return 0x0;\n"
+"  if (object->IsA() != OBJECTTYPE::Class()) return 0x0;\n\n"
+"  const OBJECTTYPE* myObject = dynamic_cast<const OBJECTTYPE*>(object);\n" 
+"  if (!myObject) return 0x0;\n\n"
+"  TH1* h = 0x0;\n\n"
+"// Set bins, xmin and xmax here\n"
+"  Int_t n = 1;\n"
+"  Double_t xmin = 0;\n"
+"  Double_t xmax = 100;\n\n" 
+"  if(!(h = (TH1*)gROOT->FindObject(\"h\"))){\n"
+"    h = new TH1(\"h\", \"Title\", n, xmin, xmax);\n"
+"    h->GetXaxis()->SetTitle("");\n"
+"    h->GetYaxis()->SetTitle("");\n"
+"  } else h->Reset();\n"
+
+,"  if (!object) return kFALSE;\n"
+"  if (!object2) return kFALSE;\n"
+"  if (object->IsA() != OBJECTTYPE::Class()) return kFALSE;\n"
+"  if (object2->IsA() != OBJECTTYPE::Class()) return kFALSE;\n\n"
+"  const OBJECTTYPE* myObject = dynamic_cast<const OBJECTTYPE*>(object);\n"
+"  const OBJECTTYPE* myObject2 = dynamic_cast<const OBJECTTYPE*>(object2);\n" 
+"  if (!myObject) return kFALSE;\n"
+"  if (!myObject2) return kFALSE;\n"
+
+,"  n = 0;\n"
+"  r = 0x0;\n"
+"  if (!object) return;\n"
+"  if (!object2) return;\n"
+"  if (object->IsA() != OBJECTTYPE::Class()) return;\n"
+"  if (object2->IsA() != OBJECTTYPE::Class()) return;\n\n"
+"  const OBJECTTYPE* myObject = dynamic_cast<const OBJECTTYPE*>(object);\n"
+"  const OBJECTTYPE* myObject2 = dynamic_cast<const OBJECTTYPE*>(object2);\n" 
+"  if (!myObject) return;\n"
+"  if (!myObject2) return;\n"
+
+,"  if (!object) return 0x0;\n"
+"  if (!object2) return 0x0;\n"
+"  if (object->IsA() != OBJECTTYPE::Class()) return 0x0;\n"
+"  if (object2->IsA() != OBJECTTYPE::Class()) return 0x0;\n\n"
+"  const OBJECTTYPE* myObject = dynamic_cast<const OBJECTTYPE*>(object);\n"
+"  const OBJECTTYPE* myObject2 = dynamic_cast<const OBJECTTYPE*>(object2);\n" 
+"  if (!myObject) return 0x0;\n"
+"  if (!myObject2) return 0x0;\n"
+"  TH1* h = 0x0;\n\n"
+"// Set bins, xmin and xmax here\n"
+"  Int_t n = 1;\n"
+"  Double_t xmin = 0;\n"
+"  Double_t xmax = 100;\n\n" 
+"  if(!(h = (TH1*)gROOT->FindObject(\"h\"))){\n"
+"    h = new TH1(\"h\", \"Title\", n, xmin, xmax);\n"
+"    h->GetXaxis()->SetTitle("");\n"
+"    h->GetYaxis()->SetTitle("");\n"
+"  } else h->Reset();\n"
+};
+
+//______________________________________________________
+void AliEveGeneralMacroWizard::Create(Int_t type)
+{
+  const Char_t* name = fTextName->GetText();
+  if(strcmp(name,"")==0){
+    AliInfo("Please specify a name for your macro.");
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                 "Please specify a name for your macro.", kMBIconExclamation, kMBOk);
+    //fCombo->Select(-1);
+    return;
+  }
+
+  Bool_t useGivenType = kFALSE;
+
+  // Remove white-spaces
+  TString* typeStr = new TString();
+
+  typeStr->Append(fTextObjectType->GetText());
+  typeStr->ReplaceAll(" ", "");
+  fTextObjectType->SetText(typeStr->Data(), kFALSE);
+
+  // If an object type is provided by the user, use it!
+  if (strlen(typeStr->Data()) > 0)
+  {
+    // Check, if the class really exists
+    if (TClass::GetClass(typeStr->Data()) != 0x0)
+    {
+      useGivenType = kTRUE; 
+    }
+    else
+    {
+      Int_t buttonsPressed = 0;
+      new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Unknown object type", 
+        Form("The class of your object, \"%s\" has not been found. Do you really want to create your macro with this object type?", 
+             typeStr->Data()), kMBIconExclamation, kMBYes | kMBNo, &buttonsPressed);
+
+      if (buttonsPressed & kMBYes)  useGivenType = kTRUE;
+      else useGivenType = kFALSE;
+
+      // Cancel creation
+      if (!useGivenType)
+      {
+        typeStr->Clear();
+        if (typeStr != 0) delete typeStr;
+        typeStr = 0;
+        return;
+      }
+    }
+  }
+
+  // Note: gSystem->AccessPathName(...) returns kTRUE, if the access FAILED!
+  if(!gSystem->AccessPathName(Form("./%s.C", name))){
+    // If there is already a file with this name -> Error
+    AliInfo(Form("A macro \"%s.C\" already exists in the current directory!\nPlease choose another name!", name));
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                 Form("A macro \"%s.C\" already exists in the current directory!\nPlease choose another name!", name), kMBIconExclamation, kMBOk);
+    //fCombo->Select(-1);
+    return;
+  }
+
+  FILE* fp = 0x0;
+  if(!(fp = fopen(Form("%s.C", name), "wt"))){
+    AliInfo("Couldn't create macro file.");
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                 "Couldn't create macro file.", kMBIconExclamation, kMBOk);
+    //fCombo->Select(-1);
+    return;
+  }
+
+  TGText* comment = fTextEdit->GetText();
+  Char_t* line = 0x0; Int_t iline = 0;
+  while((line = comment->GetLine(TGLongPosition(0,iline++), 200))) fprintf(fp, "// %s\n", line);
+
+  fprintf(fp, "\n%s\n", fGeneralIncludes);
+
+  TString* tempStr = new TString();
+
+  // Use default type
+  if (!useGivenType)
+  {
+    typeStr->Clear();
+    typeStr->Append("TObject");
+  }
+
+  switch(type){
+  case AliEveListAnalyser::kSingleObjectSelect:
+    // Use "Bool_t 'NAME'(const 'OBJECTTYPE' *object)\n"
+    tempStr->Append("Bool_t ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object)\n");
+    fprintf(fp, tempStr->Data());
+    break;
+  case AliEveListAnalyser::kCorrelObjectSelect:
+    // Use "Bool_t 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE' *object2)\n"
+    tempStr->Append("Bool_t ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, const ").Append(typeStr->Data()).Append(" *object2)\n");
+    fprintf(fp, tempStr->Data());
+    break;
+  case AliEveListAnalyser::kSingleObjectAnalyse:    
+    // Use "void 'NAME'(const 'OBJECTTYPE' *object, Double_t*& r, Int_t& n)\n"
+    tempStr->Append("void ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, Double_t*& r, Int_t& n)\n");
+    fprintf(fp, tempStr->Data());
+    break;
+  case AliEveListAnalyser::kSingleObjectHisto:
+    // Use "TH1* 'NAME'(const 'OBJECTTYPE' *object)\n"
+    tempStr->Append("TH1* ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object)\n");
+    fprintf(fp, tempStr->Data());
+    break;
+  case AliEveListAnalyser::kCorrelObjectAnalyse:
+    // Use "void 'NAME'(const TObject *object, const TObject *object2, Double_t*& r, Int_t& n)\n"
+    tempStr->Append("void ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, const ").Append(typeStr->Data()).Append(" *object2, Double_t*& r, Int_t& n)\n");
+    fprintf(fp, tempStr->Data());
+    break;
+  case AliEveListAnalyser::kCorrelObjectHisto:
+    // Use "TH1* 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE' *object2)\n"
+    tempStr->Append("TH1* ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, const ").Append(typeStr->Data()).Append(" *object2)\n");
+    fprintf(fp, tempStr->Data());
+    break;
+  default:
+    AliInfo(Form("Unknown type[%d]", type));
+    new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
+                 Form("Unknown type[%d]", type), kMBIconExclamation, kMBOk);
+    fclose(fp);
+    gSystem->Exec(Form("rm -f %s.C", name));
+    //fCombo->Select(-1);
+
+    tempStr->Clear();
+    if (tempStr != 0) delete tempStr;
+    tempStr = 0;
+
+    typeStr->Clear();
+    if (typeStr != 0) delete typeStr;
+    typeStr = 0;
+
+    return;
+  }
+
+  tempStr->Clear();
+  if (tempStr != 0) delete tempStr;
+  tempStr = 0;
+
+  typeStr->Clear();
+  if (typeStr != 0) delete typeStr;
+  typeStr = 0;
+      
+  if (useGivenType)
+  {
+    // Replace "OBJECTTYPE" with the class name
+    TString* tempStr = new TString();
+    tempStr->Append(fGeneralMacroTemplate_WithType[type]);
+
+    tempStr->ReplaceAll("OBJECTTYPE", fTextObjectType->GetText());
+
+    fprintf(fp, "{\n%s\n", tempStr->Data());
+
+    if (tempStr != 0)
+    {
+      tempStr->Clear();
+      delete tempStr;
+      tempStr = 0;
+    }
+  }
+  else
+  {
+    fprintf(fp, "{\n%s\n", fGeneralMacroTemplate[type]);
+  }
+  fprintf(fp, "// add your own code here\n\n\n}\n");
+  fclose(fp);
+
+  Emit("Create(Int_t)", type);
+  Create((Char_t*)name);
+  CloseWindow();
+}
+
+//______________________________________________________
+void AliEveGeneralMacroWizard::Create(Char_t *name)
+{
+  Emit("Create(Char_t*)", Form("%s.C", name));
+}
+
+//______________________________________________________
+void AliEveGeneralMacroWizard::HandleCreate()
+{
+  Create(fCombo->GetSelected());
+}
diff --git a/EVE/EveDet/AliEveListAnalyserEditor.h b/EVE/EveDet/AliEveListAnalyserEditor.h
new file mode 100644 (file)
index 0000000..ad36251
--- /dev/null
@@ -0,0 +1,193 @@
+// Author: Benjamin Hess   06/11/2009
+
+/*************************************************************************
+ * Copyright (C) 2009, Alexandru Bercuci, Benjamin Hess.                 *
+ * All rights reserved.                                                  *
+ *************************************************************************/
+
+#ifndef AliEveListAnalyserEditor_H
+#define AliEveListAnalyserEditor_H
+
+
+// TODO: Documentation
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// AliEveListAnalyserEditor                                     //
+//                                                                      //
+// The AliEveListAnalyserEditor provides the graphical func-    //
+// tionality for the AliEveListAnalyser. It creates the tabs    //
+// and canvases, when they are needed and, as well, frees allocated     //
+// memory on destruction (or if new events are loaded and thus some     //
+// tabs are closed).                                                    //
+// The function DrawHistos() accesses the temporary file created by the //
+// AliEveListAnalyser and draws the desired data (the file will //
+// be created within the call of ApplyMacros()). Have a look at this    //
+// function to learn more about the structure of the file and how to    //
+// access the data.                                                     //
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef ROOT_TGedFrame
+#include <TGedFrame.h>
+#endif
+
+#ifndef ROOT_TGFrame
+#include <TGFrame.h>
+#endif
+
+//class AliEveTRDTrack;
+class AliEveListAnalyser;
+class AliTRDReconstructor;
+class TCanvas;     
+class TEveBrowser;           
+class TEveGedEditor;
+class TEveManager;
+class TFile;
+class TGButtonGroup;
+class TGCheckButton;
+class TGFileInfo;
+class TGGroupFrame;
+class TGHorizontal3DLine;
+class TGHorizontalFrame;
+class TGLabel;
+class TGListBox;
+class TGRadioButton;
+class TGString;
+class TGTab;
+class TGTextButton;
+class TGTextEntry;
+class TGVerticalFrame;
+class TH1;
+class TMacroData;
+class TMap;
+class TMapIter;
+class TTree;
+
+class AliEveListAnalyserEditor: public TGedFrame
+{
+public:
+  AliEveListAnalyserEditor(const TGWindow* p = 0, Int_t width = 170, Int_t height = 30,
+                                      UInt_t options = kChildFrame, Pixel_t back = GetDefaultFrameBackground());
+  virtual ~AliEveListAnalyserEditor();
+  virtual void SetModel(TObject* obj);
+
+  void    AddMacro(const Char_t* name, const Char_t* path = ".");  
+  void    ApplyMacros();
+  void    BrowseMacros();
+  void    CloseTabs();
+  void    DrawHistos();
+  Int_t   GetNSelectedHistograms() const;
+  void    HandleMacroPathSet();
+  void    HandleNewEventLoaded();
+  void    HandleTabChangedToIndex(Int_t);
+  void    NewMacros();
+  void    RemoveMacros();
+  void    SaveMacroList(TMap* list);
+//  void    SetTrackColor(Int_t ind);
+//  void    SetTrackModel(Int_t ind);
+  void    UpdateDataFromMacroListSelection();
+  void    UpdateHistoList();
+  void    UpdateMacroList();
+  void    UpdateMacroListSelection(Int_t ind);
+  
+protected:
+  AliEveListAnalyser* fM;                                               // Model object
+
+  void InheritMacroList();                               
+  void InheritStyle();                                    
+
+private:
+  AliEveListAnalyserEditor(const AliEveListAnalyserEditor&);            // Not implemented
+  AliEveListAnalyserEditor& operator=(const AliEveListAnalyserEditor&); // Not implemented 
+
+  TCanvas*          fHistoCanvas;            // Canvas for the histograms
+  TGString*         fHistoCanvasName;        // Name of the histogram canvas
+
+  TMap*             fInheritedMacroList;     // Stores the from the analyse object list inherited macro list
+
+  Bool_t            fInheritSettings;        // Flag indicating, whether the macro list will be inherited from
+                                             // the previously loaded analyse object list within the next call of SetModel
+
+// TODO: Old version with "style" still alive has comment:
+// Flag indicating, whether the macro list and the style settings will be 
+// inherited from the previously loaded track list within the next call 
+// of SetModel
+
+//  TGHorizontalFrame* fStyleFrame;            // Frame for the style stuff
+  TGVerticalFrame*   fMainFrame;             // Top frame for macro functionality.
+  TGVerticalFrame*   fHistoFrame;            // Top frame for the histogram stuff
+  TGVerticalFrame*   fHistoSubFrame;         // Frame for the histogram buttons themselves
+  TGHorizontalFrame* fBrowseFrame;           // Frame for features corresponding to searching macros
+//  TGButtonGroup*     fbgStyleColor;          // Button group for the color model
+//  TGButtonGroup*     fbgStyleTrack;          // Button group for the track model
+  
+//  TGRadioButton**    frbColor;               // Radio buttons for the color model
+//  TGRadioButton**    frbTrack;               // Radio buttons for the track model
+
+  TGTextButton*   fbBrowse;                  // "Browse" button
+  TGTextButton*   fbNew;                     // "New" button
+  TGTextButton*   fbApplyMacros;             // "Apply macros" button
+  TGTextButton*   fbRemoveMacros;            // "Remove macros" button
+  TGTextButton*   fbDrawHisto;               // "Draw histogram" button
+  TGTextEntry*    fteField;                  // Text field to insert macro path manually
+  TGListBox*      ftlMacroList;              // To display the list of (process) macros
+  TGListBox*      ftlMacroSelList;           // To display the list of (selection) macros
+
+  TGFileInfo*     fFileInfo;                 // Holds data about opening macros
+  Char_t**        fFileTypes;                // File types (for macros)
+
+  // Some labels
+  TGLabel* fLabel1;
+  TGLabel* fLabel2;
+  TGLabel* fLabel3;
+  TGLabel* fLabel4;
+     
+  // Some lines
+  TGHorizontal3DLine *fLine1;
+  TGHorizontal3DLine *fLine2;
+  TGHorizontal3DLine *fLine3;
+  TGHorizontal3DLine *fLine4;
+//  TGHorizontal3DLine *fLine5;  
+
+  TGCheckButton** fCheckButtons;            // Check buttons for histograms
+
+  // Help functions
+  void SetDrawingToHistoCanvasTab();        
+  void UpdateHistoCanvasTab();              
+
+  ClassDef(AliEveListAnalyserEditor, 0);    // Editor for AliEveListAnalyser.
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// AliEveGeneralMacroWizard                                             //
+//                                                                      //
+// Wizard for creating new macros.                                      //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+class TGTextEdit;
+class TGComboBox;
+class AliEveGeneralMacroWizard : public TGMainFrame
+{
+public:
+  AliEveGeneralMacroWizard(const TGWindow* p = 0);
+  void Create(Int_t type); //*SIGNAL*
+  void Create(Char_t *pname); //*SIGNAL*
+  void HandleCreate();
+
+private:
+  AliEveGeneralMacroWizard(const AliEveGeneralMacroWizard&);
+  AliEveGeneralMacroWizard& operator=(const AliEveGeneralMacroWizard&);
+
+  TGTextEntry *fTextName;
+  TGTextEntry *fTextObjectType;
+  TGComboBox  *fCombo;
+  TGTextEdit  *fTextEdit;
+  TGTextButton *fbCreate;                  // "Done" button
+  TGTextButton *fbCancel;                  // "Cancel" button
+  
+  ClassDef(AliEveGeneralMacroWizard, 0);      // Helper class to create macro templates 
+};
+
+#endif
index 1730080..50d8aea 100644 (file)
@@ -74,7 +74,6 @@
 #include <AliTRDReconstructor.h>
 
 #include <EveDet/AliEveTRDTrackList.h>
-#include <EveDet/AliEveTRDTrackList.h>
 #include <EveDet/AliEveTRDTrackListEditor.h>
 
 #include <../PWG1/TRD/AliTRDrecoTask.h>
@@ -195,6 +194,9 @@ Int_t AliEveTRDTrackList::AddMacro(const Char_t* path, const Char_t* nameC, Bool
  
   gROOT->ProcessLineSync(Form(".L %s+%c", pathname, forceReload ? '+' : ' '));
 
+  // We need this line... otherwise, in some cases, there will be problems concerning ACLIC
+  gROOT->ProcessLineSync(Form(".L %s", pathname));
+
   AliEveTRDTrackListMacroType type = GetMacroType(name, kFALSE);
 
   // Clean up again
@@ -477,7 +479,7 @@ Bool_t AliEveTRDTrackList::ApplyProcessMacros(const TList* selIterator, const TL
         // Loop over all pairs behind the current one - together with the other loop this will be a loop
         // over all pairs. We have a pair of tracks, if and only if both tracks of the pair are selected (Rnr-state)
         // and are not equal.
-        // The correlated tracks process macro will applied to all pairs that will be additionally selected by
+        // The correlated tracks process macro will be applied to all pairs that will be additionally selected by
         // all correlated tracks selection macros.
         TEveElement::List_i iter2 = iter;
         iter2++;
@@ -533,7 +535,7 @@ Bool_t AliEveTRDTrackList::ApplyProcessMacros(const TList* selIterator, const TL
         // Loop over all pairs behind the current one - together with the other loop this will be a loop
         // over all pairs. We have a pair of tracks, if and only if both tracks of the pair are selected (Rnr-state)
         // and are not equal.
-        // The correlated tracks process macro will applied to all pairs that will be additionally selected by
+        // The correlated tracks process macro will be applied to all pairs that will be additionally selected by
         // all correlated tracks selection macros.
         TEveElement::List_i iter2 = iter;
         iter2++;
@@ -636,9 +638,9 @@ void AliEveTRDTrackList::ApplySTSelectionMacros(const TList* iterator)
   // Clear root
   // A.B. gROOT->Reset();
 
-  // Select all tracks at first. A track is then deselect, if at least one selection macro
-  // returns kFALSE for this track
-  // Enable all tracks (Note: EnableListElements(..) will call "ElementChanged", which will cause unforeseen behavior!)
+  // Select all tracks at first. A track is then deselected, if at least one selection macro
+  // returns kFALSE for this track.
+  // Enable all tracks (Note: EnableListElements(..) will call "ElementChanged", which will cause unforeseen behaviour!)
   for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter) ((TEveElement*)(*iter))->SetRnrState(kTRUE);
   SetRnrState(kTRUE);
   
@@ -748,12 +750,12 @@ AliEveTRDTrackList::AliEveTRDTrackListMacroType AliEveTRDTrackList::GetMacroType
       if (strstr(f->GetMangledName(), "oPconstsPAliTRDtrackV1mUsP") != 0x0 &&
           strstr(f->GetMangledName(), "cOconstsPAliTRDtrackV1mUsP") != 0x0)
       {
-        // Single track select macro?
+        // Correlated track select macro?
         if (!strcmp(f->GetReturnTypeName(), "Bool_t")) 
         { 
           type = kCorrelTrackSelect;     
         }
-        // single track histo macro?
+        // Correlated track histo macro?
         else if (!strcmp(f->GetReturnTypeName(), "TH1*"))
         {
           type = kCorrelTrackHisto;
index 88199a7..8733a4e 100644 (file)
@@ -148,7 +148,7 @@ AliEveTRDTrackListEditor::AliEveTRDTrackListEditor(const TGWindow* p, Int_t widt
   fBrowseFrame->AddFrame(fbBrowse);
   
   fbNew = new TGTextButton(fBrowseFrame, "New");
-  fbNew->SetToolTipText("Start macro creation wizzard");
+  fbNew->SetToolTipText("Start macro creation wizard");
   fbNew->Connect("Clicked()", "AliEveTRDTrackListEditor", this, "NewMacros()");
   fBrowseFrame->AddFrame(fbNew);
   fMainFrame->AddFrame(fBrowseFrame);
@@ -355,10 +355,10 @@ void AliEveTRDTrackListEditor::ApplyMacros()
 //______________________________________________________
 void AliEveTRDTrackListEditor::NewMacros()
 {
-  // Start the macro creation wizzard.
+  // Start the macro creation wizard.
   // thanks to Jacek Otwinowski<J.Otwinowski@GSI.DE> for this suggestion
 
-  AliEveTRDMacroWizzard *wizz = new AliEveTRDMacroWizzard();
+  AliEveTRDMacroWizard *wizz = new AliEveTRDMacroWizard();
   wizz->Connect("Create(Char_t*)", "AliEveTRDTrackListEditor", this, "AddMacro(Char_t*)");
 }
 
@@ -1071,7 +1071,7 @@ void AliEveTRDTrackListEditor::UpdateMacroList()
       else
       {
         Error("AliEveTRDTrackListEditor::UpdateMacroList()", 
-              Form("Macro \"%s/%s.C\" has neither a selection macro nor a process macro!",
+              Form("Macro \"%s/%s.C\" is neither a selection macro nor a process macro!",
                    macro->GetPath(), macro->GetName()));                                        
       }
     }
@@ -1100,10 +1100,10 @@ void AliEveTRDTrackListEditor::UpdateMacroListSelection(Int_t ind)
 
 
 /////////////////////////////////////////////////
-ClassImp(AliEveTRDMacroWizzard)
+ClassImp(AliEveTRDMacroWizard)
 
 //______________________________________________________
-AliEveTRDMacroWizzard::AliEveTRDMacroWizzard(const TGWindow* p)
+AliEveTRDMacroWizard::AliEveTRDMacroWizard(const TGWindow* p)
   :TGMainFrame(p ? p : gClient->GetRoot(), 10, 10, kMainFrame | kVerticalFrame)
   ,fText(0x0)
   ,fCombo(0x0)
@@ -1162,7 +1162,7 @@ AliEveTRDMacroWizzard::AliEveTRDMacroWizzard(const TGWindow* p)
   // horizontal frame
   TGHorizontalFrame *fFrameAction = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
   fbCancel = new TGTextButton(fFrameAction, "Cancel");
-  fbCancel->SetToolTipText("Exit macro creation wizzard");
+  fbCancel->SetToolTipText("Exit macro creation wizard");
   fFrameAction->AddFrame(fbCancel, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2)); 
   fbCreate = new TGTextButton(fFrameAction, "Done");
   fbCreate->SetToolTipText("Use settings to create the macro");
@@ -1188,7 +1188,7 @@ AliEveTRDMacroWizzard::AliEveTRDMacroWizzard(const TGWindow* p)
   AddFrame(fFrameText, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
 
 
-  SetWindowName("TRD Macro Wizzard");
+  SetWindowName("TRD Macro Wizard");
   SetMWMHints(kMWMDecorAll,
               kMWMFuncAll,
               kMWMInputModeless);
@@ -1198,9 +1198,9 @@ AliEveTRDMacroWizzard::AliEveTRDMacroWizzard(const TGWindow* p)
   MapWindow();
 
   // Do the linking
-  //fCombo->Connect("Selected(Int_t)", "AliEveTRDMacroWizzard", this, "Create(Int_t)");
-  fbCreate->Connect("Clicked()", "AliEveTRDMacroWizzard", this, "HandleCreate()");
-  fbCancel->Connect("Clicked()", "AliEveTRDMacroWizzard", this, "CloseWindow()");
+  //fCombo->Connect("Selected(Int_t)", "AliEveTRDMacroWizard", this, "Create(Int_t)");
+  fbCreate->Connect("Clicked()", "AliEveTRDMacroWizard", this, "HandleCreate()");
+  fbCancel->Connect("Clicked()", "AliEveTRDMacroWizard", this, "CloseWindow()");
 
   // Standard choice
   fCombo->Select(1, kFALSE);
@@ -1258,7 +1258,7 @@ const Char_t *fMacroTemplate[7] = {
 "  } else h->Reset();\n"
 };
 //______________________________________________________
-void AliEveTRDMacroWizzard::Create(Int_t typ)
+void AliEveTRDMacroWizard::Create(Int_t type)
 {
   const Char_t *name = fText->GetText();
   if(strcmp(name,"")==0){
@@ -1294,7 +1294,7 @@ void AliEveTRDMacroWizzard::Create(Int_t typ)
 
   fprintf(fp, "\n%s\n", fIncludes);
 
-  switch(typ){
+  switch(type){
   case AliEveTRDTrackList::kSingleTrackSelect:
     fprintf(fp, "Bool_t %s(const AliTRDtrackV1 *track)\n", name);
     break;
@@ -1314,32 +1314,32 @@ void AliEveTRDMacroWizzard::Create(Int_t typ)
     fprintf(fp, "TH1* %s(const AliTRDtrackV1 *track, const AliTRDtrackV1 *track2)\n", name);
     break;
   default:
-    AliInfo(Form("Unknown typ[%d]", typ));
+    AliInfo(Form("Unknown type[%d]", type));
     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
-                 Form("Unknown typ[%d]", typ), kMBIconExclamation, kMBOk);
+                 Form("Unknown type[%d]", type), kMBIconExclamation, kMBOk);
     fclose(fp);
     gSystem->Exec(Form("rm -f %s.C", name));
     //fCombo->Select(-1);
     return;
   }
   
-  fprintf(fp, "{\n%s\n", fMacroTemplate[typ]);
+  fprintf(fp, "{\n%s\n", fMacroTemplate[type]);
   fprintf(fp, "// add your own code here\n\n\n}\n");
   fclose(fp);
 
-  Emit("Create(Int_t)", typ);
+  Emit("Create(Int_t)", type);
   Create((Char_t*)name);
   CloseWindow();
 }
 
 //______________________________________________________
-void AliEveTRDMacroWizzard::Create(Char_t *name)
+void AliEveTRDMacroWizard::Create(Char_t *name)
 {
   Emit("Create(Char_t*)", Form("%s.C", name));
 }
 
 //______________________________________________________
-void AliEveTRDMacroWizzard::HandleCreate()
+void AliEveTRDMacroWizard::HandleCreate()
 {
   Create(fCombo->GetSelected());
 }
index 37aa86c..4d9b268 100644 (file)
@@ -150,19 +150,27 @@ private:
   ClassDef(AliEveTRDTrackListEditor, 0);    // Editor for AliEveTRDTrackList.
 };
 
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// AliEveTRDMacroWizard                                                //
+//                                                                      //
+// Wizard for creating new macros.                                     //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
 class TGTextEdit;
 class TGComboBox;
-class AliEveTRDMacroWizzard : public TGMainFrame
+class AliEveTRDMacroWizard : public TGMainFrame
 {
 public:
-  AliEveTRDMacroWizzard(const TGWindow* p = 0);
-  void Create(Int_t typ); //*SIGNAL*
+  AliEveTRDMacroWizard(const TGWindow* p = 0);
+  void Create(Int_t type); //*SIGNAL*
   void Create(Char_t *pname); //*SIGNAL*
   void HandleCreate();
 
 private:
-  AliEveTRDMacroWizzard(const AliEveTRDMacroWizzard&);
-  AliEveTRDMacroWizzard& operator=(const AliEveTRDMacroWizzard&);
+  AliEveTRDMacroWizard(const AliEveTRDMacroWizard&);
+  AliEveTRDMacroWizard& operator=(const AliEveTRDMacroWizard&);
 
   TGTextEntry *fText;
   TGComboBox  *fCombo;
@@ -170,7 +178,7 @@ private:
   TGTextButton *fbCreate;                  // "Done" button
   TGTextButton *fbCancel;                  // "Cancel" button
   
-  ClassDef(AliEveTRDMacroWizzard, 0);      // Helper class to create macro templates 
+  ClassDef(AliEveTRDMacroWizard, 0);      // Helper class to create macro templates 
 };
 
 #endif
index bc81e79..20bd7a2 100644 (file)
 #pragma link off all globals;
 #pragma link off all classes;
 
+// Analysis
+#pragma link C++ class AliEveListAnalyser+;
+#pragma link C++ class AliEveListAnalyserEditor+;
+#pragma link C++ class AliEveGeneralMacroWizard+;
+
 // EMCAL
 #pragma link C++ class AliEveEMCALData+;
 #pragma link C++ class AliEveEMCALSModuleData+;
@@ -89,7 +94,7 @@
 #pragma link C++ class AliEveTRDTrack+;
 #pragma link C++ class AliEveTRDTrackList+;
 #pragma link C++ class AliEveTRDTrackListEditor+;
-#pragma link C++ class AliEveTRDMacroWizzard+;
+#pragma link C++ class AliEveTRDMacroWizard+;
 #pragma link C++ class AliEveTRDmcm+;
 
 // TOF
index dada2f7..890c7af 100644 (file)
@@ -35,6 +35,8 @@ alieve_clean_compiled_macros:
        @echo "***** Removing .d and .$(SOEXT) files from EVE/alice-macros/ *****"
        $(MUTE)rm -f $(ALICE_ROOT)/EVE/alice-macros/*_C.d
        $(MUTE)rm -f $(ALICE_ROOT)/EVE/alice-macros/*_C.$(SOEXT)
+       $(MUTE)rm -f -R $(HOME)/.trdQArec
+       $(MUTE)rm -f -R $(HOME)/.QArec
 
 ifeq (macosx,$(ALICE_TARGET))