comparison tests/test_riboplot.py @ 3:8e1efafa6277

Updated version * Bugfix: blue lines in some plots (bar colors were not set correctly) * Cookiecutter template * Additional unit tests * Add plot legend
author Vimalkumar Velayudhan <vimal@biotechcoder.com>
date Wed, 12 Aug 2015 09:27:45 +0100
parents
children 2ffa8172dce1
comparison
equal deleted inserted replaced
2:b6fd86c539ea 3:8e1efafa6277
1 import os
2 import shutil
3 import logging
4 import unittest
5 import tempfile
6
7 from riboplot import ribocore, riboplot
8
9 # use testing configuration
10 CONFIG = riboplot.CONFIG = riboplot.config.TestingConfig()
11 logging.disable(logging.CRITICAL)
12
13 RIBO_FILE = os.path.join(CONFIG.DATA_DIR, '5hRPFsorted.bam')
14 RNA_FILE = os.path.join(CONFIG.DATA_DIR, '5hmRNAsorted.bam')
15 TRANSCRIPT_NAME = 'gi|148357119|ref|NM_001098396.1|'
16 TRANSCRIPTOME_FASTA = os.path.join(CONFIG.DATA_DIR, 'zebrafish.fna')
17 TRANSCRIPTOME_FASTA_MINUS1 = os.path.join(CONFIG.DATA_DIR, 'zebrafish_minus1.fna')
18
19
20 class CheckArgumentsTestCase(unittest.TestCase):
21 """Check if all arguments sent on the command line are valid."""
22 parser = riboplot.create_parser()
23
24 def test_bedtools_missing(self):
25 """If bedtools is not in PATH, raise an error."""
26 args = self.parser.parse_args(
27 ['-b', RIBO_FILE, '-f', TRANSCRIPTOME_FASTA, '-t', TRANSCRIPT_NAME, '-n', RNA_FILE])
28 save_path = os.environ['PATH']
29 os.environ['PATH'] = ''
30 self.assertRaises(OSError, ribocore.check_optional_arguments, args.ribo_file, args.rna_file)
31 os.environ['PATH'] = save_path
32
33 def test_is_bam_valid(self):
34 """Test if BAM file is valid."""
35 valid = ribocore.is_bam_valid(RIBO_FILE)
36 self.assertTrue(valid)
37
38 # test with a FASTA file (which is not BAM)
39 self.assertRaises(ValueError, ribocore.is_bam_valid, TRANSCRIPTOME_FASTA)
40
41 def test_bam_has_index(self):
42 """Check if BAM file has an index."""
43 # RPF file has an index
44 has_index = ribocore.bam_has_index(RIBO_FILE)
45 self.assertTrue(has_index)
46
47 # RNA file doesn't have an index
48 has_index = ribocore.bam_has_index(RNA_FILE)
49 self.assertFalse(has_index)
50
51 def test_create_bam_index(self):
52 """Index a BAM file."""
53 ribocore.create_bam_index(RNA_FILE)
54
55 # check if index exists
56 has_index = ribocore.bam_has_index(RNA_FILE)
57 self.assertTrue(has_index)
58
59 # remove index
60 os.remove('{}.bai'.format(RNA_FILE))
61
62 def test_valid_read_length(self):
63 """Read length should be a valid integer."""
64 args = self.parser.parse_args(['-b', RIBO_FILE, '-f', TRANSCRIPTOME_FASTA,
65 '-t', TRANSCRIPT_NAME, '-l', '28'])
66 ribocore.check_optional_arguments(ribo_file=args.ribo_file, read_length=args.read_length)
67
68 def test_invalid_read_length(self):
69 """An error is raised if an invalid read length is used."""
70 args = self.parser.parse_args(['-b', RIBO_FILE, '-f', TRANSCRIPTOME_FASTA, '-t', TRANSCRIPT_NAME,
71 '-l', '-1']) # invalid read length -1
72 self.assertRaises(ribocore.ArgumentError, ribocore.check_optional_arguments,
73 args.ribo_file, None, args.read_length)
74
75 args = self.parser.parse_args(['-b', RIBO_FILE, '-f', TRANSCRIPTOME_FASTA, '-t', TRANSCRIPT_NAME,
76 '-l', '100']) # invalid read length 100
77 self.assertRaises(ribocore.ArgumentError, ribocore.check_optional_arguments,
78 args.ribo_file, None, args.read_length)
79
80 def test_valid_read_offset(self):
81 """Read offset should be positive."""
82 args = self.parser.parse_args(['-b', RIBO_FILE, '-f', TRANSCRIPTOME_FASTA, '-t', TRANSCRIPT_NAME,
83 '-s', '-1']) # invalid read offset -1
84 self.assertRaises(ribocore.ArgumentError, ribocore.check_optional_arguments,
85 args.ribo_file, None, None, args.read_offset)
86
87 def test_is_fasta_valid(self):
88 """A valid FASTA file can be opened with pysam.FastaFile."""
89 self.assertTrue(ribocore.is_fasta_valid(TRANSCRIPTOME_FASTA))
90
91 def test_missing_transcript_in_fasta(self):
92 """If a transcript is missing in FASTA, an error is raised."""
93 args = self.parser.parse_args(['-b', RIBO_FILE, '-f', TRANSCRIPTOME_FASTA, '-t', TRANSCRIPT_NAME]) # invalid read offset -1
94 self.assertRaises(ribocore.ArgumentError, ribocore.check_required_arguments,
95 args.ribo_file, args.transcriptome_fasta, 'hello')
96
97 def test_missing_transcript_in_bam(self):
98 """If a transcript is missing in BAM, an error is raised."""
99 # testing with an unrelated BAM file
100 args = self.parser.parse_args(['-b', '/home/vimal/tmp/empty_tp/RiboSeq.bam', '-f', TRANSCRIPTOME_FASTA,
101 '-t', TRANSCRIPT_NAME])
102 self.assertRaises(ribocore.ArgumentError, ribocore.check_required_arguments, args.ribo_file,
103 args.transcriptome_fasta, args.transcript_name)
104
105
106 class RNACountsTestCase(unittest.TestCase):
107
108 def test_get_rna_counts(self):
109 """Test get RNA counts for transcript from RNA-Seq BAM file. Assumes bedtools is installed."""
110 counts = riboplot.get_rna_counts(RNA_FILE, TRANSCRIPT_NAME)
111 self.assertIsInstance(counts, dict)
112 self.assertTrue(len(counts) > 0)
113
114
115 class RiboPlotTestCase(unittest.TestCase):
116
117 def test_get_codon_positions(self):
118 """Get codon positions in all frames given a sequence."""
119 # the positions on this sequence were calculated manually.
120 fasta = ('AACCGGAGCACCCAGAGAAAACCCACGCAAACGCAGGGAGAATTTGCAAACTCCACACA'
121 'GAAATGCCAGCTGATCCAGCCGAGCCTCGAGTCAGCATCCTTGCTTGTTGGATGCCTGA'
122 'TTGCAGTTCAACTCCAAACTCAGTTGGACCAGCTGATCAGTG')
123 codon_positions = riboplot.get_start_stops(fasta)
124 expected = {1: {'starts': [], 'stops': []},
125 2: {'starts': [], 'stops': [71, 116, 152]},
126 3: {'starts': [63, 111], 'stops': []}}
127 self.assertEqual(codon_positions, expected)
128
129 def test_valid_riboplot_run(self):
130 """A good riboplot run"""
131 output_dir = tempfile.mkdtemp()
132 print 'Output path is {}'.format(output_dir)
133 parser = riboplot.create_parser()
134 args = parser.parse_args(['-b', RIBO_FILE, '-f', TRANSCRIPTOME_FASTA, '-t', TRANSCRIPT_NAME,
135 '-o', output_dir])
136 riboplot.main(args)
137 for fname in ('riboplot.png', 'riboplot.svg', 'RiboCounts.csv'):
138 self.assertTrue(os.path.exists(os.path.join(output_dir, fname)))
139 shutil.rmtree(output_dir)
140
141 def test_transcript_with_no_counts(self):
142 """If the transcript has no ribocounts, no plot should be produced."""
143 transcript = 'gi|62955616|ref|NM_001017822.1|' # has no reads
144 output_dir = tempfile.mkdtemp()
145 parser = riboplot.create_parser()
146 args = parser.parse_args(['-b', RIBO_FILE, '-f', TRANSCRIPTOME_FASTA, '-t', transcript, '-o', output_dir])
147 self.assertRaises(ribocore.RiboPlotError, riboplot.main, args)
148 for fname in ('riboplot.png', 'riboplot.svg', 'RiboCounts.csv'):
149 self.assertFalse(os.path.exists(os.path.join(output_dir, fname)))
150 shutil.rmtree(output_dir)
151
152 @unittest.skip('todo')
153 def test_get_ribo_counts(self):
154 """Get RiboSeq read counts"""
155 pass
156
157 @unittest.skip('todo')
158 def test_write_ribo_counts(self):
159 """Write RiboSeq read counts as CSV."""
160 pass
161
162 @unittest.skip('todo')
163 def test_plot_read_counts(self):
164 """Generate riboplots"""
165 pass