From 4620b422235632ceb643567e2376fb76805a5d0c Mon Sep 17 00:00:00 2001 From: Sara Pucillo Date: Fri, 13 Nov 2026 19:09:05 +0100 Subject: [PATCH 1/7] [PWGLF] Add StrangenessV0s hands-on tutorial --- Tutorials/PWGLF/Strangeness/CMakeLists.txt | 2 +- .../StrangenessV0s_HandsOn/README.md | 118 +++++++ .../StrangenessV0s_HandsOn/checkTables.C | 126 +++++++ .../jsonConfigs/skeleton.json | 20 ++ .../jsonConfigs/step0.json | 20 ++ .../jsonConfigs/step1.json | 25 ++ .../jsonConfigs/step2.json | 27 ++ .../jsonConfigs/step3.json | 198 +++++++++++ .../jsonConfigs/step4.json | 200 +++++++++++ .../o2physics/AnalysisV0/CMakeLists.txt | 40 +++ .../strangeness_derived_v0_skeleton.cxx | 81 +++++ .../strangeness_derived_v0_step0.cxx | 96 +++++ .../strangeness_derived_v0_step1.cxx | 158 +++++++++ .../strangeness_derived_v0_step2.cxx | 198 +++++++++++ .../strangeness_derived_v0_step3.cxx | 244 +++++++++++++ .../strangeness_derived_v0_step4.cxx | 333 ++++++++++++++++++ .../StrangenessV0s_HandsOn/runSkeleton.sh | 42 +++ .../StrangenessV0s_HandsOn/runStep0.sh | 42 +++ .../StrangenessV0s_HandsOn/runStep1.sh | 42 +++ .../StrangenessV0s_HandsOn/runStep2.sh | 42 +++ .../StrangenessV0s_HandsOn/runStep3.sh | 42 +++ .../StrangenessV0s_HandsOn/runStep4.sh | 41 +++ 22 files changed, 2136 insertions(+), 1 deletion(-) create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/checkTables.C create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step1.json create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step2.json create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step3.json create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step4.json create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/CMakeLists.txt create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step0.cxx create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step1.cxx create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step2.cxx create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step3.cxx create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step4.cxx create mode 100755 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runSkeleton.sh create mode 100755 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep0.sh create mode 100755 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep1.sh create mode 100755 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep2.sh create mode 100755 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep3.sh create mode 100755 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep4.sh diff --git a/Tutorials/PWGLF/Strangeness/CMakeLists.txt b/Tutorials/PWGLF/Strangeness/CMakeLists.txt index 6a9ca0389f0..3a2fe4d79ca 100644 --- a/Tutorials/PWGLF/Strangeness/CMakeLists.txt +++ b/Tutorials/PWGLF/Strangeness/CMakeLists.txt @@ -11,4 +11,4 @@ add_subdirectory(Original) add_subdirectory(Derived) - +add_subdirectory(StrangenessV0s_HandsOn/o2physics/AnalysisV0) diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md new file mode 100644 index 00000000000..8a727bf721a --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md @@ -0,0 +1,118 @@ +# Strangeness hands-on — V0s in pp @ √s = 5.36 TeV (derived data) + +In this hands-on session you will write an analysis task for **K0S, Λ and Λbar** on strangeness derived +data of pp collisions at 5.36 TeV, in 5 steps, starting from a skeleton. + +You will learn how to: +- use the strangeness derived data and structure your analysis task; +- reconstruct K0S, Λ and Λbar; +- apply topological, kinematic and PID (TPC and TOF) selections; +- access the MC information of the V0s to compute the efficiency. + +## Preparation + +Update O2Physics and enter the environment: + +```bash +alienv enter O2Physics/latest +which o2-analysistutorial-lf-strangeness-derived-v0-skeleton # must exist +which o2-analysistutorial-lf-strangeness-derived-v0-step0 # checkpoint +``` + +Clone this repository: + +```bash +git clone https://github.com/StrangenessV0s_HandsOn +cd StrangenessV0s_HandsOn +``` + +Download the two input files (strangeness derived data, ~<200> MB each): + +```bash +# real data -> data/AO2D.root (used by skeleton and steps 0-3) +rsync -r -u --progress USERNAME@lxplus.cern.ch:/eos/user///tutorialData/data/AO2D.root data +# Monte Carlo -> MC/AO2D.root (used by step 4, which needs the MC truth) +rsync -r -u --progress USERNAME@lxplus.cern.ch:/eos/user///tutorialData/MC/AO2D.root MC +``` + +Alternatively, download them from CERNBox links. + +The run scripts do not contain the file paths: they read them from two text files (one path per line, +relative to the repository folder or absolute): + +| File | Content | Used by | +|---|---|---| +| `input_data.txt` | `data/AO2D.root` | `runSkeleton.sh`, `runStep0-3.sh` | +| `input_MC.txt` | `MC/AO2D.root` | `runStep4.sh` | + +If you save the files elsewhere, edit these two text files. To run steps 0-3 on the MC (e.g. to compare +with data): `INPUTFILE=input_MC.txt ./runStep2.sh`. + +## How to work + +The code you will modify is the skeleton in O2Physics: +`Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx`. +The checkpoints of each step are in the same folder (`strangeness_derived_v0_stepX.cxx`). + +```bash +./runSkeleton.sh # "No problems!" must be printed +root -l results/skeleton/AnalysisResults.root +``` + +After modifying and recompiling the skeleton, run it with the configuration of a given step: + +```bash +TASK=o2-analysistutorial-lf-strangeness-derived-v0-skeleton ./runStep1.sh +``` + +Without `TASK=...` the checkpoint of the step is run: useful to compare with your results. + +| Step | What is added | Tables | What to look at | +|---|---|---|---| +| skeleton | loop over events, sel8, \|z\| < 10 cm | `StraCollisions`, `StraEvSels` | `eventSelection/hVertexZRec` | +| 0 | loop over V0s, K0S, Λ, Λbar invariant masses | `V0Cores` | `kzeroShort/hMassK0Short`, `lambda/hMassLambda` | +| 1 | topological selections (`Filter` + dynamic columns), rapidity, competing mass rejection | `V0Cores` | `hMass*Selected`, `hV0CosPA`, `hV0Radius` | +| 2 | TPC PID of the daughters (`posTrackExtra_as<>`) | `V0Extras`, `DauTrackExtras`, `DauTrackTPCPIDs` | `hNSigmaPos/NegPionFromK0s`, `hMass*Selected` | +| 3 | TOF PID optimised for secondary particles (`strangenesstofpid` task) | `V0TOFNSigmas` | `hMass*SelectedWithTOF` | +| 4 | MC truth: true reconstructed and generated V0s | `V0CoreMCLabels`, `V0MCCores`, `V0MCCollRefs` | `hPt*TrueRec`, `genParticles/hPt*Gen` | + +Step 1 selections (in `jsonConfigs/step1.json`): + +| Selection | Value | Getter | Column | +|---|---|---|---| +| DCA pos./neg. daughter to PV | > 0.06 cm | `dcapostopv()`, `dcanegtopv()` | standard | +| DCA between daughters | < 0.5 cm | `dcaV0daughters()` | standard | +| cosine of pointing angle | > 0.995 | `v0cosPA()` | **standard** in derived data | +| decay radius | > 0.9 cm | `v0radius()` | dynamic | +| rapidity | \|y\| < 0.5 | `yK0Short()`, `yLambda()` | dynamic | + +Hints for the steps: +- **Step 0**: look at the `aod::V0Cores` table in `PWGLF/DataModel/LFStrangenessTables.h` and at the getters + `.mK0Short()`, `.mLambda()`, `.mAntiLambda()`. +- **Step 1**: keep only standard V0s (`v0Type() == 1`); a `Filter` cannot cut on dynamic columns. +- **Step 2**: K0S → π⁺π⁻, Λ → pπ⁻, Λbar → p̄π⁺. You need `LFStrangenessPIDTables.h`. +- **Step 3**: look at `.positiveHasTOF()`, `.negativeHasTOF()` and `.tofNSigmaK0PiPlus()`, `.tofNSigmaLaPr()`, … in `LFStrangenessPIDTables.h`. +- **Step 4**: `has_v0MCCore()`, `v0MCCore_as()`, `.pdgCode()` with `PDG_t::kK0Short`, + `PDG_t::kLambda0`, `PDG_t::kLambda0Bar`; select only primary particles (`.isPhysicalPrimary()`). + +## Checkpoints + +- **Step 0**: peaks at ~0.497 GeV/c² (K0S) and ~1.116 GeV/c² (Λ, Λbar), already visible thanks to the derived data pre-selections. +- **Step 1**: the background is reduced. +- **Step 2**: the Nσ bands of the pions from K0S are centred at 0; the background under the Λ and Λbar peaks is further reduced. +- **Step 3**: TOF further suppresses the combinatorial background. +- **Step 4**: `hPt*TrueRec / hPt*Gen` gives the efficiency (× acceptance) as a function of pT. + +## If something does not run + +```bash +root -l -b -q "checkTables.C(\"$(cat input_data.txt)\")" # data: step 4 "CANNOT run" is expected +root -l -b -q "checkTables.C(\"$(cat input_MC.txt)\")" # MC: all steps must be ok +``` + +The macro tells you which steps can run with the file and, if a table has an old version, which converter +to use: + +```bash +CONVERTERS='o2-analysis-lf-straevselsconverter6 ${OPTION} | ' ./runStep0.sh +``` diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/checkTables.C b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/checkTables.C new file mode 100644 index 00000000000..1df2e8b869e --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/checkTables.C @@ -0,0 +1,126 @@ +// Checks which strangeness tables (and which versions) are present in a derived AO2D +// and reports which steps of the V0 tutorial (o2-analysistutorial-lf-strangeness-derived-v0-*) can run. +// +// Usage: root -l -b -q 'checkTables.C("data/AO2D.root")' or something like root -l -b -q "checkTables.C(\"$(cat input_data.txt)\")" + +#include +#include +#include +#include + +#include +#include +#include +#include + +struct RequiredTable { + std::string base; // tree name without version, e.g. "o2straevsels" + int version; // version required by the current O2Physics data model + int firstStep; // first step that uses it (-1 = skeleton) + std::string hint; // converter to use if the version in the file is older +}; + +int findVersion(TDirectory* dir, const std::string& base) +{ + int found = -1; + TIter next(dir->GetListOfKeys()); + while (TKey* key = static_cast(next())) { + TString name = key->GetName(); + name.ToLower(); + if (name == base.c_str()) { + found = std::max(found, 0); + } else if (name.BeginsWith((base + "_").c_str())) { + TString v = name(base.size() + 1, name.Length()); + if (v.IsDigit()) { + found = std::max(found, v.Atoi()); + } + } + } + return found; +} + +void checkTables(const char* fname = "data/AO2D.root") +{ + const std::vector required = { + {"o2stracollision", 0, -1, ""}, + {"o2straevsels", 6, -1, "o2-analysis-lf-straevselsconverterN (chain up to straevselsconverter6)"}, + {"o2v0core", 0, 0, ""}, + {"o2v0extra", 0, 2, ""}, + {"o2dautrackextra", 3, 2, "o2-analysis-lf-stradautracksextraconverterN (up to stradautracksextraconverter3)"}, + {"o2dautracktpcpid", 1, 2, "o2-analysis-lf-stradautrackstpcpidconverter"}, + // step 3: tables read as input by the helper task strangenesstofpid, + // not by the analysis itself: the tutorial only uses V0s + {"o2strastamps", 1, 3, "o2-analysis-lf-strastampsconverter"}, + {"o2straevtimes", 1, 3, "o2-analysis-lf-stradautrackstofpidconverter3"}, + {"o2dautracktofpid", 3, 3, "o2-analysis-lf-stradautrackstofpidconverterN (up to stradautrackstofpidconverter4)"}, + {"o2v0collref", 0, 3, ""}, + {"o2casccore", 0, 3, ""}, + {"o2cascextra", 0, 3, ""}, + {"o2casccollref", 0, 3, ""}, + // step 4: MC + {"o2v0coremclabel", 0, 4, ""}, + {"o2v0mccore", 2, 4, "o2-analysis-lf-v0coresconverter / v0coresconverter2"}, + {"o2v0mccollref", 0, 4, ""}, + {"o2stracolllabels", 0, 4, ""}, + {"o2stramccollision", 2, 4, "o2-analysis-lf-stramccollisionconverter / stramccollisionconverter2"}, + }; + + TFile* f = TFile::Open(fname); + if (!f || f->IsZombie()) { + std::cout << "Cannot open " << fname << std::endl; + return; + } + TDirectory* df = nullptr; + TIter next(f->GetListOfKeys()); + while (TKey* key = static_cast(next())) { + if (TString(key->GetName()).BeginsWith("DF_")) { + df = f->GetDirectory(key->GetName()); + break; + } + } + if (!df) { + std::cout << "No DF_* folder in " << fname << std::endl; + return; + } + + std::cout << "\nTrees in " << df->GetName() << ":\n"; + TIter nextTree(df->GetListOfKeys()); + while (TKey* key = static_cast(nextTree())) { + std::cout << " " << key->GetName() << "\n"; + } + + int firstBrokenStep = 99; // first step that cannot run, even with converters + int firstConverterStep = 99; // first step that needs converters + std::cout << "\nTables required by the tutorial:\n"; + for (const auto& t : required) { + int v = findVersion(df, t.base); + TString status = "ok"; + if (v < 0) { + status = "MISSING"; + firstBrokenStep = std::min(firstBrokenStep, t.firstStep); + } else if (v < t.version) { + status = Form("v%d < v%d required", v, t.version); + firstConverterStep = std::min(firstConverterStep, t.firstStep); + } else if (v > t.version) { + status = Form("v%d > v%d: O2Physics is older than the data, update it", v, t.version); + firstBrokenStep = std::min(firstBrokenStep, t.firstStep); + } + TString step = t.firstStep < 0 ? "skeleton" : Form("step%d", t.firstStep); + std::cout << Form(" %-20s (from %-8s) %s", t.base.c_str(), step.Data(), status.Data()); + if (status != "ok" && !t.hint.empty() && v >= 0) { + std::cout << "\n -> " << t.hint; + } + std::cout << "\n"; + } + + std::cout << "\nSummary:\n"; + for (int s = -1; s <= 4; s++) { + TString name = s < 0 ? "skeleton" : Form("step%d", s); + TString res = s >= firstBrokenStep ? "CANNOT run with this file" + : s >= firstConverterStep ? "ok, but converters are needed" + : "ok"; + std::cout << Form(" %-8s %s\n", name.Data(), res.Data()); + } + std::cout << std::endl; + f->Close(); +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json new file mode 100644 index 00000000000..a050b65a63f --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json @@ -0,0 +1,20 @@ +{ + "internal-dpl-clock": "", + "internal-dpl-aod-reader": { + "time-limit": "0", + "orbit-offset-enumeration": "0", + "orbit-multiplier-enumeration": "0", + "start-value-enumeration": "0", + "end-value-enumeration": "-1", + "step-value-enumeration": "1", + "aod-file": "@input_data.txt" + }, + "internal-dpl-aod-spawner": "", + "strangeness_derived_tutorial": { + "nBins": "100", + "cutzvertex": "10" + }, + "internal-dpl-aod-writer": "", + "internal-dpl-aod-global-analysis-file-sink": "", + "internal-dpl-injected-dummy-sink": "" +} \ No newline at end of file diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json new file mode 100644 index 00000000000..a050b65a63f --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json @@ -0,0 +1,20 @@ +{ + "internal-dpl-clock": "", + "internal-dpl-aod-reader": { + "time-limit": "0", + "orbit-offset-enumeration": "0", + "orbit-multiplier-enumeration": "0", + "start-value-enumeration": "0", + "end-value-enumeration": "-1", + "step-value-enumeration": "1", + "aod-file": "@input_data.txt" + }, + "internal-dpl-aod-spawner": "", + "strangeness_derived_tutorial": { + "nBins": "100", + "cutzvertex": "10" + }, + "internal-dpl-aod-writer": "", + "internal-dpl-aod-global-analysis-file-sink": "", + "internal-dpl-injected-dummy-sink": "" +} \ No newline at end of file diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step1.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step1.json new file mode 100644 index 00000000000..12f1baaf327 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step1.json @@ -0,0 +1,25 @@ +{ + "internal-dpl-clock": "", + "internal-dpl-aod-reader": { + "time-limit": "0", + "orbit-offset-enumeration": "0", + "orbit-multiplier-enumeration": "0", + "start-value-enumeration": "0", + "end-value-enumeration": "-1", + "step-value-enumeration": "1", + "aod-file": "@input_data.txt" + }, + "strangeness_derived_tutorial": { + "nBins": "100", + "cutzvertex": "10", + "v0setting_dcav0dau": "0.5", + "v0setting_dcapostopv": "0.06", + "v0setting_dcanegtopv": "0.06", + "v0setting_cospa": "0.995", + "v0setting_radius": "0.9", + "v0setting_rapidity": "0.5" + }, + "internal-dpl-aod-writer": "", + "internal-dpl-aod-global-analysis-file-sink": "", + "internal-dpl-injected-dummy-sink": "" +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step2.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step2.json new file mode 100644 index 00000000000..e03ccd2f520 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step2.json @@ -0,0 +1,27 @@ +{ + "internal-dpl-clock": "", + "internal-dpl-aod-reader": { + "time-limit": "0", + "orbit-offset-enumeration": "0", + "orbit-multiplier-enumeration": "0", + "start-value-enumeration": "0", + "end-value-enumeration": "-1", + "step-value-enumeration": "1", + "aod-file": "@input_data.txt" + }, + "strangeness_derived_tutorial": { + "nBins": "100", + "cutzvertex": "10", + "v0setting_dcav0dau": "0.5", + "v0setting_dcapostopv": "0.06", + "v0setting_dcanegtopv": "0.06", + "v0setting_cospa": "0.995", + "v0setting_radius": "0.9", + "v0setting_rapidity": "0.5", + "NSigmaTPCPion": "4", + "NSigmaTPCProton": "4" + }, + "internal-dpl-aod-writer": "", + "internal-dpl-aod-global-analysis-file-sink": "", + "internal-dpl-injected-dummy-sink": "" +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step3.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step3.json new file mode 100644 index 00000000000..5cfa1067bce --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step3.json @@ -0,0 +1,198 @@ +{ + "internal-dpl-clock": "", + "internal-dpl-aod-reader": { + "time-limit": "0", + "orbit-offset-enumeration": "0", + "orbit-multiplier-enumeration": "0", + "start-value-enumeration": "0", + "end-value-enumeration": "-1", + "step-value-enumeration": "1", + "aod-file": "@input_data.txt" + }, + "strangenesstofpid": { + "v0Calibration.qaMassWindow": "0.005", + "axisP": { + "values": [ + 0, + 0, + 0.10000000149011612, + 0.20000000298023224, + 0.30000001192092896, + 0.4000000059604645, + 0.5, + 0.6000000238418579, + 0.699999988079071, + 0.800000011920929, + 0.8999999761581421, + 1, + 1.100000023841858, + 1.2000000476837158, + 1.2999999523162842, + 1.399999976158142, + 1.5, + 1.600000023841858, + 1.7000000476837158, + 1.7999999523162842, + 1.899999976158142, + 2, + 2.200000047683716, + 2.4000000953674316, + 2.5999999046325684, + 2.799999952316284, + 3, + 3.200000047683716, + 3.4000000953674316, + 3.5999999046325684, + 3.799999952316284, + 4, + 4.400000095367432, + 4.800000190734863, + 5.199999809265137, + 5.599999904632568, + 6, + 6.5, + 7, + 7.5, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 17, + 19, + 21, + 23, + 25, + 30, + 35, + 40, + 50 + ] + }, + "axisRatioMethods": { + "values": [ + 400, + 0.8999999761581421, + 1.899999976158142 + ] + }, + "v0Calibration.qaCosPA": "0.999", + "rejectUndefinedTof": "1", + "v0Calibration.qaDCADau": "0.5", + "axisDeltaTime": { + "values": [ + 2000, + -1000, + 1000 + ] + }, + "ccdb.ccdb-url": "http://alice-ccdb.cern.ch", + "v0Calibration.qaTPCNSigma": "5", + "ccdb.lutPath": "GLO/Param/MatLUT", + "axisDeltaTimeVsPrimaryCalculation": { + "values": [ + 500, + -500, + 500 + ] + }, + "axisEta": { + "values": [ + 20, + -1, + 1 + ] + }, + "axisTimeLong": { + "values": [ + 3000, + -1500000, + 1500000 + ] + }, + "calculationMethod": "0", + "calculateCascades": "0", + "axisNSigma": { + "values": [ + 200, + -10, + 10 + ] + }, + "axisSmallP": { + "values": [ + 250, + 0, + 2.5 + ] + }, + "manualRunNumber": "544122", + "calculateV0TOFPIDs": "-1", + "processDerivedData": "1", + "calculateV0s": "1", + "axisBCshift": { + "values": [ + 130, + -3006569.541579235, + 237032.45348549983 + ] + }, + "doBCshift": "1", + "useCustomRunNumber": "0", + "axisPosition": { + "values": [ + 400, + -400, + 400 + ] + }, + "processStandardData": "0", + "axisTime": { + "values": [ + 400, + 10000, + 50000 + ] + }, + "calculateCascTOFPIDs": "0", + "ccdb.mVtxPath": "GLO/Calib/MeanVertex", + "calculateV0TOFDebugs": "-1", + "axisSnp": { + "values": [ + 220, + -1.100000023841858, + 1.100000023841858 + ] + }, + "ccdb.grpmagPath": "GLO/Config/GRPMagField", + "ccdb.grpPath": "GLO/GRP/GRP", + "doNSigmas": "1", + "calculateV0TOFBetas": "-1", + "reassociateTracks": "1", + "ccdb.nSigmaPath": "Users/d/ddobrigk/stratof", + "doQA": "0", + "d_bz": "-999", + "tofPosition": "377.934", + "doQANSigma": "0" + }, + "strangeness_derived_tutorial": { + "nBins": "100", + "cutzvertex": "10", + "v0setting_dcav0dau": "0.5", + "v0setting_dcapostopv": "0.06", + "v0setting_dcanegtopv": "0.06", + "v0setting_cospa": "0.995", + "v0setting_radius": "0.9", + "v0setting_rapidity": "0.5", + "NSigmaTPCPion": "4", + "NSigmaTPCProton": "4", + "NSigmaTOFPion": "3", + "NSigmaTOFProton": "3" + }, + "internal-dpl-aod-writer": "", + "internal-dpl-aod-global-analysis-file-sink": "", + "internal-dpl-injected-dummy-sink": "" +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step4.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step4.json new file mode 100644 index 00000000000..7e0aca27bc9 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step4.json @@ -0,0 +1,200 @@ +{ + "internal-dpl-clock": "", + "internal-dpl-aod-reader": { + "time-limit": "0", + "orbit-offset-enumeration": "0", + "orbit-multiplier-enumeration": "0", + "start-value-enumeration": "0", + "end-value-enumeration": "-1", + "step-value-enumeration": "1", + "aod-file": "@input_MC.txt" + }, + "strangenesstofpid": { + "v0Calibration.qaMassWindow": "0.005", + "axisP": { + "values": [ + 0, + 0, + 0.10000000149011612, + 0.20000000298023224, + 0.30000001192092896, + 0.4000000059604645, + 0.5, + 0.6000000238418579, + 0.699999988079071, + 0.800000011920929, + 0.8999999761581421, + 1, + 1.100000023841858, + 1.2000000476837158, + 1.2999999523162842, + 1.399999976158142, + 1.5, + 1.600000023841858, + 1.7000000476837158, + 1.7999999523162842, + 1.899999976158142, + 2, + 2.200000047683716, + 2.4000000953674316, + 2.5999999046325684, + 2.799999952316284, + 3, + 3.200000047683716, + 3.4000000953674316, + 3.5999999046325684, + 3.799999952316284, + 4, + 4.400000095367432, + 4.800000190734863, + 5.199999809265137, + 5.599999904632568, + 6, + 6.5, + 7, + 7.5, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 17, + 19, + 21, + 23, + 25, + 30, + 35, + 40, + 50 + ] + }, + "axisRatioMethods": { + "values": [ + 400, + 0.8999999761581421, + 1.899999976158142 + ] + }, + "v0Calibration.qaCosPA": "0.999", + "rejectUndefinedTof": "1", + "v0Calibration.qaDCADau": "0.5", + "axisDeltaTime": { + "values": [ + 2000, + -1000, + 1000 + ] + }, + "ccdb.ccdb-url": "http://alice-ccdb.cern.ch", + "v0Calibration.qaTPCNSigma": "5", + "ccdb.lutPath": "GLO/Param/MatLUT", + "axisDeltaTimeVsPrimaryCalculation": { + "values": [ + 500, + -500, + 500 + ] + }, + "axisEta": { + "values": [ + 20, + -1, + 1 + ] + }, + "axisTimeLong": { + "values": [ + 3000, + -1500000, + 1500000 + ] + }, + "calculationMethod": "0", + "calculateCascades": "0", + "axisNSigma": { + "values": [ + 200, + -10, + 10 + ] + }, + "axisSmallP": { + "values": [ + 250, + 0, + 2.5 + ] + }, + "manualRunNumber": "544122", + "calculateV0TOFPIDs": "-1", + "processDerivedData": "1", + "calculateV0s": "1", + "axisBCshift": { + "values": [ + 130, + -3006569.541579235, + 237032.45348549983 + ] + }, + "doBCshift": "1", + "useCustomRunNumber": "0", + "axisPosition": { + "values": [ + 400, + -400, + 400 + ] + }, + "processStandardData": "0", + "axisTime": { + "values": [ + 400, + 10000, + 50000 + ] + }, + "calculateCascTOFPIDs": "0", + "ccdb.mVtxPath": "GLO/Calib/MeanVertex", + "calculateV0TOFDebugs": "-1", + "axisSnp": { + "values": [ + 220, + -1.100000023841858, + 1.100000023841858 + ] + }, + "ccdb.grpmagPath": "GLO/Config/GRPMagField", + "ccdb.grpPath": "GLO/GRP/GRP", + "doNSigmas": "1", + "calculateV0TOFBetas": "-1", + "reassociateTracks": "1", + "ccdb.nSigmaPath": "Users/d/ddobrigk/stratof", + "doQA": "0", + "d_bz": "-999", + "tofPosition": "377.934", + "doQANSigma": "0" + }, + "strangeness_derived_tutorial": { + "nBins": "100", + "cutzvertex": "10", + "v0setting_dcav0dau": "0.5", + "v0setting_dcapostopv": "0.06", + "v0setting_dcanegtopv": "0.06", + "v0setting_cospa": "0.995", + "v0setting_radius": "0.9", + "v0setting_rapidity": "0.5", + "NSigmaTPCPion": "4", + "NSigmaTPCProton": "4", + "NSigmaTOFPion": "3", + "NSigmaTOFProton": "3", + "processRecMC": "1", + "processGenMC": "1" + }, + "internal-dpl-aod-writer": "", + "internal-dpl-aod-global-analysis-file-sink": "", + "internal-dpl-injected-dummy-sink": "" +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/CMakeLists.txt b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/CMakeLists.txt new file mode 100644 index 00000000000..5e598293329 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/CMakeLists.txt @@ -0,0 +1,40 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2physics_add_dpl_workflow(strangeness-derived-v0-skeleton + SOURCES strangeness_derived_v0_skeleton.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-derived-v0-step0 + SOURCES strangeness_derived_v0_step0.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-derived-v0-step1 + SOURCES strangeness_derived_v0_step1.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-derived-v0-step2 + SOURCES strangeness_derived_v0_step2.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-derived-v0-step3 + SOURCES strangeness_derived_v0_step3.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-derived-v0-step4 + SOURCES strangeness_derived_v0_step4.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx new file mode 100644 index 00000000000..1a0dc9dac15 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx @@ -0,0 +1,81 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief Skeleton of the V0 strangeness tutorial on derived data (K0S, Lambda, AntiLambda) +/// \author Sara Pucillo +/// based on the O2AT strangeness derived-data tutorial from: +/// \author Romain Schotter +/// and on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// SKELETON +// Starting point of the V0 tutorial: loop over the selected events (sel8, |z| < 10 cm) +// and fill a histogram with the z position of the primary vertex. +// Goal of the hands-on: improve this file step by step up to step 4 +// (checkpoints: strangeness_derived_v0_stepX.cxx). + +struct strangeness_derived_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + void init(InitContext const&) + { + // Axes + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + void process(soa::Filtered>::iterator const& collision) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step0.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step0.cxx new file mode 100644 index 00000000000..6915039b602 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step0.cxx @@ -0,0 +1,96 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief Step0 of the V0 strangeness tutorial on derived data (K0S, Lambda, AntiLambda) +/// \author Sara Pucillo +/// based on the O2AT strangeness derived-data tutorial from: +/// \author Romain Schotter +/// and on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 0 +// Starting point: loop over all V0s and fill invariant mass histograms + +struct strangeness_derived_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rK0Short{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda{"lambda", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + void init(InitContext const&) + { + // Axes + AxisSpec K0ShortMassAxis = {100, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec LambdaMassAxis = {100, 1.08f, 1.15f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // K0S/Lambda/AntiLambda reconstruction + rK0Short.add("hMassK0Short", "hMassK0Short", {HistType::kTH1F, {K0ShortMassAxis}}); + + rLambda.add("hMassLambda", "hMassLambda", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambda", "hMassAntiLambda", {HistType::kTH1F, {LambdaMassAxis}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + void process(soa::Filtered>::iterator const& collision, + aod::V0Cores const& V0s) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + // V0s + for (const auto& v0 : V0s) { + rK0Short.fill(HIST("hMassK0Short"), v0.mK0Short()); + rLambda.fill(HIST("hMassLambda"), v0.mLambda()); + rLambda.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step1.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step1.cxx new file mode 100644 index 00000000000..616fe730f08 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step1.cxx @@ -0,0 +1,158 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief Step1 of the V0 strangeness tutorial on derived data (K0S, Lambda, AntiLambda) +/// \author Sara Pucillo +/// based on the O2AT strangeness derived-data tutorial from: +/// \author Romain Schotter +/// and on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 0 +// Starting point: loop over all V0s and fill invariant mass histograms +// STEP 1 +// Apply selections on topological variables of V0s + +struct strangeness_derived_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rK0Short{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda{"lambda", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + // Configurable parameters for V0 selection + Configurable v0setting_dcav0dau{"v0setting_dcav0dau", 0.5, "DCA V0 daughters"}; + Configurable v0setting_dcapostopv{"v0setting_dcapostopv", 0.06, "DCA positive to PV"}; + Configurable v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.06, "DCA negative to PV"}; + Configurable v0setting_cospa{"v0setting_cospa", 0.995, "V0 CosPA"}; + Configurable v0setting_radius{"v0setting_radius", 0.9, "V0 radius"}; + Configurable v0setting_rapidity{"v0setting_rapidity", 0.5, "V0 rapidity window"}; + + void init(InitContext const&) + { + // Axes + AxisSpec K0ShortMassAxis = {100, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec LambdaMassAxis = {100, 1.08f, 1.15f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // K0S/Lambda/AntiLambda reconstruction + rK0Short.add("hMassK0Short", "hMassK0Short", {HistType::kTH1F, {K0ShortMassAxis}}); + rK0Short.add("hMassK0ShortSelected", "hMassK0ShortSelected", {HistType::kTH1F, {K0ShortMassAxis}}); + + rLambda.add("hMassLambda", "hMassLambda", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambda", "hMassAntiLambda", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassLambdaSelected", "hMassLambdaSelected", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambdaSelected", "hMassAntiLambdaSelected", {HistType::kTH1F, {LambdaMassAxis}}); + + // V0 topological variables (after selections) + rK0Short.add("hV0DCADaughters", "hV0DCADaughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rK0Short.add("hV0CosPA", "hV0CosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + rK0Short.add("hV0Radius", "hV0Radius", {HistType::kTH1F, {{100, 0.0f, 50.0f}}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + // Filters on V0s + // Cannot filter on dynamic columns + Filter preFilterV0 = (aod::v0data::dcaV0daughters < v0setting_dcav0dau && + nabs(aod::v0data::dcapostopv) > v0setting_dcapostopv && + nabs(aod::v0data::dcanegtopv) > v0setting_dcanegtopv); + + void process(soa::Filtered>::iterator const& collision, + soa::Filtered const& V0s) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + // V0s + for (const auto& v0 : V0s) { + rK0Short.fill(HIST("hMassK0Short"), v0.mK0Short()); + rLambda.fill(HIST("hMassLambda"), v0.mLambda()); + rLambda.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); + + // Keep only standard V0s (type 1): type 0 = not passing the standard V0 selections, 2-3 = photon-like (TPC-only) + if (v0.v0Type() != 1) + continue; + + // Topological selections not applied in the Filter + // (in V0Cores the cosine of pointing angle is a regular column: it could also be moved into the Filter) + if (v0.v0cosPA() < v0setting_cospa) + continue; + // Cut on dynamic columns + if (v0.v0radius() < v0setting_radius) + continue; + + // From here on, the same V0 is tested under the three mass hypotheses (K0S, Lambda, AntiLambda): + // the hypothesis-dependent selections cannot use 'continue', they are stored in booleans + + // Kinematic selection + bool isK0Short = std::abs(v0.yK0Short()) < v0setting_rapidity; + bool isLambda = std::abs(v0.yLambda()) < v0setting_rapidity; + bool isAntiLambda = std::abs(v0.yLambda()) < v0setting_rapidity; + + // Fill histograms! (if possible) + if (isK0Short) { + rK0Short.fill(HIST("hMassK0ShortSelected"), v0.mK0Short()); + + rK0Short.fill(HIST("hV0DCADaughters"), v0.dcaV0daughters()); + rK0Short.fill(HIST("hV0CosPA"), v0.v0cosPA()); + rK0Short.fill(HIST("hV0Radius"), v0.v0radius()); + } + if (isLambda) { + rLambda.fill(HIST("hMassLambdaSelected"), v0.mLambda()); + } + if (isAntiLambda) { + rLambda.fill(HIST("hMassAntiLambdaSelected"), v0.mAntiLambda()); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step2.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step2.cxx new file mode 100644 index 00000000000..aaa99080542 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step2.cxx @@ -0,0 +1,198 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief Step2 of the V0 strangeness tutorial on derived data (K0S, Lambda, AntiLambda) +/// \author Sara Pucillo +/// based on the O2AT strangeness derived-data tutorial from: +/// \author Romain Schotter +/// and on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 0 +// Starting point: loop over all V0s and fill invariant mass histograms +// STEP 1 +// Apply selections on topological variables of V0s +// STEP 2 +// Apply TPC PID selections on V0 daughter tracks + +struct strangeness_derived_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rK0Short{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda{"lambda", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + // Configurable parameters for V0 selection + Configurable v0setting_dcav0dau{"v0setting_dcav0dau", 0.5, "DCA V0 daughters"}; + Configurable v0setting_dcapostopv{"v0setting_dcapostopv", 0.06, "DCA positive to PV"}; + Configurable v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.06, "DCA negative to PV"}; + Configurable v0setting_cospa{"v0setting_cospa", 0.995, "V0 CosPA"}; + Configurable v0setting_radius{"v0setting_radius", 0.9, "V0 radius"}; + Configurable v0setting_rapidity{"v0setting_rapidity", 0.5, "V0 rapidity window"}; + + // Configurable parameters for PID selection + Configurable NSigmaTPCPion{"NSigmaTPCPion", 4, "NSigmaTPCPion"}; + Configurable NSigmaTPCProton{"NSigmaTPCProton", 4, "NSigmaTPCProton"}; + + void init(InitContext const&) + { + // Axes + AxisSpec K0ShortMassAxis = {100, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec LambdaMassAxis = {100, 1.08f, 1.15f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + AxisSpec ptAxis = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec nSigmaAxis = {100, -10.0f, 10.0f, "N#sigma_{TPC}"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // K0S/Lambda/AntiLambda reconstruction + rK0Short.add("hMassK0Short", "hMassK0Short", {HistType::kTH1F, {K0ShortMassAxis}}); + rK0Short.add("hMassK0ShortSelected", "hMassK0ShortSelected", {HistType::kTH1F, {K0ShortMassAxis}}); + + rLambda.add("hMassLambda", "hMassLambda", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambda", "hMassAntiLambda", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassLambdaSelected", "hMassLambdaSelected", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambdaSelected", "hMassAntiLambdaSelected", {HistType::kTH1F, {LambdaMassAxis}}); + + // V0 topological variables (after selections) + rK0Short.add("hV0DCADaughters", "hV0DCADaughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rK0Short.add("hV0CosPA", "hV0CosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + rK0Short.add("hV0Radius", "hV0Radius", {HistType::kTH1F, {{100, 0.0f, 50.0f}}}); + + // TPC PID of the K0S daughters, in the K0S peak region, before the PID selection + rK0Short.add("hNSigmaPosPionFromK0s", "hNSigmaPosPionFromK0s", {HistType::kTH2F, {ptAxis, nSigmaAxis}}); + rK0Short.add("hNSigmaNegPionFromK0s", "hNSigmaNegPionFromK0s", {HistType::kTH2F, {ptAxis, nSigmaAxis}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + // Filters on V0s + // Cannot filter on dynamic columns + Filter preFilterV0 = (aod::v0data::dcaV0daughters < v0setting_dcav0dau && + nabs(aod::v0data::dcapostopv) > v0setting_dcapostopv && + nabs(aod::v0data::dcanegtopv) > v0setting_dcanegtopv); + + // Defining the type of the daughter tracks + using dauTracks = soa::Join; + + void process(soa::Filtered>::iterator const& collision, + soa::Filtered> const& V0s, + dauTracks const&) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + // V0s + for (const auto& v0 : V0s) { + const auto& posDaughterTrack = v0.posTrackExtra_as(); + const auto& negDaughterTrack = v0.negTrackExtra_as(); + + rK0Short.fill(HIST("hMassK0Short"), v0.mK0Short()); + rLambda.fill(HIST("hMassLambda"), v0.mLambda()); + rLambda.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); + + // Keep only standard V0s (type 1): type 0 = not passing the standard V0 selections, 2-3 = photon-like (TPC-only) + if (v0.v0Type() != 1) + continue; + + // Topological selections not applied in the Filter + // (in V0Cores the cosine of pointing angle is a regular column: it could also be moved into the Filter) + if (v0.v0cosPA() < v0setting_cospa) + continue; + // Cut on dynamic columns + if (v0.v0radius() < v0setting_radius) + continue; + + // From here on, the same V0 is tested under the three mass hypotheses (K0S, Lambda, AntiLambda): + // the hypothesis-dependent selections cannot use 'continue', they are stored in booleans + + // Kinematic selection + bool isK0Short = std::abs(v0.yK0Short()) < v0setting_rapidity; + bool isLambda = std::abs(v0.yLambda()) < v0setting_rapidity; + bool isAntiLambda = std::abs(v0.yLambda()) < v0setting_rapidity; + + // TPC PID QA of the K0S daughters (in the K0S peak region, before the PID selection) + if (isK0Short && std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < 0.01) { + rK0Short.fill(HIST("hNSigmaPosPionFromK0s"), v0.positivept(), posDaughterTrack.tpcNSigmaPi()); + rK0Short.fill(HIST("hNSigmaNegPionFromK0s"), v0.negativept(), negDaughterTrack.tpcNSigmaPi()); + } + + // TPC PID selection + // K0S -> pi+ pi- + if (std::abs(posDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion || std::abs(negDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion) { + isK0Short = false; + } + // Lambda -> p pi- + if (std::abs(posDaughterTrack.tpcNSigmaPr()) > NSigmaTPCProton || std::abs(negDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion) { + isLambda = false; + } + // AntiLambda -> pbar pi+ + if (std::abs(posDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion || std::abs(negDaughterTrack.tpcNSigmaPr()) > NSigmaTPCProton) { + isAntiLambda = false; + } + + // Fill histograms! (if possible) + if (isK0Short) { + rK0Short.fill(HIST("hMassK0ShortSelected"), v0.mK0Short()); + + rK0Short.fill(HIST("hV0DCADaughters"), v0.dcaV0daughters()); + rK0Short.fill(HIST("hV0CosPA"), v0.v0cosPA()); + rK0Short.fill(HIST("hV0Radius"), v0.v0radius()); + } + if (isLambda) { + rLambda.fill(HIST("hMassLambdaSelected"), v0.mLambda()); + } + if (isAntiLambda) { + rLambda.fill(HIST("hMassAntiLambdaSelected"), v0.mAntiLambda()); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step3.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step3.cxx new file mode 100644 index 00000000000..bd9c4141262 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step3.cxx @@ -0,0 +1,244 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief Step3 of the V0 strangeness tutorial on derived data (K0S, Lambda, AntiLambda) +/// \author Sara Pucillo +/// based on the O2AT strangeness derived-data tutorial from: +/// \author Romain Schotter +/// and on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 0 +// Starting point: loop over all V0s and fill invariant mass histograms +// STEP 1 +// Apply selections on topological variables of V0s +// STEP 2 +// Apply TPC PID selections on V0 daughter tracks +// STEP 3 +// Apply TOF PID selections on V0 daughter tracks (if info is available) + +struct strangeness_derived_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rK0Short{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda{"lambda", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + // Configurable parameters for V0 selection + Configurable v0setting_dcav0dau{"v0setting_dcav0dau", 0.5, "DCA V0 daughters"}; + Configurable v0setting_dcapostopv{"v0setting_dcapostopv", 0.06, "DCA positive to PV"}; + Configurable v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.06, "DCA negative to PV"}; + Configurable v0setting_cospa{"v0setting_cospa", 0.995, "V0 CosPA"}; + Configurable v0setting_radius{"v0setting_radius", 0.9, "V0 radius"}; + Configurable v0setting_rapidity{"v0setting_rapidity", 0.5, "V0 rapidity window"}; + + // Configurable parameters for PID selection + Configurable NSigmaTPCPion{"NSigmaTPCPion", 4, "NSigmaTPCPion"}; + Configurable NSigmaTPCProton{"NSigmaTPCProton", 4, "NSigmaTPCProton"}; + + // Configurable parameters for TOF PID selection + Configurable NSigmaTOFPion{"NSigmaTOFPion", 3, "NSigmaTOFPion"}; + Configurable NSigmaTOFProton{"NSigmaTOFProton", 3, "NSigmaTOFProton"}; + + void init(InitContext const&) + { + // Axes + AxisSpec K0ShortMassAxis = {100, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec LambdaMassAxis = {100, 1.08f, 1.15f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + AxisSpec ptAxis = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec nSigmaAxis = {100, -10.0f, 10.0f, "N#sigma_{TPC}"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // K0S/Lambda/AntiLambda reconstruction + rK0Short.add("hMassK0Short", "hMassK0Short", {HistType::kTH1F, {K0ShortMassAxis}}); + rK0Short.add("hMassK0ShortSelected", "hMassK0ShortSelected", {HistType::kTH1F, {K0ShortMassAxis}}); + rK0Short.add("hMassK0ShortSelectedWithTOF", "hMassK0ShortSelectedWithTOF", {HistType::kTH1F, {K0ShortMassAxis}}); + + rLambda.add("hMassLambda", "hMassLambda", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambda", "hMassAntiLambda", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassLambdaSelected", "hMassLambdaSelected", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambdaSelected", "hMassAntiLambdaSelected", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassLambdaSelectedWithTOF", "hMassLambdaSelectedWithTOF", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambdaSelectedWithTOF", "hMassAntiLambdaSelectedWithTOF", {HistType::kTH1F, {LambdaMassAxis}}); + + // V0 topological variables (after selections) + rK0Short.add("hV0DCADaughters", "hV0DCADaughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rK0Short.add("hV0CosPA", "hV0CosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + rK0Short.add("hV0Radius", "hV0Radius", {HistType::kTH1F, {{100, 0.0f, 50.0f}}}); + + // TPC PID of the K0S daughters, in the K0S peak region, before the PID selection + rK0Short.add("hNSigmaPosPionFromK0s", "hNSigmaPosPionFromK0s", {HistType::kTH2F, {ptAxis, nSigmaAxis}}); + rK0Short.add("hNSigmaNegPionFromK0s", "hNSigmaNegPionFromK0s", {HistType::kTH2F, {ptAxis, nSigmaAxis}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + // Filters on V0s + // Cannot filter on dynamic columns + Filter preFilterV0 = (aod::v0data::dcaV0daughters < v0setting_dcav0dau && + nabs(aod::v0data::dcapostopv) > v0setting_dcapostopv && + nabs(aod::v0data::dcanegtopv) > v0setting_dcanegtopv); + + // Defining the type of the daughter tracks + using dauTracks = soa::Join; + + void process(soa::Filtered>::iterator const& collision, + soa::Filtered> const& V0s, + dauTracks const&) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + // V0s + for (const auto& v0 : V0s) { + const auto& posDaughterTrack = v0.posTrackExtra_as(); + const auto& negDaughterTrack = v0.negTrackExtra_as(); + + rK0Short.fill(HIST("hMassK0Short"), v0.mK0Short()); + rLambda.fill(HIST("hMassLambda"), v0.mLambda()); + rLambda.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); + + // Keep only standard V0s (type 1): type 0 = not passing the standard V0 selections, 2-3 = photon-like (TPC-only) + if (v0.v0Type() != 1) + continue; + + // Topological selections not applied in the Filter + // (in V0Cores the cosine of pointing angle is a regular column: it could also be moved into the Filter) + if (v0.v0cosPA() < v0setting_cospa) + continue; + // Cut on dynamic columns + if (v0.v0radius() < v0setting_radius) + continue; + + // From here on, the same V0 is tested under the three mass hypotheses (K0S, Lambda, AntiLambda): + // the hypothesis-dependent selections cannot use 'continue', they are stored in booleans + + // Kinematic selection + bool isK0Short = std::abs(v0.yK0Short()) < v0setting_rapidity; + bool isLambda = std::abs(v0.yLambda()) < v0setting_rapidity; + bool isAntiLambda = std::abs(v0.yLambda()) < v0setting_rapidity; + + // TPC PID QA of the K0S daughters (in the K0S peak region, before the PID selection) + if (isK0Short && std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < 0.01) { + rK0Short.fill(HIST("hNSigmaPosPionFromK0s"), v0.positivept(), posDaughterTrack.tpcNSigmaPi()); + rK0Short.fill(HIST("hNSigmaNegPionFromK0s"), v0.negativept(), negDaughterTrack.tpcNSigmaPi()); + } + + // TPC PID selection + // K0S -> pi+ pi- + if (std::abs(posDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion || std::abs(negDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion) { + isK0Short = false; + } + // Lambda -> p pi- + if (std::abs(posDaughterTrack.tpcNSigmaPr()) > NSigmaTPCProton || std::abs(negDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion) { + isLambda = false; + } + // AntiLambda -> pbar pi+ + if (std::abs(posDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion || std::abs(negDaughterTrack.tpcNSigmaPr()) > NSigmaTPCProton) { + isAntiLambda = false; + } + + // TOF PID check (applied only if the daughter has a TOF signal) + bool k0ShortPassTOFSelection = true; + bool lambdaPassTOFSelection = true; + bool antiLambdaPassTOFSelection = true; + if (v0.positiveHasTOF()) { + if (std::abs(v0.tofNSigmaK0PiPlus()) > NSigmaTOFPion) { + k0ShortPassTOFSelection &= false; + } + if (std::abs(v0.tofNSigmaLaPr()) > NSigmaTOFProton) { + lambdaPassTOFSelection &= false; + } + if (std::abs(v0.tofNSigmaALaPi()) > NSigmaTOFPion) { + antiLambdaPassTOFSelection &= false; + } + } + if (v0.negativeHasTOF()) { + if (std::abs(v0.tofNSigmaK0PiMinus()) > NSigmaTOFPion) { + k0ShortPassTOFSelection &= false; + } + if (std::abs(v0.tofNSigmaLaPi()) > NSigmaTOFPion) { + lambdaPassTOFSelection &= false; + } + if (std::abs(v0.tofNSigmaALaPr()) > NSigmaTOFProton) { + antiLambdaPassTOFSelection &= false; + } + } + // Equivalent short form: v0.tofK0ShortCompatibility(nSigma), v0.tofLambdaCompatibility(nSigma), ... + + // Fill histograms! (if possible) + if (isK0Short) { + rK0Short.fill(HIST("hMassK0ShortSelected"), v0.mK0Short()); + if (k0ShortPassTOFSelection) { + rK0Short.fill(HIST("hMassK0ShortSelectedWithTOF"), v0.mK0Short()); + } + + rK0Short.fill(HIST("hV0DCADaughters"), v0.dcaV0daughters()); + rK0Short.fill(HIST("hV0CosPA"), v0.v0cosPA()); + rK0Short.fill(HIST("hV0Radius"), v0.v0radius()); + } + if (isLambda) { + rLambda.fill(HIST("hMassLambdaSelected"), v0.mLambda()); + if (lambdaPassTOFSelection) { + rLambda.fill(HIST("hMassLambdaSelectedWithTOF"), v0.mLambda()); + } + } + if (isAntiLambda) { + rLambda.fill(HIST("hMassAntiLambdaSelected"), v0.mAntiLambda()); + if (antiLambdaPassTOFSelection) { + rLambda.fill(HIST("hMassAntiLambdaSelectedWithTOF"), v0.mAntiLambda()); + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step4.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step4.cxx new file mode 100644 index 00000000000..89525c1529e --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step4.cxx @@ -0,0 +1,333 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief Step4 of the V0 strangeness tutorial on derived data (K0S, Lambda, AntiLambda) +/// \author Sara Pucillo +/// based on the O2AT strangeness derived-data tutorial from: +/// \author Romain Schotter +/// and on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 0 +// Starting point: loop over all V0s and fill invariant mass histograms +// STEP 1 +// Apply selections on topological variables of V0s +// STEP 2 +// Apply TPC PID selections on V0 daughter tracks +// STEP 3 +// Apply TOF PID selections on V0 daughter tracks (if info is available) +// STEP 4 +// Check the MC information of the V0s + +struct strangeness_derived_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rK0Short{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda{"lambda", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rGenParticles{"genParticles", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + // Configurable parameters for V0 selection + Configurable v0setting_dcav0dau{"v0setting_dcav0dau", 0.5, "DCA V0 daughters"}; + Configurable v0setting_dcapostopv{"v0setting_dcapostopv", 0.06, "DCA positive to PV"}; + Configurable v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.06, "DCA negative to PV"}; + Configurable v0setting_cospa{"v0setting_cospa", 0.995, "V0 CosPA"}; + Configurable v0setting_radius{"v0setting_radius", 0.9, "V0 radius"}; + Configurable v0setting_rapidity{"v0setting_rapidity", 0.5, "V0 rapidity window"}; + + // Configurable parameters for PID selection + Configurable NSigmaTPCPion{"NSigmaTPCPion", 4, "NSigmaTPCPion"}; + Configurable NSigmaTPCProton{"NSigmaTPCProton", 4, "NSigmaTPCProton"}; + + // Configurable parameters for TOF PID selection + Configurable NSigmaTOFPion{"NSigmaTOFPion", 3, "NSigmaTOFPion"}; + Configurable NSigmaTOFProton{"NSigmaTOFProton", 3, "NSigmaTOFProton"}; + + void init(InitContext const&) + { + // Axes + AxisSpec K0ShortMassAxis = {100, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec LambdaMassAxis = {100, 1.08f, 1.15f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + AxisSpec ptAxis = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec nSigmaAxis = {100, -10.0f, 10.0f, "N#sigma_{TPC}"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // K0S/Lambda/AntiLambda reconstruction + rK0Short.add("hMassK0Short", "hMassK0Short", {HistType::kTH1F, {K0ShortMassAxis}}); + rK0Short.add("hMassK0ShortSelected", "hMassK0ShortSelected", {HistType::kTH1F, {K0ShortMassAxis}}); + rK0Short.add("hMassK0ShortSelectedWithTOF", "hMassK0ShortSelectedWithTOF", {HistType::kTH1F, {K0ShortMassAxis}}); + rK0Short.add("hMassK0ShortTrueRec", "hMassK0ShortTrueRec", {HistType::kTH1F, {K0ShortMassAxis}}); + rK0Short.add("hPtK0ShortTrueRec", "hPtK0ShortTrueRec", {HistType::kTH1F, {ptAxis}}); + rK0Short.add("hMassK0ShortTrueRecWithTOF", "hMassK0ShortTrueRecWithTOF", {HistType::kTH1F, {K0ShortMassAxis}}); + rK0Short.add("hPtK0ShortTrueRecWithTOF", "hPtK0ShortTrueRecWithTOF", {HistType::kTH1F, {ptAxis}}); + + rLambda.add("hMassLambda", "hMassLambda", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambda", "hMassAntiLambda", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassLambdaSelected", "hMassLambdaSelected", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambdaSelected", "hMassAntiLambdaSelected", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassLambdaSelectedWithTOF", "hMassLambdaSelectedWithTOF", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassAntiLambdaSelectedWithTOF", "hMassAntiLambdaSelectedWithTOF", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hMassLambdaTrueRec", "hMassLambdaTrueRec", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hPtLambdaTrueRec", "hPtLambdaTrueRec", {HistType::kTH1F, {ptAxis}}); + rLambda.add("hMassLambdaTrueRecWithTOF", "hMassLambdaTrueRecWithTOF", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hPtLambdaTrueRecWithTOF", "hPtLambdaTrueRecWithTOF", {HistType::kTH1F, {ptAxis}}); + rLambda.add("hMassAntiLambdaTrueRec", "hMassAntiLambdaTrueRec", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hPtAntiLambdaTrueRec", "hPtAntiLambdaTrueRec", {HistType::kTH1F, {ptAxis}}); + rLambda.add("hMassAntiLambdaTrueRecWithTOF", "hMassAntiLambdaTrueRecWithTOF", {HistType::kTH1F, {LambdaMassAxis}}); + rLambda.add("hPtAntiLambdaTrueRecWithTOF", "hPtAntiLambdaTrueRecWithTOF", {HistType::kTH1F, {ptAxis}}); + + // V0 topological variables (after selections) + rK0Short.add("hV0DCADaughters", "hV0DCADaughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rK0Short.add("hV0CosPA", "hV0CosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + rK0Short.add("hV0Radius", "hV0Radius", {HistType::kTH1F, {{100, 0.0f, 50.0f}}}); + + // TPC PID of the K0S daughters, in the K0S peak region, before the PID selection + rK0Short.add("hNSigmaPosPionFromK0s", "hNSigmaPosPionFromK0s", {HistType::kTH2F, {ptAxis, nSigmaAxis}}); + rK0Short.add("hNSigmaNegPionFromK0s", "hNSigmaNegPionFromK0s", {HistType::kTH2F, {ptAxis, nSigmaAxis}}); + + // Generated level histograms + rEventSelection.add("hVertexZGen", "hVertexZGen", {HistType::kTH1F, {vertexZAxis}}); + rGenParticles.add("hPtK0ShortGen", "hPtK0ShortGen", {HistType::kTH1F, {ptAxis}}); + rGenParticles.add("hPtLambdaGen", "hPtLambdaGen", {HistType::kTH1F, {ptAxis}}); + rGenParticles.add("hPtAntiLambdaGen", "hPtAntiLambdaGen", {HistType::kTH1F, {ptAxis}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + Filter posZFilterMC = (nabs(o2::aod::mccollision::posZ) < cutzvertex); + + // Filters on V0s + // Cannot filter on dynamic columns + Filter preFilterV0 = (aod::v0data::dcaV0daughters < v0setting_dcav0dau && + nabs(aod::v0data::dcapostopv) > v0setting_dcapostopv && + nabs(aod::v0data::dcanegtopv) > v0setting_dcanegtopv); + + // Defining the type of the daughter tracks + using dauTracks = soa::Join; + + void processRecMC(soa::Filtered>::iterator const& collision, + soa::Filtered> const& V0s, + dauTracks const&, + aod::V0MCCores const& /*v0mccores*/) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + // V0s + for (const auto& v0 : V0s) { + const auto& posDaughterTrack = v0.posTrackExtra_as(); + const auto& negDaughterTrack = v0.negTrackExtra_as(); + + rK0Short.fill(HIST("hMassK0Short"), v0.mK0Short()); + rLambda.fill(HIST("hMassLambda"), v0.mLambda()); + rLambda.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); + + // Keep only standard V0s (type 1): type 0 = not passing the standard V0 selections, 2-3 = photon-like (TPC-only) + if (v0.v0Type() != 1) + continue; + + // Topological selections not applied in the Filter + // (in V0Cores the cosine of pointing angle is a regular column: it could also be moved into the Filter) + if (v0.v0cosPA() < v0setting_cospa) + continue; + // Cut on dynamic columns + if (v0.v0radius() < v0setting_radius) + continue; + + // From here on, the same V0 is tested under the three mass hypotheses (K0S, Lambda, AntiLambda): + // the hypothesis-dependent selections cannot use 'continue', they are stored in booleans + + // Kinematic selection + bool isK0Short = std::abs(v0.yK0Short()) < v0setting_rapidity; + bool isLambda = std::abs(v0.yLambda()) < v0setting_rapidity; + bool isAntiLambda = std::abs(v0.yLambda()) < v0setting_rapidity; + + // TPC PID QA of the K0S daughters (in the K0S peak region, before the PID selection) + if (isK0Short && std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < 0.01) { + rK0Short.fill(HIST("hNSigmaPosPionFromK0s"), v0.positivept(), posDaughterTrack.tpcNSigmaPi()); + rK0Short.fill(HIST("hNSigmaNegPionFromK0s"), v0.negativept(), negDaughterTrack.tpcNSigmaPi()); + } + + // TPC PID selection + // K0S -> pi+ pi- + if (std::abs(posDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion || std::abs(negDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion) { + isK0Short = false; + } + // Lambda -> p pi- + if (std::abs(posDaughterTrack.tpcNSigmaPr()) > NSigmaTPCProton || std::abs(negDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion) { + isLambda = false; + } + // AntiLambda -> pbar pi+ + if (std::abs(posDaughterTrack.tpcNSigmaPi()) > NSigmaTPCPion || std::abs(negDaughterTrack.tpcNSigmaPr()) > NSigmaTPCProton) { + isAntiLambda = false; + } + + // TOF PID check (applied only if the daughter has a TOF signal) + bool k0ShortPassTOFSelection = true; + bool lambdaPassTOFSelection = true; + bool antiLambdaPassTOFSelection = true; + if (v0.positiveHasTOF()) { + if (std::abs(v0.tofNSigmaK0PiPlus()) > NSigmaTOFPion) { + k0ShortPassTOFSelection &= false; + } + if (std::abs(v0.tofNSigmaLaPr()) > NSigmaTOFProton) { + lambdaPassTOFSelection &= false; + } + if (std::abs(v0.tofNSigmaALaPi()) > NSigmaTOFPion) { + antiLambdaPassTOFSelection &= false; + } + } + if (v0.negativeHasTOF()) { + if (std::abs(v0.tofNSigmaK0PiMinus()) > NSigmaTOFPion) { + k0ShortPassTOFSelection &= false; + } + if (std::abs(v0.tofNSigmaLaPi()) > NSigmaTOFPion) { + lambdaPassTOFSelection &= false; + } + if (std::abs(v0.tofNSigmaALaPr()) > NSigmaTOFProton) { + antiLambdaPassTOFSelection &= false; + } + } + // Equivalent short form: v0.tofK0ShortCompatibility(nSigma), v0.tofLambdaCompatibility(nSigma), ... + + // Fill histograms! (if possible) + if (isK0Short) { + rK0Short.fill(HIST("hMassK0ShortSelected"), v0.mK0Short()); + if (k0ShortPassTOFSelection) { + rK0Short.fill(HIST("hMassK0ShortSelectedWithTOF"), v0.mK0Short()); + } + + rK0Short.fill(HIST("hV0DCADaughters"), v0.dcaV0daughters()); + rK0Short.fill(HIST("hV0CosPA"), v0.v0cosPA()); + rK0Short.fill(HIST("hV0Radius"), v0.v0radius()); + } + if (isLambda) { + rLambda.fill(HIST("hMassLambdaSelected"), v0.mLambda()); + if (lambdaPassTOFSelection) { + rLambda.fill(HIST("hMassLambdaSelectedWithTOF"), v0.mLambda()); + } + } + if (isAntiLambda) { + rLambda.fill(HIST("hMassAntiLambdaSelected"), v0.mAntiLambda()); + if (antiLambdaPassTOFSelection) { + rLambda.fill(HIST("hMassAntiLambdaSelectedWithTOF"), v0.mAntiLambda()); + } + } + + // MC truth info + if (!v0.has_v0MCCore()) { + continue; + } + auto v0mccore = v0.v0MCCore_as(); + + // Efficiency is computed for primary particles only (e.g. Lambda from Xi decays are excluded) + if (!v0mccore.isPhysicalPrimary()) { + continue; + } + + // Checking that the V0 is a true K0S / Lambda / AntiLambda + if (v0mccore.pdgCode() == PDG_t::kK0Short && isK0Short) { + rK0Short.fill(HIST("hMassK0ShortTrueRec"), v0.mK0Short()); + rK0Short.fill(HIST("hPtK0ShortTrueRec"), v0.pt()); + if (k0ShortPassTOFSelection) { + rK0Short.fill(HIST("hMassK0ShortTrueRecWithTOF"), v0.mK0Short()); + rK0Short.fill(HIST("hPtK0ShortTrueRecWithTOF"), v0.pt()); + } + } + if (v0mccore.pdgCode() == PDG_t::kLambda0 && isLambda) { + rLambda.fill(HIST("hMassLambdaTrueRec"), v0.mLambda()); + rLambda.fill(HIST("hPtLambdaTrueRec"), v0.pt()); + if (lambdaPassTOFSelection) { + rLambda.fill(HIST("hMassLambdaTrueRecWithTOF"), v0.mLambda()); + rLambda.fill(HIST("hPtLambdaTrueRecWithTOF"), v0.pt()); + } + } + if (v0mccore.pdgCode() == PDG_t::kLambda0Bar && isAntiLambda) { + rLambda.fill(HIST("hMassAntiLambdaTrueRec"), v0.mAntiLambda()); + rLambda.fill(HIST("hPtAntiLambdaTrueRec"), v0.pt()); + if (antiLambdaPassTOFSelection) { + rLambda.fill(HIST("hMassAntiLambdaTrueRecWithTOF"), v0.mAntiLambda()); + rLambda.fill(HIST("hPtAntiLambdaTrueRecWithTOF"), v0.pt()); + } + } + } + } + + void processGenMC(soa::Filtered::iterator const& mcCollision, + const soa::SmallGroups>& collisions, + const soa::SmallGroups>& v0MC) + { + if (collisions.size() < 1) // to process generated collisions that've been reconstructed at least once + return; + rEventSelection.fill(HIST("hVertexZGen"), mcCollision.posZ()); + + for (const auto& v0mc : v0MC) { + if (!v0mc.isPhysicalPrimary()) + continue; + // rapidityMC(i): i = 0 -> K0S mass hypothesis, 1 -> Lambda, 2 -> AntiLambda + if (v0mc.pdgCode() == PDG_t::kK0Short && std::abs(v0mc.rapidityMC(0)) < v0setting_rapidity) { + rGenParticles.fill(HIST("hPtK0ShortGen"), v0mc.ptMC()); + } + if (v0mc.pdgCode() == PDG_t::kLambda0 && std::abs(v0mc.rapidityMC(1)) < v0setting_rapidity) { + rGenParticles.fill(HIST("hPtLambdaGen"), v0mc.ptMC()); + } + if (v0mc.pdgCode() == PDG_t::kLambda0Bar && std::abs(v0mc.rapidityMC(2)) < v0setting_rapidity) { + rGenParticles.fill(HIST("hPtAntiLambdaGen"), v0mc.ptMC()); + } + } + } + + PROCESS_SWITCH(strangeness_derived_tutorial, processRecMC, "Process Run 3 mc, reconstructed", true); + PROCESS_SWITCH(strangeness_derived_tutorial, processGenMC, "Process Run 3 mc, generated", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runSkeleton.sh b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runSkeleton.sh new file mode 100755 index 00000000000..1bc63dc4a72 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runSkeleton.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="skeleton" +LOGFILE="log-${STEP}.txt" + +# directory of this script +DIR_THIS="$(dirname "$(realpath "$0")")" + +# run from the folder of this script, so that the relative paths in input_data.txt work +cd "$DIR_THIS" || exit 1 + +# input: text file with the list of AO2D files to analyse (one path per line) +# default: real data, input_data.txt -> data/AO2D.root +# to run this step on the MC instead: INPUTFILE=input_MC.txt ./runSkeleton.sh +INPUTFILE="${INPUTFILE:-input_data.txt}" + +# Task to run. Default: the checkpoint of this step. +# To run YOUR code (the skeleton you are modifying) with the configuration of this step: +# TASK=o2-analysistutorial-lf-strangeness-derived-v0-skeleton ./runSkeleton.sh +TASK="${TASK:-o2-analysistutorial-lf-strangeness-derived-v0-skeleton}" + +OPTION="-b --configuration json://$DIR_THIS/jsonConfigs/$STEP.json" + +# If checkTables.C reports old table versions, prepend the suggested converters, e.g.: +# CONVERTERS='o2-analysis-lf-straevselsconverter6 ${OPTION} | ' ./runSkeleton.sh +CONVERTERS="${CONVERTERS:-}" +WORKFLOW="${TASK} ${OPTION}" + +eval "${CONVERTERS}${WORKFLOW} --aod-file @${INPUTFILE}" > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "$DIR_THIS/results/$STEP" + mv "AnalysisResults.root" "$DIR_THIS/results/$STEP/AnalysisResults.root" + mv "dpl-config.json" "$DIR_THIS/results/$STEP/dpl-config-$STEP.json" +else + echo "Error: Exit code $rc" + echo "Check the log file $LOGFILE" + exit $rc +fi diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep0.sh b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep0.sh new file mode 100755 index 00000000000..6b4acd5b7b1 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep0.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="step0" +LOGFILE="log-${STEP}.txt" + +# directory of this script +DIR_THIS="$(dirname "$(realpath "$0")")" + +# run from the folder of this script, so that the relative paths in input_data.txt work +cd "$DIR_THIS" || exit 1 + +# input: text file with the list of AO2D files to analyse (one path per line) +# default: real data, input_data.txt -> data/AO2D.root +# to run this step on the MC instead: INPUTFILE=input_MC.txt ./runStep0.sh +INPUTFILE="${INPUTFILE:-input_data.txt}" + +# Task to run. Default: the checkpoint of this step. +# To run YOUR code (the skeleton you are modifying) with the configuration of this step: +# TASK=o2-analysistutorial-lf-strangeness-derived-v0-skeleton ./runStep0.sh +TASK="${TASK:-o2-analysistutorial-lf-strangeness-derived-v0-step0}" + +OPTION="-b --configuration json://$DIR_THIS/jsonConfigs/$STEP.json" + +# If checkTables.C reports old table versions, prepend the suggested converters, e.g.: +# CONVERTERS='o2-analysis-lf-straevselsconverter6 ${OPTION} | ' ./runStep0.sh +CONVERTERS="${CONVERTERS:-}" +WORKFLOW="${TASK} ${OPTION}" + +eval "${CONVERTERS}${WORKFLOW} --aod-file @${INPUTFILE}" > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "$DIR_THIS/results/$STEP" + mv "AnalysisResults.root" "$DIR_THIS/results/$STEP/AnalysisResults.root" + mv "dpl-config.json" "$DIR_THIS/results/$STEP/dpl-config-$STEP.json" +else + echo "Error: Exit code $rc" + echo "Check the log file $LOGFILE" + exit $rc +fi diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep1.sh b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep1.sh new file mode 100755 index 00000000000..7f7bdd77e44 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep1.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="step1" +LOGFILE="log-${STEP}.txt" + +# directory of this script +DIR_THIS="$(dirname "$(realpath "$0")")" + +# run from the folder of this script, so that the relative paths in input_data.txt work +cd "$DIR_THIS" || exit 1 + +# input: text file with the list of AO2D files to analyse (one path per line) +# default: real data, input_data.txt -> data/AO2D.root +# to run this step on the MC instead: INPUTFILE=input_MC.txt ./runStep1.sh +INPUTFILE="${INPUTFILE:-input_data.txt}" + +# Task to run. Default: the checkpoint of this step. +# To run YOUR code (the skeleton you are modifying) with the configuration of this step: +# TASK=o2-analysistutorial-lf-strangeness-derived-v0-skeleton ./runStep1.sh +TASK="${TASK:-o2-analysistutorial-lf-strangeness-derived-v0-step1}" + +OPTION="-b --configuration json://$DIR_THIS/jsonConfigs/$STEP.json" + +# If checkTables.C reports old table versions, prepend the suggested converters, e.g.: +# CONVERTERS='o2-analysis-lf-straevselsconverter6 ${OPTION} | ' ./runStep1.sh +CONVERTERS="${CONVERTERS:-}" +WORKFLOW="${TASK} ${OPTION}" + +eval "${CONVERTERS}${WORKFLOW} --aod-file @${INPUTFILE}" > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "$DIR_THIS/results/$STEP" + mv "AnalysisResults.root" "$DIR_THIS/results/$STEP/AnalysisResults.root" + mv "dpl-config.json" "$DIR_THIS/results/$STEP/dpl-config-$STEP.json" +else + echo "Error: Exit code $rc" + echo "Check the log file $LOGFILE" + exit $rc +fi diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep2.sh b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep2.sh new file mode 100755 index 00000000000..320c60bdf30 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep2.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="step2" +LOGFILE="log-${STEP}.txt" + +# directory of this script +DIR_THIS="$(dirname "$(realpath "$0")")" + +# run from the folder of this script, so that the relative paths in input_data.txt work +cd "$DIR_THIS" || exit 1 + +# input: text file with the list of AO2D files to analyse (one path per line) +# default: real data, input_data.txt -> data/AO2D.root +# to run this step on the MC instead: INPUTFILE=input_MC.txt ./runStep2.sh +INPUTFILE="${INPUTFILE:-input_data.txt}" + +# Task to run. Default: the checkpoint of this step. +# To run YOUR code (the skeleton you are modifying) with the configuration of this step: +# TASK=o2-analysistutorial-lf-strangeness-derived-v0-skeleton ./runStep2.sh +TASK="${TASK:-o2-analysistutorial-lf-strangeness-derived-v0-step2}" + +OPTION="-b --configuration json://$DIR_THIS/jsonConfigs/$STEP.json" + +# If checkTables.C reports old table versions, prepend the suggested converters, e.g.: +# CONVERTERS='o2-analysis-lf-straevselsconverter6 ${OPTION} | ' ./runStep2.sh +CONVERTERS="${CONVERTERS:-}" +WORKFLOW="${TASK} ${OPTION}" + +eval "${CONVERTERS}${WORKFLOW} --aod-file @${INPUTFILE}" > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "$DIR_THIS/results/$STEP" + mv "AnalysisResults.root" "$DIR_THIS/results/$STEP/AnalysisResults.root" + mv "dpl-config.json" "$DIR_THIS/results/$STEP/dpl-config-$STEP.json" +else + echo "Error: Exit code $rc" + echo "Check the log file $LOGFILE" + exit $rc +fi diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep3.sh b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep3.sh new file mode 100755 index 00000000000..f2dab308652 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep3.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="step3" +LOGFILE="log-${STEP}.txt" + +# directory of this script +DIR_THIS="$(dirname "$(realpath "$0")")" + +# run from the folder of this script, so that the relative paths in input_data.txt work +cd "$DIR_THIS" || exit 1 + +# input: text file with the list of AO2D files to analyse (one path per line) +# default: real data, input_data.txt -> data/AO2D.root +# to run this step on the MC instead: INPUTFILE=input_MC.txt ./runStep3.sh +INPUTFILE="${INPUTFILE:-input_data.txt}" + +# Task to run. Default: the checkpoint of this step. +# To run YOUR code (the skeleton you are modifying) with the configuration of this step: +# TASK=o2-analysistutorial-lf-strangeness-derived-v0-skeleton ./runStep3.sh +TASK="${TASK:-o2-analysistutorial-lf-strangeness-derived-v0-step3}" + +OPTION="-b --configuration json://$DIR_THIS/jsonConfigs/$STEP.json" + +# If checkTables.C reports old table versions, prepend the suggested converters, e.g.: +# CONVERTERS='o2-analysis-lf-straevselsconverter6 ${OPTION} | ' ./runStep3.sh +CONVERTERS="${CONVERTERS:-}" +WORKFLOW="o2-analysis-lf-strangenesstofpid ${OPTION} | ${TASK} ${OPTION}" + +eval "${CONVERTERS}${WORKFLOW} --aod-file @${INPUTFILE}" > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "$DIR_THIS/results/$STEP" + mv "AnalysisResults.root" "$DIR_THIS/results/$STEP/AnalysisResults.root" + mv "dpl-config.json" "$DIR_THIS/results/$STEP/dpl-config-$STEP.json" +else + echo "Error: Exit code $rc" + echo "Check the log file $LOGFILE" + exit $rc +fi diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep4.sh b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep4.sh new file mode 100755 index 00000000000..a619a856b91 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep4.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="step4" +LOGFILE="log-${STEP}.txt" + +# directory of this script +DIR_THIS="$(dirname "$(realpath "$0")")" + +# run from the folder of this script, so that the relative paths in input_data.txt work +cd "$DIR_THIS" || exit 1 + +# input: text file with the list of AO2D files to analyse (one path per line) +# step 4 needs the MC truth: default input_MC.txt -> MC/AO2D.root +INPUTFILE="${INPUTFILE:-input_MC.txt}" + +# Task to run. Default: the checkpoint of this step. +# To run YOUR code (the skeleton you are modifying) with the configuration of this step: +# TASK=o2-analysistutorial-lf-strangeness-derived-v0-skeleton ./runStep4.sh +TASK="${TASK:-o2-analysistutorial-lf-strangeness-derived-v0-step4}" + +OPTION="-b --configuration json://$DIR_THIS/jsonConfigs/$STEP.json" + +# If checkTables.C reports old table versions, prepend the suggested converters, e.g.: +# CONVERTERS='o2-analysis-lf-straevselsconverter6 ${OPTION} | ' ./runStep4.sh +CONVERTERS="${CONVERTERS:-}" +WORKFLOW="o2-analysis-lf-strangenesstofpid ${OPTION} | ${TASK} ${OPTION}" + +eval "${CONVERTERS}${WORKFLOW} --aod-file @${INPUTFILE}" > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "$DIR_THIS/results/$STEP" + mv "AnalysisResults.root" "$DIR_THIS/results/$STEP/AnalysisResults.root" + mv "dpl-config.json" "$DIR_THIS/results/$STEP/dpl-config-$STEP.json" +else + echo "Error: Exit code $rc" + echo "Check the log file $LOGFILE" + exit $rc +fi From ce9f4e747558d46d5d1be30d4bcc20e1459d8081 Mon Sep 17 00:00:00 2001 From: Sara Pucillo Date: Fri, 13 Nov 2026 20:02:02 +0100 Subject: [PATCH 2/7] Fix MegaLinter errors --- .../StrangenessV0s_HandsOn/checkTables.C | 71 +++++++++++-------- .../StrangenessV0s_HandsOn/input_MC.txt | 1 + .../StrangenessV0s_HandsOn/input_data.txt | 1 + .../jsonConfigs/skeleton.json | 2 +- .../jsonConfigs/step0.json | 2 +- .../jsonConfigs/step1.json | 2 +- .../jsonConfigs/step2.json | 2 +- .../jsonConfigs/step3.json | 2 +- .../jsonConfigs/step4.json | 2 +- .../strangeness_derived_v0_skeleton.cxx | 4 +- .../strangeness_derived_v0_step0.cxx | 4 +- .../strangeness_derived_v0_step1.cxx | 16 ++--- .../strangeness_derived_v0_step2.cxx | 14 ++-- .../strangeness_derived_v0_step3.cxx | 14 ++-- .../strangeness_derived_v0_step4.cxx | 25 ++++--- 15 files changed, 92 insertions(+), 70 deletions(-) create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_MC.txt create mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_data.txt diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/checkTables.C b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/checkTables.C index 1df2e8b869e..26372504761 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/checkTables.C +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/checkTables.C @@ -1,8 +1,21 @@ -// Checks which strangeness tables (and which versions) are present in a derived AO2D -// and reports which steps of the V0 tutorial (o2-analysistutorial-lf-strangeness-derived-v0-*) can run. +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. // -// Usage: root -l -b -q 'checkTables.C("data/AO2D.root")' or something like root -l -b -q "checkTables.C(\"$(cat input_data.txt)\")" +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file checkTables.C +/// \brief Checks which strangeness tables (and which versions) are present in a derived AO2D +/// and reports which steps of the V0 tutorial (o2-analysistutorial-lf-strangeness-derived-v0-*) can run. +/// +/// Usage: root -l -b -q 'checkTables.C("data/AO2D.root")' or something like root -l -b -q "checkTables.C(\"$(cat input_data.txt)\")" +#include #include #include #include @@ -14,17 +27,17 @@ #include struct RequiredTable { - std::string base; // tree name without version, e.g. "o2straevsels" - int version; // version required by the current O2Physics data model - int firstStep; // first step that uses it (-1 = skeleton) - std::string hint; // converter to use if the version in the file is older + std::string base; // tree name without version, e.g. "o2straevsels" + int version{0}; // version required by the current O2Physics data model + int firstStep{-1}; // first step that uses it (-1 = skeleton) + std::string hint; // converter to use if the version in the file is older }; int findVersion(TDirectory* dir, const std::string& base) { int found = -1; TIter next(dir->GetListOfKeys()); - while (TKey* key = static_cast(next())) { + while (TKey* key = dynamic_cast(next())) { TString name = key->GetName(); name.ToLower(); if (name == base.c_str()) { @@ -42,27 +55,27 @@ int findVersion(TDirectory* dir, const std::string& base) void checkTables(const char* fname = "data/AO2D.root") { const std::vector required = { - {"o2stracollision", 0, -1, ""}, - {"o2straevsels", 6, -1, "o2-analysis-lf-straevselsconverterN (chain up to straevselsconverter6)"}, - {"o2v0core", 0, 0, ""}, - {"o2v0extra", 0, 2, ""}, - {"o2dautrackextra", 3, 2, "o2-analysis-lf-stradautracksextraconverterN (up to stradautracksextraconverter3)"}, - {"o2dautracktpcpid", 1, 2, "o2-analysis-lf-stradautrackstpcpidconverter"}, + {.base = "o2stracollision", .version = 0, .firstStep = -1, .hint = ""}, + {.base = "o2straevsels", .version = 6, .firstStep = -1, .hint = "o2-analysis-lf-straevselsconverterN (chain up to straevselsconverter6)"}, + {.base = "o2v0core", .version = 0, .firstStep = 0, .hint = ""}, + {.base = "o2v0extra", .version = 0, .firstStep = 2, .hint = ""}, + {.base = "o2dautrackextra", .version = 3, .firstStep = 2, .hint = "o2-analysis-lf-stradautracksextraconverterN (up to stradautracksextraconverter3)"}, + {.base = "o2dautracktpcpid", .version = 1, .firstStep = 2, .hint = "o2-analysis-lf-stradautrackstpcpidconverter"}, // step 3: tables read as input by the helper task strangenesstofpid, // not by the analysis itself: the tutorial only uses V0s - {"o2strastamps", 1, 3, "o2-analysis-lf-strastampsconverter"}, - {"o2straevtimes", 1, 3, "o2-analysis-lf-stradautrackstofpidconverter3"}, - {"o2dautracktofpid", 3, 3, "o2-analysis-lf-stradautrackstofpidconverterN (up to stradautrackstofpidconverter4)"}, - {"o2v0collref", 0, 3, ""}, - {"o2casccore", 0, 3, ""}, - {"o2cascextra", 0, 3, ""}, - {"o2casccollref", 0, 3, ""}, + {.base = "o2strastamps", .version = 1, .firstStep = 3, .hint = "o2-analysis-lf-strastampsconverter"}, + {.base = "o2straevtimes", .version = 1, .firstStep = 3, .hint = "o2-analysis-lf-stradautrackstofpidconverter3"}, + {.base = "o2dautracktofpid", .version = 3, .firstStep = 3, .hint = "o2-analysis-lf-stradautrackstofpidconverterN (up to stradautrackstofpidconverter4)"}, + {.base = "o2v0collref", .version = 0, .firstStep = 3, .hint = ""}, + {.base = "o2casccore", .version = 0, .firstStep = 3, .hint = ""}, + {.base = "o2cascextra", .version = 0, .firstStep = 3, .hint = ""}, + {.base = "o2casccollref", .version = 0, .firstStep = 3, .hint = ""}, // step 4: MC - {"o2v0coremclabel", 0, 4, ""}, - {"o2v0mccore", 2, 4, "o2-analysis-lf-v0coresconverter / v0coresconverter2"}, - {"o2v0mccollref", 0, 4, ""}, - {"o2stracolllabels", 0, 4, ""}, - {"o2stramccollision", 2, 4, "o2-analysis-lf-stramccollisionconverter / stramccollisionconverter2"}, + {.base = "o2v0coremclabel", .version = 0, .firstStep = 4, .hint = ""}, + {.base = "o2v0mccore", .version = 2, .firstStep = 4, .hint = "o2-analysis-lf-v0coresconverter / v0coresconverter2"}, + {.base = "o2v0mccollref", .version = 0, .firstStep = 4, .hint = ""}, + {.base = "o2stracolllabels", .version = 0, .firstStep = 4, .hint = ""}, + {.base = "o2stramccollision", .version = 2, .firstStep = 4, .hint = "o2-analysis-lf-stramccollisionconverter / stramccollisionconverter2"}, }; TFile* f = TFile::Open(fname); @@ -72,7 +85,7 @@ void checkTables(const char* fname = "data/AO2D.root") } TDirectory* df = nullptr; TIter next(f->GetListOfKeys()); - while (TKey* key = static_cast(next())) { + while (TKey* key = dynamic_cast(next())) { if (TString(key->GetName()).BeginsWith("DF_")) { df = f->GetDirectory(key->GetName()); break; @@ -85,7 +98,7 @@ void checkTables(const char* fname = "data/AO2D.root") std::cout << "\nTrees in " << df->GetName() << ":\n"; TIter nextTree(df->GetListOfKeys()); - while (TKey* key = static_cast(nextTree())) { + while (TKey* key = dynamic_cast(nextTree())) { std::cout << " " << key->GetName() << "\n"; } @@ -116,7 +129,7 @@ void checkTables(const char* fname = "data/AO2D.root") std::cout << "\nSummary:\n"; for (int s = -1; s <= 4; s++) { TString name = s < 0 ? "skeleton" : Form("step%d", s); - TString res = s >= firstBrokenStep ? "CANNOT run with this file" + TString res = s >= firstBrokenStep ? "CANNOT run with this file" : s >= firstConverterStep ? "ok, but converters are needed" : "ok"; std::cout << Form(" %-8s %s\n", name.Data(), res.Data()); diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_MC.txt b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_MC.txt new file mode 100644 index 00000000000..900ccbc2fc1 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_MC.txt @@ -0,0 +1 @@ +file:///eos/user/s/spucillo/O2AT6_tutorial/MC/AO2D.root diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_data.txt b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_data.txt new file mode 100644 index 00000000000..9eff51ed538 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_data.txt @@ -0,0 +1 @@ +file:///eos/user/s/spucillo/O2AT6_tutorial/data/AO2D.root diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json index a050b65a63f..36bb5ccd936 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json @@ -10,7 +10,7 @@ "aod-file": "@input_data.txt" }, "internal-dpl-aod-spawner": "", - "strangeness_derived_tutorial": { + "strangeness-derived-v0-tutorial": { "nBins": "100", "cutzvertex": "10" }, diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json index a050b65a63f..36bb5ccd936 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json @@ -10,7 +10,7 @@ "aod-file": "@input_data.txt" }, "internal-dpl-aod-spawner": "", - "strangeness_derived_tutorial": { + "strangeness-derived-v0-tutorial": { "nBins": "100", "cutzvertex": "10" }, diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step1.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step1.json index 12f1baaf327..95faf947a1b 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step1.json +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step1.json @@ -9,7 +9,7 @@ "step-value-enumeration": "1", "aod-file": "@input_data.txt" }, - "strangeness_derived_tutorial": { + "strangeness-derived-v0-tutorial": { "nBins": "100", "cutzvertex": "10", "v0setting_dcav0dau": "0.5", diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step2.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step2.json index e03ccd2f520..19301322340 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step2.json +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step2.json @@ -9,7 +9,7 @@ "step-value-enumeration": "1", "aod-file": "@input_data.txt" }, - "strangeness_derived_tutorial": { + "strangeness-derived-v0-tutorial": { "nBins": "100", "cutzvertex": "10", "v0setting_dcav0dau": "0.5", diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step3.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step3.json index 5cfa1067bce..171bb1cf638 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step3.json +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step3.json @@ -178,7 +178,7 @@ "tofPosition": "377.934", "doQANSigma": "0" }, - "strangeness_derived_tutorial": { + "strangeness-derived-v0-tutorial": { "nBins": "100", "cutzvertex": "10", "v0setting_dcav0dau": "0.5", diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step4.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step4.json index 7e0aca27bc9..94a48da0c81 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step4.json +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step4.json @@ -178,7 +178,7 @@ "tofPosition": "377.934", "doQANSigma": "0" }, - "strangeness_derived_tutorial": { + "strangeness-derived-v0-tutorial": { "nBins": "100", "cutzvertex": "10", "v0setting_dcav0dau": "0.5", diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx index 1a0dc9dac15..bcb1d62db4d 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx @@ -42,7 +42,7 @@ using namespace o2::framework::expressions; // Goal of the hands-on: improve this file step by step up to step 4 // (checkpoints: strangeness_derived_v0_stepX.cxx). -struct strangeness_derived_tutorial { +struct StrangenessDerivedV0Skeleton { // Histograms are defined with HistogramRegistry HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -77,5 +77,5 @@ struct strangeness_derived_tutorial { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc, TaskName{"strangeness-derived-v0-tutorial"})}; } diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step0.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step0.cxx index 6915039b602..91839e54a54 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step0.cxx +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step0.cxx @@ -39,7 +39,7 @@ using namespace o2::framework::expressions; // STEP 0 // Starting point: loop over all V0s and fill invariant mass histograms -struct strangeness_derived_tutorial { +struct StrangenessDerivedV0Step0 { // Histograms are defined with HistogramRegistry HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rK0Short{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -92,5 +92,5 @@ struct strangeness_derived_tutorial { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc, TaskName{"strangeness-derived-v0-tutorial"})}; } diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step1.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step1.cxx index 616fe730f08..09d7e29eb72 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step1.cxx +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step1.cxx @@ -21,7 +21,6 @@ #include "Common/DataModel/EventSelection.h" -#include #include #include #include @@ -44,7 +43,7 @@ using namespace o2::framework::expressions; // STEP 1 // Apply selections on topological variables of V0s -struct strangeness_derived_tutorial { +struct StrangenessDerivedV0Step1 { // Histograms are defined with HistogramRegistry HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rK0Short{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -114,17 +113,18 @@ struct strangeness_derived_tutorial { rLambda.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); // Keep only standard V0s (type 1): type 0 = not passing the standard V0 selections, 2-3 = photon-like (TPC-only) - if (v0.v0Type() != 1) + if (v0.v0Type() != 1) { continue; - + } // Topological selections not applied in the Filter // (in V0Cores the cosine of pointing angle is a regular column: it could also be moved into the Filter) - if (v0.v0cosPA() < v0setting_cospa) + if (v0.v0cosPA() < v0setting_cospa) { continue; + } // Cut on dynamic columns - if (v0.v0radius() < v0setting_radius) + if (v0.v0radius() < v0setting_radius) { continue; - + } // From here on, the same V0 is tested under the three mass hypotheses (K0S, Lambda, AntiLambda): // the hypothesis-dependent selections cannot use 'continue', they are stored in booleans @@ -154,5 +154,5 @@ struct strangeness_derived_tutorial { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc, TaskName{"strangeness-derived-v0-tutorial"})}; } diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step2.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step2.cxx index aaa99080542..18f2e22ecf8 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step2.cxx +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step2.cxx @@ -47,7 +47,7 @@ using namespace o2::framework::expressions; // STEP 2 // Apply TPC PID selections on V0 daughter tracks -struct strangeness_derived_tutorial { +struct StrangenessDerivedV0Step2 { // Histograms are defined with HistogramRegistry HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rK0Short{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -134,16 +134,18 @@ struct strangeness_derived_tutorial { rLambda.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); // Keep only standard V0s (type 1): type 0 = not passing the standard V0 selections, 2-3 = photon-like (TPC-only) - if (v0.v0Type() != 1) + if (v0.v0Type() != 1) { continue; - + } // Topological selections not applied in the Filter // (in V0Cores the cosine of pointing angle is a regular column: it could also be moved into the Filter) - if (v0.v0cosPA() < v0setting_cospa) + if (v0.v0cosPA() < v0setting_cospa) { continue; + } // Cut on dynamic columns - if (v0.v0radius() < v0setting_radius) + if (v0.v0radius() < v0setting_radius) { continue; + } // From here on, the same V0 is tested under the three mass hypotheses (K0S, Lambda, AntiLambda): // the hypothesis-dependent selections cannot use 'continue', they are stored in booleans @@ -194,5 +196,5 @@ struct strangeness_derived_tutorial { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc, TaskName{"strangeness-derived-v0-tutorial"})}; } diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step3.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step3.cxx index bd9c4141262..5ac5ed34f86 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step3.cxx +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step3.cxx @@ -49,7 +49,7 @@ using namespace o2::framework::expressions; // STEP 3 // Apply TOF PID selections on V0 daughter tracks (if info is available) -struct strangeness_derived_tutorial { +struct StrangenessDerivedV0Step3 { // Histograms are defined with HistogramRegistry HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rK0Short{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -143,16 +143,18 @@ struct strangeness_derived_tutorial { rLambda.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); // Keep only standard V0s (type 1): type 0 = not passing the standard V0 selections, 2-3 = photon-like (TPC-only) - if (v0.v0Type() != 1) + if (v0.v0Type() != 1) { continue; - + } // Topological selections not applied in the Filter // (in V0Cores the cosine of pointing angle is a regular column: it could also be moved into the Filter) - if (v0.v0cosPA() < v0setting_cospa) + if (v0.v0cosPA() < v0setting_cospa) { continue; + } // Cut on dynamic columns - if (v0.v0radius() < v0setting_radius) + if (v0.v0radius() < v0setting_radius) { continue; + } // From here on, the same V0 is tested under the three mass hypotheses (K0S, Lambda, AntiLambda): // the hypothesis-dependent selections cannot use 'continue', they are stored in booleans @@ -240,5 +242,5 @@ struct strangeness_derived_tutorial { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc, TaskName{"strangeness-derived-v0-tutorial"})}; } diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step4.cxx b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step4.cxx index 89525c1529e..e602921b6df 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step4.cxx +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step4.cxx @@ -53,7 +53,7 @@ using namespace o2::framework::expressions; // STEP 4 // Check the MC information of the V0s -struct strangeness_derived_tutorial { +struct StrangenessDerivedV0Step4 { // Histograms are defined with HistogramRegistry HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rK0Short{"kzeroShort", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -168,17 +168,18 @@ struct strangeness_derived_tutorial { rLambda.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); // Keep only standard V0s (type 1): type 0 = not passing the standard V0 selections, 2-3 = photon-like (TPC-only) - if (v0.v0Type() != 1) + if (v0.v0Type() != 1) { continue; - + } // Topological selections not applied in the Filter // (in V0Cores the cosine of pointing angle is a regular column: it could also be moved into the Filter) - if (v0.v0cosPA() < v0setting_cospa) + if (v0.v0cosPA() < v0setting_cospa) { continue; + } // Cut on dynamic columns - if (v0.v0radius() < v0setting_radius) + if (v0.v0radius() < v0setting_radius) { continue; - + } // From here on, the same V0 is tested under the three mass hypotheses (K0S, Lambda, AntiLambda): // the hypothesis-dependent selections cannot use 'continue', they are stored in booleans @@ -302,13 +303,15 @@ struct strangeness_derived_tutorial { const soa::SmallGroups>& collisions, const soa::SmallGroups>& v0MC) { - if (collisions.size() < 1) // to process generated collisions that've been reconstructed at least once + if (collisions.size() < 1) { // to process generated collisions that've been reconstructed at least once return; + } rEventSelection.fill(HIST("hVertexZGen"), mcCollision.posZ()); for (const auto& v0mc : v0MC) { - if (!v0mc.isPhysicalPrimary()) + if (!v0mc.isPhysicalPrimary()) { continue; + } // rapidityMC(i): i = 0 -> K0S mass hypothesis, 1 -> Lambda, 2 -> AntiLambda if (v0mc.pdgCode() == PDG_t::kK0Short && std::abs(v0mc.rapidityMC(0)) < v0setting_rapidity) { rGenParticles.fill(HIST("hPtK0ShortGen"), v0mc.ptMC()); @@ -322,12 +325,12 @@ struct strangeness_derived_tutorial { } } - PROCESS_SWITCH(strangeness_derived_tutorial, processRecMC, "Process Run 3 mc, reconstructed", true); - PROCESS_SWITCH(strangeness_derived_tutorial, processGenMC, "Process Run 3 mc, generated", true); + PROCESS_SWITCH(StrangenessDerivedV0Step4, processRecMC, "Process Run 3 mc, reconstructed", true); + PROCESS_SWITCH(StrangenessDerivedV0Step4, processGenMC, "Process Run 3 mc, generated", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc, TaskName{"strangeness-derived-v0-tutorial"})}; } From c5654fd27d7b32f77f9f6cc12733b3eebf1438d9 Mon Sep 17 00:00:00 2001 From: spucillo <93769017+spucillo@users.noreply.github.com> Date: Fri, 13 Nov 2026 20:06:34 +0100 Subject: [PATCH 3/7] Update skeleton.json --- .../StrangenessV0s_HandsOn/jsonConfigs/skeleton.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json index 36bb5ccd936..d1b05b7f975 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json @@ -17,4 +17,4 @@ "internal-dpl-aod-writer": "", "internal-dpl-aod-global-analysis-file-sink": "", "internal-dpl-injected-dummy-sink": "" -} \ No newline at end of file +} From 5d5451d5193c15f615a2a43331764c9453fd6cbd Mon Sep 17 00:00:00 2001 From: spucillo <93769017+spucillo@users.noreply.github.com> Date: Fri, 13 Nov 2026 20:06:55 +0100 Subject: [PATCH 4/7] Update step0.json --- .../Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json index 36bb5ccd936..d1b05b7f975 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json @@ -17,4 +17,4 @@ "internal-dpl-aod-writer": "", "internal-dpl-aod-global-analysis-file-sink": "", "internal-dpl-injected-dummy-sink": "" -} \ No newline at end of file +} From 1132b4da9364057631649f84ff77eaba8d7dffda Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 13 Nov 2026 19:12:32 +0000 Subject: [PATCH 5/7] MegaLinter fixes --- .../StrangenessV0s_HandsOn/README.md | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md index 8a727bf721a..8b87bd5cae4 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md +++ b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md @@ -40,10 +40,10 @@ Alternatively, download them from CERNBox links. The run scripts do not contain the file paths: they read them from two text files (one path per line, relative to the repository folder or absolute): -| File | Content | Used by | -|---|---|---| +| File | Content | Used by | +|------------------|------------------|-----------------------------------| | `input_data.txt` | `data/AO2D.root` | `runSkeleton.sh`, `runStep0-3.sh` | -| `input_MC.txt` | `MC/AO2D.root` | `runStep4.sh` | +| `input_MC.txt` | `MC/AO2D.root` | `runStep4.sh` | If you save the files elsewhere, edit these two text files. To run steps 0-3 on the MC (e.g. to compare with data): `INPUTFILE=input_MC.txt ./runStep2.sh`. @@ -67,24 +67,24 @@ TASK=o2-analysistutorial-lf-strangeness-derived-v0-skeleton ./runStep1.sh Without `TASK=...` the checkpoint of the step is run: useful to compare with your results. -| Step | What is added | Tables | What to look at | -|---|---|---|---| -| skeleton | loop over events, sel8, \|z\| < 10 cm | `StraCollisions`, `StraEvSels` | `eventSelection/hVertexZRec` | -| 0 | loop over V0s, K0S, Λ, Λbar invariant masses | `V0Cores` | `kzeroShort/hMassK0Short`, `lambda/hMassLambda` | -| 1 | topological selections (`Filter` + dynamic columns), rapidity, competing mass rejection | `V0Cores` | `hMass*Selected`, `hV0CosPA`, `hV0Radius` | -| 2 | TPC PID of the daughters (`posTrackExtra_as<>`) | `V0Extras`, `DauTrackExtras`, `DauTrackTPCPIDs` | `hNSigmaPos/NegPionFromK0s`, `hMass*Selected` | -| 3 | TOF PID optimised for secondary particles (`strangenesstofpid` task) | `V0TOFNSigmas` | `hMass*SelectedWithTOF` | -| 4 | MC truth: true reconstructed and generated V0s | `V0CoreMCLabels`, `V0MCCores`, `V0MCCollRefs` | `hPt*TrueRec`, `genParticles/hPt*Gen` | +| Step | What is added | Tables | What to look at | +|----------|-----------------------------------------------------------------------------------------|-------------------------------------------------|-------------------------------------------------| +| skeleton | loop over events, sel8, \|z\| < 10 cm | `StraCollisions`, `StraEvSels` | `eventSelection/hVertexZRec` | +| 0 | loop over V0s, K0S, Λ, Λbar invariant masses | `V0Cores` | `kzeroShort/hMassK0Short`, `lambda/hMassLambda` | +| 1 | topological selections (`Filter` + dynamic columns), rapidity, competing mass rejection | `V0Cores` | `hMass*Selected`, `hV0CosPA`, `hV0Radius` | +| 2 | TPC PID of the daughters (`posTrackExtra_as<>`) | `V0Extras`, `DauTrackExtras`, `DauTrackTPCPIDs` | `hNSigmaPos/NegPionFromK0s`, `hMass*Selected` | +| 3 | TOF PID optimised for secondary particles (`strangenesstofpid` task) | `V0TOFNSigmas` | `hMass*SelectedWithTOF` | +| 4 | MC truth: true reconstructed and generated V0s | `V0CoreMCLabels`, `V0MCCores`, `V0MCCollRefs` | `hPt*TrueRec`, `genParticles/hPt*Gen` | Step 1 selections (in `jsonConfigs/step1.json`): -| Selection | Value | Getter | Column | -|---|---|---|---| -| DCA pos./neg. daughter to PV | > 0.06 cm | `dcapostopv()`, `dcanegtopv()` | standard | -| DCA between daughters | < 0.5 cm | `dcaV0daughters()` | standard | -| cosine of pointing angle | > 0.995 | `v0cosPA()` | **standard** in derived data | -| decay radius | > 0.9 cm | `v0radius()` | dynamic | -| rapidity | \|y\| < 0.5 | `yK0Short()`, `yLambda()` | dynamic | +| Selection | Value | Getter | Column | +|------------------------------|-------------|--------------------------------|------------------------------| +| DCA pos./neg. daughter to PV | > 0.06 cm | `dcapostopv()`, `dcanegtopv()` | standard | +| DCA between daughters | < 0.5 cm | `dcaV0daughters()` | standard | +| cosine of pointing angle | > 0.995 | `v0cosPA()` | **standard** in derived data | +| decay radius | > 0.9 cm | `v0radius()` | dynamic | +| rapidity | \|y\| < 0.5 | `yK0Short()`, `yLambda()` | dynamic | Hints for the steps: - **Step 0**: look at the `aod::V0Cores` table in `PWGLF/DataModel/LFStrangenessTables.h` and at the getters From 8f447ce88d1b2881d3a170981a4da8d85a9edad1 Mon Sep 17 00:00:00 2001 From: Sara Pucillo Date: Sat, 14 Nov 2026 11:22:52 +0100 Subject: [PATCH 6/7] [Tutorial,PWGLF] Move V0 hands-on into Derived/AnalysisV0, remove input files --- Tutorials/PWGLF/Strangeness/CMakeLists.txt | 1 - .../AnalysisV0/CMakeLists.txt | 0 .../AnalysisV0}/README.md | 20 +++++++++---------- .../AnalysisV0}/checkTables.C | 0 .../AnalysisV0}/jsonConfigs/skeleton.json | 0 .../AnalysisV0}/jsonConfigs/step0.json | 0 .../AnalysisV0}/jsonConfigs/step1.json | 0 .../AnalysisV0}/jsonConfigs/step2.json | 0 .../AnalysisV0}/jsonConfigs/step3.json | 0 .../AnalysisV0}/jsonConfigs/step4.json | 0 .../AnalysisV0}/runSkeleton.sh | 0 .../AnalysisV0}/runStep0.sh | 0 .../AnalysisV0}/runStep1.sh | 0 .../AnalysisV0}/runStep2.sh | 0 .../AnalysisV0}/runStep3.sh | 0 .../AnalysisV0}/runStep4.sh | 0 .../strangeness_derived_v0_skeleton.cxx | 0 .../strangeness_derived_v0_step0.cxx | 0 .../strangeness_derived_v0_step1.cxx | 0 .../strangeness_derived_v0_step2.cxx | 0 .../strangeness_derived_v0_step3.cxx | 0 .../strangeness_derived_v0_step4.cxx | 0 .../PWGLF/Strangeness/Derived/CMakeLists.txt | 3 ++- .../StrangenessV0s_HandsOn/input_MC.txt | 1 - .../StrangenessV0s_HandsOn/input_data.txt | 1 - 25 files changed, 12 insertions(+), 14 deletions(-) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn/o2physics => Derived}/AnalysisV0/CMakeLists.txt (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/README.md (90%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/checkTables.C (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/jsonConfigs/skeleton.json (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/jsonConfigs/step0.json (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/jsonConfigs/step1.json (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/jsonConfigs/step2.json (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/jsonConfigs/step3.json (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/jsonConfigs/step4.json (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/runSkeleton.sh (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/runStep0.sh (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/runStep1.sh (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/runStep2.sh (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/runStep3.sh (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn => Derived/AnalysisV0}/runStep4.sh (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn/o2physics => Derived}/AnalysisV0/strangeness_derived_v0_skeleton.cxx (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn/o2physics => Derived}/AnalysisV0/strangeness_derived_v0_step0.cxx (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn/o2physics => Derived}/AnalysisV0/strangeness_derived_v0_step1.cxx (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn/o2physics => Derived}/AnalysisV0/strangeness_derived_v0_step2.cxx (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn/o2physics => Derived}/AnalysisV0/strangeness_derived_v0_step3.cxx (100%) rename Tutorials/PWGLF/Strangeness/{StrangenessV0s_HandsOn/o2physics => Derived}/AnalysisV0/strangeness_derived_v0_step4.cxx (100%) delete mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_MC.txt delete mode 100644 Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_data.txt diff --git a/Tutorials/PWGLF/Strangeness/CMakeLists.txt b/Tutorials/PWGLF/Strangeness/CMakeLists.txt index 3a2fe4d79ca..049a1e3f025 100644 --- a/Tutorials/PWGLF/Strangeness/CMakeLists.txt +++ b/Tutorials/PWGLF/Strangeness/CMakeLists.txt @@ -11,4 +11,3 @@ add_subdirectory(Original) add_subdirectory(Derived) -add_subdirectory(StrangenessV0s_HandsOn/o2physics/AnalysisV0) diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/CMakeLists.txt b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/CMakeLists.txt similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/CMakeLists.txt rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/CMakeLists.txt diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/README.md similarity index 90% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/README.md index 8a727bf721a..9351b64902a 100644 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/README.md +++ b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/README.md @@ -19,16 +19,16 @@ which o2-analysistutorial-lf-strangeness-derived-v0-skeleton # must exist which o2-analysistutorial-lf-strangeness-derived-v0-step0 # checkpoint ``` -Clone this repository: +Go to the folder of the hands-on in your O2Physics source directory: ```bash -git clone https://github.com/StrangenessV0s_HandsOn -cd StrangenessV0s_HandsOn +cd ~/alice/O2Physics/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0 ``` Download the two input files (strangeness derived data, ~<200> MB each): ```bash +mkdir -p data MC # real data -> data/AO2D.root (used by skeleton and steps 0-3) rsync -r -u --progress USERNAME@lxplus.cern.ch:/eos/user///tutorialData/data/AO2D.root data # Monte Carlo -> MC/AO2D.root (used by step 4, which needs the MC truth) @@ -38,20 +38,20 @@ rsync -r -u --progress USERNAME@lxplus.cern.ch:/eos/user///tutorialData Alternatively, download them from CERNBox links. The run scripts do not contain the file paths: they read them from two text files (one path per line, -relative to the repository folder or absolute): +relative to this folder or absolute), which you have to create (the paths are also given in the slides): -| File | Content | Used by | -|---|---|---| -| `input_data.txt` | `data/AO2D.root` | `runSkeleton.sh`, `runStep0-3.sh` | -| `input_MC.txt` | `MC/AO2D.root` | `runStep4.sh` | +```bash +echo "data/AO2D.root" > input_data.txt # used by runSkeleton.sh, runStep0-3.sh +echo "MC/AO2D.root" > input_MC.txt # used by runStep4.sh +``` If you save the files elsewhere, edit these two text files. To run steps 0-3 on the MC (e.g. to compare with data): `INPUTFILE=input_MC.txt ./runStep2.sh`. ## How to work -The code you will modify is the skeleton in O2Physics: -`Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx`. +The code you will modify is the skeleton in this folder: +`Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_skeleton.cxx`. The checkpoints of each step are in the same folder (`strangeness_derived_v0_stepX.cxx`). ```bash diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/checkTables.C b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/checkTables.C similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/checkTables.C rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/checkTables.C diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/skeleton.json similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/skeleton.json rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/skeleton.json diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/step0.json similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step0.json rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/step0.json diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step1.json b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/step1.json similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step1.json rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/step1.json diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step2.json b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/step2.json similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step2.json rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/step2.json diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step3.json b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/step3.json similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step3.json rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/step3.json diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step4.json b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/step4.json similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/jsonConfigs/step4.json rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/jsonConfigs/step4.json diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runSkeleton.sh b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runSkeleton.sh similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runSkeleton.sh rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runSkeleton.sh diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep0.sh b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runStep0.sh similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep0.sh rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runStep0.sh diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep1.sh b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runStep1.sh similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep1.sh rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runStep1.sh diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep2.sh b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runStep2.sh similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep2.sh rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runStep2.sh diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep3.sh b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runStep3.sh similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep3.sh rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runStep3.sh diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep4.sh b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runStep4.sh similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/runStep4.sh rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/runStep4.sh diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_skeleton.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_skeleton.cxx rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_skeleton.cxx diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step0.cxx b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_step0.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step0.cxx rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_step0.cxx diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step1.cxx b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_step1.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step1.cxx rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_step1.cxx diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step2.cxx b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_step2.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step2.cxx rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_step2.cxx diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step3.cxx b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_step3.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step3.cxx rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_step3.cxx diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step4.cxx b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_step4.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/o2physics/AnalysisV0/strangeness_derived_v0_step4.cxx rename to Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/strangeness_derived_v0_step4.cxx diff --git a/Tutorials/PWGLF/Strangeness/Derived/CMakeLists.txt b/Tutorials/PWGLF/Strangeness/Derived/CMakeLists.txt index f593f821726..22143268c59 100644 --- a/Tutorials/PWGLF/Strangeness/Derived/CMakeLists.txt +++ b/Tutorials/PWGLF/Strangeness/Derived/CMakeLists.txt @@ -10,4 +10,5 @@ # or submit itself to any jurisdiction. add_subdirectory(Analysis) -# add_subdirectory(DerivedDataProduction) \ No newline at end of file +# add_subdirectory(DerivedDataProduction) +add_subdirectory(AnalysisV0) diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_MC.txt b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_MC.txt deleted file mode 100644 index 900ccbc2fc1..00000000000 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_MC.txt +++ /dev/null @@ -1 +0,0 @@ -file:///eos/user/s/spucillo/O2AT6_tutorial/MC/AO2D.root diff --git a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_data.txt b/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_data.txt deleted file mode 100644 index 9eff51ed538..00000000000 --- a/Tutorials/PWGLF/Strangeness/StrangenessV0s_HandsOn/input_data.txt +++ /dev/null @@ -1 +0,0 @@ -file:///eos/user/s/spucillo/O2AT6_tutorial/data/AO2D.root From bf563f8d0fb172f9d002995ce36f7c91a8841044 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Sat, 14 Nov 2026 10:33:27 +0000 Subject: [PATCH 7/7] MegaLinter fixes --- .../Strangeness/Derived/AnalysisV0/README.md | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/README.md b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/README.md index 9351b64902a..533f48b7681 100644 --- a/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/README.md +++ b/Tutorials/PWGLF/Strangeness/Derived/AnalysisV0/README.md @@ -67,24 +67,24 @@ TASK=o2-analysistutorial-lf-strangeness-derived-v0-skeleton ./runStep1.sh Without `TASK=...` the checkpoint of the step is run: useful to compare with your results. -| Step | What is added | Tables | What to look at | -|---|---|---|---| -| skeleton | loop over events, sel8, \|z\| < 10 cm | `StraCollisions`, `StraEvSels` | `eventSelection/hVertexZRec` | -| 0 | loop over V0s, K0S, Λ, Λbar invariant masses | `V0Cores` | `kzeroShort/hMassK0Short`, `lambda/hMassLambda` | -| 1 | topological selections (`Filter` + dynamic columns), rapidity, competing mass rejection | `V0Cores` | `hMass*Selected`, `hV0CosPA`, `hV0Radius` | -| 2 | TPC PID of the daughters (`posTrackExtra_as<>`) | `V0Extras`, `DauTrackExtras`, `DauTrackTPCPIDs` | `hNSigmaPos/NegPionFromK0s`, `hMass*Selected` | -| 3 | TOF PID optimised for secondary particles (`strangenesstofpid` task) | `V0TOFNSigmas` | `hMass*SelectedWithTOF` | -| 4 | MC truth: true reconstructed and generated V0s | `V0CoreMCLabels`, `V0MCCores`, `V0MCCollRefs` | `hPt*TrueRec`, `genParticles/hPt*Gen` | +| Step | What is added | Tables | What to look at | +|----------|-----------------------------------------------------------------------------------------|-------------------------------------------------|-------------------------------------------------| +| skeleton | loop over events, sel8, \|z\| < 10 cm | `StraCollisions`, `StraEvSels` | `eventSelection/hVertexZRec` | +| 0 | loop over V0s, K0S, Λ, Λbar invariant masses | `V0Cores` | `kzeroShort/hMassK0Short`, `lambda/hMassLambda` | +| 1 | topological selections (`Filter` + dynamic columns), rapidity, competing mass rejection | `V0Cores` | `hMass*Selected`, `hV0CosPA`, `hV0Radius` | +| 2 | TPC PID of the daughters (`posTrackExtra_as<>`) | `V0Extras`, `DauTrackExtras`, `DauTrackTPCPIDs` | `hNSigmaPos/NegPionFromK0s`, `hMass*Selected` | +| 3 | TOF PID optimised for secondary particles (`strangenesstofpid` task) | `V0TOFNSigmas` | `hMass*SelectedWithTOF` | +| 4 | MC truth: true reconstructed and generated V0s | `V0CoreMCLabels`, `V0MCCores`, `V0MCCollRefs` | `hPt*TrueRec`, `genParticles/hPt*Gen` | Step 1 selections (in `jsonConfigs/step1.json`): -| Selection | Value | Getter | Column | -|---|---|---|---| -| DCA pos./neg. daughter to PV | > 0.06 cm | `dcapostopv()`, `dcanegtopv()` | standard | -| DCA between daughters | < 0.5 cm | `dcaV0daughters()` | standard | -| cosine of pointing angle | > 0.995 | `v0cosPA()` | **standard** in derived data | -| decay radius | > 0.9 cm | `v0radius()` | dynamic | -| rapidity | \|y\| < 0.5 | `yK0Short()`, `yLambda()` | dynamic | +| Selection | Value | Getter | Column | +|------------------------------|-------------|--------------------------------|------------------------------| +| DCA pos./neg. daughter to PV | > 0.06 cm | `dcapostopv()`, `dcanegtopv()` | standard | +| DCA between daughters | < 0.5 cm | `dcaV0daughters()` | standard | +| cosine of pointing angle | > 0.995 | `v0cosPA()` | **standard** in derived data | +| decay radius | > 0.9 cm | `v0radius()` | dynamic | +| rapidity | \|y\| < 0.5 | `yK0Short()`, `yLambda()` | dynamic | Hints for the steps: - **Step 0**: look at the `aod::V0Cores` table in `PWGLF/DataModel/LFStrangenessTables.h` and at the getters