The xarray.DataArray
stucture for uvecs#
xarrayuvecs
propose a accessor for xarray.DataArray
to work on “Unit VECctor that are Symmetrical” (UVECS).
In this case symetrical mean that a vector x has the same meaning than -x. Therefore is can be usefull to describe non directional orientation such as crystallographic orientation for instance.
In this notebook we will show what can be done using xarrayuvec
accessor.
import xarrayaita.loadData_aita as lda #here are some function to build xarrayaita structure
import xarrayaita.aita as xa
import xarrayuvecs.uvecs as xu
import xarrayuvecs.lut2d as lut2d
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import xarray as xr
Load data
# path to data and microstructure
path_data='orientation_test.dat'
path_micro='micro_test.bmp'
data=lda.aita5col(path_data,path_micro)
data
<xarray.Dataset> Size: 100MB Dimensions: (y: 2500, x: 1000, uvecs: 2) Coordinates: * x (x) float64 8kB 0.0 0.02 0.04 0.06 ... 19.92 19.94 19.96 19.98 * y (y) float64 20kB 49.98 49.96 49.94 49.92 ... 0.06 0.04 0.02 0.0 Dimensions without coordinates: uvecs Data variables: orientation (y, x, uvecs) float64 40MB 2.395 0.6451 5.377 ... 0.6098 0.6473 quality (y, x) int64 20MB 0 90 92 93 92 92 94 ... 96 96 96 96 97 97 96 micro (y, x) float64 20MB 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 grainId (y, x) int64 20MB 1 1 1 1 1 1 1 1 1 1 1 ... 1 1 1 1 1 1 1 1 1 1 Attributes: date: b'Thursday, 19 Nov 2015, 11:24 am\r' unit: millimeters step_size: 0.02 path_dat: orientation_test.dat
What is an xarrayuvecs
DataArray
?#
data.orientation.head(2)
<xarray.DataArray 'orientation' (y: 2, x: 2, uvecs: 2)> Size: 64B array([[[2.39476627, 0.64507369], [5.37718489, 1.04999008]], [[5.35955707, 1.15837502], [5.35885894, 1.12975162]]]) Coordinates: * x (x) float64 16B 0.0 0.02 * y (y) float64 16B 49.98 49.96 Dimensions without coordinates: uvecs
xarrayuvecs
accessor should be used on xarray.DataArray
da that have a dimension of \(m\times n \times 2\). The da[:,:,0] correspond to the azimuth \(\Phi\) coordinate of the unit vector and da[:,:,1] to the colatitude \(\theta\).
plt.figure(figsize=(10,10))
plt.subplot(1,2,1)
data.orientation[:,:,0].plot()
plt.axis('equal')
plt.title('azimuth $\Phi$')
plt.subplot(1,2,2)
data.orientation[:,:,1].plot()
plt.axis('equal')
plt.title('colatitude $\theta$')
Text(0.5, 1.0, 'colatitude $\theta$')
Export different coordinate systems#
Bunge Euler convention#
The Bunge Euler convention is widely used in the crystallographic community.
\(\phi_1\) is the rotation around \(Oz\)
\(\phi\) is the rotation around \(Ou\)
data['Bunge_Euler']=data.orientation.uvecs.bunge_euler()
plt.figure(figsize=(10,10))
plt.subplot(1,2,1)
data.Bunge_Euler[:,:,0].plot()
plt.axis('equal')
plt.title('phi1')
plt.subplot(1,2,2)
data.Bunge_Euler[:,:,1].plot()
plt.axis('equal')
plt.title('phi')
Text(0.5, 1.0, 'phi')
Cartesien coordinate#
You can also extract the vector in cartesien coordinate.
data['oXYZ']=data.orientation.uvecs.xyz()
plt.figure(figsize=(15,10))
plt.subplot(1,3,1)
data.oXYZ[:,:,0].plot(cmap=cm.viridis)
plt.axis('equal')
plt.title('X')
plt.subplot(1,3,2)
data.oXYZ[:,:,1].plot(cmap=cm.viridis)
plt.axis('equal')
plt.title('Y')
plt.subplot(1,3,3)
data.oXYZ[:,:,2].plot(cmap=cm.viridis)
plt.axis('equal')
plt.title('Z')
Text(0.5, 1.0, 'Z')
Colormap#
Colormap plot of the orientations can be done using different colorwheels.
Full colorwheel#
The colorcode used to display one orientation is choosen using a given colorwheel (show below). Using the “Full Colorwheel” displays a given color for a given orientation. For instance:
a black pixel display an orientation along the z-axis \((0,0,1)\)
a red pixel display an orientation along the minus x-axis \((-1,0,0)\)
a blue pixel display an orientation along the \(\left(\frac{\sqrt(2)}{2},\frac{-\sqrt(2)}{2},0\right)\)
In this representation the azimut is represented in a (0,360°) frame, and the colatitude in a (0, 90°) frame.
This representation is usefull but contains drawbacks. For instance the color codding is discontinous. Therefore vectors \(\left(1,0,+\delta_z\right)\) and \(\left(1,0,-\delta_z\right)\) show very different colors (pale blue and red) even if the angle between both decreases to 0 as \(\delta_z\) decreases to 0.
lut_f=lut2d.lut()
plt.figure(figsize=(3,3))
plt.imshow(lut_f)
plt.axis('equal')
plt.axis('off')
plt.title('Full colorwheel')
Text(0.5, 1.0, 'Full colorwheel')
The colormap associated with this colorwheel can be computed using xarrayuvecs
data['FullColormap']=data.orientation.uvecs.calc_colormap()
plt.figure(figsize=(5,10))
data.FullColormap.plot.imshow()
plt.axis('equal')
(-0.01, 19.990000000000002, -0.010000000000001563, 49.99000000000001)
Semi colorwheel#
The semi colorwheel is another representation of the orientation. It has the advantage not to have any discountinuities but one color does not correspond to a unique orientation.
In this representation the azimut is represented in a (0,180°) frame, and the colatitude in a (-90°, 90°) frame.
Warning
\((x,y,z)\) and \((-x,-y,z)\) share the same colorcoding.
lut_s=lut2d.lut(semi=True)
plt.figure(figsize=(3,3))
plt.imshow(lut_s)
plt.axis('equal')
plt.axis('off')
plt.title('Semi colorwheel')
Text(0.5, 1.0, 'Semi colorwheel')
data['SemiColormap']=data.orientation.uvecs.calc_colormap(semi=True)
plt.figure(figsize=(5,10))
data.SemiColormap.plot.imshow()
plt.axis('equal')
(-0.01, 19.990000000000002, -0.010000000000001563, 49.99000000000001)
Orientation Density Function#
The Orientation Density Function (ODF) is a probability density distribution of the orientations. Therefore its integral over the sphere is equal to 1.
It is evaluated using a Kernel Density Estimation (KDE) with a gaussian kernel.
Warning
The representation is quite sensitive to the ‘bandwidth’ bw parameter of the gaussian kernel that should be choosen carefully.
plt.figure(figsize=(14,14))
plt.subplot(221)
data.orientation.uvecs.plotODF(bw=0.02,cmap=cm.viridis)
plt.title('bw=0.02')
plt.subplot(222)
data.orientation.uvecs.plotODF(bw=0.1,cmap=cm.viridis)
plt.title('bw=0.1')
plt.subplot(223)
data.orientation.uvecs.plotODF(bw=0.2,cmap=cm.viridis)
plt.title('bw=0.2')
plt.subplot(224)
data.orientation.uvecs.plotODF(bw=2.,cmap=cm.viridis)
plt.title('bw=2')
Text(0.5, 1.0, 'bw=2')