Integrate over 2d polygon quadpy - python

I am trying to integrate a function on a 2d polygon described by its vertices as follow
import numpy as np
import quadpy
def f(x):
return x[0]
poly = np.array([[0.0, 0.0], [1.0, 0.0], [0, 1], [1,1]])
scheme = quadpy.t2.get_good_scheme(10)
val = scheme.integrate(f, poly)
But I get
QuadpyError: Wrong domain shape.
I really appreciate any kind of help

quad.t2 is for triangles, three points are expected. Your polygon is a square, you have to use quad.c2.
import quadpy
scheme = quadpy.c2.get_good_scheme(7)
val = scheme.integrate(
lambda x : x[0],
[ [[0.0, 0.0], [1.0, 0.0]], [[0.0, 1.0], [1.0, 1.0]] ]
)
val
This gives 0.5, which is easy to get mathematically.
See the link for the way to specify the quadrilateral.

Related

Difference between SimpleITK.Euler3DTransform and scipy.spatial.transform.Rotation.from_euler?

Using these two library functions:
SimpleITK.Euler3DTransform
scipy.spatial.transform.Rotation.from_euler
to create a simple rotation matrix from Euler Angles:
import numpy as np
import SimpleITK as sitk
from scipy.spatial.transform import Rotation
from math import pi
euler_angles = [pi / 10, pi / 18, pi / 36]
sitk_matrix = sitk.Euler3DTransform((0, 0, 0), *euler_angles).GetMatrix()
sitk_matrix = np.array(sitk_matrix).reshape((3,3))
print(np.array_str(sitk_matrix, precision=3, suppress_small=True))
order = 'XYZ' # Different results for any order in ['XYZ','XZY','YZX','YXZ','ZXY','ZYX','xyz','xzy','yzx','yxz','zxy','zyx']
scipy_matrix = Rotation.from_euler(order, euler_angles).as_matrix()
print(np.array_str(scipy_matrix, precision=3, suppress_small=True))
I get two different results:
[[ 0.976 -0.083 0.2 ]
[ 0.139 0.947 -0.288]
[-0.165 0.309 0.937]]
[[ 0.981 -0.086 0.174]
[ 0.136 0.943 -0.304]
[-0.138 0.322 0.937]]
Why? How can I compute the same matrix as SimpleITK using scipy?
The issue is that the itk.Euler3DTransform class by default applies the rotation matrix multiplications in Z # X # Y order and the Rotation.from_euler function in Z # Y # X order.
Note that this is independent of the order you specified. The order you specify refers to the order of the angles, not the order of the matrix multiplications.
If you are using the itk.Euler3DTransform directly as you showed in your example, you can actually change the default behavior for itk to perform the matrix multiplication in Z # Y # X order.
I never worked with sitk but in theory and based on the documentation, something like this should work:
euler_transform = sitk.Euler3DTransform((0, 0, 0), *euler_angles)
euler_transform.SetComputeZYX(True)
sitk_matrix = euler_transform.GetMatrix()
Alternatively, I wrote a function which is similar to Rotation.from_euler but has the option to specify the rotation order as well:
def build_rotation_3d(radians: NDArray,
radians_oder: str = 'XYZ',
rotation_order: str = 'ZYX',
dims: List[str] = ['X', 'Y', 'Z']) -> NDArray:
x_rad, y_rad, z_rad = radians[(np.searchsorted(dims, list(radians_oder)))]
x_cos, y_cos, z_cos = np.cos([x_rad, y_rad, z_rad], dtype=np.float64)
x_sin, y_sin, z_sin = np.sin([x_rad, y_rad, z_rad], dtype=np.float64)
x_rot = np.asarray([
[1.0, 0.0, 0.0, 0.0],
[0.0, x_cos, -x_sin, 0.0],
[0.0, x_sin, x_cos, 0.0],
[0.0, 0.0, 0.0, 1.0],
])
y_rot = np.asarray([
[y_cos, 0.0, y_sin, 0.0],
[0.0, 1.0, 0.0, 0.0],
[-y_sin, 0.0, y_cos, 0.0],
[0.0, 0.0, 0.0, 1.0],
])
z_rot = np.asarray([
[z_cos, -z_sin, 0.0, 0.0],
[z_sin, z_cos, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
])
rotations = np.asarray([x_rot, y_rot, z_rot])[(np.searchsorted(dims, list(rotation_order)))]
return rotations[0] # rotations[1] # rotations[2]
What is your 'order' string. When I ran your code with order='xyz', I get the same results for SimpleITK and scipy's Rotation.

Hausdorff Distance 2D

i am new to programming and currently working with Python. Can someone explain to me why is it that by changing the order of variable will end up with different results as compared to Euclidean distance obtaining the same results?
Below is the array i used for this experiment to understand the use
u = np.array([[1.0, 0.0], [0.0, 1.0], [-1.0, 0.0], [0.0, -1.0]])
v = np.array([[2.0, 0.0], [0.0, 2.0], [-2.0, 0.0], [0.0, -4.0]])
(directed_hausdorff(u, v)[:])) --> output = (2.23606797749979, 3, 0) and
(directed_hausdorff(v, u)[:])) --> output = v,u = (3.0, 3, 3)
Thank you!

