Bladeren bron

Added comments and resources

Reema Gupta 10 maanden geleden
bovenliggende
commit
3a9952cab2
1 gewijzigde bestanden met toevoegingen van 114 en 50 verwijderingen
  1. 114 50
      notebooks/05-nix.ipynb

+ 114 - 50
notebooks/05-nix.ipynb

@@ -8,7 +8,7 @@
     }
    },
    "source": [
-    "# Storing the data and analysis results"
+    "# Data organization and storage with NIX (and odML)"
    ]
   },
   {
@@ -281,13 +281,14 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "id: ee066f7a-c76f-41d2-97a4-bf84873d8ae6\n",
-      "created at: 2023-07-13 23:57:01\n",
-      "updated at: 2023-07-13 23:57:01\n"
+      "id: 1dc6a25a-6817-45ca-9ea1-cbc2a1f4095c\n",
+      "created at: 2023-07-14 16:23:42\n",
+      "updated at: 2023-07-14 16:23:42\n"
      ]
     }
    ],
    "source": [
+    "# Almost all nix entities have these standard fields associated\n",
     "import datetime as dt\n",
     "\n",
     "print(\"id:\", nixfile.id)\n",
@@ -369,6 +370,8 @@
    },
    "outputs": [],
    "source": [
+    "# Re-using code snippet from previous tutorial to \n",
+    "# get the trial data we were working with\n",
     "with neo.io.NixIO('../data/i140703-001.nix', 'ro') as io:\n",
     "    block = io.read_block()\n",
     "\n",
@@ -470,6 +473,7 @@
     "binned_spiketrains = elephant.conversion.BinnedSpikeTrain(\n",
     "    sua_spiketrains_with_spikes, binsize=3*pq.ms)\n",
     "\n",
+    "# Cross correlation analysis result to store\n",
     "cross_corr_matrix = elephant.spike_train_correlation.correlation_coefficient(\n",
     "    binned_spiketrains)"
    ]
@@ -506,6 +510,8 @@
     }
    ],
    "source": [
+    "# nix files are hierarchical and must contain atleast\n",
+    "# one block in order to store data\n",
     "nixfile.blocks"
    ]
   },
@@ -554,6 +560,7 @@
    "outputs": [],
    "source": [
     "# Storing the cross correlation matrix as a data array\n",
+    "# Attributes label and unit help store self-describing data\n",
     "cross_coerr_data_array = analysis_nixblock.create_data_array(\n",
     "    name=\"correlation_matrix\", array_type=\"nix.analysis.correlation\", \n",
     "    data=cross_corr_matrix,\n",
@@ -593,6 +600,7 @@
     }
    ],
    "source": [
+    "# Set dimension represents categories rather than physical quantities\n",
     "cross_coerr_data_array.append_set_dimension(\n",
     "    labels=[\"neuron %i\" % i for i in range(cross_corr_matrix.shape[0])])\n",
     "cross_coerr_data_array.append_set_dimension(\n",
@@ -620,9 +628,10 @@
    },
    "outputs": [],
    "source": [
+    "# Retrieving the data array 'correlation_matrix'\n",
     "plot_data_array = nixfile.blocks['analysis'].data_arrays['correlation_matrix']\n",
     "\n",
-    "# Extract the plot data\n",
+    "# Extracting data to plot\n",
     "plot_data = plot_data_array[:]\n",
     "np.fill_diagonal(plot_data, np.nan) # Set diagonal to NaN for better visualization"
    ]
@@ -705,6 +714,7 @@
     "                                                        data=st,\n",
     "                                                        label=\"Time\", \n",
     "                                                        unit=\"s\")\n",
+    "    # Appends a new RangeDimension that uses the DataArray itself as provider for the ticks\n",
     "    st_data_array.append_range_dimension_using_self()\n",
     "                                                        \n",
     "    "
@@ -731,6 +741,7 @@
    },
    "outputs": [],
    "source": [
+    "# Using list comprehension to find data arrays which were named in a standardized way\n",
     "st_arrays = [da for da in analysis_nixblock.data_arrays if \"nix.analysis.spiketrain\" in da.type]"
    ]
   },
