Plot field variable on IPF contour #440
Replies: 4 comments 4 replies
-
Hi @arovinelli, thanks! Assuming you have an auxiliary value (porosity or similar) for each data point (orientation), you can pass these to the |
Beta Was this translation helpful? Give feedback.
-
Hi @arovinelli, this isn't easily doable from the public facing API but can be done by following the logic in orix.measure.pole_density_function and adapting for your use case. Here's a small example which may help: from orix.sampling.S2_sampling import _sample_S2_equal_area_coordinates
from orix.plot import StereographicPlot
from orix.projections import StereographicProjection
from orix.vector import Vector3d
import numpy as np
from matplotlib import pyplot as plt
# setup projection
hemisphere = "upper"
poles = {"upper": -1, "lower": 1}
sp = StereographicProjection(poles[hemisphere])
# setup polar grid
resolution = 1.0 # degrees
azimuth_coords, polar_coords = _sample_S2_equal_area_coordinates(
resolution,
hemisphere=hemisphere,
azimuth_endpoint=True,
)
azimuth_grid, polar_grid = np.meshgrid(azimuth_coords, polar_coords, indexing="ij")
# simulate auxiliary variable
azimuth_center_grid, polar_center_grid = np.meshgrid(
azimuth_coords[:-1] + np.diff(azimuth_coords) / 2,
polar_coords[:-1] + np.diff(polar_coords) / 2,
indexing="ij",
)
variable = np.zeros_like(polar_center_grid)
mask = (azimuth_center_grid >= 1 * np.pi / 3) * (azimuth_center_grid < 2 * np.pi / 3)
variable[mask] = np.cos(polar_center_grid[mask])
mask = (azimuth_center_grid >= 4 * np.pi / 3) * (azimuth_center_grid < 5 * np.pi / 3)
variable[mask] = np.cos(polar_center_grid[mask])
# plot
fig, ax = plt.subplots(subplot_kw=dict(projection="stereographic"))
v_grid = Vector3d.from_polar(azimuth=azimuth_grid, polar=polar_grid).unit
x, y = sp.vector2xy(v_grid)
ax.pcolormesh(x.reshape(azimuth_grid.shape), y.reshape(azimuth_grid.shape), variable) from orix.quaternion.symmetry import D3 as symmetry
# in crystal fundamental sector
v_center_grid = Vector3d.from_polar(
azimuth=azimuth_center_grid, polar=polar_center_grid
).unit
# fold back in into fundamental sector
v_center_grid_fs = v_center_grid.in_fundamental_sector(symmetry)
azimuth_center_fs, polar_center_fs, _ = v_center_grid_fs.to_polar()
# calculate histogram values for vectors folded back into
# fundamental sector
i = np.digitize(azimuth_center_fs, azimuth_coords[1:-1])
j = np.digitize(polar_center_fs, polar_coords[1:-1])
# recompute histogram
temp = np.zeros((azimuth_coords.size - 1, polar_coords.size - 1))
# add hist data to new histogram without buffering
np.add.at(temp, (i.ravel(), j.ravel()), variable.ravel())
temp = np.ma.array(temp, mask=~(v_center_grid <= symmetry.fundamental_sector))
# plot
fig, ax = plt.subplots(subplot_kw=dict(projection="stereographic"))
v_grid = Vector3d.from_polar(azimuth=azimuth_grid, polar=polar_grid).unit
x, y = sp.vector2xy(v_grid)
ax.pcolormesh(x.reshape(azimuth_grid.shape), y.reshape(azimuth_grid.shape), temp)
ax.restrict_to_sector(symmetry.fundamental_sector) If you are looking for a contour plot like in the reference you cited then this is possible using v_grid = Vector3d.from_polar(azimuth=azimuth_center_grid, polar=polar_center_grid).unit
x, y = sp.vector2xy(v_grid)
ax.contourf(x.reshape(v_grid.shape), y.reshape(v_grid.shape), temp, levels=10)
ax.restrict_to_sector(symmetry.fundamental_sector) I hope this is of use and points you in the right direction! If you think this feature is of general use then we could consider adding a simpler public facing API in the future. |
Beta Was this translation helpful? Give feedback.
-
@arovinelli thanks for clarifying. If you wanted to plot some orientations in the Inverse Pole Figure, you could view for example the lab Z-direction in the crystal reference frame. I think the example below is perhaps more suited to your use case: from orix.measure import pole_density_function
from orix.vector import Vector3d
from orix.quaternion import Orientation
import numpy as np
from matplotlib import pyplot as plt
from orix.quaternion.symmetry import Th
symmetry = Th
# 10 random euler angles
euler = np.random.rand(10, 3) * 2 * np.pi
ori = Orientation.from_euler(euler) # create orientations
v = ori * Vector3d.zvector() # sample-Z in crystal reference frame
# values of variable for a given orientation
vals = np.arange(v.size) + 1 # 1, 2, 3 ...
hist, (x, y) = pole_density_function(
v,
resolution=0.5,
sigma=0,
log=False,
hemisphere="upper",
symmetry=symmetry,
weights=vals,
mrd=False,
)
# plot
fig, ax = plt.subplots(subplot_kw=dict(projection="ipf", symmetry=symmetry))
pc = ax.pcolormesh(x, y, hist)
plt.colorbar(pc, label="Variable", ax=ax) You can see here that the values scale from 0-10 as expected from the setup ( To demonstrate this you may wish to apply some blurring to improve the visualisation of the data or to simulate some uncertainty in the data. In the example below This scaling can be undone in this case by scaling as |
Beta Was this translation helpful? Give feedback.
-
@hakonanes yes I think there is some value in including them in the docs too. It would also be nice to add a option to plot the PDF as a contour plot (both filled and unfilled), as this seems to be a common representation in the field. I can look into this when I find some time 😄. |
Beta Was this translation helpful? Give feedback.
-
hi there, very nice tool.
I have a quick question: I would like to plot a customs scalar variable (say porosity) over an IPF, starting from discrete orientation data. The plot should be filled (same as here ), and the color should be associated to the custom variable value. Is this currently possible ?
Thanks in advance
Beta Was this translation helpful? Give feedback.
All reactions