one.alf.spec
The complete ALF specification descriptors and validators.
Module attributes
The ALF part names and their definitions. |
|
The session specification pattern |
|
The collection and revision specification pattern |
|
The filename specification pattern |
|
The collection, revision and filename specification pattern |
|
The full ALF path specification pattern |
Functions
Print a description of an ALF part. |
|
Checks if the syntax corresponds to a session path. |
|
Bool test for randomly generated hexadecimal uuid validity. |
|
Bool test for randomly generated hexadecimal uuid validity. |
|
Returns a True for a given file name if it is an ALF file, otherwise returns False |
|
Returns a template string representing the where the ALF parts lie in an ALF path. |
|
Convert camel case string to space separated string. |
|
Construct a regular expression pattern for parsing or validating an ALF |
|
Given a set of ALF file parts, return a valid ALF file name. |
Classes
Data QC outcomes. |
- SPEC_DESCRIPTION = {'Subjects': 'An optional directory to indicate that the experiment data are divided by subject. If organizing by lab, this directory is required.', 'attribute': 'Together with the object, the attribute represents the type of data in the file, for example "times", "amplitudes", "clusters". The names should be in Haskell case, however the following three attributes may be separated by an underscore, e.g. "stimOn_times".\nThe attribute "times" is reserved for discrete event times and comprises a numerical array containing times of the events in seconds, relative to a universal timescale common to all files.\nThe attribute "intervals" should have two columns, indicating the start and end times of each interval relative to the universal timescale.\nContinuous timeseries are represented by the "timestamps" attribute. The file may contain a vector of times in universal seconds if unevenly sampled, or two rows each representing a synchronization point, the first column giving the sample number (counting from 0), and the second column giving the corresponding time in universal seconds. The times corresponding to all samples are then found by linear interpolation. NB: the "timestamps" file is an exception to the rule that all files representing a continuous timeseries object must have one row per sample, as it will often have substantially less.', 'collection': 'An optional folder to group data by modality, device, etc. This is necessary when a session contains multiple measurements of the same type, from example spike times from multiple probes. Label examples include "probe00", "raw_video_data".', 'date': 'The date on which the experiment session took place, in ISO format, i.e. yyyy-mm-dd', 'extension': 'ALF can deal with any sort of file, as long as it has a concept of a number of rows (or primary dimension). The type of file is recognized by its extension. \nPreferred choices:\n\n.npy: numpy array file. This is recommended over flat binary since datatype and shape is stored in the file. If you have an array of 3 or more dimensions, the first dimension counts as the number of rows.\n\n.tsv: tab-delimited text file. This is recommended over comma-separated filessince text fields often have commas in. All rows should have the same number of columns. The first row contains tab-separated names for each column.\n\n.bin: flat binary file. It’s better to use .npy for storing binary data but some recording systems save in flat binary. Rather than convert them, you can ALFize a flat binary file by adding a metadata file, which specifies the number of columns (as the size of the "columns" array) and the binary datatype as a top-level key "dtype", using numpy naming conventions.', 'extra': 'File names could have as many optional parts as you like: "object.attribute.x1.x2.[…].xN.extension". The extra name parts play no formal role, but can serve several additional purposes. For example, it could be a UUID or file hash for archiving purposes. If there are multiple files with the same object, attribute, and extensions but different extra parts, these should be treated as files to be concatenated, for example to allow multiple-part tif files as produced by scanimage to be encoded in ALF. The concatenation would happen in hierarchical lexicographical order: i.e. by lexicographic order of x1, then x2, etc.', 'lab': 'The name of the lab where the data were collected (optional).', 'namespace': 'An option filename prefix for data that are not not expected to be a community standard, for example task specific events. The namespace may also be used to indicate data unique to a given piece of hardware or software, and is identified by underscores, e.g. "_iblrig_", "_phy_".', 'number': 'The sequential session number of the day, optionally zero-padded to be three numbers, e.g. 001, 002, etc.', 'object': 'Every file describing a given object has the same number of rows (i.e. the 1st dimension of an npy file, number of frames in a video file, etc). You can therefore think of the files for an object as together defining a table, with column headings given by the attribute in the file names, and values given by the file contents. Object names should be in Haskell case and pluralized, e.g. "wheelMoves", "sparseNoise", "trials".\nEncoding of relations between objects can be achieved by a simplified relational model. If the attribute name of one file matches the object name of a second, then the first file is guaranteed to contain integers referring to the rows of the second. For example, "spikes.clusters.npy" would contain integer references to the rows of "clusters.brain_location.json" and "clusters.probes.npy"; and "clusters.probes.npy" would contain integer references to "probes.insertion.json". \nBe careful of plurals ("clusters.probe.npy" would not correspond to "probes.insertion.json") and remember we count arrays starting from 0.', 'revision': 'An optional folder to organize data by version. The version label is arbitrary, however the folder must start and end with pound signs, e.g. "#v1.0.0#". Unlike collections, if a specified revision is not found, the previous revision will be returned. The revisions are ordered lexicographically.', 'subject': 'The subject name, typically an arbitrary label', 'timescale': 'If you want to represent times relative to another (non-universal) timescale, a timescale can be appended after an underscore e.g. "spikes.times_ephysClock.npy", "trials.intervals_nidaq", "wheel.timestamps_bpod.csv".'}
The ALF part names and their definitions.
- Type:
dict
- SESSION_SPEC = '({lab}/Subjects/)?{subject}/{date}/{number}'
The session specification pattern
- Type:
str
- COLLECTION_SPEC = '({collection}/)?(#{revision}#/)?'
The collection and revision specification pattern
- Type:
str
- FILE_SPEC = '_?{namespace}?_?{object}\\.{attribute}(?:_{timescale})?(?:\\.{extra})*\\.{extension}$'
The filename specification pattern
- Type:
str
- REL_PATH_SPEC = '({collection}/)?(#{revision}#/)?_?{namespace}?_?{object}\\.{attribute}(?:_{timescale})?(?:\\.{extra})*\\.{extension}$'
The collection, revision and filename specification pattern
- Type:
str
- FULL_SPEC = '({lab}/Subjects/)?{subject}/{date}/{number}/({collection}/)?(#{revision}#/)?_?{namespace}?_?{object}\\.{attribute}(?:_{timescale})?(?:\\.{extra})*\\.{extension}$'
The full ALF path specification pattern
- Type:
str
- class QC(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Bases:
IntEnum
Data QC outcomes.
This enumeration is used by the Alyx database. NB: Pandas cache tables use different codes.
- CRITICAL = 50
Dataset practically unusable, e.g. clock can’t be aligned; data missing or inaccurate.
- FAIL = 40
Dataset does not meet expected standards, e.g. trial event timings different to protocol.
- WARNING = 30
Dataset has minor quality issues, e.g. relatively high SNR, that should not affect most analyses.
- NOT_SET = 0
Dataset quality has not been assessed.
- PASS = 10
Dataset considered ‘gold-standard’, e.g. tight trial event timings, low recorded SNR.
- path_pattern() str [source]
Returns a template string representing the where the ALF parts lie in an ALF path. Brackets denote optional parts. This is used for documentation purposes only.
- describe(part=None, width=99)[source]
Print a description of an ALF part. Prints the path pattern along with a description of the given ALF part (or all parts if None).
- Parameters:
part (str) – ALF part to describe. One from SPEC_DESCRIPTION.keys(). If None, all parts are described.
width (int) – The max line length.
- Return type:
None
Examples
>>> describe() >>> describe('collection') >>> describe('extension', width=120)
- regex(spec: str = '({lab}/Subjects/)?{subject}/{date}/{number}/({collection}/)?(#{revision}#/)?_?{namespace}?_?{object}\\.{attribute}(?:_{timescale})?(?:\\.{extra})*\\.{extension}$', **kwargs) Pattern [source]
Construct a regular expression pattern for parsing or validating an ALF
- Parameters:
spec (str) – The spec string to construct the regular expression from
kwargs (dict[str]) – Optional patterns to replace the defaults
- Returns:
A regular expression Pattern object
- Return type:
re.Pattern
Examples
Regex for a filename
>>> pattern = regex(spec=FILE_SPEC)
Regex for a complete path (including root)
>>> pattern = '.*' + regex(spec=FULL_SPEC).pattern
Regex pattern for specific object name
>>> pattern = regex(object='trials')
- is_valid(filename)[source]
Returns a True for a given file name if it is an ALF file, otherwise returns False
- Parameters:
filename (str) – The name of the file to evaluate
- Returns:
True if filename is valid ALF
- Return type:
bool
Examples
>>> is_valid('trials.feedbackType.npy') True >>> is_valid('_ns_obj.attr1.2622b17c-9408-4910-99cb-abf16d9225b9.metadata.json') True >>> is_valid('spike_train.npy') False >>> is_valid('channels._phy_ids.csv') # WARNING: attribute level namespaces are deprecated True
- is_session_path(path_object)[source]
Checks if the syntax corresponds to a session path. Note that there is no physical check about existence nor contents
- Parameters:
path_object (str, pathlib.Path) – The path object to validate
- Returns:
True if session path a valid ALF session path
- Return type:
bool
- is_uuid_string(string: str) bool [source]
Bool test for randomly generated hexadecimal uuid validity. NB: unlike is_uuid, is_uuid_string checks that uuid is correctly hyphen separated
- is_uuid(uuid: str | int | bytes | UUID, versions=(4,)) bool [source]
Bool test for randomly generated hexadecimal uuid validity. Unlike is_uuid_string, this function accepts UUID objects
- to_alf(object, attribute, extension, namespace=None, timescale=None, extra=None)[source]
Given a set of ALF file parts, return a valid ALF file name. Essential periods and underscores are added by the function.
- Parameters:
object (str) – The ALF object name
attribute (str) – The ALF object attribute name
extension (str) – The file extension
namespace (str) – An optional namespace
timescale (str, tuple) – An optional timescale
extra (str, tuple) – One or more optional extra ALF attributes
- Returns:
A file name string built from the ALF parts
- Return type:
str
Examples
>>> to_alf('spikes', 'times', 'ssv') 'spikes.times.ssv' >>> to_alf('spikes', 'times', 'ssv', namespace='ibl') '_ibl_spikes.times.ssv' >>> to_alf('spikes', 'times', 'ssv', namespace='ibl', timescale='ephysClock') '_ibl_spikes.times_ephysClock.ssv' >>> to_alf('spikes', 'times', 'ssv', namespace='ibl', timescale=('ephys clock', 'minutes')) '_ibl_spikes.times_ephysClock_minutes.ssv' >>> to_alf('spikes', 'times', 'npy', namespace='ibl', timescale='ephysClock', extra='raw') '_ibl_spikes.times_ephysClock.raw.npy' >>> to_alf('wheel', 'timestamps', 'npy', 'ibl', 'bpod', ('raw', 'v12')) '_ibl_wheel.timestamps_bpod.raw.v12.npy'
- readableALF(name: str, capitalize: bool = False) str [source]
Convert camel case string to space separated string.
Given an ALF object name or attribute, return a string where the camel case words are space separated. Acronyms/initialisms are preserved.
- Parameters:
name (str) – The ALF part to format (e.g. object name or attribute).
capitalize (bool) – If true, return with the first letter capitalized.
- Returns:
The name formatted for display, with spaces and capitalization.
- Return type:
str
Examples
>>> readableALF('sparseNoise') == 'sparse noise' >>> readableALF('someROIDataset') == 'some ROI dataset' >>> readableALF('someROIDataset', capitalize=True) == 'Some ROI dataset'
See also
_dromedary