Input and output¶
Reading GATE ROOT files, checking their contents, and writing the extracted data to the supported output formats.
Reader¶
Extraction of GATE trees into the package representation.
The module provides read_tree(), the entry point used by the command
line interface and by code using the package as a library. It opens a GATE
ROOT file, extracts one tree and closes the file again.
Use RootFile directly when several
trees are read from the same file, so that the file is opened only once.
Public functions:
- read_tree(path, tree, branches, tree_name, validate) -> TreeData
Read one tree from a GATE ROOT file.
- read_hits_trees(path, branches, tree_names, validate, add_source_branch) -> TreeData
Read the hits of a GATE ROOT file as a single dataset.
- opengate_gate_tree.io.reader.read_tree(path, tree, branches=None, tree_name=None, validate=True)[source]¶
Read one tree from a GATE ROOT file.
- Parameters:
path (Path) – Path to the GATE ROOT file.
tree (GateTree) – Tree to read.
branches (Sequence[str] | None) – Branches to read. When omitted or empty, every branch of the tree is read. Repeated names are read once, at the position of their first occurrence.
tree_name (str | None) – Name of the tree in the file, when it differs from the standard one or when a file holds several trees of hits.
validate (bool) – Whether to recognise the structure of the “Hits” tree and check the tree against it before reading. Turn it off to extract branches from a file whose structure the package does not know.
- Returns:
Columns of the requested branches.
- Return type:
- Raises:
RootFileError – If the path is not a readable ROOT file.
TreeNotFoundError – If the tree is not present in the file.
AmbiguousTreeError – If several trees hold hits and none of them was named.
UnknownHitsVariantError – If the structure of the “Hits” tree is not a supported one.
HitsTreeValidationError – If the “Hits” tree does not match the structure it was recognised as.
BranchNotFoundError – If any requested branch is not present in the tree.
UnsupportedBranchTypeError – If any requested branch uses an unsupported type.
ValueError – If any requested branch name is empty.
- opengate_gate_tree.io.reader.read_hits_trees(path, branches=None, tree_names=None, validate=True, add_source_branch=True)[source]¶
Read the hits of a GATE ROOT file as a single dataset.
A file splitting its hits into one tree per run, or one per sensitive detector, is read as one dataset with the trees placed one after another. Identifiers are left as GATE wrote them, so an event is still told apart by its run and its event identifier together.
- Parameters:
path (Path) – Path to the GATE ROOT file.
branches (Sequence[str] | None) – Branches to read from every tree. When omitted or empty, every branch is read.
tree_names (Sequence[str] | None) – Trees to read, in the order their rows should follow. When omitted, every tree of the file holding hits is read, in file order.
validate (bool) – Whether to recognise the structure of each tree and check it.
add_source_branch (bool) – Whether to record which tree each row came from, in a column named
sourceTreeName.
- Returns:
Rows of every tree that was read, one tree after another.
- Return type:
- Raises:
RootFileError – If the path is not a readable ROOT file.
TreeNotFoundError – If the file holds no hits, or a named tree is not present.
UnknownHitsVariantError – If the structure of a tree is not a supported one.
HitsTreeValidationError – If a tree does not match the structure it was recognised as.
TreeMergeError – If the trees do not hold the same structure.
BranchNotFoundError – If any requested branch is not present in a tree.
ROOT files¶
Reading GATE ROOT files.
The module defines RootFile, a thin wrapper over uproot that
exposes the parts of a GATE output file the package works with.
Only trees are considered. GATE files also store histograms, such as
latest_event_ID and total_nb_primaries; they are ignored when the file
contents are inspected and are never carried over to an output file.
Reading the “Hits” tree recognises which structure it has and checks the tree
against it before any data is loaded, so a file that is not what it is taken
for is reported rather than half read. Passing validate=False extracts the
branches without asking what structure they form, which is what a file from a
GATE build the package does not know needs.
Hits are not always stored under the name “Hits”. The GateToTree output
calls its tree tree, and a file can hold one tree per run or one per
sensitive detector, named after it. A tree asked for by name is used as given;
otherwise the name is matched, and for hits the trees are examined so that one
holding them is found whatever it is called.
Public objects:
- RootFile
Reader for a single GATE ROOT file.
- class opengate_gate_tree.io.rootfile.RootFile(path)[source]¶
Reader for a single GATE ROOT file.
The file is opened on construction and should be closed when no longer needed, either through
close()or by using the instance as a context manager.- Parameters:
path (Path)
- __exit__(exc_type, exc_value, traceback)[source]¶
Close the underlying file.
- Parameters:
exc_type (type[BaseException] | None)
exc_value (BaseException | None)
traceback (TracebackType | None)
- Return type:
None
- property tree_names: tuple[str, ...]¶
Names of the trees stored in the file, without cycle numbers.
Objects that are not trees, such as the histograms written by GATE, are not reported.
- has_tree(tree)[source]¶
Return whether the requested tree is present in the file.
Hits are looked for the way they are read: by name first, then by structure, so a file whose hits sit in a tree called something else answers
Truehere and can be read. A file holding hits in several trees answersTrueas well, although reading it needs one of them to be named.
- hits_tree_names()[source]¶
Return the names of the trees holding hits, whatever they are called.
A tree holds hits when its branches form one of the supported structures. A file usually holds one such tree, but the output can be split into one tree per run or per sensitive detector.
- resolve_tree_name(tree, name=None)[source]¶
Return the key under which the requested tree is stored.
A name given by the caller is used as it is. Otherwise names are compared exactly, then without regard to case, and for hits the trees are examined as a last step, so that a tree holding them is found even when it is called something else.
- Parameters:
- Returns:
Key of the tree in the file.
- Return type:
- Raises:
TreeNotFoundError – If the tree is not present in the file.
AmbiguousTreeError – If several trees hold hits and none of them was named.
- branch_names(tree, name=None)[source]¶
Return the branch names of the requested tree, in file order.
- Raises:
TreeNotFoundError – If the tree is not present in the file.
AmbiguousTreeError – If several trees hold hits and none of them was named.
- Parameters:
- Return type:
- detect_hits_tree(tree_name=None)[source]¶
Recognise the structure of the “Hits” tree stored in the file.
- Parameters:
tree_name (str | None) – Name of the tree in the file, when the caller knows it.
- Returns:
Structure of the tree.
- Return type:
- Raises:
TreeNotFoundError – If the file holds no “Hits” tree.
AmbiguousTreeError – If several trees hold hits and none of them was named.
UnknownHitsVariantError – If the structure of the tree is not a supported one.
- read(tree, branches=None, tree_name=None, validate=True)[source]¶
Read a tree into the package representation.
- Parameters:
tree (GateTree) – Tree to read.
branches (Sequence[str] | None) – Branches to read. When omitted or empty, every branch is read. Repeated names are read once, at the position of their first occurrence.
tree_name (str | None) – Name of the tree in the file, when it differs from the standard one or when a file holds several trees of hits.
validate (bool) – Whether to recognise the structure of the “Hits” tree and check the tree against it. The check covers the whole tree, not only the branches being read, and runs before any data is loaded. Other trees are read the same way either way.
- Returns:
Columns of the requested branches.
- Return type:
- Raises:
TreeNotFoundError – If the tree is not present in the file.
AmbiguousTreeError – If several trees hold hits and none of them was named.
UnknownHitsVariantError – If the structure of the “Hits” tree is not a supported one.
HitsTreeValidationError – If the “Hits” tree does not match the structure it was recognised as.
BranchNotFoundError – If any requested branch is not present in the tree.
UnsupportedBranchTypeError – If any requested branch uses an unsupported type.
ValueError – If any requested branch name is empty.
- read_hits(branches=None, tree_names=None, validate=True, add_source_branch=True)[source]¶
Read the hits of the file as a single dataset.
A file splitting its hits into one tree per run, or one per sensitive detector, is read as one dataset with the trees placed one after another. Every tree is held in memory before they are joined, so this needs room for the whole file.
- Parameters:
branches (Sequence[str] | None) – Branches to read from every tree. When omitted or empty, every branch is read.
tree_names (Sequence[str] | None) – Trees to read, in the order their rows should follow. When omitted, every tree of the file holding hits is read, in file order.
validate (bool) – Whether to recognise the structure of each tree and check it.
add_source_branch (bool) – Whether to record which tree each row came from.
- Returns:
Rows of every tree that was read, one tree after another.
- Return type:
- Raises:
TreeNotFoundError – If the file holds no hits, or a named tree is not present.
UnknownHitsVariantError – If the structure of a tree is not a supported one.
HitsTreeValidationError – If a tree does not match the structure it was recognised as.
TreeMergeError – If the trees do not hold the same structure.
BranchNotFoundError – If any requested branch is not present in a tree.
Validation¶
Consistency checks for GATE ROOT files.
The module holds the checks performed before and while a tree is extracted: the input path, the presence of the requested tree and branches, and whether the branch types are supported.
The functions take plain names rather than a RootFile
so that the module stays independent of the reader and can be tested on its own.
Public functions:
- validate_root_file_path(path: Path) -> None
Check that the path can point to a readable ROOT file.
- find_tree_name(available: Sequence[str], tree: GateTree) -> str | None
Look up the key of a tree without raising.
- resolve_tree_name(available: Sequence[str], tree: GateTree, source: Path | None) -> str
Look up the key of a tree, reporting the available trees when absent.
- resolve_requested_tree_name(available: Sequence[str], name: str, source: Path | None) -> str
Look up a tree the caller named.
- find_hits_tree_names(branches_by_tree: Mapping[str, Sequence[str]]) -> tuple[str, …]
Names of the trees whose branches form a supported “Hits” structure.
- validate_branches_present(available: Sequence[str], requested: Sequence[str]) -> None
Check that every requested branch exists in the tree.
- validate_branch_interpretations(interpretations: Mapping[str, Any]) -> None
Check that every branch uses a supported type.
- branch_type_name(interpretation: Any) -> str
Name the type a branch is stored with.
- opengate_gate_tree.io.validation.validate_root_file_path(path)[source]¶
Check that the path can point to a readable ROOT file.
- Parameters:
path (Path) – Path to check.
- Raises:
RootFileError – If the extension is wrong, the path does not exist, or it is not a regular file.
- Return type:
None
- opengate_gate_tree.io.validation.find_tree_name(available, tree)[source]¶
Return the key under which a tree is stored, or
Nonewhen absent.Names are compared exactly first, then without regard to case.
- opengate_gate_tree.io.validation.resolve_tree_name(available, tree, source=None)[source]¶
Return the key under which the requested tree is stored.
- Parameters:
- Returns:
Matching key.
- Return type:
- Raises:
TreeNotFoundError – If no tree of the requested name is present.
- opengate_gate_tree.io.validation.resolve_requested_tree_name(available, name, source=None)[source]¶
Return the key of a tree the caller named.
- Parameters:
- Returns:
The name, once it is known to be present.
- Return type:
- Raises:
TreeNotFoundError – If no tree of that name is present.
- opengate_gate_tree.io.validation.find_hits_tree_names(branches_by_tree)[source]¶
Return the names of the trees holding a supported “Hits” structure.
- Parameters:
branches_by_tree (Mapping[str, Sequence[str]]) – Tree names mapped to their branch names.
supported (A tree counts as holding hits when it holds every branch of a)
here (structure. Matching a marker branch is not enough)
diagnosis (of a file to read is not the place for the leniency that makes a)
useful.
- Returns:
Names of the trees whose branches form a structure the package supports, in the order they were given.
- Return type:
- opengate_gate_tree.io.validation.validate_branches_present(available, requested)[source]¶
Check that every requested branch exists in the tree.
- Parameters:
- Raises:
BranchNotFoundError – If any requested branch is missing.
- Return type:
None
- opengate_gate_tree.io.validation.validate_branch_interpretations(interpretations)[source]¶
Check that every branch uses a type supported by the package.
Scalar branches, fixed-width array branches and text branches are supported. Branches whose length varies per entry are not, because they have no representation in the supported output formats.
The check runs on the uproot interpretation rather than on loaded data: text branches and branches of varying length both load as object arrays, so they cannot be told apart afterwards.
- Parameters:
interpretations (Mapping[str, Any]) – Branch name to uproot interpretation mapping.
- Raises:
UnsupportedBranchTypeError – If any branch uses an unsupported type.
- Return type:
None
- opengate_gate_tree.io.validation.branch_type_name(interpretation)[source]¶
Return the name of the type a branch is stored with.
The names are the ones the branch schemas use, so that what a file holds can be compared with what a structure describes.
- Parameters:
interpretation (Any) – Interpretation of the branch, as reported by uproot.
- Returns:
"text"for a text branch, the name of the scalar type for a numeric one,"<type>[<width>]"for a fixed-width array branch, and"unsupported"for a type the package cannot represent.- Return type:
File names¶
Names of the files a run writes.
An output file is named after the title the caller gave it, the tree the data
came from, and the format it is written in: patient_01.hits.csv. The tree
is part of the name because one input file holds several trees, and a run
extracting the hits and a run extracting the singles of the same simulation
should not land on the same name.
The report of a run, when one is asked for, goes next to the data under the
same title: patient_01.hits.stats.json.
Naming lives here rather than in the command line, so that code using the package as a library lands on the same names without repeating the rule.
Public functions:
- build_output_file_name(title, tree, file_format) -> str
Name of the file holding an extracted tree.
- build_output_file_path(directory, title, tree, file_format) -> Path
Path of the file holding an extracted tree.
- build_statistics_file_path(directory, title, tree) -> Path
Path of the report describing an extracted tree.
- opengate_gate_tree.io.naming.build_output_file_name(title, tree, file_format)[source]¶
Return the name of the file holding an extracted tree.
- Parameters:
title (str) – Title of the run, used as the first part of the name.
tree (GateTree) – Tree the data was extracted from.
file_format (OutputFileFormat) – Format the data is written in.
- Returns:
Name in the form
<title>.<tree>.<format>.- Return type:
- opengate_gate_tree.io.naming.build_output_file_path(directory, title, tree, file_format)[source]¶
Return the path of the file holding an extracted tree.
- Parameters:
directory (Path) – Directory the file is written to.
title (str) – Title of the run.
tree (GateTree) – Tree the data was extracted from.
file_format (OutputFileFormat) – Format the data is written in.
- Returns:
Path of the output file.
- Return type:
Path
Statistics files¶
Writing a summary of extracted data to a file.
The report is written as JSON, because it is meant to be read by whatever
comes next in the analysis as much as by a person: a run compared against
another one, a table of process counts, a check that a file holds what a
simulation was supposed to produce. The rendering meant for reading is
format_statistics().
Public functions:
- write_statistics(statistics, path) -> Path
Write a summary as a JSON file.
- opengate_gate_tree.io.statistics.write_statistics(statistics, path)[source]¶
Write a summary as a JSON file.
- Parameters:
statistics (TreeStatistics) – Summary to write.
path (Path) – Path of the output file. An existing file is overwritten.
- Returns:
Path that was written to.
- Return type:
Path
- Raises:
ExportError – If the file cannot be written.
Output formats¶
OutputFileFormat enum and parser.
This module defines the OutputFileFormat enum and provides a function to parse strings into OutputFileFormat enum members.
- class opengate_gate_tree.io.fileformat.OutputFileFormat(*values)[source]¶
Enum representing the output file format.
- opengate_gate_tree.io.fileformat.parse_output_file_format(name)[source]¶
Parse a string into an OutputFileFormat enum member.
- Parameters:
name (str) – Name of the output file format member.
- Returns:
Corresponding OutputFileFormat enum member.
- Return type:
- Raises:
ValueError – If the name does not correspond to any OutputFileFormat member.
Writers¶
Export of extracted GATE trees to the supported output formats.
The subpackage holds one writer per output format and the lookup used to pick one. Output files carry the extracted tree only: the histograms stored next to the trees in a GATE file are not copied over.
Public functions:
- get_writer(file_format: OutputFileFormat) -> TreeWriter
Return the writer producing the requested format.
- write_tree(data: TreeData, path: Path, file_format: OutputFileFormat) -> Path
Write the data in the requested format.
- opengate_gate_tree.io.writers.get_writer(file_format)[source]¶
Return the writer producing the requested format.
- Parameters:
file_format (OutputFileFormat) – Requested output format.
- Returns:
Writer for the requested format.
- Return type:
- Raises:
ExportError – If no writer produces the requested format.
- opengate_gate_tree.io.writers.write_tree(data, path, file_format)[source]¶
Write the data in the requested format.
- Parameters:
data (TreeData) – Data to write.
path (Path) – Path of the output file. An existing file is overwritten.
file_format (OutputFileFormat) – Format of the output file.
- Returns:
Path that was written to.
- Return type:
Path
- Raises:
ExportError – If no writer produces the requested format, or the file cannot be written.
Shared parts of the output writers.
The module defines the interface every writer implements and the helpers they share, mainly the normalization of text columns.
Text columns need a different representation per backend. Both accepted representations start from a list of strings, so the conversion lives here: uproot rejects NumPy unicode arrays in a tree, and h5py rejects them when a string data type is requested.
Public objects:
- TreeWriter
Interface implemented by every output writer.
- is_text_column(column) -> bool
Report whether a column holds text.
- as_text_list(name, column) -> list[str]
Return a text column as a list of strings.
- prepare_output_directory(path) -> None
Create the directory the output file will be written to.
- reject_branch_names(data, characters, file_format, reason) -> None
Refuse branch names a backend cannot store faithfully.
- class opengate_gate_tree.io.writers.base.TreeWriter(*args, **kwargs)[source]¶
Interface implemented by every output writer.
- opengate_gate_tree.io.writers.base.reject_branch_names(data, characters, file_format, reason)[source]¶
Refuse branch names a backend cannot store faithfully.
Both backends accept such a name and then write something other than what was asked for, without reporting anything. Refusing the file is the only way the caller learns about it before reading the result.
- Parameters:
data (TreeData) – Data about to be written.
characters (str) – Characters the backend cannot carry in a branch name.
file_format (OutputFileFormat) – Format being written, named in the message.
reason (str) – What the backend would do with such a name.
- Raises:
ExportError – If any branch name holds one of the characters.
- Return type:
None
- opengate_gate_tree.io.writers.base.is_text_column(column)[source]¶
Report whether a column holds text rather than numbers.
- opengate_gate_tree.io.writers.base.as_text_list(name, column)[source]¶
Return a text column as a list of strings.
- Parameters:
name (str) – Branch name, used in the error message.
column (numpy.ndarray) – Column to convert.
- Returns:
Column values as strings.
- Return type:
- Raises:
ExportError – If the column holds values that are not text. An array of Python objects can hold anything, and converting such values with
strwould write something other than the data the caller provided.
- opengate_gate_tree.io.writers.base.prepare_output_directory(path)[source]¶
Create the directory the output file will be written to.
- Parameters:
path (Path) – Path of the output file.
- Raises:
ExportError – If the directory cannot be created.
- Return type:
None
Export of a GATE tree to CSV.
A CSV file holds scalar cells, so fixed-width array branches are written as one
column per component, named <branch>_<index>. The file therefore does not
carry the branch back as an array when read again; ROOT and HDF5 do.
Public objects:
- CsvTreeWriter
Writer producing a CSV file.
- class opengate_gate_tree.io.writers.csv_writer.CsvTreeWriter[source]¶
Writer producing a CSV file.
- write(data, path)[source]¶
Write the data as CSV.
- Parameters:
data (TreeData) – Data to write.
path (Path) – Path of the output file. An existing file is overwritten.
- Returns:
Path that was written to.
- Return type:
Path
- Raises:
ExportError – If the file cannot be written.
Export of a GATE tree to HDF5.
The tree becomes one group holding one dataset per branch. Fixed-width array
branches keep their shape as two-dimensional datasets, so volumeID is
written as (entries, width) rather than split into separate columns.
Text branches are written with a variable-length UTF-8 string type and read
back with h5py through asstr().
The group tracks insertion order, because HDF5 lists links alphabetically by default and the branch order carries meaning for the analysis reading the file.
Public objects:
- Hdf5TreeWriter
Writer producing an HDF5 file.
- class opengate_gate_tree.io.writers.hdf5_writer.Hdf5TreeWriter[source]¶
Writer producing an HDF5 file.
- write(data, path)[source]¶
Write the data as HDF5.
- Parameters:
data (TreeData) – Data to write.
path (Path) – Path of the output file. An existing file is overwritten.
- Returns:
Path that was written to.
- Return type:
Path
- Raises:
ExportError – If a branch name holds a slash, or the file cannot be written.
Export of a GATE tree to ROOT.
The tree is written as a TTree, the container the analysis code reading
these files expects. Assigning a mapping to a key of an uproot file writes a
ROOT::RNTuple instead, which round-trips through uproot but cannot be read
by code using TTree::Draw, SetBranchAddress or RDataFrame. The
writer therefore declares the branches with mktree and appends the data
with extend.
Data is appended only when the tree holds entries: extend raises on an
empty batch that contains a text branch, while mktree on its own already
produces a valid tree with every branch declared.
Public objects:
- RootTreeWriter
Writer producing a ROOT file holding a TTree.
- class opengate_gate_tree.io.writers.root_writer.RootTreeWriter[source]¶
Writer producing a ROOT file holding a TTree.
- write(data, path)[source]¶
Write the data as a ROOT TTree.
- Parameters:
data (TreeData) – Data to write.
path (Path) – Path of the output file. An existing file is overwritten.
- Returns:
Path that was written to.
- Return type:
Path
- Raises:
ExportError – If the data holds no branches, a branch name holds a bracket, or the file cannot be written.