Faster alternative to itertools.product - python

Is there a faster way to get all coordinate combinations for x, y, z than itertools.product?. For an example I have the ranges: x: 10-310, y: 10-310 and z: 0-65.
EDIT
For example i have to put all cordinates in a polydata like here:
points1 = vtk.vtkPoints()
for coords in itertools.product(x1,y1,z1):
points1.InsertNextPoint(coords)
boxPolyData1 = vtk.vtkPolyData()
boxPolyData1.SetPoints(points1)

Use np.mgrid:
import numpy as np
x, y, z = np.mgrid[10:311, 10:311, 0:66]
I assumed you wanted the end points 310 and 65 inclusive.

Related

Python 2D self-avoiding random walk

I want to make a self-avoiding 2D random walk in python. Imagine it like the dot is on the square grid and it can only go up, down, left or right but it cannot land twice on the same point. I have an idea how to do it, but my programming skills aren't very good (I'm a beginner) and the code doesn't work.
The end product should look something like this:
enter image description here
My idea was to create two lists: one where I store x and y (i.e. the coordinates I've already been to) and one with the points that are around the point I'm currently at (I marked it as neighbors). I want to create a new variable surviving_neighbors. This would be a list of coordinates of the surrounding points where I have not yet been to (e.g. I am currently at (1,1); I have already been at (0,1) and (1,2) so that my surviving neighbors would be (1,0 ) and (2,1)). I want to get Surviving_neighbors using the difference method: I put neighbors.difference(list of coordinates) and save in a variable what is in the list of neighbors, but not in the list of coordinates I was on. The first problem I have is that I don't have one list with coordinates, but x and y are stored separately. Next, I would use choice(surviving_neighbors) and thus choose new coordinates. This creates another problem: I probably won't be able to call it a trajectory, but I'll have to define it again in terms of x and y...
The teacher suggested that I store x and y as vectors, but I have no idea how to do that.
Code:
from random import choice
import numpy as np
from matplotlib import pyplot as plt
plt.style.use(['science', 'notebook', 'dark background'])
x, y = 0, 0
coordinates = [(x, y)]
for time in range(10):
dx, dy = choice([(0, 1), (-1, 0), (0, 1), (0, -1)])
x, y = x + dx, y + dy
X.append(x)
Y.append(y)
neighbors = [x+1, y
x-1
y
x, y+1
x, y-1]
surviving_neighbors = neighbors.difference(X, Y)
trajectory = choice(surviving_neighbors)
plt.plot()
Hard to know where you are going with this, here is a basic working example;
This is invalid as they don't exist;
plt.style.use(['science', 'notebook', 'dark background'])
Possible values are;
['Solarize_Light2', '_classic_test_patch', '_mpl-gallery',
'_mpl-gallery-nogrid', 'bmh', 'classic', 'dark_background', 'fast',
'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn-v0_8',
'seaborn-v0_8-bright', 'seaborn-v0_8-colorblind', 'seaborn-v0_8-dark',
'seaborn-v0_8-dark-palette', 'seaborn-v0_8-darkgrid',
'seaborn-v0_8-deep', 'seaborn-v0_8-muted', 'seaborn-v0_8-notebook',
'seaborn-v0_8-paper', 'seaborn-v0_8-pastel', 'seaborn-v0_8-poster',
'seaborn-v0_8-talk', 'seaborn-v0_8-ticks', 'seaborn-v0_8-white',
'seaborn-v0_8-whitegrid', 'tableau-colorblind10']
from random import choice
from matplotlib import pyplot as plt
plt.style.use('seaborn-v0_8-darkgrid')
print(plt.style.available)
#2D self-avoiding random walk
def dotty(n):
x, y = 0, 0
path = [(x, y)]
for i in range(n):
# pick the closest point but it must complete without crossing itself
x, y = choice([(x+1, y), (x-1, y), (x, y+1), (x, y-1)])
if (x, y) in path:
return path
path.append((x, y))
return path
# show plot
def show_path(path):
plt.figure(figsize=(10, 10))
# draw points
plt.scatter(*zip(*path), s=5, c='k')
# draw lines in red
plt.plot(*zip(*path), c='r')
plt.show()
# main
if __name__ == '__main__':
path = dotty(100000)
show_path(path)
Output:

contour graph tuple index out of range

I'm trying to use the contour function of matplotlib.pyplot. I get an error tuple index out of range.
import numpy as np
from sklearn.datasets import make_regression
import matplotlib.pyplot as plt
import math
x, y = make_regression(n_samples=100, n_features=1, noise=10)
y = y + abs(y/2)
thetaInitial = np.random.randn(3,1)
thetaFinal = np.random.randn(3,1)
def f(x): return x**2+x
xmesh, ymesh = np.meshgrid(x, y)
print("x :", xmesh.shape); print("y :", ymesh.shape); print("z: ", z.shape)
z = f(np.array([xmesh, ymesh]))
plt.contour(X=xmesh, Y=ymesh, Z= z, levels=20)
­
tuple index out of range
There are a few problems that need to be addressed:
Please, read the documentation to obtain contour plots with `help(plt.contour).
from the docs, you'll see that x, y needs to be monotonically sorted. You can achieve that with np.sort(x.reshape(len(x))).
You evaluated your function with z = f(np.array([xmesh, ymesh])), obtaining an array with shape (2, 100, 100). From the docs, Z must be a 2D array. So you have to execute plt.contour(X=xmesh, Y=ymesh, Z=z[0]) or z[1].

pyplot, plotting from left to right

I have some data I want to plot, x and y is in the same format as this small piece of example code.
import matplotlib.pyplot as plt
y = [1,1,3,4]
x = [1,4,2,3]
plt.plot(x,y,'-o')
plt.show()
This results in quite a weird graph.
What pyplot does is drawing a line from the first point inserted to the second, then to the third etc.
I want it to draw a line from low-x to high-x, but I can seem to find a nice way to do this. I want my line to be like this.
What is the easiest way to achieve this, given my x and y data is in the same format but more complex than this example?
To get the graph as you mentioned, you need to have values in x in sorted order, which you can achieve like this:
z = sorted(zip(x,y))
x=[i[0] for i in z]
y=[i[1] for i in z]
and now using x and y for ploting (not tested).
you can sort your x list with simultaneously changing the y,
import matplotlib.pyplot as plt
y = [1,1,3,4]
x = [1,4,2,3]
for i in range(len(x)):
for k in range( len( x ) - 1, i, -1 ):
if ( x[k] < x[k - 1] ):
x[k-1],x[k]=x[k],x[k-1]
y[k-1],y[k]= y[k],y[k-1]
print x,y
plt.plot(x,y,'-o')
plt.show()

Correct usage of scipy.interpolate.RegularGridInterpolator

I am a little confused by the documentation for scipy.interpolate.RegularGridInterpolator.
Say for instance I have a function f: R^3 => R which is sampled on the vertices of the unit cube. I would like to interpolate so as to find values inside the cube.
import numpy as np
# Grid points / sample locations
X = np.array([[0,0,0], [0,0,1], [0,1,0], [0,1,1], [1,0,0], [1,0,1], [1,1,0], [1,1,1.]])
# Function values at the grid points
F = np.random.rand(8)
Now, RegularGridInterpolator takes a points argument, and a values argument.
points : tuple of ndarray of float, with shapes (m1, ), ..., (mn, )
The points defining the regular grid in n dimensions.
values : array_like, shape (m1, ..., mn, ...)
The data on the regular grid in n dimensions.
I interpret this as being able to call as such:
import scipy.interpolate as irp
rgi = irp.RegularGridInterpolator(X, F)
However, when I do so, I get the following error:
ValueError: There are 8 point arrays, but values has 1 dimensions
What am I misinterpreting in the docs?
Ok I feel silly when I answer my own question, but I found my mistake with help from the documentation of the original regulargrid lib:
https://github.com/JohannesBuchner/regulargrid
points should be a list of arrays that specifies how the points are spaced along each axis.
For example, to take the unit cube as above, I should set:
pts = ( np.array([0,1.]), )*3
or if I had data which was sampled at higher resolution along the last axis, I might set:
pts = ( np.array([0,1.]), np.array([0,1.]), np.array([0,0.5,1.]) )
Finally, values has to be of shape corresponding to the grid laid out implicitly by points. For example,
val_size = map(lambda q: q.shape[0], pts)
vals = np.zeros( val_size )
# make an arbitrary function to test:
func = lambda pt: (pt**2).sum()
# collect func's values at grid pts
for i in range(pts[0].shape[0]):
for j in range(pts[1].shape[0]):
for k in range(pts[2].shape[0]):
vals[i,j,k] = func(np.array([pts[0][i], pts[1][j], pts[2][k]]))
So finally,
rgi = irp.RegularGridInterpolator(points=pts, values=vals)
runs and performs as desired.
Your answer is nicer, and it's perfectly OK for you to accept it. I'm just adding this as an "alternate" way to script it.
import numpy as np
import scipy.interpolate as spint
RGI = spint.RegularGridInterpolator
x = np.linspace(0, 1, 3) # or 0.5*np.arange(3.) works too
# populate the 3D array of values (re-using x because lazy)
X, Y, Z = np.meshgrid(x, x, x, indexing='ij')
vals = np.sin(X) + np.cos(Y) + np.tan(Z)
# make the interpolator, (list of 1D axes, values at all points)
rgi = RGI(points=[x, x, x], values=vals) # can also be [x]*3 or (x,)*3
tst = (0.47, 0.49, 0.53)
print rgi(tst)
print np.sin(tst[0]) + np.cos(tst[1]) + np.tan(tst[2])
returns:
1.93765972087
1.92113615659

Python scipy getting the results of Delaunay triangulation

I am using scipy.spatial.Delaunay to triangulate a cloud of 3D points.
Each point is imported in an array with the structure R, G, B, X, Y, Z, only the values X, Y, Z are used to triangulate.
I calculate the barycentric coordinates of a list of "target" points.
For each target, I'd like to get:
the R, G, B of each point of the simplex in which target is located.
the barycentric coordinates of target
I cannot figure out how to get these data with my code.
print bcoords works fine (it generates a series of 4 values for each target):
[[ 2.89657287e-01 3.98169955e-01 1.24220635e-01 1.87952122e-01]
[ 3.24695465e-01 3.99228351e-01 8.91849061e-02 1.86891278e-01]
[ 2.89657287e-01 3.98169955e-01 1.24220635e-01 1.87952122e-01]
...,
[ -1.13763739e+03 1.32600196e+03 2.61787735e+02 -4.49152304e+02]
[ -1.13764457e+03 1.32600118e+03 2.61796224e+02 -4.49152837e+02]
[ -1.13765132e+03 1.32600045e+03 2.61804205e+02 -4.49153338e+02]]
However, print tetrahedra generates a list of numbers:
[915 915 915 ..., -1 -1 -1]
And this list is a list of indices
How can I replace it with a list of vertices?
code:
import csv
import numpy as np
import scipy.spatial
points = np.array([(int(R), int(G), int(B), float(X), float(Y), float(Z))
for R, G, B, X, Y, Z in csv.reader(open('XYZcolorlist_D65.csv'))])
# load X,Y,Z coordinates of 'points' in a np.array
# alternative points = pd.read_csv('XYZcolorlist_D65.csv')
tri = scipy.spatial.Delaunay(points[:,[3,4,5]])
# do the triangulation
indices = tri.simplices
# indices of vertices
vertices = points[indices]
# the vertices for each tetrahedron
targets = np.array([(float(X), float(Y), float(Z))
for name, X, Y, Z, crap in csv.reader(open('targets.csv'))])
# load the XYZ target values in a np.array
tetrahedra = tri.find_simplex(targets)
# find which tetrahedron each point belong to
X = tri.transform[tetrahedra,:3]
Y = targets - tri.transform[tetrahedra,3]
b = np.einsum('ijk,ik->ij', X, Y)
bcoords = np.c_[b, 1 - b.sum(axis=1)]
# find the barycentric coordinates of each point
#np.savetxt('coords.out', bcoords, fmt="%f")
print points.shape
print indices.shape
print vertices.shape
print tetrahedra.shape
print bcoords.shape
print bcoords
print tetrahedra
print indices
print vertices

Categories

Resources