Skip to content

Commit

Permalink
Merge pull request #310 from neurodata/develop
Browse files Browse the repository at this point in the history
update for 0.3.0 release
  • Loading branch information
tathey1 committed Jun 29, 2021
2 parents cd6b962 + 48c42a6 commit 93ed519
Show file tree
Hide file tree
Showing 17 changed files with 1,049 additions and 114 deletions.
1 change: 0 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ jobs:
python3 -m venv venv
. venv/bin/activate
pip install pytest pytest-cov codecov black
pip install -r requirements.txt
pip install -e .
- run:
name: run tests
Expand Down
2 changes: 2 additions & 0 deletions brainlit/algorithms/trace_analysis/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from brainlit.algorithms.trace_analysis.fit_spline import *
from brainlit.algorithms.trace_analysis.spline_fxns import *
317 changes: 317 additions & 0 deletions docs/notebooks/algorithms/biccn_demo.ipynb

Large diffs are not rendered by default.

327 changes: 306 additions & 21 deletions docs/notebooks/algorithms/spline_fxns_tutorial.ipynb

Large diffs are not rendered by default.

67 changes: 56 additions & 11 deletions docs/notebooks/algorithms/view_swc_spline.ipynb

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions docs/reference/algs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ Connect Fragments
.. autoapiclass:: viterbi_algorithm
:members:

.. currentmodule:: brainlit.algorithms.trace_analysis

Trace Analysis
--------------

.. autoapifunction:: speed
.. autoapifunction:: curvature
.. autoapifunction:: torsion
.. autoapiclass:: GeometricGraph
:members:

.. currentmodule:: brainlit.algorithms.detect_somas

Soma Detection
Expand Down
11 changes: 11 additions & 0 deletions docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ Demonstrate fragment path connections using Viterbi algorithm on a simple grid e

notebooks/algorithms/viterbi_tutorial.ipynb

Trace Analysis
--------------
Demonstrate estimation of curvature and torsion on simple curve, and fitting splines to a neuron.

.. toctree::
:maxdepth: 1

notebooks/algorithms/spline_fxns_tutorial.ipynb
notebooks/algorithms/view_swc_spline.ipynb
notebooks/algorithms/biccn_demo.ipynb

