예제 #1
0
def reorient(structure, miller_index, rotate=0.):
    # Align miller_index direction to z-direction [0,0,1]
    struct = structure.copy()
    latt = struct.lattice
    recp = latt.reciprocal_lattice_crystallographic
    normal = recp.get_cartesian_coords(miller_index)
    normal /= np.linalg.norm(normal)
    z = [0, 0, 1]
    rot_axis = np.cross(normal, z)
    # Check if normal and z are linearly dependent
    if not np.isclose(rot_axis, [0, 0, 0]).all():
        angle = np.arccos(np.clip(np.dot(normal, z), -1.0, 1.0))
        struct = RotationTransformation(
            rot_axis, math.degrees(angle)).apply_transformation(struct)
    # Align other axis (longest) to x-axis
    lattm = struct.lattice.matrix
    basis_lengths_xy = [
        lattm[0][0]**2 + lattm[0][1]**2, lattm[1][0]**2 + lattm[1][1]**2,
        lattm[2][0]**2 + lattm[2][1]**2
    ]
    max_ind = basis_lengths_xy.index(max(basis_lengths_xy))
    max_basis = list(lattm[max_ind])
    max_basis[2] = 0
    max_basis /= np.linalg.norm(max_basis)
    angle2 = np.arccos(np.clip(np.dot(max_basis, [1, 0, 0]), -1.0, 1.0))
    struct = RotationTransformation(
        z, math.degrees(angle2)).apply_transformation(struct)
    # Check if correct sign of rotation was applied, if not: rotate twice the angle the other direction
    if abs(struct.lattice.matrix[max_ind][1]) > 1e-5:
        struct = RotationTransformation(
            z, -2 * math.degrees(angle2)).apply_transformation(struct)
    if rotate:
        struct = RotationTransformation(z, rotate).apply_transformation(struct)
    return struct
예제 #2
0
def test_get_symmetry_hash():
    """Test the symmetry hashes"""
    zif3 = MOFChecker.from_cif(
        os.path.join(THIS_DIR, "test_files", "ZIF-3.cif"))
    print(type(zif3.structure))
    hash_a = get_symmetry_hash(zif3.structure, tight=True)
    assert len(hash_a) == 275
    hash_b = get_symmetry_hash(zif3.structure)
    assert len(hash_b) == 47
    assert hash_a[-3:] == hash_b[-3:]

    zif4 = MOFChecker.from_cif(
        os.path.join(THIS_DIR, "test_files", "ZIF-4.cif"))
    hash_zif4_a = get_symmetry_hash(zif4.structure, tight=True)
    hash_zif4_b = get_symmetry_hash(zif4.structure)

    assert hash_zif4_a != hash_a
    assert hash_zif4_b != hash_b

    assert zif4.symmetry_hash == hash_zif4_b

    structure = Structure.from_file(
        os.path.join(THIS_DIR, "test_files", "ABAXUZ.cif"))
    original_hash = get_symmetry_hash(MOFChecker(structure).structure)

    # rotate structure
    rotation_transformer = RotationTransformation([1, 0, 0], 10)
    rotated_structure = rotation_transformer.apply_transformation(structure)
    assert get_symmetry_hash(
        MOFChecker(rotated_structure).structure) == original_hash

    # create supercell
    structure.make_supercell([1, 2, 1])
    print(type(structure))
    assert get_symmetry_hash(MOFChecker(structure).structure) == original_hash