@@ -755,6 +766,9 @@
    },
    "outputs": [],
    "source": [
+    "# Groups establish a simple way of grouping entities that in some way belong together\n",
+    "# Group exists inside a Block and can contain (link) DataArrays, Tags, and MultiTags\n",
+    "\n",
     "correlation_analysis_group = analysis_nixblock.create_group(name=\"SUA correlation analysis\", type_=\"nix.analysis.group\")\n",
     "[correlation_analysis_group.data_arrays.append(st) for st in st_arrays]\n",
     "correlation_analysis_group.data_arrays.append(cross_coerr_data_array)"
@@ -781,7 +795,8 @@
     }
    ],
    "source": [
-    "correlation_analysis_group.data_arrays"
+    "# Inspecting data arrays in the 'SUA correlation analysis' group\n",
+    "analysis_nixblock.groups['SUA correlation analysis'].data_arrays"
    ]
   },
   {
@@ -818,7 +833,9 @@
    },
    "outputs": [],
    "source": [
+    "# Getting the LFP signal stored for the selected trial\n",
     "ana_sig = trial.analogsignals[0]\n",
+    "# Calculating the power spectrum densities using elephant\n",
     "freq, psd = elephant.spectral.welch_psd(ana_sig)"
    ]
   },
@@ -843,6 +860,7 @@
    },
    "outputs": [],
    "source": [
+    "# Storing the PSDs as a data array\n",
     "welch_psd_data_array = analysis_nixblock.create_data_array(\n",
     "    \"welch_psd\", \"nix.sampled.multichannel\", \n",
     "    data=psd,\n",
@@ -882,11 +900,12 @@
     }
    ],
    "source": [
+    "# Ranged dimension for the frequencies\n",
     "welch_psd_data_array.append_range_dimension(freq, \n",
     "                                            label=\"Frequency\", \n",
     "                                            unit=str(freq.units))\n",
     "\n",
-    "\n",
+    "# Set dimension for the PSD estimates\n",
     "welch_psd_data_array.append_set_dimension()"
    ]
   },
@@ -922,6 +941,7 @@
    },
    "outputs": [],
    "source": [
+    "# Storing neo analog signal with LFP data as a data array\n",
     "ana_sig_data_array = analysis_nixblock.create_data_array(\n",
     "    \"analysed_lfp_signal\", \"nix.sampled.multichannel\", \n",
     "    data=ana_sig,\n",
@@ -968,6 +988,7 @@
     }
    ],
    "source": [
+    "# Appending the time dimension using a sampling interval, label, unit and an offset\n",
     "ana_sig_data_array.append_sampled_dimension(sampling_interval=float(ana_sig.sampling_period.magnitude),\n",
     "                                            label=\"Time\",\n",
     "                                            unit=str(ana_sig.times.units),\n",
@@ -1072,7 +1093,14 @@
     "\n",
     "Tagging in n-D             |  Example\n",
     ":-------------------------:|:-------------------------:\n",
-    "![](../images/3d_mtag.png)  |  ![](../images/multiple_rois.png)"
+    "![](../images/3d_mtag.png)  |  ![](../images/multiple_rois.png)\n",
+    "\n",
+    ">  \"Lenna\" by Original full portrait: \"Playmate of the Month\". Playboy\n",
+    ">  Magazine. November 1972, photographed by Dwight Hooker.This 512x512\n",
+    ">  electronic/mechanical scan of a section of the full portrait:\n",
+    ">  Alexander Sawchuk and two others[1] - The USC-SIPI image\n",
+    ">  database. Via Wikipedia -\n",
+    ">  http://en.wikipedia.org/wiki/File:Lenna.png#mediaviewer/File:Lenna.png"
    ]
   },
   {
@@ -1109,6 +1137,7 @@
     }
    ],
    "source": [
+    "# Extracting events for the selected trial\n",
     "trial.events[0].labels\n",
     "trial.events[0].times"
    ]
@@ -1134,7 +1163,9 @@
     }
    ],
    "source": [
+    "# Creating a data array to store event times\n",
     "events_data_array = analysis_nixblock.create_data_array(\"event times\", \"nix.events\", data=trial.events[0].times)\n",
+    "# Appending set dimension with labels as the event names\n",
     "events_data_array.append_set_dimension(labels=trial.events[0].labels)"
    ]
   },
