pdf_report.py 5.87 KB
Newer Older
bow's avatar
bow committed
1
#!/usr/bin/env python
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
# Biopet is built on top of GATK Queue for building bioinformatic
# pipelines. It is mainly intended to support LUMC SHARK cluster which is running
# SGE. But other types of HPC that are supported by GATK Queue (such as PBS)
# should also be able to execute Biopet tools and pipelines.
#
# Copyright 2014 Sequencing Analysis Support Core - Leiden University Medical Center
#
# Contact us at: sasc@lumc.nl
#
# A dual licensing mode is applied. The source code within this project that are
# not part of GATK Queue is freely available for non-commercial use under an AGPL
# license; For commercial users or users who do not want to follow the AGPL
# license, please contact us to obtain a separate license.
#
bow's avatar
bow committed
17
# pdf_report.py
18
#
bow's avatar
bow committed
19
20
# TeX template generation script for Gentrap pipeline.

21
from __future__ import print_function
bow's avatar
bow committed
22
23
24
25
26
27

import argparse
import json
import locale
import os
import re
28
29
import sys
from os import path
bow's avatar
bow committed
30
31
32

from jinja2 import Environment, FileSystemLoader

bow's avatar
bow committed
33

bow's avatar
bow committed
34
# set locale for digit grouping
35
locale.setlocale(locale.LC_ALL, "")
bow's avatar
bow committed
36
37
38
39
40
41
42
43

# HACK: remove this and use jinja2 only for templating
class LongTable(object):

    """Class representing a longtable in LaTeX."""

    def __init__(self, caption, label, header, aln, colnum):
        self.lines = [
44
45
46
47
48
49
50
51
52
            "\\begin{center}",
            "\\captionof{table}{%s}" % caption,
            "\\label{%s}" % label,
            "\\begin{longtable}{%s}" % aln,
            "\\hline",
            "%s" % header,
            "\\hline \\hline",
            "\\endhead",
            "\\hline \\multicolumn{%i}{c}{\\textit{Continued on next page}}\\\\" % \
bow's avatar
bow committed
53
                    colnum,
54
55
56
57
            "\\hline",
            "\\endfoot",
            "\\hline",
            "\\endlastfoot",
bow's avatar
bow committed
58
59
60
        ]

    def __str__(self):
61
        return "\n".join(self.lines)
bow's avatar
bow committed
62
63
64
65
66

    def add_row(self, row):
        self.lines.append(row)

    def end(self):
67
68
69
        self.lines.extend(["\\end{longtable}", "\\end{center}",
            "\\addtocounter{table}{-1}"])

bow's avatar
bow committed
70
71

# filter functions for the jinja environment
bow's avatar
bow committed
72
73
74
def nice_int(num, default="None"):
    if num is None:
        return default
75
    return locale.format("%i", int(num), grouping=True)
bow's avatar
bow committed
76
77


bow's avatar
bow committed
78
79
80
def nice_flt(num, default="None"):
    if num is None:
        return default
81
    return locale.format("%.2f", float(num), grouping=True)
bow's avatar
bow committed
82
83
84
85
86


# and some handy functions
def natural_sort(inlist):
    key = lambda x: [int(a) if a.isdigit() else a.lower() for a in
87
            re.split("([0-9]+)", x)]
bow's avatar
bow committed
88
89
90
91
    inlist.sort(key=key)
    return inlist


bow's avatar
bow committed
92
def write_template(run, template_file, logo_file):
bow's avatar
bow committed
93

94
95
    template_file = path.abspath(path.realpath(template_file))
    template_dir = path.dirname(template_file)
bow's avatar
bow committed
96
97
98
    # spawn environment and create output directory
    env = Environment(loader=FileSystemLoader(template_dir))

99
100
101
102
103
104
105
    # change delimiters since LaTeX may use "{{", "{%", or "{#"
    env.block_start_string = "((*"
    env.block_end_string = "*))"
    env.variable_start_string = "((("
    env.variable_end_string = ")))"
    env.comment_start_string = "((="
    env.comment_end_string = "=))"
bow's avatar
bow committed
106
107
108
109
110
111

    # trim all block-related whitespaces
    env.trim_blocks = True
    env.lstrip_blocks = True

    # put in out filter functions
112
113
    env.filters["nice_int"] = nice_int
    env.filters["nice_flt"] = nice_flt
bow's avatar
bow committed
114
115

    # write tex template for pdflatex
116
    jinja_template = env.get_template(path.basename(template_file))
bow's avatar
bow committed
117
    run.logo = logo_file
bow's avatar
bow committed
118
    render_vars = {
bow's avatar
bow committed
119
        "run": run,
bow's avatar
bow committed
120
121
122
    }
    rendered = jinja_template.render(**render_vars)

123
    print(rendered, file=sys.stdout)
bow's avatar
bow committed
124
125


bow's avatar
bow committed
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
class GentrapLib(object):

    def __init__(self, run, sample, name, summary):
        assert isinstance(run, GentrapRun)
        assert isinstance(sample, GentrapSample)
        self.run = run
        self.sample = sample
        self.name = name
        self._raw = summary
        self.flexiprep = summary.get("flexiprep", {})
        self.clipping = not self.flexiprep["settings"]["skip_clip"]
        self.trimming = not self.flexiprep["settings"]["skip_trim"]
        self.is_paired_end = self.flexiprep["settings"]["paired"]

    def __repr__(self):
        return "{0}(sample=\"{1}\", lib=\"{2}\")".format(
                self.__class__.__name__, self.sample.name, self.name)


class GentrapSample(object):

    def __init__(self, run, name, summary):
        assert isinstance(run, GentrapRun)
        self.run = run
        self.name = name
        self._raw = summary
        self.lib_names = sorted(summary["libraries"].keys())
        self.libs = \
            {l: GentrapLib(self.run, self, l, summary["libraries"][l]) \
                for l in self.lib_names}

    def __repr__(self):
        return "{0}(\"{1}\")".format(self.__class__.__name__, self.name)


class GentrapRun(object):

    def __init__(self, summary_file):

        with open(summary_file, "r") as src:
            summary = json.load(src)

        self._raw = summary
        self.summary_file = summary_file
        self.sample_names = sorted(summary["samples"].keys())
        self.samples = \
            {s: GentrapSample(self, s, summary["samples"][s]) \
                for s in self.sample_names}

        self.files = summary["gentrap"]["files"]
        self.executables = summary["gentrap"]["executables"]
        self.settings = summary["gentrap"]["settings"]
        self.version = self.settings["version"]

    def __repr__(self):
        return "{0}(\"{1}\")".format(self.__class__.__name__,
                                        self.summary_file)


185
if __name__ == "__main__":
bow's avatar
bow committed
186
187

    parser = argparse.ArgumentParser()
188
189
190
191
    parser.add_argument("summary_file", type=str,
            help="Path to Gentrap summary file")
    parser.add_argument("template_file", type=str,
            help="Path to main template file")
bow's avatar
bow committed
192
193
    parser.add_argument("logo_file", type=str,
            help="Path to main logo file")
bow's avatar
bow committed
194
195
    args = parser.parse_args()

bow's avatar
bow committed
196
197
    run = GentrapRun(args.summary_file)
    write_template(run, args.template_file, args.logo_file)