FairShip
Loading...
Searching...
No Matches
makeGenieEvents Namespace Reference

Functions

dict[int, float] extract_nu_over_nubar (Path neutrino_flux, Sequence[int] particles)
 
None _ensure_dir (Path path)
 
Mapping[str, str|None]|None _build_env (Path|None gxmlpath)
 
str _target_code (str name)
 
Sequence[int] _pdg_list (Sequence[int] particles)
 
None make_splines_cli (str target, Path work_dir, int nknots, float emax)
 
None make_events (*int run, int nevents, Sequence[int] particles, str targetcode, str|None process, float emin, float emax, Path neutrino_flux, Path splines, int seed, Mapping[str, str|None]|None env_vars, Path work_dir, Mapping[int, float] nu_over_nubar)
 
argparse.ArgumentParser _build_parser ()
 
int main (Sequence[str]|None argv=None)
 

Variables

str DEFAULT_XSEC_FILE = "gxspl-FNALsmall.xml"
 
str DEFAULT_FLUX_FILE = "pythia8_Geant4_1.0_withCharm_nu.root"
 
Path DEFAULT_SPLINE_DIR
 
Path DEFAULT_FILE_DIR = Path("/eos/experiment/ship/data/Mbias/background-prod-2018")
 
dict TARGET_CODE
 
list NUPDGLIST = [16, -16, 14, -14, 12, -12]
 

Detailed Description

Generate GENIE neutrino interaction events from flux histograms.

This "launcher" wraps `genie_utils` (gmkspl/gevgen/gntpc helpers) and adds:
- Argument parsing with sensible defaults and validation
- Automatic neutrino/antineutrino scaling based on flux hist sums
- Structured logging and robust error reporting

Typical use
-----------
$ python $FAIRSHIP/macro/makeGenieEvents.py sim \
    --seed 65539 \
    --output ./work \
    --filedir /eos/experiment/ship/data/Mbias/background-prod-2018 \
    --target iron \
    --nevents 1000 \
    --particles 16 -16 \
    --emin 0.5 --emax 350 \
    --xsec-file gxspl-FNALsmall.xml \
    --flux-file pythia8_Geant4_1.0_withCharm_nu.root \
    --event-generator-list CC

Notes
-----
- This tool *does not* modify your parent shell environment.
- GXMLPATH is automatically set to $FAIRSHIP_ROOT/shipgen/genie_config by default.
- Use `--gxmlpath` to override the default GXMLPATH if needed.

Function Documentation

◆ _build_env()

Mapping[str, str | None] | None makeGenieEvents._build_env ( Path | None  gxmlpath)
protected
Build per-call env overrides (sets GXMLPATH).

Definition at line 103 of file makeGenieEvents.py.

103def _build_env(gxmlpath: Path | None) -> Mapping[str, str | None] | None:
104 """Build per-call env overrides (sets GXMLPATH)."""
105 fairship_root_path = os.getenv("FAIRSHIP_ROOT") or os.getenv("FAIRSHIP")
106 if not fairship_root_path:
107 raise OSError(
108 "FAIRSHIP_ROOT (or FAIRSHIP) environment variable is not set. "
109 "Please run inside the FairShip alienv environment."
110 )
111 val = str(gxmlpath) if gxmlpath else fairship_root_path + "/shipgen/genie_config"
112 return {"GXMLPATH": val}
113
114

◆ _build_parser()

argparse.ArgumentParser makeGenieEvents._build_parser ( )
protected

Definition at line 200 of file makeGenieEvents.py.

