def get_local_grid(resolution=2, center=None, grid_width=10):
    """
    Generates a grid of rotations about a given rotation

    Parameters
    ----------
    resolution : float, optional
        The characteristic distance between a rotation and its neighbour (degrees)
    center : euler angle tuple or orix.quaternion.rotation.Rotation, optional
        The rotation at which the grid is centered. If None (default) uses the identity
    grid_width : float, optional
        The largest angle of rotation away from center that is acceptable (degrees)

    Returns
    -------
    rotation_list : list of tuples
    """
    if isinstance(center, tuple):
        z = np.deg2rad(np.asarray(center))
        center = Rotation.from_euler(z,
                                     convention="bunge",
                                     direction="crystal2lab")

    orix_grid = get_sample_local(resolution=resolution,
                                 center=center,
                                 grid_width=grid_width)
    rotation_list = get_list_from_orix(orix_grid, rounding=2)
    return rotation_list
Exemplo n.º 2
0
def uniform_SO3_sample(resolution):
    """
    Returns rotations that are evenly spaced according to the Haar measure on
    SO3

    Parameters
    ----------
    resolution : float
        The characteristic distance between a rotation and its neighbour (degrees)

    Returns
    -------
    q : orix.quaternion.rotation.Rotation
        grid containing appropriate rotations
    """
    num_steps = int(np.ceil(360 / resolution))
    if num_steps % 2 == 1:
        num_steps = int(num_steps + 1)
    half_steps = int(num_steps / 2)

    alpha = np.linspace(0, 2 * np.pi, num=num_steps, endpoint=False)
    beta = np.arccos(np.linspace(1, -1, num=half_steps, endpoint=False))
    gamma = np.linspace(0, 2 * np.pi, num=num_steps, endpoint=False)
    q = np.asarray(list(product(alpha, beta, gamma)))

    # convert to quaternions
    q = Rotation.from_euler(q, convention="bunge", direction="crystal2lab")
    # remove duplicates
    q = q.unique()
    return q
Exemplo n.º 3
0
def dict2crystalmap(dictionary):
    """Get a crystal map from necessary items in a dictionary.

    Parameters
    ----------
    dictionary : dict
        Dictionary with crystal map information.

    Returns
    -------
    CrystalMap
    """
    dictionary = copy.deepcopy(dictionary)

    data = dictionary["data"]
    header = dictionary["header"]

    # New dictionary with CrystalMap initialization arguments as keys
    crystal_map_dict = {
        # Use dstack and squeeze to allow more rotations per data point
        "rotations":
        Rotation.from_euler(
            np.dstack((data.pop("phi1"), data.pop("Phi"),
                       data.pop("phi2"))).squeeze(), ),
        "scan_unit":
        header["scan_unit"],
        "phase_list":
        dict2phaselist(header["phases"]),
        "phase_id":
        data.pop("phase_id"),
        "is_in_data":
        data.pop("is_in_data"),
    }
    # Add standard items by updating the new dictionary
    for direction in ["z", "y", "x"]:
        this_direction = data.pop(direction)
        if hasattr(this_direction, "__iter__") is False:
            this_direction = None
        crystal_map_dict[direction] = this_direction
    _ = [data.pop(i) for i in ["id"]]
    # What's left should be properties like quality metrics etc.
    crystal_map_dict.update({"prop": data})

    return CrystalMap(**crystal_map_dict)
Exemplo n.º 4
0
def loadang(file_string: str):
    """Load ``.ang`` files.

    Parameters
    ----------
    file_string : str
        Path to the ``.ang`` file. This file is assumed to list the Euler
        angles in the Bunge convention in the first three columns.

    Returns
    -------
    Rotation

    """
    from orix.quaternion.rotation import Rotation
    data = np.loadtxt(file_string)
    euler = data[:, :3]
    rotation = Rotation.from_euler(euler)
    return rotation
