コード例 #1
0
def get_spacegroup_type(hall_number):
    """
    Get space group information corresponding to the Hall number.

    Args:
        hall_number: Integer with the Hall number.

    Returns:
        Dictionary with the corresponding space group information. Keys:
        - `arithmetic_crystal_class_number`
        - `arithmetic_crystal_class_symbol`
        - `choice`
        - `hall_symbol`
        - 'international`
        - `international_full`
        - `international_short`
        - `number`
        - `pointgroup_international`
        - `pointgroup_schoenflies`
        - `schoenflies`

        None if `spglib` fails to determine space group type.

    Raises:
        ImportError: If `spglib` cannot be imported.

    """
    _check_spglib_install()
    return spglib.get_spacegroup_type(hall_number)
コード例 #2
0
ファイル: spg_mapping.py プロジェクト: tkotani/ecalj
def get_spgroup_data_realtime():
    """
    Return a dictionary that has the spacegroup number as key, and a tuple 
    as value, with (crystal family letter, centering, has_inversion),
    got in real time using spglib methods.
    """
    import json
    import spglib

    info = {}
    for hall_n in range(1, 531):
        data = spglib.get_spacegroup_type(hall_n)
        number = data['number']
        int_short = data['international_short']
        pg_int = data['pointgroup_international']

        if number not in info:
            info[int(number)] = (get_crystal_family(number),  # get cyrstal family
                                 # centering from the first letter of the first
                                 # spacegroup that I encounter
                                 int_short[0],
                                 pointgroup_has_inversion(pgnum_from_pgint(
                                     pg_int)),  # pointgroup has inversion
                                 )
    return info
コード例 #3
0
    def test_get_symmetry_dataset(self):
        for fname, spgnum, reffname in zip(self._filenames,
                                           self._spgnum_ref,
                                           self._ref_filenames):
            cell = read_vasp(fname)

            if 'distorted' in fname:
                symprec = 1e-1
            else:
                symprec = 1e-5
            dataset = get_symmetry_dataset(cell, symprec=symprec)
            self.assertEqual(dataset['number'], spgnum, msg=("%s" % fname))

            for i in range(spg_to_hall[spgnum - 1], spg_to_hall[spgnum]):
                dataset = get_symmetry_dataset(cell, hall_number=i,
                                               symprec=symprec)
                self.assertEqual(type(dataset), dict, msg=("%s/%d" % (fname, i)))
                self.assertEqual(dataset['hall_number'], i, msg=("%s" % fname))
                spg_type = get_spacegroup_type(dataset['hall_number'])
                self.assertEqual(dataset['international'],
                                 spg_type['international_short'],
                                 msg=("%s" % fname))
                self.assertEqual(dataset['hall'], spg_type['hall_symbol'],
                                 msg=("%s" % fname))
                self.assertEqual(dataset['choice'], spg_type['choice'],
                                 msg=("%s" % fname))
                self.assertEqual(dataset['pointgroup'],
                                 spg_type['pointgroup_schoenflies'],
                                 msg=("%s" % fname))

            wyckoffs = dataset['wyckoffs']
            with open(reffname) as f:
                wyckoffs_ref = yaml.load(f, Loader=yaml.FullLoader)['wyckoffs']
            for w, w_ref in zip(wyckoffs, wyckoffs_ref):
                self.assertEqual(w, w_ref, msg=("%s" % fname))
コード例 #4
0
ファイル: test_spglib.py プロジェクト: atztogo/spglib
    def test_find_primitive(self):
        for fname in self._filenames:
            cell = read_vasp(fname)
            if 'distorted' in fname:
                symprec = 1e-1
            else:
                symprec = 1e-5

            dataset = get_symmetry_dataset(cell, symprec=symprec)
            primitive = find_primitive(cell, symprec=symprec)

            spg_type = get_spacegroup_type(dataset['hall_number'])
            c = spg_type['international_short'][0]
            if c in ['A', 'B', 'C', 'I']:
                multiplicity = 2
            elif c == 'F':
                multiplicity = 4
            elif c == 'R':
                self.assertEqual(spg_type['choice'], 'H')
                if spg_type['choice'] == 'H':
                    multiplicity = 3
                else:  # spg_type['choice'] == 'R'
                    multiplicity = 1
            else:
                multiplicity = 1
            self.assertEqual(len(dataset['std_types']),
                             len(primitive[2]) * multiplicity,
                             msg=("multi: %d, %s" % (multiplicity, fname)))
コード例 #5
0
ファイル: test_spglib.py プロジェクト: atztogo/spglib
    def test_get_symmetry_dataset(self):
        for fname, spgnum, reffname in zip(self._filenames,
                                           self._spgnum_ref,
                                           self._ref_filenames):
            cell = read_vasp(fname)

            if 'distorted' in fname:
                symprec = 1e-1
            else:
                symprec = 1e-5
            dataset = get_symmetry_dataset(cell, symprec=symprec)
            self.assertEqual(dataset['number'], spgnum, msg=("%s" % fname))

            for i in range(spg_to_hall[spgnum - 1], spg_to_hall[spgnum]):
                dataset = get_symmetry_dataset(cell, hall_number=i,
                                               symprec=symprec)
                self.assertEqual(dataset['hall_number'], i, msg=("%s" % fname))
                spg_type = get_spacegroup_type(dataset['hall_number'])
                self.assertEqual(dataset['international'],
                                 spg_type['international_short'],
                                 msg=("%s" % fname))
                self.assertEqual(dataset['hall'], spg_type['hall_symbol'],
                                 msg=("%s" % fname))
                self.assertEqual(dataset['choice'], spg_type['choice'],
                                 msg=("%s" % fname))
                self.assertEqual(dataset['pointgroup'],
                                 spg_type['pointgroup_schoenflies'],
                                 msg=("%s" % fname))

            wyckoffs = dataset['wyckoffs']
            with open(reffname) as f:
                wyckoffs_ref = yaml.load(f)['wyckoffs']
            for w, w_ref in zip(wyckoffs, wyckoffs_ref):
                self.assertEqual(w, w_ref, msg=("%s" % fname))
コード例 #6
0
def get_spgroup_data_realtime():
    """
    Return a dictionary that has the spacegroup number as key, and a tuple
    as value, with content::

       (crystal family letter, centering, has_inversion),

    got in real time using spglib methods.
    """
    import json
    import spglib

    info = {}
    for hall_n in range(1, 531):
        data = spglib.get_spacegroup_type(hall_n)
        number = data["number"]
        int_short = data["international_short"]
        pg_int = data["pointgroup_international"]

        if number not in info:
            info[int(number)] = (
                get_crystal_family(number),  # get cyrstal family
                # centering from the first letter of the first
                # spacegroup that I encounter
                int_short[0],
                pointgroup_has_inversion(
                    pgnum_from_pgint(pg_int)),  # pointgroup has inversion
            )
    return info
コード例 #7
0
    def test_find_primitive(self):
        for fname in self._filenames:
            cell = read_vasp(fname)
            if 'distorted' in fname:
                symprec = 1e-1
            else:
                symprec = 1e-5

            dataset = get_symmetry_dataset(cell, symprec=symprec)
            primitive = find_primitive(cell, symprec=symprec)

            spg_type = get_spacegroup_type(dataset['hall_number'])
            c = spg_type['international_short'][0]
            if c in ['A', 'B', 'C', 'I']:
                multiplicity = 2
            elif c == 'F':
                multiplicity = 4
            elif c == 'R':
                self.assertEqual(spg_type['choice'], 'H')
                if spg_type['choice'] == 'H':
                    multiplicity = 3
                else:  # spg_type['choice'] == 'R'
                    multiplicity = 1
            else:
                multiplicity = 1
            self.assertEqual(len(dataset['std_types']),
                             len(primitive[2]) * multiplicity,
                             msg=("multi: %d, %s" % (multiplicity, fname)))
