HPS-MC
 
Loading...
Searching...
No Matches
add_mother_full_truth.cc
Go to the documentation of this file.
1#include <stdio.h>
2#include <stdlib.h>
3#include <math.h>
4#include <string.h>
5#include <stdhep_util.hh>
6
7#include <unistd.h>
8#include <iostream>
9#include <vector>
10using namespace std;
11
18const double ELECTRON_MASS = 0.000511;
19const double BEAM_ENERGY = 3.74;
20
22 int idhep;
23 int isthep;
24 int jmohep[2];
25 double phep[5]; // px, py, pz, E, mass
26};
27
33
34bool read_lhe_event_aprime(FILE* lhe_file, int nup, LHEParticle& scattered_electron,
35 LHEParticle& aprime, int id_pair) {
36 char line[1000];
37
38 bool found_aprime = false;
39 bool found_scattered = false;
40
41 // Read all particles in the event
42 for (int i = 0; i < nup; i++) {
43 if (fgets(line, 1000, lhe_file) == NULL) return false;
44
45 LHEParticle temp;
46 sscanf(line, "%d %d %d %d %*d %*d %lf %lf %lf %lf %lf",
47 &temp.idhep, &temp.isthep,
48 &temp.jmohep[0], &temp.jmohep[1],
49 &temp.phep[0], &temp.phep[1], &temp.phep[2],
50 &temp.phep[3], &temp.phep[4]);
51
52 // Find A-prime (id_pair, status 2)
53 if (temp.idhep == id_pair && temp.isthep == 2) {
54 aprime = temp;
55 found_aprime = true;
56 }
57
58 // Find scattered electron (11, status 1, energy < beam energy)
59 if (temp.idhep == 11 && temp.isthep == 1 && temp.phep[3] < BEAM_ENERGY) {
60 scattered_electron = temp;
61 found_scattered = true;
62 }
63 }
64
65 if (!found_aprime || !found_scattered) {
66 fprintf(stderr, "Error: Could not find required particles in A-prime LHE event\n");
67 fprintf(stderr, " Found pair particle (%d): %d, Found scattered electron: %d\n",
68 id_pair, found_aprime, found_scattered);
69 return false;
70 }
71
72 return true;
73}
74
75bool read_lhe_event_radiative(FILE* lhe_file, int nup, LHEParticle& scattered_lepton,
76 LHEParticle& electron, LHEParticle& positron) {
77 char line[1000];
78
79 bool found_scattered = false;
80 bool found_electron = false;
81 bool found_positron = false;
82
83 // Read all particles in the event
84 for (int i = 0; i < nup; i++) {
85 if (fgets(line, 1000, lhe_file) == NULL) return false;
86
87 LHEParticle temp;
88 sscanf(line, "%d %d %d %d %*d %*d %lf %lf %lf %lf %lf",
89 &temp.idhep, &temp.isthep,
90 &temp.jmohep[0], &temp.jmohep[1],
91 &temp.phep[0], &temp.phep[1], &temp.phep[2],
92 &temp.phep[3], &temp.phep[4]);
93
94 // Find scattered lepton (13, status 1, energy < beam energy)
95 if (temp.idhep == 13 && temp.isthep == 1 && temp.phep[3] < BEAM_ENERGY) {
96 scattered_lepton = temp;
97 found_scattered = true;
98 }
99
100 // Find electron (11, status 1)
101 if (temp.idhep == 11 && temp.isthep == 1) {
102 electron = temp;
103 found_electron = true;
104 }
105
106 // Find positron (-11, status 1)
107 if (temp.idhep == -11 && temp.isthep == 1) {
108 positron = temp;
109 found_positron = true;
110 }
111 }
112
113 if (!found_scattered || !found_electron || !found_positron) {
114 fprintf(stderr, "Error: Could not find required particles in radiative LHE event\n");
115 fprintf(stderr, " Found scattered lepton: %d, Found electron: %d, Found positron: %d\n",
116 found_scattered, found_electron, found_positron);
117 return false;
118 }
119
120 return true;
121}
122
123bool read_lhe_event(FILE* lhe_file, EventType& event_type, int& nup,
124 LHEParticle& scattered_particle, LHEParticle& pair_or_electron,
125 LHEParticle& positron, int id_pair) {
126 char line[1000];
127
128 // Find <event> tag
129 bool found_event = false;
130 while (fgets(line, 1000, lhe_file) != NULL) {
131 if (strstr(line, "<event") != NULL) {
132 found_event = true;
133 break;
134 }
135 }
136
137 if (!found_event) return false;
138
139 // Read event header
140 if (fgets(line, 1000, lhe_file) == NULL) return false;
141 sscanf(line, "%d", &nup);
142
143 // Determine event type
144 if (nup == 7) {
145 event_type = EVENT_APRIME;
146 return read_lhe_event_aprime(lhe_file, nup, scattered_particle, pair_or_electron, id_pair);
147 } else if (nup == 6) {
148 event_type = EVENT_RADIATIVE;
149 return read_lhe_event_radiative(lhe_file, nup, scattered_particle, pair_or_electron, positron);
150 } else {
151 fprintf(stderr, "Error: Unknown event type with nup=%d (expected 6 or 7)\n", nup);
152 event_type = EVENT_UNKNOWN;
153 return false;
154 }
155}
156
157int main(int argc, char** argv)
158{
159 int id_beam = 623;
160 int id_pair = 622;
161
162 int c;
163
164 while ((c = getopt(argc, argv, "hi:j:")) != -1) {
165 switch (c) {
166 case 'h':
167 printf("-h: print this help\n");
168 printf("-i: PDG ID of beam particle (scattered electron/muon, default 623)\n");
169 printf("-j: PDG ID of pair particle (A-prime/virtual photon, default 622)\n");
170 printf("Usage: %s [-i beam_id] [-j pair_id] <input stdhep> <input lhe> <output stdhep>\n", argv[0]);
171 return 0;
172 case 'i':
173 id_beam = atoi(optarg);
174 break;
175 case 'j':
176 id_pair = atoi(optarg);
177 break;
178 case '?':
179 printf("Invalid option or missing option argument; -h to list options\n");
180 return 1;
181 default:
182 abort();
183 }
184 }
185
186 if (argc - optind < 3) {
187 printf("Usage: %s [-i beam_id] [-j pair_id] <input stdhep> <input lhe> <output stdhep>\n", argv[0]);
188 printf("Use -h for help\n");
189 return 1;
190 }
191
192 int istream = 0;
193 int ostream = 1;
194
195 // Open input STDHEP file
196 int n_events = open_read(argv[optind], istream);
197 if (n_events <= 0) {
198 fprintf(stderr, "Error: Could not open STDHEP file %s\n", argv[optind]);
199 return 1;
200 }
201
202 // Open input LHE file
203 FILE* lhe_file = fopen(argv[optind + 1], "r");
204 if (!lhe_file) {
205 fprintf(stderr, "Error: Could not open LHE file %s\n", argv[optind + 1]);
206 close_read(istream);
207 return 1;
208 }
209
210 // Open output STDHEP file
211 open_write(argv[optind + 2], ostream, n_events);
212
213 printf("Processing events with:\n");
214 printf(" Beam particle ID: %d\n", id_beam);
215 printf(" Pair particle ID: %d\n", id_pair);
216
217 int event_count = 0;
218 int aprime_count = 0;
219 int radiative_count = 0;
220
221 // Process each event
222 while (true) {
223 // Read STDHEP event
224 if (!read_next(istream)) {
225 break; // No more events
226 }
227
228 vector<stdhep_entry> input_event;
229 int nevhep = read_stdhep(&input_event);
230
231 // Read LHE event
232 EventType event_type;
233 int nup;
234 LHEParticle scattered_particle, pair_or_electron, positron;
235
236 if (!read_lhe_event(lhe_file, event_type, nup, scattered_particle,
237 pair_or_electron, positron, id_pair)) {
238 fprintf(stderr, "Error reading LHE event %d\n", event_count);
239 break;
240 }
241
242 // Build output event with unified logic
243 vector<stdhep_entry> output_event;
244
245 if (event_type == EVENT_APRIME) {
246 aprime_count++;
247
248 // ===== Find particles in STDHEP by mother relationship =====
249
250 // Find scattered electron: jmohep[0] = 0 AND idhep = 11
251 int scattered_idx = -1;
252 for (size_t i = 0; i < input_event.size(); i++) {
253 if (input_event[i].jmohep[0] == 0 && input_event[i].idhep == 11) {
254 scattered_idx = i;
255 break;
256 }
257 }
258
259 // Find e+e- pair: jmohep[0] = 1 AND idhep = ±11
260 int electron_idx = -1;
261 int positron_idx = -1;
262 int pair_count = 0;
263
264 for (size_t i = 0; i < input_event.size(); i++) {
265 if (input_event[i].jmohep[0] == 1) {
266 if (input_event[i].idhep == 11) {
267 if (electron_idx == -1) {
268 electron_idx = i;
269 pair_count++;
270 }
271 } else if (input_event[i].idhep == -11) {
272 if (positron_idx == -1) {
273 positron_idx = i;
274 pair_count++;
275 }
276 }
277 }
278 }
279
280 // Validation
281 if (electron_idx == -1 || positron_idx == -1) {
282 fprintf(stderr, "Error: Event %d - Could not find e+e- pair with jmohep[0]=1\n", event_count);
283 fprintf(stderr, " Found electron: %d, Found positron: %d\n",
284 (electron_idx != -1), (positron_idx != -1));
285 break;
286 }
287
288 if (pair_count > 2) {
289 fprintf(stderr, "Warning: Event %d - Found %d particles with jmohep[0]=1, using first two\n",
290 event_count, pair_count);
291 }
292
293 if (input_event.size() > 3 && scattered_idx != -1) {
294 printf("Info: A-prime event %d has %lu particles (>3), ignoring extras\n",
295 event_count, input_event.size());
296 }
297
298 // Determine vertex for scattered electron (623)
299 double scattered_vertex[4];
300 if (scattered_idx != -1) {
301 // Use scattered electron's vertex
302 for (int j = 0; j < 4; j++) {
303 scattered_vertex[j] = input_event[scattered_idx].vhep[j];
304 }
305 } else {
306 // No scattered electron found (N=2 case), use (0, 0, 0.02, 0)
307 scattered_vertex[0] = 0.0;
308 scattered_vertex[1] = 0.0;
309 scattered_vertex[2] = 0.02;
310 scattered_vertex[3] = 0.0;
311 }
312
313 // ===== Entry 0: Scattered electron (id_beam) =====
314 stdhep_entry entry0;
315 entry0.isthep = 1;
316 entry0.idhep = id_beam;
317 entry0.jmohep[0] = 0;
318 entry0.jmohep[1] = 0;
319 entry0.jdahep[0] = 0;
320 entry0.jdahep[1] = 0;
321 entry0.phep[0] = scattered_particle.phep[0];
322 entry0.phep[1] = scattered_particle.phep[1];
323 entry0.phep[2] = scattered_particle.phep[2];
324 entry0.phep[3] = scattered_particle.phep[3];
325 entry0.phep[4] = ELECTRON_MASS;
326 for (int j = 0; j < 4; j++) {
327 entry0.vhep[j] = scattered_vertex[j];
328 }
329 output_event.push_back(entry0);
330
331 // ===== Entry 1: A-prime (id_pair) =====
332 stdhep_entry entry1;
333 entry1.isthep = 2;
334 entry1.idhep = id_pair;
335 entry1.jmohep[0] = 0;
336 entry1.jmohep[1] = 0;
337 entry1.jdahep[0] = 2;
338 entry1.jdahep[1] = 3;
339 entry1.phep[0] = pair_or_electron.phep[0];
340 entry1.phep[1] = pair_or_electron.phep[1];
341 entry1.phep[2] = pair_or_electron.phep[2];
342 entry1.phep[3] = pair_or_electron.phep[3];
343 entry1.phep[4] = pair_or_electron.phep[4];
344 // Use e+e- vertex (displaced vertex)
345 for (int j = 0; j < 4; j++) {
346 entry1.vhep[j] = input_event[electron_idx].vhep[j];
347 }
348 output_event.push_back(entry1);
349
350 // ===== Entry 2: Positron (-11) =====
351 stdhep_entry entry2 = input_event[positron_idx];
352 entry2.jmohep[0] = 2; // Mother is entry 1 (the 622)
353 entry2.jmohep[1] = 0;
354 entry2.phep[4] = ELECTRON_MASS;
355 output_event.push_back(entry2);
356
357 // ===== Entry 3: Electron (11) =====
358 stdhep_entry entry3 = input_event[electron_idx];
359 entry3.jmohep[0] = 2; // Mother is entry 1 (the 622)
360 entry3.jmohep[1] = 0;
361 entry3.phep[4] = ELECTRON_MASS;
362 output_event.push_back(entry3);
363
364 } else if (event_type == EVENT_RADIATIVE) {
365 radiative_count++;
366
367 // ===== Find particles in STDHEP by mother relationship =====
368
369 // Find scattered lepton: jmohep[0] = 0 AND idhep = 13
370 int scattered_idx = -1;
371 for (size_t i = 0; i < input_event.size(); i++) {
372 if (input_event[i].jmohep[0] == 0 && input_event[i].idhep == 13) {
373 scattered_idx = i;
374 break;
375 }
376 }
377
378 // Find e+e- pair: jmohep[0] = 1 AND idhep = ±11
379 // For radiative, if no particles with jmohep[0]=1, check jmohep[0]=0
380 int electron_idx = -1;
381 int positron_idx = -1;
382 int pair_count = 0;
383
384 // First try jmohep[0] = 1
385 for (size_t i = 0; i < input_event.size(); i++) {
386 if (input_event[i].jmohep[0] == 1) {
387 if (input_event[i].idhep == 11) {
388 if (electron_idx == -1) {
389 electron_idx = i;
390 pair_count++;
391 }
392 } else if (input_event[i].idhep == -11) {
393 if (positron_idx == -1) {
394 positron_idx = i;
395 pair_count++;
396 }
397 }
398 }
399 }
400
401 // If not found with jmohep[0]=1, try jmohep[0]=0 (radiative default case)
402 if (electron_idx == -1 || positron_idx == -1) {
403 for (size_t i = 0; i < input_event.size(); i++) {
404 if (input_event[i].jmohep[0] == 0) {
405 if (input_event[i].idhep == 11 && electron_idx == -1) {
406 electron_idx = i;
407 } else if (input_event[i].idhep == -11 && positron_idx == -1) {
408 positron_idx = i;
409 }
410 }
411 }
412 }
413
414 // Validation
415 if (electron_idx == -1 || positron_idx == -1) {
416 fprintf(stderr, "Error: Event %d - Could not find e+e- pair in radiative event\n", event_count);
417 fprintf(stderr, " Found electron: %d, Found positron: %d\n",
418 (electron_idx != -1), (positron_idx != -1));
419 break;
420 }
421
422 if (pair_count > 2) {
423 fprintf(stderr, "Warning: Event %d - Found %d particles with jmohep[0]=1, using first two\n",
424 event_count, pair_count);
425 }
426
427 if (input_event.size() > 2 && scattered_idx != -1) {
428 printf("Info: Radiative event %d has %lu particles (>2), ignoring extras\n",
429 event_count, input_event.size());
430 }
431
432 // Determine vertex for scattered lepton (623)
433 double scattered_vertex[4];
434 if (scattered_idx != -1) {
435 // Use scattered lepton's vertex
436 for (int j = 0; j < 4; j++) {
437 scattered_vertex[j] = input_event[scattered_idx].vhep[j];
438 }
439 } else {
440 // No scattered lepton found, use e+e- vertex
441 for (int j = 0; j < 4; j++) {
442 scattered_vertex[j] = input_event[electron_idx].vhep[j];
443 }
444 }
445
446 // ===== Entry 0: Scattered lepton (id_beam) =====
447 stdhep_entry entry0;
448 entry0.isthep = 1;
449 entry0.idhep = id_beam;
450 entry0.jmohep[0] = 0;
451 entry0.jmohep[1] = 0;
452 entry0.jdahep[0] = 0;
453 entry0.jdahep[1] = 0;
454 entry0.phep[0] = scattered_particle.phep[0];
455 entry0.phep[1] = scattered_particle.phep[1];
456 entry0.phep[2] = scattered_particle.phep[2];
457 entry0.phep[3] = scattered_particle.phep[3];
458 entry0.phep[4] = ELECTRON_MASS;
459 for (int j = 0; j < 4; j++) {
460 entry0.vhep[j] = scattered_vertex[j];
461 }
462 output_event.push_back(entry0);
463
464 // ===== Entry 1: Virtual photon (id_pair) =====
465 // Calculate 4-momentum sum from STDHEP e+e- (more accurate than LHE)
466 stdhep_entry entry1;
467 entry1.isthep = 2;
468 entry1.idhep = id_pair;
469 entry1.jmohep[0] = 0;
470 entry1.jmohep[1] = 0;
471 entry1.jdahep[0] = 2;
472 entry1.jdahep[1] = 3;
473
474 // Sum 4-momenta from STDHEP particles
475 entry1.phep[0] = input_event[electron_idx].phep[0] + input_event[positron_idx].phep[0]; // px
476 entry1.phep[1] = input_event[electron_idx].phep[1] + input_event[positron_idx].phep[1]; // py
477 entry1.phep[2] = input_event[electron_idx].phep[2] + input_event[positron_idx].phep[2]; // pz
478 entry1.phep[3] = input_event[electron_idx].phep[3] + input_event[positron_idx].phep[3]; // E
479
480 // Calculate invariant mass
481 double E2 = entry1.phep[3] * entry1.phep[3];
482 double px2 = entry1.phep[0] * entry1.phep[0];
483 double py2 = entry1.phep[1] * entry1.phep[1];
484 double pz2 = entry1.phep[2] * entry1.phep[2];
485 entry1.phep[4] = sqrt(E2 - px2 - py2 - pz2);
486
487 // Vertex same as e+e- pair
488 for (int j = 0; j < 4; j++) {
489 entry1.vhep[j] = input_event[electron_idx].vhep[j];
490 }
491 output_event.push_back(entry1);
492
493 // ===== Entry 2: Electron (11) =====
494 stdhep_entry entry2 = input_event[electron_idx];
495 entry2.jmohep[0] = 2; // Mother is entry 1 (the 622)
496 entry2.jmohep[1] = 0;
497 // Mass already correct (0.000511)
498 output_event.push_back(entry2);
499
500 // ===== Entry 3: Positron (-11) =====
501 stdhep_entry entry3 = input_event[positron_idx];
502 entry3.jmohep[0] = 2; // Mother is entry 1 (the 622)
503 entry3.jmohep[1] = 0;
504 // Mass already correct (0.000511)
505 output_event.push_back(entry3);
506
507 } else {
508 fprintf(stderr, "Error: Unknown event type for event %d\n", event_count);
509 break;
510 }
511
512 // Write output event
513 write_stdhep(&output_event, event_count);
514 write_file(ostream);
515
516 event_count++;
517
518 if (event_count % 1000 == 0) {
519 printf("Processed %d events (%d A-prime, %d radiative)\n",
520 event_count, aprime_count, radiative_count);
521 }
522 }
523
524 // Clean up
525 close_read(istream);
526 fclose(lhe_file);
527 close_write(ostream);
528
529 printf("\nSuccessfully processed %d events\n", event_count);
530 printf(" A-prime events: %d\n", aprime_count);
531 printf(" Radiative events: %d\n", radiative_count);
532
533 return 0;
534}
const double ELECTRON_MASS
bool read_lhe_event_radiative(FILE *lhe_file, int nup, LHEParticle &scattered_lepton, LHEParticle &electron, LHEParticle &positron)
@ EVENT_RADIATIVE
bool read_lhe_event(FILE *lhe_file, EventType &event_type, int &nup, LHEParticle &scattered_particle, LHEParticle &pair_or_electron, LHEParticle &positron, int id_pair)
int main(int argc, char **argv)
const double BEAM_ENERGY
bool read_lhe_event_aprime(FILE *lhe_file, int nup, LHEParticle &scattered_electron, LHEParticle &aprime, int id_pair)
void open_write(char *filename, int ostream, int n_events)
int open_read(char *filename, int istream, int n_events)
void write_stdhep(vector< stdhep_entry > *new_event, int nevhep)
int read_stdhep(vector< stdhep_entry > *new_event)
bool read_next(int istream)
void close_read(int istream)
void write_file(int ostream)
void close_write(int ostream)
Definition stdhep_util.hh:7
int idhep
Definition stdhep_util.hh:9
double vhep[4]
int jmohep[2]
double phep[5]
int isthep
Definition stdhep_util.hh:8
int jdahep[2]