示例#1
0
 def __init__(self, wp, coordinate, specie=1):
     self.position = np.array(coordinate)
     self.specie = Element(specie).short_name
     self.multiplicity = wp.multiplicity
     self.wp = wp
     self.PBC = wp.PBC
     self.update(coordinate)
示例#2
0
    def get_box(self):
        """
        Given a molecule, find a minimum orthorhombic box containing it.
        Size is calculated using min and max x, y, and z values,
        plus the padding defined by the vdw radius
        For best results, call oriented_molecule first.

        Args:
            mol: a pymatgen Molecule object. Should be oriented along its principle axes.

        Returns:
            a Box object
        """
        mol, P = reoriented_molecule(self.mol)
        minx, miny, minz, maxx, maxy, maxz = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
        for p in mol:
            x, y, z = p.coords
            r = Element(p.species_string).vdw_radius
            if x - r < minx:
                minx = x - r
            if y - r < miny:
                miny = y - r
            if z - r < minz:
                minz = z - r
            if x + r > maxx:
                maxx = x + r
            if y + r > maxy:
                maxy = y + r
            if z + r > maxz:
                maxz = z + r
        self.box = Box(minx, maxx, miny, maxy, minz, maxz)
        self.axes = P
示例#3
0
    def estimate_volume(self):
        """
        Estimates the volume of a unit cell based on the number and types of ions.
        Assumes each atom takes up a sphere with radius equal to its covalent bond
        radius.

        Returns:
            a float value for the estimated volume
        """
        volume = 0
        for numIon, specie in zip(self.numIons, self.species):
            r = random.uniform(
                Element(specie).covalent_radius,
                Element(specie).vdw_radius)
            volume += numIon * 4 / 3 * np.pi * r**3
        return self.factor * volume
示例#4
0
    def get_tol(self, specie1, specie2):
        """
        Returns the tolerance between two species.
        
        Args:
            specie1, specie2: the atomic number (int or float), name (str), symbol (str),
                an Element object, or a pymatgen Specie object

        Returns:
            the tolerance between the provided pair of atomic species
        """
        if self.prototype == "single_value":
            return self.matrix[0][0]
        index1 = Element.number_from_specie(specie1)
        index2 = Element.number_from_specie(specie2)
        if index1 is not None and index2 is not None:
            return self.matrix[index1][index2]
        else:
            return None
示例#5
0
 def print_all(self):
     print("--Tol_matrix class object--")
     print("  Prototype: " + str(self.prototype))
     print("  Atomic radius type: " + str(self.radius_type))
     print("  Radius scaling factor: " + str(self.f))
     if self.prototype == "single value":
         print("  Custom tolerance value: " + str(self.matrix([0][0])))
     else:
         if self.custom_values == []:
             print("  Custom tolerance values: None")
         else:
             print("  Custom tolerance values:")
             for tup in self.custom_values:
                 name1 = str(Element(tup[0]).short_name)
                 name2 = str(Element(tup[1]).short_name)
                 # print("    " + name1+ ", " + name2 + ": " +str(self.get_tol(tup[0],tup[1])))
                 s += "\n{:s}-{:s}: {:6.3f}".format(
                     name1, name2, self.get_tol(tup[0], tup[1]))
             print(s)
示例#6
0
 def set_tol(self, specie1, specie2, value):
     """
     Sets the distance tolerance between two species.
     
     Args:
         specie1, specie2: the atomic number (int or float), name (str), symbol (str),
             an Element object, or a pymatgen Specie object
         value:
             the tolerance (in Angstroms) to set to
     """
     index1 = Element.number_from_specie(specie1)
     index2 = Element.number_from_specie(specie2)
     if index1 is None or index2 is None:
         return
     self.matrix[index1][index2] = float(value)
     if index1 != index2:
         self.matrix[index2][index1] = float(value)
     if (index1, index2) not in self.custom_values and (
             index2,
             index1,
     ) not in self.custom_values:
         larger = max(index1, index2)
         smaller = min(index1, index2)
         self.custom_values.append((smaller, larger))
