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\).

Definition of the Azimuth and Colatitude.}

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$')
../_images/42521a676e69b2ab2354b61a5b6012b4965d67c2130e06d1991ac2cb36fd814e.png

Export different coordinate systems#

Bunge Euler convention#

The Bunge Euler convention is widely used in the crystallographic community.

  1. \(\phi_1\) is the rotation around \(Oz\)

  2. \(\phi\) is the rotation around \(Ou\)

Definition of the Bunge Euler angle.

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')
../_images/7e02e7b50915daa3234810ddf593d5bdf5c83ef6f254f3747f854f5c2e1130bc.png

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')
../_images/3968c2c8470fd99b2b4000d42238f96ea8e0448a778efe5cc955af93f68a8aca.png

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:

  1. a black pixel display an orientation along the z-axis \((0,0,1)\)

  2. a red pixel display an orientation along the minus x-axis \((-1,0,0)\)

  3. 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')
../_images/feb9a929744d08bb1e0155a33e2c10c22f994ba7e99b9c5c2ab75b6dd48f5587.png

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)
../_images/7a5506a527a2f2f2cb32044fcf443f52a349c6ec359d8a38627d40db2d2e9e9f.png

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')
../_images/62bd8f845fc8178c118fe27742187c934b153d0e32a094c6e01dc78c5b5a3406.png
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)
../_images/f617a136d3056a962a1ffe066890997fe23540b7cca57da749facf20b185d6e3.png

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')
../_images/953177a4470776f534d0dcf25631bbfc4639b68dd6ba8815dd17f03f72157da0.png