コード例 #8
0
    def test_get_symmetry_dataset(self):
        for fname, spgnum in zip(self._filenames, self._spgnum_ref):
            cell = read_vasp(fname)

            if 'distorted' in fname:
                symprec = 1e-1
            else:
                symprec = 1e-5
            dataset = get_symmetry_dataset(cell, symprec=symprec)
            self.assertEqual(dataset['number'], spgnum, msg=("%s" % fname))

            for i in range(spg_to_hall[spgnum - 1], spg_to_hall[spgnum]):
                dataset = get_symmetry_dataset(cell, hall_number=i,
                                               symprec=symprec)
                self.assertEqual(dataset['hall_number'], i, msg=("%s" % fname))
                spg_type = get_spacegroup_type(dataset['hall_number'])
                self.assertEqual(dataset['international'],
                                 spg_type['international_short'],
                                 msg=("%s" % fname))
                self.assertEqual(dataset['hall'], spg_type['hall_symbol'],
                                 msg=("%s" % fname))
                self.assertEqual(dataset['choice'], spg_type['choice'],
                                 msg=("%s" % fname))
                self.assertEqual(dataset['pointgroup'],
                                 spg_type['pointgroup_schoenflies'],
                                 msg=("%s" % fname))
コード例 #9
0
ファイル: sgacore.py プロジェクト: rknbeiv/Miscellaneous
def print_pointgroup(dataset):
    spacegroup_type = spglib.get_spacegroup_type(dataset['hall_number'])
    print "\nPOINT GROUP OF CRYSTAL"
    print "\tPoint group (number) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[0]
    print "\tPoint group (crystal family) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[1]
    print "\tPoint group (crystal_system) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[2]
    print "\tPoint group (crystal_class) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[3]
    print "\tPoint group (HM_inter_full) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[4]
    print "\tPoint group (HM_inter_short) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[5]
    print "\tPoint group (shubnikov) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[6]
    print "\tPoint group (schoenflies) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[7]
    print "\tPoint group (orbifold) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[8]
    print "\tPoint group (coxeter) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[9]
    print "\tPoint group (order) :: ", pointgroup_database(
        spacegroup_type['pointgroup_schoenflies'])[10]
コード例 #10
0
 def spacegroup_info(self):
     """Translate Hall number to space group type information.
     Returned as an attribute dict
     """
     info = spglib.get_spacegroup_type(self.hall_number)
     if info is None:
         raise ValueError("the hall number could not be converted")
     return AttributeDict(info)
コード例 #11
0
ファイル: spg.py プロジェクト: pearcandy/ciflib
def print_dataset(dataset):
    print('- ' + 'spg_dataset')
    print('  number', dataset['number'])
    print('  international', dataset['international'])
    print('  hall_symbol', dataset['hall'])
    print('  hall_number', dataset['hall_number'])
    print('  choice', dataset['choice'])
    print('  pointgroup', dataset['pointgroup'])
    print('  trans_matrix\n', dataset['transformation_matrix'])
    print('  original_shift\n', dataset['origin_shift'])
    hall_number = dataset['hall_number']
    sgtype = spglib.get_spacegroup_type(hall_number)
コード例 #12
0
def get_crystal_type_name(hall_number):
    """get crystal type code, denoting the crystal system

    Parameters
    ----------
    hall_number: int

    Returns
    -------
    crystal_type_name: str

    """
    sg_number = spglib.get_spacegroup_type(hall_number)["number"]
    return get_crystal_system_name(sg_number)
コード例 #13
0
    def get_iso(self, symprec):

        DG = self.matrices

        mat_list = [mat.rotation_matrix for mat in DG]
        vec_list = [mat.translation_vector for mat in DG]

        h_number = spglib.get_hall_number_from_symmetry(np.around(
            mat_list, decimals=4), np.around(vec_list, decimals=6), symprec = symprec)
        sg_type_data=spglib.get_spacegroup_type(h_number)
        iso_sg=sg_type_data['international_short']
        iso_sg_num=sg_type_data['number']

        return iso_sg, iso_sg_num
コード例 #14
0
def get_crystal_type_code(hall_number):
    """get crystal type code, denoting the crystal system

    Parameters
    ----------
    hall_number: int

    Returns
    -------
    crystal_type_code: int

    """
    sg_number = spglib.get_spacegroup_type(hall_number)["number"]
    crystal_type = get_crystal_system_name(sg_number)
    return CRYSTAL_TYPE_TO_NUM_MAP[crystal_type]
コード例 #15
0
def get_iso(path, iv):

    DG = path.get_DG()

    outputfile = open(iv.image_dir + "/../results/output.out", "a")

    h_number = spglib.get_hall_number_from_symmetry(np.around(DG[0][:],
                                                              decimals=4),
                                                    np.around(DG[1][:],
                                                              decimals=6),
                                                    symprec=iv.gentol)
    sg_type_data = spglib.get_spacegroup_type(h_number)
    iso_sg = sg_type_data['international_short']
    iso_sg_num = sg_type_data['number']

    return iso_sg, iso_sg_num
コード例 #16
0
ファイル: f34.py プロジェクト: tilde-lab/aiida-crystal-dft
    def read(self, file):
        """Read and parse fort.34 file"""
        if isinstance(file, str):
            with open(file) as f:
                data = f.read()
        else:
            data = file.read()
        parsed_data = _parse_string(f34_parser(), data)
        self.dimensionality, self.centring, self.crystal_type = parsed_data['header']
        if self.dimensionality != 3:
            raise NotImplementedError('Structure with dimensionality < 3 currently not supported')

        # primitive cell vectors and basis positions in cartesian coordinates
        abc = np.array(parsed_data['abc'].asList()).reshape((3, 3))
        positions = np.array([d[1:] for d in parsed_data['geometry']])

        # convert positions to fractional
        positions = np.dot(np.linalg.inv(abc).T, positions.T).T
        atomic_numbers = [d[0] for d in parsed_data['geometry']]

        # convert to conventional cell
        cell = (abc, positions, atomic_numbers)
        cell = spglib.standardize_cell(cell, to_primitive=False, no_idealize=False)
        self.abc, self.positions, atomic_numbers = cell

        # ECPs
        self.atomic_numbers = [num if num < 201 else num - 200 for num in atomic_numbers]

        # get symmetry operations
        self.n_symops = parsed_data['n_symops']
        self.symops = np.array(parsed_data['symops'].asList()).reshape(self.n_symops * 4, 3)
        rotations = np.zeros((self.n_symops, 3, 3))
        for i in range(3):
            rotations[:, i] = self.symops[i::4]

        # convert symmetry operations from cartesian to fractional
        rotations = np.dot(np.dot(np.linalg.inv(abc.T), rotations), abc.T)

        # have to round rotations matrix as it is used to find symmetry group
        rotations = np.round(np.swapaxes(rotations, 0, 1), 9)
        translations = np.dot(self.symops[3::4], np.linalg.inv(abc))
        hall = spglib.get_hall_number_from_symmetry(rotations, translations)
        self.space_group = int(spglib.get_spacegroup_type(hall)['number'])
        # we have conventional cell now
        return self
コード例 #17
0
ファイル: test_spglib.py プロジェクト: ltalirz/cod-tools
 def test_get_symmetry_dataset(self):
     for fname in self._filenames:
         spgnum = int(fname.split('-')[1])
         cell = read_vasp("./data/%s" % fname)
         if 'distorted' in fname:
             dataset = get_symmetry_dataset(cell, symprec=1e-1)
         else:
             dataset = get_symmetry_dataset(cell, symprec=1e-5)
         self.assertEqual(dataset['number'], spgnum,
                          msg=("%s" % fname))
         spg_type = get_spacegroup_type(dataset['hall_number'])
         self.assertEqual(dataset['international'],
                          spg_type['international_short'],
                          msg=("%s" % fname))
         self.assertEqual(dataset['hall'], spg_type['hall_symbol'],
                          msg=("%s" % fname))
         self.assertEqual(dataset['choice'], spg_type['choice'],
                          msg=("%s" % fname))
         self.assertEqual(dataset['pointgroup'],
                          spg_type['pointgroup_schoenflies'],
                          msg=("%s" % fname))
