diff --git a/docs/api/cifdump.rst b/docs/api/cifdump.rst
new file mode 100644
index 00000000..52f40503
--- /dev/null
+++ b/docs/api/cifdump.rst
@@ -0,0 +1,4 @@
+.. _cifdump:
+
+.. autoprogram:: reciprocalspaceship.commandline.cifdump:parse_arguments()
+ :prog: rs.cifdump
diff --git a/docs/api/index.rst b/docs/api/index.rst
index 72258505..dbfcca37 100644
--- a/docs/api/index.rst
+++ b/docs/api/index.rst
@@ -95,6 +95,7 @@ Commandline tools to support common use cases.
:hidden:
mtzdump
+ cifdump
.. Manual table for commandline tools
@@ -109,5 +110,8 @@ Commandline tools to support common use cases.
rs.mtzdump
|
Summarize the contents of an MTZ file |
+ rs.cifdump
|
+ Summarize the contents of a CIF file |
+
diff --git a/reciprocalspaceship/commandline/cifdump.py b/reciprocalspaceship/commandline/cifdump.py
new file mode 100644
index 00000000..3867f0ae
--- /dev/null
+++ b/reciprocalspaceship/commandline/cifdump.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+"""
+Summarize the contents of a CIF 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(cif, precision):
+ """Summarize contents of CIF file"""
+ with pd.option_context("display.precision", precision):
+ print(f"Spacegroup: {cif.spacegroup.short_name()}")
+ print(f"Extended Hermann-Mauguin name: {cif.spacegroup.xhm()}")
+ print(
+ (
+ f"Unit cell dimensions: {cif.cell.a:.3f} {cif.cell.b:.3f} {cif.cell.c:.3f} "
+ f"{cif.cell.alpha:.3f} {cif.cell.beta:.3f} {cif.cell.gamma:.3f}"
+ )
+ )
+ print(f"\ncif.head():\n\n{cif.head()}")
+ print(f"\ncif.describe():\n\n{cif.describe()}")
+ print(f"\ncif.dtypes:\n\n{cif.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()
diff --git a/setup.py b/setup.py
index ca31e8c9..277304f9 100644
--- a/setup.py
+++ b/setup.py
@@ -90,6 +90,7 @@ def getVersionNumber():
entry_points={
"console_scripts": [
"rs.mtzdump=reciprocalspaceship.commandline.mtzdump:main",
+ "rs.cifdump=reciprocalspaceship.commandline.cifdump:main"
]
},
classifiers=[