]>
Commit | Line | Data |
---|---|---|
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 | 87 | ClassImp(AliEveListAnalyser) |
88 | ||
89 | /////////////////////////////////////////////////////////// | |
ce239ca6 | 90 | ///////////// AliEveListAnalyser //////////////////////// |
00dc25ef | 91 | /////////////////////////////////////////////////////////// |
92 | AliEveListAnalyser::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 | //______________________________________________________ | |
124 | AliEveListAnalyser::~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 | //______________________________________________________ | |
161 | Int_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 | 258 | Bool_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 | 306 | Int_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 | //______________________________________________________ | |
383 | void 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 | //______________________________________________________ | |
416 | void 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 | //______________________________________________________ |
491 | void 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 | //______________________________________________________ | |
505 | Bool_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 | 924 | void 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 | 1007 | TClass* 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 | 1038 | AliEveListAnalyser::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 | 1250 | void 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 | //______________________________________________________ | |
1284 | void 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 | //______________________________________________________ | |
1328 | void 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 | //______________________________________________________ | |
1337 | Bool_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 | //______________________________________________________ | |
1358 | Bool_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 | } |