@@ -1148,7 +1179,9 @@
    },
    "outputs": [],
    "source": [
-    "multi_tag = analysis_nixblock.create_multi_tag(\"analog signal events\", \"nix.events\", positions=events_data_array)\n",
+    "# Creating a multi tag to link the LFP signal with the events\n",
+    "multi_tag = analysis_nixblock.create_multi_tag(\"LFP signal\", \"nix.events\", positions=events_data_array)\n",
+    "# Referencing the LFP signal data array from the created multi tag\n",
     "multi_tag.references.append(ana_sig_data_array)"
    ]
   },
@@ -1173,6 +1206,7 @@
     }
    ],
    "source": [
+    "# Associating additional data (PSD estimates) with the LFP signal multi tag using feature\n",
     "multi_tag.create_feature(welch_psd_data_array, nixio.LinkType.Indexed)"
    ]
   },
@@ -1199,7 +1233,7 @@
     {
      "data": {
       "text/plain": [
-       "[MultiTag: {name = analog signal events, type = nix.events}]"
+       "[MultiTag: {name = LFP signal, type = nix.events}]"
       ]
      },
      "execution_count": 28,
@@ -1208,6 +1242,7 @@
     }
    ],
    "source": [
+    "# Retrieving available multi tags in the analysis block\n",
     "nixfile.blocks['analysis'].multi_tags"
    ]
   },
@@ -1232,7 +1267,8 @@
     }
    ],
    "source": [
-    "anasig_multi_tag = nixfile.blocks[\"analysis\"].multi_tags[\"analog signal events\"]\n",
+    "# Using the LFP signal to fetch the referenced data array\n",
+    "anasig_multi_tag = nixfile.blocks[\"analysis\"].multi_tags[\"LFP signal\"]\n",
     "\n",
     "anasig_multi_tag.references[0]"
    ]
@@ -1258,6 +1294,7 @@
     }
    ],
    "source": [
+    "# Retrieving tagged positions in the referenced data array\n",
     "anasig_multi_tag.positions"
    ]
   },
@@ -1271,8 +1308,8 @@
    },
    "outputs": [],
    "source": [
-    "# Note how we are able to create self describing figures with the \n",
-    "# information in the multtag and the referenced data arrays \n",
+    "# We are able to create self describing figures with ONLY the \n",
+    "# information in the multi tag, the referenced data arrays and associated feature\n",
     "\n",
     "plot_chans = 5\n",
     "\n",
@@ -1289,8 +1326,7 @@
     "frequencies = list(plot_psd_dim_x.ticks)\n",
     "\n",
     "events = anasig_multi_tag.positions\n",
-    "events_annotation = events.dimensions[0].labels\n",
-    "\n"
+    "events_annotation = events.dimensions[0].labels"
    ]
   },
   {
@@ -1439,7 +1475,7 @@
     }
    },
    "source": [
-    "### The odml data model in NIX \n",
+    "### The odML (open metadata Markup Language) data model in NIX \n",
     "![odML Logo](../images/odMLLogo-small.png) \n",
     "\n",
     "![odML metadata model](../images/nix_odML_model_simplified.png) \n"
@@ -1594,7 +1630,7 @@
     "# We want to add information about a subject that was used in the \n",
     "# experiment.\n",
     "sub_sec = sec.create_section(name=\"subject\", \n",
-    "                             type_=\"data.recording\")"
+    "                             type_=\"data.analysis.subject\")"
    ]
   },
   {
@@ -1638,7 +1674,7 @@
      "output_type": "stream",
      "text": [
       "recording.20230715 [data.analysis]\n",
-      "  subject [data.recording]\n",
+      "  subject [data.analysis.subject]\n",
       "      |- subjectID: ('78376446-f096-47b9-8bfe-ce1eb43a48dc',)\n",
       "      |- species: ('Mus Musculus',)\n",
       "      |- age: ('4',)weeks\n"
@@ -1689,7 +1725,7 @@
      "output_type": "stream",
      "text": [
       "recording.20230715 [data.analysis]\n",
-      "  subject [data.recording]\n",
+      "  subject [data.analysis.subject]\n",
       "      |- subjectID: ('78376446-f096-47b9-8bfe-ce1eb43a48dc',)\n",
       "      |- species: ('Mus Musculus',)\n",
       "      |- age: ('4',)weeks\n"
@@ -1747,6 +1783,8 @@
    },
    "outputs": [],
    "source": [
+    "# An opened file should be closed after you are done with it to finish \n",
+    "# any pending write and free any resources used by h5py and maintain data integrity\n",
     "nixfile.close()"
    ]
   },
@@ -1771,6 +1809,7 @@
    },
    "outputs": [],
    "source": [
+    "# Here we use a context manager to open and work with the file\n",
     "with neo.io.NixIO('analysis_results.nix', 'rw') as io:\n",
     "    io.write(trials)"
    ]
