def _parse_name_type(mol_dict: Settings) -> None: """Set the ``"name"`` and ``"type"`` keys in **mol_dict**. The new values of ``"name"`` and ``"type"`` depend on the value of ``mol_dict["mol"]``. Parameters ---------- mol_dict : |plams.Settings|_ A Settings instance containing the ``"mol"`` key. ``mol_dict["mol"]`` is exp Raises ------ TypeError Raised ``mol_dict["mol"]`` is an instance of neither :class:`str`, :class:`Molecule` nor :class:`mol`. """ mol = mol_dict.mol if isinstance(mol, str): if isfile(mol): # mol is a file mol_dict.type = mol.rsplit('.', 1)[-1] mol_dict.name = basename(mol.rsplit('.', 1)[0]) elif isdir(mol): # mol is a directory mol_dict.type = 'folder' mol_dict.name = basename(mol) else: # mol is (probably; hopefully?) a SMILES string i = 1 + len(mol_dict.path) if 'path' in mol_dict else 0 mol_dict.type = 'smiles' mol_dict.mol = mol[i:] mol_dict.name = santize_smiles(mol_dict.mol) elif isinstance(mol, Molecule): # mol is an instance of plams.Molecule mol_dict.type = 'plams_mol' if not mol.properties.name: mol_dict.name = Chem.MolToSmiles(Chem.RemoveHs(molkit.to_rdmol(mol)), canonical=True) else: mol_dict.name = mol.properties.name elif isinstance(mol, Chem.rdchem.Mol): # mol is an instance of rdkit.Chem.Mol mol_dict.type = 'rdmol' mol_dict.name = Chem.MolToSmiles(Chem.RemoveHs(mol), canonical=True) else: raise TypeError(f"mol_dict['mol'] expects an instance of 'str', 'Molecule' or 'Mol'; " f"observed type: '{mol.__class__.__name__}'")
def validate_mol(args: Sequence[Union[Any, Settings]], mol_type: str, path: Optional[str] = None, validate_path: bool = True) -> None: r"""Validate the ``"input_ligands"``, ``"input_cores"`` and ``"input_qd"`` blocks in the input. Performs an inpalce update of **args**. Examples -------- An example using a list of .xyz files as input .. code:: python # A list of .xyz files >>> args1 = ['mol1.xyz', 'mol2.xyz'] >>> mol_type = 'input_ligands' >>> validate_mol(args1, mol_type) >>> print(args1[0], '\n', args1[1]) # doctest: +SKIP is_core: False mol: /path/to/my/current/working/dir/mol1.xyz name: mol1 path: /path/to/my/current/working/dir type: smiles is_core: False mol: /path/to/my/current/working/dir/mol2.xyz name: mol2 path: /path/to/my/current/working/dir type: smiles Another example using a list of .pdb-containing dictionaries as input .. code :: python # A list of Settings instances with .xyz files >>> print(args2) # doctest: +SKIP [mol3.pdb: guess_bonds: True mol4.pdb: guess_bonds: True ] >>> mol_type = 'input_ligands' >>> path = '/path/to/custom/working/dir' >>> validate_mol(args2, mol_type, path) # doctest: +SKIP >>> print(args2[0], '\n', args2[1]) # doctest: +SKIP guess_bonds: True is_core: True mol: /path/to/custom/working/dir/mol3.pdb name: mol3 path: /path/to/custom/working/dir type: smiles guess_bonds: True is_core: True mol: /path/to/custom/working/dir/mol4.pdb name: mol4 path: /path/to/custom/working/dir type: smiles Parameters ---------- args : |list|_ [|plams.Settings|_] A list of input molecules. Accepts strings, PLAMS molecules and RDKit molecules. Additional arguments can be provided by putting above-mentioned molecules in a dictionary. mol_type : str The type of molecule. Accepted values are ``"input_ligands"`` and ``"input_cores"``. path : str Optional: The path to the molecule-containing directory. Raises ------ FileNotFoundError Raised if **path** cannot be found. NotADirectoryError Raised if **path** is not a directory. ValueError Raised if the **mol_type** parameter is neither ``"input_cores"`` nor ``"input_ligands"``. SchemaError Raised if invalid input settings are found in while validating **args**. """ # Validate arguments is_core = _check_core(mol_type) is_qd = _check_qd(mol_type) if validate_path: _path = validate_path_func(path) else: _path = path for i, dict_ in enumerate(args): if not isinstance(dict_, dict): # No optional arguments provided mol = dict_ mol_dict = Settings({'path': _path, 'is_core': is_core, 'is_qd': is_qd}) else: # Optional arguments have been provided: parse and validate them if dict_.get('parsed'): continue mol, mol_dict = next(iter(dict_.items())) mol_dict.setdefault('is_core', is_core) mol_dict.setdefault('is_qd', is_qd) mol_dict = mol_schema.validate(mol_dict) mol_dict.setdefault('path', _path) if isinstance(mol, str) and not isfile(mol): mol = join(mol_dict.path, mol) mol_dict.mol = mol mol_dict.parsed = True _parse_name_type(mol_dict) args[i] = mol_dict