Source code for tad_mctc.io.write.writer
# This file is part of tad-mctc.
#
# SPDX-Identifier: Apache-2.0
# Copyright (C) 2024 Grimme Group
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
I/O Write: General
==================
General writer for files to a path.
"""
from __future__ import annotations
from pathlib import Path
from ...typing import Any, PathLike, Tensor
from .turbomole import write_turbomole_fileobj
from .xyz import write_xyz_fileobj
__all__ = ["write"]
[docs]
def write(
filepath: PathLike,
numbers: Tensor,
positions: Tensor,
ftype: str | None = None,
mode: str = "w",
overwrite: bool = False,
**kwargs: Any,
) -> None:
"""
Write the structure to the given file path.
Parameters
----------
filepath : PathLike
File path to write the structure to.
numbers : Tensor
Tensor of atomic numbers.
positions : Tensor
Tensor of atomic positions (shape: ``(nat, 3)`` in atomic units).
ftype : str | None, optional
File type. If None, the file extension is used to infer the type.
mode : str, optional
Mode in which the file is opened. Defaults to ``"w"``.
overwrite : bool, optional
If False and the file exists, a FileExistsError is raised.
**kwargs : Any
Additional arguments for the specific writer.
Raises
------
FileExistsError
If the file exists and overwrite is False.
ValueError
If the file type is unknown.
NotImplementedError
If the file type is recognized but no writer is available.
"""
path = Path(filepath)
if path.exists() and not overwrite:
raise FileExistsError(
f"The file '{filepath}' already exists. "
"If you want to overwrite it, set `overwrite=True`."
)
# Infer file type from file extension if not provided.
if ftype is None and path.suffix:
ftype = path.suffix.casefold()[1:]
fname = path.name.casefold()
if ftype in ("xyz", "log"):
writer = write_xyz_fileobj
elif ftype in ("qm9",):
raise NotImplementedError(
f"Filetype '{ftype}' (QM9 XYZ) recognized but no writer available."
)
elif ftype in ("tmol", "tm", "turbomole") or fname == "coord":
writer = write_turbomole_fileobj
elif ftype in ("mol", "sdf", "gen", "pdb"):
raise NotImplementedError(
f"Filetype '{ftype}' recognized but no writer available."
)
elif ftype in ("qchem",):
raise NotImplementedError(
f"Filetype '{ftype}' (Q-Chem) recognized but no writer available."
)
elif ftype in ("poscar", "contcar", "vasp", "crystal") or fname in (
"poscar",
"contcar",
"vasp",
):
raise NotImplementedError(
f"Filetype '{ftype}' (VASP/CRYSTAL) recognized but no writer available."
)
elif ftype in ("ein", "gaussian"):
raise NotImplementedError(
f"Filetype '{ftype}' (Gaussian) recognized but no writer available."
)
elif ftype in ("json", "qcschema"):
raise NotImplementedError(
f"Filetype '{ftype}' (QCSchema) recognized but no writer available."
)
else:
raise ValueError(f"Unknown filetype '{ftype}' in '{fname}'.")
# Open the file and call the selected writer.
with open(path, mode=mode, encoding="utf-8") as fileobj:
writer(fileobj, numbers, positions, **kwargs)