@@ -1787,7 +1826,7 @@
     {
      "data": {
       "text/plain": [
-       "[Block: {name = analysis, type = nix.Analyis}, Block: {name = neo.block.dd219909d34f46039d56e2ba56e67c69, type = neo.block}]"
+       "[Block: {name = analysis, type = nix.Analyis}, Block: {name = neo.block.419ca38fe6c34b0681d343f97ad85610, type = neo.block}]"
       ]
      },
      "execution_count": 44,
@@ -1796,6 +1835,7 @@
     }
    ],
    "source": [
+    "# Inspecting blocks we created in our nix file\n",
     "nixfile = nixio.File.open('analysis_results.nix', nixio.FileMode.ReadWrite)\n",
     "nixfile.blocks"
    ]
@@ -2254,13 +2294,14 @@
       "  DataArray: {name = event times, type = nix.events}\n",
       "    Shape: (4,) Unit:None\n",
       "    SetDimension: {index = 1}\n",
-      "  MultiTag: {name = analog signal events, type = nix.events}\n",
+      "  MultiTag: {name = LFP signal, type = nix.events}\n",
       "    Position Shape:(4,) Units: ()\n",
       "    Feature: {data = welch_psd, link_type = LinkType.Indexed }\n"
      ]
     }
    ],
    "source": [
+    "# Inspecting the analysis block we created\n",
     "nixfile.blocks['analysis'].pprint()"
    ]
   },
@@ -2274,6 +2315,8 @@
    },
    "outputs": [],
    "source": [
+    "# Using list comprehension to find the block written with neo NixIO and\n",
+    "# which has a block type as neo.block\n",
     "neo_block = [blk for blk in nixfile.blocks if \"neo.block\" == blk.type]"
    ]
   },
@@ -2290,8 +2333,8 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Block: {name = neo.block.dd219909d34f46039d56e2ba56e67c69, type = neo.block}\n",
-      "  Group: {name = neo.segment.7a5b6b8af9a346c7a0c8811d3089aff3, type = neo.segment}\n",
+      "Block: {name = neo.block.419ca38fe6c34b0681d343f97ad85610, type = neo.block}\n",
+      "  Group: {name = neo.segment.e0931657cae4486ea53b924a1d59f0aa, type = neo.segment}\n",
       "    *DataArray: {name = neo.analogsignal.18037944fdf2472d9c49cff8ea26e4ff.0, type = neo.analogsignal}\n",
       "      Shape: (2000,) Unit:uV\n",
       "      SampledDimension: {index = 1}\n",
@@ -2582,7 +2625,7 @@
       "      SampledDimension: {index = 1}\n",
       "    *MultiTag: {name = neo.event.a89cbc9d1ef24da3b4f7d457677f403f, type = neo.event}\n",
       "      Position Shape:(4,) Units: ()\n",
-      "    *MultiTag: {name = neo.epoch.546ebda4a6654bdea49a75a625b7b57c, type = neo.epoch}\n",
+      "    *MultiTag: {name = neo.epoch.b3623520b67945d4897ca11b7b6d8e88, type = neo.epoch}\n",
       "      Position Shape:(1,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.22a41c20c0614a238d32dea2d46673ca, type = neo.spiketrain}\n",
       "      Position Shape:(3,) Units: ()\n",
@@ -2727,13 +2770,7 @@
       "    *MultiTag: {name = neo.spiketrain.35f3e6c175de4950b563ccadaf0ffccd, type = neo.spiketrain}\n",
       "      Position Shape:(0,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.0ea0033ec21340aab6c274842189bdd6, type = neo.spiketrain}\n",
