Exemplo n.º 1
0
 def _flowable(self, n):
     tags = {
         'name': lambda node: self.__name(node),
         'para': lambda node: platypus.Paragraph(self._textual(node), self.styles.para_style_get(node), **(utils.attr_get(node, [], {'bulletText': 'str'}))),
         'xpre': lambda node: platypus.XPreformatted(self._textual(node), self.styles.para_style_get(node), **(utils.attr_get(node, [], {'bulletText': 'str', 'dedent': 'int', 'frags': 'int'}))),
         'pre': lambda node: platypus.Preformatted(self._textual(node), self.styles.para_style_get(node), **(utils.attr_get(node, [], {'bulletText': 'str', 'dedent': 'int'}))),
         'illustration': lambda node: self._illustration(node),
         'blockTable': lambda node: self._table(node),
         'title': lambda node: platypus.Paragraph(self._textual(node), reportlab.lib.styles.getSampleStyleSheet()['Title'], **(utils.attr_get(node, [], {'bulletText': 'str'}))),
         'h1': lambda node: platypus.Paragraph(self._textual(node), reportlab.lib.styles.getSampleStyleSheet()['Heading1'], **(utils.attr_get(node, [], {'bulletText': 'str'}))),
         'h2': lambda node: platypus.Paragraph(self._textual(node), reportlab.lib.styles.getSampleStyleSheet()['Heading2'], **(utils.attr_get(node, [], {'bulletText': 'str'}))),
         'h3': lambda node: platypus.Paragraph(self._textual(node), reportlab.lib.styles.getSampleStyleSheet()['Heading3'], **(utils.attr_get(node, [], {'bulletText': 'str'}))),
         'image': lambda node: platypus.Image(node.getAttribute('file'), mask=(250, 255, 250, 255, 250, 255), **(utils.attr_get(node, ['width', 'height', 'preserveAspectRatio', 'anchor']))),
         'spacer': lambda node: platypus.Spacer(
             width=utils.unit_get(node.getAttribute('width') if node.hasAttribute('width') else '1cm'),
             height=utils.unit_get(node.getAttribute('length'))),
         'barCode': lambda node: code39.Extended39(self._textual(node)),
         'pageBreak': lambda node: platypus.PageBreak(),     # FIXME: it is not in RML std
         'nextPage': lambda node: platypus.PageBreak(),
         'condPageBreak': lambda node: platypus.CondPageBreak(**(utils.attr_get(node, ['height']))),
         'setNextTemplate': lambda node: platypus.NextPageTemplate(str(node.getAttribute('name'))),
         'nextFrame': lambda node: platypus.CondPageBreak(1000),  # TODO: change the 1000 !
         'ul': lambda node: self._list(node),
         'keepInFrame': lambda node: self.__keep_in_frame(node),
     }
     retvalue = tags.get(n.localName)
     if retvalue:
         return retvalue(n)
     else:
         sys.stderr.write('Warning: flowable not yet implemented: %s !\n' % (n.localName,))
