Пример #1
0
 def __init__(self, start_monomer, s_head, s_tail,
              monomer, head, tail,
              end_monomer, e_head, e_tail,
              n_units, link_distance=1.0, linear_chain=False):
     """
     Args:
         start_monomer (Molecule): Starting molecule
         s_head (int): starting atom index of the start_monomer molecule
         s_tail (int): tail atom index of the start_monomer
         monomer (Molecule): The monomer
         head (int): index of the atom in the monomer that forms the head
         tail (int): tail atom index. monomers will be connected from
             tail to head
         end_monomer (Molecule): Terminal molecule
         e_head (int): starting atom index of the end_monomer molecule
         e_tail (int): tail atom index of the end_monomer
         n_units (int): number of monomer units excluding the start and
             terminal molecules
         link_distance (float): distance between consecutive monomers
         linear_chain (bool): linear or random walk polymer chain
     """
     self.start = s_head
     self.end = s_tail
     self.monomer = monomer
     self.n_units = n_units
     self.link_distance = link_distance
     self.linear_chain = linear_chain
     # translate monomers so that head atom is at the origin
     start_monomer.translate_sites(range(len(start_monomer)),
                                   - monomer.cart_coords[s_head])
     monomer.translate_sites(range(len(monomer)),
                             - monomer.cart_coords[head])
     end_monomer.translate_sites(range(len(end_monomer)),
                                 - monomer.cart_coords[e_head])
     self.mon_vector = monomer.cart_coords[tail] - monomer.cart_coords[head]
     self.moves = {1: [1, 0, 0],
                   2: [0, 1, 0],
                   3: [0, 0, 1],
                   4: [-1, 0, 0],
                   5: [0, -1, 0],
                   6: [0, 0, -1]}
     self.prev_move = 1
     # places the start monomer at the beginning of the chain
     self.molecule = start_monomer.copy()
     self.length = 1
     # create the chain
     self._create(self.monomer, self.mon_vector)
     # terminate the chain with the end_monomer
     self.n_units += 1
     end_mon_vector = end_monomer.cart_coords[e_tail] - \
                      end_monomer.cart_coords[e_head]
     self._create(end_monomer, end_mon_vector)
     self.molecule = Molecule.from_sites(self.molecule.sites)
Пример #2
0
 def __init__(self, start_monomer, s_head, s_tail,
              monomer, head, tail,
              end_monomer, e_head, e_tail,
              n_units, link_distance=1.0, linear_chain=False):
     """
     Args:
         start_monomer (Molecule): Starting molecule
         s_head (int): starting atom index of the start_monomer molecule
         s_tail (int): tail atom index of the start_monomer
         monomer (Molecule): The monomer
         head (int): index of the atom in the monomer that forms the head
         tail (int): tail atom index. monomers will be connected from
             tail to head
         end_monomer (Molecule): Terminal molecule
         e_head (int): starting atom index of the end_monomer molecule
         e_tail (int): tail atom index of the end_monomer
         n_units (int): number of monomer units excluding the start and
             terminal molecules
         link_distance (float): distance between consecutive monomers
         linear_chain (bool): linear or random walk polymer chain
     """
     self.start = s_head
     self.end = s_tail
     self.monomer = monomer
     self.n_units = n_units
     self.link_distance = link_distance
     self.linear_chain = linear_chain
     # translate monomers so that head atom is at the origin
     start_monomer.translate_sites(range(len(start_monomer)),
                                   - monomer.cart_coords[s_head])
     monomer.translate_sites(range(len(monomer)),
                             - monomer.cart_coords[head])
     end_monomer.translate_sites(range(len(end_monomer)),
                                 - monomer.cart_coords[e_head])
     self.mon_vector = monomer.cart_coords[tail] - monomer.cart_coords[head]
     self.moves = {1: [1, 0, 0],
                   2: [0, 1, 0],
                   3: [0, 0, 1],
                   4: [-1, 0, 0],
                   5: [0, -1, 0],
                   6: [0, 0, -1]}
     self.prev_move = 1
     # places the start monomer at the beginning of the chain
     self.molecule = start_monomer.copy()
     self.length = 1
     # create the chain
     self._create(self.monomer, self.mon_vector)
     # terminate the chain with the end_monomer
     self.n_units += 1
     end_mon_vector = end_monomer.cart_coords[e_tail] - \
                      end_monomer.cart_coords[e_head]
     self._create(end_monomer, end_mon_vector)
     self.molecule = Molecule.from_sites(self.molecule.sites)