예제 #3
0
    def rotate_c_parallel_to_z(self):
        """
        Rotates the cell such that lattice vector c is parallel to the
        Cartesian z-axis.

        Note: this method doesn't change the fractional coordinates of the
        sites. However, the Cartesian coordinates may be changed.
        """

        # rotate about the z-axis until c lies in the x-z plane
        rotation = RotationTransformation(
            [0, 0, 1], 180 - (180 / np.pi) *
            np.arctan2(self.lattice.matrix[2][1], self.lattice.matrix[2][0]))
        new_structure = rotation.apply_transformation(self)
        self.modify_lattice(new_structure.lattice)

        # rotate about the y-axis to make c parallel to the z-axis
        rotation = RotationTransformation(
            [0, 1, 0], 180 - (180 / np.pi) *
            np.arctan2(self.lattice.matrix[2][0], self.lattice.matrix[2][2]))
        new_structure = rotation.apply_transformation(self)
        self.modify_lattice(new_structure.lattice)

        # make sure c is pointing along the positive z-axis
        if self.lattice.matrix[2][2] < 0:
            # rotate 180 degrees about the x-axis
            rotation = RotationTransformation([1, 0, 0], 180)
            new_structure = rotation.apply_transformation(self)
            self.modify_lattice(new_structure.lattice)
예제 #4
0
def create_sample(edc, structure, angle_start, angle_change):
    dps = []
    for orientation in create_pair(angle_start, angle_change):
        axis, angle = euler2axangle(orientation[0], orientation[1],
                                    orientation[2], 'rzxz')
        rotation = RotationTransformation(axis, angle, angle_in_radians=True)
        rotated_structure = rotation.apply_transformation(structure)
        data = edc.calculate_ed_data(
            rotated_structure,
            reciprocal_radius=0.9,  #avoiding a reflection issue
            with_direct_beam=False)
        dps.append(data.as_signal(2 * half_side_length, 0.025, 1).data)
    dp = pxm.ElectronDiffraction([dps[0:2], dps[2:]])
    dp.set_diffraction_calibration(1 / half_side_length)
    return dp
예제 #5
0
def planar_structure_normalization(structure):
    '''
    This function does the following:
        1. check whether the structure is planar using coordniates standard deviation
        2. move the planar layer to the center of c-direction

    Args:
        structure: pymatgen structure
    Return:
        a boolean whether the structure is planar
        tranformed pymatgen structure
    '''
    tol = 1E-3 # tolerance to check whether the structure is planar
    is_planar = True

    coords = structure.frac_coords
    ts = TransformedStructure(structure, [])
    
    if np.std(coords[:,2]) < tol : 
        center_translate = 0.5 - coords[:,2].mean()
    elif np.std(coords[:,0]) < tol :
        ts.append_transformation(SupercellTransformation([[0,0,1],[0,1,0],[1,0,0]]))
        ts.append_transformation(RotationTransformation([0,1,0], 90))        
        center_translate = 0.5 - coords[:,0].mean()
    elif np.std(coords[:,1]) < tol :
        ts.append_transformation(SupercellTransformation([[1,0,0],[0,0,1],[0,1,0]]))
        ts.append_transformation(RotationTransformation([1,0,0], 90)) 
        center_translate = 0.5 - coords[:,1].mean()
    else : 
        is_planar = False
        transformed_structure = None

    if is_planar:
        ts.append_transformation(TranslateSitesTransformation(
                            list(range(len(structure))), [0,0,center_translate]))        
        # Use pymatgen 2019.7.2, ts.structures[-1] may change in a newer version           
        transformed_structure = ts.structures[-1]
    
    return is_planar, transformed_structure
