{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Data Structures and I/O" ] }, { "cell_type": "code", "execution_count": 1, "id": "1", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:07.980795Z", "iopub.status.busy": "2026-10-07T14:52:07.980572Z", "iopub.status.idle": "2026-10-07T14:52:07.989716Z", "shell.execute_reply": "2026-10-07T14:52:07.988646Z" } }, "outputs": [], "source": [ "# This cells setups the environment when executed in Google Colab.\n", "try:\n", " import google.colab\n", " !curl -s https://raw.githubusercontent.com/ibs-lab/cedalion/dev/scripts/colab_setup.py -o colab_setup.py\n", " # Select branch with --branch \"branch name\" (default is \"dev\")\n", " %run colab_setup.py\n", "except ImportError:\n", " pass" ] }, { "cell_type": "code", "execution_count": 2, "id": "2", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:07.991371Z", "iopub.status.busy": "2026-10-07T14:52:07.991205Z", "iopub.status.idle": "2026-10-07T14:52:09.655386Z", "shell.execute_reply": "2026-10-07T14:52:09.654445Z" }, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import xarray as xr\n", "import tempfile\n", "from pathlib import Path\n", "\n", "import cedalion\n", "import cedalion.io\n", "import cedalion.data\n", "import cedalion.nirs\n", "import cedalion.xrutils as xrutils\n", "\n", "pd.set_option('display.max_rows', 10)\n", "xr.set_options(display_expand_data=False);" ] }, { "cell_type": "code", "execution_count": 3, "id": "3", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:09.657781Z", "iopub.status.busy": "2026-10-07T14:52:09.657454Z", "iopub.status.idle": "2026-10-07T14:52:09.661066Z", "shell.execute_reply": "2026-10-07T14:52:09.660194Z" } }, "outputs": [], "source": [ "# helper function\n", "def calc_concentratoin(rec):\n", " od = cedalion.nirs.cw.int2od(rec[\"amp\"])\n", " dpf = xr.DataArray([6, 6], dims=\"wavelength\", coords={\"wavelength\" : od.wavelength})\n", " return cedalion.nirs.cw.od2conc(od, rec.geo3d, dpf)" ] }, { "cell_type": "markdown", "id": "4", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Reading Snirf Files\n", "\n", "Snirf files can be loaded with the `cedalion.io.read_snirf` method. This returns a list of `cedalion.dataclasses.Recording` objects. The " ] }, { "cell_type": "code", "execution_count": 4, "id": "5", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:09.662828Z", "iopub.status.busy": "2026-10-07T14:52:09.662612Z", "iopub.status.idle": "2026-10-07T14:52:09.919432Z", "shell.execute_reply": "2026-10-07T14:52:09.918571Z" } }, "outputs": [ { "data": { "text/plain": [ "PosixPath('/home/runner/.cache/cedalion/dev/fingertapping.zip.unzip/fingertapping/sub-01_task-tapping_nirs.snirf')" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "[]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "1" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "path_to_snirf_file = cedalion.data.get_fingertapping_snirf_path()\n", "\n", "recordings = cedalion.io.read_snirf(path_to_snirf_file)\n", "\n", "display(path_to_snirf_file)\n", "display(recordings)\n", "display(len(recordings))" ] }, { "cell_type": "markdown", "id": "6", "metadata": {}, "source": [ "## Accessing example datasets\n", "\n", "Example datasets are accessible through functions in `cedalion.data`. These take care of downloading, caching and updating the data files. Often they also already load the data." ] }, { "cell_type": "markdown", "id": "7", "metadata": {}, "source": [] }, { "cell_type": "code", "execution_count": 5, "id": "8", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:09.921305Z", "iopub.status.busy": "2026-10-07T14:52:09.921070Z", "iopub.status.idle": "2026-10-07T14:52:10.051775Z", "shell.execute_reply": "2026-10-07T14:52:10.048185Z" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "rec = cedalion.data.get_fingertapping()\n", "display(rec)" ] }, { "cell_type": "markdown", "id": "9", "metadata": {}, "source": [ "## Recording containers\n", "\n", "The class `cedalion.dataclasses.Recording` is Cedalion's **main data container** to carry related data objects through the program. \n", "It can store time series, masks, auxiliary timeseries, probe, headmodel and stimulus information as well as meta data about the recording.\n", "It has the following properties:\n", "\n", "\n", "\n", "| field | description | \n", "|------------|------------------------------------------------------------|\n", "| timeseries | a dictionary of timeseries objects | \n", "| masks | a dictionary of masks that flag time points as good or bad | \n", "| geo3d | 3D probe geometry | \n", "| geo2d | 2D probe geometry | \n", "| stim | dataframe with stimulus information |\n", "| aux_ts | dictionary of auxiliary time series objects |\n", "| aux_obj | dictionary for any other auxiliary objects |\n", "| head_model | voxel image, cortex and scalp surfaces |\n", "| meta_data | dictionary for meta data |\n", "\n", "* container is very similar to the layout of a snirf file\n", "* `Recording` maps mainly to nirs groups\n", "* timeseries objects map to data elements\n", "\n", "\n", "### Dictionaries in `Recording`\n", "\n", "- dictionaries are key value stores\n", "- maintain order in which values are added -> facilitate workflows\n", "- the user differentiates time series by name. \n", "- names are free to choose but there are a few **canonical names** used by `read_snirf` and expected by `write_snirf`:\n", "\n", "| data type | canonical name| \n", "|-----------------------------------|---------------|\n", "| unprocessed raw | \"amp\" |\n", "| processed raw | \"amp\" |\n", "| processed dOD | \"od\" |\n", "| processed concentrations | \"conc\" |\n", "| processed central moments\" | \"moments\" |\n", "| processed blood flow inddata_structures_oldex | \"bfi\" |\n", "| processed HRF dOD | \"hrf_od\" |\n", "| processed HRF central moments | \"hrf_moments\" |\n", "| processed HRF concentrations\" | \"hrf_conc\" |\n", "| processed HRF blood flow index | \"hrf_bfi\" |\n", "| processed absorption coefficient | \"mua\" |\n", "| processed scattering coefficient | \"musp\" |\n", " \n", " \n", "\n" ] }, { "cell_type": "markdown", "id": "10", "metadata": {}, "source": [ "### Inspecting a Recording container" ] }, { "cell_type": "code", "execution_count": 6, "id": "11", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:10.054276Z", "iopub.status.busy": "2026-10-07T14:52:10.054038Z", "iopub.status.idle": "2026-10-07T14:52:10.063724Z", "shell.execute_reply": "2026-10-07T14:52:10.063026Z" } }, "outputs": [ { "data": { "text/plain": [ "odict_keys(['amp'])" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "xarray.core.dataarray.DataArray" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display(rec.timeseries.keys())\n", "display(type(rec.timeseries[\"amp\"]))" ] }, { "cell_type": "code", "execution_count": 7, "id": "12", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:10.065959Z", "iopub.status.busy": "2026-10-07T14:52:10.065766Z", "iopub.status.idle": "2026-10-07T14:52:10.075183Z", "shell.execute_reply": "2026-10-07T14:52:10.074518Z" } }, "outputs": [ { "data": { "text/plain": [ "OrderedDict([('SubjectID', 'P1'),\n", " ('MeasurementDate', '2020-01-01'),\n", " ('MeasurementTime', '13:16:16Z'),\n", " ('LengthUnit', 'm'),\n", " ('TimeUnit', 's'),\n", " ('FrequencyUnit', 'Hz'),\n", " ('DateOfBirth', '1986-01-01'),\n", " ('MNE_coordFrame', 4),\n", " ('sex', '1')])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rec.meta_data" ] }, { "cell_type": "markdown", "id": "13", "metadata": {}, "source": [ "Shortcut for accessing time series:" ] }, { "cell_type": "code", "execution_count": 8, "id": "14", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:10.077615Z", "iopub.status.busy": "2026-10-07T14:52:10.077421Z", "iopub.status.idle": "2026-10-07T14:52:10.085378Z", "shell.execute_reply": "2026-10-07T14:52:10.084315Z" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rec[\"amp\"] is rec.timeseries[\"amp\"]" ] }, { "cell_type": "markdown", "id": "15", "metadata": {}, "source": [ "## Time Series\n", "\n", "
\n", "\n", "
\n", "\n", "- mulitvariate time series are stored in `xarray.DataArrays`\n", "- if it has dimensions 'channel' and 'time' we call it a `NDTimeSeries`\n", "- named dimensions\n", "- coordinates\n", "- physical units\n", "\n" ] }, { "cell_type": "code", "execution_count": 9, "id": "16", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:10.087317Z", "iopub.status.busy": "2026-10-07T14:52:10.087101Z", "iopub.status.idle": "2026-10-07T14:52:10.130512Z", "shell.execute_reply": "2026-10-07T14:52:10.129962Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray (channel: 28, wavelength: 2, time: 23239)> Size: 10MB\n",
       "[V] 0.09137 0.09099 0.09102 0.09044 0.09094 ... 1.277 1.273 1.273 1.273 1.276\n",
       "Coordinates:\n",
       "  * time        (time) float64 186kB 0.0 0.128 0.256 ... 2.974e+03 2.974e+03\n",
       "    samples     (time) int64 186kB 0 1 2 3 4 5 ... 23234 23235 23236 23237 23238\n",
       "  * channel     (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n",
       "    source      (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S8' 'S8' 'S8'\n",
       "    detector    (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'\n",
       "  * wavelength  (wavelength) float64 16B 760.0 850.0\n",
       "Attributes:\n",
       "    data_type_group:  unprocessed raw
" ], "text/plain": [ " Size: 10MB\n", "[V] 0.09137 0.09099 0.09102 0.09044 0.09094 ... 1.277 1.273 1.273 1.273 1.276\n", "Coordinates:\n", " * time (time) float64 186kB 0.0 0.128 0.256 ... 2.974e+03 2.974e+03\n", " samples (time) int64 186kB 0 1 2 3 4 5 ... 23234 23235 23236 23237 23238\n", " * channel (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n", " source (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S8' 'S8' 'S8'\n", " detector (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'\n", " * wavelength (wavelength) float64 16B 760.0 850.0\n", "Attributes:\n", " data_type_group: unprocessed raw" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rec[\"amp\"]" ] }, { "cell_type": "code", "execution_count": 10, "id": "17", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:10.133061Z", "iopub.status.busy": "2026-10-07T14:52:10.132871Z", "iopub.status.idle": "2026-10-07T14:52:10.295163Z", "shell.execute_reply": "2026-10-07T14:52:10.294559Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'concentration' (chromo: 2, channel: 28, time: 23239)> Size: 10MB\n",
       "[µM] 0.1336 0.00383 0.3486 0.1915 0.4156 ... -1.037 -1.004 -1.073 -1.067 -1.076\n",
       "Coordinates:\n",
       "  * chromo    (chromo) <U3 24B 'HbO' 'HbR'\n",
       "  * time      (time) float64 186kB 0.0 0.128 0.256 ... 2.974e+03 2.974e+03\n",
       "    samples   (time) int64 186kB 0 1 2 3 4 5 ... 23234 23235 23236 23237 23238\n",
       "  * channel   (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n",
       "    source    (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S7' 'S8' 'S8' 'S8'\n",
       "    detector  (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'
" ], "text/plain": [ " Size: 10MB\n", "[µM] 0.1336 0.00383 0.3486 0.1915 0.4156 ... -1.037 -1.004 -1.073 -1.067 -1.076\n", "Coordinates:\n", " * chromo (chromo) \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray (label: 55, digitized: 3)> Size: 1kB\n",
       "[m] -0.04161 0.0268 0.1299 -0.06477 0.05814 ... 0.06258 0.08226 0.01751 0.06619\n",
       "Coordinates:\n",
       "    type     (label) object 440B PointType.SOURCE ... PointType.LANDMARK\n",
       "  * label    (label) <U3 660B 'S1' 'S2' 'S3' 'S4' 'S5' ... '25' '26' '27' '28'\n",
       "Dimensions without coordinates: digitized
" ], "text/plain": [ " Size: 1kB\n", "[m] -0.04161 0.0268 0.1299 -0.06477 0.05814 ... 0.06258 0.08226 0.01751 0.06619\n", "Coordinates:\n", " type (label) object 440B PointType.SOURCE ... PointType.LANDMARK\n", " * label (label) \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray (channel: 28, wavelength: 2)> Size: 448B\n",
       "[V] 0.09514 0.1902 0.2256 0.6123 0.1177 ... 0.485 0.5704 0.9371 0.6681 1.259\n",
       "Coordinates:\n",
       "  * channel     (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n",
       "    source      (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S8' 'S8' 'S8'\n",
       "    detector    (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'\n",
       "  * wavelength  (wavelength) float64 16B 760.0 850.0
" ], "text/plain": [ " Size: 448B\n", "[V] 0.09514 0.1902 0.2256 0.6123 0.1177 ... 0.485 0.5704 0.9371 0.6681 1.259\n", "Coordinates:\n", " * channel (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n", " source (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S8' 'S8' 'S8'\n", " detector (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'\n", " * wavelength (wavelength) float64 16B 760.0 850.0" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "amp = rec[\"amp\"]\n", "\n", "amp.mean(\"time\") " ] }, { "cell_type": "markdown", "id": "22", "metadata": {}, "source": [ "get the second channel formed by S1 and D2:" ] }, { "cell_type": "code", "execution_count": 13, "id": "23", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:10.327112Z", "iopub.status.busy": "2026-10-07T14:52:10.326944Z", "iopub.status.idle": "2026-10-07T14:52:10.339653Z", "shell.execute_reply": "2026-10-07T14:52:10.338925Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray (wavelength: 2, time: 23239)> Size: 372kB\n",
       "[V] 0.2275 0.2297 0.2261 0.2259 0.2267 ... 0.6126 0.6136 0.6072 0.6087 0.6091\n",
       "Coordinates:\n",
       "  * time        (time) float64 186kB 0.0 0.128 0.256 ... 2.974e+03 2.974e+03\n",
       "    samples     (time) int64 186kB 0 1 2 3 4 5 ... 23234 23235 23236 23237 23238\n",
       "    channel     <U4 16B 'S1D2'\n",
       "    source      object 8B 'S1'\n",
       "    detector    object 8B 'D2'\n",
       "  * wavelength  (wavelength) float64 16B 760.0 850.0\n",
       "Attributes:\n",
       "    data_type_group:  unprocessed raw
" ], "text/plain": [ " Size: 372kB\n", "[V] 0.2275 0.2297 0.2261 0.2259 0.2267 ... 0.6126 0.6136 0.6072 0.6087 0.6091\n", "Coordinates:\n", " * time (time) float64 186kB 0.0 0.128 0.256 ... 2.974e+03 2.974e+03\n", " samples (time) int64 186kB 0 1 2 3 4 5 ... 23234 23235 23236 23237 23238\n", " channel \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray (channel: 28, digitized: 3)> Size: 672B\n",
       "[m] -0.04161 0.0268 0.1299 -0.04161 0.0268 ... 0.06571 0.08189 0.02043 0.06571\n",
       "Coordinates:\n",
       "    type      (channel) object 224B PointType.SOURCE ... PointType.SOURCE\n",
       "    label     (channel) <U3 336B 'S1' 'S1' 'S1' 'S1' ... 'S7' 'S8' 'S8' 'S8'\n",
       "  * channel   (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n",
       "    source    (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S7' 'S8' 'S8' 'S8'\n",
       "    detector  (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'\n",
       "Dimensions without coordinates: digitized
" ], "text/plain": [ " Size: 672B\n", "[m] -0.04161 0.0268 0.1299 -0.04161 0.0268 ... 0.06571 0.08189 0.02043 0.06571\n", "Coordinates:\n", " type (channel) object 224B PointType.SOURCE ... PointType.SOURCE\n", " label (channel) \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray (channel: 28)> Size: 224B\n",
       "[m] 0.03929 0.03891 0.04089 0.00826 0.03718 ... 0.00732 0.04067 0.03344 0.007534\n",
       "Coordinates:\n",
       "  * channel   (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n",
       "    source    (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S7' 'S8' 'S8' 'S8'\n",
       "    detector  (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'
" ], "text/plain": [ " Size: 224B\n", "[m] 0.03929 0.03891 0.04089 0.00826 0.03718 ... 0.00732 0.04067 0.03344 0.007534\n", "Coordinates:\n", " * channel (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n", " source (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S7' 'S8' 'S8' 'S8'\n", " detector (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "distances = xrutils.norm(rec.geo3d.loc[amp.source] - rec.geo3d.loc[amp.detector], \"digitized\")\n", "display(distances)" ] }, { "cell_type": "markdown", "id": "27", "metadata": {}, "source": [ "Physical units:" ] }, { "cell_type": "code", "execution_count": 16, "id": "28", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:10.381660Z", "iopub.status.busy": "2026-10-07T14:52:10.381437Z", "iopub.status.idle": "2026-10-07T14:52:10.394479Z", "shell.execute_reply": "2026-10-07T14:52:10.393562Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray (channel: 28)> Size: 28B\n",
       "True True True False True True True ... False True True False True True False\n",
       "Coordinates:\n",
       "  * channel   (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n",
       "    source    (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S7' 'S8' 'S8' 'S8'\n",
       "    detector  (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'
" ], "text/plain": [ " Size: 28B\n", "True True True False True True True ... False True True False True True False\n", "Coordinates:\n", " * channel (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n", " source (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S7' 'S8' 'S8' 'S8'\n", " detector (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "rec.masks[\"distance_mask\"] = distances > 1.5 * cedalion.units.cm\n", "display(rec.masks[\"distance_mask\"])" ] }, { "cell_type": "markdown", "id": "29", "metadata": {}, "source": [ "Additional functionality through accessors:" ] }, { "cell_type": "code", "execution_count": 17, "id": "30", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:10.396027Z", "iopub.status.busy": "2026-10-07T14:52:10.395862Z", "iopub.status.idle": "2026-10-07T14:52:10.406114Z", "shell.execute_reply": "2026-10-07T14:52:10.405240Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray (channel: 28)> Size: 224B\n",
       "[mm] 39.29 38.91 40.89 8.26 37.18 37.6 ... 40.43 37.22 7.32 40.67 33.44 7.534\n",
       "Coordinates:\n",
       "  * channel   (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n",
       "    source    (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S7' 'S8' 'S8' 'S8'\n",
       "    detector  (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'
" ], "text/plain": [ " Size: 224B\n", "[mm] 39.29 38.91 40.89 8.26 37.18 37.6 ... 40.43 37.22 7.32 40.67 33.44 7.534\n", "Coordinates:\n", " * channel (channel) object 224B 'S1D1' 'S1D2' 'S1D3' ... 'S8D8' 'S8D16'\n", " source (channel) object 224B 'S1' 'S1' 'S1' 'S1' ... 'S7' 'S8' 'S8' 'S8'\n", " detector (channel) object 224B 'D1' 'D2' 'D3' 'D9' ... 'D7' 'D8' 'D16'" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "distances.pint.to(\"mm\")" ] }, { "cell_type": "markdown", "id": "31", "metadata": {}, "source": [ "## Writing snirf files\n", "\n", "- pass `Recording` object to `cedalion.io.write_snirf`\n", "- caveat: many `Recording`fields have correspondants in snirf files, but not all." ] }, { "cell_type": "code", "execution_count": 18, "id": "32", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:10.407719Z", "iopub.status.busy": "2026-10-07T14:52:10.407571Z", "iopub.status.idle": "2026-10-07T14:52:10.762479Z", "shell.execute_reply": "2026-10-07T14:52:10.760966Z" } }, "outputs": [], "source": [ "with tempfile.TemporaryDirectory() as tmpdir:\n", " output_path = Path(tmpdir).joinpath(\"test.snirf\")\n", "\n", " cedalion.io.write_snirf(output_path, rec)" ] }, { "cell_type": "markdown", "id": "33", "metadata": {}, "source": [ "## Summary\n", "\n", "In this notebook you have seen Cedalion's three primary data types:\n", "\n", "| Type | xarray type | Key dimensions | Purpose |\n", "|------|------------|---------------|--------|\n", "| `NDTimeSeries` | `DataArray` | `channel`, `wavelength`/`chromo`, `time` | Timeseries data with labels and units |\n", "| `LabeledPoints` | `DataArray` | `label`, `` | Optode/landmark 3-D positions |\n", "| `Recording` | Python dataclass | — | Session container: timeseries, geometry, stim, masks |\n", "\n", "**Key takeaways:**\n", "- Use `.sel()` and `.loc[]` to index by label rather than by position.\n", "- Canonical timeseries keys (`\"amp\"`, `\"od\"`, `\"conc\"`) are used by `read_snirf` and `write_snirf`; you can add your own under any name.\n", "- Physical units are attached via pint-xarray (`.pint.quantify()`, `.pint.to()`); always check that units are preserved after array operations.\n", "\n", "**Next steps:** see the [Quick Start guide](../../docs/getting_started/quickstart.md) for a complete preprocessing pipeline, or jump directly into the [Tutorial Notebooks](../../docs/tutorial.rst)." ] }, { "cell_type": "markdown", "id": "34", "metadata": {}, "source": [ "## References" ] }, { "cell_type": "code", "execution_count": 19, "id": "35", "metadata": { "execution": { "iopub.execute_input": "2026-10-07T14:52:10.764834Z", "iopub.status.busy": "2026-10-07T14:52:10.764624Z", "iopub.status.idle": "2026-10-07T14:52:11.245813Z", "shell.execute_reply": "2026-10-07T14:52:11.244914Z" } }, "outputs": [ { "data": { "text/html": [ "

Methods used

[1]Luke2021cedalion.data.get_fingertapping, cedalion.data.get_fingertapping_snirf_pathRobert Luke and David McAlpine.\n", "fNIRS Finger Tapping Data in BIDS Format.\n", "September 2021.\n", "doi:10.5281/zenodo.5529797.
[2]Tucker2022cedalion.io.snirf.read_snirfStephen Tucker, Jay Dubb, Sreekanth Kura, Alexander von Lühmann, Robert Franke, Jörn M. Horschig, Samuel Powell, Robert Oostenveld, Michael Lührs, Édouard Delaire, Zahra M. Aghajan, Hanseok Yun, Meryem A. Yücel, Qianqian Fang, Theodore J. Huppert, Blaise deB. Frederick, Luca Pollonini, David A. Boas, and Robert Luke.\n", "Introduction to the shared near infrared spectroscopy format.\n", "Neurophotonics, 10(1):013507, 2022.\n", "doi:10.1117/1.NPh.10.1.013507.
[3]Delpy1988cedalion.nirs.cw.int2od, cedalion.nirs.cw.od2concD. T. Delpy, M. Cope, P. van der Zee, S. Arridge, S. Wray, and J. Wyatt.\n", "Estimation of optical pathlength through tissue from direct time of flight measurement.\n", "Physics in Medicine and Biology, 33(12):1433–1442, 1988.\n", "doi:10.1088/0031-9155/33/12/008.
[4]Villringer1997cedalion.nirs.cw.int2od, cedalion.nirs.cw.od2concArno Villringer and Britton Chance.\n", "Non-invasive optical spectroscopy and imaging of human brain function.\n", "Trends in Neurosciences, 20(10):435–442, 1997.\n", "doi:10.1016/S0166-2236(97)01132-6.
[5]Prahl1998cedalion.nirs.common.get_extinction_coefficientsScott A. Prahl.\n", "Optical absorption of hemoglobin.\n", "Oregon Medical Laser Center, online resource, 1998.\n", "URL: https://omlc.org/spectra/hemoglobin/.
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "cedalion.bib.dump_to_notebook()" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "cedalion_default_3.11", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.15" } }, "nbformat": 4, "nbformat_minor": 5 }