@@ -594,7 +594,7 @@ def _docstringer(docstring: _Union[str, _Callable],
594594 docstring : str or callable, optional
595595 Docstring (of callable) to extend.
596596 adopted_* : str or callable, optional
597- Additional information to insert into/ append to respective section.
597+ Additional information to insert into or append to respective section.
598598
599599 Notes
600600 -----
@@ -680,7 +680,7 @@ def extend_docstring(docstring: _Union[None, str, _Callable] = None,
680680 docstring : str or callable, optional
681681 Docstring to extend. Defaults to that of decorated function.
682682 adopted_* : str or callable, optional
683- Additional information to insert into/ append to respective section.
683+ Additional information to insert into or append to respective section.
684684
685685 Notes
686686 -----
@@ -804,6 +804,49 @@ def get_cell_data_group(f: _h5py.File) -> str:
804804 return get_cell_data_group (f )
805805
806806
807+ def _standardize_MillerBravais (idx : _IntSequence ) -> _np .ndarray :
808+ """
809+ Convert Miller-Bravais indices with missing component to standard (full) form.
810+
811+ Parameters
812+ ----------
813+ idx : numpy.ndarray, shape (...,4) or (...,3)
814+ Miller–Bravais indices of crystallographic direction [uvtw] or plane normal (hkil).
815+ The third index (t or i) can be omitted completely or given as "..." (Ellipsis).
816+
817+ Returns
818+ -------
819+ uvtw|hkil : numpy.ndarray, shape (...,4)
820+ Miller-Bravais indices of [uvtw] direction or (hkil) plane normal.
821+
822+ """
823+ def expand (v : _np .ndarray ) -> _np .ndarray :
824+ """Expand from 3 to 4 indices."""
825+ return _np .block ([v [...,:2 ], - _np .sum (v [...,:2 ],axis = - 1 ,keepdims = True ), v [...,2 :]])
826+
827+ a = _np .asarray (idx )
828+ if _np .issubdtype (a .dtype ,_np .signedinteger ):
829+ if a .shape [- 1 ] == 4 :
830+ if (_np .sum (a [...,:3 ],axis = - 1 ) != 0 ).any (): raise ValueError (rf'u+v+t≠0 | h+k+i≠0: { a } ' )
831+ return a
832+ elif a .shape [- 1 ] == 3 :
833+ return expand (a )
834+ else :
835+ if a .shape [- 1 ] == 4 :
836+ b = (_np .block ([a [...,:2 ],
837+ _np .where (a [...,2 :3 ] == ..., - _np .sum (a [...,:2 ],axis = - 1 ,keepdims = True ),a [...,2 :3 ]),
838+ a [...,3 :]]))
839+ if (_np .sum (b [...,:3 ].astype (int ),axis = - 1 ) != 0 ).any (): raise ValueError (rf'u+v+t≠0 | h+k+i≠0: { b } ' )
840+ elif a .shape [- 1 ] == 3 :
841+ b = expand (a )
842+
843+ if (b != (c := b .astype (int ))).any ():
844+ raise ValueError (f'"uvtw" | "hkil" are not (castable to) signed integers: { a } ' )
845+ return c
846+
847+ raise ValueError (f'invalid Miller-Bravais indices { a } ' )
848+
849+
807850def Bravais_to_Miller (* ,
808851 uvtw : _Optional [_IntSequence ] = None ,
809852 hkil : _Optional [_IntSequence ] = None ) -> _np .ndarray :
@@ -812,8 +855,9 @@ def Bravais_to_Miller(*,
812855
813856 Parameters
814857 ----------
815- uvtw|hkil : numpy.ndarray, shape (...,4)
858+ uvtw|hkil : numpy.ndarray, shape (...,4) or (...,3)
816859 Miller–Bravais indices of crystallographic direction [uvtw] or plane normal (hkil).
860+ The third index (t or i) can be omitted completely or given as "..." (Ellipsis).
817861
818862 Returns
819863 -------
@@ -823,23 +867,22 @@ def Bravais_to_Miller(*,
823867 """
824868 if (uvtw is not None ) ^ (hkil is None ):
825869 raise KeyError ('specify either "uvtw" or "hkil"' )
826- if uvtw is not None and (_np .sum (_np .asarray (uvtw )[...,:3 ],axis = - 1 ) != 0 ).any ():
827- raise ValueError (rf'u+v+t≠0: { uvtw } ' )
828- if hkil is not None and (_np .sum (_np .asarray (hkil )[...,:3 ],axis = - 1 ) != 0 ).any ():
829- raise ValueError (rf'h+k+i≠0: { hkil } ' )
830-
831- axis ,basis = (_np .array (uvtw ),_np .array ([[2 ,1 ,0 ,0 ],
832- [1 ,2 ,0 ,0 ],
833- [0 ,0 ,0 ,1 ]])) \
834- if hkil is None else \
835- (_np .array (hkil ),_np .array ([[1 ,0 ,0 ,0 ],
836- [0 ,1 ,0 ,0 ],
837- [0 ,0 ,0 ,1 ]]))
870+ elif uvtw is not None :
871+ axis ,basis = _standardize_MillerBravais (uvtw ),_np .array ([[2 ,1 ,0 ,0 ],
872+ [1 ,2 ,0 ,0 ],
873+ [0 ,0 ,0 ,1 ]])
874+ elif hkil is not None :
875+ axis ,basis = _standardize_MillerBravais (hkil ),_np .array ([[1 ,0 ,0 ,0 ],
876+ [0 ,1 ,0 ,0 ],
877+ [0 ,0 ,0 ,1 ]])
838878 uvw_hkl = _np .einsum ('il,...l' ,basis ,axis )
839- if not _np .issubdtype (uvw_hkl .dtype ,_np .signedinteger ):
840- raise TypeError ('"uvtw"/"hkil" are not (signed) integers' )
879+
841880 return uvw_hkl // _np .gcd .reduce (uvw_hkl ,axis = - 1 ,keepdims = True )
842881
882+
883+ MillerBravais_to_Miller = Bravais_to_Miller
884+
885+
843886def Miller_to_Bravais (* ,
844887 uvw : _Optional [_IntSequence ] = None ,
845888 hkl : _Optional [_IntSequence ] = None ) -> _np .ndarray :
@@ -868,12 +911,16 @@ def Miller_to_Bravais(*,
868911 [ 0 , 1 , 0 ],
869912 [- 1 ,- 1 , 0 ],
870913 [ 0 , 0 , 1 ]]))
871- uvtw_hkil = _np .einsum ('il,...l' ,basis ,axis )
872- if not _np .issubdtype (uvtw_hkil .dtype ,_np .signedinteger ):
873- raise TypeError ('"uvw"/"hkl" are not (signed) integers' )
914+ if (axis != axis .astype (int )).any ():
915+ raise ValueError (f'"uvt" | "hki" are not (castable to) signed integers: { axis } ' )
916+ uvtw_hkil = _np .einsum ('il,...l' ,basis ,axis .astype (int ))
917+
874918 return uvtw_hkil // _np .gcd .reduce (uvtw_hkil ,axis = - 1 ,keepdims = True )
875919
876920
921+ Miller_to_MillerBravais = Miller_to_Bravais
922+
923+
877924def dict_prune (d : _Dict ) -> _Dict :
878925 """
879926 Recursively remove empty dictionaries.
0 commit comments