Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions Tutorials/PWGHF/DataModelMini.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, Tracks, "_1"); //! prong 1
} // namespace hf_track_index

// Track index skim table
DECLARE_SOA_TABLE(HfT2Prongs, "AOD", "HFT2PRONG", //! table with prongs indices
DECLARE_SOA_TABLE(HfT2Prongs, "AOD", "HFT2PRONG", //! table with prong indices
o2::soa::Index<>,
hf_track_index::Prong0Id,
hf_track_index::Prong1Id);

Expand All @@ -53,43 +54,44 @@ namespace hf_cand_prong2
{
// Candidate columns
// collision properties
DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! collisions
DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! collision
// secondary vertex
DECLARE_SOA_COLUMN(XSecondaryVertex, xSecondaryVertex, float); //! x coordinate of the secondary vertex
DECLARE_SOA_COLUMN(YSecondaryVertex, ySecondaryVertex, float); //! y coordinate of the secondary vertex
DECLARE_SOA_COLUMN(ZSecondaryVertex, zSecondaryVertex, float); //! z coordinate of the secondary vertex
DECLARE_SOA_DYNAMIC_COLUMN(RSecondaryVertex, rSecondaryVertex, //! radius of the secondary vertex
DECLARE_SOA_COLUMN(XSecondaryVertex, xSecondaryVertex, float); //! x coordinate of the secondary vertex [cm]
DECLARE_SOA_COLUMN(YSecondaryVertex, ySecondaryVertex, float); //! y coordinate of the secondary vertex [cm]
DECLARE_SOA_COLUMN(ZSecondaryVertex, zSecondaryVertex, float); //! z coordinate of the secondary vertex [cm]
DECLARE_SOA_DYNAMIC_COLUMN(RSecondaryVertex, rSecondaryVertex, //! radius of the secondary vertex [cm]
[](float xVtxS, float yVtxS) -> float { return RecoDecay::sqrtSumOfSquares(xVtxS, yVtxS); });
// prong properties
DECLARE_SOA_COLUMN(PxProng0, pxProng0, float); //! px of prong 0
DECLARE_SOA_COLUMN(PyProng0, pyProng0, float); //! py of prong 0
DECLARE_SOA_COLUMN(PzProng0, pzProng0, float); //! pz of prong 0
DECLARE_SOA_DYNAMIC_COLUMN(PtProng0, ptProng0, //! pt of prong 0
DECLARE_SOA_COLUMN(PxProng0, pxProng0, float); //! px of prong 0 [GeV/c]
DECLARE_SOA_COLUMN(PyProng0, pyProng0, float); //! py of prong 0 [GeV/c]
DECLARE_SOA_COLUMN(PzProng0, pzProng0, float); //! pz of prong 0 [GeV/c]
DECLARE_SOA_DYNAMIC_COLUMN(PtProng0, ptProng0, //! pt of prong 0 [GeV/c]
[](float px, float py) -> float { return RecoDecay::pt(px, py); });
DECLARE_SOA_COLUMN(PxProng1, pxProng1, float); //! px of prong 1
DECLARE_SOA_COLUMN(PyProng1, pyProng1, float); //! py of prong 1
DECLARE_SOA_COLUMN(PzProng1, pzProng1, float); //! pz of prong 1
DECLARE_SOA_DYNAMIC_COLUMN(PtProng1, ptProng1, //! pt of prong 1
DECLARE_SOA_COLUMN(PxProng1, pxProng1, float); //! px of prong 1 [GeV/c]
DECLARE_SOA_COLUMN(PyProng1, pyProng1, float); //! py of prong 1 [GeV/c]
DECLARE_SOA_COLUMN(PzProng1, pzProng1, float); //! pz of prong 1 [GeV/c]
DECLARE_SOA_DYNAMIC_COLUMN(PtProng1, ptProng1, //! pt of prong 1 [GeV/c]
[](float px, float py) -> float { return RecoDecay::pt(px, py); });
// candidate properties
DECLARE_SOA_DYNAMIC_COLUMN(DecayLength, decayLength, //! decay length of candidate
DECLARE_SOA_DYNAMIC_COLUMN(DecayLength, decayLength, //! decay length of candidate [cm]
[](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { return RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}); });
DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! pt of candidate
DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! pt of candidate [GeV/c]
[](float px, float py) -> float { return RecoDecay::pt(px, py); });
DECLARE_SOA_EXPRESSION_COLUMN(Px, px, //! px of candidate
DECLARE_SOA_EXPRESSION_COLUMN(Px, px, //! px of candidate [GeV/c]
float, 1.f * pxProng0 + 1.f * pxProng1);
DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! py of candidate
DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! py of candidate [GeV/c]
float, 1.f * pyProng0 + 1.f * pyProng1);
DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! pz of candidate
DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! pz of candidate [GeV/c]
float, 1.f * pzProng0 + 1.f * pzProng1);
DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! invariant mass of candidate
DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! invariant mass of candidate [GeV/c^2]
[](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array<double, 2>& m) -> float { return RecoDecay::m(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); });
DECLARE_SOA_DYNAMIC_COLUMN(Cpa, cpa, //! cosine of pointing angle of candidate
[](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::cpa(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); });
} // namespace hf_cand_prong2

// Candidate table
DECLARE_SOA_TABLE(HfTCand2ProngBase, "AOD", "HFTCAND2PBASE", //! 2-prong candidate table
o2::soa::Index<>,
hf_cand_prong2::CollisionId,
collision::PosX, collision::PosY, collision::PosZ,
hf_cand_prong2::XSecondaryVertex, hf_cand_prong2::YSecondaryVertex, hf_cand_prong2::ZSecondaryVertex,
Expand All @@ -116,7 +118,7 @@ namespace hf_selcandidate_d0
{
// Candidate selection columns
DECLARE_SOA_COLUMN(IsSelD0, isSelD0, int); //! selection flag for D0
DECLARE_SOA_COLUMN(IsSelD0bar, isSelD0bar, int); //! selection flag for D0 bar
DECLARE_SOA_COLUMN(IsSelD0bar, isSelD0bar, int); //! selection flag for D0bar
} // namespace hf_selcandidate_d0

// Candidate selection table
Expand Down
57 changes: 33 additions & 24 deletions Tutorials/PWGHF/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,72 @@

Welcome to the heavy-flavour analysis tutorial!

This directory contains the code and configuration for running a minimalistic version of the D<sup>0</sup> analysis on Run 3 real data.
This directory contains the code and configuration for running a minimalistic version of the D<sup>0</sup> analysis on Run 3 data.

See the [official PWG-HF O<sup>2</sup> documentation](https://aliceo2group.github.io/analysis-framework/docs/advanced-specifics/pwghf.html) for the overview of the full heavy-flavour analysis framework.
See the [PWG-HF O<sup>2</sup> documentation](https://aliceo2group.github.io/analysis-framework/docs/advanced-specifics/pwghf.html) for the overview of the full heavy-flavour analysis framework.

## Setup

1. Create a dedicated working directory on your device.
This is the directory, where you will put your input files, run the code and produce the output files, so it is a good idea to have it outside the O2Physics repository.
2. Put the input file(s) `AO2D.root` (and `AnalysisResults_trees.root`) in the working directory.
3. Load the O2Physics environment.
1. Create and enter a dedicated working directory on your device.
This is the directory, where you will put your input files, run the code, and produce the output files, so it is a good idea to have it outside the O2Physics repository.
1. Put the input file(s) `AO2D.root` (and `AnalysisResults_trees.root`) in the working directory (or in a dedicated directory for input data).
1. Copy the [`input_skim.txt`](input_skim.txt) and [`input_task.txt`](input_task.txt) files into the working directory and adjust the paths inside if needed.
1. Load the O2Physics environment.

## Skim production

The file `AnalysisResults_trees.root` contains a derived table with track index skims of 2-prong decay candidates.
This table contains paired track indices which point to the track table in the parent `AO2D.root` file.
It is produced from the `AO2D.root` file by a dedicated workflow `o2-analysistutorial-hf-skim-creator-mini` (implemented in [`skimCreatorMini.cxx`](skimCreatorMini.cxx)).
The mini skim creator workflow `o2-analysistutorial-hf-skim-creator-mini` (implemented in [`skimCreatorMini.cxx`](skimCreatorMini.cxx)) is a simplified version of the `o2-analysis-hf-track-index-skim-creator` workflow (implemented in [`trackIndexSkimCreator.cxx`](https://github.com/AliceO2Group/O2Physics/blob/master/PWGHF/TableProducer/trackIndexSkimCreator.cxx)) which is used for the central production of linked derived data for all HF analyses and which performs:

If you need to produce these derived skims, you can do that by executing the [`run_skim.sh`](run_skim.sh) bash script in the working directory:
- the HF event selection,
- the HF secondary-track selection,
- the HF secondary-vertex reconstruction and loose selection of found HF decay candidates.

The mini skim creator processes the `AO2D.root` file(s) and produces a derived table [`HfT2Prongs`](DataModelMini.h) with track index skims of 2-prong decay candidates.
This table contains paired track indices which point to tracks in the track table in the parent `AO2D.root` file.

These derived skims are produced by executing the [`run_skim.sh`](run_skim.sh) bash script in the working directory:

```bash
bash ~/alice/O2Physics/Tutorials/PWGHF/run_skim.sh
~/alice/O2Physics/Tutorials/PWGHF/run_skim.sh
```

It will use the configuration from [`dpl-config_skim.json`](dpl-config_skim.json).
It processes files specified in `./input_skim.txt`, uses the configuration from [`dpl-config_skim.json`](dpl-config_skim.json), and produces the `./AnalysisResults_trees.root` file with the derived table and the `./AnalysisResults.root` file with control histograms.

## Mini task

The mini task workflow `o2-analysistutorial-hf-task-mini` (implemented in [`taskMini.cxx`](taskMini.cxx)) is a simplified version of the D<sup>0</sup> analysis chain part which includes:

- the 2-prong candidate creator,
- the D<sup>0</sup> candidate selector,
- the D<sup>0</sup> analysis task.
- the 2-prong candidate creator (for the full candidate reconstruction),
- the D<sup>0</sup> candidate selector (for the candidate selection),
- the D<sup>0</sup> analysis task (for the analysis of selected candidates and filling of output histograms).

The first step (candidate creator) consumes the track index skim table and therefore needs the derived `AnalysisResults_trees.root` file as input.

Processing the derived file requires access to the parent `AO2D.root` file.
The absolute path to the parent file is stored in the derived file but it can be overridden with the parameter `aod-parent-base-path-replacement` in the JSON configuration,
where one has to provide a replacement mask in the format `"old-path-to-parent;new-path-to-parent"`.
The absolute path to the parent file is stored in the derived file but it can be overridden with the command line parameter `--aod-parent-base-path-replacement "old-path-to-parent;new-path-to-parent"`.
(If the parent and the derived files are both in the same directory, `new-path-to-parent` can be empty.)

Run the mini task by executing the [`run_task.sh`](run_task.sh) bash script in the working directory:

```bash
bash ~/alice/O2Physics/Tutorials/PWGHF/run_task.sh
~/alice/O2Physics/Tutorials/PWGHF/run_task.sh
```

It will use the configuration from [`dpl-config_task.json`](dpl-config_task.json) and produce the output file `AnalysisResults.root` with histograms in the working directory.
It processes files specified in `./input_task.txt`, uses the configuration from [`dpl-config_task.json`](dpl-config_task.json), and produces the `./AnalysisResults.root` file with histograms.

### Exercise tips
## Exercise tips

Organise your working environment so that you can easily switch between running the code in the working directory and modifying the code in the O2Physics repository.

When you execute the bash script, the terminal output is saved in the `stdout.log` log file in the working directory.
When you execute the bash script, the terminal output is saved in the `./stdout.log` log file.
If an error occurs, the script will report the non-zero exit code and ask you to check the log file to find the problem.
If you get errors that have to be tolerated, you need to remove the `--min-failure-level error` option from the command.

The full O<sup>2</sup> configuration is dumped at the end of processing into the `./dpl-config.json` file.
It is useful to compare it with the input configuration file to spot mismatches.

The full O<sup>2</sup> configuration is dumped at the end of processing into the `dpl-config.json` file in the working directory.
See the [rebuilding instructions](https://aliceo2group.github.io/analysis-framework/docs/gettingstarted/installing.html#building-partially-for-development-using-ninja) in the analysis framework documentation for advice on compiling your code changes.

See the [rebuilding instructions](https://aliceo2group.github.io/analysis-framework/docs/gettingstarted/installing.html#building-partially-for-development-using-ninja) in the official O<sup>2</sup> analysis framework documentation for advice on compiling your code changes.
See the [Troubleshooting](https://aliceo2group.github.io/analysis-framework/docs/troubleshooting/) section of the analysis framework documentation for debugging advice.

See the [Troubleshooting](https://aliceo2group.github.io/analysis-framework/docs/troubleshooting/) section of the official O<sup>2</sup> analysis framework documentation for debugging advice.
Consider using the [Shell rc utilities](https://aliceo2group.github.io/analysis-framework/docs/tools/#shell-rc-utilities) for easier recompilation and debugging.
Loading
Loading