{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Storing estimated HRFs in snirf files\n", "\n", "This notebook estimates the HRF in a finger-tapping experiment by blockaveraging and then stores the result in a snirf file." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2024-09-02T16:04:21.893747Z", "iopub.status.busy": "2024-09-02T16:04:21.893595Z", "iopub.status.idle": "2024-09-02T16:04:23.463127Z", "shell.execute_reply": "2024-09-02T16:04:23.462605Z" } }, "outputs": [], "source": [ "from pathlib import Path\n", "import tempfile\n", "\n", "import matplotlib.pyplot as p\n", "import numpy as np\n", "import xarray as xr\n", "from snirf import Snirf\n", "\n", "import cedalion\n", "import cedalion.datasets\n", "import cedalion.io\n", "import cedalion.nirs\n", "\n", "xr.set_options(display_max_rows=3, display_values_threshold=50, display_expand_data=False)\n", "np.set_printoptions(precision=4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load a finger-tapping dataset \n", "\n", "For this demo we load an example finger-tapping recording through `cedalion.datasets.get_fingertapping`. The file contains a single NIRS element with one block of raw amplitude data. " ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2024-09-02T16:04:23.465682Z", "iopub.status.busy": "2024-09-02T16:04:23.465324Z", "iopub.status.idle": "2024-09-02T16:04:23.572857Z", "shell.execute_reply": "2024-09-02T16:04:23.572332Z" } }, "outputs": [], "source": [ "rec = cedalion.datasets.get_fingertapping()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2024-09-02T16:04:23.575149Z", "iopub.status.busy": "2024-09-02T16:04:23.574976Z", "iopub.status.idle": "2024-09-02T16:04:23.578530Z", "shell.execute_reply": "2024-09-02T16:04:23.578081Z" } }, "outputs": [], "source": [ "# Rename events\n", "rec.stim.cd.rename_events( {\n", " \"1.0\" : \"control\",\n", " \"2.0\" : \"Tapping/Left\",\n", " \"3.0\" : \"Tapping/Right\"\n", "})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculate concentrations" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2024-09-02T16:04:23.580489Z", "iopub.status.busy": "2024-09-02T16:04:23.580204Z", "iopub.status.idle": "2024-09-02T16:04:23.636684Z", "shell.execute_reply": "2024-09-02T16:04:23.636157Z" } }, "outputs": [], "source": [ "dpf = xr.DataArray([6, 6], dims=\"wavelength\", coords={\"wavelength\" : rec[\"amp\"].wavelength})\n", "rec[\"od\"] = - np.log( rec[\"amp\"] / rec[\"amp\"].mean(\"time\") )\n", "rec[\"conc\"] = cedalion.nirs.beer_lambert(rec[\"amp\"], rec.geo3d, dpf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Frequency filtering and splitting into epochs" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2024-09-02T16:04:23.639128Z", "iopub.status.busy": "2024-09-02T16:04:23.638951Z", "iopub.status.idle": "2024-09-02T16:04:23.718534Z", "shell.execute_reply": "2024-09-02T16:04:23.717970Z" } }, "outputs": [], "source": [ "rec[\"conc_freqfilt\"] = rec[\"conc\"].cd.freq_filter(fmin=0.02, fmax=0.5, butter_order=4)\n", "\n", "\n", "cf_epochs = rec[\"conc_freqfilt\"].cd.to_epochs(\n", " rec.stim, # stimulus dataframe\n", " [\"Tapping/Left\", \"Tapping/Right\"], # select events\n", " before=5, # seconds before stimulus\n", " after=20, # seconds after stimulus\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Blockaveraging to estimate the HRFs" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2024-09-02T16:04:23.720740Z", "iopub.status.busy": "2024-09-02T16:04:23.720563Z", "iopub.status.idle": "2024-09-02T16:04:23.739441Z", "shell.execute_reply": "2024-09-02T16:04:23.738982Z" } }, "outputs": [ { "data": { "text/html": [ "
<xarray.DataArray 'concentration' (trial_type: 2, chromo: 2, channel: 28,\n", " reltime: 196)> Size: 176kB\n", "[µM] -0.05399 -0.05393 -0.05398 -0.05408 ... -0.005362 -0.005991 -0.007054\n", "Coordinates: (3/6)\n", " * chromo (chromo) <U3 24B 'HbO' 'HbR'\n", " * channel (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n", " ... ...\n", " * trial_type (trial_type) object 16B 'Tapping/Left' 'Tapping/Right'
\n", " | onset | \n", "duration | \n", "value | \n", "trial_type | \n", "
---|---|---|---|---|
0 | \n", "61.824 | \n", "5.0 | \n", "1.0 | \n", "control | \n", "
1 | \n", "87.296 | \n", "5.0 | \n", "1.0 | \n", "control | \n", "
2 | \n", "181.504 | \n", "5.0 | \n", "1.0 | \n", "control | \n", "
3 | \n", "275.712 | \n", "5.0 | \n", "1.0 | \n", "control | \n", "
4 | \n", "544.640 | \n", "5.0 | \n", "1.0 | \n", "control | \n", "
... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
87 | \n", "2234.112 | \n", "5.0 | \n", "1.0 | \n", "Tapping/Right | \n", "
88 | \n", "2334.848 | \n", "5.0 | \n", "1.0 | \n", "Tapping/Right | \n", "
89 | \n", "2362.240 | \n", "5.0 | \n", "1.0 | \n", "Tapping/Right | \n", "
90 | \n", "2677.504 | \n", "5.0 | \n", "1.0 | \n", "Tapping/Right | \n", "
91 | \n", "2908.032 | \n", "5.0 | \n", "1.0 | \n", "Tapping/Right | \n", "
92 rows × 4 columns
\n", "\n", " | sourceIndex | \n", "detectorIndex | \n", "wavelengthIndex | \n", "dataType | \n", "dataUnit | \n", "
---|---|---|---|---|---|
0 | \n", "1 | \n", "1 | \n", "1 | \n", "1 | \n", "volt | \n", "
1 | \n", "1 | \n", "1 | \n", "2 | \n", "1 | \n", "volt | \n", "
2 | \n", "1 | \n", "9 | \n", "1 | \n", "1 | \n", "volt | \n", "
\n", " | sourceIndex | \n", "detectorIndex | \n", "wavelengthIndex | \n", "dataType | \n", "dataUnit | \n", "
---|---|---|---|---|---|
53 | \n", "8 | \n", "15 | \n", "2 | \n", "1 | \n", "volt | \n", "
54 | \n", "8 | \n", "8 | \n", "1 | \n", "1 | \n", "volt | \n", "
55 | \n", "8 | \n", "8 | \n", "2 | \n", "1 | \n", "volt | \n", "
\n", " | sourceIndex | \n", "detectorIndex | \n", "wavelengthIndex | \n", "dataType | \n", "dataUnit | \n", "dataTypeLabel | \n", "
---|---|---|---|---|---|---|
0 | \n", "1 | \n", "1 | \n", "1 | \n", "99999 | \n", "dimensionless | \n", "dOD | \n", "
1 | \n", "1 | \n", "1 | \n", "2 | \n", "99999 | \n", "dimensionless | \n", "dOD | \n", "
2 | \n", "1 | \n", "9 | \n", "1 | \n", "99999 | \n", "dimensionless | \n", "dOD | \n", "
\n", " | sourceIndex | \n", "detectorIndex | \n", "wavelengthIndex | \n", "dataType | \n", "dataUnit | \n", "dataTypeLabel | \n", "
---|---|---|---|---|---|---|
53 | \n", "8 | \n", "15 | \n", "2 | \n", "99999 | \n", "dimensionless | \n", "dOD | \n", "
54 | \n", "8 | \n", "8 | \n", "1 | \n", "99999 | \n", "dimensionless | \n", "dOD | \n", "
55 | \n", "8 | \n", "8 | \n", "2 | \n", "99999 | \n", "dimensionless | \n", "dOD | \n", "
\n", " | sourceIndex | \n", "detectorIndex | \n", "dataType | \n", "dataUnit | \n", "dataTypeLabel | \n", "
---|---|---|---|---|---|
0 | \n", "1 | \n", "1 | \n", "99999 | \n", "micromolar | \n", "HbO | \n", "
1 | \n", "1 | \n", "1 | \n", "99999 | \n", "micromolar | \n", "HbR | \n", "
2 | \n", "1 | \n", "9 | \n", "99999 | \n", "micromolar | \n", "HbO | \n", "
\n", " | sourceIndex | \n", "detectorIndex | \n", "dataType | \n", "dataUnit | \n", "dataTypeLabel | \n", "
---|---|---|---|---|---|
53 | \n", "8 | \n", "15 | \n", "99999 | \n", "micromolar | \n", "HbR | \n", "
54 | \n", "8 | \n", "8 | \n", "99999 | \n", "micromolar | \n", "HbO | \n", "
55 | \n", "8 | \n", "8 | \n", "99999 | \n", "micromolar | \n", "HbR | \n", "
\n", " | sourceIndex | \n", "detectorIndex | \n", "dataType | \n", "dataUnit | \n", "dataTypeLabel | \n", "
---|---|---|---|---|---|
0 | \n", "1 | \n", "1 | \n", "99999 | \n", "micromolar | \n", "HbO | \n", "
1 | \n", "1 | \n", "1 | \n", "99999 | \n", "micromolar | \n", "HbR | \n", "
2 | \n", "1 | \n", "9 | \n", "99999 | \n", "micromolar | \n", "HbO | \n", "
\n", " | sourceIndex | \n", "detectorIndex | \n", "dataType | \n", "dataUnit | \n", "dataTypeLabel | \n", "
---|---|---|---|---|---|
53 | \n", "8 | \n", "15 | \n", "99999 | \n", "micromolar | \n", "HbR | \n", "
54 | \n", "8 | \n", "8 | \n", "99999 | \n", "micromolar | \n", "HbO | \n", "
55 | \n", "8 | \n", "8 | \n", "99999 | \n", "micromolar | \n", "HbR | \n", "
\n", " | sourceIndex | \n", "detectorIndex | \n", "dataType | \n", "dataUnit | \n", "dataTypeLabel | \n", "dataTypeIndex | \n", "
---|---|---|---|---|---|---|
0 | \n", "1 | \n", "1 | \n", "99999 | \n", "micromolar | \n", "HRF HbO | \n", "3 | \n", "
1 | \n", "1 | \n", "1 | \n", "99999 | \n", "micromolar | \n", "HRF HbR | \n", "3 | \n", "
2 | \n", "1 | \n", "9 | \n", "99999 | \n", "micromolar | \n", "HRF HbO | \n", "3 | \n", "
\n", " | sourceIndex | \n", "detectorIndex | \n", "dataType | \n", "dataUnit | \n", "dataTypeLabel | \n", "dataTypeIndex | \n", "
---|---|---|---|---|---|---|
109 | \n", "8 | \n", "15 | \n", "99999 | \n", "micromolar | \n", "HRF HbR | \n", "4 | \n", "
110 | \n", "8 | \n", "8 | \n", "99999 | \n", "micromolar | \n", "HRF HbO | \n", "4 | \n", "
111 | \n", "8 | \n", "8 | \n", "99999 | \n", "micromolar | \n", "HRF HbR | \n", "4 | \n", "
<xarray.DataArray (channel: 28, chromo: 2, trial_type: 2, time: 196)> Size: 176kB\n", "[µM] -0.05399 -0.05393 -0.05398 -0.05408 ... -0.005362 -0.005991 -0.007054\n", "Coordinates: (3/7)\n", " * time (time) float64 2kB -4.992 -4.864 -4.736 ... 19.71 19.84 19.97\n", " samples (time) int64 2kB 0 1 2 3 4 5 6 7 ... 189 190 191 192 193 194 195\n", " ... ...\n", " * trial_type (trial_type) <U13 104B 'Tapping/Left' 'Tapping/Right'\n", "Attributes:\n", " data_type_group: processed HRF concentrations