Example #1
0
    def plot_ipf(self, **kwargs):
        """ Create the inverse pole figure for direction Z.

        :param ax: a reference to a pyplot ax to draw the poles.
        :param mk: marker used to plot the poles (square by default).
        :param bool ann: Annotate the pole with the coordinates of the vector
            if True (False by default).
        
        """
        ax = kwargs.get('ax')
        self.plot_pf_background(ax, labels=False)
        # now plot the sample axis
        for grain in self.microstructure.grains:
            g = Orientation.Rodrigues2OrientationMatrix(grain['orientation'])
            if self.axis == 'Z':
                axis = self.z
            elif self.axis == 'Y':
                axis = self.y
            else:
                axis = self.x
            axis_rot = g.dot(axis)
            kwargs['col'] = self.get_color_from_field(grain)
            self.plot_crystal_dir(axis_rot, **kwargs)
            if self.verbose:
                print('plotting ', self.axis, ' in crystal CS:', axis_rot)
        ax.axis([-1.1, 1.1, -1.1, 1.1])
        ax.axis('off')
        ax.set_title('%s-axis inverse %s projection' % (self.axis, self.proj))
Example #2
0
    def create_pf_contour(self, ax=None, ang_step=10):
        """Compute the distribution of orientation and plot it using contouring.

        This plot the distribution of orientation in the microstructure
        associated with this PoleFigure instance, as a continuous
        distribution using angular bining with the specified step.
        the distribution is constructed at runtime by discretizing the
        angular space and counting the number of poles in each bin.
        Then the plot_pf_contour method is called to actually plot the data.

        .. warning::

           This function has not been tested properly, use at your own risk.

        :param ax: a reference to a pyplot ax to draw the contours.
        :param int ang_step: angular step in degrees to use for constructing
            the orientation distribution data (10 degrees by default)
        
        """
        # discretise the angular space (azimuth and altitude)
        ang_step *= np.pi / 180  # change to radians
        n_phi = int(1 + 2 * np.pi / ang_step)
        n_psi = int(1 + 0.5 * np.pi / ang_step)
        phis = np.linspace(0, 2 * np.pi, n_phi)
        psis = np.linspace(0, np.pi / 2, n_psi)
        xv, yv = np.meshgrid(phis, psis)
        values = np.zeros((n_psi, n_phi), dtype=int)
        for grain in self.microstructure.grains:
            g = Orientation.Rodrigues2OrientationMatrix(grain['orientation'])
            gt = g.transpose()
            for hkl_plane in self.poles:
                c = hkl_plane.normal()
                c_rot = gt.dot(c)
                # handle poles pointing down
                if c_rot[2] < 0:
                    c_rot *= -1  # make unit vector have z>0
                if c_rot[1] >= 0:
                    phi = np.arccos(c_rot[0] /
                                    np.sqrt(c_rot[0]**2 + c_rot[1]**2))
                else:
                    phi = 2 * np.pi - np.arccos(
                        c_rot[0] / np.sqrt(c_rot[0]**2 + c_rot[1]**2))
                psi = np.arccos(c_rot[2])  # since c_rot is normed
                i_phi = int((phi + 0.5 * ang_step) / ang_step) % n_phi
                j_psi = int((psi + 0.5 * ang_step) / ang_step) % n_psi
                values[j_psi, i_phi] += 1
        if self.proj == 'stereo':  # double check which one is flat/stereo
            x = (2 * yv / np.pi) * np.cos(xv)
            y = (2 * yv / np.pi) * np.sin(xv)
        else:
            x = np.sin(yv) * np.cos(xv)
            y = np.sin(yv) * np.sin(xv)
        # close the pole figure by duplicating azimuth=0
        values[:, -1] = values[:, 0]
        self.plot_pf_contour(ax, x, y, values)
Example #3
0
    def plot_pf(self, ax=None, mk='o', ann=False):
        """Create the direct pole figure.

        :param ax: a reference to a pyplot ax to draw the poles.
        :param mk: marker used to plot the poles (disc by default).
        :param bool ann: Annotate the pole with the coordinates of the vector
            if True (False by default).
            
        """
        self.plot_pf_background(ax)
        kwargs = {'ax': ax, 'mk': mk, 'ann': ann}
        if self.resize_markers:
            # compute the max grain volume to normalize
            volume_max = max(self.microstructure.get_grain_volumes())
        for grain in self.microstructure.grains:
            g = Orientation.Rodrigues2OrientationMatrix(grain['orientation'])
            gt = g.transpose()
            if self.resize_markers:
                kwargs['mksize'] = 0.15 * np.sqrt(
                    grain['volume'] / volume_max) * 1000
            label = ''
            if self.map_field == 'grain_id':
                label = 'grain ' + str(grain['idnumber'])
            kwargs['lab'] = label

            for i, hkl_plane in enumerate(self.poles):
                if i > 0:
                    kwargs['lab'] = ''
                c = hkl_plane.normal()
                c_rot = gt.dot(c)
                if self.verbose:
                    h, k, l = hkl_plane.miller_indices()
                    print('plotting (%d%d%d) with normal %s in sample CS '
                          '(corrected for pf axis): %s' % (h, k, l, c, c_rot))
                col = self.get_color_from_field(grain)
                kwargs['col'] = col
                self.plot_pf_dir(c_rot, **kwargs)
        ax.axis([-1.1, 1.1, -1.1, 1.1])
        if self.pflegend and self.map_field == 'grain_id':
            ax.legend(bbox_to_anchor=(0.05, 1),
                      loc=1,
                      numpoints=1,
                      prop={'size': 10})
        ax.axis('off')
        ax.set_title('{%s} direct %s projection' % (self.family, self.proj))
