diff --git a/qcelemental/models/molecule.py b/qcelemental/models/molecule.py index 5944001f..2575db2a 100644 --- a/qcelemental/models/molecule.py +++ b/qcelemental/models/molecule.py @@ -737,9 +737,11 @@ def to_string( # type: ignore *, atom_format: str = None, ghost_format: str = None, + post_format: str = None, width: int = 17, prec: int = 12, return_data: bool = False, + use_masses: bool = False, ): r"""Returns a string that can be used by a variety of programs. @@ -754,9 +756,11 @@ def to_string( # type: ignore units=units, atom_format=atom_format, ghost_format=ghost_format, + post_format=post_format, width=width, prec=prec, return_data=return_data, + use_masses=use_masses, ) def get_hash(self): diff --git a/qcelemental/molparse/to_string.py b/qcelemental/molparse/to_string.py index f95e7a4b..e2b2d31b 100644 --- a/qcelemental/molparse/to_string.py +++ b/qcelemental/molparse/to_string.py @@ -14,9 +14,11 @@ def to_string( *, atom_format: str = None, ghost_format: str = None, + post_format: str = None, width: int = 17, prec: int = 12, return_data: bool = False, + use_masses: bool = False, ) -> Union[str, Tuple[str, Dict]]: r"""Format a string representation of QM molecule. @@ -45,6 +47,9 @@ def to_string( ghost_format General format is ``'@{elem}'``. Like `atom_format`, but this formatter is used when `real=False`. To suppress ghost atoms, use `ghost_format=''`. + post_format + General format is ``''``. Like `atom_format`, but this formatter can + add text beyond z-coord in element-x-y-z. Uncommon to call directly. width Field width for formatting coordinate float. prec @@ -53,6 +58,10 @@ def to_string( Whether to return dictionary with additional info from the molrec that's not expressible in the string but may be of interest to the QC program. Note that field names are in QCSchema, not molrec, language. + use_masses + Write mass data from `molrec` to string. Most commonly, masses are + omitted from format so that CMS program internal mass data can be used. + Available for `dtype`: nwchem Returns ------- @@ -223,10 +232,12 @@ def to_dict(self) -> Dict: atom_format = "{elem}{elbl}" ghost_format = "bq{elem}{elbl}" + if use_masses: + post_format = " mass {mass}" # TODO handle which units valid umap = {"bohr": "bohr", "angstrom": "angstroms", "nm": "nanometers", "pm": "picometers"} - atoms = _atoms_formatter(molrec, geom, atom_format, ghost_format, width, prec, 2) + atoms = _atoms_formatter(molrec, geom, atom_format, ghost_format, width, prec, 2, post_format=post_format) first_line = f"""geometry units {umap.get(units.lower())}""" # noautosym nocenter # no reorienting input geometry @@ -471,7 +482,7 @@ def to_dict(self) -> Dict: return smol_ret -def _atoms_formatter(molrec, geom, atom_format, ghost_format, width, prec, sp, xyze=False): +def _atoms_formatter(molrec, geom, atom_format, ghost_format, width, prec, sp, *, xyze=False, post_format=""): """Format a list of strings, one per atom from `molrec`.""" nat = geom.shape[0] @@ -500,6 +511,11 @@ def _atoms_formatter(molrec, geom, atom_format, ghost_format, width, prec, sp, x atom.append(nuc) atom.extend([fxyz.format(x, width=width, prec=prec) for x in geom[iat]]) + + if post_format: + post = post_format.format(**atominfo) + atom.append(post) + if xyze: atom.append(atom.pop(0).rstrip()) atoms.append(sp.join(atom)) @@ -507,7 +523,7 @@ def _atoms_formatter(molrec, geom, atom_format, ghost_format, width, prec, sp, x return atoms -def formula_generator(elem): +def formula_generator(elem: List[str]) -> str: """Return simple chemical formula from element list `elem`. >>> formula_generator(['C', 'Ca', 'O', 'O', 'Ag'] diff --git a/qcelemental/tests/test_molparse_to_string.py b/qcelemental/tests/test_molparse_to_string.py index c9974266..ce7005e1 100644 --- a/qcelemental/tests/test_molparse_to_string.py +++ b/qcelemental/tests/test_molparse_to_string.py @@ -96,6 +96,13 @@ bqH {au2:.12f} 0.000000000000 0.000000000000 H_other -{au2:.12f} 0.000000000000 0.000000000000 +end +""", + "ans2_nwchem_au_mass": f"""geometry units bohr +Co 0.000000000000 0.000000000000 0.000000000000 mass 58.93319429 +bqH 2.000000000000 0.000000000000 0.000000000000 mass 1.00782503223 +H_other -2.000000000000 0.000000000000 0.000000000000 mass 1.00782503223 + end """, "ans2_madness_au": f"""geometry @@ -252,6 +259,7 @@ (("subject2", {"dtype": "xyz", "units": "angstrom", "ghost_format": ""}), "ans2c_ang"), (("subject2", {"dtype": "cfour", "units": "angstrom"}), "ans2_cfour_ang"), (("subject2", {"dtype": "nwchem", "units": "angstrom"}), "ans2_nwchem_ang"), + (("subject2", {"dtype": "nwchem", "units": "bohr", "use_masses": True}), "ans2_nwchem_au_mass"), (("subject2", {"dtype": "madness", "units": "bohr"}), "ans2_madness_au"), (("subject2", {"dtype": "madness", "units": "angstrom"}), "ans2_madness_ang"), (("subject2", {"dtype": "mrchem", "units": "bohr"}), "ans2_mrchem_au"),