Soma Detection
--------------
Demonstrate simple soma detection algorithm on known somas in Janelia dataset, brain1.
Expand Down
2 changes: 1 addition & 1 deletion experiments/axon_geometry/notebooks/autocorrelation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"for brain in brains:\n",
" data_dir = os.path.join(experiment_dir, \"data\", brain)\n",
" segments_swc_dir = os.path.join(data_dir, \"segments_swc\")\n",
" trace_data_dir = os.path.join(data_dir, \"trace_data\", \"1\")\n",
" trace_data_dir = os.path.join(data_dir, \"trace_data\", \"1\", \"no_dropout\")\n",
" print(f\"Directory where swcs reside: {segments_swc_dir}\")\n",
" \n",
" for i in tqdm(np.arange(0, max_id)):\n",
Expand Down
34 changes: 19 additions & 15 deletions experiments/axon_geometry/notebooks/class_length_segment.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,13 @@
"outputs": [],
"source": [
"#specify brain1 or brain2 below\n",
"brain = \"brain2\"\n",
"brain = \"brain1\"\n",
"\n",
"root_dir = Path(os.path.abspath('')).parents[1]\n",
"experiment_dir = os.path.join(root_dir, \"axon_geometry\")\n",
"data_dir = os.path.join(experiment_dir, \"data\", brain)\n",
"segments_swc_dir = os.path.join(data_dir, \"segments_swc\")\n",
"trace_data_dir = os.path.join(data_dir, \"trace_data\")\n",
"trace_data_dir = os.path.join(trace_data_dir, \"1\")\n",
"trace_data_dir = os.path.join(data_dir, \"trace_data\", \"1\", \"no_dropout\")\n",
"print(f\"Directory where swcs reside: {segments_swc_dir}\")"
]
},
Expand Down Expand Up @@ -107,7 +106,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Density of `log` segment lengths as a function of spline class"
"# Density of curvature/torsion as a function of spline depth in the spline tree"
]
},
{
Expand All @@ -120,21 +119,24 @@
"sns.set_context(\"paper\")\n",
"sns.set(font_scale=1.2)\n",
"\n",
"g = sns.FacetGrid(df, col=\"measure\", hue=\"class\", height=4)\n",
"g.map(sns.kdeplot, \"log_seg_length\", bw_adjust=1.8)\n",
"g.set_axis_labels(r\"$\\log$ segment length\", \"density\")\n",
"g.add_legend(title=\"Segment class\")\n",
"legend_labels = [\"primary\", \"collateral\", \"terminal\"]\n",
"for t, l in zip(g._legend.texts, legend_labels): t.set_text(l)\n",
"g = sns.FacetGrid(df, col=\"measure\", hue=\"height\", height=4)\n",
"g.map(sns.kdeplot, \"value\")\n",
"\n",
"g.set_axis_labels(r\"value ($\\mu m^{-1}$)\", \"density\")\n",
"\n",
"g.add_legend(title=\"Segment depth\")\n",
" \n",
"g.set(xlim=[0, .2], xticks=[0, .1, .2])\n",
"\n",
"plt.subplots_adjust(top=0.85)\n",
"g.fig.suptitle(\"Brain 1\" if brain==\"brain1\" else \"Brain 2\")\n",
"\n",
"axes = g.axes.flatten()\n",
"axes[0].set_title(\"curvature\")\n",
"axes[1].set_title(\"torsion\")\n",
"g.savefig(os.path.join(experiment_dir, \"figures\", f\"{brain}_seg_length_class_density.eps\"))\n",
"g.savefig(os.path.join(experiment_dir, \"figures\", f\"{brain}_seg_length_class_density.jpg\"))"
"\n",
"g.savefig(os.path.join(experiment_dir, \"figures\", f\"{brain}_mean_value_depth_density.eps\"))\n",
"g.savefig(os.path.join(experiment_dir, \"figures\", f\"{brain}_mean_value_depth_density.jpg\"))"
]
},
{
Expand All @@ -159,7 +161,6 @@
"legend_labels = [\"primary\", \"collateral\", \"terminal\"]\n",
"for t, l in zip(g._legend.texts, legend_labels): t.set_text(l)\n",
" \n",
"#g.set(xlim=[-3, 0], xticks=[-3, -2, -1, 0], yticks=[0, 1, 2, 3])\n",
"g.set(xlim=[0, .2], xticks=[0, .1, .2])\n",
"\n",
"plt.subplots_adjust(top=0.85)\n",
Expand Down Expand Up @@ -239,7 +240,7 @@
],
"metadata": {
"kernelspec": {
"name": "env",
"name": "python3",
"display_name": "Python 3.8.6 ('env': venv)"
},
"language_info": {
Expand All @@ -252,7 +253,10 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
"version": "3.8.10"
},
"interpreter": {
"hash": "c48f87b51193a18c36f6ec1b39da40df380a4c3fb2fa54b3e413dc2378ec9052"
}
},
"nbformat": 4,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@
"#specify brain1 or brain2 below\n",
"brain = \"brain1\"\n",
"\n",
"dropout_version = \"no_dropout\"\n",
"\n",
"root_dir = Path(os.path.abspath('')).parents[1]\n",
"experiment_dir = os.path.join(root_dir, \"axon_geometry\")\n",
"data_dir = os.path.join(experiment_dir, \"data\", brain)\n",
"segments_swc_dir = os.path.join(data_dir, \"segments_swc\")\n",
"trace_data_dir = os.path.join(data_dir, \"trace_data\")\n",
"trace_data_dir = os.path.join(trace_data_dir, \"1\")\n",
"trace_data_dir = os.path.join(data_dir, \"trace_data\", \"1\", \"no_dropout\")\n",
"print(f\"Directory where swcs reside: {segments_swc_dir}\")"
]
},
Expand Down Expand Up @@ -109,7 +110,7 @@
"# Sign Test\n",
"Assume samples from different neurons are independent\n",
"\n",
"Bonferroni correction across 3 class comparisons and 2 parameters, and directionality of effect (3*2*2=12)\n",
"Bonferroni correction across 3 class comparisons and 2 parameters, and directionality of effect (3x2x2=12)\n",
"\n",
"Null Hypothesis: P(X>Y)=0.5"
]
Expand Down Expand Up @@ -177,7 +178,7 @@
],
"metadata": {
"kernelspec": {
"name": "env",
"name": "python3",
"display_name": "Python 3.8.6 ('env': venv)"
},
"language_info": {
Expand All @@ -190,7 +191,10 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
"version": "3.8.10"
},
"interpreter": {
"hash": "c48f87b51193a18c36f6ec1b39da40df380a4c3fb2fa54b3e413dc2378ec9052"
}
},
"nbformat": 4,
Expand Down
3 changes: 1 addition & 2 deletions experiments/axon_geometry/notebooks/examine_neurons.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@
"experiment_dir = os.path.join(root_dir, \"axon_geometry\")\n",
"data_dir = os.path.join(experiment_dir, \"data\", brain)\n",
"segments_swc_dir = os.path.join(data_dir, \"segments_swc\")\n",
"trace_data_dir = os.path.join(data_dir, \"trace_data\")\n",
"trace_data_dir = os.path.join(trace_data_dir, \"1\")\n",
"trace_data_dir = os.path.join(data_dir, \"trace_data\", \"1\", \"no_dropout\")\n",
"print(f\"Directory where swcs reside: {segments_swc_dir}\")"
]
},
Expand Down
92 changes: 79 additions & 13 deletions experiments/axon_geometry/notebooks/example_neuron.ipynb

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"for brain in brains:\n",
" data_dir = os.path.join(experiment_dir, \"data\", brain)\n",
" segments_swc_dir = os.path.join(data_dir, \"segments_swc\")\n",
" trace_data_dir = os.path.join(data_dir, \"trace_data\", \"1\")\n",
" trace_data_dir = os.path.join(data_dir, \"trace_data\", \"1\", \"no_dropout\")\n",
" print(f\"Directory where swcs reside: {segments_swc_dir}\")\n",
" \n",
" for i in tqdm(np.arange(0, max_id)):\n",
Expand Down
187 changes: 187 additions & 0 deletions experiments/axon_geometry/notebooks/resample_trace.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
{
"metadata": {
"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.8.10"
},
"orig_nbformat": 4,
"kernelspec": {
"name": "python3",
"display_name": "Python 3.8.6 ('env': venv)"
},
"interpreter": {
"hash": "c48f87b51193a18c36f6ec1b39da40df380a4c3fb2fa54b3e413dc2378ec9052"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"source": [
"In order to run this notebook, you must have generated data with random dropout of trace vertices. This can be done by uncommenting the bottom of `generate_trace_data.ipynb`"
],
"cell_type": "markdown",
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"import os\n",
"import pandas as pd\n",
"import seaborn as sns\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import scipy\n",
"from tqdm import tqdm"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"max_id = 300\n",
"\n",
"def classify_height(row):\n",
" height = row[\"height\"]\n",
" if height <= 2:\n",
" return height\n",
" else:\n",
" return 3\n",
"\n",
"def numerical_class(row):\n",
" _class = row[\"class\"]\n",
" if _class == \"primary\":\n",
" return 0\n",
" if _class == \"collateral\":\n",
" return 1\n",
" if _class == \"terminal\":\n",
" return 2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#specify brain1 or brain2 below\n",
"brain = \"brain1\"\n",
"\n",
"root_dir = Path(os.path.abspath('')).parents[1]\n",
"experiment_dir = os.path.join(root_dir, \"axon_geometry\")\n",
"data_dir = os.path.join(experiment_dir, \"data\", brain)\n",
"segments_swc_dir = os.path.join(data_dir, \"segments_swc\")\n",
"print(f\"Directory where swcs reside: {segments_swc_dir}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"for i in range(20):\n",
" print(f\"****************Iter: {i}********************\")\n",
" dropout_version = \"10pct_iter\" + str(i)\n",
" trace_data_dir = os.path.join(data_dir, \"trace_data\")\n",
" trace_data_dir = os.path.join(trace_data_dir, \"1\")\n",
" trace_data_dir = os.path.join(trace_data_dir, dropout_version)\n",
" df_path = os.path.join(trace_data_dir, \"df.csv\")\n",
" if os.path.exists(df_path):\n",
" df = pd.read_csv(df_path)\n",
" else:\n",
" df = pd.DataFrame(columns=[\"seg_id\", \"class\", \"height\", \"log_seg_length\", \"measure\", \"value\", \"log_value\"])\n",
" for i in tqdm(np.arange(0, max_id)):\n",
" i = int(i)\n",
" trace_data_path = os.path.join(trace_data_dir, \"{}.npy\".format(i))\n",
" if os.path.exists(trace_data_path) is True:\n",
" trace_data = np.load(trace_data_path, allow_pickle=True)\n",
"\n",
" for node in trace_data:\n",
" seg_length = node[\"seg_length\"]\n",
" height = node[\"height\"]\n",
" _class = node[\"class\"]\n",
" mean_curvature = node[\"mean_curvature\"]\n",
" mean_torsion = node[\"mean_torsion\"]\n",
" \n",
" log_seg_length = np.log10(seg_length)\n",
"\n",
" log_mean_curvature = np.log10(mean_curvature)\n",
" df = df.append({\"seg_id\": i, \"height\": height, \"class\": _class, \"log_seg_length\": log_seg_length, \"measure\": \"curvature\", \"value\": mean_curvature, \"log_value\": log_mean_curvature}, ignore_index=True)\n",
"\n",
" log_mean_torsion = np.log10(mean_torsion)\n",
" df = df.append({\"seg_id\": i, \"height\": height, \"class\": _class, \"log_seg_length\": log_seg_length, \"measure\": \"torsion\", \"value\": mean_torsion, \"log_value\": log_mean_torsion}, ignore_index=True)\n",
" df.to_csv(df_path)\n",
" df[\"class\"] = df.apply(numerical_class, axis=1)\n",
" df[\"height_class\"] = df.apply(classify_height, axis=1)\n",
"\n",
"\n",
" measures = [\"curvature\", \"torsion\"]\n",
"\n",
" classes = {0: \"primary\", 1: \"collateral\", 2: \"terminal\"}\n",
" n = len(classes)\n",
" matrix_pairs = np.triu(np.ones((n, n)), k=1)\n",
" (coord_pairs_x, coord_pairs_y) = np.where(matrix_pairs == 1)\n",
"\n",
" for measure in measures:\n",
" for class_1, class_2 in zip(coord_pairs_x, coord_pairs_y):\n",
" Y1 = []\n",
" Y2 = []\n",
" segment_numbers = []\n",
" X_class = []\n",
" neuron_id = 0\n",
" #collect data from all neurons\n",
" for i in np.arange(0, max_id):\n",
" sample_query = df.loc[(df['seg_id'] == i) & ((df['class'] == class_1)) & (df['measure'] == measure)]\n",
" num_segments = len(sample_query.index)\n",
" if num_segments > 0:\n",
" Y1.append(np.mean(sample_query[\"value\"].to_numpy()))\n",
" sample_query = df.loc[(df['seg_id'] == i) & ((df['class'] == class_2)) & (df['measure'] == measure)]\n",
" Y2.append(np.mean(sample_query[\"value\"].to_numpy()))\n",
"\n",
" # Sign Test\n",
" dif = np.subtract(Y1, Y2)\n",
" k = np.sum(dif > 0)\n",
" n = dif.shape[0]\n",
" upper_bool = k > n // 2\n",
" if upper_bool:\n",
" p = np.sum(scipy.stats.binom.pmf(range(k,n+1), n=n, p=0.5))\n",
" else:\n",
" p = np.sum(scipy.stats.binom.pmf(range(0,k+1), n=n, p=0.5))\n",
"\n",
" if p < 0.05/12:\n",
" if upper_bool:\n",
" symb = \">\"\n",
" else:\n",
" symb = \"<\"\n",
" print(f\"{classes[class_1]} {symb} {classes[class_2]} in {measure}\")\n",
" print(f\"p-val was: {p}\")\n",
" else:\n",
" print(f\"No difference between {classes[class_1]} and {classes[class_2]} in {measure}\")\n",
" print(f\"p-val was: {p}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
]
}

0 comments on commit 93ed519

Please sign in to comment.