def get_grid_around_beam_direction(beam_rotation,
                                   resolution,
                                   angular_range=(0, 360)):
    """
    Creates a rotation list of rotations for which the rotation is about given beam direction

    Parameters
    ----------
    beam_rotation : tuple
        A desired beam direction as a rotation (rzxz eulers), usually found via get_rotation_from_z_to_direction

    resolution : float
        The resolution of the grid (degrees)

    angular_range : tuple
        The minimum (included) and maximum (excluded) rotation around the beam direction to be included

    Returns
    -------
    rotation_list : list of tuples

    Example
    -------
    >>> from diffsims.generators.zap_map_generator import get_rotation_from_z_to_direction
    >>> beam_rotation = get_rotation_from_z_to_direction(structure,[1,1,1])
    >>> grid = get_grid_around_beam_direction(beam_rotation,1)
    """
    z = np.deg2rad(np.asarray(beam_rotation))
    beam_rotation = Rotation.from_euler(z,
                                        convention="bunge",
                                        direction="crystal2lab")

    angles = np.deg2rad(
        np.arange(start=angular_range[0],
                  stop=angular_range[1],
                  step=resolution))
    axes = np.repeat([[0, 0, 1]], angles.shape[0], axis=0)
    in_plane_rotation = Rotation.from_neo_euler(
        AxAngle.from_axes_angles(axes, angles))

    orix_grid = beam_rotation * in_plane_rotation
    rotation_list = get_list_from_orix(orix_grid, rounding=2)
    return rotation_list
Exemplo n.º 6
0
def loadctf(file_string: str):
    """Load ``.ang`` files.

    Parameters
    ----------
    file_string : str
        Path to the ``.ctf`` file. This file is assumed to list the Euler
        angles in the Bunge convention in the columns 5, 6, and 7.

    Returns
    -------
    Rotation

    """

    from orix.quaternion.rotation import Rotation
    data = np.loadtxt(file_string, skiprows=17)[:, 5:8]
    euler = np.radians(data)
    rotation = Rotation.from_euler(euler)
    return rotation
Exemplo n.º 7
0
 def test_from_to_matrix2(self, e):
     r = Rotation.from_euler(e.reshape((5, 2, 3)))
     assert np.allclose(Rotation.from_matrix(r.to_matrix()).data, r.data)
Exemplo n.º 8
0
 def test_unsupported_conv_from(self, e):
     with pytest.raises(ValueError, match="The chosen convention is not one of "):
         _ = Rotation.from_euler(e, convention="unsupported")
Exemplo n.º 9
0
 def test_passing_degrees_warns(self):
     with pytest.warns(UserWarning, match="Angles are assumed to be in radians, "):
         r = Rotation.from_euler([90, 0, 0], convention="bunge")
         assert np.allclose(r.data, [0.5253, 0, 0, -0.8509], atol=1e-4)
Exemplo n.º 10
0
 def test_direction_kwarg_dumb(self, e):
     with pytest.raises(ValueError, match="The chosen direction is not one of "):
         _ = Rotation.from_euler(e, direction="dumb_direction")
Exemplo n.º 11
0
 def test_unsupported_conv_to(self, e):
     r = Rotation.from_euler(e)
     with pytest.raises(ValueError, match="The chosen convention is not supported,"):
         _ = r.to_euler(convention="unsupported")
Exemplo n.º 12
0
 def test_direction_kwarg(self, e):
     _ = Rotation.from_euler(e, direction="lab2crystal")
Exemplo n.º 13
0
 def test_Krakow_Hielscher(self, e):
     _ = Rotation.from_euler(e, convention="Krakow_Hielscher")
Exemplo n.º 14
0
def test_direction_kwarg(e):
    r = Rotation.from_euler(e, direction="lab2crystal")
Exemplo n.º 15
0
def test_direction_kwarg_dumb(e):
    r = Rotation.from_euler(e, direction="dumb_direction")
Exemplo n.º 16
0
def test_unsupported_conv_to(e):
    r = Rotation.from_euler(e)
    r.to_euler(convention="unsupported")
