{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Add Cubes Around Surface of Precentral Gyrus" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Label(name=precentral, index=24, color=#3c14dc)" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "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')\n", "\n", "precentral_label, = filter(lambda l: l.name == 'precentral', surface.annotation.labels.values())\n", "precentral_label" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "PolygonalChain(vertex_indices=(62118, 63255, 63264, 64542, 64562, 65878, 65895, 65925, 65957, 65958, 67222, 67255, 68439, 68458, 69743, 69744, 71109, 72350, 73534, 74843, 76105, 76087, 77297, 77310, 78461, 78462, 79548, 79560, 80703, 81917, 83081, 83082, 84257, 85504, 85505, 86741, 88079, 89444, 90726, 90727, 91981, 91982, 93119, 93120, 93121, 93122, 94229, 94230, 94237, 94238, 94239, 94240, 94241, 94251, 94252, 94265, 95347, 95348, 95337, 96419, 97510, 98721, 98741, 99968, 99979, 99993, 98779, 98778, 98793, 98792, 98807, 98821, 98836, 98854, 97631, 97630, 97609, 97608, 97588, 97587, 97586, 97568, 97585, 96505, 96504, 95443, 95442, 94373, 95456, 95455, 95441, 95425, 95424, 95439, 94343, 94328, 94327, 94326, 94305, 94290, 94280, 93167, 93156, 94270, 94261, 95343, 95334, 96405, 97497, 97496, 97488, 98658, 98641, 99907, 101136, 102349, 102367, 103514, 103537, 103538, 103539, 103540, 104676, 104698, 104699, 105798, 105799, 105818, 106903, 106924, 107998, 107999, 108000, 109016, 109032, 110099, 110116, 110117, 110139, 111256, 111257, 111281, 111282, 111283, 111284, 111285, 112562, 113902, 112541, 111263, 111262, 110146, 110145, 110124, 109058, 109039, 108029, 108007, 106931, 106930, 107985, 106913, 105825, 105826, 105810, 105786, 104687, 104661, 103525, 103504, 102357, 102356, 102340, 102339, 102330, 101115, 101114, 101104, 101103, 101096, 101095, 101087, 102303, 102302, 102301, 102291, 103445, 103444, 103443, 103430, 103429, 103428, 103427, 103426, 102268, 102267, 102245, 101045, 101023, 99812, 99798, 98568, 97416, 96296, 96297, 95223, 94129, 93039, 93053, 91880, 90631, 89341, 87980, 87964, 87942, 87921, 87903, 87885, 89265, 89243, 89220, 90550, 90532, 90513, 91779, 91765, 91750, 91751, 91728, 91729, 91715, 92897, 92898, 91703, 90405, 90404, 89146, 87756, 87755, 86506, 86516, 86533, 86554, 85333, 84049, 84058, 84057, 82885, 82897, 81685, 81684, 80488, 80503, 79351, 79350, 79369, 79368, 78316, 79400, 79399, 79398, 79428, 79427, 79426, 79448, 79447, 78351, 78350, 79445, 80594, 80574, 80546, 80545, 80520, 79367, 78288, 78276, 77094, 75876, 74640, 74639, 73344, 72119, 70772, 69437, 68225, 68224, 67020, 67019, 67018, 67017, 67016, 67006, 67005, 66996, 66986, 66977, 66976, 66968, 65585, 65576, 64210, 64203, 64202, 64195, 64187, 64175, 64163, 62960, 62959, 62950, 62949, 62941, 62931, 62930, 61818, 60749, 60750, 60747, 59710, 58616, 58620, 57502, 56329, 55100, 53824, 52441, 51013, 51012, 49598, 48178, 46811, 46815, 45343, 45344, 45355, 43785, 43786, 43800, 42258, 40741, 39193, 39213, 37761, 36281, 34870, 33454, 33450, 32065, 32072, 32073, 32080, 33464, 33471, 33472, 33479, 33486, 34919, 34920, 33497, 34932, 34946, 36359, 37820, 37832, 39293, 39306, 40864, 42390, 43954, 43967, 45559, 47010, 48397, 48417, 49856, 51276, 52723, 52724, 52744, 52745, 52746, 54085, 54086, 54087, 54088, 54089, 54090, 54108, 54109, 54110, 52778, 52779, 51323, 51324, 51325, 51326, 51327, 51343, 51344, 52796, 52797, 52798, 52799, 54150, 55369, 56555, 57747, 58890, 58889, 58903, 60001, 60013, 61045, 61044, 62119, 62118, 62107))" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "border_chain, = surface.find_label_border_polygonal_chains(precentral_label)\n", "border_chain" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "scrolled": true }, "outputs": [], "source": [ "import itertools, numpy\n", "from freesurfer_surface import Vertex, Triangle\n", "\n", "def slice_offset(iterable, offset):\n", " return itertools.islice(iterable, offset, len(iterable))\n", "\n", "def unit_vector(vector: numpy.array) -> numpy.array:\n", " return vector / numpy.linalg.norm(vector)\n", "\n", "BORDER_WIDTH = 0.8 # mm\n", "\n", "for vertex_triplet_indices in zip(*(slice_offset(border_chain.vertex_indices, o) for o in range(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 = unit_vector(vertex_triplet_coords[2] - vertex_triplet_coords[1]) * BORDER_WIDTH / 2\n", " upward_vector = unit_vector(numpy.cross(backward_vector, forward_vector)) * BORDER_WIDTH / 2\n", " sideward_vector = unit_vector(numpy.cross(upward_vector, forward_vector)) * BORDER_WIDTH / 2\n", " cross_section_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", " corner_indices = [[surface.add_vertex(Vertex(*(coords + forward_dir))) for coords in cross_section_corners]\n", " for forward_dir in [-forward_vector, +forward_vector]]\n", " for surface_corner_indices in corner_indices:\n", " surface.triangles.append(Triangle(surface_corner_indices[:3]))\n", " surface.triangles.append(Triangle(surface_corner_indices[2:] + surface_corner_indices[:1]))\n", " for i in range(4):\n", " j = (i + 1) % 4\n", " surface.triangles.append(Triangle((corner_indices[0][i], corner_indices[0][j], corner_indices[1][j])))\n", " surface.triangles.append(Triangle((corner_indices[0][i], corner_indices[1][j], corner_indices[1][i])))\n", "\n", "surface.write_triangular('precentral-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 }