Warning, /firebird/docs/dd4hep-plugin.md is written in an unsupported language. File is not indexed.
0001 # DD4hep Plugin
0002
0003 Plugin for DD4hep that writes true particle trajectories (via Geant4 event/stepping actions)
0004 to the Firebird data-exchange (DEX) format for visualization.
0005
0006 <a href="https://eic.github.io/firebird/">
0007 <img src="./media/eic_dis_animation_v7.gif" title="EIC ePIC DIS event" />
0008 </a>
0009
0010
0011 ## Usage
0012
0013 Here is the plan:
0014
0015 1. Build C++ plugin with cmake
0016 2. Add resulting files to `LD_LBRARY_PATH` so dd4hep could find the plugin
0017 3. Run npsim/dd4hep with python steering file, that sets up the plugin
0018 4. \[optional\] Configure plugin parameters (cuts and what to write)
0019
0020 ### 1. Build and install the plugin
0021
0022 ```bash
0023 git clone https://github.com/eic/firebird.git
0024 cd firebird/dd4hep-plugin
0025
0026 cmake -B build -S .
0027 cmake --build build
0028 cmake --install build # installs into prefix/lib by default
0029
0030 ls prefix/lib # verify libfirebird-dd4hep.so is present
0031
0032 # Make the library and .components file discoverable:
0033 export LD_LIBRARY_PATH="$(pwd)/prefix/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
0034 ```
0035
0036 ### 2. Run ddsim with a steering file
0037
0038 The plugin ships with several pre-made steering files (see below). Pass one
0039 via the `--steeringFile` flag:
0040
0041 ```bash
0042 ddsim \
0043 --steeringFile=my_steering.py \
0044 --compactFile=geometry \
0045 -N=5 \
0046 --outputFile=sim_output.edm4hep.root \
0047 --inputFiles sim_input.hepmc
0048 ```
0049
0050 > (!) Look for EIC specific example below!
0051
0052 This produces `sim_output.firebird.json` — a Firebird-format JSON file
0053 containing the trajectory data.
0054
0055 > **Note:** For large events, or when optical photons are saved, the output
0056 > file can easily reach gigabytes in size.
0057
0058
0059 ## How it works
0060
0061 The plugin provides several Geant4 "actions" that can be injected into DD4hep
0062 processing through a steering file or Python configuration:
0063
0064 - **`FirebirdTrajectoryWriterEventAction`** — the primary action. It collects
0065 Geant4 trajectories at the end of each event (the same trajectories used by
0066 the Geant4 event display) and writes them in Firebird format. Users
0067 configure momentum, position, and particle-type cuts in the steering file
0068 to control output size.
0069
0070 - **`FirebirdTrajectoryWriterSteppingAction`** — uses the Geant4 stepping
0071 action to write data as it is generated. It does not offer advantages over
0072 the event action by default (event-action trajectories may include
0073 additional smoothing points), but **users can modify the C++ code** to
0074 access internal Geant4 data that is only available during stepping: detailed
0075 physics-process information, per-step energy deposits, etc.
0076
0077 - **`TextDumpingSteppingAction`** — a stepping action that writes track and
0078 step data to a plain-text file for custom analysis or visualization (not
0079 Firebird format). Also serves as a simple C++ plugin example.
0080
0081 ### Pre-made steering files
0082
0083 | File | Description |
0084 |------|-------------|
0085 | `firebird_steering.py` | Default. Saves everything above 350 MeV (no optical photons). |
0086 | `cuts_example_steering.py` | Demonstrates all available cuts. |
0087 | `optical_steering.py` | Saves only generator particles and optical photons — useful for inspecting detectors like DIRC. |
0088 | `save_all_steering.py` | Saves all particles above 1 MeV including optical photons. Use with care — easily produces gigabyte-sized files. |
0089
0090
0091 ## Configuration Options
0092
0093 ### FirebirdTrajectoryWriterEventAction
0094
0095 | Parameter | Type | Default | Description |
0096 |-----------|------|---------|-------------|
0097 | `OutputFile` | string | `"trajectories.firebird.json"` | Output JSON file path |
0098 | `ComponentName` | string | `"Geant4Trajectories"` | Group name shown in the Firebird display |
0099 | `SaveOptical` | bool | `false` | Save optical photons regardless of other filters |
0100 | `OnlyPrimary` | bool | `false` | Keep only primary tracks (ParentID = 0) |
0101 | `VertexCut` | bool | `false` | Enable vertex position filtering |
0102 | `VertexZMin` | double | −5000 | Minimum vertex Z [mm] |
0103 | `VertexZMax` | double | 5000 | Maximum vertex Z [mm] |
0104 | `StepCut` | bool | `false` | Enable per-step position filtering |
0105 | `StepZMin` | double | −5000 | Minimum step Z [mm] |
0106 | `StepZMax` | double | 5000 | Maximum step Z [mm] |
0107 | `StepRMax` | double | 5000 | Maximum step radial distance from beam axis [mm] |
0108 | `MomentumMin` | double | 150 | Lower momentum cut [MeV/c] |
0109 | `MomentumMax` | double | 1e12 | Upper momentum cut [MeV/c] |
0110 | `TrackLengthMin` | double | 0 | Minimum track path length [mm] |
0111 | `SaveParticles` | vector\<int\> | `[]` | PDG whitelist. Empty = save all types. |
0112 | `RequireRichTrajectory` | bool | `true` | Only save trajectories that provide proper time information |
0113 | `VerboseTimeExtraction` | bool | `false` | Log time-extraction internals (attribute names, parsed values) |
0114 | `VerboseSteps` | bool | `false` | Log every trajectory point: position, time, and PDG — one line per point |
0115
0116 ### Filter order
0117
0118 Filters are applied in this order:
0119
0120 1. **Particle type** — `SaveOptical` bypasses all other filters for optical
0121 photons; `SaveParticles` restricts to a PDG whitelist.
0122 2. **Track source** — `OnlyPrimary` keeps only ParentID = 0.
0123 3. **Momentum** — tracks outside \[`MomentumMin`, `MomentumMax`\] are dropped.
0124 4. **Track length** — tracks shorter than `TrackLengthMin` are dropped.
0125 5. **Vertex position** — if `VertexCut` is enabled, tracks whose vertex Z
0126 falls outside \[`VertexZMin`, `VertexZMax`\] are dropped.
0127 6. **Rich trajectory** — if `RequireRichTrajectory` is true, non-rich
0128 trajectories (or those without extractable time) are dropped.
0129 7. **Step position** — if `StepCut` is enabled, individual points outside
0130 the Z/R bounds are removed. Tracks with no surviving points are dropped.
0131
0132 ### Steering file example
0133
0134 ```python
0135 event_action = DDG4.EventAction(
0136 kernel, 'FirebirdTrajectoryWriterEventAction/TrajectoryWriter')
0137
0138 event_action.ComponentName = "Geant4Trajectories"
0139 event_action.OutputFile = "mytrajectories.firebird.json"
0140 event_action.OnlyPrimary = True
0141 event_action.MomentumMin = 350 # MeV/c
0142 event_action.StepCut = True
0143 event_action.StepZMin = -3000 # mm
0144 event_action.StepZMax = 3000 # mm
0145 event_action.StepRMax = 2000 # mm
0146 event_action.VerboseSteps = False # set True for per-point diagnostics
0147
0148 kernel.eventAction().add(event_action)
0149 ```
0150
0151 ### FirebirdTrajectoryWriterSteppingAction
0152
0153 Similar configuration options are available for the stepping-action variant.
0154 See the source code for details.
0155
0156
0157 ## EIC-specific example
0158
0159 EIC provides Docker images with the full HEP stack (ROOT, Geant4, DD4hep,
0160 Acts, etc.). You can use
0161 [eic_shell](https://eic.github.io/tutorial-setting-up-environment/index.html)
0162 or the
0163 [eicweb/eic_xl](https://hub.docker.com/r/eicweb/eic_xl/tags) image:
0164
0165 ```bash
0166 docker pull eicweb/eic_xl:nightly
0167 docker run --rm -it \
0168 -v /host/path/to/firebird:/mnt/firebird \
0169 -v /host/path/to/data:/mnt/data \
0170 eicweb/eic_xl:nightly
0171 ```
0172
0173 Inside the container:
0174
0175 ```bash
0176 # Build and install the plugin
0177 cd /mnt/firebird/dd4hep-plugin
0178 cmake -B build -S .
0179 cmake --build build
0180 cmake --install build
0181
0182 export LD_LIBRARY_PATH="$(pwd)/prefix/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
0183
0184 # Load the ePIC detector
0185 source /opt/detector/epic-main/bin/thisepic.sh
0186
0187 # Copy / edit a steering file
0188 cp firebird_steering.py /mnt/data/steering.py
0189
0190 # Grab sample input data
0191 xrdcp root://dtn2001.jlab.org:1094//work/eic2/EPIC/EVGEN/CI/pythia8NCDIS_5x41_minQ2=1_beamEffects_xAngle=-0.025_hiDiv_1_20ev.hepmc3.tree.root \
0192 /mnt/data/test.hepmc3.tree.root
0193
0194 # Run 10 events (note: *.edm4hep.root output name is mandatory)
0195 ddsim \
0196 --steeringFile=/mnt/data/steering.py \
0197 --compactFile=$DETECTOR_PATH/epic_craterlake_5x41.xml \
0198 -N=10 \
0199 --outputFile=/mnt/data/sim_output.edm4hep.root \
0200 --inputFiles /mnt/data/test.hepmc3.tree.root
0201 ```
0202
0203
0204 ## Text stepping-dump format
0205
0206 The `TextDumpingSteppingAction` writes a simple hierarchical text format:
0207
0208 ```
0209 # E - event: run_num event_num
0210 # T - track: id pdg pdg_name status eta phi qOverP px py pz vx vy vz
0211 # P - point: x y z t
0212 E 0 0
0213 T 8 2212 proton 1 3.571 2.262 6.40e-05 -559.9 677.4 15608.9 0.039 0.053 18.658
0214 P 0.039 0.053 18.658 -0.079
0215 P -17.623 21.759 515.686 1.584
0216 P -17.942 22.145 524.567 1.614
0217 ...
0218 ```
0219
0220 Each event (`E`) contains one or more tracks (`T`), each followed by its
0221 step points (`P`). The first `P` after a `T` is the pre-step point; all
0222 subsequent ones are post-step points. Every track has at least two points.