Пример #3
0
def insert_g3testset(coll):
    for f in glob.glob("g*.txt"):
        print("Parsing " + f)
        for (m, charge, spin) in parse_file(f):
            try:
                clean_sites = []
                for site in m:
                    if Element.is_valid_symbol(site.specie.symbol):
                        clean_sites.append(site)
                clean_mol = Molecule.from_sites(clean_sites,
                                                charge=charge,
                                                spin_multiplicity=spin)
                xyz = XYZ(clean_mol)
                bb = BabelMolAdaptor.from_string(str(xyz), "xyz")
                pbmol = pb.Molecule(bb.openbabel_mol)
                smiles = pbmol.write("smi").split()[0]
                can = pbmol.write("can").split()[0]
                inchi = pbmol.write("inchi")
                svg = pbmol.write("svg")
                d = {"molecule": clean_mol.as_dict()}
                comp = clean_mol.composition
                d["pretty_formula"] = comp.reduced_formula
                d["formula"] = comp.formula
                d["composition"] = comp.as_dict()
                d["elements"] = list(comp.as_dict().keys())
                d["nelements"] = len(comp)
                d["charge"] = charge
                d["spin_multiplicity"] = spin
                d["smiles"] = smiles
                d["can"] = can
                d["inchi"] = inchi
                # d["names"] = get_nih_names(smiles)
                d["svg"] = svg
                d["xyz"] = str(xyz)
                d["tags"] = ["G305 test set"]
                coll.update(
                    {
                        "inchi": inchi,
                        "charge": charge,
                        "spin_multiplicity": spin
                    }, {"$set": d},
                    upsert=True)
            except Exception as ex:
                print("Error in {}".format(f))
                exc_type, exc_value, exc_traceback = sys.exc_info()
                traceback.print_exception(exc_type,
                                          exc_value,
                                          exc_traceback,
                                          limit=2,
                                          file=sys.stdout)
        print("{} parsed!".format(f))
Пример #4
0
    def fit(self, p: Molecule):
        """Order, rotate and transform `p` molecule according to the best match.

        Args:
            p: a `Molecule` object what will be matched with the target one.

        Returns:
            p_prime: Rotated and translated of the `p` `Molecule` object
            rmsd: Root-mean-square-deviation between `p_prime` and the `target`
        """

        inds, U, V, rmsd = self.match(p)

        # Translate and rotate `mol1` unto `mol2` using Kabsch algorithm.
        p_prime = Molecule.from_sites([p[i] for i in inds])
        for site in p_prime:
            site.coords = np.dot(site.coords, U) + V

        return p_prime, rmsd
Пример #5
0
    def fit(self, p: Molecule, ignore_warning=False):
        """Order, rotate and transform `p` molecule according to the best match.

        A `ValueError` will be raised when the total number of possible combinations
        become unfeasible (more than a million combinations).

        Args:
            p: a `Molecule` object what will be matched with the target one.
            ignore_warning: ignoring error when the number of combination is too large

        Returns:
            p_prime: Rotated and translated of the `p` `Molecule` object
            rmsd: Root-mean-square-deviation between `p_prime` and the `target`
        """

        inds, U, V, rmsd = self.match(p, ignore_warning=ignore_warning)

        p_prime = Molecule.from_sites([p[i] for i in inds])
        for site in p_prime:
            site.coords = np.dot(site.coords, U) + V

        return p_prime, rmsd