200def _build_parser() -> argparse.ArgumentParser:
201 p = argparse.ArgumentParser(description="Run GENIE neutrino simulation")
202 sub = p.add_subparsers(dest="cmd", required=True)
203
204 # sim command
205 ap = sub.add_parser("sim", help="Make GENIE simulation file(s)")
206 ap.add_argument("-s", "--seed", type=int, default=65539, help="RNG seed (default: GENIE 65539)")
207 ap.add_argument(
208 "-o",
209 "--output",
210 dest="work_dir",
211 type=Path,
212 default=Path("./work"),
213 help="Output directory",
214 )
215 ap.add_argument(
216 "-f",
217 "--filedir",
218 dest="filedir",
219 type=Path,
220 default=DEFAULT_FILE_DIR,
221 help="Flux dir",
222 )
223 ap.add_argument(
224 "-c",
225 "--crosssectiondir",
226 dest="splinedir",
227 type=Path,
228 default=DEFAULT_SPLINE_DIR,
229 help="Spline dir",
230 )
231 ap.add_argument(
232 "--xsec-file",
233 type=str,
234 default=DEFAULT_XSEC_FILE,
235 help=f"Spline XML (default: {DEFAULT_XSEC_FILE})",
236 )
237 ap.add_argument(
238 "--flux-file",
239 type=str,
240 default=DEFAULT_FLUX_FILE,
241 help=f"Flux ROOT (default: {DEFAULT_FLUX_FILE})",
242 )
243 ap.add_argument(
244 "-t",
245 "--target",
246 type=str,
247 default="iron",
248 choices=sorted(TARGET_CODE),
249 help="Target material",
250 )
251 ap.add_argument("-n", "--nevents", type=int, default=100, help="Events per neutrino species")
252 ap.add_argument("--emin", type=float, default=0.5, help="Min Eν [GeV]")
253 ap.add_argument("--emax", type=float, default=350.0, help="Max Eν [GeV]")
254 ap.add_argument(
255 "-e",
256 "--event-generator-list",
257 dest="evtype",
258 type=str,
259 default=None,
260 help="GENIE generator list (e.g. CC, CCDIS, CCQE, CharmCCDIS, RES, CCRES, ...)",
261 )
262 ap.add_argument("--gxmlpath", type=Path, default=None, help="Override GXMLPATH")
263 ap.add_argument(
264 "-p",
265 "--particles",
266 nargs="+",
267 type=int,
268 default=NUPDGLIST,
269 help="PDGs (e.g. 16 -16 14 -14 12 -12). Default: all flavors",
270 )
271 ap.add_argument("-r", "--run", type=int, default=1, help="GENIE run number")
272 ap.add_argument(
273 "-v",
274 "--verbose",
275 action="count",
276 default=0,
277 help="Increase verbosity (-v or -vv)",
278 )
279
280 # spline command
281 ap1 = sub.add_parser("spline", help="Make a new cross-section spline (xsec_splines.xml)")
282 ap1.add_argument("-t", "--target", type=str, default="iron", choices=sorted(TARGET_CODE))
283 ap1.add_argument("-o", "--output", dest="work_dir", type=Path, default=Path("./work"))
284 ap1.add_argument("-n", "--nknots", type=int, default=500)
285 ap1.add_argument("--emax", type=float, default=400.0)
286
287 return p
288
289

◆ _ensure_dir()

None makeGenieEvents._ensure_dir ( Path  path)
protected

Definition at line 99 of file makeGenieEvents.py.

99def _ensure_dir(path: Path) -> None:
100 path.mkdir(parents=True, exist_ok=True)
101
102

◆ _pdg_list()

Sequence[int] makeGenieEvents._pdg_list ( Sequence[int]  particles)
protected

Definition at line 122 of file makeGenieEvents.py.

122def _pdg_list(particles: Sequence[int]) -> Sequence[int]:
123 return [int(p) for p in particles]
124
125

◆ _target_code()

str makeGenieEvents._target_code ( str  name)
protected

Definition at line 115 of file makeGenieEvents.py.

115def _target_code(name: str) -> str:
116 code = TARGET_CODE.get(name.lower())
117 if not code:
118 raise ValueError(f"Unknown target '{name}'. Choices: {', '.join(TARGET_CODE)}")
119 return code
120
121

◆ extract_nu_over_nubar()

dict[int, float] makeGenieEvents.extract_nu_over_nubar ( Path  neutrino_flux,
Sequence[int]  particles 
)
Compute ν/ν̄ = sum(nu)/sum(nubar) from 1D flux histograms.

Definition at line 72 of file makeGenieEvents.py.

