Make atom_columns of XYZ load_one more hackable
Make it easier for the user to change how a column is parsed. For example, change the units of coordinates from angstrom to bohr.
I'll mention here how this can be accomplished at the time of writing. We can see from there how to simplify it.
from iodata import load_one
from iodata.formats.xyz import DEFAULT_ATOM_COLMNS
ATOM_COLUMNS = [
DEFAULT_ATOM_COLUMNS[0],
("atcoords", None, (3,), float,
(lambda word: float(word)),
(lambda value: "{:15.10f}".format(value)))
]
data = load_one("example_in_bohr.xyz", atom_columns=ATOM_COLUMNS)
The main limitation of the current approach of defining the columns is that everything must be repeated when one is only interested in just changing one little detail. Here is an attempt to get around this...
We can define the columns through dictionaries, in which it is easier to override certain fields, while the rest is kept to the default. We can put this in iodata.xyz:
DEFAULT_COLUMN_SETTINGS = {
"atnums", {
"dictkey": None,
"shape": (),
"type": int,
"parse": (lambda word: int(word) if word.isdigit() else sym2num[word.title()]),
"format": (lambda atnum: "{:2s}".format(num2sym[atnum])),
"unit": angstrom,
}
"atcoords", {
"dictkey": None,
"shape": (3,),
"type": float,
"parse": (lambda word: float(word)),
"format": (lambda value: format(value, "15.10f")),
"unit": angstrom,
}
}
DEFAULT_COLUMNS = ["atnums", "atcoords"]
We can add optional arguments for load_one and dump_one in iodata.xyz to override these two defaults. For the case of column_settings, dictionary updates can be used, such that it becomes possible to modify just one setting in the defaults, without having to repeat everything. This would allow switching units for XYZ files as follows:
from iodata import load_one
data = load_one("example_in_bohr.xyz", column_settings={"atcoords": {"unit": 1}})
@FarnazH What do you think?