I want to calculate the magnetic field of a wire using biot-savart-law. Some people recommend to use numpy arrays. At first i did it with vpython and it worked. But know I want to use Matplotlib for visualisation. Therefore I need arrays right? But I stuck now.
I also posted this question to codereview, but they send me to stackoverflow.
The problem is in this line --> bfield2 = konstante*I*cross(dl, (rx,ry,rz))/r**3
import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from visual import *
I = 1
mu0 = 1e-7
konstante = mu0/(4*np.pi)
# wire elements; always lenght one
coord = [(0,0), (1,0), (2,0), (3,0), (4,0), (5,0), (6,0), (7,0), (8,0), (9,0), (9,1),
(9,2), (9,3), (9,4), (9,5), (9,6), (9,7), (9,8)]
# draw the wires
#for i in range(len(coord)-1):
# wire = curve(pos=(coord[i],coord[i+1]), radius=0.2)
# calculate the b-field
def bfield(x,y,z):
bfield3 = 0
# number of wire elements
for i in range(len(coord)-1):
# center of the wire element
wiremiddlex = coord[i][0]+(coord[i+1][0]-coord[i][0])/2.0
wiremiddley = coord[i][1]+(coord[i+1][1]-coord[i][1])/2.0
wiremiddlez = 0
rx = x-wiremiddlex
ry = y-wiremiddley
rz = 0
r = (rx**2+ry**2+rz**2)**0.5
dl = ((coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0)
bfield2 = konstante*I*cross(dl, (rx,ry,rz))/r**3 # i have to use numpy arrays
bfield3 += (bfield2[0]**2 + bfield2[1]**2 + bfield2[2]**2)**0.5
return bfield3
# visualize
xwidth=10
ywidth=10
delta = 1
x = np.arange(0, xwidth, delta)
y = np.arange(0, ywidth, delta)
X, Y = np.meshgrid(x, y)
slicee = 3
Z = bfield(X,Y,slicee)
plt.figure()
CS = plt.contour(X, Y, Z)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Simplest default with labels')
plt.show()
EDIT No. 7: I delete the other Edits. I don't want to confuse. The output in not correct. Please see the next Edit.
# Calculation of a magnetic field of a wire
# later I want to to it three dimensional
import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from pylab import *
I = 10000000000
mu0 = 1e-7
constant = mu0/(4*np.pi)
# wire elements; always lenght one
coord = [(0,0), (1,0), (2,0), (3,0), (4,0), (5,0), (6,0), (7,0), (8,0),
(9,0), (9,1), (9,2), (9,3), (9,4), (9,5), (9,6), (9,7), (9,8),
(8,8), (7,8), (6,8), (5,8)]
# calculate the b-field
def bfield(x,y,z):
b2 = np.zeros((xwidth,ywidth))
for x in range(xwidth):
for y in range(ywidth):
# number of wire elements
for i in range(21):
rx = (coord[i][0]+coord[i+1][0])/2. - x
ry = (coord[i][1]+coord[i+1][1])/2. - y
rz = z * 1.0 # = z-0
r = (rx**2+ry**2+rz**2)**0.5 # distance r between field and middle of the wire
dl = np.array([(coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0])
b = np.cross(dl, np.array([rx,ry,rz]))
e = constant*I*b/r**3
b2[y][x] += e[2] # why not x y?
return b2
xwidth = 15
ywidth = 15
delay = 1
x = np.arange(0, xwidth, delay)
y = np.arange(0, ywidth, delay)
X, Y = np.meshgrid(x, y)
slicee = 0.1
Z = bfield(X,Y,slicee)
# visualize
plt.figure()
CS = plt.contour(X, Y, Z)
plt.clabel(CS, inline=1, fontsize=10)
x1 = array([0,1,2,3,4,5,6,7,8,9,9,9,9,9,9,9,9,9,8,7,6,5])
y1 = array([0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8,8,8,8])
plot(x1,y1)
plt.title('magnetic field')
plt.show()
Last edit:
Finally i did it without numpy.
The following version works.
# Calculation of a magnetic field of a wire
# later I want to to it three dimensional
import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from pylab import *
# constant
I = 10000000000
mu0 = 1e-7
constant = mu0/(4*np.pi)
# wire position
coord = [(10,10), (20,10), (20,20), (10,20), (10,25)]
coord2 = []
# devide path of the wire in parts of length one
parts = 0
for n in range(len(coord)-1):
lengthx = coord[n+1][0] - coord[n][0]
lengthy = coord[n+1][1] - coord[n][1]
length = (lengthx**2 + lengthy**2)**.5
for m in range(int(length)):
coord2.append((coord[n][0]+lengthx/length*m, coord[n][1]+lengthy/length*m))
parts += 1
# calculate the b-field
def bfield(x,y,z):
b = 0
for i in range(parts-1):
dlx = coord2[i+1][0]-coord2[i][0]
dly = coord2[i+1][1]-coord2[i][1]
dlz = 0
dl = np.array([dlx,dly,dlz])
rspace_minus_rwire_x = x - (coord2[i][0]+dlx)
rspace_minus_rwire_y = y - (coord2[i][1]+dly)
rspace_minus_rwire_z = z - 0
rspace_minus_rwire = np.array([rspace_minus_rwire_x, rspace_minus_rwire_y, rspace_minus_rwire_z])
absr = (rspace_minus_rwire_x**2 + rspace_minus_rwire_y**2 + rspace_minus_rwire_z**2)**0.5
a = constant * I * np.cross(dl, rspace_minus_rwire) / absr**3
b += (a[0]**2 + a[1]**2 + a[2]**2)**0.5
return b
xwidth = 26
ywidth = 26
z = 1
bmatrix = np.zeros((xwidth,ywidth))
for x in range(xwidth):
for y in range(ywidth):
bmatrix[x][y] = bfield(x,y,z)
# visualize
plt.figure()
x = range(xwidth)
y = range(ywidth)
z = bmatrix[x][y].T
contour(x,y,z,35)
plt.show()
Change
dl = ((coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0)
bfield2 = konstante*I*cross(dl, (rx,ry,rz))/r**3 # i have to use numpy arrays
To
dl = np.array([(coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0])
bfield2 = konstante*I*cross(dl, np.array([rx,ry,rz]))/r**3 # i have to use numpy arrays
I don't have Numpy on this machine, so this is untested. Basically, change your tuples into a numpy arrays using np.array.
You could probably also leave dl alone and change bfield2 to use np.array(dl) instead of dl.
This is not any answer tou your original question, but just a hint how to operate with numpy arrays:
In []: coord = [(0,0), (1,0), (2,0), (3,0), (4,0), (5,0), (6,0), (7,0), (8,0), (9,0), (9,1), (9,2), (9,3), (9,4), (9,5), (9,6), (9,7), (9,8)]
In []: coord= np.array(coord).T
In []: coord
Out[]:
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8]])
In [170]: wiremiddle= (coord[:, 1:]- coord[:, :-1])/ 2.
In []: wiremiddle
Out[]:
array([[ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]])
I'll hope this will help to rewrite your code.
you do this:
bfield3 = 0
maybe you should do something like this:
bfield3 = np.zeros((len(...),len(...)))
Or maybe bfield3 is allocated already? and you just want to set all values to zero? Then do this:
bfield3[:,:] = 0
I would avoid bringing in the visual module, which it appears you are using only for the call to 'cross' and use numpy's cross in its place:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.cross.html
You'll have to change a couple of lines to make dl and the second argument of cross numpy arrays
dl = np.array([(coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0])
and double check to make sure that numpy's cross is doing the same thing that visual's was.
If you insist on using the visual cross method, then it is clear from the error that you're having a type conflict which you'll have to resolve
Related
I'm trying to project 3D body keypoints to 2D keypoints,
My 3D points are:
points = np.array([[-7.55801499e-02, -3.69511306e-01, -2.63576955e-01],
[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ 3.08661222e-01, -2.93346141e-02, 3.72593999e-02],
[ 5.96781611e-01, -2.82074720e-01, 4.71359938e-01],
[ 5.38534284e-01, -8.05779934e-01, 4.68694866e-01],
[-3.67936224e-01, -1.09069087e-01, 9.90774706e-02],
[-5.24732828e-01, -2.87176669e-01, 6.09635711e-01],
[-4.37022656e-01, -7.87327409e-01, 4.43706572e-01],
[ 1.33009470e-09, -5.10657072e-09, 1.00000000e+00],
[ 1.13241628e-01, 3.25177647e-02, 1.24026799e+00],
[ 3.43442023e-01, -2.51034945e-01, 1.90472209e+00],
[ 2.57550180e-01, -2.86886752e-01, 2.75528717e+00],
[-1.37361348e-01, -2.60521360e-02, 1.19951272e+00],
[-3.26779515e-01, -5.59706092e-01, 1.75905156e+00],
[-4.65996087e-01, -7.69565761e-01, 2.56634569e+00],
[-1.89841837e-02, -3.19088846e-01, -3.69913191e-01],
[-1.61812544e-01, -3.10732543e-01, -3.47061515e-01],
[ 7.68100023e-02, -1.19293019e-01, -3.72248143e-01],
[-2.24317372e-01, -1.02143347e-01, -3.32051814e-01],
[-3.77829641e-01, -1.19915462e+00, 2.56900430e+00],
[-5.45104921e-01, -1.13393784e+00, 2.57149625e+00],
[-5.66698492e-01, -6.89325571e-01, 2.67840290e+00],
[ 4.65222150e-01, -6.44857705e-01, 2.83186650e+00],
[ 5.27995050e-01, -4.69421804e-01, 2.87518311e+00],
[ 1.77749291e-01, -1.74753308e-01, 2.88810611e+00]])
I plotted them using:
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.set_xlim3d(1, -1)
ax.set_ylim3d(1, -1)
ax.set_zlim3d(1, -1)
ax.scatter3D(points[:, 0], points[:, 1],
points[:, 2], cmap='Greens')
The result is:
I want an array of 2D points with the same camera view, so my desired result a 2D array:
I have tried so far:
import cv2
ans = []
for k in range(25):
tmp = np.array(s[0, k, :]).reshape(1,3)
revc = np.array([0, 0, 0], np.float) # rotation vector
tvec = np.array([0, 0, 0], np.float) # translation vector
fx = fy = 1.0
cx = cy = 0.0
cameraMatrix = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]])
result = cv2.projectPoints(tmp, revc, tvec, cameraMatrix, None)
ans.append(result[0])
ans = np.array(ans).squeeze()
But the result I'm getting is:
plt.scatter(ans[:,0], ans[:, 1])
I can't figure out why the information is lost during projection, kindly help me in this. Also its not necessary for me to use OpenCV so you can suggest other methods like using numpy too.
Thanks
Here's a way to do this from "scratch". I have the following import statements:
import numpy as np
import matplotlib.pyplot as plt
from numpy import sin,cos,pi
from scipy.linalg import norm
After your 3d plotting code, I added the following:
azim = ax.azim*pi/180
elev = ax.elev*pi/180
elev *= 1.2 # this seems to improve the outcome
a_vec = np.array([cos(azim),sin(azim),0])
normal = cos(elev)*a_vec + np.array([0,0,sin(elev)])
z_vec = np.array([0,0,1])
y_comp = z_vec - (z_vec#normal)*normal
y_comp = y_comp/norm(y_comp)
x_comp = np.cross(y_comp,normal)
proj_mat = np.vstack([x_comp,y_comp]) # build projection matrix
proj_mat = -proj_mat # account for flipped axes
points_2D = points # proj_mat.T # apply projection
plt.figure()
plt.scatter(*points_2D.T)
plt.gca().set_aspect('equal', adjustable='box')
plt.axis('off')
plt.show()
The resulting points:
I have a 3D scalar field mesh given in non-cartesian coordinate system.
After coordinate transformation back to conventional cartesian coordinates
mlab.contour3d displays wrong result, while mlab.points3d works as expected. How can I view isosurfaces of given mesh in different coordinate systems?
This is my code
import os
import numpy as np
# fix incorrect order in foregroud objects
os.environ['ETS_TOOLKIT'] = 'qt4'
os.environ['QT_API'] = 'pyqt'
from mayavi import mlab
def plot_cell(cell, mlab):
for nr, i in enumerate(cell):
coord = np.zeros((4, 3), dtype=float)
coord[1] = i
for nr2, j in enumerate(cell):
if nr == nr2:
continue
coord[2] = i + j
for nr3, k in enumerate(cell):
if nr3 == nr or nr3 == nr2:
continue
coord[3] = i + j + k
mlab.plot3d(*coord.T, color=(0, 0, 0), line_width=0.01)
# generate data in non-cartesian coordinate system
scaled_coord = [np.linspace(0, 1, 20, endpoint=False) for i in range(3)]
XYZ = np.array(np.meshgrid(*scaled_coord, indexing="ij"))
data = np.sin(2*np.pi*XYZ[0])*np.sin(2*np.pi*XYZ[1])*np.sin(2*np.pi*XYZ[2])
plot_cell(np.eye(3), mlab)
mlab.contour3d(*XYZ, data)
mlab.savefig("old_coord.png")
mlab.close()
# transform to cartesian coordinates
cell = np.array(
[[ 1. , 0. , 0. ],
[-0.5 , 0.87, 0. ],
[ 0. , 0. , 3.07]])
transformation_matrix = cell.T
XYZ2 = np.einsum('ij,jabc->iabc', transformation_matrix, XYZ)
# plot transformed result
plot_cell(cell, mlab)
mlab.contour3d(*XYZ2, data)
mlab.savefig("new_coord.png")
mlab.close()
# plot points
plot_cell(cell, mlab)
mlab.points3d(*XYZ2, data)
mlab.savefig("new_coord_expected.png")
mlab.close()
After watching 3D Visualization with Mayavi I managed to solve it myself.
Problem is that mlab.contour3d works only with rectilinear grid data (grid generated with np.meshgrid or np.mgrid). In my case one can use tvtk.StructuredGrid object for structured grids which have same topology as
rectilinear grid but nonuniform spacing and directions between points.
This is working code:
import os
import numpy as np
from tvtk.api import tvtk
# fix incorrect order in foregroud objects
os.environ['ETS_TOOLKIT'] = 'qt4'
os.environ['QT_API'] = 'pyqt'
from mayavi import mlab
def plot_cell(cell, mlab):
for nr, i in enumerate(cell):
coord = np.zeros((4, 3), dtype=float)
coord[1] = i
for nr2, j in enumerate(cell):
if nr == nr2:
continue
coord[2] = i + j
for nr3, k in enumerate(cell):
if nr3 == nr or nr3 == nr2:
continue
coord[3] = i + j + k
mlab.plot3d(*coord.T, color=(0, 0, 0), line_width=0.01)
scaled_coord = [np.linspace(0, 1, 20, endpoint=False) for i in range(3)]
ABC = np.array(np.meshgrid(*scaled_coord, indexing="ij"))
data = np.sin(2*np.pi*ABC[0])*np.sin(2*np.pi*ABC[1])*np.sin(2*np.pi*ABC[2])
# transform to cartesian coordinates
cell = np.array(
[[ 1. , 0. , 0. ],
[-0.5 , 0.87, 0. ],
[ 0. , 0. , 3.07]])
transformation_matrix = cell.T
x, y, z = np.einsum('ij,jabc->iabc', transformation_matrix, ABC)
def generate_structured_grid(x, y, z, scalars):
pts = np.empty(z.shape + (3,), dtype=float)
pts[..., 0] = x
pts[..., 1] = y
pts[..., 2] = z
pts = pts.transpose(2, 1, 0, 3).copy()
pts.shape = int(pts.size / 3), 3
scalars = scalars.T.copy()
sg = tvtk.StructuredGrid(dimensions=x.shape, points=pts)
sg.point_data.scalars = scalars.ravel()
sg.point_data.scalars.name = 'scalars'
return sg
sgrid = generate_structured_grid(x, y, z, data)
src = mlab.pipeline.add_dataset(sgrid)
isosurface = mlab.pipeline.iso_surface(src)
plot_cell(cell, mlab)
mlab.show()
I want to render a volume in matplotlib. The volume is a simple 7x7x7 cube, and I want to be able to see all internal voxels (even though I know it will look like a mess).
I've been able to render voxels with transparency, but any voxel not on the surface seems to never be drawn.
Each 7x7 slice of the volume should look like this:
I've thrown together a MWE
The following code creates a 5x5x5 volume with a red,green,blue,yellow, and cyan 5x5 layers. The alpha of each layer is set to .5, so the whole thing should be see-through.
Then I chang the colors of all non-surface voxels to black with alpha 1, so if they were showing we should be able to see a black box in the center.
Rendering it by itself produces the figure on the left, but if we remove the fill from the cyan layer, we can see that the black box does indeed exist, it is just not being shown because it is 100% occluded even though those occluding voxels have alpha less than 1.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # NOQA
spatial_axes = [5, 5, 5]
filled = np.ones(spatial_axes, dtype=np.bool)
colors = np.empty(spatial_axes + [4], dtype=np.float32)
alpha = .5
colors[0] = [1, 0, 0, alpha]
colors[1] = [0, 1, 0, alpha]
colors[2] = [0, 0, 1, alpha]
colors[3] = [1, 1, 0, alpha]
colors[4] = [0, 1, 1, alpha]
# set all internal colors to black with alpha=1
colors[1:-1, 1:-1, 1:-1, 0:3] = 0
colors[1:-1, 1:-1, 1:-1, 3] = 1
fig = plt.figure()
ax = fig.add_subplot('111', projection='3d')
ax.voxels(filled, facecolors=colors, edgecolors='k')
fig = plt.figure()
ax = fig.add_subplot('111', projection='3d')
filled[-1] = False
ax.voxels(filled, facecolors=colors, edgecolors='k')
Is there any way to render all occluded voxels?
To turn my comments above into an answer:
You may always just plot all voxels as in
Representing voxels with matplotlib
3D discrete heatmap in matplotlib
The official example solves this problem by offsettingt the faces of the voxels by a bit, such they are all drawn.
This matplotlib issue discusses the missing faces on internal cubes. There is a pull request which has some issues still and it hence not merged yet.
Despite the small issues, you may monkey patch the current status of the pull request into your code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D, art3d # NOQA
from matplotlib.cbook import _backports
from collections import defaultdict
import types
def voxels(self, *args, **kwargs):
if len(args) >= 3:
# underscores indicate position only
def voxels(__x, __y, __z, filled, **kwargs):
return (__x, __y, __z), filled, kwargs
else:
def voxels(filled, **kwargs):
return None, filled, kwargs
xyz, filled, kwargs = voxels(*args, **kwargs)
# check dimensions
if filled.ndim != 3:
raise ValueError("Argument filled must be 3-dimensional")
size = np.array(filled.shape, dtype=np.intp)
# check xyz coordinates, which are one larger than the filled shape
coord_shape = tuple(size + 1)
if xyz is None:
x, y, z = np.indices(coord_shape)
else:
x, y, z = (_backports.broadcast_to(c, coord_shape) for c in xyz)
def _broadcast_color_arg(color, name):
if np.ndim(color) in (0, 1):
# single color, like "red" or [1, 0, 0]
return _backports.broadcast_to(
color, filled.shape + np.shape(color))
elif np.ndim(color) in (3, 4):
# 3D array of strings, or 4D array with last axis rgb
if np.shape(color)[:3] != filled.shape:
raise ValueError(
"When multidimensional, {} must match the shape of "
"filled".format(name))
return color
else:
raise ValueError("Invalid {} argument".format(name))
# intercept the facecolors, handling defaults and broacasting
facecolors = kwargs.pop('facecolors', None)
if facecolors is None:
facecolors = self._get_patches_for_fill.get_next_color()
facecolors = _broadcast_color_arg(facecolors, 'facecolors')
# broadcast but no default on edgecolors
edgecolors = kwargs.pop('edgecolors', None)
edgecolors = _broadcast_color_arg(edgecolors, 'edgecolors')
# include possibly occluded internal faces or not
internal_faces = kwargs.pop('internal_faces', False)
# always scale to the full array, even if the data is only in the center
self.auto_scale_xyz(x, y, z)
# points lying on corners of a square
square = np.array([
[0, 0, 0],
[0, 1, 0],
[1, 1, 0],
[1, 0, 0]
], dtype=np.intp)
voxel_faces = defaultdict(list)
def permutation_matrices(n):
""" Generator of cyclic permutation matices """
mat = np.eye(n, dtype=np.intp)
for i in range(n):
yield mat
mat = np.roll(mat, 1, axis=0)
for permute in permutation_matrices(3):
pc, qc, rc = permute.T.dot(size)
pinds = np.arange(pc)
qinds = np.arange(qc)
rinds = np.arange(rc)
square_rot = square.dot(permute.T)
for p in pinds:
for q in qinds:
p0 = permute.dot([p, q, 0])
i0 = tuple(p0)
if filled[i0]:
voxel_faces[i0].append(p0 + square_rot)
# draw middle faces
for r1, r2 in zip(rinds[:-1], rinds[1:]):
p1 = permute.dot([p, q, r1])
p2 = permute.dot([p, q, r2])
i1 = tuple(p1)
i2 = tuple(p2)
if filled[i1] and (internal_faces or not filled[i2]):
voxel_faces[i1].append(p2 + square_rot)
elif (internal_faces or not filled[i1]) and filled[i2]:
voxel_faces[i2].append(p2 + square_rot)
# draw upper faces
pk = permute.dot([p, q, rc-1])
pk2 = permute.dot([p, q, rc])
ik = tuple(pk)
if filled[ik]:
voxel_faces[ik].append(pk2 + square_rot)
# iterate over the faces, and generate a Poly3DCollection for each voxel
polygons = {}
for coord, faces_inds in voxel_faces.items():
# convert indices into 3D positions
if xyz is None:
faces = faces_inds
else:
faces = []
for face_inds in faces_inds:
ind = face_inds[:, 0], face_inds[:, 1], face_inds[:, 2]
face = np.empty(face_inds.shape)
face[:, 0] = x[ind]
face[:, 1] = y[ind]
face[:, 2] = z[ind]
faces.append(face)
poly = art3d.Poly3DCollection(faces,
facecolors=facecolors[coord],
edgecolors=edgecolors[coord],
**kwargs
)
self.add_collection3d(poly)
polygons[coord] = poly
return polygons
spatial_axes = [5, 5, 5]
filled = np.ones(spatial_axes, dtype=np.bool)
colors = np.empty(spatial_axes + [4], dtype=np.float32)
alpha = .5
colors[0] = [1, 0, 0, alpha]
colors[1] = [0, 1, 0, alpha]
colors[2] = [0, 0, 1, alpha]
colors[3] = [1, 1, 0, alpha]
colors[4] = [0, 1, 1, alpha]
# set all internal colors to black with alpha=1
colors[1:-1, 1:-1, 1:-1, 0:3] = 0
colors[1:-1, 1:-1, 1:-1, 3] = 1
fig = plt.figure()
ax = fig.add_subplot('111', projection='3d')
ax.voxels = types.MethodType(voxels, ax)
ax.voxels(filled, facecolors=colors, edgecolors='k',internal_faces=True)
fig = plt.figure()
ax = fig.add_subplot('111', projection='3d')
ax.voxels = types.MethodType(voxels, ax)
filled[-1] = False
ax.voxels(filled, facecolors=colors, edgecolors='k',internal_faces=True)
plt.show()
I am doing a cubic spline interpolation using scipy.interpolate.splrep as following:
import numpy as np
import scipy.interpolate
x = np.linspace(0, 10, 10)
y = np.sin(x)
tck = scipy.interpolate.splrep(x, y, task=0, s=0)
F = scipy.interpolate.PPoly.from_spline(tck)
I print t and c:
print F.x
array([ 0. , 0. , 0. , 0. ,
2.22222222, 3.33333333, 4.44444444, 5.55555556,
6.66666667, 7.77777778, 10. , 10. ,
10. , 10. ])
print F.c
array([[ -1.82100357e-02, -1.82100357e-02, -1.82100357e-02,
-1.82100357e-02, 1.72952212e-01, 1.26008293e-01,
-4.93704109e-02, -1.71230879e-01, -1.08680287e-01,
1.00658224e-01, 1.00658224e-01, 1.00658224e-01,
1.00658224e-01],
[ -3.43151441e-01, -3.43151441e-01, -3.43151441e-01,
-3.43151441e-01, -4.64551679e-01, 1.11955696e-01,
5.31983340e-01, 3.67415303e-01, -2.03354294e-01,
-5.65621916e-01, 1.05432909e-01, 1.05432909e-01,
1.05432909e-01],
[ 1.21033389e+00, 1.21033389e+00, 1.21033389e+00,
1.21033389e+00, -5.84561936e-01, -9.76335250e-01,
-2.60847433e-01, 7.38484392e-01, 9.20774403e-01,
6.63563923e-02, -9.56285846e-01, -9.56285846e-01,
-9.56285846e-01],
[ -4.94881722e-18, -4.94881722e-18, -4.94881722e-18,
-4.94881722e-18, 7.95220057e-01, -1.90567963e-01,
-9.64317117e-01, -6.65101515e-01, 3.74151231e-01,
9.97097891e-01, -5.44021111e-01, -5.44021111e-01,
-5.44021111e-01]])
So I had supplied the x array as :
array([ 0. , 1.11111111, 2.22222222, 3.33333333,
4.44444444, 5.55555556, 6.66666667, 7.77777778,
8.88888889, 10. ])
Q.1: The F.x (knots) are not the same as original x array and has duplicate values (possibly to force first derivative to zero?). Also some values in x (1.11111111, 8.88888889) are missing in F.x. Any ideas?
Q.2 The shape of F.c is (4, 13). I understand that 4 comes from the fact that it is cubic spline fit. But I do not know how do I select coefficients for each of the 9 sections that I want (from x = 0 to x=1.11111, x = 1.111111 to x = 2.222222 and so on). Any help in extraction of the coefficients for different segments would be appreciated.
If you want to have the knots in specific locations along the curves you need to use the argument task=-1 of splrep and give an array of interior knots as the t argument.
The knots in t must satisfy the following condition:
If provided, knots t must satisfy the Schoenberg-Whitney conditions, i.e., there must be a subset of data points x[j] such that t[j] < x[j] < t[j+k+1], for j=0, 1,...,n-k-2.
See the documentation here.
Then you should get F.c of the following size (4, <length of t> + 2*(k+1)-1) corresponding to the consecutive intervals along the curve (k+1 knots are added at either end of the curve by splrep).
Try the following:
import numpy as np
import scipy.interpolate
x = np.linspace(0, 10, 20)
y = np.sin(x)
t = np.linspace(0, 10, 10)
tck = scipy.interpolate.splrep(x, y, t=t[1:-1])
F = scipy.interpolate.PPoly.from_spline(tck)
print(F.x)
print(F.c)
# Accessing coeffs of nth segment: index = k + n - 1
# Eg. for second segment:
print(F.c[:,4])
I am trying to get the rasterized line data from a pylab plot function. My code is like so:
fitfunc = lambda p, x: p[0] + p[1] * sin(2 * pi * x / data[head[0]].size + p[2])
errfunc = lambda p, x, y: fitfunc(p, x) - y
data = np.genfromtxt(dataFileName, dtype=None, delimiter='\t', names=True)
xAxisSeries =linspace(0., data[head[0]].max(), data[head[0]].size)
p0 = [489., 1000., 9000.] # Initial guess for the parameters
p1, success = optimize.leastsq(errfunc, p0[:], args=(xAxisSeries, data[head[1]]))
time = linspace(xAxisSeries.min(), xAxisSeries.max(), 1000)
plotinfo = plot(time, fitfunc(p1, time), 'r-')
I want to get the x and y line data from plotinfo. When I use "type(plotinfo)," plotinfo is a list, but when using "print plotinfo," it is a 2dlist object.
import numpy as np
import matplotlib.pyplot as plt
N=4
x=np.linspace(0, 10, N)
y=np.cumsum(np.random.random(N) - 0.5)
line=plt.plot(x,y)[0]
path=line._path
These are the original (x,y) data points:
print(path.vertices)
# [[ 0. 0.08426592]
# [ 3.33333333 0.14204252]
# [ 6.66666667 0.41860647]
# [ 10. 0.22516175]]
Here we (linearly) interpolate to find additional points. You can increase the argument to path.interpolated to find more interpolated points between the original points.
path2=path.interpolated(2)
print(path2.vertices)
# [[ 0. 0.08426592]
# [ 1.66666667 0.11315422]
# [ 3.33333333 0.14204252]
# [ 5. 0.2803245 ]
# [ 6.66666667 0.41860647]
# [ 8.33333333 0.32188411]
# [ 10. 0.22516175]]