72def extract_nu_over_nubar(neutrino_flux: Path, particles: Sequence[int]) -> dict[int, float]:
73 """Compute ν/ν̄ = sum(nu)/sum(nubar) from 1D flux histograms."""
74 f = ROOT.TFile(str(neutrino_flux), "READ")
75 if not f or f.IsZombie():
76 raise FileNotFoundError(f"Cannot open flux file: {neutrino_flux}")
77 try:
78 ratios: dict[int, float] = {}
79 for pdg in particles:
80 fam = abs(int(pdg))
81 h_nu = f.Get(get_1D_flux_name(fam))
82 h_nubar = f.Get(get_1D_flux_name(-fam))
83 if not h_nu or not h_nubar:
84 raise FileNotFoundError(
85 f"Missing hists {get_1D_flux_name(fam)} / {get_1D_flux_name(-fam)} in {neutrino_flux}"
86 )
87 s_nu = float(h_nu.GetSumOfWeights())
88 s_nubar = float(h_nubar.GetSumOfWeights())
89 if s_nubar <= 0.0:
90 raise FileNotFoundError(f"ν̄ sum of weights is zero for family {fam} in {neutrino_flux}")
91 ratios[fam] = s_nu / s_nubar
92 log_output = f"ν/ν̄ ratio for |PDG|={fam}: {ratios[fam]:.4f} (nu={s_nu}, nubar={s_nubar})"
93 logging.info(log_output)
94 return ratios
95 finally:
96 f.Close()
97
98

◆ main()

int makeGenieEvents.main ( Sequence[str] | None   argv = None)
Launch GENIE event generation or spline creation from CLI args.

Definition at line 290 of file makeGenieEvents.py.

290def main(argv: Sequence[str] | None = None) -> int:
291 """Launch GENIE event generation or spline creation from CLI args."""
292 # CLI
293 parser = _build_parser()
294 args = parser.parse_args(argv)
295
296 # logging
297 level = logging.WARNING
298 if args.verbose == 1:
299 level = logging.INFO
300 elif args.verbose >= 2:
301 level = logging.DEBUG
302 logging.basicConfig(level=level, format="%(levelname)s %(name)s: %(message)s")
303
304 # ROOT env
306
307 if args.cmd == "spline":
308 make_splines_cli(
309 target=args.target,
310 work_dir=args.work_dir,
311 nknots=args.nknots,
312 emax=args.emax,
313 )
314 return 0
315
316 # sim
317 env_vars = _build_env(gxmlpath=args.gxmlpath)
318 targetcode = _target_code(args.target)
319
320 splines = (args.splinedir / args.xsec_file).resolve()
321 flux = (args.filedir / args.flux_file).resolve()
322 if not splines.is_file():
323 parser.error(f"Spline file not found: {splines}")
324 if not flux.is_file():
325 parser.error(f"Flux ROOT file not found: {flux}")
326
327 particles = _pdg_list(args.particles)
328 nu_over_nubar = extract_nu_over_nubar(flux, particles)
329
330 logging.info(f"Seed: {args.seed} | Target: {args.target} ({targetcode}) | Process: {args.evtype or 'ALL'}")
331 make_events(
332 run=int(args.run),
333 nevents=int(args.nevents),
334 particles=particles,
335 targetcode=targetcode,
336 process=args.evtype,
337 emin=float(args.emin),
338 emax=float(args.emax),
339 neutrino_flux=flux,
340 splines=splines,
341 seed=int(args.seed),
342 env_vars=env_vars,
343 work_dir=args.work_dir.resolve(),
344 nu_over_nubar=nu_over_nubar,
345 )
346 logging.info("Event generation completed successfully.")
347 return 0
348
349
void main()
Definition: example_test.cpp:1
None configure(darkphoton=None)

◆ make_events()

None makeGenieEvents.make_events ( *int  run,
int  nevents,
Sequence[int]  particles,
str  targetcode,
str | None  process,
float  emin,
float  emax,
Path  neutrino_flux,
Path  splines,
int  seed,
Mapping[str, str | None] | None  env_vars,
Path  work_dir,
Mapping[int, float]  nu_over_nubar 
)
Generate events for PDGs, convert to GST, and attach 2D flux.

Definition at line 140 of file makeGenieEvents.py.

