]>
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 | ||
84 | #include <EveDet/AliEveListAnalyser.h> | |
85 | #include <EveDet/AliEveListAnalyserEditor.h> | |
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); | |
182 | sprintf(pathname, "%s/%s", systemPath, nameC); | |
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 | { | |
319 | Error("AliEveListAnalyser::AddPrimSelectedObject", "Zero pointer!\n"); | |
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 | { | |
ce239ca6 | 425 | Error("AliEveListAnalyser::AddSecSelectedSingleObjectToList", "Zero pointer!\n"); |
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 | |
523 | if (fDataTree == 0x0){ | |
524 | TDirectory *cwd = gDirectory; | |
525 | fDataTree = new TTreeSRedirector(Form("/tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER"))); | |
526 | cwd->cd(); | |
527 | } | |
528 | if (!fDataTree){ | |
529 | Error("Apply process macros", Form("File \"/tmp/ListAnalyserMacroData_%s.root\" could not be accessed properly!", | |
530 | gSystem->Getenv("USER"))); | |
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; | |
542 | ||
543 | ||
544 | TGeneralMacroData* macro = 0; | |
545 | ||
d52fea52 | 546 | TString* procCmds = 0; |
00dc25ef | 547 | AliEveListAnalyserMacroType* mProcType = 0; |
548 | if (procIterator->GetEntries() > 0) { | |
d52fea52 | 549 | procCmds = new TString[procIterator->GetEntries()]; |
00dc25ef | 550 | mProcType = new AliEveListAnalyserMacroType[procIterator->GetEntries()]; |
551 | } | |
6e420565 | 552 | |
6e420565 | 553 | TClass** mProcObjectType = 0; |
004e0620 | 554 | TClass** mProcObjectType2 = 0; |
6e420565 | 555 | if (procIterator->GetEntries() > 0) { |
556 | mProcObjectType = new TClass*[procIterator->GetEntries()]; | |
004e0620 | 557 | mProcObjectType2 = new TClass*[procIterator->GetEntries()]; |
6e420565 | 558 | } |
00dc25ef | 559 | |
d52fea52 | 560 | TString* selCmds = 0; |
00dc25ef | 561 | AliEveListAnalyserMacroType* mSelType = 0; |
562 | if (selIterator->GetEntries() > 0) { | |
d52fea52 | 563 | selCmds = new TString[selIterator->GetEntries()]; |
00dc25ef | 564 | mSelType = new AliEveListAnalyserMacroType[selIterator->GetEntries()]; |
565 | } | |
6e420565 | 566 | |
6e420565 | 567 | TClass** mSelObjectType = 0; |
004e0620 | 568 | TClass** mSelObjectType2 = 0; |
6e420565 | 569 | if (selIterator->GetEntries() > 0) { |
570 | mSelObjectType = new TClass*[selIterator->GetEntries()]; | |
004e0620 | 571 | mSelObjectType2 = new TClass*[selIterator->GetEntries()]; |
6e420565 | 572 | } |
00dc25ef | 573 | |
574 | Bool_t selectedByCorrSelMacro = kFALSE; | |
575 | ||
576 | AliEveListAnalyserMacroType macroType = kUnknown; | |
577 | Int_t numHistoMacros = 0; | |
578 | TH1** histos = 0; | |
579 | ||
580 | TEveElement* object1 = 0; | |
581 | TEveElement* object2 = 0; | |
c1869a7c | 582 | TH1* returnedHist = 0x0; |
00dc25ef | 583 | |
584 | // Collect the commands for each process macro and add them to "data-from-list" | |
585 | for (Int_t i = 0; i < procIterator->GetEntries(); i++){ | |
00dc25ef | 586 | macro = (TGeneralMacroData*)fMacroList->GetValue(procIterator->At(i)->GetTitle()); |
587 | ||
588 | if (!macro){ | |
589 | Error("Apply process macros", | |
590 | Form("Macro list is corrupted: Macro \"%s\" is not registered!", | |
591 | procIterator->At(i)->GetTitle())); | |
592 | continue; | |
593 | } | |
594 | ||
595 | #ifdef AliEveListAnalyser_DEBUG | |
596 | printf("AliEveListAnalyser: Checking process macro: %s\n", macro->GetName()); | |
597 | #endif | |
598 | ||
004e0620 | 599 | // Find the object types of the macro |
6e420565 | 600 | mProcObjectType[i] = macro->GetObjectType(); |
004e0620 | 601 | mProcObjectType2[i] = macro->GetObjectType2(); |
6e420565 | 602 | |
00dc25ef | 603 | // Find the type of the process macro |
604 | macroType = macro->GetType(); | |
605 | if (macroType == kSingleObjectHisto || macroType == kCorrelObjectHisto){ | |
606 | mProcType[i] = macroType; | |
607 | numHistoMacros++; | |
608 | // Create the command | |
d52fea52 | 609 | procCmds[i] = macro->GetCmd(); |
00dc25ef | 610 | |
611 | // Add to "data-from-list" -> Mark as a histo macro with the substring "(histo macro)" | |
612 | fDataFromMacroList->Add(new TObjString(Form("%s (histo macro)", macro->GetName()))); | |
613 | } else if (macroType == kSingleObjectAnalyse || macroType == kCorrelObjectAnalyse) { | |
614 | mProcType[i] = macroType; | |
615 | // Create the command | |
d52fea52 | 616 | procCmds[i] = macro->GetCmd(); |
00dc25ef | 617 | |
618 | // Add to "data-from-list" | |
619 | fDataFromMacroList->Add(new TObjString(macro->GetName())); | |
620 | } else { | |
621 | Error("Apply process macros", | |
622 | Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a process macro!", | |
623 | macro->GetPath(), macro->GetName())); | |
624 | mProcType[i] = kUnknown; | |
625 | } | |
626 | } | |
627 | ||
628 | // Collect the commands for each selection macro and add them to "data-from-list" | |
629 | for (Int_t i = 0; i < selIterator->GetEntries(); i++){ | |
00dc25ef | 630 | macro = (TGeneralMacroData*)fMacroList->GetValue(selIterator->At(i)->GetTitle()); |
631 | ||
632 | if (!macro){ | |
633 | Error("Apply process macros", | |
634 | Form("Macro list is corrupted: Macro \"%s\" is not registered!", | |
635 | selIterator->At(i)->GetTitle())); | |
636 | continue; | |
637 | } | |
638 | ||
639 | #ifdef AliEveListAnalyser_DEBUG | |
640 | printf("AliEveListAnalyser: Checking selection macro: %s\n", macro->GetName()); | |
641 | #endif | |
6e420565 | 642 | |
004e0620 | 643 | // Find the object types of the macro |
6e420565 | 644 | mSelObjectType[i] = macro->GetObjectType(); |
004e0620 | 645 | mSelObjectType2[i] = macro->GetObjectType2(); |
00dc25ef | 646 | |
647 | // Find the type of the process macro | |
648 | macroType = macro->GetType(); | |
649 | ||
650 | // Single Object select macro | |
651 | if (macroType == kSingleObjectSelect) { | |
004e0620 | 652 | // Has already been processed by ApplySOSelectionMacros(...) |
00dc25ef | 653 | mSelType[i] = macroType; |
654 | } | |
655 | // Correlated Objects select macro | |
656 | else if (macroType == kCorrelObjectSelect) { | |
657 | mSelType[i] = macroType; | |
658 | ||
659 | // Create the command | |
d52fea52 | 660 | selCmds[i] = macro->GetCmd(); |
00dc25ef | 661 | } else { |
662 | Error("Apply process macros", | |
663 | Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a selection macro!", | |
664 | macro->GetPath(), macro->GetName())); | |
665 | mSelType[i] = kUnknown; | |
666 | } | |
667 | } | |
668 | ||
669 | // Allocate memory for the histograms | |
670 | if (numHistoMacros > 0) histos = new TH1*[numHistoMacros]; | |
671 | for (Int_t i = 0; i < numHistoMacros; i++) histos[i] = 0x0; | |
672 | ||
004e0620 | 673 | Bool_t secondBeforeFirstObject = kTRUE; |
674 | ||
675 | ||
ce239ca6 | 676 | ////////////////////////////////////// |
677 | // WALK THROUGH THE LIST OF OBJECTS // | |
678 | ////////////////////////////////////// | |
00dc25ef | 679 | for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter){ |
680 | if(!(object1 = dynamic_cast<TEveElement*>(*iter))) continue; | |
681 | ||
682 | // Skip objects that have not been selected | |
683 | if (!object1->GetRnrState()) continue; | |
684 | ||
685 | // Cast to the "real" object behind | |
c51e9ba0 | 686 | gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)%p;", (void*)object1)); |
00dc25ef | 687 | gROOT->ProcessLineSync("TObject* automaticObject_1 = (TObject*)automaticEveElement->GetUserData();"); |
688 | ||
689 | // Collect data for each macro | |
690 | for (Int_t i = 0, histoIndex = 0; i < procIterator->GetEntries(); i++){ | |
6e420565 | 691 | // Find the type of the object and relate it to the macro object type |
692 | // Only apply macro to this object, if... | |
693 | // ... the macro takes objects of exactly this type. | |
694 | // ... the macro object type is a child of this object's type. | |
695 | // Otherwise: Continue | |
696 | ||
697 | // Finally, via procCmds[i], the automatic objects are casted to the correct type and analysed by each macro! | |
698 | if (((TObject*)object1->GetUserData())->IsA() != mProcObjectType[i] && | |
699 | !((TObject*)object1->GetUserData())->InheritsFrom(mProcObjectType[i])) continue; | |
700 | ||
701 | ||
00dc25ef | 702 | // Single object histo |
703 | if (mProcType[i] == kSingleObjectHisto){ | |
c1869a7c | 704 | returnedHist = (TH1*)gROOT->ProcessLineSync(procCmds[i]); |
705 | if (returnedHist) | |
706 | { | |
707 | if (!histos[histoIndex]) histos[histoIndex] = returnedHist; | |
708 | else | |
709 | { | |
710 | histos[histoIndex]->Add((const TH1*)returnedHist); | |
711 | delete returnedHist; | |
712 | returnedHist = 0; | |
713 | } | |
714 | } | |
715 | histoIndex++; | |
00dc25ef | 716 | // Correlated Objects histo |
717 | } else if (mProcType[i] == kCorrelObjectHisto) { | |
004e0620 | 718 | // To get all pairs, do the second loop over all objects. |
719 | // 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 | |
720 | // (this is not true, if we have different types - even if they inherit from the same classes!). | |
721 | // Thus: If the latter case occurs, we ignore an object pair, if the second object is BEFORE the first object in the list. | |
722 | // Since then the pair has already been taken into account. | |
723 | // Furthermore, we have a pair of objects, if and only if both objects of the pair are selected (Rnr-state) | |
00dc25ef | 724 | // and are not equal. |
725 | // The correlated objects process macro will be applied to all pairs that will be additionally selected by | |
726 | // all correlated objects selection macros. | |
004e0620 | 727 | |
728 | secondBeforeFirstObject = kTRUE; | |
729 | for (TEveElement::List_i iter2 = this->BeginChildren(); iter2 != this->EndChildren(); ++iter2) | |
00dc25ef | 730 | { |
004e0620 | 731 | // If the objects are the same, it is not a pair -> continue. From now on: 2nd object BEHIND the 1st object in the list! |
732 | if (iter == iter2) | |
733 | { | |
734 | secondBeforeFirstObject = kFALSE; | |
735 | continue; | |
736 | } | |
00dc25ef | 737 | if(!(object2 = dynamic_cast<TEveElement*>(*iter2))) continue; |
738 | ||
739 | // Skip objects that have not been selected | |
740 | if (!object2->GetRnrState()) continue; | |
6e420565 | 741 | |
6e420565 | 742 | // Same check of the macro object type as before |
004e0620 | 743 | if (((TObject*)object2->GetUserData())->IsA() != mProcObjectType2[i] && |
744 | !((TObject*)object2->GetUserData())->InheritsFrom(mProcObjectType2[i])) continue; | |
745 | // Do not process object pairs twice | |
746 | if (secondBeforeFirstObject) | |
747 | { | |
748 | if (mProcObjectType[i] == mProcObjectType2[i]) continue; | |
749 | } | |
00dc25ef | 750 | |
751 | // Cast to the "real" object behind | |
c51e9ba0 | 752 | gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)%p;", (void*)object2)); |
00dc25ef | 753 | gROOT->ProcessLineSync("TObject* automaticObject_2 = (TObject*)automaticEveElement->GetUserData();"); |
754 | ||
755 | // Select object by default (so it will be processed, if there are no correlated objects selection macros!) | |
756 | selectedByCorrSelMacro = kTRUE; | |
757 | for (Int_t j = 0; j < selIterator->GetEntries(); j++){ | |
758 | if (mSelType[j] == kCorrelObjectSelect){ | |
6e420565 | 759 | // Check, whether the macro can deal with both objects. If not, skip it. |
760 | // Note: Again, via selCmds[i], the automatic objects are casted to the correct type! | |
761 | if (((TObject*)object1->GetUserData())->IsA() != mSelObjectType[j] && | |
762 | !((TObject*)object1->GetUserData())->InheritsFrom(mSelObjectType[j])) continue; | |
004e0620 | 763 | if (((TObject*)object2->GetUserData())->IsA() != mSelObjectType2[j] && |
764 | !((TObject*)object2->GetUserData())->InheritsFrom(mSelObjectType2[j])) continue; | |
6e420565 | 765 | |
00dc25ef | 766 | selectedByCorrSelMacro = (Bool_t)gROOT->ProcessLineSync(selCmds[j]); |
c1869a7c | 767 | if (!selectedByCorrSelMacro) break; |
00dc25ef | 768 | } |
769 | } | |
770 | ||
771 | // If the pair has not been selected by the correlated objects selection macros, skip it! | |
772 | if (!selectedByCorrSelMacro) continue; | |
c1869a7c | 773 | |
774 | returnedHist = (TH1*)gROOT->ProcessLineSync(procCmds[i]); | |
775 | if (returnedHist) | |
776 | { | |
777 | if (!histos[histoIndex]) histos[histoIndex] = returnedHist; | |
778 | else | |
779 | { | |
780 | histos[histoIndex]->Add((const TH1*)returnedHist); | |
781 | ||
782 | delete returnedHist; | |
783 | returnedHist = 0; | |
784 | } | |
785 | } | |
00dc25ef | 786 | } |
787 | histoIndex++; | |
788 | } | |
789 | // Single object analyse | |
790 | else if (mProcType[i] == kSingleObjectAnalyse) { | |
791 | // Create data pointers in CINT, execute the macro and get the data | |
792 | gROOT->ProcessLineSync("Double_t* results = 0;"); | |
793 | gROOT->ProcessLineSync("Int_t n = 0;"); | |
794 | gROOT->ProcessLineSync(procCmds[i]); | |
795 | Double_t* results = (Double_t*)gROOT->ProcessLineSync("results;"); | |
796 | Int_t nResults = (Int_t)gROOT->ProcessLineSync("n;"); | |
797 | ||
798 | if (results == 0) { | |
799 | Error("Apply macros", Form("Error reading data from macro \"%s\"", procIterator->At(i)->GetTitle())); | |
800 | continue; | |
801 | } | |
802 | for (Int_t resInd = 0; resInd < nResults; resInd++){ | |
803 | (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << results[resInd] << (Char_t*)"\n"; | |
804 | } | |
805 | ||
806 | delete results; | |
807 | results = 0; | |
808 | } | |
809 | // Correlated objects analyse | |
810 | else if (mProcType[i] == kCorrelObjectAnalyse){ | |
004e0620 | 811 | // To get all pairs, do the second loop over all objects. |
812 | // 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 | |
813 | // (this is not true, if we have different types - even if they inherit from the same classes!). | |
814 | // Thus: If the latter case occurs, we ignore an object pair, if the second object is BEFORE the first object in the list. | |
815 | // Since then the pair has already been taken into account. | |
816 | // Furthermore, we have a pair of objects, if and only if both objects of the pair are selected (Rnr-state) | |
00dc25ef | 817 | // and are not equal. |
818 | // The correlated objects process macro will be applied to all pairs that will be additionally selected by | |
819 | // all correlated objects selection macros. | |
00dc25ef | 820 | |
004e0620 | 821 | secondBeforeFirstObject = kTRUE; |
822 | for (TEveElement::List_i iter2 = this->BeginChildren(); iter2 != this->EndChildren(); ++iter2) | |
823 | { | |
824 | // If the objects are the same, it is not a pair -> continue. From now on: 2nd object BEHIND the 1st object in the list! | |
825 | if (iter == iter2) | |
826 | { | |
827 | secondBeforeFirstObject = kFALSE; | |
828 | continue; | |
829 | } | |
00dc25ef | 830 | if(!(object2 = dynamic_cast<TEveElement*>(*iter2))) continue; |
831 | ||
832 | // Skip objects that have not been selected | |
833 | if (!object2->GetRnrState()) continue; | |
6e420565 | 834 | |
6e420565 | 835 | // Same check of the macro object type as before |
004e0620 | 836 | if (((TObject*)object2->GetUserData())->IsA() != mProcObjectType2[i] && |
837 | !((TObject*)object2->GetUserData())->InheritsFrom(mProcObjectType2[i])) continue; | |
838 | // Do not process object pairs twice | |
839 | if (secondBeforeFirstObject) | |
840 | { | |
841 | if (mProcObjectType[i] == mProcObjectType2[i]) continue; | |
842 | } | |
00dc25ef | 843 | |
844 | // Cast to the "real" object behind | |
c51e9ba0 | 845 | gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)%p;", (void*)object2)); |
00dc25ef | 846 | gROOT->ProcessLineSync("TObject* automaticObject_2 = (TObject*)automaticEveElement->GetUserData();"); |
847 | ||
848 | // Select object by default (so it will be processed, if there are no correlated objects selection macros!) | |
849 | selectedByCorrSelMacro = kTRUE; | |
850 | for (Int_t j = 0; j < selIterator->GetEntries(); j++) { | |
851 | if (mSelType[j] == kCorrelObjectSelect) { | |
6e420565 | 852 | // Check, whether the macro can deal with both objects. If not, skip it. |
004e0620 | 853 | // Note: Again, via selCmds[i], the automatic objects are casted to the correct type! |
6e420565 | 854 | if (((TObject*)object1->GetUserData())->IsA() != mSelObjectType[j] && |
855 | !((TObject*)object1->GetUserData())->InheritsFrom(mSelObjectType[j])) continue; | |
004e0620 | 856 | if (((TObject*)object2->GetUserData())->IsA() != mSelObjectType2[j] && |
857 | !((TObject*)object2->GetUserData())->InheritsFrom(mSelObjectType2[j])) continue; | |
6e420565 | 858 | |
00dc25ef | 859 | selectedByCorrSelMacro = (Bool_t)gROOT->ProcessLineSync(selCmds[j]); |
860 | if (!selectedByCorrSelMacro) break; | |
861 | } | |
862 | } | |
863 | ||
864 | // If the pair has not been selected by the correlated objects selection macros, skip it! | |
865 | if (!selectedByCorrSelMacro) continue; | |
866 | ||
867 | // Create data pointers in CINT, execute the macro and get the data | |
868 | gROOT->ProcessLineSync("Double_t* results = 0;"); | |
869 | gROOT->ProcessLineSync("Int_t n = 0;"); | |
870 | gROOT->ProcessLineSync(procCmds[i]); | |
871 | Double_t* results = (Double_t*)gROOT->ProcessLineSync("results;"); | |
872 | Int_t nResults = (Int_t)gROOT->ProcessLineSync("n;"); | |
873 | ||
874 | if (results == 0) { | |
875 | Error("Apply macros", Form("Error reading data from macro \"%s\"", procIterator->At(i)->GetTitle())); | |
876 | continue; | |
877 | } | |
878 | for (Int_t resInd = 0; resInd < nResults; resInd++) { | |
879 | (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << results[resInd] << (Char_t*)"\n"; | |
880 | } | |
881 | ||
882 | delete results; | |
883 | results = 0; | |
884 | } | |
885 | } | |
886 | } | |
887 | } | |
888 | ||
889 | for (Int_t i = 0, histoIndex = 0; i < procIterator->GetEntries() && histoIndex < numHistoMacros; i++) { | |
890 | if (mProcType[i] == kSingleObjectHisto || mProcType[i] == kCorrelObjectHisto) { | |
891 | // Might be empty (e.g. no objects have been selected)! | |
892 | if (histos[histoIndex]) { | |
893 | (*fDataTree) << Form("ObjectData%d", i) << Form("Macro%d=", i) << histos[histoIndex] << (Char_t*)"\n"; | |
894 | } | |
895 | histoIndex++; | |
896 | } | |
897 | } | |
898 | ||
899 | if (fDataTree != 0) delete fDataTree; | |
900 | fDataTree = 0; | |
901 | ||
902 | if (procCmds != 0) delete [] procCmds; | |
903 | procCmds = 0; | |
6e420565 | 904 | if (mProcObjectType != 0) delete mProcObjectType; |
905 | mProcObjectType = 0; | |
004e0620 | 906 | if (mProcObjectType2 != 0) delete mProcObjectType2; |
907 | mProcObjectType2 = 0; | |
908 | if (mProcType != 0) delete [] mProcType; | |
00dc25ef | 909 | mProcType = 0; |
910 | ||
911 | if (selCmds != 0) delete [] selCmds; | |
912 | selCmds = 0; | |
6e420565 | 913 | if (mSelObjectType != 0) delete mSelObjectType; |
914 | mSelObjectType = 0; | |
004e0620 | 915 | if (mSelObjectType2 != 0) delete mSelObjectType2; |
916 | mSelObjectType2 = 0; | |
917 | if (mSelType != 0) delete [] mSelType; | |
00dc25ef | 918 | mSelType = 0; |
919 | ||
920 | if (histos != 0) delete [] histos; | |
921 | histos = 0; | |
922 | ||
923 | // Clear root | |
924 | // A.B. gROOT->Reset(); | |
925 | ||
926 | // If there is data, select the first data set | |
927 | if (procIterator->GetEntries() > 0) SETBIT(fHistoDataSelected, 0); | |
928 | ||
929 | // Now the data is stored in "/tmp/ListAnalyserMacroData_$USER.root" | |
930 | // The editor will access this file to display the data | |
931 | return kTRUE; | |
932 | } | |
933 | ||
934 | //______________________________________________________ | |
004e0620 | 935 | void AliEveListAnalyser::ApplySOSelectionMacros(const TList* iterator) |
00dc25ef | 936 | { |
937 | // Uses the iterator (for the selected selection macros) to apply the selected macros to the data. | |
938 | // The rnr-states of the objects are set according to the result of the macro calls (kTRUE, if all | |
939 | // macros return kTRUE for this object, otherwise: kFALSE). | |
004e0620 | 940 | // "SO" stands for "single object". This means that only single object selection macros are applied. |
00dc25ef | 941 | // Correlated objects selection macros will be used inside the call of ApplyProcessMacros(...)! |
942 | ||
943 | TGeneralMacroData* macro = 0; | |
944 | AliEveListAnalyserMacroType macroType = kUnknown; | |
945 | TEveElement* object1 = 0; | |
946 | Bool_t selectedByMacro = kFALSE; | |
947 | ||
948 | // Clear root | |
949 | // A.B. gROOT->Reset(); | |
950 | ||
951 | // Select all objecs at first. A object is then deselected, if at least one selection macro | |
952 | // returns kFALSE for this object. | |
953 | // Enable all objects (Note: EnableListElements(..) will call "ElementChanged", which will cause unforeseen behaviour!) | |
954 | for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter) ((TEveElement*)(*iter))->SetRnrState(kTRUE); | |
955 | SetRnrState(kTRUE); | |
956 | ||
957 | for (Int_t i = 0; i < iterator->GetEntries(); i++){ | |
958 | macro = (TGeneralMacroData*)fMacroList->GetValue(iterator->At(i)->GetTitle()); | |
959 | ||
960 | if (!macro){ | |
961 | Error("Apply selection macros", | |
962 | Form("Macro list is corrupted: Macro \"%s\" is not registered!", iterator->At(i)->GetTitle())); | |
963 | continue; | |
964 | } | |
965 | ||
966 | #ifdef AliEveListAnalyser_DEBUG | |
967 | printf("AliEveListAnalyser: Applying selection macro: %s\n", macro->GetName()); | |
968 | #endif | |
969 | ||
970 | // Determine macro type | |
971 | macroType = macro->GetType(); | |
972 | ||
973 | // Single object select macro | |
974 | if (macroType == kSingleObjectSelect){ | |
975 | // Walk through the list of objects | |
976 | for (TEveElement::List_i iter = this->BeginChildren(); iter != this->EndChildren(); ++iter) | |
977 | { | |
978 | object1 = dynamic_cast<TEveElement*>(*iter); | |
979 | ||
980 | if (!object1) continue; | |
981 | ||
982 | // If the object has already been deselected, nothing is to do here | |
983 | if (!object1->GetRnrState()) continue; | |
984 | ||
6e420565 | 985 | // Find the type of the object and relate it to the macro object type |
986 | // Only apply macro to this object, if... | |
987 | // ... the macro takes objects of exactly this type. | |
988 | // ... the macro object type is a child of this object's type. | |
989 | // Otherwise: Continue | |
990 | if (((TObject*)object1->GetUserData())->IsA() != macro->GetObjectType() && | |
991 | !((TObject*)object1->GetUserData())->InheritsFrom(macro->GetObjectType())) continue; | |
992 | ||
00dc25ef | 993 | // Cast to the "real" object behind |
c51e9ba0 | 994 | gROOT->ProcessLineSync(Form("TEveElement *automaticEveElement = (TEveElement*)%p;", (void*)object1)); |
00dc25ef | 995 | gROOT->ProcessLineSync("TObject* automaticObject_1 = (TObject*)automaticEveElement->GetUserData();"); |
996 | ||
6e420565 | 997 | // GetCmd() will cast the automatic objects to the correct type for each macro! |
00dc25ef | 998 | selectedByMacro = (Bool_t)gROOT->ProcessLineSync(macro->GetCmd()); |
999 | object1->SetRnrState(selectedByMacro && object1->GetRnrState()); | |
1000 | } | |
1001 | } | |
1002 | // Correlated objects select macro | |
1003 | else if (macroType == kCorrelObjectSelect){ | |
1004 | // Will be processed in ApplyProcessMacros(...) | |
1005 | continue; | |
1006 | } else { | |
1007 | Error("Apply selection macros", | |
1008 | Form("Macro list corrupted: Macro \"%s/%s.C\" is not registered as a selection macro!", | |
1009 | macro->GetPath(), macro->GetName())); | |
1010 | } | |
1011 | } | |
1012 | ||
1013 | // Clear root | |
1014 | // A.B. gROOT->Reset(); | |
1015 | } | |
1016 | ||
ce239ca6 | 1017 | //______________________________________________________ |
004e0620 | 1018 | TClass* AliEveListAnalyser::GetMacroObjectType(const Char_t* name, Int_t argNum) const |
ce239ca6 | 1019 | { |
004e0620 | 1020 | // Returns the type of object (of argument argNum) the macro with name "name" is dealing with; |
ce239ca6 | 1021 | // e.g. if you have the signature: |
1022 | // void MyMacro(const AliTRDtrackV1* track, Double_t* &results, Int_t& nResults) | |
1023 | // the call 'GetMacroObjectType("MyMacro")' yields the AliTRDtrackV1-class. | |
1024 | // If the macro is not found (or there is an error), 0x0 is returned. | |
1025 | ||
004e0620 | 1026 | if (argNum - 1 < 0) return 0x0; |
1027 | ||
ce239ca6 | 1028 | TFunction* f = gROOT->GetGlobalFunction(name, 0 , kTRUE); |
1029 | TMethodArg* m = 0; | |
1030 | TList* list = 0; | |
1031 | ||
1032 | if (f) | |
1033 | { | |
1034 | list = f->GetListOfMethodArgs(); | |
1035 | ||
1036 | if (!list->IsEmpty()) | |
1037 | { | |
004e0620 | 1038 | m = (TMethodArg*)list->At(argNum - 1); |
ce239ca6 | 1039 | |
1040 | if (m) return TClass::GetClass(m->GetTypeName()); | |
1041 | } | |
1042 | } | |
1043 | ||
1044 | // Error | |
1045 | return 0x0; | |
1046 | } | |
1047 | ||
00dc25ef | 1048 | //______________________________________________________ |
004e0620 | 1049 | AliEveListAnalyser::AliEveListAnalyserMacroType AliEveListAnalyser::GetMacroType(const Char_t* name, const Char_t* objectType, |
1050 | const Char_t* objectType2, Bool_t UseList) const | |
00dc25ef | 1051 | { |
004e0620 | 1052 | // Returns the type of the corresponding macro, that accepts pointers of the classes "objectType" (first pointer) and |
1053 | // objectType2" (second pointer) as parametres. | |
00dc25ef | 1054 | // If "UseList" is kTRUE, the type will be looked up in the internal list (very fast). But if this list |
1055 | // does not exist, you have to use kFALSE for this parameter. Then the type will be determined by the | |
1056 | // prototype! NOTE: It is assumed that the macro has been compiled! If not, the return value is not | |
1057 | // predictable, but normally will be kUnknown. | |
1058 | // Note: AddMacro(Fast) will update the internal list and RemoveMacros respectively. | |
1059 | ||
1060 | AliEveListAnalyserMacroType type = kUnknown; | |
1061 | ||
1062 | TString* typeStr = 0; | |
004e0620 | 1063 | TString* typeStr2 = 0; |
00dc25ef | 1064 | |
1065 | if (objectType != 0) | |
1066 | { | |
1067 | typeStr = new TString(objectType); | |
1068 | // Remove white-spaces | |
1069 | typeStr->ReplaceAll(" ", ""); | |
1070 | } | |
1071 | else | |
1072 | { | |
1073 | typeStr = new TString("TObject"); | |
1074 | } | |
004e0620 | 1075 | if (objectType2 != 0) |
1076 | { | |
1077 | typeStr2 = new TString(objectType2); | |
1078 | // Remove white-spaces | |
1079 | typeStr2->ReplaceAll(" ", ""); | |
1080 | } | |
1081 | else | |
1082 | { | |
1083 | typeStr2 = new TString("TObject"); | |
1084 | } | |
00dc25ef | 1085 | |
1086 | TString* mangled1Str = new TString(); | |
1087 | TString* mangled2Str = new TString(); | |
1088 | TString* mangled3Str = new TString(); | |
1089 | TString* mangled4Str = new TString(); | |
1090 | TString* mangledArg1Str = new TString(); | |
1091 | TString* mangledArg2Str = new TString(); | |
1092 | ||
1093 | // We want "const 'OBJECTTYPE'*" | |
1094 | mangled1Str->Append("const ").Append(*typeStr).Append("*"); | |
1095 | ||
1096 | // We want "const 'OBJECTTYPE'*, Double_t*&, Int_t&" | |
1097 | mangled2Str->Append("const ").Append(*typeStr).Append("*, Double_t*&, Int_t&"); | |
1098 | ||
004e0620 | 1099 | // We want "const 'OBJECTTYPE'*, const 'OBJECTTYPE2'*" |
1100 | mangled3Str->Append("const ").Append(*typeStr).Append("*, const ").Append(*typeStr2).Append("*"); | |
00dc25ef | 1101 | |
004e0620 | 1102 | // We want "const 'OBJECTTYPE'*, const 'OBJECTTYPE2'*, Double_t*&, Int_t&" |
1103 | mangled4Str->Append("const ").Append(*typeStr).Append("*, const ").Append(*typeStr2).Append("*, Double_t*&, Int_t&"); | |
00dc25ef | 1104 | |
1105 | // We want "oPconstsP'OBJECTTYPE'mUsP" | |
1106 | mangledArg1Str->Append("oPconstsP").Append(*typeStr).Append("mUsP"); | |
1107 | ||
004e0620 | 1108 | // We want "cOconstsP'OBJECTTYPE2'mUsP" |
1109 | mangledArg2Str->Append("cOconstsP").Append(*typeStr2).Append("mUsP"); | |
00dc25ef | 1110 | |
1111 | // Re-do the check of the macro type | |
1112 | if (!UseList){ | |
1113 | // Single object select macro or single object histo macro? | |
1114 | TFunction* f = gROOT->GetGlobalFunctionWithPrototype(name, mangled1Str->Data(), kTRUE); | |
1115 | ||
1116 | if (f != 0x0) | |
1117 | { | |
1118 | // Some additional check (is the parameter EXACTLY of the desired type?) | |
1119 | if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0) | |
1120 | { | |
1121 | // Single object select macro? | |
1122 | if (!strcmp(f->GetReturnTypeName(), "Bool_t")) | |
1123 | { | |
1124 | type = kSingleObjectSelect; | |
1125 | } | |
1126 | // single object histo macro? | |
1127 | else if (!strcmp(f->GetReturnTypeName(), "TH1*")) | |
1128 | { | |
1129 | type = kSingleObjectHisto; | |
1130 | } | |
1131 | } | |
1132 | } | |
1133 | // Single object analyse macro? | |
1134 | else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled2Str->Data(), kTRUE)) | |
1135 | != 0x0) | |
1136 | { | |
1137 | if (!strcmp(f->GetReturnTypeName(), "void")) | |
1138 | { | |
1139 | // Some additional check (are the parameters EXACTLY of the desired type?) | |
1140 | if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 && | |
1141 | strstr(f->GetMangledName(), "cODouble_tmUaNsP") != 0x0 && | |
1142 | strstr(f->GetMangledName(), "cOInt_taNsP") != 0x0) | |
1143 | { | |
1144 | type = kSingleObjectAnalyse; | |
1145 | } | |
1146 | } | |
1147 | } | |
1148 | // Correlated objects select macro or correlated objects histo macro? | |
1149 | else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled3Str->Data(), kTRUE)) | |
1150 | != 0x0) | |
1151 | { | |
1152 | // Some additional check (is the parameter EXACTLY of the desired type?) | |
1153 | if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 && | |
1154 | strstr(f->GetMangledName(), mangledArg2Str->Data()) != 0x0) | |
1155 | { | |
1156 | // Correlated objects select macro? | |
1157 | if (!strcmp(f->GetReturnTypeName(), "Bool_t")) | |
1158 | { | |
1159 | type = kCorrelObjectSelect; | |
1160 | } | |
1161 | // Correlated objects histo macro? | |
1162 | else if (!strcmp(f->GetReturnTypeName(), "TH1*")) | |
1163 | { | |
1164 | type = kCorrelObjectHisto; | |
1165 | } | |
1166 | } | |
1167 | } | |
1168 | // Correlated objects analyse macro? | |
1169 | else if ((f = gROOT->GetGlobalFunctionWithPrototype(name, mangled4Str->Data(), kTRUE)) | |
1170 | != 0x0) | |
1171 | { | |
1172 | if (!strcmp(f->GetReturnTypeName(), "void")) | |
1173 | { | |
1174 | // Some additional check (is the parameter EXACTLY of the desired type?) | |
1175 | if (strstr(f->GetMangledName(), mangledArg1Str->Data()) != 0x0 && | |
1176 | strstr(f->GetMangledName(), mangledArg2Str->Data()) != 0x0 && | |
1177 | strstr(f->GetMangledName(), "cODouble_tmUaNsP") != 0x0 && | |
1178 | strstr(f->GetMangledName(), "cOInt_taNsP") != 0x0) | |
1179 | { | |
1180 | type = kCorrelObjectAnalyse; | |
1181 | } | |
1182 | } | |
1183 | } | |
1184 | } | |
1185 | // Use list to look up the macro type | |
1186 | else | |
1187 | { | |
1188 | TGeneralMacroData* macro = 0; | |
1189 | macro = (TGeneralMacroData*)fMacroList->GetValue(name); | |
1190 | if (macro == 0) return kUnknown; | |
1191 | ||
1192 | type = macro->GetType(); | |
1193 | switch (type) | |
1194 | { | |
1195 | case kSingleObjectSelect: | |
1196 | case kSingleObjectAnalyse: | |
1197 | case kSingleObjectHisto: | |
1198 | case kCorrelObjectSelect: | |
1199 | case kCorrelObjectAnalyse: | |
1200 | case kCorrelObjectHisto: | |
1201 | break; | |
1202 | default: | |
1203 | type = kUnknown; | |
1204 | break; | |
1205 | } | |
1206 | } | |
1207 | ||
1208 | // Clean up | |
1209 | if (mangled1Str != 0) | |
1210 | { | |
1211 | mangled1Str->Clear(); | |
1212 | delete mangled1Str; | |
1213 | mangled1Str = 0; | |
1214 | } | |
1215 | if (mangled2Str != 0) | |
1216 | { | |
1217 | mangled2Str->Clear(); | |
1218 | delete mangled2Str; | |
1219 | mangled2Str = 0; | |
1220 | } | |
1221 | if (mangled3Str != 0) | |
1222 | { | |
1223 | mangled3Str->Clear(); | |
1224 | delete mangled3Str; | |
1225 | mangled3Str = 0; | |
1226 | } | |
1227 | if (mangled4Str != 0) | |
1228 | { | |
1229 | mangled4Str->Clear(); | |
1230 | delete mangled4Str; | |
1231 | mangled4Str = 0; | |
1232 | } | |
1233 | if (mangledArg1Str != 0) | |
1234 | { | |
1235 | mangledArg1Str->Clear(); | |
1236 | delete mangledArg1Str; | |
1237 | mangledArg1Str = 0; | |
1238 | } | |
1239 | if (mangledArg2Str != 0) | |
1240 | { | |
1241 | mangledArg2Str->Clear(); | |
1242 | delete mangledArg2Str; | |
1243 | mangledArg2Str = 0; | |
1244 | } | |
1245 | if (typeStr != 0) | |
1246 | { | |
1247 | typeStr->Clear(); | |
1248 | delete typeStr; | |
1249 | typeStr = 0; | |
1250 | } | |
004e0620 | 1251 | if (typeStr2 != 0) |
1252 | { | |
1253 | typeStr2->Clear(); | |
1254 | delete typeStr2; | |
1255 | typeStr2 = 0; | |
1256 | } | |
00dc25ef | 1257 | |
1258 | ||
1259 | return type; | |
1260 | } | |
1261 | ||
ce239ca6 | 1262 | |
1263 | /* | |
00dc25ef | 1264 | //______________________________________________________ |
ce239ca6 | 1265 | void AliEveListAnalyser::RemovePrimSelectedObjects() |
00dc25ef | 1266 | { |
ce239ca6 | 1267 | // Removes the (primarily) selected objects in the viewer from the list (objects that are already in the list are ignored). |
1268 | // Hold the CTRL-key for multiple selection. | |
00dc25ef | 1269 | |
ce239ca6 | 1270 | TEveSelection* eveSel = gEve->GetSelection(); |
1271 | ||
1272 | if (!eveSel) | |
00dc25ef | 1273 | { |
ce239ca6 | 1274 | Error("AliEveListAnalyser::RemovePrimSelectedObjects", "Failed to get the selection!\n"); |
1275 | return; | |
1276 | } | |
1277 | ||
1278 | TEveElement* elem = 0x0; | |
1279 | Bool_t changedSomething = kFALSE; | |
00dc25ef | 1280 | |
ce239ca6 | 1281 | for (TEveElement::List_i iter = eveSel->BeginChildren(); iter != eveSel->EndChildren(); ++iter) |
1282 | { | |
1283 | if(!(elem = dynamic_cast<TEveElement*>(*iter))) continue; | |
1284 | ||
1285 | // Check, if element is already there. If so, remove it! | |
1286 | if (this->HasChild(elem) && elem != this) | |
1287 | { | |
1288 | this->RemoveElement(elem); | |
1289 | this->SetTitle(Form("Objects %d", this->NumChildren())); | |
1290 | changedSomething = kTRUE; | |
00dc25ef | 1291 | } |
ce239ca6 | 1292 | } |
00dc25ef | 1293 | |
ce239ca6 | 1294 | if (changedSomething) gEve->Redraw3D(); |
00dc25ef | 1295 | } |
ce239ca6 | 1296 | */ |
00dc25ef | 1297 | |
1298 | //______________________________________________________ | |
1299 | void AliEveListAnalyser::RemoveSelectedMacros(const TList* iterator) | |
1300 | { | |
1301 | // Uses the iterator (for the selected macros) to remove the selected macros from | |
1302 | // the corresponding list. | |
1303 | ||
1304 | TObject* key = 0; | |
1305 | TPair* entry = 0; | |
1306 | for (Int_t i = 0; i < iterator->GetEntries(); i++) | |
1307 | { | |
1308 | entry = (TPair*)fMacroList->FindObject(iterator->At(i)->GetTitle()); | |
1309 | ||
1310 | if (entry == 0) | |
1311 | { | |
1312 | Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Macro \"%s\" not found in list!", | |
1313 | iterator->At(i)->GetTitle())); | |
1314 | continue; | |
1315 | } | |
1316 | key = entry->Key(); | |
1317 | ||
1318 | if (key == 0) | |
1319 | { | |
1320 | Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Key for macro \"%s\" not found in list!", | |
1321 | iterator->At(i)->GetTitle())); | |
1322 | continue; | |
1323 | } | |
1324 | ||
1325 | // Key and value will be deleted, too, since fMacroList is the owner of them | |
1326 | Bool_t rem = fMacroList->DeleteEntry(key); | |
1327 | ||
1328 | if (rem) | |
1329 | { | |
1330 | #ifdef AliEveListAnalyser_DEBUG | |
1331 | printf("AliEveListAnalyser::RemoveSelectedMacros(): Removed macro: %s\n", iterator->At(i)->GetTitle()); | |
1332 | #endif | |
1333 | } | |
1334 | else | |
1335 | { | |
1336 | Error("AliEveListAnalyser::RemoveSelectedMacros", Form("Macro \"%s\" could not be removed from the list!", | |
1337 | iterator->At(i)->GetTitle())); | |
1338 | } | |
1339 | } | |
1340 | } | |
3c3cfd5f | 1341 | |
1342 | //______________________________________________________ | |
1343 | void AliEveListAnalyser::ResetObjectList() | |
1344 | { | |
ce239ca6 | 1345 | // Removes all objects from the list. |
3c3cfd5f | 1346 | |
1347 | RemoveElements(); | |
ce239ca6 | 1348 | this->SetTitle(Form("Objects %d", this->NumChildren())); |
3c3cfd5f | 1349 | } |
1350 | ||
1351 | //______________________________________________________ | |
1352 | Bool_t AliEveListAnalyser::StartAddingObjects() | |
1353 | { | |
ce239ca6 | 1354 | // Starts adding objects for the analysis. Returns kTRUE on success. |
3c3cfd5f | 1355 | |
1356 | if (fConnected == kFALSE) | |
1357 | { | |
ce239ca6 | 1358 | fConnected = TQObject::Connect("TEvePointSet", "PointSelected(Int_t)", "AliEveListAnalyser", this, "AddSecSelectedSingleObjectToList(Int_t)"); |
1359 | if (fConnected) fConnected = TQObject::Connect(gEve->GetSelection(), "SelectionAdded(TEveElement*)", "AliEveListAnalyser", this, "AddPrimSelectedObject(TEveElement*)"); | |
1360 | ||
3c3cfd5f | 1361 | if (fConnected) return kTRUE; |
1362 | ||
1363 | Error("AliEveListAnalyser::StartAddingObjects", "Connection failed!"); | |
ce239ca6 | 1364 | |
1365 | // Connection of 2nd signal failed, but first connection succeeded -> Disconnect 1st signal. | |
1366 | TQObject::Disconnect("TEvePointSet", "PointSelected(Int_t)", this, "AddObjectToList(Int_t)"); | |
3c3cfd5f | 1367 | } |
1368 | ||
1369 | return kFALSE; | |
1370 | } | |
1371 | ||
1372 | //______________________________________________________ | |
1373 | Bool_t AliEveListAnalyser::StopAddingObjects() | |
1374 | { | |
ce239ca6 | 1375 | // Stops adding objects for the analysis. Returns kTRUE on success. |
3c3cfd5f | 1376 | |
1377 | if (fConnected) | |
1378 | { | |
ce239ca6 | 1379 | Bool_t dis1 = kFALSE, dis2 = kFALSE; |
1380 | dis1 = TQObject::Disconnect("TEvePointSet", "PointSelected(Int_t)", this, "AddSecSelectedSingleObjectToList(Int_t)"); | |
1381 | dis2 = TQObject::Disconnect(gEve->GetSelection(), "SelectionAdded(TEveElement*)", this, "AddPrimSelectedObject(TEveElement*)"); | |
1382 | ||
1383 | if (dis1 || dis2) fConnected = kFALSE; | |
1384 | if (dis1 && dis2) return kTRUE; | |
3c3cfd5f | 1385 | else |
1386 | { | |
1387 | Error("AliEveListAnalyser::StopAddingObjects", "Disconnection failed!"); | |
ce239ca6 | 1388 | |
3c3cfd5f | 1389 | return kFALSE; |
1390 | } | |
1391 | } | |
1392 | ||
1393 | return kTRUE; | |
1394 | } |