-      "      Position Shape:(1,) Units: ()\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
+      "      Position Shape:(1,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.aa43c17c239a4f40b2c32f423172dea1, type = neo.spiketrain}\n",
       "      Position Shape:(2,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.01efc24b2b624a8e947194c52f65d76a, type = neo.spiketrain}\n",
@@ -2815,7 +2852,13 @@
       "    *MultiTag: {name = neo.spiketrain.cd076e05273b496bb5d59ade0f93ca0c, type = neo.spiketrain}\n",
       "      Position Shape:(3,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.a63824101562431291326e51fde94a5b, type = neo.spiketrain}\n",
-      "      Position Shape:(179,) Units: ()\n",
+      "      Position Shape:(179,) Units: ()\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
       "    *MultiTag: {name = neo.spiketrain.f22a1df5ee064c5fa754dbc044676e3d, type = neo.spiketrain}\n",
       "      Position Shape:(0,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.75b8e381504143c688ffe3c2cd1c8104, type = neo.spiketrain}\n",
@@ -3132,7 +3175,7 @@
       "      Position Shape:(0,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.f659d3d7de144272b45cf20c90b76d94, type = neo.spiketrain}\n",
       "      Position Shape:(17,) Units: ()\n",
-      "  Group: {name = neo.segment.0c440ea0bfd7466db5afc26a2768b224, type = neo.segment}\n",
+      "  Group: {name = neo.segment.df0d1f96ea6c4a6888cd77bad07ca810, type = neo.segment}\n",
       "    *DataArray: {name = neo.analogsignal.18037944fdf2472d9c49cff8ea26e4ff.0, type = neo.analogsignal}\n",
       "      Shape: (2000,) Unit:uV\n",
       "      SampledDimension: {index = 1}\n",
@@ -3423,7 +3466,7 @@
       "      SampledDimension: {index = 1}\n",
       "    *MultiTag: {name = neo.event.a89cbc9d1ef24da3b4f7d457677f403f, type = neo.event}\n",
       "      Position Shape:(4,) Units: ()\n",
-      "    *MultiTag: {name = neo.epoch.2cb65767008845d9ad95c915980c445f, type = neo.epoch}\n",
+      "    *MultiTag: {name = neo.epoch.ee12d935fb2d4436990e453d00a755e5, type = neo.epoch}\n",
       "      Position Shape:(1,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.22a41c20c0614a238d32dea2d46673ca, type = neo.spiketrain}\n",
       "      Position Shape:(3,) Units: ()\n",
@@ -3967,7 +4010,7 @@
       "      Position Shape:(0,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.f659d3d7de144272b45cf20c90b76d94, type = neo.spiketrain}\n",
       "      Position Shape:(17,) Units: ()\n",
-      "  Group: {name = neo.segment.08aad15a9a0241998c2b06aba0d52999, type = neo.segment}\n",
+      "  Group: {name = neo.segment.2a5983aa4f5649aa8dcf2796f1557ad8, type = neo.segment}\n",
       "    *DataArray: {name = neo.analogsignal.18037944fdf2472d9c49cff8ea26e4ff.0, type = neo.analogsignal}\n",
       "      Shape: (2000,) Unit:uV\n",
       "      SampledDimension: {index = 1}\n",
@@ -4258,7 +4301,7 @@
       "      SampledDimension: {index = 1}\n",
       "    *MultiTag: {name = neo.event.a89cbc9d1ef24da3b4f7d457677f403f, type = neo.event}\n",
       "      Position Shape:(4,) Units: ()\n",
-      "    *MultiTag: {name = neo.epoch.78707d777f2d448684fb31e1331379d0, type = neo.epoch}\n",
+      "    *MultiTag: {name = neo.epoch.cacfb62fd6144ed290af9946a6763149, type = neo.epoch}\n",
       "      Position Shape:(1,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.22a41c20c0614a238d32dea2d46673ca, type = neo.spiketrain}\n",
       "      Position Shape:(3,) Units: ()\n",
@@ -4802,7 +4845,7 @@
       "      Position Shape:(0,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.f659d3d7de144272b45cf20c90b76d94, type = neo.spiketrain}\n",
       "      Position Shape:(17,) Units: ()\n",
