mtex-toolbox / mtex

MTEX is a free Matlab toolbox for quantitative texture analysis. Homepage:
http://mtex-toolbox.github.io/
GNU General Public License v2.0
285 stars 185 forks source link

Crystal Shape and EBSD data don't align when rotating the EBSD data or changing plotting conventions #1952

Open creuzige opened 1 year ago

creuzige commented 1 year ago

What do you want to do? I'd like to superimpose the crystal shapes on an IPF colormap, but I need to rotate the data (keepXY option) so the pole figures and other orientation data is preserved. Right now it looks like the crystal shapes use the plotting convention orientation, not any of the rotations applied to the EBSD data.

What data do you have? I've tried this with my own data, but the Crystal Shapes demo seems to show the same thing, so I included that below.

What code do you use? Please provide minimalist code with code in the following form

% From https://mtex-toolbox.github.io/CrystalShapes.html

% import some hexagonal data
mtexdata titanium;

%% part 1 - no data rotation, plotting convention matches EBSD axes

% Explicity set plotting convention
setMTEXpref('xAxisDirection','east');
setMTEXpref('zAxisDirection','intoPlane');

% define a simple hexagonal crystal shape
cS = crystalShape.hex(ebsd.CS)

% compute some grains
grains = calcGrains(ebsd);
grains = smooth(grains,5);

% and plot them
figure(1);
plot(grains,grains.meanOrientation)

% find the big ones
isBig = grains.grainSize>50;

% define a list of crystal shape that is oriented as the grain mean
% orientation and scaled according to the grain area
cSGrains = grains(isBig).meanOrientation * cS * 0.7 * sqrt(grains(isBig).area);

% now we can plot these crystal shapes at the grain centers
hold on
plot(grains(isBig).centroid + cSGrains)
hold off

%% part 2 - rotate orienttations by 90 about x
% plotting convention unchanged

% -90 deg rotation about X 
ebsd_p2 = rotate(ebsd,rotation('axis',xvector,'angle',-90*degree),'keepXY');

% compute some grains
grains_p2 = calcGrains(ebsd_p2);
grains_p2 = smooth(grains_p2,5);

% and plot them
figure(2);
plot(grains_p2,grains_p2.meanOrientation)

% find the big ones
isBig_p2 = grains_p2.grainSize>50;

% define a list of crystal shape that is oriented as the grain mean
% orientation and scaled according to the grain area
cSGrains_p2 = grains(isBig_p2).meanOrientation * cS * 0.7 * sqrt(grains(isBig_p2).area);

% now we can plot these crystal shapes at the grain centers
hold on
plot(grains_p2(isBig_p2).centroid + cSGrains_p2)
hold off

% RESULT:
% orientation colors change, 
% BUT, the crystal shapes don't change to reflect the orientation change

%% part 3 - change plotting convention
%  change so Z is north.  No rotation to the orientations

% Explicity set plotting convention
setMTEXpref('xAxisDirection','east');
setMTEXpref('zAxisDirection','south');

%use original data
ebsd_p3 = ebsd

% compute some grains
grains_p3 = calcGrains(ebsd_p3);
grains_p3 = smooth(grains_p3,5);

% and plot them
figure(3);
plot(grains_p3,grains_p3.meanOrientation)

% find the big ones
isBig_p3 = grains_p3.grainSize>50;

% define a list of crystal shape that is oriented as the grain mean
% orientation and scaled according to the grain area
cSGrains_p3 = grains(isBig_p3).meanOrientation * cS * 0.7 * sqrt(grains(isBig_p3).area);

% now we can plot these crystal shapes at the grain centers
hold on
plot(grains_p3(isBig_p3).centroid + cSGrains_p3)
hold off

% RESULT:
% image flipped from Fig1 in the image y direction 
% Maybe upper/lower surface symmetry, but not obvious

%% part 4 - change plotting convention
%  change so Z is north.  No rotation to the orientations

% Explicity set plotting convention
setMTEXpref('xAxisDirection','east');
setMTEXpref('zAxisDirection','north');

%use original data
ebsd_p4 = ebsd

% compute some grains
grains_p4 = calcGrains(ebsd_p4);
grains_p4 = smooth(grains_p4,5);

% and plot them
figure(4);
plot(grains_p4,grains_p4.meanOrientation)

% find the big ones
isBig_p4 = grains_p4.grainSize>50;

% define a list of crystal shape that is oriented as the grain mean
% orientation and scaled according to the grain area
cSGrains_p4 = grains(isBig_p4).meanOrientation * cS * 0.7 * sqrt(grains(isBig_p4).area);

% now we can plot these crystal shapes at the grain centers
hold on
plot(grains_p4(isBig_p4).centroid + cSGrains_p4)
hold off

% RESULT:
% image also flipped from Fig1 in the image y direction 
% Changing from south to north should have addressed upper/lower surface symmetry

What result do you get See inline with the different figure plots. Fig 1 - original data; Fig2 - rotating the data doesn't change the crystal shape. Figs3 and 4 changed the orientation conventions, which changed the crystal shape, but also the rest of the plot (flipped vertically). Manually flipping the image (flip vertically) did not recover the expected orientations either.

What result do you expect

What MTEX version do you use? 5.9.0

ralfHielscher commented 1 year ago

Hi Adam,

there are a couple of mistakes in your script.

  1. When computing the crystalshape you always using the old grain orientation
    cSGrains_p2 = grains(isBig_p2).meanOrientation * cS * 0.7 * sqrt(grains(isBig_p2).area);

    whereas it should be

    cSGrains_p2 = grains_p2(isBig_p2).meanOrientation * cS * 0.7 * sqrt(grains(isBig_p2).area);
  2. setMTEXpref('zAxisDirection','north'); is not defined in MTEX prior to MTEX 6.0. You can only have z intoPlane or outOfPlane. With MTEX 6.0 maps can be arbitrarily aligned. I would be happy if you could try it out :smile:

Ralf

creuzige commented 1 year ago

Ok, after staring at this example and my larger data set, I think I see the issue for the crystal shape comment (haven't tried to sort out the zAxisDirection option in v6.0 yet). I think it comes down to the 'keepXY' command when applying a rotation to the EBSD data, and that there's conflicting coordinate systems in the IPF Colormaps when trying to superimpose the crystal shapes after rotating with keepXY...

For some additional context, the EBSD data I have (not shown) has the following sample orientations:

EBSD_X || AM_X EBSD_Y || AM_Z EBSD_Z || AM_Y

Where "EBSD_" is analogous to the A_1, A_2, A3 reference frame Reference Frame Alignment page, and the "AM" reference frame is the microstructure relevant reference frame I'm trying to display my data in (similar to RD, TD, ND in rolled sheet).

A -90° Rotation about X puts the EBSD and AM coordinate systems in alignment, so that's why I'd been applying the that rotation, and I wanted to keep the map coordinates so I used the 'keepXY' flag.

Here's the IPF colormaps for X, Y, and Z respectively: Debug-fig11 Debug-fig12 Debug-fig13

And the superimposed crystal shapes on the Z IPF colormap: Debug-fig14

Then I've applied the -90° rotation, and as expected the IPF colormaps for Y and Z switch (not shown individually). But here's the Z IPF colormap with superimposed crystal shapes on the rotated data: Debug-fig24

On first glance, all looks like one would expect. The crystals rotate between the two plots, and the colors swap between Y and Z. But if look at it with the view relative to the grain shapes, they have have not moved (since I choose keepXY). To me, that implies that the crystal shape should not move between the plots if the 'keepXY' option was applied. I think what I'd want here is an option when showing the crystal shape to keepXY as well...

PS I've talked to a few other people about a similar issues in rotations of sample coordinate systems. The Reference Frame Alignment page is a good starting point, but I think there are some additional subtleties. If you want I can see if I could create a good example to help folks with this?

Also, I cleaned up the example script below if it's useful:

% From https://mtex-toolbox.github.io/CrystalShapes.html

% import some hexagonal data
mtexdata titanium;

%% part 1 - no data rotation, plotting convention matches EBSD axes

% Explicity set plotting convention
setMTEXpref('xAxisDirection','east');
setMTEXpref('zAxisDirection','intoPlane');

CrystalPlot(ebsd, ebsd.CS, 10)

%% part 2 - rotate orienttations by 90 about x

ebsd_data=ebsd;

ebsd_p2 = rotate(ebsd,rotation('axis',xvector,'angle',-90*degree),'keepXY');

CrystalPlot(ebsd_p2, ebsd_p2.CS, 20)

%% use a function to pass EBSD data
function CrystalPlot(ebsd_data, CrySym, figcounter)

% Define an orientation map for colorkey
oM = ipfHSVKey(CrySym);

% compute some grains
grains = calcGrains(ebsd_data);
grains = smooth(grains,5);

%% Plot the X vector map
oM.inversePoleFigureDirection = xvector;

% transform orientations into a list of colors
color = oM.orientation2color(ebsd_data.orientations);

figure(1+figcounter);
plot(ebsd_data,color,'figSize','huge','micronbar','off');
hold on;

plot(grains.boundary,'linewidth',2,'linecolor','k');
%plot(grains2('Ni-superalloy').boundary,'linewidth',1,'linecolor','k');

hold off;

%% Plot the Y vector map
oM.inversePoleFigureDirection = yvector;

% transform orientations into a list of colors
color = oM.orientation2color(ebsd_data.orientations);

figure(2+figcounter);
plot(ebsd_data,color,'figSize','huge','micronbar','off');
hold on;

plot(grains.boundary,'linewidth',2,'linecolor','k');
%plot(grains2('Ni-superalloy').boundary,'linewidth',1,'linecolor','k');

hold off;

%% Plot the Z vector map
oM.inversePoleFigureDirection = zvector;

% transform orientations into a list of colors
color = oM.orientation2color(ebsd_data.orientations);

figure(3+figcounter);
plot(ebsd_data,color,'figSize','huge','micronbar','off');
hold on;

plot(grains.boundary,'linewidth',2,'linecolor','k');
%plot(grains2('Ni-superalloy').boundary,'linewidth',1,'linecolor','k');

hold off;

%% Plot the default (Z vector?) map with grains superimposed
% define a simple hexagonal crystal shape
cS = crystalShape.hex(ebsd_data.CS)

% and plot them
figure(4+figcounter);
plot(grains,grains.meanOrientation)

% find the big ones
isBig = grains.grainSize>50;

% define a list of crystal shape that is oriented as the grain mean
% orientation and scaled according to the grain area
cSGrains = grains(isBig).meanOrientation * cS * 0.7 * sqrt(grains(isBig).area);

% now we can plot these crystal shapes at the grain centers
hold on
plot(grains(isBig).centroid + cSGrains)
hold off

%% Scatter Plot Pole Figure
% disp('Plot Pole Figure with Grain Sizes')

%Use sqrt of area

%which crystal planes
%MUST also show symettry
h = Miller({1,0,0},{1,1,0},{1,1,1},CrySym);

figure(5+figcounter); % plot in a new window
%plotPDF(ori,h)
%Plot all the points

plotPDF(grains.meanOrientation,h,'points','all','marker','o',...
    'MarkerSize',3, 'MarkerEdgeColor','k','MarkerFaceColor','k');

end