示例#7
0
文件: XRD.py 项目: yfyh2013/PyXtal
    def atom_scatter(self, crystal):
        """ N*M array; N: atoms, M: N_hkl"""
        f = np.zeros([sum(crystal.composition), len(self.d_hkl)])
        d0 = 1/2/self.d_hkl
        count = 0
        for i, ele in enumerate(crystal.atom_type):
            c = Element(ele).scatter
            f_tmp = c[0]*np.exp(-c[4]*d0) + \
                    c[1]*np.exp(-c[5]*d0) + \
                    c[2]*np.exp(-c[6]*d0) + \
                    c[3]*np.exp(-c[7]*d0) + c[8]
            for j in range(count,count+crystal.composition[i]):
                f[j] = f_tmp
            count += crystal.composition[i]

        self.f = f
def read_molecule(mol, name):
    x = np.transpose([mol.record["coords"][0]["conformers"][0]["x"]])
    y = np.transpose([mol.record["coords"][0]["conformers"][0]["y"]])
    z = np.transpose([mol.record["coords"][0]["conformers"][0]["z"]])

    xyz = np.concatenate((x, y, z), axis=1)
    numbers = mol.record["atoms"]["element"]
    elements = [Element(i).short_name for i in numbers]
    volume = mol.volume_3d
    pubchemid = mol.cid
    molecule = {
        "name": name,
        "elements": elements,
        "xyz": xyz,
        "volume": volume,
        "pubchem id": pubchemid,
    }
    return molecule
示例#9
0
    def __init__(self,
                 wp=None,
                 coordinate=None,
                 specie=1,
                 diag=False,
                 search=False):
        self.position = np.array(coordinate)
        self.specie = Element(specie).short_name
        self.diag = diag
        self.wp = wp
        if self.diag:
            self.wp.diagonalize_symops()
            #self.position = project_point(self.position, wp[0])

        self._get_dof()
        self.PBC = self.wp.PBC
        self.multiplicity = self.wp.multiplicity
        if search:
            self.search_position()
        self.update()
示例#10
0
    def intensity(self, crystal):
        """
        This function calculates all that is necessary to find the intensities.
        This scheme is based off of pymatgen
        Needs improvement from different correction factors.
        """

        d0 = (1 / 2 / self.d_hkl)**2

        # obtiain scattering parameters, atomic numbers, and occus (need to look into occus)
        coeffs = []
        zs = []

        for elem in crystal.get_chemical_symbols():
            if elem == 'D':
                elem = 'H'
            c = ATOMIC_SCATTERING_PARAMS[elem]
            z = Element(elem).z
            coeffs.append(c)
            zs.append(z)

        coeffs = np.array(coeffs)
        self.peaks = {}
        two_thetas = []

        # self.march_parameter = 1
        TWO_THETA_TOL = 1e-5  # tolerance to find repeating angles
        SCALED_INTENSITY_TOL = 1e-5  # threshold for intensities

        for hkl, s2, theta, d_hkl in zip(self.hkl_list, d0, self.theta,
                                         self.d_hkl):

            # calculate the scattering factor sf
            g_dot_r = np.dot(crystal.get_scaled_positions(),
                             np.transpose([hkl])).T[0]
            sf = zs - 41.78214 * s2 * np.sum(
                coeffs[:, :, 0] * np.exp(-coeffs[:, :, 1] * s2), axis=1)

            # calculate the structure factor f
            f = np.sum(sf * np.exp(2j * np.pi * g_dot_r))

            # calculate the lorentz polarization factor lf
            lf = (1 + np.cos(2 * theta)**2) / (np.sin(theta)**2 *
                                               np.cos(theta))

            # calculate the preferred orientation factor
            if self.preferred_orientation != False:
                G = self.march_parameter
                po = ((G * np.cos(theta))**2 + 1 / G * np.sin(theta)**2)**(-3 /
                                                                           2)
            else:
                po = 1

            # calculate the intensity I
            I = (f * f.conjugate()).real

            # calculate 2*theta
            two_theta = np.degrees(2 * theta)

            # find where the scattered angles are equal
            ind = np.where(
                np.abs(np.subtract(two_thetas, two_theta)) < TWO_THETA_TOL)

            # append intensity, hkl plane, and thetas to lists
            if len(ind[0]) > 0:
                self.peaks[two_thetas[ind[0][0]]][0] += I * lf * po
                self.peaks[two_thetas[ind[0][0]]][1].append(tuple(hkl))
            else:
                self.peaks[two_theta] = [I * lf * po, [tuple(hkl)], d_hkl]
                two_thetas.append(two_theta)

        # obtain important intensities (defined by SCALED_INTENSITY_TOL)
        # and corresponding 2*theta, hkl plane + multiplicity, and d_hkl

        max_intensity = max([v[0] for v in self.peaks.values()])
        x = []
        y = []
        hkls = []
        d_hkls = []
        count = 0
        for k in sorted(self.peaks.keys()):
            count += 1
            v = self.peaks[k]
            fam = self.get_unique_families(v[1])
            if v[0] / max_intensity * 100 > SCALED_INTENSITY_TOL:
                x.append(k)
                y.append(v[0])

                hkls.append([{
                    "hkl": hkl,
                    "multiplicity": mult
                } for hkl, mult in fam.items()])
                d_hkls.append(v[2])

        self.theta2 = x
        self.xrd_intensity = y
        self.hkl_labels = hkls
        self.d_hkls = d_hkls