コード例 #18
0
def get_centering_code(hall_number):
    """get crystal centering codes, to convert from primitive to conventional

    Parameters
    ----------
    hall_number: int

    Returns
    -------
    centering_code: int

    """
    sg_data = spglib.get_spacegroup_type(hall_number)
    sg_symbol = sg_data["international"]
    lattice_type = get_lattice_type_name(sg_data["number"])
    crystal_type = get_crystal_system_name(sg_data["number"])

    if "P" in sg_symbol or lattice_type == "hexagonal":
        return 1
    elif lattice_type == "rhombohedral":
        # can also be P_R (if a_length == c_length in conventional cell),
        # but crystal doesn't appear to use that anyway
        return 1
    elif "I" in sg_symbol:
        return 6
    elif "F" in sg_symbol:
        return 5
    elif "C" in sg_symbol:
        if crystal_type == "monoclinic":
            return 4
            # TODO this is P_C but don't know what code it is, maybe 3?
            # [[1.0, -1.0, 0.0], [1.0, 1.0, 0.0], [0.0, 0.0, 1.0]]
        return 4
    # elif "A" in sg_symbol:
    #     return 2
    #     TODO check this is always correct (not in original function)

    return 1
コード例 #19
0
def gui_file_write(structure_data, symmetry_data=None):
    """Create string of gui file content (for CRYSTAL17).

    Parameters
    ----------
    structure_data: aiida.StructureData or dict or ase.Atoms
        dict with keys: 'pbc', 'atomic_numbers', 'ccoords', 'lattice',
        or ase.Atoms, or any object that has method structure_data.get_ase()
    symmetry_data: dict or None
        keys; 'crystal_type_code', 'centring_code', 'space_group',
        'operations', 'basis'

    Returns
    -------
    lines: list[str]
        list of lines in the file

    Notes
    -----
    Older versions of CRYSTAL are not compatible,
    because they only specify symmetrically inequivalent atomic positions
    (rather than all)

    Symmetry operations and atomic positions are assumed to be cartesian
    (rather than fractional)

    """
    structure_dict = convert_structure(structure_data, "dict")

    dimensionality = sum(structure_dict["pbc"])
    atomic_numbers = structure_dict["atomic_numbers"]
    ccoords = structure_dict["ccoords"]
    lattice = structure_dict["lattice"]

    if symmetry_data is None:
        structure = convert_structure(structure_data, "aiida")
        symmetry_data = structure_to_symmetry(structure)

    if isinstance(symmetry_data, dict):
        crystal_type = symmetry_data["crystal_type_code"]
        centring_code = symmetry_data["centring_code"]
        sg_num = symmetry_data["space_group"]
        symops = symmetry_data["operations"]
        basis = symmetry_data["basis"]
    else:
        # TODO specific test for SymmetryData, and move this to separate function
        symops = symmetry_data.data.operations
        basis = symmetry_data.data.basis
        hall_number = symmetry_data.hall_number
        if hall_number is None:
            hall_number = get_hall_number_from_symmetry(symops, basis, lattice)
        crystal_type = get_crystal_type_code(hall_number)
        centring_code = get_centering_code(hall_number)
        sg_num = spglib.get_spacegroup_type(hall_number)["number"]

    if basis == "fractional":
        symops = operations_frac_to_cart(symops, lattice)
    else:
        if basis != "cartesian":
            raise AssertionError(
                "symmetry basis must be fractional or cartesian")

    # sort the symmetry operations (useful to standardize for testing)
    # symops = np.sort(symops, axis=0)

    num_symops = len(symops)
    sym_lines = []
    for symop in symops:
        sym_lines.append(symop[0:3])
        sym_lines.append(symop[3:6])
        sym_lines.append(symop[6:9])
        sym_lines.append(symop[9:12])

    # for all output numbers, we round to 9 dp and add 0, so we don't get -0.0

    geom_str_list = []
    geom_str_list.append("{0} {1} {2}".format(dimensionality, centring_code,
                                              crystal_type))
    geom_str_list.append("{0:17.9E} {1:17.9E} {2:17.9E}".format(
        *(np.round(lattice[0], 9) + 0.0)))
    geom_str_list.append("{0:17.9E} {1:17.9E} {2:17.9E}".format(
        *(np.round(lattice[1], 9) + 0.0)))
    geom_str_list.append("{0:17.9E} {1:17.9E} {2:17.9E}".format(
        *(np.round(lattice[2], 9) + 0.0)))
    geom_str_list.append(str(num_symops))
    for sym_line in sym_lines:
        geom_str_list.append("{0:17.9E} {1:17.9E} {2:17.9E}".format(
            *(np.round(sym_line, 9) + 0.0)))
    geom_str_list.append(str(len(atomic_numbers)))
    for anum, coord in zip(atomic_numbers, ccoords):
        geom_str_list.append("{0:3} {1:17.9E} {2:17.9E} {3:17.9E}".format(
            anum, *(np.round(coord, 10) + 0.0)))

    geom_str_list.append("{0} {1}".format(sg_num, num_symops))
    geom_str_list.append("")

    return geom_str_list
コード例 #20
0
ファイル: crystal.py プロジェクト: interjz4/scikit-ued-1
    def spacegroup_info(self, symprec = 1e-2, angle_tolerance = -1.0):
        """ 
        Returns a dictionary containing space-group information. This information
        is computed from the crystal unit cell, and is not taken from records if available.
        
        Parameters
        ----------
        symprec : float, optional
            Symmetry-search distance tolerance in Cartesian coordinates [Angstroms].
        angle_tolerance: float, optional
            Symmetry-search tolerance in degrees. If the value is negative (default), 
            an internally optimized routine is used to judge symmetry.
        
        Returns
        -------
        info : dict or None
            Dictionary of space-group information. The following keys are available:

            * ``'international_symbol'``: International Tables of Crystallography space-group symbol (short);

            * ``'international_full'``: International Tables of Crystallography space-group full symbol;

            * ``'hall_symbol'`` : Hall symbol;

            * ``'pointgroup'`` : International Tables of Crystallography point-group;

            * ``'international_number'`` : International Tables of Crystallography space-group number (between 1 and 230);

            * ``'hall_number'`` : Hall number (between 1 and 531).

            If symmetry-determination has failed, None is returned.
        
        Raises
        ------
        RuntimeError : If symmetry-determination has yielded an error.
        
        Notes
        -----
        Note that crystals generated from the Protein Data Bank are often incomplete; 
        in such cases the space-group information will be incorrect.
        """
        dataset = get_symmetry_dataset(cell = self._spglib_cell(),
                                       symprec = symprec, 
                                       angle_tolerance = angle_tolerance)

        if dataset: 
            spg_type = get_spacegroup_type(dataset['hall_number'])

            info = {'international_symbol': dataset['international'],
                    'hall_symbol'         : dataset['hall'],
                    'international_number': dataset['number'],
                    'hall_number'         : dataset['hall_number'],
                    'international_full'  : spg_type['international_full'],
                    'pointgroup'          : spg_type['pointgroup_international']} 

            err_msg = get_error_message()
            if (err_msg != 'no error'):
                raise RuntimeError('Symmetry-determination has returned the following error: {}'.format(err_msg))
            
            return info
        
        return None