Пример #6
0
    def __init__(self, sites, ff_label=None, charges=None, velocities=None,
                 topologies=None):
        """

        Args:
            sites ([Site] or SiteCollection): A group of sites in a
                list or as a Molecule/Structure.
            ff_label (str): Site property key for labeling atoms of
                different types. Default to None, i.e., use
                site.species_string.
            charges ([q, ...]): Charge of each site in a (n,)
                array/list, where n is the No. of sites. Default to
                None, i.e., search site property for charges.
            velocities ([[vx, vy, vz], ...]): Velocity of each site in
                a (n, 3) array/list, where n is the No. of sites.
                Default to None, i.e., search site property for
                velocities.
            topologies (dict): Bonds, angles, dihedrals and improper
                dihedrals defined by site indices. Default to None,
                i.e., no additional topology. All four valid keys
                listed below are optional.
                {
                    "Bonds": [[i, j], ...],
                    "Angles": [[i, j, k], ...],
                    "Dihedrals": [[i, j, k, l], ...],
                    "Impropers": [[i, j, k, l], ...]
                }

        """
        if not isinstance(sites, SiteCollection):
            sites = Molecule.from_sites(sites)

        if ff_label:
            type_by_sites = sites.site_properties.get(ff_label)
        else:
            type_by_sites = [site.species_string for site in sites]
        # search for site property if not override
        if charges is None:
            charges = sites.site_properties.get("charge")
        if velocities is None:
            velocities = sites.site_properties.get("velocities")
        # validate shape
        if charges is not None:
            charge_arr = np.array(charges)
            assert charge_arr.shape == (len(sites),),\
                "Wrong format for charges"
            charges = charge_arr.tolist()
        if velocities is not None:
            velocities_arr = np.array(velocities)
            assert velocities_arr.shape == (len(sites), 3), \
                "Wrong format for velocities"
            velocities = velocities_arr.tolist()

        if topologies:
            topologies = {k: v for k, v in topologies.items()
                          if k in SECTION_KEYWORDS["topology"]}

        self.sites = sites
        self.ff_label = ff_label
        self.charges = charges
        self.velocities = velocities
        self.topologies = topologies
        self.type_by_sites = type_by_sites
        self.species = set(type_by_sites)
Пример #7
0
    def __init__(self, sites, ff_label=None, charges=None, velocities=None,
                 topologies=None):
        """

        Args:
            sites ([Site] or SiteCollection): A group of sites in a
                list or as a Molecule/Structure.
            ff_label (str): Site property key for labeling atoms of
                different types. Default to None, i.e., use
                site.species_string.
            charges ([q, ...]): Charge of each site in a (n,)
                array/list, where n is the No. of sites. Default to
                None, i.e., search site property for charges.
            velocities ([[vx, vy, vz], ...]): Velocity of each site in
                a (n, 3) array/list, where n is the No. of sites.
                Default to None, i.e., search site property for
                velocities.
            topologies (dict): Bonds, angles, dihedrals and improper
                dihedrals defined by site indices. Default to None,
                i.e., no additional topology. All four valid keys
                listed below are optional.
                {
                    "Bonds": [[i, j], ...],
                    "Angles": [[i, j, k], ...],
                    "Dihedrals": [[i, j, k, l], ...],
                    "Impropers": [[i, j, k, l], ...]
                }

        """
        if not isinstance(sites, (Molecule, Structure)):
            sites = Molecule.from_sites(sites)

        if ff_label:
            type_by_sites = sites.site_properties.get(ff_label)
        else:
            type_by_sites = [site.specie.symbol for site in sites]
        # search for site property if not override
        if charges is None:
            charges = sites.site_properties.get("charge")
        if velocities is None:
            velocities = sites.site_properties.get("velocities")
        # validate shape
        if charges is not None:
            charge_arr = np.array(charges)
            assert charge_arr.shape == (len(sites),),\
                "Wrong format for charges"
            charges = charge_arr.tolist()
        if velocities is not None:
            velocities_arr = np.array(velocities)
            assert velocities_arr.shape == (len(sites), 3), \
                "Wrong format for velocities"
            velocities = velocities_arr.tolist()

        if topologies:
            topologies = {k: v for k, v in topologies.items()
                          if k in SECTION_KEYWORDS["topology"]}

        self.sites = sites
        self.ff_label = ff_label
        self.charges = charges
        self.velocities = velocities
        self.topologies = topologies
        self.type_by_sites = type_by_sites
        self.species = set(type_by_sites)
