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