What is the cleanest way to get the view direction relative to your scene in vispy?
view.scene.transform contains a whole chain of transforms:
In [88]: view.scene.transform
Out[88]:
<ChainTransform [<STTransform scale=[ 960. -540. 1. 1.] translate=[ 960. 540. 0. 0.] at 0x139757309901840>,
MatrixTransform(matrix=[[26.44507, 0.0, 0.0, 0.0],
[0.0, 47.013458, 0.0, 0.0],
[0.0, 0.0, -1e-06, 0.0],
[-0.0, -0.0, -0.0, 1.0]] at 0x7f1bc8d526d0),
<Inverse of '<ChainTransform [MatrixTransform(matrix=[[0.64390097845776273, -0.18562251042644023, -0.74225050593726238, 0.0],\n [0.74851597030808681, 0.35377196489238, 0.56086472437650059, 0.0],\n [0.15847830177938896, -0.91672770247177038, 0.36673552784799862, 0.0],\n [0.002241050448888897, 0.013296952664039196, 0.015024409939918581, 1.0]] at 0x7f1bc8c81710)] at 0x7f1bc8cb7e90>'>] at 0x7f1bc8e75490>
I could write something to parse lists of transforms of varous types and compose them, and extract the view direction from the composed transform, but I suspect I'm swimming upstream.
Vispy transformations have a map and imap function you can use to map coordinates between scene and screen coordinates in either direction. I used them on points and threw in a lot of assertions to be safe; there are probably simpler implementations. I tested this for orthographic projection. I ~think it will work for perspective projections too as long as the center of projection is in the middle of the screen.
def get_view_direction_in_scene_coordinates(view):
import numpy
tform=view.scene.transform
w,h = view.canvas.size
screen_center = numpy.array([w/2,h/2,0,1]) # in homogeneous screen coordinates
d1 = numpy.array([0,0,1,0]) # in homogeneous screen coordinates
point_in_front_of_screen_center = screen_center + d1 # in homogeneous screen coordinates
p1 = tform.imap(point_in_front_of_screen_center) # in homogeneous scene coordinates
p0 = tform.imap(screen_center) # in homogeneous screen coordinates
assert(abs(p1[3]-1.0) < 1e-5) # normalization necessary before subtraction
assert(abs(p0[3]-1.0) < 1e-5)
d2 = p1 - p0 # in homogeneous screen coordinates
assert(abs(d2[3])< 1e-5)
d3 = d2[0:3] # in 3D screen coordinates
d4 = d3 / numpy.linalg.norm(d3)
return d4
Related
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.
I am trying to find the best curve that will describe my data. my data are stored in numpy arrays of t and dur they are both in values only from 0-1. However the best fit I get according to R**2 score is this yellow line with score of 0.979388 which doesn't fit my data because it is way off from expected values when it is well above 1 in Y axis:
t = [1.0, 1.0, 1.0, 1.0, 1.0, 0.33695652173913043, 0.010869565217391304, 1.0, 0.018518518518518517, 1.0, 1.0, 1.0, 1.0, 1.0, 0.005076142131979695, 1.0, 1.0, 1.0, 1.0, 0.03225806451612903, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.25, 1.0]
dur = [1.0, 1.0, 1.0, 1.0, 0.9999999999999998, 0.2688679245283018, 0.2688679245283018, 1.0, 0.46692607003891046, 1.0, 1.0, 1.0, 1.0, 1.0, 0.4444444444444444, 1.0, 1.0, 1.0, 1.0, 0.34210526315789475, 1.0, 1.0, 1.0, 1.0, 1.0, 0.4714285714285715, 0.4714285714285715, 1.0]
#polynomial curve fitting
mymodel1 = np.poly1d(np.polyfit(t, dur, 1))
mymodel2 = np.poly1d(np.polyfit(t, dur, 2))
mymodel3 = np.poly1d(np.polyfit(t, dur, 3))
mymodel4 = np.poly1d(np.polyfit(t, dur, 4))
#polynomial score
p1 = r2_score(dur, mymodel1(t))
p2 = r2_score(dur, mymodel2(t))
p3 = r2_score(dur, mymodel3(t))
p4 = r2_score(dur, mymodel4(t))
#append results of R**2 to list of tuples from which I extract best score
fit = []
fit.append(p1)
fit.append(p2)
fit.append(p3)
fit.append(p4)
fitname = []
fitname.append('p1')
fitname.append('p2')
fitname.append('p3')
fitname.append('p4')
#append best result value
resultValue.append(max(fitTuple,key=lambda item:item[0])[0])
#append best result name
resultName.append(max(fitTuple,key=lambda item:item[0])[1])
#plot values from regression models
myline = np.linspace(0, 1, 100)
plt.plot(myline, mymodel1(myline),color = "black")
plt.plot(myline, mymodel2(myline),color = "black")
plt.plot(myline, mymodel3(myline),color = "black")
plt.plot(myline, mymodel4(myline),color = "yellow")
This is what is called "overfitting". If you fit overly complex models to your data, the models will usually have very high R^2 and indeed meet the data points of the data you use for training quite well, but are clearly not the appropriate choice, as can be seen when trying to fit new data, e.g. they don't interpolate well. And fitting polynomials of high degree is usually taken as a standard example for overfitting.
If you want to stick with polynomial models, you should think about what the least complex model, i.e. in this case the lowest degree polynomial, is, that you would still think appropriate for your data. In your case, quadratic seems OK.
One usually employs more sophisticated methods for regression, like those provided in e.g. scikit learn, which can help you find the right model (e.g. via cross-validation) and also provide regularization techniques. For model selection, see here.
I am looking to do a reverse type of (numpy) interpolation.
Consider the case where I have a 'risk' value of 2.2, and that is mapped to this tenor-point value of 1.50.
Consider a have a tenor-list of list (or array) = [0.5, 1.0, 2.0, 3.0, 5.0].
Now, I would like to attribute this risk-value of 2.2 to what it would be, as mapped to the closest two tenor-points (in this case 1.0 and 2.0), in the form of a linear interpolation.
In this example, the function will generate the risk-value of 2.0, (which is mapped to expiry value of 1.50) to
for the 1.0 tenor point : of 2.2 * (1.5 - 1.0)/(2.0 - 1.0)
for the 2.0 tenor point : of 2.2 * (2.0 - 1.5)/(2.0 - 1.0)
Is there a numpy/scipy/panda or python code that would do this?
Thanks!
Well, I have attempted a bit of a different approach but maybe this helps you. I try to interpolate the points for the new grid points using interpolate.interp1d (with the option to extrapolate points fill_value="extrapolate") to extend the range beyond the interval given. In your first example the new points were always internal, in the comment example also external, so I used the more general case. This still might be polished, but should give an idea:
import numpy as np
from scipy import interpolate
def dist_val(vpt, arr):
dist = np.abs(arr-np.full_like(arr, vpt))
i0 = np.argmin(dist)
dist[i0] = np.max(dist) + 1
i1 = np.argmin(dist)
return (i0, i1)
def dstr_lin(ra, tnl, tnh):
'''returns a risk-array like ra for tnh based on tnl'''
if len(tnh) < len(tnl) or len(ra) != len(tnl):
return -1
rah = []
for vh in tnh:
try:
rah.append((vh, ra[tnl.index(vh)]))
except ValueError:
rah.append((vh, float(interpolate.interp1d(tnl, ra, fill_value="extrapolate")(vh))))
return rah
ra = [0.422, 1.053, 100.423, -99.53]
tn_low = [1.0, 2.0, 5.0, 10.0]
tn_high = [1.0, 2.0, 3.0, 5.0, 7.0, 10.0, 12.0, 15.0]
print(dstr_lin(ra, tn_low, tn_high))
this results in
[(1.0, 0.422), (2.0, 1.053), (3.0, 34.17633333333333), (5.0, 100.423), (7.0, 20.4418), (10.0, -99.53), (12.0, -179.51120000000003), (15.0, -299.483)]
Careful though, I am not sure how "well behaved" your data is, interpolation or extrapolation might swing out of range so use with care.
I need to integrate the area under a curve, but rather than integrating the entire area under the curve at once, I would like to integrate partial areas at a specified interval of 5m. I.e, I would like to know the area under the curve from 0-5m, 5 - 10m, 10 - 15m, etc.
However, the spacing between my x values is irregular (i.e., it does not go [1, 2, 3, 4...] but rather could go, [1, 1.2, 2, 2.3, 3.1, 4...]. So I can't go by index number but rather need to go by values, and I want to create intervals of every 5 meters.
# Here is a sample of the data set (which I do NOT use in the function below, just an example of how irregular the spacing between x values is)
x = [0, 1.0, 2.0, 3.0, 4.3, 5.0, 6.0, 7.0, 8.0, 9.0, 10, 12, 12.5, 12.7, 13, 14.5, 15, 15.5, 16, 16.5]
y = [0, -0.44, -0.83, -0.91, -1.10, -1.16, -1.00, -1.02, -1.05, -1.0, -0.94, - 0.89, -1, -1.39, -1.44, -1.88, -1.9, -1.94, -2.03, -1.9]
I've created a function to get the partial area based on one specific interval (5<x<10), but I need to figure out how to do this for the entire dataframe.
from scipy.integrate import simps
def partial_area (y, x):
x =df.query('5 <= X <= 10')['X']
y =df.query('5 <= X <= 10')['Z']
area = simps(y,x)
return (area)
area = partial_area(y,x)
I'm stuck on the best way to go about this, as I'm not sure how to create intervals by data values rather than index.
I'm trying to create a script for mirroring transforms across the yz plane in Maya.
I was able to set up a node network that gets the desired results. I took a node at the origin with sz set to -1 and a source node from the left side (lf_grp for this test), and fed their worldMatrix attrs into a multMatrix node. Then I passed the output (multMatrix.matrixSum) through a decompose matrix and into my destination node.
I'd really prefer to not create a bunch of nodes to do my mirroring - running a create/connect/disconnect/delete cycle every time is slow and painful... I'd rather just "math the crap out of it" through my script, but I can't seem to figure out how to actually multiply my two matrices...
Oh, I'm using the MTransformationMatrix since it handles a few things for you that the MMatrix does not - like rotation order (at least from what I've read...)
Thank you for any help you can give!
import maya.cmds as mc
import maya.OpenMaya as om
src_xfm = 'lf_grp'
mir_matrix_vals = [-1.0, -0.0, -0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0]
# get src xfm matrix
#
selList = om.MSelectionList()
selList.add(src_xfm)
mDagPath = om.MDagPath()
selList.getDagPath(0, mDagPath)
src_xfmFn = om.MFnTransform(mDagPath)
src_matrix = src_xfmFn.transformation()
# construct mir xfm matrix
#
mir_matrix = om.MTransformationMatrix()
tmp_matrix = om.MMatrix()
om.MScriptUtil().createMatrixFromList(mir_matrix_vals, tmp_matrix)
mir_matrix = om.MTransformationMatrix(tmp_matrix)
# multiply matrices to get mirrored matrix
#
dst_matrix = src_matrix * mir_matrix # HOW DO YOU DO THIS????
Here's how do to it using the openMaya api version 2.
Nowadays this is the preferred method for doing Python api work - among other things it's a lot less wordy and avoids MScriptUtil, which is prone to crashiness if used incorrectly. It's also faster for most things.
This is the plain matrix multiplication:
from maya.api.OpemMaya import MMatrix
mat1 = MMatrix ([0.707107, 0, -0.707107, 0, 0.5, 0.707107, 0.5, 0, 0.5, -0.707107, 0.5, 0, 0, 0, 0, 1])
mat2 = MMatrix([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 100, 200, 300, 1])
print mat1 * mat2
# (((0.707107, 0, -0.707107, 0), (0.5, 0.707107, 0.5, 0), (0.5, -0.707107, 0.5, 0), (100, 200, 300, 1)))
You can't directly multiply an MTransformationMatrix -- that class isn't a linear algebra matrix, it's an accessor for the various position, rotation, scale, shear and pivot data functions of a matrix. You use it if you want get around doing all of the concatenating math yourself on a transform node, like setting its rotation without changing its scale.
You can get the underlyying matrix from an MTransformationMatrix with its asMatrix() function. To apply a matrix to an object :
from maya.api.OpenMaya import MTransformationMatrix, MGlobal, MSelectionList, MFnDagNode
sel = MGlobal.getActiveSelectionList() # selection
dagpath = sel.getDependNode(0) # first node
transform_node = MFnTransform(dagpath) # MFnTransform
xfm= transform_node.transformation().asMatrix() # matrix
new_matrix = mat1 * xfm # math
new_trans = MTransformationMatrix(new_matrix)
transform_node.setTransformation(new_trans)