2020from copy import deepcopy
2121
2222from diffpy .structure .symmetryutilities import expandPosition
23- from diffpy .structure import Structure
23+ from diffpy .structure import Structure , Lattice
2424import numba as nb
2525import numpy as np
2626from orix .vector import Miller , Vector3d
@@ -696,33 +696,17 @@ def calculate_structure_factor(
696696 """
697697
698698 # Compute one structure factor per set {hkl}
699- hkl_sets = self .get_hkl_sets ()
700-
701- # For each set, get the indices of the first vector in the
702- # present vectors, accounting for potential multiple dimensions
703- # and avoding computing the unique vectors again
704- first_idx = []
705- for arr in list (hkl_sets .values ()):
706- i = []
707- for arr_i in arr :
708- i .append (arr_i [0 ])
709- first_idx .append (i )
710- first_idx_arr = np .array (first_idx ).T
711-
712- # Get 2D array of unique vectors, one for each set
713- hkl_unique = self .hkl [tuple (first_idx_arr )]
714-
699+ unique , inds = self .unique (use_symmetry = True , return_inverse = True )
700+ hkl_unique = unique .hkl
715701 structure_factor = _get_kinematical_structure_factor (
716702 structure = self .phase .structure ,
717703 g_indices = hkl_unique ,
718704 g_hkls_array = self .phase .structure .lattice .rnorm (hkl_unique ),
719705 debye_waller_factors = debye_waller_factors ,
720706 scattering_params = scattering_params ,
721707 )
722-
723708 # Set structure factors of all symmetrically equivalent vectors
724- for i , idx in enumerate (hkl_sets .values ()):
725- self ._structure_factor [idx ] = structure_factor [i ]
709+ self ._structure_factor [:] = structure_factor [inds ]
726710
727711 def calculate_theta (self , voltage ):
728712 r"""Populate :attr:`theta` with the Bragg angle :math:`theta_B`
@@ -1517,7 +1501,7 @@ def transpose(self, *axes):
15171501 new ._update_shapes ()
15181502 return new
15191503
1520- def unique (self , use_symmetry = False , return_index = False ):
1504+ def unique (self , use_symmetry = False , return_index = False , return_inverse = False ):
15211505 """The unique vectors.
15221506
15231507 Parameters
@@ -1528,48 +1512,51 @@ def unique(self, use_symmetry=False, return_index=False):
15281512 return_index : bool, optional
15291513 Whether to return the indices of the (flattened) data where
15301514 the unique entries were found. Default is ``False``.
1515+ return_inverse: bool, optional
1516+ Whether to also return the indices to reconstruct the
1517+ (flattened) data from the unique data.
15311518
15321519 Returns
15331520 -------
15341521 ReciprocalLatticeVector
15351522 Flattened unique vectors.
15361523 idx : numpy.ndarray
15371524 Indices of the unique data in the (flattened) array.
1538-
1525+ inv : numpy.ndarray
1526+ Indices to reconstruct the original vectors from the unique
15391527 """
15401528
15411529 # TODO: Reduce floating point precision in orix!
15421530 def miller_unique (miller , use_symmetry = False ):
1543- v , idx = Vector3d (miller ).unique (return_index = True )
1531+ v , idx , inv = Vector3d (miller ).unique (return_index = True , return_inverse = True )
1532+ idx = idx [::- 1 ]
1533+ inv = inv [::- 1 ]
15441534
15451535 if use_symmetry :
15461536 operations = miller .phase .point_group
15471537 n_v = v .size
1548- v2 = operations .outer (v ).flatten ().reshape (* (n_v , operations .size ))
1538+ v2 = operations .outer (v [:: - 1 ] ).flatten ().reshape (* (n_v , operations .size ))
15491539 data = v2 .data .round (6 ) # Reduced precision
1550- data_sorted = np .zeros_like (data )
1551- for i in range (n_v ):
1552- a = data [i ]
1553- order = np .lexsort (a .T ) # Sort by column 1, 2, then 3
1554- data_sorted [i ] = a [order ]
1555- _ , idx = np .unique (data_sorted , return_index = True , axis = 0 )
1556- v = v [idx [::- 1 ]]
1540+ _ , idx , inv = np .unique (data , return_index = True , return_inverse = True , axis = 0 )
1541+ v = v [idx ]
15571542
15581543 m = miller .__class__ (xyz = v .data , phase = miller .phase )
15591544 m .coordinate_format = miller .coordinate_format
1560- return m , idx
15611545
1562- # kwargs = dict(use_symmetry=use_symmetry, return_index=True)
1563- # miller, idx = self.to_miller().unique(**kwargs)
1564- miller , idx = miller_unique (self .to_miller (), use_symmetry )
1565- idx = idx [::- 1 ]
1546+ return m , idx , inv
1547+
1548+ miller , idx , inv = miller_unique (self .to_miller (), use_symmetry )
15661549
15671550 new_rlv = self .from_miller (miller )
15681551 new_rlv ._structure_factor = self .structure_factor .ravel ()[idx ]
15691552 new_rlv ._theta = self .theta .ravel ()[idx ]
15701553
1571- if return_index :
1554+ if return_index and return_inverse :
1555+ return new_rlv , idx , inv
1556+ elif return_index :
15721557 return new_rlv , idx
1558+ elif return_inverse :
1559+ return new_rlv , inv
15731560 else :
15741561 return new_rlv
15751562
@@ -1623,7 +1610,7 @@ def _atom_eq(atom1, atom2):
16231610
16241611 return (
16251612 atom1 .element == atom2 .element
1626- and np .allclose (atom1 .xyz , atom2 .xyz , atol = 1e-7 )
1613+ and np .allclose (atom1 .xyz_cartn , atom2 .xyz_cartn , atol = 1e-7 )
16271614 and atom1 .occupancy == atom2 .occupancy
16281615 and np .allclose (atom1 .U , atom2 .U , atol = 1e-7 )
16291616 and np .allclose (atom1 .Uisoequiv , atom2 .Uisoequiv , atol = 1e-7 )
@@ -1646,9 +1633,17 @@ def _expand_unit_cell(space_group, structure):
16461633 new_structure : diffpy.structure.Structure
16471634
16481635 """
1649-
1636+ # Transform to diffpy axis conventions
1637+ structure_matrix = structure .lattice .base
1638+ pos = structure .xyz_cartn
1639+ structure = Structure (
1640+ atoms = list (structure ),
1641+ lattice = Lattice (* structure .lattice .abcABG ()),
1642+ )
16501643 new_structure = Structure (lattice = structure .lattice )
1644+ structure .xyz_cartn = pos
16511645
1646+ # Perform symmetry expansion
16521647 for atom in structure :
16531648 equal = []
16541649 for atom2 in new_structure :
@@ -1660,6 +1655,10 @@ def _expand_unit_cell(space_group, structure):
16601655 new_atom .xyz = new_position
16611656 new_structure .append (new_atom )
16621657
1658+ # Transform back to orix convention
1659+ old_xyz_cartn = new_structure .xyz_cartn
1660+ new_structure .lattice .setLatBase (structure_matrix )
1661+ new_structure .xyz_cartn = old_xyz_cartn
16631662 return new_structure
16641663
16651664
0 commit comments