コード例 #21
0
ファイル: ciflib.py プロジェクト: pearcandy/ciflib
def make_cifdata(cell, atoms, tol=1.0e-5):
    cifdata = []

    scell = spglib.standardize_cell(cell)
    print('*** scell ***')
    print_cell(scell)
    dataset = spglib.get_symmetry_dataset(scell, tol)

    wyckoffs = dataset['wyckoffs']
    equiv_atoms = dataset['equivalent_atoms']
    trans_matrix = dataset['transformation_matrix']
    origin_shift = dataset['origin_shift']
    hall_number = dataset['hall_number']
    hall_symbol = dataset['hall']
    sg_type = spglib.get_spacegroup_type(hall_number)
    print('trans_matrix')
    print(trans_matrix)
    print('origin_shift')
    print(origin_shift)

    lattice = scell[0]
    positions = scell[1]
    numbers = scell[2]
    cifdata.append(('data_', ''))
    cifdata.append(('', None))

    chemform = ''
    num = [0 for i in range(len(atoms))]
    for i, a in enumerate(atoms):
        for n in numbers:
            if (i == n):
                num[i] += 1
    if ('C' in atoms):
        chemform += 'C' + str(num[atoms.index('C')]) + ' '
    if ('H' in atoms):
        chemform += 'H' + str(num[atoms.index('H')]) + ' '
    for i, a in enumerate(atoms):
        if (a != 'C' and a != 'H'):
            chemform += a + str(num[i]) + ' '
    chemform = chemform.strip()
    print('chemical formula', chemform)

    cifdata.append(('_chemical_formula_sum', chemform))
    crystal_system = get_crystal_system(dataset['number'])
    cifdata.append(('_space_group_crystal_system', crystal_system))

    name_HM = sanitize_name_HM(sg_type['international_short'])
    cifdata.append(('_symmetry_space_group_name_H-M', name_HM))
    cifdata.append(('_symmetry_Int_Tables_number', dataset['number']))
    cifdata.append(('_symmetry_space_group_name_Hall', hall_symbol))
    cifdata.append(('', None))

    cifdata_symmetry_list = ('loop_symmetry', [])
    cifdata_symmetry_list[1].append(
        ['_symmetry_equiv_pos_site_id', '_symmetry_equiv_pos_as_xyz'])

    ind = 0
    for rot, trans in zip(dataset['rotations'], dataset['translations']):
        symbols = make_symop(rot, trans)
        ind += 1
        cifdata_symmetry_list[1].append([ind, symbols])

    cifdata.append(cifdata_symmetry_list)
    cifdata.append(("", None))

    a, b, c = celllength(lattice)
    alpha, beta, gamma = cellangle(lattice)
    cifdata.append(('_cell_length_a', a))
    cifdata.append(('_cell_length_b', b))
    cifdata.append(('_cell_length_c', c))
    cifdata.append(('_cell_angle_alpha', alpha))
    cifdata.append(('_cell_angle_beta', beta))
    cifdata.append(('_cell_angle_gamma', gamma))
    cifdata.append(('', None))

    # find inequivalent atoms and calculate their multiplicitis
    inequiv_atoms = collections.OrderedDict()
    for num in equiv_atoms:
        if num not in inequiv_atoms:
            inequiv_atoms[num] = 1
        else:
            inequiv_atoms[num] += 1

    print('space group number %s' % dataset['number'])
    print('space group %s' % dataset['international'])
    print('hall symbol %s' % dataset['hall'])

    print('name wyckoff  multiplicity  x y z')

    cifdata_atomlist = ('loop_atom', [])
    cifdata_atomlist[1].append([
        '_atom_site_label', '_atom_site_fract_x', '_atom_site_fract_y',
        '_atom_site_fract_z', '_atom_site_occupancy',
        '_atom_site_symmetry_multiplicity', '_atom_site_Wyckoff_symbol',
        '_atom_site_type_symbol'
    ])
    suffix_list = {}
    for atom in atoms:
        suffix_list[atom] = 1
    for num in inequiv_atoms:
        atom_type_number = numbers[num]
        atom_type = atoms[atom_type_number]
        atom_label = atom_type + str(suffix_list[atom_type])
        suffix_list[atom_type] += 1
        cifdata_atomlist[1].append([
            atom_label, positions[num][0], positions[num][1],
            positions[num][2], 1.0, inequiv_atoms[num], wyckoffs[num],
            atom_type
        ])
        print(atom_label, atom_type, wyckoffs[num], inequiv_atoms[num],
              positions[num][0], positions[num][1], positions[num][2])

    cifdata.append(cifdata_atomlist)
    cifdata.append(('', None))

    return cifdata
コード例 #22
0
"""
This script is used to determine the transform from the system specififed by
first Hall number in each space group, into the system that correponds to the
conventional settings for that space group.

This information is needed because the normalizers and Wyckoff positions in
Bilbao Crystallographic Server are given in the conventional setttings only by
default.
"""
import spglib
from collections import defaultdict

space_hall_map = defaultdict(list)

for hall_number in range(1, 531):
    dataset = spglib.get_spacegroup_type(hall_number)
    number = dataset["number"]
    space_hall_map[number].append(hall_number)

degenerate_spgs = []
for key, value in space_hall_map.items():
    if len(value) == 1:
        continue

    degenerate_spgs.append(key)
    first_hall = value[0]
    dataset = spglib.get_spacegroup_type(first_hall)
    choice = dataset["choice"]

    # try:
    # origin = int(choice)
コード例 #23
0
ファイル: symmetry.py プロジェクト: loafbaker/PyChemia
 def get_space_group_type(self, symprec=1e-5):
     return spg.get_spacegroup_type(self.hall_number(symprec=symprec))
コード例 #24
0
def crystal_space_group(system, symprec=1e-5, to_primitive=False,
                        no_idealize=False):
    """
    Uses spglib to evaluate space group information for a given system.
    
    Parameters
    ----------
    system : atomman.System
        The system to analyze.
    symprec : float
        Absolute length tolerance to use in identifying symmetry of atomic
        sites and system boundaries.
    to_primitive : bool
        Indicates if the returned unit cell is conventional (False) or
        primitive (True). Default value is False.
    no_idealize : bool
        Indicates if the atom positions in the returned unit cell are averaged
        (True) or idealized based on the structure (False).  Default value is
        False.
    
    Returns
    -------
    dict
        Results dictionary containing space group information and an associated
        unit cell system.
    """
    # Identify the standardized unit cell representation
    ucell = spglib.standardize_cell(system.dump('spglib_cell'),
                                    to_primitive=to_primitive,
                                    no_idealize=no_idealize, symprec=symprec)
    
    # Convert back to atomman systems and normalize
    ucell = am.load('spglib_cell', ucell, symbols=system.symbols)
    ucell.atoms.pos -= ucell.atoms.pos[0]
    ucell = ucell.normalize()
    
    # Get space group metadata
    sym_data = spglib.get_symmetry_dataset(ucell.dump('spglib_cell'))
    spg_type = spglib.get_spacegroup_type(sym_data['hall_number'])
    
    # Generate Pearson symbol
    if spg_type['number'] <= 2:
        crystalclass = 'a'
    elif spg_type['number'] <= 15:
        crystalclass = 'm'
    elif spg_type['number'] <= 74:
        crystalclass = 'o'
    elif spg_type['number'] <= 142:
        crystalclass = 't'
    elif spg_type['number'] <= 194:
        crystalclass = 'h'
    else:
        crystalclass = 'c'
    
    latticetype = spg_type['international'][0]
    if latticetype in ['A', 'B']:
        latticetype = 'C'
    
    natoms = str(ucell.natoms)
    pearson = crystalclass + latticetype + natoms
    
    # Return results
    results_dict = spg_type
    results_dict['ucell'] = ucell
    results_dict['hall_number'] = sym_data['hall_number']
    results_dict['wyckoffs'] = sym_data['wyckoffs']
    results_dict['pearson'] = pearson
    
    return results_dict