Пример #8
0
    def __init__(
        self,
        site_collection: Union[SiteCollection, Site],
        color_scheme: str = "Jmol",
        radius_scheme: str = "uniform",
        cmap: str = "coolwarm",
        cmap_range: Optional[Tuple[float, float]] = None,
    ):
        """
        Create a legend for a given SiteCollection to choose how to
        display colors and radii for the given sites and the species
        on those sites.

        If a site has a "display_color" or "display_radius" site
        property defined, this can be used to manually override the
        displayed colors and radii respectively.

        Args:
            site_collection: SiteCollection or, for convenience, a
            single site can be provided and this will be converted
            into a SiteCollection
            color_scheme: choose how to color-code species, one of
            "Jmol", "VESTA", "accessible" or a scalar site property
            (e.g. magnetic moment) or a categorical/string site
            property (e.g. Wyckoff label)
            radius_scheme: choose the radius for a species, one of
            ...
            cmap: only used if color_mode is set to a scalar site
            property, defines the matplotlib color map to use, by
            default is blue-white-red for negative to postive values
            cmap_range: only used if color_mode is set to a scalar site
            property, defines the minimum and maximum values of the
            color scape
        """

        if isinstance(site_collection, Site):
            site_collection = Molecule.from_sites([site_collection])

        site_prop_types = self.analyze_site_props(site_collection)

        self.allowed_schemes = (["VESTA", "Jmol", "accessible"] +
                                site_prop_types.get("scalar", []) +
                                site_prop_types.get("categorical", []))

        if color_scheme not in self.allowed_schemes:
            warnings.warn(f"Color scheme {color_scheme} not available, "
                          f"falling back to {self.default_scheme}.")
            color_scheme = self.default_scheme

        # if color-coding by a scalar site property, determine minimum and
        # maximum values for color scheme, will default to be symmetric
        # about zero
        if color_scheme in site_prop_types.get("scalar",
                                               []) and not cmap_range:
            props = np.array(site_collection.site_properties[color_scheme])
            prop_max = max([abs(min(props)), max(props)])
            prop_min = -prop_max
            cmap_range = (prop_min, prop_max)

        el_colors = EL_COLORS.copy()
        el_colors.update(
            self.generate_accessible_color_scheme_on_the_fly(site_collection))

        self.categorical_colors = self.generate_categorical_color_scheme_on_the_fly(
            site_collection, site_prop_types)

        self.el_colors = el_colors
        self.site_prop_types = site_prop_types
        self.site_collection = site_collection
        self.color_scheme = color_scheme
        self.radius_mode = radius_scheme
        self.cmap = cmap
        self.cmap_range = cmap_range
Пример #9
0
def site_layout(symmetrizer: StructureSymmetrizer):
    columns = []
    distance_cutoff = 2.0
    angle_cutoff = 0.3
    cnn = CrystalNN()
    nn_info = cnn.get_all_nn_info(structure=symmetrizer.structure)

    for name, site in symmetrizer.sites.items():
        wyckoff_contents = []
        data = dict()
        data["Site Symmetry"] = site.site_symmetry
        data["Wyckoff Letter"] = site.wyckoff_letter
        wyckoff_contents.append(html.Label(f"{name}", className="mpc-label"))
        site_data = []
        repr_idx = site.equivalent_atoms[0]
        for idx in site.equivalent_atoms:
            coords = symmetrizer.structure[idx].frac_coords
            site_data += [(pretty_frac_format(coords[0]),
                           pretty_frac_format(coords[1]),
                           pretty_frac_format(coords[2]))]

        # lgf = LocalGeometryFinder()
        # lgf.setup_structure(structure=symmetrizer.structure)

        # se = lgf.compute_structure_environments(
        #     maximum_distance_factor=distance_cutoff + 0.01)
        # strategy = SimplestChemenvStrategy(
        #     distance_cutoff=distance_cutoff, angle_cutoff=angle_cutoff
        # )
        # lse = LightStructureEnvironments.from_structure_environments(
        #     strategy=strategy, structure_environments=se)

    # represent the local environment as a molecule

        mol = Molecule.from_sites(
            [symmetrizer.structure[repr_idx]] + [i["site"] for i in nn_info[repr_idx]]
        )
        mol = mol.get_centered_molecule()
        mg = MoleculeGraph.with_empty_graph(molecule=mol)
        for i in range(1, len(mol)):
            mg.add_edge(0, i)

        view = html.Div(
            [
                StructureMoleculeComponent(
                    struct_or_mol=mg,
                    disable_callbacks=True,
                    id=f"{symmetrizer.structure.composition.reduced_formula}_site_{repr_idx}",
                    scene_settings={"enableZoom": False, "defaultZoom": 0.6},
                )._sub_layouts["struct"]
            ],
            style={"width": "300px", "height": "300px"},
        )

        # env = lse.coordination_environments[repr_idx]
        # all_ce = AllCoordinationGeometries()
        # co = all_ce.get_geometry_from_mp_symbol(env[0]["ce_symbol"])
        # name = co.name

        data.update(
            {
                # "Environment": name,
                # "IUPAC Symbol": co.IUPAC_symbol_str,
                "Structure": view,
            }
        )

        wyckoff_contents.append(get_data_list(data))
        wyckoff_contents.append(Reveal(get_table(site_data),
                                       title=f"Positions ({len(site_data)})",
                                       id=f"{name}-positions"))
        columns.append(Column(html.Div(wyckoff_contents)))
    _layout = Columns(columns)

    return Columns([Column([H4("Sites"), html.Div(_layout)])])