示例#11
0
def test_modules():
    print("====== Testing functionality for pyXtal version 0.1dev ======")

    global failed_package
    failed_package = False  # Record if errors occur at any level

    reset()

    print("Importing sys...")
    try:
        import sys

        print("Success!")
    except Exception as e:
        fail(e)
        sys.exit(0)

    print("Importing numpy...")
    try:
        import numpy as np

        print("Success!")
    except Exception as e:
        fail(e)
        sys.exit(0)

    I = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])

    print("Importing pymatgen...")
    try:
        import pymatgen

        print("Success!")
    except Exception as e:
        fail(e)
        sys.exit(0)

    try:
        from pymatgen.core.operations import SymmOp
    except Exception as e:
        fail(e)
        sys.exit(0)

    print("Importing pandas...")
    try:
        import pandas

        print("Success!")
    except Exception as e:
        fail(e)
        sys.exit(0)

    print("Importing spglib...")
    try:
        import spglib

        print("Success!")
    except Exception as e:
        fail(e)
        sys.exit(0)

    print("Importing openbabel...")
    try:
        import ase

        print("Success!")
    except:
        print(
            "Error: could not import openbabel. Try reinstalling the package.")

    print("Importing pyxtal...")
    try:
        import pyxtal

        print("Success!")
    except Exception as e:
        fail(e)
        sys.exit(0)

    print("=== Testing modules ===")

    # =====database.element=====
    print("pyxtal.database.element")
    reset()
    try:
        import pyxtal.database.element
    except Exception as e:
        fail(e)

    print("  class Element")
    try:
        from pyxtal.database.element import Element
    except Exception as e:
        fail(e)
    if passed():
        for i in range(1, 95):
            if passed():
                try:
                    ele = Element(i)
                except:
                    fail("Could not access Element # " + str(i))
                try:
                    y = ele.sf
                    y = ele.z
                    y = ele.short_name
                    y = ele.long_name
                    y = ele.valence
                    y = ele.valence_electrons
                    y = ele.covalent_radius
                    y = ele.vdw_radius
                    y = ele.get_all(0)
                except:
                    fail("Could not access attribute for element # " + str(i))
                try:
                    ele.all_z()
                    ele.all_short_names()
                    ele.all_long_names()
                    ele.all_valences()
                    ele.all_valence_electrons()
                    ele.all_covalent_radii()
                    ele.all_vdw_radii()
                except:
                    fail("Could not access class methods")

    check()

    # =====database.hall=====
    print("pyxtal.database.hall")
    reset()
    try:
        import pyxtal.database.hall
    except Exception as e:
        fail(e)

    print("  hall_from_hm")
    try:
        from pyxtal.database.hall import hall_from_hm
    except Exception as e:
        fail(e)

    if passed():
        for i in range(1, 230):
            if passed():
                try:
                    hall_from_hm(i)
                except:
                    fail("Could not access hm # " + str(i))

    check()

    # =====database.collection=====
    print("pyxtal.database.collection")
    reset()
    try:
        import pyxtal.database.collection
    except Exception as e:
        fail(e)

    print("  Collection")
    try:
        from pyxtal.database.collection import Collection
    except Exception as e:
        fail(e)

    if passed():
        for i in range(1, 230):
            if passed():
                try:
                    molecule_collection = Collection("molecules")
                except:
                    fail("Could not access hm # " + str(i))

    check()

    # =====operations=====
    print("pyxtal.operations")
    reset()
    try:
        import pyxtal.operations
    except Exception as e:
        fail(e)

    print("  random_vector")
    try:
        from pyxtal.operations import random_vector
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in range(10):
                random_vector()
        except Exception as e:
            fail(e)

    check()

    print("  angle")
    try:
        from pyxtal.operations import angle
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in range(10):
                v1 = random_vector()
                v2 = random_vector()
                angle(v1, v2)
        except Exception as e:
            fail(e)

    check()

    print("  random_shear_matrix")
    try:
        from pyxtal.operations import random_shear_matrix
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in range(10):
                random_shear_matrix()
        except Exception as e:
            fail(e)

    check()

    print("  is_orthogonal")
    try:
        from pyxtal.operations import is_orthogonal
    except Exception as e:
        fail(e)

    if passed():
        try:
            a = is_orthogonal([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
            b = is_orthogonal([[0, 0, 1], [1, 0, 0], [1, 0, 0]])
            if a is True and b is False:
                pass
            else:
                fail()
        except Exception as e:
            fail(e)

    check()

    print("  aa2matrix")
    try:
        from pyxtal.operations import aa2matrix
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in range(10):
                aa2matrix(1, 1, random=True)
        except Exception as e:
            fail(e)

    check()

    print("  matrix2aa")
    try:
        from pyxtal.operations import matrix2aa
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in range(10):
                m = aa2matrix(1, 1, random=True)
                aa = matrix2aa(m)
        except Exception as e:
            fail(e)

    check()

    print("  rotate_vector")
    try:
        from pyxtal.operations import rotate_vector
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in range(10):
                v1 = random_vector()
                v2 = random_vector()
                rotate_vector(v1, v2)
        except Exception as e:
            fail(e)

    check()

    print("  are_equal")
    try:
        from pyxtal.operations import are_equal
    except Exception as e:
        fail(e)

    if passed():
        try:
            op1 = SymmOp.from_xyz_string("x,y,z")
            op2 = SymmOp.from_xyz_string("x,y,z+1")
            a = are_equal(op1, op2, PBC=[0, 0, 1])
            b = are_equal(op1, op2, PBC=[1, 0, 0])
            if a is True and b is False:
                pass
            else:
                fail()
        except Exception as e:
            fail(e)

    check()

    print("  class OperationAnalyzer")
    try:
        from pyxtal.operations import OperationAnalyzer
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in range(10):
                m = aa2matrix(1, 1, random=True)
                t = random_vector()
                op1 = SymmOp.from_rotation_and_translation(m, t)
                OperationAnalyzer(op1)
        except Exception as e:
            fail(e)

    check()

    print("  class Orientation")
    try:
        from pyxtal.operations import Orientation
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in range(10):
                v1 = random_vector()
                c1 = random_vector()
                o = Orientation.from_constraint(v1, c1)
        except Exception as e:
            fail(e)

    check()

    # =====symmetry=====
    print("pyxtal.symmetry")
    reset()
    try:
        import pyxtal.symmetry
    except Exception as e:
        fail(e)

    print("  get_wyckoffs (may take a moment)")
    try:
        from pyxtal.symmetry import get_wyckoffs
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in [1, 2, 229, 230]:
                get_wyckoffs(i)
                get_wyckoffs(i, organized=True)
        except:
            fail(" Could not access Wyckoff positions for space group # " +
                 str(i))

    check()

    print("  get_wyckoff_symmetry (may take a moment)")
    try:
        from pyxtal.symmetry import get_wyckoff_symmetry
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in [1, 2, 229, 230]:
                get_wyckoff_symmetry(i)
                get_wyckoff_symmetry(i, molecular=True)
        except:
            fail("Could not access Wyckoff symmetry for space group # " +
                 str(i))

    check()

    print("  get_wyckoffs_generators (may take a moment)")
    try:
        from pyxtal.symmetry import get_wyckoff_generators
    except Exception as e:
        fail(e)

    if passed():
        try:
            for i in [1, 2, 229, 230]:
                get_wyckoff_generators(i)
        except:
            fail("Could not access Wyckoff generators for space group # " +
                 str(i))

    check()

    print("  letter_from_index")
    try:
        from pyxtal.symmetry import letter_from_index
    except Exception as e:
        fail(e)

    if passed():
        try:
            if letter_from_index(0, get_wyckoffs(47)) == "A":
                pass
            else:
                fail()
        except Exception as e:
            fail(e)

    check()

    print("  index_from_letter")
    try:
        from pyxtal.symmetry import index_from_letter
    except Exception as e:
        fail(e)

    if passed():
        try:
            if index_from_letter("A", get_wyckoffs(47)) == 0:
                pass
            else:
                fail()
        except Exception as e:
            fail(e)

    check()

    print("  jk_from_i")
    try:
        from pyxtal.symmetry import jk_from_i
    except Exception as e:
        fail(e)

    if passed():
        try:
            w = get_wyckoffs(2, organized=True)
            j, k = jk_from_i(1, w)
            if j == 1 and k == 0:
                pass
            else:
                print(j, k)
                fail()
        except Exception as e:
            fail(e)

    check()

    print("  i_from_jk")
    try:
        from pyxtal.symmetry import i_from_jk
    except Exception as e:
        fail(e)

    if passed():
        try:
            w = get_wyckoffs(2, organized=True)
            j, k = jk_from_i(1, w)
            i = i_from_jk(j, k, w)
            if i == 1:
                pass
            else:
                print(j, k)
                fail()
        except Exception as e:
            fail(e)

    check()

    print("  ss_string_from_ops")
    try:
        from pyxtal.symmetry import ss_string_from_ops
    except Exception as e:
        fail(e)

    if passed():
        try:
            strings = ["1", "4 . .", "2 3 ."]
            for i, sg in enumerate([1, 75, 195]):
                ops = get_wyckoffs(sg)[0]
                ss_string_from_ops(ops, sg, dim=3)
        except Exception as e:
            fail(e)

    check()

    print("  Wyckoff_position")
    try:
        from pyxtal.symmetry import Wyckoff_position
    except Exception as e:
        fail(e)

    if passed():
        try:
            wp = Wyckoff_position.from_group_and_index(20, 1)
        except Exception as e:
            fail(e)

    check()

    print("  Group")
    try:
        from pyxtal.symmetry import Group
    except Exception as e:
        fail(e)

    if passed():
        try:
            g3 = Group(230)
            g2 = Group(80, dim=2)
            g1 = Group(75, dim=1)
        except Exception as e:
            fail(e)

    check()

    # =====crystal=====
    print("pyxtal.crystal")
    reset()
    try:
        import pyxtal.crystal
    except Exception as e:
        fail(e)

    print("  random_crystal")
    try:
        from pyxtal.crystal import random_crystal
    except Exception as e:
        fail(e)

    if passed():
        try:
            c = random_crystal(1, ["H"], [1], 10.0)
            if c.valid is True:
                pass
            else:
                fail()
        except Exception as e:
            fail(e)

    check()

    print("  random_crystal_2D")
    try:
        from pyxtal.crystal import random_crystal_2D
    except Exception as e:
        fail(e)

    if passed():
        try:
            c = random_crystal_2D(1, ["H"], [1], 10.0)
            if c.valid is True:
                pass
            else:
                fail()
        except Exception as e:
            fail(e)

    check()

    # =====molecule=====
    print("pyxtal.molecule")
    reset()
    try:
        import pyxtal.molecule
    except Exception as e:
        fail(e)

    check()

    print("  Collections")
    try:
        from pyxtal.molecule import mol_from_collection
    except Exception as e:
        fail(e)

    if passed():
        try:
            h2o = mol_from_collection("H2O")
            ch4 = mol_from_collection("CH4")
        except Exception as e:
            fail(e)

    print("  get_inertia_tensor")
    try:
        from pyxtal.molecule import get_inertia_tensor
    except Exception as e:
        fail(e)

    if passed():
        try:
            get_inertia_tensor(h2o)
            get_inertia_tensor(ch4)
        except Exception as e:
            fail(e)

    check()

    print("  get_moment_of_inertia")
    try:
        from pyxtal.molecule import get_moment_of_inertia
    except Exception as e:
        fail(e)

    if passed():
        try:
            v = random_vector()
            get_moment_of_inertia(h2o, v)
            get_moment_of_inertia(ch4, v)
        except Exception as e:
            fail(e)

    check()

    print("  reoriented_molecule")
    try:
        from pyxtal.molecule import reoriented_molecule
    except Exception as e:
        fail(e)

    if passed():
        try:
            reoriented_molecule(h2o)
            reoriented_molecule(ch4)
        except Exception as e:
            fail(e)

    check()

    print("  orientation_in_wyckoff_position")
    try:
        from pyxtal.molecule import orientation_in_wyckoff_position
    except Exception as e:
        fail(e)

    if passed():
        try:
            w = get_wyckoffs(20)
            ws = get_wyckoff_symmetry(20, molecular=True)
            wp = Wyckoff_position.from_group_and_index(20, 1)
            orientation_in_wyckoff_position(h2o, wp)
            orientation_in_wyckoff_position(ch4, wp)
        except Exception as e:
            fail(e)

    check()

    # =====molecular_crystal=====
    print("pyxtal.molecular_crystal")
    reset()
    try:
        import pyxtal.crystal
    except Exception as e:
        fail(e)

    print("  molecular_crystal")
    try:
        from pyxtal.molecular_crystal import molecular_crystal
    except Exception as e:
        fail(e)

    if passed():
        try:
            c = molecular_crystal(1, ["H2O"], [1], 10.0)
            if c.valid is True:
                pass
            else:
                fail()
        except Exception as e:
            fail(e)

    check()

    print("  molecular_crystal_2D")
    try:
        from pyxtal.molecular_crystal import molecular_crystal_2D
    except Exception as e:
        fail(e)

    if passed():
        try:
            c = molecular_crystal_2D(1, ["H2O"], [1], 10.0)
            if c.valid is True:
                pass
            else:
                fail()
        except Exception as e:
            fail(e)

    check()

    end(condition=2)
示例#12
0
 def __getitem__(self, index):
     new_index = Element.number_from_specie(index)
     return self.matrix[index]
示例#13
0
    def __init__(self, *tuples, prototype="atomic", factor=1.0):
        f = factor
        self.prototype = prototype
        if prototype == "atomic":
            f *= 0.5
            attrindex = 5
            self.radius_type = "covalent"
        elif prototype == "molecular":
            attrindex = 5
            self.radius_type = "covalent"
            f *= 1.2
        elif prototype == "metallic":
            attrindex = 7
            self.radius_type = "metallic"
            f *= 0.5
        else:
            self.radius_type = "N/A"
        self.f = f
        H = Element("H")
        m = [[0.0] * (len(H.elements_list) + 1)]
        for i, tup1 in enumerate(H.elements_list):
            m.append([0.0])
            for j, tup2 in enumerate(H.elements_list):
                # Get the appropriate atomic radii
                if tup1[attrindex] is None:
                    if tup1[5] is None:
                        val1 = None
                    else:
                        # Use the covalent radius
                        val1 = tup1[5]
                else:
                    val1 = tup1[attrindex]
                if tup2[attrindex] is None:
                    if tup2[5] is None:
                        val2 = None
                    else:
                        # Use the covalent radius
                        val2 = tup1[5]
                else:
                    val2 = tup2[attrindex]
                if val1 is not None and val2 is not None:
                    m[-1].append(f * (val1 + val2))
                else:
                    # If no radius is found for either atom, set tolerance to None
                    m[-1].append(None)
        self.matrix = np.array(
            m
        )  # A symmetric np matrix storing the tolerance between specie pairs
        self.custom_values = (
            []
        )  # A list of tuples storing which species pair tolerances have custom values

        try:
            for tup in tuples:
                self.set_tol(*tup)
        except:
            printx(
                "Error: Could not set custom tolerance value(s).\n" +
                "All custom entries should be entered using the following form:\n"
                +
                "(specie1, specie2, value), where value is the tolerance in Angstroms.",
                priority=1,
            )

        self.radius_list = []
        for i in range(len(self.matrix)):
            if i == 0:
                continue
            x = self.get_tol(i, i)
            self.radius_list.append(x)