Example #4
0
 def test_RodriguesConversion(self):
     rod = [0.1449, -0.0281, 0.0616]
     g = Orientation.Rodrigues2OrientationMatrix(rod)
     calc_rod = Orientation.OrientationMatrix2Rodrigues(g)
     for i in range(3):
         self.assertAlmostEquals(calc_rod[i], rod[i])
Example #5
0
    def plot_sst(self, **kwargs):
        """ Create the inverse pole figure in the unit standard triangle.

        :param ax: a reference to a pyplot ax to draw the poles.
        :param mk: marker used to plot the poles (square by default).
        :param bool ann: Annotate the pole with the coordinates of the vector
            if True (False by default).
        
        """
        # first draw the boundary of the symmetry domain limited by 3 hkl plane
        # normals, called here A, B and C
        symmetry = self.lattice.get_symmetry()
        ax = kwargs.get('ax')
        if symmetry is Symmetry.cubic:
            sst_poles = [(0, 0, 1), (1, 0, 1), (1, 1, 1)]
            ax.axis([-0.05, 0.45, -0.05, 0.40])
        elif symmetry is Symmetry.hexagonal:
            sst_poles = [(0, 0, 1), (2, -1, 0), (1, 0, 0)]
            ax.axis([-0.05, 1.05, -0.05, 0.6])
        else:
            print('unsuported symmetry: %s' % symmetry)
        A = HklPlane(*sst_poles[0], lattice=self.lattice)
        B = HklPlane(*sst_poles[1], lattice=self.lattice)
        C = HklPlane(*sst_poles[2], lattice=self.lattice)
        self.plot_line_between_crystal_dir(A.normal(),
                                           B.normal(),
                                           ax=ax,
                                           col='k')
        self.plot_line_between_crystal_dir(B.normal(),
                                           C.normal(),
                                           ax=ax,
                                           col='k')
        self.plot_line_between_crystal_dir(C.normal(),
                                           A.normal(),
                                           ax=ax,
                                           col='k')
        # display the 3 crystal axes
        poles = [A, B, C]
        v_align = ['top', 'top', 'bottom']
        for i in range(3):
            hkl = poles[i]
            c_dir = hkl.normal()
            c = c_dir + self.z
            c /= c[2]  # SP'/SP = r/z with r=1
            pole_str = '%d%d%d' % hkl.miller_indices()
            if symmetry is Symmetry.hexagonal:
                pole_str = '%d%d%d%d' % HklPlane.three_to_four_indices(
                    *hkl.miller_indices())
            ax.annotate(pole_str, (c[0], c[1] - (2 * (i < 2) - 1) * 0.01),
                        xycoords='data',
                        fontsize=12,
                        horizontalalignment='center',
                        verticalalignment=v_align[i])

        # now plot the sample axis
        if self.resize_markers:
            # compute the max grain volume to normalize
            volume_max = max(self.microstructure.get_grain_volumes())
        for grain in self.microstructure.grains:
            g = Orientation.Rodrigues2OrientationMatrix(grain['orientation'])
            if self.resize_markers:
                kwargs['mksize'] = 0.15 * np.sqrt(
                    grain['volume'] / volume_max) * 1000
            # compute axis and apply SST symmetry
            if self.axis == 'Z':
                axis = self.z
            elif self.axis == 'Y':
                axis = self.y
            else:
                axis = self.x
            axis_rot = self.sst_symmetry(g.dot(axis))
            label = ''
            if self.map_field == 'grain_id':
                label = 'grain ' + str(grain['idnumber'])
            kwargs['lab'] = label
            kwargs['col'] = self.get_color_from_field(grain)
            self.plot_crystal_dir(axis_rot, **kwargs)
            if self.verbose:
                print('plotting %s in crystal CS: %s' % (self.axis, axis_rot))
        ax.axis('off')
        ax.set_title('%s-axis SST inverse %s projection' %
                     (self.axis, self.proj))