예제 #1
0
def check_installation(f=sys.stdout):
    """ Print out any problems with the installation. 
    """
    import nesoni
    from nesoni import runr, config

    ok = [True]

    def report(line):
        if ok[0]:
            ok[0] = False
            config.write_colored_text(
                f, config.colored(31, '\nInstallation problems:\n\n'))
        print >> f, line
        print >> f

    try:
        runr.run_script('', silent=True)
    except Exception:
        report('Couldn\'t run R. Some tools require R.')

    if ok[0]:
        try:
            runr.run_script(
                'library(nesoni)\n'
                'stopifnot(nesoni_version() == version)',
                silent=True,
                version=nesoni.VERSION)
        except AssertionError:
            path = os.path.join(os.path.dirname(__file__), 'nesoni-r')
            report(
                'Nesoni R module not installed or wrong version. To install:')
            report('  R CMD INSTALL ' + path)

    try:
        require_samtools()
    except Error:
        report('samtools not installed.')

    try:
        require_shrimp_2()
    except Error:
        report('SHRiMP not installed.')

    return ok
예제 #2
0
def check_installation(f=sys.stdout):
    """ Print out any problems with the installation. 
    """
    import nesoni
    from nesoni import runr, config
    
    ok = [True]
    def report(line):
        if ok[0]:
            ok[0] = False
            config.write_colored_text(f,config.colored(31,'\nInstallation problems:\n\n'))        
        print >> f, line
        print >> f
    
    try:
        runr.run_script('',silent=True)
    except Exception:
        report('Couldn\'t run R. Some tools require R.')
    
    if ok[0]:
        try: 
            runr.run_script(
                'library(nesoni)\n'
                'stopifnot(nesoni_version() == version)',
            silent=True,version=nesoni.VERSION)
        except AssertionError:
            path = os.path.join(os.path.dirname(__file__),'nesoni-r')
            report('Nesoni R module not installed or wrong version. To install:')
            report('  R CMD INSTALL '+path)
        
    try: require_samtools()
    except Error:
        report('samtools not installed.')
    
    try: require_shrimp_2()
    except Error:
        report('SHRiMP not installed.')
    
    return ok
   def run(self):
       assert self.method in ("limma", "fitnoise1", "fitnoise2"), "Unknown method."
       assert self.method != "limma" or not self.empirical_controls
       
       title = self.get_title()
   
       n_alt = len(self.alt)
       n_null = len(self.null)
       
       suffix = '-dedup' if self.dedup else ''
   
       genewise_filename = join(self.analysis,'expression','genewise'+suffix,'counts.csv')
       genewise_norm_filename = join(self.analysis,'expression','genewise'+suffix,'norm.csv')

       primarypeakwise_filename = join(self.analysis,'expression','primarypeakwise'+suffix,'counts.csv')
       primarypeakwise_norm_filename = join(self.analysis,'expression','primarypeakwise'+suffix,'norm.csv')

       peakwise_filename = join(self.analysis,'expression','peakwise'+suffix,'counts.csv')
       peakwise_norm_filename = join(self.analysis,'expression','peakwise'+suffix,'norm.csv')

       pairwise_filename = join(self.analysis,'peak-shift'+suffix,'individual-pairs.csv')
       pairwise_norm_filename = join(self.analysis,'peak-shift'+suffix,'individual-pairs-norm.csv')

   
       reader = io.Table_reader(genewise_filename, 'Count')
       reader.close()
       samples = [ item for i, item in enumerate(reader.headings) if reader.groups[i] == 'Count' ]
       tags = { }
       for item in samples:
           tags[item] = [ item ]
       for line in reader.comments:
           if line.startswith('#sampleTags='):
               parts = line[len('#sampleTags='):].split(',')
               tags[parts[0]] = parts
              
       model = [ ]
       for term in self.alt + self.null:        
           spec = selection.term_specification(term)
           model.append([ selection.weight(spec, tags[item]) for item in samples ])
       model = zip(*model) #Transpose
       
       select = [ any(row) for row in model ]
       model = [ row for row,selected in zip(model,select) if selected ]
       model_columns = [ selection.term_name(item) for item in self.alt + self.null ]
       model_rows = [ item for keep, item in zip(select, samples) if keep ]
       
       #degust complains if name starts with '-', delimits with commas
       model_columns = [ ('.' if item[:1] == '-' else '') + item.replace(',',';') for item in model_columns ]
       
       pairs_n_alt = n_alt       
       pairs_select = select + select
       pairs_model = (
           [ (0,) * n_alt + row + (0,) for row in model ] +
           [ row[:n_alt]  + row + (1,) for row in model ] 
           )
       pairs_model_columns = (
           [ item+'-interaction' for item in model_columns[:n_alt] ] +
           model_columns +
           [ 'pair2' ]
           )
       pairs_model_rows = [ item+'-peak1' for item in model_rows ] + [ item+'-peak2' for item in model_rows ]
       
       
       design_str = '['+('-'*(8*n_alt-2))+'] test coefficients\n'
       for row, name in zip(model, model_rows):
           design_str += "%s %s\n" % (''.join('%7g ' % item for item in row), name)
       
       print
       print "Design matrix"
       print design_str
       print
       print 'Pair design matrix'
       print '['+('-'*(8*n_alt-2))+'] test coefficients'
       for row, name in zip(pairs_model, pairs_model_rows):
           print ''.join('%7g ' % item for item in row), name
       print
       
       
       workspace = self.get_workspace()
       
       runr.run_script(TEST_R, self.tell,
           DIR = workspace.working_dir,
           METHOD = self.method,
           WEIGHT = self.weight,
           EMPIRICAL_CONTROLS = self.empirical_controls,
           MIN_READS = self.min_reads,
           BIOTYPE = self.biotype,
           RELATION = self.relation,
           QUANTILE_TAIL = self.quantile_tail,
           DO_EXPRESSION = self.do_expression,
           DO_TAIL_LENGTH = self.do_tail_length,
           VERBOSE = self.verbose,
           
           GENEWISE_FILENAME = genewise_filename,
           GENEWISE_NORM_FILENAME = genewise_norm_filename,
           PRIMARYPEAKWISE_FILENAME = primarypeakwise_filename,
           PRIMARYPEAKWISE_NORM_FILENAME = primarypeakwise_norm_filename,
           PEAKWISE_FILENAME = peakwise_filename,
           PEAKWISE_NORM_FILENAME = peakwise_norm_filename,
           PAIRWISE_FILENAME = pairwise_filename,
           PAIRWISE_NORM_FILENAME = pairwise_norm_filename,
           
           N_ALT = n_alt,
           SELECT = select,
           MODEL = model,
           MODEL_COLUMNS = model_columns,
           PAIRS_N_ALT = pairs_n_alt,
           PAIRS_SELECT = pairs_select,
           PAIRS_MODEL = pairs_model,
           PAIRS_MODEL_COLUMNS = pairs_model_columns,
           )
       if self.tell: return
       
       reporter = reporting.Reporter(workspace.working_dir, title, style=web.style())
       
       if self.dedup:
           reporter.p('Read deduplication was used.')
       
       reporter.write('<table>\n')
       for is_expression, entities, result, aveexpr, subtitle, terms in [
           (True, 'genes', 'genewise-voom', 'avg.expression', 'Genewise expression level', model_columns[:n_alt]),
           (False, 'genes', 'genewise-tail', 'avg.tail', 'Genewise tail length', model_columns[:n_alt]),
           (True, 'primary peaks', 'primarypeakwise-voom', 'avg.expression', 'Primary-peakwise expression level', model_columns[:n_alt]),
           (False, 'primary peaks', 'primarypeakwise-tail', 'avg.tail', 'Primary-peakwise tail length', model_columns[:n_alt]),
           (True, 'peaks', 'peakwise-voom', 'avg.expression', 'Peakwise expression level', model_columns[:n_alt]),
           (False, 'peaks', 'peakwise-tail', 'avg.tail', 'Peakwise tail length', model_columns[:n_alt]),
           (True, 'peak pairs', 'pairwise-voom', 'avg.expression', 'Peak-pair expression shift', pairs_model_columns[:n_alt]),
           (False, 'peak pairs', 'pairwise-tail', 'avg.tail', 'Peak-pair tail length shift', pairs_model_columns[:n_alt]),
           ]:
           #data = io.read_grouped_table(workspace/(result+'-toptable.csv'))['All']
           #n = 0
           #n_01 = 0
           #n_05 = 0
           #for row in data.values():
           #    fdr = float(row['adj.P.Val'])
           #    if fdr <= 0.01: n_01 += 1
           #    if fdr <= 0.05: n_05 += 1
           #    n += 1
           
           if is_expression and not self.do_expression: continue
           if not is_expression and not self.do_tail_length: continue
           
           io.execute([
               'degust.py',
               '--name', title + ' : ' + subtitle,
               '--avg', aveexpr,
               '--primary', 'baseline',
               '--logFC', ','.join(terms),
               '--fdr', 'adj.P.Val',
               '--info', 'gene,locus_tag,product,reads,polya.reads,tail.lengths,'+aveexpr,
               '--notour', '1',
               '--out', workspace/(result+'.html'),
               workspace/(result+'-toptable.csv'),
               ])

           with open(workspace/(result+'.txt'),'rU') as f:
               lines = f.readlines()
           
           reporter.write('<tr><td valign="top" width="33%">')
           reporter.subheading( reporter.href(workspace/(result+'.html'), subtitle) )
           #reporter.p( '%d %s, %d with fdr&lt;=0.01, %d with fdr&lt;=0.05' % (n,entities,n_01,n_05) )
           line = reporter.href(workspace/(result+'-toptable.csv'), 'Spreadsheet')
           if result.endswith('voom'):
               line += ', ' + reporter.href(workspace/(result+'.png'), 'voom plot')
           reporter.p(line)
           for line in lines[-2:]:
               reporter.p(line.strip())
           reporter.write('</td><td valign="top"><br/><br/>')
           for line in lines[:-2]:
               reporter.write(line.strip() + '<br/>\n')
           reporter.write('</td></tr>')

       reporter.write('</table>\n')
       
       reporter.subheading("Design matrix")
       
       reporter.write('<pre>' + design_str + '</pre>')
       
       reporter.close()