scipy.optimize, IndexError: Invalid Index to Scalar Variable

I am trying to implement scipy.optimmize.minimize on a multivariate scalar function using the nelder-mead method. My function definition when called in a print function works perfectly fine. When I turn on minimize it throws the IndexError.
from scipy.optimize import minimize
import math
import numpy as np
c_ = [1.,1.,1.]
d_ = [1.,1.,1.]
x_=[c_,d_]
def hamiltonian(x_):
N=len(c_)
return np.sum([(1/n**3.0)*(n-i)*i*(x_[0][(n-i)]*x_[0][i]+x_[1][(n-i)]*x_[1][i])-(1/n**3.0/alpha**2.0)*np.sum([x_[0][(n-i-j)]*x_[0][i]*x_[1][j] for j in range(0,(n-i+1))]) for n in range(1,N) for i in range(0,(n+1))])
print hamiltonian(x_) #no problem here
res = minimize(hamiltonian, x_, method='nelder-mead') #problem here
That is because x_ is a list of lists:
>>> x_
[[1.0, 1.0, 1.0], [1.0, 1.0, 1.0]]
Thus replace the line x_=[c_,d_] with:
>>> x_ = c_ + d_
You'll also have to modify your hamiltonian for a 1xN or Nx1 list/array.
The simplest hack that I can think of is:
def hamiltonian(x_):
N=len(c_)
if type(x_[0]) == np.array:
x_ = np.concatenate((x_[0:N], x_[N:]), axis=0)
return np.sum([(1/n**3.0)*(n-i)*i*(x_[0][(n-i)]*x_[0][i]+x_[1][(n-i)]*x_[1][i])-(1/n**3.0/alpha**2.0)*np.sum([x_[0][(n-i-j)]*x_[0][i]*x_[1][j] for j in range(0,(n-i+1))]) for n in range(1,N) for i in range(0,(n+1))])

Python: Creating nested lists of floats using a for loop

I am working with a list of points [(1,2),(3,4),(5,6),(7,8)]. I want to find the euclidean distance from each point to every other point in the list.
I then need a new list created to represent each point in the original list, and in the new list I will add the distances relating to that point only.
So far I have:
for i in mat_ary1:
points_dist_i = []
for j in i:
row = []
x2 = [u[0] for u in i]
y2 = [u[1] for u in i]
# Calculate the distance from point j to all others
for a in x2:
dist_x_1 = pow((a - j[0]),2)
for b in y2:
dist_y_1 = pow((b - j[1]),2)
dist_xy_1 = float('{0:.2f}'.format((math.sqrt(dist_x_1 + dist_y_1))))
for item in j:
if item not in row:
row.append(dist_xy_1)
else:
continue
points_dist_i.append(row)
Each i in mat_ary1 represents a list of points. With the loops I am using I appear to repeating the same calculations.
My input seems to be duplicating the rows:
[[6.32, 6.32], [6.32, 6.32], [0.0, 0.0], [0.0, 0.0]]
[[11.4, 11.4], [11.4, 11.4], [0.0, 0.0], [0.0, 0.0]]
[[16.49, 16.49], [16.49, 16.49], [0.0, 0.0], [0.0, 0.0]]
[[14.32, 14.32], [14.32, 14.32], [0.0, 0.0], [0.0, 0.0]]
[[13.0, 13.0], [13.0, 13.0], [0.0, 0.0], [0.0, 0.0]]
[[11.66, 11.66], [11.66, 11.66], [0.0, 0.0], [0.0, 0.0]]
You can use the following nested list comprehension
>>> import math
>>> [[math.hypot(point[0]-x, point[1]-y) for x,y in points] for point in points]
[[0.0, 2.8284271247461903, 5.656854249492381, 8.48528137423857],
[2.8284271247461903, 0.0, 2.8284271247461903, 5.656854249492381],
[5.656854249492381, 2.8284271247461903, 0.0, 2.8284271247461903],
[8.48528137423857, 5.656854249492381, 2.8284271247461903, 0.0]]
This essentially makes a matrix with the distance from one point to any other point, where the row and column indexes are the "from" and "to" points, in which case the matrix will also be symmetric about the diagonal, and the diagonal will be all zeros.
Scikit-learn has a function for this exact problem, and it will probably be the fastest implementation if your array is large.
>>>>from sklearn.metrics.pairwise import pairwise_distances
>>>>pairwise_distances(mat_ary1)
array([[ 0. , 2.82842712, 5.65685425, 8.48528137],
[ 2.82842712, 0. , 2.82842712, 5.65685425],
[ 5.65685425, 2.82842712, 0. , 2.82842712],
[ 8.48528137, 5.65685425, 2.82842712, 0. ]])

