Пример #1
0
def string_array_to_molecule(parser_fun, file_name, mol=None):
    """
    Convert a Numpy string array like:

    [['C', '-1.487460', '-0.028670', '-0.000060'],
    ['O', '0.376340', '0.028670', '-0.000060'],
    ['H', '-1.818910', '-1.067060', '-0.000060'],
    ['H', '-1.866470', '0.473700', '0.889930'],
    ['H', '-1.866470', '0.473700', '-0.890040'],
    ['H', '0.756720', '-0.950010', '-0.000060']]

    To a plams ``Molecule``.
    """
    string_array_to_float = np.vectorize(float)
    mols = parse_file(parser_fun, file_name).asList()
    last_mol = np.array(mols[-1])
    elems = last_mol[:, 0]
    coords = string_array_to_float(last_mol[:, 1:])
    if mol:
        if len(coords) == len(mol):
            plams_mol = mol
            for i in range(len(plams_mol)):
                plams_mol.atoms[i].coords = tuple(
                    [float(c) for c in coords[i]])
        else:
            raise RuntimeError('Output molecule does not match input molecule')
    else:
        plams_mol = Molecule()
        for e, c in zip(elems, coords):
            plams_mol.add_atom(Atom(symbol=e, coords=tuple(c)))
    return plams_mol
Пример #2
0
def string_array_to_molecule(parser_fun, file_name, mol=None):
    """
    Convert a Numpy string array like:

    [['C', '-1.487460', '-0.028670', '-0.000060'],
    ['O', '0.376340', '0.028670', '-0.000060'],
    ['H', '-1.818910', '-1.067060', '-0.000060'],
    ['H', '-1.866470', '0.473700', '0.889930'],
    ['H', '-1.866470', '0.473700', '-0.890040'],
    ['H', '0.756720', '-0.950010', '-0.000060']]

    To a plams ``Molecule``.
    """
    string_array_to_float = np.vectorize(float)
    mols = parse_file(parser_fun, file_name).asList()
    last_mol = np.array(mols[-1])
    elems = last_mol[:, 0]
    coords = string_array_to_float(last_mol[:, 1:])
    if mol:
        if len(coords) == len(mol):
            plams_mol = mol
            for i in range(len(plams_mol)):
                plams_mol.atoms[i].coords = tuple([float(c) for c in coords[i]])
        else:
            raise RuntimeError('Output molecule does not match input molecule')
    else:
        plams_mol = Molecule()
        for e, c in zip(elems, coords):
            plams_mol.add_atom(Atom(symbol=e, coords=tuple(c)))
    return plams_mol
Пример #3
0
def tuplesXYZ_to_plams(xs):
    """ Transform a list of namedTuples to a Plams molecule """
    plams_mol = Molecule()
    for at in xs:
        symb = at.symbol
        cs = at.xyz
        plams_mol.add_atom(Atom(symbol=symb, coords=tuple(cs)))

    return plams_mol
Пример #4
0
def tuplesXYZ_to_plams(xs):
    """ Transform a list of namedTuples to a Plams molecule """
    plams_mol = Molecule()
    for at in xs:
        symb = at.symbol
        cs = at.xyz
        plams_mol.add_atom(Atom(symbol=symb, coords=tuple(cs)))

    return plams_mol
Пример #5
0
def geometry_to_molecule(geometry):
    """
    Convert a list of XYZ coordinates to a Molecule object
    """
    mol = Molecule()

    for i in range(0, len(geometry)):
        mol.add_atom(
            Atom(symbol=geometry[i][0],
                 coords=(geometry[i][1], geometry[i][2], geometry[i][3])))

    return mol
Пример #6
0
def parse_molecule_traj(file_traj: PathLike) -> Molecule:
    """Read Molecules from the job_name.traj file."""
    mols = manyXYZ(file_traj)
    # Last geometry corresponds to the optimized structure
    opt_mol = mols[-1]

    plams_mol = Molecule()
    for at in opt_mol:
        symb = at.symbol
        cs = at.xyz
        plams_mol.add_atom(Atom(symbol=symb, coords=tuple(cs)))

    return plams_mol
