-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Reconstruction constructor in CoordSys3D #13056
Conversation
Add rotation_equations.
Set rotation_equations to None for parent None and rotation_matrix None
sympy/vector/coordsysrect.py
Outdated
trans_eq3 = matrix[6]*self.x + matrix[7]*self.y + matrix[8]*self.z | ||
trans_eq1 = matrix[0]*variables[0] + matrix[1]*variables[1] + matrix[2]*variables[2] | ||
trans_eq2 = matrix[3]*variables[0] + matrix[4]*variables[1] + matrix[5]*variables[2] | ||
trans_eq3 = matrix[6]*variables[0] + matrix[7]*variables[1] + matrix[8]*variables[2] | ||
|
||
return trans_eq1, trans_eq2, trans_eq3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we operate with lambda
, it would be easier.
@@ -98,6 +98,33 @@ def __new__(cls, name, location=None, rotation_matrix=None, | |||
location = Vector.zero | |||
origin = Point(name + '.origin') | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What to do here:
- check that if
ŧransformation
isNone
. - if it is None, computer
transformation
from the rotation and traslation. Make identity if they are also None. - if it is not None, check that rotation and translation are None
- transform
transformation
to aLambda
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why do that.
You assume that we have to use transformation
or (rotation
and translation
), so transformation
should have information about every three transformations.
I think that it could be easier sometimes to split transformation into steps. For example for transformation
set cylindrical
and for location set some vector
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do it the general way, no need to complicate the code with special cases. Translations are subsets of transformations. In the special cases of rotation and translations, we could store some markers to remind of the special case (and remember the steps).
I suggest to return |
I used your idea in constructor, when |
@@ -109,12 +156,11 @@ def __new__(cls, name, location=None, rotation_matrix=None, | |||
# they may actually be 'coincident' wrt the root system. | |||
if parent is not None: | |||
obj = super(CoordSys3D, cls).__new__( | |||
cls, Symbol(name), location, parent_orient, parent) | |||
cls, Symbol(name), transformation, parent) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
transformation
need to be defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
transformation
has to be a SymPy type, if we are going to use a lambda, we need to use SymPy's Lambda
(with capital L).
sympy/vector/coordsysrect.py
Outdated
if parent is None: | ||
transformation_equations = None | ||
else: | ||
transformation_equations = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The aim is to define transformation
, we may not need transformation_equations
.
sympy/vector/coordsysrect.py
Outdated
raise ValueError | ||
|
||
if parent is None: | ||
transformation_equations = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why None
? We have transformation != None
in this case. We should just check that transformation
is correct (and transform it to a SymPy type).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't implement this part yet.
I just put None
to create some structure for case when transformation
is not None
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we need to think first, how transformation
should look like. Should we just use _connect_to_standard_cartesian
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That code can be OK. I would prefer that transformation
be finally transformed into a Lambda
object, it makes more sense with the hashing.
sympy/vector/coordsysrect.py
Outdated
@@ -174,7 +220,7 @@ def __new__(cls, name, location=None, rotation_matrix=None, | |||
|
|||
obj._parent_rotation_matrix = parent_orient | |||
obj._origin = origin | |||
|
|||
obj.transformation_equations = transformation_equations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Store transformation
, not transformation_equations
(they are the same thing in the end).
sympy/vector/coordsysrect.py
Outdated
raise ValueError("The transformation equation does not " | ||
"create orthogonal coordinate system") | ||
else: | ||
if not (location and rotation_matrix) is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This condition is wrong. Both have to be None
otherwise raise an exception
sympy/vector/coordsysrect.py
Outdated
lame_coefficients = connect_to[1] | ||
inverse_transformation = connect_to[2] | ||
else: | ||
transformation = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is definitely wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't cover this scenario. When you accept the case when parent
is None
I will update this part.
I wrote about it on gitter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove the parent
case. Sorry, didn't read gitter.
sympy/vector/coordsysrect.py
Outdated
# See lines 80:99. Location is somehow treated only when parent is put. | ||
# We are not able to create independent vector, so we can't assign | ||
# anything to location. | ||
translation_equations = lambda x, y, z: (x, y, z) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we should treat the parent as being a default standard coordinate system if it is not specified. Otherwise what sense does it make to specify the transformation?
sympy/vector/coordsysrect.py
Outdated
x, y, z = symbols('x y z') | ||
transformation = rotation_equations(*translation_equations(x, y, z)) | ||
lame_coefficients = _set_lame_coefficient_mapping('cartesian', (x, y, z)) | ||
inverse_transformation = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, this could be specified. You just have to immagine that there is some default coordinate system used as a reference if parent == None
.
sympy/vector/coordsysrect.py
Outdated
lame_coefficients = _set_lame_coefficient_mapping('cartesian', (x, y, z)) | ||
inverse_transformation = None | ||
|
||
if not CoordSys3D._check_orthogonality(transformation, (x, y, z)): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there are only rotations and translations, we don't need this check.
sympy/vector/coordsysrect.py
Outdated
@@ -98,6 +213,65 @@ def __new__(cls, name, location=None, rotation_matrix=None, | |||
location = Vector.zero | |||
origin = Point(name + '.origin') | |||
|
|||
if transformation is None: | |||
if parent is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This if
loop is not very useful. The case where parent == None
and parent != None
could be handled by the same code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be, but the one difference between these two cases is with variables
. When we have parent
we can construct transformation equations using base scalars from parent
system. Otherwise we can't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are using lambdas in order to avoid this problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I see. I will simplify this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another thing is translation
. Without parent
it doesn't have sense, so we need to distinguish two cases. But I think we can still simplify the code a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why doesn't it make sense? Anyway, the code in the master supports location even without parent, so we need to keep the compatibility.
sympy/vector/coordsysrect.py
Outdated
lame_coefficients = _set_lame_coefficient_mapping('cartesian', parent.base_scalars()) | ||
inverse_transformation = _set_inv_trans_equations('cartesian', parent.base_scalars()) | ||
|
||
if not CoordSys3D._check_orthogonality(transformation, parent.base_scalars()): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useless check, it will always pass (for rotations and translations).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
sympy/vector/coordsysrect.py
Outdated
if location is not None and rotation_matrix is not None: | ||
raise ValueError | ||
|
||
if parent is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would remove this if
.
5ef983a
to
181c2a5
Compare
sympy/vector/coordsysrect.py
Outdated
else: | ||
inverse_transformation_equations = None | ||
|
||
elif isinstance(curv_coord_type, (tuple, list, Tuple, collections.Callable)): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Callable
should be a separate case.
Almost finished constructor. Lame_coefficinets, transformation, inverse_transfromation are Lambda, so they can easily depend on desired variables. Creating base scalars with custom str has the same form as base scalars created in standard name: class_name + '.' + variable_names.
sympy/vector/coordsysrect.py
Outdated
rotation_lambda = lambda x, y, z: (x, y, z) | ||
if rotation_matrix is not None: | ||
rotation_lambda = \ | ||
lambda x, y, z: parent._rotation_trans_equations(parent_orient, (x, y, z)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with lambda
no need for parent
here.
sympy/vector/coordsysrect.py
Outdated
obj._inverse_transformation = inverse_transformation | ||
obj._h1, obj._h2, obj._h3 = lame_coefficients(obj._x, obj._y, obj._z) | ||
if parent is not None: | ||
obj._transformation = transformation(parent._x, parent._y, parent._z) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think transformation
should remain a Lambda
.
sympy/vector/coordsysrect.py
Outdated
obj._transformation = transformation(parent._x, parent._y, parent._z) | ||
else: | ||
obj._transformation = transformation(obj._x, obj._y, obj._z) | ||
obj._inverse_transformation = inverse_transformation(obj._x, obj._y, obj._z) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also this one, I think it's easier if it remains in the lambda
form.
sympy/vector/coordsysrect.py
Outdated
|
||
""" | ||
|
||
x1, x2, x3 = symbols("x1, x2, x3", cls=Dummy) | ||
|
||
if isinstance(curv_coord_type, string_types): | ||
if variables is None: | ||
variables = _default_variables(curv_coord_type) | ||
|
||
transformation_equations = _set_transformation_equations_mapping(curv_coord_type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
transformation_equations
is a lambda
, we need a SymPy Lambda
(capital L) for hashing and internal stuff of SymPy.
sympy/vector/coordsysrect.py
Outdated
raise ValueError("The transformation equation does not " | ||
"create orthogonal coordinate system") | ||
|
||
lame_coefficients = cls._calculate_lame_coefficients(transformation_equations(*variables), variables) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need to pass variables
here? I believe a single lambda
is enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was the most difficult part for me and I didn't find clear solution with lambda
but I can try once again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in _calculate_lame_coefficients
you can use some Dummy
variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I will try.
Remove parameter variables from _calculate_lame_coefficinets, _calculate_inv_trans_equations, _check_orthogonality All transformation in constructor are Lambda object.
Inverse transformation is calculated only when user needs it. when transformation is choosen from pre-defined ones, inverse is also set.
ed4caf2
to
ad3b703
Compare
Remove dependency of parameter variables from every method. Change form of setting transformation. Variable names should be put together with equations. Remove simplify in _calculate_lame_coefficients for a while. Useage of simplify produce errors which isn't resolve yet.
if transformation is None: | ||
transformation = Tuple(rotation_matrix, location) | ||
|
||
if isinstance(transformation, Tuple): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why that?
In this case, we are not able to set transformation
as equations with variables. Previously, we could do that. For example:
a = CoordSys3D('a', transformation=Tuple(((x*cos(y), x*sin(y), z)), (x, y, z)))
But now you assumed that in following manner we're providing rotation and translation transformations.
Look at the code in _connect_to_cartesian
method, lines 363:367
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought a bit over the weekend, if we pass a rotation and/or translation, it needs to be stored in transformation
and passed to the superclass (SymPy's hashing requirements). If we transform the rotation and/or translation into a Lambda
, the code will slow down a lot, because when the class is reconstructed all orthogonality checks and computations are performed (at least, I think that's the problem).
We can still pass the transformation equations by wrapping them in a Lambda
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main problem is that when calling the superclass in the constructor, we need a fixed argument order. The same argument order must return the same object if called on the constructor. This requirement is pretty restrictive on the way we may write the constructor, so we need to choose a precise way to pack the information without losing speed.
Simplification in constructor. Remove unnescessary if condition. Fix tests, doctests.
raises(ValueError, lambda: a._connect_to_standard_cartesian((x, y, z))) | ||
|
||
|
||
def test_check_orthogonality(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why has this test disappeared?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I must did it earlier, but I shouldn't. I will do it
assert simplify(a.lame_coefficients()) == (1, sqrt(a.x**2), 1) | ||
|
||
raises(ValueError, lambda: a._connect_to_standard_cartesian((x, y, z))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can test invalid parameters to the constructor
sympy/vector/tests/test_printing.py
Outdated
v.append(a*N.i - b*N.j) | ||
v.append((a**2 + N.x)*N.i + N.k) | ||
v.append((a**2 + b)*N.i + 3*(C.y - c)*N.k) | ||
v.append(a * N.i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes should be reverted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why, but some expression change their order like was c - C.y
and know C.y - c
sympy/vector/tests/test_printing.py
Outdated
⎛ 2 ⎞ N_i + ⎛⌠ ⎞ N_k\n\ | ||
⎝a + b⎠ ⎜⎮ f(b) db⎟ \n\ | ||
⎝⌡ ⎠ \ | ||
""") | ||
pretty_v_11 = u( | ||
"""\ | ||
"""\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't notice that. I will revert
sympy/vector/tests/test_printing.py
Outdated
@@ -68,26 +70,26 @@ def upretty(expr): | |||
|
|||
for x in v: | |||
d.append(x | N.k) | |||
s = 3*N.x**2*C.y | |||
s = 3 * N.x ** 2 * C.y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you use some auto-formatter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, by mistake
assert a._check_orthogonality() is True | ||
x, y, z = symbols('x y z') | ||
u,v = symbols('u, v') | ||
a = CoordSys3D('a', transformation=((x*sin(y)*cos(z), x*sin(y)*sin(z), x*cos(y)), (x, y, z))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't the tuple (x, y, z)
come before the expression?
That's why I suggest to simply use: lambda x, y, z: (x*sin(y)*cos(z), x*sin(y)*sin(z), x*cos(y))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will add also support for lambda
.
assert simplify(a.lame_coefficients()) == (1, sqrt(a.x**2), 1) | ||
a._connect_to_standard_cartesian(((x, y, z), (x * sin(y) * cos(z), x * sin(y) * sin(z), x * cos(y))), inverse=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is the block from here on still missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not support now these type of transformation
.
Here we mainly tested _connect_to_standard_cartesian
which now is removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just pass a lambda to CoordSys3D
constructor. You added support for this tuples.
f7acc15
to
bebd39f
Compare
sympy/vector/coordsysrect.py
Outdated
raise TypeError("rotation_matrix should be an Immutable" + | ||
"Matrix instance") | ||
parent_orient = rotation_matrix | ||
rotation_matrix = rotation_matrix.as_immutable() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be de-indented
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
Variables now are first in tuple. Add support for python's lambda. Add test for wrong transformation argument in constructor. Fix indent inconstructor.
bebd39f
to
a6fc5bd
Compare
870a844
to
063ab1b
Compare
This PR introduces to constructor transformation equation.
These equations will be obtain from
rotation_matrix
,location
(for translations), and for changing type of coordinate system. After obtaining these equations, method for transformation composition will be used.We need to deal with two situation. When we want to connect our coordinate system (parent coordinate system) and when we want to just set transformation equations.