From 4c16f7bf354e994dd27a5ac261c51762dfbed973 Mon Sep 17 00:00:00 2001 From: choglass Date: Mon, 13 May 2024 08:53:29 +0200 Subject: [PATCH] Generate refcell --- cell2mol/charge_assignment.py | 8 +- cell2mol/classes.py | 160 +- cell2mol/connectivity.py | 14 +- cell2mol/test/Based_reference.ipynb | 2455 +++++++++++++++++++++++++-- 4 files changed, 2437 insertions(+), 200 deletions(-) diff --git a/cell2mol/charge_assignment.py b/cell2mol/charge_assignment.py index 34324f10..e026dd5f 100644 --- a/cell2mol/charge_assignment.py +++ b/cell2mol/charge_assignment.py @@ -827,6 +827,7 @@ def balance_charge(unique_indices: list, unique_species: list, debug: int=0) -> # Expands tmpdistr to include same species, generating alldistr: alldistr = [] + final_charges= [] for distr in tmpdistr: tmp = [] for u in unique_indices: @@ -837,14 +838,15 @@ def balance_charge(unique_indices: list, unique_species: list, debug: int=0) -> final_charge_distribution = [] for idx, d in enumerate(alldistr): if debug >= 2: print(f"BALANCE: distribution={d}") - final_charge = np.sum(d) - if final_charge == 0: + charges_sum = np.sum(d) + if charges_sum == 0: final_charge_distribution.append(d) + final_charges.append(distr) elif iserror: if debug >= 1: print("Error found in BALANCE: one species has no possible charges") final_charge_distribution = [] - return final_charge_distribution + return final_charge_distribution, final_charges ####################################################### def prepare_unresolved(unique_indices: list, unique_species: list, distributions: list, debug: int=0): diff --git a/cell2mol/classes.py b/cell2mol/classes.py index bf639256..206b749f 100644 --- a/cell2mol/classes.py +++ b/cell2mol/classes.py @@ -19,19 +19,21 @@ #### CLASSES FOR CELL2MOL 2 #### ################################## class specie(object): - def __init__(self, labels: list, coord: list, radii: list=None) -> None: + def __init__(self, labels: list, coord: list, frac_coord: list, radii: list=None) -> None: # Sanity Checks assert len(labels) == len(coord) + assert len(coord) == len(frac_coord) # Optional Information if radii is not None: self.radii = radii else: self.radii = get_radii(labels) self.type = "specie" - self.version = "0.1" + self.version = "2.0" self.labels = labels self.coord = coord + self.frac_coord = frac_coord self.formula = labels2formula(labels) self.eleccount = labels2electrons(labels) ### Assuming neutral specie (so basically this is the sum of atomic numbers) self.natoms = len(labels) @@ -99,7 +101,9 @@ def get_parent_indices(self, subtype: str): def get_centroid(self): from cell2mol.other import compute_centroid self.centroid = compute_centroid(np.array(self.coord)) - if hasattr(self,"frac_coord"): self.frac_centroid = compute_centroid(np.array(self.frac_coord)) # If fractional coordinates exists, then also computes their centroid + if hasattr(self,"frac_coord"): + self.frac_centroid = compute_centroid(np.array(self.frac_coord)) + # If fractional coordinates exists, then also computes their centroid return self.centroid ############ @@ -108,15 +112,15 @@ def set_fractional_coord(self, frac_coord: list, debug: int=0) -> None: self.frac_coord = frac_coord ############ - def get_fractional_coord(self, cell_vector=None, debug: int=0) -> None: - if cell_vector is None: - if self.check_parent("cell"): - cell = self.get_parent("cell") - if hasattr(cell,"cellvec"): cell_vector = cell.cellvec.copy() - else: print("SPECIE.GET_FRACTIONAL_COORD: get_fractional coordinates. Missing cell vector. Please provide it"); return None - if debug > 1: print(f"SPECIE.GET_FRACTIONAL_COORD: Using cell_vector:{cell_vector}") - self.frac_coord = cart2frac(self.coord, cell_vector) - return self.frac_coord + # def get_fractional_coord(self, cell_vector=None, debug: int=0) -> None: + # if cell_vector is None: + # if self.check_parent("cell"): + # cell = self.get_parent("cell") + # if hasattr(cell,"cellvec"): cell_vector = cell.cell_vector.copy() + # else: print("SPECIE.GET_FRACTIONAL_COORD: get_fractional coordinates. Missing cell vector. Please provide it"); return None + # if debug > 1: print(f"SPECIE.GET_FRACTIONAL_COORD: Using cell_vector:{cell_vector}") + # self.frac_coord = cart2frac(self.coord, cell_vector) + # return self.frac_coord ############ def get_atomic_numbers(self): @@ -186,10 +190,10 @@ def set_atoms(self, atomlist=None, create_adjacencies: bool=False, debug: int=0) ## For each l in labels, create an atom class object. ismetal = elemdatabase.elementblock[l] == "d" or elemdatabase.elementblock[l] == "f" if debug > 0: print(f"SPECIE.SET_ATOMS: {ismetal=}") - if ismetal: newatom = metal(l, self.coord[idx], radii=self.radii[idx]) - else: newatom = atom(l, self.coord[idx], radii=self.radii[idx]) + if ismetal: newatom = metal(l, self.coord[idx], self.frac_coord[idx], radii=self.radii[idx]) + else: newatom = atom(l, self.coord[idx], self.frac_coord[idx],radii=self.radii[idx]) if debug > 0: print(f"SPECIE.SET_ATOMS: added atom to specie: {self.formula}") - newatom.add_parent(self,index=idx) + newatom.add_parent(self, index=idx) self.atoms.append(newatom) if create_adjacencies: @@ -340,9 +344,9 @@ def __repr__(self, indirect: bool=False): ### MOLECULE ## ############### class molecule(specie): - def __init__(self, labels: list, coord: list, radii: list=None) -> None: + def __init__(self, labels: list, coord: list, frac_coord: list, radii: list=None) -> None: self.subtype = "molecule" - specie.__init__(self, labels, coord, radii) + specie.__init__(self, labels, coord, frac_coord, radii) def __repr__(self): to_print = "" @@ -389,6 +393,7 @@ def split_complex(self, debug: int=0): # Split the "rest" to obtain the ligands rest_labels = extract_from_list(rest_idx, self.labels, dimension=1) rest_coord = extract_from_list(rest_idx, self.coord, dimension=1) + rest_frac = extract_from_list(rest_idx, self.frac_coord, dimension=1) rest_indices = extract_from_list(rest_idx, self.indices, dimension=1) rest_radii = extract_from_list(rest_idx, self.radii, dimension=1) rest_atoms = extract_from_list(rest_idx, self.atoms, dimension=1) @@ -397,7 +402,6 @@ def split_complex(self, debug: int=0): print(f"SPLIT COMPLEX: rest indices: {rest_indices}") print(f"SPLIT COMPLEX: rest radii: {rest_radii}") - if hasattr(self,"frac_coord"): rest_frac = extract_from_list(rest_idx, self.frac_coord, dimension=1) if debug > 0: print(f"SPLIT COMPLEX: splitting species with {len(rest_labels)} atoms in block") if hasattr(self,"cov_factor"): blocklist = split_species(rest_labels, rest_coord, radii=rest_radii, cov_factor=self.cov_factor, debug=debug) else: blocklist = split_species(rest_labels, rest_coord, radii=rest_radii, cov_factor=self.cov_factor, debug=debug) @@ -409,11 +413,12 @@ def split_complex(self, debug: int=0): lig_indices = extract_from_list(b, rest_indices, dimension=1) lig_labels = extract_from_list(b, rest_labels, dimension=1) lig_coord = extract_from_list(b, rest_coord, dimension=1) + lig_frac_coord = extract_from_list(b, rest_frac, dimension=1) lig_radii = extract_from_list(b, rest_radii, dimension=1) lig_atoms = extract_from_list(b, rest_atoms, dimension=1) if debug > 0: print(f"CREATING LIGAND: {labels2formula(lig_labels)}") # Create Ligand Object - newligand = ligand(lig_labels, lig_coord, radii=lig_radii) + newligand = ligand(lig_labels, lig_coord, lig_frac_coord, radii=lig_radii) # For debugging newligand.origin = "split_complex" # Define the molecule as parent of the ligand. Bottom-Up hierarchy @@ -424,19 +429,15 @@ def split_complex(self, debug: int=0): newligand.set_atoms(atomlist=lig_atoms) # Inherit the adjacencies from molecule newligand.inherit_adjmatrix("molecule") - # If fractional coordinates are available... - if hasattr(self,"frac_coord"): - lig_frac_coord = extract_from_list(b, rest_frac, dimension=1) - newligand.set_fractional_coord(lig_frac_coord) # Add ligand to the list. Top-Down hierarchy self.ligands.append(newligand) ## Arranges Metals for m in metal_idx: ## We were creating the metal again, but it is already in the list of molecule.atoms - #newmetal = metal(self.labels[m], self.coord[m], self.radii[m]) - #newmetal.add_parent(self, index=self.indices[m]) - #self.metals.append(newmetal) + # newmetal = metal(self.labels[m], self.coord[m], self.frac_coord[m], self.radii[m]) + # newmetal.add_parent(self, index=self.indices[m]) + # self.metals.append(newmetal) self.metals.append(self.atoms[m]) return self.ligands, self.metals @@ -466,9 +467,9 @@ def correct_smiles(self, debug: int=0): ### LIGAND #### ############### class ligand(specie): - def __init__(self, labels: list, coord: list, radii: list=None) -> None: + def __init__(self, labels: list, coord: list, frac_coord: list, radii: list=None) -> None: self.subtype = "ligand" - specie.__init__(self, labels, coord, radii) + specie.__init__(self, labels, coord, frac_coord, radii) self.evaluate_as_nitrosyl() ####################################################### @@ -588,10 +589,11 @@ def split_ligand(self, debug: int=0): if debug >= 2: print(f"LIGAND.SPLIT_LIGAND: {self.indices=}") print(f"LIGAND.SPLIT_LIGAND: {connected_idx=}") - conn_labels = extract_from_list(connected_idx, self.labels, dimension=1) - conn_coord = extract_from_list(connected_idx, self.coord, dimension=1) - conn_radii = extract_from_list(connected_idx, self.radii, dimension=1) - conn_atoms = extract_from_list(connected_idx, self.atoms, dimension=1) + conn_labels = extract_from_list(connected_idx, self.labels, dimension=1) + conn_coord = extract_from_list(connected_idx, self.coord, dimension=1) + conn_frac_coord = extract_from_list(connected_idx, self.frac_coord, dimension=1) + conn_radii = extract_from_list(connected_idx, self.radii, dimension=1) + conn_atoms = extract_from_list(connected_idx, self.atoms, dimension=1) if debug >= 2: print(f"LIGAND.SPLIT_LIGAND: {conn_labels=}") if hasattr(self,"cov_factor"): blocklist = split_species(conn_labels, conn_coord, radii=conn_radii, cov_factor=self.cov_factor, debug=debug) @@ -602,12 +604,13 @@ def split_ligand(self, debug: int=0): if debug >= 2 : print(f"LIGAND.SPLIT_LIGAND: block={b}") gr_indices = extract_from_list(b, connected_idx, dimension=1, debug=debug) if debug > 1: print(f"LIGAND.SPLIT_LIGAND: {gr_indices=}") - gr_labels = extract_from_list(b, conn_labels, dimension=1, debug=debug) - gr_coord = extract_from_list(b, conn_coord, dimension=1) - gr_radii = extract_from_list(b, conn_radii, dimension=1) - gr_atoms = extract_from_list(b, conn_atoms, dimension=1) + gr_labels = extract_from_list(b, conn_labels, dimension=1, debug=debug) + gr_coord = extract_from_list(b, conn_coord, dimension=1) + gr_frac_coord = extract_from_list(b, conn_frac_coord, dimension=1) + gr_radii = extract_from_list(b, conn_radii, dimension=1) + gr_atoms = extract_from_list(b, conn_atoms, dimension=1) # Create Group Object - newgroup = group(gr_labels, gr_coord, radii=gr_radii) + newgroup = group(gr_labels, gr_coord, gr_frac_coord, radii=gr_radii) # For debugging newgroup.origin = "split_ligand" # Define the ligand as parent of the group. Bottom-Up hierarchy @@ -651,9 +654,9 @@ def get_hapticity(self, debug: int=0): #### GROUP #### ############### class group(specie): - def __init__(self, labels: list, coord: list, radii: list=None) -> None: + def __init__(self, labels: list, coord: list, frac_coord: list, radii: list=None) -> None: self.subtype = "group" - specie.__init__(self, labels, coord, radii) + specie.__init__(self, labels, coord, frac_coord, radii) ####################################################### def __repr__(self): @@ -765,7 +768,7 @@ def get_denticity(self, debug: int=0): class bond(object): def __init__(self, atom1: object, atom2: object, bond_order: int=1): self.type = "bond" - self.version = "0.1" + self.version = "2.0" self.atom1 = atom1 self.atom2 = atom2 self.order = bond_order @@ -791,19 +794,21 @@ def __repr__(self): ### ATOM ###### ############### class atom(object): - def __init__(self, label: str, coord: list, radii: float=None, frac_coord: list=None) -> None: + def __init__(self, label: str, coord: list, frac_coord: list=None, radii: float=None) -> None: self.type = "atom" - self.version = "0.1" + self.version = "2.0" self.label = label self.coord = coord self.atnum = elemdatabase.elementnr[label] self.block = elemdatabase.elementblock[label] self.parents = [] self.parents_index = [] + self.formula = label + if frac_coord is not None: self.frac_coord = frac_coord if radii is None: self.radii = get_radii(label) else: self.radii = radii - if frac_coord is not None: self.frac_coord = frac_coord + ############ def add_parent(self, parent: object, index: int, overwrite: bool=True): @@ -1053,9 +1058,9 @@ def reset_mconnec(self, met, diff: int=-1, debug: int=0): #### METAL #### ############### class metal(atom): - def __init__(self, label: str, coord: list, radii: float=None, frac_coord: list=None) -> None: + def __init__(self, label: str, coord: list, frac_coord: list=None, radii: float=None) -> None: self.subtype = "metal" - atom.__init__(self, label, coord, radii=radii, frac_coord=frac_coord) + atom.__init__(self, label, coord, frac_coord=frac_coord, radii=radii) ####################################################### def get_valence_elec (self, m_ox: int): @@ -1193,22 +1198,26 @@ def __repr__(self): #### CELL #### ############## class cell(object): - def __init__(self, name: str, labels: list, pos: list, cellvec: list, cellparam: list) -> None: - self.version = "0.1" + def __init__(self, name: str, labels: list, pos: list, frac_coord: list, cell_vector, cell_param) -> None: + self.version = "2.0" self.type = "cell" - self.subtype = "cell" self.name = name self.labels = labels self.coord = pos - self.cellvec = cellvec - self.cellparam = cellparam + self.frac_coord = frac_coord + self.cell_vector = cell_vector + self.cell_param = cell_param self.natoms = len(labels) - self.frac_coord = cart2frac(self.coord, self.cellvec) + + ####################################################### + def get_subtype(self, subtype): + self.subtype = subtype ####################################################### def get_unique_species(self, debug: int=0): - if not hasattr(self,"is_fragmented"): self.reconstruct(debug=debug) - if self.is_fragmented: return None # Stopping. self.is_fragmented must be false to determine the charges of the cell + #if not hasattr(self,"is_fragmented"): self.reconstruct(debug=debug) + #if self.is_fragmented: return None # Stopping. self.is_fragmented must be false to determine the charges of the cell + if debug >= 0: print(f"Getting unique species in cell") self.unique_species = [] self.unique_indices = [] @@ -1218,7 +1227,9 @@ def get_unique_species(self, debug: int=0): typelist_mets = [] # temporary variable specs_found = -1 - for idx, mol in enumerate(self.moleclist): + if self.subtype == "reference": moleculist = self.refmoleclist + else: moleculist = self.moleclist + for idx, mol in enumerate(moleculist): if debug >= 2: print(f"Molecule {idx} formula={mol.formula}") if not mol.iscomplex: found = False @@ -1270,9 +1281,9 @@ def get_unique_species(self, debug: int=0): return self.unique_species ####################################################### - def get_fractional_coord(self): - self.frac_coord = cart2frac(self.coord, self.cellvec) - return self.frac_coord + # def get_fractional_coord(self): + # self.frac_coord = cart2frac(self.coord, self.cellvec) + # return self.frac_coord ####################################################### def check_missing_H(self, debug: int=0): @@ -1289,9 +1300,12 @@ def get_reference_molecules(self, ref_labels: list, ref_fracs: list, cov_factor: print(" GETREFS: Generate reference molecules ") print("#########################################") - # In the info file, the reference molecules only have fractional coordinates. We convert them to cartesian - ref_pos = frac2cart_fromparam(ref_fracs, self.cellparam) - + # Convert fractional coordinates to cartesian + ref_pos = frac2cart_fromparam(ref_fracs, self.cell_param) + + # Define reference cell + refcell = cell(self.name, ref_labels, ref_pos, ref_fracs, self.cell_vector, self.cell_param) + refcell.get_subtype("reference") # Get reference molecules blocklist = split_species(ref_labels, ref_pos, cov_factor=cov_factor) @@ -1299,12 +1313,14 @@ def get_reference_molecules(self, ref_labels: list, ref_fracs: list, cov_factor: for b in blocklist: mol_labels = extract_from_list(b, ref_labels, dimension=1) mol_coord = extract_from_list(b, ref_pos, dimension=1) - mol_frac_coord = extract_from_list(b, self.frac_coord, dimension=1) - newmolec = molecule(mol_labels, mol_coord) + mol_frac_coord = extract_from_list(b, ref_fracs, dimension=1) + newmolec = molecule(mol_labels, mol_coord, mol_frac_coord) newmolec.add_parent(self, indices=b) - newmolec.set_fractional_coord(mol_frac_coord) + newmolec.add_parent(refcell, indices=b) newmolec.set_adjacency_parameters(cov_factor, metal_factor) newmolec.set_atoms(create_adjacencies=True, debug=debug) + for atom, idx in zip(newmolec.atoms, b): + atom.add_parent(refcell, index=idx) # This must be below the frac_coord, so they are carried on to the ligands if newmolec.iscomplex: newmolec.split_complex() self.refmoleclist.append(newmolec) @@ -1383,8 +1399,9 @@ def get_moleclist(self, cov_factor: float=1.3, metal_factor: float=1.0, debug: i if debug > 0: print(f"CELL.MOLECLIST: doing block={b}") mol_labels = extract_from_list(b, self.labels, dimension=1) mol_coord = extract_from_list(b, self.coord, dimension=1) + mol_frac_coord = extract_from_list(b, self.frac_coord, dimension=1) # Creates Molecule Object - newmolec = molecule(mol_labels, mol_coord) + newmolec = molecule(mol_labels, mol_coord, mol_frac_coord) # For debugging newmolec.origin = "cell.get_moleclist" # Adds cell as parent of the molecule, with indices b @@ -1392,11 +1409,6 @@ def get_moleclist(self, cov_factor: float=1.3, metal_factor: float=1.0, debug: i newmolec.set_adjacency_parameters(cov_factor, metal_factor) # Creates The atom objects with adjacencies newmolec.set_atoms(create_adjacencies=True, debug=debug) - # If fractional coordinates are available... - if hasattr(self,"frac_coord"): - assert len(self.frac_coord) == len(self.coord) - mol_frac_coord = extract_from_list(b, self.frac_coord, dimension=1) - newmolec.set_fractional_coord(mol_frac_coord, debug=debug) # The split_complex must be below the frac_coord, so they are carried on to the ligands # if newmolec.iscomplex: # if debug > 0: print(f"CELL.MOLECLIST: splitting complex") @@ -1451,8 +1463,8 @@ def reconstruct(self, cov_factor: float=None, metal_factor: float=None, debug: i self.error_get_fragments = False ## Classifies fragments - for f in fragments: - if not hasattr(f,"frac_coord"): f.get_fractional_coord(self.cellvec) + # for f in fragments: + # if not hasattr(f,"frac_coord"): f.get_fractional_coord(self.cellvec) molecules, fragments, hydrogens = classify_fragments(fragments, self.refmoleclist, debug=debug) if debug > 0: print(f"CELL.RECONSTRUCT: {len(molecules)} {molecules=}") if debug > 0: print(f"CELL.RECONSTRUCT: {len(fragments)} {fragments=}") @@ -1714,10 +1726,12 @@ def __repr__(self): to_print = f'------------- Cell2mol CELL Object ----------------\n' to_print += f' Version = {self.version}\n' to_print += f' Type = {self.type}\n' + if hasattr(self,'subtype'): to_print += f' Sub-Type = {self.subtype}\n' to_print += f' Name (Refcode) = {self.name}\n' to_print += f' Num Atoms = {self.natoms}\n' - to_print += f' Cell Parameters a:c = {self.cellparam[0:3]}\n' - to_print += f' Cell Parameters al:ga = {self.cellparam[3:6]}\n' + to_print += f' Cell Parameters a:c = {self.cell_param[0:3]}\n' + to_print += f' Cell Parameters al:ga = {self.cell_param[3:6]}\n' + # to_print += f' Cell Vector = {self.cell_vector}\n' if hasattr(self,"moleclist"): to_print += f' # Molecules: = {len(self.moleclist)}\n' to_print += f' With Formulae: \n' diff --git a/cell2mol/connectivity.py b/cell2mol/connectivity.py index 34f99dc1..0d7f4393 100644 --- a/cell2mol/connectivity.py +++ b/cell2mol/connectivity.py @@ -596,6 +596,7 @@ def split_group(original_group, conn_idx, debug: int=0): if debug > 1: print(f"GROUP.SPLIT_GROUP: {conn_idx=}") conn_labels = extract_from_list(conn_idx, original_group.labels, dimension=1) conn_coord = extract_from_list(conn_idx, original_group.coord, dimension=1) + conn_frac_coord = extract_from_list(conn_idx, original_group.frac_coord, dimension=1) conn_radii = extract_from_list(conn_idx, original_group.radii, dimension=1) conn_atoms = extract_from_list(conn_idx, original_group.atoms, dimension=1) if debug > 1: print(f"GROUP.SPLIT_GROUP: {conn_labels=}") @@ -607,13 +608,14 @@ def split_group(original_group, conn_idx, debug: int=0): ## Arranges Groups for b in blocklist: if debug > 1: print(f"GROUP.SPLIT_GROUP: block={b}") - gr_indices = extract_from_list(b, conn_idx, dimension=1) - gr_labels = extract_from_list(b, conn_labels, dimension=1) - gr_coord = extract_from_list(b, conn_coord, dimension=1) - gr_radii = extract_from_list(b, conn_radii, dimension=1) - gr_atoms = extract_from_list(b, conn_atoms, dimension=1) + gr_indices = extract_from_list(b, conn_idx, dimension=1) + gr_labels = extract_from_list(b, conn_labels, dimension=1) + gr_coord = extract_from_list(b, conn_coord, dimension=1) + gr_frac_coord = extract_from_list(b, conn_frac_coord, dimension=1) + gr_radii = extract_from_list(b, conn_radii, dimension=1) + gr_atoms = extract_from_list(b, conn_atoms, dimension=1) # Create Group Object - newgroup = group(gr_labels, gr_coord, radii=gr_radii) + newgroup = group(gr_labels, gr_coord, gr_frac_coord, radii=gr_radii) # For debugging newgroup.origin = "split_group" # Define the GROUP as parent of the group. Bottom-Up hierarchy diff --git a/cell2mol/test/Based_reference.ipynb b/cell2mol/test/Based_reference.ipynb index 3a1666c2..30719338 100644 --- a/cell2mol/test/Based_reference.ipynb +++ b/cell2mol/test/Based_reference.ipynb @@ -2,100 +2,2372 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 64, "id": "f2657264-6361-480f-8f6e-2d3c7cea4cc7", "metadata": {}, + "outputs": [], + "source": [ + "from scipy import sparse\n", + "from ase.build import molecule\n", + "from ase.neighborlist import get_connectivity_matrix\n", + "from ase.neighborlist import natural_cutoffs\n", + "from ase.neighborlist import NeighborList\n", + "import ase\n", + "import numpy as np\n", + "from ase.io import read\n", + "from ase import Atoms\n", + "import ase.visualize\n", + "from ase.visualize.plot import plot_atoms\n", + "from cell2mol.read_write import readinfo\n", + "from cell2mol.cell_operations import frac2cart_fromparam, cart2frac\n", + "import nglview\n", + "from ase.build import molecule\n", + "from ase.neighborlist import NeighborList\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5ff88c96-bda9-4f00-8323-20a1386d5253", + "metadata": {}, + "outputs": [], + "source": [ + "folder = \"error_2\"\n", + "name = \"BOFFOS\"\n", + "infopath = f\"{folder}/{name}/{name}.info\"\n", + "input_path = f\"{folder}/{name}/{name}.cif\"" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "c883d74e-e2c3-463e-86ae-1133495aaee1", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 0 and 59 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 0 and 60 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 2 and 61 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 2 and 62 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 3 and 63 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 3 and 64 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 4 and 65 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 4 and 66 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 5 and 67 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 5 and 68 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 6 and 69 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 6 and 70 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 7 and 71 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 7 and 72 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 8 and 73 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 8 and 74 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 9 and 75 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 9 and 76 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 10 and 77 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 10 and 78 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 11 and 79 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 11 and 80 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 15 and 81 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 15 and 82 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 16 and 83 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 16 and 84 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 17 and 85 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 17 and 86 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 18 and 87 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 18 and 88 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 19 and 89 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 19 and 90 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 20 and 91 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 20 and 92 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 21 and 93 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 21 and 94 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 22 and 95 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 22 and 96 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 23 and 97 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 23 and 98 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 24 and 99 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 24 and 100 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 25 and 101 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 25 and 102 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 26 and 103 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 26 and 104 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 27 and 105 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 27 and 106 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 28 and 107 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 28 and 108 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 29 and 109 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 29 and 110 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 30 and 111 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 30 and 112 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 31 and 113 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 31 and 114 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 32 and 115 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 32 and 116 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 33 and 117 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 33 and 118 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 34 and 119 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 34 and 120 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 35 and 121 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 35 and 122 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 36 and 123 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 36 and 124 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 37 and 125 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 37 and 126 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 38 and 127 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 38 and 128 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 39 and 129 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 39 and 130 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 40 and 131 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 40 and 132 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 41 and 133 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 41 and 134 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 42 and 135 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 42 and 136 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 43 and 137 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 43 and 138 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 44 and 139 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 44 and 140 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 45 and 141 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 45 and 142 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 46 and 143 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 46 and 144 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 47 and 145 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 47 and 146 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 48 and 147 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 48 and 148 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 49 and 149 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 49 and 150 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 50 and 151 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 50 and 152 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 51 and 153 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 51 and 154 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 52 and 155 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n", + "/Users/ycho/miniconda3/envs/cell2mol/lib/python3.10/site-packages/ase/spacegroup/spacegroup.py:433: UserWarning: scaled_positions 52 and 156 are equivalent\n", + " warnings.warn('scaled_positions %d and %d '\n" + ] + } + ], + "source": [ + "atoms = read(input_path)\n", + "cell_labels = atoms.get_chemical_symbols()\n", + "cell_pos = atoms.positions\n", + "cell_fracs = atoms.get_scaled_positions()\n", + "cell_vector = atoms.cell.array\n", + "# cell_parameters = atoms.cell.cellpar()\n", + "space_group = atoms.info['spacegroup']\n", + "sym_ops = space_group.get_op()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "0158d29e-2ed5-44ba-ad4c-42cf61be04b5", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "#########################################\n", + " GETREFS: Generate reference molecules \n", + "#########################################\n", + "GETREFS: found 10 reference molecules\n", + "GETREFS: ['C6-O12-Fe', 'H24-C12-O6', 'H2-O', 'H2-O', 'H2-O', 'H24-C12-O6', 'H24-C12-O6', 'K', 'K', 'K']\n", + "GETREFS: [------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 19\n", + " Formula = C6-O12-Fe\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Number of Ligands = 3\n", + " Number of Metals = 1\n", + "---------------------------------------------------\n", + ", ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + ", ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + ", ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + ", ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + ", ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + ", ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + ", ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + ", ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + ", ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + "]\n", + "GETREFS: working with C6-O12-Fe\n", + "GETREFS: working with H24-C12-O6\n", + "GETREFS: working with H2-O\n", + "GETREFS: working with H2-O\n", + "GETREFS: working with H2-O\n", + "GETREFS: working with H24-C12-O6\n", + "GETREFS: working with H24-C12-O6\n", + "GETREFS: working with K\n", + "GETREFS: working with K\n", + "GETREFS: working with K\n" + ] + }, + { + "data": { + "text/plain": [ + "[------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 19\n", + " Formula = C6-O12-Fe\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Number of Ligands = 3\n", + " Number of Metals = 1\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from cell2mol.classes import cell\n", + "\n", + "labels, pos, ref_labels, ref_fracs, cellvec, cell_param = readinfo(infopath)\n", + "# labels, pos, and cellvec will not be used\n", + "ref_pos = frac2cart_fromparam(ref_fracs, cell_param)\n", + "refcell = cell(name, ref_labels, ref_pos, ref_fracs, cell_vector, cell_param)\n", + "refcell.get_subtype(\"reference\")\n", + "refcell.get_reference_molecules(ref_labels, ref_fracs)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "1f863811-1f37-44a3-82cc-9b91889b45e3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Adjacency [8, 10, 18] ['O', 'O', 'C']\n", + "Adjacency [12, 13, 16] ['O', 'O', 'C']\n", + "Adjacency [7, 9, 17] ['O', 'O', 'C']\n", + "Adjacency [11, 14, 15] ['O', 'O', 'C']\n", + "Adjacency [1, 2, 6] ['O', 'O', 'C']\n", + "Adjacency [3, 4, 5] ['O', 'O', 'C']\n", + "Adjacency [0, 7, 8, 9] ['O', 'H', 'H', 'C']\n", + "Adjacency [1, 6, 10, 11] ['O', 'C', 'H', 'H']\n", + "Adjacency [1, 13, 14, 15] ['O', 'H', 'H', 'C']\n", + "Adjacency [2, 12, 16, 17] ['O', 'C', 'H', 'H']\n", + "Adjacency [2, 19, 20, 21] ['O', 'H', 'H', 'C']\n", + "Adjacency [3, 18, 22, 23] ['O', 'C', 'H', 'H']\n", + "Adjacency [3, 25, 26, 27] ['O', 'H', 'H', 'C']\n", + "Adjacency [4, 24, 28, 29] ['O', 'C', 'H', 'H']\n", + "Adjacency [4, 31, 32, 33] ['O', 'H', 'H', 'C']\n", + "Adjacency [5, 30, 34, 35] ['O', 'C', 'H', 'H']\n", + "Adjacency [5, 37, 38, 39] ['O', 'H', 'H', 'C']\n", + "Adjacency [0, 36, 40, 41] ['O', 'C', 'H', 'H']\n", + "Adjacency [0, 7, 8, 9] ['O', 'H', 'H', 'C']\n", + "Adjacency [1, 6, 10, 11] ['O', 'C', 'H', 'H']\n", + "Adjacency [1, 13, 14, 15] ['O', 'H', 'H', 'C']\n", + "Adjacency [2, 12, 16, 17] ['O', 'C', 'H', 'H']\n", + "Adjacency [2, 19, 20, 21] ['O', 'H', 'H', 'C']\n", + "Adjacency [3, 18, 22, 23] ['O', 'C', 'H', 'H']\n", + "Adjacency [3, 25, 26, 27] ['O', 'H', 'H', 'C']\n", + "Adjacency [4, 24, 28, 29] ['O', 'C', 'H', 'H']\n", + "Adjacency [4, 31, 32, 33] ['O', 'H', 'H', 'C']\n", + "Adjacency [5, 30, 34, 35] ['O', 'C', 'H', 'H']\n", + "Adjacency [5, 37, 38, 39] ['O', 'H', 'H', 'C']\n", + "Adjacency [0, 36, 40, 41] ['O', 'C', 'H', 'H']\n", + "Adjacency [0, 7, 8, 9] ['O', 'H', 'H', 'C']\n", + "Adjacency [1, 6, 10, 11] ['O', 'C', 'H', 'H']\n", + "Adjacency [1, 13, 14, 15] ['O', 'H', 'H', 'C']\n", + "Adjacency [2, 12, 16, 17] ['O', 'C', 'H', 'H']\n", + "Adjacency [2, 19, 20, 21] ['O', 'H', 'H', 'C']\n", + "Adjacency [3, 18, 22, 23] ['O', 'C', 'H', 'H']\n", + "Adjacency [3, 25, 26, 27] ['O', 'H', 'H', 'C']\n", + "Adjacency [4, 24, 28, 29] ['O', 'C', 'H', 'H']\n", + "Adjacency [4, 31, 32, 33] ['O', 'H', 'H', 'C']\n", + "Adjacency [5, 30, 34, 35] ['O', 'C', 'H', 'H']\n", + "Adjacency [5, 37, 38, 39] ['O', 'H', 'H', 'C']\n", + "Adjacency [0, 36, 40, 41] ['O', 'C', 'H', 'H']\n", + "-------------------------------\n", + "Errors in Reference Molecules\n", + "-------------------------------\n", + "Cell2mol terminated with error number 0. Message:\n", + "No Errors Found\n", + "\n" + ] + } + ], + "source": [ + "if not refcell.has_isolated_H: \n", + " refcell.check_missing_H() \n", + "refcell.assess_errors(ref=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f04d448e-110b-49cf-9ff8-6fa2360caf3a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C6-O12-Fe ['reference'] [[1, 8, 9, 10, 11, 51, 52, 73, 74, 75, 76, 77, 78, 79, 80, 153, 154, 155, 156]]\n", + "-- C2-O4 split_complex ['molecule', 'reference'] [[8, 10, 12, 13, 16, 18], [1, 8, 9, 10, 11, 51, 52, 73, 74, 75, 76, 77, 78, 79, 80, 153, 154, 155, 156]]\n", + "-- C2-O4 split_complex ['molecule', 'reference'] [[7, 9, 11, 14, 15, 17], [1, 8, 9, 10, 11, 51, 52, 73, 74, 75, 76, 77, 78, 79, 80, 153, 154, 155, 156]]\n", + "-- C2-O4 split_complex ['molecule', 'reference'] [[1, 2, 3, 4, 5, 6], [1, 8, 9, 10, 11, 51, 52, 73, 74, 75, 76, 77, 78, 79, 80, 153, 154, 155, 156]]\n" + ] + } + ], + "source": [ + "for ref in refcell.refmoleclist:\n", + " if ref.iscomplex :\n", + " print(ref.formula, [p.subtype for p in ref.parents], [p_idx for p_idx in ref.parents_indices])\n", + " # for met in ref.metals:\n", + " # print(\"--\", met.label, [p.subtype for p in met.parents], [p_idx for p_idx in met.parents_index])\n", + " # # for g in met.groups:\n", + " # print(g.formula, [p.subtype for p in g.parents], [p_idx for p_idx in g.parents_indices])\n", + " \n", + " for lig in ref.ligands:\n", + " print(\"--\", lig.formula, lig.origin, [p.subtype for p in lig.parents], [p_idx for p_idx in lig.parents_indices])\n", + " # for a in lig.atoms:\n", + " # print(a.label, [p.subtype for p in a.parents], [p_idx for p_idx in a.parents_index])\n", + " # for g in lig.groups:\n", + " # print(g.formula, [p.subtype for p in g.parents], [p_idx for p_idx in g.parents_indices])\n", + " # else :\n", + " # print(ref.formula, [p.subtype for p in ref.parents], [p_idx for p_idx in ref.parents_indices])\n", + " # print(\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "01f7c701-6be8-4363-adbd-1d03479a9602", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + "---------------------------------------------------\n", + " # of Ref Molecules: = 10\n", + " With Formulae: \n", + " 0: C6-O12-Fe \n", + " 1: H24-C12-O6 \n", + " 2: H2-O \n", + " 3: H2-O \n", + " 4: H2-O \n", + " 5: H24-C12-O6 \n", + " 6: H24-C12-O6 \n", + " 7: K \n", + " 8: K \n", + " 9: K " + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "refcell" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e4b8c994-8003-4527-a886-9fde45ba91ad", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Getting unique species in cell\n" + ] + }, + { + "data": { + "text/plain": [ + "[------------- Cell2mol LIGAND Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = ligand\n", + " Number of Atoms = 6\n", + " Formula = C2-O4\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Origin = split_complex\n", + " Number of Groups = 2\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol METAL Object --------------\n", + " Version = 2.0\n", + " Type = atom\n", + " Sub-Type = metal\n", + " Label = Fe\n", + " Atomic Number = 26\n", + " Index in Molecule = 0\n", + " Metal Adjacency (mconnec) = 6\n", + " Regular Adjacencies (connec) = 6\n", + " ----------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "refcell.get_unique_species()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e7a8f538-b934-4356-8db5-e622900e5911", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[------------- Cell2mol LIGAND Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = ligand\n", + " Number of Atoms = 6\n", + " Formula = C2-O4\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Origin = split_complex\n", + " Number of Groups = 2\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol METAL Object --------------\n", + " Version = 2.0\n", + " Type = atom\n", + " Sub-Type = metal\n", + " Label = Fe\n", + " Atomic Number = 26\n", + " Index in Molecule = 0\n", + " Metal Adjacency (mconnec) = 6\n", + " Regular Adjacencies (connec) = 6\n", + " ----------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------,\n", + " ------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " ---------------------------------------------------]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "refcell.unique_species" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "140c087d-4417-4556-9e8c-9b59f10e0d01", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 0, 0, 1, 2, 3, 3, 3, 2, 2, 4, 4, 4]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "refcell.unique_indices" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "3ee5f5ff-b498-4e1a-8085-8632bb0a2152", + "metadata": {}, + "outputs": [], + "source": [ + "debug = 2" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "34d00dd5-dd6f-427c-86a6-68f17b903b6e", + "metadata": {}, + "outputs": [], + "source": [ + "from cell2mol.read_write import writexyz" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "f710248d-389f-431f-b994-979c08342845", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function writexyz in module cell2mol.read_write:\n", + "\n", + "writexyz(fdir, fname, labels, pos, charge: int = 0, spin: int = 1)\n", + " ##############\n", + "\n" + ] + } + ], + "source": [ + "help(writexyz)" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "ec60909d-e258-480f-b347-448a063670de", + "metadata": {}, + "outputs": [], + "source": [ + "for idx, specie in enumerate(refcell.refmoleclist):\n", + " if specie.formula == \"H24-C12-O6\":\n", + " writexyz(f\"{folder}/{name}\", f\"ref_{specie.formula}_{idx}.xyz\", \n", + " specie.labels, specie.coord)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "51665722-d915-490e-8064-a0a361a4cba0", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " GET_PROTONATION_STATES: Evaluating group O with parent_indices [2]\n", + " GET_PROTONATION_STATES: evaluating non-haptic group with index 2 and label O\n", + " GET_PROTONATION_STATES: Evaluating group O with parent_indices [1]\n", + " GET_PROTONATION_STATES: evaluating non-haptic group with index 1 and label O\n", + " GET_PROTONATION_STATES:protonation_states=[------------- Cell2mol Protonation ----------------\n", + " Status = True\n", + " Labels = ['O', 'O', 'O', 'O', 'C', 'C']\n", + " Type = Local\n", + " Atoms added in positions = [0 0 0 0 0 0]\n", + " Atoms blocked (no atoms added) = [0 1 1 0 0 0]\n", + "---------------------------------------------------\n", + "]\n", + " POSCHARGE will try charges [0, -1, 1, -2, 2, -3, 3, -4, 4]\n", + " POSCHARGE: charge 0 with smiles [O-][C+]([O-])[C+]([O-])[O-]\n", + " POSCHARGE: charge 0 with smiles [O-][C+]([O-])[C+]([O-])[O-]\n", + " POSCHARGE: charge 0 with smiles [O-][C+]([O-])[C+]([O-])[O-]\n", + " POSCHARGE: charge 0 with smiles O=C([O-])C(=O)[O-]\n", + " POSCHARGE: charge 0 with smiles [O-][C+]([O-])[C+]([O-])[O-]\n", + " POSCHARGE: charge 0 with smiles [O-][C+]([O-])[C-]([O-])[O-]\n", + " POSCHARGE: charge 0 with smiles [O-][C+]([O-])[C+]([O-])[O-]\n", + " POSCHARGE: charge 0 with smiles [O-]C([O-])=C([O-])[O-]\n", + " POSCHARGE: charge 0 with smiles [O-][C+]([O-])[C+]([O-])[O-]\n", + " NEW SELECT FUNCTION: uncorr_total: [-2, -2, -2, -2, -2, -4, -2, -4, -2]\n", + " NEW SELECT FUNCTION: uncorr_abs_total: [2, 2, 2, 2, 2, 4, 2, 4, 2]\n", + " NEW SELECT FUNCTION: uncorr_abs_atcharge: [6, 6, 6, 2, 6, 6, 6, 4, 6]\n", + " NEW SELECT FUNCTION: uncorr_zwitt: [True, True, True, False, True, True, True, False, True]\n", + " NEW SELECT FUNCTION: coincide: [False, False, False, True, False, False, False, True, False]\n", + " NEW SELECT FUNCTION: listofmintot: [0, 1, 2, 3, 4, 6, 8]\n", + " NEW SELECT FUNCTION: listofminabs: [3]\n", + " NEW SELECT FUNCTION: tmplist: [3], including:\n", + " NEW SELECT FUNCTION: Corr_charge=-2\n", + " NEW SELECT FUNCTION: Smiles=O=C([O-])C(=O)[O-]\n", + " NEW SELECT FUNCTION: found corr_charges=[-2]\n", + " NEW SELECT FUNCTION: doing tgt_charge=-2\n", + " NEW SELECT FUNCTION: charge_state added\n", + " NEW SELECT FUNCTION: Case 1, only one entry for -2 in tmplist\n", + " POSCHARGE: doing empty PROTONATION for this specie\n", + " CREATED EMPTY PROTONATION ------------- Cell2mol Protonation ----------------\n", + " Status = True\n", + " Labels = ['O', 'O', 'O', 'O', 'O', 'O', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H']\n", + " Type = Empty\n", + " Atoms added in positions = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + " Atoms blocked (no atoms added) = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "---------------------------------------------------\n", + "\n", + " POSCHARGE will try charges [0, -1, 1, -2, 2, -3, 3]\n", + " POSCHARGE: charge 0 with smiles [H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n", + " POSCHARGE: charge 0 with smiles [H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n", + " POSCHARGE: charge 0 with smiles [H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n", + " POSCHARGE: charge 0 with smiles [H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n", + " POSCHARGE: charge 0 with smiles [H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n", + " POSCHARGE: charge 0 with smiles [H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n", + " POSCHARGE: charge 0 with smiles [H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n", + " NEW SELECT FUNCTION: uncorr_total: [0, 0, 0, 0, 0, 0, 0]\n", + " NEW SELECT FUNCTION: uncorr_abs_total: [0, 0, 0, 0, 0, 0, 0]\n", + " NEW SELECT FUNCTION: uncorr_abs_atcharge: [0, 0, 0, 0, 0, 0, 0]\n", + " NEW SELECT FUNCTION: uncorr_zwitt: [False, False, False, False, False, False, False]\n", + " NEW SELECT FUNCTION: coincide: [True, False, False, False, False, False, False]\n", + " NEW SELECT FUNCTION: listofmintot: [0, 1, 2, 3, 4, 5, 6]\n", + " NEW SELECT FUNCTION: listofminabs: [0, 1, 2, 3, 4, 5, 6]\n", + " NEW SELECT FUNCTION: tmplist: [0], including:\n", + " NEW SELECT FUNCTION: Corr_charge=0\n", + " NEW SELECT FUNCTION: Smiles=[H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n", + " NEW SELECT FUNCTION: found corr_charges=[0]\n", + " NEW SELECT FUNCTION: doing tgt_charge=0\n", + " NEW SELECT FUNCTION: charge_state added\n", + " NEW SELECT FUNCTION: Case 1, only one entry for 0 in tmplist\n", + " POSCHARGE: doing empty PROTONATION for this specie\n", + " CREATED EMPTY PROTONATION ------------- Cell2mol Protonation ----------------\n", + " Status = True\n", + " Labels = ['O', 'H', 'H']\n", + " Type = Empty\n", + " Atoms added in positions = [0, 0, 0]\n", + " Atoms blocked (no atoms added) = [0, 0, 0]\n", + "---------------------------------------------------\n", + "\n", + " POSCHARGE will try charges [0, -1, 1, -2, 2, -3, 3]\n", + " POSCHARGE: charge 0 with smiles [H]O[H]\n", + " POSCHARGE: charge 0 with smiles [H]O[H]\n", + " POSCHARGE: charge 0 with smiles [H]O[H]\n", + " POSCHARGE: charge 0 with smiles [H]O[H]\n", + " POSCHARGE: charge 0 with smiles [H]O[H]\n", + " POSCHARGE: charge 0 with smiles [H]O[H]\n", + " POSCHARGE: charge 0 with smiles [H]O[H]\n", + " NEW SELECT FUNCTION: uncorr_total: [0, 0, 0, 0, 0, 0, 0]\n", + " NEW SELECT FUNCTION: uncorr_abs_total: [0, 0, 0, 0, 0, 0, 0]\n", + " NEW SELECT FUNCTION: uncorr_abs_atcharge: [0, 0, 0, 0, 0, 0, 0]\n", + " NEW SELECT FUNCTION: uncorr_zwitt: [False, False, False, False, False, False, False]\n", + " NEW SELECT FUNCTION: coincide: [True, False, False, False, False, False, False]\n", + " NEW SELECT FUNCTION: listofmintot: [0, 1, 2, 3, 4, 5, 6]\n", + " NEW SELECT FUNCTION: listofminabs: [0, 1, 2, 3, 4, 5, 6]\n", + " NEW SELECT FUNCTION: tmplist: [0], including:\n", + " NEW SELECT FUNCTION: Corr_charge=0\n", + " NEW SELECT FUNCTION: Smiles=[H]O[H]\n", + " NEW SELECT FUNCTION: found corr_charges=[0]\n", + " NEW SELECT FUNCTION: doing tgt_charge=0\n", + " NEW SELECT FUNCTION: charge_state added\n", + " NEW SELECT FUNCTION: Case 1, only one entry for 0 in tmplist\n", + " POSCHARGE: doing empty PROTONATION for this specie\n", + " CREATED EMPTY PROTONATION ------------- Cell2mol Protonation ----------------\n", + " Status = True\n", + " Labels = ['K']\n", + " Type = Empty\n", + " Atoms added in positions = [0]\n", + " Atoms blocked (no atoms added) = [0]\n", + "---------------------------------------------------\n", + "\n", + " POSCHARGE will try charges [0, -1, 1, -2, 2, -3, 3]\n", + " POSCHARGE: charge 0 with smiles [K+]\n", + " POSCHARGE: charge 0 with smiles [K+]\n", + " POSCHARGE: charge 0 with smiles [K+]\n", + " POSCHARGE: charge 0 with smiles [K+]\n", + " POSCHARGE: charge 0 with smiles [K+]\n", + " POSCHARGE: charge 0 with smiles [K+]\n", + " POSCHARGE: charge 0 with smiles [K+]\n", + " NEW SELECT FUNCTION: uncorr_total: [1, 1, 1, 1, 1, 1, 1]\n", + " NEW SELECT FUNCTION: uncorr_abs_total: [1, 1, 1, 1, 1, 1, 1]\n", + " NEW SELECT FUNCTION: uncorr_abs_atcharge: [1, 1, 1, 1, 1, 1, 1]\n", + " NEW SELECT FUNCTION: uncorr_zwitt: [False, False, False, False, False, False, False]\n", + " NEW SELECT FUNCTION: coincide: [False, False, True, False, False, False, False]\n", + " NEW SELECT FUNCTION: listofmintot: [0, 1, 2, 3, 4, 5, 6]\n", + " NEW SELECT FUNCTION: listofminabs: [0, 1, 2, 3, 4, 5, 6]\n", + " NEW SELECT FUNCTION: tmplist: [2], including:\n", + " NEW SELECT FUNCTION: Corr_charge=1\n", + " NEW SELECT FUNCTION: Smiles=[K+]\n", + " NEW SELECT FUNCTION: found corr_charges=[1]\n", + " NEW SELECT FUNCTION: doing tgt_charge=1\n", + " NEW SELECT FUNCTION: charge_state added\n", + " NEW SELECT FUNCTION: Case 1, only one entry for 1 in tmplist\n" + ] + } + ], + "source": [ + "selected_cs = []\n", + "for idx, specie in enumerate(refcell.unique_species):\n", + " tmp = specie.get_possible_cs(debug=debug)\n", + " if tmp is None: \n", + " print(\"error\")\n", + " if specie.subtype != \"metal\":\n", + " selected_cs.append(list([cs.corr_total_charge for cs in specie.possible_cs]))\n", + " else :\n", + " selected_cs.append(specie.possible_cs) " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "886cec55-200e-452c-9714-b20943578d8b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[-2], [2, 3], [0], [0], [1]]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "selected_cs" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "e7aff900-25e6-41bd-a88e-d38206017d81", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "BALANCE: iterlist [[-2], [2, 3], [0], [0], [1]]\n", + "BALANCE: unique_indices [0, 0, 0, 1, 2, 3, 3, 3, 2, 2, 4, 4, 4]\n", + "BALANCE: tmpdistr [(-2, 2, 0, 0, 1), (-2, 3, 0, 0, 1)]\n", + "BALANCE: alldistr added: [-2, -2, -2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 1]\n", + "BALANCE: distribution=[-2, -2, -2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 1]\n", + "BALANCE: alldistr added: [-2, -2, -2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1]\n", + "BALANCE: distribution=[-2, -2, -2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 1]\n", + "BALANCE: distribution=[-2, -2, -2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1]\n" + ] + } + ], + "source": [ + "from cell2mol.charge_assignment import balance_charge\n", + "final_charge_distribution, final_charges = balance_charge(refcell.unique_indices, refcell.unique_species, debug=debug)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "d40fc43b-29e8-4b27-9347-436c058d8139", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[-2, -2, -2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1]]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "final_charge_distribution" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "c12edebe-69b1-4d31-8687-9329f3568f55", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(-2, 3, 0, 0, 1)]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "final_charges" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "131a0049-5821-4e2f-a58c-4fb094021d14", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 C2-O4\n", + "------------- Cell2mol Protonation ----------------\n", + " Status = True\n", + " Labels = ['O', 'O', 'O', 'O', 'C', 'C']\n", + " Type = Local\n", + " Atoms added in positions = [0 0 0 0 0 0]\n", + " Atoms blocked (no atoms added) = [0 1 1 0 0 0]\n", + "---------------------------------------------------\n", + "\n", + "1 Fe\n", + "2 H24-C12-O6\n", + "------------- Cell2mol Protonation ----------------\n", + " Status = True\n", + " Labels = ['O', 'O', 'O', 'O', 'O', 'O', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H']\n", + " Type = Empty\n", + " Atoms added in positions = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + " Atoms blocked (no atoms added) = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "---------------------------------------------------\n", + "\n", + "3 H2-O\n", + "------------- Cell2mol Protonation ----------------\n", + " Status = True\n", + " Labels = ['O', 'H', 'H']\n", + " Type = Empty\n", + " Atoms added in positions = [0, 0, 0]\n", + " Atoms blocked (no atoms added) = [0, 0, 0]\n", + "---------------------------------------------------\n", + "\n", + "4 K\n", + "------------- Cell2mol Protonation ----------------\n", + " Status = True\n", + " Labels = ['K']\n", + " Type = Empty\n", + " Atoms added in positions = [0]\n", + " Atoms blocked (no atoms added) = [0]\n", + "---------------------------------------------------\n", + "\n" + ] + } + ], + "source": [ + "for specie, final_charge in zip(refcell.unique_species, final_charges[0]):\n", + " print(specie.unique_index, specie.formula)\n", + " if (specie.subtype == \"molecule\" and specie.iscomplex == False) or (specie.subtype == \"ligand\"):\n", + " charge_list = [cs.corr_total_charge for cs in specie.possible_cs]\n", + " idx = charge_list.index(final_charge)\n", + " cs = specie.possible_cs[idx]\n", + " specie.charge_state = cs\n", + " print(specie.charge_state.protonation)\n", + " specie.set_charges(cs.corr_total_charge, cs.corr_atom_charges, cs.smiles, cs.rdkit_obj)\n", + " else :\n", + " charge_list = specie.possible_cs \n", + " idx = charge_list.index(final_charge)\n", + " cs = specie.possible_cs[idx]\n", + " specie.set_charge(cs) \n", + " # print(specie)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "638b5114-5366-49d6-8c66-54d12ba888ad", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C2-O4 canonical smiles: O=C([O-])C(=O)[O-]\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "H24-C12-O6 canonical smiles: [H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "H2-O canonical smiles: [H]O[H]\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAIAAAAiOjnJAAAABmJLR0QA/wD/AP+gvaeTAAALUUlEQVR4nO3dXWxTdRjH8afburG3DGRjRDZehA7cBGGAMxpRZHFiGkKMMyIevNEZIxa4wJJIrDEsLHBTEm5miKaAJsCNWUFchkRdhnOYkYkTZGRsc4yB48WNzknpHi/Oactwru3o09N2v0+4OGHnf/ps/dKW05cZmJkAwi1B7wEgPiEsEIGwQATCAhEIC0QgLBCBsEAEwgIRCAtEICwQgbBABMICEQgLRCAsEIGwQATCAhEIC0QgLBCBsEAEwgIRCAtEICwQgbBABMICEQgLRCAsEIGwQATCAhEIC0QgLBCBsEAEwgIRCAtEICwQgbBABMICEQgLRCAsEIGwQATCAhEIC0QgLBCBsEAEwgIRCAtEICwQgbBABMICEQgLRCAsEIGwQATCAhEIC0QgLBCBsEAEwgIRCAtEICwQgbBABMICEQgLRCAsEJE09pe/+OILdaOwsHDJkiUBD+dyub766it1e/ny5QUFBQ84H8i5cOHC6dOn1e21a9emp6cHXHLmzJnffvtN3V6/fv1Yu/KYfLtt3bp17D1VHR0dviV79+4NZgnoZe/evb4rq6OjI5glW7duDbIc3BWCCIQFIhAWiEBYIAJhgQiEBSIQFohAWCACYYGIAE/p+HR1dX377bcBd7t27dqDzQP6OHXq1MWLFwPu1tXVFeQBgw3r0KFDhw4dCnJniDmvv/56eA+Iu0IQEewtlslkKioqCrjb33//XVtb+2AjgQ7KyspSU1MD7tba2trW1hbMAYMNa+3atbt27Qq4W2dn5+zZs4M8JkSP6urqWbNmBdztgw8+2L17dzAHxF0hiEBYIAJhgQiEBSIiEVZPT09jY2MELggCamxs7OnpicAFRSIsq9X61FNPvfrqq52dnRG4OBhVT0/PO++88/TTT2/bti0CFxeJsGbNmpWSknLkyJGioqLKysqhoaEIXCj4DA0NVVZWFhQUfPrpp8nJyTNnzozAhUYirB07drS1tSmKMjg4uH37dpPJtH//fr7nLUAgx+l0FhUVbd++3eVymc3m1tbWHTt2ROByI/TgPS8vb//+/SdPnnz88ce7u7vffPPNlStXtrS0RObSJ6Zz5869+OKLa9asaW9vf/TRR7/55hun0/nII49E5tIj+r/C5557rrm52eFwTJs27fvvvy8uLt6wYcPVq1cjOcNEcOPGjU2bNi1cuLC2tvahhx6y2+1nz54tKyuL5AwBntJZtWqVumEymYI5XGpqqm9Jfn7+f3dISEjYsGHDmjVrqqqq7Hb7gQMHnE7ntm3bNm/enJKSEsrkMAq32/35559/+OGHfX19SUlJFRUVlZWV2dnZo+6cn5/vu7KCeaKQiEwmk29JAGF4R+14/f7772azWR2joKDA6XTqOEwcqKure+yxx9Sf56pVq86ePavjMHqGpaqrq/O9bqK0tPTXX3/Ve6LYc+HChfLyct+NyuHDh/WeKArCYuY7d+7Y7fasrCwiMhqNFovl5s2beg8VGwYGBmw2m/ooIiMjw2azDQ0N6T0Uc5SEperr67NYLImJiUSkPuS8e/eu3kNFL4/H43A4cnNziSghIUFRlN7eXr2H8ouisFTNzc0rVqxQb9UXL1783Xff6T1RNGpsbCwpKVF/SiUlJY2NjXpPdL+oC0tVU1MzZ84c9QdnNpvb29v1niha/PHHH4qiGAwGIsrLy3M4HMPDw3oPNYooDYuZBwcHq6qqMjMziSg5OdlisfT39+s9lJ5cLpfNZlPPC6SlpVmt1oGBAb2H+l/RG5bq8uXLvn+gDz/8cHV1tcfj0XuoSBseHj58+LDvpcNmsznIz0nTUbSHpWpoaFi2bJn6Y/1EUbipSe+JIqip6RNFUb/3ZcuWNTQ06D1QUGIjLPb+qy1csOBybi4bDFxezp2deg8lrKeHKyo4MbE3J2e+yVRdXR1D/02OmbBUnv5+tlo5JYWJODOTd+7k6DhtE2ZDQ7xzJ2dmMhGnpLDV6om1x5cxFpamq4sVhYmYiPPz2eHQe6CwqqnhuXO1785s5osX9R5oPGIzLNXJk7xokXYFrFzJLS16D/TAzp3j1au172jBAv76a70HGr9YDouZPR52OHjaNCbihARWFL56Ve+ZxuX6dbZYOCmJiXjKFLbb2e3We6YHEuNhqW7cYKuVk5O1a6Wqiv/5R++ZguZ2c3U15+QwESclcUUFX7um90xhEBdhqc6f55de0u5H5s/no0f1HigIJ07wwoXazM8/z7/8ovdAYRNHYanq6riwULuqSku5tVXvgf5HWxuXl2tzzpvHUfBCl/CKu7CY+c4dtts5K4uJ2Ghki4Vv3dJ7pnvcvs02m3bGJD2dbba4PGMSj2Gp+vrYYuHERCbiqVPZbmfdzy4OD7PDwdOnMxEbDKwofOWKziOJMXB8vw2ruZk2b6b6eiKiJUvIbifva3KCNThIzc3055/U10dElJ1NOTlUXExpaaEdp6mJNm0i9R3hTzxBe/bQk0+GdoTYonfZEVFTw7Nn+085XroUeInHwwcOcGkpT5qkLbz3z6RJXFrKBw9yMM+Id3ezorDBwEQ8YwY7HByVL3QJr4kRFjMPDnJVFWdkMBGnprLVymM8SfLTT/5Tr2P/WbRorGfEXa77LzSKX+gSXhMmLFUwNx5Hj3J6+oh6CgpYUXjLFt6yhd94g+fNG/HV9HQ+dmyUyxrHzWQcmWBhqerreelS7So/cWLEl5qa2Gj0R2M2j35u6cwZLi3172Y03n+7deKE9qWlS7m+XvB7iVYTMixm9nh43z5et27EX96+zfPn+3P5+OMAB/noI//Oc+fefze3bh3v2xfUg7B4NFHDGtWuXf5QNm4Masn69f4lu3cLzxdL4v10Q/A8HjKZ6NIlIqLp06mtjTIyAq+6fp1MJrp5k4hozhxqa6PERNk5YwQ+KtKrvl6riogUJaiqiGjqVPL9TodLl7QTZoCw/Boa/NuvvBLCwtde82+fOhW2eWIcwvLyfUqq0UiLFoWwsLjYf/eHj1r1QlheHR3axty5NGlSCAvT0sj3aWa+g0x4CMtLfQBORFOmhLzWt8R3kAkPYXn99Ze2kZkZ8tqsLG3j1q2wzRPjEJaX0aht3L0b8lq3W9tITg7bPDEOYXlNnqxtDAyEvLa/X9sYx91onEJYXr4mxvHbh32fz4uwvBCWV2GhttHVFdpj8OvX6fJlbdv7EaCAsLy8n2NGzHT6dAgLf/xxlINMeAjL696XLH/5ZQgLDx70bz/7bNjmiXF4EvoeJSXU1ERElJ5O589TXl7gJe3tVFRE6m8HeuYZ+uEH2QljB26x7rFxo7bhctF771HAf3LDw/Tuu+T7nVPvvy84W8zR+3U70cTj4RUr/K+veuutsd4x5nb7P/GGiF94YSK8RSJ4CGuk9naePNmfy+LFfPz4/Z/P4XbzsWP+t8YTcXY2d3frNHGUwmOs/2hpodWr6coV/99MmULLl1NuLhFRby/9/POI8xEzZ9Lx4/6zFUBEePA+uo4OsljI6Qywm8FAL79Me/bQjBkRGSuWIKz/V19Pn31GtbUjbr1UM2ZQWRm9/Xacv5v5ASCsQJipvZ16e7W32Ofk0PTpFKlfJxm7EBaIwHksEIGwQATCAhEIC0QgLBCBsEAEwgIRCAtEICwQgbBABMICEQgLRCAsEIGwQATCAhEIC0QgLBCBsEAEwgIRCAtEICwQgbBABMICEQgLRCAsEIGwQATCAhEIC0QgLBCBsEAEwgIRCAtEICwQgbBABMICEQgLRCAsEIGwQATCAhEIC0QgLBCBsEAEwgIRCAtEICwQgbBABMICEQgLRCAsEIGwQATCAhEIC0QgLBCBsEAEwgIRCAtEICwQgbBABMICEQgLRCAsEIGwQMS/9u5PDtVVpwsAAAB6elRYdHJka2l0UEtMIHJka2l0IDIwMjMuMDkuNgAAeJx7v2/tPQYg4GdAAGYgZgLiBkYOAQUQW5IXSDqW5OeCcGayX2muohQHVLEMgzYjgwaQwcgIo7kZGEEGiICkxfVAQnCTV6/SWgqk94M4D92W2QMtsYOy98PYYgBrQxOkGMRALQAAAKZ6VFh0TU9MIHJka2l0IDIwMjMuMDkuNgAAeJyNUEEKwjAQvOcV84GW7S4Fc2yaoiJNQKN/8O7/MWtJ2h4UZ3OYnczAsAaKq788X6hgbwxAP561Fg8hIjNDCdx0PAeMaXBFGeM9pBsEnBN59s4hxbkoHSIaaukDZf3CqlSzjBO6lq0lOeRv7r/4JPuaf4xT8LsqSzkXg1/L6fDaQFfZ5rdu3csRMjdvKVVDaTN9UcoAAABDelRYdFNNSUxFUyByZGtpdCAyMDIzLjA5LjYAAHici/aI9Y/2iFWo0TDUM7K0NDDRMdAzMtWxNtDRNdAD0roowpo1ABZrCqz5EbocAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "K canonical smiles: [K+]\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import display\n", + "from rdkit.Chem.Draw import IPythonConsole\n", + "IPythonConsole.drawOptions.addAtomIndices = False\n", + "IPythonConsole.molSize = 200,200\n", + "from rdkit import Chem\n", + "from cell2mol.connectivity import create_bonds_spicie\n", + "\n", + "for specie, final_charge in zip(refcell.unique_species, final_charges[0]):\n", + " if (specie.subtype == \"molecule\" and specie.iscomplex == False) or (specie.subtype == \"ligand\"):\n", + " create_bonds_spicie(specie, debug=0)\n", + " print(specie.formula, \"canonical smiles:\", Chem.MolToSmiles(specie.rdkit_obj, canonical=True))\n", + " display(specie.rdkit_obj)" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "id": "dac7d765-a01e-48bc-aabe-b56630e2302a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + ". of >" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "specie.rdkit_obj." + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "d124aee4-31f7-4c89-b71e-7d1ab93c0fa8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 19\n", + " Formula = C6-O12-Fe\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Number of Ligands = 3\n", + " Number of Metals = 1\n", + "---------------------------------------------------\n", + "\n", + "------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Total Charge = 0\n", + " Smiles = [H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n", + "---------------------------------------------------\n", + "\n", + "------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Total Charge = 0\n", + " Smiles = [H]O[H]\n", + "---------------------------------------------------\n", + "\n", + "------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + "\n", + "------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 3\n", + " Formula = H2-O\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Total Charge = 0\n", + " Smiles = [H]O[H]\n", + "---------------------------------------------------\n", + "\n", + "------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + "\n", + "------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 42\n", + " Formula = H24-C12-O6\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + "---------------------------------------------------\n", + "\n", + "------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Total Charge = 1\n", + " Smiles = [K+]\n", + "---------------------------------------------------\n", + "\n", + "------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Total Charge = 1\n", + " Smiles = [K+]\n", + "---------------------------------------------------\n", + "\n", + "------------- Cell2mol MOLECULE Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = molecule\n", + " Number of Atoms = 1\n", + " Formula = K\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Total Charge = 1\n", + " Smiles = [K+]\n", + "---------------------------------------------------\n", + "\n" + ] + } + ], + "source": [ + "for ref in refcell.refmoleclist:\n", + " print(ref)" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "3f52255f-9317-43c5-9c9d-61f7b71c64ff", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['O10', 'O21', 'O21', 'O10', 'C30', 'C30'] ['O10', 'O21', 'O21', 'O10', 'C30', 'C30']\n", + "len(mols)=1 received from xyz2mol with charge 1\n", + "['O10', 'O21', 'O21', 'O10', 'C30', 'C30'] ['O10', 'O21', 'O21', 'O10', 'C30', 'C30']\n", + "len(mols)=1 received from xyz2mol with charge 1\n", + "['O10', 'O21', 'O21', 'O10', 'C30', 'C30'] ['O10', 'O21', 'O21', 'O10', 'C30', 'C30']\n", + "len(mols)=1 received from xyz2mol with charge 1\n", + "\n", + "H24-C12-O6 0\n", + "['O20', 'O20', 'O20', 'O20', 'O20', 'O20', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10'] ['O20', 'O20', 'O20', 'O20', 'O20', 'O20', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10']\n", + "len(mols)=1 received from xyz2mol with charge 1\n", + "H24-C12-O6 H24-C12-O6 True\n", + "\n", + "H2-O 0\n", + "['O20', 'H10', 'H10'] ['O20', 'H10', 'H10']\n", + "len(mols)=1 received from xyz2mol with charge 1\n", + "H2-O H2-O True\n", + "\n", + "['O20', 'H10', 'H10'] ['O20', 'H10', 'H10']\n", + "[0 2 1]\n", + "H2-O H2-O True\n", + "\n", + "H2-O 0\n", + "['O20', 'H10', 'H10'] ['O20', 'H10', 'H10']\n", + "len(mols)=1 received from xyz2mol with charge 1\n", + "H2-O H2-O True\n", + "\n", + "['O20', 'O20', 'O20', 'O20', 'O20', 'O20', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10'] ['O20', 'O20', 'O20', 'O20', 'O20', 'O20', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10']\n", + "[ 1 5 4 3 2 0 6 8 41 39 40 16 33 20 38 30 34 32 27 28 31 24 29 26\n", + " 21 22 25 18 35 23 36 19 37 15 13 17 12 14 11 9 7 10]\n", + "H24-C12-O6 H24-C12-O6 True\n", + "\n", + "['O20', 'O20', 'O20', 'O20', 'O20', 'O20', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10'] ['O20', 'O20', 'O20', 'O20', 'O20', 'O20', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10', 'C40', 'H10', 'H10']\n", + "[ 5 0 4 3 2 1 6 40 7 39 41 38 36 34 37 33 11 35 27 31 13 24 25 29\n", + " 21 26 23 18 19 22 15 20 17 12 16 28 30 32 14 9 10 8]\n", + "H24-C12-O6 H24-C12-O6 True\n", + "\n", + "K 1\n", + "['K00'] ['K00']\n", + "len(mols)=1 received from xyz2mol with charge 1\n", + "K K True\n", + "\n", + "K 1\n", + "['K00'] ['K00']\n", + "len(mols)=1 received from xyz2mol with charge 1\n", + "K K True\n", + "\n", + "K 1\n", + "['K00'] ['K00']\n", + "len(mols)=1 received from xyz2mol with charge 1\n", + "K K True\n", + "\n" + ] + } + ], + "source": [ + "from cell2mol.connectivity import compare_species, compare_metals\n", + "from cell2mol.charge_assignment import check_rdkit_obj_connectivity, charge_state\n", + "for ref in refcell.refmoleclist:\n", + " if hasattr(ref, \"totcharge\"):\n", + " print(ref.formula, ref.totcharge)\n", + " if ref.iscomplex:\n", + " for lig in ref.ligands:\n", + " for specie in refcell.unique_species:\n", + " if specie.subtype == \"ligand\":\n", + " issame = compare_species(lig, specie)\n", + " set_charge_state(specie, lig)\n", + " # print(lig.formula, specie.formula, issame)\n", + " for met in ref.metals:\n", + " for specie in refcell.unique_species:\n", + " if specie.subtype == \"metal\":\n", + " issame = compare_metals(met, specie)\n", + " met.set_charge(specie.charge)\n", + " # print(met.formula, specie.formula, issame) \n", + " else:\n", + " for specie in refcell.unique_species: \n", + " if specie.subtype == \"molecule\":\n", + " issame = compare_species(ref, specie)\n", + " if issame:\n", + " set_charge_state(specie, ref)\n", + " print(ref.formula, specie.formula, issame)\n", + " print(\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "b14cd28d-11a8-424c-bd00-78dc8f902b8e", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "from cell2mol.hungarian import reorder\n", + "\n", + "def set_charge_state(unique_specie, target):\n", + " \n", + " prot = unique_specie.charge_state.protonation\n", + " \n", + " ref_data, target_data = arrange_data_for_reorder(unique_specie, target)\n", + " print(ref_data, target_data)\n", + " dummy1, dummy2, map12 = reorder(ref_data, target_data, unique_specie.coord, target.coord)\n", + " if np.array_equal(map12, np.arange(len(target_data))):\n", + " cs = get_charge_test(final_charge, prot)\n", + " target.set_charges(cs.corr_total_charge, cs.corr_atom_charges, cs.smiles, cs.rdkit_obj)\n", + " else:\n", + " print(map12)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "25cd9a2b-f684-40d6-ae58-e611feab4884", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------- Cell2mol LIGAND Object --------------\n", + " Version = 2.0\n", + " Type = specie\n", + " Sub-Type = ligand\n", + " Number of Atoms = 6\n", + " Formula = C2-O4\n", + " Covalent Radii Factor = 1.3\n", + " Metal Radii Factor = 1.0\n", + " Has Adjacency Matrix = YES\n", + " Total Charge = -2\n", + " Smiles = O=C([O-])C(=O)[O-]\n", + " Origin = split_complex\n", + " Number of Groups = 2\n", + "---------------------------------------------------\n", + " -2\n" + ] + }, + { + "ename": "ValueError", + "evalue": "Final molecular charge does not match input; could not find valid bond ordering", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Input \u001b[0;32mIn [31]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (specie\u001b[38;5;241m.\u001b[39msubtype \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmolecule\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m specie\u001b[38;5;241m.\u001b[39miscomplex \u001b[38;5;241m==\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m) \u001b[38;5;129;01mor\u001b[39;00m (specie\u001b[38;5;241m.\u001b[39msubtype \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mligand\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28mprint\u001b[39m(specie, final_charge)\n\u001b[0;32m----> 5\u001b[0m \u001b[43mrdDetermineBonds\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mDetermineBondOrders\u001b[49m\u001b[43m(\u001b[49m\u001b[43mspecie\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrdkit_obj\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcharge\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfinal_charge\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[0;31mValueError\u001b[0m: Final molecular charge does not match input; could not find valid bond ordering" + ] + } + ], + "source": [ + "# Didn't work!!\n", + "# from rdkit.Chem import rdDetermineBonds\n", + "# for specie, final_charge in zip(refcell.unique_species, final_charges[0]):\n", + "# if (specie.subtype == \"molecule\" and specie.iscomplex == False) or (specie.subtype == \"ligand\"):\n", + "# print(specie, final_charge)\n", + "# rdDetermineBonds.DetermineBondOrders(specie.rdkit_obj, charge=final_charge)" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "id": "12c93c12-783e-40b7-9edf-b53549cf63f8", + "metadata": {}, + "outputs": [], + "source": [ + "import py3Dmol\n", + "\n", + "def draw_with_spheres(mol):\n", + " v = py3Dmol.view(width=300,height=300)\n", + " IPythonConsole.addMolToView(mol,v)\n", + " v.zoomTo()\n", + " v.setStyle({'sphere':{'radius':0.3},'stick':{'radius':0.2}});\n", + " v.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 157, + "id": "6236142f-8174-4792-bf12-1eab6467909b", + "metadata": {}, + "outputs": [], + "source": [ + "# from rdkit.Chem import rdDetermineBonds\n", + "xyzfile = \"unique_specie_H24-C12-O6_2.xyz\"\n", + "raw_mol = Chem.MolFromXYZFile(f\"/Users/ycho/cell2mol/cell2mol/test/error_2/BOFFOS/{xyzfile}\")\n", + "conn_mol = Chem.Mol(raw_mol)\n", + "rdDetermineBonds.DetermineBonds(conn_mol,charge=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 160, + "id": "b5eeb097-b459-4523-a0c1-29a387af3627", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 160, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conn_mol" + ] + }, + { + "cell_type": "code", + "execution_count": 162, + "id": "de2ee693-75bc-4cc7-8a97-2e2736820440", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6 0 SINGLE\n", + "7 6 SINGLE\n", + "8 6 SINGLE\n", + "9 6 SINGLE\n", + "9 1 SINGLE\n", + "10 9 SINGLE\n", + "11 9 SINGLE\n", + "12 1 SINGLE\n", + "13 12 SINGLE\n", + "14 12 SINGLE\n", + "15 12 SINGLE\n", + "15 2 SINGLE\n", + "16 15 SINGLE\n", + "17 15 SINGLE\n", + "18 2 SINGLE\n", + "19 18 SINGLE\n", + "20 18 SINGLE\n", + "21 18 SINGLE\n", + "21 3 SINGLE\n", + "22 21 SINGLE\n", + "23 21 SINGLE\n", + "24 3 SINGLE\n", + "25 24 SINGLE\n", + "26 24 SINGLE\n", + "27 24 SINGLE\n", + "27 4 SINGLE\n", + "28 27 SINGLE\n", + "29 27 SINGLE\n", + "30 4 SINGLE\n", + "31 30 SINGLE\n", + "32 30 SINGLE\n", + "33 5 SINGLE\n", + "33 30 SINGLE\n", + "34 33 SINGLE\n", + "35 33 SINGLE\n", + "36 5 SINGLE\n", + "37 36 SINGLE\n", + "38 36 SINGLE\n", + "39 0 SINGLE\n", + "39 36 SINGLE\n", + "40 39 SINGLE\n", + "41 39 SINGLE\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[H]C1([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC([H])([H])C([H])([H])OC1([H])[H]\n" + ] + } + ], + "source": [ + "from IPython.display import display\n", + "from rdkit.Chem.Draw import IPythonConsole\n", + "IPythonConsole.drawOptions.addAtomIndices = True\n", + "IPythonConsole.molSize = 200,200\n", + "for b in mol.GetBonds():\n", + " print(b.GetBeginAtomIdx(), b.GetEndAtomIdx(), b.GetBondType())\n", + "display(mol)\n", + "smiles = Chem.MolToSmiles(mol, canonical=True)\n", + "print(smiles)" + ] + }, + { + "cell_type": "raw", + "id": "4e51a85a-b6eb-4bd1-b8b1-c76557c461d1", + "metadata": {}, + "source": [ + "# def getcharge(labels: list, pos: list, conmat: np.ndarray, ich: int, cov_factor: float=1.3, allow: bool=True, debug: int=0) -> list:\n", + " ## Generates the connectivity of a molecule given a charge.\n", + " # The molecule is described by the labels, and the atomic cartesian coordinates \"pos\"\n", + " # The adjacency matrix is also provided (conmat)\n", + " #:return iscorrect: boolean variable with a notion of whether the function delivered a good=True or bad=False connectivity\n", + " #:return total_charge: total charge associated with the connectivity\n", + " #:return atom_charge: atomic charge for each atom of the molecule\n", + " #:return mols: rdkit molecule object\n", + " #:return smiles: smiles representation of the molecule\n", + "\n", + " # mols = xyz2mol(atnums,pos,conmat,cov_factor,charge=ich,use_graph=True,allow_charged_fragments=allow,embed_chiral=True,use_huckel=False)\n", + "from rdkit import Chem\n", + "\n", + "from cell2mol.xyz2mol import xyz2mol\n", + "def get_charge_test(charge: int, prot: object, allow: bool=True, debug: int=0): \n", + " ## Generates the connectivity of a molecule given a desired charge (charge).\n", + " # The molecule is described by a protonation states that has labels, and the atomic cartesian coordinates \"coords\"\n", + " # The adjacency matrix is also provided in the protonation state(adjmat)\n", + " #:return charge_state which is an object with the necessary information for other functions to handle the result\n", + "\n", + " natoms = prot.natoms\n", + " atnums = prot.atnums\n", + "\n", + " ##########################\n", + " # xyz2mol is called here #\n", + " ##########################\n", + " # use_graph is called for a faster generation\n", + " # allow_charged_fragments is necessary for non-neutral molecules\n", + " # embed_chiral shouldn't ideally be necessary, but it runs a sanity check that improves the proposed connectivity\n", + " # use_huckel false means that the xyz2mol adjacency will be generated based on atom distances and vdw radii.\n", + " # instead of use_huckel, we provide the adjacency matrix \n", + "\n", + " mols = xyz2mol(atnums, prot.coords, prot.adjmat, prot.cov_factor, charge=charge, allow_charged_fragments=allow)\n", + " print(f\"{len(mols)=} received from xyz2mol with charge {charge}\")\n", + " \n", + " if len(mols) > 1: print(\"WARNING: More than 1 mol received from xyz2mol for initcharge:\", charge)\n", + "\n", + " # Smiles are generated with rdkit\n", + " smiles = Chem.MolToSmiles(mols[0])\n", + " if debug >= 2: print(f\"GET_CHARGE. {smiles=}\")\n", + " # Gets the resulting charges\n", + " atom_charge = []\n", + " total_charge = 0\n", + " for i in range(natoms):\n", + " a = mols[0].GetAtomWithIdx(i) # Returns a particular Atom\n", + " atom_charge.append(a.GetFormalCharge())\n", + " total_charge += a.GetFormalCharge()\n", + "\n", + " # Connectivity is checked\n", + " iscorrect = check_rdkit_obj_connectivity(mols[0], prot.natoms, charge, debug=debug)\n", + "\n", + " # Charge_state is initiated\n", + " ch_state = charge_state(iscorrect, total_charge, atom_charge, mols[0], smiles, charge, allow, prot)\n", + "\n", + " return ch_state" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8cc24d95-8f26-4ac0-a49b-9c96f27b6e9a", + "metadata": {}, + "outputs": [], + "source": [ + "def reorder_protonation (prot, map12, debug: int=0):\n", + " if debug > 0: print(\"PROTONATION.REORDER. labels:\", prot.labels)\n", + " if debug > 0: print(\"PROTONATION.REORDER. received map:\", map)\n", + "\n", + " ## for protonation states with added atoms, the reorder map will have fewer items. Correct it here \n", + " mapext = np.copy(map12)\n", + " if prot.added_atoms > 0 and len(map12) < len(prot.labels):\n", + " for ldx in range(0,prot.added_atoms):\n", + " mapext = np.append(mapext,len(map12)+ldx)\n", + " if debug > 0: print(\"PROTONATION.REORDER. extended map:\", mapext)\n", + "\n", + " assert len(mapext) == len(prot.labels)\n", + " assert len(map12) == len(prot.addedlist)\n", + " if len(map12) > 0:\n", + " reordered_labels = [prot.labels[i] for i in mapext]\n", + " reordered_coords = [prot.coords[i] for i in mapext]\n", + " reordered_addedlist = [prot.addedlist[i] for i in map12]\n", + " reordered_block = [prot.block[i] for i in map12]\n", + " reordered_metal_electrons = [prot.metal_electrons[i] for i in map12]\n", + " reordered_elemlist = [prot.elemlist[i] for i in map12]\n", + "\n", + "\n", + " reordered_protonation = protonation(reordered_labels, reordered_coords, prot.cov_factor, prot.added_atoms,\n", + " reordered_addedlist, reordered_block, reordered_metal_electrons, reordered_elemlist, \n", + " tmpsmiles=prot.tmpsmiles, os=prot.os, typ=\"Reordered\", parent=prot.parent)\n", + " print(\"CREATED REORDERED PROTONATION\", reordered_protonation)\n", + "\n", + " return reordered_protonation" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "89b03457-30be-4f68-bfdd-6a1eab038a02", + "metadata": {}, "outputs": [ { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "5789be2d0bc14915a6005864a7e07ef8", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + "SAVING cell2mol CELL object to error_2/BOFFOS/Ref_Cell_BOFFOS_NEW.cell\n" + ] } ], "source": [ - "from scipy import sparse\n", - "from ase.build import molecule\n", - "from ase.neighborlist import get_connectivity_matrix\n", - "from ase.neighborlist import natural_cutoffs\n", - "from ase.neighborlist import NeighborList\n", - "import ase\n", - "import numpy as np\n", - "from ase.io import read\n", - "from ase import Atoms\n", - "import ase.visualize\n", - "from ase.visualize.plot import plot_atoms\n", - "from cell2mol.read_write import readinfo\n", - "from cell2mol.cell_operations import frac2cart_fromparam, cart2frac\n", - "import nglview\n", - "from ase.build import molecule\n", - "from ase.neighborlist import NeighborList\n", - "import matplotlib.pyplot as plt" + "refcell.save(f\"{folder}/{name}/Ref_Cell_{name}_NEW.cell\")" ] }, { "cell_type": "code", - "execution_count": 2, - "id": "5ff88c96-bda9-4f00-8323-20a1386d5253", + "execution_count": 38, + "id": "d83153eb-1102-47a0-bcd9-10c66e1a3f39", "metadata": {}, "outputs": [], "source": [ - "folder = \"error_2\"\n", - "name = \"BOFFOS\"\n", - "infopath = f\"{folder}/{name}/{name}.info\"\n", - "input_path = f\"{folder}/{name}/{name}.cif\"" + "load_cell = np.load(f\"{folder}/{name}/Ref_Cell_{name}_NEW.cell\", allow_pickle=True)" ] }, { "cell_type": "code", - "execution_count": 7, - "id": "6c9cf56e-10ab-4a85-83ea-a9b6813a083d", + "execution_count": 55, + "id": "f6fee965-de76-43a7-82a8-9af05d55435f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "COMPARE_SPECIES. Comparing:\n", + "C2-O4\n", + "C2-O4\n", + "COMPARE_SPECIES. kdx ldx elem1 - elem2 : reordered - reference\n", + "COMPARE_SPECIES. Comparing:\n", + "C2-O4\n", + "C2-O4\n", + "COMPARE_SPECIES. kdx ldx elem1 - elem2 : reordered - reference\n", + "COMPARE_SPECIES. Comparing:\n", + "C2-O4\n", + "C2-O4\n", + "COMPARE_SPECIES. kdx ldx elem1 - elem2 : reordered - reference\n", + "3\n" + ] + } + ], + "source": [ + "for ref in load_cell.refmoleclist:\n", + " if ref.iscomplex:\n", + " occurrence = ref.get_occurrence(ref.ligands[0])\n", + " print(occurrence)\n", + " # print(ref.metals)\n", + " # print(ref.ligands)\n", + " # else:\n", + " # print(ref)" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "id": "6bc36f34-5717-4a8c-8dfb-7defc23292b1", "metadata": {}, "outputs": [], "source": [ - "labels, pos, ref_labels, ref_fracs, cellvec, cellparam = readinfo(infopath)" + "ref = refcell.refmoleclist[0]" ] }, { "cell_type": "code", - "execution_count": 8, - "id": "c883d74e-e2c3-463e-86ae-1133495aaee1", + "execution_count": 90, + "id": "68436123-a378-43e0-9111-091f60c6d9a0", + "metadata": {}, + "outputs": [], + "source": [ + "spec_object = refcell.unique_species[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "id": "6be6b6ba-f358-4e77-8769-4d0e1a4960ea", "metadata": { "scrolled": true }, + "outputs": [ + { + "data": { + "text/plain": [ + "[8, 8, 8, 8, 6, 6]" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spec_object.possible_cs[0].protonation.atnums" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "97ea9d39-4f3a-413b-a5d7-ddd950259bc8", + "metadata": {}, "outputs": [], "source": [ - "atoms = read(input_path)\n", - "cell_labels = atoms.get_chemical_symbols()\n", - "cell_pos = atoms.positions\n", - "cell_fracs = atoms.get_scaled_positions()\n", - "cell_vector = atoms.cell\n", - "# cell_parameters = atoms.cell.cellpar()\n", - "space_group = atoms.info['spacegroup']\n", - "sym_ops = space_group.get_op()" + "def arrange_data_for_reorder(reference: object, target: object, debug: int=0):\n", + " # To do the reorder, we create new tags that include as much information as possible.\n", + " # Ideally, we aim to include the label + the connectivity + the metal connectivity\n", + " t_totconnec = 0\n", + " t_totmconnec = 0\n", + " for a in target.atoms:\n", + " t_totconnec += a.connec\n", + " t_totmconnec += a.mconnec\n", + " r_totconnec = 0\n", + " r_totmconnec = 0\n", + " for a in reference.atoms:\n", + " r_totconnec += a.connec\n", + " r_totmconnec += a.mconnec\n", + " if t_totconnec == r_totconnec: useconec = True\n", + " else: useconec = False\n", + " if t_totmconnec == r_totmconnec: usemconec = True\n", + " else: usemconec = False\n", + " # For target\n", + " target_data = []\n", + " for a in target.atoms:\n", + " data = a.label\n", + " if useconec: data += str(a.connec)\n", + " if usemconec: data += str(a.mconnec)\n", + " target_data.append(data)\n", + " # For reference\n", + " ref_data = []\n", + " for a in reference.atoms:\n", + " data = a.label\n", + " if useconec: data += str(a.connec)\n", + " if usemconec: data += str(a.mconnec)\n", + " ref_data.append(data)\n", + " return ref_data, target_data" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 111, + "id": "ab466d45-4e91-472d-8b0c-d54ec4f1ea73", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[8, 10, 12, 13, 16, 18]" + ] + }, + "execution_count": 111, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lig.get_parent_indices(\"molecule\")" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "id": "7a830fdf-d4c0-4192-8772-b09692190d4f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['O', 'O', 'O', 'O', 'C', 'C'] [8, 10, 12, 13, 16, 18]\n", + "['O10', 'O21', 'O21', 'O10', 'C30', 'C30'] ['O10', 'O21', 'O21', 'O10', 'C30', 'C30']\n", + "['O', 'O', 'O', 'O', 'C', 'C'] [7, 9, 11, 14, 15, 17]\n", + "['O10', 'O21', 'O21', 'O10', 'C30', 'C30'] ['O10', 'O21', 'O21', 'O10', 'C30', 'C30']\n", + "['O', 'O', 'O', 'O', 'C', 'C'] [1, 2, 3, 4, 5, 6]\n", + "['O10', 'O21', 'O21', 'O10', 'C30', 'C30'] ['O10', 'O21', 'O21', 'O10', 'C30', 'C30']\n" + ] + } + ], + "source": [ + "from cell2mol.hungarian import reorder\n", + "\n", + "for lig in ref.ligands:\n", + " \n", + " print(lig.labels, lig.get_parent_indices(\"molecule\"))\n", + " ref_data, target_data = arrange_data_for_reorder(spec_object, lig)\n", + " print(ref_data, target_data)\n", + " dummy1, dummy2, map12 = reorder(ref_data, target_data, spec_object.coord, lig.coord)\n", + " if np.array_equal(map12, np.arange(len(target_data))):\n", + " cs = get_charge_test(final_charge, prot)\n", + " specie.set_charges(cs.corr_total_charge, cs.corr_atom_charges, cs.smiles, cs.rdkit_obj)\n", + " else:\n", + " print(map12)\n", + " # if (map12, np.arrange(len()target_data.all():\n", + " # print(\"Yes\")" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "id": "d17bf0ea-de21-422e-894a-3366649703a8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['O', 'O', 'O', 'O', 'C', 'C']\n", + "[1 1 1 1 3 3]\n", + "['O', 'O', 'O', 'O', 'O', 'O', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'C', 'H', 'H']\n", + "[2 2 2 2 2 2 4 1 1 4 1 1 4 1 1 4 1 1 4 1 1 4 1 1 4 1 1 4 1 1 4 1 1 4 1 1 4\n", + " 1 1 4 1 1]\n", + "['O', 'H', 'H']\n", + "[2 1 1]\n", + "['K']\n", + "[0]\n" + ] + } + ], + "source": [ + "for specie in refcell.unique_species:\n", + " if specie.subtype != \"metal\":\n", + " for cs in specie.possible_cs:\n", + " print(cs.protonation.labels)\n", + " print(cs.protonation.adjnum)" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "42385279-6a91-4248-9843-1b71ffff6bf1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "H24-C12-O6 0\n", + "H24-C12-O6 H24-C12-O6 True\n", + "\n", + "H2-O 0\n", + "H2-O H2-O True\n", + "\n", + "H2-O H2-O True\n", + "\n", + "H2-O H2-O True\n", + "\n", + "H24-C12-O6 H24-C12-O6 True\n", + "\n", + "H24-C12-O6 H24-C12-O6 True\n", + "\n", + "K 1\n", + "K K True\n", + "\n", + "K K True\n", + "\n", + "K K True\n", + "\n" + ] + } + ], + "source": [ + "from cell2mol.connectivity import compare_species, compare_metals\n", + "for ref in refcell.refmoleclist:\n", + " if hasattr(ref, \"totcharge\"):\n", + " print(ref.formula, ref.totcharge, ref.)\n", + " if ref.iscomplex:\n", + " for lig in ref.ligands:\n", + " for specie in refcell.unique_species:\n", + " if specie.subtype == \"ligand\":\n", + " issame = compare_species(lig, specie)\n", + " # print(lig.formula, specie.formula, issame)\n", + " for met in ref.metals:\n", + " for specie in refcell.unique_species:\n", + " if specie.subtype == \"metal\":\n", + " issame = compare_metals(met, specie)\n", + " # print(met.formula, specie.formula, issame) \n", + " else:\n", + " for specie in refcell.unique_species: \n", + " if specie.subtype == \"molecule\":\n", + " issame = compare_species(ref, specie)\n", + " if issame:\n", + " print(ref.formula, specie.formula, issame)\n", + " print(\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 14, "id": "475c10ec-29e4-4a15-9d13-bf04ac534884", "metadata": {}, "outputs": [], "source": [ "from cell2mol.classes import cell\n", - "newcell = cell(name, cell_labels, cell_pos, cell_vector, cellparam)\n", - "newcell.frac_coord = cell_fracs" + "newcell = cell(name, cell_labels, cell_pos, cell_fracs, cell_vector, cell_param)\n", + "newcell.get_subtype(\"unit_cell\")" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "15380c6f-777e-4f49-a62a-5bae4afc4264", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + "]\n", + "[------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + "]\n", + "[------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + "]\n", + "[------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + "]\n", + "[------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + "]\n", + "[------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + "]\n", + "[------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + "]\n", + "[------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + "]\n", + "[------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + "]\n", + "[------------- Cell2mol CELL Object ----------------\n", + " Version = 2.0\n", + " Type = cell\n", + " Sub-Type = reference\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 157\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + "]\n" + ] + } + ], + "source": [ + "for ref in refcell.refmoleclist:\n", + " print(ref.parents)" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 8, + "id": "f7e884c2-765d-4369-a595-3ebf9943c1c7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "------------- Cell2mol CELL Object ----------------\n", + " Version = 0.1\n", + " Type = cell\n", + " Name (Refcode) = BOFFOS\n", + " Num Atoms = 525\n", + " Cell Parameters a:c = [24.369, 24.369, 9.748]\n", + " Cell Parameters al:ga = [90.0, 90.0, 120.0]\n", + " Cell vector = [[ 24.369 0. 0. ]\n", + " [-12.1845 21.10417306 0. ]\n", + " [ 0. 0. 9.748 ]]\n", + "---------------------------------------------------\n", + " # of Ref Molecules: = 10\n", + " With Formulae: \n", + " 0: C6-O12-Fe \n", + " 1: H24-C12-O6 \n", + " 2: H2-O \n", + " 3: H2-O \n", + " 4: H2-O \n", + " 5: H24-C12-O6 \n", + " 6: H24-C12-O6 \n", + " 7: K \n", + " 8: K \n", + " 9: K " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "newcell" + ] + }, + { + "cell_type": "code", + "execution_count": 9, "id": "c57291bf-26ab-4474-b711-e66b8ae533ca", "metadata": {}, "outputs": [], @@ -105,7 +2377,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 10, "id": "a86e4043-ddb1-4d81-afdf-a569eadd96cc", "metadata": {}, "outputs": [ @@ -340,7 +2612,7 @@ " ---------------------------------------------------]" ] }, - "execution_count": 12, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -737,72 +3009,19 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 21, "id": "e058d609-060e-4147-afa3-87cd37633cf0", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "------------- Cell2mol LIGAND Object --------------\n", - " Version = 0.1\n", - " Type = specie\n", - " Sub-Type = ligand\n", - " Number of Atoms = 6\n", - " Formula = C2-O4\n", - " Covalent Radii Factor = 1.3\n", - " Metal Radii Factor = 1.0\n", - " Has Adjacency Matrix = YES\n", - " Origin = split_complex\n", - " Number of Groups = 2\n", - "---------------------------------------------------\n", - " [-2]\n", - "------------- Cell2mol METAL Object --------------\n", - " Version = 0.1\n", - " Type = atom\n", - " Sub-Type = metal\n", - " Label = Fe\n", - " Atomic Number = 26\n", - " Index in Molecule = 0\n", - " Metal Adjacency (mconnec) = 6\n", - " Regular Adjacencies (connec) = 6\n", - " Possible Charges = [2, 3]\n", - "----------------------------------------------------\n", - " [2, 3]\n", - "------------- Cell2mol MOLECULE Object --------------\n", - " Version = 0.1\n", - " Type = specie\n", - " Sub-Type = molecule\n", - " Number of Atoms = 42\n", - " Formula = H24-C12-O6\n", - " Covalent Radii Factor = 1.3\n", - " Metal Radii Factor = 1.0\n", - " Has Adjacency Matrix = YES\n", - "---------------------------------------------------\n", - " [0]\n", - "------------- Cell2mol MOLECULE Object --------------\n", - " Version = 0.1\n", - " Type = specie\n", - " Sub-Type = molecule\n", - " Number of Atoms = 3\n", - " Formula = H2-O\n", - " Covalent Radii Factor = 1.3\n", - " Metal Radii Factor = 1.0\n", - " Has Adjacency Matrix = YES\n", - "---------------------------------------------------\n", - " [0]\n", - "------------- Cell2mol MOLECULE Object --------------\n", - " Version = 0.1\n", - " Type = specie\n", - " Sub-Type = molecule\n", - " Number of Atoms = 1\n", - " Formula = K\n", - " Covalent Radii Factor = 1.3\n", - " Metal Radii Factor = 1.0\n", - " Has Adjacency Matrix = YES\n", - "---------------------------------------------------\n", - " [1]\n" + "ename": "NameError", + "evalue": "name 'unique_species' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Input \u001b[0;32mIn [21]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m spec, cs \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mzip\u001b[39m(\u001b[43munique_species\u001b[49m, selected_cs):\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(spec, cs)\n", + "\u001b[0;31mNameError\u001b[0m: name 'unique_species' is not defined" ] } ], @@ -881,7 +3100,7 @@ "\n", " # Expands tmpdistr to include same species, generating alldistr:\n", " alldistr = []\n", - " final_charge_list= []\n", + " final_selected_charges= []\n", " for distr in tmpdistr:\n", " tmp = []\n", " for u in unique_indices:\n", @@ -895,13 +3114,13 @@ " final_charge = np.sum(d)\n", " if final_charge == 0:\n", " final_charge_distribution.append(d)\n", - " final_charge_list.append(distr)\n", + " final_selected_charges.append(distr)\n", " if debug >= 2: print(\"\")\n", " elif iserror:\n", " if debug >= 1: print(\"Error found in BALANCE: one species has no possible charges\")\n", " final_charge_distribution = []\n", "\n", - " return final_charge_distribution, final_charge_list" + " return final_charge_distribution, final_selected_charges" ] }, {