goldpan.dataset¶
A dataset definition: which raw files, how to read them, and which processing to run on them. One TOML file, read by both
packages: goldsluice runs the processing in batch, goldpan reads the pulses and the processed quantities back.
The file (r76.dataset.toml):
[dataset]
name = "r76-nai"
output = "r76-nai" # the processed quantities: a goldpan Parquet dataset (directory), keep it outside the repository
# output_format = "root" # optional: RQ-style ROOT files instead, with our names (needs root_detector = N too)
# registry = ["../registry"] # optional: folders of detector records (goldpan.registry), relative to this file
# metadata = "r76.series.csv" # optional: run metadata per series (high voltage, trigger setting, ...), joined to the events when read
[[sources]] # where the pulses come from; as many as you like
name = "side2"
format = "idx" # any adapter: idx, midas, parquet, or one you registered
paths = ["~/idx/07221203_2025_F0001"] # raw files or dump folders ...
glob = "~/idx/07221203_2025_F*" # ... and/or a pattern (sorted)
detector = "NAI-S2" # the detector name (the adapter's detector_name)
readout = "DCRC_RUN76" # a preset of goldpan.config, or { pretrigger_samples = 1000, glitch_samples = 10, sample_period_s = 0.8e-6 }
[sources.read] # the other keyword arguments of the adapter's read(), verbatim
channels = { Side2pA = [0, 0], Side2pB = [0, 1] }
roles = { Side2pA = "phonon", Side2pB = "phonon" }
[[processing]] # the steps, in order; each adds quantities to the channels it names
algorithm = "peak" # a goldsluice algorithm
channels = "role:phonon" # "all", "role:<role>", or a list of channel names
[processing.params]
glitch_samples = "@readout.glitch_samples" # "@readout.<field>": taken from the readout of the data
pretrigger_samples = "@readout.pretrigger_samples"
amps_per_adc = 1.5e-9
Where the output goes. output may be a full path ("C:/data/goldsluice-output/r76-nai", or "~/goldsluice-output/r76-nai"), which is used as
written. A relative output ("r76-nai") is put under the folder named by the environment variable GOLDSLUICE_OUTPUT when it is set, so the
definition holds no path of your machine and the same file runs on every computer; when it is not set, a relative output is relative to the
folder of the definition file, as before (and goldsluice run refuses it if that is inside a repository that does not ignore it).
An unfinished run. goldsluice run writes _goldsluice_status.json into the output folder (STATUS_FILE): {"state": "running", ...}
when it starts and {"state": "complete", "started": ..., "finished": ..., "files": N, ...} when every raw file of the definition has been processed.
If a run stops (an error, Ctrl-C, a crash) the state stays running, and Dataset.processed() warns that the output may be incomplete. An output
folder made before this file existed has none and is read without a warning.
Steps that build on each other. A step reads the raw trace unless it has an input. A step whose algorithm gives a trace (a filter or a
baseline subtraction: goldsluice algorithms lists them) has a name, writes no quantities, and a later step with input = "<name>"
reads its result instead of the raw trace, for the channels the two steps share. A suffix is appended to the names of the quantities
of a step, so that the same algorithm can run on both (adc_max, and adc_max_lp from the filtered trace). The quantities of a step must
still be written once: two steps giving the same name is an error. Steps run in the order written, and an input is a step above:
[[processing]]
algorithm = "lowpass" # a filter: gives a trace, so it has a name
name = "lp"
channels = "role:phonon"
[processing.params]
cutoff_hz = 50e3
order = 4
sample_period_s = "@readout.sample_period_s"
[[processing]]
algorithm = "peak"
channels = "role:phonon"
input = "lp" # the peak of the filtered trace
suffix = "_lp" # adc_max_lp, current_max_lp
[processing.params]
...
Different steps for different sources. Every step runs on every source unless it has sources, a list of source names. Use it when the
detectors need different processing; a step on role:phonon already adapts to each detector’s own channels, so name sources only when the steps differ.
A step that reads a filter (input) must run on a subset of the sources the filter runs on, and every source needs at least one step. A source’s output is
redone only when the steps that run on it change. Read back together, the sources show their different quantities as records of different
fields (an awkward union), so pick one source’s rows by series before you use its fields:
[[sources]]
name = "nai"
detector = "NAI-S2"
...
[[sources]]
name = "ge"
detector = "GE-1"
...
[[processing]]
algorithm = "peak"
channels = "role:phonon" # no `sources`: runs on both
...
[[processing]]
algorithm = "rise_crossing"
channels = "role:phonon"
sources = ["ge"] # only the raw files of the source "ge"
...
Run metadata. metadata is a reference to facts about whole series that an analysis needs for every event (high voltage, trigger setting,
…): today a CSV file with a series column and any other columns (hv_v, trigger_value, trigger, …), relative to this file, one row per series;
later it may name a database instead, and nothing else in the file changes. The values are joined at read time: Dataset.processed() (and so
read()) adds one column per column of the table to the events, taken from the row of their series, so a change of a value never needs the data to be
processed again. Nothing is written into the output and the fingerprint does not change. A series that has events but is not listed is an error that
names it, and so is a column named like a quantity or a channel (processed(metadata=False) skips the join). The table is also at
spec.run_metadata(), and goldpan.runmeta joins and groups it for events you have already. ROOT output is not read by processed(), so it has no metadata.
Writing a definition. dump(definition, path) writes a definition file from a mapping with the layout of the file (the same thing tomllib gives
for it, so a program, such as a form in a browser, can build it from what the user chose) or from a DatasetSpec; dumps gives the text. It
checks the definition the way load does before it writes anything, so a file it writes always loads, and load of it gives back the same
definition. Comments are not kept and nothing is added, so write format_version yourself if the file should say which format it uses.
Nothing is assumed: the readout, the channels and every algorithm parameter are written down, in the file or in a registry it names.
With registry (and/or the environment variable GOLDPAN_REGISTRY), a source whose detector is a name in the registry takes the
readout, the [sources.read] defaults of its file format and, for ROOT output, root_detector from the detector’s record
(goldpan.registry); whatever the file itself states wins, key by key, and a readout that disagrees with the registry’s is a warning.
A detector name that is not in any registry is only a label, as before. Dataset.open(path) gives the same file to both packages:
ds = Dataset.open("r76.dataset.toml")
ev = ds.read() # the pulses, with the processed quantities attached (one Events)
q = ds.processed() # only the processed quantities, no pulses: small and fast
ev.quantities["Side2pA"]["current_max"]
With output_format = "root" the quantities are written as ROOT files in the layout of the collaboration’s RQ files (rqDir/eventTree
and rqDir/zip<N>, see goldpan.adapters.rq_root.write), under our names (Side2pA_adc_max); root_detector is that N. Read them with
goldpan.adapters.rq_root.read: Dataset.processed() reads the Parquet output only.
The processed quantities are stored one record per channel (quantities["Side2pA"]["adc_max"]), keyed by series, dump,
event. python -m goldsluice run <file> produces them; reading them before that raises an error that says so.
Module Attributes
|
|
The file in an output folder that says whether the last |
|
The environment variable that holds the folder under which a relative |
Functions
|
Write a dataset definition to the file |
|
The text of a dataset definition file, for |
|
A short hash of what determines the processed quantities of |
|
Read and check a dataset definition file. |
|
The contents of |
|
The pulses of one raw file of |
|
A step as it is hashed and recorded in the provenance: |
Classes
|
A dataset definition opened for reading: the pulses from its sources and the quantities processed from them. |
|
|
|
|
|
- goldpan.dataset.FORMAT_VERSION = 7¶
registry(and a detector named in a registry supplies readout,[sources.read]defaults androot_detector). 4: a relativeoutputgoes under$GOLDSLUICE_OUTPUTwhen that is set. 5:metadata, a reference (a CSV file) to run metadata per series, joined to the events when they are read. 6: steps may have aname, aninput(thenameof an earlier step whose result they read) and asuffixfor their quantities. 7: a step may havesources, the names of the sources it applies to (without it a step applies to all of them).- Type:
The version of the dataset definition file; a reader refuses a newer one. 2
- Type:
output_formatandroot_detector. 3
- goldpan.dataset.STATUS_FILE = '_goldsluice_status.json'¶
The file in an output folder that says whether the last
goldsluice runfinished (seeoutput_status).
- goldpan.dataset.ENV_OUTPUT = 'GOLDSLUICE_OUTPUT'¶
The environment variable that holds the folder under which a relative
outputof a definition is placed.
- class goldpan.dataset.Source(name: str, format: str, patterns: Tuple[str, ...], detector: str, readout: goldpan.config.PulseConfig | None, read: Mapping[str, Any], base: pathlib.Path, detector_record: goldpan.registry.DetectorRecord | None = None)[source]¶
Bases:
object- Parameters:
- patterns: Tuple[str, ...]¶
The
pathsandglobentries as written (with~and relative to the folder of the definition file when used).
- readout: PulseConfig | None¶
- detector_record: DetectorRecord | None = None¶
The registry’s record of
detector, if a registry has one;readandreadoutalready include what it supplies.
- class goldpan.dataset.Step(algorithm: str, channels: Any, params: Mapping[str, Any], name: str | None = None, input: str | None = None, suffix: str = '', sources: Tuple[str, ...] | None = None)[source]¶
Bases:
object- Parameters:
- name: str | None = None¶
What later steps call this one (
input = "<name>"); needed by a step whose algorithm gives a trace (a filter).
- input: str | None = None¶
The
nameof an earlier step whose resulting trace this step reads instead of the raw trace, orNone.
- suffix: str = ''¶
Appended to the names of the quantities this step writes (
adc_maxbecomesadc_max_lp), so that the same algorithm can run on the raw trace and on a filtered one.
- sources: Tuple[str, ...] | None = None¶
The names of the sources this step applies to, or
Nonefor all of them.
- applies_to(source_name)[source]¶
Does this step run on the raw files of the source called
source_name? (Always, unless the step names itssources.)
- resolve(config)[source]¶
The parameters with every
"@readout.<field>"replaced by that field ofconfig.- Parameters:
config (PulseConfig)
- Return type:
- class goldpan.dataset.DatasetSpec(name: str, output: pathlib.Path, sources: Tuple[goldpan.dataset.Source, ...], steps: Tuple[goldpan.dataset.Step, ...], path: pathlib.Path, raw: Mapping[str, Any], output_format: str = 'parquet', root_detector: int | None = None, registry: goldpan.registry.Registry | None = None, metadata: pathlib.Path | None = None)[source]¶
Bases:
object- Parameters:
- output_format: str = 'parquet'¶
"parquet"(a goldpan dataset) or"root"(RQ-style ROOT files,goldpan.adapters.rq_root.write).
- root_detector: int | None = None¶
The number
Nof thezip<N>tree of the ROOT output; required withoutput_format = "root"(written in the file, or thenumberof the registry’s record of the detector), otherwiseNone.
- registry: Registry | None = None¶
The registry the definition names (and the environment variable adds); empty if there is none.
- metadata: Path | None = None¶
The file the definition names as its run metadata (
[dataset] metadata), orNone. It is not opened until it is used.
- goldpan.dataset.load(path)[source]¶
Read and check a dataset definition file. Nothing is opened: the raw files need not exist yet.
- Return type:
- goldpan.dataset.dumps(definition, *, base='.', header='')[source]¶
The text of a dataset definition file, for
definition: a mapping with the same layout as the file ({"dataset": {...}, "sources": [...], "processing": [...]}, whattomllibgives for it) or aDatasetSpec(itsraw). The definition is checked first, exactly asloadchecks a file, as if the file were in the folderbase(relativeregistryandmetadataare looked for there), so text thatloadwould refuse is never produced, andload(dump(...))gives back the same definition.headeris written as comment lines at the top. Keys are written as given and nothing is added, not evenformat_version. Tables go in the order dataset, sources, steps, withreadandparamsas sub-tables; comments of an earlier file are not kept.
- goldpan.dataset.dump(definition, path, *, header='')[source]¶
Write a dataset definition to the file
path(seedumpsfor whatdefinitionis and how it is checked; the check looks at the folder ofpath) and return it loaded from there, so the caller has whatload(path)gives. A definition that does not pass the check is not written, and an existing file atpathis left alone.- Parameters:
header (str)
- Return type:
- goldpan.dataset.step_record(step)[source]¶
A step as it is hashed and recorded in the provenance:
name,input,suffixandsourcesappear only when the step has them, so a definition without them keeps the fingerprint it had before the keys existed.
- goldpan.dataset.fingerprint(spec, source)[source]¶
A short hash of what determines the processed quantities of
source: how it is read and the processing steps that run on it (a step that names othersourcesdoes not count). The batch run stores it in every output file and skips a file whose fingerprint has not changed.- Parameters:
spec (DatasetSpec)
source (Source)
- Return type:
- goldpan.dataset.read_raw(source, path, *, chunk=None)[source]¶
The pulses of one raw file of
sourceasEventsread by its adapter: oneEvents, or withchunkpieces of at most that many events when the adapter can (iter_chunks; otherwise the whole file is one piece).
- goldpan.dataset.output_status(out)[source]¶
The contents of
_goldsluice_status.jsonin the output folderout({"state": "running" | "complete", ...}), orNoneif the folder has no such file (it was made before the file existed, or is not a goldsluice output).- Return type:
dict | None
- class goldpan.dataset.Dataset(spec)[source]¶
Bases:
objectA dataset definition opened for reading: the pulses from its sources and the quantities processed from them.
- Parameters:
spec (DatasetSpec)
- processed(*, detector=None, metadata=True)[source]¶
The processed quantities of a detector, without pulses (an
Eventswith no traces): one record per event. With the run metadata of the definition (metadata) each event also gets its series’ values as columns, joined now (metadata=Falseleaves them out).