docu
This commit is contained in:
+234
-16
@@ -1,3 +1,153 @@
|
||||
"""
|
||||
============================================================
|
||||
G4Calo Public Interface Functions
|
||||
============================================================
|
||||
|
||||
This module provides two main functions intended for student use:
|
||||
- run_batch(...)
|
||||
- display_event(...)
|
||||
|
||||
They allow running Geant4 calorimeter simulations and visualising
|
||||
individual events using a pandas-like, lightweight data structure
|
||||
(MiniFrame) built for teaching and analysis.
|
||||
|
||||
------------------------------------------------------------
|
||||
Function: run_batch(...)
|
||||
------------------------------------------------------------
|
||||
Purpose
|
||||
-------
|
||||
Run a full Geant4 simulation batch with automatic parallelisation
|
||||
and return the results as a lightweight, pandas-like table (MiniFrame).
|
||||
|
||||
Overview
|
||||
--------
|
||||
`run_batch` distributes a requested number of Geant4 events across
|
||||
available CPU cores, runs all mini-batches in parallel, collects their
|
||||
temporary ROOT output files, converts them to numpy arrays, and
|
||||
finally assembles everything into a single MiniFrame for analysis
|
||||
or visualisation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
gd : GeometryDescriptor
|
||||
The calorimeter geometry to simulate.
|
||||
|
||||
nEvents : int
|
||||
Total number of events to simulate. Must be > 0.
|
||||
|
||||
particleSpec : str or list[str]
|
||||
Particle type(s) to generate, e.g. "gamma" or ["e-", "pi+"].
|
||||
|
||||
minEnergy_GeV : float
|
||||
Minimum kinetic energy in GeV for the primary particles.
|
||||
|
||||
maxEnergy_GeV : float, optional
|
||||
Maximum kinetic energy in GeV. If negative (default), identical
|
||||
to minEnergy_GeV.
|
||||
|
||||
filename : str, optional
|
||||
Optional output file name for storing the resulting MiniFrame
|
||||
using pickle format. If empty, no file is written.
|
||||
|
||||
no_mp : bool, optional
|
||||
If True, disables multiprocessing and runs all events sequentially.
|
||||
Useful for debugging.
|
||||
|
||||
manual_seed : int, optional
|
||||
Optional random-seed override. If < 0 (default), an internal per-core
|
||||
seed sequence is generated and persisted between runs.
|
||||
|
||||
Returns
|
||||
-------
|
||||
MiniFrame
|
||||
A table-like object containing one row per simulated event.
|
||||
Each row stores scalar quantities (e.g. true_energy, total_dep_energy)
|
||||
and fixed-size arrays for each sensor-level variable
|
||||
(sensor_energy, sensor_x, sensor_y, ...).
|
||||
|
||||
Notes
|
||||
-----
|
||||
- Automatically chooses the number of cores so that each core processes
|
||||
at least ~80 events.
|
||||
- Temporary ROOT files are written to /dev/shm or /tmp and removed after merging.
|
||||
- Prints timing information for simulation and concatenation steps.
|
||||
- For deterministic results, specify manual_seed.
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> df = run_batch(gd, nEvents=1000, particleSpec="gamma", minEnergy_GeV=1.0)
|
||||
>>> print(df.describe())
|
||||
>>> df.to_pickle("results.pkl")
|
||||
|
||||
------------------------------------------------------------
|
||||
Function: display_event(...)
|
||||
------------------------------------------------------------
|
||||
Purpose
|
||||
-------
|
||||
Visualise the energy deposition of a single simulated event in 3D
|
||||
using Plotly.
|
||||
|
||||
Overview
|
||||
--------
|
||||
`display_event` performs a one-event Geant4 simulation with the given
|
||||
geometry, retrieves deposited sensor energies, and renders a 3D view
|
||||
of the calorimeter including materials, layers, sensors, and the
|
||||
incoming particle direction.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
gd : GeometryDescriptor
|
||||
The calorimeter geometry descriptor (modified in-place).
|
||||
|
||||
particleSpec : str or list[str]
|
||||
Particle type(s) to simulate, e.g. "e-", "pi+", "gamma".
|
||||
|
||||
energy : float
|
||||
Particle kinetic energy in GeV.
|
||||
|
||||
logE : bool, optional
|
||||
If True, use logarithmic scaling for sensor opacity
|
||||
(currently not implemented).
|
||||
|
||||
renderer : str, optional
|
||||
Optional Plotly renderer ("browser", "notebook", "png", ...).
|
||||
If omitted, uses the default interactive renderer.
|
||||
|
||||
seed : int, optional
|
||||
Optional random seed for reproducibility.
|
||||
|
||||
outfile : str, optional
|
||||
If provided, saves the figure as an interactive HTML file
|
||||
instead of displaying it.
|
||||
|
||||
Returns
|
||||
-------
|
||||
None — the function displays or saves the visualisation.
|
||||
|
||||
What the Plot Shows
|
||||
-------------------
|
||||
- Coloured cubes for each material layer (colour legend included)
|
||||
- Black semi-transparent cubes for sensors, opacity ∝ deposited energy
|
||||
- Red arrow showing incoming particle direction
|
||||
- Axes labelled in mm (x, y, z following HEP conventions)
|
||||
- Interactive rotation and zoom supported
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> display_event(gd, particleSpec="gamma", energy=1.0, renderer="browser")
|
||||
|
||||
Typical Workflow
|
||||
----------------
|
||||
>>> df = run_batch(gd, 200, "e-", 1.0)
|
||||
>>> print(df.describe())
|
||||
>>> display_event(gd, "e-", 1.0, renderer="browser")
|
||||
|
||||
These two functions form the primary interface for student exercises:
|
||||
`run_batch` to simulate, and `display_event` to visualise results.
|
||||
All heavy lifting (parallelisation, I/O, and conversion) is handled
|
||||
internally so that focus remains on physics interpretation.
|
||||
"""
|
||||
|
||||
import threading
|
||||
import time
|
||||
import warnings
|
||||
@@ -6,16 +156,6 @@ import sys
|
||||
from minicalo_tools import TempFileManager
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
'''
|
||||
give G4Calo package an executable that takes input and output json files names
|
||||
|
||||
This calls the actual Geant stuff.
|
||||
The input are all the arguments and a geometry descriptor
|
||||
The output is the data frame as well as the changed geometry descriptor
|
||||
|
||||
The user only interacts with a wrapper that calls this executable through a system call
|
||||
'''
|
||||
|
||||
|
||||
from minicalo import GeometryDescriptor
|
||||
|
||||
@@ -199,12 +339,52 @@ def run_batch(
|
||||
filename: str = "",
|
||||
no_mp: bool = False,
|
||||
manual_seed : int = -1):
|
||||
'''
|
||||
splits the batch in jobs depending on how many cores are available and runs mini batches in parallel
|
||||
this will create threads.
|
||||
If no_mp is set to True, it will run the batch in a single thread
|
||||
The seeding is not thread safe (unless provided by hand)
|
||||
'''
|
||||
"""
|
||||
Run a full Geant4 simulation batch with automatic parallelisation.
|
||||
|
||||
Distributes the requested number of events across CPU cores, runs each
|
||||
mini-batch in parallel, collects temporary ROOT files, converts them to
|
||||
numpy arrays, and merges everything into a lightweight, pandas-like
|
||||
MiniFrame.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
gd : GeometryDescriptor
|
||||
Calorimeter geometry to simulate.
|
||||
nEvents : int
|
||||
Total number of events to simulate.
|
||||
particleSpec : str or list[str]
|
||||
Particle type(s), e.g. "gamma" or ["e-", "pi+"].
|
||||
minEnergy_GeV : float
|
||||
Minimum kinetic energy in GeV.
|
||||
maxEnergy_GeV : float, optional
|
||||
Maximum kinetic energy in GeV. If negative, equals minEnergy_GeV.
|
||||
filename : str, optional
|
||||
Optional pickle filename for saving results.
|
||||
no_mp : bool, optional
|
||||
Disable multiprocessing (run single-threaded) for debugging.
|
||||
manual_seed : int, optional
|
||||
Optional random seed. If < 0, seeds are generated automatically.
|
||||
|
||||
Returns
|
||||
-------
|
||||
MiniFrame
|
||||
Table-like structure with one row per event, containing both scalar
|
||||
values and fixed-size sensor arrays.
|
||||
|
||||
Notes
|
||||
-----
|
||||
- Automatically chooses the number of cores to balance workload.
|
||||
- Temporary files are written to /dev/shm or /tmp and removed after merging.
|
||||
- Prints timing information for both simulation and data assembly.
|
||||
- For reproducibility, set manual_seed.
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> df = run_batch(gd, 1000, "gamma", 1.0)
|
||||
>>> print(df.describe())
|
||||
>>> df.to_pickle("results.pkl")
|
||||
"""
|
||||
assert nEvents > 0
|
||||
assert minEnergy_GeV > 0
|
||||
|
||||
@@ -346,6 +526,44 @@ def display_event(gd : GeometryDescriptor,
|
||||
particleSpec,
|
||||
energy: float,
|
||||
logE = False, renderer=None, seed = -1, outfile : str = ""):
|
||||
"""
|
||||
Visualise a single simulated event in 3D using Plotly.
|
||||
|
||||
Runs a one-event Geant4 simulation with the provided geometry, extracts
|
||||
the deposited sensor energies, and renders an interactive 3D view of
|
||||
the calorimeter with materials, layers, and energy deposition.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
gd : GeometryDescriptor
|
||||
The calorimeter geometry (modified in place by the simulation).
|
||||
particleSpec : str or list[str]
|
||||
Particle type(s), e.g. "e-", "pi+", "gamma".
|
||||
energy : float
|
||||
Particle kinetic energy in GeV.
|
||||
logE : bool, optional
|
||||
Use logarithmic opacity scaling (currently not implemented).
|
||||
renderer : str, optional
|
||||
Plotly renderer ("browser", "notebook", etc.). Default: interactive.
|
||||
seed : int, optional
|
||||
Random seed for reproducibility.
|
||||
outfile : str, optional
|
||||
If set, saves the figure as an interactive HTML file.
|
||||
|
||||
Returns
|
||||
-------
|
||||
None — displays or saves a 3D Plotly figure.
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> display_event(gd, "gamma", 1.0, renderer="browser")
|
||||
|
||||
The plot shows:
|
||||
- Coloured cubes for material layers
|
||||
- Semi-transparent black cubes for sensors (opacity ∝ deposited energy)
|
||||
- Red arrow for incoming particle direction
|
||||
- Interactive rotation and zoom
|
||||
"""
|
||||
|
||||
gd = _fill_event(gd, particleSpec, energy)
|
||||
|
||||
|
||||
+68
-3
@@ -1,4 +1,45 @@
|
||||
# minipandas.py
|
||||
"""
|
||||
MiniFrame: a minimal, NumPy-backed, pandas-like table.
|
||||
|
||||
Each column is a NumPy array sharing the same row length (axis 0).
|
||||
Columns may be:
|
||||
• scalar columns: shape (N,)
|
||||
• vector columns: shape (N, M) with fixed M across the frame
|
||||
|
||||
Supports familiar pandas patterns:
|
||||
• len(mf), mf.shape, mf.keys(), "col" in mf
|
||||
• column access: mf["col"] -> ndarray
|
||||
• row selection: mf[idx], mf[:N], mf[mask] -> MiniFrame (views where possible)
|
||||
• head(), copy(), describe(), to_pandas(), to_pickle()/read_pickle()
|
||||
|
||||
Parameters
|
||||
----------
|
||||
data : Mapping[str, np.ndarray or scalar]
|
||||
Column data. Scalars are broadcast to length N.
|
||||
length : int, optional (keyword-only)
|
||||
Row count N to use when all provided values are scalars. If omitted,
|
||||
N is inferred from the first non-scalar column.
|
||||
|
||||
Notes
|
||||
-----
|
||||
- Only 1D (N,) and 2D (N, M) columns are supported.
|
||||
- Vector columns are expanded to wide columns (<name>_0..M-1) by to_pandas().
|
||||
- Properties:
|
||||
scalar_cols -> list[str] # columns with ndim == 1
|
||||
vector_cols -> list[str] # columns with ndim == 2
|
||||
vector_length(col) -> int or None
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> mf = MiniFrame({"run": 7, "event": np.arange(5), "energy": np.random.rand(5, 4)})
|
||||
>>> mf[:3] # first 3 rows
|
||||
>>> mf["energy"] # raw ndarray (5, 4)
|
||||
>>> mf.describe() # quick stats
|
||||
>>> df = mf.to_pandas() # convert to pandas (energy -> energy_0.._3)
|
||||
>>> mf.to_pickle("out.pkl")
|
||||
>>> mf2 = MiniFrame.read_pickle("out.pkl")
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
import numpy as np
|
||||
@@ -213,9 +254,33 @@ def concat(
|
||||
copy: bool = False,
|
||||
) -> MiniFrame:
|
||||
"""
|
||||
Concatenate MiniFrames along rows (axis=0). Column sets and per-column shapes must match.
|
||||
Args match pandas.concat subset for familiarity; only axis=0 is supported.
|
||||
"""
|
||||
Concatenate MiniFrames along rows (axis=0), pandas-style.
|
||||
|
||||
This is a lightweight analogue of pandas.concat for MiniFrame objects.
|
||||
All frames must have identical column sets and per-column shapes
|
||||
(except for the row dimension).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
objs : Iterable[MiniFrame]
|
||||
Frames to concatenate.
|
||||
axis : int, default 0
|
||||
Only axis=0 (row-wise) is supported.
|
||||
ignore_index : bool, default False
|
||||
Accepted for API similarity; MiniFrame has no explicit index (no-op).
|
||||
copy : bool, default False
|
||||
If True, return a deep copy of the result.
|
||||
|
||||
Returns
|
||||
-------
|
||||
MiniFrame
|
||||
The row-wise concatenation of the input frames.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> mf = mpd.concat([mf1, mf2])
|
||||
>>> mf.shape
|
||||
"""
|
||||
objs = list(objs)
|
||||
if not objs:
|
||||
raise ValueError("minipandas.concat: empty iterable.")
|
||||
|
||||
Reference in New Issue
Block a user