Skip to content

Commit 1694b7f

Browse files
Adding agents.md
1 parent 31c22ce commit 1694b7f

1 file changed

Lines changed: 225 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# AGENTS.md — EventNtuple Coding Agent Instructions
2+
3+
## Project Overview
4+
5+
EventNtuple is a Mu2e (Fermilab) art/ROOT analysis ntuple package. It fills a flat
6+
ROOT ntuple from Mu2e reconstruction output (KalSeeds, CaloCluster, CRV, etc.) and
7+
provides a Python/ROOT analysis library (RooUtil) and distributed job runner (roodask).
8+
9+
**Framework:** `art` (Fermilab) + `cetmodules` CMake layer + `fhiclcpp` configuration.
10+
**Languages:** C++17 (modules, helpers, structs), FHiCL (job config), Python 3.12+ (helpers/tools).
11+
12+
---
13+
14+
## Build Commands
15+
16+
Environment must be set up via Muse before building:
17+
18+
```bash
19+
mu2einit
20+
muse setup # or: muse setup AnalysisMDC2020 / AnalysisMDC2025
21+
muse build -j4 --mu2eCompactPrint
22+
```
23+
24+
Alternative Spack-based build:
25+
26+
```bash
27+
spack develop event-ntuple@main
28+
spack concretize -f && spack install
29+
```
30+
31+
Run the ntuple maker:
32+
33+
```bash
34+
mu2e -c EventNtuple/fcl/from_mcs-mockdata.fcl -S your-art-filelist.txt
35+
```
36+
37+
---
38+
39+
## Test / Validation Commands
40+
41+
All validation scripts are in `validation/`. There is no unit test framework; tests
42+
run the full art job and compare histograms.
43+
44+
```bash
45+
# Quick smoke test: runs from_mcs-mockdata.fcl, creates histograms
46+
bash validation/quick_test.sh
47+
48+
# Test all FCL files for a campaign
49+
bash validation/test_fcls.sh MDC2020
50+
bash validation/test_fcls.sh MDC2025
51+
bash validation/test_fcls.sh Run1B
52+
53+
# Test RooUtil library
54+
bash validation/test_rooutil.sh
55+
56+
# Test all RooUtil example macros
57+
bash validation/test_rooutil_examples.sh
58+
59+
# Test Python ntuplehelper
60+
python validation/ntuplehelper-test.py
61+
62+
# Test roodask distributed runner
63+
bash validation/roodask_test.sh
64+
```
65+
66+
To run a **single FCL test** manually:
67+
68+
```bash
69+
mu2e -c EventNtuple/fcl/<specific>.fcl -S filelist.txt -n 100
70+
```
71+
72+
---
73+
74+
## FHiCL Configuration Structure
75+
76+
### Branch / MC Data Configuration (Key Area for Improvement)
77+
78+
Branch configuration is defined in `fcl/prolog.fcl`. Each track type is a FHiCL table:
79+
80+
```
81+
DeM : {
82+
input : "MergeKKDeM" # input KalSeedPtr collection tag
83+
branch : "dem" # output ROOT branch name
84+
options : {
85+
fillMC : true # toggle MC truth filling for this branch
86+
fillHits : true # toggle hit-level info
87+
genealogyDepth : -1 # MC genealogy depth (-1 = all)
88+
matchDepth : -1 # MC match depth (-1 = all)
89+
}
90+
trkQualTags : ["TrkQualDeM"]
91+
trkPIDTags : ["TrkPIDDeM"]
92+
}
93+
```
94+
95+
Global MC switch lives in `EventNtupleMaker` config: `FillMCInfo : true/false`.
96+
Per-branch MC is controlled by `options.fillMC`. Both must be true for MC to fill.
97+
98+
**Current issue:** Branch on/off and MC on/off are scattered across individual track
99+
tables in `prolog.fcl` and duplicated in every campaign FCL. When adding a new
100+
track type or toggling MC for a subset of branches, edits are required in many places.
101+
102+
**Preferred direction for improvement:**
103+
- Define a single `BranchOptions` prolog table with canonical defaults.
104+
- Use `@table::` inheritance for per-branch overrides rather than full re-specification.
105+
- Consider a top-level `MCOptions` table that can be overlaid to flip all `fillMC` flags.
106+
- Campaign FCLs should `#include prolog.fcl` and only override what differs.
107+
108+
---
109+
110+
## C++ Code Style
111+
112+
### File Naming
113+
- Headers: `PascalCase.hh` in `inc/`
114+
- Sources: `PascalCase.cc` in `src/`
115+
- Module plugins: `PascalCase_module.cc`
116+
117+
### Namespaces
118+
All production code lives in `namespace mu2e {}`.
119+
RooUtil library uses `namespace rooutil {}`.
120+
121+
### Struct / Class Naming
122+
- Ntuple info structs: `PascalCase` ending in `Info` or `InfoMC` (e.g. `TrkInfo`, `CaloClusterInfoMC`)
123+
- Each struct lives in its own `inc/<StructName>.hh` header
124+
125+
### Member Naming
126+
- Module private members: leading underscore (`_conf`, `_fillmc`, `_ntuple`)
127+
- Struct data members: `snake_case` (no underscore suffix); initialized to sentinel values
128+
- Integers: `int status = -1;`
129+
- Floats: `float chisq = -1;` or `float mom = std::numeric_limits<float>::min();`
130+
- Booleans: `bool flag = false;`
131+
132+
### Info Struct Pattern (required for `ntuplehelper` compatibility)
133+
```cpp
134+
namespace mu2e {
135+
struct FooInfo {
136+
// required comment on every leaf for ntuplehelper autodoc
137+
int status = -1; // fit status
138+
float mom = -1; // momentum at tracker entrance (MeV/c)
139+
140+
void reset() { *this = FooInfo(); }
141+
};
142+
}
143+
```
144+
Every leaf **must** have an inline `//` comment — this is parsed by `ntuplehelper --list-all-branches`.
145+
146+
### Includes (C++ ordering)
147+
1. Mu2e Offline headers (`Offline/…`)
148+
2. art framework headers (`art/…`, `canvas/…`, `fhiclcpp/…`)
149+
3. ROOT headers
150+
4. Local EventNtuple headers (`EventNtuple/inc/…`)
151+
5. C++ standard library (`<vector>`, `<string>`, etc.)
152+
153+
### Error Handling
154+
- Throw via `cet::exception`: `throw cet::exception("EventNtuple") << "message";`
155+
- Do not use raw `std::exception` or `exit()` in art modules
156+
- Warnings via `mf::LogWarning("EventNtuple") << "message";`
157+
158+
### FHiCL Config Structs (in modules)
159+
```cpp
160+
struct Config {
161+
fhicl::Atom<bool> fillMC { Name("FillMCInfo"), Comment("Fill MC info"), true };
162+
fhicl::Table<SubConf> sub { Name("SubConfig") };
163+
fhicl::Sequence<art::InputTag> tags { Name("InputTags") };
164+
};
165+
```
166+
167+
---
168+
169+
## Python Code Style
170+
171+
- Python 3.12+; no type annotations required but welcome
172+
- `snake_case` for all functions, methods, and variables
173+
- Class names: `PascalCase`
174+
- No f-strings required; format strings acceptable
175+
- `roodask/roodask.py` is intentionally a **single-file script** — do not split it
176+
177+
---
178+
179+
## FHiCL Style Guidelines
180+
181+
- Use `BEGIN_PROLOG` / `END_PROLOG` for all reusable tables
182+
- Use `@local::` for prolog references; `@table::` for struct inheritance/merging
183+
- Do not duplicate full table bodies — inherit with `@table::Base` then override fields
184+
- One `#include` per dependency; include Offline prologs before EventNtuple prologs
185+
- Comment all numeric constants with units: `MaxDE : 500.0 # MeV`
186+
- Boolean flags: `true` / `false` (lowercase, no quotes)
187+
188+
---
189+
190+
## Adding a New Branch (Developer Checklist)
191+
192+
See `doc/developers.md` for the full walkthrough. Summary:
193+
194+
1. Create `inc/FooInfo.hh` with commented struct (see struct pattern above)
195+
2. Add fill logic to `src/InfoStructHelper.cc` (or `InfoMCStructHelper.cc` for MC)
196+
3. Register branch in `src/EventNtupleMaker_module.cc`
197+
4. Add prolog table to `fcl/prolog.fcl` using `@table::` inheritance
198+
5. Regenerate `doc/branches.md`: `ntuplehelper --list-all-branches --export-to-md`
199+
6. Run `bash validation/quick_test.sh` to confirm no runtime errors
200+
201+
---
202+
203+
## Key Files Reference
204+
205+
| File | Role |
206+
|---|---|
207+
| `src/EventNtupleMaker_module.cc` | Main `art::EDAnalyzer`; branch registration and filling |
208+
| `src/InfoStructHelper.cc` | Reco → struct fill logic |
209+
| `src/InfoMCStructHelper.cc` | MC truth → struct fill logic |
210+
| `inc/*Info*.hh` | One ntuple branch struct per file |
211+
| `fcl/prolog.fcl` | Master FHiCL prolog (track types, branch configs, MC options) |
212+
| `fcl/from_mcs-mockdata.fcl` | Default/reference job FCL |
213+
| `helper/ntuplehelper.py` | Python ntuple inspection tool |
214+
| `rooutil/inc/RooUtil.hh` | ROOT analysis library |
215+
| `rooutil/roodask/roodask.py` | Dask distributed job runner (single-file) |
216+
| `validation/quick_test.sh` | Primary smoke test |
217+
| `doc/developers.md` | Developer guide for adding branches |
218+
219+
---
220+
221+
## roodask Sub-tool (rooutil/roodask/)
222+
223+
See `rooutil/roodask/.github/copilot-instructions.md` for detailed architecture.
224+
Key points: single-file CLI, auto-generates C++ `main()` wrapper, shared NFS filesystem,
225+
full environment propagated to Dask workers. Do not split `roodask.py` into multiple files.

0 commit comments

Comments
 (0)