import itertools
try:
from collections import OrderedDict
except ImportError:
from oldpymodules import OrderedDict
from qcdb.modelchems import Method, BasisSet, Error, methods, bases, errors
mc_archive = {'mtd': methods, 'bas': bases, 'err': errors}
# define helper functions for formatting table cells
[docs]def val(kw):
return r"""%s""" % (kw['matelem'])
[docs]def graphics(kw):
mc = '-'.join([kw[bit] for bit in ['mtd', 'opt', 'bas']])
return r"""\includegraphics[width=6.67cm,height=3.5mm]{%s%s.pdf}""" % (kw['plotpath'], mc)
[docs]def lmtdbas(kw):
return """%-20s""" % (methods[kw['mtd']].latex + '/' + bases[kw['bas']].latex)
[docs]def label(kw):
return """ %-20s""" % (mc_archive[kw['target']][kw[kw['target']]].latex)
[docs]def table_generic(dbse, serrors,
mtd, bas, columnplan, rowplan=['bas', 'mtd'],
opt=['CP'], err=['mae'], sset=['default'],
landscape=False, standalone=True, subjoin=True,
plotpath='', theme='', filename=None):
"""
Arrays *mtd* and *bas* contain the keys to the qcdb.Method and
qcdb.BasisSet objects that span all those that the table may
encompass. If method and basis are to be scanned over, the arrays
should be in the desired order.
"""
def table_header(kw, abbr, head1, head0, head2): # TODO caption, label
"""Form table header"""
text.append('')
text.append(r"""\begingroup""")
text.append(r"""\squeezetable""")
text.append(r"""\begin{%s}[h!tp]""" % ('sidewaystable' if landscape else 'table'))
text.append(r"""\renewcommand{\baselinestretch}{1}""")
# text += r"""\\caption{$errorhash{$error} of the interaction energy for databases and their subsets with basis set $basishash{$basis}.""" + '\n'
# text += r"""\\label{tbl:qc-merge4dbse-".$error."-".$basis."-r".$round."}}""" + '\n'
text.append(r"""\caption{""")
text.append(r"""\label{tbl:qcdb-%s-%s}}""" % (theme, '-'.join([kw[bit] for bit in tag])))
text.append(r"""\begin{ruledtabular}""")
text.append(r"""\begin{tabular}{%s}""" % (abbr))
text.append(head1)
text.append(head0)
text.append(head2)
text.append(hline)
def table_footer():
"""Form table footer"""
text.append(r"""\end{tabular}""")
text.append(r"""\end{ruledtabular}""")
text.append(r"""\footnotetext[1]{Errors with respect to Gold Standard (see Sec. II D for plot details). Guide lines are at 0, 0.3, and 1.0 kcal/mol overbound ($-$) and underbound ($+$).}""")
text.append(r"""\end{%s}""" % ('sidewaystable' if landscape else 'table'))
text.append(r"""\endgroup""")
text.append(r"""\clearpage""")
text.append('')
def matelem(dict_row, dict_col):
"""Return merge of index dictionaries *dict_row* and *dict_col* (precedence) with error string from serrors appended at key 'matelem'."""
kw = dict(dict_row, **dict_col)
kw['matelem'] = serrors['-'.join([kw[bit] for bit in ['mtd', 'opt', 'bas']])][kw['sset']][kw['dbse']][kw['err']]
return kw
# form LaTeX reference tag
tag = []
for key in ['dbse', 'sset', 'mtd', 'opt', 'bas', 'err']:
if len(locals()[key]) == 1 or (key == rowplan[0] and not subjoin):
tag.append(key)
tag = set(tag)
for col in columnplan:
tag -= set(col[4].keys())
# form column headers
start = 1
stop = 1
head0 = ''
for index in range(2, len(columnplan)):
if columnplan[index][1] == columnplan[index - 1][1]:
stop = index
else:
head0 += r"""\cline{%d-%d}""" % (start + 1, stop + 1)
start = index
stop = index
if index + 1 == len(columnplan):
head0 += r"""\cline{%d-%d}""" % (start + 1, stop + 1)
abbr = ''.join([col[0] for col in columnplan])
h1 = [(k, len(list(g))) for k, g in itertools.groupby([col[1] for col in columnplan])]
head1 = ' & '.join([r"""\multicolumn{%d}{c}{\textbf{%s}}""" % (repeat, label) for (label, repeat) in h1]) + r""" \\"""
h2 = [(k, len(list(g))) for k, g in itertools.groupby([col[2] for col in columnplan])]
head2 = ' & '.join([r"""\multicolumn{%d}{c}{\textbf{%s}}""" % (repeat, label) for (label, repeat) in h2]) + r""" \\"""
# form table body
text = []
nH = len(rowplan)
hline = r"""\hline"""
kw = {'plotpath': plotpath, 'sset': sset[0], 'dbse': dbse[0], 'err': err[0],
'mtd': mtd[0], 'opt': opt[0], 'bas': bas[0]}
if standalone:
text.append(r"""""")
text.append(r"""\documentclass[aip,jcp,preprint,superscriptaddress,floatfix]{revtex4-1}""")
text.append(r"""\usepackage{bm}""")
text.append(r"""\usepackage{dcolumn}""")
text.append(r"""\usepackage{rotating}""")
text.append(r"""\begin{document}""")
if nH == 1:
subjoin = True
if subjoin:
table_header(kw, abbr, head1, head0, head2)
if text[-1] != hline:
text.append(hline)
for hier0 in locals()[rowplan[0]]:
kw[rowplan[0]] = hier0
kw['target'] = rowplan[0]
if nH > 1:
if not subjoin:
table_header(kw, abbr, head1, head0, head2)
if text[-1] != hline:
text.append(hline)
text.append(r"""\textbf{%s} \\""" % (mc_archive[rowplan[0]][hier0].latex))
for hier1 in locals()[rowplan[1]]:
kw[rowplan[1]] = hier1
kw['target'] = rowplan[1]
if nH > 2:
text.append(r"""\enspace\textbf{%s} \\""" % (mc_archive[rowplan[1]][hier1].latex))
for hier2 in locals()[rowplan[2]]:
kw[rowplan[2]] = hier2
kw['target'] = rowplan[2]
text.append(r"""\enspace\enspace""" + ' & '.join([col[3](matelem(kw, col[4])) for col in columnplan]) + r""" \\""")
else:
text.append(r"""\enspace""" + ' & '.join([col[3](matelem(kw, col[4])) for col in columnplan]) + r""" \\""")
if not subjoin:
table_footer()
else:
text.append(' & '.join([col[3](matelem(kw, col[4])) for col in columnplan]) + r""" \\""")
if subjoin:
table_footer()
if standalone:
text.append(r"""\end{document}""")
text = '\n'.join(text)
print text
if __name__ == "__main__":
serrors = {'MP2-CP-adtz': {'hb': {'S22': OrderedDict([('mae', ' 0.38'), ('mape', ' 2.5')]), 'HBC1': OrderedDict([('mae', ' 0.28'), ('mape', ' 2.5')]), 'NBC1': None, 'HSG': OrderedDict([('mae', ' 0.28'), ('mape', ' 1.9')]), 'DB4': OrderedDict([('mae', ' 0.31'), ('mape', ' 2.3')])}, 'default': {'S22': OrderedDict([('mae', ' 0.89'), ('mape', ' 19.2')]), 'HBC1': OrderedDict([('mae', ' 0.28'), ('mape', ' 2.5')]), 'NBC1': OrderedDict([('mae', ' 1.10'), ('mape', ' 139.0')]), 'HSG': OrderedDict([('mae', ' 0.18'), ('mape', ' 9.6')]), 'DB4': OrderedDict([('mae', ' 0.61'), ('mape', ' 42.6')])}, 'mxdd': {'S22': OrderedDict([('mae', ' 1.13'), ('mape', ' 27.1')]), 'HBC1': None, 'NBC1': OrderedDict([('mae', ' 1.10'), ('mape', ' 139.0')]), 'HSG': OrderedDict([('mae', ' 0.16'), ('mape', ' 10.9')]), 'DB4': OrderedDict([('mae', ' 0.80'), ('mape', ' 59.0')])}}, 'CCSD-CP-adz': {'hb': {'S22': OrderedDict([('mae', ' 2.42'), ('mape', ' 18.0')]), 'HBC1': OrderedDict([('mae', ' 2.09'), ('mape', ' 15.3')]), 'NBC1': None, 'HSG': OrderedDict([('mae', ' 2.29'), ('mape', ' 14.8')]), 'DB4': OrderedDict([('mae', ' 2.27'), ('mape', ' 16.1')])}, 'default': {'S22': OrderedDict([('mae', ' 1.82'), ('mape', ' 32.3')]), 'HBC1': OrderedDict([('mae', ' 2.09'), ('mape', ' 15.3')]), 'NBC1': OrderedDict([('mae', ' 1.15'), ('mape', ' 147.4')]), 'HSG': OrderedDict([('mae', ' 1.14'), ('mape', ' 85.9')]), 'DB4': OrderedDict([('mae', ' 1.55'), ('mape', ' 70.2')])}, 'mxdd': {'S22': OrderedDict([('mae', ' 1.54'), ('mape', ' 39.0')]), 'HBC1': None, 'NBC1': OrderedDict([('mae', ' 1.15'), ('mape', ' 147.4')]), 'HSG': OrderedDict([('mae', ' 0.95'), ('mape', ' 97.7')]), 'DB4': OrderedDict([('mae', ' 1.21'), ('mape', ' 94.7')])}}, 'MP2-CP-atz': {'hb': {'S22': OrderedDict([('mae', ' 0.70'), ('mape', ' 5.0')]), 'HBC1': OrderedDict([('mae', ' 0.52'), ('mape', ' 4.1')]), 'NBC1': None, 'HSG': OrderedDict([('mae', ' 0.61'), ('mape', ' 4.0')]), 'DB4': OrderedDict([('mae', ' 0.61'), ('mape', ' 4.4')])}, 'default': {'S22': OrderedDict([('mae', ' 0.86'), ('mape', ' 17.0')]), 'HBC1': OrderedDict([('mae', ' 0.52'), ('mape', ' 4.1')]), 'NBC1': OrderedDict([('mae', ' 0.98'), ('mape', ' 126.7')]), 'HSG': OrderedDict([('mae', ' 0.24'), ('mape', ' 13.5')]), 'DB4': OrderedDict([('mae', ' 0.65'), ('mape', ' 40.3')])}, 'mxdd': {'S22': OrderedDict([('mae', ' 0.94'), ('mape', ' 22.6')]), 'HBC1': None, 'NBC1': OrderedDict([('mae', ' 0.98'), ('mape', ' 126.7')]), 'HSG': OrderedDict([('mae', ' 0.18'), ('mape', ' 15.1')]), 'DB4': OrderedDict([('mae', ' 0.70'), ('mape', ' 54.8')])}}, 'CCSD-CP-atz': {'hb': {'S22': OrderedDict([('mae', ' 1.41'), ('mape', ' 10.5')]), 'HBC1': OrderedDict([('mae', ' 1.11'), ('mape', ' 8.4')]), 'NBC1': None, 'HSG': OrderedDict([('mae', ' 1.39'), ('mape', ' 9.0')]), 'DB4': OrderedDict([('mae', ' 1.30'), ('mape', ' 9.3')])}, 'default': {'S22': OrderedDict([('mae', ' 1.27'), ('mape', ' 23.5')]), 'HBC1': OrderedDict([('mae', ' 1.11'), ('mape', ' 8.4')]), 'NBC1': OrderedDict([('mae', ' 0.97'), ('mape', ' 123.2')]), 'HSG': OrderedDict([('mae', ' 0.77'), ('mape', ' 57.9')]), 'DB4': OrderedDict([('mae', ' 1.03'), ('mape', ' 53.3')])}, 'mxdd': {'S22': OrderedDict([('mae', ' 1.20'), ('mape', ' 29.6')]), 'HBC1': None, 'NBC1': OrderedDict([('mae', ' 0.97'), ('mape', ' 123.2')]), 'HSG': OrderedDict([('mae', ' 0.67'), ('mape', ' 66.1')]), 'DB4': OrderedDict([('mae', ' 0.95'), ('mape', ' 73.0')])}}, 'CCSD-CP-adtz': {'hb': {'S22': OrderedDict([('mae', ' 1.03'), ('mape', ' 7.6')]), 'HBC1': OrderedDict([('mae', ' 0.76'), ('mape', ' 5.9')]), 'NBC1': None, 'HSG': OrderedDict([('mae', ' 1.02'), ('mape', ' 6.6')]), 'DB4': OrderedDict([('mae', ' 0.94'), ('mape', ' 6.7')])}, 'default': {'S22': OrderedDict([('mae', ' 1.05'), ('mape', ' 20.0')]), 'HBC1': OrderedDict([('mae', ' 0.76'), ('mape', ' 5.9')]), 'NBC1': OrderedDict([('mae', ' 0.90'), ('mape', ' 113.9')]), 'HSG': OrderedDict([('mae', ' 0.62'), ('mape', ' 46.7')]), 'DB4': OrderedDict([('mae', ' 0.83'), ('mape', ' 46.6')])}, 'mxdd': {'S22': OrderedDict([('mae', ' 1.06'), ('mape', ' 25.7')]), 'HBC1': None, 'NBC1': OrderedDict([('mae', ' 0.90'), ('mape', ' 113.9')]), 'HSG': OrderedDict([('mae', ' 0.55'), ('mape', ' 53.3')]), 'DB4': OrderedDict([('mae', ' 0.84'), ('mape', ' 64.3')])}}, 'MP2-CP-adz': {'hb': {'S22': OrderedDict([('mae', ' 1.64'), ('mape', ' 12.2')]), 'HBC1': OrderedDict([('mae', ' 1.41'), ('mape', ' 10.4')]), 'NBC1': None, 'HSG': OrderedDict([('mae', ' 1.42'), ('mape', ' 9.1')]), 'DB4': OrderedDict([('mae', ' 1.49'), ('mape', ' 10.6')])}, 'default': {'S22': OrderedDict([('mae', ' 0.97'), ('mape', ' 16.2')]), 'HBC1': OrderedDict([('mae', ' 1.41'), ('mape', ' 10.4')]), 'NBC1': OrderedDict([('mae', ' 0.70'), ('mape', ' 95.9')]), 'HSG': OrderedDict([('mae', ' 0.46'), ('mape', ' 30.5')]), 'DB4': OrderedDict([('mae', ' 0.88'), ('mape', ' 38.3')])}, 'mxdd': {'S22': OrderedDict([('mae', ' 0.65'), ('mape', ' 18.0')]), 'HBC1': None, 'NBC1': OrderedDict([('mae', ' 0.70'), ('mape', ' 95.9')]), 'HSG': OrderedDict([('mae', ' 0.30'), ('mape', ' 34.1')]), 'DB4': OrderedDict([('mae', ' 0.55'), ('mape', ' 49.3')])}}}
#print serrors['CCSD-CP-adtz']['hb']['HSG']['mape']
columnplan = [
['l', r"""Method \& Basis Set""", '', label, {}],
['d', r'S22', 'HB', val, {'sset': 'hb', 'dbse': 'S22'}],
['d', r'S22', 'MX/DD', val, {'sset': 'mxdd', 'dbse': 'S22'}],
['d', r'S22', 'TT', val, {'sset': 'default', 'dbse': 'S22'}],
['d', r'Overall', 'HB', val, {'sset': 'hb', 'dbse': 'DB4'}],
['d', r'Overall', 'MX/DD', val, {'sset': 'mxdd', 'dbse': 'DB4'}],
['d', r'Overall', 'TT', val, {'sset': 'default', 'dbse': 'DB4'}]]
table_generic(columnplan=columnplan, dbse=['DB4'], serrors=serrors, mtd=['MP2', 'CCSD'], bas=['adz', 'atz'], theme='test', subjoin=False)