def test_substitute(self): structure = Structure.from_file(os.path.join(PymatgenTest.TEST_FILES_DIR, "Li2O.cif")) molecule = FunctionalGroups["methyl"] structure_copy = copy.deepcopy(structure) structure_copy_graph = copy.deepcopy(structure) sg = StructureGraph.with_local_env_strategy(structure, MinimumDistanceNN()) sg_copy = copy.deepcopy(sg) # Ensure that strings and molecules lead to equivalent substitutions sg.substitute_group(1, molecule, MinimumDistanceNN) sg_copy.substitute_group(1, "methyl", MinimumDistanceNN) self.assertEqual(sg, sg_copy) # Ensure that the underlying structure has been modified as expected structure_copy.substitute(1, "methyl") self.assertEqual(structure_copy, sg.structure) # Test inclusion of graph dictionary graph_dict = { (0, 1): {"weight": 0.5}, (0, 2): {"weight": 0.5}, (0, 3): {"weight": 0.5}, } sg_with_graph = StructureGraph.with_local_env_strategy(structure_copy_graph, MinimumDistanceNN()) sg_with_graph.substitute_group(1, "methyl", MinimumDistanceNN, graph_dict=graph_dict) edge = sg_with_graph.graph.get_edge_data(11, 13)[0] self.assertEqual(edge["weight"], 0.5)
def _preprocess_input_to_graph( input: Union[Structure, StructureGraph, Molecule, MoleculeGraph], bonding_strategy: str = "CrystalNN", bonding_strategy_kwargs: Optional[Dict] = None, ) -> Union[StructureGraph, MoleculeGraph]: if isinstance(input, Structure): # ensure fractional co-ordinates are normalized to be in [0,1) # (this is actually not guaranteed by Structure) input = input.as_dict(verbosity=0) for site in input["sites"]: site["abc"] = np.mod(site["abc"], 1) input = Structure.from_dict(input) if not input.is_ordered: # calculating bonds in disordered structures is currently very flaky bonding_strategy = "CutOffDictNN" # we assume most uses of this class will give a structure as an input argument, # meaning we have to calculate the graph for bonding information, however if # the graph is already known and supplied, we will use that if isinstance(input, StructureGraph) or isinstance( input, MoleculeGraph): graph = input else: if (bonding_strategy not in StructureMoleculeComponent. available_bonding_strategies.keys()): raise ValueError( "Bonding strategy not supported. Please supply a name " "of a NearNeighbor subclass, choose from: {}".format( ", ".join(StructureMoleculeComponent. available_bonding_strategies.keys()))) else: bonding_strategy_kwargs = bonding_strategy_kwargs or {} if bonding_strategy == "CutOffDictNN": if "cut_off_dict" in bonding_strategy_kwargs: # TODO: remove this hack by making args properly JSON serializable bonding_strategy_kwargs["cut_off_dict"] = { (x[0], x[1]): x[2] for x in bonding_strategy_kwargs["cut_off_dict"] } bonding_strategy = StructureMoleculeComponent.available_bonding_strategies[ bonding_strategy](**bonding_strategy_kwargs) try: if isinstance(input, Structure): graph = StructureGraph.with_local_env_strategy( input, bonding_strategy) else: graph = MoleculeGraph.with_local_env_strategy( input, bonding_strategy) except: # for some reason computing bonds failed, so let's not have any bonds(!) if isinstance(input, Structure): graph = StructureGraph.with_empty_graph(input) else: graph = MoleculeGraph.with_empty_graph(input) return graph
def test_mul(self): square_sg_mul = self.square_sg * (2, 1, 1) square_sg_mul_ref_str = """Structure Graph Structure: Full Formula (H2) Reduced Formula: H2 abc : 10.000000 5.000000 50.000000 angles: 90.000000 90.000000 90.000000 Sites (2) # SP a b c --- ---- --- --- --- 0 H 0 0 0 1 H 0.5 0 -0 Graph: bonds from to to_image ---- ---- ------------ 0 0 (0, 1, 0) 0 0 (0, -1, 0) 0 1 (0, 0, 0) 0 1 (-1, 0, 0) 1 1 (0, 1, 0) 1 1 (0, -1, 0) """ square_sg_mul_actual_str = str(square_sg_mul) # only testing bonds portion, # the c frac_coord of the second H can vary from # 0 to -0 depending on machine precision square_sg_mul_ref_str = "\n".join(square_sg_mul_ref_str.splitlines()[11:]) square_sg_mul_actual_str = "\n".join(square_sg_mul_actual_str.splitlines()[11:]) self.assertStrContentEqual(square_sg_mul_actual_str, square_sg_mul_ref_str) # test sequential multiplication sq_sg_1 = self.square_sg * (2, 2, 1) sq_sg_1 = sq_sg_1 * (2, 2, 1) sq_sg_2 = self.square_sg * (4, 4, 1) self.assertEqual(sq_sg_1.graph.number_of_edges(), sq_sg_2.graph.number_of_edges()) # TODO: the below test still gives 8 != 4 # self.assertEqual(self.square_sg.get_coordination_of_site(0), 4) mos2_sg_mul = self.mos2_sg * (3, 3, 1) for idx in mos2_sg_mul.structure.indices_from_symbol("Mo"): self.assertEqual(mos2_sg_mul.get_coordination_of_site(idx), 6) mos2_sg_premul = StructureGraph.with_local_env_strategy(self.structure * (3, 3, 1), MinimumDistanceNN()) self.assertTrue(mos2_sg_mul == mos2_sg_premul) # test 3D Structure nio_sg = StructureGraph.with_local_env_strategy(self.NiO, MinimumDistanceNN()) nio_sg = nio_sg * 3 for n in range(len(nio_sg)): self.assertEqual(nio_sg.get_coordination_of_site(n), 6)
def setUp(self): self.maxDiff = None # trivial example, simple square lattice for testing structure = Structure(Lattice.tetragonal(5.0, 50.0), ["H"], [[0, 0, 0]]) self.square_sg = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) # TODO: decorating still fails because the structure graph gives a CN of 8 for this square lattice # self.square_sg.decorate_structure_with_ce_info() # body-centered square lattice for testing structure = Structure(Lattice.tetragonal(5.0, 50.0), ["H", "He"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.bc_square_sg = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(-1, -1, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) # body-centered square lattice for testing # directions reversed, should be equivalent to bc_square structure = Structure(Lattice.tetragonal(5.0, 50.0), ["H", "He"], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.bc_square_sg_r = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) self.bc_square_sg_r.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(-1, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(-1, -1, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(0, -1, 0), to_jimage=(0, 0, 0)) # MoS2 example, structure graph obtained from critic2 # (not ground state, from mp-1023924, single layer) stdout_file = os.path.join(PymatgenTest.TEST_FILES_DIR, "critic2/MoS2_critic2_stdout.txt") with open(stdout_file) as f: reference_stdout = f.read() self.structure = Structure.from_file(os.path.join(PymatgenTest.TEST_FILES_DIR, "critic2/MoS2.cif")) c2o = Critic2Analysis(self.structure, reference_stdout) self.mos2_sg = c2o.structure_graph(include_critical_points=False) latt = Lattice.cubic(4.17) species = ["Ni", "O"] coords = [[0, 0, 0], [0.5, 0.5, 0.5]] self.NiO = Structure.from_spacegroup(225, latt, species, coords).get_primitive_structure() # BCC example. self.bcc = Structure(Lattice.cubic(5.0), ["He", "He"], [[0, 0, 0], [0.5, 0.5, 0.5]]) warnings.simplefilter("ignore")
def _preprocess_input_to_graph( input: Union[Structure, StructureGraph], bonding_strategy: str = DEFAULTS["bonding_strategy"], bonding_strategy_kwargs: Optional[Dict] = None, ) -> Union[StructureGraph, MoleculeGraph]: # ensure fractional co-ordinates are normalized to be in [0,1) # (this is actually not guaranteed by Structure) try: input = input.as_dict(verbosity=0) except TypeError: # TODO: remove this, necessary for Slab(?), some structure subclasses don't have verbosity input = input.as_dict() for site in input["sites"]: site["abc"] = np.mod(site["abc"], 1) input = Structure.from_dict(input) if not input.is_ordered: # calculating bonds in disordered structures is currently very flaky bonding_strategy = "CutOffDictNN" if (bonding_strategy not in StructureComponent.available_bonding_strategies.keys()): raise ValueError( "Bonding strategy not supported. Please supply a name " "of a NearNeighbor subclass, choose from: {}".format(", ".join( StructureComponent.available_bonding_strategies.keys()))) else: bonding_strategy_kwargs = bonding_strategy_kwargs or {} if bonding_strategy == "CutOffDictNN": if "cut_off_dict" in bonding_strategy_kwargs: # TODO: remove this hack by making args properly JSON serializable bonding_strategy_kwargs["cut_off_dict"] = { (x[0], x[1]): x[2] for x in bonding_strategy_kwargs["cut_off_dict"] } bonding_strategy = StructureComponent.available_bonding_strategies[ bonding_strategy](**bonding_strategy_kwargs) try: with warnings.catch_warnings(): warnings.simplefilter("ignore") graph = StructureGraph.with_local_env_strategy( input, bonding_strategy) except: # for some reason computing bonds failed, so let's not have any bonds(!) graph = StructureGraph.with_empty_graph(input) return graph
def _get_graphs(cutoff, ordered_structures): """ Generate graph representations of magnetic structures with nearest neighbor bonds. Right now this only works for MinimumDistanceNN. Args: cutoff (float): Cutoff in Angstrom for nearest neighbor search. ordered_structures (list): Structure objects. Returns: sgraphs (list): StructureGraph objects. """ # Strategy for finding neighbors if cutoff: strategy = MinimumDistanceNN(cutoff=cutoff, get_all_sites=True) else: strategy = MinimumDistanceNN() # only NN # Generate structure graphs sgraphs = [ StructureGraph.with_local_env_strategy(s, strategy=strategy) for s in ordered_structures ] return sgraphs
def _has_stray_molecules(self) -> bool: self._set_cnn() sgraph = StructureGraph.with_local_env_strategy(self.structure, self._cnn) molecules = get_subgraphs_as_molecules_all(sgraph) if len(molecules) > 0: return True return False
def get_bonds(self): graph = StructureGraph.with_local_env_strategy( self.structure, CutOffDictNN({("Si", "O"): 2.0, ("O", "Si"): 2.0}) ) # GULP starts counting on 1 return [(u + 1, v + 1, "single") for u, v in graph.graph.edges()]
def from_dict(cls, d): scene_dicts = { k: {k2: np.array(v2) for k2, v2 in v.items()} for k, v in d["scene_dicts"].items() } return cls(scene_dicts, StructureGraph.from_dict(d["structure_graph"]))
def subgraph_translate3(read_path, write_dir): ''' This function takes the metal-deficient structure and saves the all connected components (i.e. linkers) ''' ase_struct = read(read_path) struct = pm.get_structure(ase_struct) n_atoms = len(struct.sites) sg = StructureGraph.with_local_env_strategy(struct, env.JmolNN(tol=.3)) count = 1 for i in range(n_atoms): for j in range(n_atoms): if i != j: try: sg.alter_edge(i, j, new_weight=count) except: pass count += 1 A = sg.get_subgraphs_as_molecules(use_weights=True) ls = [] count = 0 for mol in A: if len(mol.sites) > 4: smiles = getSmiles(mol) ls.append(smiles) path = write_dir + 'mol_' + str(count) + '.xyz' saveMol(mol, path) count += 1 return count, ls
def test_no_duplicate_hops(self): test_structure_dict = { "@module": "pymatgen.core.structure", "@class": "Structure", "charge": None, "lattice": { "matrix": [[2.990355, -5.149042, 0.0], [2.990355, 5.149042, 0.0], [0.0, 0.0, 24.51998]] }, "sites": [ { "species": [{ "element": "Ba", "occu": 1 }], "abc": [0.005572, 0.994428, 0.151095], "properties": {} }, ], } test_structure = Structure.from_dict(test_structure_dict) nn = MinimumDistanceNN(cutoff=6, get_all_sites=True) sg = StructureGraph.with_local_env_strategy(test_structure, nn) self.assertEqual(sg.graph.number_of_edges(), 3)
def __init__(self, structure, migrating_specie, max_path_length=10, symprec=0.1, vac_mode=False): """ Args: structure: Input structure that contains all sites. migrating_specie (Specie-like): The specie that migrates. E.g., "Li". max_path_length (float): Maximum length of NEB path in the unit of Angstrom. Defaults to None, which means you are setting the value to the min cutoff until finding 1D or >1D percolating paths. symprec (float): Symmetry precision to determine equivalence. """ self.structure = structure self.migrating_specie = get_el_sp(migrating_specie) self.symprec = symprec self.a = SpacegroupAnalyzer(self.structure, symprec=self.symprec) self.symm_structure = self.a.get_symmetrized_structure() self.only_sites = self.get_only_sites() self.unique_hops = None # Generate the graph edges between these all the sites self.s_graph = StructureGraph.with_local_env_strategy( self.only_sites, MinimumDistanceNN( cutoff=max_path_length, get_all_sites=True)) # weights in this graph are the distances self.s_graph.set_node_attributes()
def structure_graph(self, edge_weight="bond_length", edge_weight_units="Å"): """ A StructureGraph object describing bonding information in the crystal. Lazily constructed. :param edge_weight: a value to store on the Graph edges, by default this is "bond_length" but other supported values are any of the attributes of CriticalPoint :return: """ sg = StructureGraph.with_empty_graph(self.structure, name="bonds", edge_weight_name=edge_weight, edge_weight_units=edge_weight_units) edges = self.edges.copy() idx_to_delete = [] # check for duplicate bonds for idx, edge in edges.items(): unique_idx = self.nodes[idx]['unique_idx'] # only check edges representing bonds, not rings if self.critical_points[unique_idx].type == CriticalPointType.bond: if idx not in idx_to_delete: for idx2, edge2 in edges.items(): if idx != idx2 and edge == edge2: idx_to_delete.append(idx2) warnings.warn("Duplicate edge detected, try re-running " "critic2 with custom parameters to fix this. " "Mostly harmless unless user is also " "interested in rings/cages.") logger.debug("Duplicate edge between points {} (unique point {})" "and {} ({}).".format(idx, self.nodes[idx]['unique_idx'], idx2, self.nodes[idx2]['unique_idx'])) # and remove any duplicate bonds present for idx in idx_to_delete: del edges[idx] for idx, edge in edges.items(): unique_idx = self.nodes[idx]['unique_idx'] # only add edges representing bonds, not rings if self.critical_points[unique_idx].type == CriticalPointType.bond: from_idx = edge['from_idx'] to_idx = edge['to_idx'] from_lvec = edge['from_lvec'] to_lvec = edge['to_lvec'] if edge_weight == "bond_length": weight = self.structure.get_distance(from_idx, to_idx) else: weight = getattr(self.critical_points[unique_idx], edge_weight, None) sg.add_edge(from_idx, to_idx, from_jimage=from_lvec, to_jimage=to_lvec, weight=weight) return sg
def test_from_local_env_and_equality_and_diff(self): nn = MinimumDistanceNN() sg = StructureGraph.with_local_env_strategy(self.structure, nn) self.assertEqual(sg.graph.number_of_edges(), 6) nn2 = MinimumOKeeffeNN() sg2 = StructureGraph.with_local_env_strategy(self.structure, nn2) self.assertTrue(sg == sg2) self.assertTrue(sg == self.mos2_sg) # TODO: find better test case where graphs are different diff = sg.diff(sg2) self.assertEqual(diff["dist"], 0) self.assertEqual(self.square_sg.get_coordination_of_site(0), 2)
def _has_lone_atom(self): self._set_cnn() graph = StructureGraph.with_local_env_strategy(self.structure, self._cnn) for site in range(len(self.structure)): nbr = graph.get_connected_sites(site) if not nbr: return True return False
def get_interaction_graph(self, filename=None): """ Get a StructureGraph with edges and weights that correspond to exchange interactions and J_ij values, respectively. Args: filename (str): if not None, save interaction graph to filename. Returns: igraph (StructureGraph): Exchange interaction graph. """ structure = self.ordered_structures[0] sgraph = self.sgraphs[0] unique_site_ids = self.unique_site_ids dists = self.dists tol = self.tol igraph = StructureGraph.with_empty_graph( structure, edge_weight_name="exchange_constant", edge_weight_units="meV") if "<J>" in self.ex_params: # Only <J> is available warning_msg = """ Only <J> is available. The interaction graph will not tell you much. """ warnings.warn(warning_msg) # J_ij exchange interaction matrix for i, node in enumerate(sgraph.graph.nodes): connections = sgraph.get_connected_sites(i) for c in connections: jimage = c[1] # relative integer coordinates of atom j dx = jimage[0] dy = jimage[1] dz = jimage[2] j = c[2] # index of neighbor dist = c[-1] # i <-> j distance j_exc = self._get_j_exc(i, j, dist) igraph.add_edge(i, j, to_jimage=jimage, weight=j_exc, warn_duplicates=False) # Save to a json file if desired if filename: if filename.endswith(".json"): dumpfn(igraph, filename) else: filename += ".json" dumpfn(igraph, filename) return igraph
def test_build(self): builder = BondBuilder(self.materials, self.bonding) runner = Runner([builder]) runner.run() doc = list(self.bonding.query(criteria={'task_id': 'mp-779001'}))[0] sg = StructureGraph.from_dict(doc['graph']) self.assertIsInstance(sg, StructureGraph) self.assertIn('Hf-O(6)', doc['summary']['coordination_envs'])
def compare_graph_pair_cached(self, items): nn_strategy = JmolNN() crystal_a = self.reduced_structure_dict[ self.scalar_feature_matrix.iloc[items[0]]["name"]] crystal_b = self.reduced_structure_dict[ self.scalar_feature_matrix.iloc[items[1]]["name"]] if self.try_supercell: crystal_a, crystal_b = attempt_supercell_pymatgen( crystal_a, crystal_b) sgraph_a = StructureGraph.with_local_env_strategy( crystal_a, nn_strategy) sgraph_b = StructureGraph.with_local_env_strategy( crystal_b, nn_strategy) try: if sgraph_a == sgraph_b: logger.debug("Found duplicate") return items except ValueError: logger.debug("Structures were probably not different") return False
def get_cooccurrence_pairs(struct): pairs = [] struct_graph = StructureGraph.with_local_env_strategy(struct, CrystalNN()) labels = {i: spec.name for i, spec in enumerate(struct.species)} G = struct_graph.graph.to_undirected() for n in labels: target = labels[n] # TODO what if the atom doesn't have any neighbors? neighbors = [labels[i] for i in G.neighbors(n)] for neighbor in neighbors: pairs.append((target, neighbor)) return pairs
def get_distance_vectors(self, sgraph: StructureGraph) -> dict: """Creates the distance vectors between connected nodes. Useful when walking through the graph later. """ distance_vectors = {} for u in sgraph.graph.nodes: ucoords = sgraph.structure[u].coords for conn_site in sgraph.get_connected_sites(u): v = conn_site.index vcoords = conn_site.site.coords distance_vectors[(u, v)] = vcoords - ucoords return distance_vectors
def test_from_edges(self): edges = { (0, 0, (0, 0, 0), (1, 0, 0)): None, (0, 0, (0, 0, 0), (-1, 0, 0)): None, (0, 0, (0, 0, 0), (0, 1, 0)): None, (0, 0, (0, 0, 0), (0, -1, 0)): None, } structure = Structure(Lattice.tetragonal(5.0, 50.0), ["H"], [[0, 0, 0]]) sg = StructureGraph.with_edges(structure, edges) self.assertEqual(sg, self.square_sg)
def test_no_duplicate_hops(self): test_structure = Structure( lattice=[[2.990355, -5.149042, 0.0], [2.990355, 5.149042, 0.0], [0.0, 0.0, 24.51998]], species=["Ba"], coords=[[0.005572, 0.994428, 0.151095]], ) nn = MinimumDistanceNN(cutoff=6, get_all_sites=True) sg = StructureGraph.with_local_env_strategy(test_structure, nn) self.assertEqual(sg.graph.number_of_edges(), 3)
def count_cooccurrences_single(struct): counts = {} struct_graph = StructureGraph.with_local_env_strategy(struct, CrystalNN()) labels = {i: spec.name for i, spec in enumerate(struct.species)} G = struct_graph.graph.to_undirected() for n in labels: target = labels[n] neighbors = [labels[i] for i in G.neighbors(n)] for neighbor in neighbors: key = frozenset([target, neighbor]) if key not in counts: counts[key] = 0 counts[key] += 1 return counts
def _has_undercoordinated_nitrogen(self, tolerance=10): """ Captures missing hydrogens on amino groups. Basically two common cases: 1. Have the N on a carbon and no hydrogen at all 2. (not that common) due to incorrect symmetry resolution we have only one h in a bent orientation """ undercoordinated_nitrogen = False for site_index in self.n_indices: cn = self.get_cn(site_index) # pylint:disable=invalid-name if cn == 1: # this is suspicous, but it also might a CN wish is perfectly fine # to check this, we first see if the neighbor is carbon # and then what its coordination number is graph = StructureGraph.with_local_env_strategy( self.structure, self._cnn ) neighbors = graph.get_connected_sites(site_index) if (self.get_cn(neighbors[0].index) > 2) and ( str(neighbors[0].periodic_site.specie) == "C" ): undercoordinated_nitrogen = True break if cn == 2: # ToDo: Check if it is bound to metal, then it might be a nitride graph = StructureGraph.with_local_env_strategy( self.structure, self._cnn ) neighbors = graph.get_connected_sites(site_index) angle = self.structure.get_angle( site_index, neighbors[0].index, neighbors[1].index ) if np.abs(90 - angle) > tolerance: undercoordinated_nitrogen = True break self._undercoordinated_nitrogen = undercoordinated_nitrogen
def construct_clean_graph(structure: Structure, structure_graph: StructureGraph) -> nx.Graph: """Creates a networkx graph with atom numbers as node labels""" edges = {(u, v) for u, v, d in structure_graph.graph.edges(keys=False, data=True)} graph = nx.Graph() graph.add_edges_from(edges) for node in graph.nodes: graph.nodes[node]["specie"] = str(structure[node].specie) graph.nodes[node]["specie-cn"] = ( str(structure[node].specie) + "-" + str(structure_graph.get_coordination_of_site(node))) return graph
def make_scene_dicts(parchg_list, defect_pos, level=None): band_indices = [c.split(".")[-2] for c in parchg_list] # parchgs = [Chgcar.from_file(c) for c in parchg_list] parchgs = [] for c in parchg_list: try: parchgs.append(Chgcar.from_file(c)) except ValueError: continue if len(parchgs) == 0: return None structure: Structure = parchgs[0].structure if len(parchg_list) > 1: for parchg in parchgs[1:]: assert structure == parchg.structure lattice_matrix = parchgs[0].structure.lattice.matrix # centering to [0.5, 0.5, 0.5] shift_vector = np.array([0.5 - pos for pos in defect_pos]) shape = parchgs[0].data["total"].shape shift_numbers = np.array(np.rint(shape * shift_vector), dtype=np.int) actual_shift_vector = shift_numbers / shape step_size = int(min(parchgs[0].dim) / 30) results = {} for name, parchg in zip(band_indices, parchgs): for spin in [Spin.up, Spin.down]: spin_str = "up" if spin is Spin.up else "down" key = name + "_" + spin_str data = parchg.spin_data[spin] x_shifted = np.roll(data, shift_numbers[0], axis=0) xy_shifted = np.roll(x_shifted, shift_numbers[1], axis=1) xyz_shifted = np.roll(xy_shifted, shift_numbers[2], axis=2) try: vertices, faces = get_vertices_and_faces(xyz_shifted, lattice_matrix, step_size=step_size, level=level) results[key] = {"vertices": vertices, "faces": faces} except RuntimeError: continue structure.translate_sites(indices=list(range(len(structure))), vector=actual_shift_vector) graph = StructureGraph.with_empty_graph(structure=structure) return SceneDicts(results, structure_graph=graph)
def get_mol_pymatgen(dataframe, nbrStruc): for i in range(nbrStruc): filename = dataframe.iloc[i,0] if (filename != "QAPHUK"): print(filename) parser = CifParser("../data/cif/{}.cif".format(filename)) structure = parser.get_structures()[0] sg = StructureGraph.with_local_env_strategy(structure, locenv.JmolNN()) my_molecules = sg.get_subgraphs_as_molecules() #molecule = MoleculeGraph.with_local_env_strategy(my_molecules,locenv.JmolNN()) #print(molecule) #crystool.view(my_molecules) my_molecules = pyxyz.XYZ(my_molecules) #print(my_molecules) pyxyz.XYZ.write_file(my_molecules,"../data/xyz_pymatgen/{}.xyz".format(filename))
def with_local_env_strategy(cls, structure: Structure, migrating_specie: str, nn: NearNeighbors, **kwargs) -> "MigrationGraph": """ Using a specific nn strategy to get the connectivity graph between all the migrating ion sites. Args: structure: Input structure that contains all sites. migrating_specie: The specie that migrates. E.g. "Li". nn: The specific local environment object used to connect the migrating ion sites. Returns: A constructed MigrationGraph object """ only_sites = get_only_sites_from_structure(structure, migrating_specie) migration_graph = StructureGraph.with_local_env_strategy( only_sites, nn) return cls(structure=structure, m_graph=migration_graph, **kwargs)
def get_local_environment( structure: Structure, n: int, loc_env_strategy: NearNeighbors ) -> List[Molecule]: """Create the molecule object of the local environment based on a given local environment strategy Args: structure (Structure): Input structure n (int): The site index loc_env_strategy (NearNeighbors): Returns: Molecule: [description] """ s_graph = StructureGraph.with_local_env_strategy(loc_env_strategy) return s_graph.get_subgraphs_as_molecules()
def test_draw(self): # draw MoS2 graph self.mos2_sg.draw_graph_to_file("MoS2_single.pdf", image_labels=True, hide_image_edges=False) mos2_sg = self.mos2_sg * (9, 9, 1) mos2_sg.draw_graph_to_file("MoS2.pdf", algo="neato") # draw MoS2 graph that's been successively multiplied mos2_sg_2 = self.mos2_sg * (3, 3, 1) mos2_sg_2 = mos2_sg_2 * (3, 3, 1) mos2_sg_2.draw_graph_to_file("MoS2_twice_mul.pdf", algo="neato", hide_image_edges=True) # draw MoS2 graph that's generated from a pre-multiplied Structure mos2_sg_premul = StructureGraph.with_local_env_strategy(self.structure * (3, 3, 1), MinimumDistanceNN()) mos2_sg_premul.draw_graph_to_file("MoS2_premul.pdf", algo="neato", hide_image_edges=True) # draw graph for a square lattice self.square_sg.draw_graph_to_file("square_single.pdf", hide_image_edges=False) square_sg = self.square_sg * (5, 5, 1) square_sg.draw_graph_to_file("square.pdf", algo="neato", image_labels=True, node_labels=False) # draw graph for a body-centered square lattice self.bc_square_sg.draw_graph_to_file("bc_square_single.pdf", hide_image_edges=False) bc_square_sg = self.bc_square_sg * (9, 9, 1) bc_square_sg.draw_graph_to_file("bc_square.pdf", algo="neato", image_labels=False) # draw graph for a body-centered square lattice defined in an alternative way self.bc_square_sg_r.draw_graph_to_file("bc_square_r_single.pdf", hide_image_edges=False) bc_square_sg_r = self.bc_square_sg_r * (9, 9, 1) bc_square_sg_r.draw_graph_to_file("bc_square_r.pdf", algo="neato", image_labels=False) # delete generated test files test_files = ( "bc_square_r_single.pdf", "bc_square_r.pdf", "bc_square_single.pdf", "bc_square.pdf", "MoS2_premul.pdf", "MoS2_single.pdf", "MoS2_twice_mul.pdf", "MoS2.pdf", "square_single.pdf", "square.pdf", ) for test_file in test_files: os.remove(test_file)
def with_distance(cls, structure: Structure, migrating_specie: str, max_distance: float, **kwargs) -> "MigrationGraph": """ Using a specific nn strategy to get the connectivity graph between all the migrating ion sites. Args: max_distance: Maximum length of NEB path in the unit of Angstrom. Defaults to None, which means you are setting the value to the min cutoff until finding 1D or >1D percolating paths. Returns: A constructed MigrationGraph object """ only_sites = get_only_sites_from_structure(structure, migrating_specie) migration_graph = StructureGraph.with_local_env_strategy( only_sites, MinimumDistanceNN(cutoff=max_distance, get_all_sites=True), ) return cls(structure=structure, m_graph=migration_graph, **kwargs)