예제 #6
0
    def get_diffraction_library(self,
                                structure_library,
                                calibration,
                                reciprocal_radius,
                                representation='euler'):
        """Calculates a dictionary of diffraction data for a library of crystal
        structures and orientations.

        Each structure in the structure library is rotated to each associated
        orientation and the diffraction pattern is calculated each time.

        Parameters
        ----------
        structure_library : dict
            Dictionary of structures and associated orientations (represented as
            Euler angles or axis-angle pairs) for which electron diffraction is
            to be simulated.

        calibration : float
            The calibration of experimental data to be correlated with the
            library, in reciprocal Angstroms per pixel.

        reciprocal_radius : float
            The maximum g-vector magnitude to be included in the simulations.

        representation : 'euler' or 'axis-angle'
            The representation in which the orientations are provided.
            If 'euler' the zxz convention is taken and values are in radians, if
            'axis-angle' the rotational angle is in degrees.

        Returns
        -------
        diffraction_library : dict of :class:`DiffractionSimulation`
            Mapping of crystal structure and orientation to diffraction data
            objects.

        """
        # Define DiffractionLibrary object to contain results
        diffraction_library = DiffractionLibrary()
        # The electron diffraction calculator to do simulations
        diffractor = self.electron_diffraction_calculator
        # Iterate through phases in library.
        for key in structure_library.keys():
            phase_diffraction_library = dict()
            structure = structure_library[key][0]
            orientations = structure_library[key][1]
            # Iterate through orientations of each phase.
            for orientation in tqdm(orientations, leave=False):
                if representation=='axis-angle':
                    axis = [orientation[0], orientation[1], orientation[2]]
                    angle = orientation[3] / 180 * pi
                if representation=='euler':
                    axis, angle = euler2axangle(orientation[0], orientation[1],
                                                orientation[2], 'rzxz')
                # Apply rotation to the structure
                rotation = RotationTransformation(axis, angle,
                                                  angle_in_radians=True)
                rotated_structure = rotation.apply_transformation(structure)
                # Calculate electron diffraction for rotated structure
                data = diffractor.calculate_ed_data(rotated_structure,
                                                    reciprocal_radius)
                # Calibrate simulation
                data.calibration = calibration
                # Construct diffraction simulation library.
                phase_diffraction_library[tuple(orientation)] = data
            diffraction_library[key] = phase_diffraction_library
        return diffraction_library
예제 #7
0
    def rotate_to_principal_directions(self):
        """
        Rotates the cell into the principal directions. That is, lattice vector
        a is parallel to the Cartesian x-axis, lattice vector b lies in the
        Cartesian x-y plane and the z-component of lattice vector c is
        positive.

        Note: this method doesn't change the fractional coordinates of the
        sites. However, the Cartesian coordinates may be changed.
        """

        # rotate about the z-axis to align a vertically with the x-axis
        rotation = RotationTransformation(
            [0, 0, 1], 180 - (180 / np.pi) *
            np.arctan2(self.lattice.matrix[0][1], self.lattice.matrix[0][0]))
        new_structure = rotation.apply_transformation(self)
        self.modify_lattice(new_structure.lattice)

        # rotate about the y-axis to make a parallel to the x-axis
        rotation = RotationTransformation(
            [0, 1, 0], (180 / np.pi) *
            np.arctan2(self.lattice.matrix[0][2], self.lattice.matrix[0][0]))
        new_structure = rotation.apply_transformation(self)
        self.modify_lattice(new_structure.lattice)

        # rotate about the x-axis to make b lie in the x-y plane
        rotation = RotationTransformation(
            [1, 0, 0], 180 - (180 / np.pi) *
            np.arctan2(self.lattice.matrix[1][2], self.lattice.matrix[1][1]))
        new_structure = rotation.apply_transformation(self)
        self.modify_lattice(new_structure.lattice)

        # make sure they are all pointing in positive directions
        if self.lattice.matrix[0][0] < 0:
            # rotate about y-axis to make a positive
            rotation = RotationTransformation([0, 1, 0], 180)
            new_structure = rotation.apply_transformation(self)
            self.modify_lattice(new_structure.lattice)
        if self.lattice.matrix[1][1] < 0:
            # rotate about x-axis to make b positive
            rotation = RotationTransformation([1, 0, 0], 180)
            new_structure = rotation.apply_transformation(self)
            self.modify_lattice(new_structure.lattice)
        if self.lattice.matrix[2][2] < 0:
            # mirror c across the x-y plane to make it positive
            # a and b
            a = self.lattice.matrix[0]
            b = self.lattice.matrix[1]
            # the components of c
            cx = self.lattice.matrix[2][0]
            cy = self.lattice.matrix[2][1]
            cz = -1 * self.lattice.matrix[2][2]
            self.modify_lattice(Lattice([a, b, [cx, cy, cz]]))