コード例 #25
0
ファイル: ciflib.py プロジェクト: pearcandy/ciflib
def summary(cry, cell, hallnum_ccell, hallnum_pcell, cif, tol=1.0e-5):
    f = open('caldata.txt', 'a')

    # cif
    f.write(cry.matid + ' ')
    chemform = cry.chemical_formula_sum
    chemform = chemform.replace(' ', '')
    f.write(chemform + ' ')
    f.write(cry.space_group_crystal_system + ' ')
    f.write(str(cry.symmetry_Int_Tables_number) + ' ')
    f.write(cry.symmetry_space_group_name + ' ')
    la = cry.cell.length_a
    lb = cry.cell.length_b
    lc = cry.cell.length_c
    aa = cry.cell.angle_alpha
    ab = cry.cell.angle_beta
    ac = cry.cell.angle_gamma
    f.write(
        str(la) + ' ' + str(lb) + ' ' + str(lc) + ' ' + str(aa) + ' ' +
        str(ab) + ' ' + str(ac) + ' ')

    #tol = 1.0e-5

    # conv cell
    sgtype = spglib.get_spacegroup_type(hallnum_ccell)
    spgnum = sgtype['number']
    spgname = sgtype['international_short']
    f.write(str(spgnum) + ' ' + spgname + ' ')

    # prim cell
    sgtype = spglib.get_spacegroup_type(hallnum_pcell)
    spgnum = sgtype['number']
    spgname = sgtype['international_short']
    f.write(str(spgnum) + ' ' + spgname + ' ')

    # calc cell
    scell = spglib.standardize_cell(cell)
    dataset = spglib.get_symmetry_dataset(scell, tol)
    spgnum = dataset['number']
    hallnum = dataset['hall_number']
    sgtype = spglib.get_spacegroup_type(hallnum)
    spgname = sgtype['international_short']
    f.write(str(spgnum) + ' ' + spgname + ' ')
    lattice = scell[0]
    a, b, c = celllength(lattice)
    alpha, beta, gamma = cellangle(lattice)
    f.write(
        str(a) + ' ' + str(b) + ' ' + str(c) + ' ' + str(alpha) + ' ' +
        str(beta) + ' ' + str(gamma) + ' ')

    # cif2cell
    cmd = './cif2cell.sh ' + cif
    os.system(cmd)
    cell, atoms = read_structure_vasp('POSCAR.cif2cell')
    scell = spglib.standardize_cell(cell)
    dataset = spglib.get_symmetry_dataset(scell, tol)
    spgnum = dataset['number']
    hallnum = dataset['hall_number']
    sgtype = spglib.get_spacegroup_type(hallnum)
    spgname = sgtype['international_short']
    f.write(str(spgnum) + ' ' + spgname + ' ')

    f.write('\n')
コード例 #26
0
    def get_HSKP(self, structure):

        structure_dataset = spglib.get_symmetry_dataset(structure, symprec = 1e-05, angle_tolerance = -1.0)
        structure_basis = structure_dataset['std_lattice']
        sgnum = structure_dataset['number']
        hall_num = structure_dataset['hall_number']
        pg_international = spglib.get_spacegroup_type(hall_num)['pointgroup_international']
        inversion_symmetry = self.pg_inversion(self.get_pgnum(pg_international))
        a, b, c, cosalpha, cosbeta, cosgamma = self.get_lattice_constant(structure_basis)
        time_reversal = True
        
        if sgnum in range (195, 231):
            self.cubic(sgnum)
        elif sgnum in range (75, 143):
            self.tetragonal(sgnum, a, b, c)
        elif sgnum in range (16, 75):
            self.orthorhombic(sgnum, a, b, c)
        elif sgnum in range (168, 195):
            self.hexagonal(sgnum)
        elif sgnum in range (143, 168):
            self.trigonal(sgnum, a, b, c)
        elif sgnum in range(3, 16):
            self.monoclinic(sgnum, a, b, c, cosbeta)
        elif sgnum in (1, 3):
            rec1 = self.rec_real_transf(structure_basis)
            rec2 = spglib.niggli_reduce(rec1)
            real2 = self.rec_real_transf(rec2)
            ka2, kb2, kc2, coskalpha2, coskbeta2, coskgamma2 = self.get_lattice_constant(rec2)
            conditions = np.array([abs(kb2 * kc2 * coskalpha2), \
                         abs(kc2 * ka2 * coskbeta2), \
                         abs(ka2 * kb2 * coskgamma2)])

            matrix_M2 = [np.array([[0, 0, 1], [1, 0, 0], [0, 1, 0]]), \
                         np.array([[0, 1, 0], [0, 0, 1], [1, 0, 0]]), \
                         np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])]

            smallest_condition = np.argsort(conditions)[0]
            M2 = matrix_M2[smallest_condition]
            real3 = np.dot(np.array(real2).T, M2).T
            rec3 = self.rec_real_transf(real3)
            ka3, kb3, kc3, coskalpha3, coskbeta3, coskgamma3 = self.get_lattice_constant(rec3)
            
            if (coskalpha3 > 0. and coskbeta3 > 0 and coskgamma3 > 0) or \
               (coskalpha3 < 0 and coskbeta3 < 0 and coskgamma3 < 0):
                matrix_M3 = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])

            elif (coskalpha3 > 0 and coskbeta3 < 0 and coskgamma3 < 0) or \
                 (coskalpha3 < 0 and coskbeta3 > 0 and coskgamma3 > 0):
                matrix_M3 = np.array([[1, 0, 0], [0, -1, 0], [0, 0, -1]])

            elif (coskalpha3 < 0 and coskbeta3 > 0 and coskgamma3 < 0) or \
                 (coskalpha3 > 0 and coskbeta3 < 0 and coskgamma3 > 0):  
                matrix_M3 = np.array([[-1, 0, 0], [0, 1, 0], [0, 0, -1]])

            elif (coskalpha3 < 0 and coskbeta3 < 0 and coskgamma3 > 0) or \
                 (coskalpha3 > 0 and coskbeta3 > 0 and coskgamma3 < 0):
                matrix_M3 = np.array([[-1, 0, 0], [0, -1, 0], [0, 0, 1]])

            else:
                print('Error! Can not get M3 matrix for aP lattice')
                
            real4 = np.dot(real3.T, matrix_M3).T
            rec4 = self.rec_real_transf(real4)
            ka, kb, kc, coskalpha, coskbeta, coskgamma = get_cell_params(rec4)
            self.triclinic(coskalpha, coskbeta, coskgamma)
            
        if not inversion_symmetry and not time_reversal:
            augmented_path = True
        else:
            augmented_path = False

        if augmented_path:
            for pointname, coords in list(self.kpath['Kpoints'].items()):
                if pointname == '\Gamma':
                    continue
                self.kpath['Kpoints']["{}'".format(pointname)] = \
                                     [-coords[0], -coords[1], -coords[2]]
                
            for i in range(0, len(self.kpath['Path'])):
                path_list = []
                old_path = copy.deepcopy(self.kpath['Path'][i - 1])
                for path in old_path:
                    if path == '\Gamma':
                        new_path = path
                    else:
                        new_path = "{}'".format(path)
                    path_list.append(new_path)
                self.kpath['Path'].append(path_list)
コード例 #27
0
ファイル: symmetry.py プロジェクト: yfyh2013/PyChemia
 def get_space_group_type(self, symprec=1e-5):
     return spg.get_spacegroup_type(self.hall_number(symprec=symprec))
コード例 #28
0
# Maintainer: Pengji Zhou

# NOTE: this is the code for record that generates the hall number - space group number mapping.
# The use of this code is not required to use this package

# hall_spacegroup_mapping
import spglib as spg
import json

two_origin_choice_list = [
    48, 50, 59, 68, 70, 85, 86, 88, 125, 126, 129, 130, 133, 134, 137, 138,
    141, 142, 201, 203, 222, 224, 227, 228
]
H_R_choice_list = [146, 148, 155, 160, 161, 166, 167]