Пример #7
0
def supstitution_symmetry(mol):
    """Returns atomic symbols of substituted atoms (or first conection of non diatomic ligand).

    Writes type of substitution symetry at the molecular properties

    Parameters
    ----------
    mol : |plams.Molecule|
        A PLAMS molecule

    Returns
    -------
    str
        Type of subsymmetry

    """
    dataframe, type_of_symetry = [], []
    ligand_identity = mol.properties.ligID

    # Defining C atoms conected to substituents and making Molecule object (cmol) out of them
    catoms = mol.properties.coords_other_arrays
    cmol = Molecule()
    for at in catoms:
        cmol.add_atom(mol.closest_atom(at))

    # If substitution is linear, simple combinations without repetition can be applied
    if len(ligand_identity) <= 2:
        if len(ligand_identity) == 1:
            logger.warning(
                "One does not simply ask for subsymmetry of one atom!")
            return
        elif len(ligand_identity) == 0:
            logger.warning(
                "One does not simply ask for subsymmetry of no atom")
            return
        else:
            subsymmetry = 'linear'
    else:
        # Getting non zero row indices from data frame - defines symmetry type

        dataframe = get_symmetry(cmol, decimals=2)
        type_of_symetry = np.unique(dataframe.to_numpy().nonzero()[0])

        # Assign type of symetry and atomic symbols
        if list(type_of_symetry) == [0, 1, 8, 9]:
            subsymmetry = 'D2h'
        else:
            logger.warning("Subsymmetry is not recognized")
            return

    return subsymmetry
Пример #8
0
def _test_distribute(mol: Molecule, symbol: str, **kwargs) -> Molecule:
    """Helper function for :func:`test_distribute`."""
    if not isinstance(mol, Molecule):
        mol = Molecule(mol)

    _idx_in = [i for i, at in enumerate(mol) if at.symbol == symbol]
    idx_in = np.fromiter(_idx_in, count=len(_idx_in), dtype=int)
    idx_out = distribute_idx(mol, idx_in, **kwargs)

    a = symbol
    b = 'I' if a != 'I' else 'Br'
    mol2 = Molecule()
    for i, at in enumerate(mol):
        if at.symbol != symbol:
            continue
        symbol_new = a if i not in idx_out else b
        mol2.add_atom(Atom(symbol=symbol_new, coords=at.coords, mol=mol2))
    return mol2
Пример #9
0
def _parse_ion(ion: Molecule | str | int) -> Tuple[Molecule, Atom]:
    """Interpret and parse the **ion** argument in :func:`.get_xyn`.

    Construct and return a new :math:`XY_{n=0}` molecule and the atom :math:`X` itself.
    If **ion** is a polyatomic ion then :math:`XY_{n=0}` is a copy of **ion** and :math:`X`
    is the first atom with a non-zero charge.

    Parameters
    ----------
    ion : |str|_, |int|_ or |plams.Molecule|_
        An ion (:math:`X`), be it mono- (*e.g.* atomic number or symbol) or poly-atomic.

    Returns
    -------
    |plams.Molecule|_ and |plams.Atom|_
        A :math:`XY_{n=0}` molecule and the the charged atom from :math:`X`.

    Raises
    ------
    MoleculeError
        Raised if ion is an instance of :math:`Molecule` but does not contain any charged atoms.

    """
    if isinstance(ion, Molecule):
        XYn = ion.copy()
        for i, at in enumerate(XYn, 1):
            if not at.properties.charge:
                continue

            # Found an atom with non-zero charge; return a copy
            ret = XYn.copy()
            return ret, ret[i]

        raise MoleculeError(
            "No atoms were found in 'ion' with a non-zero charge")

    else:
        # Ion is an atomic number or symbol
        X = Atom(atnum=to_atnum(ion))
        XYn = Molecule()
        XYn.add_atom(X)
        return XYn, X
Пример #10
0
def from_rdmol(rdkit_mol, confid=-1):
    """
    Translate an RDKit molecule into a PLAMS molecule type.

    :parameter rdkit_mol: RDKit molecule
    :parameter int confid: conformer identifier from which to take coordinates
    :type rdkit_mol: rdkit.Chem.Mol
    :return: a PLAMS molecule
    :rtype: plams.Molecule

    """
    if isinstance(rdkit_mol, Molecule):
        return rdkit_mol
    # Create plams molecule
    plams_mol = Molecule()
    total_charge = 0
    try:
        Chem.Kekulize(rdkit_mol)
    except:
        pass
    conf = rdkit_mol.GetConformer(id=confid)
    for rd_atom in rdkit_mol.GetAtoms():
        pos = conf.GetAtomPosition(rd_atom.GetIdx())
        ch = rd_atom.GetFormalCharge()
        pl_atom = Atom(rd_atom.GetAtomicNum(),
                       coords=(pos.x, pos.y, pos.z),
                       charge=ch)
        if rd_atom.GetPDBResidueInfo():
            pl_atom.properties.pdb_info = get_PDBResidueInfo(rd_atom)
        plams_mol.add_atom(pl_atom)
        total_charge += ch
    for bond in rdkit_mol.GetBonds():
        at1 = plams_mol.atoms[bond.GetBeginAtomIdx()]
        at2 = plams_mol.atoms[bond.GetEndAtomIdx()]
        plams_mol.add_bond(Bond(at1, at2, bond.GetBondTypeAsDouble()))
    plams_mol.charge = total_charge
    for propname in rdkit_mol.GetPropNames():
        plams_mol.properties[propname] = rdkit_mol.GetProp(propname)
    return plams_mol
