]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/CreateWeightedRejectList.C
Introduce missing L4S4 chamber in sector 17
[u/mrichter/AliRoot.git] / MUON / CreateWeightedRejectList.C
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17
18 ///
19 /// \ingroup macros
20 ///
21 /// \file CreateWeightedRejectList.C
22 ///
23 /// \brief Macro test for the creation of a RejectList object (for simulations) in the OCDB, for the MUON Tracke 
24 ///
25 /// Usage:
26 ///
27 /// root[0] .L CreateWeightedRejectList.C+
28 /// root[1] CreateWeightedRejectList("runlist.txt","local://$HOME/myLocalOCDB");
29 ///
30 /// where runlist.txt has 2 integers per line = "run nevents"
31 /// where nevents is the number of events where there's (for instance) a CMUS1B trigger
32 ///
33 ///
34 /// Assuming the file coming from the Export feature of the logbook is runlist.logbook.txt =>
35 ///
36 /// 115521;PHYSICS_1;1357;0.9
37 /// 115516;PHYSICS_1;944;0.9
38 ///
39 /// The awk command below will output the needed format for this macro :
40 ///
41 /// awk '{split ($0,a,";"); print a[1] " " a[3];}' runlist.logbook.txt =>
42 ///
43 /// 115521 1357
44 /// 115516 944
45 ///
46 /// \author Matthieu Lenhardt, Subatech
47 ///
48
49 #include "AliCDBEntry.h"
50 #include "AliCDBManager.h"
51 #include "AliDAQ.h"
52 #include "AliDCSValue.h"
53 #include "AliMUONCDB.h"
54 #include "AliMUONCalibParamNI.h"
55 #include "AliMUONCalibrationData.h"
56 #include "AliMUONPadStatusMaker.h"
57 #include "AliMUONPadStatusMapMaker.h"
58 #include "AliMUONRecoParam.h"
59 #include "AliMUONRejectList.h"
60 #include "AliMUONRejectList.h"
61 #include "AliMUONTrackerData.h"
62 #include "AliMUONVCalibParam.h"
63 #include "AliMpBusPatch.h"
64 #include "AliMpCDB.h"
65 #include "AliMpConstants.h"
66 #include "AliMpDCSNamer.h"
67 #include "AliMpDDLStore.h"
68 #include "AliMpDEIterator.h"
69 #include "AliMpDEManager.h"
70 #include "AliMpDetElement.h"
71 #include "AliSysInfo.h"
72 #include "TEnv.h"
73 #include <Riostream.h>
74 #include <TFile.h>
75 #include <TGrid.h>
76 #include <TMap.h>
77 #include <TObjArray.h>
78 #include <TObject.h>
79 #include <TTree.h>
80 #include <vector>
81 #include "AliCounterCollection.h"
82
83 #include "AliMUONTrackerDataWrapper.h"
84 #include "AliMUONPainterDataRegistry.h"
85
86 class RunInfo
87 {
88 public:
89   RunInfo(Int_t run, Long64_t nevents) : fNumber(run), fNevents(nevents) { }
90
91   Int_t Number() const { return fNumber; }
92
93   Long64_t Nevents() const { return fNevents; }
94
95   void SetNevents(Long64_t n) { fNevents = n; }
96
97 private:
98   Int_t fNumber;
99   Long64_t fNevents;
100 };
101
102 std::ostream& operator<<(std::ostream& out, const RunInfo& run)
103 {
104   out << Form("RUN %09d NEVENTS %lld",run.Number(),run.Nevents());
105   return out;
106 }
107
108 AliMUONRejectList* CheckDE_BP_ManuPedestals(Int_t rejectMask, AliMUONPadStatusMaker& status);
109
110 Int_t AddEventsSingleRun(Int_t run_number, Long64_t nEvents,AliMUONRejectList& rejectedEvents);
111
112 std::vector<RunInfo> runs;
113
114 //______________________________________________________________________________
115 AliMUONRejectList* CreateWeightedRejectList(AliCounterCollection& cc,
116                                             const char* ocdbPath="local:///Users/laurent/Alice/OCDBcopy2013",
117                                             const char* weigthWithTrigger="CMSL7-B-NOPF-MUON")
118 {
119   // create the reject using the runs in the collection
120   //
121   // the counter collection is expected to have "trigger","event","run" rubrics
122   // and event:PSALL should be a valid one.
123   //
124   
125   if (!gGrid)
126   {
127     TGrid::Connect("alien://");
128   }
129   
130   AliCDBManager::Instance()->SetDefaultStorage(ocdbPath);
131   
132   AliMUONRejectList* weightedRejectList = new AliMUONRejectList;
133   
134   AliMUONRejectList rejectedEvents;
135
136   TString sruns = cc.GetKeyWords("run");
137   TObjArray* truns = sruns.Tokenize(",");
138   
139   TIter next(truns);
140   TObjString* s;
141   
142   Double_t nEventsTotal(0.0);
143   
144   while ( ( s = static_cast<TObjString*>(next())) )
145   {
146     Int_t runNumber = s->String().Atoi();
147     AliSysInfo::Instance()->AddStamp(Form("RUN%d",runNumber));
148     Long64_t nEvents = cc.GetSum(Form("trigger:%s/event:PSALL/run:%d",weigthWithTrigger,runNumber));
149     if (!nEvents)
150     {
151       std::cout << "No events for run " << runNumber << " ??" << std::endl;
152       continue;
153     }
154     nEventsTotal += AddEventsSingleRun(runNumber,nEvents,rejectedEvents);
155   }
156   
157   delete truns;
158   
159   AliMpDEIterator DEiter;
160   
161   for (DEiter.First(); !DEiter.IsDone(); DEiter.Next())
162     if (DEiter.CurrentDEId() < 1100)
163     {
164       Int_t DEid = DEiter.CurrentDEId();
165       
166       Double_t nBadEventsDE = rejectedEvents.DetectionElementProbability(DEid);
167       Double_t nEventsTotalDE = static_cast<Double_t>(nEventsTotal);
168       Float_t probaDE = 0.0;
169       if (nEventsTotalDE != 0.0)
170         probaDE = nBadEventsDE / nEventsTotalDE;
171       weightedRejectList->SetDetectionElementProbability(DEid, probaDE);
172       
173       Int_t nBusPatches = DEiter.CurrentDE()->GetNofBusPatches();
174       for (Int_t ii = 0; ii < nBusPatches; ii++)
175       {
176         Int_t BPid = DEiter.CurrentDE()->GetBusPatchId(ii);
177         
178         Double_t nBadEventsBP = rejectedEvents.BusPatchProbability(BPid);
179         Double_t nEventsTotalBP = nEventsTotalDE - nBadEventsDE;
180         Float_t probaBP = 0.0;
181         if (nEventsTotalBP != 0.0)
182           probaBP = nBadEventsBP / nEventsTotalBP;
183         weightedRejectList->SetBusPatchProbability(BPid, probaBP);
184         
185         Int_t nManus = AliMpDDLStore::Instance(kFALSE)->GetBusPatch(BPid, kFALSE)->GetNofManus();
186         for (Int_t jj = 0; jj < nManus; jj++)
187               {
188           Int_t manuId = AliMpDDLStore::Instance(kFALSE)->GetBusPatch(BPid, kFALSE)->GetManuId(jj);
189           
190           Double_t nBadEventsManu = rejectedEvents.ManuProbability(DEid, manuId);
191           Double_t nEventsTotalManu = nEventsTotalBP - nBadEventsBP;
192           Float_t probaManu = 0.0;
193           if (nEventsTotalManu != 0.0)
194             probaManu = nBadEventsManu / nEventsTotalManu;
195           weightedRejectList->SetManuProbability(DEid, manuId, probaManu);
196           
197           for (Int_t channel = 0; channel < AliMpConstants::ManuNofChannels(); channel++)
198           {
199             Double_t nBadEventsChannel = rejectedEvents.ChannelProbability(DEid, manuId, channel);
200             Double_t nEventsTotalChannel = nEventsTotalManu - nBadEventsManu;
201             Float_t probaChannel = 0.0;
202             if (nEventsTotalChannel != 0.0)
203             {
204               probaChannel = nBadEventsChannel / nEventsTotalChannel;
205             }
206             
207             weightedRejectList->SetChannelProbability(DEid, manuId, channel, probaChannel);
208           }
209               }
210       }
211     }
212   
213   
214   AliMUONTrackerData* td = new AliMUONTrackerData("WeightedRejectList","RejectList",*weightedRejectList);
215   
216   AliMUONVTrackerDataMaker* dw = new AliMUONTrackerDataWrapper(td);
217   
218   AliMUONPainterDataRegistry::Instance()->Register(dw);
219
220   return weightedRejectList;
221 }
222
223 //______________________________________________________________________________
224 bool CreateWeightedRejectList(const char* runlistfile="runlist.txt", 
225                               const char* rejectListPath="local://$HOME/OCDB",
226                               const char* author="Matthieu Lenhardt")
227 {
228   /// Create a weighted RejectList for the runs included in the run list
229   /// The cuts are the same that the one applied in the RecoParam used to create the ESDs.
230   ///
231   /// \param runlistfile : an ASCII file where each line is a pair "run nevents"
232   /// \param rejectListPath : set this to the folder where the RejectList will be created (must have right access to it, of course)
233   
234   TGrid::Connect("alien://");
235   
236   ifstream in(runlistfile);
237   int run, nevents;
238   
239   while ( in >> run >> nevents ) 
240   {
241     runs.push_back(RunInfo(run,nevents));
242   };
243   
244   for ( std::vector<RunInfo>::size_type i = 0; i < runs.size(); ++i )
245   {
246     cout << runs[i] << endl;
247   }
248   
249   if (runs.empty()) return false;
250   
251   Int_t firstRun = runs[0].Number();
252   Int_t lastRun = runs[runs.size()-1].Number();
253   
254   const char* rawOCDB = "raw://";
255   
256   AliCDBManager* manager = AliCDBManager::Instance();
257
258   manager->SetCacheFlag(kFALSE);
259   
260   manager->SetDefaultStorage(rawOCDB);
261
262   manager->SetSpecificStorage("MUON/Calib/RejectList", rejectListPath);
263   
264   AliMUONRejectList weightedRejectList;
265   AliMUONRejectList rejectedEvents;
266   
267   Long64_t nEventsTotal = 0;
268   
269   for (std::vector<RunInfo>::size_type ii = 0; ii < runs.size(); ++ii)
270   {
271     Int_t runNumber = runs[ii].Number();
272     AliSysInfo::Instance()->AddStamp(Form("RUN%d",runNumber));
273     Long64_t nEvents = runs[ii].Nevents();
274     nEventsTotal += AddEventsSingleRun(runNumber, nEvents, rejectedEvents);
275   }  
276   
277   AliMpDEIterator DEiter;
278   
279   for (DEiter.First(); !DEiter.IsDone(); DEiter.Next())
280     if (DEiter.CurrentDEId() < 1100)
281     {
282       Int_t DEid = DEiter.CurrentDEId();
283       
284       Double_t nBadEventsDE = rejectedEvents.DetectionElementProbability(DEid);
285       Double_t nEventsTotalDE = static_cast<Double_t>(nEventsTotal);
286       Float_t probaDE = 0.0;
287       if (nEventsTotalDE != 0.0)
288         probaDE = nBadEventsDE / nEventsTotalDE;
289       weightedRejectList.SetDetectionElementProbability(DEid, probaDE);
290       
291       Int_t nBusPatches = DEiter.CurrentDE()->GetNofBusPatches();
292       for (Int_t ii = 0; ii < nBusPatches; ii++)
293       {
294         Int_t BPid = DEiter.CurrentDE()->GetBusPatchId(ii);
295         
296         Double_t nBadEventsBP = rejectedEvents.BusPatchProbability(BPid);
297         Double_t nEventsTotalBP = nEventsTotalDE - nBadEventsDE;
298         Float_t probaBP = 0.0;
299         if (nEventsTotalBP != 0.0)
300           probaBP = nBadEventsBP / nEventsTotalBP;
301         weightedRejectList.SetBusPatchProbability(BPid, probaBP);
302         
303         Int_t nManus = AliMpDDLStore::Instance(kFALSE)->GetBusPatch(BPid, kFALSE)->GetNofManus();
304         for (Int_t jj = 0; jj < nManus; jj++)
305               {
306           Int_t manuId = AliMpDDLStore::Instance(kFALSE)->GetBusPatch(BPid, kFALSE)->GetManuId(jj);
307           
308           Double_t nBadEventsManu = rejectedEvents.ManuProbability(DEid, manuId);
309           Double_t nEventsTotalManu = nEventsTotalBP - nBadEventsBP;
310           Float_t probaManu = 0.0;
311           if (nEventsTotalManu != 0.0)
312             probaManu = nBadEventsManu / nEventsTotalManu;
313           weightedRejectList.SetManuProbability(DEid, manuId, probaManu);
314           
315           for (Int_t channel = 0; channel < AliMpConstants::ManuNofChannels(); channel++)
316           {
317             Double_t nBadEventsChannel = rejectedEvents.ChannelProbability(DEid, manuId, channel);
318             Double_t nEventsTotalChannel = nEventsTotalManu - nBadEventsManu;
319             Float_t probaChannel = 0.0;
320             if (nEventsTotalChannel != 0.0)
321             {
322               probaChannel = nBadEventsChannel / nEventsTotalChannel;
323             }
324             
325             weightedRejectList.SetChannelProbability(DEid, manuId, channel, probaChannel);
326           }
327               }
328       }
329     }
330   
331   
332   AliMUONCDB::WriteToCDB(&weightedRejectList, "MUON/Calib/RejectList",
333                          firstRun , lastRun, 
334                          "Weighted reject List for MCH, for simulations only", 
335                          author);
336   
337   return true;
338 }
339
340 //____________________________________________________________________________________________
341 AliMUONRejectList* CheckDE_BP_ManuPedestals(Int_t rejectMask, AliMUONPadStatusMaker& status)
342 {
343   AliMUONRejectList* nBadChannels = new AliMUONRejectList;
344   
345   AliMpDEIterator DEiter;
346   for (DEiter.First(); !DEiter.IsDone(); DEiter.Next())
347     if (DEiter.CurrentDEId() < 1100)
348     {
349       Int_t DEid = DEiter.CurrentDEId();
350       Int_t nBusPatches = DEiter.CurrentDE()->GetNofBusPatches();
351       for (Int_t ii = 0; ii < nBusPatches; ii++)
352       {
353         Int_t BPid = DEiter.CurrentDE()->GetBusPatchId(ii);
354         
355         Int_t nManus = AliMpDDLStore::Instance(kFALSE)->GetBusPatch(BPid, kFALSE)->GetNofManus();
356         for (Int_t jj = 0; jj < nManus; jj++)
357               {
358           Int_t manuId = AliMpDDLStore::Instance(kFALSE)->GetBusPatch(BPid, kFALSE)->GetManuId(jj);
359           
360           Int_t nChannels = DEiter.CurrentDE()->NofChannelsInManu(manuId);
361           for (Int_t channel = 0; channel < nChannels; channel++)
362           {
363             Int_t padStatus = status.PadStatus(DEid, manuId, channel);
364             if ((rejectMask == 0 && padStatus != 0) || (padStatus & rejectMask) != 0)
365             {
366               nBadChannels->SetDetectionElementProbability(DEid, nBadChannels->DetectionElementProbability(DEid) + 1.0);
367               nBadChannels->SetBusPatchProbability(BPid, nBadChannels->BusPatchProbability(BPid) + 1.0);
368               nBadChannels->SetManuProbability(DEid, manuId, nBadChannels->ManuProbability(DEid, manuId) + 1.0);
369               nBadChannels->SetChannelProbability(DEid, manuId, channel, 1.0);
370             }
371           }
372               }
373       }
374     }
375   
376   return nBadChannels;
377 }
378
379
380 //____________________________________________________________________________________________
381 Int_t AddEventsSingleRun(Int_t runNumber, Long64_t nEvents, AliMUONRejectList& rejectedEvents)
382 {
383   AliCDBManager::Instance()->SetRun(runNumber);
384   
385   AliMpCDB::LoadAll();
386
387   Double_t maxBadChannels = 80.0;
388   
389   AliMUONRecoParam *recoParam = AliMUONCDB::LoadRecoParam();
390   AliMUONCalibrationData calibrationData(runNumber);
391   AliMUONPadStatusMaker status(calibrationData);
392   
393   status.SetLimits(*recoParam);
394   
395   Int_t rejectMask = recoParam->PadGoodnessMask();
396   
397   // Functions to compute the number of bad channels at the DE, BP and Manu level
398   AliMUONRejectList* nBadChannels = CheckDE_BP_ManuPedestals(rejectMask, status);
399   
400   AliMpDEIterator DEiter;
401   for (DEiter.First(); !DEiter.IsDone(); DEiter.Next())
402     if (DEiter.CurrentDEId() < 1100)
403     {
404       Int_t DEid = DEiter.CurrentDEId();
405       Int_t nBusPatches = DEiter.CurrentDE()->GetNofBusPatches();
406       
407       Double_t nChannelsDE = static_cast<Double_t>(AliMpDDLStore::Instance(kFALSE)->GetDetElement(DEid)->NofChannels());
408       Double_t nBadChannelsDE = nBadChannels->DetectionElementProbability(DEid);
409       Double_t ratioBadChannelsDE = 0.0;
410       if (nChannelsDE != 0.0)
411         ratioBadChannelsDE = 100.0 * nBadChannelsDE / nChannelsDE;
412       
413       
414       Bool_t goodDE = kTRUE;
415       if (ratioBadChannelsDE >= maxBadChannels)
416       {
417         Double_t newRejectedEventsDE = rejectedEvents.DetectionElementProbability(DEid) + static_cast<Double_t>(nEvents);
418         rejectedEvents.SetDetectionElementProbability(DEid, newRejectedEventsDE);
419         goodDE = kFALSE;
420       }
421                 
422       if (goodDE)      
423         for (Int_t ii = 0; ii < nBusPatches; ii++)
424         {
425           Int_t BPid = DEiter.CurrentDE()->GetBusPatchId(ii);
426           Int_t nManus = AliMpDDLStore::Instance(kFALSE)->GetBusPatch(BPid, kFALSE)->GetNofManus();
427           
428           Double_t nChannelsBP = static_cast<Double_t>(nManus * AliMpConstants::ManuNofChannels());
429           Double_t nBadChannelsBP = nBadChannels->BusPatchProbability(BPid);
430           Double_t ratioBadChannelsBP = 100.0 * nBadChannelsBP / nChannelsBP;
431           
432           Bool_t goodBP = kTRUE;
433           
434           if (goodBP)
435             if (ratioBadChannelsBP >= maxBadChannels)
436             {
437               Double_t newRejectedEventsBP = rejectedEvents.BusPatchProbability(BPid) + static_cast<Double_t>(nEvents);
438               rejectedEvents.SetBusPatchProbability(BPid, newRejectedEventsBP);
439               goodBP = kFALSE;
440             }
441           
442           if (goodBP)
443             for (Int_t jj = 0; jj < nManus; jj++)
444             {
445               Int_t manuId = AliMpDDLStore::Instance(kFALSE)->GetBusPatch(BPid, kFALSE)->GetManuId(jj);
446               
447               Double_t nChannelsManu = DEiter.CurrentDE()->NofChannelsInManu(manuId);;
448               Double_t nBadChannelsManu = nBadChannels->ManuProbability(DEid, manuId);
449               Double_t ratioBadChannelsManu = 100.0 * nBadChannelsManu / nChannelsManu;
450               
451               Bool_t goodManu = kTRUE;
452               
453               if (ratioBadChannelsManu >= maxBadChannels)
454               {
455                 Double_t newRejectedEventsManu = rejectedEvents.ManuProbability(DEid, manuId) + static_cast<Double_t>(nEvents);
456                 rejectedEvents.SetManuProbability(DEid, manuId, newRejectedEventsManu);
457                 goodManu = kFALSE;
458               }
459               
460               
461               Int_t nChannels = DEiter.CurrentDE()->NofChannelsInManu(manuId);
462               
463               if (goodManu)
464                 for (Int_t channel = 0; channel < nChannels; channel++)
465                   if (nBadChannels->ChannelProbability(DEid, manuId, channel) > 0.0)
466                   {
467                     Double_t newRejectedEventsChannel = rejectedEvents.ChannelProbability(DEid, manuId, channel) + static_cast<Double_t>(nEvents);
468                     rejectedEvents.SetChannelProbability(DEid, manuId, channel, newRejectedEventsChannel);
469                   } // end of Channels loop
470             } // end of MANUs loop          
471         } // end of BPs loop
472     } // end of DEs loop
473   
474   delete nBadChannels;
475   
476   return nEvents;
477 }
478
479 //______________________________________________________________________________
480 //
481 //
482 // The code below might be used someday to retrieve the number of events
483 // with at least one muon directly from a runlist, instead of requiring
484 // as input both the run numbers and the number of events.
485 //
486 // This approach though is not without its problems :
487 //
488 // - even if we are using tags, as the tags are chunk-based (for the moment at
489 //   least), it's pretty slow to loop on all the chunks (it is becoming usual
490 //   to get runs with some 600 chunks or so...)
491 // - if part of a run is not reconstructed (for whatever reason) with the pass
492 //   we use to compute the number of events with at least one muon, we might
493 //   underestimate its weight in the final rejectlist for the next passes (
494 //   if for the next passes the full run is correctly reconstructed for instance)
495 // - a muon in the tag = either a trigger track or a tracker track, i.e. we don't
496 //   know for sure it's a good track...
497 //
498 // Given all those reasons, we for the moment use a dumb approach : 
499 //
500 // - go to alice-logbook.cern.ch . Select the runs you want and the trigger class
501 //   you want (most probably CMUS1B), and export the list as (run,nevents)
502 // - run this macro with this (run,nevents) list
503 //
504 //______________________________________________________________________________
505
506 #if 0
507
508 #include "TChain.h"
509 #include "AliDetectorTagCuts.h"
510 #include "AliEventTagCuts.h"
511 #include "AliLHCTagCuts.h"
512 #include "AliRunTagCuts.h"
513 #include "AliTagAnalysis.h"
514 #include "TGridResult.h"
515
516 //______________________________________________________________________________
517 bool CreateXMLCollectionFromRunList(const char* collectionName, 
518                                     const char* runlist,
519                                     const char* type,
520                                     int passNumber)
521 {
522   /// From a list of run, create a collection with only events containing at least one muon
523   /// \param collectionName : output name of the collection (without extension, which will be .xml)
524   /// \param runlist : text file containing one integer per line = one run number per line
525   /// \param type : files to consider, either ESD or AD
526   /// \param passNumber : 1 or 2 most probably (to distinguish which reco pass is used)
527   
528   if (!gGrid) TGrid::Connect("alien://");
529   if (!gGrid) 
530   {
531     return 0x0;
532   }
533   
534   TString stype(type);
535   stype.ToUpper();
536   
537   if ( stype != "ESD" && stype != "AOD" )
538   {
539     cout << "Only ESD or AOD type supported" << endl;
540     return false;
541   }
542   
543   ifstream in(gSystem->ExpandPathName(runlist));
544   Int_t runNumber;
545   Int_t ntagfiles(0);
546   
547   AliTagAnalysis tagAnalysis("ESD");
548   
549   while ( in >> runNumber ) 
550   {
551     TGridResult *res = gGrid->Query("/alice/data",
552                                     Form("%09d/%ss/pass%d/*%d*/Run%d.Event*.ESD.tag.root",
553                                          runNumber,stype.Data(),passNumber,runNumber,runNumber));
554     Int_t nFiles = res->GetEntries();
555     if (!nFiles) 
556     {
557       continue;
558     }
559     
560     for (Int_t i = 0; i < nFiles; ++i) 
561     {
562       TString filename = res->GetKey(i, "turl");
563       if(filename == "") continue;
564       tagAnalysis.AddTagsFile(filename.Data(),kFALSE);
565       ++ntagfiles;
566     }
567     delete res;
568   }
569   
570   cout << ntagfiles << " tag files added" << endl;
571   
572   AliRunTagCuts runCuts;
573   AliEventTagCuts eventCuts;
574   AliLHCTagCuts lhcCuts;
575   AliDetectorTagCuts detCuts;
576   
577   eventCuts.SetNMuonRange(1,99999);
578   
579   return tagAnalysis.CreateXMLCollection(collectionName,&runCuts,&lhcCuts,&detCuts,&eventCuts);  
580   
581 }
582
583 //______________________________________________________________________________
584 TChain* CreateChainFromXMLCollection(const char* collectionName, const char* type)
585 {
586   /// Create a chain from an XML collection file.
587   
588   if (!gGrid) TGrid::Connect("alien://");
589   if (!gGrid) 
590   {
591     return 0x0;
592   }
593   
594   TString stype(type);
595   stype.ToUpper();
596   
597   if ( stype != "ESD" && stype != "AOD" )
598   {
599     cout << "Only ESD or AOD type supported" << endl;
600     return 0x0;
601   }
602   
603   AliTagAnalysis tagAnalysis(stype.Data());
604   
605   return tagAnalysis.CreateChainFromCollection(collectionName,stype=="ESD" ? "esdTree":"aodTree");
606 }
607
608 #endif