spacegroup_hall_mapping = {}
for hall_number in range(1, 531):
    spacegroup_type = spg.get_spacegroup_type(hall_number)
    if spacegroup_type['number'] not in spacegroup_hall_mapping:
        if spacegroup_type[
                'number'] in two_origin_choice_list + H_R_choice_list:
            shift = 1
        else:
            shift = 0
        spacegroup_hall_mapping[
            spacegroup_type['number']] = hall_number + shift

with open('space_group_hall_mapping.json', 'w') as f:
    json.dump(spacegroup_hall_mapping, f)
コード例 #29
0
"""
Goes through the spglib database for different Hall numbers and extracts space
group specific intormation. The results are then written to a python file for
later use.
"""
import spglib
import pickle

space_groups = {}
space_group_database = {}

for hall_number in range(1, 531):
    dataset = spglib.get_spacegroup_type(hall_number)
    number = dataset["number"]
    international_short = dataset["international_short"]

    # Check that the spglib data has no two different international symbols for
    # the same space group number
    old = space_groups.get(number)
    if old is not None:
        if old != international_short:
            raise LookupError("Two spacegroups have different point groups!")
    else:
        if number not in space_group_database:
            space_group_database[number] = {}

        # Point group. There actually seeems to be a bug in spglib 1.9.4, where
        # the Hermann-Mauguin point group symbol is in the plalce of Schonflies
        # data and vice versa.
        pointgroup = dataset["pointgroup_schoenflies"]
        space_group_database[number]["pointgroup"] = pointgroup
コード例 #30
0
    def symmetry(self, symprec=1e-2, angle_tolerance=-1.0):
        """ 
        Returns a dictionary containing space-group information. This information 
        is computed from the crystal unit cell.
        
        Parameters
        ----------
        symprec : float, optional
            Symmetry-search distance tolerance in Cartesian coordinates [Angstroms].
        angle_tolerance: float, optional
            Symmetry-search tolerance in degrees. If the value is negative (default), 
            an internally optimized routine is used to judge symmetry.
        
        Returns
        -------
        info : dict
            Dictionary of space-group information. The following keys are available:

            * ``'international_symbol'``: International Tables of Crystallography 
              space-group symbol (short);

            * ``'international_full'``: International Tables of 
              Crystallography space-group full symbol;

            * ``'hall_symbol'`` : Hall symbol;

            * ``'hm_symbol'`` : Hermann-Mauguin symbol;

            *``'centering'``: Centering-type ("P", "F", etc.);

            * ``'pointgroup'`` : International Tables of 
              Crystallography point-group;

            * ``'international_number'`` : International Tables of 
              Crystallography space-group number (between 1 and 230);

            * ``'hall_number'`` : Hall number (between 1 and 531).
        
        Raises
        ------
        RuntimeError : if symmetry-determination has not succeeded.
        
        Notes
        -----
        Note that crystals generated from the Protein Data Bank are often incomplete; 
        in such cases the space-group information will be incorrect.
        """
        dataset = get_symmetry_dataset(cell=self._spglib_cell(),
                                       symprec=symprec,
                                       angle_tolerance=angle_tolerance)

        if dataset is None:
            raise RuntimeError(
                "[SPGLIB] Symmetry-determination has not found a match.")

        spg_type = get_spacegroup_type(dataset["hall_number"])
        hm_symbol = Hall2HM[dataset["hall"]]

        # We do not distinguish between base-centered "A", "B", and "C"
        # "A" and "B" are translated to "C"
        centering = CenteringType(hm_symbol[0] if hm_symbol[0] not in
                                  {"A", "B"} else "C")
        info = {
            "international_symbol": dataset["international"],
            "hall_symbol": dataset["hall"],
            "hm_symbol": hm_symbol,
            "centering": centering,
            "international_number": dataset["number"],
            "hall_number": dataset["hall_number"],
            "international_full": spg_type["international_full"],
            "pointgroup": spg_type["pointgroup_international"],
        }

        err_msg = get_error_message()
        if err_msg != "no error":
            raise RuntimeError(
                "[SPGLIB] Symmetry-determination has returned the following error: {err_msg}"
            )

        return info
コード例 #31
0
def crystal_space_group(system: am.System,
                        symprec: float = 1e-5,
                        to_primitive: bool = False,
                        no_idealize: bool = False) -> dict:
    """
    Uses spglib to evaluate space group information for a given system.
    
    Parameters
    ----------
    system : atomman.System
        The system to analyze.
    symprec : float, optional
        Absolute length tolerance to use in identifying symmetry of atomic
        sites and system boundaries. Default value is 1e-5
    to_primitive : bool, optional
        Indicates if the returned unit cell is conventional (False) or
        primitive (True). Default value is False.
    no_idealize : bool, optional
        Indicates if the atom positions in the returned unit cell are averaged
        (True) or idealized based on the structure (False).  Default value is
        False.
    
    Returns
    -------
    dict
        Dictionary of results consisting of keys:

        - **'number'** (*int*) The spacegroup number.
        - **'international_short'** (*str*) The short international spacegroup
          symbol.
        - **'international_full'** (*str*) The full international spacegroup
          symbol.
        - **'international'** (*str*) The international spacegroup symbol.
        - **'schoenflies'** (*str*) The schoenflies spacegroup symbol.
        - **'hall_symbol'** (*str*) The Hall symbol.
        - **'choice'** (*str*) The setting choice if there is one.
        - **'pointgroup_international'** (*str*) The international pointgroup
          symbol.
        - **'pointgroup_schoenflies'** (*str*) The schoenflies pointgroup
          symbol.
        - **'arithmetic_crystal_class_number'** (*int*) The arithmetic crystal
          class number.
        - **'arithmetic_crystal_class_symbol'** (*str*) The arithmetic crystal
          class symbol.
        - **'ucell'** (*am.System*) The spacegroup-processed unit cell.
        - **'hall_number'** (*int*) The Hall number.
        - **'wyckoffs'** (*list*) A list of the spacegroup's Wyckoff symbols
          where atoms are found.
        - **'equivalent_atoms'** (*list*) A list of indices indicating which
          atoms are equivalent to others.
        - **'pearson'** (*str*) The Pearson symbol.
        - **'wyckoff_fingerprint'** (*str*) The Wyckoff symbols joined
          together.
    """
    # Identify the standardized unit cell representation
    sym_data = spglib.get_symmetry_dataset(system.dump('spglib_cell'),
                                           symprec=symprec)
    ucell = spglib.standardize_cell(system.dump('spglib_cell'),
                                    to_primitive=to_primitive,
                                    no_idealize=no_idealize,
                                    symprec=symprec)

    # Convert back to atomman systems and normalize
    ucell = am.load('spglib_cell', ucell, symbols=system.symbols)
    ucell.atoms.pos -= ucell.atoms.pos[0]
    ucell = ucell.normalize()

    # Throw error if natoms > 2000
    natoms = ucell.natoms
    if natoms > 2000:
        raise RuntimeError('too many positions')

    # Average extra per-atom properties by mappings to primitive
    for index in np.unique(sym_data['mapping_to_primitive']):
        for key in system.atoms.prop():
            if key in ['atype', 'pos']:
                continue
            value = system.atoms.view[key][sym_data['mapping_to_primitive'] ==
                                           index].mean()
            if key not in ucell.atoms.prop():
                ucell.atoms.view[key] = np.zeros_like(value)
            ucell.atoms.view[key][sym_data['std_mapping_to_primitive'] ==
                                  index] = value

    # Get space group metadata
    sym_data = spglib.get_symmetry_dataset(ucell.dump('spglib_cell'))
    spg_type = spglib.get_spacegroup_type(sym_data['hall_number'])

    # Generate Pearson symbol
    if spg_type['number'] <= 2:
        crystalclass = 'a'
    elif spg_type['number'] <= 15:
        crystalclass = 'm'
    elif spg_type['number'] <= 74:
        crystalclass = 'o'
    elif spg_type['number'] <= 142:
        crystalclass = 't'
    elif spg_type['number'] <= 194:
        crystalclass = 'h'
    else:
        crystalclass = 'c'

    latticetype = spg_type['international'][0]
    if latticetype in ['A', 'B']:
        latticetype = 'C'

    pearson = crystalclass + latticetype + str(natoms)

    # Generate Wyckoff fingerprint
    fingerprint_dict = {}
    usites, uindices = np.unique(sym_data['equivalent_atoms'],
                                 return_index=True)
    for usite, uindex in zip(usites, uindices):
        atype = ucell.atoms.atype[uindex]
        wykoff = sym_data['wyckoffs'][uindex]
        if atype not in fingerprint_dict:
            fingerprint_dict[atype] = [wykoff]
        else:
            fingerprint_dict[atype].append(wykoff)
    fingerprint = []
    for atype in sorted(fingerprint_dict.keys()):
        fingerprint.append(''.join(sorted(fingerprint_dict[atype])))
    fingerprint = ' '.join(fingerprint)

    # Return results
    results_dict = spg_type
    results_dict['ucell'] = ucell
    results_dict['hall_number'] = sym_data['hall_number']
    results_dict['wyckoffs'] = sym_data['wyckoffs']
    results_dict['equivalent_atoms'] = sym_data['equivalent_atoms']
    results_dict['pearson'] = pearson
    results_dict['wyckoff_fingerprint'] = fingerprint

    return results_dict
