'flowcell': lane.flowcell.flowcell_id,
'lane_number': int(lane.lane_number),
'library_name': lane.library.library_name,
- 'library_id': lane.library_id,
+ 'library_id': lane.library.library_id,
'pM': float(lane.pM),
}
info = {
"pk": 11042,
"model": "samples.library",
"fields": {
- "library_id": "11039",
+ "library_id": "SL039",
"ten_nM_dilution": false,
"avg_lib_size": 300,
"library_name": "Paired ends 99 GM12892",
self.failUnlessEqual(lane_dict['flowcell'], lane.flowcell.flowcell_id)
self.failUnlessEqual(lane_dict['lane_number'], lane.lane_number)
self.failUnlessEqual(lane_dict['library_name'], lane.library.library_name)
- self.failUnlessEqual(lane_dict['library_id'], lane.library_id)
+ self.failUnlessEqual(lane_dict['library_id'], lane.library.library_id)
self.failUnlessAlmostEqual(lane_dict['pM'], float(lane.pM))
self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
self.failUnlessEqual(lane_dict['flowcell'], lane.flowcell.flowcell_id)
self.failUnlessEqual(lane_dict['lane_number'], lane.lane_number)
self.failUnlessEqual(lane_dict['library_name'], lane.library.library_name)
- self.failUnlessEqual(lane_dict['library_id'], lane.library_id)
+ self.failUnlessEqual(lane_dict['library_id'], lane.library.library_id)
self.failUnlessAlmostEqual(lane_dict['pM'], float(lane.pM))
def test_invalid_flowcell(self):
"""
response = self.client.get(u'/experiments/config/303TUAAXX/json')
self.failUnlessEqual(response.status_code, 302)
+
+ def test_library_id(self):
+ """
+ Library IDs should be flexible, so make sure we can retrive a non-numeric ID
+ """
+ self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
+ response = self.client.get('/experiments/config/303TUAAXX/json')
+ self.failUnlessEqual(response.status_code, 200)
+ flowcell = json.loads(response.content)
+
+ self.failUnlessEqual(flowcell['lane_set']['3']['library_id'], 'SL039')
+
+ response = self.client.get('/samples/library/SL039/json')
+ self.failUnlessEqual(response.status_code, 200)
+ library_sl039 = json.loads(response.content)
+
+ self.failUnlessEqual(library_sl039['library_id'], 'SL039')
(r'^$', 'htsworkflow.frontend.experiments.views.index'),
#(r'^liblist$', 'htsworkflow.frontend.experiments.views.test_Libs'),
#(r'^(?P<run_folder>.+)/$', 'gaworkflow.frontend.experiments.views.detail'),
- (r'^config/(?P<fc_id>.+)/json', 'htsworkflow.frontend.experiments.experiments.flowcell_json'),
+ (r'^config/(?P<fc_id>.+)/json$', 'htsworkflow.frontend.experiments.experiments.flowcell_json'),
(r'^fcsheet/(?P<fcid>.+)/$', 'htsworkflow.frontend.experiments.views.makeFCSheet'),
(r'^updStatus$', 'htsworkflow.frontend.experiments.experiments.updStatus'),
(r'^getConfile$', 'htsworkflow.frontend.experiments.experiments.getConfile'),
[
+ {
+ "model": "samples.Cellline",
+ "pk": 1,
+ "fields": {
+ "cellline_name": "Unknown",
+ "notes": "Unknown"
+ }
+ },
+ {
+ "model": "samples.Cellline",
+ "pk": 2,
+ "fields": {
+ "cellline_name": "C2C12 Exponential",
+ "notes": ""
+ }
+ },
+ {
+ "model": "samples.Cellline",
+ "pk": 3,
+ "fields": {
+ "cellline_name": "C2C12 60 hrs",
+ "notes": "Unknown"
+ }
+ },
{
"model": "samples.LibraryType",
"pk": 1,
"fields": {
"name": "Paired End"
}
+ },
+ {
+ "model": "samples.ExperimentType",
+ "pk": 1,
+ "fields": {
+ "name": "Unknown"
+ }
+ },
+ {
+ "model": "samples.ExperimentType",
+ "pk": 2,
+ "fields": {
+ "name": "ChIP-seq"
+ }
+ },
+ {
+ "model": "samples.ExperimentType",
+ "pk": 4,
+ "fields": {
+ "name": "RNA-seq"
+ }
+ },
+ {
+ "model": "samples.ExperimentType",
+ "pk": 7,
+ "fields": {
+ "name": "De Novo"
+ }
+ },
+ {
+ "model": "samples.ExperimentType",
+ "pk": 8,
+ "fields": {
+ "name": "Whole Genome"
+ }
+ },
+ {
+ "model": "samples.ExperimentType",
+ "pk": 9,
+ "fields": {
+ "name": "Small RNA"
+ }
+ },
+ {
+ "model": "samples.ExperimentType",
+ "pk": 10,
+ "fields": {
+ "name": "Multiplexed"
+ }
+ },
+ {
+ "model": "samples.Species",
+ "pk": 1,
+ "fields": {
+ "scientific_name": "Mus musculus",
+ "common_name": "mouse"
+ }
+ },
+ {
+ "model": "samples.Species",
+ "pk": 2,
+ "fields": {
+ "scientific_name": "Drosophila melanogaster",
+ "common_name": "fruit fly"
+ }
+ },
+ {
+ "model": "samples.Species",
+ "pk": 3,
+ "fields": {
+ "scientific_name": "Caenorhabditis elegans",
+ "common_name": ""
+ }
+ },
+ {
+ "model": "samples.Species",
+ "pk": 8,
+ "fields": {
+ "scientific_name": "Homo sapiens",
+ "common_name": ""
+ }
}
+
]
--- /dev/null
+[
+ {"pk": 5, "model": "auth.user",
+ "fields": {
+ "username": "test",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": false,
+ "is_staff": false,
+ "last_login": "2009-01-01 00:00:01",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
+ "email": "",
+ "date_joined": "2009-01-01 00:01:01"
+ }
+ },
+ {"pk": 10984, "model": "samples.library",
+ "fields": {
+ "library_id": "10981",
+ "ten_nM_dilution": false,
+ "avg_lib_size": 400,
+ "library_name": "Paired End Multiplexed Sp-BAC",
+ "creation_date": "2009-07-21",
+ "cell_line": 1,
+ "library_species": 2,
+ "library_type": null,
+ "made_by": "Igor",
+ "affiliations": [
+ 40
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "Done",
+ "tags": [],
+ "made_for": "Andy Cameron",
+ "amplified_from_sample": null,
+ "notes": "Combined 10957-10968",
+ "undiluted_concentration": "5.1",
+ "successful_pM": null,
+ "experiment_type": 10,
+ "antibody": null
+ }
+ },
+ {
+ "pk": 11019,
+ "model": "samples.library",
+ "fields": {
+ "library_id": "11016",
+ "ten_nM_dilution": false,
+ "avg_lib_size": 325,
+ "library_name": "Paired End Pfl #3 MP 7/24/9 a",
+ "creation_date": "2009-08-06",
+ "cell_line": 1,
+ "library_species": 1,
+ "library_type": 2,
+ "made_by": "Lorian",
+ "affiliations": [
+ 41
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": 11006,
+ "notes": "7/31/2009 16:08:22\tColor: Blue",
+ "undiluted_concentration": "35.5",
+ "successful_pM": null,
+ "experiment_type": 8,
+ "antibody": null
+ }
+ },
+ {
+ "pk": 11042,
+ "model": "samples.library",
+ "fields": {
+ "library_id": "11039",
+ "ten_nM_dilution": false,
+ "avg_lib_size": 300,
+ "library_name": "Paired ends 99 GM12892",
+ "creation_date": "2009-08-25",
+ "cell_line": 1,
+ "library_species": 8,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 4,
+ 8,
+ 12
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "Brian Williams",
+ "amplified_from_sample": null,
+ "notes": "fragment size = 300 bp, Amicon filtered\r\nnanodrop: 56.3",
+ "undiluted_concentration": "28.7",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {
+ "pk": 11006,
+ "model": "samples.library",
+ "fields": {
+ "library_id": "11003",
+ "ten_nM_dilution": false,
+ "avg_lib_size": 325,
+ "library_name": "Paired End Pfl #3 MP 7/24/9",
+ "creation_date": "2009-08-05",
+ "cell_line": 1,
+ "library_species": 1,
+ "library_type": 2,
+ "made_by": "Lorian",
+ "affiliations": [
+ 41
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": true,
+ "stopping_point": "1A",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "7/31/2009 16:08:22\tColor: Blue",
+ "undiluted_concentration": null,
+ "successful_pM": null,
+ "experiment_type": 8,
+ "antibody": null
+ }
+ }
+]
import datetime
import unittest
+
+try:
+ import json
+except ImportError, e:
+ import simplejson as json
+
+from django.test import TestCase
+
from htsworkflow.frontend.samples.models import \
Affiliation, \
ExperimentType, \
Species, \
Library
+from htsworkflow.frontend.samples.views import \
+ library_dict, \
+ library_json
+
# The django test runner flushes the database between test suites not cases,
# so to be more compatible with running via nose we flush the database tables
# of interest before creating our sample data.
)
obj.library_10002.save()
-class LibraryTestCase(unittest.TestCase):
+class LibraryTestCase(TestCase):
def setUp(self):
create_db(self)
self.failUnless(len(self.library_10002.affiliations.all()), 2)
self.failUnless(self.library_10001.affiliation(), 'Alice, Bob')
+class SampleWebTestCase(TestCase):
+ """
+ Test returning data from our database in rest like ways.
+ (like returning json objects)
+ """
+ fixtures = ['test_samples.json']
+
+ def test_library_info(self):
+
+ for lib in Library.objects.all():
+ lib_dict = library_dict(lib.library_id)
+ self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
+ url = '/samples/library/%s/json' % (lib.library_id,)
+ lib_response = self.client.get(url)
+ self.failUnlessEqual(lib_response.status_code, 200)
+ lib_json = json.loads(lib_response.content)
+
+ for d in [lib_dict, lib_json]:
+ # amplified_from_sample is a link to the library table,
+ # I want to use the "library_id" for the data lookups not
+ # the embedded primary key.
+ # It gets slightly confusing on how to implement sending the right id
+ # since amplified_from_sample can be null
+ #self.failUnlessEqual(d['amplified_from_sample'], lib.amplified_from_sample)
+ self.failUnlessEqual(d['antibody_id'], lib.antibody_id)
+ self.failUnlessEqual(d['avg_lib_size'], lib.avg_lib_size)
+ self.failUnlessEqual(d['cell_line'], lib.cell_line.cellline_name)
+ self.failUnlessEqual(d['cell_line_id'], lib.cell_line_id)
+ self.failUnlessEqual(d['experiment_type'], lib.experiment_type.name)
+ self.failUnlessEqual(d['experiment_type_id'], lib.experiment_type_id)
+ self.failUnlessEqual(d['id'], lib.id)
+ self.failUnlessEqual(d['library_id'], lib.library_id)
+ self.failUnlessEqual(d['library_name'], lib.library_name)
+ self.failUnlessEqual(d['library_species'], lib.library_species.scientific_name)
+ self.failUnlessEqual(d['library_species_id'], lib.library_species_id)
+ self.failUnlessEqual(d['library_type_id'], lib.library_type_id)
+ if lib.library_type_id is not None:
+ self.failUnlessEqual(d['library_type'], lib.library_type.name)
+ else:
+ self.failUnlessEqual(d['library_type'], None)
+ self.failUnlessEqual(d['made_for'], lib.made_for)
+ self.failUnlessEqual(d['made_by'], lib.made_by)
+ self.failUnlessEqual(d['notes'], lib.notes)
+ self.failUnlessEqual(d['replicate'], lib.replicate)
+ self.failUnlessEqual(d['stopping_point'], lib.stopping_point)
+ self.failUnlessEqual(d['successful_pM'], lib.successful_pM)
+ self.failUnlessEqual(d['undiluted_concentration'],
+ unicode(lib.undiluted_concentration))
+ def test_invalid_library(self):
+ """
+ Make sure we get a 404 if we request an invalid library id
+ """
+ self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
+ response = self.client.get('/samples/library/nottheone/json')
+ self.failUnlessEqual(response.status_code, 404)
+
+
+ def test_library_not_logged_in(self):
+ """
+ Make sure we get a 302 if we're not logged in
+ """
+ response = self.client.get('/samples/library/10981/json')
+ self.failUnlessEqual(response.status_code, 302)
+ self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
+ response = self.client.get('/samples/library/10981/json')
+ self.failUnlessEqual(response.status_code, 200)
--- /dev/null
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+ (r"^library/(?P<library_id>\w+)/json", 'htsworkflow.frontend.samples.views.library_json'),
+ (r"^species/(?P<species_id>\w+)/json", 'htsworkflow.frontend.samples.views.species_json'),
+)
# Create your views here.
+import StringIO
+import logging
+import os
+try:
+ import json
+except ImportError, e:
+ import simplejson as json
+
from htsworkflow.frontend.experiments.models import FlowCell
from htsworkflow.frontend.samples.changelist import ChangeList
from htsworkflow.frontend.samples.models import Library
from htsworkflow.util import opener
from django.core.exceptions import ObjectDoesNotExist
-from django.http import HttpResponse, HttpResponseRedirect
+from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.template.loader import get_template
from django.contrib.auth.decorators import login_required
-import StringIO
-import logging
-import os
-
LANE_LIST = [1,2,3,4,5,6,7,8]
SAMPLES_CONTEXT_DEFAULTS = {
'app_name': 'Flowcell/Library Tracker',
lib = Library.objects.get(library_id=lib_id)
return HttpResponseRedirect('/admin/samples/library/%s' % (lib.id,))
+def library_dict(library_id):
+ """
+ Given a library id construct a dictionary containing important information
+ return None if nothing was found
+ """
+ try:
+ lib = Library.objects.get(library_id = library_id)
+ except Library.DoesNotExist, e:
+ return None
+
+ info = {
+ # 'affiliations'?
+ # 'aligned_reads': lib.aligned_reads,
+ #'amplified_into_sample': lib.amplified_into_sample, # into is a colleciton...
+ #'amplified_from_sample_id': lib.amplified_from_sample,
+ #'antibody_name': lib.antibody_name(), # we have no antibodies.
+ 'antibody_id': lib.antibody_id,
+ 'avg_lib_size': lib.avg_lib_size,
+ 'cell_line': lib.cell_line.cellline_name,
+ 'cell_line_id': lib.cell_line_id,
+ 'experiment_type': lib.experiment_type.name,
+ 'experiment_type_id': lib.experiment_type_id,
+ 'id': lib.id,
+ 'library_id': lib.library_id,
+ 'library_name': lib.library_name,
+ 'library_species': lib.library_species.scientific_name,
+ 'library_species_id': lib.library_species_id,
+ #'library_type': lib.library_type.name,
+ 'library_type_id': lib.library_type_id,
+ 'made_for': lib.made_for,
+ 'made_by': lib.made_by,
+ 'notes': lib.notes,
+ 'replicate': lib.replicate,
+ 'stopping_point': lib.stopping_point,
+ 'successful_pM': lib.successful_pM,
+ 'undiluted_concentration': unicode(lib.undiluted_concentration)
+ }
+ if lib.library_type_id is None:
+ info['library_type'] = None
+ else:
+ info['library_type'] = lib.library_type.name
+ return info
+
+@login_required
+def library_json(request, library_id):
+ """
+ Return a json formatted library dictionary
+ """
+ # what validation should we do on library_id?
+
+ lib = library_dict(library_id)
+ if lib is None:
+ raise Http404
+
+ lib_json = json.dumps(lib)
+ return HttpResponse(lib_json, mimetype='application/json')
+
@login_required
def user_profile(request):
"""
# library id to admin url
(r'^library_id_to_admin_url/(?P<lib_id>\w+)/$',
'htsworkflow.frontend.samples.views.library_id_to_admin_url'),
+ # sample / library information
+ (r'^samples/', include('htsworkflow.frontend.samples.urls')),
# Raw result files
(r'^results/(?P<flowcell_id>\w+)/(?P<cnm>C[1-9]-[0-9]+)/summary/',
'htsworkflow.frontend.samples.views.summaryhtm_fc_cnm'),