├── .gitignore
├── LICENSE
├── README.md
├── data
├── Glasser_2016.32k.L.label.gii
├── MyelinMap_flat_vectors.L.func.gii
├── MyelinMap_inflated_vectors.L.func.gii
├── S1200.MyelinMap.L.func.gii
├── fs_LR.32k.L.flat.surf.gii
├── fs_LR.32k.L.inflated.surf.gii
├── geodesic_distance_flat_vectors.func.gii
├── geodesic_distance_inflated_vectors.func.gii
├── lh.aparc.annot
├── lh.cortex.label
├── lh.inflated
├── lh.sulc
├── lh.thickness
└── v1_geodesic.func.gii
├── examples
├── alpha_colours.ipynb
├── arrows_map.ipynb
├── flat_map.ipynb
├── hcp_example.ipynb
├── plot_surface_with_parcellation.ipynb
└── script_matplotlib.py
├── figs
└── demo_plot.png
├── matplotlib_surface_plotting
├── __init__.py
└── matplotlib_surface_plotting.py
├── setup.py
└── test
└── test-pip.py
/.gitignore:
--------------------------------------------------------------------------------
1 | **/__pycache__/
2 | *.egg-info/
3 | dist/
4 | build/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 kwagstyl
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Matplotlib surface plotting
2 |
3 | Matplotlib 3D mesh plotter for plotting brain meshes
4 | 
5 |
6 | pip install matplotlib-surface-plotting
7 |
8 | Run example:
9 |
10 | python scripts/script_matplotlib.py
11 | to create demo_plot.png using demo files
12 |
13 |
14 | Based on a matplotlib blogpost by Nicolas P. Rougier
15 |
16 | Contributors: M. Ripart, U. Popple, K. Wagstyl
17 |
--------------------------------------------------------------------------------
/data/Glasser_2016.32k.L.label.gii:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
235 |
236 |
237 |
238 |
239 |
240 |
241 | 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
242 |
243 |
244 |
--------------------------------------------------------------------------------
/data/lh.aparc.annot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kwagstyl/matplotlib_surface_plotting/9dcb13dbbd8d0ed765089486ef28dce225ebebb2/data/lh.aparc.annot
--------------------------------------------------------------------------------
/data/lh.inflated:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kwagstyl/matplotlib_surface_plotting/9dcb13dbbd8d0ed765089486ef28dce225ebebb2/data/lh.inflated
--------------------------------------------------------------------------------
/data/lh.sulc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kwagstyl/matplotlib_surface_plotting/9dcb13dbbd8d0ed765089486ef28dce225ebebb2/data/lh.sulc
--------------------------------------------------------------------------------
/data/lh.thickness:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kwagstyl/matplotlib_surface_plotting/9dcb13dbbd8d0ed765089486ef28dce225ebebb2/data/lh.thickness
--------------------------------------------------------------------------------
/examples/hcp_example.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 8,
6 | "metadata": {
7 | "collapsed": true
8 | },
9 | "outputs": [],
10 | "source": [
11 | "import os, sys\n",
12 | "sys.path.append('../matplotlib_surface_plotting/')\n",
13 | "\n",
14 | "from matplotlib_surface_plotting import plot_surf\n",
15 | "import nibabel as nb\n",
16 | "import numpy as np"
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": 9,
22 | "metadata": {
23 | "collapsed": true
24 | },
25 | "outputs": [],
26 | "source": [
27 | "import numpy as np\n",
28 | "import matplotlib.pyplot as plt\n",
29 | "from matplotlib.collections import PolyCollection\n",
30 | "from matplotlib import cm\n",
31 | "\n",
32 | "def normalize_v3(arr):\n",
33 | " ''' Normalize a numpy array of 3 component vectors shape=(n,3) '''\n",
34 | " lens = np.sqrt( arr[:,0]**2 + arr[:,1]**2 + arr[:,2]**2 )\n",
35 | " arr[:,0] /= lens\n",
36 | " arr[:,1] /= lens\n",
37 | " arr[:,2] /= lens \n",
38 | " return arr\n",
39 | "\n",
40 | "def normal_vectors(vertices,faces):\n",
41 | " norm = np.zeros( vertices.shape, dtype=vertices.dtype )\n",
42 | " tris = vertices[faces]\n",
43 | " n = np.cross( tris[::,1 ] - tris[::,0] , tris[::,2 ] - tris[::,0] )\n",
44 | " n=normalize_v3(n)\n",
45 | " return n\n",
46 | "# norm[ faces[:,0] ] += n\n",
47 | "# norm[ faces[:,1] ] += n\n",
48 | "# norm[ faces[:,2] ] += n\n",
49 | " # return normalize_v3(norm)\n",
50 | "\n",
51 | "\n",
52 | "def frustum(left, right, bottom, top, znear, zfar):\n",
53 | " M = np.zeros((4, 4), dtype=np.float32)\n",
54 | " M[0, 0] = +2.0 * znear / (right - left)\n",
55 | " M[1, 1] = +2.0 * znear / (top - bottom)\n",
56 | " M[2, 2] = -(zfar + znear) / (zfar - znear)\n",
57 | " M[0, 2] = (right + left) / (right - left)\n",
58 | " M[2, 1] = (top + bottom) / (top - bottom)\n",
59 | " M[2, 3] = -2.0 * znear * zfar / (zfar - znear)\n",
60 | " M[3, 2] = -1.0\n",
61 | " return M\n",
62 | "\n",
63 | "def perspective(fovy, aspect, znear, zfar):\n",
64 | " h = np.tan(0.5*np.radians(fovy)) * znear\n",
65 | " w = h * aspect\n",
66 | " return frustum(-w, w, -h, h, znear, zfar)\n",
67 | "\n",
68 | "def translate(x, y, z):\n",
69 | " return np.array([[1, 0, 0, x], [0, 1, 0, y],\n",
70 | " [0, 0, 1, z], [0, 0, 0, 1]], dtype=float)\n",
71 | "\n",
72 | "def xrotate(theta):\n",
73 | " t = np.pi * theta / 180\n",
74 | " c, s = np.cos(t), np.sin(t)\n",
75 | " return np.array([[1, 0, 0, 0], \n",
76 | " [0, c, -s, 0],\n",
77 | " [0, s, c, 0], \n",
78 | " [0, 0, 0, 1]], dtype=float)\n",
79 | "\n",
80 | "def yrotate(theta):\n",
81 | " t = np.pi * theta / 180\n",
82 | " c, s = np.cos(t), np.sin(t)\n",
83 | " return np.array([[ c, 0, s, 0], \n",
84 | " [ 0, 1, 0, 0],\n",
85 | " [-s, 0, c, 0], \n",
86 | " [ 0, 0, 0, 1]], dtype=float)\n",
87 | "\n",
88 | "def zrotate(theta):\n",
89 | " t = np.pi * theta / 180\n",
90 | " c, s = np.cos(t), np.sin(t)\n",
91 | " return np.array([[ c, -s, 0, 0], \n",
92 | " [ s, c, 0, 0],\n",
93 | " [0, 0, 1, 0], \n",
94 | " [ 0, 0, 0, 1]], dtype=float)\n",
95 | "\n",
96 | "def shading_intensity(vertices,faces, light = np.array([0,0,1]),shading=0.7):\n",
97 | " \"\"\"shade calculation based on light source\n",
98 | " default is vertical light.\n",
99 | " shading controls amount of shading.\n",
100 | " Also saturates so top 20 % of vertices all have max intensity.\"\"\"\n",
101 | " face_normals=normal_vectors(vertices,faces)\n",
102 | " intensity = np.dot(face_normals, light)\n",
103 | " intensity[np.isnan(intensity)]=1\n",
104 | " shading = 0.7 \n",
105 | " #top 20% all become fully coloured\n",
106 | " intensity = (1-shading)+shading*(intensity-np.min(intensity))/((np.percentile(intensity,80)-np.min(intensity)))\n",
107 | " #saturate\n",
108 | " intensity[intensity>1]=1\n",
109 | " #flat maps have lots of nans which need to become 1\n",
110 | " intensity[np.isnan(intensity)]=1\n",
111 | " return intensity\n",
112 | "\n",
113 | "def f7(seq):\n",
114 | " #returns uniques but in order to retain neighbour triangle relationship\n",
115 | " seen = set()\n",
116 | " seen_add = seen.add\n",
117 | " return [x for x in seq if not (x in seen or seen_add(x))];\n",
118 | "\n",
119 | "\n",
120 | "def get_ring_of_neighbours(island, neighbours, vertex_indices=None, ordered=False):\n",
121 | " \"\"\"Calculate ring of neighbouring vertices for an island of cortex\n",
122 | " If ordered, then vertices will be returned in connected order\"\"\"\n",
123 | " if not vertex_indices:\n",
124 | " vertex_indices=np.arange(len(island))\n",
125 | " if not ordered:\n",
126 | "\n",
127 | " neighbours_island = neighbours[island]\n",
128 | " unfiltered_neighbours = []\n",
129 | " for n in neighbours_island:\n",
130 | " unfiltered_neighbours.extend(n)\n",
131 | " unique_neighbours = np.setdiff1d(np.unique(unfiltered_neighbours), vertex_indices[island])\n",
132 | " return unique_neighbours\n",
133 | "\n",
134 | "def get_neighbours_from_tris(tris, label=None):\n",
135 | " \"\"\"Get surface neighbours from tris\n",
136 | " Input: tris\n",
137 | " Returns Nested list. Each list corresponds \n",
138 | " to the ordered neighbours for the given vertex\"\"\"\n",
139 | " n_vert=np.max(tris+1)\n",
140 | " neighbours=[[] for i in range(n_vert)]\n",
141 | " for tri in tris:\n",
142 | " neighbours[tri[0]].extend([tri[1],tri[2]])\n",
143 | " neighbours[tri[2]].extend([tri[0],tri[1]])\n",
144 | " neighbours[tri[1]].extend([tri[2],tri[0]])\n",
145 | " #Get unique neighbours\n",
146 | " for k in range(len(neighbours)): \n",
147 | " if label is not None:\n",
148 | " neighbours[k] = set(neighbours[k]).intersection(label)\n",
149 | " else :\n",
150 | " neighbours[k]=f7(neighbours[k])\n",
151 | " return np.array(neighbours)\n",
152 | "\n",
153 | "def adjust_colours_pvals(colours, pvals,triangles,mask=None):\n",
154 | " \"\"\"red ring around clusters and greying out non-significant vertices\"\"\"\n",
155 | " if mask is not None:\n",
156 | " verts_masked = mask[triangles].any(axis=1)\n",
157 | " colours[verts_masked,:] = np.array([0.86,0.86,0.86,1])\n",
158 | " neighbours=get_neighbours_from_tris(triangles)\n",
159 | " ring=get_ring_of_neighbours(pvals<0.05,neighbours)\n",
160 | " if len(ring)>0:\n",
161 | " ring_label = np.zeros(len(neighbours)).astype(bool)\n",
162 | " ring_label[ring]=1\n",
163 | " ring=get_ring_of_neighbours(ring_label,neighbours)\n",
164 | " ring_label[ring]=1\n",
165 | " colours[ring_label[triangles].any(axis=1),:] = np.array([1.0,0,0,1])\n",
166 | " grey_out=pvals<0.05\n",
167 | " verts_grey_out= grey_out[triangles].any(axis=1)\n",
168 | " colours[verts_grey_out,:] = (1.5*colours[verts_grey_out] + np.array([0.86,0.86,0.86,1]))/2.5\n",
169 | " return colours\n",
170 | "\n",
171 | "def frontback(T):\n",
172 | " \"\"\"\n",
173 | " Sort front and back facing triangles\n",
174 | " Parameters:\n",
175 | " -----------\n",
176 | " T : (n,3) array\n",
177 | " Triangles to sort\n",
178 | " Returns:\n",
179 | " --------\n",
180 | " front and back facing triangles as (n1,3) and (n2,3) arrays (n1+n2=n)\n",
181 | " \"\"\"\n",
182 | " Z = (T[:,1,0]-T[:,0,0])*(T[:,1,1]+T[:,0,1]) + \\\n",
183 | " (T[:,2,0]-T[:,1,0])*(T[:,2,1]+T[:,1,1]) + \\\n",
184 | " (T[:,0,0]-T[:,2,0])*(T[:,0,1]+T[:,2,1])\n",
185 | " return Z < 0, Z >= 0\n",
186 | "\n",
187 | "\n",
188 | "\n",
189 | "\n",
190 | "def plot_surf(vertices, faces, overlay, rotate=[270,90], cmap='viridis', filename=None, label=False,\n",
191 | " vmax=None, vmin=None, x_rotate=270,z_rotate=0, pvals=None, colorbar=True, title=None, mask=None, base_size=6,\n",
192 | " flat_map=False,\n",
193 | " ):\n",
194 | " \"\"\"plot mesh surface with a given overlay\n",
195 | " vertices - vertex locations\n",
196 | " faces - triangles of vertex indices definings faces\n",
197 | " overlay - array to be plotted\n",
198 | " cmap - matplotlib colormap\n",
199 | " rotate - 270 for lateral on lh, 90 for medial\n",
200 | " \"\"\"\n",
201 | " vertices=vertices.astype(np.float)\n",
202 | " F=faces.astype(int)\n",
203 | " vertices = (vertices-(vertices.max(0)+vertices.min(0))/2)/max(vertices.max(0)-vertices.min(0))\n",
204 | " if not isinstance(rotate,list):\n",
205 | " rotate=[rotate]\n",
206 | " if not isinstance(overlay,list):\n",
207 | " overlays=[overlay]\n",
208 | " else:\n",
209 | " overlays=overlay\n",
210 | " if flat_map:\n",
211 | " z_rotate=90\n",
212 | " rotate=[90]\n",
213 | " \n",
214 | " #change light source if z is rotate\n",
215 | " light = np.array([0,0,1,1]) @ yrotate(z_rotate)\n",
216 | " intensity=shading_intensity(vertices, F, light=light[:3],shading=0.7)\n",
217 | " print(intensity.shape)\n",
218 | " #make figure dependent on rotations\n",
219 | " \n",
220 | " fig = plt.figure(figsize=(base_size*len(rotate)+colorbar*(base_size-2),(base_size-1)*len(overlays)))\n",
221 | " if title is not None:\n",
222 | " plt.title(title, fontsize=25)\n",
223 | " plt.axis('off')\n",
224 | " for k,overlay in enumerate(overlays):\n",
225 | " #colours smoothed (mean) or median if label\n",
226 | " if label:\n",
227 | " colours = np.median(overlay[F],axis=1)\n",
228 | " else:\n",
229 | " colours = np.mean(overlay[F],axis=1)\n",
230 | " if vmax is not None:\n",
231 | " colours = (colours - vmin)/(vmax-vmin)\n",
232 | " colours = np.clip(colours,0,1)\n",
233 | " else:\n",
234 | " colours = (colours - colours.min())/(colours.max()-colours.min())\n",
235 | " vmax = colours.max()\n",
236 | " vmin = colours.min()\n",
237 | " C = plt.get_cmap(cmap)(colours) \n",
238 | " if pvals is not None:\n",
239 | " C = adjust_colours_pvals(C,pvals,F,mask)\n",
240 | " \n",
241 | " \n",
242 | " #adjust intensity based on light source here\n",
243 | "\n",
244 | " C[:,0] *= intensity\n",
245 | " C[:,1] *= intensity\n",
246 | " C[:,2] *= intensity\n",
247 | " for i,view in enumerate(rotate):\n",
248 | " MVP = perspective(25,1,1,100) @ translate(0,0,-3) @ yrotate(view) @ zrotate(z_rotate) @ xrotate(x_rotate) @ zrotate(270*flat_map) \n",
249 | " #translate coordinates based on viewing position\n",
250 | " V = np.c_[vertices, np.ones(len(vertices))] @ MVP.T\n",
251 | " \n",
252 | " V /= V[:,3].reshape(-1,1)\n",
253 | " \n",
254 | " V = V[F]\n",
255 | " \n",
256 | " #triangle coordinates\n",
257 | " T = V[:,:,:2]\n",
258 | " #get Z values for ordering triangle plotting\n",
259 | " Z = -V[:,:,2].mean(axis=1)\n",
260 | " #sort the triangles based on their z coordinate. If front/back views then need to sort a different axis\n",
261 | "#sort the triangles based on their z coordinate. If front/back views then need to sort a different axis\n",
262 | " front, back = frontback(T)\n",
263 | " T=T[front]\n",
264 | " s_C = C[front]\n",
265 | " Z = Z[front]\n",
266 | " I = np.argsort(Z)\n",
267 | " T, s_C = T[I,:], s_C[I,:]\n",
268 | " ax = fig.add_subplot(len(overlays),len(rotate)+1,2*k+i+1, xlim=[-.9,+.9], ylim=[-.9,+.9],aspect=1, frameon=False,\n",
269 | " xticks=[], yticks=[])\n",
270 | " #s_C[:,3]=0.3\n",
271 | " #print(s_C)\n",
272 | " collection = PolyCollection(T, closed=True, linewidth=0,antialiased=False, facecolor=s_C)\n",
273 | " collection.set_alpha(1)\n",
274 | " ax.add_collection(collection)\n",
275 | " plt.subplots_adjust(left =0 , right =1, top=1, bottom=0,wspace=0, hspace=0)\n",
276 | " if colorbar:\n",
277 | " cbar = fig.colorbar(cm.ScalarMappable( cmap=cmap), ticks=[0,0.5, 1],cax = fig.add_axes([0.7, 0.3, 0.03, 0.38]))\n",
278 | " cbar.ax.set_yticklabels([np.round(vmin,decimals=2), np.round(np.mean([vmin,vmax]),decimals=2),\n",
279 | " np.round(vmax,decimals=2)])\n",
280 | " cbar.ax.tick_params(labelsize=25)\n",
281 | " if filename is not None:\n",
282 | " fig.savefig(filename,bbox_inches = 'tight',pad_inches=0,transparent=True)\n",
283 | " return \n",
284 | "\n",
285 | "\n",
286 | "\n"
287 | ]
288 | },
289 | {
290 | "cell_type": "code",
291 | "execution_count": null,
292 | "metadata": {
293 | "collapsed": true
294 | },
295 | "outputs": [],
296 | "source": []
297 | },
298 | {
299 | "cell_type": "code",
300 | "execution_count": 10,
301 | "metadata": {
302 | "collapsed": true
303 | },
304 | "outputs": [],
305 | "source": [
306 | "#vertices = (vertices-(vertices.max(0)+vertices.min(0))/2)/max(vertices.max(0)-vertices.min(0))\n",
307 | "#vertices = np.roll(vertices,1,axis=1)"
308 | ]
309 | },
310 | {
311 | "cell_type": "code",
312 | "execution_count": 11,
313 | "metadata": {
314 | "collapsed": true
315 | },
316 | "outputs": [],
317 | "source": [
318 | "# vector_file=nb.load('../data/MyelinMap_inflated_vectors.L.func.gii')\n",
319 | "# vectors=np.array([vector_file.darrays[0].data,\n",
320 | "# vector_file.darrays[1].data,\n",
321 | "# vector_file.darrays[2].data])"
322 | ]
323 | },
324 | {
325 | "cell_type": "code",
326 | "execution_count": 12,
327 | "metadata": {},
328 | "outputs": [],
329 | "source": [
330 | "surf=nb.load('../data/fs_LR.32k.L.inflated.surf.gii')\n",
331 | "vertices,faces = surf.darrays[0].data,surf.darrays[1].data"
332 | ]
333 | },
334 | {
335 | "cell_type": "code",
336 | "execution_count": 13,
337 | "metadata": {},
338 | "outputs": [],
339 | "source": [
340 | "overlay = nb.load('../data/S1200.MyelinMap.L.func.gii').darrays[0].data"
341 | ]
342 | },
343 | {
344 | "cell_type": "code",
345 | "execution_count": 14,
346 | "metadata": {},
347 | "outputs": [],
348 | "source": [
349 | "surf=nb.load('../data/fs_LR.32k.L.flat.surf.gii')\n",
350 | "vertices,faces = surf.darrays[0].data,surf.darrays[1].data"
351 | ]
352 | },
353 | {
354 | "cell_type": "code",
355 | "execution_count": 15,
356 | "metadata": {
357 | "collapsed": true
358 | },
359 | "outputs": [],
360 | "source": [
361 | "# vertices[:,2]+=vertices[:,0]\n",
362 | "# vertices[:,0]=0"
363 | ]
364 | },
365 | {
366 | "cell_type": "code",
367 | "execution_count": 16,
368 | "metadata": {},
369 | "outputs": [
370 | {
371 | "name": "stderr",
372 | "output_type": "stream",
373 | "text": [
374 | "/home/kwagstyl/anaconda2/envs/padl/lib/python3.7/site-packages/ipykernel_launcher.py:9: RuntimeWarning: invalid value encountered in true_divide\n",
375 | " if __name__ == '__main__':\n",
376 | "/home/kwagstyl/anaconda2/envs/padl/lib/python3.7/site-packages/ipykernel_launcher.py:10: RuntimeWarning: invalid value encountered in true_divide\n",
377 | " # Remove the CWD from sys.path while we load stuff.\n",
378 | "/home/kwagstyl/anaconda2/envs/padl/lib/python3.7/site-packages/ipykernel_launcher.py:11: RuntimeWarning: invalid value encountered in true_divide\n",
379 | " # This is added back by InteractiveShellApp.init_path()\n",
380 | "/home/kwagstyl/anaconda2/envs/padl/lib/python3.7/site-packages/ipykernel_launcher.py:80: RuntimeWarning: divide by zero encountered in true_divide\n",
381 | "/home/kwagstyl/anaconda2/envs/padl/lib/python3.7/site-packages/ipykernel_launcher.py:80: RuntimeWarning: invalid value encountered in true_divide\n"
382 | ]
383 | },
384 | {
385 | "name": "stdout",
386 | "output_type": "stream",
387 | "text": [
388 | "(59013,)\n"
389 | ]
390 | },
391 | {
392 | "data": {
393 | "image/png": "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\n",
394 | "text/plain": [
395 | ""
396 | ]
397 | },
398 | "metadata": {
399 | "needs_background": "light"
400 | },
401 | "output_type": "display_data"
402 | }
403 | ],
404 | "source": [
405 | "plot_surf(vertices,faces,overlay,rotate=90,flat_map=True,\n",
406 | " vmin=1,vmax=2)"
407 | ]
408 | },
409 | {
410 | "cell_type": "code",
411 | "execution_count": 647,
412 | "metadata": {},
413 | "outputs": [
414 | {
415 | "data": {
416 | "text/plain": [
417 | "array([ 1.0000000e+00, 0.0000000e+00, -1.8369702e-16, 1.0000000e+00])"
418 | ]
419 | },
420 | "execution_count": 647,
421 | "metadata": {},
422 | "output_type": "execute_result"
423 | }
424 | ],
425 | "source": [
426 | "light = np.array([0,0,1,1]) @ yrotate(270)\n",
427 | "light"
428 | ]
429 | },
430 | {
431 | "cell_type": "code",
432 | "execution_count": 584,
433 | "metadata": {},
434 | "outputs": [
435 | {
436 | "data": {
437 | "text/plain": [
438 | ""
439 | ]
440 | },
441 | "execution_count": 584,
442 | "metadata": {},
443 | "output_type": "execute_result"
444 | },
445 | {
446 | "data": {
447 | "image/png": "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\n",
448 | "text/plain": [
449 | ""
450 | ]
451 | },
452 | "metadata": {
453 | "needs_background": "light"
454 | },
455 | "output_type": "display_data"
456 | }
457 | ],
458 | "source": [
459 | "\n",
460 | "plt.scatter(vertices[:,1],vertices[:,2])"
461 | ]
462 | },
463 | {
464 | "cell_type": "code",
465 | "execution_count": 1,
466 | "metadata": {},
467 | "outputs": [
468 | {
469 | "ename": "NameError",
470 | "evalue": "name 'intensity' is not defined",
471 | "output_type": "error",
472 | "traceback": [
473 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
474 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
475 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mintensity\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
476 | "\u001b[0;31mNameError\u001b[0m: name 'intensity' is not defined"
477 | ]
478 | }
479 | ],
480 | "source": [
481 | "intensity"
482 | ]
483 | },
484 | {
485 | "cell_type": "code",
486 | "execution_count": null,
487 | "metadata": {
488 | "collapsed": true
489 | },
490 | "outputs": [],
491 | "source": []
492 | }
493 | ],
494 | "metadata": {
495 | "kernelspec": {
496 | "display_name": "padl",
497 | "language": "python",
498 | "name": "padl"
499 | },
500 | "language_info": {
501 | "codemirror_mode": {
502 | "name": "ipython",
503 | "version": 3
504 | },
505 | "file_extension": ".py",
506 | "mimetype": "text/x-python",
507 | "name": "python",
508 | "nbconvert_exporter": "python",
509 | "pygments_lexer": "ipython3",
510 | "version": "3.7.4"
511 | }
512 | },
513 | "nbformat": 4,
514 | "nbformat_minor": 2
515 | }
516 |
--------------------------------------------------------------------------------
/examples/script_matplotlib.py:
--------------------------------------------------------------------------------
1 | import os, sys
2 | sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
3 |
4 | from matplotlib_surface_plotting import plot_surf
5 | import nibabel as nb
6 | import numpy as np
7 |
8 | vertices, faces=nb.freesurfer.io.read_geometry('../data/lh.inflated')
9 | overlay = nb.freesurfer.io.read_morph_data('../data/lh.thickness')
10 |
11 | #optional masking of medial wall
12 | cortex=nb.freesurfer.io.read_label('../data/lh.cortex.label')
13 | mask=np.ones_like(overlay).astype(bool)
14 | mask[cortex]=0
15 | overlay[mask]=np.min(overlay)
16 |
17 | plot_surf( vertices, faces, overlay, rotate=[90,270], filename='demo_plot.png',
18 | vmax = np.max(overlay[cortex]),vmin=np.min(overlay[cortex]),mask=mask,
19 | pvals=np.ones_like(overlay), cmap_label='thickness \n(mm)')
20 |
--------------------------------------------------------------------------------
/figs/demo_plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kwagstyl/matplotlib_surface_plotting/9dcb13dbbd8d0ed765089486ef28dce225ebebb2/figs/demo_plot.png
--------------------------------------------------------------------------------
/matplotlib_surface_plotting/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | from .matplotlib_surface_plotting import plot_surf
--------------------------------------------------------------------------------
/matplotlib_surface_plotting/matplotlib_surface_plotting.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 | from matplotlib.collections import PolyCollection
4 | from matplotlib import cm
5 |
6 | def normalize_v3(arr):
7 | ''' Normalize a numpy array of 3 component vectors shape=(n,3) '''
8 | lens = np.sqrt( arr[:,0]**2 + arr[:,1]**2 + arr[:,2]**2 )
9 | arr[:,0] /= lens
10 | arr[:,1] /= lens
11 | arr[:,2] /= lens
12 | return arr
13 |
14 | def normal_vectors(vertices,faces):
15 | norm = np.zeros( vertices.shape, dtype=vertices.dtype )
16 | tris = vertices[faces]
17 | n = np.cross( tris[::,1 ] - tris[::,0] , tris[::,2 ] - tris[::,0] )
18 | n=normalize_v3(n)
19 | return n
20 |
21 | def vertex_normals(vertices,faces):
22 | norm = np.zeros( vertices.shape, dtype=vertices.dtype )
23 | tris = vertices[faces]
24 | n = np.cross( tris[::,1 ] - tris[::,0] , tris[::,2 ] - tris[::,0] )
25 | n=normalize_v3(n)
26 | norm[ faces[:,0] ] += n
27 | norm[ faces[:,1] ] += n
28 | norm[ faces[:,2] ] += n
29 | return normalize_v3(norm)
30 |
31 |
32 | def frustum(left, right, bottom, top, znear, zfar):
33 | M = np.zeros((4, 4), dtype=np.float32)
34 | M[0, 0] = +2.0 * znear / (right - left)
35 | M[1, 1] = +2.0 * znear / (top - bottom)
36 | M[2, 2] = -(zfar + znear) / (zfar - znear)
37 | M[0, 2] = (right + left) / (right - left)
38 | M[2, 1] = (top + bottom) / (top - bottom)
39 | M[2, 3] = -2.0 * znear * zfar / (zfar - znear)
40 | M[3, 2] = -1.0
41 | return M
42 |
43 | def perspective(fovy, aspect, znear, zfar):
44 | h = np.tan(0.5*np.radians(fovy)) * znear
45 | w = h * aspect
46 | return frustum(-w, w, -h, h, znear, zfar)
47 |
48 | def translate(x, y, z):
49 | return np.array([[1, 0, 0, x], [0, 1, 0, y],
50 | [0, 0, 1, z], [0, 0, 0, 1]], dtype=float)
51 |
52 | def xrotate(theta):
53 | t = np.pi * theta / 180
54 | c, s = np.cos(t), np.sin(t)
55 | return np.array([[1, 0, 0, 0], [0, c, -s, 0],
56 | [0, s, c, 0], [0, 0, 0, 1]], dtype=float)
57 |
58 | def yrotate(theta):
59 | t = np.pi * theta / 180
60 | c, s = np.cos(t), np.sin(t)
61 | return np.array([[ c, 0, s, 0], [ 0, 1, 0, 0],
62 | [-s, 0, c, 0], [ 0, 0, 0, 1]], dtype=float)
63 |
64 | def zrotate(theta):
65 | t = np.pi * theta / 180
66 | c, s = np.cos(t), np.sin(t)
67 | return np.array([[ c, -s, 0, 0],
68 | [ s, c, 0, 0],
69 | [0, 0, 1, 0],
70 | [ 0, 0, 0, 1]], dtype=float)
71 |
72 | def shading_intensity(vertices,faces, light = np.array([0,0,1]),shading=0.7):
73 | """shade calculation based on light source
74 | default is vertical light.
75 | shading controls amount of shading.
76 | Also saturates so top 20 % of vertices all have max intensity."""
77 | face_normals=normal_vectors(vertices,faces)
78 | intensity = np.dot(face_normals, light)
79 | intensity[np.isnan(intensity)]=1
80 | shading = 0.7
81 | #top 20% all become fully coloured
82 | intensity = (1-shading)+shading*(intensity-np.min(intensity))/((np.percentile(intensity,80)-np.min(intensity)))
83 | #saturate
84 | intensity[intensity>1]=1
85 |
86 | return intensity
87 |
88 |
89 | def f7(seq):
90 | #returns uniques but in order to retain neighbour triangle relationship
91 | seen = set()
92 | seen_add = seen.add
93 | return [x for x in seq if not (x in seen or seen_add(x))];
94 |
95 |
96 | def get_ring_of_neighbours(island, neighbours, vertex_indices=None, ordered=False):
97 | """Calculate ring of neighbouring vertices for an island of cortex
98 | If ordered, then vertices will be returned in connected order"""
99 | if not vertex_indices:
100 | vertex_indices=np.arange(len(island))
101 | if not ordered:
102 |
103 | neighbours_island = neighbours[island]
104 | unfiltered_neighbours = []
105 | for n in neighbours_island:
106 | unfiltered_neighbours.extend(n)
107 | unique_neighbours = np.setdiff1d(np.unique(unfiltered_neighbours), vertex_indices[island])
108 | return unique_neighbours
109 |
110 | def get_neighbours_from_tris(tris, label=None):
111 | """Get surface neighbours from tris
112 | Input: tris
113 | Returns Nested list. Each list corresponds
114 | to the ordered neighbours for the given vertex"""
115 | n_vert=np.max(tris+1)
116 | neighbours=[[] for i in range(n_vert)]
117 | for tri in tris:
118 | neighbours[tri[0]].extend([tri[1],tri[2]])
119 | neighbours[tri[2]].extend([tri[0],tri[1]])
120 | neighbours[tri[1]].extend([tri[2],tri[0]])
121 | #Get unique neighbours
122 | for k in range(len(neighbours)):
123 | if label is not None:
124 | neighbours[k] = set(neighbours[k]).intersection(label)
125 | else :
126 | neighbours[k]=f7(neighbours[k])
127 | return np.array(neighbours,dtype=object)
128 |
129 | def mask_colours(colours,triangles,mask,mask_colour=None):
130 | """grey out mask"""
131 | if mask is not None:
132 | if mask_colour is None:
133 | mask_colour = np.array([0.86,0.86,0.86,1])
134 | verts_masked = mask[triangles].any(axis=1)
135 | colours[verts_masked,:] = mask_colour
136 | return colours
137 |
138 | def adjust_colours_pvals(colours, pvals,triangles,mask=None,mask_colour=None,
139 | border_colour = np.array([1.0,0,0,1])):
140 | """red ring around clusters and greying out non-significant vertices"""
141 | colours=mask_colours(colours,triangles,mask,mask_colour)
142 | neighbours=get_neighbours_from_tris(triangles)
143 | ring=get_ring_of_neighbours(pvals<0.05,neighbours)
144 | if len(ring)>0:
145 | ring_label = np.zeros(len(neighbours)).astype(bool)
146 | ring_label[ring]=1
147 | ring=get_ring_of_neighbours(ring_label,neighbours)
148 | ring_label[ring]=1
149 | colours[ring_label[triangles].any(axis=1),:] = border_colour
150 | grey_out=pvals<0.05
151 | verts_grey_out= grey_out[triangles].any(axis=1)
152 | colours[verts_grey_out,:] = (1.5*colours[verts_grey_out] + np.array([0.86,0.86,0.86,1]))/2.5
153 | return colours
154 |
155 |
156 |
157 | def add_parcellation_colours(colours,parcel,triangles,labels=None,
158 | mask=None,filled=False,mask_colour=None, neighbours=None):
159 | """delineate regions"""
160 | colours=mask_colours(colours,triangles,mask,mask_colour=mask_colour)
161 | #normalise rois and colors
162 | rois=list(set(parcel))
163 | if 0 in rois:
164 | rois.remove(0)
165 | if labels is None :
166 | labels = dict(zip(rois, np.random.rand(len(rois),4)))
167 | #remove transparent rois
168 | #find vertices that delineate rois
169 | if filled:
170 | colours=np.zeros_like(colours)
171 | for l,label in enumerate(rois):
172 | colours[np.median(parcel[triangles],axis=1)==label]=labels[label]
173 | return colours
174 | if neighbours is None:
175 | neighbours=get_neighbours_from_tris(triangles)
176 | matrix_colored = np.zeros([len(triangles), len(rois)])
177 | for l,label in enumerate(rois):
178 | ring=get_ring_of_neighbours(parcel!=label,neighbours)
179 | if len(ring)>0:
180 | ring_label = np.zeros(len(neighbours)).astype(bool)
181 | ring_label[ring]=1
182 | # ring=get_ring_of_neighbours(ring_label,neighbours)
183 | # ring_label[ring]=1
184 | # matrix_colored[:,l] = ring_label[triangles].sum(axis=1)
185 | matrix_colored[:,l] = np.median(ring_label[triangles],axis=1) #ring_label[triangles].sum(axis=1)
186 | #update colours with delineation
187 | maxis = [max(matrix_colored[i,:]) for i in range(0,len(colours))]
188 | colours = np.array([labels[rois[np.random.choice(np.where(matrix_colored[i,:] == maxi)[0])]]
189 | if maxi!=0 else colours[i] for i,maxi in enumerate(maxis)])
190 | return colours
191 |
192 |
193 | def adjust_colours_alpha(colours,alpha):
194 | """grey out vertices according to scalar"""
195 | #rescale alpha to 0.2-1.0
196 | alpha_rescaled = 0.1+0.9*(alpha-np.min(alpha))/(np.max(alpha)-np.min(alpha))
197 | colours = (alpha_rescaled*colours.T).T + ((1-alpha_rescaled)*np.array([0.86,0.86,0.86,1]).reshape(-1,1)).T
198 | colours = np.clip(colours, 0,1)
199 | return colours
200 |
201 | def frontback(T):
202 | """
203 | Sort front and back facing triangles
204 | Parameters:
205 | -----------
206 | T : (n,3) array
207 | Triangles to sort
208 | Returns:
209 | --------
210 | front and back facing triangles as (n1,3) and (n2,3) arrays (n1+n2=n)
211 | """
212 | Z = (T[:,1,0]-T[:,0,0])*(T[:,1,1]+T[:,0,1]) + \
213 | (T[:,2,0]-T[:,1,0])*(T[:,2,1]+T[:,1,1]) + \
214 | (T[:,0,0]-T[:,2,0])*(T[:,0,1]+T[:,2,1])
215 | return Z < 0, Z >= 0
216 |
217 | def normalized(a, axis=-1, order=2):
218 | l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
219 | l2[l2==0] = 1
220 | return a / np.expand_dims(l2, axis)
221 |
222 |
223 | def plot_surf(vertices, faces,overlay, rotate=[90,270], cmap='viridis', filename='plot.png', label=False,
224 | vmax=None, vmin=None, x_rotate=270, pvals=None, colorbar=True, cmap_label='value',
225 | title=None, mask=None, base_size=6, arrows=None,arrow_subset=None,arrow_size=0.5,
226 | arrow_colours = None,arrow_head=0.05,arrow_width=0.001,
227 | mask_colour=None,transparency=1,show_back=False,border_colour = np.array([1,0,0,1]),
228 | alpha_colour = None,flat_map=False, z_rotate=0,neighbours=None,
229 | parcel=None, parcel_cmap=None,filled_parcels=False,return_ax=False):
230 | """ This function plot mesh surface with a given overlay.
231 | Features available : display in flat surface, display parcellation on top, display gradients arrows on top
232 |
233 |
234 | Parameters:
235 | ----------
236 | vertices : numpy array
237 | vertex locations
238 | faces : numpy array
239 | triangles of vertex indices definings faces
240 | overlay : numpy array
241 | array to be plotted
242 | rotate : tuple, optional
243 | rotation angle for lateral on lh, and medial
244 | cmap : string, optional
245 | matplotlib colormap
246 | filename : string, optional
247 | name of the figure to save
248 | label : bool, optional
249 | colours smoothed (mean) or median if label
250 | vmin, vmax : float, optional
251 | min and max value for display intensity
252 | x_rotate : int, optional
253 |
254 | pvals : bool, optional
255 |
256 | colorbar : bool, optional
257 | display or not colorbar
258 | cmap_label : string, optional
259 | label of the colorbar
260 | title : string, optional
261 | title of the figure
262 | mask : numpy array, optional
263 | vector to mask part of the surface
264 | base_size : int, optional
265 |
266 | arrows : numpy array, optional
267 | dipsplay arrows in the directions of gradients on top of the surface
268 | arrow_subset : numpy array, optional
269 | vector containing at which vertices display an arrow
270 | arrow_size : float, optional
271 | size of the arrow
272 | arrow_colours:
273 | alpha_colour : float, optional
274 | value to play with transparency of the overlay
275 | flat_map : bool, optional
276 | display on flat map
277 | z_rotate : int, optional
278 | transparency : float, optional
279 | value between 0-1 to play with mesh transparency
280 | show_back : bool, optional
281 | display or hide the faces in the back of the mesh (z<0)
282 | parcel : numpy array, optional
283 | delineate rois on top of the surface
284 | parcel_cmap : dictionary, optional
285 | dic containing labels and colors associated for the parcellation
286 | filled_parcels: fill the parcel colours
287 | neighbours : provided neighbours in case faces is only a subset of all vertices
288 |
289 | """
290 | vertices=vertices.astype(np.float32)
291 | F=faces.astype(int)
292 | vertices = (vertices-(vertices.max(0)+vertices.min(0))/2)/max(vertices.max(0)-vertices.min(0))
293 | if not isinstance(rotate,list):
294 | rotate=[rotate]
295 | if not isinstance(overlay,list):
296 | overlays=[overlay]
297 | else:
298 | overlays=overlay
299 | if parcel is not None:
300 | if parcel.sum() == 0:
301 | parcel = None
302 | if flat_map:
303 | z_rotate=90
304 | rotate=[90]
305 | intensity = np.ones(len(F))
306 | else:
307 | #change light source if z is rotate
308 | light = np.array([0,0,1,1]) @ yrotate(z_rotate)
309 | intensity=shading_intensity(vertices, F, light=light[:3],shading=0.7)
310 | #make figure dependent on rotations
311 |
312 | fig = plt.figure(figsize=(base_size*len(rotate)+colorbar*(base_size-2),
313 | (base_size-1)*len(overlays)))
314 | if title is not None:
315 | plt.title(title, fontsize=25)
316 | plt.axis('off')
317 | for k,overlay in enumerate(overlays):
318 | #colours smoothed (mean) or median if label
319 | if label:
320 | colours = np.median(overlay[F],axis=1)
321 | else:
322 | colours = np.mean(overlay[F],axis=1)
323 | if vmax is not None:
324 | colours = (colours - vmin)/(vmax-vmin)
325 | colours = np.clip(colours,0,1)
326 | else:
327 | vmax = colours.max()
328 | vmin = colours.min()
329 | colours = (colours - colours.min())/(colours.max()-colours.min())
330 | C = plt.get_cmap(cmap)(colours)
331 | if alpha_colour is not None:
332 | C = adjust_colours_alpha(C,np.mean(alpha_colour[F],axis=1))
333 | if pvals is not None:
334 | C = adjust_colours_pvals(C,pvals,F,mask,mask_colour=mask_colour,
335 | border_colour=border_colour)
336 | elif mask is not None:
337 | C = mask_colours(C,F,mask,mask_colour=mask_colour)
338 | if parcel is not None :
339 | C = add_parcellation_colours(C,parcel,F,parcel_cmap,
340 | mask,mask_colour=mask_colour,
341 | filled=filled_parcels, neighbours=neighbours)
342 |
343 | #adjust intensity based on light source here
344 | C[:,0] *= intensity
345 | C[:,1] *= intensity
346 | C[:,2] *= intensity
347 |
348 | collection = PolyCollection([], closed=True, linewidth=0,antialiased=False, facecolor=C, cmap=cmap)
349 | for i,view in enumerate(rotate):
350 | MVP = perspective(25,1,1,100) @ translate(0,0,-3) @ yrotate(view) @ zrotate(z_rotate) @ xrotate(x_rotate) @ zrotate(270*flat_map)
351 | #translate coordinates based on viewing position
352 | V = np.c_[vertices, np.ones(len(vertices))] @ MVP.T
353 |
354 | V /= V[:,3].reshape(-1,1)
355 | center = np.array([0, 0, 0, 1]) @ MVP.T;
356 | center /= center[3];
357 | # add vertex positions to A_dir before transforming them
358 | if arrows is not None:
359 | #calculate arrow position + small shift in surface normal direction
360 | vertex_normal_orig = vertex_normals(vertices,faces)
361 | A_base = np.c_[vertices+vertex_normal_orig*0.01, np.ones(len(vertices))] @ MVP.T
362 | A_base /= A_base[:,3].reshape(-1,1)
363 |
364 | #calculate arrow direction
365 | A_dir = np.copy(arrows)
366 | #normalise arrow size
367 | max_arrow = np.max(np.linalg.norm(arrows,axis=1))
368 | A_dir = arrow_size*A_dir/max_arrow
369 | A_dir = np.c_[A_dir, np.ones(len(A_dir))] @ MVP.T
370 | A_dir /= A_dir[:,3].reshape(-1,1)
371 | # A_dir *= 0.1;
372 |
373 | V = V[F]
374 |
375 | #triangle coordinates
376 | T = V[:,:,:2]
377 | #get Z values for ordering triangle plotting
378 | Z = -V[:,:,2].mean(axis=1)
379 | #sort the triangles based on their z coordinate. If front/back views then need to sort a different axis
380 | front, back = frontback(T)
381 | if show_back == False:
382 | T=T[front]
383 | s_C = C[front]
384 | Z = Z[front]
385 | else:
386 | s_C = C
387 | I = np.argsort(Z)
388 | T, s_C = T[I,:], s_C[I,:]
389 | ax = fig.add_subplot(len(overlays),len(rotate)+1,2*k+i+1, xlim=[-.98,+.98], ylim=[-.98,+.98],aspect=1, frameon=False,
390 | xticks=[], yticks=[])
391 | collection = PolyCollection(T, closed=True, linewidth=0,antialiased=False, facecolor=s_C, cmap=cmap)
392 | collection.set_alpha(transparency)
393 | ax.add_collection(collection)
394 | #add arrows to image
395 | if arrows is not None:
396 | front_arrows = F[front].ravel()
397 | for arrow_index,i in enumerate(arrow_subset):
398 | if i in front_arrows and A_base[i,2] < center[2] + 0.01:
399 | arrow_colour = 'k'
400 | if arrow_colours is not None:
401 | arrow_colour = arrow_colours[arrow_index]
402 | #if length of arrows corresponds perfectly with coordinates
403 | # assume 1:1 matching
404 | if len(A_dir) == len(A_base):
405 | direction = A_dir[i]
406 | #otherwise, assume it is a custom list matching the
407 | elif len(A_dir) == len(arrow_subset):
408 | direction = A_dir[arrow_index]
409 | half = direction * 0.5
410 |
411 | ax.arrow(A_base[i,0] - half[0],
412 | A_base[i,1] - half[1],
413 | direction[0], direction[1],
414 | head_width=arrow_head,width =arrow_width,
415 | color = arrow_colour)
416 | # ax.arrow(A_base[idx,0], A_base[idx,1], A_dir[i,0], A_dir[i,1], head_width=0.01)
417 | plt.subplots_adjust(left =0 , right =1, top=1, bottom=0,wspace=0, hspace=0)
418 |
419 | if colorbar:
420 | l=0.7
421 | if len(rotate)==1:
422 | l=0.5
423 | cbar_size= [l, 0.3, 0.03, 0.38]
424 | cbar = fig.colorbar(collection,
425 | ticks=[0,0.5, 1],
426 | cax = fig.add_axes(cbar_size),
427 | )
428 | cbar.ax.set_yticklabels([np.round(vmin,decimals=2), np.round(np.mean([vmin,vmax]),decimals=2),
429 | np.round(vmax,decimals=2)])
430 | cbar.ax.tick_params(labelsize=25)
431 | cbar.ax.set_title(cmap_label, fontsize=25, pad = 30)
432 | if filename is not None:
433 | fig.savefig(filename,bbox_inches = 'tight',pad_inches=0,transparent=True)
434 | if return_ax:
435 | return fig,ax,MVP
436 | return
437 |
438 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | with open("README.md", "r", encoding="utf-8") as fh:
4 | long_description = fh.read()
5 |
6 |
7 | setup(name='matplotlib_surface_plotting',
8 | version='0.12',
9 | packages=find_packages(),
10 | install_requires=['nibabel',
11 | 'matplotlib>=3.3.2'],
12 | package_dir={'matplotlib_surface_plotting':'matplotlib_surface_plotting'},
13 | url="https://github.com/kwagstyl/matplotlib_surface_plotting",
14 | description="Brain mesh plotting in matplotlib",
15 | long_description=long_description,
16 | long_description_content_type="text/markdown",
17 | )
18 |
--------------------------------------------------------------------------------
/test/test-pip.py:
--------------------------------------------------------------------------------
1 | import matplotlib_surface_plotting
2 |
3 | print("imported!")
--------------------------------------------------------------------------------