def slab_has_mirror_sym(slab, nterm=1, tol=0.01):
    '''This function tests if the input slab has a mirror symmetry in the c-direction (given tolerance 'tol' in Angstrom).
    Specify 'nterm' (number of unique terminations) to ensure enough subtractions from the top/bottom of the layer are considered.
    Unit cell can be of any shape, however make sure that the layer thickness in c-direction is thick enough
    (recommendation: SlabGenerator with min_slab_size=4, in_unit_planes=True)
    Remark: A bug in pymatgen/transformations/standard_transformations.py was fixed in version pymatgen-2020.4.29

    Output: [mirror_sym, error] where 'mirror_sym' is the mirror symmetry (True or False),
    'error' may contain an error message in case any step of the unit cell rotation didn't work, otherwise contains empty string

    Procedure:
    1. Rotate unit cell such that Cartesian coordinates of a and b basis vectors is of form (a_x,0,0) and (b_x,b_y,0), respectively.
    2. Create new c-direction orthogonal to a and b.
    3. Add atoms from slab in step 1 to new unit cell of step 2.
    4. Use function mirror_sym_check to check symmetry for the initial slab, the slab with the topmost, the slab with lowermost layer missing,
    and the slab with both topmost/lowermost layers missing. If nterm > 3, additionally np.floor(nterm/2) layers are subtracted from either side and their symmetry checked.
    '''
    error = ""
    if round(slab.lattice.alpha, 1) == 90.0 and round(slab.lattice.beta,
                                                      1) == 90.0:
        slab_straight = Structure(slab._lattice, slab.species_and_occu,
                                  slab.frac_coords)
    else:
        R = slab.lattice.matrix
        #print(R)
        #if a base vector not parallel to x-axis in caartesian coords, rotate the cell/structure such that it is
        if abs(R[0, 1]) > 0.0001 or abs(R[0, 2]) > 0.0001:
            x = [1, 0, 0]
            rot_axis = np.cross(R[0], x)
            angle = np.arccos(
                np.clip(
                    np.dot(R[0] / np.linalg.norm(R[0]), x / np.linalg.norm(x)),
                    -1.0, 1.0))
            slab = RotationTransformation(
                rot_axis, math.degrees(angle)).apply_transformation(slab)
            R = slab.lattice.matrix
            #In case the wrong sign of the rotation was applied, rotate back twice the angle:
            if abs(R[0, 1]) > 0.0001 or abs(R[0, 2]) > 0.0001:
                slab = RotationTransformation(
                    rot_axis,
                    -2 * math.degrees(angle)).apply_transformation(slab)
                R = slab.lattice.matrix
            if abs(R[0, 1]) > 0.0001 or abs(R[0, 2]) > 0.0001:
                error = "Error. Could not rotate a-axis to be parallel to x-axis."
            #print(R)
        #if b vector not lying in cartesian x-y plane, rotate to make it so (i.e. z-component of b vector = 0)
        if abs(R[1, 2]) > 0.0001 and not error:
            b_x_flat = [0, 0, 0]
            b_x_flat[1] = R[1, 1]
            b_x_flat[2] = R[1, 2]
            x = [1, 0, 0]
            y = [0, 1, 0]
            angle2 = np.arccos(
                np.clip(
                    np.dot(b_x_flat / np.linalg.norm(b_x_flat),
                           y / np.linalg.norm(y)), -1.0, 1.0)
            )  #angle between y-axis and b vector projected onto y-z-plane
            slab = RotationTransformation(
                x, math.degrees(angle2)).apply_transformation(slab)
            R = slab.lattice.matrix
            #In case the wrong sign of the rotation was applied, rotate back twice the angle:
            if abs(R[1, 2]) > 0.0001:
                slab = RotationTransformation(
                    x, -2 * math.degrees(angle2)).apply_transformation(slab)
                R = slab.lattice.matrix
            if abs(R[1, 2]) > 0.0001:
                error = "Error. Could not rotate b-vector to lie within x-y-plane."
            if R[1, 1] < -0.0001:
                error = "Error. Vector b faces into negative y-direction (which could cause problems)."
        #Now create new c-direction that is orthogonal to the rotated a and b vectors
        if not error:
            N = np.array(R)  #new lattice vectors
            N[2] = np.cross(R[0], R[1])
            N[2] = N[2] * np.dot(
                R[2], N[2]) / (np.linalg.norm(N[2]) * np.linalg.norm(N[2]))
            latticeN = Lattice(N)  #new lattice with c perpendicular to a,b
            #Add atoms from rotated unit cell to new unit cell with orthogonal c-direction
            slab_straight = Structure(latticeN,
                                      slab.species,
                                      slab.cart_coords,
                                      coords_are_cartesian=True)
    #Check mirror symmetry for straightened slab as well as slabs that are missing either (or both) topmost, lowermost atom-layers
    if not error:
        mirror_sym = False

        #Checks mirror symmetry of slab_straight without any layers removed
        slab_orig = Structure(slab_straight._lattice,
                              slab_straight.species_and_occu,
                              slab_straight.frac_coords)
        msym, err = mirror_sym_check(slab_orig, tol=tol)
        if msym:
            mirror_sym = True
        if not err == '':
            error = err

        #Checks mirror symmetry of slab_straight with lowermost layer removed
        min_value = np.min(slab_orig.cart_coords[:, 2])
        first_layer_size = len(
            np.where(np.abs(min_value - slab_orig.cart_coords[:, 2]) < tol)[0])
        for i in range(first_layer_size):
            index_to_remove = np.argmin(slab_orig.frac_coords[:, 2])
            slab_orig.remove_sites([index_to_remove])
        msym, err = mirror_sym_check(slab_orig, tol=tol)
        if msym:
            mirror_sym = True
        if not err == '':
            error = err

        #Checks mirror symmetry of slab_straight with topmost layer removed
        max_value = np.max(slab_straight.cart_coords[:, 2])
        first_layer_size = len(
            np.where(
                np.abs(max_value - slab_straight.cart_coords[:, 2]) < tol)[0])
        for i in range(first_layer_size):
            index_to_remove = np.argmax(slab_straight.frac_coords[:, 2])
            slab_straight.remove_sites([index_to_remove])
        msym, err = mirror_sym_check(slab_straight, tol=tol)
        if msym:
            mirror_sym = True
        if not err == '':
            error = err

        #Checks mirror symmetry of slab_straight with lowermost and topmost layers removed
        min_value = np.min(slab_straight.cart_coords[:, 2])
        first_layer_size = len(
            np.where(
                np.abs(min_value - slab_straight.cart_coords[:, 2]) < tol)[0])
        for i in range(first_layer_size):
            index_to_remove = np.argmin(slab_straight.frac_coords[:, 2])
            slab_straight.remove_sites([index_to_remove])
        msym, err = mirror_sym_check(slab_straight, tol=tol)
        if msym:
            mirror_sym = True
        if not err == '':
            error = err

        #If nterm is larger than 3, remove additonal layers from either side to ensure
        #that we check all relevant slabs that could yield proof that there is mirror symmetry
        if nterm > 3:
            slab_orig = Structure(slab_straight._lattice,
                                  slab_straight.species_and_occu,
                                  slab_straight.frac_coords)
            #delete more layers nterm/2 rounded down on either side from the slab_straight (which had one each side already subtracted)
            for term in range(int(np.floor(nterm / 2))):
                max_value = np.max(slab_straight.cart_coords[:, 2])
                first_layer_size = len(
                    np.where(
                        np.abs(max_value -
                               slab_straight.cart_coords[:, 2]) < tol)[0])
                for i in range(first_layer_size):
                    index_to_remove = np.argmax(slab_straight.frac_coords[:,
                                                                          2])
                    slab_straight.remove_sites([index_to_remove])
                msym, err = mirror_sym_check(slab_straight, tol=tol)
                if msym:
                    mirror_sym = True
                if not err == '':
                    error = err

                min_value = np.min(slab_orig.cart_coords[:, 2])
                first_layer_size = len(
                    np.where(
                        np.abs(min_value -
                               slab_orig.cart_coords[:, 2]) < tol)[0])
                for i in range(first_layer_size):
                    index_to_remove = np.argmin(slab_orig.frac_coords[:, 2])
                    slab_orig.remove_sites([index_to_remove])
                msym, err = mirror_sym_check(slab_orig, tol=tol)
                if msym:
                    mirror_sym = True
                if not err == '':
                    error = err

    else:
        #Mirror symmetry is set to False in case there was an error along the way.
        mirror_sym = False

    return mirror_sym, error