-      "  Group: {name = neo.segment.d577554006304c5f8f0c82c2e685e858, type = neo.segment}\n",
+      "  Group: {name = neo.segment.816be4fe5bc94534918f007a30929d69, type = neo.segment}\n",
       "    *DataArray: {name = neo.analogsignal.18037944fdf2472d9c49cff8ea26e4ff.0, type = neo.analogsignal}\n",
       "      Shape: (2000,) Unit:uV\n",
       "      SampledDimension: {index = 1}\n",
@@ -5093,7 +5136,7 @@
       "      SampledDimension: {index = 1}\n",
       "    *MultiTag: {name = neo.event.a89cbc9d1ef24da3b4f7d457677f403f, type = neo.event}\n",
       "      Position Shape:(4,) Units: ()\n",
-      "    *MultiTag: {name = neo.epoch.e13f9e8ed7f9435fb2563ffb95fb5b14, type = neo.epoch}\n",
+      "    *MultiTag: {name = neo.epoch.f0c92560ae2b445b8d3f2560cb3a567e, type = neo.epoch}\n",
       "      Position Shape:(1,) Units: ()\n",
       "    *MultiTag: {name = neo.spiketrain.22a41c20c0614a238d32dea2d46673ca, type = neo.spiketrain}\n",
       "      Position Shape:(3,) Units: ()\n",
@@ -5928,10 +5971,10 @@
       "  DataArray: {name = neo.event.a89cbc9d1ef24da3b4f7d457677f403f.times, type = neo.event.times}\n",
       "    Shape: (4,) Unit:s\n",
       "    SetDimension: {index = 1}\n",
-      "  DataArray: {name = neo.epoch.546ebda4a6654bdea49a75a625b7b57c.times, type = neo.epoch.times}\n",
+      "  DataArray: {name = neo.epoch.b3623520b67945d4897ca11b7b6d8e88.times, type = neo.epoch.times}\n",
       "    Shape: (1,) Unit:s\n",
       "    SetDimension: {index = 1}\n",
-      "  DataArray: {name = neo.epoch.546ebda4a6654bdea49a75a625b7b57c.durations, type = neo.epoch.durations}\n",
+      "  DataArray: {name = neo.epoch.b3623520b67945d4897ca11b7b6d8e88.durations, type = neo.epoch.durations}\n",
       "    Shape: (1,) Unit:s\n",
       "  DataArray: {name = neo.spiketrain.22a41c20c0614a238d32dea2d46673ca.times, type = neo.spiketrain.times}\n",
       "    Shape: (3,) Unit:s\n",
@@ -6475,24 +6518,24 @@
       "    Shape: (0,) Unit:s\n",
       "  DataArray: {name = neo.spiketrain.f659d3d7de144272b45cf20c90b76d94.times, type = neo.spiketrain.times}\n",
       "    Shape: (17,) Unit:s\n",
-      "  DataArray: {name = neo.epoch.2cb65767008845d9ad95c915980c445f.times, type = neo.epoch.times}\n",
+      "  DataArray: {name = neo.epoch.ee12d935fb2d4436990e453d00a755e5.times, type = neo.epoch.times}\n",
       "    Shape: (1,) Unit:s\n",
       "    SetDimension: {index = 1}\n",
-      "  DataArray: {name = neo.epoch.2cb65767008845d9ad95c915980c445f.durations, type = neo.epoch.durations}\n",
+      "  DataArray: {name = neo.epoch.ee12d935fb2d4436990e453d00a755e5.durations, type = neo.epoch.durations}\n",
       "    Shape: (1,) Unit:s\n",
-      "  DataArray: {name = neo.epoch.78707d777f2d448684fb31e1331379d0.times, type = neo.epoch.times}\n",
+      "  DataArray: {name = neo.epoch.cacfb62fd6144ed290af9946a6763149.times, type = neo.epoch.times}\n",
       "    Shape: (1,) Unit:s\n",
       "    SetDimension: {index = 1}\n",
-      "  DataArray: {name = neo.epoch.78707d777f2d448684fb31e1331379d0.durations, type = neo.epoch.durations}\n",
+      "  DataArray: {name = neo.epoch.cacfb62fd6144ed290af9946a6763149.durations, type = neo.epoch.durations}\n",
       "    Shape: (1,) Unit:s\n",