Exemplo n.º 17
0
Arquivo: ang.py Projeto: haal9751/orix
def file_reader(filename):
    """Return a :class:`~orix.crystal_map.crystal_map.CrystalMap` object
    from a file in EDAX TLS's .ang format. The map in the input is
    assumed to be 2D.

    Many vendors produce an .ang file. Supported vendors are
    * EDAX TSL

    * NanoMegas ASTAR Index

    * EMsoft (from program `EMdpmerge`)

    * orix

    All points satisfying the following criteria are classified as not
    indexed:

    * EDAX TSL: confidence index == -1

    Parameters
    ----------
    filename : str
        Path and file name.

    Returns
    -------
    CrystalMap
    """
    # Get file header
    with open(filename) as f:
        header = _get_header(f)

    # Get phase names and crystal symmetries from header (potentially empty)
    phase_ids, phase_names, symmetries, lattice_constants = _get_phases_from_header(
        header)
    structures = []
    for name, abcABG in zip(phase_names, lattice_constants):
        structures.append(Structure(title=name, lattice=Lattice(*abcABG)))

    # Read all file data
    file_data = np.loadtxt(filename)

    # Get vendor and column names
    n_rows, n_cols = file_data.shape
    vendor, column_names = _get_vendor_columns(header, n_cols)

    # Data needed to create a CrystalMap object
    data_dict = {
        "euler1": None,
        "euler2": None,
        "euler3": None,
        "x": None,
        "y": None,
        "phase_id": None,
        "prop": {},
    }
    for column, name in enumerate(column_names):
        if name in data_dict.keys():
            data_dict[name] = file_data[:, column]
        else:
            data_dict["prop"][name] = file_data[:, column]

    # Add phase list to dictionary
    data_dict["phase_list"] = PhaseList(
        names=phase_names,
        point_groups=symmetries,
        structures=structures,
        ids=phase_ids,
    )

    # Set which data points are not indexed
    if vendor in ["orix", "tsl"]:
        data_dict["phase_id"][np.where(data_dict["prop"]["ci"] == -1)] = -1
    # TODO: Add not-indexed convention for INDEX ASTAR

    # Set scan unit
    if vendor in ["tsl", "emsoft"]:
        scan_unit = "um"
    else:  # NanoMegas
        scan_unit = "nm"
    data_dict["scan_unit"] = scan_unit

    # Create rotations
    data_dict["rotations"] = Rotation.from_euler(
        np.column_stack((data_dict.pop("euler1"), data_dict.pop("euler2"),
                         data_dict.pop("euler3"))), )

    return CrystalMap(**data_dict)
Exemplo n.º 18
0
def test_unsupported_conv_from(e):
    r = Rotation.from_euler(e, convention="unsupported")
Exemplo n.º 19
0
 def test_to_from_euler(self, e):
     """Checks that going euler2quat2euler gives no change."""
     r = Rotation.from_euler(e)
     e2 = r.to_euler()
     assert np.allclose(e, e2.data)
Exemplo n.º 20
0
def file_reader(filename, refined=False, **kwargs):
    """Return a :class:`~orix.crystal_map.crystal_map.CrystalMap` object
    from a file in EMsoft's dictionary indexing dot product file format.

    Parameters
    ----------
    filename : str
        Path and file name.
    refined : bool, optional
        Whether to return refined orientations (default is False).
    kwargs
        Keyword arguments passed to :func:`h5py.File`.

    Returns
    -------
    CrystalMap
    """
    mode = kwargs.pop("mode", "r")
    f = File(filename, mode=mode, **kwargs)

    # Get groups for convenience
    ebsd_group = f["Scan 1/EBSD"]
    data_group = ebsd_group["Data"]
    header_group = ebsd_group["Header"]
    phase_group = header_group["Phase/1"]

    # Get map shape and step sizes
    ny = header_group["nRows"][:][0]
    nx = header_group["nColumns"][:][0]
    step_y = header_group["Step Y"][:][0]
    map_size = ny * nx

    # Some of the data needed to create a CrystalMap object
    phase_name, point_group, structure = _get_phase(phase_group)
    data_dict = {
        # Get map coordinates ("Y Position" data set is not correct in EMsoft as of
        # 2020-04, see:
        # https://github.com/EMsoft-org/EMsoft/blob/7762e1961508fe3e71d4702620764ceb98a78b9e/Source/EMsoftHDFLib/EMh5ebsd.f90#L1093)
        "x":
        data_group["X Position"][:],
        # y = data_group["Y Position"][:]
        "y":
        np.sort(np.tile(np.arange(ny) * step_y, nx)),
        # Get phase IDs
        "phase_id":
        data_group["Phase"][:],
        # Get phase name, point group and structure (lattice)
        "phase_list":
        PhaseList(
            Phase(name=phase_name,
                  point_group=point_group,
                  structure=structure)),
        "scan_unit":
        "um",
    }

    # Get rotations
    if refined:
        euler = data_group["RefinedEulerAngles"][:]  # Radians
    else:  # Get n top matches for each pixel
        top_match_idx = data_group["TopMatchIndices"][:][:map_size] - 1
        dictionary_size = data_group["FZcnt"][:][0]
        # Degrees
        dictionary_euler = data_group[
            "DictionaryEulerAngles"][:][:dictionary_size]
        dictionary_euler = np.deg2rad(dictionary_euler)
        euler = dictionary_euler[top_match_idx, :]
    data_dict["rotations"] = Rotation.from_euler(euler)

    # Get number of top matches kept per data point
    n_top_matches = f["NMLparameters/EBSDIndexingNameListType/nnk"][:][0]

    data_dict["prop"] = _get_properties(
        data_group=data_group,
        n_top_matches=n_top_matches,
        map_size=map_size,
    )

    f.close()

    return CrystalMap(**data_dict)