예제 #4
0
파일: test.py 프로젝트: stu2/tail-tools
   def run(self):
       title = self.get_title()
   
       n_alt = len(self.alt)
       n_null = len(self.null)
       
       suffix = '-dedup' if self.dedup else ''
   
       genewise_filename = join(self.analysis,'expression','genewise'+suffix,'counts.csv')
       genewise_norm_filename = join(self.analysis,'expression','genewise'+suffix,'norm.csv')

       peakwise_filename = join(self.analysis,'expression','peakwise'+suffix,'counts.csv')
       peakwise_norm_filename = join(self.analysis,'expression','peakwise'+suffix,'norm.csv')

       pairwise_filename = join(self.analysis,'peak-shift'+suffix,'individual-pairs.csv')
       pairwise_norm_filename = join(self.analysis,'peak-shift'+suffix,'individual-pairs-norm.csv')

   
       reader = io.Table_reader(genewise_filename, 'Count')
       reader.close()
       samples = [ item for i, item in enumerate(reader.headings) if reader.groups[i] == 'Count' ]
       tags = { }
       for item in samples:
           tags[item] = [ item ]
       for line in reader.comments:
           if line.startswith('#sampleTags='):
               parts = line[len('#sampleTags='):].split(',')
               tags[parts[0]] = parts
              
       model = [ ]
       for term in self.alt + self.null:        
           spec = term_specification(term)
           model.append([ 1 if selection.matches(spec, tags[item]) else 0 for item in samples ])
       model = zip(*model) #Transpose
       
       select = [ any(row) for row in model ]
       model = [ row for row,selected in zip(model,select) if selected ]
       model_columns = [ term_name(item) for item in self.alt + self.null ]
       
       pairs_n_alt = n_alt       
       pairs_select = select + select
       pairs_model = (
           [ (0,) * n_alt + row + (0,) for row in model ] +
           [ row[:n_alt]  + row + (1,) for row in model ] 
           )
       pairs_model_columns = (
           [ item+'-interaction' for item in model_columns[:n_alt] ] +
           model_columns +
           [ 'pair2' ]
           )
       
       workspace = self.get_workspace()
       
       runr.run_script(TEST_R, self.tell,
           SOURCE = os.path.join(os.path.dirname(__file__),'tail_tools.R'),
           DIR = workspace.working_dir,
           MIN_READS = self.min_reads,
           GENEWISE_FILENAME = genewise_filename,
           GENEWISE_NORM_FILENAME = genewise_norm_filename,
           PEAKWISE_FILENAME = peakwise_filename,
           PEAKWISE_NORM_FILENAME = peakwise_norm_filename,
           PAIRWISE_FILENAME = pairwise_filename,
           PAIRWISE_NORM_FILENAME = pairwise_norm_filename,
           
           N_ALT = n_alt,
           SELECT = select,
           MODEL = model,
           MODEL_COLUMNS = model_columns,
           PAIRS_N_ALT = pairs_n_alt,
           PAIRS_SELECT = pairs_select,
           PAIRS_MODEL = pairs_model,
           PAIRS_MODEL_COLUMNS = pairs_model_columns,
           )
       if self.tell: return
       
       reporter = reporting.Reporter(workspace.working_dir, title)
       
       if self.dedup:
           reporter.p('Read deduplication was used.')
       
       for entities, result, aveexpr, subtitle, terms in [
           ('genes', 'genewise-voom', 'avg.expression', 'Genewise expression level', model_columns[:n_alt]),
           ('genes', 'genewise-tail', 'avg.tail', 'Genewise tail length', model_columns[:n_alt]),
           ('peaks', 'peakwise-voom', 'avg.expression', 'Peakwise expression level', model_columns[:n_alt]),
           ('peaks', 'peakwise-tail', 'avg.tail', 'Peakwise tail length', model_columns[:n_alt]),
           ('peak pairs', 'pairwise-voom', 'avg.expression', 'Peak-pair expression shift', pairs_model_columns[:n_alt]),
           ('peak pairs', 'pairwise-tail', 'avg.tail', 'Peak-pair tail length shift', pairs_model_columns[:n_alt]),
           ]:
           #data = io.read_grouped_table(workspace/(result+'-toptable.csv'))['All']
           #n = 0
           #n_01 = 0
           #n_05 = 0
           #for row in data.values():
           #    fdr = float(row['adj.P.Val'])
           #    if fdr <= 0.01: n_01 += 1
           #    if fdr <= 0.05: n_05 += 1
           #    n += 1
           
           io.execute([
               'degust.py',
               '--name', title + ' : ' + subtitle,
               '--avg', aveexpr,
               '--primary', 'baseline',
               '--logFC', ','.join(terms),
               '--fdr', 'adj.P.Val',
               '--info', 'gene,locus_tag,product,reads,polya.reads,tail.lengths,'+aveexpr,
               '--notour', '1',
               '--out', workspace/(result+'.html'),
               workspace/(result+'-toptable.csv'),
               ])
            
           reporter.subheading( reporter.href(workspace/(result+'.html'), subtitle) )
           #reporter.p( '%d %s, %d with fdr&lt;=0.01, %d with fdr&lt;=0.05' % (n,entities,n_01,n_05) )
           with open(workspace/(result+'.txt'),'rU') as f:
               for line in f:
                   reporter.write(line.strip() + '<br/>\n')
        
       reporter.close()
    def run(self):
        assert self.method in ("limma", "fitnoise1", "fitnoise2"), "Unknown method."
        assert self.method != "limma" or not self.empirical_controls

        title = self.get_title()

        n_alt = len(self.alt)
        n_null = len(self.null)

        suffix = "-dedup" if self.dedup else ""

        genewise_filename = join(self.analysis, "expression", "genewise" + suffix, "counts.csv")
        genewise_norm_filename = join(self.analysis, "expression", "genewise" + suffix, "norm.csv")

        primarypeakwise_filename = join(self.analysis, "expression", "primarypeakwise" + suffix, "counts.csv")
        primarypeakwise_norm_filename = join(self.analysis, "expression", "primarypeakwise" + suffix, "norm.csv")

        peakwise_filename = join(self.analysis, "expression", "peakwise" + suffix, "counts.csv")
        peakwise_norm_filename = join(self.analysis, "expression", "peakwise" + suffix, "norm.csv")

        pairwise_filename = join(self.analysis, "peak-shift" + suffix, "individual-pairs.csv")
        pairwise_norm_filename = join(self.analysis, "peak-shift" + suffix, "individual-pairs-norm.csv")

        reader = io.Table_reader(genewise_filename, "Count")
        reader.close()
        samples = [item for i, item in enumerate(reader.headings) if reader.groups[i] == "Count"]
        tags = {}
        for item in samples:
            tags[item] = [item]
        for line in reader.comments:
            if line.startswith("#sampleTags="):
                parts = line[len("#sampleTags=") :].split(",")
                tags[parts[0]] = parts

        model = []
        for term in self.alt + self.null:
            spec = selection.term_specification(term)
            model.append([selection.weight(spec, tags[item]) for item in samples])
        model = zip(*model)  # Transpose

        select = [any(row) for row in model]
        model = [row for row, selected in zip(model, select) if selected]
        model_columns = [selection.term_name(item) for item in self.alt + self.null]
        model_rows = [item for keep, item in zip(select, samples) if keep]

        # degust complains if name starts with '-', delimits with commas
        model_columns = [("." if item[:1] == "-" else "") + item.replace(",", ";") for item in model_columns]

        pairs_n_alt = n_alt
        pairs_select = select + select
        pairs_model = [(0,) * n_alt + row + (0,) for row in model] + [row[:n_alt] + row + (1,) for row in model]
        pairs_model_columns = [item + "-interaction" for item in model_columns[:n_alt]] + model_columns + ["pair2"]
        pairs_model_rows = [item + "-peak1" for item in model_rows] + [item + "-peak2" for item in model_rows]

        design_str = "[" + ("-" * (8 * n_alt - 2)) + "] test coefficients\n"
        for row, name in zip(model, model_rows):
            design_str += "%s %s\n" % ("".join("%7g " % item for item in row), name)

        print
        print "Design matrix"
        print design_str
        print
        print "Pair design matrix"
        print "[" + ("-" * (8 * n_alt - 2)) + "] test coefficients"
        for row, name in zip(pairs_model, pairs_model_rows):
            print "".join("%7g " % item for item in row), name
        print

        workspace = self.get_workspace()

        runr.run_script(
            TEST_R,
            self.tell,
            SOURCE=os.path.join(os.path.dirname(__file__), "tail_tools.R"),
            DIR=workspace.working_dir,
            METHOD=self.method,
            WEIGHT=self.weight,
            EMPIRICAL_CONTROLS=self.empirical_controls,
            MIN_READS=self.min_reads,
            BIOTYPE=self.biotype,
            RELATION=self.relation,
            QUANTILE_TAIL=self.quantile_tail,
            DO_EXPRESSION=self.do_expression,
            DO_TAIL_LENGTH=self.do_tail_length,
            VERBOSE=self.verbose,
            GENEWISE_FILENAME=genewise_filename,
            GENEWISE_NORM_FILENAME=genewise_norm_filename,
            PRIMARYPEAKWISE_FILENAME=primarypeakwise_filename,
            PRIMARYPEAKWISE_NORM_FILENAME=primarypeakwise_norm_filename,
            PEAKWISE_FILENAME=peakwise_filename,
            PEAKWISE_NORM_FILENAME=peakwise_norm_filename,
            PAIRWISE_FILENAME=pairwise_filename,
            PAIRWISE_NORM_FILENAME=pairwise_norm_filename,
            N_ALT=n_alt,
            SELECT=select,
            MODEL=model,
            MODEL_COLUMNS=model_columns,
            PAIRS_N_ALT=pairs_n_alt,
            PAIRS_SELECT=pairs_select,
            PAIRS_MODEL=pairs_model,
            PAIRS_MODEL_COLUMNS=pairs_model_columns,
        )
        if self.tell:
            return

        reporter = reporting.Reporter(workspace.working_dir, title, style=web.style())

        if self.dedup:
            reporter.p("Read deduplication was used.")

        reporter.write("<table>\n")
        for is_expression, entities, result, aveexpr, subtitle, terms in [
            (True, "genes", "genewise-voom", "avg.expression", "Genewise expression level", model_columns[:n_alt]),
            (False, "genes", "genewise-tail", "avg.tail", "Genewise tail length", model_columns[:n_alt]),
            (
                True,
                "primary peaks",
                "primarypeakwise-voom",
                "avg.expression",
                "Primary-peakwise expression level",
                model_columns[:n_alt],
            ),
            (
                False,
                "primary peaks",
                "primarypeakwise-tail",
                "avg.tail",
                "Primary-peakwise tail length",
                model_columns[:n_alt],
            ),
            (True, "peaks", "peakwise-voom", "avg.expression", "Peakwise expression level", model_columns[:n_alt]),
            (False, "peaks", "peakwise-tail", "avg.tail", "Peakwise tail length", model_columns[:n_alt]),
            (
                True,
                "peak pairs",
                "pairwise-voom",
                "avg.expression",
                "Peak-pair expression shift",
                pairs_model_columns[:n_alt],
            ),
            (
                False,
                "peak pairs",
                "pairwise-tail",
                "avg.tail",
                "Peak-pair tail length shift",
                pairs_model_columns[:n_alt],
            ),
        ]:
            # data = io.read_grouped_table(workspace/(result+'-toptable.csv'))['All']
            # n = 0
            # n_01 = 0
            # n_05 = 0
            # for row in data.values():
            #    fdr = float(row['adj.P.Val'])
            #    if fdr <= 0.01: n_01 += 1
            #    if fdr <= 0.05: n_05 += 1
            #    n += 1

            if is_expression and not self.do_expression:
                continue
            if not is_expression and not self.do_tail_length:
                continue

            io.execute(
                [
                    "degust.py",
                    "--name",
                    title + " : " + subtitle,
                    "--avg",
                    aveexpr,
                    "--primary",
                    "baseline",
                    "--logFC",
                    ",".join(terms),
                    "--fdr",
                    "adj.P.Val",
                    "--info",
                    "gene,locus_tag,product,reads,polya.reads,tail.lengths," + aveexpr,
                    "--notour",
                    "1",
                    "--out",
                    workspace / (result + ".html"),
                    workspace / (result + "-toptable.csv"),
                ]
            )

            with open(workspace / (result + ".txt"), "rU") as f:
                lines = f.readlines()

            reporter.write('<tr><td valign="top" width="33%">')
            reporter.subheading(reporter.href(workspace / (result + ".html"), subtitle))
            # reporter.p( '%d %s, %d with fdr&lt;=0.01, %d with fdr&lt;=0.05' % (n,entities,n_01,n_05) )
            line = reporter.href(workspace / (result + "-toptable.csv"), "Spreadsheet")
            if result.endswith("voom"):
                line += ", " + reporter.href(workspace / (result + ".png"), "voom plot")
            reporter.p(line)
            for line in lines[-2:]:
                reporter.p(line.strip())
            reporter.write('</td><td valign="top"><br/><br/>')
            for line in lines[:-2]:
                reporter.write(line.strip() + "<br/>\n")
            reporter.write("</td></tr>")

        reporter.write("</table>\n")

        reporter.subheading("Design matrix")

        reporter.write("<pre>" + design_str + "</pre>")

        reporter.close()