Exemplo n.º 2
0
 def _flowable(self, node):
     if node.localName == 'para':
         style = self.styles.para_style_get(node)
         return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'})))
     elif node.localName == 'name':
         self.styles.names[
             node.getAttribute('id')] = node.getAttribute('value')
         return None
     elif node.localName == 'xpre':
         style = self.styles.para_style_get(node)
         return platypus.XPreformatted(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str', 'dedent': 'int', 'frags': 'int'})))
     elif node.localName == 'pre':
         style = self.styles.para_style_get(node)
         return platypus.Preformatted(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str', 'dedent': 'int'})))
     elif node.localName == 'illustration':
         return self._illustration(node)
     elif node.localName == 'blockTable':
         return self._table(node)
     elif node.localName == 'title':
         styles = reportlab.lib.styles.getSampleStyleSheet()
         style = styles['Title']
         return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'})))
     elif node.localName == 'h1':
         styles = reportlab.lib.styles.getSampleStyleSheet()
         style = styles['Heading1']
         return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'})))
     elif node.localName == 'h2':
         styles = reportlab.lib.styles.getSampleStyleSheet()
         style = styles['Heading2']
         return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'})))
     elif node.localName == 'h3':
         styles = reportlab.lib.styles.getSampleStyleSheet()
         style = styles['Heading3']
         return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'})))
     elif node.localName == 'image':
         return platypus.Image(node.getAttribute('file'), mask=(250, 255, 250, 255, 250, 255), **(utils.attr_get(node, ['width', 'height', 'preserveAspectRatio', 'anchor'])))
     elif node.localName == 'spacer':
         if node.hasAttribute('width'):
             width = utils.unit_get(node.getAttribute('width'))
         else:
             width = utils.unit_get('1cm')
         length = utils.unit_get(node.getAttribute('length'))
         return platypus.Spacer(width=width, height=length)
     elif node.localName == 'barCode':
         return code39.Extended39(self._textual(node))
     elif node.localName == 'pageBreak':
         return platypus.PageBreak()
     elif node.localName == 'condPageBreak':
         return platypus.CondPageBreak(**(utils.attr_get(node, ['height'])))
     elif node.localName == 'setNextTemplate':
         return platypus.NextPageTemplate(str(node.getAttribute('name')))
     elif node.localName == 'nextFrame':
         return platypus.CondPageBreak(1000)  # TODO: change the 1000 !
     elif node.localName == 'ul':
         return self._list(node)
     else:
         sys.stderr.write(
             'Warning: flowable not yet implemented: %s !\n' % (node.localName,))
         return None
Exemplo n.º 3
0
    def elem2flow(self, elem, style, width):
        "Convert this element to an iteration of flowables."
        #print "elem2flow(%r)" % elem.__class__.__name__
        if isinstance(elem, html.PRE):
            assert len(elem.content) == 1
            yield platypus.Preformatted(elem.content[0].text, style)

        elif isinstance(elem, html.UL):
            for li in elem.content:
                istyle = self.getElementStyle(li, parent=elem)
                for fl in self.elem2flow(li, istyle, width):
                    yield fl

        elif isinstance(elem, html.LI):
            yield self.makepar(elem.toxml(), style)

        elif elem.__class__ is html.IMG:
            yield platypus.Image()

        elif isinstance(elem, html.TABLE):
            t = self.pdftable(elem, width, style)
            #pt=PdfTable(elem)
            #t=pt.buildTable(width,style)
            if t is None: return
            #print "gonna yield", t
            yield t

        #elif elem.fragmentable:
        elif isinstance(elem, html.Container):
            #print "fragmentable %s" % elem.__class__.__name__
            frags = []
            for e in elem.content:
                if e.fragmentable:
                    #print "gonna elem2frags(%s)"% e.__class__.__name__
                    for f in self.elem2frags(e, style):
                        frags.append(f)
                elif e.flowable:
                    # found non-fragmentable element inside a flowable
                    if len(frags) > 0:
                        yield self.makepar("", style, frags=frags)
                    for ee in self.elem2flow(e, style, width):
                        yield ee
                    frags = []
##                 if e.__class__ is html.IMG:
##                     yield self.makepar("",style,frags=frags)
##                     yield platypus.Image()
##                     frags=[]
#elif e.__class__ is H1:
#    yield self.makepar("",style,frags=frags)
            yield self.makepar("", style, frags=frags)

            #yield platypus.Table(data)
        else:
            raise "Cannot flow %r" % elem
Exemplo n.º 4
0
    def _flowable(self, node, extra_style=None):
        if node.tag=='pto':
            return self._pto(node)
        if node.tag=='para':
            style = self.styles.para_style_get(node)
            if extra_style:
                style.__dict__.update(extra_style)
            result = []
            for i in self._textual(node).split('\n'):
                result.append(platypus.Paragraph(i, style, **(utils.attr_get(node, [], {'bulletText':'str'}))))
            return result
        elif node.tag=='barCode':
            try:
                from reportlab.graphics.barcode import code128
                from reportlab.graphics.barcode import code39
                from reportlab.graphics.barcode import code93
                from reportlab.graphics.barcode import common
                from reportlab.graphics.barcode import fourstate
                from reportlab.graphics.barcode import usps
                from reportlab.graphics.barcode import createBarcodeDrawing

            except ImportError:
                _logger.warning("Cannot use barcode renderers:", exc_info=True)
                return None
            args = utils.attr_get(node, [], {'ratio':'float','xdim':'unit','height':'unit','checksum':'int','quiet':'int','width':'unit','stop':'bool','bearers':'int','barWidth':'float','barHeight':'float'})
            codes = {
                'codabar': lambda x: common.Codabar(x, **args),
                'code11': lambda x: common.Code11(x, **args),
                'code128': lambda x: code128.Code128(str(x), **args),
                'standard39': lambda x: code39.Standard39(str(x), **args),
                'standard93': lambda x: code93.Standard93(str(x), **args),
                'i2of5': lambda x: common.I2of5(x, **args),
                'extended39': lambda x: code39.Extended39(str(x), **args),
                'extended93': lambda x: code93.Extended93(str(x), **args),
                'msi': lambda x: common.MSI(x, **args),
                'fim': lambda x: usps.FIM(x, **args),
                'postnet': lambda x: usps.POSTNET(x, **args),
                'ean13': lambda x: createBarcodeDrawing('EAN13', value=str(x), **args),
                'qrcode': lambda x: createBarcodeDrawing('QR', value=x, **args),
            }
            code = 'code128'
            if node.get('code'):
                code = node.get('code').lower()
            return codes[code](self._textual(node))
        elif node.tag=='name':
            self.styles.names[ node.get('id')] = node.get('value')
            return None
        elif node.tag=='xpre':
            style = self.styles.para_style_get(node)
            return platypus.XPreformatted(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str','dedent':'int','frags':'int'})))
        elif node.tag=='pre':
            style = self.styles.para_style_get(node)
            return platypus.Preformatted(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str','dedent':'int'})))
        elif node.tag=='illustration':
            return  self._illustration(node)
        elif node.tag=='blockTable':
            return  self._table(node)
        elif node.tag=='title':
            styles = reportlab.lib.styles.getSampleStyleSheet()
            style = styles['Title']
            return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str'})))
        elif re.match('^h([1-9]+[0-9]*)$', (node.tag or '')):
            styles = reportlab.lib.styles.getSampleStyleSheet()
            style = styles['Heading'+str(node.tag[1:])]
            return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str'})))
        elif node.tag=='image':
            image_data = False
            if not node.get('file'):
                if node.get('name'):
                    if node.get('name') in self.doc.images:
                        _logger.debug("Image %s read ", node.get('name'))
                        image_data = self.doc.images[node.get('name')].read()
                    else:
                        _logger.warning("Image %s not defined", node.get('name'))
                        return False
                else:
                    import base64
                    newtext = node.text
                    if self.localcontext:
                        newtext = utils._process_text(self, node.text or '')
                    image_data = base64.decodestring(newtext)
                if not image_data:
                    _logger.debug("No inline image data")
                    return False
                image = StringIO(image_data)
            else:
                _logger.debug("Image get from file %s", node.get('file'))
                image = _open_image(node.get('file'), path=self.doc.path)
            return platypus.Image(image, mask=(250,255,250,255,250,255), **(utils.attr_get(node, ['width','height'])))
        elif node.tag=='spacer':
            if node.get('width'):
                width = utils.unit_get(node.get('width'))
            else:
                width = utils.unit_get('1cm')
            length = utils.unit_get(node.get('length'))
            return platypus.Spacer(width=width, height=length)
        elif node.tag=='section':
            return self.render(node)
        elif node.tag == 'pageNumberReset':
            return PageReset()
        elif node.tag in ('pageBreak', 'nextPage'):
            return platypus.PageBreak()
        elif node.tag=='condPageBreak':
            return platypus.CondPageBreak(**(utils.attr_get(node, ['height'])))
        elif node.tag=='setNextTemplate':
            return platypus.NextPageTemplate(str(node.get('name')))
        elif node.tag=='nextFrame':
            return platypus.CondPageBreak(1000)           # TODO: change the 1000 !
        elif node.tag == 'setNextFrame':
            from reportlab.platypus.doctemplate import NextFrameFlowable
            return NextFrameFlowable(str(node.get('name')))
        elif node.tag == 'currentFrame':
            from reportlab.platypus.doctemplate import CurrentFrameFlowable
            return CurrentFrameFlowable(str(node.get('name')))
        elif node.tag == 'frameEnd':
            return EndFrameFlowable()
        elif node.tag == 'hr':
            width_hr=node.get('width') or '100%'
            color_hr=node.get('color')  or 'black'
            thickness_hr=node.get('thickness') or 1
            lineCap_hr=node.get('lineCap') or 'round'
            return platypus.flowables.HRFlowable(width=width_hr,color=color.get(color_hr),thickness=float(thickness_hr),lineCap=str(lineCap_hr))
        else:
            sys.stderr.write('Warning: flowable not yet implemented: %s !\n' % (node.tag,))
            return None
Exemplo n.º 5
0
 def getPreEl(self, txt):
     s = platypus.Spacer(0.1 * inch, 0.1 * inch)
     p = platypus.Preformatted(txt, PreStyle)
     precomps = [s, p]
     result = platypus.KeepTogether(precomps)
     return result
Exemplo n.º 6
0
 def pre(self,txt,style=None):
     if style is None:
         style = self.stylesheet.Code
     return self.append(platypus.Preformatted(txt,style))
Exemplo n.º 7
0
 def _flowable(self, node):
     if node.localName=='para':
         style = self.styles.para_style_get(node)
         return platypus.Paragraph(
             self._textual(node), style,
             **(utils.getAttrsAsDict(node, [], {'bulletText':'str'})))
     elif node.localName=='name':
         self.styles.names[ node.getAttribute('id')] = node.getAttribute('value')
         return None
     elif node.localName=='xpre':
         style = self.styles.para_style_get(node)
         return platypus.XPreformatted(
             self._textual(node), style,
             **(utils.getAttrsAsDict(node, [], {'bulletText':'str','dedent':'int','frags':'int'})))
     elif node.localName=='pre':
         style = self.styles.para_style_get(node)
         return platypus.Preformatted(
             self._textual(node), style,
             **(utils.getAttrsAsDict(node, [], {'bulletText':'str','dedent':'int'})))
     elif node.localName=='illustration':
         return  self._illustration(node)
     elif node.localName=='blockTable':
         return  self._table(node)
     elif node.localName=='title':
         styles = reportlab.lib.styles.getSampleStyleSheet()
         style = styles['Title']
         return platypus.Paragraph(
             self._textual(node), style,
             **(utils.getAttrsAsDict(node, [], {'bulletText':'str'})))
     elif node.localName=='h1':
         styles = reportlab.lib.styles.getSampleStyleSheet()
         style = styles['Heading1']
         return platypus.Paragraph(
             self._textual(node), style,
             **(utils.getAttrsAsDict(node, [], {'bulletText':'str'})))
     elif node.localName=='h2':
         styles = reportlab.lib.styles.getSampleStyleSheet()
         style = styles['Heading2']
         return platypus.Paragraph(
             self._textual(node), style,
             **(utils.getAttrsAsDict(node, [], {'bulletText':'str'})))
     elif node.localName=='h3':
         styles = reportlab.lib.styles.getSampleStyleSheet()
         style = styles['Heading3']
         return platypus.Paragraph(
             self._textual(node), style,
             **(utils.getAttrsAsDict(node, [], {'bulletText':'str'})))
     elif node.localName=='image':
         return platypus.Image(
             node.getAttribute('file'), mask=(250, 255, 250, 255, 250, 255),
             **(utils.getAttrsAsDict(node, ['width','height'])))
     elif node.localName=='spacer':
         if node.hasAttribute('width'):
             width = utils.as_pt(node.getAttribute('width'))
         else:
             width = utils.as_pt('1cm')
         length = utils.as_pt(node.getAttribute('length'))
         return platypus.Spacer(width=width, height=length)
     elif node.localName=='pageBreak':
         return platypus.PageBreak()
     elif node.localName=='condPageBreak':
         return platypus.CondPageBreak(**(utils.getAttrsAsDict(node, ['height'])))
     elif node.localName=='setNextTemplate':
         return platypus.NextPageTemplate(str(node.getAttribute('name')))
     elif node.localName=='nextFrame':
         return platypus.CondPageBreak(1000)           # TODO: change the 1000 !
     elif barcode_codes and node.localName=='barCode':
         code = barcode_codes.get(node.getAttribute('code'), Code128)
         attr_types = {'barWidth': 'pt', 'barHeight': 'pt',
                       'fontName': 'text', 'fontSize': 'pt',
                       'humanReadable': 'bool'}
         return code(
             self._textual(node),
             **utils.getAttrsAsDict(node, ['barWidth', 'barHeight'], attr_types))
     else:
         sys.stderr.write('Warning: flowable not yet implemented: %s !\n' % (node.localName,))
         return None
def create_report(inbam1, invcf1, inbam2, invcf2, infasta, snpMatrix,
	quantityWantSites, rows, output):
	# Attempt to auto-detect sample names (experimental)
	S1Name = (get_prefix(inbam1, invcf1)).rstrip('.fastq-reference')
	S2Name = (get_prefix(inbam2, invcf2)).rstrip('.fastq-reference')

	pairwiseSNPs = get_pairwiseSNPlist(snpMatrix, S1Name, S2Name)
	pairwiseSNPpositions = pairwiseSNPs.keys()

	if quantityWantSites > len(pairwiseSNPpositions):
		print 'Selecting all {} putative SNP sites to print...'.format(len(pairwiseSNPpositions))
		quantityWantSites = len(pairwiseSNPpositions)
	randSitesUnsorted = random.sample(pairwiseSNPpositions, quantityWantSites)  #randomly selected sites to investigate
	randSitesUnsortedInts = [int(i) for i in randSitesUnsorted]  #convert strings to integers
	listWantSitesVCF = sorted(randSitesUnsortedInts, reverse=True)  #for pileup report building
	randSites = sorted(randSitesUnsortedInts)

	vcfData1, vcfData2 = get_vcf_data(randSites, invcf1, invcf2)

	if len(vcfData1) != len(vcfData2):
		print 'ERROR: unequal number of SNPs identified between {} and {}'.format(S1Name, S2Name)
		sys.exit('ERROR in VCF parsing')
	numSites = len(vcfData1)

	# Calculate page and frames
	doc = Platypus.BaseDocTemplate(output, topMargin=0, bottomMargin=0, leftMargin=10, rightMargin=0)
	doc.pagesize = landscape(A4) #ISO Code A4
	# A4 Dimensions: 297 mm x 210 mm ; 11.69 in x 8.27 in ; 842 pt x 595 pt

	frameCount = 2  #(numsites + (-numsites%6)) // 6
	frameWidth = doc.height / frameCount
	frameHeight = doc.width - .05 * inch
	frames = []

	# Construct a frame for each column
	for frame in range(frameCount):
		leftMargin = doc.leftMargin + frame * frameWidth
		column = Platypus.Frame(leftMargin, doc.bottomMargin, frameWidth, frameHeight)
		frames.append(column)
	template = Platypus.PageTemplate(frames=frames)
	doc.addPageTemplates(template)

	PAGE_HEIGHT = defaultPageSize[0] #size in points
	PAGE_WIDTH  = defaultPageSize[1]
	styles = getSampleStyleSheet()
	style  = styles['Normal']
	style.fontName = 'Courier'
	style.fontSize = 6.5

	Title = ('Report containing {} of {} putative SNPs for {} and {}'.format(
		str(quantityWantSites), str(len(pairwiseSNPpositions)),
		os.path.basename(invcf1), os.path.basename(invcf2)))
	report = [Paragraph(Title, styles['Heading2'])]

	while numSites > 0:
		# handle SNP sites at beginning of Chrom (<50 bases in)
		posMinusFitty = (listWantSitesVCF[numSites - 1] - 50)
		centeredPos = str(max(posMinusFitty, 0))

		pos = str(vcfData1[numSites-1][0])
		gap = Platypus.Spacer(0.25, 0.05*inch)

		# vcfData lists are ordered: [pos, chrom, qual, DP, MQ, alt]
		for sample in [[vcfData1, inbam1, S1Name], [vcfData2, inbam2, S2Name]]:
			pileup = Platypus.Preformatted(get_ttview(sample[1], infasta,
								(sample[0][1][1]), centeredPos, rows), style)

			qual = sample[0][numSites-1][2]
			DP   = sample[0][numSites-1][3]
			MQ   = sample[0][numSites-1][4]
			SNP  = str(sample[0][numSites-1][5])
			
			header = Paragraph('{} at position {} for {} with a QUAL of {}, MQ of {}, and raw read depth (DP) of {}'.format(
				SNP, pos, sample[2], qual, MQ, DP), styles['Heading6'])
			report.append(Platypus.KeepTogether([gap, header, pileup]))

		numSites -= 1

	doc.build(report)
Exemplo n.º 9
0
 def pre(self, text):
     p = pdf.Preformatted(text, style=self.styles['Code'])
     self.elements.append(p)
Exemplo n.º 10
0
     self.styles.names[node.get('id')] = node.get('value')
     return None
 elif node.tag == 'xpre':
     style = self.styles.para_style_get(node)
     return platypus.XPreformatted(
         self._textual(node), style,
         **(utils.attr_get(node, [], {
             'bulletText': 'str',
             'dedent': 'int',
             'frags': 'int'
         })))
 elif node.tag == 'pre':
     style = self.styles.para_style_get(node)
     return platypus.Preformatted(
         self._textual(node), style,
         **(utils.attr_get(node, [], {
             'bulletText': 'str',
             'dedent': 'int'
         })))
 elif node.tag == 'illustration':
     return self._illustration(node)
 elif node.tag == 'blockTable':
     return self._table(node)
 elif node.tag == 'title':
     styles = reportlab.lib.styles.getSampleStyleSheet()
     style = styles['Title']
     return platypus.Paragraph(
         self._textual(node), style,
         **(utils.attr_get(node, [], {'bulletText': 'str'})))
 elif re.match('^h([1-9]+[0-9]*)$', (node.tag or '')):
     styles = reportlab.lib.styles.getSampleStyleSheet()
     style = styles['Heading' + str(node.tag[1:])]
def main():
    args = parseArgs()
    inbam = args.bam
    infasta = args.fasta
    invcf = args.vcf
    numsites = args.numsites
    output = args.output
    rows = args.rows

    SNPs, INDELs = get_vcf(invcf)
    vcfSNPs = len(SNPs)
    print 'Identified %s putative SNPs' % vcfSNPs
    #print 'Identified %s putative INDEL bases' % len(INDELs)

    # enable explicitly given positions (e.g., -p '89,3969181,44,123456') to investigate
    if args.positions:
        posList = [int(n) for n in args.positions.split(',')]
        listWantSitesVCF = []
        for i in posList:
            if any(i in x for x in SNPs):
                for SNP in SNPs:
                    if SNP[1] == i:
                        listWantSitesVCF.append(SNP)
            else:
                sys.exit('ERROR: specified position %s not a SNP' % i)
        quantityWantSites = len(listWantSitesVCF)
        listWantSitesVCF.reverse()

    # randomly select SNP sites if positions (-p) unspecified
    else:
        quantityWantSites = int(numsites)
        if quantityWantSites > vcfSNPs:
            print 'Number of requested SNP sites to investigate exceeds number of identified SNPs'
            print 'Selecting all %s putative SNP sites to print...' % vcfSNPs
            quantityWantSites = vcfSNPs

        randSitesUnsorted = random.sample(
            SNPs, quantityWantSites)  #randomly selected sites to investigate
        listWantSitesVCF = sorted(randSitesUnsorted,
                                  key=itemgetter(1),
                                  reverse=True)

    #calculate page and frames
    doc = Platypus.BaseDocTemplate(output,
                                   topMargin=0,
                                   bottomMargin=0,
                                   leftMargin=10,
                                   rightMargin=0)
    doc.pagesize = landscape(A4)  #ISO Code A4
    # A4 Dimensions: 297 mm x 210 mm ; 11.69 in x 8.27 in ; 842 pt x 595 pt

    frameCount = 2  #(numsites + (-numsites%6)) // 6
    frameWidth = doc.height / frameCount
    frameHeight = doc.width - .05 * inch
    frames = []

    #construct a frame for each column
    for frame in range(frameCount):
        leftMargin = doc.leftMargin + frame * frameWidth
        column = Platypus.Frame(leftMargin, doc.bottomMargin, frameWidth,
                                frameHeight)
        frames.append(column)
    template = Platypus.PageTemplate(frames=frames)
    doc.addPageTemplates(template)

    PAGE_HEIGHT = defaultPageSize[0]  #size in points
    PAGE_WIDTH = defaultPageSize[1]
    styles = getSampleStyleSheet()
    style = styles['Normal']
    style.fontName = 'Courier'
    style.fontSize = 6.5

    Title = ('Report containing ' + str(quantityWantSites) + ' of ' +
             str(vcfSNPs) + ' putative SNPs for ' + os.path.basename(invcf))
    report = [Paragraph(Title, styles['Heading2'])]

    while quantityWantSites > 0:
        posMinusFitty = (listWantSitesVCF[quantityWantSites - 1][1] - 50)
        centeredPos = max(
            posMinusFitty,
            0)  #handles SNP sites at beginning of chrom (<50 bases in)

        pileup = Platypus.Preformatted(
            get_ttview(inbam, infasta,
                       listWantSitesVCF[quantityWantSites - 1][0], centeredPos,
                       rows), style)
        pos = str(listWantSitesVCF[quantityWantSites - 1][1])
        QUAL = str(listWantSitesVCF[quantityWantSites - 1][2])
        DP = str(listWantSitesVCF[quantityWantSites - 1][3])
        MQ = str(listWantSitesVCF[quantityWantSites - 1][4])
        SNP = str(listWantSitesVCF[quantityWantSites - 1][5])
        header = Paragraph(
            SNP + ' at position ' + pos + ' with a QUAL of ' + QUAL +
            ', MQ of ' + MQ + ', and raw read depth (DP) of ' + DP,
            styles['Heading6'])
        gap = Platypus.Spacer(0.25, 0.05 * inch)
        report.append(Platypus.KeepTogether([gap, header, pileup]))
        quantityWantSites -= 1
    doc.build(report)