-      "  DataArray: {name = neo.epoch.e13f9e8ed7f9435fb2563ffb95fb5b14.times, type = neo.epoch.times}\n",
+      "  DataArray: {name = neo.epoch.f0c92560ae2b445b8d3f2560cb3a567e.times, type = neo.epoch.times}\n",
       "    Shape: (1,) Unit:s\n",
       "    SetDimension: {index = 1}\n",
-      "  DataArray: {name = neo.epoch.e13f9e8ed7f9435fb2563ffb95fb5b14.durations, type = neo.epoch.durations}\n",
+      "  DataArray: {name = neo.epoch.f0c92560ae2b445b8d3f2560cb3a567e.durations, type = neo.epoch.durations}\n",
       "    Shape: (1,) Unit:s\n",
       "  MultiTag: {name = neo.event.a89cbc9d1ef24da3b4f7d457677f403f, type = neo.event}\n",
       "    Position Shape:(4,) Units: ()\n",
-      "  MultiTag: {name = neo.epoch.546ebda4a6654bdea49a75a625b7b57c, type = neo.epoch}\n",
+      "  MultiTag: {name = neo.epoch.b3623520b67945d4897ca11b7b6d8e88, type = neo.epoch}\n",
       "    Position Shape:(1,) Units: ()\n",
       "  MultiTag: {name = neo.spiketrain.22a41c20c0614a238d32dea2d46673ca, type = neo.spiketrain}\n",
       "    Position Shape:(3,) Units: ()\n",
@@ -7036,16 +7079,17 @@
       "    Position Shape:(0,) Units: ()\n",
       "  MultiTag: {name = neo.spiketrain.f659d3d7de144272b45cf20c90b76d94, type = neo.spiketrain}\n",
       "    Position Shape:(17,) Units: ()\n",
-      "  MultiTag: {name = neo.epoch.2cb65767008845d9ad95c915980c445f, type = neo.epoch}\n",
+      "  MultiTag: {name = neo.epoch.ee12d935fb2d4436990e453d00a755e5, type = neo.epoch}\n",
       "    Position Shape:(1,) Units: ()\n",
-      "  MultiTag: {name = neo.epoch.78707d777f2d448684fb31e1331379d0, type = neo.epoch}\n",
+      "  MultiTag: {name = neo.epoch.cacfb62fd6144ed290af9946a6763149, type = neo.epoch}\n",
       "    Position Shape:(1,) Units: ()\n",
-      "  MultiTag: {name = neo.epoch.e13f9e8ed7f9435fb2563ffb95fb5b14, type = neo.epoch}\n",
+      "  MultiTag: {name = neo.epoch.f0c92560ae2b445b8d3f2560cb3a567e, type = neo.epoch}\n",
       "    Position Shape:(1,) Units: ()\n"
      ]
     }
    ],
    "source": [
+    "# We can see here how neo uses nix entities under the hood to represent data\n",
     "neo_block[0].pprint()"
    ]
   },
@@ -7061,6 +7105,26 @@
    "source": [
     "nixfile.close()"
    ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Resources\n",
+    "\n",
+    "|   Resource    |   NIX     |   odML  |\n",
+    "|---------------|-----------|---------|\n",
+    "| Homepage      | https://g-node.github.io/nix/ | https://g-node.github.io/python-odml/|\n",
+    "| GitHub        | https://github.com/G-Node/nix | https://github.com/G-Node/python-odml|\n",
+    "| Tutorial     | https://nixpy.readthedocs.io/en/latest/getting_started.html |  https://python-odml.readthedocs.io/en/latest/tutorial.html |\n",
+    "| PyPI          | https://pypi.org/project/nixio/ | https://pypi.org/project/odML/ |\n",
+    "\n",
+    "#### Related projects:\n",
+    "\n",
+    "- [odML Tables](https://odmltables.readthedocs.io/en/version1.0/) - odML-tables is a tool to convert hierarchical representations of metadata stored in the odML format to flat, tabluar formats\n",
+    "- [odml-ui](https://github.com/G-Node/odml-ui) - The odML-Editor is a standalone GUI application used for working with the odML Documents\n",
+    "- [NixView](https://github.com/bendalab/nixview) - A Qt based viewer for nix datafiles"
+   ]
   }
  ],
  "metadata": {