Пример #11
0
def create_molecule(name, r=2.25):
    mol = Molecule()
    mol.add_atom(Atom(symbol='Ba', coords=(0, 0, 0)))
    mol.add_atom(Atom(symbol='F', coords=(0, 0, r)))

    return mol
    AtomNamesList = kf.read('Molecule', 'AtomicNumbers')
    AtomSymbolList = kf.read('Molecule', 'AtomSymbols')
    Coords = Units.convert(kf.read('Molecule', 'Coords'), 'Bohr', 'Angstrom')
    energy = Units.convert(kf.read('AMSResults', 'Energy'), 'au',
                           'kcal/mol')  # 1 Hartree = 1 a.u

    npCoords = np.array(Coords)
    npCoords = npCoords.reshape(int(npCoords.size / 3), 3)

    mol = Molecule()
    AtomSymbolList = AtomSymbolList.strip()
    SymbolList = list(AtomSymbolList.split())
    SymbolList = [s.strip() for s in SymbolList]

    for at, coord in zip(SymbolList, npCoords):
        mol.add_atom(Atom(symbol=at, coords=coord))

    # Keep in mind, that coordinate indexing starts from 0;
    pes_at1 = Atom(symbol=SymbolList[pes_atom1_id - 1],
                   coords=npCoords[pes_atom1_id - 1])
    pes_at2 = Atom(symbol=SymbolList[pes_atom2_id - 1],
                   coords=npCoords[pes_atom2_id - 1])
    pes_bond = Bond(pes_at1, pes_at2)
    line = [(pes_atom1_id, pes_atom2_id), direction, PESnum,
            pes_bond.length(), energy]
    data.append(line)

column_names = [
    'id', 'str/sq', 'PES', 'Bond length [A]', 'Energy [kcal / mol]'
]
table_data = pd.DataFrame(data, columns=column_names)
Пример #13
0
def run_ff_anionic(mol: Molecule, anchor: Atom, s: Settings) -> None:
    r"""Assign neutral parameters to an anionic species (*e.g.* carboxylate).

    Consists of 4 distinct steps:

    * **mol** is capped with a proton: *e.g.*
      :math:`RCO_2^- \rightarrow RCO_2H`.
    * Parameters are guessed for both fragments (using MATCH_) and then recombined into **mol**.
    * The capping proton is removed again.
    * The atomic charge of **anchor** is adjusted such that
      the total moleculair charge becomes zero.

    Performs an inplace update of **mol**.

    .. _MATCH: http://brooks.chem.lsa.umich.edu/index.php?page=match&subdir=articles/resources/software

    Parameters
    ----------
    mol : :class:`Molecule<scm.plams.mol.molecule.Molecule>`
        A cationic molecule.

    anchor : :class:`Atom<scm.plams.mol.atom.Atom>`
        The atom in **mol** with the formal negative charge.

    s : :class:`Settings<scm.plams.core.settings.Settings>`
        The job Settings to-be passed to :class:`MATCHJob<nanoCAT.ff.match_job.MATCHJob>`.

    See Also
    --------
    :func:`run_match_job()<nanoCAT.ff.ff_assignment.run_match_job>`
        Assign atom types and charges to **mol** based on the results of MATCH_.

    :func:`run_ff_cationic()<nanoCAT.ff.ff_cationic.run_ff_cationic>`
        Assign neutral parameters to a cationic species (*e.g.* ammonium).

    """  # noqa
    if anchor not in mol:
        raise MoleculeError("Passed 'anchor' is not part of 'mol'")
    anchor.properties.charge = 0

    # Cap the anion with a proton
    mol_with_h = add_Hs(mol)
    _cap_h = mol_with_h[-1]
    cap_h = Atom(atnum=_cap_h.atnum,
                 coords=_cap_h.coords,
                 mol=mol,
                 settings=mol[1].properties.copy())

    cap_h.properties.pdb_info.IsHeteroAtom = False
    cap_h.properties.pdb_info.Name = 'Hxx'
    mol.add_atom(cap_h)
    mol.add_bond(Bond(anchor, cap_h, mol=mol))

    # Guess parameters and remove the capping proton
    run_match_job(mol, s)
    mol.delete_atom(cap_h)

    # Set the total charge of the system to 0
    anchor.properties.charge_float -= sum(at.properties.charge_float
                                          for at in mol)
    return None