Skip to content

Sanitize direction2color inputs#639

Open
argerlt wants to merge 7 commits intopyxem:developfrom
argerlt:sanitize_direction2color
Open

Sanitize direction2color inputs#639
argerlt wants to merge 7 commits intopyxem:developfrom
argerlt:sanitize_direction2color

Conversation

@argerlt
Copy link
Copy Markdown
Collaborator

@argerlt argerlt commented Mar 5, 2026

Description of the change

This should solve #638:

  • The input 'direction' in IPFColorKeyTSL must now be a sample vector (Miller is not allowed)
  • direction2color now accepts both crystal and sample vectors, as long as the crystals are of the same Laue class as the color key.

Progress of the PR

Minimal example of the bug fix or new feature

import numpy as np

import orix.crystal_map as ocm
import orix.plot as opl
import orix.quaternion as oqu
import orix.quaternion.symmetry as osm
import orix.vector as ove

p1 = ocm.Phase(name="fakename", point_group=osm.Oh)
p2 = ocm.Phase(name="fakename", point_group=osm.D6h)
arr = np.linspace(0, 5, 30).reshape(10, 3)
v = ove.Vector3d(arr)
g1 = oqu.Orientation.random(5, symmetry=p1.point_group)
g2 = oqu.Orientation.random(5, symmetry=p2.point_group)
m1 = ove.Miller(xyz=arr, phase=p1)
m2 = ove.Miller(xyz=arr, phase=p2)

These operations are allowed:

ckey_dir = opl.DirectionColorKeyTSL(osm.Oh)
rbg = ckey_dir.direction2color(v)
rbg = ckey_dir.direction2color(m1)

ckey_ori = opl.IPFColorKeyTSL(symmetry=osm.Oh, direction=v[0])
rbg = ckey_ori.orientation2color(g1)

While these are not, and also throw informative errors

# ckey_ori = opl.IPFColorKeyTSL(symmetry=osm.Oh, direction=m1)
>>> ValueError: The Viewing direction must a real space vector (Vector3d), not a cystal vector (Miller)

# ckey_ori = opl.IPFColorKeyTSL(symmetry=osm.Oh, direction=[1,1,1,1])
>>> ValueError: 'direction' cannot be interpreted as a Vector3d

# ckey_ori = opl.IPFColorKeyTSL(symmetry=osm.Oh, direction=v)
>>> ValueError: 'direction' only accepts a single vector as an input

# rbg = ckey_dir.direction2color(m2)
>>> ValueError: 'direction' has a Laue group of 6/mmm, which differs  from the Laue group m-3m used by this color key

For reviewers

  • The PR title is short, concise, and will make sense 1 year later.
  • New functions are imported in corresponding __init__.py.
  • New features, API changes, and deprecations are mentioned in the unreleased
    section in CHANGELOG.rst.
  • Contributor(s) are listed correctly in __credits__ in orix/__init__.py and in
    .zenodo.json.

@argerlt
Copy link
Copy Markdown
Collaborator Author

argerlt commented Mar 5, 2026

pre-commit.ci autofix

@argerlt argerlt requested a review from hakonanes March 5, 2026 01:18
@hakonanes hakonanes added the bug Something isn't working label Mar 5, 2026
@hakonanes hakonanes added this to the v0.15.0 milestone Mar 5, 2026
@hakonanes
Copy link
Copy Markdown
Member

Thank you for making this fix. I don't have time right now, but I'll go through it soon when I have.

Just quickly, passing a vector to orientation2color() doesn't make any sense to me. It shouldn't be supported.

@argerlt
Copy link
Copy Markdown
Collaborator Author

argerlt commented Mar 5, 2026

Passing a vector to orientation2color()

Ah, I agree. Code itself is correct, but my description in this PR is wrong, as is the changelog entry. I'll fix it.

@argerlt
Copy link
Copy Markdown
Collaborator Author

