Commit e105516afadc50f51d7f314536b0d2a8b89c38a5
1 parent
403139ae
added spherical harmonics file and updated network code to support vectorization
Showing
2 changed files
with
154 additions
and
0 deletions
Show diff stats
python/network.py
... | ... | @@ -76,6 +76,7 @@ class Fiber: |
76 | 76 | |
77 | 77 | #print(volume) |
78 | 78 | return volume |
79 | + | |
79 | 80 | ''' |
80 | 81 | Writes the header given and open file descripion, number of verticies and number of edges. |
81 | 82 | ''' |
... | ... | @@ -331,3 +332,33 @@ def distancefield(nodeList, edgeList, R=(100, 100, 100)): |
331 | 332 | D, I = tree.query(Q) |
332 | 333 | |
333 | 334 | return D |
335 | + | |
336 | +#returns the number of points in the network | |
337 | +def npoints(N, F): | |
338 | + n = 0 | |
339 | + for f in F: | |
340 | + n = n + len(f.points) - 2 | |
341 | + n = n + len(N) | |
342 | + return n | |
343 | + | |
344 | +#returns the number of linear segments in the network | |
345 | +def nsegments(N, F): | |
346 | + n = 0 | |
347 | + for f in F: | |
348 | + n = n + len(f.points) - 1 | |
349 | + return n | |
350 | + | |
351 | +def vectorize(N, F): | |
352 | + #initialize three coordinate vectors () | |
353 | + n = nsegments(N, F) | |
354 | + X = np.zeros((n)) | |
355 | + Y = np.zeros((n)) | |
356 | + Z = np.zeros((n)) | |
357 | + idx = 0 | |
358 | + for i in range(0, len(F)): | |
359 | + for j in range(0, len(F[i].points)-1): | |
360 | + X[idx] = F[i].points[j][0]-F[i].points[j+1][0] | |
361 | + Y[idx] = F[i].points[j][1]-F[i].points[j+1][1] | |
362 | + Z[idx] = F[i].points[j][2]-F[i].points[j+1][2] | |
363 | + idx = idx + 1 | |
364 | + return X, Y, Z | ... | ... |
1 | +# -*- coding: utf-8 -*- | |
2 | +""" | |
3 | +Created on Mon Dec 18 16:31:36 2017 | |
4 | + | |
5 | +@author: david | |
6 | +""" | |
7 | + | |
8 | +import numpy | |
9 | +import scipy | |
10 | +import matplotlib.pyplot as plt | |
11 | +from matplotlib import cm, colors | |
12 | +from mpl_toolkits.mplot3d import Axes3D | |
13 | +import math | |
14 | + | |
15 | + | |
16 | +def sph2cart(theta, phi, r): | |
17 | + x = r * numpy.cos(theta) * numpy.sin(phi) | |
18 | + y = r * numpy.sin(theta) * numpy.sin(phi) | |
19 | + z = r * numpy.cos(phi) | |
20 | + | |
21 | + return x, y, z | |
22 | + | |
23 | +def cart2sph(x,y,z): | |
24 | + r = numpy.sqrt(x**2+y**2+z**2) | |
25 | + theta = numpy.arctan2(y,x) | |
26 | + phi = numpy.arccos(z/r) | |
27 | + #if(x == 0): | |
28 | + # phi = 0 | |
29 | + #else: | |
30 | + # phi = numpy.arccos(z/r) | |
31 | + #phi = numpy.arctan2(numpy.sqrt(x**2 + y**2), z) | |
32 | + return r, theta, phi | |
33 | + | |
34 | + | |
35 | +def sh(theta, phi, l, m): | |
36 | + | |
37 | + if m < 0: | |
38 | + return numpy.sqrt(2) * (-1)**m * scipy.special.sph_harm(abs(m), l, theta, phi).imag | |
39 | + elif m > 0: | |
40 | + return numpy.sqrt(2) * (-1)**m * scipy.special.sph_harm(m, l, theta, phi).real | |
41 | + else: | |
42 | + return scipy.special.sph_harm(0, l, theta, phi).real | |
43 | + | |
44 | +#calculate a spherical harmonic value from a set of coefficients and a spherical coordinate | |
45 | +def sh_coeff(theta, phi, C): | |
46 | + | |
47 | + s = numpy.zeros(theta.shape) | |
48 | + c = range(len(C)) | |
49 | + | |
50 | + for c in range(len(C)): | |
51 | + l, m = i2lm(c) #get the 2D indices | |
52 | + s = s + C[c] * sh(theta, phi, l, m) | |
53 | + | |
54 | + return s | |
55 | + | |
56 | +#plot a spherical harmonic function on a sphere using N points | |
57 | +def sh_plot(C, N): | |
58 | + phi = numpy.linspace(0, numpy.pi, N) | |
59 | + theta = numpy.linspace(0, 2*numpy.pi, N) | |
60 | + phi, theta = numpy.meshgrid(phi, theta) | |
61 | + | |
62 | + # The Cartesian coordinates of the unit sphere | |
63 | + x = numpy.sin(phi) * numpy.cos(theta) | |
64 | + y = numpy.sin(phi) * numpy.sin(theta) | |
65 | + z = numpy.cos(phi) | |
66 | + | |
67 | + # Calculate the spherical harmonic Y(l,m) and normalize to [0,1] | |
68 | + fcolors = sh_coeff(theta, phi, C) | |
69 | + fmax, fmin = fcolors.max(), fcolors.min() | |
70 | + fcolors = (fcolors - fmin)/(fmax - fmin) | |
71 | + | |
72 | + # Set the aspect ratio to 1 so our sphere looks spherical | |
73 | + fig = plt.figure(figsize=plt.figaspect(1.)) | |
74 | + ax = fig.add_subplot(111, projection='3d') | |
75 | + ax.plot_surface(x, y, z, rstride=1, cstride=1, facecolors=cm.seismic(fcolors)) | |
76 | + # Turn off the axis planes | |
77 | + ax.set_axis_off() | |
78 | + plt.show() | |
79 | + | |
80 | +def i2lm(i): | |
81 | + l = numpy.floor(numpy.sqrt(i)) | |
82 | + m = i - l *(l + 1) | |
83 | + return l, m | |
84 | + | |
85 | +def lm2i(l, m): | |
86 | + return l * (l+1) + m | |
87 | + | |
88 | +#generates a set of spherical harmonic coefficients from samples using linear least squares | |
89 | +def linfit(theta, phi, s, nc): | |
90 | + #allocate space for the matrix | |
91 | + A = numpy.zeros((nc, nc)) | |
92 | + | |
93 | + #calculate each of the matrix coefficients | |
94 | + #(see SH technical report in the vascular_viz repository) | |
95 | + for i in range(nc): | |
96 | + li, mi = i2lm(i) | |
97 | + yi = sh(theta, phi, li, mi) | |
98 | + for j in range(nc): | |
99 | + lj, mj = i2lm(j) | |
100 | + yj = sh(theta, phi, lj, mj) | |
101 | + A[i, j] = numpy.sum(yi * yj) | |
102 | + | |
103 | + #calculate the RHS values | |
104 | + b = numpy.zeros(nc) | |
105 | + for j in range(nc): | |
106 | + lj, mj = i2lm(j) | |
107 | + yj = sh(theta, phi, lj, mj) | |
108 | + b[j] = numpy.sum(yj * s) | |
109 | + | |
110 | + #solve the system of linear equations | |
111 | + return numpy.linalg.solve(A, b) | |
112 | + | |
113 | +#generate a scatter plot in 3D using spherical coordinates | |
114 | +def scatterplot3d(theta, phi, r): | |
115 | + #convert all of the samples to cartesian coordinates | |
116 | + X, Y, Z = sph2cart(theta, phi, r) | |
117 | + | |
118 | + fig = plt.figure() | |
119 | + ax = fig.add_subplot(111, projection='3d') | |
120 | + ax.scatter(X, Y, Z) | |
121 | + plt.show() | |
122 | + | |
123 | + | ... | ... |