|
@@ -0,0 +1,124 @@
|
|
|
|
+{
|
|
|
|
+ "cells": [
|
|
|
|
+ {
|
|
|
|
+ "cell_type": "markdown",
|
|
|
|
+ "metadata": {},
|
|
|
|
+ "source": [
|
|
|
|
+ "# Add Continuous Borders Around Labelled Regions"
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "cell_type": "code",
|
|
|
|
+ "execution_count": 1,
|
|
|
|
+ "metadata": {},
|
|
|
|
+ "outputs": [],
|
|
|
|
+ "source": [
|
|
|
|
+ "from freesurfer_surface import Surface\n",
|
|
|
|
+ "\n",
|
|
|
|
+ "SUBJECTS_DIR = '../tests/subjects'\n",
|
|
|
|
+ "surface = Surface.read_triangular(SUBJECTS_DIR + '/fabian/surf/lh.pial')\n",
|
|
|
|
+ "surface.load_annotation_file(SUBJECTS_DIR + '/fabian/label/lh.aparc.annot')"
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "cell_type": "code",
|
|
|
|
+ "execution_count": 2,
|
|
|
|
+ "metadata": {
|
|
|
|
+ "scrolled": true
|
|
|
|
+ },
|
|
|
|
+ "outputs": [],
|
|
|
|
+ "source": [
|
|
|
|
+ "import numpy\n",
|
|
|
|
+ "from freesurfer_surface import Label, Vertex\n",
|
|
|
|
+ "\n",
|
|
|
|
+ "def unit_vector(vector: numpy.array) -> numpy.array:\n",
|
|
|
|
+ " return vector / numpy.linalg.norm(vector)\n",
|
|
|
|
+ "\n",
|
|
|
|
+ "def add_border_around_labelled_surface(label: Label, border_length_add_mm: float,\n",
|
|
|
|
+ " border_height_mm: float, border_width_mm: float):\n",
|
|
|
|
+ " border_chain, = surface.find_label_border_polygonal_chains(label)\n",
|
|
|
|
+ " print('#{}/{}: {} border segments'.format(label.index, \n",
|
|
|
|
+ " label.name,\n",
|
|
|
|
+ " len(border_chain.vertex_indices)))\n",
|
|
|
|
+ " for vertex_triplet_indices in border_chain.adjacent_vertex_indices(3):\n",
|
|
|
|
+ " vertex_triplet_coords = tuple(numpy.array(surface.vertices[idx])\n",
|
|
|
|
+ " for idx in vertex_triplet_indices)\n",
|
|
|
|
+ " backward_vector = vertex_triplet_coords[0] - vertex_triplet_coords[1]\n",
|
|
|
|
+ " forward_vector = vertex_triplet_coords[2] - vertex_triplet_coords[1]\n",
|
|
|
|
+ " forward_vector = unit_vector(forward_vector) \\\n",
|
|
|
|
+ " * (numpy.linalg.norm(forward_vector) + border_length_add_mm)\n",
|
|
|
|
+ " upward_vector = unit_vector(numpy.cross(backward_vector, forward_vector)) * border_height_mm / 2\n",
|
|
|
|
+ " sideward_vector = unit_vector(numpy.cross(upward_vector, forward_vector)) * border_width_mm / 2\n",
|
|
|
|
+ " base_corners = [vertex_triplet_coords[1] + v\n",
|
|
|
|
+ " for v in [-upward_vector -sideward_vector,\n",
|
|
|
|
+ " -upward_vector +sideward_vector,\n",
|
|
|
|
+ " +upward_vector +sideward_vector,\n",
|
|
|
|
+ " +upward_vector -sideward_vector]]\n",
|
|
|
|
+ " top_corners = [v + forward_vector for v in base_corners]\n",
|
|
|
|
+ " base_indices = [surface.add_vertex(Vertex(*coords)) for coords in base_corners]\n",
|
|
|
|
+ " top_indices = [surface.add_vertex(Vertex(*coords)) for coords in top_corners]\n",
|
|
|
|
+ " for surface_indices in [base_indices, top_indices]:\n",
|
|
|
|
+ " surface.add_rectangle(surface_indices)\n",
|
|
|
|
+ " for i in range(4):\n",
|
|
|
|
+ " j = (i + 1) % 4\n",
|
|
|
|
+ " surface.add_rectangle((base_indices[i], base_indices[j],\n",
|
|
|
|
+ " top_indices[j], top_indices[i]))"
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "cell_type": "code",
|
|
|
|
+ "execution_count": 3,
|
|
|
|
+ "metadata": {},
|
|
|
|
+ "outputs": [
|
|
|
|
+ {
|
|
|
|
+ "name": "stdout",
|
|
|
|
+ "output_type": "stream",
|
|
|
|
+ "text": [
|
|
|
|
+ "#17/paracentral: 167 border segments\n",
|
|
|
|
+ "#22/postcentral: 396 border segments\n",
|
|
|
|
+ "#24/precentral: 418 border segments\n"
|
|
|
|
+ ]
|
|
|
|
+ }
|
|
|
|
+ ],
|
|
|
|
+ "source": [
|
|
|
|
+ "for label in filter(lambda l: 'central' in l.name, surface.annotation.labels.values()):\n",
|
|
|
|
+ " add_border_around_labelled_surface(label,\n",
|
|
|
|
+ " border_length_add_mm=0.2,\n",
|
|
|
|
+ " border_height_mm=1.5,\n",
|
|
|
|
+ " border_width_mm=1.0)\n",
|
|
|
|
+ " \n",
|
|
|
|
+ "surface.write_triangular('border.lh.pial')"
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "cell_type": "markdown",
|
|
|
|
+ "metadata": {},
|
|
|
|
+ "source": [
|
|
|
|
+ "```sh\n",
|
|
|
|
+ "freeview --surface examples/precentral-border.lh.pial:annot=tests/subjects/fabian/label/lh.aparc.annot\n",
|
|
|
|
+ "```"
|
|
|
|
+ ]
|
|
|
|
+ }
|
|
|
|
+ ],
|
|
|
|
+ "metadata": {
|
|
|
|
+ "kernelspec": {
|
|
|
|
+ "display_name": "Python 3",
|
|
|
|
+ "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.6.7"
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ "nbformat": 4,
|
|
|
|
+ "nbformat_minor": 2
|
|
|
|
+}
|