reciprocalspaceship
reciprocalspaceship copied to clipboard
A `rs.cifdump` utility?
In the matchmaps
quickstart guide, I recommend using the rs.mtzdump
utility to figure out what the columns in your dataset are called. However, now that matchmaps
also supports cif
inputs, I'm realizing that there is no equivalent command-line utility for such files! It seems to me that, if we're deciding that we want to support cifs, that we should fully commit to that.
There is also no function for writing out a cif file, but that feels less urgent to me. Others may disagree.
for future reference, I did this the other day by mostly a simple find and replace on rs.mtzdump. I asked @LuisA92 to make a corresponding fix to rs.read_cif() to better handle multi-block sfCIFs.
#!/usr/bin/env python
"""
Summarize the contents of an sfCIF file.
Examples
--------
In order to summarize contents of file.cif::
> rs.cifdump file.cif
If you would like to interactively inspect file.cif in an IPython
shell, use the "--embed" argument::
> rs.cifdump file.cif --embed
If multiple CIF files are listed, they will be summarized sequentially,
and can be accessed in an IPython shell as a dictionary called `cifs`::
> rs.cifdump file1.cif file2.cif file3.cif --embed
Usage Details
-------------
"""
import argparse
import pandas as pd
import reciprocalspaceship as rs
# If matplotlib is available, use pylab to setup IPython environment
try:
from pylab import *
except:
pass
def parse_arguments():
"""Parse commandline arguments"""
parser = argparse.ArgumentParser(
formatter_class=argparse.RawTextHelpFormatter, description=__doc__
)
# Required arguments
parser.add_argument("cif", nargs="+", help="cif file(s) to summarize")
# Optional arguments
parser.add_argument(
"--embed",
action="store_true",
help=(
"cif file(s) will be summarized, and an IPython " "shell will be started"
),
)
parser.add_argument(
"-p",
"--precision",
type=int,
default=3,
help="Number of significant digits to output for floats",
)
return parser
def summarize(ds, precision):
"""Summarize contents of cif file"""
with pd.option_context("display.precision", precision):
print(f"Spacegroup: {ds.spacegroup.short_name()}")
print(f"Extended Hermann-Mauguin name: {ds.spacegroup.xhm()}")
print(
(
f"Unit cell dimensions: {ds.cell.a:.3f} {ds.cell.b:.3f} {ds.cell.c:.3f} "
f"{ds.cell.alpha:.3f} {ds.cell.beta:.3f} {ds.cell.gamma:.3f}"
)
)
print(f"\nds.head():\n\n{ds.head()}")
print(f"\nds.describe():\n\n{ds.describe()}")
print(f"\nds.dtypes:\n\n{ds.dtypes}")
return
def main():
# Parse commandline arguments
parser = parse_arguments()
args = parser.parse_args()
if len(args.cif) == 1:
cif = rs.read_cif(args.cif[0])
summarize(cif, args.precision)
else:
cifs = dict(zip(args.cif, map(rs.read_cif, args.cif)))
for key, value in cifs.items():
print(f"cif file: {key}\n")
summarize(value, args.precision)
print(f"{'-'*50}")
# Begin IPython shell
if args.embed:
from IPython import embed
bold = "\033[1m"
end = "\033[0m"
if "cifs" in locals():
header = f"rs.DataSets stored in {bold}cifs{end} dictionary"
else:
header = f"rs.DataSet stored as {bold}cif{end}"
print()
embed(colors="neutral", header=header)
return
if __name__ == "__main__":
parser = main()
Closed by #283