'Print a list of all templates, ranked according to efficiency.
If test_stats is available, the templates are ranked according to their
relative contribution (summed for all rules created from a given template,
weighted by score) to the performance on the test set. If no test_stats, then
statistics collected during training are used instead. There is also
an unweighted measure (just counting the rules). This is less informative,
though, as many low-score rules will appear towards end of training.
:param test_stats: dictionary of statistics collected during testing
:type test_stats: dict of str -> any (but usually numbers)
:param printunused: if True, print a list of all unused templates
:type printunused: bool
:return: None
:rtype: None'

def print_template_statistics(self, test_stats=None, printunused=True):

    tids = [r.templateid for r in self._rules]
    train_stats = self.train_stats()
    trainscores = train_stats['rulescores']
    assert (len(trainscores) == len(tids)), 'corrupt    statistics:    {0}    train    scores    for    {1}    rules'.format(trainscores, tids)
    template_counts = Counter(tids)
    weighted_traincounts = Counter()
    for (tid, score) in zip(tids, trainscores):
        weighted_traincounts[tid] += score
    tottrainscores = sum(trainscores)
    def det_tplsort(tpl_value):
        return (tpl_value[1], repr(tpl_value[0]))
    def print_train_stats():
        print('TEMPLATE    STATISTICS    (TRAIN)        {0}    templates,    {1}    rules)'.format(len(template_counts), len(tids)))
        print('TRAIN    ({tokencount:7d}    tokens)    initial    {initialerrors:5d}    {initialacc:.4f}    final:    {finalerrors:5d}    {finalacc:.4f}    '.format(**train_stats))
        head = '#ID    |    Score    (train)    |        #Rules                    |    Template'
        print(head, '\n', ('-' * len(head)), sep='')
        train_tplscores = sorted(weighted_traincounts.items(), key=det_tplsort, reverse=True)
        for (tid, trainscore) in train_tplscores:
            s = '{0}    |    {1:5d}            {2:5.3f}    |{3:4d}            {4:.3f}    |    {5}'.format(tid, trainscore, (trainscore / tottrainscores), template_counts[tid], (template_counts[tid] / len(tids)), Template.ALLTEMPLATES[int(tid)])
            print(s)
    def print_testtrain_stats():
        testscores = test_stats['rulescores']
        print('TEMPLATE    STATISTICS    (TEST    AND    TRAIN)    ({0}    templates,    {1}    rules)'.format(len(template_counts), len(tids)))
        print('TEST        ({tokencount:7d}    tokens)    initial    {initialerrors:5d}    {initialacc:.4f}    final:    {finalerrors:5d}    {finalacc:.4f}    '.format(**test_stats))
        print('TRAIN    ({tokencount:7d}    tokens)    initial    {initialerrors:5d}    {initialacc:.4f}    final:    {finalerrors:5d}    {finalacc:.4f}    '.format(**train_stats))
        weighted_testcounts = Counter()
        for (tid, score) in zip(tids, testscores):
            weighted_testcounts[tid] += score
        tottestscores = sum(testscores)
        head = '#ID    |    Score    (test)    |    Score    (train)    |        #Rules                    |    Template'
        print(head, '\n', ('-' * len(head)), sep='')
        test_tplscores = sorted(weighted_testcounts.items(), key=det_tplsort, reverse=True)
        for (tid, testscore) in test_tplscores:
            s = '{0:s}    |{1:5d}        {2:6.3f}    |        {3:4d}            {4:.3f}    |{5:4d}            {6:.3f}    |    {7:s}'.format(tid, testscore, (testscore / tottestscores), weighted_traincounts[tid], (weighted_traincounts[tid] / tottrainscores), template_counts[tid], (template_counts[tid] / len(tids)), Template.ALLTEMPLATES[int(tid)])
            print(s)
    def print_unused_templates():
        usedtpls = set([int(tid) for tid in tids])
        unused = [(tid, tpl) for (tid, tpl) in enumerate(Template.ALLTEMPLATES) if (tid not in usedtpls)]
        print('UNUSED    TEMPLATES    ({0})'.format(len(unused)))
        for (tid, tpl) in unused:
            print('{0:03d}    {1:s}'.format(tid, str(tpl)))
    if (test_stats is None):
        print_train_stats()
    else:
        print_testtrain_stats()
    print()
    if printunused:
        print_unused_templates()
    print()
