From c3a90c298e2c40474ced2a7c719d65ab36550c63 Mon Sep 17 00:00:00 2001 From: Juraj Smiesko Date: Tue, 1 Sep 2026 10:29:41 +0200 Subject: [PATCH 1/3] Gen/ee: clone/cd instructions, OMP_NUM_THREADS, blockquote Q&A, rename dirs Add a top-level "Getting started" section with the git clone command, and a note in Gen/ee/README.md that all commands assume starting from that stage's folder. Prefix WHIZARD with OMP_NUM_THREADS=1 by default, since it otherwise grabs every core on the machine, which is unfriendly on shared nodes; join it with the existing cross-section note into one numbered Notes: block. Fence the three Q&A
blocks with '>' to match the rest of the doc's blockquote-style asides. Rename the scratch working directories from test_whizard/ to whizard_prod/mumuH and pythia_prod/, split by tool rather than sample - this also fixes WW/ZZ being nested under "test_whizard" despite using no WHIZARD step at all. Verified the full pipeline end-to-end against the new layout. --- Gen/ee/README.md | 164 ++++++++++++++++++-------------- Gen/ee/solutions/backgrounds.md | 4 +- README.md | 12 +++ 3 files changed, 104 insertions(+), 76 deletions(-) diff --git a/Gen/ee/README.md b/Gen/ee/README.md index fd8a234..98d4c7d 100644 --- a/Gen/ee/README.md +++ b/Gen/ee/README.md @@ -6,6 +6,13 @@ generator WHIZARD generates the hard process $e^{+}e^{-} \rightarrow \mu^{+} \mu^{-} H$, then Pythia8 showers, hadronizes, and decays $H \rightarrow b \bar{b}$. +All commands below assume you start from the `Gen/ee` folder in the cloned +repository: + +```bash +cd GenToAna-Tutorial/Gen/ee +``` + ## Environment setup @@ -108,21 +115,27 @@ Run it in its own directory, as WHIZARD produces a lot of additional helper files: ```bash -mkdir -p test_whizard/mumuH && cd test_whizard/mumuH +mkdir -p whizard_prod/mumuH && cd whizard_prod/mumuH cp ../../mumuH.sin . -whizard mumuH.sin +OMP_NUM_THREADS=1 whizard mumuH.sin ``` This produces `mumuH.lhe`. -> **Note:** WHIZARD also computes and prints the process cross-section -> during the `integrate` step above — look for the `Integral[fb]`/ -> `Error[fb]` columns in the last combined row of the iteration table -> (also echoed in the generated `mumuH.log` file). This is the -> cross-section for the exact final state computed here -> ($e^{+}e^{-} \rightarrow \mu^{+} \mu^{-} H$), not the total $ZH$ -> production cross-section — it already includes the -> $Z \rightarrow \mu^{+} \mu^{-}$ branching fraction (~3.37%). +> Notes: +> 1. WHIZARD uses OpenMP and by default grabs all available cores on the +> machine, which isn't friendly (or efficient) on shared/multi-user +> nodes. `OMP_NUM_THREADS=1` restricts it to a single thread; drop it +> if you're on a machine you have exclusively to yourself and want the +> integration step to finish faster. +> 2. WHIZARD also computes and prints the process cross-section during +> the `integrate` step above — look for the `Integral[fb]`/`Error[fb]` +> columns in the last combined row of the iteration table (also echoed +> in the generated `mumuH.log` file). This is the cross-section for +> the exact final state computed here +> ($e^{+}e^{-} \rightarrow \mu^{+} \mu^{-} H$), not the total $ZH$ +> production cross-section — it already includes the +> $Z \rightarrow \mu^{+} \mu^{-}$ branching fraction (~3.37%). Two settings are deliberately left out rather than pinned explicitly, relying on their WHIZARD defaults: @@ -135,31 +148,31 @@ relying on their WHIZARD defaults: > file into Pythia8 downstream, see > [WHIZARD manual](https://whizard.hepforge.org/manual.pdf). -
-❓ Question: - -WHIZARD generates $e^{+}e^{-} \rightarrow \mu^{+} \mu^{-} H$ directly. Why -not $e^{+}e^{-} \rightarrow Z H$ with $Z \rightarrow \mu^{+} \mu^{-}$ -instead — isn't the final state identical? - -
-✅ Answer: - -WHIZARD computes the complete matrix element for the exact final state -directly, rather than treating it as production ($e^{+}e^{-} \rightarrow Z -H$) followed by a separate, on-shell $Z \rightarrow \mu^{+} \mu^{-}$ -decay. WHIZARD does support that factorized "cascade decay" mode too, and -it can retain full spin correlations between production and decay, but it -still restricts the intermediate boson to being on-shell, discarding the -true Breit-Wigner off-shell tails and any other diagrams contributing to -the same final state that don't proceed through that resonance ([WHIZARD -reference paper](https://arxiv.org/abs/0708.4233), Section 6.6). At -$\sqrt{s} = 240$ GeV there's only about 24 GeV of phase space left over the -$H + Z$ mass threshold, so the $Z$'s few-GeV width has a non-negligible -effect on the exact lineshape. - -
-
+>
+> ❓ Question: +> +> WHIZARD generates $e^{+}e^{-} \rightarrow \mu^{+} \mu^{-} H$ directly. Why +> not $e^{+}e^{-} \rightarrow Z H$ with $Z \rightarrow \mu^{+} \mu^{-}$ +> instead — isn't the final state identical? +> +>
+> ✅ Answer: +> +> WHIZARD computes the complete matrix element for the exact final state +> directly, rather than treating it as production ($e^{+}e^{-} \rightarrow Z +> H$) followed by a separate, on-shell $Z \rightarrow \mu^{+} \mu^{-}$ +> decay. WHIZARD does support that factorized "cascade decay" mode too, and +> it can retain full spin correlations between production and decay, but it +> still restricts the intermediate boson to being on-shell, discarding the +> true Breit-Wigner off-shell tails and any other diagrams contributing to +> the same final state that don't proceed through that resonance ([WHIZARD +> reference paper](https://arxiv.org/abs/0708.4233), Section 6.6). At +> $\sqrt{s} = 240$ GeV there's only about 24 GeV of phase space left over the +> $H + Z$ mass threshold, so the $Z$'s few-GeV width has a non-negligible +> effect on the exact lineshape. +> +>
+>
## Step 2: Pythia8 - shower, hadronize, decay $H \rightarrow b \bar{b}$ @@ -214,26 +227,26 @@ LesHouches:matchInOut = off 25:onIfAny = 5 ``` -
-❓ Question: - -The card sets `PartonLevel:ISR = off` but leaves `PartonLevel:FSR` on -(Pythia8's default). Shouldn't initial- and final-state radiation be -treated the same way? - -
-✅ Answer: - -WHIZARD's `isr_handler`, turned on in Step 1, already applied the -initial-state radiation, as an energy redistribution on the beam momenta, so -Pythia8's own initial-state shower would double-count it if left on. FSR is -different: the LHE file from Step 1 has the Higgs *undecayed*, and Pythia8's -final-state shower is what both decays $H \rightarrow b \bar{b}$ and showers the -resulting $b/\bar{b}$ before hadronization. Turn it off and the $b/\bar{b}$ go -straight into string fragmentation with zero shower. - -
-
+>
+> ❓ Question: +> +> The card sets `PartonLevel:ISR = off` but leaves `PartonLevel:FSR` on +> (Pythia8's default). Shouldn't initial- and final-state radiation be +> treated the same way? +> +>
+> ✅ Answer: +> +> WHIZARD's `isr_handler`, turned on in Step 1, already applied the +> initial-state radiation, as an energy redistribution on the beam momenta, so +> Pythia8's own initial-state shower would double-count it if left on. FSR is +> different: the LHE file from Step 1 has the Higgs *undecayed*, and Pythia8's +> final-state shower is what both decays $H \rightarrow b \bar{b}$ and showers the +> resulting $b/\bar{b}$ before hadronization. Turn it off and the $b/\bar{b}$ go +> straight into string fragmentation with zero shower. +> +>
+>
The steering script [`pythia_gen.py`](pythia_gen.py) reads the card above. No HepMC file is ever written to disk here: `GenAlg` writes the @@ -322,33 +335,36 @@ iosvc = IOSvc() iosvc.Output = "mumuH_Hbb.root" ``` -
-❓ Question: - -The script sets `pythia8gen.ErrorMax = 20`. What do you think would happen -at this stage's actual sample size (10,000 events) if this were left at -Gaudi's default, `ErrorMax = 1`? - -
-✅ Answer: - -A small fraction of events (roughly 1 in a few thousand) hit a Pythia8-level -failure that retrying doesn't recover from — for example an energy-momentum -conservation check. With `ErrorMax = 1`, a single such event aborts the *entire* -run, not just that one event. Raising `ErrorMax` lets Gaudi skip a handful of -individually-unrecoverable events and keep going instead. - -
-
+>
+> ❓ Question: +> +> The script sets `pythia8gen.ErrorMax = 20`. What do you think would happen +> at this stage's actual sample size (10,000 events) if this were left at +> Gaudi's default, `ErrorMax = 1`? +> +>
+> ✅ Answer: +> +> A small fraction of events (roughly 1 in a few thousand) hit a Pythia8-level +> failure that retrying doesn't recover from — for example an energy-momentum +> conservation check. With `ErrorMax = 1`, a single such event aborts the *entire* +> run, not just that one event. Raising `ErrorMax` lets Gaudi skip a handful of +> individually-unrecoverable events and keep going instead. +> +>
+>
> **Note:** Gaudi itself flags `ErrorMax` as `[[deprecated]]` (a warning > appears at run time), but as of this Key4hep release there's no > replacement — the property is still fully functional under the hood, so > this tutorial keeps using it as-is until a better alternative exists. -Copy both files next to the LHEf file produced in Step 1 and run: +Set up a separate directory for this step, copy in the LHEf file produced +in Step 1 alongside the card and steering script, and run: ```bash +cd ../.. && mkdir -p pythia_prod/mumuH && cd pythia_prod/mumuH +cp ../../whizard_prod/mumuH/mumuH.lhe . cp ../../mumuH_Hbb.cmd ../../pythia_gen.py . k4run pythia_gen.py ``` diff --git a/Gen/ee/solutions/backgrounds.md b/Gen/ee/solutions/backgrounds.md index 69ca7ee..741e2b2 100644 --- a/Gen/ee/solutions/backgrounds.md +++ b/Gen/ee/solutions/backgrounds.md @@ -20,7 +20,7 @@ IDEA values used for the signal instead — so smearing is consistent across signal and backgrounds, rather than each card using its own values. ```bash -mkdir -p test_whizard/WW && cd test_whizard/WW +mkdir -p pythia_prod/WW && cd pythia_prod/WW cp ../../solutions/p8_ee_WW_ecm240.cmd ../../pythia_gen.py . k4run pythia_gen.py --Pythia8.PythiaInterface.pythiacard=p8_ee_WW_ecm240.cmd --IOSvc.Output=WW.root ``` @@ -36,7 +36,7 @@ electroweak diboson process — dominated by ZZ away from resonance, but also including some gamma*/Z interference, hence the setting name): ```bash -mkdir -p test_whizard/ZZ && cd test_whizard/ZZ +mkdir -p pythia_prod/ZZ && cd pythia_prod/ZZ cp ../../solutions/p8_ee_ZZ_ecm240.cmd ../../pythia_gen.py . k4run pythia_gen.py --Pythia8.PythiaInterface.pythiacard=p8_ee_ZZ_ecm240.cmd --IOSvc.Output=ZZ.root ``` diff --git a/README.md b/README.md index 63d2d24..1fd1640 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,18 @@ Fast/Parametric **S**imulation (Delphes) to physics **Ana**lysis. - **FCC-hh (shorter, advanced transfer):** HH -> b b gamma gamma, reusing the FCC-ee material with less hand-holding, extending the physics objects covered to photons. +## Getting started + +Clone the repository: + +```bash +git clone https://github.com/HEP-FCC/GenToAna-Tutorial.git +cd GenToAna-Tutorial +``` + +(If you plan to submit fixes, fork the repo first and clone your fork +instead — see [CONTRIBUTING.md](CONTRIBUTING.md).) + ## Structure Each stage has its own top-level directory, split by collider, with a From 5652472e4d31419787ecfc85c892bab691a56586 Mon Sep 17 00:00:00 2001 From: Juraj Smiesko Date: Tue, 1 Sep 2026 10:38:07 +0200 Subject: [PATCH 2/3] Clarify "background" terminology, drop unmade-slides/presenting claims Note in Gen/ee/README.md and solutions/backgrounds.md that "background" here means a different physics process (WW, ZZ), not the beam-induced background FullSim students may expect - this tutorial has no BIB overlay at all. Also drop the top-level README's claims that each section has introductory slides and that students present their solutions, since neither was actually done. --- Gen/ee/README.md | 11 +++++++++-- Gen/ee/solutions/backgrounds.md | 7 +++++++ README.md | 5 ++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Gen/ee/README.md b/Gen/ee/README.md index 98d4c7d..a701b12 100644 --- a/Gen/ee/README.md +++ b/Gen/ee/README.md @@ -188,13 +188,13 @@ script"; `k4run` is Key4hep's command-line tool for running these scripts. > 1. To get a list of all available commandline arguments which one can use to > adjust the steering script use: > ```bash -> k4run steering_script.py --help +> k4run --help > ``` > 2. To check that a steering script is valid without actually running the > job (parses the config, wires up components, but generates no events), > use: > ```bash -> k4run steering_script.py --dry-run +> k4run --dry-run > ``` > 3. Gaudi components of the Key4hep ecosystem are spread through many > packages, here we primarily use the Gaudi components from @@ -389,6 +389,13 @@ Pythia8 generates these hard processes itself. See [`solutions/backgrounds.md`](solutions/backgrounds.md) for the walkthrough; the cards themselves are also in the [`solutions/`](solutions) folder. +> **Note:** "Background" here means a different *physics process* (WW, +> ZZ) that can mimic the mumuH signal in the final state — not the +> beam-induced background familiar from FullSim studies, where machine- +> related backgrounds are overlaid onto a signal event at the +> simulation/reconstruction level. This tutorial's fast simulation chain +> doesn't include beam-induced background overlay at all. + ## What's next diff --git a/Gen/ee/solutions/backgrounds.md b/Gen/ee/solutions/backgrounds.md index 741e2b2..13af8bc 100644 --- a/Gen/ee/solutions/backgrounds.md +++ b/Gen/ee/solutions/backgrounds.md @@ -5,6 +5,13 @@ e+e- -> WW and e+e- -> ZZ (diboson) production. Unlike the signal, these don't need WHIZARD: Pythia8 can generate the hard process itself directly, so this is a single Pythia8 step with no LHE file involved at all. +> **Note:** "Background" here means a different *physics process* (WW, +> ZZ) that can mimic the mumuH signal in the final state — not the +> beam-induced background familiar from FullSim studies, where machine- +> related backgrounds are overlaid onto a signal event at the +> simulation/reconstruction level. This tutorial's fast simulation chain +> doesn't include beam-induced background overlay at all. + Both reuse the signal's [`pythia_gen.py`](../pythia_gen.py) steering script as-is — only the card and output filename change, and both are overridable at the command line via `k4run`'s property overrides, so no file edits or diff --git a/README.md b/README.md index 1fd1640..1dd91bf 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,8 @@ Analysis/ ## Format -Each section is introduced with brief slides, then students work through the -markdown material directly in this repo (VSCodium + extensions recommended -for an all-in-one setup). Students present their solutions; reference +Students work through the markdown material directly in this repo +(VSCodium + extensions recommended for an all-in-one setup). Reference solutions are also provided here for offline use. ## Branches From 791da47f3546a3fcdac90009cb72dc6cfa584954 Mon Sep 17 00:00:00 2001 From: Juraj Smiesko Date: Tue, 1 Sep 2026 11:13:52 +0200 Subject: [PATCH 3/3] Fix cd path in Gen/ee/README.md's getting-started snippet Should be relative to the already-cloned repo root, not include the repo directory name itself. --- Gen/ee/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gen/ee/README.md b/Gen/ee/README.md index a701b12..3f09fbd 100644 --- a/Gen/ee/README.md +++ b/Gen/ee/README.md @@ -10,7 +10,7 @@ All commands below assume you start from the `Gen/ee` folder in the cloned repository: ```bash -cd GenToAna-Tutorial/Gen/ee +cd Gen/ee ```