예제 #9
0
 def test_rotation_transformation(self):
     t = RotationTransformation([0, 1, 0], 30, False)
     s2 = t.apply_transformation(self.struct)
     s1 = t.inverse.apply_transformation(s2)
     self.assertTrue(
         (abs(s1.lattice.matrix - self.struct.lattice.matrix) < 1e-8).all())
예제 #10
0
 def test_as_from_dict(self):
     t = RotationTransformation([0, 1, 0], 30, False)
     d = t.as_dict()
     self.assertEqual(type(RotationTransformation.from_dict(d)),
                      RotationTransformation)
예제 #11
0
    def get_diffraction_library(self,
                                structure_library,
                                calibration,
                                reciprocal_radius,
                                half_shape,
                                representation='euler',
                                with_direct_beam=True):
        """Calculates a dictionary of diffraction data for a library of crystal
        structures and orientations.

        Each structure in the structure library is rotated to each associated
        orientation and the diffraction pattern is calculated each time.

        Parameters
        ----------
        structure_library : dict
            Dictionary of structures and associated orientations (represented as
            Euler angles or axis-angle pairs) for which electron diffraction is
            to be simulated.

        calibration : float
            The calibration of experimental data to be correlated with the
            library, in reciprocal Angstroms per pixel.

        reciprocal_radius : float
            The maximum g-vector magnitude to be included in the simulations.

        representation : 'euler' or 'axis-angle'
            The representation in which the orientations are provided.
            If 'euler' the zxz convention is taken and values are in radians, if
            'axis-angle' the rotational angle is in degrees.

        half_shape: tuple
            The half shape of the target patterns, for 144x144 use (72,72) etc

        Returns
        -------
        diffraction_library : dict of :class:`DiffractionSimulation`
            Mapping of crystal structure and orientation to diffraction data
            objects.

        """
        # Define DiffractionLibrary object to contain results
        diffraction_library = DiffractionLibrary()
        # The electron diffraction calculator to do simulations
        diffractor = self.electron_diffraction_calculator
        # Iterate through phases in library.
        for key in structure_library.keys():
            phase_diffraction_library = dict()
            structure = structure_library[key][0]
            orientations = structure_library[key][1]
            # Iterate through orientations of each phase.
            for orientation in tqdm(orientations, leave=False):
                if representation == 'axis-angle':
                    axis = [orientation[0], orientation[1], orientation[2]]
                    angle = orientation[3] / 180 * pi
                if representation == 'euler':
                    axis, angle = euler2axangle(orientation[0], orientation[1],
                                                orientation[2], 'rzxz')
                # Apply rotation to the structure
                rotation = RotationTransformation(axis,
                                                  angle,
                                                  angle_in_radians=True)
                rotated_structure = rotation.apply_transformation(structure)
                # Calculate electron diffraction for rotated structure
                data = diffractor.calculate_ed_data(rotated_structure,
                                                    reciprocal_radius,
                                                    with_direct_beam)
                # Calibrate simulation
                data.calibration = calibration
                pattern_intensities = data.intensities
                pixel_coordinates = np.rint(
                    data.calibrated_coordinates[:, :2] +
                    half_shape).astype(int)
                # Construct diffraction simulation library, removing those that contain no peaks
                if len(pattern_intensities) > 0:
                    phase_diffraction_library[tuple(orientation)] = \
                    {'Sim':data,'intensities':pattern_intensities, \
                     'pixel_coords':pixel_coordinates, \
                     'pattern_norm': np.sqrt(np.dot(pattern_intensities,pattern_intensities))}
                    diffraction_library[key] = phase_diffraction_library
        return diffraction_library