コード例 #32
0
print('')

dataset = spglib.get_symmetry_dataset( rutile )
print("[get_symmetry_dataset] ['international']")
print("  Spacegroup of Rutile is %s (%d)." % (dataset['international'],
                                              dataset['number']))
print('')
print("[get_symmetry_dataset] ['pointgroup']")
print("  Pointgroup of Rutile is %s." % (dataset['pointgroup']))
print('')
print("[get_symmetry_dataset] ['hall']")
print("  Hall symbol of Rutile is %s (%d)." % (dataset['hall'],
                                               dataset['hall_number']))
print('')
print '========================================================='
spacegroup_type = spglib.get_spacegroup_type(dataset['hall_number'])
print spacegroup_type
print("[get_symmetry_dataset] ['wyckoffs']")
alphabet = "abcdefghijklmnopqrstuvwxyz"
print("  Wyckoff letters of Rutile are: ", dataset['wyckoffs'])
print('')
print("[get_symmetry_dataset] ['equivalent_atoms']")
print("  Mapping to equivalent atoms of Rutile are: ")
for i, x in enumerate(dataset['equivalent_atoms']):
  print("  %d -> %d" % (i + 1, x + 1))
print('')
print("[get_symmetry_dataset] ['rotations'], ['translations']")
print("  Symmetry operations of Rutile unitcell are:")
for i, (rot,trans) in enumerate(zip(dataset['rotations'],
                                    dataset['translations'])):
    print("  --------------- %4d ---------------" % (i + 1))
コード例 #33
0
def crystal_space_group(system,
                        symprec=1e-5,
                        to_primitive=False,
                        no_idealize=False):
    """
    Uses spglib to evaluate space group information for a given system.
    
    Parameters
    ----------
    system : atomman.System
        The system to analyze.
    symprec : float
        Absolute length tolerance to use in identifying symmetry of atomic
        sites and system boundaries.
    to_primitive : bool
        Indicates if the returned unit cell is conventional (False) or
        primitive (True). Default value is False.
    no_idealize : bool
        Indicates if the atom positions in the returned unit cell are averaged
        (True) or idealized based on the structure (False).  Default value is
        False.
    
    Returns
    -------
    dict
        Results dictionary containing space group information and an associated
        unit cell system.
    """
    # Identify the standardized unit cell representation
    ucell = spglib.standardize_cell(system.dump('spglib_cell'),
                                    to_primitive=to_primitive,
                                    no_idealize=no_idealize,
                                    symprec=symprec)

    # Convert back to atomman systems and normalize
    ucell = am.load('spglib_cell', ucell, symbols=system.symbols)
    ucell.atoms.pos -= ucell.atoms.pos[0]
    ucell = ucell.normalize()

    # Get space group metadata
    sym_data = spglib.get_symmetry_dataset(ucell.dump('spglib_cell'))
    spg_type = spglib.get_spacegroup_type(sym_data['hall_number'])

    # Generate Pearson symbol
    if spg_type['number'] <= 2:
        crystalclass = 'a'
    elif spg_type['number'] <= 15:
        crystalclass = 'm'
    elif spg_type['number'] <= 74:
        crystalclass = 'o'
    elif spg_type['number'] <= 142:
        crystalclass = 't'
    elif spg_type['number'] <= 194:
        crystalclass = 'h'
    else:
        crystalclass = 'c'

    latticetype = spg_type['international'][0]
    if latticetype in ['A', 'B']:
        latticetype = 'C'

    natoms = str(ucell.natoms)
    pearson = crystalclass + latticetype + natoms

    # Return results
    results_dict = spg_type
    results_dict['ucell'] = ucell
    results_dict['hall_number'] = sym_data['hall_number']
    results_dict['wyckoffs'] = sym_data['wyckoffs']
    results_dict['pearson'] = pearson

    return results_dict
コード例 #34
0
def crystal_space_group(system,
                        symprec=1e-5,
                        to_primitive=False,
                        no_idealize=False):
    """
    Uses spglib to evaluate space group information for a given system.
    
    Parameters
    ----------
    system : atomman.System
        The system to analyze.
    symprec : float
        Absolute length tolerance to use in identifying symmetry of atomic
        sites and system boundaries.
    to_primitive : bool
        Indicates if the returned unit cell is conventional (False) or
        primitive (True). Default value is False.
    no_idealize : bool
        Indicates if the atom positions in the returned unit cell are averaged
        (True) or idealized based on the structure (False).  Default value is
        False.
    
    Returns
    -------
    dict
        Results dictionary containing space group information and an associated
        unit cell system.
    """
    # Identify the standardized unit cell representation
    sym_data = spglib.get_symmetry_dataset(system.dump('spglib_cell'),
                                           symprec=symprec)
    ucell = spglib.standardize_cell(system.dump('spglib_cell'),
                                    to_primitive=to_primitive,
                                    no_idealize=no_idealize,
                                    symprec=symprec)

    # Convert back to atomman systems and normalize
    ucell = am.load('spglib_cell', ucell, symbols=system.symbols)
    ucell.atoms.pos -= ucell.atoms.pos[0]
    ucell = ucell.normalize()

    # Average extra per-atom properties by mappings to primitive
    for index in np.unique(sym_data['mapping_to_primitive']):
        for key in system.atoms.prop():
            if key in ['atype', 'pos']:
                continue
            value = system.atoms.view[key][sym_data['mapping_to_primitive'] ==
                                           index].mean()
            if key not in ucell.atoms.prop():
                ucell.atoms.view[key] = np.zeros_like(value)
            ucell.atoms.view[key][sym_data['std_mapping_to_primitive'] ==
                                  index] = value

    # Get space group metadata
    sym_data = spglib.get_symmetry_dataset(ucell.dump('spglib_cell'))
    spg_type = spglib.get_spacegroup_type(sym_data['hall_number'])

    # Generate Pearson symbol
    if spg_type['number'] <= 2:
        crystalclass = 'a'
    elif spg_type['number'] <= 15:
        crystalclass = 'm'
    elif spg_type['number'] <= 74:
        crystalclass = 'o'
    elif spg_type['number'] <= 142:
        crystalclass = 't'
    elif spg_type['number'] <= 194:
        crystalclass = 'h'
    else:
        crystalclass = 'c'

    latticetype = spg_type['international'][0]
    if latticetype in ['A', 'B']:
        latticetype = 'C'

    natoms = str(ucell.natoms)
    pearson = crystalclass + latticetype + natoms

    # Generate Wyckoff fingerprint
    fingerprint_dict = {}
    usites, uindices = np.unique(sym_data['equivalent_atoms'],
                                 return_index=True)
    for usite, uindex in zip(usites, uindices):
        atype = ucell.atoms.atype[uindex]
        wykoff = sym_data['wyckoffs'][uindex]
        if atype not in fingerprint_dict:
            fingerprint_dict[atype] = [wykoff]
        else:
            fingerprint_dict[atype].append(wykoff)
    fingerprint = []
    for atype in sorted(fingerprint_dict.keys()):
        fingerprint.append(''.join(sorted(fingerprint_dict[atype])))
    fingerprint = ' '.join(fingerprint)

    # Return results
    results_dict = spg_type
    results_dict['ucell'] = ucell
    results_dict['hall_number'] = sym_data['hall_number']
    results_dict['wyckoffs'] = sym_data['wyckoffs']
    results_dict['equivalent_atoms'] = sym_data['equivalent_atoms']
    results_dict['pearson'] = pearson
    results_dict['wyckoff_fingerprint'] = fingerprint

    return results_dict
