Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ShipSoft/FairShip/llms.txt

Use this file to discover all available pages before exploring further.

ShipGeoConfig provides the geometry configuration layer for FairShip. At its core is AttrDict, a dictionary subclass that supports attribute-style access so that deeply nested detector parameters can be read as ship_geo.strawtubes.width instead of ship_geo['strawtubes']['width']. The Config class extends AttrDict with serialisation to/from both Python pickle (legacy) and JSON (current) formats. The module-level helper load_from_root_file transparently handles both formats when reading a ShipGeo object stored in a ROOT geometry file, making it the primary entry point for analysis scripts.
from ShipGeoConfig import AttrDict, Config, load_from_root_file
import ROOT

# --- Load from a ROOT geometry file ---
geo_file = ROOT.TFile.Open("geofile_full.conical.Pythia8-TGeant4.root", "read")
ship_geo = load_from_root_file(geo_file, "ShipGeo")

# Attribute-style access to nested parameters
print(ship_geo.DecayVolumeMedium)   # e.g. 'vacuums' or 'helium'
print(ship_geo.target.z0)
print(ship_geo.TrackStation1.z)

# --- Build a config programmatically ---
cfg = Config()
cfg.shield = AttrDict()
cfg.shield.length = 35.0   # cm
cfg.shield.material = "iron"
print(cfg.shield.length)   # 35.0

# --- Serialise and deserialise ---
json_str = cfg.dumps_json()
cfg2 = Config().loads_json(json_str)
print(cfg2.shield.material)  # iron

AttrDict

AttrDict is a dict subclass that maps its own __dict__ to itself, enabling transparent attribute access for all keys.
d = AttrDict(x=1, y=2)
assert d['x'] == d.x    # True
d.z = 3                 # equivalent to d['z'] = 3

Constructor

*args
any
Positional arguments forwarded verbatim to the dict constructor. Accepts an existing mapping, an iterable of key-value pairs, or nothing.
**kwargs
any
Keyword arguments forwarded to the dict constructor; each becomes an initial key-value pair accessible as an attribute.

Methods

clone() -> AttrDict

Returns a shallow-recursive deep clone of this AttrDict. For every value that is itself an AttrDict, clone() is called recursively; all other values are copied by reference.
original = AttrDict(a=1, nested=AttrDict(b=2))
copy = original.clone()
copy.nested.b = 99
print(original.nested.b)  # 2  — original is unaffected
return
AttrDict
A new AttrDict that is a deep clone of this instance, with nested AttrDict values also cloned.

Config

Config extends AttrDict with serialisation helpers for persisting geometry configurations to disk or ROOT files. It supports two wire formats — JSON (current default) and pickle (legacy) — and detects the format automatically on load.

Constructor

*args
any
Passed through to AttrDict.__init__.
**kwargs
any
Passed through to AttrDict.__init__.

loads(buff: bytes) -> Config

Deserialise configuration from pickle bytes, replacing the current contents of this Config object in place.
buff
bytes
required
Pickle-serialised bytes, typically obtained from Config.dumps() or read from a legacy binary file.
return
Config
Returns self after updating, enabling chained construction such as Config().loads(data).

loads_json(json_str: str) -> Config

Deserialise configuration from a JSON string. All nested dict objects in the JSON are recursively converted to AttrDict instances so that attribute access works at every nesting level.
json_str
str
required
A valid JSON string, typically the output of Config.dumps_json() or a stored TObjString in a ROOT file.
return
Config
Returns self after populating, enabling chained construction such as Config().loads_json(json_str).
json_str = '{"target": {"z0": -7000.0}, "DecayVolumeMedium": "vacuums"}'
cfg = Config().loads_json(json_str)
print(cfg.target.z0)           # -7000.0
print(cfg.DecayVolumeMedium)   # vacuums

dumps() -> bytes

Serialise this Config to pickle bytes.
return
bytes
Pickle-serialised representation of the configuration.

dumps_json() -> str

Serialise this Config to a JSON string with two-space indentation. Non-serialisable values are converted to strings via default=str.
return
str
A pretty-printed JSON string representation of the configuration.
cfg = Config()
cfg.magnet = AttrDict(length=4.0, field=1.5)
print(cfg.dumps_json())
# {
#   "magnet": {
#     "length": 4.0,
#     "field": 1.5
#   }
# }

load(filename) -> Config

Load configuration from a file on disk in pickle format. The filename may contain environment variable references (expanded via os.path.expandvars).
filename
str
required
Path to a pickle-format configuration file. Environment variables such as $FAIRSHIP are expanded automatically.
return
Config
Returns self after loading.

dump(filename) -> int

Write this Config to a file on disk in pickle format.
filename
str
required
Destination file path. Environment variables in the path are expanded via os.path.expandvars.
return
int
Number of bytes written to the file.

clone() -> Config

Returns a recursive deep clone of this Config. Nested AttrDict values are cloned recursively; all other values are copied by reference.
return
Config
A new Config that is a deep clone of this instance.

__str__() -> str

Returns a human-readable summary of the configuration, listing all non-private keys (those not beginning with _) in sorted order.
print(cfg)
# ShipGeoConfig:
#   DecayVolumeMedium: vacuums
#   magnet: {'field': 1.5, 'length': 4.0}
#   target: {'z0': -7000.0}

load_from_root_file

load_from_root_file(root_file, key: str = "ShipGeo") -> Config
Load a Config from an open ROOT TFile or a file path string. This is the standard entry point for analysis scripts that need to access detector geometry parameters. The function automatically detects whether the stored object is in the current JSON format (a string beginning with {) or the legacy pickle format, and deserialises accordingly.
root_file
ROOT.TFile | str
required
Either an already-open ROOT.TFile object or a string path to a ROOT file. When a string path is given, the file is opened and closed automatically within this call.
key
str
default:"ShipGeo"
The key name of the configuration object stored in the ROOT file. Defaults to "ShipGeo". Raises ValueError if no object with this key exists in the file.
return
Config
A fully populated Config object with attribute-style access to all geometry parameters.
import ROOT
from ShipGeoConfig import load_from_root_file

# Open as TFile first (keeps file open for further reads)
geo_file = ROOT.TFile.Open("geofile_full.conical.Pythia8-TGeant4.root", "read")
ship_geo = load_from_root_file(geo_file, "ShipGeo")

# Or pass the path directly (file opened and closed internally)
ship_geo = load_from_root_file("geofile_full.conical.Pythia8-TGeant4.root")

# Inspect the decay volume medium
medium = ship_geo.DecayVolumeMedium   # 'helium' or 'vacuums'

# Access target z-position
z_target = ship_geo.target.z0         # in cm

# Track station position
z_ts1 = ship_geo.TrackStation1.z      # in cm

# Round-trip through JSON
json_str = ship_geo.dumps_json()
ship_geo2 = Config().loads_json(json_str)
If the stored object is neither a valid JSON string nor a valid pickle byte stream, pickle.loads will raise an exception. Always use load_from_root_file rather than reading the raw object yourself to benefit from automatic format detection.

Build docs developers (and LLMs) love