argerlt commented Mar 6, 2026

pre-commit.ci autofix

Copy link
Copy Markdown
Member

@hakonanes hakonanes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good changes! I've got a couple of suggestions and requests for improvements.

Comment on lines +71 to +72
h_laue = direction.phase.point_group.laue.name
if h_laue == self.symmetry.name:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to use the Laue class equality here instead of just the name. The equality check uses the symmetry hash, which includes both the name and rotations (quaternion and handedness).

direction.phase.point_group.laue == self.symmetry

direction : orix.vector.Vector3d, optional
Sample direction. If not given, sample Z direction (out of
plane) is used.
Viewing direction the defines the IPF coloring. for the TSL
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to mention fibers here? The sample direction gives the crystal direction which colors the orientation. I think this is a simpler explanation. And the old "If not given, ..." description should be good still.

Sample direction. If not given, sample Z direction (out of
plane) is used.
Viewing direction the defines the IPF coloring. for the TSL
colormap, this defines the fiber of orientations that will be
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you:

  1. Move the parameter description to the class docstring
  2. Remove this docstring

Otherwise it won't show in our API reference.

This is a remnant of my limited documentation skills some years ago...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm seeing now that the orientation color key inheritance is poorly implemented. If it's fine with you, I'd like to make a few updates to your branch?

if direction is not None:
if isinstance(direction, Miller):
raise ValueError(
"The Viewing direction must a real space vector (Vector3d), not a cystal vector (Miller)"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest trying to keep wording simpler:

Suggested change
"The Viewing direction must a real space vector (Vector3d), not a cystal vector (Miller)"
"The sample direction must be a sample vector, not a crystal vector"

Comment on lines +47 to +50
rgb = rgb_key.direction2color(direction=v)
rgb = rgb_key.direction2color(direction=m1)
with pytest.raises(ValueError, match="'direction' has a Laue group"):
rgb = rgb_key.direction2color(direction=m2)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rgb = rgb_key.direction2color(direction=v)
rgb = rgb_key.direction2color(direction=m1)
with pytest.raises(ValueError, match="'direction' has a Laue group"):
rgb = rgb_key.direction2color(direction=m2)
rgb1 = rgb_key.direction2color(direction=v)
rgb2 = rgb_key.direction2color(direction=m1)
assert np.allclose(rgb1, rgb2)
with pytest.raises(ValueError, match="'direction' has a Laue group"):
rgb_key.direction2color(direction=m2)

)
if not isinstance(direction, Vector3d):
try:
direction = Vector3d(np.asanyarray(direction))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we allow this, we need to update the signature type hints. I suggest the following:

    def __init__(
        self, symmetry: Symmetry, direction: Vector3d | list | tuple | None = None
    ) -> None:

Comment on lines +64 to +65
except:
raise ValueError("'direction' cannot be interpreted as a Vector3d")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error catching should be narrowed, and the thrown error communicated to the user:

Suggested change
except:
raise ValueError("'direction' cannot be interpreted as a Vector3d")
except DimensionError as err:
raise ValueError("'direction' cannot be interpreted as a Vector3d") from err

except:
raise ValueError("'direction' cannot be interpreted as a Vector3d")
if direction.size != 1:
raise ValueError("'direction' only accepts a single vector as an input")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise ValueError("'direction' only accepts a single vector as an input")
raise ValueError("Only one sample direction can be given")

Comment on lines +28 to +29
- ``IPFColorKeyTSL`` will now only accept a single ``Vector3D`` as the `direction` setting
during creation.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- ``IPFColorKeyTSL`` will now only accept a single ``Vector3D`` as the `direction` setting
during creation.
- ``IPFColorKeyTSL`` now only accepts a single ``Vector3d`` as the ``direction``.

@hakonanes
Copy link
Copy Markdown
Member

Also, how about merging to main and making a patch release 0.14.3 right away? It is a bug after all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants