AliPhysics  608b256 (608b256)
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 <sstream>
18 #include <vector>
19 #include <algorithm>
20 #include <memory>
21 #include <fstream>
22 #include <iostream>
23 #include <bitset>
24 
25 #include <TFile.h>
26 #include <TMath.h>
27 #include <TRandom.h>
28 #include <TChain.h>
29 #include <TGrid.h>
30 #include <TGridResult.h>
31 #include <TSystem.h>
32 #include <TUUID.h>
33 #include <TKey.h>
34 #include <TProfile.h>
35 #include <TH1F.h>
36 #include <TRandom3.h>
37 #include <TList.h>
38 
39 #include <AliLog.h>
40 #include <AliAnalysisManager.h>
41 #include <AliVEvent.h>
42 #include <AliAODEvent.h>
43 #include <AliESDEvent.h>
44 #include <AliMCEvent.h>
45 #include <AliInputEventHandler.h>
46 #include <AliVHeader.h>
47 #include <AliAODMCHeader.h>
48 #include <AliGenPythiaEventHeader.h>
49 
50 #include "AliYAMLConfiguration.h"
51 #include "AliEmcalList.h"
52 #include "AliEmcalContainerUtils.h"
53 
55 
59 
64 {
65  if (!gGrid) {
66  AliInfoGeneralStream("AliAnalysisTaskEmcalEmbeddingHelper") << "Trying to connect to AliEn ...\n";
67  TGrid::Connect("alien://");
68  }
69  if (!gGrid) {
70  AliFatalGeneral("AliAnalysisTaskEmcalEmbeddingHelper", "Cannot access AliEn!");
71  }
72 }
73 
80 bool IsFileAccessible(std::string filename)
81 {
82  // Connect to AliEn if necessary
83  // Usually, `gGrid` will exist, so we won't need to waste time on find()
84  if (!gGrid && filename.find("alien://") != std::string::npos) {
86  }
87 
88  // AccessPathName() cannot handle the "#", so we need to strip it to check that the file exists.
89  if (filename.find(".zip#") != std::string::npos) {
90  std::size_t pos = filename.find_last_of("#");
91  filename.erase(pos);
92  }
93 
94  // AccessPathName() has an odd return value - false means that the file exists.
95  // NOTE: This is extremely inefficienct for TAlienSystem. It calls
96  // -> gapi_access() -> gapi_stat(). gapi_stat() calls "ls -l" on the basename directory,
97  // which can cause a load on AliEn.
98  bool res = gSystem->AccessPathName(filename.c_str());
99  // Normalize the result to true if file exists (needed because of the odd return value)
100  res = (res == false);
101  if (res == false) {
102  AliDebugGeneralStream("AliAnalysisTaskEmcalEmbeddingHelper", 4) << "File \"" << filename << "\" doees not exist!\n";
103  }
104 
105  return res;
106 }
107 
109 
115  fTriggerMask(0),
116  fMCRejectOutliers(false),
117  fPtHardJetPtRejectionFactor(4),
118  fZVertexCut(10),
119  fMaxVertexDist(999),
120  fInitializedConfiguration(false),
121  fInitializedNewFile(false),
122  fInitializedEmbedding(false),
123  fWrappedAroundTree(false),
124  fTreeName(""),
125  fNPtHardBins(1),
126  fPtHardBin(-1),
127  fRandomEventNumberAccess(kFALSE),
128  fRandomFileAccess(kTRUE),
129  fCreateHisto(true),
130  fYAMLConfig(),
131  fUseInternalEventSelection(false),
132  fUseManualInternalEventCuts(false),
133  fInternalEventCuts(),
134  fEmbeddedEventUsed(true),
135  fValidatedPhysicsSelection(false),
136  fInternalEventTriggerMask(0),
137  fCentMin(-999),
138  fCentMax(-999),
139  fRandomRejectionFactor(1.),
140  fRandom(0),
141  fAutoConfigurePtHardBins(false),
142  fAutoConfigureBasePath(""),
143  fAutoConfigureTrainTypePath(""),
144  fAutoConfigureIdentifier(""),
145  fFilePattern(""),
146  fInputFilename(""),
147  fFileListFilename(""),
148  fFilenameIndex(-1),
149  fFilenames(),
150  fConfigurationPath(""),
151  fEmbeddedRunlist(),
152  fPythiaCrossSectionFilenames(),
153  fExternalFile(nullptr),
154  fChain(nullptr),
155  fCurrentEntry(0),
156  fLowerEntry(0),
157  fUpperEntry(0),
158  fOffset(0),
159  fMaxNumberOfFiles(0),
160  fFileNumber(0),
161  fHistManager(),
162  fOutput(nullptr),
163  fExternalEvent(nullptr),
164  fExternalHeader(nullptr),
165  fPythiaHeader(nullptr),
166  fPythiaTrials(0),
167  fPythiaTrialsFromFile(0),
168  fPythiaCrossSection(0.),
169  fPythiaCrossSectionFromFile(0.),
170  fPythiaPtHard(0.),
171  fPrintTimingInfoToLog(false),
172  fTimer()
173 {
174  if (fgInstance != nullptr) {
175  AliError("An instance of AliAnalysisTaskEmcalEmbeddingHelper already exists: it will be deleted!!!");
176  delete fgInstance;
177  }
178 
179  fgInstance = this;
180 }
181 
188  AliAnalysisTaskSE(name),
189  fTriggerMask(0),
190  fMCRejectOutliers(false),
192  fZVertexCut(10),
193  fMaxVertexDist(999),
195  fInitializedNewFile(false),
196  fInitializedEmbedding(false),
197  fWrappedAroundTree(false),
198  fTreeName("aodTree"),
199  fNPtHardBins(1),
200  fPtHardBin(-1),
201  fRandomEventNumberAccess(kFALSE),
202  fRandomFileAccess(kTRUE),
203  fCreateHisto(true),
204  fYAMLConfig(),
208  fEmbeddedEventUsed(true),
211  fCentMin(-999),
212  fCentMax(-999),
214  fRandom(0),
216  fAutoConfigureBasePath("alien:///alice/cern.ch/user/a/alitrain/"),
217  fAutoConfigureTrainTypePath("PWGJE/Jets_EMC_PbPb/"),
218  fAutoConfigureIdentifier("autoConfigIdentifier"),
219  fFilePattern(""),
220  fInputFilename(""),
221  fFileListFilename(""),
222  fFilenameIndex(-1),
223  fFilenames(),
224  fConfigurationPath(""),
228  fChain(nullptr),
229  fCurrentEntry(0),
230  fLowerEntry(0),
231  fUpperEntry(0),
232  fOffset(0),
234  fFileNumber(0),
235  fHistManager(name),
236  fOutput(nullptr),
240  fPythiaTrials(0),
244  fPythiaPtHard(0.),
245  fPrintTimingInfoToLog(false),
246  fTimer()
247 {
248  if (fgInstance != 0) {
249  AliError("An instance of AliAnalysisTaskEmcalEmbeddingHelper already exists: it will be deleted!!!");
250  delete fgInstance;
251  }
252 
253  fgInstance = this;
254 
255  if (fCreateHisto) {
256  DefineOutput(1, AliEmcalList::Class());
257  }
258 }
259 
266 {
267  if (fgInstance == this) fgInstance = nullptr;
268  if (fExternalEvent) delete fExternalEvent;
269  if (fExternalFile) {
270  fExternalFile->Close();
271  delete fExternalFile;
272  }
273 }
274 
276 {
277  // Initialize %YAML configuration, if one is given
278  bool initializedYAML = InitializeYamlConfig();
279 
281 
282  // Get file list
283  bool result = GetFilenames();
284 
285  if (result && initializedYAML) {
287  }
288 
289  if (removeDummyTask == true) {
290  RemoveDummyTask();
291  }
292 
293  // Initialize the YAML config object for streaming
295 
296  // Print the results of the initialization
297  // Print outside of the ALICE Log system to ensure that it is always available!
298  std::cout << *this;
299 
300  return result;
301 }
302 
310 {
311  // Following the variable blocks defined in the header
312  // Embedded event properties
313  std::vector<std::string> physicsSelection;
314  bool res = fYAMLConfig.GetProperty("embeddedEventPhysicsSelection", physicsSelection, false);
315  if (res) {
317  }
318  res = fYAMLConfig.GetProperty("enableMCOutlierRejection", fMCRejectOutliers, false);
319  res = fYAMLConfig.GetProperty("ptHardJetPtRejectionFactor", fPtHardJetPtRejectionFactor, false);
320  res = fYAMLConfig.GetProperty("embeddedEventZVertexCut", fZVertexCut, false);
321  res = fYAMLConfig.GetProperty("maxVertexDifferenceDistance", fMaxVertexDist, false);
322 
323  // Embedding helper properties
324  res = fYAMLConfig.GetProperty("treeName", fTreeName, false);
325  res = fYAMLConfig.GetProperty("nPtHardBins", fNPtHardBins, false);
326  res = fYAMLConfig.GetProperty("ptHardBin", fPtHardBin, false);
327  res = fYAMLConfig.GetProperty("randomEventNumberAccess", fRandomEventNumberAccess, false);
328  res = fYAMLConfig.GetProperty("randomFileAccess", fRandomFileAccess, false);
329  res = fYAMLConfig.GetProperty("createHisto", fCreateHisto, false);
330  res = fYAMLConfig.GetProperty("printTimingInfoInLog", fPrintTimingInfoToLog, false);
331  // More general embedding helper properties
332  res = fYAMLConfig.GetProperty("filePattern", fFilePattern, false);
333  res = fYAMLConfig.GetProperty("inputFilename", fInputFilename, false);
334  res = fYAMLConfig.GetProperty("fileListFilename", fFileListFilename, false);
335  res = fYAMLConfig.GetProperty("filenameIndex", fFilenameIndex, false);
336  // Configuration path makes no sense, as we are already using the %YAML configuration
337  res = fYAMLConfig.GetProperty("runlist", fEmbeddedRunlist, false);
338  // Generally should not be set
339  res = fYAMLConfig.GetProperty("filenames", fFilenames, false);
340  res = fYAMLConfig.GetProperty("fPythiaCrossSectionFilenames", fPythiaCrossSectionFilenames, false);
341 
342  // Internal event selection properties
343  // NOTE: Need to define the base name here so that the property path is not ambiguous (due to otherwise only being `const char *`)
344  std::string baseName = "internalEventSelection";
345  res = fYAMLConfig.GetProperty({baseName, "enabled"}, fUseInternalEventSelection, false);
346  res = fYAMLConfig.GetProperty({baseName, "useManualCuts"}, fUseManualInternalEventCuts, false);
347  // Centrality
348  std::vector <double> centralityRange;
349  res = fYAMLConfig.GetProperty({baseName, "centralityRange"}, centralityRange, false);
350  if (res) {
351  if (centralityRange.size() != 2) {
352  AliErrorStream() << "Passed centrality range with " << centralityRange.size() << " entries, but 2 values are required. Ignoring values.\n";
353  }
354  else {
355  AliDebugStream(1) << "Setting internal event centrality range to [" << centralityRange.at(0) << ", " << centralityRange.at(1) << "]\n";
356  fCentMin = centralityRange.at(0);
357  fCentMax = centralityRange.at(1);
358  }
359  }
360  // Physics selection
361  res = fYAMLConfig.GetProperty({baseName, "physicsSelection"}, physicsSelection, false);
362  if (res) {
364  }
365 
366  // Auto configure pt hard properties
367  res = fYAMLConfig.GetProperty("autoConfigurePtHardBins", fAutoConfigurePtHardBins, false);
368  res = fYAMLConfig.GetProperty("autoConfigureBasePath", fAutoConfigureBasePath, false);
369  res = fYAMLConfig.GetProperty("autoConfigureTrainTypePath", fAutoConfigureTrainTypePath, false);
370  res = fYAMLConfig.GetProperty("autoConfigureIdentifier", fAutoConfigureIdentifier, false);
371  // Random rejection
372  res = fYAMLConfig.GetProperty("randomRejectionFactor", fRandomRejectionFactor, false);
373 }
374 
399 {
400  // Determine the pattern filename if not yet set
401  if (fInputFilename == "") {
402  if (fTreeName == "aodTree") {
403  fInputFilename = "AliAOD.root";
404  }
405  else if (fTreeName == "esdTree") {
406  fInputFilename = "AliESDs.root";
407  }
408  else {
409  AliFatal(TString::Format("Requested default (pattern) input filename, but could not determine file type from tree name \"%s\". Please check the tree name and set the pattern input filename", fTreeName.Data()));
410  }
411  }
412 
413  // Retrieve filenames if we don't have them yet.
414  if (fFilenames.size() == 0)
415  {
416  // Handle pt hard bin auto configuration
418  {
419  if (fPtHardBin > 0) {
420  AliFatal("Requested both pt hard bin auto configuration and selected a non-zero pt hard bin. These are incompatible options. Please check your configuration.");
421  }
422  bool success = AutoConfigurePtHardBins();
423  if (success == false) {
424  AliFatal("Pt hard bin auto configuration requested, but it failed. Please check the logs.\n");
425  }
426  }
427 
428  // Handle if fPtHardBin is set
429  // This will require formatting the file pattern in the proper way to support these substitutions
430  if (fPtHardBin != -1 && fFilePattern != "") {
431  fFilePattern = TString::Format(fFilePattern, fPtHardBin);
432  }
433 
434  // Setup AliEn access if needed
435  if (fFilePattern.Contains("alien://") || fFileListFilename.Contains("alien://")) {
437  }
438 
439  // Retrieve AliEn filenames directly from AliEn
440  bool usedFilePattern = false;
441  if (fFilePattern.Contains("alien://")) {
442  usedFilePattern = true;
443  AliDebug(2, TString::Format("Trying to retrieve file list from AliEn with pattern file %s...", fFilePattern.Data()));
444 
445  // Create a temporary filename based on a UUID to make sure that it doesn't overwrite any files
446  if (fFileListFilename == "") {
448  }
449 
450  // The query command cannot handle "alien://" in the file pattern, so we need to remove it for the command
451  TString filePattern = fFilePattern;
452  filePattern.ReplaceAll("alien://", "");
453 
454  // Execute the grid query to get the filenames
455  AliDebug(2, TString::Format("Trying to retrieve file list from AliEn with pattern \"%s\" and input filename \"%s\"", filePattern.Data(), fInputFilename.Data()));
456  auto result = gGrid->Query(filePattern.Data(), fInputFilename.Data());
457 
458  if (result) {
459 
460  // Loop over the result to store it in the fileList file
461  std::ofstream outFile(fFileListFilename);
462  for (int i = 0; i < result->GetEntries(); i++)
463  {
464  TString path = result->GetKey(i, "turl");
465  // "turl" corresponds to the full AliEn url
466 
467  // If a runlist is specified for good embedded runs, only include the file if it is in this runlist
468  if (IsRunInRunlist(path.Data())) {
469  outFile << path << "\n";
470  }
471  }
472  outFile.close();
473  }
474  else {
475  AliErrorStream() << "Failed to run grid query\n";
476  return false;
477  }
478  }
479 
480  // Handle a filelist on AliEn
481  if (fFileListFilename.Contains("alien://")) {
482  // Check if we already used the file pattern
483  if (usedFilePattern) {
484  AliErrorStream() << "You set both the file pattern and the file list filename! The file list filename will override the pattern! Pattern: \"" << fFilePattern << "\", filename: \"" << fFileListFilename << "\"\nPlease check that this is the desired behavior!\n";
485  }
486 
487  // Determine the local filename and copy file to local directory
488  std::string alienFilename = fFileListFilename.Data();
489  fFileListFilename = gSystem->BaseName(alienFilename.c_str());
491 
492  TFile::Cp(alienFilename.c_str(), fFileListFilename.Data());
493  }
494 
495  std::ifstream inputFile(fFileListFilename);
496 
497  // Copy available files into the filenames vector
498  // From:: https://stackoverflow.com/a/8365247
499  std::copy(std::istream_iterator<std::string>(inputFile),
500  std::istream_iterator<std::string>(),
501  std::back_inserter(fFilenames));
502 
503  inputFile.close();
504  }
505 
506  if (fFilenames.size() == 0) {
507  AliFatal(TString::Format("Filenames from pattern \"%s\" and file list \"%s\" yielded an empty list!", fFilePattern.Data(), fFileListFilename.Data()));
508  }
509 
510  // Add "#" to files in there are any zip files
511  // It is require to open the proper root file within the zip
512  for (auto filename : fFilenames)
513  {
514  if (filename.find(".zip") != std::string::npos && filename.find("#") == std::string::npos) {
515  filename += "#";
517  if (fTreeName == "aodTree") {
518  filename += "#AliAOD.root";
519  }
520  else if (fTreeName == "esdTree") {
521  filename += "#AliESDs.root";
522  }
523  else {
524  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()));
525  return false;
526  }
527  }
528  }
529 
530  // Determine whether AliEn is needed
531  // It is possible that this has not been determined up to this point
532  for (auto filename : fFilenames)
533  {
534  if (filename.find("alien://") != std::string::npos) {
536  // No point in continuing to search once we know that it is needed
537  break;
538  }
539  }
540 
541  // Check if each filenames exists. If they do not exist, then remove them for fFilenames
542  unsigned int initialSize = fFilenames.size();
543  // NOTE: We invert the result of IsFileAccessible because we should return true for files that should be _removed_ (ie are inaccessible)
544  fFilenames.erase(std::remove_if(fFilenames.begin(), fFilenames.end(), [](const std::string & filename) {return (::IsFileAccessible(filename) == false);} ), fFilenames.end());
545 
546  AliInfoStream() << "Found " << fFilenames.size() << " files to embed (" << (initialSize - fFilenames.size()) << " filename(s) inaccessible or invalid)\n";
547 
548  // Determine pythia filename
550 
551  return true;
552 }
553 
559 {
560  // Get the initial filename. Use the first entry as a proxy for other input files
561  std::string externalEventFilename = "";
562  if (fFilenames.size() > 0) {
563  externalEventFilename = fFilenames.at(0);
564  }
565  else {
566  return;
567  }
568 
569  std::vector <std::string> pythiaBaseFilenames = {"pyxsec.root", "pyxsec_hists.root"};
570  AliInfoStream() << "Attempting to determine pythia cross section filename. It can be normal to see some TFile::Init() errors!\n";
571  std::string pythiaXSecFilename = "";
572  for (auto & name : pythiaBaseFilenames) {
573  pythiaXSecFilename = ConstructFullPythiaXSecFilename(externalEventFilename, name, true);
574  if (pythiaXSecFilename != "") {
575  AliDebugStream(4) << "Found pythia cross section filename \"" << name << "\"\n";
576  fPythiaXSecFilename = name;
577  break;
578  }
579  }
580 
581  if (fPythiaXSecFilename == "") {
582  // Failed entirely - just give up on this
583  // We will use an empty filename as a proxy for whether the file has been found (empty is equivalent to not found)
584  AliErrorStream() << "Failed to find pythia x sec file! Continuing with only the pythia header!\n";
585  }
586  else {
587  AliInfoStream() << "Found pythia cross section file \"" << fPythiaXSecFilename << "\".\n";
588  }
589 }
590 
591 
599 bool AliAnalysisTaskEmcalEmbeddingHelper::IsRunInRunlist(const std::string & path) const
600 {
601  if (fEmbeddedRunlist.size() == 0) {
602  return true;
603  }
604 
605  for (auto run : fEmbeddedRunlist) {
606  if (path.find(run) != std::string::npos) {
607  return true;
608  }
609  }
610  return false;
611 }
612 
619 {
620  if (fConfigurationPath == "") {
621  AliInfo("No Embedding YAML configuration was provided");
622  }
623  else {
624  AliInfoStream() << "Embedding YAML configuration was provided: \"" << fConfigurationPath << "\".\n";
625 
626  int addedConfig = fYAMLConfig.AddConfiguration(fConfigurationPath, "yamlConfig");
627  if (addedConfig < 0) {
628  AliError("YAML Configuration not found!");
629  return false;
630  }
631  }
632 
633  return true;
634 }
635 
652 {
653  bool returnValue = false;
654 
655  AliInfoStream() << "Attempting to auto configure pt hard bins.\n";
656  // %YAML configuration containing pt hard bin to train number mapping
658 
659  // Handle AliEn explicitly here since the default base path contains "alien://"
660  if (fAutoConfigureBasePath.find("alien://") != std::string::npos && !gGrid) {
662  }
663 
664  // Get train ID
665  // Need to get the char * directly because it may be null.
666  const char * trainNumberStr = gSystem->Getenv("TRAIN_RUN_ID");
667  std::stringstream trainNumberSS;
668  if (trainNumberStr) {
669  trainNumberSS << trainNumberStr;
670  }
671  if (trainNumberSS.str() == "") {
672  AliFatal("Cannot retrieve train ID.");
673  }
674  // Extract train number from the string
675  int trainNumber;
676  trainNumberSS >> trainNumber;
677 
678  // Determine the file path
680  filename += "/";
682  filename += "/";
684  // Add ".yaml" if it is not already there
685  std::string yamlExtension = ".yaml";
686  if (filename.find(yamlExtension) == std::string::npos) {
687  filename += yamlExtension;
688  }
689 
690  // Check if file exists
691  if (gSystem->AccessPathName(filename.c_str())) {
692  // File _does not_ exist
693  AliInfoStream() << "Train pt hard bin configuration file not available, so creating a new empty configuration named \"" << fAutoConfigureIdentifier << "\".\n";
694  // Use an empty configuration
696  }
697  else {
698  AliInfoStream() << "Opening configuration located at \"" << filename << "\".\n";
699  // Use the existing configuration
701  }
702 
703  // Look for each pt hard bin, and then retrieve the corresponding train number
704  // Once an open pt hard bin is found, add the current train number
705  int tempTrainNumber = -1;
706  bool getPropertyReturnValue = false;
707  std::stringstream propertyName;
708  for (int ptHardBin = 1; ptHardBin <= fNPtHardBins; ptHardBin++)
709  {
710  propertyName.str("");
711  propertyName << ptHardBin;
712  getPropertyReturnValue = config.GetProperty(propertyName.str(), tempTrainNumber, false);
713  if (getPropertyReturnValue != true) {
714  AliInfoStream() << "Train " << trainNumber << " will use pt hard bin " << ptHardBin << ".\n";
715  // We have determine our pt hard bin!
716  fPtHardBin = ptHardBin;
717 
718  // Write the train number back out to the %YAML configuration and save it
719  config.WriteProperty(propertyName.str(), trainNumber, fAutoConfigureIdentifier);
721 
722  // NOTE: Cannot clean up the YAML file on the last pt hard bin because the train can be launched
723  // multiple times due to tests, etc. Therefore, we have to accept that we are leaving around used
724  // YAML config files.
725 
726  // We are done - continue on.
727  returnValue = true;
728  break;
729  }
730  else {
731  AliDebugStream(2) << "Found pt hard bin " << ptHardBin << " corresponding to train number " << trainNumber << ".\n";
732  // If train was already allocated (say, by a test train), then use that pt hard bin
733  if (tempTrainNumber == trainNumber) {
734  AliInfoStream() << "Train run number " << trainNumber << " was already found assigned to pt hard bin " << ptHardBin << ". That pt hard bin will be used.\n";
735  fPtHardBin = ptHardBin;
736 
737  // We are done - continue on.
738  returnValue = true;
739  break;
740  }
741  // Otherwise, nothing to be done.
742  }
743  }
744 
745  return returnValue;
746 }
747 
756 {
757  std::string tempStr = "";
758  if (fFileListFilename == "") {
759  tempStr = "fileList";
760  }
761  TUUID tempUUID;
762  tempStr += ".";
763  tempStr += tempUUID.AsString();
764  tempStr += ".txt";
765 
766  return tempStr;
767 }
768 
777 {
778  while (filename.rbegin() != filename.rend() && *(filename.rbegin()) == '/') {
779  filename.pop_back();
780  }
781 
782  return filename;
783 }
784 
790 {
791  // This determines which file is added first to the TChain, thus determining the order of processing
792  // Random file access. Only do this if the user has no set the filename index and request random file access
793  if (fFilenameIndex == -1 && fRandomFileAccess) {
794  // Floor ensures that we it doesn't overflow
795  TRandom3 rand(0);
796  fFilenameIndex = TMath::FloorNint(rand.Rndm()*fFilenames.size());
797  // +1 to account for the fact that the filenames vector is 0 indexed.
798  AliInfo(TString::Format("Starting with random file number %i!", fFilenameIndex+1));
799  }
800  // If not random file access, then start from the beginning
801  if (fFilenameIndex < 0 || static_cast<UInt_t>(fFilenameIndex) >= fFilenames.size()) {
802  // Skip notifying on -1 since it will likely be set there due to constructor.
803  if (fFilenameIndex != -1) {
804  AliWarning(TString::Format("File index %i out of range from 0 to %lu! Resetting to 0!", fFilenameIndex, fFilenames.size()));
805  }
806  fFilenameIndex = 0;
807  }
808 
809  // +1 to account for the fact that the filenames vector is 0 indexed.
810  AliInfo(TString::Format("Starting with file number %i out of %lu", fFilenameIndex+1, fFilenames.size()));
811 }
812 
822 {
823  Int_t attempts = -1;
824 
825  do {
826  // Reset to start of tree
827  if (fCurrentEntry == fUpperEntry) {
829  fWrappedAroundTree = true;
830  }
831 
833  // Continue with GetEntry as normal
834  }
835  else {
836  // NOTE: On transition from one file to the next, this calls the next entry that would be expected.
837  // However, if it is for the last file, it tries to GetEntry() of one entry past the end of the last
838  // file. Normally, this would be a problem, however GetEntry() just doesn't fill the fields of an
839  // invalid index instead of throwing an error. So "invalid values" are filled for a file that doesn't
840  // exist, but then they are immediately replaced by the lines below that reset the access values and
841  // re-init the tree. The benefit of this approach is it simplies file counting (we don't need to
842  // carefully increment here and in InitTree()) and preserves the desired behavior when we are not at
843  // the last file.
844  InitTree();
845  }
846 
847  // Load current event
848  // Can be a simple less than, because fFileNumber counts from 0.
850  fChain->GetEntry(fCurrentEntry);
851  }
852  else {
853  AliError("====================================================================================================");
854  AliError("== No more files available to embed from the TChain! Restarting from the beginning of the TChain! ==");
855  AliError("== Be careful to check that this is the desired action! ==");
856  AliError("====================================================================================================");
857 
858  // Reset the relevant access values
859  // fCurrentEntry and fLowerEntry are automatically reset in InitTree()
860  fFileNumber = 0;
861  fUpperEntry = 0;
862 
863  // Re-init back to the start
864  InitTree();
865 
866  // Access the relevant entry
867  // We are certain that fFileNumber is less than fMaxNumberOfFiles, so we are resetting to start
868  fChain->GetEntry(fCurrentEntry);
869  }
870  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));
871 
872  // Set relevant event properties
874 
875  // Increment current entry
876  fCurrentEntry++;
877 
878  // Provide a check for number of attempts
879  attempts++;
880  if (attempts == 1000)
881  AliWarning("After 1000 attempts no event has been accepted by the event selection (trigger, centrality...)!");
882 
883  // Record event properties
884  if (fCreateHisto) {
886  }
887 
888  } while (!IsEventSelected());
889 
890  if (fCreateHisto) {
891  fHistManager.FillTH1("fHistEventCount", "Accepted");
892  fHistManager.FillTH1("fHistEmbeddedEventsAttempted", attempts);
893  }
894 
895  if (!fChain) return kFALSE;
896 
897  return kTRUE;
898 }
899 
905 {
906  AliDebug(4, "Set event properties");
907  fExternalHeader = fExternalEvent->GetHeader();
908 
909  // Handle pythia header if AOD
910  AliAODMCHeader* aodMCH = dynamic_cast<AliAODMCHeader*>(fExternalEvent->FindListObject(AliAODMCHeader::StdBranchName()));
911  if (aodMCH) {
912  for (UInt_t i = 0;i<aodMCH->GetNCocktailHeaders();i++) {
913  fPythiaHeader = dynamic_cast<AliGenPythiaEventHeader*>(aodMCH->GetCocktailHeader(i));
914  if (fPythiaHeader) break;
915  }
916  }
917 
918  if (fPythiaHeader)
919  {
920  fPythiaCrossSection = fPythiaHeader->GetXsection();
921  fPythiaTrials = fPythiaHeader->Trials();
922  fPythiaPtHard = fPythiaHeader->GetPtHard();
923  // It is identically zero if the cross section is not available
924  if (fPythiaCrossSection == 0.) {
925  AliDebugStream(4) << "Taking the pythia cross section avg from the xsec file.\n";
927  }
928  // It is identically zero if the number of trials is not available
929  if (fPythiaTrials == 0.) {
930  AliDebugStream(4) << "Taking the pythia trials avg from the xsec file.\n";
932  }
933  // Pt hard is inherently event-by-event and cannot by taken as a avg quantity.
934 
935  AliDebugStream(4) << "Pythia header is defined!\n";
936  AliDebugStream(4) << "fPythiaCrossSection: " << fPythiaCrossSection << "\n";
937  }
938 }
939 
944 {
945  // Fill trials, xsec, pt hard
946  fHistManager.FillTH1("fHistTrials", fPtHardBin, fPythiaTrials);
948  fHistManager.FillTH1("fHistPtHard", fPythiaPtHard);
949 }
950 
957 {
959  return kTRUE;
960  }
961 
962  if (fCreateHisto) {
963  // Keep count of number of rejected events
964  fHistManager.FillTH1("fHistEventCount", "Rejected");
965  }
966 
967  return kFALSE;
968 }
969 
976 {
977  // Check if pt hard bin is 0, indicating a problem with the event or the grid.
978  // In such a case, the event should be rejected.
979  // This condition should only be applied if we have a valid pythia header.
980  // (pt hard should still be set even if the production wasn't done in pt hard bins).
981  if (fPythiaPtHard == 0. && fPythiaHeader) {
982  AliDebugStream(3) << "Event rejected due to pt hard = 0, indicating a problem with the external event.\n";
983  if (fCreateHisto) {
984  fHistManager.FillTH1("fHistEmbeddedEventRejection", "PtHardIs0", 1);
985  }
986  return kFALSE;
987  }
988 
989  // Physics selection
990  if (fTriggerMask != 0) {
991  UInt_t res = 0;
992  const AliESDEvent *eev = dynamic_cast<const AliESDEvent*>(fExternalEvent);
993  if (eev) {
994  AliFatal("Event selection is not implemented for embedding ESDs.");
995  // Unfortunately, the normal method of retrieving the trigger mask (commented out below) doesn't work for the embedded event since we don't
996  // create an input handler and I am not an expert on getting a trigger mask. Further, embedding ESDs is likely to be inefficient, so it is
997  // probably best to avoid it if possible.
998  //
999  // Suggestions are welcome here!
1000  //res = (dynamic_cast<AliInputEventHandler*>(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))->IsEventSelected();
1001  } else {
1002  const AliAODEvent *aev = dynamic_cast<const AliAODEvent*>(fExternalEvent);
1003  if (aev) {
1004  res = (dynamic_cast<AliVAODHeader*>(aev->GetHeader()))->GetOfflineTrigger();
1005  }
1006  }
1007 
1008  if ((res & fTriggerMask) == 0) {
1009  AliDebug(3, Form("Event rejected due to physics selection. Event trigger mask: %d, trigger mask selection: %d.",
1010  res, fTriggerMask));
1011  if (fCreateHisto) {
1012  fHistManager.FillTH1("fHistEmbeddedEventRejection", "PhysSel", 1);
1013  }
1014  return kFALSE;
1015  }
1016  }
1017 
1018  // Vertex selection
1019  Double_t externalVertex[3]={0};
1020  Double_t inputVertex[3]={0};
1021  const AliVVertex *externalVert = fExternalEvent->GetPrimaryVertex();
1022  const AliVVertex *inputVert = AliAnalysisTaskSE::InputEvent()->GetPrimaryVertex();
1023  if (externalVert && inputVert) {
1024  externalVert->GetXYZ(externalVertex);
1025  inputVert->GetXYZ(inputVertex);
1026 
1027  if (TMath::Abs(externalVertex[2]) > fZVertexCut) {
1028  AliDebug(3, Form("Event rejected due to Z vertex selection. Event Z vertex: %f, Z vertex cut: %f",
1029  externalVertex[2], fZVertexCut));
1030  if (fCreateHisto) {
1031  fHistManager.FillTH1("fHistEmbeddedEventRejection", "Vz", 1);
1032  }
1033  return kFALSE;
1034  }
1035  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]));
1036  if (dist > fMaxVertexDist) {
1037  AliDebug(3, Form("Event rejected because the distance between the current and embedded vertices is > %f. "
1038  "Current event vertex (%f, %f, %f), embedded event vertex (%f, %f, %f). Distance = %f",
1039  fMaxVertexDist, inputVertex[0], inputVertex[1], inputVertex[2], externalVertex[0], externalVertex[1], externalVertex[2], dist));
1040  if (fCreateHisto) {
1041  fHistManager.FillTH1("fHistEmbeddedEventRejection", "VertexDist", 1);
1042  }
1043  return kFALSE;
1044  }
1045  }
1046 
1047  // Check for pt hard bin outliers
1049  {
1050  // Pythia jet / pT-hard > factor
1051  // This corresponds to "condition 1" in AliAnalysisTaskEmcal
1052  // NOTE: The other "conditions" defined there are not really suitable to define here, since they
1053  // depend on the input objects of the event
1054  if (fPtHardJetPtRejectionFactor > 0.) {
1055  TLorentzVector jet;
1056 
1057  Int_t nTriggerJets = fPythiaHeader->NTriggerJets();
1058 
1059  AliDebugStream(4) << "Pythia Njets: " << nTriggerJets << ", pT Hard: " << fPythiaPtHard << "\n";
1060 
1061  Float_t tmpjet[]={0,0,0,0};
1062  for (Int_t iJet = 0; iJet< nTriggerJets; iJet++) {
1063  fPythiaHeader->TriggerJet(iJet, tmpjet);
1064 
1065  jet.SetPxPyPzE(tmpjet[0],tmpjet[1],tmpjet[2],tmpjet[3]);
1066 
1067  AliDebugStream(5) << "Pythia jet " << iJet << ", pycell jet pT: " << jet.Pt() << "\n";
1068 
1069  //Compare jet pT and pt Hard
1070  if (jet.Pt() > fPtHardJetPtRejectionFactor * fPythiaPtHard) {
1071  AliDebugStream(3) << "Event rejected because of MC outlier removal. Pythia header jet with: pT Hard " << fPythiaPtHard << ", pycell jet pT " << jet.Pt() << ", rejection factor " << fPtHardJetPtRejectionFactor << "\n";
1072  fHistManager.FillTH1("fHistEmbeddedEventRejection", "MCOutlier", 1);
1073  return kFALSE;
1074  }
1075  }
1076  }
1077  }
1078 
1079  return kTRUE;
1080 }
1081 
1088 {
1089  if (!fChain) return kFALSE;
1090 
1091  if (!fExternalEvent) {
1092  if (fTreeName == "aodTree") {
1093  fExternalEvent = new AliAODEvent();
1094  }
1095  else if (fTreeName == "esdTree") {
1096  fExternalEvent = new AliESDEvent();
1097  }
1098  else {
1099  AliError(Form("Tree name %s not recognized!", fTreeName.Data()));
1100  return kFALSE;
1101  }
1102  }
1103 
1104  fExternalEvent->ReadFromTree(fChain, fTreeName);
1105 
1106  return kTRUE;
1107 }
1108 
1115 {
1116  SetupEmbedding();
1117 
1118  // Reinitialize the YAML config after it was streamed so that it can be used properly.
1120 
1121  // Setup AliEventCuts
1123  {
1124  AliDebugStream(1) << "Configuring AliEventCuts for internal event selection.\n";
1125  // Handle manual cuts
1127  fInternalEventCuts.SetManualMode();
1128  // Implement these cuts by retrieving the event cuts object and setting them manually.
1129  }
1130 
1131  // Trigger selection
1132  bool useEventCutsAutomaticTriggerSelection = false;
1133  bool res = fYAMLConfig.GetProperty(std::vector<std::string>({"internalEventSelection", "useEventCutsAutomaticTriggerSelection"}), useEventCutsAutomaticTriggerSelection, false);
1134  if (res && useEventCutsAutomaticTriggerSelection) {
1135  // Use the automatic selection. We will validate the trigger mask later because it
1136  // isn't yet set if we're using automatic mode.
1137  AliDebugStream(1) << "Using the automatic trigger selection from AliEventCuts.\n";
1138  }
1139  else {
1140  // Use the cuts selected by via YAML.
1141  std::bitset<32> triggerMask(fInternalEventTriggerMask);
1142  AliDebugStream(1) << "Using the trigger selection specified via YAML: " << triggerMask << ".\n";
1143  fInternalEventCuts.OverrideAutomaticTriggerSelection(fInternalEventTriggerMask);
1144  }
1145  }
1146 
1147  // Set up timer for logging purposes
1148  if (fPrintTimingInfoToLog) {
1149  fTimer = TStopwatch();
1150  }
1151 
1152  if (!fCreateHisto) {
1153  return;
1154  }
1155 
1156  // Create output list
1157  OpenFile(1);
1158  fOutput = new AliEmcalList();
1159  fOutput->SetOwner();
1160 
1161  // Get the histograms from AliEventCuts
1163  // This list will be owned by fOutput, so it won't be leaked.
1164  TList * eventCutsOutput = new TList();
1165  eventCutsOutput->SetOwner(kTRUE);
1166  eventCutsOutput->SetName("EventCuts");
1167 
1168  // Add the event cuts to the output
1169  fInternalEventCuts.AddQAplotsToList(eventCutsOutput);
1170  fOutput->Add(eventCutsOutput);
1171  }
1172 
1173  // Create histograms
1174  TString histName;
1175  TString histTitle;
1176 
1177  // Cross section
1178  histName = "fHistXsection";
1179  histTitle = "Pythia Cross Section;p_{T} hard bin; XSection";
1180  fHistManager.CreateTProfile(histName, histTitle, fNPtHardBins, 0, fNPtHardBins);
1181 
1182  // Trials
1183  histName = "fHistTrials";
1184  histTitle = "Number of Pythia Trials;p_{T} hard bin;Trials";
1185  fHistManager.CreateTH1(histName, histTitle, fNPtHardBins, 0, fNPtHardBins);
1186 
1187  // Pt hard spectra
1188  histName = "fHistPtHard";
1189  histTitle = "p_{T} Hard Spectra;p_{T} hard;Counts";
1190  fHistManager.CreateTH1(histName, histTitle, 500, 0, 1000);
1191 
1192  // Count of accepted and rejected events
1193  histName = "fHistEventCount";
1194  histTitle = "Event count;Result;Count";
1195  auto histEventCount = fHistManager.CreateTH1(histName, histTitle, 2, 0, 2);
1196  histEventCount->GetXaxis()->SetBinLabel(1,"Accepted");
1197  histEventCount->GetXaxis()->SetBinLabel(2,"Rejected");
1198 
1199  // Event rejection reason
1200  histName = "fHistEmbeddedEventRejection";
1201  histTitle = "Reasons to reject embedded event";
1202  std::vector<std::string> binLabels = {"PhysSel", "MCOutlier", "Vz", "VertexDist", "PtHardIs0"};
1203  auto histEmbeddedEventRejection = fHistManager.CreateTH1(histName, histTitle, binLabels.size(), 0, binLabels.size());
1204  // Set label names
1205  for (unsigned int i = 1; i <= binLabels.size(); i++) {
1206  histEmbeddedEventRejection->GetXaxis()->SetBinLabel(i, binLabels.at(i-1).c_str());
1207  }
1208  histEmbeddedEventRejection->GetYaxis()->SetTitle("Counts");
1209 
1210  // Rejected events in embedded event selection
1211  histName = "fHistEmbeddedEventsAttempted";
1212  histTitle = "Number of embedded events rejected by event selection before success;Number of rejected events;Counts";
1213  fHistManager.CreateTH1(histName, histTitle, 200, 0, 200);
1214 
1215  // Number of files embedded
1216  histName = "fHistNumberOfFilesEmbedded";
1217  histTitle = "Number of files which contributed events to be embedded";
1218  fHistManager.CreateTH1(histName, histTitle, 1, 0, 2);
1219 
1220  // File number which was embedded
1221  histName = "fHistAbsoluteFileNumber";
1222  histTitle = "Number of times each absolute file number was embedded";
1223  fHistManager.CreateTH1(histName, histTitle, fMaxNumberOfFiles, 0, fMaxNumberOfFiles);
1224 
1226  // Internal event cut statistics
1227  histName = "fHistInternalEventCutsStats";
1228  histTitle = "Number of events to pass each cut";
1229  binLabels = {"passedEventCuts", "centrality", "passedRandomRejection", "passedAllCuts"};
1230  auto histInternalEventCutsStats = fHistManager.CreateTH1(histName, histTitle, binLabels.size(), 0, binLabels.size());
1231  // Set label names
1232  for (unsigned int i = 1; i <= binLabels.size(); i++) {
1233  histInternalEventCutsStats->GetXaxis()->SetBinLabel(i, binLabels.at(i-1).c_str());
1234  }
1235  histInternalEventCutsStats->GetYaxis()->SetTitle("Number of selected events");
1236  }
1237 
1238  // Time to execute InitTree()
1239  if (fPrintTimingInfoToLog) {
1240  histName = "fInitTreeCPUtime";
1241  histTitle = "CPU time to execute InitTree() (s)";
1242  fHistManager.CreateTH1(histName, histTitle, 200, 0, 2000);
1243 
1244  histName = "fInitTreeRealtime";
1245  histTitle = "Real time to execute InitTree() (s)";
1246  fHistManager.CreateTH1(histName, histTitle, 200, 0, 2000);
1247  }
1248 
1249  // Add all histograms to output list
1250  TIter next(fHistManager.GetListOfHistograms());
1251  TObject* obj = 0;
1252  while ((obj = next())) {
1253  fOutput->Add(obj);
1254  }
1255 
1256  PostData(1, fOutput);
1257 }
1258 
1266 {
1267  // Determine which file to start with
1269 
1270  // Setup TChain
1271  fChain = new TChain(fTreeName);
1272 
1273  // Determine whether AliEn is needed
1274  for (auto filename : fFilenames)
1275  {
1276  if (filename.find("alien://") != std::string::npos) {
1277  ::ConnectToAliEn();
1278  // No point in continuing to search once we know that it is needed
1279  break;
1280  }
1281  }
1282 
1283  // Add files for TChain
1284  // See: https://stackoverflow.com/a/8533198
1285  bool wrapped = false;
1286  std::string fullPythiaXSecFilename = "";
1287  for (auto filename = fFilenames.begin() + fFilenameIndex; (filename != fFilenames.begin() + fFilenameIndex || !wrapped); filename++)
1288  {
1289  // Wraps the loop back around to the beginning
1290  if (filename == fFilenames.end())
1291  {
1292  // Explicit check is needed. Otherwise, an offset of 0 would load the 0th entry twice.
1293  if (fFilenameIndex == 0) {
1294  break;
1295  }
1296  filename = fFilenames.begin();
1297  wrapped = true;
1298  }
1299 
1300  // Add to the Chain
1301  AliDebugStream(4) << "Adding file to the embedded input chain \"" << *filename << "\".\n";
1302  fChain->Add(filename->c_str());
1303 
1304  // Determine the full pythia cross section filename based on the previously determined filename
1305  // If we have determined that it doesn't exist in the initialization then we don't repeated attempt to open
1306  // the file (which will fail)
1307  if (fPythiaXSecFilename != "") {
1308  // Could check here again whether it exists here, but almost certainly unnecessary.
1309  // Further, we won't check to ensure that rapid, repeated file access on AliEn doesn't cause any problmes!
1310  fullPythiaXSecFilename = ConstructFullPythiaXSecFilename(*filename, fPythiaXSecFilename, false);
1311 
1312  AliDebugStream(4) << "Adding pythia cross section file \"" << fullPythiaXSecFilename << "\".\n";
1313 
1314  // They will automatically be ordered the same as the files to embed!
1315  fPythiaCrossSectionFilenames.push_back(fullPythiaXSecFilename);
1316  }
1317  }
1318 
1319  // Keep track of the total number of files in the TChain to ensure that we don't start repeating within the chain
1320  fMaxNumberOfFiles = fChain->GetListOfFiles()->GetEntries();
1321 
1322  if (fFilenames.size() > fMaxNumberOfFiles) {
1323  AliErrorStream() << "Number of input files (" << fFilenames.size() << ") is larger than the number of available files (" << fMaxNumberOfFiles << "). Something went wrong when adding some of those files to the TChain!\n";
1324  }
1325 
1326  // Setup input event
1327  Bool_t res = InitEvent();
1328  if (!res) return kFALSE;
1329 
1330  return kTRUE;
1331 }
1332 
1343 std::string AliAnalysisTaskEmcalEmbeddingHelper::ConstructFullPythiaXSecFilename(std::string externalEventFilename, const std::string & pythiaFilename, bool testIfExists) const
1344 {
1345  std::string pythiaXSecFilename = "";
1346 
1347  // Remove "#*.root" if necessary
1348  if (externalEventFilename.find(".zip#") != std::string::npos) {
1349  std::size_t pos = externalEventFilename.find_last_of("#");
1350  externalEventFilename.erase(pos);
1351  }
1352 
1353  // Handle different file types
1354  if (externalEventFilename.find(".zip") != std::string::npos)
1355  {
1356  // Handle zip files
1357  pythiaXSecFilename = externalEventFilename;
1358  pythiaXSecFilename += "#";
1359  pythiaXSecFilename += pythiaFilename;
1360 
1361  // Check if the file is accessible
1362  if (testIfExists) {
1363  // Unfortunately, we cannot test for the existence of a file in an archive.
1364  // Instead, we have to tolerate TFile throwing an error (maximum of two).
1365  std::unique_ptr<TFile> fTemp(TFile::Open(pythiaXSecFilename.c_str(), "READ"));
1366 
1367  if (!fTemp) {
1368  AliDebugStream(4) << "File " << pythiaXSecFilename.c_str() << " does not exist!\n";
1369  pythiaXSecFilename = "";
1370  }
1371  else {
1372  AliDebugStream(4) << "Found pythia cross section file \"" << pythiaXSecFilename.c_str() << "\".\n";
1373  }
1374  }
1375  }
1376  else
1377  {
1378  // Handle normal root files
1379  pythiaXSecFilename = gSystem->DirName(externalEventFilename.c_str());
1380  pythiaXSecFilename += "/";
1381  pythiaXSecFilename += pythiaFilename;
1382 
1383  // Check if the file is accessible
1384  if (testIfExists) {
1385  if(::IsFileAccessible(pythiaXSecFilename)) {
1386  AliDebugStream(4) << "Found pythia cross section file \"" << pythiaXSecFilename.c_str() << "\".\n";
1387  }
1388  else {
1389  AliDebugStream(4) << "File " << pythiaXSecFilename.c_str() << " does not exist!\n";
1390  pythiaXSecFilename = "";
1391  }
1392  }
1393  }
1394 
1395  return pythiaXSecFilename;
1396 }
1397 
1404 {
1405  if (fInitializedConfiguration == false) {
1406  AliFatal("The configuration is not initialized. Check that Initialize() was called!");
1407  }
1408 
1409  // Setup TChain
1410  Bool_t res = SetupInputFiles();
1411  if (!res) { return; }
1412 
1413  // Note if getting random event access
1415  AliInfo("Random event number access enabled!");
1416  }
1417 
1418  fInitializedEmbedding = kTRUE;
1419 }
1420 
1432 {
1433  // Start the timer (for logging purposes)
1434  if (fPrintTimingInfoToLog) {
1435  fTimer.Start(kTRUE);
1436  std::cout << "InitTree() has started for file " << (fFilenameIndex + fFileNumber + 1) % fMaxNumberOfFiles << fChain->GetCurrentFile()->GetName() << "..." << std::endl;
1437  }
1438 
1439  // Load first entry of the (next) file so that we can query information about it
1440  // (it is inaccessible otherwise).
1441  // Since fUpperEntry is the total number of entries, loading it will retrieve the
1442  // next tree (in the next file) since entries are indexed starting from 0.
1443  fChain->GetEntry(fUpperEntry);
1444 
1445  // Determine tree size and current entry
1446  // Set the limits of the new tree
1448  // Fine to be += as long as we started at 0
1449  fUpperEntry += fChain->GetTree()->GetEntries();
1450 
1451  // Jump ahead at random if desired
1452  // Determines the offset into the tree
1454  TRandom3 rand(0);
1455  fOffset = TMath::Nint(rand.Rndm()*(fUpperEntry-fLowerEntry))-1;
1456  }
1457  else {
1458  fOffset = 0;
1459  }
1460 
1461  // Sets which entry to start if the try
1463 
1464  // Keep track of the number of files that we have gone through
1465  // To start from 0, we only increment if fLowerEntry > 0
1466  if (fLowerEntry > 0) {
1467  fFileNumber++;
1468  }
1469 
1470  // Add to the count the number of files which were embedded
1471  fHistManager.FillTH1("fHistNumberOfFilesEmbedded", 1);
1472  fHistManager.FillTH1("fHistAbsoluteFileNumber", (fFileNumber + fFilenameIndex) % fMaxNumberOfFiles);
1473 
1474  // Check for pythia cross section and extract if possible
1475  // fFileNumber corresponds to the next file
1476  // If there are pythia filenames, the number of match the file number of the tree.
1477  // If we previously gave up on extracting then there should be no entires
1478  if (fPythiaCrossSectionFilenames.size() > 0) {
1479  // Need to check that fFileNumber is smaller than the size of the vector because we don't check if
1482 
1483  if (!success) {
1484  AliDebugStream(3) << "Failed to retrieve cross section from xsec file. Will still attempt to get the information from the header.\n";
1485  }
1486  }
1487  else {
1488  AliErrorStream() << "Attempted to read past the end of the pythia cross section filenames vector. File number: " << fFileNumber << ", vector size: " << fPythiaCrossSectionFilenames.size() << ".\nThis should only occur if we have run out of files to embed!\n";
1489  }
1490  }
1491 
1492  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));
1493  // NOTE: Cannot use this print message, as it is possible that fMaxNumberOfFiles != fFilenames.size() because
1494  // invalid filenames may be included in the fFilenames count!
1495  //AliDebug(2, TString::Format("Will start embedding file %i as the %ith file beginning from entry %i.", (fFilenameIndex + fFileNumber) % fMaxNumberOfFiles, fFileNumber, fCurrentEntry));
1496 
1497  // (re)set whether we have wrapped the tree
1498  fWrappedAroundTree = false;
1499 
1500  // Note that the tree in the new file has been initialized
1501  fInitializedNewFile = kTRUE;
1502 
1503  // Stop timer (for logging purposes)
1504  if (fPrintTimingInfoToLog) {
1505  fTimer.Stop();
1506  std::cout << "InitTree() complete. CPU time: " << fTimer.CpuTime() << " (s). Real time: " << fTimer.RealTime() << " (s)." << std::endl;
1507  fHistManager.FillTH1("fInitTreeCPUtime", fTimer.CpuTime());
1508  fHistManager.FillTH1("fInitTreeRealtime", fTimer.RealTime());
1509  }
1510 
1511 }
1512 
1521 {
1522  std::unique_ptr<TFile> fxsec(TFile::Open(pythiaFileName.c_str()));
1523 
1524  if (fxsec)
1525  {
1526  int trials = 0;
1527  double crossSection = 0;
1528  double nEvents = 0;
1529  // Check if it's a tree
1530  TTree *xtree = dynamic_cast<TTree*>(fxsec->Get("Xsection"));
1531  if (xtree) {
1532  UInt_t ntrials = 0;
1533  Double_t xsection = 0;
1534  xtree->SetBranchAddress("xsection",&xsection);
1535  xtree->SetBranchAddress("ntrials",&ntrials);
1536  xtree->GetEntry(0);
1537  trials = ntrials;
1538  crossSection = xsection;
1539  // TODO: Test this on a file which has pyxsec.root!
1540  nEvents = 1.;
1541  AliFatal("Have no tested pyxsec.root files. Need to determine the proper way to get nevents!!");
1542  }
1543  else {
1544  // Check if it's instead the histograms
1545  // find the Tlist we want to be independent of the name so use the Tkey
1546  TKey* key = static_cast<TKey*>(fxsec->GetListOfKeys()->At(0));
1547  if (!key) return false;
1548  TList *list = dynamic_cast<TList*>(key->ReadObj());
1549  if (!list) return false;
1550  TProfile * crossSectionHist = static_cast<TProfile*>(list->FindObject("h1Xsec"));
1551  // check for failure
1552  if(!(crossSectionHist->GetEntries())) {
1553  // No cross section information available - fall back to raw
1554  AliErrorStream() << "No cross section information available in file \"" << fxsec->GetName() << "\". Will still attempt to extract cross section information from pythia header.\n";
1555  } else {
1556  // Cross section histogram filled - take it from there
1557  crossSection = crossSectionHist->GetBinContent(1);
1558  if(!crossSection) AliErrorStream() << GetName() << ": Cross section 0 for file " << pythiaFileName << std::endl;
1559  }
1560  TH1F * trialsHist = static_cast<TH1F*>(list->FindObject("h1Trials"));
1561  trials = trialsHist->GetBinContent(1);
1562  nEvents = trialsHist->GetEntries();
1563  }
1564 
1565  // If successful in retrieving the values, normalize the xsec and trials by the number of events
1566  // in the file. This way, we can use it as an approximate event-by-event value
1567  // We do not want to just use the overall value because some of the events may be rejected by various
1568  // event selections, so we only want that ones that were actually use. The easiest way to do so is by
1569  // filling it for each event.
1570  fPythiaTrialsFromFile = trials/nEvents;
1571  // Do __NOT__ divide by nEvents here! The value is already from a TProfile and therefore is already the mean!
1572  fPythiaCrossSectionFromFile = crossSection;
1573 
1574  return true;
1575  }
1576  else {
1577  AliDebugStream(3) << "Unable to open file \"" << pythiaFileName << "\". Will attempt to use values from the header.";
1578  }
1579 
1580  // Could not open file
1581  return false;
1582 }
1583 
1590 {
1591  if (!fInitializedEmbedding) {
1592  AliError("Chain not initialized before running! Setting up now.");
1593  SetupEmbedding();
1594  }
1595 
1596  // Apply internal event selection
1598  fEmbeddedEventUsed = false;
1599  if (fInternalEventCuts.AcceptEvent(AliAnalysisTaskSE::InputEvent()) == true)
1600  {
1601  fEmbeddedEventUsed = true;
1602  fHistManager.FillTH1("fHistInternalEventCutsStats", "passedEventCuts", 1);
1603 
1604  // Validate the event selection. We will only do this once, but we must wait
1605  // until `AcceptEvent(...)` is called once in case automatic setup is used.
1606  if (fValidatedPhysicsSelection == false) {
1607  // Validate that the trigger selection in the other tasks is a subset of the internal event selection
1608  AliDebugStream(1) << "Validating physics selection.\n";
1611  AliDebugStream(1) << "Successfully validated the physics selection!\n";
1612  }
1613 
1614  // The event was accepted by AliEventCuts. Now check for additional cuts.
1615  // Centrality
1616  // NOTE: If the centrality range is the same as AliEventCuts, then simply all will pass
1617  // If a wider centrality range than in AliEventCuts is needed then it must be _entirely_
1618  // configured through manual mode.
1619  if (fCentMin != -999 && fCentMax != -999) {
1620  if (fInternalEventCuts.GetCentrality() < fCentMin || fInternalEventCuts.GetCentrality() > fCentMax) {
1621  fEmbeddedEventUsed = false;
1622  }
1623  else {
1624  fHistManager.FillTH1("fHistInternalEventCutsStats", "centrality", 1);
1625  }
1626  }
1627  // Now reject events based on a rejection factor if set, where the fraction of events
1628  // kept is equal to 1 / fRandomRejectionFactor
1629  if(fRandomRejectionFactor > 1.) {
1630  Double_t rand = fRandom.Rndm();
1631  if(fRandomRejectionFactor > 1./rand) {
1632  fEmbeddedEventUsed = false;
1633  }
1634  else {
1635  fHistManager.FillTH1("fHistInternalEventCutsStats", "passedRandomRejection", 1);
1636  }
1637  }
1638  if (fEmbeddedEventUsed) {
1639  // Record all cuts passed
1640  fHistManager.FillTH1("fHistInternalEventCutsStats", "passedAllCuts", 1);
1641  }
1642  }
1643 
1644  // If the internal event was rejected, then record and move on.
1645  if (fEmbeddedEventUsed == false) {
1646  if (fCreateHisto) {
1647  PostData(1, fOutput);
1648  }
1649  return;
1650  }
1651  }
1652 
1653  if (!fInitializedNewFile) {
1654  InitTree();
1655  }
1656 
1657  Bool_t res = GetNextEntry();
1658 
1659  if (!res) {
1660  AliError("Unable to get the event to embed. Nothing will be embedded.");
1661  return;
1662  }
1663 
1664  if (fCreateHisto && fOutput) {
1665  PostData(1, fOutput);
1666  }
1667 }
1668 
1678 {
1679  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1680  if (!mgr) {
1681  AliFatal("No analysis manager to connect to.");
1682  }
1683 
1684  // Check that the internal event physics selection that has been applied is a subset of
1685  // the collision candidates that are selected. Otherwise, it could be quite misleading.
1686  // NOTE: We either set `fTriggerMask` to our internal event selection, or it was set automatically.
1687  // In either case, `fInternalEventCuts.fTriggerMask` should have the correct internal
1688  // event physics selection.
1689  // For information on the comparison method, see: https://stackoverflow.com/a/8639510
1690  UInt_t collisionCandidates = this->GetCollisionCandidates();
1691  bool res = (fInternalEventCuts.fTriggerMask | collisionCandidates) == collisionCandidates;
1692  if (res == false) {
1693  std::stringstream message;
1694  message << "Collision candidates selected for the embedding helper are more restrictive than"
1695  << " the internal event physics selection! You will not have access to all of the events"
1696  << " selected in the internal event physics selection. Please expand your trigger mask set"
1697  << " via SelectCollisionCandidates().\n"
1698  << std::bitset<32>(fInternalEventCuts.fTriggerMask) << " <- Embedding helper internal event physics selection\n"
1699  << std::bitset<32>(collisionCandidates) << " <- Collision candidates\n";
1700  AliFatal(message.str().c_str());
1701  }
1702 
1703  auto tasks = mgr->GetTasks();
1704  for (auto t : *tasks)
1705  {
1706  auto task = dynamic_cast<AliAnalysisTaskSE *>(t);
1707  if (!task || task->GetName() == GetName()) {
1708  // Skip the task if it's not an analysis task or if it's the embedding
1709  // helper, since it's allowed to have a broader physics selection than the
1710  // internal event physics selection.
1711  continue;
1712  }
1713 
1714  // Compare the selected collision candidates to the embedding helper physics selection.
1715  // Every subsequent task must be a subset or equal to the embedding helper physics selection.
1716  // Otherwise, subsequent tasks will be be selected for internal events where we haven't update
1717  // the embedded event. This will lead to double counting, double corrections, etc.
1718  // For information on the comparison method, see: https://stackoverflow.com/a/8639510
1719  UInt_t taskCollisionCandidates = task->GetCollisionCandidates();
1720  res = (taskCollisionCandidates | collisionCandidates) == collisionCandidates;
1721  if (res == false) {
1722  std::stringstream message;
1723  message << "The physics selection of all tasks must be a subset of the physics selection used"
1724  << " in the embedding helper.\n"
1725  << std::bitset<32>(collisionCandidates) << " <- Embedding helper internal event physics selection\n"
1726  << std::bitset<32>(taskCollisionCandidates) << " <- Task \"" << task->GetName() << "\" collision candidates\n";
1727  AliFatal(message.str().c_str());
1728  }
1729  }
1730 }
1731 
1736 {
1737 }
1738 
1744 {
1745  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1746  if (!mgr)
1747  {
1748  AliErrorStream() << "No analysis manager to connect to.\n";
1749  return;
1750  }
1751 
1752  // Remove the dummy task
1753  std::string dummyTaskName = GetName();
1754  dummyTaskName += "_dummyTask";
1755  TObjArray * tasks = mgr->GetTasks();
1756  if (tasks) {
1757  AliAnalysisTaskSE * dummyTask = dynamic_cast<AliAnalysisTaskSE *>(tasks->FindObject(dummyTaskName.c_str()));
1758  if (!dummyTask) {
1759  AliErrorStream() << "Could not remove dummy task \"" << dummyTaskName << "\" from analysis manager! Was it added?\n";
1760  }
1761  // Actually remove the task
1762  tasks->Remove(dummyTask);
1763  AliDebugStream(1) << "Removed dummy task named \"" << dummyTaskName << "\".\n";
1764  }
1765  else {
1766  AliErrorStream() << "Could not retrieve tasks from the analysis manager.\n";
1767  }
1768 }
1769 
1771 {
1773  return &fInternalEventCuts;
1774  }
1775  else {
1776  AliErrorStream() << "Enable manual mode in AliEventCuts (though the embedding helper) to access this object.\n";
1777  }
1778  return nullptr;
1779 }
1780 
1782 {
1783  // Get the pointer to the existing analysis manager via the static access method.
1784  //==============================================================================
1785  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1786  if (!mgr)
1787  {
1788  ::Error("AddTaskEmcalEmbeddingHelper", "No analysis manager to connect to.");
1789  return 0;
1790  }
1791 
1792  // Check the analysis type using the event handlers connected to the analysis manager.
1793  //==============================================================================
1794  AliVEventHandler* handler = mgr->GetInputEventHandler();
1795  if (!handler)
1796  {
1797  ::Error("AddTaskEmcalEmbeddingHelper", "This task requires an input event handler");
1798  return 0;
1799  }
1800 
1801  TString name = "AliAnalysisTaskEmcalEmbeddingHelper";
1802 
1803  AliAnalysisTaskEmcalEmbeddingHelper * mgrTask = static_cast<AliAnalysisTaskEmcalEmbeddingHelper *>(mgr->GetTask(name.Data()));
1804  if (mgrTask) return mgrTask;
1805 
1806  // Create the task that manages
1807  AliAnalysisTaskEmcalEmbeddingHelper * embeddingHelper = new AliAnalysisTaskEmcalEmbeddingHelper(name.Data());
1808 
1809  //-------------------------------------------------------
1810  // Final settings, pass to manager and set the containers
1811  //-------------------------------------------------------
1812 
1813  mgr->AddTask(embeddingHelper);
1814 
1815  // Create containers for input/output
1816  AliAnalysisDataContainer* cInput = mgr->GetCommonInputContainer();
1817 
1818  TString outputContainerName(name);
1819  outputContainerName += "_histos";
1820 
1821  AliAnalysisDataContainer * cOutput = mgr->CreateContainer(outputContainerName.Data(),
1822  TList::Class(),
1823  AliAnalysisManager::kOutputContainer,
1824  Form("%s", AliAnalysisManager::GetCommonFileName()));
1825 
1826  mgr->ConnectInput(embeddingHelper, 0, cInput);
1827  mgr->ConnectOutput(embeddingHelper, 1, cOutput);
1828 
1829  return embeddingHelper;
1830 }
1831 
1833 {
1834  // Get the pointer to the existing analysis manager via the static access method.
1835  //==============================================================================
1836  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1837  if (!mgr)
1838  {
1839  ::Error("ConfigureEmcalEmbeddingHelperOnLEGOTrain", "No analysis manager to connect to.");
1840  return nullptr;
1841  }
1842 
1843  // Retrieve the embedding helper
1844  auto embeddingHelperConst = AliAnalysisTaskEmcalEmbeddingHelper::GetInstance();
1845  // Cast away const-ness on the pointer since the underlying object is not const and we need to be able to modify it.
1846  auto embeddingHelper = const_cast<AliAnalysisTaskEmcalEmbeddingHelper *>(embeddingHelperConst);
1847 
1848  // Fatal if we can't find the task
1849  if (!embeddingHelper) {
1850  AliFatalClass("Could not find embedding helper, Did you remember to create it?");
1851  }
1852 
1853  AliInfoClassStream() << "Found embedding helper to configure.\n";
1854 
1855  // AliAnalysisTaskCfg will require a task to be returned, so we add a dummy task to the analysis manager,
1856  // which will be removed when the user calls Initialize(true) on the embedding helper.
1857  mgr->AddTask(new AliAnalysisTaskSE("AliAnalysisTaskEmcalEmbeddingHelper_dummyTask"));
1858 
1859  return embeddingHelper;
1860 }
1861 
1867 std::string AliAnalysisTaskEmcalEmbeddingHelper::toString(bool includeFileList) const
1868 {
1869  std::stringstream tempSS;
1870 
1871  // General embedding helper information
1872  tempSS << std::boolalpha;
1873  tempSS << GetName() << ": Embedding helper configuration:\n";
1874  tempSS << "Create histos: " << fCreateHisto << "\n";
1875  tempSS << "Pt Hard Bin: " << fPtHardBin << "\n";
1876  tempSS << "N Pt Hard Bins: " << fNPtHardBins << "\n";
1877  tempSS << "File pattern: \"" << fFilePattern << "\"\n";
1878  tempSS << "Input filename: \"" << fInputFilename << "\"\n";
1879  tempSS << "Pythia cross section filename: \"" << fPythiaXSecFilename << "\"\n";
1880  tempSS << "File list filename: \"" << fFileListFilename << "\"\n";
1881  tempSS << "Tree name: " << fTreeName << "\n";
1882  tempSS << "Print timing info to log: " << fPrintTimingInfoToLog << "\n";
1883  tempSS << "Random event number access: " << fRandomEventNumberAccess << "\n";
1884  tempSS << "Random file access: " << fRandomFileAccess << "\n";
1885  tempSS << "Starting file index: " << fFilenameIndex << "\n";
1886  tempSS << "Number of files to embed: " << fFilenames.size() << "\n";
1887  tempSS << "YAML configuration path: \"" << fConfigurationPath << "\"\n";
1888  tempSS << "Enable internal event selection: " << fUseInternalEventSelection << "\n";
1889  tempSS << "Use manual event cuts mode for internal event selection: " << fUseManualInternalEventCuts << "\n";
1890  if (fCentMin != -999 && fCentMax != -999) {
1891  tempSS << "Internal event selection centrality range: [" << fCentMin << ", " << fCentMax << "]\n";
1892  }
1893  else {
1894  tempSS << "Internal event selection centrality range disabled.\n";
1895  }
1896  tempSS << "Internal event physics selection via class (should propagate to AliEventCuts): " << std::bitset<32>(fInternalEventTriggerMask) << "\n";
1897  tempSS << "Internal event physics selection via AliEventCuts: " << std::bitset<32>(fInternalEventCuts.fTriggerMask) << "\n";
1898 
1899  std::bitset<32> triggerMask(fTriggerMask);
1900  tempSS << "\nEmbedded event settings:\n";
1901  tempSS << "Trigger mask (binary): " << triggerMask << "\n";
1902  tempSS << "Reject outliers: " << fMCRejectOutliers << "\n";
1903  tempSS << "Pt hard jet pt rejection factor: " << fPtHardJetPtRejectionFactor << "\n";
1904  tempSS << "Z vertex cut: " << fZVertexCut << "\n";
1905  tempSS << "Max difference between internal and embedded vertex: " << fMaxVertexDist << "\n";
1906  tempSS << "Random event rejection factor: " << fRandomRejectionFactor << "\n";
1907 
1908  if (includeFileList) {
1909  tempSS << "\nFiles to embed:\n";
1910  for (auto filename : fFilenames) {
1911  tempSS << "\t" << filename << "\n";
1912  }
1913  }
1914 
1915  return tempSS.str();
1916 }
1917 
1925 std::ostream & AliAnalysisTaskEmcalEmbeddingHelper::Print(std::ostream & in) const {
1926  in << toString();
1927  return in;
1928 }
1929 
1938 std::ostream & operator<<(std::ostream & in, const AliAnalysisTaskEmcalEmbeddingHelper & myTask)
1939 {
1940  std::ostream & result = myTask.Print(in);
1941  return result;
1942 }
1943 
1951 {
1952  std::string temp(opt);
1953  bool includeFileList = false;
1954  if (temp == "FILELIST") {
1955  includeFileList = true;
1956  }
1957  Printf("%s", toString(includeFileList).c_str());
1958 }
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
bool fMCRejectOutliers
If true, MC outliers will be rejected.
double fPythiaCrossSection
! Pythia cross section for the current event (extracted from the pythia header).
Int_t fLowerEntry
! First entry of the current tree to be used for embedding
TRandom3 fRandom
for random rejection of events
TString fFileListFilename
Name of the file list containing paths to files to embed.
int fPythiaTrialsFromFile
! Average number of trials extracted from a xsec file.
Bool_t fRandomFileAccess
If true, it will start embedding from a random file in the input files list.
TStopwatch fTimer
! Timer for the InitTree() function
TSystem * gSystem
Int_t fCurrentEntry
! Current entry in the current tree
bool WriteConfiguration(const std::string &filename, const unsigned int i) const
TFile * fExternalFile
! External file used for embedding
Int_t fNPtHardBins
Total number of pt hard bins.
TChain * fChain
! External TChain (tree) containing the events available for embedding
Declaration of class AliAnalysisTaskEmcalEmbeddingHelper.
bool fAutoConfigurePtHardBins
If true, attempt to auto configure pt hard bins. Only works on the LEGO train.
bool fInitializedConfiguration
Notes if the configuration has been initialized.
bool GetProperty(std::vector< std::string > propertyPath, const std::string &propertyName, T &property, const bool requiredProperty) const
bool IsRunInRunlist(const std::string &path) const
AliVHeader * fExternalHeader
! Header of the current external event
AliGenPythiaEventHeader * fPythiaHeader
! Pythia header of the current external event
const AliEventCuts * GetInternalEventCuts() const
Event cuts object for accessing centrality, etc from another task if so inclined. ...
TString fInputFilename
Filename of input root files.
friend std::ostream & operator<<(std::ostream &in, const AliAnalysisTaskEmcalEmbeddingHelper &myTask)
std::vector< std::string > fEmbeddedRunlist
Good runlist for files to embed.
std::string fAutoConfigureBasePath
The base path to the auto configuration (for example, "/alice/cern.ch/user/a/alitrain/") ...
std::string fConfigurationPath
Path to YAML configuration.
static UInt_t DeterminePhysicsSelectionFromYAML(const std::vector< std::string > &selections)
int Int_t
Definition: External.C:63
void CreateTProfile(const char *name, const char *title, int nbinsX, double xmin, double xmax, Option_t *opt="")
Create a new TProfile within the container.
std::string fPythiaXSecFilename
Name of the pythia x sec filename (either "pyxsec.root" or "pyxsec_hists.root")
unsigned int UInt_t
Definition: External.C:33
THashList * GetListOfHistograms() const
Get the list of histograms.
Definition: THistManager.h:671
float Float_t
Definition: External.C:68
bool fInitializedEmbedding
! Notes where the TChain has been initialized for embedding
bool fUseInternalEventSelection
If true, apply internal event selection though AliEventCuts.
std::string toString(bool includeFileList=false) const
Implementation of task to embed external events.
UInt_t fMaxNumberOfFiles
! Max number of files that are in the TChain
TH1 * CreateTH1(const char *name, const char *title, int nbins, double xmin, double xmax, Option_t *opt="")
Create a new TH1 within the container.
void FillProfile(const char *name, double x, double y, double weight=1.)
Double_t nEvents
plot quality messages
Double_t fMaxVertexDist
Max distance between Z vertex of internal and embedded event.
AliVEvent * fExternalEvent
! Current external event available for embedding
std::vector< std::string > fPythiaCrossSectionFilenames
Paths to the pythia xsection files.
bool fValidatedPhysicsSelection
Validate that the physics selection is set appropriately.
bool fPrintTimingInfoToLog
Flag to print time to execute InitTree(), for logging purposes.
void FillTH1(const char *hname, double x, double weight=1., Option_t *opt="")
Fill a 1D histogram within the container.
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 fCreateHisto
If true, create QA histograms.
bool fEmbeddedEventUsed
! If true, the internal event was selected, so the embedded event is used. Defaults to true so other ...
Enhanced TList-derived class that implements correct merging for pt_hard binned production.
Definition: AliEmcalList.h:25
bool fWrappedAroundTree
! Notes whether we have wrapped around the tree, which is important if the offset into the tree is no...
Double_t fPtHardJetPtRejectionFactor
Factor which the pt hard bin is multiplied by to compare against pythia header jets pt...
PWG::Tools::AliYAMLConfiguration fYAMLConfig
Hanldes configuration from YAML.
int AddEmptyConfiguration(const std::string &configurationName)
Add YAML configuration at configurationFilename to available configurations.
double fPythiaPtHard
! Pt hard of the current event (extracted from the pythia header).
static AliAnalysisTaskEmcalEmbeddingHelper * AddTaskEmcalEmbeddingHelper()
THistManager fHistManager
Manages access to all histograms.
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
UInt_t fFileNumber
! File number corresponding to the current tree
bool fUseManualInternalEventCuts
If true, manual event cuts mode will be used for AliEventCuts.
bool IsFileAccessible(std::string filename)
YAML configuration class for AliPhysics.
bool WriteProperty(std::string propertyName, T &property, std::string configurationName="")
std::string RemoveTrailingSlashes(std::string filename) const
int AddConfiguration(std::string configurationFilename, std::string configurationName="")
double fCentMax
Maximum centrality for internal event selection.
const char Option_t
Definition: External.C:48
AliEmcalList * fOutput
! List which owns the output histograms to be saved
AliEventCuts fInternalEventCuts
If enabled, Handles internal event selection.
UInt_t fInternalEventTriggerMask
Internal event physics selection (trigger mask) to be used with AliEventCuts.
bool Bool_t
Definition: External.C:53
std::string fAutoConfigureIdentifier
How the auto configuration YAML file should be identified. (for example, "rehlersTrain") ...
Double_t fRandomRejectionFactor
factor by which to reject events
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.
double fPythiaCrossSectionFromFile
! Average pythia cross section extracted from a xsec file.
std::vector< std::string > fFilenames
Paths to the files to embed.
static AliAnalysisTaskEmcalEmbeddingHelper * ConfigureEmcalEmbeddingHelperOnLEGOTrain()
std::string fAutoConfigureTrainTypePath
The path associated with the train type (for example, "PWGJE/Jets_EMC_PbPb/")
TString fFilePattern
File pattern to select AliEn files using alien_find.
int fPythiaTrials
! Number of pythia trials for the current event (extracted from the pythia header).
double fCentMin
Minimum centrality for internal event selection.
TList * OpenFile(const char *fname)
Definition: DrawAnaELoss.C:65
static const AliAnalysisTaskEmcalEmbeddingHelper * GetInstance()
std::string ConstructFullPythiaXSecFilename(std::string inputFilename, const std::string &pythiaFilename, bool testIfExists) const