2fb394511989b32e6cb97d7a507cf28fce71fc2d
[htsworkflow.git] / htsworkflow / frontend / samples / test_samples.py
1 import datetime
2
3 try:
4     import json
5 except ImportError, e:
6     import simplejson as json
7
8 from django.test import TestCase
9
10 from htsworkflow.frontend.samples.models import \
11         Affiliation, \
12         ExperimentType, \
13         Species, \
14         Library
15
16 from htsworkflow.frontend.samples.views import \
17      library_dict, \
18      library_json
19
20 from htsworkflow.frontend.auth import apidata
21 from htsworkflow.util.conversion import unicode_or_none
22 from htsworkflow.util.ethelp import validate_xhtml
23
24 class LibraryTestCase(TestCase):
25     fixtures = ['test_samples.json']
26
27     def setUp(self):
28         create_db(self)
29
30     def testOrganism(self):
31         self.assertEquals(self.library_10001.organism(), 'human')
32
33     def testAffiliations(self):
34         self.library_10001.affiliations.add(self.affiliation_alice)
35         self.library_10002.affiliations.add(
36                 self.affiliation_alice,
37                 self.affiliation_bob
38         )
39         self.failUnless(len(self.library_10001.affiliations.all()), 1)
40         self.failUnless(self.library_10001.affiliation(), 'Alice')
41
42         self.failUnless(len(self.library_10002.affiliations.all()), 2)
43         self.failUnless(self.library_10001.affiliation(), 'Alice, Bob')
44
45
46 class SampleWebTestCase(TestCase):
47     """
48     Test returning data from our database in rest like ways.
49     (like returning json objects)
50     """
51     fixtures = ['test_samples.json']
52
53     def test_library_info(self):
54         for lib in Library.objects.all():
55             lib_dict = library_dict(lib.id)
56             url = '/samples/library/%s/json' % (lib.id,)
57             lib_response = self.client.get(url, apidata)
58             self.failUnlessEqual(lib_response.status_code, 200)
59             lib_json = json.loads(lib_response.content)
60
61             for d in [lib_dict, lib_json]:
62                 # amplified_from_sample is a link to the library table,
63                 # I want to use the "id" for the data lookups not
64                 # the embedded primary key.
65                 # It gets slightly confusing on how to implement sending the right id
66                 # since amplified_from_sample can be null
67                 #self.failUnlessEqual(d['amplified_from_sample'], lib.amplified_from_sample)
68                 self.failUnlessEqual(d['antibody_id'], lib.antibody_id)
69                 self.failUnlessEqual(d['cell_line_id'], lib.cell_line_id)
70                 self.failUnlessEqual(d['cell_line'], unicode_or_none(lib.cell_line))
71                 self.failUnlessEqual(d['experiment_type'], lib.experiment_type.name)
72                 self.failUnlessEqual(d['experiment_type_id'], lib.experiment_type_id)
73                 self.failUnlessEqual(d['gel_cut_size'], lib.gel_cut_size)
74                 self.failUnlessEqual(d['hidden'], lib.hidden)
75                 self.failUnlessEqual(d['id'], lib.id)
76                 self.failUnlessEqual(d['insert_size'], lib.insert_size)
77                 self.failUnlessEqual(d['library_name'], lib.library_name)
78                 self.failUnlessEqual(d['library_species'], lib.library_species.scientific_name)
79                 self.failUnlessEqual(d['library_species_id'], lib.library_species_id)
80                 self.failUnlessEqual(d['library_type_id'], lib.library_type_id)
81                 if lib.library_type_id is not None:
82                     self.failUnlessEqual(d['library_type'], lib.library_type.name)
83                 else:
84                     self.failUnlessEqual(d['library_type'], None)
85                     self.failUnlessEqual(d['made_for'], lib.made_for)
86                     self.failUnlessEqual(d['made_by'], lib.made_by)
87                     self.failUnlessEqual(d['notes'], lib.notes)
88                     self.failUnlessEqual(d['replicate'], lib.replicate)
89                     self.failUnlessEqual(d['stopping_point'], lib.stopping_point)
90                     self.failUnlessEqual(d['successful_pM'], lib.successful_pM)
91                     self.failUnlessEqual(d['undiluted_concentration'],
92                                          unicode(lib.undiluted_concentration))
93                 # some specific tests
94                 if lib.id == '10981':
95                     # test a case where there is no known status
96                     lane_set = {u'status': u'Unknown',
97                                 u'paired_end': True,
98                                 u'read_length': 75,
99                                 u'lane_number': 1,
100                                 u'lane_id': 1193,
101                                 u'flowcell': u'303TUAAXX',
102                                 u'status_code': None}
103                     self.failUnlessEqual(len(d['lane_set']), 1)
104                     self.failUnlessEqual(d['lane_set'][0], lane_set)
105                 elif lib.id == '11016':
106                     # test a case where there is a status
107                     lane_set = {u'status': 'Good',
108                                 u'paired_end': True,
109                                 u'read_length': 75,
110                                 u'lane_number': 5,
111                                 u'lane_id': 1197,
112                                 u'flowcell': u'303TUAAXX',
113                                 u'status_code': 2}
114                     self.failUnlessEqual(len(d['lane_set']), 1)
115                     self.failUnlessEqual(d['lane_set'][0], lane_set)
116
117
118     def test_invalid_library_json(self):
119         """
120         Make sure we get a 404 if we request an invalid library id
121         """
122         response = self.client.get('/samples/library/nottheone/json', apidata)
123         self.failUnlessEqual(response.status_code, 404)
124
125
126     def test_invalid_library(self):
127         response = self.client.get('/library/nottheone/')
128         self.failUnlessEqual(response.status_code, 404)
129
130
131     def test_library_no_key(self):
132         """
133         Make sure we get a 302 if we're not logged in
134         """
135         response = self.client.get('/samples/library/10981/json')
136         self.failUnlessEqual(response.status_code, 403)
137         response = self.client.get('/samples/library/10981/json', apidata)
138         self.failUnlessEqual(response.status_code, 200)
139
140     def test_library_rdf(self):
141         import RDF
142         from htsworkflow.util.rdfhelp import get_model, \
143              dump_model, \
144              fromTypedNode, \
145              load_string_into_model, \
146              rdfNS, \
147              libraryOntology
148         model = get_model()
149
150         response = self.client.get('/library/10981/')
151         self.assertEqual(response.status_code, 200)
152         content = response.content
153         load_string_into_model(model, 'rdfa', content)
154
155         body = """prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
156         prefix libns: <http://jumpgate.caltech.edu/wiki/LibraryOntology#>
157
158         select ?library ?name ?library_id ?gel_cut ?made_by
159         where {
160            ?library a libns:library ;
161                     libns:name ?name ;
162                     libns:library_id ?library_id ;
163                     libns:gel_cut ?gel_cut ;
164                     libns:made_by ?made_by
165         }"""
166         query = RDF.SPARQLQuery(body)
167         for r in query.execute(model):
168             self.assertEqual(fromTypedNode(r['library_id']), u'10981')
169             self.assertEqual(fromTypedNode(r['name']),
170                              u'Paired End Multiplexed Sp-BAC')
171             self.assertEqual(fromTypedNode(r['gel_cut']), 400)
172             self.assertEqual(fromTypedNode(r['made_by']), u'Igor')
173
174         state = validate_xhtml(content)
175         if state is not None:
176             self.assertTrue(state)
177
178         # validate a library page.
179         from htsworkflow.util.rdfhelp import add_default_schemas
180         from htsworkflow.util.rdfinfer import Infer
181         add_default_schemas(model)
182         inference = Infer(model)
183         errmsgs = list(inference.run_validation())
184         self.assertEqual(len(errmsgs), 0)
185
186     def test_library_index_rdfa(self):
187         from htsworkflow.util.rdfhelp import \
188              add_default_schemas, get_model, load_string_into_model, \
189              dump_model
190         from htsworkflow.util.rdfinfer import Infer
191
192         model = get_model()
193         add_default_schemas(model)
194         inference = Infer(model)
195
196         response = self.client.get('/library/')
197         self.assertEqual(response.status_code, 200)
198         load_string_into_model(model, 'rdfa', response.content)
199
200         errmsgs = list(inference.run_validation())
201         self.assertEqual(len(errmsgs), 0)
202
203         body =  """prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
204         prefix libns: <http://jumpgate.caltech.edu/wiki/LibraryOntology#>
205
206         select ?library ?library_id ?name ?species ?species_name
207         where {
208            ?library a libns:Library .
209            OPTIONAL { ?library libns:library_id ?library_id . }
210            OPTIONAL { ?library libns:species ?species .
211                       ?species libns:species_name ?species_name . }
212            OPTIONAL { ?library libns:name ?name . }
213         }"""
214         bindings = set(['library', 'library_id', 'name', 'species', 'species_name'])
215         query = RDF.SPARQLQuery(body)
216         count = 0
217         for r in query.execute(model):
218             count += 1
219             for name, value in r.items():
220                 self.assertTrue(name in bindings)
221                 self.assertTrue(value is not None)
222
223         self.assertEqual(count, len(Library.objects.filter(hidden=False)))
224
225         state = validate_xhtml(response.content)
226         if state is not None: self.assertTrue(state)
227
228
229 # The django test runner flushes the database between test suites not cases,
230 # so to be more compatible with running via nose we flush the database tables
231 # of interest before creating our sample data.
232 def create_db(obj):
233     obj.species_human = Species.objects.get(pk=8)
234     obj.experiment_rna_seq = ExperimentType.objects.get(pk=4)
235     obj.affiliation_alice = Affiliation.objects.get(pk=1)
236     obj.affiliation_bob = Affiliation.objects.get(pk=2)
237
238     Library.objects.all().delete()
239     obj.library_10001 = Library(
240         id = "10001",
241         library_name = 'C2C12 named poorly',
242         library_species = obj.species_human,
243         experiment_type = obj.experiment_rna_seq,
244         creation_date = datetime.datetime.now(),
245         made_for = 'scientist unit 2007',
246         made_by = 'microfludics system 7321',
247         stopping_point = '2A',
248         undiluted_concentration = '5.01',
249         hidden = False,
250     )
251     obj.library_10001.save()
252     obj.library_10002 = Library(
253         id = "10002",
254         library_name = 'Worm named poorly',
255         library_species = obj.species_human,
256         experiment_type = obj.experiment_rna_seq,
257         creation_date = datetime.datetime.now(),
258         made_for = 'scientist unit 2007',
259         made_by = 'microfludics system 7321',
260         stopping_point = '2A',
261         undiluted_concentration = '5.01',
262         hidden = False,
263     )
264     obj.library_10002.save()
265
266 try:
267     import RDF
268     HAVE_RDF = True
269
270     rdfNS = RDF.NS("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
271     xsdNS = RDF.NS("http://www.w3.org/2001/XMLSchema#")
272     libNS = RDF.NS("http://jumpgate.caltech.edu/wiki/LibraryOntology#")
273 except ImportError,e:
274     HAVE_RDF = False
275
276
277 class TestRDFaLibrary(TestCase):
278     fixtures = ['test_samples.json']
279
280     def test_parse_rdfa(self):
281         model = get_rdf_memory_model()
282         parser = RDF.Parser(name='rdfa')
283         url = '/library/10981/'
284         lib_response = self.client.get(url)
285         self.failIfEqual(len(lib_response.content), 0)
286
287         parser.parse_string_into_model(model,
288                                        lib_response.content,
289                                        'http://localhost'+url)
290         # http://jumpgate.caltech.edu/wiki/LibraryOntology#affiliation>
291         self.check_literal_object(model, ['Bob'], p=libNS['affiliation'])
292         self.check_literal_object(model, ['Multiplexed'], p=libNS['experiment_type'])
293         self.check_literal_object(model, ['400'], p=libNS['gel_cut'])
294         self.check_literal_object(model, ['Igor'], p=libNS['made_by'])
295         self.check_literal_object(model, ['Paired End Multiplexed Sp-BAC'], p=libNS['name'])
296         self.check_literal_object(model, ['Drosophila melanogaster'], p=libNS['species_name'])
297
298         self.check_uri_object(model,
299                               [u'http://localhost/lane/1193'],
300                               p=libNS['has_lane'])
301
302         fc_uri = RDF.Uri('http://localhost/flowcell/303TUAAXX/')
303         self.check_literal_object(model,
304                                   [u"303TUAAXX"],
305                                   s=fc_uri, p=libNS['flowcell_id'])
306
307     def check_literal_object(self, model, values, s=None, p=None, o=None):
308         statements = list(model.find_statements(
309             RDF.Statement(s,p,o)))
310         self.failUnlessEqual(len(statements), len(values),
311                         "Couln't find %s %s %s" % (s,p,o))
312         for s in statements:
313             self.failUnless(s.object.literal_value['string'] in values)
314
315
316     def check_uri_object(self, model, values, s=None, p=None, o=None):
317         statements = list(model.find_statements(
318             RDF.Statement(s,p,o)))
319         self.failUnlessEqual(len(statements), len(values),
320                         "Couln't find %s %s %s" % (s,p,o))
321         for s in statements:
322             self.failUnless(unicode(s.object.uri) in values)
323
324
325
326 def get_rdf_memory_model():
327     storage = RDF.MemoryStorage()
328     model = RDF.Model(storage)
329     return model