diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..59eceb91 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,9 @@ +# Code owners +# +# Lines starting with '#' are comments. +# Each line is a file pattern followed by one or more owners. + +# These owners will be the default owners for everything in the repo. +* @ginnocen @vkucera + +# Order is important. The last matching pattern has the most precedence. diff --git a/FirstAnalysis/README.md b/FirstAnalysis/README.md index be0f0f48..a426ca78 100644 --- a/FirstAnalysis/README.md +++ b/FirstAnalysis/README.md @@ -1,19 +1,29 @@ -# O2 First analysis utilities - -## Table of contents - -* [Introduction](#introduction) -* [Available samples ALICE3](#available-samples-alice3) - +# O2 first analysis utilities ## Introduction The main purpose of this folder is to provide analysis tools to perform analysis of O2 analysis task outputs. It includes for the moment a set of QA plotting macros to inspect `AnalysisResults.root` of MC and data samples. -It also includes some preliminary functionalities for performing efficiency corrections of HF analyses. It is currently being used -also for performing Run5 analysis. +It also includes some preliminary functionalities for performing efficiency corrections of HF analyses. +It is currently being used also for performing Run5 analysis. +## Instructions for contributors + +* Write documentation comments to make the code easy to understand. +* Every file should contain the following details at the top: + * what the code does, + * which input it needs (e.g. output of which O2 workflow), + * how to run it (in case simply executing the script is not enough), + * names of authors, contributors, maintainers (to contact in case of problems or questions). +* Follow [PEP 8 naming conventions](https://www.python.org/dev/peps/pep-0008/#naming-conventions) in Python code. +* Do not use hard-coded paths! A default path should point to a file directly produced by the framework (e.g. `../codeHF/AnalysisResults_O2.root`). ## Available samples ALICE3 * D2H KrKr production (X events): * AOD O2 tables: `/data/Run5data/EMBEDDING_KrKr_CCBARLc_scenario3/TEST` * Analysis result: `/data/Run5data_samples/EMBEDDING_KrKr_CCBARLc_scenario3_20210224/AnalysisResults_O2.root` + +## Plotting +The analyses validation is supposed to use the [HFPlot tool](https://github.com/benedikt-voelkel/HFPlot) for plotting purposes in the future. +It is basically a *pythonic* wrapper around `ROOT` with some automated features. +As a first use case it is implemented in [distrib_studies.py](distrib_studies.py). +A more extensive README can be found [here](https://github.com/benedikt-voelkel/HFPlot) and there are also some examples provided. diff --git a/FirstAnalysis/distrib_studies.py b/FirstAnalysis/distrib_studies.py index 1b83fdbc..9c2b0249 100644 --- a/FirstAnalysis/distrib_studies.py +++ b/FirstAnalysis/distrib_studies.py @@ -4,7 +4,7 @@ import yaml from hfplot.plot_spec_root import ROOTFigure -from hfplot.style import ROOTStyle1D +from hfplot.style import StyleObject1D from ROOT import TFile @@ -47,12 +47,12 @@ def distr_studies(hadron="X3872", collision="pp14p0", yrange="absy1p44"): lptMax = [] # Define some styles - style_sig = ROOTStyle1D() + style_sig = StyleObject1D() style_sig.markercolor = 2 style_sig.markerstyle = 21 style_sig.markersize = 2 style_sig.draw_options = "P" - style_bkg = ROOTStyle1D() + style_bkg = StyleObject1D() style_bkg.markerstyle = 23 style_bkg.markersize = 2 style_bkg.draw_options = "P" diff --git a/README.md b/README.md index 3a0f8ac8..4b921f23 100644 --- a/README.md +++ b/README.md @@ -3,24 +3,6 @@ [![GitHub Mega-Linter](https://github.com/AliceO2Group/Run3Analysisvalidation/workflows/Mega-Linter/badge.svg?branch=master)](https://github.com/marketplace/actions/mega-linter) [![GitHub Clang Format Linter](https://github.com/AliceO2Group/Run3Analysisvalidation/workflows/Clang%20Format%20Linter/badge.svg)](https://github.com/marketplace/actions/clang-format-lint) -## Table of contents - -* [Introduction](#introduction) -* [Overview](#overview) - * [Execution](#execution) - * [Configuration](#configuration) -* [Preparation](#preparation) - * [Build AliPhysics and O2](#build-aliphysics-and-o2) - * [Download the validation framework](#download-the-validation-framework) - * [Install parallelisation software](#install-parallelisation-software) -* [Run the framework](#run-the-framework) -* [Job debugging](#job-debugging) -* [Heavy-flavour analyses](#heavy-flavour-analyses) -* [Keep your repositories and installations up to date and clean](#keep-your-repositories-and-installations-up-to-date-and-clean) -* [Continuous integration tests](#continuous-integration-tests) - * [C++](#c) - * [Python](#python) - ## Introduction The main purpose of the Run 3 validation framework is to provide a compact and flexible tool for validation of the @@ -251,25 +233,25 @@ You can easily extend the script to include any other local Git repository and a ## Continuous integration tests Validity and quality of the code in the repository are checked on GitHub by several tools (linters) that support many coding languages. -Linters run automatically for every push or pull request. +Linters run automatically for every push or pull request event. **Please make sure that your code passes all the tests before making a pull request.** -Here are some tips how to check your code locally with the linters that usually complain the most. +It is possible to check your code locally (before even committing or pushing): -### C++ +### Space checker -* [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) - automatic reformatting of C++ sources files according to configurable style guides +```bash +bash /exec/check_spaces.sh +``` + +### [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) ```bash clang-format -style=file -i ``` -### Python - -* [Black](https://github.com/psf/black) - “uncompromising Python code formatter” -* [flake8](https://gitlab.com/pycqa/flake8) - “tool that glues together pep8, pyflakes, mccabe, and third-party plugins to check the style and quality of some python code” -* [isort](https://github.com/PyCQA/isort) - “utility to sort imports alphabetically, and automatically separated into sections and by type” +### [Mega-Linter](https://nvuillam.github.io/mega-linter/mega-linter-runner/) ```bash -black . && flake8 . && isort . +mega-linter-runner ``` diff --git a/codeHF/Compare.C b/codeHF/Compare.C index 444ffc0a..ee085338 100644 --- a/codeHF/Compare.C +++ b/codeHF/Compare.C @@ -37,15 +37,17 @@ Int_t Compare(TString filerun3 = "AnalysisResults_O2.root", TString filerun1 = " return 1; } + TString labelParticle = ""; + // Histogram specification: axis label, Run 1 name, Run 3 path/name, rebin, log scale histogram, log scale ratio VecSpecHis vecHisTracks; - AddHistogram(vecHisTracks, "#it{p}_{T} before selections (GeV/#it{c})", "hPtAllTracks", "hf-produce-sel-track/hpt_nocuts", 2, 1, 0); - AddHistogram(vecHisTracks, "#it{p}_{T} after selections (GeV/#it{c})", "hPtSelTracks", "hf-produce-sel-track/hpt_cuts_2prong", 2, 1, 0); - AddHistogram(vecHisTracks, "DCA XY to prim. vtx. (2-prong sel.) (cm)", "hImpParSelTracks2prong", "hf-produce-sel-track/hdcatoprimxy_cuts_2prong", 2, 1, 0); - AddHistogram(vecHisTracks, "DCA XY to prim. vtx. (3-prong sel.) (cm)", "hImpParSelTracks3prong", "hf-produce-sel-track/hdcatoprimxy_cuts_3prong", 2, 1, 0); - AddHistogram(vecHisTracks, "#it{#eta} (2-prong sel.)", "hEtaSelTracks2prong", "hf-produce-sel-track/heta_cuts_2prong", 2, 0, 0); - AddHistogram(vecHisTracks, "#it{#eta} (3-prong sel.)", "hEtaSelTracks3prong", "hf-produce-sel-track/heta_cuts_3prong", 2, 0, 0); + AddHistogram(vecHisTracks, "#it{p}_{T} before selections (GeV/#it{c})", "hPtAllTracks", "hf-tag-sel-tracks/hpt_nocuts", 2, 1, 0); + AddHistogram(vecHisTracks, "#it{p}_{T} after selections (GeV/#it{c})", "hPtSelTracks", "hf-tag-sel-tracks/hpt_cuts_2prong", 2, 1, 0); + AddHistogram(vecHisTracks, "DCA XY to prim. vtx. (2-prong sel.) (cm)", "hImpParSelTracks2prong", "hf-tag-sel-tracks/hdcatoprimxy_cuts_2prong", 2, 1, 0); + AddHistogram(vecHisTracks, "DCA XY to prim. vtx. (3-prong sel.) (cm)", "hImpParSelTracks3prong", "hf-tag-sel-tracks/hdcatoprimxy_cuts_3prong", 2, 1, 0); + AddHistogram(vecHisTracks, "#it{#eta} (2-prong sel.)", "hEtaSelTracks2prong", "hf-tag-sel-tracks/heta_cuts_2prong", 2, 0, 0); + AddHistogram(vecHisTracks, "#it{#eta} (3-prong sel.)", "hEtaSelTracks3prong", "hf-tag-sel-tracks/heta_cuts_3prong", 2, 0, 0); VecSpecHis vecHisSkim; AddHistogram(vecHisSkim, "secondary vtx x - 2prong (cm)", "h2ProngVertX", "hf-track-index-skims-creator/hvtx2_x", 5, 1, 0); @@ -76,7 +78,14 @@ Int_t Compare(TString filerun3 = "AnalysisResults_O2.root", TString filerun1 = " AddHistogram(vecHisD0, "decay length XY (cm)", "hDecLenXYD0", "hf-task-d0/hdeclengthxy", 2, 1, 0); AddHistogram(vecHisD0, "decay length error (cm)", "hDecLenErrD0", "hf-task-d0/hDecLenErr", 1, 1, 0); AddHistogram(vecHisD0, "decay length XY error (cm)", "hDecLenXYErrD0", "hf-task-d0/hDecLenXYErr", 1, 1, 0); - AddHistogram(vecHisD0, "cos. pointing angle", "hCosPointD0", "hf-task-d0/hCPA", 2, 1, 0); + AddHistogram(vecHisD0, "cos pointing angle", "hCosPointD0", "hf-task-d0/hCPA", 2, 1, 0); + + labelParticle = "D^{0} #rightarrow #pi K"; + VecSpecHis vecHisD0MC; + AddHistogram(vecHisD0MC, labelParticle + ", matched prompt: #it{p}_{T}^{rec} (GeV/#it{c})", "hPtRecoPromptD0Kpi", "hf-task-d0-mc/hPtRecSigPrompt", 2, 1, 0); + AddHistogram(vecHisD0MC, labelParticle + ", gen. prompt: #it{p}_{T}^{gen} (GeV/#it{c})", "hPtGenPromptD0Kpi", "hf-task-d0-mc/hPtGenPrompt", 2, 1, 0); + AddHistogram(vecHisD0MC, labelParticle + ", matched non-prompt: #it{p}_{T}^{rec} (GeV/#it{c})", "hPtRecoFeeddwD0Kpi", "hf-task-d0-mc/hPtRecSigNonPrompt", 2, 1, 0); + AddHistogram(vecHisD0MC, labelParticle + ", gen. non-prompt: #it{p}_{T}^{gen} (GeV/#it{c})", "hPtGenFeeddwD0Kpi", "hf-task-d0-mc/hPtGenNonPrompt", 2, 1, 0); VecSpecHis vecHisDPlus; AddHistogram(vecHisDPlus, "#it{p}_{T} prong 0 (GeV/#it{c})", "hPtDplusDau0", "hf-task-dplus/hPtProng0", 2, 1, 0); @@ -88,13 +97,14 @@ Int_t Compare(TString filerun3 = "AnalysisResults_O2.root", TString filerun1 = " AddHistogram(vecHisDPlus, "decay length (cm)", "hDecLenDplus", "hf-task-dplus/hDecayLength", 4, 1, 0); AddHistogram(vecHisDPlus, "decay length XY (cm)", "hDecLenXYDplus", "hf-task-dplus/hDecayLengthXY", 4, 1, 0); AddHistogram(vecHisDPlus, "norm. decay length XY", "hNormDecLenXYDplus", "hf-task-dplus/hNormalisedDecayLengthXY", 2, 1, 0); - AddHistogram(vecHisDPlus, "cos. pointing angle", "hCosPointDplus", "hf-task-dplus/hCPA", 2, 1, 0); - AddHistogram(vecHisDPlus, "cos. pointing angle XY", "hCosPointXYDplus", "hf-task-dplus/hCPAxy", 2, 1, 0); + AddHistogram(vecHisDPlus, "cos pointing angle", "hCosPointDplus", "hf-task-dplus/hCPA", 2, 1, 0); + AddHistogram(vecHisDPlus, "cos pointing angle XY", "hCosPointXYDplus", "hf-task-dplus/hCPAxy", 2, 1, 0); AddHistogram(vecHisDPlus, "norm. IP", "hNormIPDplus", "hf-task-dplus/hMaxNormalisedDeltaIP", 4, 1, 0); AddHistogram(vecHisDPlus, "decay length error (cm)", "hDecLenErrDplus", "hf-task-dplus/hDecayLengthError", 2, 1, 0); AddHistogram(vecHisDPlus, "decay length XY error (cm)", "hDecLenXYErrDplus", "hf-task-dplus/hDecayLengthXYError", 2, 1, 0); AddHistogram(vecHisDPlus, "prong 0 impact parameter (cm)", "hImpParDplusDau0", "hf-task-dplus/hd0Prong0", 2, 1, 0); AddHistogram(vecHisDPlus, "prong 1 impact parameter (cm)", "hImpParDplusDau1", "hf-task-dplus/hd0Prong1", 2, 1, 0); + AddHistogram(vecHisDPlus, "prong 2 impact parameter (cm)", "hImpParDplusDau2", "hf-task-dplus/hd0Prong2", 2, 1, 0); AddHistogram(vecHisDPlus, "prong impact parameter error (cm)", "hImpParErrDplusDau", "hf-task-dplus/hImpactParameterError", 2, 1, 0); AddHistogram(vecHisDPlus, "sq. sum of prong imp. par. (cm^{2})", "hSumSqImpParDplusDau", "hf-task-dplus/hImpactParameterProngSqSum", 2, 1, 0); @@ -105,7 +115,14 @@ Int_t Compare(TString filerun3 = "AnalysisResults_O2.root", TString filerun1 = " AddHistogram(vecHisLc, "#it{p}_{T} #Lambda_{c}^{#plus} (GeV/#it{c})", "hPtLc", "hf-task-lc/hptcand", 2, 1, 0); AddHistogram(vecHisLc, "3-prong mass (p K #pi) (GeV/#it{c}^{2})", "hInvMassLc", "hf-task-lc/hmass", 2, 0, 0); AddHistogram(vecHisLc, "decay length (cm)", "hDecLenLc", "hf-task-lc/hdeclength", 2, 1, 0); - AddHistogram(vecHisLc, "cos. pointing angle", "hCosPointLc", "hf-task-lc/hCPA", 2, 1, 0); + AddHistogram(vecHisLc, "cos pointing angle", "hCosPointLc", "hf-task-lc/hCPA", 2, 1, 0); + + labelParticle = "#Lambda_{c}^{#plus} #rightarrow p K #pi"; + VecSpecHis vecHisLcMC; + AddHistogram(vecHisLcMC, labelParticle + ", matched prompt: #it{p}_{T}^{rec} (GeV/#it{c})", "hPtRecoPromptLcpKpi", "hf-task-lc-mc/hPtRecSigPrompt", 2, 1, 0); + AddHistogram(vecHisLcMC, labelParticle + ", gen. prompt: #it{p}_{T}^{gen} (GeV/#it{c})", "hPtGenPromptLcpKpi", "hf-task-lc-mc/hPtGenPrompt", 2, 1, 0); + AddHistogram(vecHisLcMC, labelParticle + ", matched non-prompt: #it{p}_{T}^{rec} (GeV/#it{c})", "hPtRecoFeeddwLcpKpi", "hf-task-lc-mc/hPtRecSigNonPrompt", 2, 1, 0); + AddHistogram(vecHisLcMC, labelParticle + ", gen. non-prompt: #it{p}_{T}^{gen} (GeV/#it{c})", "hPtGenFeeddwLcpKpi", "hf-task-lc-mc/hPtGenNonPrompt", 2, 1, 0); VecSpecHis vecHisJpsi; AddHistogram(vecHisJpsi, "#it{p}_{T} prong 0 (GeV/#it{c})", "hPtJpsiDau0", "hf-task-jpsi/hptprong0", 2, 1, 0); @@ -117,7 +134,7 @@ Int_t Compare(TString filerun3 = "AnalysisResults_O2.root", TString filerun1 = " AddHistogram(vecHisJpsi, "d0 prong 1 (cm)", "hImpParJpsiDau1", "hf-task-jpsi/hd0Prong1", 2, 1, 0); AddHistogram(vecHisJpsi, "decay length (cm)", "hDecLenJpsi", "hf-task-jpsi/hdeclength", 2, 1, 0); AddHistogram(vecHisJpsi, "decay length XY (cm)", "hDecLenXYJpsi", "hf-task-jpsi/hdeclengthxy", 2, 1, 0); - AddHistogram(vecHisJpsi, "cos. pointing angle", "hCosPointJpsi", "hf-task-jpsi/hCPA", 2, 1, 0); + AddHistogram(vecHisJpsi, "cos pointing angle", "hCosPointJpsi", "hf-task-jpsi/hCPA", 2, 1, 0); AddHistogram(vecHisJpsi, "decay length error (cm)", "hDecLenErrJpsi", "hf-task-jpsi/hDecLenErr", 1, 1, 0); AddHistogram(vecHisJpsi, "decay length XY error (cm)", "hDecLenXYErrJpsi", "hf-task-jpsi/hDecLenXYErr", 1, 1, 0); @@ -125,21 +142,25 @@ Int_t Compare(TString filerun3 = "AnalysisResults_O2.root", TString filerun1 = " std::vector> vecSpecVecSpec; // Add vector specifications in the vector. - if (options.Contains("tracks")) + if (options.Contains(" tracks ")) vecSpecVecSpec.push_back(std::make_tuple("tracks", vecHisTracks, 5, 3)); - if (options.Contains("skim")) + if (options.Contains(" skim ")) vecSpecVecSpec.push_back(std::make_tuple("skim", vecHisSkim, 5, 3)); - if (options.Contains("cand2")) + if (options.Contains(" cand2 ")) vecSpecVecSpec.push_back(std::make_tuple("cand2", vecHisCand2, 5, 3)); - if (options.Contains("cand3")) + if (options.Contains(" cand3 ")) vecSpecVecSpec.push_back(std::make_tuple("cand3", vecHisCand3, 5, 3)); - if (options.Contains("d0")) + if (options.Contains(" d0 ")) vecSpecVecSpec.push_back(std::make_tuple("d0", vecHisD0, 5, 3)); - if (options.Contains("dplus")) - vecSpecVecSpec.push_back(std::make_tuple("dplus", vecHisDPlus, 6, 3)); - if (options.Contains("lc")) + if (options.Contains(" d0-mc ")) + vecSpecVecSpec.push_back(std::make_tuple("d0-mc", vecHisD0MC, 2, 2)); + if (options.Contains(" dplus ")) + vecSpecVecSpec.push_back(std::make_tuple("dplus", vecHisDPlus, 5, 4)); + if (options.Contains(" lc ")) vecSpecVecSpec.push_back(std::make_tuple("lc", vecHisLc, 5, 3)); - if (options.Contains("jpsi")) + if (options.Contains(" lc-mc ")) + vecSpecVecSpec.push_back(std::make_tuple("lc-mc", vecHisLcMC, 2, 2)); + if (options.Contains(" jpsi ")) vecSpecVecSpec.push_back(std::make_tuple("jpsi", vecHisJpsi, 5, 3)); // Histogram plot vertical margins diff --git a/codeHF/MC_d0_eff_ref.pdf b/codeHF/MC_d0_eff_ref.pdf index cab9a9cc..7816765a 100644 Binary files a/codeHF/MC_d0_eff_ref.pdf and b/codeHF/MC_d0_eff_ref.pdf differ diff --git a/codeHF/MC_d0_pT_ref.pdf b/codeHF/MC_d0_pT_ref.pdf index 02c9e3c8..050f4909 100644 Binary files a/codeHF/MC_d0_pT_ref.pdf and b/codeHF/MC_d0_pT_ref.pdf differ diff --git a/codeHF/PlotEfficiency.C b/codeHF/PlotEfficiency.C index 39677eea..876db6a9 100644 --- a/codeHF/PlotEfficiency.C +++ b/codeHF/PlotEfficiency.C @@ -10,17 +10,22 @@ Int_t PlotEfficiency(TString pathFile = "AnalysisResults.root", TString particle gStyle->SetFrameFillColor(0); // vertical margins of the pT spectra plot - Float_t marginHigh = 0.05; - Float_t marginLow = 0.05; + float marginHigh = 0.05; + float marginLow = 0.05; bool logScaleH = true; // vertical margins of the efficiency plot - Float_t marginRHigh = 0.05; - Float_t marginRLow = 0.05; + float marginRHigh = 0.05; + float marginRLow = 0.05; bool logScaleR = false; - Float_t yMin, yMax; - Int_t nRec, nGen; + double yMin, yMax; + int nRec, nGen; + int colours[] = {1, 2, 4}; + int markers[] = {24, 25, 46}; + // binning Int_t iNRebin = 4; + //Double_t* dRebin = nullptr; + //const Int_t NRebin = 1; Double_t dRebin[] = {0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 8, 10}; const Int_t NRebin = sizeof(dRebin) / sizeof(dRebin[0]) - 1; @@ -30,8 +35,9 @@ Int_t PlotEfficiency(TString pathFile = "AnalysisResults.root", TString particle return 1; } + // get list of particles TObjArray* arrayParticle = 0; - arrayParticle = particles.Tokenize("-"); + arrayParticle = particles.Tokenize(" "); TString particle = ""; // loop over particles @@ -43,59 +49,166 @@ Int_t PlotEfficiency(TString pathFile = "AnalysisResults.root", TString particle } Printf("\nPlotting efficiency for: %s", particle.Data()); - TString histonameRec = Form("hf-task-%s-mc/hPtGenSig", particle.Data()); // Use hPtRecSig for reconstruction level pT. - TH1F* hPtRec = (TH1F*)file->Get(histonameRec.Data()); - if (!hPtRec) { - Printf("Error: Failed to load %s from %s", histonameRec.Data(), pathFile.Data()); + TString outputDir = Form("hf-task-%s-mc", particle.Data()); // analysis output directory with histograms + + // inclusive candidates + TString nameHistRec = outputDir + "/hPtRecSig"; // reconstruction level pT of matched candidates + //nameHistRec = outputDir + "/hPtGenSig"; // generator level pT of matched candidates (no pT smearing) + TString nameHistgen = outputDir + "/hPtGen"; // generator level pT of generated particles + TH1F* hPtRecIncl = (TH1F*)file->Get(nameHistRec.Data()); + if (!hPtRecIncl) { + Printf("Error: Failed to load %s from %s", nameHistRec.Data(), pathFile.Data()); return 1; } - - TString histonameGen = Form("hf-task-%s-mc/hPtGen", particle.Data()); - TH1F* hPtGen = (TH1F*)file->Get(histonameGen.Data()); - if (!hPtGen) { - Printf("Error: Failed to load %s from %s", histonameGen.Data(), pathFile.Data()); + TH1F* hPtGenIncl = (TH1F*)file->Get(nameHistgen.Data()); + if (!hPtGenIncl) { + Printf("Error: Failed to load %s from %s", nameHistgen.Data(), pathFile.Data()); return 1; } + // prompt candidates + bool okPrompt = true; + nameHistRec = outputDir + "/hPtRecSigPrompt"; + TH1F* hPtRecPrompt = (TH1F*)file->Get(nameHistRec.Data()); + if (!hPtRecPrompt) { + Printf("Warning: Failed to load %s from %s", nameHistRec.Data(), pathFile.Data()); + okPrompt = false; + } + nameHistgen = outputDir + "/hPtGenPrompt"; + TH1F* hPtGenPrompt = (TH1F*)file->Get(nameHistgen.Data()); + if (!hPtGenPrompt) { + Printf("Warning: Failed to load %s from %s", nameHistgen.Data(), pathFile.Data()); + okPrompt = false; + } + + // non-prompt candidates + bool okNonPrompt = true; + nameHistRec = outputDir + "/hPtRecSigNonPrompt"; + TH1F* hPtRecNonPrompt = (TH1F*)file->Get(nameHistRec.Data()); + if (!hPtRecNonPrompt) { + Printf("Warning: Failed to load %s from %s", nameHistRec.Data(), pathFile.Data()); + okNonPrompt = false; + } + nameHistgen = outputDir + "/hPtGenNonPrompt"; + TH1F* hPtGenNonPrompt = (TH1F*)file->Get(nameHistgen.Data()); + if (!hPtGenNonPrompt) { + Printf("Warning: Failed to load %s from %s", nameHistgen.Data(), pathFile.Data()); + okNonPrompt = false; + } + TCanvas* canPt = new TCanvas(Form("canPt_%s", particle.Data()), "Pt", 1200, 1000); + TLegend* legendPt = new TLegend(0.72, 0.72, 0.92, 0.92); TCanvas* canEff = new TCanvas(Form("canEff_%s", particle.Data()), "Eff", 1200, 1000); + TLegend* legendEff = new TLegend(0.1, 0.72, 0.3, 0.92); - nGen = hPtGen->GetEntries(); - nRec = hPtRec->GetEntries(); + nGen = hPtGenIncl->GetEntries(); + nRec = hPtRecIncl->GetEntries(); // pT spectra - auto padH = canPt->cd(); - hPtGen->Rebin(iNRebin); - hPtRec->Rebin(iNRebin); - //hPtRec = (TH1F*)hPtRec->Rebin(NRebin, "hPtRecR", dRebin); - //hPtGen = (TH1F*)hPtGen->Rebin(NRebin, "hPtGenR", dRebin); - hPtGen->SetLineColor(1); - hPtGen->SetLineWidth(2); - hPtRec->SetLineColor(2); - hPtRec->SetLineWidth(1); - hPtGen->SetTitle(Form("Entries: Rec: %d, Gen: %d;#it{p}_{T} (GeV/#it{c});entries", nRec, nGen)); - hPtGen->GetYaxis()->SetMaxDigits(3); - yMin = TMath::Min(hPtRec->GetMinimum(0), hPtGen->GetMinimum(0)); - yMax = TMath::Max(hPtRec->GetMaximum(), hPtGen->GetMaximum()); - SetHistogram(hPtGen, yMin, yMax, marginLow, marginHigh, logScaleH); - SetPad(padH, logScaleH); - hPtGen->Draw(); - hPtRec->Draw("same"); - TLegend* legend = new TLegend(0.72, 0.72, 0.92, 0.92); - legend->AddEntry(hPtRec, "Rec", "L"); - legend->AddEntry(hPtGen, "Gen", "L"); - legend->Draw(); + auto padPt = canPt->cd(); + // inclusive + if (iNRebin > 1) { + hPtGenIncl->Rebin(iNRebin); + hPtRecIncl->Rebin(iNRebin); + } else if (NRebin > 1) { + hPtGenIncl = (TH1F*)hPtGenIncl->Rebin(NRebin, "hPtGenInclR", dRebin); + hPtRecIncl = (TH1F*)hPtRecIncl->Rebin(NRebin, "hPtRecInclR", dRebin); + } + yMin = std::min(hPtRecIncl->GetMinimum(0), hPtGenIncl->GetMinimum(0)); + yMax = std::max(hPtRecIncl->GetMaximum(), hPtGenIncl->GetMaximum()); + SetHistogramStyle(hPtGenIncl, colours[0], markers[0], 1.5, 2); + SetHistogramStyle(hPtRecIncl, colours[0], markers[0], 1.5, 2); + hPtGenIncl->SetTitle(Form("Entries: Rec: %d, Gen: %d;#it{p}_{T} (GeV/#it{c});entries", nRec, nGen)); + hPtGenIncl->GetYaxis()->SetMaxDigits(3); + // prompt + if (okPrompt) { + if (iNRebin > 1) { + hPtGenPrompt->Rebin(iNRebin); + hPtRecPrompt->Rebin(iNRebin); + } else if (NRebin > 1) { + hPtGenPrompt = (TH1F*)hPtGenPrompt->Rebin(NRebin, "hPtGenPromptR", dRebin); + hPtRecPrompt = (TH1F*)hPtRecPrompt->Rebin(NRebin, "hPtRecPromptR", dRebin); + } + yMin = std::min({yMin, hPtRecPrompt->GetMinimum(0), hPtGenPrompt->GetMinimum(0)}); + yMax = std::max({yMax, hPtRecPrompt->GetMaximum(), hPtGenPrompt->GetMaximum()}); + SetHistogramStyle(hPtGenPrompt, colours[1], markers[1], 1.5, 2); + SetHistogramStyle(hPtRecPrompt, colours[1], markers[1], 1.5, 2); + } + // non-prompt + if (okNonPrompt) { + if (iNRebin > 1) { + hPtGenNonPrompt->Rebin(iNRebin); + hPtRecNonPrompt->Rebin(iNRebin); + } else if (NRebin > 1) { + hPtGenNonPrompt = (TH1F*)hPtGenNonPrompt->Rebin(NRebin, "hPtGenNonPromptR", dRebin); + hPtRecNonPrompt = (TH1F*)hPtRecNonPrompt->Rebin(NRebin, "hPtRecNonPromptR", dRebin); + } + yMin = std::min({yMin, hPtRecNonPrompt->GetMinimum(0), hPtGenNonPrompt->GetMinimum(0)}); + yMax = std::max({yMax, hPtRecNonPrompt->GetMaximum(), hPtGenNonPrompt->GetMaximum()}); + SetHistogramStyle(hPtGenNonPrompt, colours[2], markers[2], 1.5, 2); + SetHistogramStyle(hPtRecNonPrompt, colours[2], markers[2], 1.5, 2); + } + SetHistogram(hPtGenIncl, yMin, yMax, marginLow, marginHigh, logScaleH); + SetPad(padPt, logScaleH); + hPtGenIncl->Draw(); + hPtRecIncl->Draw("same EP"); + legendPt->AddEntry(hPtRecIncl, "inclusive rec", "P"); + legendPt->AddEntry(hPtGenIncl, "inclusive gen", "L"); + if (okPrompt) { + hPtGenPrompt->Draw("same"); + hPtRecPrompt->Draw("same EP"); + legendPt->AddEntry(hPtRecPrompt, "prompt rec", "P"); + legendPt->AddEntry(hPtGenPrompt, "prompt gen", "L"); + } + if (okNonPrompt) { + hPtGenNonPrompt->Draw("same"); + hPtRecNonPrompt->Draw("same EP"); + legendPt->AddEntry(hPtRecNonPrompt, "non-prompt rec", "P"); + legendPt->AddEntry(hPtGenNonPrompt, "non-prompt gen", "L"); + } + legendPt->Draw(); // efficiency - auto padR = canEff->cd(); - TH1F* hEff = (TH1F*)hPtRec->Clone("hEff"); - hEff->Divide(hEff, hPtGen, 1., 1., "B"); - hEff->SetTitle(Form("Entries ratio: %g;#it{p}_{T} (GeV/#it{c});efficiency", (double)nRec / (double)nGen)); - yMin = hEff->GetMinimum(0); - yMax = hEff->GetMaximum(); - SetHistogram(hEff, yMin, yMax, marginRLow, marginRHigh, logScaleR); - SetPad(padR, logScaleR); - hEff->Draw("PE"); + auto padEff = canEff->cd(); + TH1F* hEffIncl = nullptr; + TH1F* hEffPrompt = nullptr; + TH1F* hEffNonPrompt = nullptr; + // inclusive + hEffIncl = (TH1F*)hPtRecIncl->Clone("hEffIncl"); + hEffIncl->Divide(hEffIncl, hPtGenIncl, 1., 1., "B"); + yMin = hEffIncl->GetMinimum(0); + yMax = hEffIncl->GetMaximum(); + SetHistogramStyle(hEffIncl, colours[0], markers[0], 1.5, 2); + hEffIncl->SetTitle(Form("Entries ratio: %g;#it{p}_{T} (GeV/#it{c});reconstruction efficiency", (double)nRec / (double)nGen)); + // prompt + if (okPrompt) { + hEffPrompt = (TH1F*)hPtRecPrompt->Clone("hEffPrompt"); + hEffPrompt->Divide(hPtRecPrompt, hPtGenPrompt, 1., 1., "B"); + yMin = std::min(yMin, hEffPrompt->GetMinimum(0)); + yMax = std::max(yMax, hEffPrompt->GetMaximum()); + SetHistogramStyle(hEffPrompt, colours[1], markers[1], 1.5, 2); + } + // non-prompt + if (okNonPrompt) { + hEffNonPrompt = (TH1F*)hPtRecNonPrompt->Clone("hEffNonPrompt"); + hEffNonPrompt->Divide(hPtRecNonPrompt, hPtGenNonPrompt, 1., 1., "B"); + yMin = std::min(yMin, hEffNonPrompt->GetMinimum(0)); + yMax = std::max(yMax, hEffNonPrompt->GetMaximum()); + SetHistogramStyle(hEffNonPrompt, colours[2], markers[2], 1.5, 2); + } + SetHistogram(hEffIncl, yMin, yMax, marginRLow, marginRHigh, logScaleR); + SetPad(padEff, logScaleR); + hEffIncl->Draw("EP"); + legendEff->AddEntry(hEffIncl, "inclusive", "P"); + if (okPrompt) { + hEffPrompt->Draw("same EP"); + legendEff->AddEntry(hEffPrompt, "prompt", "P"); + } + if (okNonPrompt) { + hEffNonPrompt->Draw("same EP"); + legendEff->AddEntry(hEffNonPrompt, "non-prompt", "P"); + } + legendEff->Draw(); canPt->SaveAs(Form("MC_%s_pT.pdf", particle.Data())); canEff->SaveAs(Form("MC_%s_eff.pdf", particle.Data())); diff --git a/codeHF/RunHFTaskLocal.C b/codeHF/RunHFTaskLocal.C index aefc7ef2..13970929 100644 --- a/codeHF/RunHFTaskLocal.C +++ b/codeHF/RunHFTaskLocal.C @@ -40,7 +40,7 @@ Long64_t RunHFTaskLocal(TString txtfile = "./list_ali.txt", AliPhysicsSelectionTask* physSelTask = reinterpret_cast(gInterpreter->ProcessLine(Form(".x %s(%d)", gSystem->ExpandPathName("$ALICE_PHYSICS/OADB/macros/AddTaskPhysicsSelection.C"), isMC))); - AliAnalysisTaskHFSimpleVertices* tasktr3 = reinterpret_cast(gInterpreter->ProcessLine(Form(".x %s(\"\",\"%s\")", gSystem->ExpandPathName("$ALICE_PHYSICS/PWGHF/vertexingHF/macros/AddTaskHFSimpleVertices.C"), jsonfilename.Data()))); + AliAnalysisTaskHFSimpleVertices* tasktr3 = reinterpret_cast(gInterpreter->ProcessLine(Form(".x %s(\"\",\"%s\",%d)", gSystem->ExpandPathName("$ALICE_PHYSICS/PWGHF/vertexingHF/macros/AddTaskHFSimpleVertices.C"), jsonfilename.Data(), isMC))); if (useO2Vertexer) { tasktr3->SetUseO2Vertexer(); } diff --git a/codeHF/clean.sh b/codeHF/clean.sh index 7316819e..e8a6c872 100644 --- a/codeHF/clean.sh +++ b/codeHF/clean.sh @@ -9,14 +9,17 @@ comparison_histos_skim.pdf comparison_ratios_skim.pdf \ comparison_histos_cand2.pdf comparison_ratios_cand2.pdf \ comparison_histos_cand3.pdf comparison_ratios_cand3.pdf \ comparison_histos_d0.pdf comparison_ratios_d0.pdf \ +comparison_histos_d0-mc.pdf comparison_ratios_d0-mc.pdf \ comparison_histos_dplus.pdf comparison_ratios_dplus.pdf \ comparison_histos_lc.pdf comparison_ratios_lc.pdf \ +comparison_histos_lc-mc.pdf comparison_ratios_lc-mc.pdf \ comparison_histos_jpsi.pdf comparison_ratios_jpsi.pdf \ MC_d0_eff.pdf MC_d0_pT.pdf \ MC_dplus_eff.pdf MC_dplus_pT.pdf \ MC_lc_eff.pdf MC_lc_pT.pdf \ MC_xic_eff.pdf MC_xic_pT.pdf \ MC_jpsi_eff.pdf MC_jpsi_pT.pdf \ +MC_lc-tok0sP_eff.pdf MC_lc-tok0sP_pT.pdf \ ./*.log \ output_* \ || { echo "Error: Failed to delete files."; exit 1; } diff --git a/codeHF/comparison_histos_cand2_ref.pdf b/codeHF/comparison_histos_cand2_ref.pdf index facaf089..d4a05016 100644 Binary files a/codeHF/comparison_histos_cand2_ref.pdf and b/codeHF/comparison_histos_cand2_ref.pdf differ diff --git a/codeHF/comparison_histos_d0_ref.pdf b/codeHF/comparison_histos_d0_ref.pdf index 503f0fee..b6232c30 100644 Binary files a/codeHF/comparison_histos_d0_ref.pdf and b/codeHF/comparison_histos_d0_ref.pdf differ diff --git a/codeHF/comparison_histos_skim_ref.pdf b/codeHF/comparison_histos_skim_ref.pdf index 15aed5ee..4defa534 100644 Binary files a/codeHF/comparison_histos_skim_ref.pdf and b/codeHF/comparison_histos_skim_ref.pdf differ diff --git a/codeHF/comparison_histos_tracks_ref.pdf b/codeHF/comparison_histos_tracks_ref.pdf index ead033c2..a5e5fa34 100644 Binary files a/codeHF/comparison_histos_tracks_ref.pdf and b/codeHF/comparison_histos_tracks_ref.pdf differ diff --git a/codeHF/config_tasks.sh b/codeHF/config_tasks.sh index c7fbea3d..1fc131bd 100644 --- a/codeHF/config_tasks.sh +++ b/codeHF/config_tasks.sh @@ -28,10 +28,12 @@ DATABASE_O2="workflows.yml" MAKE_GRAPH=0 # Make topology graph. # Activation of O2 workflows +# Event selection +DOO2_EVSEL=0 # event-selection and timestamp # QA DOO2_REJ_ALICE3=1 # qa-rejection DOO2_QA_EFF=0 # qa-efficiency -DOO2_QA_SIM=0 # qa-simple +DOO2_QA_EVTRK=0 # qa-event-track DOO2_MC_VALID=0 # hf-mc-validation # PID DOO2_PID_TPC=0 # pid-tpc-full @@ -41,6 +43,7 @@ DOO2_PID_TOF_QA=0 # pid-tof-qa-mc DOO2_SKIM=0 # hf-track-index-skims-creator DOO2_CAND_2PRONG=0 # hf-candidate-creator-2prong DOO2_CAND_3PRONG=0 # hf-candidate-creator-3prong +DOO2_CAND_CASC=0 # hf-candidate-creator-cascade DOO2_CAND_X=0 # hf-candidate-creator-x # Selectors DOO2_SEL_D0=0 # hf-d0-candidate-selector @@ -49,6 +52,7 @@ DOO2_SEL_LC=0 # hf-lc-candidate-selector DOO2_SEL_XIC=0 # hf-xic-topkpi-candidate-selector DOO2_SEL_JPSI=0 # hf-jpsi-candidate-selector DOO2_SEL_X=0 # hf-xic-topkpi-candidate-selector +DOO2_SEL_LCK0SP=0 # hf-lc-tok0sp-candidate-selector # User tasks DOO2_TASK_D0=0 # hf-task-d0 DOO2_TASK_DPLUS=0 # hf-task-dplus @@ -57,6 +61,7 @@ DOO2_TASK_XIC=0 # hf-task-xic DOO2_TASK_JPSI=1 # hf-task-jpsi DOO2_TASK_BPLUS=0 # hf-task-bplus DOO2_TASK_X=0 # hf-task-x +DOO2_TASK_LCK0SP=0 # hf-task-lc-tok0sp # Tree creators DOO2_TREE_D0=0 # hf-tree-creator-d0-tokpi DOO2_TREE_LC=0 # hf-tree-creator-lc-topkpi @@ -68,6 +73,7 @@ APPLYCUTS_LC=0 # Apply Λc selection cuts. APPLYCUTS_XIC=0 # Apply Ξc selection cuts. APPLYCUTS_JPSI=1 # Apply J/ψ selection cuts. APPLYCUTS_X=0 # Apply X selection cuts. +APPLYCUTS_LCK0SP=0 # Apply Λc → K0S p selection cuts. SAVETREES=0 # Save O2 tables to trees. USEO2VERTEXER=0 # Use the O2 vertexer in AliPhysics. @@ -84,6 +90,7 @@ function Clean { [ "$1" -eq 2 ] && { rm -f "$LISTFILES_ALI" "$LISTFILES_O2" "$SCRIPT_ALI" "$SCRIPT_O2" "$SCRIPT_POSTPROCESS" || ErrExit "Failed to rm created files." [ "$JSON_EDIT" ] && { rm "$JSON_EDIT" || ErrExit "Failed to rm $JSON_EDIT."; } + [ "$DATABASE_O2_EDIT" ] && { rm "$DATABASE_O2_EDIT" || ErrExit "Failed to rm $DATABASE_O2_EDIT."; } } return 0 @@ -93,7 +100,7 @@ function Clean { function AdjustJson { # Make a copy of the default JSON file to modify it. JSON_EDIT="" - if [[ $APPLYCUTS_D0 -eq 1 || $APPLYCUTS_DPLUS -eq 1 || $APPLYCUTS_LC -eq 1 || $APPLYCUTS_XIC -eq 1 || $APPLYCUTS_JPSI -eq 1 || $APPLYCUTS_X -eq 1 ]]; then + if [[ $APPLYCUTS_D0 -eq 1 || $APPLYCUTS_DPLUS -eq 1 || $APPLYCUTS_LC -eq 1 || $APPLYCUTS_XIC -eq 1 || $APPLYCUTS_JPSI -eq 1 || $APPLYCUTS_X -eq 1 || $APPLYCUTS_LCK0SP -eq 1 ]]; then JSON_EDIT="${JSON/.json/_edit.json}" cp "$JSON" "$JSON_EDIT" || ErrExit "Failed to cp $JSON $JSON_EDIT." JSON="$JSON_EDIT" @@ -124,7 +131,7 @@ function AdjustJson { ReplaceString "\"d_selectionFlagXic\": \"0\"" "\"d_selectionFlagXic\": \"1\"" "$JSON" || ErrExit "Failed to edit $JSON." fi - # Enable J/ψ selection. + # Enable J/ψ selection. if [ $APPLYCUTS_JPSI -eq 1 ]; then MsgWarn "\nUsing J/ψ selection cuts" ReplaceString "\"d_selectionFlagJpsi\": \"0\"" "\"d_selectionFlagJpsi\": \"1\"" "$JSON" || ErrExit "Failed to edit $JSON." @@ -135,27 +142,48 @@ function AdjustJson { MsgWarn "\nUsing X(3872) selection cuts" ReplaceString "\"d_selectionFlagX\": \"0\"" "\"d_selectionFlagX\": \"1\"" "$JSON" || ErrExit "Failed to edit $JSON." fi + # Enable Λc → K0S p selection. + if [ $APPLYCUTS_LCK0SP -eq 1 ]; then + MsgWarn "\nUsing Λc → K0S p selection cuts" + ReplaceString "\"selectionFlagLcK0sp\": \"0\"" "\"selectionFlagLcK0sp\": \"1\"" "$JSON" || ErrExit "Failed to edit $JSON." + fi } # Generate the O2 script containing the full workflow specification. function MakeScriptO2 { + # Enable cascade reconstruction in case of Λc → K0S p tasks + [[ $DOO2_CAND_CASC -eq 1 || $DOO2_SEL_LCK0SP -eq 1 || $DOO2_TASK_LCK0SP -eq 1 ]] && DOO2_CASC=1 || DOO2_CASC=0 + # Cascade reconstruction + [ $DOO2_CASC -eq 1 ] && SUFFIX_CASC="-v0" || SUFFIX_CASC="" + # Event selection + [ $DOO2_EVSEL -eq 1 ] && SUFFIX_EVSEL="-evsel" || SUFFIX_EVSEL="" + WORKFLOWS="" + # QA [ $DOO2_REJ_ALICE3 -eq 1 ] && WORKFLOWS+=" o2-analysis-qa-rejection" [ $DOO2_QA_EFF -eq 1 ] && WORKFLOWS+=" o2-analysis-qa-efficiency" - [ $DOO2_QA_SIM -eq 1 ] && WORKFLOWS+=" o2-analysis-qa-simple" - [ $DOO2_SKIM -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-track-index-skims-creator" - [ $DOO2_CAND_2PRONG -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-candidate-creator-2prong" - [ $DOO2_CAND_3PRONG -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-candidate-creator-3prong" - [ $DOO2_CAND_X -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-candidate-creator-x" + [ $DOO2_QA_EVTRK -eq 1 ] && WORKFLOWS+=" o2-analysis-qa-event-track" + [ $DOO2_MC_VALID -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-mc-validation" + # PID [ $DOO2_PID_TPC -eq 1 ] && WORKFLOWS+=" o2-analysis-pid-tpc-full" [ $DOO2_PID_TOF -eq 1 ] && WORKFLOWS+=" o2-analysis-pid-tof-full" [ $DOO2_PID_TOF_QA -eq 1 ] && WORKFLOWS+=" o2-analysis-pid-tof-qa-mc" + # Vertexing + WF_SKIM="o2-analysis-hf-track-index-skims-creator${SUFFIX_EVSEL}${SUFFIX_CASC}" + [ $DOO2_SKIM -eq 1 ] && WORKFLOWS+=" $WF_SKIM" + [ $DOO2_CAND_2PRONG -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-candidate-creator-2prong" + [ $DOO2_CAND_3PRONG -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-candidate-creator-3prong" + [ $DOO2_CAND_X -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-candidate-creator-x" + [ $DOO2_CAND_CASC -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-candidate-creator-cascade" + # Selectors [ $DOO2_SEL_D0 -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-d0-candidate-selector" [ $DOO2_SEL_JPSI -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-jpsi-candidate-selector" [ $DOO2_SEL_DPLUS -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-dplus-topikpi-candidate-selector" [ $DOO2_SEL_LC -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-lc-candidate-selector" [ $DOO2_SEL_XIC -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-xic-topkpi-candidate-selector" [ $DOO2_SEL_X -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-x-tojpsipipi-candidate-selector" + [ $DOO2_SEL_LCK0SP -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-lc-tok0sp-candidate-selector" + # User tasks [ $DOO2_TASK_D0 -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-task-d0" [ $DOO2_TASK_JPSI -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-task-jpsi" [ $DOO2_TASK_DPLUS -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-task-dplus" @@ -163,9 +191,10 @@ function MakeScriptO2 { [ $DOO2_TASK_XIC -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-task-xic" [ $DOO2_TASK_BPLUS -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-task-bplus" [ $DOO2_TASK_X -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-task-x" + [ $DOO2_TASK_LCK0SP -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-task-lc-tok0sp" + # Tree creators [ $DOO2_TREE_D0 -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-tree-creator-d0-tokpi" [ $DOO2_TREE_LC -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-tree-creator-lc-topkpi" - [ $DOO2_MC_VALID -eq 1 ] && WORKFLOWS+=" o2-analysis-hf-mc-validation" # Translate options into arguments of the generating script. OPT_MAKECMD="" @@ -174,6 +203,17 @@ function MakeScriptO2 { [ $SAVETREES -eq 1 ] && OPT_MAKECMD+=" -t" [ $MAKE_GRAPH -eq 1 ] && OPT_MAKECMD+=" -g" + # Make a copy of the default workflow database file before modifying it. + DATABASE_O2_EDIT="" + if [[ $DOO2_EVSEL -eq 1 || $DOO2_CASC -eq 1 ]]; then + DATABASE_O2_EDIT="${DATABASE_O2/.yml/_edit.yml}" + cp "$DATABASE_O2" "$DATABASE_O2_EDIT" || ErrExit "Failed to cp $DATABASE_O2 $DATABASE_O2_EDIT." + DATABASE_O2="$DATABASE_O2_EDIT" + + # Adjust workflow database in case of event selection or cascades enabled. + ReplaceString "- o2-analysis-hf-track-index-skims-creator" "- $WF_SKIM" "$DATABASE_O2" || ErrExit "Failed to edit $DATABASE_O2." + fi + # Generate the O2 command. MAKECMD="python3 $DIR_EXEC/make_command_o2.py $DATABASE_O2 $OPT_MAKECMD" O2EXEC=$($MAKECMD -w "$WORKFLOWS") @@ -185,8 +225,8 @@ function MakeScriptO2 { #!/bin/bash FileIn="\$1" JSON="\$2" -mkdir sockets && \ -$O2EXEC && \ +mkdir sockets && \\ +$O2EXEC && \\ rm -r sockets EOF } @@ -206,25 +246,25 @@ function MakeScriptPostprocess { # Compare AliPhysics and O2 histograms. [[ $DOALI -eq 1 && $DOO2 -eq 1 ]] && { OPT_COMPARE="" - [ $DOO2_SKIM -eq 1 ] && OPT_COMPARE+="-tracks-skim" - [ $DOO2_CAND_2PRONG -eq 1 ] && OPT_COMPARE+="-cand2" - [ $DOO2_CAND_3PRONG -eq 1 ] && OPT_COMPARE+="-cand3" - [ $DOO2_TASK_D0 -eq 1 ] && OPT_COMPARE+="-d0" - [ $DOO2_TASK_DPLUS -eq 1 ] && OPT_COMPARE+="-dplus" - [ $DOO2_TASK_LC -eq 1 ] && OPT_COMPARE+="-lc" - [ $DOO2_TASK_XIC -eq 1 ] && OPT_COMPARE+="-xic" - [ $DOO2_TASK_JPSI -eq 1 ] && OPT_COMPARE+="-jpsi" + [ $DOO2_SKIM -eq 1 ] && OPT_COMPARE+=" tracks skim " + [ $DOO2_CAND_2PRONG -eq 1 ] && OPT_COMPARE+=" cand2 " + [ $DOO2_CAND_3PRONG -eq 1 ] && OPT_COMPARE+=" cand3 " + [ $DOO2_TASK_D0 -eq 1 ] && { OPT_COMPARE+=" d0 "; [ "$ISMC" -eq 1 ] && OPT_COMPARE+=" d0-mc "; } + [ $DOO2_TASK_DPLUS -eq 1 ] && OPT_COMPARE+=" dplus " + [ $DOO2_TASK_LC -eq 1 ] && { OPT_COMPARE+=" lc "; [ "$ISMC" -eq 1 ] && OPT_COMPARE+=" lc-mc "; } + [ $DOO2_TASK_XIC -eq 1 ] && OPT_COMPARE+=" xic " + [ $DOO2_TASK_JPSI -eq 1 ] && OPT_COMPARE+=" jpsi " [ "$OPT_COMPARE" ] && POSTEXEC+=" && root -b -q -l \"$DIR_TASKS/Compare.C(\\\"\$FileO2\\\", \\\"\$FileAli\\\", \\\"$OPT_COMPARE\\\", $DORATIO)\"" } # Plot particle reconstruction efficiencies. [[ $DOO2 -eq 1 && $ISMC -eq 1 ]] && { PARTICLES="" - [ $DOO2_TASK_D0 -eq 1 ] && PARTICLES+="-d0" - [ $DOO2_TASK_DPLUS -eq 1 ] && PARTICLES+="-dplus" - [ $DOO2_TASK_LC -eq 1 ] && PARTICLES+="-lc" - [ $DOO2_TASK_XIC -eq 1 ] && PARTICLES+="-xic" - [ $DOO2_TASK_JPSI -eq 1 ] && PARTICLES+="-jpsi" - [ $DOO2_TASK_X -eq 1 ] && PARTICLES+="-x" + [ $DOO2_TASK_D0 -eq 1 ] && PARTICLES+=" d0 " + [ $DOO2_TASK_DPLUS -eq 1 ] && PARTICLES+=" dplus " + [ $DOO2_TASK_LC -eq 1 ] && PARTICLES+=" lc " + [ $DOO2_TASK_XIC -eq 1 ] && PARTICLES+=" xic " + [ $DOO2_TASK_JPSI -eq 1 ] && PARTICLES+=" jpsi " + [ $DOO2_TASK_LCK0SP -eq 1 ] && PARTICLES+=" lc-tok0sP " [ "$PARTICLES" ] && POSTEXEC+=" && root -b -q -l \"$DIR_TASKS/PlotEfficiency.C(\\\"\$FileO2\\\", \\\"$PARTICLES\\\")\"" } cat << EOF > "$SCRIPT_POSTPROCESS" diff --git a/codeHF/dpl-config_run3.json b/codeHF/dpl-config_run3.json index 1bd0895e..3afe3614 100644 --- a/codeHF/dpl-config_run3.json +++ b/codeHF/dpl-config_run3.json @@ -189,7 +189,40 @@ "d_pidTOFMaxpT": "-1.", "d_TPCNClsFindablePIDCut": "50.", "d_nSigmaTPC": "3.", - "d_nSigmaTOF": "3." + "d_nSigmaTOF": "3.", + "pTBins": { + "values": [ + "1.", + "2.", + "3.", + "4.", + "5.", + "6.", + "7.", + "8.", + "10.", + "12.", + "16.", + "24.", + "36." + ] + }, + "DPlus_to_Pi_K_Pi_cuts": { + "values": [ + ["0.2", "0.3", "0.3", "0.07", "6.", "0.96", "0.985", "2.5"], + ["0.2", "0.3", "0.3", "0.07", "5.", "0.96", "0.985", "2.5"], + ["0.2", "0.3", "0.3", "0.10", "5.", "0.96", "0.980", "2.5"], + ["0.2", "0.3", "0.3", "0.10", "5.", "0.96", "0.000", "2.5"], + ["0.2", "0.3", "0.3", "0.10", "5.", "0.96", "0.000", "2.5"], + ["0.2", "0.3", "0.3", "0.10", "5.", "0.96", "0.000", "2.5"], + ["0.2", "0.3", "0.3", "0.10", "5.", "0.96", "0.000", "2.5"], + ["0.2", "0.3", "0.3", "0.12", "5.", "0.96", "0.000", "2.5"], + ["0.2", "0.3", "0.3", "0.12", "5.", "0.96", "0.000", "2.5"], + ["0.2", "0.3", "0.3", "0.12", "5.", "0.96", "0.000", "2.5"], + ["0.2", "0.3", "0.3", "0.12", "5.", "0.96", "0.000", "2.5"], + ["0.2", "0.3", "0.3", "0.20", "5.", "0.94", "0.000", "2.5"] + ] + } }, "hf-lc-candidate-selector": { "d_pTCandMin": "0.", diff --git a/codeHF/utils_plot.h b/codeHF/utils_plot.h index 6500c28c..94f98bf3 100644 --- a/codeHF/utils_plot.h +++ b/codeHF/utils_plot.h @@ -34,3 +34,12 @@ void SetHistogram(TH1* his, Float_t yMin, Float_t yMax, Float_t marginLow, Float his->GetYaxis()->SetRangeUser(yMin - marginLow / k * yRange, yMax + marginHigh / k * yRange); } } + +void SetHistogramStyle(TH1* his, Int_t colour = 1, Int_t markerStyle = 1, Float_t markerSize = 1, Float_t lineWidth = 1) +{ + his->SetLineColor(colour); + his->SetLineWidth(lineWidth); + his->SetMarkerColor(colour); + his->SetMarkerStyle(markerStyle); + his->SetMarkerSize(markerSize); +} diff --git a/codeHF/versions_ref.txt b/codeHF/versions_ref.txt index b37a5d78..d859c446 100644 --- a/codeHF/versions_ref.txt +++ b/codeHF/versions_ref.txt @@ -1,4 +1,4 @@ -alidist: master 2021-02-03 22:10:18 +0100 c9b6c5a bump infologger (#2808) -AliPhysics: master 2021-02-03 23:01:26 +0100 64ee243e1d Merge pull request #16821 from fjonasALICE/master -O2: dev 2021-02-03 23:37:25 +0100 64d56ea416 Digits labels should be read via ConstMCTruthContainer -Run 3 validation: master 2021-02-04 00:54:48 +0100 3938aed Update input cases. +alidist: master 2021-06-19 20:37:59 +0200 a1f6ba0 Auto-update defaults-generators.sh and aligenerators.sh (#3116) +AliPhysics: master 2021-06-20 14:53:55 +0200 58e2b8e609c8 Merge pull request #17961 from jokonig/master +O2: dev 2021-06-21 00:54:13 +0200 e095f7dd17 Fix typo in PVertexer debris cleanup +Run 3 validation: master 2021-06-20 23:38:45 +0200 bd90f03 Catch more O2 errors diff --git a/codeHF/workflows.yml b/codeHF/workflows.yml index 156cc5d4..245ff11a 100644 --- a/codeHF/workflows.yml +++ b/codeHF/workflows.yml @@ -1,20 +1,54 @@ +--- options: global: "--fairmq-ipc-prefix sockets" - local: ["--aod-memory-rate-limit 2000000000", "--shm-segment-size 16000000000", "--configuration json://$JSON", "-b"] + local: + - "-b" + - "--configuration json://$JSON" + - "--aod-memory-rate-limit 2000000000" + - "--shm-segment-size 16000000000" + - "--min-failure-level error" workflows: + # Event selection + + o2-analysis-timestamp: + options: + mc: "--isMC 1" + + o2-analysis-event-selection: + options: + mc: "--isMC 1" + # Skimming - o2-analysis-hf-track-index-skims-creator: - activate: no + o2-analysis-hf-track-index-skims-creator: &skim_creator + executable: o2-analysis-hf-track-index-skims-creator tables: [HFSELTRACK, HFTRACKIDXP2, HFTRACKIDXP3] + o2-analysis-hf-track-index-skims-creator-evsel: + <<: *skim_creator + dependencies: [o2-analysis-timestamp, o2-analysis-event-selection] + options: "--doEvSel" + tables: [HFSELCOL, HFSELTRACK, HFTRACKIDXP2, HFTRACKIDXP3] + + o2-analysis-hf-track-index-skims-creator-v0: + <<: *skim_creator + dependencies: o2-analysis-lambdakzerobuilder + options: "--do-LcK0Sp" + tables: [HFSELTRACK, HFTRACKIDXCASC, HFTRACKIDXP2, HFTRACKIDXP3] + + o2-analysis-hf-track-index-skims-creator-evsel-v0: + <<: *skim_creator + dependencies: [o2-analysis-timestamp, o2-analysis-event-selection, o2-analysis-lambdakzerobuilder] + options: ["--doEvSel", "--do-LcK0Sp"] + tables: [HFSELCOL, HFSELTRACK, HFTRACKIDXCASC, HFTRACKIDXP2, HFTRACKIDXP3] + # Candidate creators o2-analysis-hf-candidate-creator-2prong: &cand_creator - activate: no - dependencies: [o2-analysis-hf-track-index-skims-creator] + dependencies: + - o2-analysis-hf-track-index-skims-creator options: mc: "--doMC" tables: @@ -23,99 +57,95 @@ workflows: o2-analysis-hf-candidate-creator-3prong: <<: *cand_creator - activate: no tables: default: [HFCANDP3BASE, HFCANDP3EXT] mc: [HFCANDP3MCREC, HFCANDP3MCGEN] + o2-analysis-hf-candidate-creator-cascade: + <<: *cand_creator + tables: + default: [HFCANDCASCBASE, HFCANDCASCEXT] + mc: [HFCANDCASCMCREC, HFCANDCASCMCGEN] + + o2-analysis-hf-candidate-creator-x: + <<: *cand_creator + dependencies: o2-analysis-hf-jpsi-candidate-selector + tables: + default: [HFCANDXBASE, HFCANDXEXT] + mc: [HFCANDXMCREC, HFCANDXMCGEN] + # Selectors o2-analysis-hf-d0-candidate-selector: &selector_2prong - activate: no dependencies: [o2-analysis-hf-candidate-creator-2prong, o2-analysis-pid-tpc-full, o2-analysis-pid-tof-full] + tables: HFSELD0CAND o2-analysis-hf-jpsi-candidate-selector: <<: *selector_2prong - activate: no tables: HFSELJPSICAND o2-analysis-hf-dplus-topikpi-candidate-selector: &selector_3prong - activate: no dependencies: [o2-analysis-hf-candidate-creator-3prong, o2-analysis-pid-tpc-full, o2-analysis-pid-tof-full] + tables: HFSELDPLUSCAND o2-analysis-hf-lc-candidate-selector: <<: *selector_3prong - activate: no + tables: HFSELLCCAND o2-analysis-hf-xic-topkpi-candidate-selector: <<: *selector_3prong - activate: no + tables: HFSELXICCAND - # Cascade candidate creators - - o2-analysis-hf-candidate-creator-x: &cand_creator_casc - activate: no - dependencies: [o2-analysis-hf-jpsi-candidate-selector] - options: - mc: "--doMC" - tables: - default: [HFCANDXBASE, HFCANDXEXT] - mc: [HFCANDXMCREC, HFCANDXMCGEN] + o2-analysis-hf-lc-tok0sp-candidate-selector: + dependencies: [o2-analysis-hf-candidate-creator-cascade, o2-analysis-pid-tpc-full, o2-analysis-pid-tof-full] + tables: HFSELLCK0SPCAND - # Cascade candidate selectors - - o2-analysis-hf-x-tojpsipipi-candidate-selector: &selector_casc - activate: no + o2-analysis-hf-x-tojpsipipi-candidate-selector: dependencies: [o2-analysis-hf-candidate-creator-x, o2-analysis-pid-tpc-full, o2-analysis-pid-tof-full] # Analysis tasks o2-analysis-hf-task-d0: &task - activate: no dependencies: o2-analysis-hf-d0-candidate-selector options: mc: "--doMC" o2-analysis-hf-task-jpsi: <<: *task - activate: no dependencies: o2-analysis-hf-jpsi-candidate-selector o2-analysis-hf-task-dplus: <<: *task - activate: no dependencies: o2-analysis-hf-dplus-topikpi-candidate-selector o2-analysis-hf-task-lc: <<: *task - activate: no dependencies: o2-analysis-hf-lc-candidate-selector o2-analysis-hf-task-xic: <<: *task - activate: no dependencies: o2-analysis-hf-xic-topkpi-candidate-selector o2-analysis-hf-task-bplus: <<: *task - activate: no dependencies: o2-analysis-hf-d0-candidate-selector o2-analysis-hf-task-x: <<: *task - activate: no dependencies: o2-analysis-hf-x-tojpsipipi-candidate-selector + o2-analysis-hf-task-lc-tok0sp: + <<: *task + dependencies: o2-analysis-hf-lc-tok0sp-candidate-selector + # Tree creators o2-analysis-hf-tree-creator-d0-tokpi: - activate: no requires_mc: yes dependencies: o2-analysis-hf-d0-candidate-selector tables: [HFCANDP2Full, HFCANDP2FullE, HFCANDP2FullP] o2-analysis-hf-tree-creator-lc-topkpi: - activate: no requires_mc: yes dependencies: o2-analysis-hf-lc-candidate-selector tables: [HFCANDP3Full, HFCANDP3FullE, HFCANDP3FullP] @@ -123,36 +153,41 @@ workflows: # QA o2-analysis-qa-efficiency: - activate: no requires_mc: yes options: "--eff-el 1 --eff-mu 1 --eff-pi 1 --eff-ka 1 --eff-pr 1" - o2-analysis-qa-simple: - activate: no + o2-analysis-qa-event-track: requires_mc: yes o2-analysis-qa-rejection: - activate: no requires_mc: yes - dependencies: [o2-analysis-hf-track-index-skims-creator, o2-analysis-pid-tpc-full, o2-analysis-pid-tof-full] + dependencies: + - o2-analysis-hf-track-index-skims-creator + - o2-analysis-pid-tpc-full + - o2-analysis-pid-tof-full o2-analysis-pid-tof-qa-mc: - activate: no requires_mc: yes dependencies: [o2-analysis-pid-tof-full, o2-analysis-pid-tof-beta] o2-analysis-hf-mc-validation: - activate: no requires_mc: yes dependencies: o2-analysis-hf-d0-candidate-selector # PID - o2-analysis-pid-tpc-full: - activate: no + o2-analysis-pid-tpc-full: {} + + o2-analysis-pid-tof-full: {} + + o2-analysis-pid-tof-beta: {} + + # LF + + o2-analysis-lambdakzerobuilder: + dependencies: [o2-analysis-trackextension, o2-analysis-weak-decay-indices] + options: "--v0radius 0.9" - o2-analysis-pid-tof-full: - activate: no + o2-analysis-trackextension: {} - o2-analysis-pid-tof-beta: - activate: no + o2-analysis-weak-decay-indices: {} diff --git a/exec/batch_ali.sh b/exec/batch_ali.sh index 072c1b6c..9bcbb4d6 100644 --- a/exec/batch_ali.sh +++ b/exec/batch_ali.sh @@ -27,13 +27,14 @@ JSON="$(realpath "$JSON")" LogFile="log_ali.log" ListIn="list_ali.txt" FilesToMerge="ListOutToMergeAli.txt" -DirBase="$PWD" IndexFile=0 -ListRunScripts="$DirBase/ListRunScriptsAli.txt" +IndexJob=0 DirOutMain="output_ali" +CMDPARALLEL="cd \"$DirOutMain/{}\" && bash \"$DIR_THIS/run_ali.sh\" \"$SCRIPT\" \"$ListIn\" \"$JSON\" \"$LogFile\"" + # Clean before running. -rm -rf "$ListRunScripts" "$FilesToMerge" "$FILEOUT" "$DirOutMain" || ErrExit "Failed to delete output files." +rm -rf "$FilesToMerge" "$FILEOUT" "$DirOutMain" || ErrExit "Failed to delete output files." CheckFile "$LISTINPUT" echo "Output directory: $DirOutMain (logfiles: $LogFile)" @@ -46,30 +47,25 @@ while read -r FileIn; do # New job if [ $((IndexFile % NFILESPERJOB)) -eq 0 ]; then mkdir -p $DirOut || ErrExit "Failed to mkdir $DirOut." - FileOut="$DirOut/$FILEOUT" - echo "$FileOut" >> "$DirBase/$FilesToMerge" || ErrExit "Failed to echo to $DirBase/$FilesToMerge." - # Add this job in the list of commands. - echo "cd \"$DirOut\" && bash \"$DIR_THIS/run_ali.sh\" \"$SCRIPT\" \"$ListIn\" \"$JSON\" \"$LogFile\"" >> "$ListRunScripts" || ErrExit "Failed to echo to $ListRunScripts." + echo "$DirOut/$FILEOUT" >> "$FilesToMerge" || ErrExit "Failed to echo to $FilesToMerge." fi echo "$FileIn" >> "$DirOut/$ListIn" || ErrExit "Failed to echo to $DirOut/$ListIn." [ "$DEBUG" -eq 1 ] && echo "Input file ($IndexFile, job $IndexJob): $FileIn" - ((IndexFile+=1)) + ((IndexFile++)) done < "$LISTINPUT" -CheckFile "$ListRunScripts" -echo "Running AliPhysics jobs... ($(wc -l < "$ListRunScripts") jobs, $NFILESPERJOB files/job)" +echo "Running AliPhysics jobs... ($((IndexJob+1)) jobs, $NFILESPERJOB files/job)" OPT_PARALLEL="--halt soon,fail=100%" if [ "$DEBUG" -eq 0 ]; then # shellcheck disable=SC2086 # Ignore unquoted options. - parallel $OPT_PARALLEL < "$ListRunScripts" > $LogFile 2>&1 + parallel $OPT_PARALLEL "$CMDPARALLEL" ::: $(seq 0 $IndexJob) > $LogFile 2>&1 else # shellcheck disable=SC2086 # Ignore unquoted options. - parallel $OPT_PARALLEL --will-cite --progress < "$ListRunScripts" > $LogFile + parallel $OPT_PARALLEL --will-cite --progress "$CMDPARALLEL" ::: $(seq 0 $IndexJob) > $LogFile fi || ErrExit "\nCheck $(realpath $LogFile)" grep -q -e '^'"W-" -e '^'"Warning" "$LogFile" && MsgWarn "There were warnings!\nCheck $(realpath $LogFile)" grep -q -e '^'"E-" -e '^'"Error" "$LogFile" && MsgErr "There were errors!\nCheck $(realpath $LogFile)" grep -q -e '^'"F-" -e '^'"Fatal" -e "segmentation" "$LogFile" && ErrExit "There were fatal errors!\nCheck $(realpath $LogFile)" -rm -f "$ListRunScripts" || ErrExit "Failed to rm $ListRunScripts." echo "Merging output files... (output file: $FILEOUT, logfile: $LogFile)" hadd "$FILEOUT" @"$FilesToMerge" >> $LogFile 2>&1 || \ diff --git a/exec/batch_convert.sh b/exec/batch_convert.sh index b67f616e..1ce7b273 100644 --- a/exec/batch_convert.sh +++ b/exec/batch_convert.sh @@ -21,13 +21,14 @@ source "$DIR_THIS/utilities.sh" || { echo "Error: Failed to load utilities."; ex LogFile="log_convert.log" ListIn="list_convert.txt" -DirBase="$PWD" IndexFile=0 -ListRunScripts="$DirBase/ListRunScriptsConversion.txt" +IndexJob=0 DirOutMain="output_conversion" +CMDPARALLEL="cd \"$DirOutMain/{}\" && bash \"$DIR_THIS/run_convert.sh\" \"$ListIn\" $ISMC \"$LogFile\"" + # Clean before running. -rm -rf "$ListRunScripts" "$LISTOUTPUT" "$DirOutMain" || ErrExit "Failed to delete output files." +rm -rf "$LISTOUTPUT" "$DirOutMain" || ErrExit "Failed to delete output files." CheckFile "$LISTINPUT" echo "Output directory: $DirOutMain (logfiles: $LogFile)" @@ -40,29 +41,24 @@ while read -r FileIn; do # New job if [ $((IndexFile % NFILESPERJOB)) -eq 0 ]; then mkdir -p $DirOut || ErrExit "Failed to mkdir $DirOut." - FileOut="$DirOut/$FILEOUT" - echo "$DirBase/$FileOut" >> "$DirBase/$LISTOUTPUT" || ErrExit "Failed to echo to $DirBase/$LISTOUTPUT." - # Add this job in the list of commands. - echo "cd \"$DirOut\" && bash \"$DIR_THIS/run_convert.sh\" \"$ListIn\" $ISMC \"$LogFile\"" >> "$ListRunScripts" || ErrExit "Failed to echo to $ListRunScripts." + echo "$DirOut/$FILEOUT" >> "$LISTOUTPUT" || ErrExit "Failed to echo to $LISTOUTPUT." fi echo "$FileIn" >> "$DirOut/$ListIn" || ErrExit "Failed to echo to $DirOut/$ListIn." [ "$DEBUG" -eq 1 ] && echo "Input file ($IndexFile, job $IndexJob): $FileIn" - ((IndexFile+=1)) + ((IndexFile++)) done < "$LISTINPUT" -CheckFile "$ListRunScripts" -echo "Running conversion jobs... ($(wc -l < "$ListRunScripts") jobs, $NFILESPERJOB files/job)" +echo "Running conversion jobs... ($((IndexJob+1)) jobs, $NFILESPERJOB files/job)" OPT_PARALLEL="--halt soon,fail=100%" if [ "$DEBUG" -eq 0 ]; then # shellcheck disable=SC2086 # Ignore unquoted options. - parallel $OPT_PARALLEL < "$ListRunScripts" > $LogFile 2>&1 + parallel $OPT_PARALLEL "$CMDPARALLEL" ::: $(seq 0 $IndexJob) > $LogFile 2>&1 else # shellcheck disable=SC2086 # Ignore unquoted options. - parallel $OPT_PARALLEL --will-cite --progress < "$ListRunScripts" > $LogFile + parallel $OPT_PARALLEL --will-cite --progress "$CMDPARALLEL" ::: $(seq 0 $IndexJob) > $LogFile fi || ErrExit "\nCheck $(realpath $LogFile)" grep -q -e '^'"W-" -e '^'"Warning" "$LogFile" && MsgWarn "There were warnings!\nCheck $(realpath $LogFile)" grep -q -e '^'"E-" -e '^'"Error" "$LogFile" && MsgErr "There were errors!\nCheck $(realpath $LogFile)" grep -q -e '^'"F-" -e '^'"Fatal" -e "segmentation" "$LogFile" && ErrExit "There were fatal errors!\nCheck $(realpath $LogFile)" -rm -f "$ListRunScripts" || ErrExit "Failed to rm $ListRunScripts." exit 0 diff --git a/exec/batch_o2.sh b/exec/batch_o2.sh index 8c66831e..b253a298 100644 --- a/exec/batch_o2.sh +++ b/exec/batch_o2.sh @@ -29,13 +29,14 @@ LogFile="log_o2.log" ListIn="list_o2.txt" FilesToMerge="ListOutToMergeO2.txt" FilesToMergeTree="ListOutToMergeO2Tree.txt" -DirBase="$PWD" IndexFile=0 -ListRunScripts="$DirBase/ListRunScriptsO2.txt" +IndexJob=0 DirOutMain="output_o2" +CMDPARALLEL="cd \"$DirOutMain/{}\" && bash \"$DIR_THIS/run_o2.sh\" \"$SCRIPT\" \"$ListIn\" \"$JSON\" \"$LogFile\"" + # Clean before running. -rm -rf "$ListRunScripts" "$FilesToMerge" "$FilesToMergeTree" "$FILEOUT" "$FILEOUT_TREE" "$DirOutMain" || ErrExit "Failed to delete output files." +rm -rf "$FilesToMerge" "$FilesToMergeTree" "$FILEOUT" "$FILEOUT_TREE" "$DirOutMain" || ErrExit "Failed to delete output files." CheckFile "$LISTINPUT" echo "Output directory: $DirOutMain (logfiles: $LogFile)" @@ -48,33 +49,26 @@ while read -r FileIn; do # New job if [ $((IndexFile % NFILESPERJOB)) -eq 0 ]; then mkdir -p $DirOut || ErrExit "Failed to mkdir $DirOut." - FileOut="$DirOut/$FILEOUT" - echo "$FileOut" >> "$DirBase/$FilesToMerge" || ErrExit "Failed to echo to $DirBase/$FilesToMerge." - [ "$FILEOUT_TREE" ] && { - FileOutTree="$DirOut/$FILEOUT_TREE" - echo "$FileOutTree" >> "$DirBase/$FilesToMergeTree" || ErrExit "Failed to echo to $DirBase/$FilesToMergeTree." - } - # Add this job in the list of commands. - echo "cd \"$DirOut\" && bash \"$DIR_THIS/run_o2.sh\" \"$SCRIPT\" \"$ListIn\" \"$JSON\" \"$LogFile\"" >> "$ListRunScripts" || ErrExit "Failed to echo to $ListRunScripts." + echo "$DirOut/$FILEOUT" >> "$FilesToMerge" || ErrExit "Failed to echo to $FilesToMerge." + [ "$FILEOUT_TREE" ] && \ + { echo "$DirOut/$FILEOUT_TREE" >> "$FilesToMergeTree" || ErrExit "Failed to echo to $FilesToMergeTree."; } fi echo "$FileIn" >> "$DirOut/$ListIn" || ErrExit "Failed to echo to $DirOut/$ListIn." [ "$DEBUG" -eq 1 ] && echo "Input file ($IndexFile, job $IndexJob): $FileIn" - ((IndexFile+=1)) + ((IndexFile++)) done < "$LISTINPUT" -CheckFile "$ListRunScripts" -echo "Running O2 jobs... ($(wc -l < "$ListRunScripts") jobs, $NJOBSPARALLEL parallel, $NFILESPERJOB files/job)" +echo "Running O2 jobs... ($((IndexJob+1)) jobs, $NJOBSPARALLEL parallel, $NFILESPERJOB files/job)" OPT_PARALLEL="--halt soon,fail=100% --jobs $NJOBSPARALLEL" if [ "$DEBUG" -eq 0 ]; then # shellcheck disable=SC2086 # Ignore unquoted options. - parallel $OPT_PARALLEL < "$ListRunScripts" > $LogFile 2>&1 + parallel $OPT_PARALLEL "$CMDPARALLEL" ::: $(seq 0 $IndexJob) > $LogFile 2>&1 else # shellcheck disable=SC2086 # Ignore unquoted options. - parallel $OPT_PARALLEL --will-cite --progress < "$ListRunScripts" > $LogFile + parallel $OPT_PARALLEL --will-cite --progress "$CMDPARALLEL" ::: $(seq 0 $IndexJob) > $LogFile fi || ErrExit "\nCheck $(realpath $LogFile)" grep -q "\\[WARN\\]" "$LogFile" && MsgWarn "There were warnings!\nCheck $(realpath $LogFile)" grep -q -e "\\[ERROR\\]" -e "segmentation" "$LogFile" && MsgErr "There were errors!\nCheck $(realpath $LogFile)" -rm -f "$ListRunScripts" || ErrExit "Failed to rm $ListRunScripts." echo "Merging output files... (output file: $FILEOUT, logfile: $LogFile)" hadd $FILEOUT @"$FilesToMerge" >> $LogFile 2>&1 || \ diff --git a/exec/check_spaces.sh b/exec/check_spaces.sh index 39ca7678..654ba83a 100644 --- a/exec/check_spaces.sh +++ b/exec/check_spaces.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Find tabs in text files +# Find tabs and trailing whitespaces in text files # This directory DIR_THIS="$(dirname "$(realpath "$0")")" diff --git a/exec/make_command_o2.py b/exec/make_command_o2.py index 8cfeeb93..bcfe1290 100644 --- a/exec/make_command_o2.py +++ b/exec/make_command_o2.py @@ -88,20 +88,15 @@ def healthy_structure(dic_full: dict): if not isinstance(dic_wf, dict): msg_err('"workflows" is not a dictionary.') return False - # Check mandatory workflow keys. + # Check workflow keys. for wf in dic_wf: dic_wf_single = dic_wf[wf] if not isinstance(dic_wf_single, dict): msg_err("%s is not a dictionary." % wf) return False - good = True - for key in ["activate"]: - if key not in dic_wf_single: - msg_err('Key "%s" not found in workflow %s.' % (key, wf)) - good = False - if not good: - return False - if not isinstance(dic_wf_single["activate"], bool): + if "activate" in dic_wf_single and not isinstance( + dic_wf_single["activate"], bool + ): msg_err('"activate" in workflow %s is not a boolean.' % wf) return False return True @@ -123,7 +118,7 @@ def activate_workflow(wf: str, dic_wf: dict, mc=False, level=0, debug=False): dic_wf_single["activate"] = False return # Activate. - if not dic_wf_single["activate"]: + if "activate" not in dic_wf_single or not dic_wf_single["activate"]: dic_wf_single["activate"] = True # Activate dependencies recursively. if "dependencies" in dic_wf_single: @@ -197,11 +192,13 @@ def main(): # Get list of primary workflows to run. # already activated in the database - list_wf_activated = [wf for wf in dic_wf if dic_wf[wf]["activate"]] + list_wf_activated = [ + wf for wf in dic_wf if "activate" in dic_wf[wf] and dic_wf[wf]["activate"] + ] if debug and list_wf_activated: eprint("\nWorkflows activated in the database:") eprint("\n".join(" " + wf for wf in list_wf_activated)) - # requested at command line + # requested on command line if workflows_add: if debug: eprint("\nWorkflows specified on command line:") @@ -223,7 +220,7 @@ def main(): if save_tables: tables = [] # list of all tables of activated workflows for wf, dic_wf_single in dic_wf.items(): - if not dic_wf_single["activate"]: + if "activate" not in dic_wf_single or not dic_wf_single["activate"]: continue if "tables" not in dic_wf_single: continue @@ -233,6 +230,8 @@ def main(): elif isinstance(tab_wf, dict): if "default" in tab_wf: join_to_list(tab_wf["default"], tables) + if not mc_mode and "real" in tab_wf: + join_to_list(tab_wf["real"], tables) if mc_mode and "mc" in tab_wf: join_to_list(tab_wf["mc"], tables) else: @@ -251,11 +250,23 @@ def main(): command = "" eprint("\nActivated workflows:") for wf, dic_wf_single in dic_wf.items(): - if not dic_wf_single["activate"]: + if "activate" not in dic_wf_single or not dic_wf_single["activate"]: continue msg_bold(" " + wf) - string_wf = wf - # Process options + # Determine the workflow executable. + if "executable" in dic_wf_single: + exec_wf = dic_wf_single["executable"] + if not isinstance(exec_wf, str): + msg_err('"executable" in %s must be str, is %s' % (wf, type(exec_wf))) + sys.exit(1) + string_wf = exec_wf + else: + string_wf = wf + # Detect duplicate workflows. + if string_wf + " " in command: + msg_err("Workflow %s is already present." % string_wf) + sys.exit(1) + # Process options. if "options" in dic_wf_single: opt_wf = dic_wf_single["options"] if isinstance(opt_wf, (str, list)): @@ -263,6 +274,8 @@ def main(): elif isinstance(opt_wf, dict): if "default" in opt_wf: string_wf += " " + join_strings(opt_wf["default"]) + if not mc_mode and "real" in opt_wf: + string_wf += " " + join_strings(opt_wf["real"]) if mc_mode and "mc" in opt_wf: string_wf += " " + join_strings(opt_wf["mc"]) else: @@ -273,12 +286,12 @@ def main(): sys.exit(1) if opt_local: string_wf += " " + opt_local - command += " | " + string_wf + command += "| \\\n" + string_wf + " " if not command: msg_err("Nothing to do!") sys.exit(1) - # Remove the leading " | ". - command = command[3:] + # Remove the leading "| \\\n". + command = command[4:] # Append global options. if opt_global: command += " " + opt_global @@ -299,11 +312,11 @@ def main(): dot += " ranksep=2 // vertical node separation\n" dot += ' node [shape=box, style="filled,rounded", fillcolor=papayawhip, fontname=Courier, fontsize=20]\n' for wf, dic_wf_single in dic_wf.items(): - if not dic_wf_single["activate"]: + if "activate" not in dic_wf_single or not dic_wf_single["activate"]: continue - # hyphens are not allowed in node names + # Hyphens are not allowed in node names. node_wf = wf.replace("-", "_") - # replace hyphens with line breaks to save horizontal space + # Replace hyphens with line breaks to save horizontal space. label_wf = wf.replace("-", "\\n") dot += ' %s [label="%s"]\n' % (node_wf, label_wf) if "dependencies" in dic_wf_single: diff --git a/exec/run_o2.sh b/exec/run_o2.sh index ca690ffe..5d8090a9 100644 --- a/exec/run_o2.sh +++ b/exec/run_o2.sh @@ -10,6 +10,6 @@ bash "$SCRIPT" "$FILEIN" "$JSON" > "$LOGFILE" 2>&1 ExitCode=$? # Show warnings and errors in the log file. -grep -e "\\[WARN\\]" -e "\\[ERROR\\]" -e "segmentation" "$LOGFILE" | sort -u +grep -e "\\[WARN\\]" -e "\\[ERROR\\]" -e "\\[FATAL\\]" -e "segmentation" -e "command not found" -e "Error:" "$LOGFILE" | sort -u exit $ExitCode diff --git a/exec/runtest.sh b/exec/runtest.sh index e4dc5303..c73f223f 100644 --- a/exec/runtest.sh +++ b/exec/runtest.sh @@ -59,8 +59,7 @@ FILEOUT_TREES_O2="AnalysisResults_trees_O2.root" # Steering commands ENVALI="alienv setenv AliPhysics/latest -c" ENVO2="alienv setenv O2/latest -c" -#ENVALIO2="alienv setenv AliPhysics/latest,O2/latest -c" -ENVPOST="$ENVALI" +ENVPOST="alienv setenv ROOT/latest -c" # Step scripts SCRIPT_O2="script_o2.sh" @@ -158,8 +157,6 @@ if [ $DOALI -eq 1 ]; then [ "$O2_ROOT" ] && { MsgWarn "O2 environment is loaded - expect errors!"; } [ "$ALICE_PHYSICS" ] && { MsgWarn "AliPhysics environment is already loaded."; ENVALI=""; } $ENVALI bash "$DIR_EXEC/batch_ali.sh" "$LISTFILES_ALI" "$JSON" "$SCRIPT_ALI" $DEBUG "$NFILESPERJOB_ALI" || exit 1 - # Run the batch script in the ALI+O2 environment. - #$ENVALIO2 bash "$DIR_EXEC/batch_ali.sh" $LISTFILES_ALI $JSON $SCRIPT_ALI $DEBUG || exit 1 mv "$FILEOUT" "$FILEOUT_ALI" || ErrExit "Failed to mv $FILEOUT $FILEOUT_ALI." fi @@ -189,10 +186,9 @@ if [ $DOPOSTPROCESS -eq 1 ]; then MsgStep "Postprocessing... (logfile: $LogFile)" MakeScriptPostprocess || ErrExit "MakeScriptPostprocess failed." CheckFile "$SCRIPT_POSTPROCESS" - [ $DEBUG -eq 1 ] && echo "Loading AliPhysics..." + [ $DEBUG -eq 1 ] && echo "Loading ROOT..." # Run the batch script in the postprocessing environment. - [ "$O2_ROOT" ] && { MsgWarn "O2 environment is loaded - expect errors!"; } - [ "$ALICE_PHYSICS" ] && { MsgWarn "AliPhysics environment is already loaded."; ENVALI=""; } + [ "$ROOTSYS" ] && { MsgWarn "ROOT environment is already loaded."; ENVPOST=""; } $ENVPOST bash "$SCRIPT_POSTPROCESS" "$FILEOUT_O2" "$FILEOUT_ALI" > $LogFile 2>&1 || ErrExit "\nCheck $(realpath $LogFile)" grep -q -e '^'"W-" -e '^'"Warning" -e "warning" "$LogFile" && MsgWarn "There were warnings!\nCheck $(realpath $LogFile)" grep -q -e '^'"E-" -e '^'"Error" "$LogFile" && MsgErr "There were errors!\nCheck $(realpath $LogFile)"