AliPhysics  b81c3d2 (b81c3d2)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AliAnalysisTaskEmcalEmbeddingHelper.cxx
Go to the documentation of this file.
1 /**************************************************************************
2  * Copyright(c) 1998-2016, 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 #include <string>
17 #include <vector>
18 #include <algorithm>
19 #include <fstream>
20 
21 #include <TFile.h>
22 #include <TMath.h>
23 #include <TRandom.h>
24 #include <TChain.h>
25 #include <TGrid.h>
26 #include <TSystem.h>
27 #include <TUUID.h>
28 
29 #include <AliLog.h>
30 #include <AliAnalysisManager.h>
31 #include <AliVEvent.h>
32 #include <AliAODEvent.h>
33 #include <AliESDEvent.h>
34 #include <AliInputEventHandler.h>
35 
37 
41 
43 
49  fTreeName(),
50  fAnchorRun(169838),
51  fPtHardBin(-1),
52  fRandomEventNumberAccess(kFALSE),
53  fRandomFileAccess(kFALSE),
54  fFilePattern(""),
55  fFileListFilename(""),
56  fFilenameIndex(-1),
57  fFilenames(),
58  fTriggerMask(AliVEvent::kAny),
59  fZVertexCut(10),
60  fMaxVertexDist(999),
61  fExternalFile(0),
62  fCurrentEntry(0),
63  fLowerEntry(0),
64  fUpperEntry(0),
65  fOffset(0),
66  fMaxNumberOfFiles(0),
67  fFileNumber(0),
68  fInitializedEmbedding(false),
69  fInitializedNewFile(false),
70  fWrappedAroundTree(false),
71  fChain(0),
72  fExternalEvent(0)
73 {
74  if (fgInstance != 0) {
75  AliError("An instance of AliAnalysisTaskEmcalEmbeddingHelper already exists: it will be deleted!!!");
76  delete fgInstance;
77  }
78 
79  fgInstance = this;
80 }
81 
88  AliAnalysisTaskSE(name),
89  fTreeName("aodTree"),
90  fAnchorRun(169838),
91  fPtHardBin(-1),
92  fRandomEventNumberAccess(kFALSE),
93  fRandomFileAccess(kFALSE),
94  fFilePattern(""),
95  fFileListFilename(""),
96  fFilenameIndex(-1),
97  fFilenames(),
98  fTriggerMask(AliVEvent::kAny),
99  fZVertexCut(10),
100  fMaxVertexDist(999),
101  fExternalFile(0),
102  fCurrentEntry(0),
103  fLowerEntry(0),
104  fUpperEntry(0),
105  fOffset(0),
106  fMaxNumberOfFiles(0),
107  fFileNumber(0),
108  fInitializedEmbedding(false),
109  fInitializedNewFile(false),
110  fWrappedAroundTree(false),
111  fChain(0),
112  fExternalEvent(0)
113 {
114  if (fgInstance != 0) {
115  AliError("An instance of AliAnalysisTaskEmcalEmbeddingHelper already exists: it will be deleted!!!");
116  delete fgInstance;
117  }
118 
119  fgInstance = this;
120 }
121 
128 {
129  if (fgInstance == this) fgInstance = 0;
130  if (fExternalEvent) delete fExternalEvent;
131  if (fExternalFile) {
132  fExternalFile->Close();
133  delete fExternalFile;
134  }
135 }
136 
161 {
162  // Retrieve filenames if we don't have them yet.
163  if (fFilenames.size() == 0)
164  {
165  // Handle if fPtHardBin or fAnchorRun are set
166  // This will require formatting the file pattern in the proper way to support these substitutions
167  if (fPtHardBin != -1) {
168  if (fAnchorRun > 0) {
169  fFilePattern = TString::Format(fFilePattern, fAnchorRun, fPtHardBin);
170  }
171  else {
172  fFilePattern = TString::Format(fFilePattern, fPtHardBin);
173  }
174  }
175 
176  // Setup AliEn access if needed
177  if (fFilePattern.Contains("alien://") || fFileListFilename.Contains("alien://")) {
178  if (!gGrid) {
179  AliInfo("Trying to connect to AliEn ...");
180  TGrid::Connect("alien://");
181  }
182  if (!gGrid) {
183  AliFatal(Form("Cannot access AliEn to retrieve file list with pattern %s!", fFilePattern.Data()));
184  }
185  }
186 
187  // Retrieve AliEn filenames directly from AliEn
188  if (fFilePattern.Contains("alien://")) {
189  AliDebug(2,Form("Trying to retrieve file list from AliEn with pattern file %s...", fFilePattern.Data()));
190 
191  // Create a temporary filename based on a UUID to make sure that it doesn't overwrite any files
192  if (fFileListFilename == "") {
194  }
195 
196  // Retrieve filenames from alien using alien_find
197  TString command = "alien_find";
198  command += fFilePattern;
199  command += " > ";
200  command += fFileListFilename;
201 
202  // Execute the alien_find command to get the filenames
203  AliDebug(2,Form("Trying to retrieve file list from AliEn with alien_find command \"%s\"", command.Data()));
204  gSystem->Exec(command.Data());
205  }
206 
207  // Handle a filelist on AliEn
208  if (fFileListFilename.Contains("alien://")) {
209  // Determine the local filename and copy file to local directory
210  std::string alienFilename = fFileListFilename.Data();
211  fFileListFilename = gSystem->BaseName(alienFilename.c_str());
213 
214  TFile::Cp(alienFilename.c_str(), fFileListFilename.Data());
215  }
216 
217  std::ifstream inputFile(fFileListFilename);
218 
219  // Copy available files into the filenames vector
220  // From:: https://stackoverflow.com/a/8365247
221  std::copy(std::istream_iterator<std::string>(inputFile),
222  std::istream_iterator<std::string>(),
223  std::back_inserter(fFilenames));
224  }
225 
226  if (fFilenames.size() == 0) {
227  AliFatal(Form("Filenames from pattern \"%s\" and file list \"%s\" yielded an empty list!", fFilePattern.Data(), fFileListFilename.Data()));
228  }
229 
230  // Add "#" to files in there are any zip files
231  // It is require to open the proper root file within the zip
232  for (auto filename : fFilenames)
233  {
234  if (filename.find(".zip") != std::string::npos && filename.find("#") == std::string::npos) {
235  if (fTreeName == "aodTree") {
236  filename += "#AliAOD.root";
237  }
238  else if (fTreeName == "esdTree") {
239  filename += "#AliESDs.root";
240  }
241  else {
242  AliError(TString::Format("Filename %s contains \".zip\" and not \"#\", but tree name %s is not recognized. Please check the file list to ensure that the proper path is set.", filename.c_str(), fTreeName.Data()));
243  }
244  }
245  }
246 
247  // Determine the next filename index
248  // This determines which file is added first to the TChain, thus determining the order of processing
249  // Random file access. Only do this if the user has no set the filename index and request random file access
250  if (fFilenameIndex == -1 && fRandomFileAccess) {
251  // - 1 ensures that we it doesn't overflow
252  fFilenameIndex = TMath::Nint(gRandom->Rndm()*fFilenames.size()) - 1;
253  AliInfo(TString::Format("Starting with random file number %i!", fFilenameIndex));
254  }
255  // If not random file access, then start from the beginning
256  if (fFilenameIndex >= fFilenames.size() || fFilenameIndex < 0) {
257  // Skip notifying on -1 since it will likely be set there due to constructor.
258  if (fFilenameIndex != -1) {
259  AliWarning(Form("File index %i out of range from 0 to %lu! Resetting to 0!", fFilenameIndex, fFilenames.size()));
260  }
261  fFilenameIndex = 0;
262  }
263 
264  AliInfo(TString::Format("Starting with file number %i out of %lu", fFilenameIndex, fFilenames.size()));
265 }
266 
275 {
276  std::string tempStr = "";
277  if (fFileListFilename == "") {
278  tempStr = "fileList";
279  }
280  TUUID tempUUID;
281  tempStr += ".";
282  tempStr += tempUUID.AsString();
283  tempStr += ".txt";
284 
285  return tempStr;
286 }
287 
297 {
298  Int_t attempts = -1;
299 
300  do {
301  // Reset to start of tree
302  if (fCurrentEntry == fUpperEntry) {
304  fWrappedAroundTree = true;
305  }
306 
308  // Continue with GetEntry as normal
309  }
310  else {
311  // NOTE: On transition from one file to the next, this calls the next entry that would be expected.
312  // However, if it is for the last file, it tries to GetEntry() of one entry past the end of the last file.
313  // Normally, this would be a problem, however GetEntry() just doesn't fill the fields of an invalid index
314  // instead of throwing an error. So "invalid values" are filled for a file that doesn't exist, but then
315  // they are immediately replaced by the lines below that reset the access values and re-init the tree.
316  // The benefit of this approach is it simplies file counting (we don't need to carefully increment here
317  // and in InitTree()) and preserves the desired behavior when we are not at the last file.
318  InitTree();
319  }
320 
321  // Load current event
322  // Can be a simple less than, because fFileNumber counts from 0.
324  fChain->GetEntry(fCurrentEntry);
325  }
326  else {
327  AliError("====================================================================================================");
328  AliError("== No more files available to embed from the TChain! Restarting from the beginning of the TChain! ==");
329  AliError("== Be careful to check that this is the desired action! ==");
330  AliError("====================================================================================================");
331 
332  // Reset the relevant access values
333  // fCurrentEntry and fLowerEntry are automatically reset in InitTree()
334  fFileNumber = 0;
335  fUpperEntry = 0;
336 
337  // Re-init back to the start
338  InitTree();
339 
340  // Access the relevant entry
341  // We are certain that fFileNumber is less than fMaxNumberOfFiles, so we are resetting to start
342  fChain->GetEntry(fCurrentEntry);
343  }
344  AliDebug(4, TString::Format("Loading entry %i between %i-%i, starting with offset %i from the lower bound of %i", fCurrentEntry, fLowerEntry, fUpperEntry, fOffset, fLowerEntry));
345 
346  // Increment current entry
347  fCurrentEntry++;
348 
349  // Provide a check for number of attempts
350  attempts++;
351  if (attempts == 1000)
352  AliWarning("After 1000 attempts no event has been accepted by the event selection (trigger, centrality...)!");
353 
354  } while (!IsEventSelected());
355 
356  if (!fChain) return kFALSE;
357 
358  return kTRUE;
359 }
360 
367 {
368  // AOD Event selection.
369  // TODO: Can we make centrality make sense here?
370  /*if (!fEsdTreeMode && fAODHeader) {
371  AliAODHeader *aodHeader = static_cast<AliAODHeader*>(fAODHeader);
372 
373  // Centrality selection
374  if (fMinCentrality >= 0) {
375  AliCentrality *cent = aodHeader->GetCentralityP();
376  Float_t centVal = cent->GetCentralityPercentile("V0M");
377  if (centVal < fMinCentrality || centVal >= fMaxCentrality) {
378  AliDebug(2,Form("Event rejected due to centrality selection. Event centrality: %f, centrality range selection: %f to %f",
379  centVal, fMinCentrality, fMaxCentrality));
380  return kFALSE;
381  }
382  }
383  }*/
384 
385  // Trigger selection
386  if (fTriggerMask != AliVEvent::kAny) {
387  UInt_t res = 0;
388  const AliESDEvent *eev = dynamic_cast<const AliESDEvent*>(InputEvent());
389  if (eev) {
390  res = ((AliInputEventHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))->IsEventSelected();
391  } else {
392  const AliAODEvent *aev = dynamic_cast<const AliAODEvent*>(InputEvent());
393  if (aev) {
394  res = ((AliVAODHeader*)aev->GetHeader())->GetOfflineTrigger();
395  }
396  }
397 
398  if ((res & fTriggerMask) == 0) {
399  AliDebug(3, Form("Event rejected due to physics selection. Event trigger mask: %d, trigger mask selection: %d.",
400  res, fTriggerMask));
401  return kFALSE;
402  }
403  }
404 
405  // Vertex selection
406  Double_t externalVertex[3]={0};
407  Double_t inputVertex[3]={0};
408  const AliVVertex *externalVert = fExternalEvent->GetPrimaryVertex();
409  const AliVVertex *inputVert = InputEvent()->GetPrimaryVertex();
410  if (externalVert && inputVert) {
411  externalVert->GetXYZ(externalVertex);
412  inputVert->GetXYZ(inputVertex);
413 
414  if (TMath::Abs(externalVertex[2]) > fZVertexCut) {
415  AliDebug(3, Form("Event rejected due to Z vertex selection. Event Z vertex: %f, Z vertex cut: %f",
416  externalVertex[2], fZVertexCut));
417  return kFALSE;
418  }
419  Double_t dist = TMath::Sqrt((externalVertex[0]-inputVertex[0])*(externalVertex[0]-inputVertex[0])+(externalVertex[1]-inputVertex[1])*(externalVertex[1]-inputVertex[1])+(externalVertex[2]-inputVertex[2])*(externalVertex[2]-inputVertex[2]));
420  if (dist > fMaxVertexDist) {
421  AliDebug(3, Form("Event rejected because the distance between the current and embedded vertices is > %f. "
422  "Current event vertex (%f, %f, %f), embedded event vertex (%f, %f, %f). Distance = %f",
423  fMaxVertexDist, inputVertex[0], inputVertex[1], inputVertex[2], externalVertex[0], externalVertex[1], externalVertex[2], dist));
424  return kFALSE;
425  }
426  }
427 
428  // TODO: Can we do selection based on the contents of the external event input objects?
429  // The previous embedding task could do so by directly accessing the elements.
430  // Certainly can't do jets (say minPt of leading jet) because this has to be embedded before them.
431  // See AliJetEmbeddingFromAODTask::IsAODEventSelected()
432 
433  return kTRUE;
434 }
435 
442 {
443  if (!fChain) return kFALSE;
444 
445  if (!fExternalEvent) {
446  if (fTreeName == "aodTree") {
447  fExternalEvent = new AliAODEvent();
448  }
449  else if (fTreeName == "esdTree") {
450  fExternalEvent = new AliESDEvent();
451  }
452  else {
453  AliError(Form("Tree name %s not recognized!", fTreeName.Data()));
454  return kFALSE;
455  }
456  }
457 
458  fExternalEvent->ReadFromTree(fChain, fTreeName);
459 
460  return kTRUE;
461 }
462 
469 {
470  SetupEmbedding();
471 }
472 
480 {
481  // Setup TChain
482  fChain = new TChain(fTreeName);
483 
484  // Determine whether AliEn is needed
485  bool requiresAlien = false;
486  for (auto filename : fFilenames)
487  {
488  if (filename.find("alien://") != std::string::npos) {
489  requiresAlien = true;
490  }
491  }
492 
493  if (requiresAlien && !gGrid) {
494  AliInfo("Trying to connect to AliEn ...");
495  TGrid::Connect("alien://");
496  }
497 
498  // Add files for TChain
499  // See: https://stackoverflow.com/a/8533198
500  bool wrapped = false;
501  TString baseFileName("");
502  for (auto filename = fFilenames.begin() + fFilenameIndex; (filename != fFilenames.begin() + fFilenameIndex || !wrapped); filename++)
503  {
504  // Wraps the loop back around to the beginning
505  if (filename == fFilenames.end())
506  {
507  // Explicit check is needed. Otherwise, an offset of 0 would load the 0th entry twice.
508  if (fFilenameIndex == 0) {
509  break;
510  }
511  filename = fFilenames.begin();
512  wrapped = true;
513  }
514 
515  // AccessPathName() cannot handle the "#", so we need to strip it to check that the file exists.
516  baseFileName = filename->c_str();
517  if (baseFileName.Contains(".zip#")) {
518  Ssiz_t pos = baseFileName.Last('#');
519  baseFileName.Remove(pos);
520  }
521 
522  // Ensure that the file is accessible
523  if (gSystem->AccessPathName(baseFileName)) {
524  AliError(Form("File %s does not exist! Skipping!", baseFileName.Data()));
525  // Do not process the file if it is unaccessible, but continue processing
526  continue;
527  }
528 
529  // Add to the Chain
530  fChain->Add(filename->c_str());
531  }
532 
533  // Keep track of the total number of files in the TChain to ensure that we don't start repeating within the chain
534  fMaxNumberOfFiles = fChain->GetListOfFiles()->GetEntries();
535 
536  if (fFilenames.size() > fMaxNumberOfFiles) {
537  AliWarning(TString::Format("Number of input files (%lu) is larger than the number of available files (%i). Some filenames were likely invalid!", fFilenames.size(), fMaxNumberOfFiles));
538  }
539 
540  // Setup input event
541  Bool_t res = InitEvent();
542  if (!res) return kFALSE;
543 
544  return kTRUE;
545 }
546 
553 {
554  // Get file list
555  GetFilenames();
556 
557  // Setup TChain
558  Bool_t res = SetupInputFiles();
559  if (!res) { return; }
560 
561  // Note if getting random event access
563  AliInfo("Random event number access enabled!");
564  }
565 
566  fInitializedEmbedding = kTRUE;
567 }
568 
580 {
581  // Load first entry of the (next) file so that we can query information about it
582  // (it is unaccessible otherwise).
583  // Since fUpperEntry is the total number of entries, loading it will retrieve the
584  // next tree (in the next file) since entries are indexed starting from 0.
585  fChain->GetEntry(fUpperEntry);
586 
587  // Determine tree size and current entry
588  // Set the limits of the new tree
590  // Fine to be += as long as we started at 0
591  fUpperEntry += fChain->GetTree()->GetEntries();
592 
593  // Jump ahead at random if desired
594  // Determines the offset into the tree
596  fOffset = TMath::Nint(gRandom->Rndm()*(fUpperEntry-fLowerEntry))-1;
597  }
598  else {
599  fOffset = 0;
600  }
601 
602  // Sets which entry to start if the try
604 
605  // Keep track of the number of files that we have gone through
606  // To start from 0, we only increment if fLowerEntry > 0
607  if (fLowerEntry > 0) {
608  fFileNumber++;
609  }
610 
611  AliDebug(2, TString::Format("Will start embedding file %i beginning from entry %i (entry %i within the file). NOTE: This file number is not equal to the absolute file number in the file list!", fFileNumber, fCurrentEntry, fCurrentEntry - fLowerEntry));
612  // NOTE: Cannot use this print message, as it is possible that fMaxNumberOfFiles != fFilenames.size() because
613  // invalid filenames may be included in the fFilenames count!
614  //AliDebug(2, TString::Format("Will start embedding file %i as the %ith file beginning from entry %i.", (fFilenameIndex + fFileNumber) % fMaxNumberOfFiles, fFileNumber, fCurrentEntry));
615 
616  // (re)set whether we have wrapped the tree
617  fWrappedAroundTree = false;
618 
619  // Note that the tree in the new file has been initialized
620  fInitializedNewFile = kTRUE;
621 }
622 
629 {
630  if (!fInitializedEmbedding) {
631  AliError("Chain not initialized before running! Setting up now.");
632  SetupEmbedding();
633  }
634 
635  if (!fInitializedNewFile) {
636  InitTree();
637  }
638 
639  Bool_t res = GetNextEntry();
640 
641  if (!res) {
642  AliError("Unable to get the event to embed. Nothing will be embedded.");
643  return;
644  }
645 }
646 
651 {
652 }
653 
662 {
663  // Get the pointer to the existing analysis manager via the static access method.
664  //==============================================================================
665  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
666  if (!mgr)
667  {
668  ::Error("AddTaskEmcalEmbeddingHelper", "No analysis manager to connect to.");
669  return 0;
670  }
671 
672  // Check the analysis type using the event handlers connected to the analysis manager.
673  //==============================================================================
674  AliVEventHandler* handler = mgr->GetInputEventHandler();
675  if (!handler)
676  {
677  ::Error("AddTaskEmcalEmbeddingHelper", "This task requires an input event handler");
678  return 0;
679  }
680 
681  TString name = "AliAnalysisTaskEmcalEmbeddingHelper";
682 
683  AliAnalysisTaskEmcalEmbeddingHelper * mgrTask = static_cast<AliAnalysisTaskEmcalEmbeddingHelper *>(mgr->GetTask(name.Data()));
684  if (mgrTask) return mgrTask;
685 
686  // Create the task that manages
688 
689  //-------------------------------------------------------
690  // Final settings, pass to manager and set the containers
691  //-------------------------------------------------------
692 
693  mgr->AddTask(embeddingHelper);
694 
695  // Create containers for input/output
696  AliAnalysisDataContainer* cInput = mgr->GetCommonInputContainer();
697 
698  /*TString outputContainerName(name);
699  outputContainerName += "_histos";
700 
701  AliAnalysisDataContainer * cOutput = mgr->CreateContainer(outputContainerName.Data(),
702  TList::Class(),
703  AliAnalysisManager::kOutputContainer,
704  Form("%s", AliAnalysisManager::GetCommonFileName()));*/
705 
706  mgr->ConnectInput(embeddingHelper, 0, cInput);
707  //mgr->ConnectOutput(embeddingHelper, 1, cOutput);
708 
709  return embeddingHelper;
710 }
Bool_t fRandomEventNumberAccess
If true, it will start embedding from a random entry in the file rather than from the first...
Double_t fZVertexCut
Z vertex cut on embedded event.
const char * filename
Definition: TestFCM.C:1
double Double_t
Definition: External.C:58
Int_t fPtHardBin
ptHard bin for the given pythia production
Int_t fLowerEntry
! First entry of the current tree to be used for embedding
Int_t fAnchorRun
Anchor run for the given pythia production.
TString fFileListFilename
Name of the file list containing paths to files to embed.
Bool_t fRandomFileAccess
If true, it will start embedding from a random file in the input files list.
TSystem * gSystem
Int_t fCurrentEntry
! Current entry in the current tree
TFile * fExternalFile
! External file used for embedding
TChain * fChain
! External TChain (tree) containing the events available for embedding
Declaration of class AliAnalysisTaskEmcalEmbeddingHelper.
TRandom * gRandom
Int_t fMaxNumberOfFiles
! Max number of files that are in the TChain
int Int_t
Definition: External.C:63
unsigned int UInt_t
Definition: External.C:33
bool fInitializedEmbedding
! Notes where the TChain has been initialized for embedding
Implementation of task to embed external events.
Double_t fMaxVertexDist
Max distance between Z vertex of internal and embedded event.
AliVEvent * fExternalEvent
! Current external event available for embedding
TString fTreeName
Name of the ESD/AOD tree where the events are to be found.
Int_t fOffset
! Offset from fLowerEntry where the loop over the tree should start
bool fWrappedAroundTree
! Notes whether we have wrapped around the tree, which is important if the offset into the tree is no...
static AliAnalysisTaskEmcalEmbeddingHelper * AddTaskEmcalEmbeddingHelper()
ClassImp(AliAnalysisTaskCRC) AliAnalysisTaskCRC
bool fInitializedNewFile
! Notes where the entry indices have been initialized for a new tree in the chain ...
static AliAnalysisTaskEmcalEmbeddingHelper * fgInstance
! Global instance of this class
const char Option_t
Definition: External.C:48
bool Bool_t
Definition: External.C:53
Int_t fUpperEntry
! Last entry of the current tree to be used for embedding
Int_t fFilenameIndex
Index of vector containing paths to files to embed.
std::vector< std::string > fFilenames
! Paths to the files to embed
TString fFilePattern
File pattern to select AliEn files.
Int_t fFileNumber
! File number corresponding to the current tree