forked from dglazier/rad
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreport-refactor1.html
More file actions
301 lines (258 loc) · 13.9 KB
/
report-refactor1.html
File metadata and controls
301 lines (258 loc) · 13.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RAD Framework: Combinatorial Analysis Pipeline</title>
<script src="https://cdn.tailwindcss.com"></script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true, theme: 'neutral', securityLevel: 'loose' });
</script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&family=JetBrains+Mono:wght@400;700&display=swap');
body { font-family: 'Inter', sans-serif; background-color: #f8fafc; color: #334155; }
h1, h2, h3 { color: #0f172a; }
.code-font { font-family: 'JetBrains Mono', monospace; }
.card { background: white; border-radius: 0.75rem; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); padding: 2rem; margin-bottom: 2rem; border: 1px solid #e2e8f0; }
.diagram-container { display: flex; justify-content: center; background-color: #ffffff; padding: 1rem; border-radius: 0.5rem; border: 1px solid #e5e7eb; margin: 1.5rem 0; }
.highlight-box { background-color: #eff6ff; border-left: 4px solid #3b82f6; padding: 1rem; border-radius: 0.25rem; }
.alert-box { background-color: #fff1f2; border-left: 4px solid #e11d48; padding: 1rem; border-radius: 0.25rem; color: #881337; }
.map-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.map-table th, .map-table td { border: 1px solid #e2e8f0; padding: 0.5rem; text-align: left; }
.map-table th { background-color: #f1f5f9; color: #475569; font-weight: 600; }
.map-table .idx-col { width: 60px; text-align: center; font-family: 'JetBrains Mono', monospace; color: #2563eb; font-weight: bold; }
.badge { display: inline-block; padding: 0.25em 0.4em; font-size: 75%; font-weight: 700; line-height: 1; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: 0.25rem; }
.badge-base { background-color: #64748b; color: white; }
.badge-derived { background-color: #2563eb; color: white; }
.badge-master { background-color: #7e22ce; color: white; } /* Purple */
.badge-linked { background-color: #059669; color: white; } /* Green */
</style>
</head>
<body class="pb-12">
<header class="bg-slate-900 text-white py-10 mb-8 shadow-xl">
<div class="container mx-auto px-6">
<div class="flex flex-col md:flex-row justify-between items-center">
<div>
<h1 class="text-4xl font-bold mb-2">RAD Framework</h1>
<h2 class="text-xl font-light text-slate-300">Combinatorial Reaction Analysis Pipeline</h2>
</div>
<div class="mt-4 md:mt-0 bg-blue-600 px-4 py-2 rounded-full text-sm font-semibold">
Project: Z Boson Search (e + p → e' + n + Z)
</div>
</div>
</div>
</header>
<main class="container mx-auto px-6 max-w-6xl">
<section class="card border-t-4 border-blue-600">
<h2 class="text-3xl font-bold mb-4">1. The Scientific Objective</h2>
<p class="text-lg mb-6">
Detectors produce "soups" of particles. The RAD framework allows us to filter and reconstruct specific decay chains where <strong>particle identity is ambiguous</strong>.
</p>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<div>
<h3 class="text-xl font-bold text-slate-800 mb-3">The Ambiguity Problem</h3>
<p class="mb-4">
Consider the electro-production of a $Z$ state (decaying to $J/\psi \, \pi^+$).
</p>
<div class="bg-slate-100 p-4 rounded-md code-font text-sm mb-4">
Reaction Final State:<br>
1. <strong>e'</strong> (Scattered Electron)<br>
2. <strong>n</strong> (Neutron)<br>
3. <strong>π<sup>+</sup></strong> (Pion)<br>
4. <strong>e<sup>+</sup></strong> (Positron from J/ψ)<br>
5. <strong>e<sup>-</sup></strong> (Electron from J/ψ)
</div>
<div class="alert-box mb-4">
<strong>The Conflict:</strong> We have <strong>two electrons</strong> in the final state.
<ul class="list-disc list-inside mt-2 text-sm">
<li>1 × Scattered Beam Electron</li>
<li>1 × Decay Electron ($J/\psi \to e^+e^-$)</li>
</ul>
</div>
</div>
<div class="diagram-container flex-col">
<div class="text-center font-bold mb-2">The Detector View vs. Physics View</div>
<pre class="mermaid">
graph TD
subgraph RawData ["Raw Detector Event"]
E1["Track 1: Electron (-)"]
E2["Track 2: Electron (-)"]
P1["Track 3: Positron (+)"]
end
subgraph Hypothesis ["Ambiguity"]
OptionA["Hypothesis A:<br/>Track 1 = Scattered<br/>Track 2 = J/psi decay"]
OptionB["Hypothesis B:<br/>Track 2 = Scattered<br/>Track 1 = J/psi decay"]
end
RawData --> Hypothesis
P1 -.->|Unique Charge| OptionA
P1 -.->|Unique Charge| OptionB
</pre>
</div>
</div>
</section>
<section class="card bg-slate-50 border border-slate-200">
<h2 class="text-2xl font-bold mb-4 text-slate-800">2. The Combinatorial Engine</h2>
<p class="mb-4 text-lg">
The core feature of this framework is the <strong>Production of Combinatorial Events</strong>.
We do not simply filter events; we <em>expand</em> them. A single raw event with ambiguous tracks is exploded into multiple "Candidate Events," each representing a unique physical permutation.
</p>
<div class="diagram-container">
<pre class="mermaid">
sequenceDiagram
participant Raw as Raw Event (N=1)
participant Engine as Combinatorial Engine
participant Analysis as Physics Analysis
Note over Raw: 2 Electrons Found
Raw->>Engine: hepmc.makeCombinations()
rect rgb(240, 248, 255)
Note over Engine: Permutation Logic
Engine->>Analysis: Candidate 1 (e1=Scat, e2=Decay)
Engine->>Analysis: Candidate 2 (e2=Scat, e1=Decay)
end
Note over Analysis: Analysis runs TWICE<br/>for this single raw event.
</pre>
</div>
</section>
<section class="card">
<h2 class="text-2xl font-bold mb-6">3. Technical Architecture & The Particle Map</h2>
<p class="mb-6">
We decouple the <strong>Computational Engine</strong> from the <strong>Physics Topology</strong>. A critical component of this engine is the <strong>Static Particle Map</strong> calculated by the <code>ParticleCreator</code>.
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 mb-8">
<div class="border rounded p-4 bg-slate-50">
<h3 class="font-bold text-slate-800 mb-2 border-b pb-2">Class Structure</h3>
<pre class="mermaid">
classDiagram
class KinematicsProcessor {
<<Base Engine>>
+Init()
+operator()
}
class KinematicProcElectro {
<<Physics Logic>>
+Constructor()
}
class ParticleCreator {
<<The Architect>>
+InitMap()
}
KinematicsProcessor <|-- KinematicProcElectro
KinematicsProcessor *-- ParticleCreator
KinematicProcElectro ..> ParticleCreator : Configures Topology
</pre>
</div>
<div class="border rounded p-4 bg-white shadow-sm">
<h3 class="font-bold text-blue-800 mb-2 border-b pb-2">The Static Particle Map</h3>
<p class="text-sm text-gray-600 mb-3">
To enable vectorization, the <code>ParticleCreator</code> assigns a <strong>Fixed Integer Index</strong> to every particle role in the reaction. This map is calculated once at setup.
</p>
<table class="map-table">
<thead>
<tr>
<th class="idx-col">Index</th>
<th>Physics Role</th>
<th>Source</th>
</tr>
</thead>
<tbody>
<tr><td class="idx-col">0</td><td>Beam Ion (p)</td><td>Beams Group</td></tr>
<tr><td class="idx-col">1</td><td>Beam Electron (e)</td><td>Beams Group</td></tr>
<tr><td class="idx-col">2</td><td>Neutron (n)</td><td>Baryons Group</td></tr>
<tr><td class="idx-col">3</td><td>Pion (π+)</td><td>Mesons Group</td></tr>
<tr><td class="idx-col">4</td><td>Scat. Electron (e')</td><td>ScatEle Group</td></tr>
<tr class="bg-blue-50"><td class="idx-col">5</td><td><strong>γ*</strong> (Virt. Photon)</td><td>Created (Diff)</td></tr>
<tr class="bg-blue-50"><td class="idx-col">6</td><td><strong>J/ψ</strong></td><td>Created (Sum)</td></tr>
<tr class="bg-blue-50"><td class="idx-col">7</td><td><strong>Z</strong></td><td>Created (Sum)</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<section class="card bg-slate-900 text-slate-200">
<h2 class="text-2xl font-bold text-white mb-4">4. Standard Analysis Script</h2>
<p class="text-slate-400 mb-4">This demonstrates a single-hypothesis analysis (Assuming the neutron is detected).</p>
<div class="font-mono text-sm overflow-x-auto">
<pre><code class="language-cpp">// 1. Define Input Candidates
rad::config::HepMCElectro hepmc{"tree", "file.root"};
hepmc.setParticleCandidates("ele", {2, 6}); // Ambiguous tracks
hepmc.setParticleIndex("pos", 3);
hepmc.setParticleIndex("pip", 4);
// 2. Generate Combinations
hepmc.makeCombinations();
// 3. Instantiate Physics Processor
rad::KinematicProcElectro kine{&hepmc};
// 4. Define Topology (Map Creation)
kine.Creator().Sum("Jpsi", {{"ele", "pos"}});
kine.Creator().Sum("Z", {{"Jpsi", "pip"}});
// 5. Run Analysis
kine.Init();
kine.Q2();
kine.Mass("JpsiMass", {"Jpsi"});
hepmc.Snapshot("Z_Analysis.root");</code></pre>
</div>
</section>
<section class="card border-l-8 border-purple-600">
<h2 class="text-2xl font-bold mb-4">5. Advanced: Multi-Hypothesis Analysis</h2>
<p class="text-lg mb-4">
Often, we want to compare two physical assumptions on the <strong>same event</strong>. For example:
</p>
<ul class="list-disc list-inside mb-4 ml-4 text-gray-700">
<li><strong>Hypothesis A:</strong> The recoil is the <strong>Detected Neutron</strong> (<code>n</code>).</li>
<li><strong>Hypothesis B:</strong> The recoil is a <strong>Calculated Neutron</strong> (<code>n_calc</code>) derived from missing momentum.</li>
</ul>
<p class="mb-4">
To do this efficiently without re-running the expensive kinematic calculations, we use a <strong>Master/Linked</strong> processor pattern.
</p>
<div class="diagram-container">
<pre class="mermaid">
sequenceDiagram
participant User
participant Master as Master Processor
participant Linked as Linked Processor (n_calc)
participant Data as Data Array (RAM)
Note over Master: Configured to create ALL particles<br/>(J/psi, Z, n, n_calc)
User->>Master: Init()
Master->>Data: Calculates 4-Vectors [Index 0...N]
Note over Linked: "For me, Baryon = n_calc"
User->>Linked: InitLinked(Master)
Linked->>Data: Aliases Master's Array
User->>Master: T() -> Uses Data[Index_n]
User->>Linked: T() -> Uses Data[Index_n_calc]
</pre>
</div>
<h3 class="font-bold text-slate-800 mt-6 mb-2">Example Code: Standard vs. Calculated Neutron</h3>
<div class="bg-gray-900 text-slate-300 p-4 rounded-md font-mono text-sm overflow-x-auto">
<pre><code class="language-cpp">// 1. MASTER PROCESSOR (Calculates Everything)
// Suffix = "" (Default). This runs the heavy event loop.
rad::KinematicProcElectro kine_std{&hepmc, ""};
// A. Define intermediates common to both
kine_std.Creator().Sum("Jpsi", {{"ele", "pos"}});
kine_std.Creator().Sum("Z", {{"Jpsi", "pip"}});
// B. Define Calculated Neutron (Even if not used in kine_std physics!)
// n_calc = (Beam + Target) - (ScatEle + Z)
kine_std.Creator().Diff("n_calc", {{names::Beams()}, {names::ScatEle(), "Z"}});
// C. Run the loop (Calculates all vectors)
kine_std.Init();
kine_std.Q2(); // -> rec_Q2
// ---------------------------------------------------------
// 2. LINKED PROCESSOR (Reuses Data)
// Clone configuration, add suffix "_calc"
rad::KinematicProcElectro kine_calc(kine_std, "_calc");
// A. Override Topology
// Tell this processor: "For you, the Baryon is 'n_calc', not 'n'"
kine_calc.Creator().OverrideGroup(names::OrderBaryons(), {"n_calc"});
// B. Link Data (Zero Computational Cost)
kine_calc.InitLinked(kine_std);
// C. Calculate Physics
// This T calculation automatically uses 'n_calc' because of the override
kine_calc.T(); // -> rec_t_calc (stored in unique column)
</code></pre>
</div>
</section>
</main>
<footer class="text-center text-gray-500 text-sm py-8">
<p>Generated for the RAD Framework Collaboration</p>
</footer>
</body>
</html>