예제 #12
0
def test_graph_hash_robustness():  # pylint: disable=too-many-locals
    """Check that duplicating or rotating the structure produces the same hash."""
    structure = Structure.from_file(
        os.path.join(THIS_DIR, "test_files", "ABAXUZ.cif"))
    original_hash = MOFChecker(structure).graph_hash

    # rotate structure
    rotation_transformer = RotationTransformation([1, 0, 0], 10)
    rotated_structure = rotation_transformer.apply_transformation(structure)
    assert MOFChecker(rotated_structure).graph_hash == original_hash

    # create supercell
    structure.make_supercell([1, 2, 1])
    assert MOFChecker(structure).graph_hash == original_hash

    # check the MOF-74 structures
    mohgoi_checker = MOFChecker(
        Structure.from_file(os.path.join(THIS_DIR, "test_files",
                                         "MOHGOI.cif")))

    todyuj_checker = MOFChecker(
        Structure.from_file(os.path.join(THIS_DIR, "test_files",
                                         "TODYUJ.cif")))

    vogtiv_checker = MOFChecker(
        Structure.from_file(os.path.join(THIS_DIR, "test_files",
                                         "VOGTIV.cif")))

    # There water on TODYUJ
    assert mohgoi_checker.graph_hash != todyuj_checker.graph_hash
    # one is the supercell of the other
    assert mohgoi_checker.graph_hash == vogtiv_checker.graph_hash

    # MOF-74-Zr.cif
    mof_74_zr = MOFChecker(
        Structure.from_file(
            os.path.join(THIS_DIR, "test_files", "MOF-74-Zr.cif")))
    assert mof_74_zr.graph_hash != todyuj_checker.graph_hash
    assert mof_74_zr.graph_hash != vogtiv_checker.graph_hash

    # # MOF-74-Zn.cif
    mof_74_zn = MOFChecker(
        Structure.from_file(
            os.path.join(THIS_DIR, "test_files", "MOF-74-Zn.cif")))
    assert mof_74_zr.scaffold_hash == mof_74_zn.scaffold_hash
    assert mof_74_zr.graph_hash != mof_74_zn.graph_hash

    # # MOF-5 is not ZIF-8
    mof_5 = MOFChecker(
        Structure.from_file(
            os.path.join(THIS_DIR, "test_files", "mof-5_cellopt.cif")))
    zif_8 = MOFChecker(
        Structure.from_file(
            os.path.join(THIS_DIR, "test_files", "ZIF-8-RASPA.cif")))
    assert mof_5.graph_hash != zif_8.graph_hash

    # # Mn-MOF-74 and UiO-67
    coknun = MOFChecker(
        Structure.from_file(
            os.path.join(THIS_DIR, "test_files", "coknun01.cif")))
    wizmac = MOFChecker(
        Structure.from_file(
            os.path.join(THIS_DIR, "test_files", "WIZMAV02_auto.cif")))
    assert coknun.graph_hash != wizmac.graph_hash