Code architecture
This page describes how the source is organized. See Coordinates and conventions and The data model for what the pieces mean physically.
What GRANDlib is
GRANDlib computes little of the physics itself. Air showers and their radio emission come from ZHAireS or CoREAS, tau propagation from DANTON, terrain from TURTLE, the geomagnetic field from GULL and sky brightness from LFMap. What GRANDlib owns is three things:
A schema — what a GRAND event is and the format the collaboration stores it in (
grand.dataio).A frame-reconciliation engine — where things are, in which frame, over what terrain, in what magnetic field (
grand.geo).An instrument-response model — effective length, Galactic noise, RF chain, ADC (
grand.sim).
Forward and back
The simulation runs forward, from shower to field to voltage to ADC counts.
grand.analysis (Marion Guelfand) runs back: it reconstructs the
arrival direction, the distance to the shower maximum and an
electromagnetic-energy estimate from recorded times and amplitudes, with
plane-wave, spherical-wave and ADF fits. Its tests show that the fits recover
what their own forward models generate; comparison with full simulations and
measured showers is still to come.
Layering
The intended layering is that grand.geo and grand.dataio sit at
the bottom and know nothing above them, grand.sim composes both and
grand.aoi and grand.basis sit on top providing the objects a user
handles and the plots they look at.
The imports do not quite follow it:
Click the figure to open it full size.
The diagram is generated from the import statements under grand/ by
python docs/dev/make_modules_diagram.py --measure. Re-run it after moving
code between subpackages.
Warning
There is a module-level import cycle. It is not visible from any one file:
grand.geo.topography imports grand.dataio.protocol
grand.dataio.root_files imports grand.basis.traces_event
grand.basis.type_trace imports grand.geo.coordinates
Python tolerates the cycle, because none of these modules needs the others’ names at import time, but it makes the package sensitive to import order. The first edge is also why topography needs ROOT (Topography, the data layer and the simulation need ROOT).
grand/basis/pipeline.py imports
Efield2Voltage inside a function rather than
at module level, which avoids a second cycle. Follow that pattern where an
upward import cannot be avoided.
grand.analysis sits on top: it imports geometry (through the package
namespace, from grand import Geodetic) and nothing in grand imports it
back.
Lazy imports
import grand loads nothing heavy: its public names (Geodetic,
Efield2Voltage, RFChain, …) are imported on first use (PEP 562).
import grand and grand.geo.coordinates therefore work without ROOT
or the compiled libraries. The documentation build uses a typed stand-in for
ROOT where it is absent.