From e279629bf9a628e288e53617d5ddce090b2be81e Mon Sep 17 00:00:00 2001 From: Stephen Scott Tucker Date: Fri, 23 Aug 2024 12:56:57 -0400 Subject: [PATCH] Proposal: `measurementLists` Group as alternative to many `measurementList1`...`measurementList2` indexed groups (#115) Co-authored-by: Samuel Powell Co-authored-by: David Boas Co-authored-by: Sreekanth kura --- .github/workflows/wordlist.txt | 1 + CHANGELOG.md | 4 +- snirf_specification.md | 120 +++++++++++++++++++++++++++++++-- 3 files changed, 120 insertions(+), 5 deletions(-) diff --git a/.github/workflows/wordlist.txt b/.github/workflows/wordlist.txt index a84e29e..f8d7b0b 100644 --- a/.github/workflows/wordlist.txt +++ b/.github/workflows/wordlist.txt @@ -281,3 +281,4 @@ dataOffset forihuelaespina StO StO2 +measurementLists diff --git a/CHANGELOG.md b/CHANGELOG.md index 311edb7..1a53454 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ SNIRF uses the [Semantic Versioning](https://semver.org) scheme. +### `2.0` In development +* Add `nirs(i)/data(j)/measurementLists` as an alternative to the indexed-Group measurementList `nirs(i)/data(j)/measurementList(k)`. ### `v1.1` @@ -22,7 +24,7 @@ SNIRF uses the [Semantic Versioning](https://semver.org) scheme. * Added language preventing `metaDataTags` sub-groups * Added notice that the summary table is intended to be machine-readable * Removed local channel indexing owing to incomplete specification. - + ### `v1.0` (September 23 2021) [View this version of the specification](https://github.com/fNIRS/snirf/blob/v1.0/snirf_specification.md) diff --git a/snirf_specification.md b/snirf_specification.md index a20167c..48c54c5 100644 --- a/snirf_specification.md +++ b/snirf_specification.md @@ -30,6 +30,18 @@ Shared Near Infrared Spectroscopy Format (SNIRF) Specification * [data.measurementList.dataTypeIndex](#nirsidatajmeasurementlistkdatatypeindex) * [data.measurementList.sourcePower](#nirsidatajmeasurementlistksourcepower) * [data.measurementList.detectorGain](#nirsidatajmeasurementlistkdetectorgain) + * [data.measurementLists](#nirsidatajmeasurementlists) + * [data.measurementLists.sourceIndex](#nirsidatajmeasurementlistssourceindex) + * [data.measurementLists.detectorIndex](#nirsidatajmeasurementlistsdetectorindex) + * [data.measurementLists.wavelengthIndex](#nirsidatajmeasurementlistswavelengthindex) + * [data.measurementLists.wavelengthActual](#nirsidatajmeasurementlistswavelengthactual) + * [data.measurementLists.wavelengthEmissionActual](#nirsidatajmeasurementlistswavelengthemissionactual) + * [data.measurementLists.dataType](#nirsidatajmeasurementlistsdatatype) + * [data.measurementLists.dataUnit](#nirsidatajmeasurementlistsdataunit) + * [data.measurementLists.dataTypeLabel](#nirsidatajmeasurementlistsdatatypelabel) + * [data.measurementLists.dataTypeIndex](#nirsidatajmeasurementlistsdatatypeindex) + * [data.measurementLists.sourcePower](#nirsidatajmeasurementlistssourcepower) + * [data.measurementLists.detectorGain](#nirsidatajmeasurementlistsdetectorgain) * [stim](#nirsistimj) * [stim.name](#nirsistimjname) * [stim.data](#nirsistimjdata) @@ -170,6 +182,18 @@ Note that this table serves as machine-readable schema for the SNIRF format. Its |            `dataTypeIndex`            | * Data type index for a given channel  |   ``  * | |            `sourcePower`              | * Source power for a given channel  |   ``    | |            `detectorGain`             | * Detector gain for a given channel  |   ``    | +|        `measurementLists`            | * source-detector information     |  `{.}` * | +|            `sourceIndex`              | * Source index for each channel |   `[,...]`* | +|            `detectorIndex`            | * Detector index for each channel |   `[,...]`* | +|            `wavelengthIndex`          | * Wavelength index for each channel |   `[,...]`* | +|            `wavelengthActual`         | * Actual wavelength for each channel |   `[,...]`  | +|            `wavelengthEmissionActual` | * Actual emission wavelength for each channel|   `[,...]`  | +|            `dataType`                 | * Data type for each channel |   `[,...]`* | +|            `dataUnit`                 | * SI unit for each channel |   `["s",...]`  | +|            `dataTypeLabel`            | * Data type name for each channel |   `["s",...]` | +|            `dataTypeIndex`            | * Data type index for each channel |   `[,...]`* | +|            `sourcePower`              | * Source power for each channel |   `[,...]`  | +|            `detectorGain`             | * Detector gain for each channel |   `[,...]`  | |     `stim{i}`                         | * Root-group for stimulus measurements       |  `{i}`    | |         `name`                        | * Name of the stimulus data     |   `"s"`  + | |         `data`                        | * Data stream of the stimulus channel | `[[,...]]` +| @@ -411,7 +435,7 @@ a time spacing of 0.2 (s) indicates a sampling rate of 5 Hz. Chunked data is allowed to support real-time streaming of data in this array. #### /nirs(i)/data(j)/measurementList(k) -* **Presence**: required +* **Presence**: required if `measurementLists` is not present * **Type**: indexed group * **Location**: `/nirs(i)/data(j)/measurementList(k)` @@ -537,6 +561,94 @@ As described below, optional variables `probe.sourceLabels` and `probe.detectorLabels` are provided for indicating the instrument specific label for sources and detectors. +#### /nirs(i)/data(j)/measurementLists +* **Presence**: required if measurementList is not present +* **Type**: group +* **Location**: `/nirs(i)/data(j)/measurementLists` + +The group for measurement list variables which map the data array onto the probe geometry (sources and detectors), data type, and wavelength. This group's datasets are arrays with size ``, with each position describing the corresponding column in the data matrix. (i.e. the values at `measurementLists/sourceIndex(3)` and `measurementLists/detectorIndex(3)` correspond to `dataTimeSeries(:,3)`). + +This group is required only if the indexed-group format `/nirs(i)/data(j)/measurementList(k)` is not used to encode the measurement list. `measurementLists` is an alternative that may offer better performance for larger probes. + +The arrays of `measurementLists` are: + +#### /nirs(i)/data(j)/measurementLists/sourceIndex +* **Presence**: required if measurementLists is present +* **Type**: integer 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/sourceIndex` + +Source indices for each channel. A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. + +#### /nirs(i)/data(j)/measurementLists/detectorIndex +* **Presence**: required if measurementLists is present +* **Type**: integer 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/detectorIndex` + +Detector indices for each channel. A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. + +#### /nirs(i)/data(j)/measurementLists/wavelengthIndex +* **Presence**: required if measurementLists is present +* **Type**: integer 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/wavelengthIndex` + +Index of the "nominal" wavelength (in `probe.wavelengths`) for each channel. A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. + +#### /nirs(i)/data(j)/measurementLists/wavelengthActual +* **Presence**: optional +* **Type**: numeric 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/wavelengthActual` + +Actual (measured) wavelength in nm, if available, for the source in each channel. A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. + +#### /nirs(i)/data(j)/measurementLists/wavelengthEmissionActual +* **Presence**: optional +* **Type**: numeric 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/wavelengthEmissionActual` + +Actual (measured) emission wavelength in nm, if available, for the source in each channel. A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. + +#### /nirs(i)/data(j)/measurementLists/dataType +* **Presence**: required if measurementLists is present +* **Type**: integer 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/dataType` + +A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. See Appendix for list of possible values. + +#### /nirs(i)/data(j)/measurementLists/dataUnit +* **Presence**: optional +* **Type**: string 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/dataUnit` + +International System of Units (SI units) identifier for each channel. A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. + +#### /nirs(i)/data(j)/measurementLists/dataTypeLabel +* **Presence**: optional +* **Type**: string 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/dataTypeLabel` + +Data-type label. A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. + +#### /nirs(i)/data(j)/measurementLists/dataTypeIndex +* **Presence**: required if measurementLists is present +* **Type**: integer 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/dataTypeIndex` + +Data-type specific parameter indices. A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. Note that the Time Domain and Diffuse Correlation Spectroscopy data types have two additional parameters and so `dataTimeIndex` must be a 2-D array with 2 columns that index the additional parameters. + +#### /nirs(i)/data(j)/measurementLists/sourcePower +* **Presence**: optional +* **Type**: numeric 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/sourcePower` + +A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. Units are optionally defined in `metaDataTags`. + +#### /nirs(i)/data(j)/measurementLists/detectorGain +* **Presence**: optional +* **Type**: numeric 1-D array +* **Location**: `/nirs(i)/data(j)/measurementLists/detectorGain` + +A 1-D array with length equal to the size of the second dimension of `/nirs(i)/data(j)/dataTimeSeries`. Units are optionally defined in `metaDataTags`. + #### /nirs(i)/stim(j) * **Presence**: optional * **Type**: indexed group @@ -574,7 +686,7 @@ used to annotate the meanings of each data column. #### /nirs(i)/stim(j)/dataLabels * **Presence**: optional -* **Type**: string array +* **Type**: string 1-D array * **Location**: `/nirs(i)/stim(j)/dataLabels(k)` This is a string array providing annotations for each data column in @@ -754,7 +866,7 @@ wavelengths>`. This is indexed by `measurementList(k).sourceIndex` and #### /nirs(i)/probe/detectorLabels * **Presence**: optional -* **Type**: string array +* **Type**: string 1-D array * **Location**: `/nirs(i)/probe/detectorLabels(j)` This is a string array providing user friendly or instrument specific labels @@ -793,7 +905,7 @@ index to the labels of the given landmark. Label names are stored in the #### /nirs(i)/probe/landmarkLabels(j) * **Presence**: optional -* **Type**: string array +* **Type**: string 1-D array * **Location**: `/nirs(i)/probe/landmarkLabels(j)` This string array stores the names of the landmarks. The first string denotes