Warning, /analysis/EventDisplayMaker/README.md is written in an unsupported language. File is not indexed.
0001 # EventDisplayMaker
0002
0003 You can load event displays and GDML files for viewing here: [sPHENIX Event Display Online Page](https://www.sphenix.bnl.gov/edisplay/)
0004
0005 Two Fun4All `SubsysReco` modules that write per-event JSON snapshots of
0006 reconstructed tracks — and optionally calorimeter towers — for loading into
0007 a 3D web-based event-display viewer. A full sPHENIX detector geometry
0008 (`gdml/sphenix.gdml`) file is included with an offset of the MVTX so the clusters line up.
0009
0010 There are two event display makers for historical reasons
0011
0012 - **`displayEvents`** — shows everything in a collision. Typically it's crossing zero so that the calorimeters can be shown as well. This was made to showcase full collisions events for the end of RHIC operations.
0013
0014 - **`event_display_maker`** — shows a decay reconstucted by KFParticle, and was the original code that `displayEvents` is derived from. It reads the
0015 output of a prior `KFParticle_sPHENIX` reconstruction, picks out events
0016 where a named "mother" particle (e.g. `K_S0`) falls in a mass window,
0017 and color-codes the daughter tracks by species so the candidate stands
0018 out against the rest of the event.
0019
0020 ## Requirements
0021
0022 Both modules need the same core set of nodes on the tree, and treat every
0023 one of them as a hard requirement — `load_nodes()` returns `ABORTRUN` if
0024 any is missing:
0025
0026 - `SvtxVertexMap`, `SvtxTrackMap`
0027 - `TRKR_CLUSTER` (used to look up cluster global positions for hit points)
0028 - `ActsGeometry` (used to convert cluster keys to global positions)
0029 - `Gl1Packet` — tried first as `GL1RAWHIT`, then `GL1Packet` to get the BCO (users can also request a specific set of BCOs to avoid processing events they don't want or grab one from their analysis they think will look good)
0030 - `TriggerRunInfo`
0031
0032 `event_display_maker` additionally requires a `KFParticle_Container` node
0033 named `<setKFParticleContainerName()>_KFParticle_Container` (default
0034 container name `"reconstructedParticles"`, so the default node name is
0035 `reconstructedParticles_KFParticle_Container`) — this is the output of
0036 whatever `KFParticle_sPHENIX` reconstruction you ran upstream.
0037
0038 Calorimeter nodes are optional and only looked up when `addCaloInfo(true)`
0039 is set. For each of EMCal/IHCal/OHCal, the calibrated tower container is
0040 tried first (`TOWERINFO_CALIB_CEMC`, etc.), falling back to the raw
0041 `TOWERS_CEMC`-style name; the matching `TOWERGEOM_*` container is also
0042 required. A missing calorimeter just gets skipped for that run (`hasEMCal`
0043 etc. get set to `false`) rather than aborting the event.
0044
0045 ## Building
0046
0047 Note the built library name doesn't match the folder name: `configure.ac`
0048 names the package `hf_trigger_data_to_json` for different legacy reasons, so the library you link/load
0049 is `libhf_trigger_data_to_json.la` (`R__LOAD_LIBRARY(libhf_trigger_data_to_json.so)`
0050 in a macro), containing both `displayEvents` and `event_display_maker`.
0051
0052 ## How it works
0053
0054 Both modules follow the same per-event shape; `event_display_maker` adds a
0055 selection/highlighting layer on top.
0056
0057 1. **Node retrieval**, as above — aborts the run if any required node is
0058 missing.
0059 2. **Loop over every reconstructed vertex** in `SvtxVertexMap` for the
0060 event. Each vertex gets its own JSON file, so a multi-vertex event
0061 produces multiple output files. The loop (and the module) stops
0062 producing further output once `setMaxEvtDisplays()` displays have been
0063 written, even mid-event.
0064 3. **(`event_display_maker` only) Select the decay.** Walk the
0065 `KFParticle_Container`, find the entry matching `setMotherName()`
0066 (default `"K_S0"`), and check its reconstructed mass against
0067 `setMassRange()`. Entries matching `setIntermediateNames()` (e.g.
0068 `Lambda0`) are kept separately for drawing. Any KFParticle whose
0069 species is one of `e-, mu-, pi+, K+, proton` **and** whose track shares
0070 the vertex's beam crossing becomes a "trigger" daughter. If fewer than
0071 `setNumberDaughters()` trigger daughters were found, the vertex is
0072 skipped.
0073 4. **Collect every track at the vertex** (`displayEvents`: this is the
0074 whole track set; `event_display_maker`: this is the *background* set,
0075 with the trigger daughters excluded by track ID so they aren't drawn
0076 twice).
0077 5. **Decode triggers** via `TriggerAnalyzer::decodeTriggers()` — this is
0078 called every event but isn't visibly used to gate anything else in the
0079 code as it stands; worth knowing if you're relying on it for trigger
0080 selection.
0081 6. **Compute the BCO** (`Gl1Packet` BCO + track beam-crossing offset) and,
0082 if `useTheseBCOs()` was set, skip this vertex unless its BCO is in that
0083 list.
0084 7. **Build the JSON.** Event metadata (run number, date, primary vertex
0085 position, a caption that differs depending on `plotsApproved()`), then
0086 for each track: its cluster/track-state hit positions (silicon hits
0087 come from the track's silicon seed, since track states don't reliably
0088 carry silicon clusters; TPC hit positions come from the track state
0089 directly, other detectors' hit positions are recomputed via
0090 `ActsGeometry::getGlobalPosition()`), and its momentum, position, decay
0091 length, charge, and draw color. `event_display_maker` additionally
0092 draws the mother and any intermediates as their own track-like entries,
0093 colored distinctly from the daughters and from the background.
0094 8. **(optional) Add calorimeter hits** if `addCaloInfo(true)`, one entry
0095 per tower above an energy threshold, with projective-geometry metadata
0096 (radius range, angular bin size, color, display scale) for each
0097 calorimeter.
0098 9. **Write the file** to `setEventDisplayPath()` as
0099 `EvtDisplay_<run>_<bco>.json` (`displayEvents`) or
0100 `EvtDisplay_<motherName>_<run>_<bco>.json` (`event_display_maker`), and
0101 increment the display counter.
0102
0103 ## Quick start
0104
0105 No example macro ships in this repo yet — these snippets are illustrative,
0106 built directly from the constructors/setters in the header files, not
0107 copied from an existing file.
0108
0109 ```cpp
0110 // General-purpose: show every track at every vertex
0111 displayEvents *disp = new displayEvents("EventDisplay");
0112 disp->setEventDisplayPath("./displays");
0113 disp->setMaxEvtDisplays(20);
0114 disp->addCaloInfo(true);
0115 se->registerSubsystem(disp);
0116 ```
0117
0118 ```cpp
0119 // KFParticle-driven: highlight K-short candidates
0120 event_display_maker *disp = new event_display_maker("KshortDisplay");
0121 disp->setKFParticleContainerName("reconstructedParticles"); // -> reconstructedParticles_KFParticle_Container
0122 disp->setMotherName("K_S0");
0123 disp->setMassRange(0.46, 0.53);
0124 disp->setMaxEvtDisplays(20);
0125 disp->addCaloInfo(true);
0126 se->registerSubsystem(disp);
0127 ```
0128
0129 ## Configuration reference
0130
0131 A number of setters have a default *argument* that differs from the
0132 member's default if the setter is never called at all — worth knowing
0133 since "I didn't call the setter" and "I called it with no arguments" give
0134 you different behavior (maybe because I was lazy or tired). Those cases are called out explicitly below.
0135
0136 ### `displayEvents`
0137
0138 | Setter | Meaning | If never called | If called with no args |
0139 |---|---|---|---|
0140 | `setEventDisplayPath(path)` | Output directory for JSON files | `"./"` | — |
0141 | `setMaxEvtDisplays(max)` | Stop after this many displays | `100` | `10` |
0142 | `setDecayTag(tag)` | Free-text tag shown in the plot caption | `"200 GeV p+p"` | — |
0143 | `useTheseBCOs(bcoList)` | Only write displays for these BCOs | all BCOs | — |
0144 | `plotsApproved(approved)` | Switch the caption between an internal/debug stamp (with BCO) and an approved-looking one | `false` | `true` |
0145 | `addCaloInfo(add)` | Include EMCal/IHCal/OHCal tower hits | `false` | `true` |
0146 | `dontShowTrackClusters(avoid)` | Suppress track hit points from the output (only in `displayEvents`) | `false` | `true` |
0147
0148 ### `event_display_maker`
0149
0150 | Setter | Meaning | If never called | If called with no args |
0151 |---|---|---|---|
0152 | `setKFParticleContainerName(name)` | Base name; node read is `<name>_KFParticle_Container` | `"reconstructedParticles"` | — (required arg) |
0153 | `setNumberDaughters(n)` | Minimum trigger daughters required at a vertex | `2` | `2` |
0154 | `setEventDisplayPath(path)` | Output directory | `"./"` | — |
0155 | `setMassRange(min, max)` | Mother mass window [GeV] | `0.4, 0.6` | `0.48, 0.51` |
0156 | `setMaxEvtDisplays(max)` | Stop after this many displays | `100` | `10` |
0157 | `setMotherName(name)` | Species name to match in the KFParticle container | `"K_S0"` | `"K_S0"` |
0158 | `setIntermediateNames(names)` | Intermediate-resonance species to also draw | *(empty)* | `{"Lambda0"}` |
0159 | `setDecayTag(tag)` | Free-text tag shown in the plot caption | `"200 GeV p+p"` | — |
0160 | `useTheseBCOs(bcoList)` | Only write displays for these BCOs | all BCOs | — |
0161 | `plotsApproved(approved)` | Switch the caption between internal/debug and approved-looking | `false` | `true` |
0162 | `addCaloInfo(add)` | Include EMCal/IHCal/OHCal tower hits | `false` | `true` |
0163
0164 Calorimeter energy thresholds differ between the two classes and aren't
0165 currently exposed as setters: `displayEvents` uses a per-calorimeter
0166 threshold (EMCal 0.08, IHCal 0.01, OHCal 0.04 GeV), while
0167 `event_display_maker` uses one flat threshold (0.005 GeV) for all three.
0168 The projective tower geometry constants (radius range, angular bin size,
0169 display color, scale) are the same fixed sPHENIX detector values in both
0170 classes.
0171
0172 ## Tips and known limitations
0173
0174 - All of `SvtxVertexMap`, `SvtxTrackMap`, `TRKR_CLUSTER`, `ActsGeometry`,
0175 `Gl1Packet`, and `TriggerRunInfo` are hard per-event requirements for
0176 both modules — missing any of them aborts the run, not just the event.
0177 - `event_display_maker`'s daughter-count check
0178 (`kfp_daughters.size() < m_number_of_daughters`) is a coarse
0179 completeness filter, not a guarantee that the *right* daughters were
0180 found — the code's own comment next to it calls this out as "risky."
0181 - One JSON file is written per *vertex*, not per event, so an event with
0182 several reconstructed vertices produces several files with the same run
0183 number but different BCOs.
0184 - `dontShowTrackClusters()` only exists on `displayEvents` — there's no
0185 equivalent toggle on `event_display_maker`.