예제 #6
0
    def run(self):
        assert self.method in ("limma", "fitnoise1",
                               "fitnoise2"), "Unknown method."
        assert self.method != "limma" or not self.empirical_controls

        title = self.get_title()

        n_alt = len(self.alt)
        n_null = len(self.null)

        suffix = '-dedup' if self.dedup else ''

        genewise_filename = join(self.analysis, 'expression',
                                 'genewise' + suffix, 'counts.csv')
        genewise_norm_filename = join(self.analysis, 'expression',
                                      'genewise' + suffix, 'norm.csv')

        primarypeakwise_filename = join(self.analysis, 'expression',
                                        'primarypeakwise' + suffix,
                                        'counts.csv')
        primarypeakwise_norm_filename = join(self.analysis, 'expression',
                                             'primarypeakwise' + suffix,
                                             'norm.csv')

        peakwise_filename = join(self.analysis, 'expression',
                                 'peakwise' + suffix, 'counts.csv')
        peakwise_norm_filename = join(self.analysis, 'expression',
                                      'peakwise' + suffix, 'norm.csv')

        pairwise_filename = join(self.analysis, 'peak-shift' + suffix,
                                 'individual-pairs.csv')
        pairwise_norm_filename = join(self.analysis, 'peak-shift' + suffix,
                                      'individual-pairs-norm.csv')

        reader = io.Table_reader(genewise_filename, 'Count')
        reader.close()
        samples = [
            item for i, item in enumerate(reader.headings)
            if reader.groups[i] == 'Count'
        ]
        tags = {}
        for item in samples:
            tags[item] = [item]
        for line in reader.comments:
            if line.startswith('#sampleTags='):
                parts = line[len('#sampleTags='):].split(',')
                tags[parts[0]] = parts

        model = []
        for term in self.alt + self.null:
            spec = selection.term_specification(term)
            model.append(
                [selection.weight(spec, tags[item]) for item in samples])
        model = zip(*model)  #Transpose

        select = [any(row) for row in model]
        model = [row for row, selected in zip(model, select) if selected]
        model_columns = [
            selection.term_name(item) for item in self.alt + self.null
        ]
        model_rows = [item for keep, item in zip(select, samples) if keep]

        #degust complains if name starts with '-', delimits with commas
        model_columns = [
            ('.' if item[:1] == '-' else '') + item.replace(',', ';')
            for item in model_columns
        ]

        pairs_n_alt = n_alt
        pairs_select = select + select
        pairs_model = ([(0, ) * n_alt + row + (0, ) for row in model] +
                       [row[:n_alt] + row + (1, ) for row in model])
        pairs_model_columns = (
            [item + '-interaction'
             for item in model_columns[:n_alt]] + model_columns + ['pair2'])
        pairs_model_rows = [item + '-peak1' for item in model_rows
                            ] + [item + '-peak2' for item in model_rows]

        design_str = '[' + ('-' * (8 * n_alt - 2)) + '] test coefficients\n'
        for row, name in zip(model, model_rows):
            design_str += "%s %s\n" % (''.join('%7g ' % item
                                               for item in row), name)

        print
        print "Design matrix"
        print design_str
        print
        print 'Pair design matrix'
        print '[' + ('-' * (8 * n_alt - 2)) + '] test coefficients'
        for row, name in zip(pairs_model, pairs_model_rows):
            print ''.join('%7g ' % item for item in row), name
        print

        workspace = self.get_workspace()

        runr.run_script(
            TEST_R,
            self.tell,
            DIR=workspace.working_dir,
            METHOD=self.method,
            WEIGHT=self.weight,
            EMPIRICAL_CONTROLS=self.empirical_controls,
            MIN_READS=self.min_reads,
            BIOTYPE=self.biotype,
            RELATION=self.relation,
            QUANTILE_TAIL=self.quantile_tail,
            DO_EXPRESSION=self.do_expression,
            DO_TAIL_LENGTH=self.do_tail_length,
            VERBOSE=self.verbose,
            GENEWISE_FILENAME=genewise_filename,
            GENEWISE_NORM_FILENAME=genewise_norm_filename,
            PRIMARYPEAKWISE_FILENAME=primarypeakwise_filename,
            PRIMARYPEAKWISE_NORM_FILENAME=primarypeakwise_norm_filename,
            PEAKWISE_FILENAME=peakwise_filename,
            PEAKWISE_NORM_FILENAME=peakwise_norm_filename,
            PAIRWISE_FILENAME=pairwise_filename,
            PAIRWISE_NORM_FILENAME=pairwise_norm_filename,
            N_ALT=n_alt,
            SELECT=select,
            MODEL=model,
            MODEL_COLUMNS=model_columns,
            PAIRS_N_ALT=pairs_n_alt,
            PAIRS_SELECT=pairs_select,
            PAIRS_MODEL=pairs_model,
            PAIRS_MODEL_COLUMNS=pairs_model_columns,
        )
        if self.tell: return

        reporter = reporting.Reporter(workspace.working_dir,
                                      title,
                                      style=web.style())

        if self.dedup:
            reporter.p('Read deduplication was used.')

        reporter.write('<table>\n')
        for is_expression, entities, result, aveexpr, subtitle, terms in [
            (True, 'genes', 'genewise-voom', 'avg.expression',
             'Genewise expression level', model_columns[:n_alt]),
            (False, 'genes', 'genewise-tail', 'avg.tail',
             'Genewise tail length', model_columns[:n_alt]),
            (True, 'primary peaks', 'primarypeakwise-voom', 'avg.expression',
             'Primary-peakwise expression level', model_columns[:n_alt]),
            (False, 'primary peaks', 'primarypeakwise-tail', 'avg.tail',
             'Primary-peakwise tail length', model_columns[:n_alt]),
            (True, 'peaks', 'peakwise-voom', 'avg.expression',
             'Peakwise expression level', model_columns[:n_alt]),
            (False, 'peaks', 'peakwise-tail', 'avg.tail',
             'Peakwise tail length', model_columns[:n_alt]),
            (True, 'peak pairs', 'pairwise-voom', 'avg.expression',
             'Peak-pair expression shift', pairs_model_columns[:n_alt]),
            (False, 'peak pairs', 'pairwise-tail', 'avg.tail',
             'Peak-pair tail length shift', pairs_model_columns[:n_alt]),
        ]:
            #data = io.read_grouped_table(workspace/(result+'-toptable.csv'))['All']
            #n = 0
            #n_01 = 0
            #n_05 = 0
            #for row in data.values():
            #    fdr = float(row['adj.P.Val'])
            #    if fdr <= 0.01: n_01 += 1
            #    if fdr <= 0.05: n_05 += 1
            #    n += 1

            if is_expression and not self.do_expression: continue
            if not is_expression and not self.do_tail_length: continue

            io.execute([
                'degust.py',
                '--name',
                title + ' : ' + subtitle,
                '--avg',
                aveexpr,
                '--primary',
                'baseline',
                '--logFC',
                ','.join(terms),
                '--fdr',
                'adj.P.Val',
                '--info',
                'gene,locus_tag,product,reads,polya.reads,tail.lengths,' +
                aveexpr,
                '--notour',
                '1',
                '--out',
                workspace / (result + '.html'),
                workspace / (result + '-toptable.csv'),
            ])

            with open(workspace / (result + '.txt'), 'rU') as f:
                lines = f.readlines()

            reporter.write('<tr><td valign="top" width="33%">')
            reporter.subheading(
                reporter.href(workspace / (result + '.html'), subtitle))
            #reporter.p( '%d %s, %d with fdr&lt;=0.01, %d with fdr&lt;=0.05' % (n,entities,n_01,n_05) )
            line = reporter.href(workspace / (result + '-toptable.csv'),
                                 'Spreadsheet')
            if result.endswith('voom'):
                line += ', ' + reporter.href(workspace /
                                             (result + '.png'), 'voom plot')
            reporter.p(line)
            for line in lines[-2:]:
                reporter.p(line.strip())
            reporter.write('</td><td valign="top"><br/><br/>')
            for line in lines[:-2]:
                reporter.write(line.strip() + '<br/>\n')
            reporter.write('</td></tr>')

        reporter.write('</table>\n')

        reporter.subheading("Design matrix")

        reporter.write('<pre>' + design_str + '</pre>')

        reporter.close()