-// Author: Benjamin Hess 06/11/2009
+// Author: Benjamin Hess 29/01/2010
/*************************************************************************
- * Copyright (C) 2009, Alexandru Bercuci, Benjamin Hess. *
+ * Copyright (C) 2009-2010, Alexandru Bercuci, Benjamin Hess. *
* All rights reserved. *
*************************************************************************/
-// TODO: Documentation
//////////////////////////////////////////////////////////////////////////
// //
-// AliEveListAnalyser //
+// 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). //
+// 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 analysis objects (these objects can be //
+// added to the list in the same way as for the TEveElementList, but //
+// also "by clicking" (cf. AliEveListAnaLyserEditor)). //
// 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 //
+// RemoveSelectedMacros(...). This function takes an iterator of the //
// list of macros that are to be removed. //
-// be removed. An entry looks like: //
+// 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(...) //
+// To find the type of objects the macro will deal with (corresponds to //
+// "YourObjectType" in the examples below) please use //
+// GetMacroObjectType(...). //
+// With ApplySOSelectionMacros(...) 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 //
// //
// Currently, the following macro types are supported: //
// Selection macros: //
-// Bool_t YourMacro(const YourObjectType*); //
-// Bool_t YourMacro(const YourObjectType*, const YourObjectType*); //
+// Bool_t YourMacro(const YourObjectType*); //
+// Bool_t YourMacro(const YourObjectType*, const YourObjectType2*); //
// //
// Process macros: //
-// void YourMacro(const YourObjectType*, Double_t*&, Int_t&); //
-// void YourMacro(const YourObjectType*, const YourObjectType*, //
+// void YourMacro(const YourObjectType*, Double_t*&, Int_t&); //
+// void YourMacro(const YourObjectType*, const YourObjectType2*, //
// Double_t*&, Int_t&); //
-// TH1* YourMacro(const YourObjectType*); //
-// TH1* YourMacro(const YourObjectType*, const YourObjectType*); //
+// TH1* YourMacro(const YourObjectType*); //
+// TH1* YourMacro(const YourObjectType*, const YourObjectType2*); //
// //
// 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 //
// Uncomment to display debugging infos
//#define AliEveListAnalyser_DEBUG
+#include <TEveManager.h>
+#include <TEveSelection.h>
#include <TFile.h>
#include <TFunction.h>
-#include <TMethodArg.h>
#include <TH1.h>
#include <TList.h>
#include <TMap.h>
+#include <TMethodArg.h>
+#include <TMethodCall.h>
#include <TObjString.h>
+#include <TQObject.h>
#include <TROOT.h>
#include <TSystem.h>
#include <TTree.h>
#include <TTreeStream.h>
-#include <TMethodCall.h>
-
-//TODO - NEW -> Ordering! resp. remove the non-needed files
-#include <TQObject.h>
-#include <TEveManager.h>
-#include <TGLSelectRecord.h>
-#include <TGLViewer.h>
#include <AliTRDReconstructor.h>
ClassImp(AliEveListAnalyser)
///////////////////////////////////////////////////////////
-///////////// AliEveListAnalyser ////////////////
+///////////// AliEveListAnalyser ////////////////////////
///////////////////////////////////////////////////////////
AliEveListAnalyser::AliEveListAnalyser(const Text_t* n, const Text_t* t, Bool_t doColor):
TEveElementList(n, t, doColor),
// Supported macro types:
// Selection macros:
// Bool_t YourMacro(const YourObjectType*)
- // Bool_t YourMacro(const YourObjectType*, const YourObjectType*)
+ // Bool_t YourMacro(const YourObjectType*, const YourObjectType2*)
//
// Process macros:
// void YourMacro(const YourObjectType*, Double_t*&, Int_t&)
- // void YourMacro(const YourObjectType*, const TObject*, Double_t*&, Int_t&)
+ // void YourMacro(const YourObjectType*, const YourObjectType2*, Double_t*&, Int_t&)
// TH1* YourMacro(const YourObjectType*)
- // TH1* YourMacro(const YourObjectType*, const YourObjectType*)
+ // TH1* YourMacro(const YourObjectType*, const YourObjectType2*)
Char_t pathname[fkMaxMacroPathNameLength];
memset(pathname, '\0', sizeof(Char_t) * fkMaxMacroPathNameLength);
gROOT->ProcessLineSync(Form(".L %s+%c", pathname, forceReload ? '+' : ' '));
TClass* objectType;
+ TClass* objectType2;
- objectType = GetMacroObjectType(name);
+ objectType = GetMacroObjectType(name, 1);
+ objectType2 = GetMacroObjectType(name, 2);
// 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);
+ // This might be a macro dealing with only 1 object... test this afterwards!
+ Bool_t testSecondObj = kFALSE;
+ if (!objectType2)
+ {
+ objectType2 = TObject::Class();
+ testSecondObj = kTRUE;
+ }
+ AliEveListAnalyserMacroType type = GetMacroType(name, objectType->GetName(), objectType2->GetName(), kFALSE);
+
+ if (testSecondObj)
+ {
+ switch (type)
+ {
+ case AliEveListAnalyser::kCorrelObjectSelect:
+ case AliEveListAnalyser::kCorrelObjectAnalyse:
+ case AliEveListAnalyser::kCorrelObjectHisto:
+ // There must be a second type -> Error!
+ return UNKNOWN_OBJECT_TYPE_ERROR;
+ break;
+ default:
+ // Ok, single object macro!
+ break;
+ }
+ }
+
// Clean up again
// A.B. gROOT->Reset();
Int_t returnValue = WARNING;
if(fMacroList->GetValue(name) == 0)
{
- returnValue = AddMacroFast(path, name, type, objectType) ? SUCCESS : ERROR;
+ returnValue = AddMacroFast(path, name, type, objectType, objectType2) ? SUCCESS : ERROR;
}
return returnValue;
}
//______________________________________________________
-Bool_t AliEveListAnalyser::AddMacroFast(const Char_t* path, const Char_t* name, AliEveListAnalyserMacroType type, TClass* objectType)
+Bool_t AliEveListAnalyser::AddMacroFast(const Char_t* path, const Char_t* name, AliEveListAnalyserMacroType type,
+ TClass* objectType, TClass* objectType2)
{
// 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;
+ // Note: If your macro takes only 1 pointer as a parameter, just use "0x0" for objectType2!
Bool_t success = kFALSE;
case kSingleObjectHisto:
case kCorrelObjectAnalyse:
case kCorrelObjectHisto:
- fMacroList->Add(new TObjString(name), new TGeneralMacroData(name, path, type, objectType));
+ fMacroList->Add(new TObjString(name), new TGeneralMacroData(name, path, type, objectType, objectType2));
// We do not know, where the element has been inserted - deselect this list
fMacroListSelected = 0;
#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());
+ printf("AliEveListAnalyser::AddMacroFast: Added macro \"%s/%s\" with object types \"%s\" and \"%s\" to the corresponding list\n",
+ path, name, objectType->GetName(), objectType2->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());
+ printf("AliEveListAnalyser::AddMacroFast: ERROR: Could not add macro \"%s/%s\" with object types \"%s\" and \"%s\" to the corresponding list\n", path, name, objectType->GetName(), objectType2->GetName());
success = kFALSE;
return success;
}
-//TODO - NEW - To be implemented, tested, documented
+
//______________________________________________________
-void AliEveListAnalyser::AddObjectToList(Int_t pointId)
+Int_t AliEveListAnalyser::AddPrimSelectedObject(TEveElement* el)
{
- TEvePointSet* ps = dynamic_cast<TEvePointSet*>((TQObject*) gTQSender);
+ // Adds the TEveElement el to the list. If it is already in the list, it is removed.
+ // If the list is the only parent of the clicked object, the object is moved outside the list in the browser (not deleted!).
+ // If you want to delete the object, just select it there and choose "Destroy" in the menu.
+ // This function is designed to be used together with a signal:
+ // It adds the (primarily) selected objects in the viewer to the list (objects that are already in the list are removed!).
+ // Returns "ERROR" (cf. defines) on error, "WARNING" if the element does not contain any user data and else "SUCCESS" (i.e.
+ // the element has been added successfully or the element is the list itself and therefore ignored, or the element is ignored
+ // because it has been added via secondary selection).
+
+ if (!el)
+ {
+ Error("AliEveListAnalyser::AddPrimSelectedObject", "Zero pointer!\n");
+
+ return ERROR;
+ }
+
+ // If the clicked element is the list itself, just do nothing.
+ if (el == this) return SUCCESS;
+
+ if (!this->HasChild(el))
+ {
+
+ // Ignore objects that do not have any user data, since these cannot be used in the analysis!
+ if (el->GetUserData() == 0x0)
+ {
+ Warning("AddPrimSelectedObject", "Selected object does not contain any \"user data\" and therefore is ignored!");
+
+ return WARNING;
+ }
+
+ // Element clicked that is not in the list (and is not the list itself!) -> Add this element to the list
+ this->AddElement(el);
+ this->SetTitle(Form("Objects %d", this->NumChildren()));
+ gEve->Redraw3D();
+ }
+ else
+ {
+ // Element clicked that is already in the list. Remove it. But: Only take care of objects that have been added
+ // via primary selection (name does not start with "[sec")
+ if (TString(el->GetElementName()).BeginsWith("[sec:")) return SUCCESS;
+
+
+ // Element is a child of this list. So, if there are only 2 parents, we know them: list + eve selection. In this case,
+ // the element needs to be destroyed. If there are more parents, just remove the element from the list.
+ // Since the elements editor will be opened, the element is not deleted, but "moved" outside the list (in the browser).
+ if (el->NumParents() > 2)
+ {
+ this->RemoveElement(el);
+ }
+ else
+ {
+ // There must be at least 2 parents!
+ if (el->NumParents() <= 1) return ERROR;
+
+ TEveElement* listObj = 0x0;
+ listObj = this->FindChild(el->GetElementName());
+ if (!listObj) return ERROR;
+
+ gEve->AddElement(listObj, 0);
+ // Alternatively: Switch on that the element is NOT destroyed, instead of adding it outside the list. Warning: Memory leaks possible.
+ //listObj->SetDestroyOnZeroRefCnt(kFALSE);
+ this->RemoveElement(listObj);
+ //gEve->RemoveElement(listObj, 0);
+ }
+ }
+
+ this->SetTitle(Form("Objects %d", this->NumChildren()));
+ gEve->Redraw3D();
+
+ return SUCCESS;
+}
+
+
+/*
+//______________________________________________________
+void AliEveListAnalyser::AddPrimSelectedObjects()
+{
+ // Adds the (primarily) selected objects in the viewer to the list (objects that are already in the list are ignored).
+ // Hold the CTRL-key for multiple selection.
+
+ TEveSelection* eveSel = gEve->GetSelection();
+ if (!eveSel)
+ {
+ Error("AliEveListAnalyser::AddPrimSelectedObjects", "Failed to get the selection!\n");
+ return;
+ }
+ TEveElement* elem = 0x0;
+ Bool_t changedSomething = kFALSE;
+
+ for (TEveElement::List_i iter = eveSel->BeginChildren(); iter != eveSel->EndChildren(); ++iter)
+ {
+ if(!(elem = dynamic_cast<TEveElement*>(*iter))) continue;
+
+ if (!this->HasChild(elem) && elem != this)
+ {
+ // Element clicked that is not in the list (and is not the list itself!) -> Add this element to list
+ this->AddElement(elem);
+ this->SetTitle(Form("Objects %d", this->NumChildren()));
+ changedSomething = kTRUE;
+ }
+ }
+
+ if (changedSomething) gEve->Redraw3D();
+}
+*/
+
+//______________________________________________________
+void AliEveListAnalyser::AddSecSelectedSingleObjectToList(Int_t pointId)
+{
+ // This function adds the selected object (secondary selection in the viewer) to the list
+ // of analysis objects. If the object is already in the list, it will be removed from it.
+ // This function is used to add single objects of a TEvePointset, e.g. single clusters.
+
+ TEvePointSet* ps = dynamic_cast<TEvePointSet*>((TQObject*) gTQSender);
if (!ps)
{
- Error("AliEveListAnalyser::AddObjectToList", "Zero pointer!\n");
+ Error("AliEveListAnalyser::AddSecSelectedSingleObjectToList", "Zero pointer!\n");
return;
}
// Check, if object is already there. If so, remove it!
- // 1st possibility: Object of the list clicked
+ // 1st possibility: Object of the list clicked. But: Only take care of objects that have been added
+ // via secondary selection (name starts with "[sec"). Note: HasChild will also return kTRUE, if e.g.
+ // the whole TEvePointSet of clusters is in the last (but maybe another point of it has been clicked!)
+
if (this->HasChild(ps))
{
- this->RemoveElement(ps);
- return;
+ if (TString(ps->GetName()).BeginsWith("[sec:"))
+ {
+ // I don't know why, but you get a crash, if you try this->RemoveElement(ps) (in some cases).
+ // So, use this way instead.
+ TEveElement* listObj = this->FindChild(ps->GetName());
+ if (listObj)
+ {
+ listObj->SetUserData(0x0);
+ this->RemoveElement(listObj);
+ this->SetTitle(Form("Objects %d", this->NumChildren()));
+ }
+
+ return;
+ }
}
-
+
TObject* obj = ps->GetPointId(pointId);
if (obj)
{
// 2nd possibility: Same object clicked again
TEveElement* listObj = 0x0;
- listObj = this->FindChild(Form("[viewer:%d] %s%d", obj->GetUniqueID(), obj->GetName(), pointId));
+ listObj = this->FindChild(Form("[sec:%d] %s%d", obj->GetUniqueID(), obj->GetName(), pointId));
if (listObj)
{
- this->RemoveElement(listObj);
+ listObj->SetUserData(0x0);
+ this->RemoveElement(listObj);
+ this->SetTitle(Form("Objects %d", this->NumChildren()));
return;
}
// Object clicked that is not in the list -> Add this object to list
- TEvePointSet* newPS = new TEvePointSet(Form("[viewer:%d] %s%d", obj->GetUniqueID(), obj->GetName(), pointId));
+ TEvePointSet* newPS = new TEvePointSet(Form("[sec:%d] %s%d", obj->GetUniqueID(), obj->GetName(), pointId));
Double_t x = 0, y = 0, z = 0;
ps->GetPoint(pointId, x, y, z);
newPS->SetPoint(0, x, y, z);
newPS->SetUserData(obj);
+ // Choose yellow for the added points and inherit style and size for the marker
newPS->SetMarkerColor(5);
- newPS->SetMarkerStyle(2);
- newPS->SetMarkerSize(2.0);
+ newPS->SetMarkerStyle(ps->GetMarkerStyle());
+ newPS->SetMarkerSize(ps->GetMarkerSize());
+ // Own points -> Will be cleared, if this object is removed
+ newPS->SetOwnIds(kTRUE);
- AddElement(newPS);
+ this->AddElement(newPS);
+ this->SetTitle(Form("Objects %d", this->NumChildren()));
gEve->Redraw3D();
}
else
{
- Error("AliEveListAnalyser::AddObjectToList", "Selected object is NULL and therefore ignored!");
+ Error("AliEveListAnalyser::AddSecSelectedSingleObjectToList", "Selected object is NULL and therefore ignored!");
}
-
-/*
- TGLSelectRecord rec = gEve->GetDefaultGLViewer()->GetSelRec();
-
- printf("Objects (%d):\n", rec.GetN());
- for (int i = 0; i < rec.GetN(); i++)
- {
- //printf("%s\n", ((TObject*)rec.GetItem(i))->IsA()->GetName());
- }
-*/
-
- //printf("Type: %s\npointID: %s\n\n", ps->IsA()->GetName(), pointId);
- //printf("Type objectsender: %s\nType sender: %s\n", ((TQObject*)gTQSender)->IsA()->GetName(), ((TQObjSender*)gTQSender)->IsA()->GetName());
}
//______________________________________________________
TGeneralMacroData* macro = 0;
- Char_t** procCmds = 0;
+ TString* procCmds = 0;
AliEveListAnalyserMacroType* mProcType = 0;
if (procIterator->GetEntries() > 0) {
- procCmds = new Char_t*[procIterator->GetEntries()];
+ procCmds = new TString[procIterator->GetEntries()];
mProcType = new AliEveListAnalyserMacroType[procIterator->GetEntries()];
}
TClass** mProcObjectType = 0;
+ TClass** mProcObjectType2 = 0;
if (procIterator->GetEntries() > 0) {
mProcObjectType = new TClass*[procIterator->GetEntries()];
+ mProcObjectType2 = new TClass*[procIterator->GetEntries()];
}
- Char_t** selCmds = 0;
+ TString* selCmds = 0;
AliEveListAnalyserMacroType* mSelType = 0;
if (selIterator->GetEntries() > 0) {
- selCmds = new Char_t*[selIterator->GetEntries()];
+ selCmds = new TString[selIterator->GetEntries()];
mSelType = new AliEveListAnalyserMacroType[selIterator->GetEntries()];
}
TClass** mSelObjectType = 0;
+ TClass** mSelObjectType2 = 0;
if (selIterator->GetEntries() > 0) {
mSelObjectType = new TClass*[selIterator->GetEntries()];
+ mSelObjectType2 = new TClass*[selIterator->GetEntries()];
}
Bool_t selectedByCorrSelMacro = kFALSE;
TEveElement* object1 = 0;
TEveElement* object2 = 0;
+ TH1* returnedHist = 0x0;
// 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){
printf("AliEveListAnalyser: Checking process macro: %s\n", macro->GetName());
#endif
- // Find the object type of the macro
+ // Find the object types of the macro
mProcObjectType[i] = macro->GetObjectType();
+ mProcObjectType2[i] = macro->GetObjectType2();
// Find the type of the process macro
macroType = macro->GetType();
mProcType[i] = macroType;
numHistoMacros++;
// Create the command
- sprintf(procCmds[i], macro->GetCmd());
+ 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());
+ procCmds[i] = macro->GetCmd();
// Add to "data-from-list"
fDataFromMacroList->Add(new TObjString(macro->GetName()));
// 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){
printf("AliEveListAnalyser: Checking selection macro: %s\n", macro->GetName());
#endif
- // Find the object type of the macro
+ // Find the object types of the macro
mSelObjectType[i] = macro->GetObjectType();
+ mSelObjectType2[i] = macro->GetObjectType2();
// Find the type of the process macro
macroType = macro->GetType();
// Single Object select macro
if (macroType == kSingleObjectSelect) {
- // Has already been processed by ApplySTSelectionMacros(...)
+ // Has already been processed by ApplySOSelectionMacros(...)
mSelType[i] = macroType;
}
// Correlated Objects select macro
mSelType[i] = macroType;
// Create the command
- sprintf(selCmds[i], macro->GetCmd());
+ selCmds[i] = macro->GetCmd();
} else {
Error("Apply process macros",
Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a selection macro!",
if (numHistoMacros > 0) histos = new TH1*[numHistoMacros];
for (Int_t i = 0; i < numHistoMacros; i++) histos[i] = 0x0;
+ Bool_t secondBeforeFirstObject = kTRUE;
+
- //////////////////////////////////
- // WALK THROUGH THE LIST OF OBJECTS
- //////////////////////////////////
+ //////////////////////////////////////
+ // WALK THROUGH THE LIST OF OBJECTS //
+ //////////////////////////////////////
for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter){
if(!(object1 = dynamic_cast<TEveElement*>(*iter))) continue;
if (!object1->GetRnrState()) continue;
// Cast to the "real" object behind
- gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object1));
+ gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)%p;", (void*)object1));
gROOT->ProcessLineSync("TObject* automaticObject_1 = (TObject*)automaticEveElement->GetUserData();");
// Collect data for each macro
// Single object histo
if (mProcType[i] == kSingleObjectHisto){
- histos[histoIndex++] = (TH1*)gROOT->ProcessLineSync(procCmds[i]);
+ returnedHist = (TH1*)gROOT->ProcessLineSync(procCmds[i]);
+ if (returnedHist)
+ {
+ if (!histos[histoIndex]) histos[histoIndex] = returnedHist;
+ else
+ {
+ histos[histoIndex]->Add((const TH1*)returnedHist);
+ delete returnedHist;
+ returnedHist = 0;
+ }
+ }
+ histoIndex++;
// 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)
+ // To get all pairs, do the second loop over all objects.
+ // But: If a macro takes 2 pointers of the same type, we must take care that one gets the same pair, when we exchange the objects
+ // (this is not true, if we have different types - even if they inherit from the same classes!).
+ // Thus: If the latter case occurs, we ignore an object pair, if the second object is BEFORE the first object in the list.
+ // Since then the pair has already been taken into account.
+ // Furthermore, 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)
+
+ secondBeforeFirstObject = kTRUE;
+ for (TEveElement::List_i iter2 = this->BeginChildren(); iter2 != this->EndChildren(); ++iter2)
{
+ // If the objects are the same, it is not a pair -> continue. From now on: 2nd object BEHIND the 1st object in the list!
+ if (iter == iter2)
+ {
+ secondBeforeFirstObject = kFALSE;
+ continue;
+ }
if(!(object2 = dynamic_cast<TEveElement*>(*iter2))) continue;
// Skip objects that have not been selected
if (!object2->GetRnrState()) continue;
// Same check of the macro object type as before
- if (((TObject*)object2->GetUserData())->IsA() != mProcObjectType[i] &&
- !((TObject*)object2->GetUserData())->InheritsFrom(mProcObjectType[i])) continue;
+ if (((TObject*)object2->GetUserData())->IsA() != mProcObjectType2[i] &&
+ !((TObject*)object2->GetUserData())->InheritsFrom(mProcObjectType2[i])) continue;
+ // Do not process object pairs twice
+ if (secondBeforeFirstObject)
+ {
+ if (mProcObjectType[i] == mProcObjectType2[i]) continue;
+ }
// Cast to the "real" object behind
- gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object2));
+ gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)%p;", (void*)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!)
// Note: Again, via selCmds[i], the automatic objects are casted to the correct type!
if (((TObject*)object1->GetUserData())->IsA() != mSelObjectType[j] &&
!((TObject*)object1->GetUserData())->InheritsFrom(mSelObjectType[j])) continue;
- if (((TObject*)object2->GetUserData())->IsA() != mSelObjectType[j] &&
- !((TObject*)object2->GetUserData())->InheritsFrom(mSelObjectType[j])) continue;
+ if (((TObject*)object2->GetUserData())->IsA() != mSelObjectType2[j] &&
+ !((TObject*)object2->GetUserData())->InheritsFrom(mSelObjectType2[j])) continue;
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]);
+
+ returnedHist = (TH1*)gROOT->ProcessLineSync(procCmds[i]);
+ if (returnedHist)
+ {
+ if (!histos[histoIndex]) histos[histoIndex] = returnedHist;
+ else
+ {
+ histos[histoIndex]->Add((const TH1*)returnedHist);
+
+ delete returnedHist;
+ returnedHist = 0;
+ }
+ }
}
histoIndex++;
}
}
// 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)
+ // To get all pairs, do the second loop over all objects.
+ // But: If a macro takes 2 pointers of the same type, we must take care that one gets the same pair, when we exchange the objects
+ // (this is not true, if we have different types - even if they inherit from the same classes!).
+ // Thus: If the latter case occurs, we ignore an object pair, if the second object is BEFORE the first object in the list.
+ // Since then the pair has already been taken into account.
+ // Furthermore, 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) {
+ secondBeforeFirstObject = kTRUE;
+ for (TEveElement::List_i iter2 = this->BeginChildren(); iter2 != this->EndChildren(); ++iter2)
+ {
+ // If the objects are the same, it is not a pair -> continue. From now on: 2nd object BEHIND the 1st object in the list!
+ if (iter == iter2)
+ {
+ secondBeforeFirstObject = kFALSE;
+ continue;
+ }
if(!(object2 = dynamic_cast<TEveElement*>(*iter2))) continue;
// Skip objects that have not been selected
if (!object2->GetRnrState()) continue;
// Same check of the macro object type as before
- if (((TObject*)object2->GetUserData())->IsA() != mProcObjectType[i] &&
- !((TObject*)object2->GetUserData())->InheritsFrom(mProcObjectType[i])) continue;
+ if (((TObject*)object2->GetUserData())->IsA() != mProcObjectType2[i] &&
+ !((TObject*)object2->GetUserData())->InheritsFrom(mProcObjectType2[i])) continue;
+ // Do not process object pairs twice
+ if (secondBeforeFirstObject)
+ {
+ if (mProcObjectType[i] == mProcObjectType2[i]) continue;
+ }
// Cast to the "real" object behind
- gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object2));
+ gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)%p;", (void*)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!)
for (Int_t j = 0; j < selIterator->GetEntries(); j++) {
if (mSelType[j] == kCorrelObjectSelect) {
// Check, whether the macro can deal with both objects. If not, skip it.
- // Note: Again, via selCmds[i], the automatic objects are casted to the correct type!
+ // Note: Again, via selCmds[i], the automatic objects are casted to the correct type!
if (((TObject*)object1->GetUserData())->IsA() != mSelObjectType[j] &&
!((TObject*)object1->GetUserData())->InheritsFrom(mSelObjectType[j])) continue;
- if (((TObject*)object2->GetUserData())->IsA() != mSelObjectType[j] &&
- !((TObject*)object2->GetUserData())->InheritsFrom(mSelObjectType[j])) continue;
+ if (((TObject*)object2->GetUserData())->IsA() != mSelObjectType2[j] &&
+ !((TObject*)object2->GetUserData())->InheritsFrom(mSelObjectType2[j])) continue;
selectedByCorrSelMacro = (Bool_t)gROOT->ProcessLineSync(selCmds[j]);
if (!selectedByCorrSelMacro) break;
if (procCmds != 0) delete [] procCmds;
procCmds = 0;
- if (mProcObjectType != 0) delete mProcObjectType;
+ if (mProcObjectType != 0) delete [] mProcObjectType;
mProcObjectType = 0;
- if (mProcType != 0) delete mProcType;
+ if (mProcObjectType2 != 0) delete [] mProcObjectType2;
+ mProcObjectType2 = 0;
+ if (mProcType != 0) delete [] mProcType;
mProcType = 0;
if (selCmds != 0) delete [] selCmds;
selCmds = 0;
- if (mSelObjectType != 0) delete mSelObjectType;
+ if (mSelObjectType != 0) delete [] mSelObjectType;
mSelObjectType = 0;
- if (mSelType != 0) delete mSelType;
+ if (mSelObjectType2 != 0) delete [] mSelObjectType2;
+ mSelObjectType2 = 0;
+ if (mSelType != 0) delete [] mSelType;
mSelType = 0;
if (histos != 0) delete [] histos;
}
//______________________________________________________
-void AliEveListAnalyser::ApplySTSelectionMacros(const TList* iterator)
+void AliEveListAnalyser::ApplySOSelectionMacros(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.
+ // "SO" 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;
!((TObject*)object1->GetUserData())->InheritsFrom(macro->GetObjectType())) continue;
// Cast to the "real" object behind
- gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)0x%xl;", object1));
+ gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)%p;", (void*)object1));
gROOT->ProcessLineSync("TObject* automaticObject_1 = (TObject*)automaticEveElement->GetUserData();");
// GetCmd() will cast the automatic objects to the correct type for each macro!
}
//______________________________________________________
-AliEveListAnalyser::AliEveListAnalyserMacroType AliEveListAnalyser::GetMacroType(const Char_t* name, const Char_t* objectType, Bool_t UseList) const
+TClass* AliEveListAnalyser::GetMacroObjectType(const Char_t* name, Int_t argNum) const
+{
+ // Returns the type of object (of argument argNum) the macro with name "name" is dealing with;
+ // e.g. if you have the signature:
+ // void MyMacro(const AliTRDtrackV1* track, Double_t* &results, Int_t& nResults)
+ // the call 'GetMacroObjectType("MyMacro")' yields the AliTRDtrackV1-class.
+ // If the macro is not found (or there is an error), 0x0 is returned.
+
+ if (argNum - 1 < 0) return 0x0;
+
+ 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(argNum - 1);
+
+ if (m) return TClass::GetClass(m->GetTypeName());
+ }
+ }
+
+ // Error
+ return 0x0;
+}
+
+//______________________________________________________
+AliEveListAnalyser::AliEveListAnalyserMacroType AliEveListAnalyser::GetMacroType(const Char_t* name, const Char_t* objectType,
+ const Char_t* objectType2, Bool_t UseList) const
{
- // Returns the type of the corresponding macro, that accepts pointers of the class "objectType" as a parametre.
+ // Returns the type of the corresponding macro, that accepts pointers of the classes "objectType" (first pointer) and
+ // objectType2" (second pointer) as parametres.
// 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
AliEveListAnalyserMacroType type = kUnknown;
TString* typeStr = 0;
+ TString* typeStr2 = 0;
if (objectType != 0)
{
{
typeStr = new TString("TObject");
}
+ if (objectType2 != 0)
+ {
+ typeStr2 = new TString(objectType2);
+ // Remove white-spaces
+ typeStr2->ReplaceAll(" ", "");
+ }
+ else
+ {
+ typeStr2 = new TString("TObject");
+ }
TString* mangled1Str = new TString();
TString* mangled2Str = new TString();
// 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 'OBJECTTYPE2'*"
+ mangled3Str->Append("const ").Append(*typeStr).Append("*, const ").Append(*typeStr2).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 "const 'OBJECTTYPE'*, const 'OBJECTTYPE2'*, Double_t*&, Int_t&"
+ mangled4Str->Append("const ").Append(*typeStr).Append("*, const ").Append(*typeStr2).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");
+ // We want "cOconstsP'OBJECTTYPE2'mUsP"
+ mangledArg2Str->Append("cOconstsP").Append(*typeStr2).Append("mUsP");
// Re-do the check of the macro type
if (!UseList){
delete typeStr;
typeStr = 0;
}
+ if (typeStr2 != 0)
+ {
+ typeStr2->Clear();
+ delete typeStr2;
+ typeStr2 = 0;
+ }
return type;
}
-// TODO: DOCUMENTATION
+
+/*
//______________________________________________________
-TClass* AliEveListAnalyser::GetMacroObjectType(const Char_t* name) const
+void AliEveListAnalyser::RemovePrimSelectedObjects()
{
- TFunction* f = gROOT->GetGlobalFunction(name, 0 , kTRUE);
- TMethodArg* m = 0;
- TList* list = 0;
+ // Removes the (primarily) selected objects in the viewer from the list (objects that are already in the list are ignored).
+ // Hold the CTRL-key for multiple selection.
- if (f)
+ TEveSelection* eveSel = gEve->GetSelection();
+
+ if (!eveSel)
{
- list = f->GetListOfMethodArgs();
-
- if (!list->IsEmpty())
- {
- m = (TMethodArg*)list->At(0);
+ Error("AliEveListAnalyser::RemovePrimSelectedObjects", "Failed to get the selection!\n");
+ return;
+ }
+
+ TEveElement* elem = 0x0;
+ Bool_t changedSomething = kFALSE;
- if (m) return TClass::GetClass(m->GetTypeName());
+ for (TEveElement::List_i iter = eveSel->BeginChildren(); iter != eveSel->EndChildren(); ++iter)
+ {
+ if(!(elem = dynamic_cast<TEveElement*>(*iter))) continue;
+
+ // Check, if element is already there. If so, remove it!
+ if (this->HasChild(elem) && elem != this)
+ {
+ this->RemoveElement(elem);
+ this->SetTitle(Form("Objects %d", this->NumChildren()));
+ changedSomething = kTRUE;
}
- }
+ }
- // Error
- return 0x0;
+ if (changedSomething) gEve->Redraw3D();
}
+*/
//______________________________________________________
void AliEveListAnalyser::RemoveSelectedMacros(const TList* iterator)
//______________________________________________________
void AliEveListAnalyser::ResetObjectList()
{
- // Remove all objects from the list.
+ // Removes all objects from the list.
RemoveElements();
+ this->SetTitle(Form("Objects %d", this->NumChildren()));
}
//______________________________________________________
Bool_t AliEveListAnalyser::StartAddingObjects()
{
- // Start adding objects for the analysis. Returns kTRUE on success.
+ // Starts adding objects for the analysis. Returns kTRUE on success.
if (fConnected == kFALSE)
{
- fConnected = TQObject::Connect("TEvePointSet", "PointSelected(Int_t)", "AliEveListAnalyser", this, "AddObjectToList(Int_t)");
- //fConnected = TQObject::Connect("TEvePointSet", "Message(char*)", "AliEveListAnalyser", this, "AddObjectToList(char*)");
+ fConnected = TQObject::Connect("TEvePointSet", "PointSelected(Int_t)", "AliEveListAnalyser", this, "AddSecSelectedSingleObjectToList(Int_t)");
+ if (fConnected) fConnected = TQObject::Connect(gEve->GetSelection(), "SelectionAdded(TEveElement*)", "AliEveListAnalyser", this, "AddPrimSelectedObject(TEveElement*)");
+
if (fConnected) return kTRUE;
Error("AliEveListAnalyser::StartAddingObjects", "Connection failed!");
+
+ // Connection of 2nd signal failed, but first connection succeeded -> Disconnect 1st signal.
+ TQObject::Disconnect("TEvePointSet", "PointSelected(Int_t)", this, "AddObjectToList(Int_t)");
}
return kFALSE;
//______________________________________________________
Bool_t AliEveListAnalyser::StopAddingObjects()
{
- // Stop adding objects for the analysis. Returns kTRUE on success.
+ // Stops adding objects for the analysis. Returns kTRUE on success.
if (fConnected)
{
- //if (TQObject::Disconnect("TEvePointSet", "AddObjectToList(Char_t*)")) fConnected = kFALSE;
- if (TQObject::Disconnect("TEvePointSet", "PointSelected(Int_t)", this, "AddObjectToList(Int_t)"))
- {
- fConnected = kFALSE;
- return kTRUE;
- }
+ Bool_t dis1 = kFALSE, dis2 = kFALSE;
+ dis1 = TQObject::Disconnect("TEvePointSet", "PointSelected(Int_t)", this, "AddSecSelectedSingleObjectToList(Int_t)");
+ dis2 = TQObject::Disconnect(gEve->GetSelection(), "SelectionAdded(TEveElement*)", this, "AddPrimSelectedObject(TEveElement*)");
+
+ if (dis1 || dis2) fConnected = kFALSE;
+ if (dis1 && dis2) return kTRUE;
else
{
Error("AliEveListAnalyser::StopAddingObjects", "Disconnection failed!");
+
return kFALSE;
}
}