Merge branch 'general-stereographic-projection' into 'development'

generalized stereographic projection to cope with all three directions (x,y,Z)

See merge request damask/DAMASK!350
This commit is contained in:
Sharan Roongta 2021-02-28 14:00:20 +00:00
commit 2691ef2114
2 changed files with 35 additions and 15 deletions

View File

@ -193,7 +193,7 @@ def scale_to_coprime(v):
return m return m
def project_stereographic(vector,normalize=False): def project_stereographic(vector,direction='z',normalize=True,keepdims=False):
""" """
Apply stereographic projection to vector. Apply stereographic projection to vector.
@ -201,18 +201,37 @@ def project_stereographic(vector,normalize=False):
---------- ----------
vector : numpy.ndarray of shape (...,3) vector : numpy.ndarray of shape (...,3)
Vector coordinates to be projected. Vector coordinates to be projected.
direction : str
Projection direction 'x', 'y', or 'z'.
Defaults to 'z'.
normalize : bool normalize : bool
Ensure unit length for vector. Defaults to False. Ensure unit length of input vector. Defaults to True.
keepdims : bool
Maintain three-dimensional output coordinates.
Default two-dimensional output uses right-handed frame spanned by
the next and next-next axis relative to the projection direction,
e.g. x-y when projecting along z and z-x when projecting along y.
Returns Returns
------- -------
coordinates : numpy.ndarray of shape (...,2) coordinates : numpy.ndarray of shape (...,2 | 3)
Projected coordinates. Projected coordinates.
Examples
--------
>>> project_stereographic(np.ones(3))
[0.3660254, 0.3660254]
>>> project_stereographic(np.ones(3),direction='x',normalize=False,keepdims=True)
[0, 0.5, 0.5]
>>> project_stereographic([0,1,1],direction='y',normalize=True,keepdims=False)
[0.41421356, 0]
""" """
v_ = vector/np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector shift = 'zyx'.index(direction)
return np.block([v_[...,:2]/(1+np.abs(v_[...,2:3])), v_ = np.roll(vector/np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector,
np.zeros_like(v_[...,2:3])]) shift,axis=-1)
return np.roll(np.block([v_[...,:2]/(1+np.abs(v_[...,2:3])),np.zeros_like(v_[...,2:3])]),
-shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2]
def execution_stamp(class_name,function_name=None): def execution_stamp(class_name,function_name=None):

View File

@ -49,17 +49,18 @@ class TestUtil:
dist_sampled = np.histogram(centers[selected],bins)[0]/N_samples*np.sum(dist) dist_sampled = np.histogram(centers[selected],bins)[0]/N_samples*np.sum(dist)
assert np.sqrt(((dist - dist_sampled) ** 2).mean()) < .025 and selected.shape[0]==N_samples assert np.sqrt(((dist - dist_sampled) ** 2).mean()) < .025 and selected.shape[0]==N_samples
@pytest.mark.parametrize('point,normalize,answer', @pytest.mark.parametrize('point,direction,normalize,keepdims,answer',
[ [
([1,0,0],False,[1,0,0]), ([1,0,0],'z',False,True, [1,0,0]),
([1,0,0],True, [1,0,0]), ([1,0,0],'z',True, False,[1,0]),
([0,1,1],False,[0,0.5,0]), ([0,1,1],'z',False,True, [0,0.5,0]),
([0,1,1],True, [0,0.41421356,0]), ([0,1,1],'y',True, False,[0.41421356,0]),
([1,1,1],False,[0.5,0.5,0]), ([1,1,0],'x',False,False,[0.5,0]),
([1,1,1],True, [0.3660254, 0.3660254, 0]), ([1,1,1],'y',True, True, [0.3660254, 0,0.3660254]),
]) ])
def test_project_stereographic(self,point,normalize,answer): def test_project_stereographic(self,point,direction,normalize,keepdims,answer):
assert np.allclose(util.project_stereographic(np.array(point),normalize=normalize),answer) assert np.allclose(util.project_stereographic(np.array(point),direction=direction,
normalize=normalize,keepdims=keepdims),answer)
@pytest.mark.parametrize('fro,to,mode,answer', @pytest.mark.parametrize('fro,to,mode,answer',
[ [