Trouble rendering box from index buffer with PyOpenGL

I'm trying to work through the beginning of the OpenGL redbook for version 2.1 and translate what I learn to the PyOpenGL binding while using Qt for the windowing framework. For some reason though, I can't seem to get my call to glDrawElements() to actually draw anything to the screen. Here are the relevant functions I have so far.
def initializeGL(self):
self.qglClearColor(QtGui.QColor(0,0,150))
self.initGeometry()
GL.glEnable(GL.GL_DEPTH_TEST)
self.buffers = GL.glGenBuffers(2)
def paintGL(self):
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
GL.glLoadIdentity()
GL.glTranslate(0.0, 0.0, -50.0)
GL.glScale(20.0, 20.0, 20.0)
GL.glRotate(self.yRotDeg, 0.2, 1.0, 0.3)
GL.glTranslate(-0.5, -0.5, -0.5)
VERTICES = 0
INDICES = 1
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.buffers[VERTICES])
GL.glBufferData(GL.GL_ARRAY_BUFFER, len(self.cubeVtxArray), self.cubeVtxArray, GL.GL_STATIC_DRAW)
offset = ctypes.c_void_p(0)
GL.glVertexPointer(3, GL.GL_FLOAT, 0, offset)
#GL.glVertexPointerf(self.cubeVtxArray)
GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, self.buffers[INDICES])
GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, len(self.cubeIdxArray), self.cubeIdxArray, GL.GL_STATIC_DRAW)
GL.glDrawElements(GL.GL_QUADS, 24, GL.GL_UNSIGNED_BYTE, offset)
#GL.glDrawArrays(GL.GL_QUADS, 0, 24)
def initGeometry(self):
self.cubeVtxArray = np.array(
[[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[1.0, 1.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0],
[1.0, 0.0, 1.0],
[1.0, 1.0, 1.0],
[0.0, 1.0, 1.0]], dtype=np.float32)
self.cubeIdxArray = np.array([
0, 1, 2, 3,
3, 2, 6, 7,
1, 0, 4, 5,
2, 1, 5, 6,
0, 3, 7, 4,
7, 6, 5, 4], dtype=np.uint8)
When I run the program, it does clear the screen to the correct color, but the cube isn't drawn. Interestingly, if I try and render using the glDrawArray() function, it does render (although it doesn't look like a cube since it's rendering the indices). What might be going wrong here?
EDIT:
Here are a couple videos of the results of glDrawElements() and glDrawArrays().
EDIT2:
My problem (as user1118321 pointed out) was that I was passing an array length as the second parameter to glBufferData() where I should have been passing a size in bytes. The solution for python is:
from OpenGL.arrays.arraydatatype import ArrayDatatype
Use ArrayDatatype.arrayByteCount(self.cubeVtxArray) as the second parameter to glBufferData() (and similarly for any other buffers).
EDIT 3:
I'd actually like to make one more edit to this since I just ended up with another related problem from my calls to glBufferData(). I thought naively that I should also be able to use sys.getsizeof() in the same way as ArrayDatatype.arrayByteCount(). This is not the case though if your buffer data is a numpy array as I ended up using. sys.getsizeof() returns the wrong size and will inadvertently chop your array a bit. Goodbye three days of my life....
One thing that looks wrong to me is that you're sending the array size as the second argument to glBufferData. You probably need to send the number of bytes of the data as that argument. So it would be something like:
len(self.cubeVtxArray) * numBytesPerElement
where numBytesPerElement would be 4 bytes per float times 3 floats per vertex = 12 bytes.
In Python, you can get the number of bytes in an array by doing the following:
from OpenGL.arrays.arraydatatype import ArrayDatatype
Use ArrayDatatype.arrayByteCount(self.cubeVtxArray) as the second parameter to glBufferData() (and similarly for any other buffers).
And you'll need to do the same thing for self.cubeIdxArray, though the numBytesPerElement will be 1 in that case.

Categories