155) -> None:
156 """Generate events for PDGs, convert to GST, and attach 2D flux."""
157 _ensure_dir(work_dir)
158 pdg_db = ROOT.TDatabasePDG()
159
160 for pdg in particles:
161 fam = abs(pdg)
162 part = pdg_db.GetParticle(int(pdg))
163 pdg_name = part.GetName() if part else str(pdg)
164
165 # anti-neutrinos scaled by flux ratio
166 N = int(nevents) if pdg > 0 else int(nevents / nu_over_nubar[fam])
167
168 out_dir = work_dir / f"genie-{pdg_name}_{N}_events"
169 _ensure_dir(out_dir)
170
171 filename = f"run_{run}_{pdg_name}_{N}_events_{targetcode}_{emin}_{emax}_GeV_{process or 'ALL'}.ghep.root"
172 ghep_path = out_dir / filename
173 gst_path = out_dir / f"genie-{filename.replace('ghep.root', 'gst.root')}"
174
175 logging.info(f"Generating {N} events for PDG {pdg_name} (run={run}) -> {ghep_path}")
176
177 generate_genie_events(
178 nevents=N,
179 nupdg=int(pdg),
180 emin=emin,
181 emax=emax,
182 targetcode=targetcode,
183 inputflux=str(neutrino_flux),
184 spline=str(splines),
185 outputfile=str(ghep_path),
186 process=process,
187 seed=int(seed),
188 irun=int(run),
189 env_vars=env_vars,
190 )
191 make_ntuples(str(ghep_path), str(gst_path), env_vars=env_vars)
192 add_hists(str(neutrino_flux), str(gst_path), int(pdg))
193
194 logging.info(f"Done PDG {pdg_name}: {ghep_path} -> {gst_path}")
195
196
197# ----------------------------- CLI & main -------------------------------------
198
199

◆ make_splines_cli()

None makeGenieEvents.make_splines_cli ( str  target,
Path  work_dir,
int  nknots,
float  emax 
)
Build xsec splines with gmkspl and write `xsec_splines.xml` to work_dir.

Definition at line 126 of file makeGenieEvents.py.

126def make_splines_cli(target: str, work_dir: Path, nknots: int, emax: float) -> None:
127 """Build xsec splines with gmkspl and write `xsec_splines.xml` to work_dir."""
128 _ensure_dir(work_dir)
129 output = work_dir / "xsec_splines.xml"
130 make_splines(
131 nupdglist=NUPDGLIST,
132 targetcode=_target_code(target),
133 emax=emax,
134 nknots=nknots,
135 outputfile=output,
136 )
137 logging.info(f"Spline file written: {output}")
138
139

Variable Documentation

◆ DEFAULT_FILE_DIR

Path makeGenieEvents.DEFAULT_FILE_DIR = Path("/eos/experiment/ship/data/Mbias/background-prod-2018")

Definition at line 59 of file makeGenieEvents.py.

◆ DEFAULT_FLUX_FILE

str makeGenieEvents.DEFAULT_FLUX_FILE = "pythia8_Geant4_1.0_withCharm_nu.root"

Definition at line 54 of file makeGenieEvents.py.

◆ DEFAULT_SPLINE_DIR

Path makeGenieEvents.DEFAULT_SPLINE_DIR
Initial value:
1= Path(
2 "/eos/experiment/ship/user/edursov/genie/genie_xsec/v3_02_00/NULL/G1802a00000-k250-e1000/data"
3)

Definition at line 56 of file makeGenieEvents.py.

◆ DEFAULT_XSEC_FILE

str makeGenieEvents.DEFAULT_XSEC_FILE = "gxspl-FNALsmall.xml"

Definition at line 53 of file makeGenieEvents.py.

◆ NUPDGLIST

list makeGenieEvents.NUPDGLIST = [16, -16, 14, -14, 12, -12]

Definition at line 67 of file makeGenieEvents.py.

◆ TARGET_CODE

dict makeGenieEvents.TARGET_CODE
Initial value:
1= {
2 "iron": "1000260560",
3 "lead": "1000822040[0.014],1000822060[0.241],1000822070[0.221],1000822080[0.524]",
4 "tungsten": "1000741840",
5}

Definition at line 61 of file makeGenieEvents.py.