コード例 #35
0
def get_sym(cell,
            symprec=1e-3,
            verbose='short',
            angle_tolerance=-1.0,
            hall_number=0):
    '''Giving a spglib cell, return symmetry analysis
       This is wrapper for spglib.get_symmetry_dataset function 
    '''

    #Space group info
    dataset = spglib.get_symmetry_dataset(cell,
                                          symprec=symprec,
                                          angle_tolerance=angle_tolerance,
                                          hall_number=hall_number)

    number = dataset['number']
    international = dataset['international']  # equil. to international_short
    hall = dataset['hall']  # equil. to hall_symbol
    hall_number = dataset['hall_number']
    choice = dataset['choice']
    transformation_matrix = dataset['transformation_matrix']
    origin_shift = dataset['origin_shift']
    wyckoffs = dataset['wyckoffs']
    site_symmetry_symbols = dataset['site_symmetry_symbols']
    equivalent_atoms = dataset['equivalent_atoms']
    crystallographic_orbits = dataset['crystallographic_orbits']
    mapping_to_primitive = dataset['mapping_to_primitive']
    rotations = dataset['rotations']
    translations = dataset['translations']
    pointgroup = dataset['pointgroup']  # equil. to pointgroup_international
    primitive_lattice = dataset['primitive_lattice']
    std_lattice = dataset['std_lattice']
    std_positions = dataset['std_positions']
    std_types = dataset['std_types']
    std_rotation_matrix = dataset['std_rotation_matrix']
    std_mapping_to_primitive = dataset['std_mapping_to_primitive']

    # Get full summetry using the Hall number
    spacegroup_type = spglib.get_spacegroup_type(hall_number)
    number = spacegroup_type['number']
    international_short = spacegroup_type['international_short']
    international_full = spacegroup_type['international_full']
    international = spacegroup_type['international']
    schoenflies = spacegroup_type['schoenflies']
    hall_symbol = spacegroup_type['hall_symbol']
    pointgroup_schoenflies = spacegroup_type['pointgroup_schoenflies']
    pointgroup_international = spacegroup_type['pointgroup_international']
    arithmetic_crystal_class_number = spacegroup_type[
        'arithmetic_crystal_class_number']
    arithmetic_crystal_class_symbol = spacegroup_type[
        'arithmetic_crystal_class_symbol']

    atoms = utils.convert_atomtype(cell[2])
    coords = cell[1]
    std_cell = cell_to_std(dataset, message=False)
    primitive_cell = cell_to_primitive(dataset, message=False)

    if verbose == 'short':
        # Cell info
        if compare_cells(cell, std_cell) and compare_cells(
                cell, primitive_cell):
            misc.print_msg("This is a standard/primitive unit cell")
        elif compare_cells(cell, std_cell):
            misc.print_msg("This is a standard unit cell")
        elif compare_cells(cell, primitive_cell):
            misc.print_msg("This is a primitive cell")

        # Basic info
        misc.print_msg("Space group  number          : {:d}".format(number))
        misc.print_msg(
            "Short international symbol   : {:s}".format(international_short))
        misc.print_msg(
            "Hall symbol                  : {:s}".format(hall_symbol))
        misc.print_msg(
            "Schoenflies symbol           : {:s}".format(schoenflies))
        misc.print_msg("International point group    : {:s}".format(
            pointgroup_international))
        misc.print_msg(
            "Origin shift                 : {:4.3f} {:4.3f} {:4.3f}".format(
                origin_shift[0], origin_shift[1], origin_shift[2]))

        # Atoms info
        # Atoms info
        misc.print_msg("===== Irreducible atoms list =====")
        misc.print_msg("  #  Atom        x          y          z")
        unique_atoms_idx = np.unique(equivalent_atoms, return_index=True)[1]
        for i, index in enumerate(unique_atoms_idx):
            coord = coords[index]
            misc.print_msg(
                "{:>3d}  {:>3s}    {:>8.5f}   {:>8.5f}   {:>8.5f}".format(
                    i + 1, atoms[index], coord[0], coord[1], coord[2]))

    elif verbose == 'full':
        # Cell info
        if compare_cells(cell, std_cell) and compare_cells(
                cell, primitive_cell):
            misc.print_msg("This is a standard/primitive unit cell")
        elif compare_cells(cell, std_cell):
            misc.print_msg("This is a standard unit cell")
        elif compare_cells(cell, primitive_cell):
            misc.print_msg("This is a primitive cell")

        # Basic info
        misc.print_msg("Space group  number          : {:d}".format(number))
        misc.print_msg(
            "Short international symbol   : {:s}".format(international_short))
        misc.print_msg(
            "Full international symbol    : {:s}".format(international_full))
        misc.print_msg(
            "Hall number                  : {:d}".format(hall_number))
        misc.print_msg(
            "Hall symbol                  : {:s}".format(hall_symbol))
        misc.print_msg(
            "Schoenflies symbol           : {:s}".format(schoenflies))
        misc.print_msg("Schoenflies point group      : {:s}".format(
            pointgroup_schoenflies))
        misc.print_msg("International point group    : {:s}".format(
            pointgroup_international))
        misc.print_msg(
            "Origin shift                 : {:4.3f} {:4.3f} {:4.3f}".format(
                origin_shift[0], origin_shift[1], origin_shift[2]))

        # Atoms info
        misc.print_msg("===== Full atoms list =====")
        misc.print_msg(
            "  #  Equil.  Atom        x         y         z     Wyckoffs   Site_symmetry"
        )
        for i, atom in enumerate(atoms):
            misc.print_msg(
                "{:>3d}  {:>3d}     {:>3s}    {:>8.5f}  {:>8.5f}  {:>8.5f}      {:>2s}          {:>5s}"
                .format(i + 1, equivalent_atoms[i] + 1, atoms[i], coords[i, 0],
                        coords[i, 1], coords[i, 2], wyckoffs[i],
                        site_symmetry_symbols[i]))
    elif verbose is None:
        # Return an standard cell object with irreducible atoms
        dataset = spglib.get_symmetry_dataset(std_cell,
                                              symprec=symprec,
                                              angle_tolerance=angle_tolerance,
                                              hall_number=hall_number)
        equivalent_atoms = dataset['equivalent_atoms']
        irred_idx = np.unique(equivalent_atoms, return_index=True)[1]
        lattice = std_lattice
        irred_coord = std_positions[irred_idx, :]
        irred_label = std_types[irred_idx]
        irred_cell = (lattice, irred_coord, irred_label)
        spacegroup = [number, international_short]

        # Get symmetry operators using the Hall number:
        # For some reason, the symmetry operators by dataset doesn't really match its space group number to write cif file
        symmetry = spglib.get_symmetry_from_database(hall_number)
        rotations = symmetry['rotations']
        translations = symmetry['translations']

        return spacegroup, irred_cell, rotations, translations