--- /dev/null
+from django.contrib import admin
+from .models import KeywordMap, Printer
+
+class KeywordMapAdmin(admin.ModelAdmin):
+ list_display = ('keyword','regex', 'url_template')
+
+class PrinterAdmin(admin.ModelAdmin):
+ list_display = ('name', 'model', 'ip_address', 'label_shape', 'label_width', 'label_height', 'notes')
+
+admin.site.register(KeywordMap, KeywordMapAdmin)
+admin.site.register(Printer, PrinterAdmin)
\ No newline at end of file
--- /dev/null
+[{"pk": 1,
+ "model": "bcmagic.keywordmap",
+ "fields": {"regex": "(?P<uuid>[A-Fa-f0-9]+)",
+ "url_template": "/samples/freezer/{{ uuid }}/",
+ "keyword": "frzr"}},
+ {"pk": 2,
+ "model": "bcmagic.keywordmap",
+ "fields": {"regex": "(?P<uuid>[A-Fa-f0-9]+)",
+ "url_template": "/samples/container/{{ uuid }}/",
+ "keyword": "cntr"}},
+ {"pk": 3,
+ "model": "bcmagic.keywordmap",
+ "fields": {"regex": "(?P<sampleid>\\d+)\\|(?P<owner>[A-Za-z0-9_\\- ]+)",
+ "url_template": "/samples/sample/{{ sampleid }}/",
+ "keyword": "s"}},
+ {"pk": 4,
+ "model": "bcmagic.keywordmap",
+ "fields": {"regex": "(?P<search>[\\S\\s]+)",
+ "url_template": "http://www.google.com/search?q={{ search }}",
+ "keyword": "gg"}},
+ {"pk": 5,
+ "model": "bcmagic.keywordmap",
+ "fields": {"regex": "(?P<search>[\\S\\s]+)",
+ "url_template": "http://www.flickr.com/search/?q={{ search }}",
+ "keyword": "flickr"}},
+ {"pk": 6,
+ "model": "bcmagic.keywordmap",
+ "fields": {"regex": "(?P<uuid>[A-Fa-f0-9]+)",
+ "url_template": "/inventory/{{ uuid }}/",
+ "keyword": "invu"}},
+ {"pk": 7,
+ "model": "bcmagic.keywordmap",
+ "fields": {"regex": "(?P<barcode_id>.+)",
+ "url_template": "/inventory/{{barcode_id}}/",
+ "keyword": "invb"}}
+]
--- /dev/null
+[{"pk": 1,
+ "model": "bcmagic.printer",
+ "fields": {"name": "ZM400 1.25x1",
+ "label_height": 1.0,
+ "notes": "Everyday use labels",
+ "label_width": 1.25,
+ "label_shape": "Square",
+ "model": "Zebra ZM400",
+ "ip_address": "131.215.34.116"}},
+ {"pk": 2,
+ "model": "bcmagic.printer",
+ "fields": {"name": "ZM400 3x3",
+ "label_height": 3.0,
+ "notes": "Larger everyday use labels",
+ "label_width": 3.0,
+ "label_shape": "Square",
+ "model": "Zebra ZM400",
+ "ip_address": "131.215.34.117"}}]
--- /dev/null
+from django import forms
+
+class BarcodeMagicForm(forms.Form):
+ magic = forms.CharField(label="Barcode Magic", required=False)
+ bcm_mode = forms.CharField(widget=forms.HiddenInput, initial="default")
+
+ class Media:
+ js = ('js/jquery.timers-1.0.0.js',
+ 'js/bcmagic-ext.js')
--- /dev/null
+from django.db import models
+
+#FIXME: Should be made more generic and probably pre-populated supported list
+# but for now, since we only have a ZM400, this will do.
+PRINTER_MODELS=[ ('Zebra ZM400', 'Zebra ZM400'),
+ ('Zebra ZM600', 'Zebra ZM600')]
+
+LABEL_SHAPES = [ ('Square', 'Square'), ('Circle', 'Circle') ]
+
+class KeywordMap(models.Model):
+ """
+ Mapper object maps keyword|arg1|arg2|...|argN to REST urls
+ """
+ keyword = models.CharField(max_length=64)
+ regex = models.CharField(max_length=1024)
+ url_template = models.TextField()
+
+class Printer(models.Model):
+ """
+ Barcode Printer Information
+ """
+ name = models.CharField(max_length=256)
+ model = models.CharField(max_length=64, choices=PRINTER_MODELS)
+ ip_address = models.IPAddressField()
+ label_shape = models.CharField(max_length=32, choices=LABEL_SHAPES)
+ label_width = models.FloatField(help_text='width or diameter in inches')
+ label_height = models.FloatField(help_text='height in inches')
+ notes = models.TextField()
+
+ def __unicode__(self):
+ return u'%s, %s, %s, %s, %sx%s' % (self.name, self.model, self.ip_address, self.label_shape, self.label_width, self.label_width)
\ No newline at end of file
--- /dev/null
+#from htsworkflow.frontend.samples import bcm_cmds
+
+#BCM_PLUGINS = {'cmd_move_sample': bcm_cmds.cmd_move_sample}
+
+_SEARCH_FUNCTIONS = {}
+
+def bcm_plugin_processor(keyword, text, bcm_mode):
+ """
+ Fixme should be made generic plugable, but am hard coding values for proof
+ of concept.
+ """
+ d = {}
+
+ if bcm_mode not in BCM_PLUGINS:
+ d['mode'] = 'Error'
+ d['status'] = 'bcm_mode plugin called "%s" was not found' % (bcm_mode)
+ return d
+
+ return BCM_PLUGINS[bcm_mode](keyword, text, bcm_mode)
+
+
+def register_search_plugin(label, search_function):
+ """
+ Registers a group label and search_function
+
+ search_function(search_string) --> (text_display, obj_url)
+ """
+
+ if label in _SEARCH_FUNCTIONS:
+ msg = "search function for label (%s) already registered." % (label)
+ raise ValueError, msg
+
+ _SEARCH_FUNCTIONS[label] = search_function
+
\ No newline at end of file
--- /dev/null
+from django.conf.urls import patterns
+
+urlpatterns = patterns('',
+ (r'^json_test/$', 'bcmagic.views.json_test'),
+ (r'^magic/$', 'bcmagic.views.magic'),
+ (r'^$', 'bcmagic.views.index'),
+)
--- /dev/null
+from django.conf import settings
+
+import ftplib
+import socket
+import StringIO
+
+
+def print_zpl(zpl_text, host=None):
+ """
+ Sends zpl_text to printer
+ """
+ if not host:
+ host = settings.BCPRINTER_PRINTER1_HOST
+ ftp = ftplib.FTP(host=host, user='blank', passwd='')
+ ftp.login()
+ ftp.storlines("STOR printme.txt", StringIO.StringIO(zpl_text))
+ ftp.quit()
+
+
+def print_zpl_socket(zpl_text, host=None, port=None):
+ """
+ Sends zpl_text to printer via a socket
+
+ if zpl_text is a list of zpl_texts, it will print each one
+ in that list.
+ """
+
+ if not host:
+ host=settings.BCPRINTER_PRINTER1_HOST
+ if not port:
+ port=settings.BCPRINTER_PRINTER1_PORT
+
+ # Process anyway if zpl_text is a list.
+ if type(zpl_text) is list:
+ zpl_text = '\n'.join(zpl_text)
+
+ s = socket.socket()
+ # PORT 9100 is default for Zebra tabletop/desktop printers
+ # PORT 6101 is default for Zebra mobile printers
+ s.connect((host, port))
+ s.sendall(zpl_text)
+ s.close()
+
+
+def report_error(message):
+ """
+ Return a dictionary with a command to display 'message'
+ """
+ return {'mode': 'Error', 'status': message}
+
+
+def redirect_to_url(url):
+ """
+ Return a bcm dictionary with a command to redirect to 'url'
+ """
+ return {'mode': 'redirect', 'url': url}
+
+
+def autofill(field, value):
+ """
+ Return a bcm dictionary with a command to automatically fill the
+ corresponding "field" with "value"
+ """
+ return {'mode': 'autofill', 'field': field, 'value': value}
--- /dev/null
+from django.http import HttpResponse
+from django.template import RequestContext, Template, Context
+from django.shortcuts import render_to_response
+from django.core.exceptions import ObjectDoesNotExist
+
+from . import models
+from .utils import report_error, redirect_to_url
+from .plugin import bcm_plugin_processor
+from . import plugin
+#from htsworkflow.util.jsonutil import encode_json
+
+try:
+ import json
+except ImportError, e:
+ import simplejson as json
+
+import re
+
+from htsworkflow.frontend.bcmagic import forms
+
+def index(request):
+ """
+ Display a barcode magic input box
+ """
+ form = forms.BarcodeMagicForm()
+
+ return render_to_response('bcmagic/magic.html', {'bcmagic': form},
+ context_instance=RequestContext(request))
+
+
+def __plugin_search(text):
+ """
+ Runs registered plugins to search for results
+ """
+
+ hits = []
+ for label, search_func in plugin._SEARCH_FUNCTIONS.items():
+ result = search_func(text)
+ if result is not None:
+ hits.extend(result)
+
+ n = len(hits)
+ if n == 0:
+ msg = 'No hits found for: %s' % (text)
+ return report_error(msg)
+ elif n == 1:
+ return redirect_to_url(hits[0][1])
+ else:
+ msg = "%d hits found for (%s); multi-hit not implemented yet." % (n, text)
+ return report_error(msg)
+
+
+ #return json.dumps(hits)
+
+
+def __magic_process(text):
+ """
+ Based on scanned text, check to see if there is map object to use
+ for a useful redirect.
+ """
+ # Split text on |
+ split_text = text.split('|')
+
+ # There should always be at least one | in a valid scan.
+ if len(split_text) <= 1:
+ #return report_error('Invalid text: %s' % (text))
+ return __plugin_search(text)
+
+ # Keyword is the first element in the list
+ keyword = split_text[0]
+
+ # Attempt to find a KeywordMap based on keyword
+ try:
+ keymap = models.KeywordMap.objects.get(keyword=keyword)
+ except ObjectDoesNotExist, e:
+ return report_error('Keyword (%s) is not defined' % (keyword))
+
+ # Remove keyword and only scan the content
+ content = '|'.join(split_text[1:])
+
+ #FIXME: would be faster to cache compiled regex
+ search = re.compile(keymap.regex)
+
+ mo = search.search(content)
+
+ # if the search was invalid
+ if not mo:
+ return report_error('(%s) failed to match (%s)' % (keymap.regex, content))
+
+ t = Template(keymap.url_template)
+ c = Context(mo.groupdict())
+
+ return redirect_to_url(str(t.render(c)))
+
+
+
+
+
+def magic(request):
+ """
+ Let the magic begin
+ """
+ d = {}
+
+ #Retrieve posted text from processing
+ if 'text' in request.POST:
+ text = request.POST['text']
+ else:
+ text = None
+
+ #Retrieve bmc_mode for processing
+ if 'bcm_mode' in request.POST:
+ bcm_mode = request.POST['bcm_mode']
+ else:
+ bcm_mode = None
+
+ ################################
+ # Handle some errors
+ ################################
+
+ # Did not receive text error
+ if text is None or text.strip() == '':
+ d['mode'] = 'Error'
+ d['status'] = 'Did not recieve text'
+
+ return HttpResponse(json.dumps(d), 'text/plain')
+
+ # Did not receive bcm_mode error
+ if bcm_mode is None or bcm_mode.strip() == '':
+ d['mode'] = 'Error'
+ d['status'] = 'Missing bcm_mode information'
+
+
+ ################################
+ # Figure out which mode to use
+ ################################
+ keyword = text.split('|')[0]
+
+ # Handle URL mode by default
+ if keyword == 'url':
+ d['mode'] = 'redirect'
+ d['url'] = text.split('|')[1]
+
+ # Pass off processing to plugins
+ elif bcm_mode != 'default':
+ d = bcm_plugin_processor(keyword, text, bcm_mode)
+
+ # Try keyword mapper
+ else:
+ d = __magic_process(text)
+
+ return HttpResponse(json.dumps(d), 'text/plain')
+
+
+
+def json_test(request):
+ d = {}
+
+ if 'text' in request.POST:
+ text = request.POST['text']
+ else:
+ text = None
+
+ #return HttpResponse(json.dumps(request.POST.items()), 'text/plain')
+ if text is None or text.strip() == '':
+ d['mode'] = 'Error'
+ d['status'] = 'Did not recieve text'
+ return HttpResponse(json.dumps(d), 'text/plain')
+
+ if text.split('|')[0] == 'url':
+ d['mode'] = 'redirect'
+ d['url'] = text.split('|')[1]
+ else:
+ d['msg'] = 'Recieved text: %s' % (text)
+ d['mode'] = 'clear'
+
+ return HttpResponse(json.dumps(d), 'text/plain')
--- /dev/null
+from django.contrib import admin
+from django.utils.translation import ugettext_lazy as _
+
+
--- /dev/null
+from django import forms
+from django.forms.util import ErrorList
+
+
+SPECIES_LIST = [#('--choose--', '--Choose--'),
+ ('hg18', 'Homo sapiens (Hg18)'),
+ ('Mm8', 'Mus musculus (Mm8)'),
+ ('arabv6', 'Arabadopsis Thaliana v6'),
+ ('other', 'Other species (Include in description)')]
+
+
+class DivErrorList(ErrorList):
+ def __unicode__(self):
+ return self.as_divs()
+
+ def as_divs(self):
+ if not self: return u''
+ return u'<div class="errorlist">%s</div>' % (''.join([u'<div class="error">%s</div>' % e for e in self]))
+
+
+
+class ConfigForm(forms.Form):
+
+ flow_cell_number = forms.CharField(min_length=2)
+ run_date = forms.DateTimeField()
+ advanced_run = forms.BooleanField(required=False)
+ read_length = forms.IntegerField(min_value=1, initial=32)
+ #eland_repeat = forms.BooleanField()
+
+ #needs a for loop or something to allow for n configurations
+ #analysis_type = forms.ChoiceField(choices=[('eland','eland')])
+ lane1_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane1_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane2_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane2_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane3_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane3_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane4_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane4_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane5_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane5_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane6_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane6_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane7_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane7_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane8_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane8_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ notes = forms.CharField(widget=forms.Textarea(attrs={'cols':'70'}), required=False)
+
+ #lane_specific_read_length = forms.IntegerField(min_value=1)
+
+ #eland_genome_lanes = forms.MultipleChoiceField(choices=[('lane1','1'),
+ # ('lane2','2'),
+ # ('lane3','3'),
+ # ('lane4','4'),
+ # ('lane5','5'),
+ # ('lane6','6'),
+ # ('lane7','7'),
+ # ('lane8','8') ])
+
+ #eland_genome = forms.ChoiceField(choices=)
+
+ #use_bases_lanes = forms.MultipleChoiceField(choices=[('lane1','1'),
+ # ('lane2','2'),
+ # ('lane3','3'),
+ # ('lane4','4'),
+ # ('lane5','5'),
+ # ('lane6','6'),
+ # ('lane7','7'),
+ # ('lane8','8') ])
+
+ #use_bases_mask = forms.CharField()
+
+ #sequence_format = forms.ChoiceField(choices=[('scarf', 'scarf')])
+
+
+
+ #subject = forms.CharField(max_length=100)
+ #message = forms.CharField()
+ #sender = forms.EmailField()
+ #cc_myself = forms.BooleanField()
+
+ def as_custom(self):
+ """
+ Displays customized html output
+ """
+ html = []
+
+ fcn = self['flow_cell_number']
+
+ html.append(fcn.label_tag() + ': ' + str(fcn) + str(fcn.errors) + '<br />')
+
+ run_date = self['run_date']
+ html.append(run_date.label_tag() + ': ' + str(run_date) + str(run_date.errors) + '<br />')
+
+ arun = self['advanced_run']
+ html.append(arun.label_tag() + ': ' + str(arun) + str(arun.errors) + '<br />')
+
+ rl = self['read_length']
+ html.append(rl.label_tag() + ': ' + str(rl) + str(rl.errors) + '<br /><br />')
+
+ html.append('<table border="0">')
+ html.append(' <tr><td>%s</td><td>%s</td><td>%s</td></tr>' \
+ % ('Lane', 'Species', 'Description'))
+
+ l1s = self['lane1_species']
+ l1d = self['lane1_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('1', str(l1s), str(l1s.errors), str(l1d), str(l1d.errors)))
+
+ l2s = self['lane2_species']
+ l2d = self['lane2_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('2', str(l2s), str(l2s.errors), str(l2d), str(l2d.errors)))
+
+ l3s = self['lane3_species']
+ l3d = self['lane3_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('3', str(l3s), str(l3s.errors), str(l3d), str(l3d.errors)))
+
+ l4s = self['lane4_species']
+ l4d = self['lane4_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('4', str(l4s), str(l4s.errors), str(l4d), str(l4d.errors)))
+
+ l5s = self['lane5_species']
+ l5d = self['lane5_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('5', str(l5s), str(l5s.errors), str(l5d), str(l5d.errors)))
+
+ l6s = self['lane6_species']
+ l6d = self['lane6_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('6', str(l6s), str(l6s.errors), str(l6d), str(l6d.errors)))
+
+ l7s = self['lane7_species']
+ l7d = self['lane7_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('7', str(l7s), str(l7s.errors), str(l7d), str(l7d.errors)))
+
+ l8s = self['lane8_species']
+ l8d = self['lane8_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('8', str(l8s), str(l8s.errors), str(l8d), str(l8d.errors)))
+
+ html.append('</table><br />')
+
+ notes = self['notes']
+ html.append('<p>Notes:</p>')
+ html.append(' %s<br />' % (str(notes)))
+
+ return '\n'.join(html)
+
+
+
--- /dev/null
+from django.db import models
+
+# Create your models here.
--- /dev/null
+from django.conf.urls import patterns, url
+
+urlpatterns = patterns('',
+ ## Example:
+
+ url(r'^(?P<flowcell>\w+)/$', 'eland_config.views.config'),
+ url(r'^$', 'eland_config.views.config'),
+ #url(r'^$', 'htsworkflow.frontend.eland_config.views.index')
+
+)
--- /dev/null
+from __future__ import absolute_import, print_function
+
+from django.conf import settings
+from django.http import HttpResponse
+from django.core.exceptions import ObjectDoesNotExist
+
+from experiments import models
+
+import os
+
+
+def _validate_input(data):
+ return data.replace('..', '').replace('/', '_').replace('\\', '_')
+
+
+def getElandConfig(flowcell, regenerate=False):
+
+ if hasattr(settings, 'UPLOADTO_CONFIG_FILE'):
+ dest = settings.UPLOADTO_CONFIG_FILE
+ else:
+ dest = '/tmp'
+ file_path = os.path.join(dest, flowcell)
+
+ #If we are regenerating the config file, skip
+ # reading of existing file. If the file doesn't
+ # exist, try to generate it form the DB.
+ if not regenerate and os.path.isfile(file_path):
+ f = open(file_path, 'r')
+ data = f.read()
+ f.close()
+ return data
+
+ try:
+ fcObj = models.FlowCell.objects.get(flowcell_id__iexact=flowcell)
+ except ObjectDoesNotExist:
+ return None
+
+ data = []
+
+ #form = form.cleaned_data
+
+ data.append("# FLOWCELL: %s" % (fcObj.flowcell_id))
+ data.append("#")
+
+ notes = fcObj.notes.replace('\r\n', '\n').replace('\r', '\n')
+ notes = notes.replace('\n', '\n# ')
+ data.append("# NOTES:")
+ data.append("# %s\n#" % (notes))
+
+ #Convert all newline conventions to unix style
+ for lane in fcObj.lane_set.all():
+ data.append("# Lane%d: %s | %s" %
+ (lane.lane_number, unicode(lane.library.id),
+ lane.library.library_name.replace('%', '%%')))
+
+ read_length = fcObj.read_length
+ #data.append("ELAND_REPEAT")
+ data.append("ELAND_MULTIPLE_INSTANCES 8")
+
+ #Construct genome dictionary to figure out what lanes to put
+ # in the config file.
+ genome_dict = {}
+
+ #l1s = form['lane1_species']
+ for lane in fcObj.lane_set.all():
+ species = lane.library.library_species.scientific_name
+ genome_dict.setdefault(species, []).append(unicode(lane.lane_number))
+
+ genome_list = genome_dict.keys()
+ genome_list.sort()
+
+ #Loop through and create entries for each species.
+ for genome in genome_list:
+ lanes = ''.join(genome_dict[genome])
+ if fcObj.paired_end:
+ data.append('%s:ANALYSIS eland_pair' % (lanes))
+ else:
+ data.append('%s:ANALYSIS eland_extended' % (lanes))
+ data.append('%s:READ_LENGTH %s' % (lanes, read_length))
+ data.append('%s:ELAND_GENOME %s' % (lanes, '%%(%s)s' % (genome)))
+ data.append('%s:USE_BASES %s' % (lanes, 'Y'*int(read_length)))
+
+ data.append('SEQUENCE_FORMAT --fastq')
+ data.append('') # want a trailing newline
+
+ data = '\n'.join(data)
+
+ f = open(file_path, 'w')
+ f.write(data)
+ f.close()
+
+ return data
+
+
+def config(request, flowcell=None):
+ """
+ Returns eland config file for a given flowcell number,
+ or returns a list of available flowcell numbers.
+ """
+
+ # Provide INDEX of available Flowcell config files.
+ if flowcell is None:
+ fc_list = [fc.flowcell_id for fc in models.FlowCell.objects.all()]
+
+ #Convert FC* list to html links
+ fc_html = ['<a href="/eland_config/%s/">%s</a>' % (fc_name, fc_name)
+ for fc_name in fc_list]
+
+ return HttpResponse('<br />'.join(fc_html))
+
+ #FIXME: Should validate flowcell input before using.
+ flowcell = _validate_input(flowcell)
+ cfg = getElandConfig(flowcell, regenerate=True)
+
+ if not cfg:
+ return HttpResponse(
+ "Hmm, config file for %s does not seem to exist." % (flowcell))
+
+ return HttpResponse(cfg, mimetype="text/plain")
--- /dev/null
+from __future__ import absolute_import, print_function
+
+from itertools import chain
+
+from django.contrib import admin
+from django.contrib.admin.widgets import FilteredSelectMultiple
+from django.forms import ModelForm
+from django.forms.fields import Field, CharField
+from django.forms.widgets import TextInput, Select
+from django.utils.encoding import force_unicode
+from django.utils.html import escape, conditional_escape
+from django.utils.translation import ugettext_lazy as _
+
+from .models import \
+ FlowCell, DataRun, DataFile, FileType, ClusterStation, Sequencer, Lane
+
+class DataFileForm(ModelForm):
+ class Meta:
+ model = DataFile
+ fields = ('random_key', 'data_run', 'library', 'file_type', 'relative_pathname')
+
+class DataFileInline(admin.TabularInline):
+ model = DataFile
+ form = DataFileForm
+ raw_id_fields = ('library',)
+ extra = 0
+
+class DataRunOptions(admin.ModelAdmin):
+ search_fields = [
+ 'flowcell_id',
+ 'run_folder',
+ 'run_note',
+ ]
+ list_display = [
+ 'runfolder_name',
+ 'result_dir',
+ 'run_start_time',
+ ]
+ fieldsets = (
+ (None, {
+ 'fields': (('flowcell', 'run_status'),
+ ('runfolder_name', 'cycle_start', 'cycle_stop'),
+ ('result_dir',),
+ ('last_update_time'),
+ ('image_software', 'image_version'),
+ ('basecall_software', 'basecall_version'),
+ ('alignment_software', 'alignment_version'),
+ ('comment',))
+ }),
+ )
+ inlines = [ DataFileInline ]
+ #list_filter = ('run_status', 'run_start_time')
+admin.site.register(DataRun, DataRunOptions)
+
+
+class FileTypeAdmin(admin.ModelAdmin):
+ list_display = ('name', 'mimetype', 'regex')
+admin.site.register(FileType, FileTypeAdmin)
+
+# lane form setup needs to come before Flowcell form config
+# as flowcell refers to the LaneInline class
+class LaneForm(ModelForm):
+ comment = CharField(widget=TextInput(attrs={'size':'80'}), required=False)
+
+ class Meta:
+ model = Lane
+ fields = ('flowcell', 'lane_number', 'library', 'pM', 'cluster_estimate',
+ 'status', 'comment')
+
+class LaneInline(admin.StackedInline):
+ """
+ Controls display of Lanes on the Flowcell form.
+ """
+ model = Lane
+ extra = 8
+ form = LaneForm
+ raw_id_fields = ('library',)
+ fieldsets = (
+ (None, {
+ 'fields': ('lane_number', 'flowcell',
+ ('library',),
+ ('pM', 'cluster_estimate', 'status'),
+ 'comment',)
+ }),
+ )
+
+class LaneOptions(admin.ModelAdmin):
+ """
+ Controls display of Lane browser
+ """
+ search_fields = ('=flowcell__flowcell_id', 'library__id', 'library__library_name' )
+ list_display = ('flowcell', 'lane_number', 'library', 'comment')
+ fieldsets = (
+ (None, {
+ 'fields': ('lane_number', 'flowcell',
+ ('library'),
+ ('pM', 'cluster_estimate'))
+ }),
+ ('Optional', {
+ 'classes': ('collapse', ),
+ 'fields': ('comment', )
+ }),
+ )
+admin.site.register(Lane, LaneOptions)
+
+class FlowCellOptions(admin.ModelAdmin):
+ class Media:
+ css = { 'all': ('css/admin_flowcell.css',) }
+ date_hierarchy = "run_date"
+ save_on_top = True
+ search_fields = ('flowcell_id',
+ 'sequencer__name',
+ 'cluster_station__name',
+ '=lane__library__id',
+ 'lane__library__library_name')
+ list_display = ('flowcell_id','run_date','Lanes')
+ list_filter = ('sequencer','cluster_station', 'paired_end')
+ fieldsets = (
+ (None, {
+ 'fields': ('run_date', ('flowcell_id','cluster_station','sequencer'),
+ ('read_length', 'control_lane', 'paired_end'),)
+ }),
+ ('Notes:', { 'fields': ('notes',),}),
+ )
+ inlines = [
+ LaneInline,
+ ]
+
+ def formfield_for_dbfield(self, db_field, **kwargs):
+ field = super(FlowCellOptions, self).formfield_for_dbfield(db_field,
+ **kwargs)
+
+ # Override field attributes
+ if db_field.name == 'sequencer':
+ # seems kind of clunky.
+ # the goal is to replace the default select/combo box with one
+ # that can strike out disabled options.
+ attrs = field.widget.widget.attrs
+ field.widget.widget = SequencerSelect(attrs=attrs, queryset=field.queryset)
+ elif db_field.name == "notes":
+ field.widget.attrs["rows"] = "3"
+ return field
+admin.site.register(FlowCell, FlowCellOptions)
+
+class ClusterStationOptions(admin.ModelAdmin):
+ list_display = ('name', 'isdefault',)
+ fieldsets = ( ( None, { 'fields': ( 'name', 'isdefault') } ), )
+admin.site.register(ClusterStation, ClusterStationOptions)
+
+class SequencerSelect(Select):
+ def __init__(self, queryset=None, *args, **kwargs):
+ super(SequencerSelect, self).__init__(*args, **kwargs)
+ self.queryset = queryset
+
+ def render_options(self, choices, selected_choices):
+ # Normalize to strings.
+ selected_choices = set([force_unicode(v) for v in selected_choices])
+ output = []
+ for option_value, option_label in chain(self.choices, choices):
+ if isinstance(option_label, (list, tuple)):
+ output.append(u'<optgroup label="%s">' % escape(force_unicode(option_value)))
+ for option in option_label:
+ output.append(self.render_option(selected_choices, *option))
+ output.append(u'</optgroup>')
+ else:
+ output.append(self.render_option(selected_choices, option_value, option_label))
+ return u'\n'.join(output)
+
+ # render_options blatently grabbed from 1.3.1 as the 1.2 version
+ # has render_option, which is what I needed to overload as a
+ # nested function in render_options
+ def render_options(self, choices, selected_choices):
+ # Normalize to strings.
+ selected_choices = set([force_unicode(v) for v in selected_choices])
+ output = []
+ for option_value, option_label in chain(self.choices, choices):
+ if isinstance(option_label, (list, tuple)):
+ output.append(u'<optgroup label="%s">' % escape(force_unicode(option_value)))
+ for option in option_label:
+ output.append(self.render_option(selected_choices, *option))
+ output.append(u'</optgroup>')
+ else:
+ output.append(self.render_option(selected_choices, option_value, option_label))
+ return u'\n'.join(output)
+
+
+ def render_option(self, selected_choices, option_value, option_label):
+ disabled_sequencers = [ unicode(s.id) for s in self.queryset.filter(active=False) ]
+ option_value = unicode(option_value)
+ selected_html = (option_value in selected_choices) and u' selected="selected"' or ''
+ cssclass = "strikeout" if option_value in disabled_sequencers else ''
+ return u'<option class="%s" value="%s"%s>%s</option>' % (
+ cssclass, escape(option_value), selected_html,
+ conditional_escape(force_unicode(option_label)))
+
+class SequencerOptions(admin.ModelAdmin):
+ list_display = ('name', 'active', 'isdefault', 'instrument_name', 'model')
+ fieldsets = ( ( None,
+ { 'fields': (
+ 'name', ('active', 'isdefault'), 'instrument_name', 'serial_number',
+ 'model', 'comment') } ), )
+
+admin.site.register(Sequencer, SequencerOptions)
--- /dev/null
+from __future__ import absolute_import, print_function
+
+# some core functions of the exp tracker module
+from datetime import datetime, timedelta
+try:
+ import json
+except ImportError, e:
+ import simplejson as json
+
+import os
+import re
+
+from django.contrib.auth.decorators import login_required
+from django.views.decorators.csrf import csrf_exempt
+from django.core.exceptions import ObjectDoesNotExist
+from django.core.mail import send_mail, mail_admins
+from django.http import HttpResponse, Http404
+from django.conf import settings
+from django.utils import timezone
+
+from htsworkflow.auth import require_api_key
+from .models import FlowCell, DataRun, Lane, LANE_STATUS_MAP
+from samples.models import Library, MultiplexIndex, HTSUser
+
+def flowcell_information(flowcell_id):
+ """
+ Return a dictionary describing a flowcell
+ """
+ try:
+ fc = FlowCell.objects.get(flowcell_id__startswith=flowcell_id)
+ except FlowCell.DoesNotExist, e:
+ return None
+
+ lane_set = {}
+ for lane in fc.lane_set.all():
+ lane_item = {
+ 'cluster_estimate': lane.cluster_estimate,
+ 'comment': lane.comment,
+ 'experiment_type': lane.library.experiment_type.name,
+ 'experiment_type_id': lane.library.experiment_type_id,
+ 'flowcell': lane.flowcell.flowcell_id,
+ 'lane_number': lane.lane_number,
+ 'library_name': lane.library.library_name,
+ 'library_id': lane.library.id,
+ 'library_species': lane.library.library_species.scientific_name,
+ 'pM': unicode(lane.pM),
+ 'read_length': lane.flowcell.read_length,
+ 'status_code': lane.status,
+ 'status': LANE_STATUS_MAP[lane.status]
+ }
+ sequences = lane.library.index_sequences()
+ if sequences is not None:
+ lane_item['index_sequence'] = sequences
+
+ lane_set.setdefault(lane.lane_number,[]).append(lane_item)
+
+ if fc.control_lane is None:
+ control_lane = None
+ else:
+ control_lane = int(fc.control_lane)
+
+ info = {
+ 'advanced_run': fc.advanced_run,
+ 'cluster_station_id': fc.cluster_station_id,
+ 'cluster_station': fc.cluster_station.name,
+ 'control_lane': control_lane,
+ # 'datarun_set': how should this be represented?,
+ 'flowcell_id': fc.flowcell_id,
+ 'id': fc.id,
+ 'lane_set': lane_set,
+ 'notes': fc.notes,
+ 'paired_end': fc.paired_end,
+ 'read_length': fc.read_length,
+ 'run_date': fc.run_date.isoformat(),
+ 'sequencer_id': fc.sequencer_id,
+ 'sequencer': fc.sequencer.name,
+ }
+
+ return info
+
+@csrf_exempt
+def flowcell_json(request, fc_id):
+ """
+ Return a JSON blob containing enough information to generate a config file.
+ """
+ require_api_key(request)
+
+ fc_dict = flowcell_information(fc_id)
+
+ if fc_dict is None:
+ raise Http404
+
+ fc_json = json.dumps(fc_dict)
+ return HttpResponse(fc_json, content_type = 'application/json')
+
+def lanes_for(username=None):
+ """
+ Given a user id try to return recent lanes as a list of dictionaries
+ """
+ query = {}
+ if username is not None:
+ user = HTSUser.objects.get(username=username)
+ query.update({'library__affiliations__users__id': user.id})
+
+ lanes = Lane.objects.filter(**query).order_by('-flowcell__run_date')
+
+
+ result = []
+ for l in lanes:
+ affiliations = l.library.affiliations.all()
+ affiliations_list = [(a.id, a.name) for a in affiliations]
+ result.append({ 'flowcell': l.flowcell.flowcell_id,
+ 'run_date': l.flowcell.run_date.isoformat(),
+ 'lane_number': l.lane_number,
+ 'library': l.library.id,
+ 'library_name': l.library.library_name,
+ 'comment': l.comment,
+ 'affiliations': affiliations_list})
+ return result
+
+@csrf_exempt
+def lanes_for_json(request, username):
+ """
+ Format lanes for a user
+ """
+ require_api_key(request)
+
+ try:
+ result = lanes_for(username)
+ except ObjectDoesNotExist, e:
+ raise Http404
+
+ #convert query set to python structure
+
+ result_json = json.dumps(result)
+ return HttpResponse(result_json, content_type='application/json')
+
+
+def updStatus(request):
+ output=''
+ user = 'none'
+ pswd = ''
+ UpdatedStatus = 'unknown'
+ fcid = 'none'
+ runfolder = 'unknown'
+ ClIP = request.META['REMOTE_ADDR']
+
+ if hasattr(request, 'user'):
+ user = request.user
+
+ #Check access permission
+ if not (user.is_superuser and settings.ALLOWED_IPS.has_key(ClIP)):
+ return HttpResponse("%s access denied from %s." % (user, ClIP))
+
+ # ~~~~~~Parameters for the job ~~~~
+ if request.REQUEST.has_key('fcid'):
+ fcid = request.REQUEST['fcid']
+ else:
+ return HttpResponse('missing fcid')
+
+ if request.REQUEST.has_key('runf'):
+ runfolder = request.REQUEST['runf']
+ else:
+ return HttpResponse('missing runf')
+
+
+ if request.REQUEST.has_key('updst'):
+ UpdatedStatus = request.REQUEST['updst']
+ else:
+ return HttpResponse('missing status')
+
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ # Update Data Run status in DB
+ # Try get rec. If not found return 'entry not found + <fcid><runfolder>', if found try update and return updated
+ try:
+ rec = DataRun.objects.get(run_folder=runfolder)
+ rec.run_status = UpdatedStatus
+
+ #if there's a message update that too
+ mytimestamp = timezone.now().__str__()
+ mytimestamp = re.sub(pattern=":[^:]*$",repl="",string=mytimestamp)
+ if request.REQUEST.has_key('msg'):
+ rec.run_note += ", "+request.REQUEST['msg']+" ("+mytimestamp+")"
+ else :
+ if UpdatedStatus == '1':
+ rec.run_note = "Started ("+mytimestamp+")"
+
+ rec.save()
+ output = "Hello "+settings.ALLOWED_IPS[ClIP]+". Updated to:'"+DataRun.RUN_STATUS_CHOICES[int(UpdatedStatus)][1].__str__()+"'"
+ except ObjectDoesNotExist:
+ output = "entry not found: "+fcid+", "+runfolder
+
+
+ #Notify researcher by email
+ # Doesn't work
+ #send_mail('Exp Tracker', 'Data Run Status '+output, 'rrauch@stanford.edu', ['rrrami@gmail.com'], fail_silently=False)
+ #mail_admins("test subject", "testing , testing", fail_silently=False)
+ # gives error: (49, "Can't assign requested address")
+ return HttpResponse(output)
+
+def generateConfile(request,fcid):
+ #granted = False
+ #ClIP = request.META['REMOTE_ADDR']
+ #if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
+
+ #if not granted: return HttpResponse("access denied.")
+
+ config = ['READ_LENGTH 25']
+ config += ['ANALYSIS eland']
+ config += ['GENOME_FILE all_chr.fa']
+ config += ['ELAND_MULTIPLE_INSTANCES 8']
+ genome_dir = 'GENOME_DIR /Volumes/Genomes/'
+ eland_genome = 'ELAND_GENOME /Volumes/Genomes/'
+
+ try:
+ fc = FlowCell.objects.get(flowcell_id=fcid)
+ for lane in fc.lane_set.all():
+ config += [ str(lane.lane_number) +":" + \
+ genome_dir + lane.library.library_species.scientific_name ]
+ config += [ str(lane.lane_number) +":" + \
+ eland_genome + lane.library.library_species.scientific_name ]
+
+ except ObjectDoesNotExist:
+ config = 'Entry not found for fcid = '+fcid
+
+ return os.linesep.join(config)
+
+def getConfile(req):
+ granted = False
+ ClIP = req.META['REMOTE_ADDR']
+ if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
+
+ if not granted: return HttpResponse("access denied. IP: "+ClIP)
+
+ fcid = 'none'
+ cnfgfile = 'Nothing found'
+ runfolder = 'unknown'
+ request = req.REQUEST
+ if request.has_key('fcid'):
+ fcid = request['fcid']
+ if request.has_key('runf'):
+ runfolder = request['runf']
+ try:
+ rec = DataRun.objects.get(run_folder=runfolder) #,flowcell_id=fcid)
+ cnfgfile = rec.config_params
+ #match_str = re.compile(r"READ_LENGTH.+$")
+ match_str = re.compile('^READ_LENGTH.+')
+ if not match_str.search(cnfgfile):
+ cnfgfile = generateConfile(request,fcid)
+ if match_str.search(cnfgfile):
+ rec = DataRun.objects.get(run_folder=runfolder) #,flowcell_id=fcid)
+ rec.config_params = cnfgfile
+ rec.save()
+ else:
+ cnfgfile = 'Failed generating config params for RunFolder = '+runfolder +', Flowcell id = '+ fcid+ ' Config Text:\n'+cnfgfile
+
+ except ObjectDoesNotExist:
+ cnfgfile = 'Entry not found for RunFolder = '+runfolder
+
+ return HttpResponse(cnfgfile, content_type='text/plain')
+
+def getLaneLibs(req):
+ granted = False
+ ClIP = req.META['REMOTE_ADDR']
+ if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
+
+ if not granted: return HttpResponse("access denied.")
+
+ request = req.REQUEST
+ fcid = 'none'
+ outputfile = ''
+ if request.has_key('fcid'):
+ fcid = request['fcid']
+ try:
+ rec = FlowCell.objects.get(flowcell_id=fcid)
+ #Ex: 071211
+ year = datetime.today().year.__str__()
+ year = replace(year,'20','')
+ month = datetime.today().month
+ if month < 10: month = "0"+month.__str__()
+ else: month = month.__str__()
+ day = datetime.today().day
+ if day < 10: day = "0"+day.__str__()
+ else: day = day.__str__()
+ mydate = year+month+day
+ outputfile = '<?xml version="1.0" ?>'
+ outputfile += '\n<SolexaResult Date="'+mydate+'" Flowcell="'+fcid+'" Client="'+settings.ALLOWED_IPS[ClIP]+'">'
+ outputfile += '\n<Lane Index="1" Name="'+rec.lane_1_library.library_name+'" Library="'+rec.lane_1_library.id+'" Genome="'+rec.lane_1_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="2" Name="'+rec.lane_2_library.library_name+'" Library="'+rec.lane_2_library.id+'" Genome="'+rec.lane_2_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="3" Name="'+rec.lane_3_library.library_name+'" Library="'+rec.lane_3_library.id+'" Genome="'+rec.lane_3_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="4" Name="'+rec.lane_4_library.library_name+'" Library="'+rec.lane_4_library.id+'" Genome="'+rec.lane_4_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="5" Name="'+rec.lane_5_library.library_name+'" Library="'+rec.lane_5_library.id+'" Genome="'+rec.lane_5_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="6" Name="'+rec.lane_6_library.library_name+'" Library="'+rec.lane_6_library.id+'" Genome="'+rec.lane_6_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="7" Name="'+rec.lane_7_library.library_name+'" Library="'+rec.lane_7_library.id+'" Genome="'+rec.lane_7_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="8" Name="'+rec.lane_8_library.library_name+'" Library="'+rec.lane_8_library.id+'" Genome="'+rec.lane_8_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n</SolexaResult>'
+ except ObjectDoesNotExist:
+ outputfile = 'Flowcell entry not found for: '+fcid
+ else: outputfile = 'Missing input: flowcell id'
+
+ return HttpResponse(outputfile, content_type='text/plain')
+
+def estimateFlowcellDuration(flowcell):
+ """
+ Attempt to estimate how long it will take to run a flowcell
+
+ """
+ # (3600 seconds * 1.5 hours per cycle )
+ sequencing_seconds_per_cycle= 3600 * 1.5
+ # 800 is a rough guess
+ pipeline_seconds_per_cycle = 800
+
+ cycles = flowcell.read_length
+ if flowcell.paired_end:
+ cycles *= 2
+ sequencing_time = timedelta(0, cycles * sequencing_seconds_per_cycle)
+ analysis_time = timedelta(0, cycles * pipeline_seconds_per_cycle)
+ estimate_mid = sequencing_time + analysis_time
+
+ return estimate_mid
+
+def estimateFlowcellTimeRemaining(flowcell):
+ estimate_mid = estimateFlowcellDuration(flowcell)
+
+ # offset for how long we've been running
+ running_time = timezone.now() - flowcell.run_date
+ estimate_mid -= running_time
+
+ return estimate_mid
+
+def roundToDays(estimate):
+ """
+ Given a time estimate round up and down in days
+ """
+ # floor estimate_mid
+ estimate_low = timedelta(estimate.days, 0)
+ # floor estimate_mid and add a day
+ estimate_high = timedelta(estimate.days+1, 0)
+
+ return (estimate_low, estimate_high)
+
+
+def makeUserLaneMap(flowcell):
+ """
+ Given a flowcell return a mapping of users interested in
+ the libraries on those lanes.
+ """
+ users = {}
+
+ for lane in flowcell.lane_set.all():
+ for affiliation in lane.library.affiliations.all():
+ for user in affiliation.users.all():
+ users.setdefault(user,[]).append(lane)
+
+ return users
+
+def getUsersForFlowcell(flowcell):
+ users = set()
+
+ for lane in flowcell.lane_set.all():
+ for affiliation in lane.library.affiliations.all():
+ for user in affiliation.users.all():
+ users.add(user)
+
+ return users
+
+def makeUserLibraryMap(libraries):
+ """
+ Given an interable set of libraries return a mapping or
+ users interested in those libraries.
+ """
+ users = {}
+
+ for library in libraries:
+ for affiliation in library.affiliations.all():
+ for user in affiliation.users.all():
+ users.setdefault(user,[]).append(library)
+
+ return users
+
+def makeAffiliationLaneMap(flowcell):
+ affs = {}
+
+ for lane in flowcell.lane_set.all():
+ for affiliation in lane.library.affiliations.all():
+ affs.setdefault(affiliation,[]).append(lane)
+
+ return affs
+
+def makeEmailLaneMap(flowcell):
+ """
+ Create a list of email addresses and the lanes associated with those users.
+
+ The email addresses can come from both the "users" table and the "affiliations" table.
+ """
+ emails = {}
+ for lane in flowcell.lane_set.all():
+ for affiliation in lane.library.affiliations.all():
+ if affiliation.email is not None and len(affiliation.email) > 0:
+ emails.setdefault(affiliation.email,set()).add(lane)
+ for user in affiliation.users.all():
+ if user.email is not None and len(user.email) > 0:
+ emails.setdefault(user.email,set()).add(lane)
+
+ return emails
--- /dev/null
+[
+ { "model": "experiments.FileType",
+ "pk": 1,
+ "fields": {
+ "name": "run_xml",
+ "mimetype": "application/vnd.htsworkflow-run-xml",
+ "regex": "run.*\\.xml\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 2,
+ "fields": {
+ "name": "Summary.htm",
+ "mimetype": "text/html",
+ "regex": "Summary\\.htm\\Z(?ms)"
+ }
+ },
+
+ { "model": "experiments.FileType",
+ "pk": 3,
+ "fields": {
+ "name": "IVC All",
+ "mimetype": "image/png",
+ "regex": "s_(?P<lane>[0-9])_all\\.png\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 4,
+ "fields": {
+ "name": "IVC Call",
+ "mimetype": "image/png",
+ "regex": "s_(?P<lane>[0-9])_call\\.png\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 5,
+ "fields": {
+ "name": "IVC Percent All",
+ "mimetype": "image/png",
+ "regex": "s_(?P<lane>[0-9])_percent_all\\.png\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 6,
+ "fields": {
+ "name": "IVC Percent Base",
+ "mimetype": "image/png",
+ "regex": "s_(?P<lane>[0-9])_percent_base\\.png\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 7,
+ "fields": {
+ "name": "IVC Percent Call",
+ "mimetype": "image/png",
+ "regex": "s_(?P<lane>[0-9])_percent_call\\.png\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 8,
+ "fields": {
+ "name": "GERALD Scores",
+ "regex": "scores\\.tar\\.bz2\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 9,
+ "fields": {
+ "name": "ELAND Result",
+ "mimetype": "chemical/seq-na-eland",
+ "regex": "s_(?P<lane>[0-9])((?P<end>[1-4])_)?_eland_result\\.txt\\.bz2\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 10,
+ "fields": {
+ "name": "ELAND Multi",
+ "mimetype": "chemical/seq-na-eland",
+ "regex": "s_(?P<lane>[0-9])((?P<end>[1-4])_)?_eland_multi\\.txt\\.bz2\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 11,
+ "fields": {
+ "name": "ELAND Extended",
+ "mimetype": "chemical/seq-na-eland",
+ "regex": "s_(?P<lane>[0-9])((?P<end>[1-4])_)?_eland_extended\\.txt\\.bz2\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 12,
+ "fields": {
+ "name": "ELAND Export",
+ "mimetype": "chemical/seq-na-eland",
+ "regex": "s_(?P<lane>[0-9])((?P<end>[1-4])_)?_export\\.txt\\.bz2\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 13,
+ "fields": {
+ "name": "SRF",
+ "mimetype": "chemical/seq-na-srf",
+ "regex": ".*_(?P<lane>[1-8])\\.srf\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 14,
+ "fields": {
+ "name": "QSEQ tarfile",
+ "mimetype": "chemical/seq-na-qseq",
+ "regex": ".*_l(?P<lane>[1-8])_r(?P<end>[1-4])\\.tar\\.bz2\\Z(?ms)"
+ }
+ },
+ { "model": "experiments.FileType",
+ "pk": 15,
+ "fields": {
+ "name": "HiSeq Fastq",
+ "mimetype": "chemical/seq-na-fastq",
+ "regex": "(?P<library>[0-9]+)_(NoIndex|[AGCT]+)_L(?P<lane>[0-9]+)_R(?P<end>[12])_(?P<split>[0-9]+)\\.fastq\\.gz"
+ }
+ }
+]
--- /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-01T00:00:01-0800",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
+ "email": "",
+ "date_joined": "2009-01-01T00:01:01-0800"
+ }
+ },
+ {"pk": 5, "model": "samples.htsuser",
+ "fields" : {}
+ },
+ {"pk": 6, "model": "auth.user",
+ "fields": {
+ "username": "admintest",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": false,
+ "is_staff": true,
+ "last_login": "2009-01-01T00:00:01-0800",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
+ "email": "",
+ "date_joined": "2009-01-01T00:01:01-0800"
+ }
+ },
+ {"pk": 6, "model": "samples.htsuser",
+ "fields" : {}
+ },
+ {"pk": 7, "model": "auth.user",
+ "fields": {
+ "username": "supertest",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": true,
+ "is_staff": true,
+ "last_login": "2009-01-01T00:00:01-0800",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
+ "email": "",
+ "date_joined": "2009-01-01T00:01:01-0800"
+ }
+ },
+ {"pk": 7, "model": "samples.htsuser",
+ "fields" : {}
+ },
+ {"pk": 1, "model": "samples.affiliation",
+ "fields": {
+ "users": [5],
+ "contact": "group 1",
+ "name": "affiliation 1",
+ "email": "pk1@example.com"
+ }
+ },
+ {"pk": 2, "model": "samples.affiliation",
+ "fields": {
+ "users": [6],
+ "contact": "group 2",
+ "name": "affiliation 2",
+ "email": "pk2@example.com"
+ }
+ },
+ {"pk": 3, "model": "samples.affiliation",
+ "fields": {
+ "users": [],
+ "contact": "group 3",
+ "name": "affiliation 3",
+ "email": "pk3@example.com"
+ }
+ },
+ {"pk": 4, "model": "samples.affiliation",
+ "fields": {
+ "users": [],
+ "contact": "group 4",
+ "name": "affiliation 4",
+ "email": "pk1@example.com"
+ }
+ },
+ {"pk": 5, "model": "samples.affiliation",
+ "fields": {
+ "users": [],
+ "contact": "group 5",
+ "name": "affiliation 5",
+ "email": "pk5@example.com"
+ }
+ },
+ {"pk": 1, "model": "experiments.clusterstation",
+ "fields": {"name": "old", "isdefault": false}},
+ {"pk": 2, "model": "experiments.clusterstation",
+ "fields": {"name": "loaner", "isdefault": true}},
+ {"pk": 3, "model": "experiments.clusterstation",
+ "fields": {"name": "new", "isdefault": false}},
+ {"pk": 1, "model": "experiments.sequencer",
+ "fields": { "name": "Rotifer (HWI-EAS229)",
+ "model": "Illumina Genome Analyzer I",
+ "active": false,
+ "isdefault": false }},
+ {"pk": 2, "model": "experiments.sequencer",
+ "fields": {"name": "Tardigrade",
+ "instrument_name": "ILLUMINA-EC5D15",
+ "model": "Illumina Genome Analyzer IIx",
+ "active": true,
+ "isdefault": true}
+ },
+ {"pk": 3, "model": "experiments.sequencer",
+ "fields": {"name": "Sequenced somewhere else.",
+ "model": "Unknown",
+ "active": true,
+ "isdefault": false}},
+ {"pk": 153, "model": "experiments.flowcell",
+ "fields": {
+ "paired_end": true,
+ "run_date": "2007-09-27T22:12:13-0800",
+ "read_length": 36,
+ "notes": "",
+ "advanced_run": false,
+ "control_lane": 2,
+ "cluster_station": 3,
+ "sequencer": 2,
+ "flowcell_id": "FC12150"
+ }
+ },
+ {"pk": 1193, "model": "experiments.lane",
+ "fields": {
+ "comment": "No change in cluster numbers, despite slight increase in pM",
+ "library": "10981",
+ "cluster_estimate": 129000,
+ "flowcell": 153,
+ "lane_number": 1,
+ "pM": "8"
+ }
+ },
+ {"pk": 1192, "model": "experiments.lane",
+ "fields": {
+ "comment": "Other library",
+ "library": "11070",
+ "cluster_estimate": 132000,
+ "flowcell": 153,
+ "lane_number": 1,
+ "pM": "7"
+ }
+ },
+
+ {"pk": "10981", "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 400,
+ "library_name": "Paired End Multiplexed Sp-BAC",
+ "creation_date": "2009-07-21",
+ "cell_line": 1,
+ "library_species": 10,
+ "library_type": null,
+ "made_by": "Igor",
+ "affiliations": [
+ 1,2
+ ],
+ "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": 1194, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11016",
+ "cluster_estimate": 152000,
+ "flowcell": 153,
+ "lane_number": 2,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11006",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 325,
+ "library_name": "Paired End Pfl #3 MP 7/24/9",
+ "creation_date": "2009-08-05",
+ "cell_line": 1,
+ "library_species": 8,
+ "library_type": 2,
+ "made_by": "Lorian",
+ "affiliations": [
+ 3
+ ],
+ "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
+ }
+ },
+ {
+ "pk": "11016",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 325,
+ "library_name": "Paired End Pfl #3 MP 7/24/9 a",
+ "creation_date": "2009-08-06",
+ "cell_line": 1,
+ "library_species": 2,
+ "library_type": 2,
+ "made_by": "Lorian",
+ "affiliations": [
+ 2
+ ],
+ "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": 1195, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "SL039",
+ "cluster_estimate": 162000,
+ "flowcell": 153,
+ "lane_number": 3,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "SL039",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_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": [
+ 3,4
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "Brian Williams",
+ "amplified_from_sample": 11006,
+ "notes": "fragment size = 300 bp, Amicon filtered\r\nnanodrop: 56.3",
+ "undiluted_concentration": "28.7",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 1196, "model": "experiments.lane",
+ "fields": {
+ "comment": "This lane's library had the second lowest concentration of all the libraries built at the same time (2.05ng/ul)",
+ "library": "11060",
+ "cluster_estimate": 24000,
+ "flowcell": 153,
+ "lane_number": 4,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11060",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired ends 100 VC_CN_4_M_MBB1185_s1",
+ "creation_date": "2009-09-01",
+ "cell_line": 1,
+ "library_species": 8,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 5
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "Brian Williams",
+ "amplified_from_sample": 11006,
+ "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 24.2",
+ "undiluted_concentration": "2.05",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 1197, "model": "experiments.lane",
+ "fields": {
+ "comment": "stuff",
+ "library": "11061",
+ "cluster_estimate": 140000,
+ "flowcell": 153,
+ "lane_number": 5,
+ "pM": "7",
+ "status": 2
+ }
+ },
+ {
+ "pk": "11061",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired ends 101 VC_CN_4_M_MBB1185_s2",
+ "creation_date": "2009-09-01",
+ "cell_line": 1,
+ "library_species": 8,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 2,4
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "Brian Williams",
+ "amplified_from_sample": null,
+ "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 33.1",
+ "undiluted_concentration": "12.9",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 1198, "model": "experiments.lane",
+ "fields": {
+ "comment": "This lane's library had the lowest concentration of all the libraries built at the same time (1.2ng/ul)",
+ "library": "11062",
+ "cluster_estimate": 2000,
+ "flowcell": 153,
+ "lane_number": 6,
+ "pM": "7",
+ "status": 0
+ }
+ },
+ {
+ "pk": "11062",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired ends 102 VC_AU_8_M_MBB4721_s1",
+ "creation_date": "2009-09-01",
+ "cell_line": 1,
+ "library_species": 8,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 4,5
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "Brian Williams",
+ "amplified_from_sample": null,
+ "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 13.9",
+ "undiluted_concentration": "1.2",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 1199, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11063",
+ "cluster_estimate": 120000,
+ "flowcell": 153,
+ "lane_number": 7,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11063",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired ends 103 VC_AU_8_M_MBB4721_s2",
+ "creation_date": "2009-09-01",
+ "cell_line": 1,
+ "library_species": 8,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 1,3
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "Brian Williams",
+ "amplified_from_sample": null,
+ "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 46.9",
+ "undiluted_concentration": "24.5",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 1200, "model": "experiments.lane",
+ "fields": {
+ "comment": "This lane's library had the third lowest concentration of all the libraries built at the same time (5.21ng/ul), but gave perfectly normal cluster numbers",
+ "library": "11064",
+ "cluster_estimate": 157000,
+ "flowcell": 153,
+ "lane_number": 8,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11064",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired ends 104 VC_CN_7_M_MBB4898_s1",
+ "creation_date": "2009-09-01",
+ "cell_line": 1,
+ "library_species": 8,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 3,5
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "Brian Williams",
+ "amplified_from_sample": null,
+ "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 20.4",
+ "undiluted_concentration": "5.21",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 152, "model": "experiments.flowcell",
+ "fields": {
+ "paired_end": false,
+ "run_date": "2009-09-10T18:30:15-0800",
+ "read_length": 38,
+ "notes": "328461 4897273 RGT-0248815\r\n328479 4897265 RGT-0249274\r\n330421 4822845 SR-0005496",
+ "advanced_run": false,
+ "control_lane": 4,
+ "cluster_station": 3,
+ "sequencer": 1,
+ "flowcell_id": "42JTNAAXX"
+ }
+ },
+ {"pk": 1185, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11035",
+ "cluster_estimate": 174000,
+ "flowcell": 152,
+ "lane_number": 1,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11035",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired ends 95 Gilberto_d3_control_LTA",
+ "creation_date": "2009-08-25",
+ "cell_line": 1,
+ "library_species": 9,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 3
+ ],
+ "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: 67.1",
+ "undiluted_concentration": "28.5",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 1186, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11037",
+ "cluster_estimate": 173000,
+ "flowcell": 152,
+ "lane_number": 2,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11037",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired ends 97 Kuntz_PDHT",
+ "creation_date": "2009-08-25",
+ "cell_line": 1,
+ "library_species": 3,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 4
+ ],
+ "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: 52.7",
+ "undiluted_concentration": "25.5",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 1187, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11045",
+ "cluster_estimate": 198000,
+ "flowcell": 152,
+ "lane_number": 3,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11045",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 250,
+ "library_name": "FLDN1 8/3/9 anti-AcH3 chip B6 a",
+ "creation_date": "2009-08-26",
+ "cell_line": null,
+ "library_species": 9,
+ "library_type": 1,
+ "made_by": "Lorian",
+ "affiliations": [
+ 5
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "2A",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/21/2009 11:57:54\tColor: Yellow",
+ "undiluted_concentration": "20.5",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {"pk": 1188, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11046",
+ "cluster_estimate": 212000,
+ "flowcell": 152,
+ "lane_number": 4,
+ "pM": "7"}
+ },
+ {
+ "pk": "11046",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 250,
+ "library_name": "FLDN1 7/8/9 anti-DiMeH3K4 chip B6 a",
+ "creation_date": "2009-08-26",
+ "cell_line": null,
+ "library_species": 9,
+ "library_type": 1,
+ "made_by": "Lorian",
+ "affiliations": [
+ 4
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "2A",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/21/2009 11:57:54\tColor: Blue",
+ "undiluted_concentration": "23.9",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {"pk": 1189, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11054",
+ "cluster_estimate": 49000,
+ "flowcell": 152,
+ "lane_number": 5,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11054",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 225,
+ "library_name": "HNDHT HLH hnd-1 strain HT115 fed anti-hlh-1 2% fix plate a",
+ "creation_date": "2009-08-31",
+ "cell_line": null,
+ "library_species": 3,
+ "library_type": 1,
+ "made_by": "Lorian",
+ "affiliations": [
+ 1
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/26/2009 14:46:56\tColor: Purple",
+ "undiluted_concentration": "1.47",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {"pk": 1190, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11056",
+ "cluster_estimate": 48000,
+ "flowcell": 152,
+ "lane_number": 6,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11056",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 225,
+ "library_name": "HNDM3 HLH hnd-1 strain mex-3 fed anti-hlh-1 2% fix plate a",
+ "creation_date": "2009-08-31",
+ "cell_line": null,
+ "library_species": 3,
+ "library_type": 1,
+ "made_by": "Lorian",
+ "affiliations": [
+ 2
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/26/2009 14:46:56\tColor: Black",
+ "undiluted_concentration": "1.42",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {"pk": 1191, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11057",
+ "cluster_estimate": 4000,
+ "flowcell": 152,
+ "lane_number": 7,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11057",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 225,
+ "library_name": "HNDM3 4H8 hnd-1 strain mex-3 fed 4H8 2% fix plate a",
+ "creation_date": "2009-08-31",
+ "cell_line": null,
+ "library_species": 3,
+ "library_type": 1,
+ "made_by": "Lorian",
+ "affiliations": [
+ 3
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/26/2009 14:46:56\tColor: Orange.",
+ "undiluted_concentration": "1.3",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {"pk": 1192, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11065",
+ "cluster_estimate": 5000,
+ "flowcell": 152,
+ "lane_number": 8,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11065",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired ends 105 Kuntz PDM3",
+ "creation_date": "2009-09-01",
+ "cell_line": 1,
+ "library_species": 3,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 4
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "Brian Williams",
+ "amplified_from_sample": null,
+ "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 30.5",
+ "undiluted_concentration": "2.47",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 151, "model": "experiments.flowcell",
+ "fields": {
+ "paired_end": false,
+ "run_date": "2009-09-08T15:39:28-0800",
+ "read_length": 38,
+ "notes": "Rebuild of broken flowcell\r\n\r\n328461 4820241 RGT-0215719\r\n328479 4897265 RGT-0249510\r\n330421 4822845 SR-0005402\r\n",
+ "advanced_run": false,
+ "control_lane": 5,
+ "cluster_station": 3,
+ "sequencer": 2,
+ "flowcell_id": "42JU1AAXX"
+ }
+ },
+ {"pk": 1177, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11034",
+ "cluster_estimate": 177000,
+ "flowcell": 151,
+ "lane_number": 1,
+ "pM": "7"
+ }
+ },
+ {"pk": 1178, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11036",
+ "cluster_estimate": 169000,
+ "flowcell": 151,
+ "lane_number": 2,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11036",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired ends 96 Kuntz_PDE1",
+ "creation_date": "2009-08-25",
+ "cell_line": 1,
+ "library_species": 3,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 5
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "Brian Williams",
+ "amplified_from_sample": null,
+ "notes": "fragment size = 300 bp",
+ "undiluted_concentration": "30.6",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {
+ "pk": "11034",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired ends 94 Gilberto_d3_denerv_LTA",
+ "creation_date": "2009-08-25",
+ "cell_line": 1,
+ "library_species": 9,
+ "library_type": 2,
+ "made_by": "Brian Williams",
+ "affiliations": [
+ 1
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "Brian Williams",
+ "amplified_from_sample": null,
+ "notes": "fragment size = 300 bp",
+ "undiluted_concentration": "27",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {
+ "pk": "12044",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 225,
+ "library_name": "Pooled Indexed Test",
+ "creation_date": "2009-08-26",
+ "cell_line": null,
+ "library_species": 9,
+ "library_type": 5,
+ "multiplex_id": "1,2,3",
+ "made_by": "Lorian",
+ "affiliations": [
+ 2
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "2A",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/21/2009 11:57:54\tColor: Orange",
+ "undiluted_concentration": "22.4",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {
+ "pk": "13044",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 225,
+ "library_name": "Dual Indexed Test",
+ "creation_date": "2009-08-26",
+ "cell_line": null,
+ "library_species": 9,
+ "library_type": 9,
+ "multiplex_id": "N701-N501",
+ "made_by": "Lorian",
+ "affiliations": [
+ 2
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "2A",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/21/2009 11:57:54\tColor: Orange",
+ "undiluted_concentration": "22.4",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {
+ "pk": "11045",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 225,
+ "library_name": "Simple Indexed Test",
+ "creation_date": "2009-08-26",
+ "cell_line": null,
+ "library_species": 9,
+ "library_type": 5,
+ "multiplex_id": "1",
+ "made_by": "Lorian",
+ "affiliations": [
+ 2
+ ],
+ "replicate": 2,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "2A",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/21/2009 11:57:54\tColor: Orange",
+ "undiluted_concentration": "22.4",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {"pk": 1179,
+ "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "12044",
+ "cluster_estimate": 196000,
+ "flowcell": 151,
+ "lane_number": 3,
+ "pM": "7"
+ }
+ },
+ {"pk": 1279,
+ "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11045",
+ "cluster_estimate": 196000,
+ "flowcell": 151,
+ "lane_number": 3,
+ "pM": "7"
+ }
+ },
+ {"pk": 1379,
+ "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "13044",
+ "cluster_estimate": 196000,
+ "flowcell": 151,
+ "lane_number": 4,
+ "pM": "7"
+ }
+ },
+
+ {
+ "pk": "11044",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 225,
+ "library_name": "p300 60h C2 FA KF 12/22/8 a",
+ "creation_date": "2009-08-26",
+ "cell_line": null,
+ "library_species": 9,
+ "library_type": 1,
+ "made_by": "Lorian",
+ "affiliations": [
+ 3
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "2A",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/21/2009 11:57:54\tColor: Orange.",
+ "undiluted_concentration": "22.4",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {"pk": 1180, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11047",
+ "cluster_estimate": 200000,
+ "flowcell": 151,
+ "lane_number": 4,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11047",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 250,
+ "library_name": "FLDN1 7/8/9 anti-TriMeH3K27 chip B6 a",
+ "creation_date": "2009-08-26",
+ "cell_line": null,
+ "library_species": 9,
+ "library_type": 1,
+ "made_by": "Lorian",
+ "affiliations": [
+ 4
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "2A",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/21/2009 11:57:54\tColor: Green",
+ "undiluted_concentration": "24.9",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {"pk": 1181, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11055",
+ "cluster_estimate": 104000,
+ "flowcell": 151,
+ "lane_number": 5,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11055",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 225,
+ "library_name": "HNDHT 4H8 hnd-1 strain HT115 fed 4H8 2% fix plate a",
+ "creation_date": "2009-08-31",
+ "cell_line": null,
+ "library_species": 3,
+ "library_type": 1,
+ "made_by": "Lorian",
+ "affiliations": [
+ 5
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "8/26/2009 14:46:56\tColor: White.",
+ "undiluted_concentration": "2.17",
+ "successful_pM": null,
+ "experiment_type": 2,
+ "antibody": null
+ }
+ },
+ {"pk": 1182, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11067",
+ "cluster_estimate": 168000,
+ "flowcell": 151,
+ "lane_number": 6,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11067",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 325,
+ "library_name": "Paired End SP-BAC Barcoding test 250-300 bp",
+ "creation_date": "2009-09-03",
+ "cell_line": 1,
+ "library_species": 10,
+ "library_type": 2,
+ "made_by": "Igor",
+ "affiliations": [
+ 1
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "Done",
+ "tags": [],
+ "made_for": "Andy Cameron",
+ "amplified_from_sample": null,
+ "notes": "12 SP BACs",
+ "undiluted_concentration": "1.45",
+ "successful_pM": null,
+ "experiment_type": 8,
+ "antibody": null
+ }
+ },
+ {"pk": 1183, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11069",
+ "cluster_estimate": 184000,
+ "flowcell": 151,
+ "lane_number": 7,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11069",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired End AG-3d-1 AG domain of floral meristem day 3, rep 1",
+ "creation_date": "2009-09-02",
+ "cell_line": null,
+ "library_species": 6,
+ "library_type": 2,
+ "made_by": "Yuling Jiao",
+ "affiliations": [
+ 2
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "Done",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "nanodrop: Xng/ul.",
+ "undiluted_concentration": "18.3",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 1184, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11070",
+ "cluster_estimate": 182000,
+ "flowcell": 151,
+ "lane_number": 8,
+ "pM": "7"
+ }
+ },
+ {
+ "pk": "11070",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 300,
+ "library_name": "Paired End AG-5d-1 AG domain of floral meristem day 5, rep 1",
+ "creation_date": "2009-09-02",
+ "cell_line": null,
+ "library_species": 6,
+ "library_type": 2,
+ "made_by": "Yuling Jiao",
+ "affiliations": [
+ 3
+ ],
+ "replicate": 1,
+ "condition": null,
+ "hidden": false,
+ "stopping_point": "Done",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": null,
+ "notes": "nanodrop: 40ng/ul\r\nCalibrated qbit with standards.\r\nMeasured 2ul library with qbit using HS kit.\r\n",
+ "undiluted_concentration": "20.3",
+ "successful_pM": null,
+ "experiment_type": 4,
+ "antibody": null
+ }
+ },
+ {"pk": 200, "model": "experiments.flowcell",
+ "fields": {
+ "paired_end": true,
+ "run_date": "2007-09-27T22:12:13-0800",
+ "read_length": 36,
+ "notes": "",
+ "advanced_run": false,
+ "control_lane": 2,
+ "cluster_station": 3,
+ "sequencer": 2,
+ "flowcell_id": "30012AAXX (failed)"
+ }
+ },
+ {"pk": 201, "model": "experiments.lane",
+ "fields": {
+ "comment": "",
+ "library": "11070",
+ "cluster_estimate": 182000,
+ "flowcell": 200,
+ "lane_number": 8,
+ "pM": "7"
+ }
+ }
+]
--- /dev/null
+[ { "model": "experiments.Sequencer",
+ "pk": 1,
+ "fields": {
+ "name": "Rotifer",
+ "instrument_name": "ILLUMINA-33A494",
+ "serial_number": "",
+ "model": "Illumina Genome Analyzer II",
+ "active": false,
+ "isdefault": false,
+ "comment": "after 2010 pipeline name, was exchanged for hiseq"
+ }
+ },
+ { "model": "experiments.Sequencer",
+ "pk": 2,
+ "fields": {
+ "name": "Tardigrade",
+ "instrument_name": "ILLUMINA-EC5D15",
+ "serial_number": "",
+ "model": "Illumina Genome Analyzer IIx",
+ "active": true,
+ "isdefault": false,
+ "comment": "after 2010 pipeline name"
+ }
+ },
+ { "model": "experiments.Sequencer",
+ "pk": 3,
+ "fields": {
+ "name": "Elsewhere",
+ "instrument_name": "",
+ "serial_number": "",
+ "model": "Unknown",
+ "active": false,
+ "isdefault": false,
+ "comment": "Sequenced somewhere else"
+ }
+ },
+ { "model": "experiments.Sequencer",
+ "pk": 4,
+ "fields": {
+ "name": "Volvox",
+ "instrument_name": "HWI-ST0787",
+ "serial_number": "",
+ "model": "Illumina HiSeq 2000",
+ "active": true,
+ "isdefault": true,
+ "comment": ""
+ }
+ },
+ { "model": "experiments.Sequencer",
+ "pk": 5,
+ "fields": {
+ "name": "Tardigrade (older)",
+ "instrument_name": "HWUSI-EAS627",
+ "serial_number": "",
+ "model": "Illumina Genome Analyzer II",
+ "active": false,
+ "isdefault": false,
+ "comment": "earlier version of tardigrade"
+ }
+ },
+ { "model": "experiments.Sequencer",
+ "pk": 6,
+ "fields": {
+ "name": "Rotifer (older)",
+ "instrument_name": "HWUSI-EAS229",
+ "serial_number": "",
+ "model": "Illumina Genome Analyzer II",
+ "active": false,
+ "isdefault": false,
+ "comment": "earlier rotifer name"
+ }
+ },
+ { "model": "experiments.Sequencer",
+ "pk": 7,
+ "fields": {
+ "name": "First sequencer",
+ "instrument_name": "USI-EAS44",
+ "serial_number": "",
+ "model": "Illumina Genome Analyzer I",
+ "active": false,
+ "isdefault": false,
+ "comment": "our first sequencer"
+ }
+ },
+ { "model": "experiments.ClusterStation",
+ "pk": 3,
+ "fields": { "name": "new", "isdefault": false }
+ }
+]
--- /dev/null
+from __future__ import absolute_import, print_function
+
+import datetime
+import glob
+import logging
+import os
+import re
+import types
+import uuid
+
+from django.conf import settings
+from django.core.exceptions import ObjectDoesNotExist
+from django.core import urlresolvers
+from django.utils import timezone
+from django.db import models
+from django.db.models.signals import post_init, pre_save
+
+from samples.models import Library
+from htsworkflow.util.conversion import parse_flowcell_id
+from htsworkflow.pipelines import runfolder
+
+import pytz
+
+LOGGER = logging.getLogger(__name__)
+default_pM = 5
+try:
+ default_pM = int(settings.DEFAULT_PM)
+except AttributeError, e:
+ LOGGER.error("invalid value for default_pm")
+
+# how many days to wait before trying to re-import a runfolder
+RESCAN_DELAY = 1
+try:
+ RESCAN_DELAY = int(settings.RESCAN_DELAY)
+except (ValueError, AttributeError):
+ LOGGER.error("Missing or invalid settings.RESCAN_DELAY, "\
+ "defaulting to %s" % (RESCAN_DELAY,))
+
+RUN_STATUS_CHOICES = (
+ (0, 'Sequencer running'), # Solexa Data Pipeline Not Yet Started'),
+ (1, 'Data Pipeline Started'),
+ (2, 'Data Pipeline Interrupted'),
+ (3, 'Data Pipeline Finished'),
+ (4, 'Collect Results Started'),
+ (5, 'Collect Results Finished'),
+ (6, 'QC Started'),
+ (7, 'QC Finished'),
+ (255, 'DONE'),
+ )
+RUN_STATUS_REVERSE_MAP = dict(((v, k) for k, v in RUN_STATUS_CHOICES))
+
+
+class ClusterStation(models.Model):
+ """List of cluster stations"""
+ name = models.CharField(max_length=50, unique=True)
+ isdefault = models.BooleanField(default=False, null=False)
+
+ class Meta:
+ ordering = ["-isdefault", "name"]
+
+ def __unicode__(self):
+ return unicode(self.name)
+
+ @classmethod
+ def default(cls):
+ d = cls.objects.filter(isdefault=True).all()
+ if len(d) > 0:
+ return d[0]
+ d = cls.objects.order_by('-id').all()
+ if len(d) > 0:
+ return d[0]
+ return None
+
+ @staticmethod
+ def update_isdefault(sender, instance, **kwargs):
+ """Clear default if needed
+ """
+ if instance.isdefault:
+ for c in ClusterStation.objects.filter(isdefault=True).all():
+ if c.id != instance.id:
+ c.isdefault = False
+ c.save()
+
+pre_save.connect(ClusterStation.update_isdefault, sender=ClusterStation)
+
+class Sequencer(models.Model):
+ """Sequencers we've owned
+ """
+ name = models.CharField(max_length=50, db_index=True)
+ instrument_name = models.CharField(max_length=50, db_index=True)
+ serial_number = models.CharField(max_length=50, db_index=True)
+ model = models.CharField(max_length=255)
+ active = models.BooleanField(default=True, null=False)
+ isdefault = models.BooleanField(default=False, null=False)
+ comment = models.CharField(max_length=255)
+
+ class Meta:
+ ordering = ["-isdefault", "-active", "name"]
+
+ def __unicode__(self):
+ name = [unicode(self.name)]
+ if self.instrument_name is not None:
+ name.append("(%s)" % (unicode(self.instrument_name),))
+ return " ".join(name)
+
+ @models.permalink
+ def get_absolute_url(self):
+ return ('experiments.views.sequencer',
+ [self.id])
+
+ @classmethod
+ def default(cls):
+ d = cls.objects.filter(isdefault=True).all()
+ if len(d) > 0:
+ return d[0]
+ d = cls.objects.order_by('active', '-id').all()
+ if len(d) > 0:
+ return d[0]
+ return None
+
+ @staticmethod
+ def update_isdefault(sender, instance, **kwargs):
+ """Clear default if needed
+ """
+ if instance.isdefault:
+ for s in Sequencer.objects.filter(isdefault=True).all():
+ if s.id != instance.id:
+ s.isdefault = False
+ s.save()
+
+pre_save.connect(Sequencer.update_isdefault, sender=Sequencer)
+
+
+class FlowCell(models.Model):
+ flowcell_id = models.CharField(max_length=20, unique=True, db_index=True)
+ run_date = models.DateTimeField()
+ advanced_run = models.BooleanField(default=False)
+ paired_end = models.BooleanField(default=False)
+ read_length = models.IntegerField(default=32) # Stanford is currenlty 25
+ control_lane = models.IntegerField(choices=[(1, 1),
+ (2, 2),
+ (3, 3),
+ (4, 4),
+ (5, 5),
+ (6, 6),
+ (7, 7),
+ (8, 8),
+ (0, 'All Lanes')],
+ null=True,
+ blank=True)
+
+ cluster_station = models.ForeignKey(ClusterStation, default=ClusterStation.default)
+ sequencer = models.ForeignKey(Sequencer, default=Sequencer.default)
+
+ notes = models.TextField(blank=True)
+
+ def __unicode__(self):
+ return unicode(self.flowcell_id)
+
+ def Lanes(self):
+ html = ['<table>']
+ for lane in self.lane_set.order_by('lane_number'):
+ cluster_estimate = lane.cluster_estimate
+ if cluster_estimate is not None:
+ cluster_estimate = "%s k" % ((int(cluster_estimate) / 1000), )
+ else:
+ cluster_estimate = 'None'
+ library_id = lane.library_id
+ library = lane.library
+ element = '<tr><td>%d</td>'\
+ '<td><a href="%s">%s</a></td><td>%s</td></tr>'
+ html.append(element % (lane.lane_number,
+ library.get_admin_url(),
+ library,
+ cluster_estimate))
+ html.append('</table>')
+ return "\n".join(html)
+ Lanes.allow_tags = True
+
+ class Meta:
+ ordering = ["-run_date"]
+
+ def get_admin_url(self):
+ # that's the django way... except it didn't work
+ return urlresolvers.reverse('admin:experiments_flowcell_change',
+ args=(self.id,))
+
+ def flowcell_type(self):
+ """Convert our boolean 'is paired' flag to a name
+ """
+ if self.paired_end:
+ return u"Paired"
+ else:
+ return u"Single"
+
+ @models.permalink
+ def get_absolute_url(self):
+ flowcell_id, status = parse_flowcell_id(self.flowcell_id)
+ return ('experiments.views.flowcell_detail',
+ [str(flowcell_id)])
+
+ def get_raw_data_directory(self):
+ """Return location of where the raw data is stored"""
+ flowcell_id, status = parse_flowcell_id(self.flowcell_id)
+
+ return os.path.join(settings.RESULT_HOME_DIR, flowcell_id)
+
+ def update_data_runs(self):
+ result_root = self.get_raw_data_directory()
+ LOGGER.debug("Update data runs flowcell root: %s" % (result_root,))
+ if result_root is None:
+ return
+
+ result_home_dir = os.path.join(settings.RESULT_HOME_DIR, '')
+ run_xml_re = re.compile(glob.fnmatch.translate('run*.xml'))
+
+ result_dirs = []
+ for dirpath, dirnames, filenames in os.walk(result_root):
+ for filename in filenames:
+ if run_xml_re.match(filename):
+ # we have a run directory
+ relative_pathname = get_relative_pathname(dirpath)
+ self.import_data_run(relative_pathname, filename)
+
+ def import_data_run(self, relative_pathname, run_xml_name, force=False):
+ """Given a result directory import files"""
+ now = timezone.now()
+ run_dir = get_absolute_pathname(relative_pathname)
+ run_xml_path = os.path.join(run_dir, run_xml_name)
+
+ runs = DataRun.objects.filter(result_dir = relative_pathname)
+ if len(runs) == 0:
+ run = DataRun()
+ created = True
+ elif len(runs) > 1:
+ raise RuntimeError("Too many data runs for %s" % (
+ relative_pathname,))
+ else:
+ run = runs[0]
+ created = False
+
+ if created or force or (now-run.last_update_time).days > RESCAN_DELAY:
+ LOGGER.debug("Importing run from %s" % (relative_pathname,))
+ run_xml_data = runfolder.load_pipeline_run_xml(run_xml_path)
+ run.flowcell = self
+ run.status = RUN_STATUS_REVERSE_MAP['DONE']
+ run.result_dir = relative_pathname
+ run.runfolder_name = run_xml_data.runfolder_name
+ run.cycle_start = run_xml_data.image_analysis.start
+ run.cycle_stop = run_xml_data.image_analysis.stop
+ naive_run_start_time = datetime.datetime.fromordinal(run_xml_data.image_analysis.date.toordinal())
+ run.run_start_time = pytz.timezone(settings.TIME_ZONE).localize(naive_run_start_time)
+ run.image_software = run_xml_data.image_analysis.software
+ run.image_version = run_xml_data.image_analysis.version
+ run.basecall_software = run_xml_data.bustard.software
+ run.basecall_version = run_xml_data.bustard.version
+ # we're frequently not running alignments
+ if run_xml_data.gerald:
+ run.alignment_software = run_xml_data.gerald.software
+ run.alignment_version = run_xml_data.gerald.version
+
+ run.last_update_time = timezone.now()
+ run.save()
+
+ run.update_result_files()
+
+
+# FIXME: should we automatically update dataruns?
+# Or should we expect someone to call update_data_runs?
+#def update_flowcell_dataruns(sender, instance, *args, **kwargs):
+# """Update our dataruns
+# """
+# if not os.path.exists(settings.RESULT_HOME_DIR):
+# return
+#
+# instance.update_data_runs()
+#post_init.connect(update_flowcell_dataruns, sender=FlowCell)
+
+
+LANE_STATUS_CODES = [(0, 'Failed'),
+ (1, 'Marginal'),
+ (2, 'Good'), ]
+LANE_STATUS_MAP = dict((int(k), v) for k, v in LANE_STATUS_CODES)
+LANE_STATUS_MAP[None] = "Unknown"
+
+
+def is_valid_lane(value):
+ if value >= 1 and value <= 8:
+ return True
+ else:
+ return False
+
+
+class Lane(models.Model):
+ flowcell = models.ForeignKey(FlowCell)
+ lane_number = models.IntegerField()
+ library = models.ForeignKey(Library)
+ pM = models.DecimalField(max_digits=5,
+ decimal_places=2,
+ blank=False,
+ null=False,
+ default=default_pM)
+ cluster_estimate = models.IntegerField(blank=True, null=True)
+ status = models.IntegerField(choices=LANE_STATUS_CODES,
+ null=True,
+ blank=True)
+ comment = models.TextField(null=True, blank=True)
+
+ @models.permalink
+ def get_absolute_url(self):
+ return ('experiments.views.flowcell_lane_detail',
+ [str(self.id)])
+
+ def __unicode__(self):
+ return self.flowcell.flowcell_id + ':' + unicode(self.lane_number)
+
+
+class DataRun(models.Model):
+ flowcell = models.ForeignKey(FlowCell, verbose_name="Flowcell Id")
+ runfolder_name = models.CharField(max_length=50)
+ result_dir = models.CharField(max_length=255)
+ last_update_time = models.DateTimeField()
+ run_start_time = models.DateTimeField()
+ cycle_start = models.IntegerField(null=True, blank=True)
+ cycle_stop = models.IntegerField(null=True, blank=True)
+ run_status = models.IntegerField(choices=RUN_STATUS_CHOICES,
+ null=True, blank=True)
+ image_software = models.CharField(max_length=50)
+ image_version = models.CharField(max_length=50)
+ basecall_software = models.CharField(max_length=50)
+ basecall_version = models.CharField(max_length=50)
+ alignment_software = models.CharField(max_length=50)
+ alignment_version = models.CharField(max_length=50)
+ comment = models.TextField(blank=True)
+
+ def update_result_files(self):
+ abs_result_dir = get_absolute_pathname(self.result_dir)
+
+ for dirname, dirnames, filenames in os.walk(abs_result_dir):
+ for filename in filenames:
+ pathname = os.path.join(dirname, filename)
+ relative_pathname = get_relative_pathname(pathname)
+ datafiles = self.datafile_set.filter(
+ data_run=self,
+ relative_pathname=relative_pathname)
+ if len(datafiles) > 0:
+ continue
+
+ metadata = find_file_type_metadata_from_filename(filename)
+ if metadata is not None:
+ metadata['filename'] = filename
+ newfile = DataFile()
+ newfile.data_run = self
+ newfile.file_type = metadata['file_type']
+ newfile.relative_pathname = relative_pathname
+
+ lane_number = metadata.get('lane', None)
+ if lane_number is not None:
+ lane = self.flowcell.lane_set.get(
+ lane_number=lane_number)
+ newfile.library = lane.library
+
+ self.datafile_set.add(newfile)
+
+ self.last_update_time = timezone.now()
+
+ def lane_files(self):
+ lanes = {}
+
+ for datafile in self.datafile_set.all():
+ metadata = datafile.attributes
+ if metadata is not None:
+ lane = metadata.get('lane', None)
+ if lane is not None:
+ lane_file_set = lanes.setdefault(lane, {})
+ normalized_name = datafile.file_type.normalized_name
+ lane_file_set[normalized_name] = datafile
+ return lanes
+
+ def ivc_plots(self, lane):
+ ivc_name = ['IVC All', 'IVC Call',
+ 'IVC Percent Base', 'IVC Percent All', 'IVC Percent Call']
+
+ plots = {}
+ for rel_filename, metadata in self.get_result_files():
+ if metadata.file_type.name in ivc_name:
+ plots[metadata.file_type.name] = (rel_filename, metadata)
+
+
+class FileType(models.Model):
+ """Represent potential file types
+
+ regex is a pattern used to detect if a filename matches this type
+ data run currently assumes that there may be a (?P<lane>) and
+ (?P<end>) pattern in the regular expression.
+ """
+ name = models.CharField(max_length=50)
+ mimetype = models.CharField(max_length=50, null=True, blank=True)
+ # regular expression from glob.fnmatch.translate
+ regex = models.TextField(null=True, blank=True)
+
+ def parse_filename(self, pathname):
+ """Does filename match our pattern?
+
+ Returns None if not, or dictionary of match variables if we do.
+ """
+ path, filename = os.path.split(pathname)
+ if len(self.regex) > 0:
+ match = re.match(self.regex, filename)
+ if match is not None:
+ # These are (?P<>) names we know about from our
+ # default regexes.
+ results = match.groupdict()
+
+ # convert int parameters
+ for attribute_name in ['lane', 'end']:
+ value = results.get(attribute_name, None)
+ if value is not None:
+ results[attribute_name] = int(value)
+
+ return results
+
+ def _get_normalized_name(self):
+ """Crush data file name into identifier friendly name"""
+ return self.name.replace(' ', '_').lower()
+ normalized_name = property(_get_normalized_name)
+
+ def __unicode__(self):
+ #return u"<FileType: %s>" % (self.name,)
+ return self.name
+
+
+def str_uuid():
+ """Helper function to set default UUID in DataFile"""
+ return str(uuid.uuid1())
+
+
+class DataFile(models.Model):
+ """Store map from random ID to filename"""
+ random_key = models.CharField(max_length=64,
+ db_index=True,
+ default=str_uuid)
+ data_run = models.ForeignKey(DataRun, db_index=True)
+ library = models.ForeignKey(Library, db_index=True, null=True, blank=True)
+ file_type = models.ForeignKey(FileType)
+ relative_pathname = models.CharField(max_length=255, db_index=True)
+
+ def _get_attributes(self):
+ return self.file_type.parse_filename(self.relative_pathname)
+ attributes = property(_get_attributes)
+
+ def _get_pathname(self):
+ return get_absolute_pathname(self.relative_pathname)
+ pathname = property(_get_pathname)
+
+ @models.permalink
+ def get_absolute_url(self):
+ return ('experiments.views.read_result_file',
+ (), {'key': self.random_key})
+
+
+def find_file_type_metadata_from_filename(pathname):
+ path, filename = os.path.split(pathname)
+ result = None
+ for file_type in FileType.objects.all():
+ result = file_type.parse_filename(filename)
+ if result is not None:
+ result['file_type'] = file_type
+ return result
+
+ return None
+
+
+def get_relative_pathname(abspath):
+ """Strip off the result home directory from a path
+ """
+ result_home_dir = os.path.join(settings.RESULT_HOME_DIR, '')
+ relative_pathname = abspath.replace(result_home_dir, '')
+ return relative_pathname
+
+
+def get_absolute_pathname(relative_pathname):
+ """Attach relative path to results home directory"""
+ return os.path.join(settings.RESULT_HOME_DIR, relative_pathname)
--- /dev/null
+from __future__ import absolute_import, print_function
+
+import re
+from lxml.html import fromstring
+try:
+ import json
+except ImportError, e:
+ import simplejson as json
+import os
+import shutil
+import sys
+import tempfile
+from urlparse import urljoin
+
+from django.conf import settings
+from django.core import mail
+from django.core.exceptions import ObjectDoesNotExist
+from django.test import TestCase
+from django.test.utils import setup_test_environment, teardown_test_environment
+from django.db import connection
+from django.conf import settings
+
+from .models import ClusterStation, DataRun, Sequencer, FlowCell, FileType, \
+ find_file_type_metadata_from_filename
+from .experiments import flowcell_information, lanes_for
+from htsworkflow.auth import apidata
+from htsworkflow.util.ethelp import validate_xhtml
+
+from htsworkflow.pipelines.test.simulate_runfolder import TESTDATA_DIR
+
+LANE_SET = range(1,9)
+
+NSMAP = {'libns':'http://jumpgate.caltech.edu/wiki/LibraryOntology#'}
+
+from django.db import connection
+
+class ClusterStationTestCases(TestCase):
+ fixtures = ['initial_data.json',
+ 'test_flowcells.json']
+
+ def test_default(self):
+ c = ClusterStation.default()
+ self.assertEqual(c.id, 2)
+
+ c.isdefault = False
+ c.save()
+
+ total = ClusterStation.objects.filter(isdefault=True).count()
+ self.assertEqual(total, 0)
+
+ other_default = ClusterStation.default()
+ self.assertEqual(other_default.id, 3)
+
+
+ def test_update_default(self):
+ old_default = ClusterStation.default()
+
+ c = ClusterStation.objects.get(pk=3)
+ c.isdefault = True
+ c.save()
+
+ new_default = ClusterStation.default()
+
+ self.assertNotEqual(old_default, new_default)
+ self.assertEqual(new_default, c)
+
+ total = ClusterStation.objects.filter(isdefault=True).count()
+ self.assertEqual(total, 1)
+
+ def test_update_other(self):
+ old_default = ClusterStation.default()
+ total = ClusterStation.objects.filter(isdefault=True).count()
+ self.assertEqual(total, 1)
+
+ c = ClusterStation.objects.get(pk=1)
+ c.name = "Primary Key 1"
+ c.save()
+
+ total = ClusterStation.objects.filter(isdefault=True).count()
+ self.assertEqual(total, 1)
+
+ new_default = ClusterStation.default()
+ self.assertEqual(old_default, new_default)
+
+
+class SequencerTestCases(TestCase):
+ fixtures = ['initial_data.json',
+ 'woldlab.json',
+ 'test_flowcells.json']
+
+ def test_default(self):
+ # starting with no default
+ s = Sequencer.default()
+ self.assertEqual(s.id, 2)
+
+ total = Sequencer.objects.filter(isdefault=True).count()
+ self.assertEqual(total, 1)
+
+ s.isdefault = False
+ s.save()
+
+ total = Sequencer.objects.filter(isdefault=True).count()
+ self.assertEqual(total, 0)
+
+ other_default = Sequencer.default()
+ self.assertEqual(other_default.id, 7)
+
+ def test_update_default(self):
+ old_default = Sequencer.default()
+
+ s = Sequencer.objects.get(pk=1)
+ s.isdefault = True
+ s.save()
+
+ new_default = Sequencer.default()
+
+ self.assertNotEqual(old_default, new_default)
+ self.assertEqual(new_default, s)
+
+ total = Sequencer.objects.filter(isdefault=True).count()
+ self.assertEqual(total, 1)
+
+
+ def test_update_other(self):
+ old_default = Sequencer.default()
+ total = Sequencer.objects.filter(isdefault=True).count()
+ self.assertEqual(total, 1)
+
+ s = Sequencer.objects.get(pk=1)
+ s.name = "Primary Key 1"
+ s.save()
+
+ total = Sequencer.objects.filter(isdefault=True).count()
+ self.assertEqual(total, 1)
+
+ new_default = Sequencer.default()
+ self.assertEqual(old_default, new_default)
+
+
+class ExperimentsTestCases(TestCase):
+ fixtures = ['initial_data.json',
+ 'test_flowcells.json',
+ ]
+
+ def setUp(self):
+ self.tempdir = tempfile.mkdtemp(prefix='htsw-test-experiments-')
+ settings.RESULT_HOME_DIR = self.tempdir
+
+ self.fc1_id = 'FC12150'
+ self.fc1_root = os.path.join(self.tempdir, self.fc1_id)
+ os.mkdir(self.fc1_root)
+ self.fc1_dir = os.path.join(self.fc1_root, 'C1-37')
+ os.mkdir(self.fc1_dir)
+ runxml = 'run_FC12150_2007-09-27.xml'
+ shutil.copy(os.path.join(TESTDATA_DIR, runxml),
+ os.path.join(self.fc1_dir, runxml))
+ for i in range(1,9):
+ shutil.copy(
+ os.path.join(TESTDATA_DIR,
+ 'woldlab_070829_USI-EAS44_0017_FC11055_1.srf'),
+ os.path.join(self.fc1_dir,
+ 'woldlab_070829_SERIAL_FC12150_%d.srf' %(i,))
+ )
+
+ self.fc2_dir = os.path.join(self.tempdir, '42JTNAAXX')
+ os.mkdir(self.fc2_dir)
+ os.mkdir(os.path.join(self.fc2_dir, 'C1-25'))
+ os.mkdir(os.path.join(self.fc2_dir, 'C1-37'))
+ os.mkdir(os.path.join(self.fc2_dir, 'C1-37', 'Plots'))
+
+ def tearDown(self):
+ shutil.rmtree(self.tempdir)
+
+ def test_flowcell_information(self):
+ """
+ Check the code that packs the django objects into simple types.
+ """
+ for fc_id in [u'FC12150', u"42JTNAAXX", "42JU1AAXX"]:
+ fc_dict = flowcell_information(fc_id)
+ fc_django = FlowCell.objects.get(flowcell_id=fc_id)
+ self.assertEqual(fc_dict['flowcell_id'], fc_id)
+ self.assertEqual(fc_django.flowcell_id, fc_id)
+ self.assertEqual(fc_dict['sequencer'], fc_django.sequencer.name)
+ self.assertEqual(fc_dict['read_length'], fc_django.read_length)
+ self.assertEqual(fc_dict['notes'], fc_django.notes)
+ self.assertEqual(fc_dict['cluster_station'], fc_django.cluster_station.name)
+
+ for lane in fc_django.lane_set.all():
+ lane_contents = fc_dict['lane_set'][lane.lane_number]
+ lane_dict = multi_lane_to_dict(lane_contents)[lane.library_id]
+ self.assertEqual(lane_dict['cluster_estimate'], lane.cluster_estimate)
+ self.assertEqual(lane_dict['comment'], lane.comment)
+ self.assertEqual(lane_dict['flowcell'], lane.flowcell.flowcell_id)
+ self.assertEqual(lane_dict['lane_number'], lane.lane_number)
+ self.assertEqual(lane_dict['library_name'], lane.library.library_name)
+ self.assertEqual(lane_dict['library_id'], lane.library.id)
+ self.assertAlmostEqual(float(lane_dict['pM']), float(lane.pM))
+ self.assertEqual(lane_dict['library_species'],
+ lane.library.library_species.scientific_name)
+
+ response = self.client.get('/experiments/config/%s/json' % (fc_id,), apidata)
+ # strptime isoformat string = '%Y-%m-%dT%H:%M:%S'
+ fc_json = json.loads(response.content)
+ self.assertEqual(fc_json['flowcell_id'], fc_id)
+ self.assertEqual(fc_json['sequencer'], fc_django.sequencer.name)
+ self.assertEqual(fc_json['read_length'], fc_django.read_length)
+ self.assertEqual(fc_json['notes'], fc_django.notes)
+ self.assertEqual(fc_json['cluster_station'], fc_django.cluster_station.name)
+
+
+ for lane in fc_django.lane_set.all():
+ lane_contents = fc_json['lane_set'][unicode(lane.lane_number)]
+ lane_dict = multi_lane_to_dict(lane_contents)[lane.library_id]
+
+ self.assertEqual(lane_dict['cluster_estimate'], lane.cluster_estimate)
+ self.assertEqual(lane_dict['comment'], lane.comment)
+ self.assertEqual(lane_dict['flowcell'], lane.flowcell.flowcell_id)
+ self.assertEqual(lane_dict['lane_number'], lane.lane_number)
+ self.assertEqual(lane_dict['library_name'], lane.library.library_name)
+ self.assertEqual(lane_dict['library_id'], lane.library.id)
+ self.assertAlmostEqual(float(lane_dict['pM']), float(lane.pM))
+ self.assertEqual(lane_dict['library_species'],
+ lane.library.library_species.scientific_name)
+
+ def test_invalid_flowcell(self):
+ """
+ Make sure we get a 404 if we request an invalid flowcell ID
+ """
+ response = self.client.get('/experiments/config/nottheone/json', apidata)
+ self.assertEqual(response.status_code, 404)
+
+ def test_no_key(self):
+ """
+ Require logging in to retrieve meta data
+ """
+ response = self.client.get(u'/experiments/config/FC12150/json')
+ self.assertEqual(response.status_code, 403)
+
+ def test_library_id(self):
+ """
+ Library IDs should be flexible, so make sure we can retrive a non-numeric ID
+ """
+ response = self.client.get('/experiments/config/FC12150/json', apidata)
+ self.assertEqual(response.status_code, 200)
+ flowcell = json.loads(response.content)
+
+ lane_contents = flowcell['lane_set']['3']
+ lane_library = lane_contents[0]
+ self.assertEqual(lane_library['library_id'], 'SL039')
+
+ response = self.client.get('/samples/library/SL039/json', apidata)
+ self.assertEqual(response.status_code, 200)
+ library_sl039 = json.loads(response.content)
+
+ self.assertEqual(library_sl039['library_id'], 'SL039')
+
+ def test_raw_id_field(self):
+ """
+ Test ticket:147
+
+ Library's have IDs, libraries also have primary keys,
+ we eventually had enough libraries that the drop down combo box was too
+ hard to filter through, unfortnately we want a field that uses our library
+ id and not the internal primary key, and raw_id_field uses primary keys.
+
+ This tests to make sure that the value entered in the raw library id field matches
+ the library id looked up.
+ """
+ expected_ids = [u'10981',u'11016',u'SL039',u'11060',
+ u'11061',u'11062',u'11063',u'11064']
+ self.client.login(username='supertest', password='BJOKL5kAj6aFZ6A5')
+ response = self.client.get('/admin/experiments/flowcell/153/')
+
+ tree = fromstring(response.content)
+ for i in range(0,8):
+ xpath_expression = '//input[@id="id_lane_set-%d-library"]'
+ input_field = tree.xpath(xpath_expression % (i,))[0]
+ library_field = input_field.find('../strong')
+ library_id, library_name = library_field.text.split(':')
+ # strip leading '#' sign from name
+ library_id = library_id[1:]
+ self.assertEqual(library_id, expected_ids[i])
+ self.assertEqual(input_field.attrib['value'], library_id)
+
+ def test_library_to_flowcell_link(self):
+ """
+ Make sure the library page includes links to the flowcell pages.
+ That work with flowcell IDs that have parenthetical comments.
+ """
+ self.client.login(username='supertest', password='BJOKL5kAj6aFZ6A5')
+ response = self.client.get('/library/11070/')
+ self.assertEqual(response.status_code, 200)
+ status = validate_xhtml(response.content)
+ if status is not None: self.assertTrue(status)
+
+ tree = fromstring(response.content)
+ flowcell_spans = tree.xpath('//span[@property="libns:flowcell_id"]',
+ namespaces=NSMAP)
+ self.assertEqual(flowcell_spans[1].text, '30012AAXX (failed)')
+ failed_fc_span = flowcell_spans[1]
+ failed_fc_a = failed_fc_span.getparent()
+ # make sure some of our RDF made it.
+ self.assertEqual(failed_fc_a.get('typeof'), 'libns:IlluminaFlowcell')
+ self.assertEqual(failed_fc_a.get('href'), '/flowcell/30012AAXX/')
+ fc_response = self.client.get(failed_fc_a.get('href'))
+ self.assertEqual(fc_response.status_code, 200)
+ status = validate_xhtml(response.content)
+ if status is not None: self.assertTrue(status)
+
+ fc_lane_response = self.client.get('/flowcell/30012AAXX/8/')
+ self.assertEqual(fc_lane_response.status_code, 200)
+ status = validate_xhtml(response.content)
+ if status is not None: self.assertTrue(status)
+
+
+ def test_pooled_multiplex_id(self):
+ fc_dict = flowcell_information('42JU1AAXX')
+ lane_contents = fc_dict['lane_set'][3]
+ self.assertEqual(len(lane_contents), 2)
+ lane_dict = multi_lane_to_dict(lane_contents)
+
+ self.assertEqual(lane_dict['12044']['index_sequence'],
+ {u'1': u'ATCACG',
+ u'2': u'CGATGT',
+ u'3': u'TTAGGC'})
+ self.assertEqual(lane_dict['11045']['index_sequence'],
+ {u'1': u'ATCACG'})
+
+
+
+ def test_lanes_for(self):
+ """
+ Check the code that packs the django objects into simple types.
+ """
+ user = 'test'
+ lanes = lanes_for(user)
+ self.assertEqual(len(lanes), 5)
+
+ response = self.client.get('/experiments/lanes_for/%s/json' % (user,), apidata)
+ lanes_json = json.loads(response.content)
+ self.assertEqual(len(lanes), len(lanes_json))
+ for i in range(len(lanes)):
+ self.assertEqual(lanes[i]['comment'], lanes_json[i]['comment'])
+ self.assertEqual(lanes[i]['lane_number'], lanes_json[i]['lane_number'])
+ self.assertEqual(lanes[i]['flowcell'], lanes_json[i]['flowcell'])
+ self.assertEqual(lanes[i]['run_date'], lanes_json[i]['run_date'])
+
+ def test_lanes_for_no_lanes(self):
+ """
+ Do we get something meaningful back when the user isn't attached to anything?
+ """
+ user = 'supertest'
+ lanes = lanes_for(user)
+ self.assertEqual(len(lanes), 0)
+
+ response = self.client.get('/experiments/lanes_for/%s/json' % (user,), apidata)
+ lanes_json = json.loads(response.content)
+
+ def test_lanes_for_no_user(self):
+ """
+ Do we get something meaningful back when its the wrong user
+ """
+ user = 'not a real user'
+ self.assertRaises(ObjectDoesNotExist, lanes_for, user)
+
+ response = self.client.get('/experiments/lanes_for/%s/json' % (user,), apidata)
+ self.assertEqual(response.status_code, 404)
+
+
+ def test_raw_data_dir(self):
+ """Raw data path generator check"""
+ flowcell_id = self.fc1_id
+ raw_dir = os.path.join(settings.RESULT_HOME_DIR, flowcell_id)
+
+ fc = FlowCell.objects.get(flowcell_id=flowcell_id)
+ self.assertEqual(fc.get_raw_data_directory(), raw_dir)
+
+ fc.flowcell_id = flowcell_id + " (failed)"
+ self.assertEqual(fc.get_raw_data_directory(), raw_dir)
+
+
+ def test_data_run_import(self):
+ srf_file_type = FileType.objects.get(name='SRF')
+ runxml_file_type = FileType.objects.get(name='run_xml')
+ flowcell_id = self.fc1_id
+ flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
+ flowcell.update_data_runs()
+ self.assertEqual(len(flowcell.datarun_set.all()), 1)
+
+ run = flowcell.datarun_set.all()[0]
+ result_files = run.datafile_set.all()
+ result_dict = dict(((rf.relative_pathname, rf) for rf in result_files))
+
+ srf4 = result_dict['FC12150/C1-37/woldlab_070829_SERIAL_FC12150_4.srf']
+ self.assertEqual(srf4.file_type, srf_file_type)
+ self.assertEqual(srf4.library_id, '11060')
+ self.assertEqual(srf4.data_run.flowcell.flowcell_id, 'FC12150')
+ self.assertEqual(
+ srf4.data_run.flowcell.lane_set.get(lane_number=4).library_id,
+ '11060')
+ self.assertEqual(
+ srf4.pathname,
+ os.path.join(settings.RESULT_HOME_DIR, srf4.relative_pathname))
+
+ lane_files = run.lane_files()
+ self.assertEqual(lane_files[4]['srf'], srf4)
+
+ runxml= result_dict['FC12150/C1-37/run_FC12150_2007-09-27.xml']
+ self.assertEqual(runxml.file_type, runxml_file_type)
+ self.assertEqual(runxml.library_id, None)
+
+ import1 = len(DataRun.objects.filter(result_dir='FC12150/C1-37'))
+ # what happens if we import twice?
+ flowcell.import_data_run('FC12150/C1-37',
+ 'run_FC12150_2007-09-27.xml')
+ self.assertEqual(
+ len(DataRun.objects.filter(result_dir='FC12150/C1-37')),
+ import1)
+
+ def test_read_result_file(self):
+ """make sure we can return a result file
+ """
+ flowcell_id = self.fc1_id
+ flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
+ flowcell.update_data_runs()
+
+ #self.client.login(username='supertest', password='BJOKL5kAj6aFZ6A5')
+
+ result_files = flowcell.datarun_set.all()[0].datafile_set.all()
+ for f in result_files:
+ url = '/experiments/file/%s' % ( f.random_key,)
+ response = self.client.get(url)
+ self.assertEqual(response.status_code, 200)
+ mimetype = f.file_type.mimetype
+ if mimetype is None:
+ mimetype = 'application/octet-stream'
+
+ self.assertEqual(mimetype, response['content-type'])
+
+ def test_flowcell_rdf(self):
+ import RDF
+ from htsworkflow.util.rdfhelp import get_model, \
+ fromTypedNode, \
+ load_string_into_model, \
+ rdfNS, \
+ libraryOntology, \
+ dump_model
+
+ model = get_model()
+
+ expected = {'1': ['11034'],
+ '2': ['11036'],
+ '3': ['12044','11045'],
+ '4': ['11047','13044'],
+ '5': ['11055'],
+ '6': ['11067'],
+ '7': ['11069'],
+ '8': ['11070']}
+ url = '/flowcell/42JU1AAXX/'
+ response = self.client.get(url)
+ self.assertEqual(response.status_code, 200)
+ status = validate_xhtml(response.content)
+ if status is not None: self.assertTrue(status)
+
+ ns = urljoin('http://localhost', url)
+ load_string_into_model(model, 'rdfa', response.content, ns=ns)
+ body = """prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+ prefix libns: <http://jumpgate.caltech.edu/wiki/LibraryOntology#>
+
+ select ?flowcell ?flowcell_id ?lane_id ?library_id
+ where {
+ ?flowcell a libns:IlluminaFlowcell ;
+ libns:flowcell_id ?flowcell_id ;
+ libns:has_lane ?lane .
+ ?lane libns:lane_number ?lane_id ;
+ libns:library ?library .
+ ?library libns:library_id ?library_id .
+ }"""
+ query = RDF.SPARQLQuery(body)
+ count = 0
+ for r in query.execute(model):
+ count += 1
+ self.assertEqual(fromTypedNode(r['flowcell_id']), u'42JU1AAXX')
+ lane_id = fromTypedNode(r['lane_id'])
+ library_id = fromTypedNode(r['library_id'])
+ self.assertTrue(library_id in expected[lane_id])
+ self.assertEqual(count, 10)
+
+
+class TestFileType(TestCase):
+ fixtures = ['initial_data.json',
+ 'test_flowcells.json',
+ ]
+
+ def test_file_type_unicode(self):
+ file_type_objects = FileType.objects
+ name = 'QSEQ tarfile'
+ file_type_object = file_type_objects.get(name=name)
+ self.assertEqual(u"QSEQ tarfile",
+ unicode(file_type_object))
+
+ def test_find_file_type(self):
+ file_type_objects = FileType.objects
+ cases = [('woldlab_090921_HWUSI-EAS627_0009_42FC3AAXX_l7_r1.tar.bz2',
+ 'QSEQ tarfile', 7, 1),
+ ('woldlab_091005_HWUSI-EAS627_0010_42JT2AAXX_1.srf',
+ 'SRF', 1, None),
+ ('s_1_eland_extended.txt.bz2','ELAND Extended', 1, None),
+ ('s_7_eland_multi.txt.bz2', 'ELAND Multi', 7, None),
+ ('s_3_eland_result.txt.bz2','ELAND Result', 3, None),
+ ('s_1_export.txt.bz2','ELAND Export', 1, None),
+ ('s_1_percent_call.png', 'IVC Percent Call', 1, None),
+ ('s_2_percent_base.png', 'IVC Percent Base', 2, None),
+ ('s_3_percent_all.png', 'IVC Percent All', 3, None),
+ ('s_4_call.png', 'IVC Call', 4, None),
+ ('s_5_all.png', 'IVC All', 5, None),
+ ('Summary.htm', 'Summary.htm', None, None),
+ ('run_42JT2AAXX_2009-10-07.xml', 'run_xml', None, None),
+ ]
+ for filename, typename, lane, end in cases:
+ ft = find_file_type_metadata_from_filename(filename)
+ self.assertEqual(ft['file_type'],
+ file_type_objects.get(name=typename))
+ self.assertEqual(ft.get('lane', None), lane)
+ self.assertEqual(ft.get('end', None), end)
+
+ def test_assign_file_type_complex_path(self):
+ file_type_objects = FileType.objects
+ cases = [('/a/b/c/woldlab_090921_HWUSI-EAS627_0009_42FC3AAXX_l7_r1.tar.bz2',
+ 'QSEQ tarfile', 7, 1),
+ ('foo/woldlab_091005_HWUSI-EAS627_0010_42JT2AAXX_1.srf',
+ 'SRF', 1, None),
+ ('../s_1_eland_extended.txt.bz2','ELAND Extended', 1, None),
+ ('/bleem/s_7_eland_multi.txt.bz2', 'ELAND Multi', 7, None),
+ ('/qwer/s_3_eland_result.txt.bz2','ELAND Result', 3, None),
+ ('/ty///1/s_1_export.txt.bz2','ELAND Export', 1, None),
+ ('/help/s_1_percent_call.png', 'IVC Percent Call', 1, None),
+ ('/bored/s_2_percent_base.png', 'IVC Percent Base', 2, None),
+ ('/example1/s_3_percent_all.png', 'IVC Percent All', 3, None),
+ ('amonkey/s_4_call.png', 'IVC Call', 4, None),
+ ('fishie/s_5_all.png', 'IVC All', 5, None),
+ ('/random/Summary.htm', 'Summary.htm', None, None),
+ ('/notrandom/run_42JT2AAXX_2009-10-07.xml', 'run_xml', None, None),
+ ]
+ for filename, typename, lane, end in cases:
+ result = find_file_type_metadata_from_filename(filename)
+ self.assertEqual(result['file_type'],
+ file_type_objects.get(name=typename))
+ self.assertEqual(result.get('lane',None), lane)
+ self.assertEqual(result.get('end', None), end)
+
+class TestEmailNotify(TestCase):
+ fixtures = ['initial_data.json',
+ 'test_flowcells.json']
+
+ def test_started_email_not_logged_in(self):
+ response = self.client.get('/experiments/started/153/')
+ self.assertEqual(response.status_code, 302)
+
+ def test_started_email_logged_in_user(self):
+ self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
+ response = self.client.get('/experiments/started/153/')
+ self.assertEqual(response.status_code, 302)
+
+ def test_started_email_logged_in_staff(self):
+ self.client.login(username='admintest', password='BJOKL5kAj6aFZ6A5')
+ response = self.client.get('/experiments/started/153/')
+ self.assertEqual(response.status_code, 200)
+
+ def test_started_email_send(self):
+ self.client.login(username='admintest', password='BJOKL5kAj6aFZ6A5')
+ response = self.client.get('/experiments/started/153/')
+ self.assertEqual(response.status_code, 200)
+
+ self.assertTrue('pk1@example.com' in response.content)
+ self.assertTrue('Lane #8 : (11064) Paired ends 104' in response.content)
+
+ response = self.client.get('/experiments/started/153/', {'send':'1','bcc':'on'})
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(mail.outbox), 4)
+ bcc = set(settings.NOTIFICATION_BCC).copy()
+ bcc.update(set(settings.MANAGERS))
+ for m in mail.outbox:
+ self.assertTrue(len(m.body) > 0)
+ self.assertEqual(set(m.bcc), bcc)
+
+ def test_email_navigation(self):
+ """
+ Can we navigate between the flowcell and email forms properly?
+ """
+ self.client.login(username='supertest', password='BJOKL5kAj6aFZ6A5')
+ response = self.client.get('/experiments/started/153/')
+ self.assertEqual(response.status_code, 200)
+ self.assertTrue(re.search('Flowcell FC12150', response.content))
+ # require that navigation back to the admin page exists
+ self.assertTrue(re.search('<a href="/admin/experiments/flowcell/153/">[^<]+</a>', response.content))
+
+def multi_lane_to_dict(lane):
+ """Convert a list of lane entries into a dictionary indexed by library ID
+ """
+ return dict( ((x['library_id'],x) for x in lane) )
+
+class TestSequencer(TestCase):
+ fixtures = ['initial_data.json',
+ 'test_flowcells.json',
+ ]
+
+ def test_name_generation(self):
+ seq = Sequencer()
+ seq.name = "Seq1"
+ seq.instrument_name = "HWI-SEQ1"
+ seq.model = "Imaginary 5000"
+
+ self.assertEqual(unicode(seq), "Seq1 (HWI-SEQ1)")
+
+ def test_lookup(self):
+ fc = FlowCell.objects.get(pk=153)
+ self.assertEqual(fc.sequencer.model,
+ "Illumina Genome Analyzer IIx")
+ self.assertEqual(fc.sequencer.instrument_name,
+ "ILLUMINA-EC5D15")
+ # well actually we let the browser tack on the host name
+ url = fc.get_absolute_url()
+ self.assertEqual(url, '/flowcell/FC12150/')
+
+ def test_rdf(self):
+ response = self.client.get('/flowcell/FC12150/', apidata)
+ tree = fromstring(response.content)
+ seq_by = tree.xpath('//div[@rel="libns:sequenced_by"]',
+ namespaces=NSMAP)
+ self.assertEqual(len(seq_by), 1)
+ self.assertEqual(seq_by[0].attrib['rel'], 'libns:sequenced_by')
+ seq = seq_by[0].getchildren()
+ self.assertEqual(len(seq), 1)
+ self.assertEqual(seq[0].attrib['about'], '/sequencer/2')
+ self.assertEqual(seq[0].attrib['typeof'], 'libns:Sequencer')
+
+ name = seq[0].xpath('./span[@property="libns:sequencer_name"]')
+ self.assertEqual(len(name), 1)
+ self.assertEqual(name[0].text, 'Tardigrade')
+ instrument = seq[0].xpath(
+ './span[@property="libns:sequencer_instrument"]')
+ self.assertEqual(len(instrument), 1)
+ self.assertEqual(instrument[0].text, 'ILLUMINA-EC5D15')
+ model = seq[0].xpath(
+ './span[@property="libns:sequencer_model"]')
+ self.assertEqual(len(model), 1)
+ self.assertEqual(model[0].text, 'Illumina Genome Analyzer IIx')
+
+ def test_flowcell_with_rdf_validation(self):
+ from htsworkflow.util.rdfhelp import add_default_schemas, \
+ dump_model, \
+ get_model, \
+ load_string_into_model
+ from htsworkflow.util.rdfinfer import Infer
+
+ model = get_model()
+ add_default_schemas(model)
+ inference = Infer(model)
+
+ url ='/flowcell/FC12150/'
+ response = self.client.get(url)
+ self.assertEqual(response.status_code, 200)
+ status = validate_xhtml(response.content)
+ if status is not None: self.assertTrue(status)
+
+ load_string_into_model(model, 'rdfa', response.content)
+
+ errmsgs = list(inference.run_validation())
+ self.assertEqual(len(errmsgs), 0)
+
+ def test_lane_with_rdf_validation(self):
+ from htsworkflow.util.rdfhelp import add_default_schemas, \
+ dump_model, \
+ get_model, \
+ load_string_into_model
+ from htsworkflow.util.rdfinfer import Infer
+
+ model = get_model()
+ add_default_schemas(model)
+ inference = Infer(model)
+
+ url = '/lane/1193'
+ response = self.client.get(url)
+ self.assertEqual(response.status_code, 200)
+ status = validate_xhtml(response.content)
+ if status is not None: self.assertTrue(status)
+
+ load_string_into_model(model, 'rdfa', response.content)
+
+ errmsgs = list(inference.run_validation())
+ self.assertEqual(len(errmsgs), 0)
+
+def suite():
+ from unittest import TestSuite, defaultTestLoader
+ suite = TestSuite()
+ for testcase in [ClusterStationTestCases,
+ SequencerTestCases,
+ ExerimentsTestCases,
+ TestFileType,
+ TestEmailNotify,
+ TestSequencer]:
+ suite.addTests(defaultTestLoader.loadTestsFromTestCase(testcase))
+ return suite
+
+if __name__ == "__main__":
+ from unittest import main
+ main(defaultTest="suite")
--- /dev/null
+from django.conf.urls import patterns
+
+urlpatterns = patterns('',
+ (r'^$', '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$', 'experiments.experiments.flowcell_json'),
+ (r'^lanes_for/(?P<username>.+)/json$', 'experiments.experiments.lanes_for_json'),
+ (r'^file/(?P<key>.+)/?$', 'experiments.views.read_result_file'),
+ (r'^started/(?P<pk>.+)/$', 'experiments.views.startedEmail'),
+ (r'^finished/(?P<pk>.+)/$', 'experiments.views.finishedEmail'),
+)
--- /dev/null
+from __future__ import absolute_import, print_function
+
+# Create your views here.
+from datetime import datetime
+import os
+
+#from django.template import Context, loader
+#shortcut to the above modules
+from django.contrib.auth.decorators import user_passes_test
+from django.conf import settings
+from django.core.exceptions import ObjectDoesNotExist
+from django.core.mail import EmailMessage, mail_managers
+from django.http import HttpResponse
+from django.shortcuts import render_to_response, get_object_or_404
+from django.template import RequestContext
+from django.template.loader import get_template
+
+from .models import DataRun, DataFile, FlowCell, Lane, Sequencer
+from .experiments import estimateFlowcellDuration, estimateFlowcellTimeRemaining, roundToDays, \
+ getUsersForFlowcell, \
+ makeEmailLaneMap
+
+def index(request):
+ all_runs = DataRun.objects.order_by('-run_start_time')
+ return render_to_response('experiments/index.html',{'data_run_list': all_runs})
+
+def detail(request, run_folder):
+ html_str = '<h2>Exp Track Details Page</h2>'
+ html_str += 'Run Folder: '+run_folder
+ r = get_object_or_404(DataRun,run_folder=run_folder)
+ return render_to_response('experiments/detail.html',{'run_f': r})
+
+def makeFCSheet(request,fcid):
+ # get Flowcell by input fcid
+ # ...
+ rec = None
+ try:
+ rec = FlowCell.objects.get(flowcell_id=fcid)
+ except ObjectDoesNotExist:
+ pass
+ lanes = ['1','2','3','4','5','6','7','8']
+ return render_to_response('experiments/flowcellSheet.html',{'fc': rec})
+
+
+@user_passes_test(lambda u: u.is_staff)
+def startedEmail(request, pk):
+ """
+ Create the we have started processing your samples email
+ """
+ fc = get_object_or_404(FlowCell, id=pk)
+
+ send = request.REQUEST.get('send',False)
+ if send in ('1', 'on', 'True', 'true', True):
+ send = True
+ else:
+ send = False
+
+ bcc_managers = request.REQUEST.get('bcc', False)
+ if bcc_managers in ('on', '1', 'True', 'true'):
+ bcc_managers = True
+ else:
+ bcc_managers = False
+
+ email_lane = makeEmailLaneMap(fc)
+ flowcell_users = getUsersForFlowcell(fc)
+ estimate = estimateFlowcellTimeRemaining(fc)
+ estimate_low, estimate_high = roundToDays(estimate)
+ email_verify = get_template('experiments/email_preview.html')
+ email_template = get_template('experiments/started_email.txt')
+ sender = settings.NOTIFICATION_SENDER
+
+ warnings = []
+ emails = []
+
+ emailless_users = []
+ for user in flowcell_users:
+ # provide warning
+ if user.email is None or len(user.email) == 0:
+ warnings.append((user.admin_url(), user.username))
+ user=None
+
+ for user_email in email_lane.keys():
+ sending = ""
+ # build body
+ context = RequestContext(request,
+ {u'flowcell': fc,
+ u'lanes': email_lane[user_email],
+ u'runfolder': 'blank',
+ u'finish_low': estimate_low,
+ u'finish_high': estimate_high,
+ u'now': datetime.now(),
+ })
+
+ # build view
+ subject = "Flowcell %s" % ( fc.flowcell_id )
+ body = email_template.render(context)
+
+ if send:
+ email = EmailMessage(subject, body, sender, to=[user_email])
+ notified = set()
+ if bcc_managers:
+ for manager in settings.MANAGERS:
+ if len(manager) > 0:
+ notified.add(manager)
+ for user in settings.NOTIFICATION_BCC:
+ if len(user) > 0:
+ notified.add(user)
+ email.bcc = list(notified)
+ email.send()
+
+ emails.append((user_email, subject, body, sending))
+
+ verify_context = RequestContext(
+ request,
+ { 'emails': emails,
+ 'flowcell': fc,
+ 'from': sender,
+ 'send': send,
+ 'site_managers': settings.MANAGERS,
+ 'title': fc.flowcell_id,
+ 'warnings': warnings,
+ })
+ return HttpResponse(email_verify.render(verify_context))
+
+def finishedEmail(request, pk):
+ """
+ """
+ return HttpResponse("I've got nothing.")
+
+
+def flowcell_detail(request, flowcell_id, lane_number=None):
+ fc = get_object_or_404(FlowCell, flowcell_id__startswith=flowcell_id)
+ fc.update_data_runs()
+
+
+ if lane_number is not None:
+ lanes = fc.lane_set.filter(lane_number=lane_number)
+ else:
+ lanes = fc.lane_set.all()
+
+ context = RequestContext(request,
+ {'flowcell': fc,
+ 'lanes': lanes})
+
+ return render_to_response('experiments/flowcell_detail.html',
+ context)
+
+def flowcell_lane_detail(request, lane_pk):
+ lane = get_object_or_404(Lane, id=lane_pk)
+ lane.flowcell.update_data_runs()
+
+ dataruns = []
+ lane.flowcell.update_data_runs()
+ for run in lane.flowcell.datarun_set.all():
+ files = run.lane_files().get(lane.lane_number, None)
+ dataruns.append((run,
+ lane.lane_number,
+ files))
+
+ context = RequestContext(request,
+ {'lib': lane.library,
+ 'lane': lane,
+ 'flowcell': lane.flowcell,
+ 'filtered_dataruns': dataruns})
+
+ return render_to_response('experiments/flowcell_lane_detail.html',
+ context)
+
+def read_result_file(self, key):
+ """Return the contents of filename if everything is approved
+ """
+ data_file = get_object_or_404(DataFile, random_key = key)
+
+ content_type = 'application/octet-stream'
+ if data_file.file_type.mimetype is not None:
+ content_type = data_file.file_type.mimetype
+
+ if os.path.exists(data_file.pathname):
+ return HttpResponse(open(data_file.pathname,'r'),
+ content_type=content_type)
+
+ raise Http404
+
+
+def sequencer(request, sequencer_id):
+ sequencer = get_object_or_404(Sequencer, id=sequencer_id)
+ context = RequestContext(request,
+ {'sequencer': sequencer})
+ return render_to_response('experiments/sequencer.html', context)
--- /dev/null
+"""
+Define some alternate authentication methods
+"""
+from django.core.exceptions import PermissionDenied
+from django.conf import settings
+
+apidata = {'apiid': u'0', 'apikey': settings.DEFAULT_API_KEY}
+
+def require_api_key(request):
+ # make sure we have the api component
+ if not (request.REQUEST.has_key('apiid') or request.REQUEST.has_key('apikey')):
+ raise PermissionDenied
+
+ # make sure the id and key are right
+ if request.REQUEST['apiid'] == apidata['apiid'] and \
+ request.REQUEST['apikey'] == apidata['apikey']:
+ return True
+ else:
+ raise PermissionDenied
+++ /dev/null
-"""
-Define some alternate authentication methods
-"""
-from django.core.exceptions import PermissionDenied
-from django.conf import settings
-
-apidata = {'apiid': u'0', 'apikey': settings.DEFAULT_API_KEY}
-
-def require_api_key(request):
- # make sure we have the api component
- if not (request.REQUEST.has_key('apiid') or request.REQUEST.has_key('apikey')):
- raise PermissionDenied
-
- # make sure the id and key are right
- if request.REQUEST['apiid'] == apidata['apiid'] and \
- request.REQUEST['apikey'] == apidata['apikey']:
- return True
- else:
- raise PermissionDenied
+++ /dev/null
-from django.contrib import admin
-from htsworkflow.frontend.bcmagic.models import KeywordMap, Printer
-
-class KeywordMapAdmin(admin.ModelAdmin):
- list_display = ('keyword','regex', 'url_template')
-
-class PrinterAdmin(admin.ModelAdmin):
- list_display = ('name', 'model', 'ip_address', 'label_shape', 'label_width', 'label_height', 'notes')
-
-admin.site.register(KeywordMap, KeywordMapAdmin)
-admin.site.register(Printer, PrinterAdmin)
\ No newline at end of file
+++ /dev/null
-[{"pk": 1,
- "model": "bcmagic.keywordmap",
- "fields": {"regex": "(?P<uuid>[A-Fa-f0-9]+)",
- "url_template": "/samples/freezer/{{ uuid }}/",
- "keyword": "frzr"}},
- {"pk": 2,
- "model": "bcmagic.keywordmap",
- "fields": {"regex": "(?P<uuid>[A-Fa-f0-9]+)",
- "url_template": "/samples/container/{{ uuid }}/",
- "keyword": "cntr"}},
- {"pk": 3,
- "model": "bcmagic.keywordmap",
- "fields": {"regex": "(?P<sampleid>\\d+)\\|(?P<owner>[A-Za-z0-9_\\- ]+)",
- "url_template": "/samples/sample/{{ sampleid }}/",
- "keyword": "s"}},
- {"pk": 4,
- "model": "bcmagic.keywordmap",
- "fields": {"regex": "(?P<search>[\\S\\s]+)",
- "url_template": "http://www.google.com/search?q={{ search }}",
- "keyword": "gg"}},
- {"pk": 5,
- "model": "bcmagic.keywordmap",
- "fields": {"regex": "(?P<search>[\\S\\s]+)",
- "url_template": "http://www.flickr.com/search/?q={{ search }}",
- "keyword": "flickr"}},
- {"pk": 6,
- "model": "bcmagic.keywordmap",
- "fields": {"regex": "(?P<uuid>[A-Fa-f0-9]+)",
- "url_template": "/inventory/{{ uuid }}/",
- "keyword": "invu"}},
- {"pk": 7,
- "model": "bcmagic.keywordmap",
- "fields": {"regex": "(?P<barcode_id>.+)",
- "url_template": "/inventory/{{barcode_id}}/",
- "keyword": "invb"}}
-]
+++ /dev/null
-[{"pk": 1,
- "model": "bcmagic.printer",
- "fields": {"name": "ZM400 1.25x1",
- "label_height": 1.0,
- "notes": "Everyday use labels",
- "label_width": 1.25,
- "label_shape": "Square",
- "model": "Zebra ZM400",
- "ip_address": "131.215.34.116"}},
- {"pk": 2,
- "model": "bcmagic.printer",
- "fields": {"name": "ZM400 3x3",
- "label_height": 3.0,
- "notes": "Larger everyday use labels",
- "label_width": 3.0,
- "label_shape": "Square",
- "model": "Zebra ZM400",
- "ip_address": "131.215.34.117"}}]
+++ /dev/null
-from django import forms
-
-class BarcodeMagicForm(forms.Form):
- magic = forms.CharField(label="Barcode Magic", required=False)
- bcm_mode = forms.CharField(widget=forms.HiddenInput, initial="default")
-
- class Media:
- js = ('js/jquery.timers-1.0.0.js',
- 'js/bcmagic-ext.js')
+++ /dev/null
-from django.db import models
-
-#FIXME: Should be made more generic and probably pre-populated supported list
-# but for now, since we only have a ZM400, this will do.
-PRINTER_MODELS=[ ('Zebra ZM400', 'Zebra ZM400'),
- ('Zebra ZM600', 'Zebra ZM600')]
-
-LABEL_SHAPES = [ ('Square', 'Square'), ('Circle', 'Circle') ]
-
-class KeywordMap(models.Model):
- """
- Mapper object maps keyword|arg1|arg2|...|argN to REST urls
- """
- keyword = models.CharField(max_length=64)
- regex = models.CharField(max_length=1024)
- url_template = models.TextField()
-
-class Printer(models.Model):
- """
- Barcode Printer Information
- """
- name = models.CharField(max_length=256)
- model = models.CharField(max_length=64, choices=PRINTER_MODELS)
- ip_address = models.IPAddressField()
- label_shape = models.CharField(max_length=32, choices=LABEL_SHAPES)
- label_width = models.FloatField(help_text='width or diameter in inches')
- label_height = models.FloatField(help_text='height in inches')
- notes = models.TextField()
-
- def __unicode__(self):
- return u'%s, %s, %s, %s, %sx%s' % (self.name, self.model, self.ip_address, self.label_shape, self.label_width, self.label_width)
\ No newline at end of file
+++ /dev/null
-#from htsworkflow.frontend.samples import bcm_cmds
-
-#BCM_PLUGINS = {'cmd_move_sample': bcm_cmds.cmd_move_sample}
-
-_SEARCH_FUNCTIONS = {}
-
-def bcm_plugin_processor(keyword, text, bcm_mode):
- """
- Fixme should be made generic plugable, but am hard coding values for proof
- of concept.
- """
- d = {}
-
- if bcm_mode not in BCM_PLUGINS:
- d['mode'] = 'Error'
- d['status'] = 'bcm_mode plugin called "%s" was not found' % (bcm_mode)
- return d
-
- return BCM_PLUGINS[bcm_mode](keyword, text, bcm_mode)
-
-
-def register_search_plugin(label, search_function):
- """
- Registers a group label and search_function
-
- search_function(search_string) --> (text_display, obj_url)
- """
-
- if label in _SEARCH_FUNCTIONS:
- msg = "search function for label (%s) already registered." % (label)
- raise ValueError, msg
-
- _SEARCH_FUNCTIONS[label] = search_function
-
\ No newline at end of file
+++ /dev/null
-from django.conf.urls import patterns
-
-urlpatterns = patterns('',
- (r'^json_test/$', 'htsworkflow.frontend.bcmagic.views.json_test'),
- (r'^magic/$', 'htsworkflow.frontend.bcmagic.views.magic'),
- (r'^$', 'htsworkflow.frontend.bcmagic.views.index'),
-)
+++ /dev/null
-from django.conf import settings
-
-import ftplib
-import socket
-import StringIO
-
-
-def print_zpl(zpl_text, host=None):
- """
- Sends zpl_text to printer
- """
- if not host:
- host = settings.BCPRINTER_PRINTER1_HOST
- ftp = ftplib.FTP(host=host, user='blank', passwd='')
- ftp.login()
- ftp.storlines("STOR printme.txt", StringIO.StringIO(zpl_text))
- ftp.quit()
-
-
-def print_zpl_socket(zpl_text, host=None, port=None):
- """
- Sends zpl_text to printer via a socket
-
- if zpl_text is a list of zpl_texts, it will print each one
- in that list.
- """
-
- if not host:
- host=settings.BCPRINTER_PRINTER1_HOST
- if not port:
- port=settings.BCPRINTER_PRINTER1_PORT
-
- # Process anyway if zpl_text is a list.
- if type(zpl_text) is list:
- zpl_text = '\n'.join(zpl_text)
-
- s = socket.socket()
- # PORT 9100 is default for Zebra tabletop/desktop printers
- # PORT 6101 is default for Zebra mobile printers
- s.connect((host, port))
- s.sendall(zpl_text)
- s.close()
-
-
-def report_error(message):
- """
- Return a dictionary with a command to display 'message'
- """
- return {'mode': 'Error', 'status': message}
-
-
-def redirect_to_url(url):
- """
- Return a bcm dictionary with a command to redirect to 'url'
- """
- return {'mode': 'redirect', 'url': url}
-
-
-def autofill(field, value):
- """
- Return a bcm dictionary with a command to automatically fill the
- corresponding "field" with "value"
- """
- return {'mode': 'autofill', 'field': field, 'value': value}
+++ /dev/null
-from django.http import HttpResponse
-from django.template import RequestContext, Template, Context
-from django.shortcuts import render_to_response
-from django.core.exceptions import ObjectDoesNotExist
-
-from htsworkflow.frontend.bcmagic import models
-from htsworkflow.frontend.bcmagic.utils import report_error, redirect_to_url
-from htsworkflow.frontend.bcmagic.plugin import bcm_plugin_processor
-from htsworkflow.frontend.bcmagic import plugin
-#from htsworkflow.util.jsonutil import encode_json
-
-try:
- import json
-except ImportError, e:
- import simplejson as json
-
-import re
-
-from htsworkflow.frontend.bcmagic import forms
-
-def index(request):
- """
- Display a barcode magic input box
- """
- form = forms.BarcodeMagicForm()
-
- return render_to_response('bcmagic/magic.html', {'bcmagic': form},
- context_instance=RequestContext(request))
-
-
-def __plugin_search(text):
- """
- Runs registered plugins to search for results
- """
-
- hits = []
- for label, search_func in plugin._SEARCH_FUNCTIONS.items():
- result = search_func(text)
- if result is not None:
- hits.extend(result)
-
- n = len(hits)
- if n == 0:
- msg = 'No hits found for: %s' % (text)
- return report_error(msg)
- elif n == 1:
- return redirect_to_url(hits[0][1])
- else:
- msg = "%d hits found for (%s); multi-hit not implemented yet." % (n, text)
- return report_error(msg)
-
-
- #return json.dumps(hits)
-
-
-def __magic_process(text):
- """
- Based on scanned text, check to see if there is map object to use
- for a useful redirect.
- """
- # Split text on |
- split_text = text.split('|')
-
- # There should always be at least one | in a valid scan.
- if len(split_text) <= 1:
- #return report_error('Invalid text: %s' % (text))
- return __plugin_search(text)
-
- # Keyword is the first element in the list
- keyword = split_text[0]
-
- # Attempt to find a KeywordMap based on keyword
- try:
- keymap = models.KeywordMap.objects.get(keyword=keyword)
- except ObjectDoesNotExist, e:
- return report_error('Keyword (%s) is not defined' % (keyword))
-
- # Remove keyword and only scan the content
- content = '|'.join(split_text[1:])
-
- #FIXME: would be faster to cache compiled regex
- search = re.compile(keymap.regex)
-
- mo = search.search(content)
-
- # if the search was invalid
- if not mo:
- return report_error('(%s) failed to match (%s)' % (keymap.regex, content))
-
- t = Template(keymap.url_template)
- c = Context(mo.groupdict())
-
- return redirect_to_url(str(t.render(c)))
-
-
-
-
-
-def magic(request):
- """
- Let the magic begin
- """
- d = {}
-
- #Retrieve posted text from processing
- if 'text' in request.POST:
- text = request.POST['text']
- else:
- text = None
-
- #Retrieve bmc_mode for processing
- if 'bcm_mode' in request.POST:
- bcm_mode = request.POST['bcm_mode']
- else:
- bcm_mode = None
-
- ################################
- # Handle some errors
- ################################
-
- # Did not receive text error
- if text is None or text.strip() == '':
- d['mode'] = 'Error'
- d['status'] = 'Did not recieve text'
-
- return HttpResponse(json.dumps(d), 'text/plain')
-
- # Did not receive bcm_mode error
- if bcm_mode is None or bcm_mode.strip() == '':
- d['mode'] = 'Error'
- d['status'] = 'Missing bcm_mode information'
-
-
- ################################
- # Figure out which mode to use
- ################################
- keyword = text.split('|')[0]
-
- # Handle URL mode by default
- if keyword == 'url':
- d['mode'] = 'redirect'
- d['url'] = text.split('|')[1]
-
- # Pass off processing to plugins
- elif bcm_mode != 'default':
- d = bcm_plugin_processor(keyword, text, bcm_mode)
-
- # Try keyword mapper
- else:
- d = __magic_process(text)
-
- return HttpResponse(json.dumps(d), 'text/plain')
-
-
-
-def json_test(request):
- d = {}
-
- if 'text' in request.POST:
- text = request.POST['text']
- else:
- text = None
-
- #return HttpResponse(json.dumps(request.POST.items()), 'text/plain')
- if text is None or text.strip() == '':
- d['mode'] = 'Error'
- d['status'] = 'Did not recieve text'
- return HttpResponse(json.dumps(d), 'text/plain')
-
- if text.split('|')[0] == 'url':
- d['mode'] = 'redirect'
- d['url'] = text.split('|')[1]
- else:
- d['msg'] = 'Recieved text: %s' % (text)
- d['mode'] = 'clear'
-
- return HttpResponse(json.dumps(d), 'text/plain')
+++ /dev/null
-from django.contrib import admin
-from django.utils.translation import ugettext_lazy as _
-
-
+++ /dev/null
-from django import forms
-from django.forms.util import ErrorList
-
-
-SPECIES_LIST = [#('--choose--', '--Choose--'),
- ('hg18', 'Homo sapiens (Hg18)'),
- ('Mm8', 'Mus musculus (Mm8)'),
- ('arabv6', 'Arabadopsis Thaliana v6'),
- ('other', 'Other species (Include in description)')]
-
-
-class DivErrorList(ErrorList):
- def __unicode__(self):
- return self.as_divs()
-
- def as_divs(self):
- if not self: return u''
- return u'<div class="errorlist">%s</div>' % (''.join([u'<div class="error">%s</div>' % e for e in self]))
-
-
-
-class ConfigForm(forms.Form):
-
- flow_cell_number = forms.CharField(min_length=2)
- run_date = forms.DateTimeField()
- advanced_run = forms.BooleanField(required=False)
- read_length = forms.IntegerField(min_value=1, initial=32)
- #eland_repeat = forms.BooleanField()
-
- #needs a for loop or something to allow for n configurations
- #analysis_type = forms.ChoiceField(choices=[('eland','eland')])
- lane1_species = forms.ChoiceField(choices=SPECIES_LIST)
- lane1_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
-
- lane2_species = forms.ChoiceField(choices=SPECIES_LIST)
- lane2_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
-
- lane3_species = forms.ChoiceField(choices=SPECIES_LIST)
- lane3_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
-
- lane4_species = forms.ChoiceField(choices=SPECIES_LIST)
- lane4_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
-
- lane5_species = forms.ChoiceField(choices=SPECIES_LIST)
- lane5_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
-
- lane6_species = forms.ChoiceField(choices=SPECIES_LIST)
- lane6_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
-
- lane7_species = forms.ChoiceField(choices=SPECIES_LIST)
- lane7_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
-
- lane8_species = forms.ChoiceField(choices=SPECIES_LIST)
- lane8_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
-
- notes = forms.CharField(widget=forms.Textarea(attrs={'cols':'70'}), required=False)
-
- #lane_specific_read_length = forms.IntegerField(min_value=1)
-
- #eland_genome_lanes = forms.MultipleChoiceField(choices=[('lane1','1'),
- # ('lane2','2'),
- # ('lane3','3'),
- # ('lane4','4'),
- # ('lane5','5'),
- # ('lane6','6'),
- # ('lane7','7'),
- # ('lane8','8') ])
-
- #eland_genome = forms.ChoiceField(choices=)
-
- #use_bases_lanes = forms.MultipleChoiceField(choices=[('lane1','1'),
- # ('lane2','2'),
- # ('lane3','3'),
- # ('lane4','4'),
- # ('lane5','5'),
- # ('lane6','6'),
- # ('lane7','7'),
- # ('lane8','8') ])
-
- #use_bases_mask = forms.CharField()
-
- #sequence_format = forms.ChoiceField(choices=[('scarf', 'scarf')])
-
-
-
- #subject = forms.CharField(max_length=100)
- #message = forms.CharField()
- #sender = forms.EmailField()
- #cc_myself = forms.BooleanField()
-
- def as_custom(self):
- """
- Displays customized html output
- """
- html = []
-
- fcn = self['flow_cell_number']
-
- html.append(fcn.label_tag() + ': ' + str(fcn) + str(fcn.errors) + '<br />')
-
- run_date = self['run_date']
- html.append(run_date.label_tag() + ': ' + str(run_date) + str(run_date.errors) + '<br />')
-
- arun = self['advanced_run']
- html.append(arun.label_tag() + ': ' + str(arun) + str(arun.errors) + '<br />')
-
- rl = self['read_length']
- html.append(rl.label_tag() + ': ' + str(rl) + str(rl.errors) + '<br /><br />')
-
- html.append('<table border="0">')
- html.append(' <tr><td>%s</td><td>%s</td><td>%s</td></tr>' \
- % ('Lane', 'Species', 'Description'))
-
- l1s = self['lane1_species']
- l1d = self['lane1_description']
- html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
- % ('1', str(l1s), str(l1s.errors), str(l1d), str(l1d.errors)))
-
- l2s = self['lane2_species']
- l2d = self['lane2_description']
- html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
- % ('2', str(l2s), str(l2s.errors), str(l2d), str(l2d.errors)))
-
- l3s = self['lane3_species']
- l3d = self['lane3_description']
- html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
- % ('3', str(l3s), str(l3s.errors), str(l3d), str(l3d.errors)))
-
- l4s = self['lane4_species']
- l4d = self['lane4_description']
- html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
- % ('4', str(l4s), str(l4s.errors), str(l4d), str(l4d.errors)))
-
- l5s = self['lane5_species']
- l5d = self['lane5_description']
- html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
- % ('5', str(l5s), str(l5s.errors), str(l5d), str(l5d.errors)))
-
- l6s = self['lane6_species']
- l6d = self['lane6_description']
- html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
- % ('6', str(l6s), str(l6s.errors), str(l6d), str(l6d.errors)))
-
- l7s = self['lane7_species']
- l7d = self['lane7_description']
- html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
- % ('7', str(l7s), str(l7s.errors), str(l7d), str(l7d.errors)))
-
- l8s = self['lane8_species']
- l8d = self['lane8_description']
- html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
- % ('8', str(l8s), str(l8s.errors), str(l8d), str(l8d.errors)))
-
- html.append('</table><br />')
-
- notes = self['notes']
- html.append('<p>Notes:</p>')
- html.append(' %s<br />' % (str(notes)))
-
- return '\n'.join(html)
-
-
-
+++ /dev/null
-from django.db import models
-
-# Create your models here.
+++ /dev/null
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns('',
- ## Example:
-
- url(r'^(?P<flowcell>\w+)/$', 'htsworkflow.frontend.eland_config.views.config'),
- url(r'^$', 'htsworkflow.frontend.eland_config.views.config'),
- #url(r'^$', 'htsworkflow.frontend.eland_config.views.index')
-
-)
+++ /dev/null
-from __future__ import absolute_import, print_function
-
-from django.conf import settings
-from django.http import HttpResponse
-from django.core.exceptions import ObjectDoesNotExist
-
-from htsworkflow.frontend.experiments import models
-
-import os
-
-
-def _validate_input(data):
- return data.replace('..', '').replace('/', '_').replace('\\', '_')
-
-
-def getElandConfig(flowcell, regenerate=False):
-
- if hasattr(settings, 'UPLOADTO_CONFIG_FILE'):
- dest = settings.UPLOADTO_CONFIG_FILE
- else:
- dest = '/tmp'
- file_path = os.path.join(dest, flowcell)
-
- #If we are regenerating the config file, skip
- # reading of existing file. If the file doesn't
- # exist, try to generate it form the DB.
- if not regenerate and os.path.isfile(file_path):
- f = open(file_path, 'r')
- data = f.read()
- f.close()
- return data
-
- try:
- fcObj = models.FlowCell.objects.get(flowcell_id__iexact=flowcell)
- except ObjectDoesNotExist:
- return None
-
- data = []
-
- #form = form.cleaned_data
-
- data.append("# FLOWCELL: %s" % (fcObj.flowcell_id))
- data.append("#")
-
- notes = fcObj.notes.replace('\r\n', '\n').replace('\r', '\n')
- notes = notes.replace('\n', '\n# ')
- data.append("# NOTES:")
- data.append("# %s\n#" % (notes))
-
- #Convert all newline conventions to unix style
- for lane in fcObj.lane_set.all():
- data.append("# Lane%d: %s | %s" %
- (lane.lane_number, unicode(lane.library.id),
- lane.library.library_name.replace('%', '%%')))
-
- read_length = fcObj.read_length
- #data.append("ELAND_REPEAT")
- data.append("ELAND_MULTIPLE_INSTANCES 8")
-
- #Construct genome dictionary to figure out what lanes to put
- # in the config file.
- genome_dict = {}
-
- #l1s = form['lane1_species']
- for lane in fcObj.lane_set.all():
- species = lane.library.library_species.scientific_name
- genome_dict.setdefault(species, []).append(unicode(lane.lane_number))
-
- genome_list = genome_dict.keys()
- genome_list.sort()
-
- #Loop through and create entries for each species.
- for genome in genome_list:
- lanes = ''.join(genome_dict[genome])
- if fcObj.paired_end:
- data.append('%s:ANALYSIS eland_pair' % (lanes))
- else:
- data.append('%s:ANALYSIS eland_extended' % (lanes))
- data.append('%s:READ_LENGTH %s' % (lanes, read_length))
- data.append('%s:ELAND_GENOME %s' % (lanes, '%%(%s)s' % (genome)))
- data.append('%s:USE_BASES %s' % (lanes, 'Y'*int(read_length)))
-
- data.append('SEQUENCE_FORMAT --fastq')
- data.append('') # want a trailing newline
-
- data = '\n'.join(data)
-
- f = open(file_path, 'w')
- f.write(data)
- f.close()
-
- return data
-
-
-def config(request, flowcell=None):
- """
- Returns eland config file for a given flowcell number,
- or returns a list of available flowcell numbers.
- """
-
- # Provide INDEX of available Flowcell config files.
- if flowcell is None:
- fc_list = [fc.flowcell_id for fc in models.FlowCell.objects.all()]
-
- #Convert FC* list to html links
- fc_html = ['<a href="/eland_config/%s/">%s</a>' % (fc_name, fc_name)
- for fc_name in fc_list]
-
- return HttpResponse('<br />'.join(fc_html))
-
- #FIXME: Should validate flowcell input before using.
- flowcell = _validate_input(flowcell)
- cfg = getElandConfig(flowcell, regenerate=True)
-
- if not cfg:
- return HttpResponse(
- "Hmm, config file for %s does not seem to exist." % (flowcell))
-
- return HttpResponse(cfg, mimetype="text/plain")
+++ /dev/null
-from itertools import chain
-from htsworkflow.frontend.experiments.models import \
- FlowCell, DataRun, DataFile, FileType, ClusterStation, Sequencer, Lane
-from django.contrib import admin
-from django.contrib.admin.widgets import FilteredSelectMultiple
-from django.forms import ModelForm
-from django.forms.fields import Field, CharField
-from django.forms.widgets import TextInput, Select
-from django.utils.encoding import force_unicode
-from django.utils.html import escape, conditional_escape
-from django.utils.translation import ugettext_lazy as _
-
-class DataFileForm(ModelForm):
- class Meta:
- model = DataFile
- fields = ('random_key', 'data_run', 'library', 'file_type', 'relative_pathname')
-
-class DataFileInline(admin.TabularInline):
- model = DataFile
- form = DataFileForm
- raw_id_fields = ('library',)
- extra = 0
-
-class DataRunOptions(admin.ModelAdmin):
- search_fields = [
- 'flowcell_id',
- 'run_folder',
- 'run_note',
- ]
- list_display = [
- 'runfolder_name',
- 'result_dir',
- 'run_start_time',
- ]
- fieldsets = (
- (None, {
- 'fields': (('flowcell', 'run_status'),
- ('runfolder_name', 'cycle_start', 'cycle_stop'),
- ('result_dir',),
- ('last_update_time'),
- ('image_software', 'image_version'),
- ('basecall_software', 'basecall_version'),
- ('alignment_software', 'alignment_version'),
- ('comment',))
- }),
- )
- inlines = [ DataFileInline ]
- #list_filter = ('run_status', 'run_start_time')
-admin.site.register(DataRun, DataRunOptions)
-
-
-class FileTypeAdmin(admin.ModelAdmin):
- list_display = ('name', 'mimetype', 'regex')
-admin.site.register(FileType, FileTypeAdmin)
-
-# lane form setup needs to come before Flowcell form config
-# as flowcell refers to the LaneInline class
-class LaneForm(ModelForm):
- comment = CharField(widget=TextInput(attrs={'size':'80'}), required=False)
-
- class Meta:
- model = Lane
- fields = ('flowcell', 'lane_number', 'library', 'pM', 'cluster_estimate',
- 'status', 'comment')
-
-class LaneInline(admin.StackedInline):
- """
- Controls display of Lanes on the Flowcell form.
- """
- model = Lane
- extra = 8
- form = LaneForm
- raw_id_fields = ('library',)
- fieldsets = (
- (None, {
- 'fields': ('lane_number', 'flowcell',
- ('library',),
- ('pM', 'cluster_estimate', 'status'),
- 'comment',)
- }),
- )
-
-class LaneOptions(admin.ModelAdmin):
- """
- Controls display of Lane browser
- """
- search_fields = ('=flowcell__flowcell_id', 'library__id', 'library__library_name' )
- list_display = ('flowcell', 'lane_number', 'library', 'comment')
- fieldsets = (
- (None, {
- 'fields': ('lane_number', 'flowcell',
- ('library'),
- ('pM', 'cluster_estimate'))
- }),
- ('Optional', {
- 'classes': ('collapse', ),
- 'fields': ('comment', )
- }),
- )
-admin.site.register(Lane, LaneOptions)
-
-class FlowCellOptions(admin.ModelAdmin):
- class Media:
- css = { 'all': ('css/admin_flowcell.css',) }
- date_hierarchy = "run_date"
- save_on_top = True
- search_fields = ('flowcell_id',
- 'sequencer__name',
- 'cluster_station__name',
- '=lane__library__id',
- 'lane__library__library_name')
- list_display = ('flowcell_id','run_date','Lanes')
- list_filter = ('sequencer','cluster_station', 'paired_end')
- fieldsets = (
- (None, {
- 'fields': ('run_date', ('flowcell_id','cluster_station','sequencer'),
- ('read_length', 'control_lane', 'paired_end'),)
- }),
- ('Notes:', { 'fields': ('notes',),}),
- )
- inlines = [
- LaneInline,
- ]
-
- def formfield_for_dbfield(self, db_field, **kwargs):
- field = super(FlowCellOptions, self).formfield_for_dbfield(db_field,
- **kwargs)
-
- # Override field attributes
- if db_field.name == 'sequencer':
- # seems kind of clunky.
- # the goal is to replace the default select/combo box with one
- # that can strike out disabled options.
- attrs = field.widget.widget.attrs
- field.widget.widget = SequencerSelect(attrs=attrs, queryset=field.queryset)
- elif db_field.name == "notes":
- field.widget.attrs["rows"] = "3"
- return field
-admin.site.register(FlowCell, FlowCellOptions)
-
-class ClusterStationOptions(admin.ModelAdmin):
- list_display = ('name', 'isdefault',)
- fieldsets = ( ( None, { 'fields': ( 'name', 'isdefault') } ), )
-admin.site.register(ClusterStation, ClusterStationOptions)
-
-class SequencerSelect(Select):
- def __init__(self, queryset=None, *args, **kwargs):
- super(SequencerSelect, self).__init__(*args, **kwargs)
- self.queryset = queryset
-
- def render_options(self, choices, selected_choices):
- # Normalize to strings.
- selected_choices = set([force_unicode(v) for v in selected_choices])
- output = []
- for option_value, option_label in chain(self.choices, choices):
- if isinstance(option_label, (list, tuple)):
- output.append(u'<optgroup label="%s">' % escape(force_unicode(option_value)))
- for option in option_label:
- output.append(self.render_option(selected_choices, *option))
- output.append(u'</optgroup>')
- else:
- output.append(self.render_option(selected_choices, option_value, option_label))
- return u'\n'.join(output)
-
- # render_options blatently grabbed from 1.3.1 as the 1.2 version
- # has render_option, which is what I needed to overload as a
- # nested function in render_options
- def render_options(self, choices, selected_choices):
- # Normalize to strings.
- selected_choices = set([force_unicode(v) for v in selected_choices])
- output = []
- for option_value, option_label in chain(self.choices, choices):
- if isinstance(option_label, (list, tuple)):
- output.append(u'<optgroup label="%s">' % escape(force_unicode(option_value)))
- for option in option_label:
- output.append(self.render_option(selected_choices, *option))
- output.append(u'</optgroup>')
- else:
- output.append(self.render_option(selected_choices, option_value, option_label))
- return u'\n'.join(output)
-
-
- def render_option(self, selected_choices, option_value, option_label):
- disabled_sequencers = [ unicode(s.id) for s in self.queryset.filter(active=False) ]
- option_value = unicode(option_value)
- selected_html = (option_value in selected_choices) and u' selected="selected"' or ''
- cssclass = "strikeout" if option_value in disabled_sequencers else ''
- return u'<option class="%s" value="%s"%s>%s</option>' % (
- cssclass, escape(option_value), selected_html,
- conditional_escape(force_unicode(option_label)))
-
-class SequencerOptions(admin.ModelAdmin):
- list_display = ('name', 'active', 'isdefault', 'instrument_name', 'model')
- fieldsets = ( ( None,
- { 'fields': (
- 'name', ('active', 'isdefault'), 'instrument_name', 'serial_number',
- 'model', 'comment') } ), )
-
-admin.site.register(Sequencer, SequencerOptions)
+++ /dev/null
-# some core functions of the exp tracker module
-from datetime import datetime, timedelta
-try:
- import json
-except ImportError, e:
- import simplejson as json
-
-import os
-import re
-
-from django.contrib.auth.decorators import login_required
-from django.views.decorators.csrf import csrf_exempt
-from django.core.exceptions import ObjectDoesNotExist
-from django.core.mail import send_mail, mail_admins
-from django.http import HttpResponse, Http404
-from django.conf import settings
-from django.utils import timezone
-
-from htsworkflow.frontend.auth import require_api_key
-from htsworkflow.frontend.experiments.models import \
- FlowCell, \
- DataRun, \
- Lane, \
- LANE_STATUS_MAP
-from htsworkflow.frontend.samples.models import Library, MultiplexIndex, HTSUser
-
-def flowcell_information(flowcell_id):
- """
- Return a dictionary describing a flowcell
- """
- try:
- fc = FlowCell.objects.get(flowcell_id__startswith=flowcell_id)
- except FlowCell.DoesNotExist, e:
- return None
-
- lane_set = {}
- for lane in fc.lane_set.all():
- lane_item = {
- 'cluster_estimate': lane.cluster_estimate,
- 'comment': lane.comment,
- 'experiment_type': lane.library.experiment_type.name,
- 'experiment_type_id': lane.library.experiment_type_id,
- 'flowcell': lane.flowcell.flowcell_id,
- 'lane_number': lane.lane_number,
- 'library_name': lane.library.library_name,
- 'library_id': lane.library.id,
- 'library_species': lane.library.library_species.scientific_name,
- 'pM': unicode(lane.pM),
- 'read_length': lane.flowcell.read_length,
- 'status_code': lane.status,
- 'status': LANE_STATUS_MAP[lane.status]
- }
- sequences = lane.library.index_sequences()
- if sequences is not None:
- lane_item['index_sequence'] = sequences
-
- lane_set.setdefault(lane.lane_number,[]).append(lane_item)
-
- if fc.control_lane is None:
- control_lane = None
- else:
- control_lane = int(fc.control_lane)
-
- info = {
- 'advanced_run': fc.advanced_run,
- 'cluster_station_id': fc.cluster_station_id,
- 'cluster_station': fc.cluster_station.name,
- 'control_lane': control_lane,
- # 'datarun_set': how should this be represented?,
- 'flowcell_id': fc.flowcell_id,
- 'id': fc.id,
- 'lane_set': lane_set,
- 'notes': fc.notes,
- 'paired_end': fc.paired_end,
- 'read_length': fc.read_length,
- 'run_date': fc.run_date.isoformat(),
- 'sequencer_id': fc.sequencer_id,
- 'sequencer': fc.sequencer.name,
- }
-
- return info
-
-@csrf_exempt
-def flowcell_json(request, fc_id):
- """
- Return a JSON blob containing enough information to generate a config file.
- """
- require_api_key(request)
-
- fc_dict = flowcell_information(fc_id)
-
- if fc_dict is None:
- raise Http404
-
- fc_json = json.dumps(fc_dict)
- return HttpResponse(fc_json, content_type = 'application/json')
-
-def lanes_for(username=None):
- """
- Given a user id try to return recent lanes as a list of dictionaries
- """
- query = {}
- if username is not None:
- user = HTSUser.objects.get(username=username)
- query.update({'library__affiliations__users__id': user.id})
-
- lanes = Lane.objects.filter(**query).order_by('-flowcell__run_date')
-
-
- result = []
- for l in lanes:
- affiliations = l.library.affiliations.all()
- affiliations_list = [(a.id, a.name) for a in affiliations]
- result.append({ 'flowcell': l.flowcell.flowcell_id,
- 'run_date': l.flowcell.run_date.isoformat(),
- 'lane_number': l.lane_number,
- 'library': l.library.id,
- 'library_name': l.library.library_name,
- 'comment': l.comment,
- 'affiliations': affiliations_list})
- return result
-
-@csrf_exempt
-def lanes_for_json(request, username):
- """
- Format lanes for a user
- """
- require_api_key(request)
-
- try:
- result = lanes_for(username)
- except ObjectDoesNotExist, e:
- raise Http404
-
- #convert query set to python structure
-
- result_json = json.dumps(result)
- return HttpResponse(result_json, content_type='application/json')
-
-
-def updStatus(request):
- output=''
- user = 'none'
- pswd = ''
- UpdatedStatus = 'unknown'
- fcid = 'none'
- runfolder = 'unknown'
- ClIP = request.META['REMOTE_ADDR']
-
- if hasattr(request, 'user'):
- user = request.user
-
- #Check access permission
- if not (user.is_superuser and settings.ALLOWED_IPS.has_key(ClIP)):
- return HttpResponse("%s access denied from %s." % (user, ClIP))
-
- # ~~~~~~Parameters for the job ~~~~
- if request.REQUEST.has_key('fcid'):
- fcid = request.REQUEST['fcid']
- else:
- return HttpResponse('missing fcid')
-
- if request.REQUEST.has_key('runf'):
- runfolder = request.REQUEST['runf']
- else:
- return HttpResponse('missing runf')
-
-
- if request.REQUEST.has_key('updst'):
- UpdatedStatus = request.REQUEST['updst']
- else:
- return HttpResponse('missing status')
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- # Update Data Run status in DB
- # Try get rec. If not found return 'entry not found + <fcid><runfolder>', if found try update and return updated
- try:
- rec = DataRun.objects.get(run_folder=runfolder)
- rec.run_status = UpdatedStatus
-
- #if there's a message update that too
- mytimestamp = timezone.now().__str__()
- mytimestamp = re.sub(pattern=":[^:]*$",repl="",string=mytimestamp)
- if request.REQUEST.has_key('msg'):
- rec.run_note += ", "+request.REQUEST['msg']+" ("+mytimestamp+")"
- else :
- if UpdatedStatus == '1':
- rec.run_note = "Started ("+mytimestamp+")"
-
- rec.save()
- output = "Hello "+settings.ALLOWED_IPS[ClIP]+". Updated to:'"+DataRun.RUN_STATUS_CHOICES[int(UpdatedStatus)][1].__str__()+"'"
- except ObjectDoesNotExist:
- output = "entry not found: "+fcid+", "+runfolder
-
-
- #Notify researcher by email
- # Doesn't work
- #send_mail('Exp Tracker', 'Data Run Status '+output, 'rrauch@stanford.edu', ['rrrami@gmail.com'], fail_silently=False)
- #mail_admins("test subject", "testing , testing", fail_silently=False)
- # gives error: (49, "Can't assign requested address")
- return HttpResponse(output)
-
-def generateConfile(request,fcid):
- #granted = False
- #ClIP = request.META['REMOTE_ADDR']
- #if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
-
- #if not granted: return HttpResponse("access denied.")
-
- config = ['READ_LENGTH 25']
- config += ['ANALYSIS eland']
- config += ['GENOME_FILE all_chr.fa']
- config += ['ELAND_MULTIPLE_INSTANCES 8']
- genome_dir = 'GENOME_DIR /Volumes/Genomes/'
- eland_genome = 'ELAND_GENOME /Volumes/Genomes/'
-
- try:
- fc = FlowCell.objects.get(flowcell_id=fcid)
- for lane in fc.lane_set.all():
- config += [ str(lane.lane_number) +":" + \
- genome_dir + lane.library.library_species.scientific_name ]
- config += [ str(lane.lane_number) +":" + \
- eland_genome + lane.library.library_species.scientific_name ]
-
- except ObjectDoesNotExist:
- config = 'Entry not found for fcid = '+fcid
-
- return os.linesep.join(config)
-
-def getConfile(req):
- granted = False
- ClIP = req.META['REMOTE_ADDR']
- if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
-
- if not granted: return HttpResponse("access denied. IP: "+ClIP)
-
- fcid = 'none'
- cnfgfile = 'Nothing found'
- runfolder = 'unknown'
- request = req.REQUEST
- if request.has_key('fcid'):
- fcid = request['fcid']
- if request.has_key('runf'):
- runfolder = request['runf']
- try:
- rec = DataRun.objects.get(run_folder=runfolder) #,flowcell_id=fcid)
- cnfgfile = rec.config_params
- #match_str = re.compile(r"READ_LENGTH.+$")
- match_str = re.compile('^READ_LENGTH.+')
- if not match_str.search(cnfgfile):
- cnfgfile = generateConfile(request,fcid)
- if match_str.search(cnfgfile):
- rec = DataRun.objects.get(run_folder=runfolder) #,flowcell_id=fcid)
- rec.config_params = cnfgfile
- rec.save()
- else:
- cnfgfile = 'Failed generating config params for RunFolder = '+runfolder +', Flowcell id = '+ fcid+ ' Config Text:\n'+cnfgfile
-
- except ObjectDoesNotExist:
- cnfgfile = 'Entry not found for RunFolder = '+runfolder
-
- return HttpResponse(cnfgfile, content_type='text/plain')
-
-def getLaneLibs(req):
- granted = False
- ClIP = req.META['REMOTE_ADDR']
- if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
-
- if not granted: return HttpResponse("access denied.")
-
- request = req.REQUEST
- fcid = 'none'
- outputfile = ''
- if request.has_key('fcid'):
- fcid = request['fcid']
- try:
- rec = FlowCell.objects.get(flowcell_id=fcid)
- #Ex: 071211
- year = datetime.today().year.__str__()
- year = replace(year,'20','')
- month = datetime.today().month
- if month < 10: month = "0"+month.__str__()
- else: month = month.__str__()
- day = datetime.today().day
- if day < 10: day = "0"+day.__str__()
- else: day = day.__str__()
- mydate = year+month+day
- outputfile = '<?xml version="1.0" ?>'
- outputfile += '\n<SolexaResult Date="'+mydate+'" Flowcell="'+fcid+'" Client="'+settings.ALLOWED_IPS[ClIP]+'">'
- outputfile += '\n<Lane Index="1" Name="'+rec.lane_1_library.library_name+'" Library="'+rec.lane_1_library.id+'" Genome="'+rec.lane_1_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
- outputfile += '\n<Lane Index="2" Name="'+rec.lane_2_library.library_name+'" Library="'+rec.lane_2_library.id+'" Genome="'+rec.lane_2_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
- outputfile += '\n<Lane Index="3" Name="'+rec.lane_3_library.library_name+'" Library="'+rec.lane_3_library.id+'" Genome="'+rec.lane_3_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
- outputfile += '\n<Lane Index="4" Name="'+rec.lane_4_library.library_name+'" Library="'+rec.lane_4_library.id+'" Genome="'+rec.lane_4_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
- outputfile += '\n<Lane Index="5" Name="'+rec.lane_5_library.library_name+'" Library="'+rec.lane_5_library.id+'" Genome="'+rec.lane_5_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
- outputfile += '\n<Lane Index="6" Name="'+rec.lane_6_library.library_name+'" Library="'+rec.lane_6_library.id+'" Genome="'+rec.lane_6_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
- outputfile += '\n<Lane Index="7" Name="'+rec.lane_7_library.library_name+'" Library="'+rec.lane_7_library.id+'" Genome="'+rec.lane_7_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
- outputfile += '\n<Lane Index="8" Name="'+rec.lane_8_library.library_name+'" Library="'+rec.lane_8_library.id+'" Genome="'+rec.lane_8_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
- outputfile += '\n</SolexaResult>'
- except ObjectDoesNotExist:
- outputfile = 'Flowcell entry not found for: '+fcid
- else: outputfile = 'Missing input: flowcell id'
-
- return HttpResponse(outputfile, content_type='text/plain')
-
-def estimateFlowcellDuration(flowcell):
- """
- Attempt to estimate how long it will take to run a flowcell
-
- """
- # (3600 seconds * 1.5 hours per cycle )
- sequencing_seconds_per_cycle= 3600 * 1.5
- # 800 is a rough guess
- pipeline_seconds_per_cycle = 800
-
- cycles = flowcell.read_length
- if flowcell.paired_end:
- cycles *= 2
- sequencing_time = timedelta(0, cycles * sequencing_seconds_per_cycle)
- analysis_time = timedelta(0, cycles * pipeline_seconds_per_cycle)
- estimate_mid = sequencing_time + analysis_time
-
- return estimate_mid
-
-def estimateFlowcellTimeRemaining(flowcell):
- estimate_mid = estimateFlowcellDuration(flowcell)
-
- # offset for how long we've been running
- running_time = timezone.now() - flowcell.run_date
- estimate_mid -= running_time
-
- return estimate_mid
-
-def roundToDays(estimate):
- """
- Given a time estimate round up and down in days
- """
- # floor estimate_mid
- estimate_low = timedelta(estimate.days, 0)
- # floor estimate_mid and add a day
- estimate_high = timedelta(estimate.days+1, 0)
-
- return (estimate_low, estimate_high)
-
-
-def makeUserLaneMap(flowcell):
- """
- Given a flowcell return a mapping of users interested in
- the libraries on those lanes.
- """
- users = {}
-
- for lane in flowcell.lane_set.all():
- for affiliation in lane.library.affiliations.all():
- for user in affiliation.users.all():
- users.setdefault(user,[]).append(lane)
-
- return users
-
-def getUsersForFlowcell(flowcell):
- users = set()
-
- for lane in flowcell.lane_set.all():
- for affiliation in lane.library.affiliations.all():
- for user in affiliation.users.all():
- users.add(user)
-
- return users
-
-def makeUserLibraryMap(libraries):
- """
- Given an interable set of libraries return a mapping or
- users interested in those libraries.
- """
- users = {}
-
- for library in libraries:
- for affiliation in library.affiliations.all():
- for user in affiliation.users.all():
- users.setdefault(user,[]).append(library)
-
- return users
-
-def makeAffiliationLaneMap(flowcell):
- affs = {}
-
- for lane in flowcell.lane_set.all():
- for affiliation in lane.library.affiliations.all():
- affs.setdefault(affiliation,[]).append(lane)
-
- return affs
-
-def makeEmailLaneMap(flowcell):
- """
- Create a list of email addresses and the lanes associated with those users.
-
- The email addresses can come from both the "users" table and the "affiliations" table.
- """
- emails = {}
- for lane in flowcell.lane_set.all():
- for affiliation in lane.library.affiliations.all():
- if affiliation.email is not None and len(affiliation.email) > 0:
- emails.setdefault(affiliation.email,set()).add(lane)
- for user in affiliation.users.all():
- if user.email is not None and len(user.email) > 0:
- emails.setdefault(user.email,set()).add(lane)
-
- return emails
+++ /dev/null
-[
- { "model": "experiments.FileType",
- "pk": 1,
- "fields": {
- "name": "run_xml",
- "mimetype": "application/vnd.htsworkflow-run-xml",
- "regex": "run.*\\.xml\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 2,
- "fields": {
- "name": "Summary.htm",
- "mimetype": "text/html",
- "regex": "Summary\\.htm\\Z(?ms)"
- }
- },
-
- { "model": "experiments.FileType",
- "pk": 3,
- "fields": {
- "name": "IVC All",
- "mimetype": "image/png",
- "regex": "s_(?P<lane>[0-9])_all\\.png\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 4,
- "fields": {
- "name": "IVC Call",
- "mimetype": "image/png",
- "regex": "s_(?P<lane>[0-9])_call\\.png\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 5,
- "fields": {
- "name": "IVC Percent All",
- "mimetype": "image/png",
- "regex": "s_(?P<lane>[0-9])_percent_all\\.png\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 6,
- "fields": {
- "name": "IVC Percent Base",
- "mimetype": "image/png",
- "regex": "s_(?P<lane>[0-9])_percent_base\\.png\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 7,
- "fields": {
- "name": "IVC Percent Call",
- "mimetype": "image/png",
- "regex": "s_(?P<lane>[0-9])_percent_call\\.png\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 8,
- "fields": {
- "name": "GERALD Scores",
- "regex": "scores\\.tar\\.bz2\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 9,
- "fields": {
- "name": "ELAND Result",
- "mimetype": "chemical/seq-na-eland",
- "regex": "s_(?P<lane>[0-9])((?P<end>[1-4])_)?_eland_result\\.txt\\.bz2\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 10,
- "fields": {
- "name": "ELAND Multi",
- "mimetype": "chemical/seq-na-eland",
- "regex": "s_(?P<lane>[0-9])((?P<end>[1-4])_)?_eland_multi\\.txt\\.bz2\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 11,
- "fields": {
- "name": "ELAND Extended",
- "mimetype": "chemical/seq-na-eland",
- "regex": "s_(?P<lane>[0-9])((?P<end>[1-4])_)?_eland_extended\\.txt\\.bz2\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 12,
- "fields": {
- "name": "ELAND Export",
- "mimetype": "chemical/seq-na-eland",
- "regex": "s_(?P<lane>[0-9])((?P<end>[1-4])_)?_export\\.txt\\.bz2\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 13,
- "fields": {
- "name": "SRF",
- "mimetype": "chemical/seq-na-srf",
- "regex": ".*_(?P<lane>[1-8])\\.srf\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 14,
- "fields": {
- "name": "QSEQ tarfile",
- "mimetype": "chemical/seq-na-qseq",
- "regex": ".*_l(?P<lane>[1-8])_r(?P<end>[1-4])\\.tar\\.bz2\\Z(?ms)"
- }
- },
- { "model": "experiments.FileType",
- "pk": 15,
- "fields": {
- "name": "HiSeq Fastq",
- "mimetype": "chemical/seq-na-fastq",
- "regex": "(?P<library>[0-9]+)_(NoIndex|[AGCT]+)_L(?P<lane>[0-9]+)_R(?P<end>[12])_(?P<split>[0-9]+)\\.fastq\\.gz"
- }
- }
-]
+++ /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-01T00:00:01-0800",
- "groups": [],
- "user_permissions": [],
- "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
- "email": "",
- "date_joined": "2009-01-01T00:01:01-0800"
- }
- },
- {"pk": 5, "model": "samples.htsuser",
- "fields" : {}
- },
- {"pk": 6, "model": "auth.user",
- "fields": {
- "username": "admintest",
- "first_name": "",
- "last_name": "",
- "is_active": true,
- "is_superuser": false,
- "is_staff": true,
- "last_login": "2009-01-01T00:00:01-0800",
- "groups": [],
- "user_permissions": [],
- "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
- "email": "",
- "date_joined": "2009-01-01T00:01:01-0800"
- }
- },
- {"pk": 6, "model": "samples.htsuser",
- "fields" : {}
- },
- {"pk": 7, "model": "auth.user",
- "fields": {
- "username": "supertest",
- "first_name": "",
- "last_name": "",
- "is_active": true,
- "is_superuser": true,
- "is_staff": true,
- "last_login": "2009-01-01T00:00:01-0800",
- "groups": [],
- "user_permissions": [],
- "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
- "email": "",
- "date_joined": "2009-01-01T00:01:01-0800"
- }
- },
- {"pk": 7, "model": "samples.htsuser",
- "fields" : {}
- },
- {"pk": 1, "model": "samples.affiliation",
- "fields": {
- "users": [5],
- "contact": "group 1",
- "name": "affiliation 1",
- "email": "pk1@example.com"
- }
- },
- {"pk": 2, "model": "samples.affiliation",
- "fields": {
- "users": [6],
- "contact": "group 2",
- "name": "affiliation 2",
- "email": "pk2@example.com"
- }
- },
- {"pk": 3, "model": "samples.affiliation",
- "fields": {
- "users": [],
- "contact": "group 3",
- "name": "affiliation 3",
- "email": "pk3@example.com"
- }
- },
- {"pk": 4, "model": "samples.affiliation",
- "fields": {
- "users": [],
- "contact": "group 4",
- "name": "affiliation 4",
- "email": "pk1@example.com"
- }
- },
- {"pk": 5, "model": "samples.affiliation",
- "fields": {
- "users": [],
- "contact": "group 5",
- "name": "affiliation 5",
- "email": "pk5@example.com"
- }
- },
- {"pk": 1, "model": "experiments.clusterstation",
- "fields": {"name": "old", "isdefault": false}},
- {"pk": 2, "model": "experiments.clusterstation",
- "fields": {"name": "loaner", "isdefault": true}},
- {"pk": 3, "model": "experiments.clusterstation",
- "fields": {"name": "new", "isdefault": false}},
- {"pk": 1, "model": "experiments.sequencer",
- "fields": { "name": "Rotifer (HWI-EAS229)",
- "model": "Illumina Genome Analyzer I",
- "active": false,
- "isdefault": false }},
- {"pk": 2, "model": "experiments.sequencer",
- "fields": {"name": "Tardigrade",
- "instrument_name": "ILLUMINA-EC5D15",
- "model": "Illumina Genome Analyzer IIx",
- "active": true,
- "isdefault": true}
- },
- {"pk": 3, "model": "experiments.sequencer",
- "fields": {"name": "Sequenced somewhere else.",
- "model": "Unknown",
- "active": true,
- "isdefault": false}},
- {"pk": 153, "model": "experiments.flowcell",
- "fields": {
- "paired_end": true,
- "run_date": "2007-09-27T22:12:13-0800",
- "read_length": 36,
- "notes": "",
- "advanced_run": false,
- "control_lane": 2,
- "cluster_station": 3,
- "sequencer": 2,
- "flowcell_id": "FC12150"
- }
- },
- {"pk": 1193, "model": "experiments.lane",
- "fields": {
- "comment": "No change in cluster numbers, despite slight increase in pM",
- "library": "10981",
- "cluster_estimate": 129000,
- "flowcell": 153,
- "lane_number": 1,
- "pM": "8"
- }
- },
- {"pk": 1192, "model": "experiments.lane",
- "fields": {
- "comment": "Other library",
- "library": "11070",
- "cluster_estimate": 132000,
- "flowcell": 153,
- "lane_number": 1,
- "pM": "7"
- }
- },
-
- {"pk": "10981", "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 400,
- "library_name": "Paired End Multiplexed Sp-BAC",
- "creation_date": "2009-07-21",
- "cell_line": 1,
- "library_species": 10,
- "library_type": null,
- "made_by": "Igor",
- "affiliations": [
- 1,2
- ],
- "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": 1194, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11016",
- "cluster_estimate": 152000,
- "flowcell": 153,
- "lane_number": 2,
- "pM": "7"
- }
- },
- {
- "pk": "11006",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 325,
- "library_name": "Paired End Pfl #3 MP 7/24/9",
- "creation_date": "2009-08-05",
- "cell_line": 1,
- "library_species": 8,
- "library_type": 2,
- "made_by": "Lorian",
- "affiliations": [
- 3
- ],
- "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
- }
- },
- {
- "pk": "11016",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 325,
- "library_name": "Paired End Pfl #3 MP 7/24/9 a",
- "creation_date": "2009-08-06",
- "cell_line": 1,
- "library_species": 2,
- "library_type": 2,
- "made_by": "Lorian",
- "affiliations": [
- 2
- ],
- "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": 1195, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "SL039",
- "cluster_estimate": 162000,
- "flowcell": 153,
- "lane_number": 3,
- "pM": "7"
- }
- },
- {
- "pk": "SL039",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_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": [
- 3,4
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "Brian Williams",
- "amplified_from_sample": 11006,
- "notes": "fragment size = 300 bp, Amicon filtered\r\nnanodrop: 56.3",
- "undiluted_concentration": "28.7",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 1196, "model": "experiments.lane",
- "fields": {
- "comment": "This lane's library had the second lowest concentration of all the libraries built at the same time (2.05ng/ul)",
- "library": "11060",
- "cluster_estimate": 24000,
- "flowcell": 153,
- "lane_number": 4,
- "pM": "7"
- }
- },
- {
- "pk": "11060",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired ends 100 VC_CN_4_M_MBB1185_s1",
- "creation_date": "2009-09-01",
- "cell_line": 1,
- "library_species": 8,
- "library_type": 2,
- "made_by": "Brian Williams",
- "affiliations": [
- 5
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "Brian Williams",
- "amplified_from_sample": 11006,
- "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 24.2",
- "undiluted_concentration": "2.05",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 1197, "model": "experiments.lane",
- "fields": {
- "comment": "stuff",
- "library": "11061",
- "cluster_estimate": 140000,
- "flowcell": 153,
- "lane_number": 5,
- "pM": "7",
- "status": 2
- }
- },
- {
- "pk": "11061",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired ends 101 VC_CN_4_M_MBB1185_s2",
- "creation_date": "2009-09-01",
- "cell_line": 1,
- "library_species": 8,
- "library_type": 2,
- "made_by": "Brian Williams",
- "affiliations": [
- 2,4
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "Brian Williams",
- "amplified_from_sample": null,
- "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 33.1",
- "undiluted_concentration": "12.9",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 1198, "model": "experiments.lane",
- "fields": {
- "comment": "This lane's library had the lowest concentration of all the libraries built at the same time (1.2ng/ul)",
- "library": "11062",
- "cluster_estimate": 2000,
- "flowcell": 153,
- "lane_number": 6,
- "pM": "7",
- "status": 0
- }
- },
- {
- "pk": "11062",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired ends 102 VC_AU_8_M_MBB4721_s1",
- "creation_date": "2009-09-01",
- "cell_line": 1,
- "library_species": 8,
- "library_type": 2,
- "made_by": "Brian Williams",
- "affiliations": [
- 4,5
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "Brian Williams",
- "amplified_from_sample": null,
- "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 13.9",
- "undiluted_concentration": "1.2",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 1199, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11063",
- "cluster_estimate": 120000,
- "flowcell": 153,
- "lane_number": 7,
- "pM": "7"
- }
- },
- {
- "pk": "11063",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired ends 103 VC_AU_8_M_MBB4721_s2",
- "creation_date": "2009-09-01",
- "cell_line": 1,
- "library_species": 8,
- "library_type": 2,
- "made_by": "Brian Williams",
- "affiliations": [
- 1,3
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "Brian Williams",
- "amplified_from_sample": null,
- "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 46.9",
- "undiluted_concentration": "24.5",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 1200, "model": "experiments.lane",
- "fields": {
- "comment": "This lane's library had the third lowest concentration of all the libraries built at the same time (5.21ng/ul), but gave perfectly normal cluster numbers",
- "library": "11064",
- "cluster_estimate": 157000,
- "flowcell": 153,
- "lane_number": 8,
- "pM": "7"
- }
- },
- {
- "pk": "11064",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired ends 104 VC_CN_7_M_MBB4898_s1",
- "creation_date": "2009-09-01",
- "cell_line": 1,
- "library_species": 8,
- "library_type": 2,
- "made_by": "Brian Williams",
- "affiliations": [
- 3,5
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "Brian Williams",
- "amplified_from_sample": null,
- "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 20.4",
- "undiluted_concentration": "5.21",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 152, "model": "experiments.flowcell",
- "fields": {
- "paired_end": false,
- "run_date": "2009-09-10T18:30:15-0800",
- "read_length": 38,
- "notes": "328461 4897273 RGT-0248815\r\n328479 4897265 RGT-0249274\r\n330421 4822845 SR-0005496",
- "advanced_run": false,
- "control_lane": 4,
- "cluster_station": 3,
- "sequencer": 1,
- "flowcell_id": "42JTNAAXX"
- }
- },
- {"pk": 1185, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11035",
- "cluster_estimate": 174000,
- "flowcell": 152,
- "lane_number": 1,
- "pM": "7"
- }
- },
- {
- "pk": "11035",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired ends 95 Gilberto_d3_control_LTA",
- "creation_date": "2009-08-25",
- "cell_line": 1,
- "library_species": 9,
- "library_type": 2,
- "made_by": "Brian Williams",
- "affiliations": [
- 3
- ],
- "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: 67.1",
- "undiluted_concentration": "28.5",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 1186, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11037",
- "cluster_estimate": 173000,
- "flowcell": 152,
- "lane_number": 2,
- "pM": "7"
- }
- },
- {
- "pk": "11037",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired ends 97 Kuntz_PDHT",
- "creation_date": "2009-08-25",
- "cell_line": 1,
- "library_species": 3,
- "library_type": 2,
- "made_by": "Brian Williams",
- "affiliations": [
- 4
- ],
- "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: 52.7",
- "undiluted_concentration": "25.5",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 1187, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11045",
- "cluster_estimate": 198000,
- "flowcell": 152,
- "lane_number": 3,
- "pM": "7"
- }
- },
- {
- "pk": "11045",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 250,
- "library_name": "FLDN1 8/3/9 anti-AcH3 chip B6 a",
- "creation_date": "2009-08-26",
- "cell_line": null,
- "library_species": 9,
- "library_type": 1,
- "made_by": "Lorian",
- "affiliations": [
- 5
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "2A",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/21/2009 11:57:54\tColor: Yellow",
- "undiluted_concentration": "20.5",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {"pk": 1188, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11046",
- "cluster_estimate": 212000,
- "flowcell": 152,
- "lane_number": 4,
- "pM": "7"}
- },
- {
- "pk": "11046",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 250,
- "library_name": "FLDN1 7/8/9 anti-DiMeH3K4 chip B6 a",
- "creation_date": "2009-08-26",
- "cell_line": null,
- "library_species": 9,
- "library_type": 1,
- "made_by": "Lorian",
- "affiliations": [
- 4
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "2A",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/21/2009 11:57:54\tColor: Blue",
- "undiluted_concentration": "23.9",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {"pk": 1189, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11054",
- "cluster_estimate": 49000,
- "flowcell": 152,
- "lane_number": 5,
- "pM": "7"
- }
- },
- {
- "pk": "11054",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 225,
- "library_name": "HNDHT HLH hnd-1 strain HT115 fed anti-hlh-1 2% fix plate a",
- "creation_date": "2009-08-31",
- "cell_line": null,
- "library_species": 3,
- "library_type": 1,
- "made_by": "Lorian",
- "affiliations": [
- 1
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/26/2009 14:46:56\tColor: Purple",
- "undiluted_concentration": "1.47",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {"pk": 1190, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11056",
- "cluster_estimate": 48000,
- "flowcell": 152,
- "lane_number": 6,
- "pM": "7"
- }
- },
- {
- "pk": "11056",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 225,
- "library_name": "HNDM3 HLH hnd-1 strain mex-3 fed anti-hlh-1 2% fix plate a",
- "creation_date": "2009-08-31",
- "cell_line": null,
- "library_species": 3,
- "library_type": 1,
- "made_by": "Lorian",
- "affiliations": [
- 2
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/26/2009 14:46:56\tColor: Black",
- "undiluted_concentration": "1.42",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {"pk": 1191, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11057",
- "cluster_estimate": 4000,
- "flowcell": 152,
- "lane_number": 7,
- "pM": "7"
- }
- },
- {
- "pk": "11057",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 225,
- "library_name": "HNDM3 4H8 hnd-1 strain mex-3 fed 4H8 2% fix plate a",
- "creation_date": "2009-08-31",
- "cell_line": null,
- "library_species": 3,
- "library_type": 1,
- "made_by": "Lorian",
- "affiliations": [
- 3
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/26/2009 14:46:56\tColor: Orange.",
- "undiluted_concentration": "1.3",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {"pk": 1192, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11065",
- "cluster_estimate": 5000,
- "flowcell": 152,
- "lane_number": 8,
- "pM": "7"
- }
- },
- {
- "pk": "11065",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired ends 105 Kuntz PDM3",
- "creation_date": "2009-09-01",
- "cell_line": 1,
- "library_species": 3,
- "library_type": 2,
- "made_by": "Brian Williams",
- "affiliations": [
- 4
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "Brian Williams",
- "amplified_from_sample": null,
- "notes": "300 bp gel fragment, Amicon filtered\r\nnanodrop: 30.5",
- "undiluted_concentration": "2.47",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 151, "model": "experiments.flowcell",
- "fields": {
- "paired_end": false,
- "run_date": "2009-09-08T15:39:28-0800",
- "read_length": 38,
- "notes": "Rebuild of broken flowcell\r\n\r\n328461 4820241 RGT-0215719\r\n328479 4897265 RGT-0249510\r\n330421 4822845 SR-0005402\r\n",
- "advanced_run": false,
- "control_lane": 5,
- "cluster_station": 3,
- "sequencer": 2,
- "flowcell_id": "42JU1AAXX"
- }
- },
- {"pk": 1177, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11034",
- "cluster_estimate": 177000,
- "flowcell": 151,
- "lane_number": 1,
- "pM": "7"
- }
- },
- {"pk": 1178, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11036",
- "cluster_estimate": 169000,
- "flowcell": 151,
- "lane_number": 2,
- "pM": "7"
- }
- },
- {
- "pk": "11036",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired ends 96 Kuntz_PDE1",
- "creation_date": "2009-08-25",
- "cell_line": 1,
- "library_species": 3,
- "library_type": 2,
- "made_by": "Brian Williams",
- "affiliations": [
- 5
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "Brian Williams",
- "amplified_from_sample": null,
- "notes": "fragment size = 300 bp",
- "undiluted_concentration": "30.6",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {
- "pk": "11034",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired ends 94 Gilberto_d3_denerv_LTA",
- "creation_date": "2009-08-25",
- "cell_line": 1,
- "library_species": 9,
- "library_type": 2,
- "made_by": "Brian Williams",
- "affiliations": [
- 1
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "Brian Williams",
- "amplified_from_sample": null,
- "notes": "fragment size = 300 bp",
- "undiluted_concentration": "27",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {
- "pk": "12044",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 225,
- "library_name": "Pooled Indexed Test",
- "creation_date": "2009-08-26",
- "cell_line": null,
- "library_species": 9,
- "library_type": 5,
- "multiplex_id": "1,2,3",
- "made_by": "Lorian",
- "affiliations": [
- 2
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "2A",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/21/2009 11:57:54\tColor: Orange",
- "undiluted_concentration": "22.4",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {
- "pk": "13044",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 225,
- "library_name": "Dual Indexed Test",
- "creation_date": "2009-08-26",
- "cell_line": null,
- "library_species": 9,
- "library_type": 9,
- "multiplex_id": "N701-N501",
- "made_by": "Lorian",
- "affiliations": [
- 2
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "2A",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/21/2009 11:57:54\tColor: Orange",
- "undiluted_concentration": "22.4",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {
- "pk": "11045",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 225,
- "library_name": "Simple Indexed Test",
- "creation_date": "2009-08-26",
- "cell_line": null,
- "library_species": 9,
- "library_type": 5,
- "multiplex_id": "1",
- "made_by": "Lorian",
- "affiliations": [
- 2
- ],
- "replicate": 2,
- "condition": null,
- "hidden": false,
- "stopping_point": "2A",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/21/2009 11:57:54\tColor: Orange",
- "undiluted_concentration": "22.4",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {"pk": 1179,
- "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "12044",
- "cluster_estimate": 196000,
- "flowcell": 151,
- "lane_number": 3,
- "pM": "7"
- }
- },
- {"pk": 1279,
- "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11045",
- "cluster_estimate": 196000,
- "flowcell": 151,
- "lane_number": 3,
- "pM": "7"
- }
- },
- {"pk": 1379,
- "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "13044",
- "cluster_estimate": 196000,
- "flowcell": 151,
- "lane_number": 4,
- "pM": "7"
- }
- },
-
- {
- "pk": "11044",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 225,
- "library_name": "p300 60h C2 FA KF 12/22/8 a",
- "creation_date": "2009-08-26",
- "cell_line": null,
- "library_species": 9,
- "library_type": 1,
- "made_by": "Lorian",
- "affiliations": [
- 3
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "2A",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/21/2009 11:57:54\tColor: Orange.",
- "undiluted_concentration": "22.4",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {"pk": 1180, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11047",
- "cluster_estimate": 200000,
- "flowcell": 151,
- "lane_number": 4,
- "pM": "7"
- }
- },
- {
- "pk": "11047",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 250,
- "library_name": "FLDN1 7/8/9 anti-TriMeH3K27 chip B6 a",
- "creation_date": "2009-08-26",
- "cell_line": null,
- "library_species": 9,
- "library_type": 1,
- "made_by": "Lorian",
- "affiliations": [
- 4
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "2A",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/21/2009 11:57:54\tColor: Green",
- "undiluted_concentration": "24.9",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {"pk": 1181, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11055",
- "cluster_estimate": 104000,
- "flowcell": 151,
- "lane_number": 5,
- "pM": "7"
- }
- },
- {
- "pk": "11055",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 225,
- "library_name": "HNDHT 4H8 hnd-1 strain HT115 fed 4H8 2% fix plate a",
- "creation_date": "2009-08-31",
- "cell_line": null,
- "library_species": 3,
- "library_type": 1,
- "made_by": "Lorian",
- "affiliations": [
- 5
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "8/26/2009 14:46:56\tColor: White.",
- "undiluted_concentration": "2.17",
- "successful_pM": null,
- "experiment_type": 2,
- "antibody": null
- }
- },
- {"pk": 1182, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11067",
- "cluster_estimate": 168000,
- "flowcell": 151,
- "lane_number": 6,
- "pM": "7"
- }
- },
- {
- "pk": "11067",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 325,
- "library_name": "Paired End SP-BAC Barcoding test 250-300 bp",
- "creation_date": "2009-09-03",
- "cell_line": 1,
- "library_species": 10,
- "library_type": 2,
- "made_by": "Igor",
- "affiliations": [
- 1
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "Done",
- "tags": [],
- "made_for": "Andy Cameron",
- "amplified_from_sample": null,
- "notes": "12 SP BACs",
- "undiluted_concentration": "1.45",
- "successful_pM": null,
- "experiment_type": 8,
- "antibody": null
- }
- },
- {"pk": 1183, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11069",
- "cluster_estimate": 184000,
- "flowcell": 151,
- "lane_number": 7,
- "pM": "7"
- }
- },
- {
- "pk": "11069",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired End AG-3d-1 AG domain of floral meristem day 3, rep 1",
- "creation_date": "2009-09-02",
- "cell_line": null,
- "library_species": 6,
- "library_type": 2,
- "made_by": "Yuling Jiao",
- "affiliations": [
- 2
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "Done",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "nanodrop: Xng/ul.",
- "undiluted_concentration": "18.3",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 1184, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11070",
- "cluster_estimate": 182000,
- "flowcell": 151,
- "lane_number": 8,
- "pM": "7"
- }
- },
- {
- "pk": "11070",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 300,
- "library_name": "Paired End AG-5d-1 AG domain of floral meristem day 5, rep 1",
- "creation_date": "2009-09-02",
- "cell_line": null,
- "library_species": 6,
- "library_type": 2,
- "made_by": "Yuling Jiao",
- "affiliations": [
- 3
- ],
- "replicate": 1,
- "condition": null,
- "hidden": false,
- "stopping_point": "Done",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": null,
- "notes": "nanodrop: 40ng/ul\r\nCalibrated qbit with standards.\r\nMeasured 2ul library with qbit using HS kit.\r\n",
- "undiluted_concentration": "20.3",
- "successful_pM": null,
- "experiment_type": 4,
- "antibody": null
- }
- },
- {"pk": 200, "model": "experiments.flowcell",
- "fields": {
- "paired_end": true,
- "run_date": "2007-09-27T22:12:13-0800",
- "read_length": 36,
- "notes": "",
- "advanced_run": false,
- "control_lane": 2,
- "cluster_station": 3,
- "sequencer": 2,
- "flowcell_id": "30012AAXX (failed)"
- }
- },
- {"pk": 201, "model": "experiments.lane",
- "fields": {
- "comment": "",
- "library": "11070",
- "cluster_estimate": 182000,
- "flowcell": 200,
- "lane_number": 8,
- "pM": "7"
- }
- }
-]
+++ /dev/null
-[ { "model": "experiments.Sequencer",
- "pk": 1,
- "fields": {
- "name": "Rotifer",
- "instrument_name": "ILLUMINA-33A494",
- "serial_number": "",
- "model": "Illumina Genome Analyzer II",
- "active": false,
- "isdefault": false,
- "comment": "after 2010 pipeline name, was exchanged for hiseq"
- }
- },
- { "model": "experiments.Sequencer",
- "pk": 2,
- "fields": {
- "name": "Tardigrade",
- "instrument_name": "ILLUMINA-EC5D15",
- "serial_number": "",
- "model": "Illumina Genome Analyzer IIx",
- "active": true,
- "isdefault": false,
- "comment": "after 2010 pipeline name"
- }
- },
- { "model": "experiments.Sequencer",
- "pk": 3,
- "fields": {
- "name": "Elsewhere",
- "instrument_name": "",
- "serial_number": "",
- "model": "Unknown",
- "active": false,
- "isdefault": false,
- "comment": "Sequenced somewhere else"
- }
- },
- { "model": "experiments.Sequencer",
- "pk": 4,
- "fields": {
- "name": "Volvox",
- "instrument_name": "HWI-ST0787",
- "serial_number": "",
- "model": "Illumina HiSeq 2000",
- "active": true,
- "isdefault": true,
- "comment": ""
- }
- },
- { "model": "experiments.Sequencer",
- "pk": 5,
- "fields": {
- "name": "Tardigrade (older)",
- "instrument_name": "HWUSI-EAS627",
- "serial_number": "",
- "model": "Illumina Genome Analyzer II",
- "active": false,
- "isdefault": false,
- "comment": "earlier version of tardigrade"
- }
- },
- { "model": "experiments.Sequencer",
- "pk": 6,
- "fields": {
- "name": "Rotifer (older)",
- "instrument_name": "HWUSI-EAS229",
- "serial_number": "",
- "model": "Illumina Genome Analyzer II",
- "active": false,
- "isdefault": false,
- "comment": "earlier rotifer name"
- }
- },
- { "model": "experiments.Sequencer",
- "pk": 7,
- "fields": {
- "name": "First sequencer",
- "instrument_name": "USI-EAS44",
- "serial_number": "",
- "model": "Illumina Genome Analyzer I",
- "active": false,
- "isdefault": false,
- "comment": "our first sequencer"
- }
- },
- { "model": "experiments.ClusterStation",
- "pk": 3,
- "fields": { "name": "new", "isdefault": false }
- }
-]
+++ /dev/null
-import datetime
-import glob
-import logging
-import os
-import re
-import types
-import uuid
-
-from django.conf import settings
-from django.core.exceptions import ObjectDoesNotExist
-from django.core import urlresolvers
-from django.utils import timezone
-from django.db import models
-from django.db.models.signals import post_init, pre_save
-
-from htsworkflow.frontend.samples.models import Library
-from htsworkflow.util.conversion import parse_flowcell_id
-from htsworkflow.pipelines import runfolder
-
-import pytz
-
-LOGGER = logging.getLogger(__name__)
-default_pM = 5
-try:
- default_pM = int(settings.DEFAULT_PM)
-except AttributeError, e:
- LOGGER.error("invalid value for frontend.default_pm")
-
-# how many days to wait before trying to re-import a runfolder
-RESCAN_DELAY = 1
-try:
- RESCAN_DELAY = int(settings.RESCAN_DELAY)
-except (ValueError, AttributeError):
- LOGGER.error("Missing or invalid settings.RESCAN_DELAY, "\
- "defaulting to %s" % (RESCAN_DELAY,))
-
-RUN_STATUS_CHOICES = (
- (0, 'Sequencer running'), # Solexa Data Pipeline Not Yet Started'),
- (1, 'Data Pipeline Started'),
- (2, 'Data Pipeline Interrupted'),
- (3, 'Data Pipeline Finished'),
- (4, 'Collect Results Started'),
- (5, 'Collect Results Finished'),
- (6, 'QC Started'),
- (7, 'QC Finished'),
- (255, 'DONE'),
- )
-RUN_STATUS_REVERSE_MAP = dict(((v, k) for k, v in RUN_STATUS_CHOICES))
-
-
-class ClusterStation(models.Model):
- """List of cluster stations"""
- name = models.CharField(max_length=50, unique=True)
- isdefault = models.BooleanField(default=False, null=False)
-
- class Meta:
- ordering = ["-isdefault", "name"]
-
- def __unicode__(self):
- return unicode(self.name)
-
- @classmethod
- def default(cls):
- d = cls.objects.filter(isdefault=True).all()
- if len(d) > 0:
- return d[0]
- d = cls.objects.order_by('-id').all()
- if len(d) > 0:
- return d[0]
- return None
-
- @staticmethod
- def update_isdefault(sender, instance, **kwargs):
- """Clear default if needed
- """
- if instance.isdefault:
- for c in ClusterStation.objects.filter(isdefault=True).all():
- if c.id != instance.id:
- c.isdefault = False
- c.save()
-
-pre_save.connect(ClusterStation.update_isdefault, sender=ClusterStation)
-
-class Sequencer(models.Model):
- """Sequencers we've owned
- """
- name = models.CharField(max_length=50, db_index=True)
- instrument_name = models.CharField(max_length=50, db_index=True)
- serial_number = models.CharField(max_length=50, db_index=True)
- model = models.CharField(max_length=255)
- active = models.BooleanField(default=True, null=False)
- isdefault = models.BooleanField(default=False, null=False)
- comment = models.CharField(max_length=255)
-
- class Meta:
- ordering = ["-isdefault", "-active", "name"]
-
- def __unicode__(self):
- name = [unicode(self.name)]
- if self.instrument_name is not None:
- name.append("(%s)" % (unicode(self.instrument_name),))
- return " ".join(name)
-
- @models.permalink
- def get_absolute_url(self):
- return ('htsworkflow.frontend.experiments.views.sequencer',
- [self.id])
-
- @classmethod
- def default(cls):
- d = cls.objects.filter(isdefault=True).all()
- if len(d) > 0:
- return d[0]
- d = cls.objects.order_by('active', '-id').all()
- if len(d) > 0:
- return d[0]
- return None
-
- @staticmethod
- def update_isdefault(sender, instance, **kwargs):
- """Clear default if needed
- """
- if instance.isdefault:
- for s in Sequencer.objects.filter(isdefault=True).all():
- if s.id != instance.id:
- s.isdefault = False
- s.save()
-
-pre_save.connect(Sequencer.update_isdefault, sender=Sequencer)
-
-
-class FlowCell(models.Model):
- flowcell_id = models.CharField(max_length=20, unique=True, db_index=True)
- run_date = models.DateTimeField()
- advanced_run = models.BooleanField(default=False)
- paired_end = models.BooleanField(default=False)
- read_length = models.IntegerField(default=32) # Stanford is currenlty 25
- control_lane = models.IntegerField(choices=[(1, 1),
- (2, 2),
- (3, 3),
- (4, 4),
- (5, 5),
- (6, 6),
- (7, 7),
- (8, 8),
- (0, 'All Lanes')],
- null=True,
- blank=True)
-
- cluster_station = models.ForeignKey(ClusterStation, default=ClusterStation.default)
- sequencer = models.ForeignKey(Sequencer, default=Sequencer.default)
-
- notes = models.TextField(blank=True)
-
- def __unicode__(self):
- return unicode(self.flowcell_id)
-
- def Lanes(self):
- html = ['<table>']
- for lane in self.lane_set.order_by('lane_number'):
- cluster_estimate = lane.cluster_estimate
- if cluster_estimate is not None:
- cluster_estimate = "%s k" % ((int(cluster_estimate) / 1000), )
- else:
- cluster_estimate = 'None'
- library_id = lane.library_id
- library = lane.library
- element = '<tr><td>%d</td>'\
- '<td><a href="%s">%s</a></td><td>%s</td></tr>'
- html.append(element % (lane.lane_number,
- library.get_admin_url(),
- library,
- cluster_estimate))
- html.append('</table>')
- return "\n".join(html)
- Lanes.allow_tags = True
-
- class Meta:
- ordering = ["-run_date"]
-
- def get_admin_url(self):
- # that's the django way... except it didn't work
- return urlresolvers.reverse('admin:experiments_flowcell_change',
- args=(self.id,))
-
- def flowcell_type(self):
- """Convert our boolean 'is paired' flag to a name
- """
- if self.paired_end:
- return u"Paired"
- else:
- return u"Single"
-
- @models.permalink
- def get_absolute_url(self):
- flowcell_id, status = parse_flowcell_id(self.flowcell_id)
- return ('htsworkflow.frontend.experiments.views.flowcell_detail',
- [str(flowcell_id)])
-
- def get_raw_data_directory(self):
- """Return location of where the raw data is stored"""
- flowcell_id, status = parse_flowcell_id(self.flowcell_id)
-
- return os.path.join(settings.RESULT_HOME_DIR, flowcell_id)
-
- def update_data_runs(self):
- result_root = self.get_raw_data_directory()
- LOGGER.debug("Update data runs flowcell root: %s" % (result_root,))
- if result_root is None:
- return
-
- result_home_dir = os.path.join(settings.RESULT_HOME_DIR, '')
- run_xml_re = re.compile(glob.fnmatch.translate('run*.xml'))
-
- result_dirs = []
- for dirpath, dirnames, filenames in os.walk(result_root):
- for filename in filenames:
- if run_xml_re.match(filename):
- # we have a run directory
- relative_pathname = get_relative_pathname(dirpath)
- self.import_data_run(relative_pathname, filename)
-
- def import_data_run(self, relative_pathname, run_xml_name, force=False):
- """Given a result directory import files"""
- now = timezone.now()
- run_dir = get_absolute_pathname(relative_pathname)
- run_xml_path = os.path.join(run_dir, run_xml_name)
-
- runs = DataRun.objects.filter(result_dir = relative_pathname)
- if len(runs) == 0:
- run = DataRun()
- created = True
- elif len(runs) > 1:
- raise RuntimeError("Too many data runs for %s" % (
- relative_pathname,))
- else:
- run = runs[0]
- created = False
-
- if created or force or (now-run.last_update_time).days > RESCAN_DELAY:
- LOGGER.debug("Importing run from %s" % (relative_pathname,))
- run_xml_data = runfolder.load_pipeline_run_xml(run_xml_path)
- run.flowcell = self
- run.status = RUN_STATUS_REVERSE_MAP['DONE']
- run.result_dir = relative_pathname
- run.runfolder_name = run_xml_data.runfolder_name
- run.cycle_start = run_xml_data.image_analysis.start
- run.cycle_stop = run_xml_data.image_analysis.stop
- naive_run_start_time = datetime.datetime.fromordinal(run_xml_data.image_analysis.date.toordinal())
- run.run_start_time = pytz.timezone(settings.TIME_ZONE).localize(naive_run_start_time)
- run.image_software = run_xml_data.image_analysis.software
- run.image_version = run_xml_data.image_analysis.version
- run.basecall_software = run_xml_data.bustard.software
- run.basecall_version = run_xml_data.bustard.version
- # we're frequently not running alignments
- if run_xml_data.gerald:
- run.alignment_software = run_xml_data.gerald.software
- run.alignment_version = run_xml_data.gerald.version
-
- run.last_update_time = timezone.now()
- run.save()
-
- run.update_result_files()
-
-
-# FIXME: should we automatically update dataruns?
-# Or should we expect someone to call update_data_runs?
-#def update_flowcell_dataruns(sender, instance, *args, **kwargs):
-# """Update our dataruns
-# """
-# if not os.path.exists(settings.RESULT_HOME_DIR):
-# return
-#
-# instance.update_data_runs()
-#post_init.connect(update_flowcell_dataruns, sender=FlowCell)
-
-
-LANE_STATUS_CODES = [(0, 'Failed'),
- (1, 'Marginal'),
- (2, 'Good'), ]
-LANE_STATUS_MAP = dict((int(k), v) for k, v in LANE_STATUS_CODES)
-LANE_STATUS_MAP[None] = "Unknown"
-
-
-def is_valid_lane(value):
- if value >= 1 and value <= 8:
- return True
- else:
- return False
-
-
-class Lane(models.Model):
- flowcell = models.ForeignKey(FlowCell)
- lane_number = models.IntegerField()
- library = models.ForeignKey(Library)
- pM = models.DecimalField(max_digits=5,
- decimal_places=2,
- blank=False,
- null=False,
- default=default_pM)
- cluster_estimate = models.IntegerField(blank=True, null=True)
- status = models.IntegerField(choices=LANE_STATUS_CODES,
- null=True,
- blank=True)
- comment = models.TextField(null=True, blank=True)
-
- @models.permalink
- def get_absolute_url(self):
- return ('htsworkflow.frontend.experiments.views.flowcell_lane_detail',
- [str(self.id)])
-
- def __unicode__(self):
- return self.flowcell.flowcell_id + ':' + unicode(self.lane_number)
-
-
-class DataRun(models.Model):
- flowcell = models.ForeignKey(FlowCell, verbose_name="Flowcell Id")
- runfolder_name = models.CharField(max_length=50)
- result_dir = models.CharField(max_length=255)
- last_update_time = models.DateTimeField()
- run_start_time = models.DateTimeField()
- cycle_start = models.IntegerField(null=True, blank=True)
- cycle_stop = models.IntegerField(null=True, blank=True)
- run_status = models.IntegerField(choices=RUN_STATUS_CHOICES,
- null=True, blank=True)
- image_software = models.CharField(max_length=50)
- image_version = models.CharField(max_length=50)
- basecall_software = models.CharField(max_length=50)
- basecall_version = models.CharField(max_length=50)
- alignment_software = models.CharField(max_length=50)
- alignment_version = models.CharField(max_length=50)
- comment = models.TextField(blank=True)
-
- def update_result_files(self):
- abs_result_dir = get_absolute_pathname(self.result_dir)
-
- for dirname, dirnames, filenames in os.walk(abs_result_dir):
- for filename in filenames:
- pathname = os.path.join(dirname, filename)
- relative_pathname = get_relative_pathname(pathname)
- datafiles = self.datafile_set.filter(
- data_run=self,
- relative_pathname=relative_pathname)
- if len(datafiles) > 0:
- continue
-
- metadata = find_file_type_metadata_from_filename(filename)
- if metadata is not None:
- metadata['filename'] = filename
- newfile = DataFile()
- newfile.data_run = self
- newfile.file_type = metadata['file_type']
- newfile.relative_pathname = relative_pathname
-
- lane_number = metadata.get('lane', None)
- if lane_number is not None:
- lane = self.flowcell.lane_set.get(
- lane_number=lane_number)
- newfile.library = lane.library
-
- self.datafile_set.add(newfile)
-
- self.last_update_time = timezone.now()
-
- def lane_files(self):
- lanes = {}
-
- for datafile in self.datafile_set.all():
- metadata = datafile.attributes
- if metadata is not None:
- lane = metadata.get('lane', None)
- if lane is not None:
- lane_file_set = lanes.setdefault(lane, {})
- normalized_name = datafile.file_type.normalized_name
- lane_file_set[normalized_name] = datafile
- return lanes
-
- def ivc_plots(self, lane):
- ivc_name = ['IVC All', 'IVC Call',
- 'IVC Percent Base', 'IVC Percent All', 'IVC Percent Call']
-
- plots = {}
- for rel_filename, metadata in self.get_result_files():
- if metadata.file_type.name in ivc_name:
- plots[metadata.file_type.name] = (rel_filename, metadata)
-
-
-class FileType(models.Model):
- """Represent potential file types
-
- regex is a pattern used to detect if a filename matches this type
- data run currently assumes that there may be a (?P<lane>) and
- (?P<end>) pattern in the regular expression.
- """
- name = models.CharField(max_length=50)
- mimetype = models.CharField(max_length=50, null=True, blank=True)
- # regular expression from glob.fnmatch.translate
- regex = models.TextField(null=True, blank=True)
-
- def parse_filename(self, pathname):
- """Does filename match our pattern?
-
- Returns None if not, or dictionary of match variables if we do.
- """
- path, filename = os.path.split(pathname)
- if len(self.regex) > 0:
- match = re.match(self.regex, filename)
- if match is not None:
- # These are (?P<>) names we know about from our
- # default regexes.
- results = match.groupdict()
-
- # convert int parameters
- for attribute_name in ['lane', 'end']:
- value = results.get(attribute_name, None)
- if value is not None:
- results[attribute_name] = int(value)
-
- return results
-
- def _get_normalized_name(self):
- """Crush data file name into identifier friendly name"""
- return self.name.replace(' ', '_').lower()
- normalized_name = property(_get_normalized_name)
-
- def __unicode__(self):
- #return u"<FileType: %s>" % (self.name,)
- return self.name
-
-
-def str_uuid():
- """Helper function to set default UUID in DataFile"""
- return str(uuid.uuid1())
-
-
-class DataFile(models.Model):
- """Store map from random ID to filename"""
- random_key = models.CharField(max_length=64,
- db_index=True,
- default=str_uuid)
- data_run = models.ForeignKey(DataRun, db_index=True)
- library = models.ForeignKey(Library, db_index=True, null=True, blank=True)
- file_type = models.ForeignKey(FileType)
- relative_pathname = models.CharField(max_length=255, db_index=True)
-
- def _get_attributes(self):
- return self.file_type.parse_filename(self.relative_pathname)
- attributes = property(_get_attributes)
-
- def _get_pathname(self):
- return get_absolute_pathname(self.relative_pathname)
- pathname = property(_get_pathname)
-
- @models.permalink
- def get_absolute_url(self):
- return ('htsworkflow.frontend.experiments.views.read_result_file',
- (), {'key': self.random_key})
-
-
-def find_file_type_metadata_from_filename(pathname):
- path, filename = os.path.split(pathname)
- result = None
- for file_type in FileType.objects.all():
- result = file_type.parse_filename(filename)
- if result is not None:
- result['file_type'] = file_type
- return result
-
- return None
-
-
-def get_relative_pathname(abspath):
- """Strip off the result home directory from a path
- """
- result_home_dir = os.path.join(settings.RESULT_HOME_DIR, '')
- relative_pathname = abspath.replace(result_home_dir, '')
- return relative_pathname
-
-
-def get_absolute_pathname(relative_pathname):
- """Attach relative path to results home directory"""
- return os.path.join(settings.RESULT_HOME_DIR, relative_pathname)
+++ /dev/null
-import re
-from lxml.html import fromstring
-try:
- import json
-except ImportError, e:
- import simplejson as json
-import os
-import shutil
-import sys
-import tempfile
-from urlparse import urljoin
-
-from django.conf import settings
-from django.core import mail
-from django.core.exceptions import ObjectDoesNotExist
-from django.test import TestCase
-from django.test.utils import setup_test_environment, teardown_test_environment
-from django.db import connection
-from django.conf import settings
-from htsworkflow.frontend.experiments import models
-from htsworkflow.frontend.experiments import experiments
-from htsworkflow.frontend.auth import apidata
-from htsworkflow.util.ethelp import validate_xhtml
-
-from htsworkflow.pipelines.test.simulate_runfolder import TESTDATA_DIR
-
-LANE_SET = range(1,9)
-
-NSMAP = {'libns':'http://jumpgate.caltech.edu/wiki/LibraryOntology#'}
-
-from django.db import connection
-
-class ClusterStationTestCases(TestCase):
- fixtures = ['initial_data.json',
- 'test_flowcells.json']
-
- def test_default(self):
- c = models.ClusterStation.default()
- self.assertEqual(c.id, 2)
-
- c.isdefault = False
- c.save()
-
- total = models.ClusterStation.objects.filter(isdefault=True).count()
- self.assertEqual(total, 0)
-
- other_default = models.ClusterStation.default()
- self.assertEqual(other_default.id, 3)
-
-
- def test_update_default(self):
- old_default = models.ClusterStation.default()
-
- c = models.ClusterStation.objects.get(pk=3)
- c.isdefault = True
- c.save()
-
- new_default = models.ClusterStation.default()
-
- self.assertNotEqual(old_default, new_default)
- self.assertEqual(new_default, c)
-
- total = models.ClusterStation.objects.filter(isdefault=True).count()
- self.assertEqual(total, 1)
-
- def test_update_other(self):
- old_default = models.ClusterStation.default()
- total = models.ClusterStation.objects.filter(isdefault=True).count()
- self.assertEqual(total, 1)
-
- c = models.ClusterStation.objects.get(pk=1)
- c.name = "Primary Key 1"
- c.save()
-
- total = models.ClusterStation.objects.filter(isdefault=True).count()
- self.assertEqual(total, 1)
-
- new_default = models.ClusterStation.default()
- self.assertEqual(old_default, new_default)
-
-
-class SequencerTestCases(TestCase):
- fixtures = ['initial_data.json',
- 'woldlab.json',
- 'test_flowcells.json']
-
- def test_default(self):
- # starting with no default
- s = models.Sequencer.default()
- self.assertEqual(s.id, 2)
-
- total = models.Sequencer.objects.filter(isdefault=True).count()
- self.assertEqual(total, 1)
-
- s.isdefault = False
- s.save()
-
- total = models.Sequencer.objects.filter(isdefault=True).count()
- self.assertEqual(total, 0)
-
- other_default = models.Sequencer.default()
- self.assertEqual(other_default.id, 7)
-
- def test_update_default(self):
- old_default = models.Sequencer.default()
-
- s = models.Sequencer.objects.get(pk=1)
- s.isdefault = True
- s.save()
-
- new_default = models.Sequencer.default()
-
- self.assertNotEqual(old_default, new_default)
- self.assertEqual(new_default, s)
-
- total = models.Sequencer.objects.filter(isdefault=True).count()
- self.assertEqual(total, 1)
-
-
- def test_update_other(self):
- old_default = models.Sequencer.default()
- total = models.Sequencer.objects.filter(isdefault=True).count()
- self.assertEqual(total, 1)
-
- s = models.Sequencer.objects.get(pk=1)
- s.name = "Primary Key 1"
- s.save()
-
- total = models.Sequencer.objects.filter(isdefault=True).count()
- self.assertEqual(total, 1)
-
- new_default = models.Sequencer.default()
- self.assertEqual(old_default, new_default)
-
-
-class ExperimentsTestCases(TestCase):
- fixtures = ['initial_data.json',
- 'test_flowcells.json',
- ]
-
- def setUp(self):
- self.tempdir = tempfile.mkdtemp(prefix='htsw-test-experiments-')
- settings.RESULT_HOME_DIR = self.tempdir
-
- self.fc1_id = 'FC12150'
- self.fc1_root = os.path.join(self.tempdir, self.fc1_id)
- os.mkdir(self.fc1_root)
- self.fc1_dir = os.path.join(self.fc1_root, 'C1-37')
- os.mkdir(self.fc1_dir)
- runxml = 'run_FC12150_2007-09-27.xml'
- shutil.copy(os.path.join(TESTDATA_DIR, runxml),
- os.path.join(self.fc1_dir, runxml))
- for i in range(1,9):
- shutil.copy(
- os.path.join(TESTDATA_DIR,
- 'woldlab_070829_USI-EAS44_0017_FC11055_1.srf'),
- os.path.join(self.fc1_dir,
- 'woldlab_070829_SERIAL_FC12150_%d.srf' %(i,))
- )
-
- self.fc2_dir = os.path.join(self.tempdir, '42JTNAAXX')
- os.mkdir(self.fc2_dir)
- os.mkdir(os.path.join(self.fc2_dir, 'C1-25'))
- os.mkdir(os.path.join(self.fc2_dir, 'C1-37'))
- os.mkdir(os.path.join(self.fc2_dir, 'C1-37', 'Plots'))
-
- def tearDown(self):
- shutil.rmtree(self.tempdir)
-
- def test_flowcell_information(self):
- """
- Check the code that packs the django objects into simple types.
- """
- for fc_id in [u'FC12150', u"42JTNAAXX", "42JU1AAXX"]:
- fc_dict = experiments.flowcell_information(fc_id)
- fc_django = models.FlowCell.objects.get(flowcell_id=fc_id)
- self.assertEqual(fc_dict['flowcell_id'], fc_id)
- self.assertEqual(fc_django.flowcell_id, fc_id)
- self.assertEqual(fc_dict['sequencer'], fc_django.sequencer.name)
- self.assertEqual(fc_dict['read_length'], fc_django.read_length)
- self.assertEqual(fc_dict['notes'], fc_django.notes)
- self.assertEqual(fc_dict['cluster_station'], fc_django.cluster_station.name)
-
- for lane in fc_django.lane_set.all():
- lane_contents = fc_dict['lane_set'][lane.lane_number]
- lane_dict = multi_lane_to_dict(lane_contents)[lane.library_id]
- self.assertEqual(lane_dict['cluster_estimate'], lane.cluster_estimate)
- self.assertEqual(lane_dict['comment'], lane.comment)
- self.assertEqual(lane_dict['flowcell'], lane.flowcell.flowcell_id)
- self.assertEqual(lane_dict['lane_number'], lane.lane_number)
- self.assertEqual(lane_dict['library_name'], lane.library.library_name)
- self.assertEqual(lane_dict['library_id'], lane.library.id)
- self.assertAlmostEqual(float(lane_dict['pM']), float(lane.pM))
- self.assertEqual(lane_dict['library_species'],
- lane.library.library_species.scientific_name)
-
- response = self.client.get('/experiments/config/%s/json' % (fc_id,), apidata)
- # strptime isoformat string = '%Y-%m-%dT%H:%M:%S'
- fc_json = json.loads(response.content)
- self.assertEqual(fc_json['flowcell_id'], fc_id)
- self.assertEqual(fc_json['sequencer'], fc_django.sequencer.name)
- self.assertEqual(fc_json['read_length'], fc_django.read_length)
- self.assertEqual(fc_json['notes'], fc_django.notes)
- self.assertEqual(fc_json['cluster_station'], fc_django.cluster_station.name)
-
-
- for lane in fc_django.lane_set.all():
- lane_contents = fc_json['lane_set'][unicode(lane.lane_number)]
- lane_dict = multi_lane_to_dict(lane_contents)[lane.library_id]
-
- self.assertEqual(lane_dict['cluster_estimate'], lane.cluster_estimate)
- self.assertEqual(lane_dict['comment'], lane.comment)
- self.assertEqual(lane_dict['flowcell'], lane.flowcell.flowcell_id)
- self.assertEqual(lane_dict['lane_number'], lane.lane_number)
- self.assertEqual(lane_dict['library_name'], lane.library.library_name)
- self.assertEqual(lane_dict['library_id'], lane.library.id)
- self.assertAlmostEqual(float(lane_dict['pM']), float(lane.pM))
- self.assertEqual(lane_dict['library_species'],
- lane.library.library_species.scientific_name)
-
- def test_invalid_flowcell(self):
- """
- Make sure we get a 404 if we request an invalid flowcell ID
- """
- response = self.client.get('/experiments/config/nottheone/json', apidata)
- self.assertEqual(response.status_code, 404)
-
- def test_no_key(self):
- """
- Require logging in to retrieve meta data
- """
- response = self.client.get(u'/experiments/config/FC12150/json')
- self.assertEqual(response.status_code, 403)
-
- def test_library_id(self):
- """
- Library IDs should be flexible, so make sure we can retrive a non-numeric ID
- """
- response = self.client.get('/experiments/config/FC12150/json', apidata)
- self.assertEqual(response.status_code, 200)
- flowcell = json.loads(response.content)
-
- lane_contents = flowcell['lane_set']['3']
- lane_library = lane_contents[0]
- self.assertEqual(lane_library['library_id'], 'SL039')
-
- response = self.client.get('/samples/library/SL039/json', apidata)
- self.assertEqual(response.status_code, 200)
- library_sl039 = json.loads(response.content)
-
- self.assertEqual(library_sl039['library_id'], 'SL039')
-
- def test_raw_id_field(self):
- """
- Test ticket:147
-
- Library's have IDs, libraries also have primary keys,
- we eventually had enough libraries that the drop down combo box was too
- hard to filter through, unfortnately we want a field that uses our library
- id and not the internal primary key, and raw_id_field uses primary keys.
-
- This tests to make sure that the value entered in the raw library id field matches
- the library id looked up.
- """
- expected_ids = [u'10981',u'11016',u'SL039',u'11060',
- u'11061',u'11062',u'11063',u'11064']
- self.client.login(username='supertest', password='BJOKL5kAj6aFZ6A5')
- response = self.client.get('/admin/experiments/flowcell/153/')
-
- tree = fromstring(response.content)
- for i in range(0,8):
- xpath_expression = '//input[@id="id_lane_set-%d-library"]'
- input_field = tree.xpath(xpath_expression % (i,))[0]
- library_field = input_field.find('../strong')
- library_id, library_name = library_field.text.split(':')
- # strip leading '#' sign from name
- library_id = library_id[1:]
- self.assertEqual(library_id, expected_ids[i])
- self.assertEqual(input_field.attrib['value'], library_id)
-
- def test_library_to_flowcell_link(self):
- """
- Make sure the library page includes links to the flowcell pages.
- That work with flowcell IDs that have parenthetical comments.
- """
- self.client.login(username='supertest', password='BJOKL5kAj6aFZ6A5')
- response = self.client.get('/library/11070/')
- self.assertEqual(response.status_code, 200)
- status = validate_xhtml(response.content)
- if status is not None: self.assertTrue(status)
-
- tree = fromstring(response.content)
- flowcell_spans = tree.xpath('//span[@property="libns:flowcell_id"]',
- namespaces=NSMAP)
- self.assertEqual(flowcell_spans[1].text, '30012AAXX (failed)')
- failed_fc_span = flowcell_spans[1]
- failed_fc_a = failed_fc_span.getparent()
- # make sure some of our RDF made it.
- self.assertEqual(failed_fc_a.get('typeof'), 'libns:IlluminaFlowcell')
- self.assertEqual(failed_fc_a.get('href'), '/flowcell/30012AAXX/')
- fc_response = self.client.get(failed_fc_a.get('href'))
- self.assertEqual(fc_response.status_code, 200)
- status = validate_xhtml(response.content)
- if status is not None: self.assertTrue(status)
-
- fc_lane_response = self.client.get('/flowcell/30012AAXX/8/')
- self.assertEqual(fc_lane_response.status_code, 200)
- status = validate_xhtml(response.content)
- if status is not None: self.assertTrue(status)
-
-
- def test_pooled_multiplex_id(self):
- fc_dict = experiments.flowcell_information('42JU1AAXX')
- lane_contents = fc_dict['lane_set'][3]
- self.assertEqual(len(lane_contents), 2)
- lane_dict = multi_lane_to_dict(lane_contents)
-
- self.assertEqual(lane_dict['12044']['index_sequence'],
- {u'1': u'ATCACG',
- u'2': u'CGATGT',
- u'3': u'TTAGGC'})
- self.assertEqual(lane_dict['11045']['index_sequence'],
- {u'1': u'ATCACG'})
-
-
-
- def test_lanes_for(self):
- """
- Check the code that packs the django objects into simple types.
- """
- user = 'test'
- lanes = experiments.lanes_for(user)
- self.assertEqual(len(lanes), 5)
-
- response = self.client.get('/experiments/lanes_for/%s/json' % (user,), apidata)
- lanes_json = json.loads(response.content)
- self.assertEqual(len(lanes), len(lanes_json))
- for i in range(len(lanes)):
- self.assertEqual(lanes[i]['comment'], lanes_json[i]['comment'])
- self.assertEqual(lanes[i]['lane_number'], lanes_json[i]['lane_number'])
- self.assertEqual(lanes[i]['flowcell'], lanes_json[i]['flowcell'])
- self.assertEqual(lanes[i]['run_date'], lanes_json[i]['run_date'])
-
- def test_lanes_for_no_lanes(self):
- """
- Do we get something meaningful back when the user isn't attached to anything?
- """
- user = 'supertest'
- lanes = experiments.lanes_for(user)
- self.assertEqual(len(lanes), 0)
-
- response = self.client.get('/experiments/lanes_for/%s/json' % (user,), apidata)
- lanes_json = json.loads(response.content)
-
- def test_lanes_for_no_user(self):
- """
- Do we get something meaningful back when its the wrong user
- """
- user = 'not a real user'
- self.assertRaises(ObjectDoesNotExist, experiments.lanes_for, user)
-
- response = self.client.get('/experiments/lanes_for/%s/json' % (user,), apidata)
- self.assertEqual(response.status_code, 404)
-
-
- def test_raw_data_dir(self):
- """Raw data path generator check"""
- flowcell_id = self.fc1_id
- raw_dir = os.path.join(settings.RESULT_HOME_DIR, flowcell_id)
-
- fc = models.FlowCell.objects.get(flowcell_id=flowcell_id)
- self.assertEqual(fc.get_raw_data_directory(), raw_dir)
-
- fc.flowcell_id = flowcell_id + " (failed)"
- self.assertEqual(fc.get_raw_data_directory(), raw_dir)
-
-
- def test_data_run_import(self):
- srf_file_type = models.FileType.objects.get(name='SRF')
- runxml_file_type = models.FileType.objects.get(name='run_xml')
- flowcell_id = self.fc1_id
- flowcell = models.FlowCell.objects.get(flowcell_id=flowcell_id)
- flowcell.update_data_runs()
- self.assertEqual(len(flowcell.datarun_set.all()), 1)
-
- run = flowcell.datarun_set.all()[0]
- result_files = run.datafile_set.all()
- result_dict = dict(((rf.relative_pathname, rf) for rf in result_files))
-
- srf4 = result_dict['FC12150/C1-37/woldlab_070829_SERIAL_FC12150_4.srf']
- self.assertEqual(srf4.file_type, srf_file_type)
- self.assertEqual(srf4.library_id, '11060')
- self.assertEqual(srf4.data_run.flowcell.flowcell_id, 'FC12150')
- self.assertEqual(
- srf4.data_run.flowcell.lane_set.get(lane_number=4).library_id,
- '11060')
- self.assertEqual(
- srf4.pathname,
- os.path.join(settings.RESULT_HOME_DIR, srf4.relative_pathname))
-
- lane_files = run.lane_files()
- self.assertEqual(lane_files[4]['srf'], srf4)
-
- runxml= result_dict['FC12150/C1-37/run_FC12150_2007-09-27.xml']
- self.assertEqual(runxml.file_type, runxml_file_type)
- self.assertEqual(runxml.library_id, None)
-
- import1 = len(models.DataRun.objects.filter(result_dir='FC12150/C1-37'))
- # what happens if we import twice?
- flowcell.import_data_run('FC12150/C1-37',
- 'run_FC12150_2007-09-27.xml')
- self.assertEqual(
- len(models.DataRun.objects.filter(result_dir='FC12150/C1-37')),
- import1)
-
- def test_read_result_file(self):
- """make sure we can return a result file
- """
- flowcell_id = self.fc1_id
- flowcell = models.FlowCell.objects.get(flowcell_id=flowcell_id)
- flowcell.update_data_runs()
-
- #self.client.login(username='supertest', password='BJOKL5kAj6aFZ6A5')
-
- result_files = flowcell.datarun_set.all()[0].datafile_set.all()
- for f in result_files:
- url = '/experiments/file/%s' % ( f.random_key,)
- response = self.client.get(url)
- self.assertEqual(response.status_code, 200)
- mimetype = f.file_type.mimetype
- if mimetype is None:
- mimetype = 'application/octet-stream'
-
- self.assertEqual(mimetype, response['content-type'])
-
- def test_flowcell_rdf(self):
- import RDF
- from htsworkflow.util.rdfhelp import get_model, \
- fromTypedNode, \
- load_string_into_model, \
- rdfNS, \
- libraryOntology, \
- dump_model
-
- model = get_model()
-
- expected = {'1': ['11034'],
- '2': ['11036'],
- '3': ['12044','11045'],
- '4': ['11047','13044'],
- '5': ['11055'],
- '6': ['11067'],
- '7': ['11069'],
- '8': ['11070']}
- url = '/flowcell/42JU1AAXX/'
- response = self.client.get(url)
- self.assertEqual(response.status_code, 200)
- status = validate_xhtml(response.content)
- if status is not None: self.assertTrue(status)
-
- ns = urljoin('http://localhost', url)
- load_string_into_model(model, 'rdfa', response.content, ns=ns)
- body = """prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
- prefix libns: <http://jumpgate.caltech.edu/wiki/LibraryOntology#>
-
- select ?flowcell ?flowcell_id ?lane_id ?library_id
- where {
- ?flowcell a libns:IlluminaFlowcell ;
- libns:flowcell_id ?flowcell_id ;
- libns:has_lane ?lane .
- ?lane libns:lane_number ?lane_id ;
- libns:library ?library .
- ?library libns:library_id ?library_id .
- }"""
- query = RDF.SPARQLQuery(body)
- count = 0
- for r in query.execute(model):
- count += 1
- self.assertEqual(fromTypedNode(r['flowcell_id']), u'42JU1AAXX')
- lane_id = fromTypedNode(r['lane_id'])
- library_id = fromTypedNode(r['library_id'])
- self.assertTrue(library_id in expected[lane_id])
- self.assertEqual(count, 10)
-
-
-class TestFileType(TestCase):
- fixtures = ['initial_data.json',
- 'test_flowcells.json',
- ]
-
- def test_file_type_unicode(self):
- file_type_objects = models.FileType.objects
- name = 'QSEQ tarfile'
- file_type_object = file_type_objects.get(name=name)
- self.assertEqual(u"QSEQ tarfile",
- unicode(file_type_object))
-
- def test_find_file_type(self):
- file_type_objects = models.FileType.objects
- cases = [('woldlab_090921_HWUSI-EAS627_0009_42FC3AAXX_l7_r1.tar.bz2',
- 'QSEQ tarfile', 7, 1),
- ('woldlab_091005_HWUSI-EAS627_0010_42JT2AAXX_1.srf',
- 'SRF', 1, None),
- ('s_1_eland_extended.txt.bz2','ELAND Extended', 1, None),
- ('s_7_eland_multi.txt.bz2', 'ELAND Multi', 7, None),
- ('s_3_eland_result.txt.bz2','ELAND Result', 3, None),
- ('s_1_export.txt.bz2','ELAND Export', 1, None),
- ('s_1_percent_call.png', 'IVC Percent Call', 1, None),
- ('s_2_percent_base.png', 'IVC Percent Base', 2, None),
- ('s_3_percent_all.png', 'IVC Percent All', 3, None),
- ('s_4_call.png', 'IVC Call', 4, None),
- ('s_5_all.png', 'IVC All', 5, None),
- ('Summary.htm', 'Summary.htm', None, None),
- ('run_42JT2AAXX_2009-10-07.xml', 'run_xml', None, None),
- ]
- for filename, typename, lane, end in cases:
- ft = models.find_file_type_metadata_from_filename(filename)
- self.assertEqual(ft['file_type'],
- file_type_objects.get(name=typename))
- self.assertEqual(ft.get('lane', None), lane)
- self.assertEqual(ft.get('end', None), end)
-
- def test_assign_file_type_complex_path(self):
- file_type_objects = models.FileType.objects
- cases = [('/a/b/c/woldlab_090921_HWUSI-EAS627_0009_42FC3AAXX_l7_r1.tar.bz2',
- 'QSEQ tarfile', 7, 1),
- ('foo/woldlab_091005_HWUSI-EAS627_0010_42JT2AAXX_1.srf',
- 'SRF', 1, None),
- ('../s_1_eland_extended.txt.bz2','ELAND Extended', 1, None),
- ('/bleem/s_7_eland_multi.txt.bz2', 'ELAND Multi', 7, None),
- ('/qwer/s_3_eland_result.txt.bz2','ELAND Result', 3, None),
- ('/ty///1/s_1_export.txt.bz2','ELAND Export', 1, None),
- ('/help/s_1_percent_call.png', 'IVC Percent Call', 1, None),
- ('/bored/s_2_percent_base.png', 'IVC Percent Base', 2, None),
- ('/example1/s_3_percent_all.png', 'IVC Percent All', 3, None),
- ('amonkey/s_4_call.png', 'IVC Call', 4, None),
- ('fishie/s_5_all.png', 'IVC All', 5, None),
- ('/random/Summary.htm', 'Summary.htm', None, None),
- ('/notrandom/run_42JT2AAXX_2009-10-07.xml', 'run_xml', None, None),
- ]
- for filename, typename, lane, end in cases:
- result = models.find_file_type_metadata_from_filename(filename)
- self.assertEqual(result['file_type'],
- file_type_objects.get(name=typename))
- self.assertEqual(result.get('lane',None), lane)
- self.assertEqual(result.get('end', None), end)
-
-class TestEmailNotify(TestCase):
- fixtures = ['initial_data.json',
- 'test_flowcells.json']
-
- def test_started_email_not_logged_in(self):
- response = self.client.get('/experiments/started/153/')
- self.assertEqual(response.status_code, 302)
-
- def test_started_email_logged_in_user(self):
- self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
- response = self.client.get('/experiments/started/153/')
- self.assertEqual(response.status_code, 302)
-
- def test_started_email_logged_in_staff(self):
- self.client.login(username='admintest', password='BJOKL5kAj6aFZ6A5')
- response = self.client.get('/experiments/started/153/')
- self.assertEqual(response.status_code, 200)
-
- def test_started_email_send(self):
- self.client.login(username='admintest', password='BJOKL5kAj6aFZ6A5')
- response = self.client.get('/experiments/started/153/')
- self.assertEqual(response.status_code, 200)
-
- self.assertTrue('pk1@example.com' in response.content)
- self.assertTrue('Lane #8 : (11064) Paired ends 104' in response.content)
-
- response = self.client.get('/experiments/started/153/', {'send':'1','bcc':'on'})
- self.assertEqual(response.status_code, 200)
- self.assertEqual(len(mail.outbox), 4)
- bcc = set(settings.NOTIFICATION_BCC).copy()
- bcc.update(set(settings.MANAGERS))
- for m in mail.outbox:
- self.assertTrue(len(m.body) > 0)
- self.assertEqual(set(m.bcc), bcc)
-
- def test_email_navigation(self):
- """
- Can we navigate between the flowcell and email forms properly?
- """
- self.client.login(username='supertest', password='BJOKL5kAj6aFZ6A5')
- response = self.client.get('/experiments/started/153/')
- self.assertEqual(response.status_code, 200)
- self.assertTrue(re.search('Flowcell FC12150', response.content))
- # require that navigation back to the admin page exists
- self.assertTrue(re.search('<a href="/admin/experiments/flowcell/153/">[^<]+</a>', response.content))
-
-def multi_lane_to_dict(lane):
- """Convert a list of lane entries into a dictionary indexed by library ID
- """
- return dict( ((x['library_id'],x) for x in lane) )
-
-class TestSequencer(TestCase):
- fixtures = ['initial_data.json',
- 'test_flowcells.json',
- ]
-
- def test_name_generation(self):
- seq = models.Sequencer()
- seq.name = "Seq1"
- seq.instrument_name = "HWI-SEQ1"
- seq.model = "Imaginary 5000"
-
- self.assertEqual(unicode(seq), "Seq1 (HWI-SEQ1)")
-
- def test_lookup(self):
- fc = models.FlowCell.objects.get(pk=153)
- self.assertEqual(fc.sequencer.model,
- "Illumina Genome Analyzer IIx")
- self.assertEqual(fc.sequencer.instrument_name,
- "ILLUMINA-EC5D15")
- # well actually we let the browser tack on the host name
- url = fc.get_absolute_url()
- self.assertEqual(url, '/flowcell/FC12150/')
-
- def test_rdf(self):
- response = self.client.get('/flowcell/FC12150/', apidata)
- tree = fromstring(response.content)
- seq_by = tree.xpath('//div[@rel="libns:sequenced_by"]',
- namespaces=NSMAP)
- self.assertEqual(len(seq_by), 1)
- self.assertEqual(seq_by[0].attrib['rel'], 'libns:sequenced_by')
- seq = seq_by[0].getchildren()
- self.assertEqual(len(seq), 1)
- self.assertEqual(seq[0].attrib['about'], '/sequencer/2')
- self.assertEqual(seq[0].attrib['typeof'], 'libns:Sequencer')
-
- name = seq[0].xpath('./span[@property="libns:sequencer_name"]')
- self.assertEqual(len(name), 1)
- self.assertEqual(name[0].text, 'Tardigrade')
- instrument = seq[0].xpath(
- './span[@property="libns:sequencer_instrument"]')
- self.assertEqual(len(instrument), 1)
- self.assertEqual(instrument[0].text, 'ILLUMINA-EC5D15')
- model = seq[0].xpath(
- './span[@property="libns:sequencer_model"]')
- self.assertEqual(len(model), 1)
- self.assertEqual(model[0].text, 'Illumina Genome Analyzer IIx')
-
- def test_flowcell_with_rdf_validation(self):
- from htsworkflow.util.rdfhelp import add_default_schemas, \
- dump_model, \
- get_model, \
- load_string_into_model
- from htsworkflow.util.rdfinfer import Infer
-
- model = get_model()
- add_default_schemas(model)
- inference = Infer(model)
-
- url ='/flowcell/FC12150/'
- response = self.client.get(url)
- self.assertEqual(response.status_code, 200)
- status = validate_xhtml(response.content)
- if status is not None: self.assertTrue(status)
-
- load_string_into_model(model, 'rdfa', response.content)
-
- errmsgs = list(inference.run_validation())
- self.assertEqual(len(errmsgs), 0)
-
- def test_lane_with_rdf_validation(self):
- from htsworkflow.util.rdfhelp import add_default_schemas, \
- dump_model, \
- get_model, \
- load_string_into_model
- from htsworkflow.util.rdfinfer import Infer
-
- model = get_model()
- add_default_schemas(model)
- inference = Infer(model)
-
- url = '/lane/1193'
- response = self.client.get(url)
- self.assertEqual(response.status_code, 200)
- status = validate_xhtml(response.content)
- if status is not None: self.assertTrue(status)
-
- load_string_into_model(model, 'rdfa', response.content)
-
- errmsgs = list(inference.run_validation())
- self.assertEqual(len(errmsgs), 0)
-
-def suite():
- from unittest import TestSuite, defaultTestLoader
- suite = TestSuite()
- for testcase in [ClusterStationTestCases,
- SequencerTestCases,
- ExerimentsTestCases,
- TestFileType,
- TestEmailNotify,
- TestSequencer]:
- suite.addTests(defaultTestLoader.loadTestsFromTestCase(testcase))
- return suite
-
-if __name__ == "__main__":
- from unittest import main
- main(defaultTest="suite")
+++ /dev/null
-from django.conf.urls import patterns
-
-urlpatterns = patterns('',
- (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'^lanes_for/(?P<username>.+)/json$', 'htsworkflow.frontend.experiments.experiments.lanes_for_json'),
- (r'^file/(?P<key>.+)/?$', 'htsworkflow.frontend.experiments.views.read_result_file'),
- (r'^started/(?P<pk>.+)/$', 'htsworkflow.frontend.experiments.views.startedEmail'),
- (r'^finished/(?P<pk>.+)/$', 'htsworkflow.frontend.experiments.views.finishedEmail'),
-
-)
+++ /dev/null
-# Create your views here.
-from datetime import datetime
-import os
-
-#from django.template import Context, loader
-#shortcut to the above modules
-from django.contrib.auth.decorators import user_passes_test
-from django.conf import settings
-from django.core.exceptions import ObjectDoesNotExist
-from django.core.mail import EmailMessage, mail_managers
-from django.http import HttpResponse
-from django.shortcuts import render_to_response, get_object_or_404
-from django.template import RequestContext
-from django.template.loader import get_template
-
-from htsworkflow.frontend.experiments.models import \
- DataRun, \
- DataFile, \
- FlowCell, \
- Lane, \
- Sequencer
-from htsworkflow.frontend.experiments.experiments import \
- estimateFlowcellDuration, \
- estimateFlowcellTimeRemaining, \
- roundToDays, \
- getUsersForFlowcell, \
- makeEmailLaneMap
-
-def index(request):
- all_runs = DataRun.objects.order_by('-run_start_time')
- return render_to_response('experiments/index.html',{'data_run_list': all_runs})
-
-def detail(request, run_folder):
- html_str = '<h2>Exp Track Details Page</h2>'
- html_str += 'Run Folder: '+run_folder
- r = get_object_or_404(DataRun,run_folder=run_folder)
- return render_to_response('experiments/detail.html',{'run_f': r})
-
-def makeFCSheet(request,fcid):
- # get Flowcell by input fcid
- # ...
- rec = None
- try:
- rec = FlowCell.objects.get(flowcell_id=fcid)
- except ObjectDoesNotExist:
- pass
- lanes = ['1','2','3','4','5','6','7','8']
- return render_to_response('experiments/flowcellSheet.html',{'fc': rec})
-
-
-@user_passes_test(lambda u: u.is_staff)
-def startedEmail(request, pk):
- """
- Create the we have started processing your samples email
- """
- fc = get_object_or_404(FlowCell, id=pk)
-
- send = request.REQUEST.get('send',False)
- if send in ('1', 'on', 'True', 'true', True):
- send = True
- else:
- send = False
-
- bcc_managers = request.REQUEST.get('bcc', False)
- if bcc_managers in ('on', '1', 'True', 'true'):
- bcc_managers = True
- else:
- bcc_managers = False
-
- email_lane = makeEmailLaneMap(fc)
- flowcell_users = getUsersForFlowcell(fc)
- estimate = estimateFlowcellTimeRemaining(fc)
- estimate_low, estimate_high = roundToDays(estimate)
- email_verify = get_template('experiments/email_preview.html')
- email_template = get_template('experiments/started_email.txt')
- sender = settings.NOTIFICATION_SENDER
-
- warnings = []
- emails = []
-
- emailless_users = []
- for user in flowcell_users:
- # provide warning
- if user.email is None or len(user.email) == 0:
- warnings.append((user.admin_url(), user.username))
- user=None
-
- for user_email in email_lane.keys():
- sending = ""
- # build body
- context = RequestContext(request,
- {u'flowcell': fc,
- u'lanes': email_lane[user_email],
- u'runfolder': 'blank',
- u'finish_low': estimate_low,
- u'finish_high': estimate_high,
- u'now': datetime.now(),
- })
-
- # build view
- subject = "Flowcell %s" % ( fc.flowcell_id )
- body = email_template.render(context)
-
- if send:
- email = EmailMessage(subject, body, sender, to=[user_email])
- notified = set()
- if bcc_managers:
- for manager in settings.MANAGERS:
- if len(manager) > 0:
- notified.add(manager)
- for user in settings.NOTIFICATION_BCC:
- if len(user) > 0:
- notified.add(user)
- email.bcc = list(notified)
- email.send()
-
- emails.append((user_email, subject, body, sending))
-
- verify_context = RequestContext(
- request,
- { 'emails': emails,
- 'flowcell': fc,
- 'from': sender,
- 'send': send,
- 'site_managers': settings.MANAGERS,
- 'title': fc.flowcell_id,
- 'warnings': warnings,
- })
- return HttpResponse(email_verify.render(verify_context))
-
-def finishedEmail(request, pk):
- """
- """
- return HttpResponse("I've got nothing.")
-
-
-def flowcell_detail(request, flowcell_id, lane_number=None):
- fc = get_object_or_404(FlowCell, flowcell_id__startswith=flowcell_id)
- fc.update_data_runs()
-
-
- if lane_number is not None:
- lanes = fc.lane_set.filter(lane_number=lane_number)
- else:
- lanes = fc.lane_set.all()
-
- context = RequestContext(request,
- {'flowcell': fc,
- 'lanes': lanes})
-
- return render_to_response('experiments/flowcell_detail.html',
- context)
-
-def flowcell_lane_detail(request, lane_pk):
- lane = get_object_or_404(Lane, id=lane_pk)
- lane.flowcell.update_data_runs()
-
- dataruns = []
- lane.flowcell.update_data_runs()
- for run in lane.flowcell.datarun_set.all():
- files = run.lane_files().get(lane.lane_number, None)
- dataruns.append((run,
- lane.lane_number,
- files))
-
- context = RequestContext(request,
- {'lib': lane.library,
- 'lane': lane,
- 'flowcell': lane.flowcell,
- 'filtered_dataruns': dataruns})
-
- return render_to_response('experiments/flowcell_lane_detail.html',
- context)
-
-def read_result_file(self, key):
- """Return the contents of filename if everything is approved
- """
- data_file = get_object_or_404(DataFile, random_key = key)
-
- content_type = 'application/octet-stream'
- if data_file.file_type.mimetype is not None:
- content_type = data_file.file_type.mimetype
-
- if os.path.exists(data_file.pathname):
- return HttpResponse(open(data_file.pathname,'r'),
- content_type=content_type)
-
- raise Http404
-
-
-def sequencer(request, sequencer_id):
- sequencer = get_object_or_404(Sequencer, id=sequencer_id)
- context = RequestContext(request,
- {'sequencer': sequencer})
- return render_to_response('experiments/sequencer.html', context)
+++ /dev/null
-from django.contrib import admin
-
-from htsworkflow.frontend.inventory.models import Item, ItemInfo, ItemType, Vendor, Location, LongTermStorage, ItemStatus, ReagentFlowcell, ReagentLibrary, PrinterTemplate
-
-class ItemAdmin(admin.ModelAdmin):
- save_as = True
- save_on_top = True
- list_display = ('uuid', 'barcode_id','item_type', 'item_info', 'location', 'force_use_uuid', 'creation_date')
- list_filter = (
- 'item_type', 'status'
- )
- search_fields = [
- 'barcode_id',
- 'uuid',
- 'status__name',
- 'item_type__name',
- 'location__name',
- 'notes'
- ]
-
-class ItemInfoAdmin(admin.ModelAdmin):
- save_as = True
- save_on_top = True
-
-class ItemTypeAdmin(admin.ModelAdmin):
- pass
-
-class VendorAdmin(admin.ModelAdmin):
- pass
-
-class LocationAdmin(admin.ModelAdmin):
- pass
-
-class LongTermStorageAdmin(admin.ModelAdmin):
- pass
-
-class ItemStatusAdmin(admin.ModelAdmin):
- pass
-
-class ReagentFlowcellAdmin(admin.ModelAdmin):
- pass
-
-class ReagentLibraryAdmin(admin.ModelAdmin):
- pass
-
-class PrinterTemplateAdmin(admin.ModelAdmin):
- list_display = ('item_type', 'printer', 'default')
-
-admin.site.register(Item, ItemAdmin)
-admin.site.register(ItemInfo, ItemInfoAdmin)
-admin.site.register(ItemType, ItemTypeAdmin)
-admin.site.register(Vendor, VendorAdmin)
-admin.site.register(Location, LocationAdmin)
-admin.site.register(LongTermStorage, LongTermStorageAdmin)
-admin.site.register(ItemStatus, ItemStatusAdmin)
-#admin.site.register(ReagentFlowcell, ReagentFlowcellAdmin)
-#admin.site.register(ReagentLibrary, ReagentLibraryAdmin)
-admin.site.register(PrinterTemplate, PrinterTemplateAdmin)
-
+++ /dev/null
-from htsworkflow.frontend.inventory.models import Item
-
-from django.core.exceptions import ObjectDoesNotExist
-
-def item_search(search):
- """
- Searches
- """
- hits = []
- try:
- item = Item.objects.get(uuid=search)
- except ObjectDoesNotExist:
- item = None
-
- if item is not None:
- hits.append((str(item), item.get_absolute_url()))
-
- try:
- item = Item.objects.get(barcode_id=search)
- except ObjectDoesNotExist:
- item = None
-
- if item is not None:
- hits.append((str(item), item.get_absolute_url()))
-
- return hits
+++ /dev/null
-[
- {"pk": 1,
- "model": "inventory.itemtype",
- "fields": {"name": "Hard Drive"}
- },
- {"pk": 2,
- "model": "inventory.itemtype",
- "fields": {"name": "Illumina SR Cluster Generation Reagents"}
- },
- {"pk": 3,
- "model": "inventory.itemtype",
- "fields": {"name": "Illumina Library Creation Reagents"}
- },
- {"pk": 4,
- "model": "inventory.itemtype",
- "fields": {"name": "Illumina Sequencing Reagents"}
- },
- {"pk": 5,
- "model": "inventory.itemtype",
- "fields": {"name": "Illumina PE Cluster Generation Reagents"}
- },
- {"pk": 6,
- "model": "inventory.itemtype",
- "fields": {"name": "Library"}
- }
-]
+++ /dev/null
-[
- {"pk": 1,
- "model": "bcmagic.printer",
- "fields": {"name": "ZM400 1.25x1",
- "label_height": 1.0,
- "notes": "Everyday use labels",
- "label_width": 1.25,
- "label_shape": "Square",
- "model": "Zebra ZM400",
- "ip_address": "131.215.34.116"}},
- {"pk": 2,
- "model": "bcmagic.printer",
- "fields": {"name": "ZM400 3x3",
- "label_height": 3.0,
- "notes": "Larger everyday use labels",
- "label_width": 3.0,
- "label_shape": "Square",
- "model": "Zebra ZM400",
- "ip_address": "131.215.34.117"}},
- { "model": "experiments.Sequencer",
- "pk": 7,
- "fields": {
- "name": "First sequencer",
- "instrument_name": "USI-EAS99",
- "serial_number": "",
- "model": "Illumina Genome Analyzer I",
- "active": false,
- "isdefault": false,
- "comment": "my first sequencer"
- }
- },
- { "model": "experiments.ClusterStation",
- "pk": 1,
- "fields": {
- "name": "Station",
- "isdefault": true
- }
- },
- {
- "pk": 1,
- "model": "inventory.vendor",
- "fields": {
- "url": "http://www.newegg.com/",
- "name": "newegg.com"
- }
- },
- {
- "pk": 1,
- "model": "inventory.location",
- "fields": {
- "uuid": "e344a4a2522211de99b00015172ce556",
- "notes": "",
- "location_description": "Office 1",
- "name": "Dev Office"
- }
- },
- {
- "pk": 1,
- "model": "inventory.iteminfo",
- "fields": {
- "model_id": "WD10EADS-00L5B1",
- "vendor": 1,
- "lot_number": "",
- "url": "http://www.newegg.com/Product/Product.aspx?Item=N82E16822136317&Tpk=WD10EADS",
- "warranty_months": 24,
- "notes": "",
- "part_number": "",
- "purchase_date": "2009-05-19",
- "qty_purchased": 17
- }
- },
- {
- "pk": 1,
- "model": "inventory.itemtype",
- "fields": {
- "name": "Hard Drive",
- "description": null
- }
- },
- {
- "pk": 1,
- "model": "inventory.itemstatus",
- "fields": {
- "notes": "",
- "name": "Used"
- }
- },
- {
- "pk": 2,
- "model": "inventory.itemstatus",
- "fields": {
- "notes": "",
- "name": "Unused"
- }
- },
- {
- "pk": 1,
- "model": "inventory.item",
- "fields": {
- "status": null,
- "modified_date": "2009-08-10T16:58:44-0800",
- "uuid": "8a90b6ce522311de99b00015172ce556",
- "barcode_id": "WCAU49183397",
- "notes": "",
- "item_info": 1,
- "force_use_uuid": false,
- "item_type": 1,
- "location": 1,
- "creation_date": "2009-06-05T15:52:26-0800"
- }
- },
- {
- "pk": 2,
- "model": "inventory.item",
- "fields": {
- "status": null,
- "modified_date": "2009-06-16T11:38:24-0800",
- "uuid": "b0792d425aa411de99b00015172ce556",
- "barcode_id": "WCAU49042470",
- "notes": "",
- "item_info": 1,
- "force_use_uuid": false,
- "item_type": 1,
- "location": 1,
- "creation_date": "2009-06-16T11:37:04-0800"
- }
- },
- {
- "pk": 1,
- "model": "inventory.printertemplate",
- "fields": {
- "default": false,
- "item_type": 1,
- "printer": 2,
- "template": "^FX=========================\r\n^FX 3\"x3\" Label\r\n^FX=========================\r\n^XA\r\n\r\n\r\n^FX======== Left Side ===========\r\n\r\n^FX------------\r\n^FX ^LH changes the 0,0 point of all subsequent location references\r\n^FX------------\r\n\r\n^LH0,50\r\n\r\n^FX ---Header---\r\n\r\n^FO25,0\r\n^CF0,50\r\n^FB250,2,,C\r\n^FD{{ item.barcode_id }}^FS\r\n\r\n^FX ---Column 1: Flowcells---\r\n\r\n^FX-----------------\r\n^FX FB command for automatic text formatting:\r\n^FX ^FB[dot width of area], [max # of lines], [change line spacing], [justification: L, C, R, J], [hanging indent]\r\n^FX-----------------\r\n\r\n^CF0,30,30\r\n^FO75,125\r\n^FB275,19,,L\r\n^FD{% for flowcell in flowcell_id_list %}{{ flowcell }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n^FX ---Date---\r\n\r\n^FO0,725\r\n^CF0,35\r\n^FB300,2,,C\r\n^FD{{ oldest_rundate|date:\"YMd\" }} - {{ latest_rundate|date:\"YMd\" }}^FS\r\n\r\n^FX ---Barcode---\r\n\r\n^FO135,795\r\n^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS\r\n\r\n^FX======== Right Side ===========\r\n\r\n^LH300,60\r\n\r\n^FX ---Header---\r\n\r\n^FO0,0\r\n^CF0,50\r\n^FB600,2,,C\r\n^FD{{ barcode_id }}^FS\r\n\r\n^FX ---Dividing line---\r\n\r\n^FX---------------\r\n^FX GB command:\r\n^FX ^GB[box width], [box height], [border thickness], [color: B, W], [corner rounding: 0-8]^FS\r\n^FX---------------\r\n\r\n^FO0,100\r\n^GB0,600,10^FS\r\n\r\n^FX ---Column 2: Libraries 1-20---\r\n\r\n^CF0,30,30\r\n^FO75,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_1_to_20 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 3: Libraries 21-40---\r\n\r\n^CF0,30,30\r\n^FO200,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_21_to_40 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 4: Libraries 41-60---\r\n\r\n^CF0,30,30\r\n^FO325,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_41_to_60 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 5: Libraries 61-80---\r\n\r\n^CF0,30,30\r\n^FO450,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_61_to_80 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Date---\r\n\r\n^FO0,715\r\n^CF0,35\r\n^FB600,2,,C\r\n^FDRun Dates: {{ oldest_rundate|date:\"YMd\" }}-{{ latest_rundate|date:\"YMd\" }}^FS\r\n\r\n^FX ---Barcode---\r\n\r\n^FO255,785\r\n^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS\r\n\r\n^LH0,0\r\n^FX ---End---\r\n^XZ\r\n"
- }
- },
- {
- "pk": 2,
- "model": "inventory.printertemplate",
- "fields": {
- "default": true,
- "item_type": 2,
- "printer": 1,
- "template": "^FX=========================\r\n^FX Harddrive Location Tracking Label\r\n^FX 300x375 dots\r\n^FX=========================\r\n\r\n^XA\r\n^LH 0,25\r\n\r\n^FO0,0\r\n^CF0,35\r\n^FB375,1,,C\r\n^FD{{ item.item_type.name }}:^FS\r\n\r\n^FX -------Text contains HD serial #-------------\r\n^FO15,75\r\n^CF0,42\r\n^FB325,3,,C\r\n^FD{% if use_uuid %}{{ item.uuid }}{% else %}{{ item.barcode_id }}{% endif %}^FS\r\n\r\n^FX -------Barcode contains HD serial #-----------\r\n^FO150,200\r\n^BXN,3,200\r\n^FD{% if use_uuid %}invu|{{ item.uuid }}{% else %}invb|{{ item.barcode_id }}{% endif %}^FS\r\n\r\n^XZ\r\n"
- }
- },
- {
- "pk": 3,
- "model": "inventory.printertemplate",
- "fields": {
- "default": false,
- "item_type": 6,
- "printer": 1,
- "template": "^XA\r\n\r\n^FX ---SIDE LABEL---\r\n^LH 190,40\r\n^CF 0,30\r\n\r\n^FX------Sideways ID------\r\n^FO 0,25\r\n^TB R,100,40\r\n^FD{{ library.id }}^FS\r\n^FX------Sideways Line------\r\n^FO 50,0\r\n^GB 5,200,5^FS\r\n\r\n^FX-------Name----------\r\n^FO 65,20\r\n^FB 325,4\r\n^FD{{ library.library_name }}^FS\r\n\r\n^FX ---TOP LABEL---\r\n^LH 12,28\r\n^CF 0,30\r\n\r\n^FX----ID #----\r\n^FO 5,25\r\n^FB 145,1,,C\r\n^FD{{ library.id }}^FS\r\n\r\n^FX----Name----\r\n^CF 0,16\r\n^FO 13,47\r\n^TB N,130,30\r\n^FD{{ library.library_name }}^FS\r\n\r\n^FX--------Barcode--------\r\n^FO 50,80\r\n^BXN ,3,200\r\n^FDl|0000000{{ library.id }}|woldlab^FS\r\n\r\n{% if not library.hidden %}\r\n^FX-----Border-------\r\n^FO 0,0\r\n^GC 150,10\r\n^FX ---End---\r\n{% endif %}\r\n^XZ\r\n"
- }
- },
- {
- "pk": 1,
- "model": "inventory.longtermstorage",
- "fields": {
- "libraries": [
- "10001",
- "10002",
- "10003"
- ],
- "modified_date": "2009-06-01T00:00:00-0800",
- "storage_devices": [
- 1
- ],
- "flowcell": 1,
- "creation_date": "2009-06-01T00:00:00-0800"
- }
- },
- {
- "pk": 2,
- "model": "inventory.longtermstorage",
- "fields": {
- "libraries": [
- "10001",
- "10002",
- "10003"
- ],
- "modified_date": "2009-06-01T00:00:00-0800",
- "storage_devices": [
- 1
- ],
- "flowcell": 2,
- "creation_date": "2009-06-01T00:00:00-0800"
- }
- },
- {"pk": 1, "model": "experiments.flowcell",
- "fields": {
- "paired_end": true,
- "run_date": "2009-09-11T22:12:13-0800",
- "read_length": 75,
- "notes": "",
- "advanced_run": false,
- "control_lane": 2,
- "flowcell_id": "11ONEAAXX"
- }
- },
- {"pk": 2, "model": "experiments.flowcell",
- "fields": {
- "paired_end": false,
- "run_date": "2010-09-11T22:12:13-0800",
- "read_length": 75,
- "notes": "",
- "advanced_run": false,
- "control_lane": 2,
- "flowcell_id": "22TWOAAXX"
- }
- },
- {"pk": 3, "model": "experiments.flowcell",
- "fields": {
- "paired_end": false,
- "run_date": "2010-09-11T22:12:13-0800",
- "read_length": 75,
- "notes": "",
- "advanced_run": false,
- "control_lane": 2,
- "flowcell_id": "33THRAAXX (failed)"
- }
- },
- {"pk": "10001", "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 400,
- "library_name": "10001",
- "creation_date": "2009-07-21",
- "cell_line": 1,
- "library_species": 2,
- "library_type": null,
- "made_by": "Igor",
- "affiliations": [
- 1
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "Done",
- "tags": [],
- "made_for": "Test",
- "amplified_from_sample": null,
- "notes": "",
- "undiluted_concentration": "1",
- "successful_pM": null,
- "experiment_type": 10,
- "antibody": null
- }
- },
- {"pk": "10002", "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 400,
- "library_name": "10002",
- "creation_date": "2009-07-21",
- "cell_line": 1,
- "library_species": 2,
- "library_type": null,
- "made_by": "Igor",
- "affiliations": [
- 1
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "Done",
- "tags": [],
- "made_for": "Test",
- "amplified_from_sample": null,
- "notes": "",
- "undiluted_concentration": "1",
- "successful_pM": null,
- "experiment_type": 10,
- "antibody": null
- }
- },
- {"pk": "10003", "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 400,
- "library_name": "10003",
- "creation_date": "2009-07-21",
- "cell_line": 1,
- "library_species": 2,
- "library_type": null,
- "made_by": "Igor",
- "affiliations": [
- 1
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "Done",
- "tags": [],
- "made_for": "Test",
- "amplified_from_sample": null,
- "notes": "",
- "undiluted_concentration": "1",
- "successful_pM": null,
- "experiment_type": 10,
- "antibody": null
- }
- },
- {"pk": 1, "model": "experiments.lane",
- "fields": {
- "comment": "10001 lane 1",
- "library": "10001",
- "cluster_estimate": 100000,
- "flowcell": 1,
- "lane_number": 1,
- "pM": "8"
- }
- },
- {"pk": 2, "model": "experiments.lane",
- "fields": {
- "comment": "10002 lane 2",
- "library": "10002",
- "cluster_estimate": 100000,
- "flowcell": 1,
- "lane_number": 2,
- "pM": "8"
- }
- },
- {"pk": 3, "model": "experiments.lane",
- "fields": {
- "comment": "10003 lane 3",
- "library": "10003",
- "cluster_estimate": 100000,
- "flowcell": 1,
- "lane_number": 3,
- "pM": "8"
- }
- },
- {"pk": 4, "model": "experiments.lane",
- "fields": {
- "comment": "10004 lane 4",
- "library": "10001",
- "cluster_estimate": 100000,
- "flowcell": 2,
- "lane_number": 4,
- "pM": "8"
- }
- },
- {"pk": 5, "model": "experiments.lane",
- "fields": {
- "comment": "10001 lane 1",
- "library": "10001",
- "cluster_estimate": 100000,
- "flowcell": 2,
- "lane_number": 1,
- "pM": "8"
- }
- },
- {"pk": 6, "model": "experiments.lane",
- "fields": {
- "comment": "10001 lane 1",
- "library": "10003",
- "cluster_estimate": 100000,
- "flowcell": 2,
- "lane_number": 2,
- "pM": "8"
- }
- },
- {"pk": 7, "model": "experiments.lane",
- "fields": {
- "comment": "10003 lane 8",
- "library": "10003",
- "cluster_estimate": 100000,
- "flowcell": 2,
- "lane_number": 8,
- "pM": "8"
- }
- },
- {"pk": 8, "model": "experiments.lane",
- "fields": {
- "comment": "10002 lane 8",
- "library": "10001",
- "cluster_estimate": 100000,
- "flowcell": 2,
- "lane_number": 8,
- "pM": "8"
- }
- },
- {"pk": 9, "model": "experiments.lane",
- "fields": {
- "comment": "10004 lane 4",
- "library": "10001",
- "cluster_estimate": 100000,
- "flowcell": 3,
- "lane_number": 4,
- "pM": "8"
- }
- },
- {"pk": 10, "model": "experiments.lane",
- "fields": {
- "comment": "10001 lane 1",
- "library": "10001",
- "cluster_estimate": 100000,
- "flowcell": 3,
- "lane_number": 1,
- "pM": "8"
- }
- },
- {"pk": 11, "model": "experiments.lane",
- "fields": {
- "comment": "10001 lane 1",
- "library": "10003",
- "cluster_estimate": 100000,
- "flowcell": 3,
- "lane_number": 2,
- "pM": "8"
- }
- },
- {"pk": 12, "model": "experiments.lane",
- "fields": {
- "comment": "10003 lane 8",
- "library": "10003",
- "cluster_estimate": 100000,
- "flowcell": 3,
- "lane_number": 8,
- "pM": "8"
- }
- },
- {"pk": 13, "model": "experiments.lane",
- "fields": {
- "comment": "10002 lane 8",
- "library": "10001",
- "cluster_estimate": 100000,
- "flowcell": 3,
- "lane_number": 8,
- "pM": "8"
- }
- }
-]
+++ /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-01T00:00:01-0800",
- "groups": [],
- "user_permissions": [],
- "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
- "email": "",
- "date_joined": "2009-01-01T00:01:01-0800"
- }
- },
- {"pk": 5, "model": "samples.htsuser",
- "fields" : {}
- },
- {"pk": 6, "model": "auth.user",
- "fields": {
- "username": "admintest",
- "first_name": "",
- "last_name": "",
- "is_active": true,
- "is_superuser": false,
- "is_staff": true,
- "last_login": "2009-01-01T00:00:01-0800",
- "groups": [],
- "user_permissions": [],
- "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
- "email": "",
- "date_joined": "2009-01-01T00:01:01-0800"
- }
- },
- {"pk": 6, "model": "samples.htsuser",
- "fields" : {}
- },
- {"pk": 7, "model": "auth.user",
- "fields": {
- "username": "supertest",
- "first_name": "",
- "last_name": "",
- "is_active": true,
- "is_superuser": true,
- "is_staff": true,
- "last_login": "2009-01-01T00:00:01-0800",
- "groups": [],
- "user_permissions": [],
- "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
- "email": "",
- "date_joined": "2009-01-01T00:01:01-0800"
- }
- },
- {"pk": 7, "model": "samples.htsuser",
- "fields" : {}
- },
- {"pk": 1, "model": "samples.affiliation",
- "fields": {
- "users": [5],
- "contact": "group 1",
- "name": "affiliation 1",
- "email": "pk1@example.com"
- }
- },
- {"pk": 2, "model": "samples.affiliation",
- "fields": {
- "users": [6],
- "contact": "group 2",
- "name": "affiliation 2",
- "email": "pk2@example.com"
- }
- },
- {"pk": 3, "model": "samples.affiliation",
- "fields": {
- "users": [],
- "contact": "group 3",
- "name": "affiliation 3",
- "email": "pk3@example.com"
- }
- },
- {"pk": 4, "model": "samples.affiliation",
- "fields": {
- "users": [],
- "contact": "group 4",
- "name": "affiliation 4",
- "email": "pk1@example.com"
- }
- },
- {"pk": 5, "model": "samples.affiliation",
- "fields": {
- "users": [],
- "contact": "group 5",
- "name": "affiliation 5",
- "email": "pk5@example.com"
- }
- }
-]
+++ /dev/null
-[{"pk": 1,
- "model": "inventory.printertemplate",
- "fields": {"default": false,
- "item_type": 1,
- "printer": 2,
- "template": "^FX=========================\r\n^FX 3\"x3\" Label\r\n^FX=========================\r\n^XA\r\n\r\n\r\n^FX======== Left Side ===========\r\n\r\n^FX------------\r\n^FX ^LH changes the 0,0 point of all subsequent location references\r\n^FX------------\r\n\r\n^LH0,50\r\n\r\n^FX ---Header---\r\n\r\n^FO25,0\r\n^CF0,50\r\n^FB250,2,,C\r\n^FD{{ item.barcode_id }}^FS\r\n\r\n^FX ---Column 1: Flowcells---\r\n\r\n^FX-----------------\r\n^FX FB command for automatic text formatting:\r\n^FX ^FB[dot width of area], [max # of lines], [change line spacing], [justification: L, C, R, J], [hanging indent]\r\n^FX-----------------\r\n\r\n^CF0,30,30\r\n^FO75,125\r\n^FB275,19,,L\r\n^FD{% for flowcell in flowcell_id_list %}{{ flowcell }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n^FX ---Date---\r\n\r\n^FO0,725\r\n^CF0,35\r\n^FB300,2,,C\r\n^FD{{ oldest_rundate|date:\"YMd\" }} - {{ latest_rundate|date:\"YMd\" }}^FS\r\n\r\n^FX ---Barcode---\r\n\r\n^FO135,795\r\n^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS\r\n\r\n^FX======== Right Side ===========\r\n\r\n^LH300,60\r\n\r\n^FX ---Header---\r\n\r\n^FO0,0\r\n^CF0,50\r\n^FB600,2,,C\r\n^FD{{ barcode_id }}^FS\r\n\r\n^FX ---Dividing line---\r\n\r\n^FX---------------\r\n^FX GB command:\r\n^FX ^GB[box width], [box height], [border thickness], [color: B, W], [corner rounding: 0-8]^FS\r\n^FX---------------\r\n\r\n^FO0,100\r\n^GB0,600,10^FS\r\n\r\n^FX ---Column 2: Libraries 1-20---\r\n\r\n^CF0,30,30\r\n^FO75,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_1_to_20 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 3: Libraries 21-40---\r\n\r\n^CF0,30,30\r\n^FO200,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_21_to_40 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 4: Libraries 41-60---\r\n\r\n^CF0,30,30\r\n^FO325,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_41_to_60 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 5: Libraries 61-80---\r\n\r\n^CF0,30,30\r\n^FO450,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_61_to_80 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Date---\r\n\r\n^FO0,715\r\n^CF0,35\r\n^FB600,2,,C\r\n^FDRun Dates: {{ oldest_rundate|date:\"YMd\" }}-{{ latest_rundate|date:\"YMd\" }}^FS\r\n\r\n^FX ---Barcode---\r\n\r\n^FO255,785\r\n^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS\r\n\r\n^LH0,0\r\n^FX ---End---\r\n^XZ\r\n"}},
- {"pk": 2,
- "model": "inventory.printertemplate",
- "fields": {"default": true,
- "item_type": 2,
- "printer": 1,
- "template": "^FX=========================\r\n^FX Harddrive Location Tracking Label\r\n^FX 300x375 dots\r\n^FX=========================\r\n\r\n^XA\r\n^LH 0,25\r\n\r\n^FO0,0\r\n^CF0,35\r\n^FB375,1,,C\r\n^FD{{ item.item_type.name }}:^FS\r\n\r\n^FX -------Text contains HD serial #-------------\r\n^FO15,75\r\n^CF0,42\r\n^FB325,3,,C\r\n^FD{% if use_uuid %}{{ item.uuid }}{% else %}{{ item.barcode_id }}{% endif %}^FS\r\n\r\n^FX -------Barcode contains HD serial #-----------\r\n^FO150,200\r\n^BXN,3,200\r\n^FD{% if use_uuid %}invu|{{ item.uuid }}{% else %}invb|{{ item.barcode_id }}{% endif %}^FS\r\n\r\n^XZ\r\n"}}
-]
+++ /dev/null
-import logging
-
-from django.db import models
-from django.db.models.signals import pre_save
-
-from htsworkflow.frontend.samples.models import Library
-from htsworkflow.frontend.experiments.models import FlowCell
-from htsworkflow.frontend.bcmagic.models import Printer
-
-LOGGER = logging.getLogger(__name__)
-
-try:
- import uuid
-except ImportError, e:
- # Some systems are using python 2.4, which doesn't have uuid
- # this is a stub
- LOGGER.warning('Real uuid is not available, initializing fake uuid module')
- class uuid:
- def uuid1(self):
- self.hex = None
- return self
-
-def _assign_uuid(sender, instance, **kwargs):
- """
- Assigns a UUID to model on save
- """
- #print 'Entered _assign_uuid'
- if instance.uuid is None or len(instance.uuid) != 32:
- instance.uuid = uuid.uuid1().hex
-
-def _switch_default(sender, instance, **kwargs):
- """
- When new instance has default == True, uncheck all other defaults
- """
- if instance.default:
- other_defaults = PrinterTemplate.objects.filter(default=True)
-
- for other in other_defaults:
- other.default = False
- other.save()
-
-
-class Vendor(models.Model):
- name = models.CharField(max_length=256)
- url = models.URLField(blank=True, null=True)
-
- def __unicode__(self):
- return u"%s" % (self.name)
-
-
-class Location(models.Model):
-
- name = models.CharField(max_length=256, unique=True)
- location_description = models.TextField()
-
- uuid = models.CharField(max_length=32, blank=True, help_text="Leave blank for automatic UUID generation", editable=False)
-
- notes = models.TextField(blank=True, null=True)
-
- def __unicode__(self):
- if len(self.location_description) > 16:
- return u"%s: %s" % (self.name, self.location_description[0:16]+u"...")
- else:
- return u"%s: %s" % (self.name, self.location_description)
-
-pre_save.connect(_assign_uuid, sender=Location)
-
-
-class ItemInfo(models.Model):
- model_id = models.CharField(max_length=256, blank=True, null=True)
- part_number = models.CharField(max_length=256, blank=True, null=True)
- lot_number = models.CharField(max_length=256, blank=True, null=True)
-
- url = models.URLField(blank=True, null=True)
-
- qty_purchased = models.IntegerField(default=1)
-
- vendor = models.ForeignKey(Vendor)
- purchase_date = models.DateField(blank=True, null=True)
- warranty_months = models.IntegerField(blank=True, null=True)
-
- notes = models.TextField(blank=True, null=True)
-
- def __unicode__(self):
- name = u''
- if self.model_id:
- name += u"model:%s " % (self.model_id)
- if self.part_number:
- name += u"part:%s " % (self.part_number)
- if self.lot_number:
- name += u"lot:%s " % (self.lot_number)
-
- return u"%s: %s" % (name, self.purchase_date)
-
- class Meta:
- verbose_name_plural = "Item Info"
-
-
-class ItemType(models.Model):
-
- name = models.CharField(max_length=64, unique=True)
- description = models.TextField(blank=True, null=True)
-
- def __unicode__(self):
- return u"%s" % (self.name)
-
-class ItemStatus(models.Model):
- name = models.CharField(max_length=64, unique=True)
- notes = models.TextField(blank=True, null=True)
-
- def __unicode__(self):
- return self.name
-
- class Meta:
- verbose_name_plural = "Item Status"
-
-
-class Item(models.Model):
-
- item_type = models.ForeignKey(ItemType)
-
- #Automatically assigned uuid; used for barcode if one is not provided in
- # barcode_id
- uuid = models.CharField(max_length=32, blank=True, help_text="Leave blank for automatic UUID generation", unique=True, editable=False)
-
- # field for existing barcodes; used instead of uuid if provided
- barcode_id = models.CharField(max_length=256, blank=True, null=True)
- force_use_uuid = models.BooleanField(default=False)
-
- item_info = models.ForeignKey(ItemInfo)
-
- location = models.ForeignKey(Location)
-
- status = models.ForeignKey(ItemStatus, blank=True, null=True)
-
- creation_date = models.DateTimeField(auto_now_add=True)
- modified_date = models.DateTimeField(auto_now=True)
-
- notes = models.TextField(blank=True, null=True)
-
- def __unicode__(self):
- if self.barcode_id is None or len(self.barcode_id) == 0:
- return u"invu|%s" % (self.uuid)
- else:
- return u"invb|%s" % (self.barcode_id)
-
- def get_absolute_url(self):
- return '/inventory/%s/' % (self.uuid)
-
-pre_save.connect(_assign_uuid, sender=Item)
-
-
-class PrinterTemplate(models.Model):
- """
- Maps templates to printer to use
- """
- item_type = models.ForeignKey(ItemType)
- printer = models.ForeignKey(Printer)
-
- default = models.BooleanField(default=False)
-
- template = models.TextField()
-
- def __unicode__(self):
- if self.default:
- return u'%s %s' % (self.item_type.name, self.printer.name)
- else:
- return u'%s %s (default)' % (self.item_type.name, self.printer.name)
-
-pre_save.connect(_switch_default, sender=PrinterTemplate)
-
-
-class LongTermStorage(models.Model):
-
- flowcell = models.ForeignKey(FlowCell)
- libraries = models.ManyToManyField(Library)
-
- storage_devices = models.ManyToManyField(Item)
-
- creation_date = models.DateTimeField(auto_now_add=True)
- modified_date = models.DateTimeField(auto_now=True)
-
- def __unicode__(self):
- return u"%s: %s" % (str(self.flowcell), ', '.join([ str(s) for s in self.storage_devices.iterator() ]))
-
- class Meta:
- verbose_name_plural = "Long Term Storage"
-
-
-
-class ReagentBase(models.Model):
-
- reagent = models.ManyToManyField(Item)
-
- creation_date = models.DateTimeField(auto_now_add=True)
- modified_date = models.DateTimeField(auto_now=True)
-
- class Meta:
- abstract = True
-
-
-class ReagentFlowcell(ReagentBase):
- """
- Links reagents and flowcells
- """
- flowcell = models.ForeignKey(FlowCell)
-
- def __unicode__(self):
- return u"%s: %s" % (str(self.flowcell), ', '.join([ str(s) for s in self.reagent.iterator() ]))
-
-
-class ReagentLibrary(ReagentBase):
- """
- Links libraries and flowcells
- """
- library = models.ForeignKey(Library)
-
- def __unicode__(self):
- return u"%s: %s" % (str(self.library), ', '.join([ str(s) for s in self.reagent.iterator() ]))
+++ /dev/null
-import RDF
-
-from django.test import TestCase
-from django.test.utils import setup_test_environment, \
- teardown_test_environment
-from django.db import connection
-from django.conf import settings
-
-from django.contrib.auth.models import User
-from django.core import urlresolvers
-
-from htsworkflow.frontend.inventory.models import Item, Vendor
-from htsworkflow.util.rdfhelp import get_model, load_string_into_model, get_serializer, inventoryOntology, libraryOntology, fromTypedNode
-
-def localhostNode(url):
- return RDF.Node(RDF.Uri('http://localhost%s' % (url,)))
-
-class InventoryTestCase(TestCase):
- fixtures = ['initial_data', 'test_user', 'test_harddisks']
-
- def test_fixture(self):
- # make sure that some of our test data is was loaded
- # since there was no error message when I typoed the test fixture
- hd1 = Item.objects.get(pk=1)
- self.failUnlessEqual(hd1.uuid, '8a90b6ce522311de99b00015172ce556')
-
- user = User.objects.get(pk=5)
- self.failUnlessEqual(user.username, 'test')
-
- def test_item(self):
- url = '/inventory/8a90b6ce522311de99b00015172ce556/'
- self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
- response = self.client.get(url)
- self.failUnlessEqual(response.status_code, 200)
-
- model = get_model()
- load_string_into_model(model, 'rdfa', response.content, url)
-
- itemNode = RDF.Node(RDF.Uri(url))
- item_type = fromTypedNode(model.get_target(itemNode, inventoryOntology['item_type']))
- self.failUnlessEqual(item_type, u'Hard Drive')
-
- def test_itemindex(self):
- url = '/inventory/it/Hard Drive/'
- indexNode = localhostNode(url)
- diskNode = localhostNode('/inventory/8a90b6ce522311de99b00015172ce556/')
- self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
-
- flowcells = self.get_flowcells_from_content(url, indexNode, diskNode)
- self.failUnlessEqual(len(flowcells), 2)
- self.failUnless('http://localhost/flowcell/11ONEAAXX/' in flowcells)
- self.failUnless('http://localhost/flowcell/22TWOAAXX/' in flowcells)
-
- def test_add_disk(self):
- url = '/inventory/it/Hard Drive/'
- #url_disk = '/inventory/8a90b6ce522311de99b00015172ce556/'
- url_disk = '/inventory/b0792d425aa411de99b00015172ce556/'
- indexNode = localhostNode(url)
- diskNode = localhostNode(url_disk)
- self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
-
- flowcells = self.get_flowcells_from_content(url, indexNode, diskNode)
- self.failUnlessEqual(len(flowcells), 0)
-
- # step two link the flowcell
- flowcell = '22TWOAAXX'
- serial = 'WCAU49042470'
- link_url = urlresolvers.reverse(
- 'htsworkflow.frontend.inventory.views.link_flowcell_and_device',
- args=(flowcell, serial))
- link_response = self.client.get(link_url)
- self.failUnlessEqual(link_response.status_code, 200)
-
- flowcells = self.get_flowcells_from_content(url, indexNode, diskNode)
- self.failUnlessEqual(len(flowcells), 1)
- self.failUnlessEqual('http://localhost/flowcell/%s/' % (flowcell),
- flowcells[0])
-
- def test_add_disk_failed_flowcell(self):
- url = '/inventory/it/Hard Drive/'
- #url_disk = '/inventory/8a90b6ce522311de99b00015172ce556/'
- url_disk = '/inventory/b0792d425aa411de99b00015172ce556/'
- indexNode = localhostNode(url)
- diskNode = localhostNode(url_disk)
- self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
-
- flowcells = self.get_flowcells_from_content(url, indexNode, diskNode)
- self.failUnlessEqual(len(flowcells), 0)
-
- # step two link the flowcell
- flowcell = '33THRAAXX'
- serial = 'WCAU49042470'
- link_url = urlresolvers.reverse(
- 'htsworkflow.frontend.inventory.views.link_flowcell_and_device',
- args=(flowcell, serial))
- link_response = self.client.get(link_url)
- self.failUnlessEqual(link_response.status_code, 200)
-
- flowcells = self.get_flowcells_from_content(url, indexNode, diskNode)
- self.failUnlessEqual(len(flowcells), 1)
- self.failUnlessEqual('http://localhost/flowcell/%s/' % (flowcell),
- flowcells[0])
-
-
- def get_flowcells_from_content(self, url, rootNode, diskNode):
- model = get_model()
-
- response = self.client.get(url)
- self.failUnlessEqual(response.status_code, 200)
-
- load_string_into_model(model, 'rdfa', response.content, rootNode.uri)
- targets = model.get_targets(diskNode, libraryOntology['flowcell_id'])
- flowcells = [ str(x.uri) for x in targets]
- return flowcells
-
-def suite():
- from unittest import TestSuite, defaultTestLoader
- suite = TestSuite()
- suite.addTests(defaultTestLoader.loadTestsFromTestCase(InventoryTestCase))
- return suite
-
-if __name__ == "__main__":
- from unittest import main
- main(defaultTest="suite")
+++ /dev/null
-from django.conf.urls import patterns
-
-urlpatterns = patterns('',
- # DATA
- (r'^data/items/$', 'htsworkflow.frontend.inventory.views.data_items'),
- # REMOTE LINKING
- (r'^lts/link/(?P<flowcell>.+)/(?P<serial>.+)/$', 'htsworkflow.frontend.inventory.views.link_flowcell_and_device'),
-
- # INDEX
- (r'^it/(?P<name>.+)/$', 'htsworkflow.frontend.inventory.views.itemtype_index'),
- (r'^(?P<uuid>[a-fA-F0-9]{32})/$', 'htsworkflow.frontend.inventory.views.item_summary_by_uuid'),
- (r'^(?P<uuid>[a-fA-F0-9]{32})/print/$', 'htsworkflow.frontend.inventory.views.item_print'),
- (r'^(?P<barcode_id>.+)/$', 'htsworkflow.frontend.inventory.views.item_summary_by_barcode'),
- (r'^all_index/$', 'htsworkflow.frontend.inventory.views.all_index'),
- (r'^$', 'htsworkflow.frontend.inventory.views.index')
- )
+++ /dev/null
-from htsworkflow.frontend.samples.changelist import HTSChangeList
-from htsworkflow.frontend.inventory.models import Item, LongTermStorage, ItemType
-from htsworkflow.frontend.inventory.admin import ItemAdmin, ItemTypeAdmin
-from htsworkflow.frontend.inventory.bcmagic import item_search
-from htsworkflow.frontend.bcmagic.plugin import register_search_plugin
-from htsworkflow.frontend.experiments.models import FlowCell
-from htsworkflow.frontend.bcmagic.forms import BarcodeMagicForm
-from htsworkflow.frontend.bcmagic.utils import print_zpl_socket
-
-from django.conf import settings
-from django.contrib.auth.decorators import login_required
-from django.core.exceptions import ObjectDoesNotExist
-from django.http import HttpResponse, HttpResponseRedirect
-from django.shortcuts import render_to_response
-from django.template import RequestContext, Template
-from django.template.loader import get_template
-
-register_search_plugin('Inventory Item', item_search)
-
-try:
- import json
-except ImportError, e:
- import simplejson as json
-
-INVENTORY_CONTEXT_DEFAULTS = {
- 'app_name': 'Inventory Tracker',
- 'bcmagic': BarcodeMagicForm()
-}
-
-def __flowcell_rundate_sort(x, y):
- """
- Sort by rundate
- """
- if x.run_date > y.run_date:
- return 1
- elif x.run_date == y.run_date:
- return 0
- else:
- return -1
-
-def __expand_longtermstorage_context(context, item):
- """
- Expand information for LongTermStorage
- """
- flowcell_list = []
- flowcell_id_list = []
- library_id_list = []
-
- for lts in item.longtermstorage_set.all():
- flowcell_list.append(lts.flowcell)
- flowcell_id_list.append(lts.flowcell.flowcell_id)
- library_id_list.extend([ lib.id for lib in lts.libraries.all() ])
-
- flowcell_list.sort(__flowcell_rundate_sort)
- context['oldest_rundate'] = flowcell_list[0].run_date
- context['latest_rundate'] = flowcell_list[-1].run_date
-
- context['flowcell_id_list'] = flowcell_id_list
- context['library_id_list_1_to_20'] = library_id_list[0:20]
- context['library_id_list_21_to_40'] = library_id_list[20:40]
- context['library_id_list_41_to_60'] = library_id_list[40:60]
- context['library_id_list_61_to_80'] = library_id_list[60:80]
-
-
-EXPAND_CONTEXT = {
- 'Hard Drive': __expand_longtermstorage_context
-}
-
-#INVENTORY_ITEM_PRINT_DEFAULTS = {
-# 'Hard Drive': 'inventory/hard_drive_shell.zpl',
-# 'default': 'inventory/default.zpl',
-# 'host': settings.BCPRINTER_PRINTER1_HOST
-#}
-
-def getPrinterTemplateByType(item_type):
- """
- returns template to use given item_type
- """
- assert item_type.printertemplate_set.count() < 2
-
- # Get the template for item_type
- if item_type.printertemplate_set.count() > 0:
- printer_template = item_type.printertemplate_set.all()[0]
- return printer_template
- # Get default
- else:
- try:
- printer_template = PrinterTemplate.objects.get(default=True)
- except ObjectDoesNotExist:
- msg = "No template for item type (%s) and no default template found" % (item_type.name)
- raise ValueError, msg
-
- return printer_template
-
-
-@login_required
-def data_items(request):
- """
- Returns items in json format
- """
- item_list = Item.objects.all()
- d = { 'results': len(item_list) }
- rows = []
-
- for item in item_list:
- item_d = {}
- item_d['uuid'] = item.uuid
- item_d['barcode_id'] = item.barcode_id
- item_d['model_id'] = item.item_info.model_id
- item_d['part_number'] = item.item_info.part_number
- item_d['lot_number'] = item.item_info.lot_number
- item_d['vendor'] = item.item_info.vendor.name
- item_d['creation_date'] = item.creation_date.strftime('%Y-%m-%d %H:%M:%S')
- item_d['modified_date'] = item.modified_date.strftime('%Y-%m-%d %H:%M:%S')
- item_d['location'] = item.location.name
-
- # Item status if exists
- if item.status is None:
- item_d['status'] = ''
- else:
- item_d['status'] = item.status.name
-
- # Stored flowcells on device
- if item.longtermstorage_set.count() > 0:
- item_d['flowcells'] = ','.join([ lts.flowcell.flowcell_id for lts in item.longtermstorage_set.all() ])
- else:
- item_d['flowcells'] = ''
-
- item_d['type'] = item.item_type.name
- rows.append(item_d)
-
- d['rows'] = rows
-
- return HttpResponse(json.dumps(d), content_type="application/javascript")
-
-@login_required
-def all_index(request):
- """
- Inventory Index View
- """
- # build changelist
- item_changelist = HTSChangeList(request, Item,
- list_filter=[],
- search_fields=[],
- list_per_page=200,
- model_admin=ItemAdmin(Item, None)
- )
-
- context_dict = {
- 'item_changelist': item_changelist,
- 'page_name': 'Inventory Index'
- }
- context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
-
- return render_to_response('inventory/inventory_all_index.html',
- context_dict,
- context_instance=RequestContext(request))
-
-@login_required
-def index(request):
- """
- Inventory Index View
- """
- # build changelist
- item_changelist = HTSChangeList(request, ItemType,
- list_filter=[],
- search_fields=['name', 'description'],
- list_per_page=50,
- model_admin=ItemTypeAdmin(ItemType, None)
- )
-
- context_dict = {
- 'item_changelist': item_changelist,
- 'page_name': 'Inventory Index'
- }
- context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
- return render_to_response('inventory/inventory_index.html',
- context_dict,
- context_instance=RequestContext(request))
-
-@login_required
-def itemtype_index(request, name):
- """
- Inventory Index View
- """
-
- name = name.replace('%20', ' ')
-
- itemtype = ItemType.objects.get(name=name)
-
- # build changelist
- item_changelist = HTSChangeList(request, Item,
- list_filter=[],
- search_fields=[],
- list_per_page=200,
- model_admin=ItemAdmin(Item, None)
- )
-
- context_dict = {
- 'item_changelist': item_changelist,
- 'page_name': 'Inventory Index'
- }
- context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
-
- return render_to_response('inventory/inventory_itemtype_index.html',
- context_dict,
- context_instance=RequestContext(request))
-
-
-@login_required
-def item_summary_by_barcode(request, barcode_id, msg=''):
- """
- Display a summary for an item by barcode
- """
- try:
- item = Item.objects.get(barcode_id=barcode_id)
- except ObjectDoesNotExist, e:
- item = None
-
- return item_summary_by_uuid(request, None, msg, item)
-
-
-@login_required
-def item_summary_by_uuid(request, uuid, msg='', item=None):
- """
- Display a summary for an item
- """
- # Use item instead of looking it up if it is passed.
- if item is None:
- try:
- item = Item.objects.get(uuid=uuid)
- except ObjectDoesNotExist, e:
- item = None
-
- context_dict = {
- 'page_name': 'Item Summary',
- 'item': item,
- 'uuid': uuid,
- 'msg': msg
- }
- context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
-
- return render_to_response('inventory/inventory_summary.html',
- context_dict,
- context_instance=RequestContext(request))
-
-
-
-
-
-
-def __expand_context(context, item):
- """
- If EXPAND_CONTEXT dictionary has item.item_type.name function registered, use it to expand context
- """
- if item.item_type.name in EXPAND_CONTEXT:
- expand_func = EXPAND_CONTEXT[item.item_type.name]
- expand_func(context, item)
-
-def _item_print(item, request):
- """
- Prints an item given a type of item label to print
- """
- #FIXME: Hard coding this for now... need to abstract later.
- context = {'item': item}
- __expand_context(context, item)
-
- # Print using barcode_id
- if not item.force_use_uuid and (item.barcode_id is None or len(item.barcode_id.strip())):
- context['use_uuid'] = False
- msg = 'Printing item with barcode id: %s' % (item.barcode_id)
- # Print using uuid
- else:
- context['use_uuid'] = True
- msg = 'Printing item with UUID: %s' % (item.uuid)
-
- printer_template = getPrinterTemplateByType(item.item_type)
-
- c = RequestContext(request, context)
- t = Template(printer_template.template)
- print_zpl_socket(t.render(c), host=printer_template.printer.ip_address)
-
- return msg
-
-@login_required
-def item_print(request, uuid):
- """
- Print a label for a given item
- """
- try:
- item = Item.objects.get(uuid=uuid)
- except ObjectDoesNotExist, e:
- item = None
- msg = "Item with UUID %s does not exist" % (uuid)
-
- if item is not None:
- msg = _item_print(item, request)
-
- return item_summary_by_uuid(request, uuid, msg)
-
-
-def link_flowcell_and_device(request, flowcell, serial):
- """
- Updates database records of a flowcell being archived on a device with a particular serial #
- """
- assert flowcell is not None
- assert serial is not None
-
- LTS_UPDATED = False
- SD_UPDATED = False
- LIBRARY_UPDATED = False
-
- ###########################################
- # Retrieve Storage Device
- try:
- sd = Item.objects.get(barcode_id=serial)
- except ObjectDoesNotExist, e:
- msg = "Item with barcode_id of %s not found." % (serial)
- raise ObjectDoesNotExist(msg)
-
- ###########################################
- # Retrieve FlowCell
- try:
- fc = FlowCell.objects.get(flowcell_id__startswith=flowcell)
- except ObjectDoesNotExist, e:
- msg = "FlowCell with flowcell_id of %s not found." % (flowcell)
- raise ObjectDoesNotExist(msg)
-
- ###########################################
- # Retrieve or create LongTermStorage Object
- count = fc.longtermstorage_set.count()
- lts = None
- if count > 1:
- msg = "There really should only be one longtermstorage object per flowcell"
- raise ValueError, msg
- elif count == 1:
- # lts already attached to flowcell
- lts = fc.longtermstorage_set.all()[0]
- else:
- lts = LongTermStorage()
- # Attach flowcell
- lts.flowcell = fc
- # Need a primary keey before linking to storage devices
- lts.save()
- LTS_UPDATED = True
-
-
- ############################################
- # Link Storage to Flowcell
-
- # Add a link to this storage device if it is not already linked.
- if sd not in lts.storage_devices.all():
- lts.storage_devices.add(sd)
- SD_UPDATED = True
-
- ###########################################
- # Add Library Links to LTS
-
- for lane in fc.lane_set.all():
- if lane.library not in lts.libraries.all():
- lts.libraries.add(lane.library)
- LIBRARY_UPDATED = True
-
- # Save Changes
- lts.save()
-
- msg = ['Success:']
- if LTS_UPDATED or SD_UPDATED or LIBRARY_UPDATED:
- msg.append(' LongTermStorage (LTS) Created: %s' % (LTS_UPDATED))
- msg.append(' Storage Device Linked to LTS: %s' % (SD_UPDATED))
- msg.append(' Libraries updated in LTS: %s' % (LIBRARY_UPDATED))
- else:
- msg.append(' No Updates Needed.')
-
- return HttpResponse('\n'.join(msg))
+++ /dev/null
-from htsworkflow.frontend.labels.models import LabelContent, LabelTemplate, LabelPrinter
-from htsworkflow.frontend.inventory.models import PrinterTemplate
-from htsworkflow.frontend.bcmagic.utils import print_zpl_socket
-from django.template import Context, Template
-from django.contrib import admin
-
-class LabelContentOptions(admin.ModelAdmin):
- save_as = True
- save_on_top = True
- search_fields = (
- 'title',
- 'subtitle',
- 'text',
- 'barcode',
- 'creator',
- )
- list_display = ('title','subtitle','text','barcode','template','creator')
- list_filter = ('template','creator',)
- fieldsets = (
- (None, {
- 'fields': (('title','subtitle','text','barcode'),
- ('template','creator'))
-
- }),
- )
- actions = ['action_print_labels']
-
- def action_print_labels(self, request, queryset):
- """
- Django action which prints labels for the selected set of labels from the
- Django Admin interface.
- """
-
- zpl_list = []
- #Iterate over selected labels to print
- for label in queryset.all():
-
- template_used = LabelTemplate.objects.get(name=label.template.name)
- # ZPL Template
- t = Template(template_used.ZPL_code)
-
- # Django Template Context
- c = Context({'label': label})
-
- # Send rendered template to the printer that the template
- # object has been attached to in the database.
- zpl_list.append(t.render(c))
-
- print_zpl_socket(zpl_list, host=template_used.printer.ip_address)
-
- self.message_user(request, "%s labels printed." % (len(queryset)))
-
- action_print_labels.short_description = "Print Selected Labels"
-
-class LabelTemplateOptions(admin.ModelAdmin):
- save_as = True
- save_on_top = True
- list_display = ('name', 'printer', 'ZPL_code')
-
-class LabelPrinterOptions(admin.ModelAdmin):
- list_display = ('name', 'ip_address', 'labels')
-
-admin.site.register(LabelContent, LabelContentOptions)
-admin.site.register(LabelTemplate, LabelTemplateOptions)
-admin.site.register(LabelPrinter, LabelPrinterOptions)
-
+++ /dev/null
-from django.db import models
-
-class LabelPrinter(models.Model):
- """
- Barcode Printer Information
- """
- name = models.CharField(max_length=256)
- model = models.CharField(max_length=64, default='ZM400')
- ip_address = models.IPAddressField()
- labels = models.CharField(max_length=200)
- notes = models.TextField(null=True, blank=True)
-
- def __unicode__(self):
- return u'%s: %s' % (self.name, self.labels)
-
-class LabelTemplate(models.Model):
- """
- Maps templates to printer to use
- """
- name = models.CharField(max_length=200)
- description = models.TextField(null=True, blank=True)
- printer = models.ForeignKey(LabelPrinter)
-
- ZPL_code = models.TextField('template')
-
- def __unicode__(self):
- return '%s %s' % (self.name, self.printer.name)
-
-class LabelContent(models.Model):
- title = models.CharField(max_length=200, null=True, blank=True)
- subtitle = models.CharField(max_length=200, null=True, blank=True)
- text = models.CharField(max_length=200, null=True, blank=True)
- barcode = models.CharField(max_length=200, null=True, blank=True)
- template = models.ForeignKey(LabelTemplate)
- creator = models.CharField(max_length=200)
+++ /dev/null
-"""
-This file demonstrates two different styles of tests (one doctest and one
-unittest). These will both pass when you run "manage.py test".
-
-Replace these with more appropriate tests for your application.
-"""
-
-from django.test import TestCase
-
-class SimpleTest(TestCase):
- def test_basic_addition(self):
- """
- Tests that 1 + 1 always equals 2.
- """
- self.failUnlessEqual(1 + 1, 2)
-
-__test__ = {"doctest": """
-Another way to test that 1 + 1 is equal to 2.
-
->>> 1 + 1 == 2
-True
-"""}
-
-def suite():
- from unittest import TestSuite, defaultTestLoader
- suite = TestSuite()
- suite.addTests(defaultTestLoader.loadTestsFromTestCase(SimpleTest))
- return suite
-
-if __name__ == "__main__":
- from unittest import main
- main(defaultTest="suite")
+++ /dev/null
-# Create your views here.
+++ /dev/null
-from django.contrib import admin
-from django.contrib.admin import widgets
-from django.contrib.auth.models import User
-from django.contrib.auth.admin import UserAdmin
-from django.contrib.auth.forms import UserCreationForm, UserChangeForm
-from django.template import Context, Template
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-from django.forms import TextInput, Textarea
-
-from htsworkflow.frontend.samples.models import \
- Antibody, Cellline, Condition, ExperimentType, HTSUser, \
- LibraryType, MultiplexIndex, Species, Affiliation, Library, Tag
-from htsworkflow.frontend.experiments.models import Lane
-from htsworkflow.frontend.inventory.models import PrinterTemplate
-from htsworkflow.frontend.bcmagic.utils import print_zpl_socket
-
-# Let's disable those pesky delete everything by accident features.
-admin.site.disable_action('delete_selected')
-
-class AffiliationOptions(admin.ModelAdmin):
- list_display = ('name','contact','email')
- fieldsets = (
- (None, {
- 'fields': (('name','contact','email','users'))
- }),
- )
-
- # some post 1.0.2 version of django has formfield_overrides
- # which would replace this code with:
- # formfield_overrids = {
- # models.ManyToMany: { 'widget': widgets.FilteredSelectMultiple }
- # }
- def formfield_for_dbfield(self, db_field, **kwargs):
- if db_field.name == 'users':
- kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
- rv = super(AffiliationOptions, self).formfield_for_dbfield(db_field, **kwargs)
- # print db_field.name, kwargs
- return rv
-
-class AntibodyOptions(admin.ModelAdmin):
- search_fields = ('antigene','nickname','catalog','antibodies','source','biology','notes')
- list_display = ('antigene','nickname','antibodies','catalog','source','biology','notes')
- list_filter = ('antibodies','source')
- fieldsets = (
- (None, {
- 'fields': (('antigene','nickname','antibodies'),('catalog','source'),('biology'),('notes'))
- }),
- )
-
-class CelllineOptions(admin.ModelAdmin):
- list_display = ('cellline_name', 'notes')
- search_fields = ('cellline_name', 'nickname', 'notes')
- fieldsets = (
- (None, {
- 'fields': (('cellline_name','nickname',),('notes'),)
- }),
- )
-
-class ConditionOptions(admin.ModelAdmin):
- list_display = (('condition_name'), ('notes'),)
- fieldsets = (
- (None, {
- 'fields': (('condition_name'),('nickname'),('notes'),)
- }),
- )
-
-class ExperimentTypeOptions(admin.ModelAdmin):
- model = ExperimentType
- #list_display = ('name',)
- #fieldsets = ( (None, { 'fields': ('name',) }), )
-
-class HTSUserCreationForm(UserCreationForm):
- class Meta:
- model = HTSUser
- fields = ("username",'first_name','last_name')
-
-class HTSUserChangeForm(UserChangeForm):
- class Meta:
- model = HTSUser
- fields = ("username",'first_name','last_name')
-
-class HTSUserOptions(UserAdmin):
- form = HTSUserChangeForm
- add_form = HTSUserCreationForm
-
-class LaneLibraryInline(admin.StackedInline):
- model = Lane
- extra = 0
-
-class Library_Inline(admin.TabularInline):
- model = Library
-
-class LibraryTypeOptions(admin.ModelAdmin):
- list_display = ['name', 'is_paired_end', 'can_multiplex']
- model = LibraryType
-
-class MultiplexIndexOptions(admin.ModelAdmin):
- model = MultiplexIndex
- list_display = ['adapter_type', 'multiplex_id', 'sequence']
-
-class LibraryOptions(admin.ModelAdmin):
- class Media:
- css = {
- "all": ("css/wide_account_number.css",)
- }
-
- date_hierarchy = "creation_date"
- save_as = True
- save_on_top = True
- search_fields = (
- 'id',
- 'library_name',
- 'cell_line__cellline_name',
- 'library_species__scientific_name',
- 'library_species__common_name',
- )
- list_display = (
- 'id',
- 'library_name',
- 'index_sequence_text',
- 'affiliation',
- 'undiluted_concentration',
- 'gel_cut_size',
- 'creation_date',
- )
- list_filter = (
- 'hidden',
- 'experiment_type',
- 'library_type',
- #'cell_line',
- 'stopping_point',
- 'made_by',
- 'library_species',
- 'affiliations',
- )
- list_display_links = ('id', 'library_name',)
- fieldsets = (
- (None, {
- 'fields': (
- ('id','library_name','hidden'),
- ('library_species', 'experiment_type'),
- ('library_type', 'multiplex_id'),
- )
- }),
- ('Experiment Detail:', {
- 'fields': (('cell_line', 'replicate',),
- ('condition',),
- ('antibody', ),
- ),
- 'classes': ('collapse',),
- }),
- ('Creation Information:', {
- 'fields' : (('made_by', 'creation_date', 'stopping_point'),
- ('amplified_from_sample'),
- ('gel_cut_size', 'insert_size',
- 'undiluted_concentration'),
- ('bioanalyzer_concentration','bioanalyzer_image_url'),
- ('bioanalyzer_summary'),
- ('notes'))
- }),
- ('Library/Project Affiliation:', {
- 'fields' : (('account_number', 'affiliations'),)
- }),
- )
- inlines = [
- LaneLibraryInline,
- ]
- actions = ['action_print_library_labels']
-
- def action_print_library_labels(self, request, queryset):
- """
- Django action which prints labels for the selected set of labels from the
- Django Admin interface.
- """
-
- #Probably should ask if the user really meant to print all selected
- # libraries if the count is above X. X=10 maybe?
-
- # Grab the library template
- #FIXME: Hardcoding library template name. Not a good idea... *sigh*.
- EVIL_HARDCODED_LIBRARY_TEMPLATE_NAME = "Library"
-
- try:
- template = PrinterTemplate.objects.get(item_type__name=EVIL_HARDCODED_LIBRARY_TEMPLATE_NAME)
- except PrinterTemplate.DoesNotExist:
- self.message_user(request, "Could not find a library template with ItemType.name of '%s'" % \
- (EVIL_HARDCODED_LIBRARY_TEMPLATE_NAME))
- return
-
- # ZPL Template
- t = Template(template.template)
-
- zpl_list = []
- #Iterate over selected labels to print
- for library in queryset.all():
-
- # Django Template Context
- c = Context({'library': library})
-
- # Send rendered template to the printer that the template
- # object has been attached to in the database.
- zpl_list.append(t.render(c))
-
- print_zpl_socket(zpl_list, host=template.printer.ip_address)
-
- self.message_user(request, "%s labels printed." % (len(queryset)))
-
- action_print_library_labels.short_description = "Print Labels"
-
- def formfield_for_dbfield(self, db_field, **kwargs):
- # Override Field type
- if db_field.name in ('affiliations', 'tags'):
- kwargs['widget'] = widgets.FilteredSelectMultiple(
- db_field.verbose_name,
- (db_field.name in self.filter_vertical)
- )
- field = super(LibraryOptions, self).formfield_for_dbfield(db_field,
- **kwargs)
- # Override field attributes
- if db_field.name == "bioanalyzer_summary":
- field.widget.attrs["rows"] = "3"
- return field
-
-class SpeciesOptions(admin.ModelAdmin):
- fieldsets = (
- (None, {
- 'fields': (('scientific_name', 'common_name'),)
- }),
- )
-
-class TagOptions(admin.ModelAdmin):
- list_display = ('tag_name', 'context')
- fieldsets = (
- (None, {
- 'fields': ('tag_name', 'context')
- }),
- )
-
-admin.site.register(Library, LibraryOptions)
-admin.site.register(Affiliation, AffiliationOptions)
-admin.site.register(Antibody, AntibodyOptions)
-admin.site.register(Cellline, CelllineOptions)
-admin.site.register(Condition, ConditionOptions)
-admin.site.register(ExperimentType, ExperimentTypeOptions)
-#admin.site.register(HTSUser, HTSUserOptions)
-admin.site.register(LibraryType, LibraryTypeOptions)
-admin.site.register(MultiplexIndex, MultiplexIndexOptions)
-admin.site.register(Species, SpeciesOptions)
-#admin.site.register(Tag, TagOptions)
+++ /dev/null
-from django.conf import settings
-from django.contrib.auth.backends import ModelBackend
-from django.core.exceptions import ImproperlyConfigured
-from django.db.models import get_model
-
-import sys
-
-class HTSUserModelBackend(ModelBackend):
- def authenticate(self, username=None, password=None):
- try:
- user = self.user_class.objects.get(username=username)
- if user.check_password(password):
- return user
- #except self.user_class.DoesNotExist:
- except Exception, e:
- print >>sys.stderr, e
- return None
-
- def get_user(self, user_id):
- try:
- return self.user_class.objects.get(pk=user_id)
- #except self.user_class.DoesNotExist:
- except Exception, e:
- print >>sys.stderr, e
- return None
-
- @property
- def user_class(self):
- if not hasattr(self, '_user_class'):
- self._user_class = get_model(*settings.CUSTOM_USER_MODEL.split('.',2))
- if not self._user_class:
- raise ImproperlyConfigured('Could not get custom user model')
- return self._user_class
-
+++ /dev/null
-import django
-from django.contrib.admin.views.main import ChangeList
-
-class HTSChangeList(ChangeList):
- def __init__(self, request, model, list_filter, search_fields,
- list_per_page, model_admin, extra_filters=None):
- """Simplification of the django model filter view
-
- The new parameter "extra_filter" should be a mapping
- of that will be passed as keyword arguments to
- queryset.filter
- """
- self.extra_filters = extra_filters
-
- args = {
- 'request': request, #request
- 'model': model, #model
- 'list_display': [], # list_display
- 'list_display_links': None, # list_display_links
- 'list_filter': list_filter, #list_filter
- 'date_hierarchy': None, # date_hierarchy
- 'search_fields': search_fields, #search_fields
- 'list_select_related': None, # list_select_related,
- 'list_per_page': list_per_page, #list_per_page
- 'list_editable': None, # list_editable
- 'model_admin': model_admin #model_admin
- }
- if django.VERSION[0] >= 1 and django.VERSION[1] >= 4:
- args['list_max_show_all'] = 20000, #list_max_show_all
- super(HTSChangeList, self).__init__(**args)
-
- self.is_popup = False
- # I removed to field in the first version
-
- self.multi_page = True
- self.can_show_all = False
-
- def get_queryset(self, request=None):
- args = {}
- if django.VERSION[0] >= 1 and django.VERSION[1] >= 4:
- args['request'] = request #list_max_show_all
-
- qs = super(HTSChangeList, self).get_query_set(**args)
- if self.extra_filters:
- new_qs = qs.filter(**self.extra_filters)
- if new_qs is not None:
- qs = new_qs
- return qs
+++ /dev/null
-[
- {
- "model": "samples.Cellline",
- "pk": 1,
- "fields": {
- "cellline_name": "Unknown",
- "notes": "Unknown"
- }
- },
- {
- "model": "samples.Cellline",
- "pk": 2,
- "fields": {
- "cellline_name": "C2C12",
- "notes": ""
- }
- },
- {
- "model": "samples.Cellline",
- "pk": 3,
- "fields": {
- "cellline_name": "C2C12 60 hrs",
- "notes": "Unknown"
- }
- },
- { "pk": 1, "model": "samples.Condition",
- "fields": {
- "condition_name": "Unknown",
- "nickname": "",
- "notes": "Unknown"
- }
- },
- {
- "model": "samples.LibraryType",
- "pk": 1,
- "fields": {
- "name": "Single End (non-multiplexed)",
- "can_multiplex": false,
- "is_paired_end": false
- }
- },
- {
- "model": "samples.LibraryType",
- "pk": 2,
- "fields": {
- "name": "Paired End (non-multiplexed)",
- "can_multiplex": false,
- "is_paired_end": true
- }
- },
- {
- "model": "samples.LibraryType",
- "pk": 5,
- "fields": {
- "name": "Barcoded Illumina",
- "can_multiplex": true,
- "is_paired_end": true
- }
- },
- {
- "model": "samples.LibraryType",
- "pk": 7,
- "fields": {
- "name": "Barcoded Small RNA",
- "can_multiplex": true,
- "is_paired_end": true
- }
- },
- {
- "model": "samples.LibraryType",
- "pk": 8,
- "fields": {
- "name": "Nextera",
- "can_multiplex": true,
- "is_paired_end": true
- }
- },
- {
- "model": "samples.LibraryType",
- "pk": 9,
- "fields": {
- "name": "Dual Index Illumina",
- "can_multiplex": true,
- "is_paired_end": true
- }
- },
- {
- "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": 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": 6,
- "fields": {
- "scientific_name": "Arabidopsis thaliana"
- }
- },
- {
- "model": "samples.Species",
- "pk": 8,
- "fields": {
- "scientific_name": "Homo sapiens",
- "common_name": "human"
- }
- },
- {
- "model": "samples.Species",
- "pk": 9,
- "fields": {
- "scientific_name": "Mus musculus",
- "common_name": "mouse"
- }
- },
- {
- "model": "samples.Species",
- "pk": 10,
- "fields": {
- "scientific_name": "Strongylocentrotus purpuratus"
- }
- },
- {
- "pk": 1,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 1,
- "adapter_type": 8,
- "sequence": "ATCACG"
- }
- },
- {
- "pk": 2,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 2,
- "adapter_type": 8,
- "sequence": "CGATGT"
- }
- },
- {
- "pk": 3,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 3,
- "adapter_type": 8,
- "sequence": "TTAGGC"
- }
- },
- {
- "pk": 4,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 4,
- "adapter_type": 8,
- "sequence": "TGACCA"
- }
- },
- {
- "pk": 5,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 5,
- "adapter_type": 8,
- "sequence": "ACAGTG"
- }
- },
- {
- "pk": 6,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 6,
- "adapter_type": 8,
- "sequence": "GCCAAT"
- }
- },
- {
- "pk": 7,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 7,
- "adapter_type": 8,
- "sequence": "CAGATC"
- }
- },
- {
- "pk": 8,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 8,
- "adapter_type": 8,
- "sequence": "ACTTGA"
- }
- },
- {
- "pk": 9,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 9,
- "adapter_type": 8,
- "sequence": "GATCAG"
- }
- },
- {
- "pk": 10,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 10,
- "adapter_type": 8,
- "sequence": "TAGCTT"
- }
- },
- {
- "pk": 11,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 11,
- "adapter_type": 8,
- "sequence": "GGCTAC"
- }
- },
- {
- "pk": 12,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 12,
- "adapter_type": 8,
- "sequence": "CTTGTA"
- }
- },
- {
- "pk": 13,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 1,
- "adapter_type": 7,
- "sequence": "ATCACG"
- }
- },
- {
- "pk": 14,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 2,
- "adapter_type": 7,
- "sequence": "CGATGT"
- }
- },
- {
- "pk": 15,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 3,
- "adapter_type": 7,
- "sequence": "TTAGGC"
- }
- },
- {
- "pk": 16,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 4,
- "adapter_type": 7,
- "sequence": "TGACCA"
- }
- },
- {
- "pk": 17,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 5,
- "adapter_type": 7,
- "sequence": "ACAGTG"
- }
- },
- {
- "pk": 18,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 6,
- "adapter_type": 7,
- "sequence": "GCCAAT"
- }
- },
- {
- "pk": 19,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 7,
- "adapter_type": 7,
- "sequence": "CAGATC"
- }
- },
- {
- "pk": 20,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 8,
- "adapter_type": 7,
- "sequence": "ACTTGA"
- }
- },
- {
- "pk": 21,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 9,
- "adapter_type": 7,
- "sequence": "GATCAG"
- }
- },
- {
- "pk": 22,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 10,
- "adapter_type": 7,
- "sequence": "TAGCTT"
- }
- },
- {
- "pk": 23,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 11,
- "adapter_type": 7,
- "sequence": "GGCTAC"
- }
- },
- {
- "pk": 24,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 12,
- "adapter_type": 7,
- "sequence": "CTTGTA"
- }
- },
- {
- "pk": 25,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 13,
- "adapter_type": 7,
- "sequence": "AGTCAA"
- }
- },
- {
- "pk": 26,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 14,
- "adapter_type": 7,
- "sequence": "AGTTCC"
- }
- },
- {
- "pk": 27,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 15,
- "adapter_type": 7,
- "sequence": "ATGTCA"
- }
- },
- {
- "pk": 28,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 16,
- "adapter_type": 7,
- "sequence": "CCGTCC"
- }
- },
- {
- "pk": 29,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 17,
- "adapter_type": 7,
- "sequence": "GTAGAG"
- }
- },
- {
- "pk": 30,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 18,
- "adapter_type": 7,
- "sequence": "GTCCGC"
- }
- },
- {
- "pk": 31,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 19,
- "adapter_type": 7,
- "sequence": "GTGAAA"
- }
- },
- {
- "pk": 32,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 20,
- "adapter_type": 7,
- "sequence": "GTGGCC"
- }
- },
- {
- "pk": 33,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 21,
- "adapter_type": 7,
- "sequence": "GTTTCG"
- }
- },
- {
- "pk": 34,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 22,
- "adapter_type": 7,
- "sequence": "CGTACG"
- }
- },
- {
- "pk": 35,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 23,
- "adapter_type": 7,
- "sequence": "GAGTGG"
- }
- },
- {
- "pk": 36,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 24,
- "adapter_type": 7,
- "sequence": "GGTAGC"
- }
- },
- {
- "pk": 37,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 25,
- "adapter_type": 7,
- "sequence": "ACTGAT"
- }
- },
- {
- "pk": 38,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 26,
- "adapter_type": 7,
- "sequence": "ATGAGC"
- }
- },
- {
- "pk": 39,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 27,
- "adapter_type": 7,
- "sequence": "ATTCCT"
- }
- },
- {
- "pk": 40,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 28,
- "adapter_type": 7,
- "sequence": "CAAAAG"
- }
- },
- {
- "pk": 41,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 29,
- "adapter_type": 7,
- "sequence": "CAACTA"
- }
- },
- {
- "pk": 42,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 30,
- "adapter_type": 7,
- "sequence": "CACCGG"
- }
- },
- {
- "pk": 43,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 31,
- "adapter_type": 7,
- "sequence": "CACGAT"
- }
- },
- {
- "pk": 44,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 32,
- "adapter_type": 7,
- "sequence": "CACTCA"
- }
- },
- {
- "pk": 45,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 33,
- "adapter_type": 7,
- "sequence": "CAGGCG"
- }
- },
- {
- "pk": 46,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 34,
- "adapter_type": 7,
- "sequence": "CATGGC"
- }
- },
- {
- "pk": 47,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 35,
- "adapter_type": 7,
- "sequence": "CATTTT"
- }
- },
- {
- "pk": 48,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 36,
- "adapter_type": 7,
- "sequence": "CCAACA"
- }
- },
- {
- "pk": 49,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 37,
- "adapter_type": 7,
- "sequence": "CGGAAT"
- }
- },
- {
- "pk": 50,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 38,
- "adapter_type": 7,
- "sequence": "CTAGCT"
- }
- },
- {
- "pk": 51,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 39,
- "adapter_type": 7,
- "sequence": "CTATAC"
- }
- },
- {
- "pk": 52,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 40,
- "adapter_type": 7,
- "sequence": "CTCAGA"
- }
- },
- {
- "pk": 53,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 41,
- "adapter_type": 7,
- "sequence": "GACGAC"
- }
- },
- {
- "pk": 54,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 42,
- "adapter_type": 7,
- "sequence": "TAATCG"
- }
- },
- {
- "pk": 55,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 43,
- "adapter_type": 7,
- "sequence": "TACAGC"
- }
- },
- {
- "pk": 56,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 44,
- "adapter_type": 7,
- "sequence": "TATAAT"
- }
- },
- {
- "pk": 57,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 45,
- "adapter_type": 7,
- "sequence": "TCATTC"
- }
- },
- {
- "pk": 58,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 46,
- "adapter_type": 7,
- "sequence": "TCCCGA"
- }
- },
- {
- "pk": 59,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 47,
- "adapter_type": 7,
- "sequence": "TCGAAG"
- }
- },
- {
- "pk": 60,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 48,
- "adapter_type": 7,
- "sequence": "TCGGCA"
- }
- },
- {
- "pk": 61,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 1,
- "adapter_type": 5,
- "sequence": "ATCACG"
- }
- },
- {
- "pk": 62,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 2,
- "adapter_type": 5,
- "sequence": "CGATGT"
- }
- },
- {
- "pk": 63,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 3,
- "adapter_type": 5,
- "sequence": "TTAGGC"
- }
- },
- {
- "pk": 64,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 4,
- "adapter_type": 5,
- "sequence": "TGACCA"
- }
- },
- {
- "pk": 65,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 5,
- "adapter_type": 5,
- "sequence": "ACAGTG"
- }
- },
- {
- "pk": 66,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 6,
- "adapter_type": 5,
- "sequence": "GCCAAT"
- }
- },
- {
- "pk": 67,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 7,
- "adapter_type": 5,
- "sequence": "CAGATC"
- }
- },
- {
- "pk": 68,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 8,
- "adapter_type": 5,
- "sequence": "ACTTGA"
- }
- },
- {
- "pk": 69,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 9,
- "adapter_type": 5,
- "sequence": "GATCAG"
- }
- },
- {
- "pk": 70,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 10,
- "adapter_type": 5,
- "sequence": "TAGCTT"
- }
- },
- {
- "pk": 71,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 11,
- "adapter_type": 5,
- "sequence": "GGCTAC"
- }
- },
- {
- "pk": 72,
- "model": "samples.MultiplexIndex",
- "fields": {
- "multiplex_id": 12,
- "adapter_type": 5,
- "sequence": "CTTGTA"
- }
- },
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N501",
- "sequence": "TAGATCGC"},
- "model": "samples.multiplexindex",
- "pk": 74
- },
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N502",
- "sequence": "CTCTCTAT"},
- "model": "samples.multiplexindex",
- "pk": 75},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N503",
- "sequence": "TATCCTCT"},
- "model": "samples.multiplexindex",
- "pk": 76},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N504",
- "sequence": "AGAGTAGA"},
- "model": "samples.multiplexindex",
- "pk": 77},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N505",
- "sequence": "GTAAGGAG"},
- "model": "samples.multiplexindex",
- "pk": 78},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N506",
- "sequence": "ACTGCATA"},
- "model": "samples.multiplexindex",
- "pk": 79},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N507",
- "sequence": "AAGGAGTA"},
- "model": "samples.multiplexindex",
- "pk": 80},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N508",
- "sequence": "CTAAGCCT"},
- "model": "samples.multiplexindex",
- "pk": 81},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N701",
- "sequence": "TAAGGCGA"},
- "model": "samples.multiplexindex",
- "pk": 82},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N702",
- "sequence": "CGTACTAG"},
- "model": "samples.multiplexindex",
- "pk": 83},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N703",
- "sequence": "AGGCAGAA"},
- "model": "samples.multiplexindex",
- "pk": 84},
- {"fields": {"adapter_type": 9, "multiplex_id": "N704", "sequence": "TCCTGA"},
- "model": "samples.multiplexindex",
- "pk": 85},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N705",
- "sequence": "GGACTCCT"},
- "model": "samples.multiplexindex",
- "pk": 86},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N706",
- "sequence": "TAGGCATG"},
- "model": "samples.multiplexindex",
- "pk": 87},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N707",
- "sequence": "CTCTCTAC"},
- "model": "samples.multiplexindex",
- "pk": 88},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N708",
- "sequence": "CAGAGAGG"},
- "model": "samples.multiplexindex",
- "pk": 89},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N709",
- "sequence": "GCTACGCT"},
- "model": "samples.multiplexindex",
- "pk": 90},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N710",
- "sequence": "CGAGGCTG"},
- "model": "samples.multiplexindex",
- "pk": 91},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N711",
- "sequence": "AAGAGGCA"},
- "model": "samples.multiplexindex",
- "pk": 92},
- {"fields": {"adapter_type": 9,
- "multiplex_id": "N712",
- "sequence": "GTAGAGGA"},
- "model": "samples.multiplexindex",
- "pk": 93}
-]
+++ /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-01T00:00:01-0800",
- "groups": [],
- "user_permissions": [],
- "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
- "email": "",
- "date_joined": "2009-01-01T00:01:01-0800"
- }
- },
- {"pk": 1, "model": "samples.affiliation",
- "fields": {
- "users": [5],
- "name": "Alice",
- "contact": "Lab Boss",
- "email": "alice@some.where.else."
- }
- },
- {"pk": 2, "model": "samples.affiliation",
- "fields": { "name": "Bob",
- "contact": "Other Lab Boss",
- "email": "bob@some.where.else"
- }
- },
- {"pk": 3, "model": "samples.affiliation",
- "fields": {
- "users": [],
- "contact": "group 3",
- "name": "affiliation 3",
- "email": "pk3@example.com"
- }
- },
- {"pk": 4, "model": "samples.affiliation",
- "fields": {
- "users": [],
- "contact": "group 4",
- "name": "affiliation 4",
- "email": "pk1@example.com"
- }
- },
- {"pk": 5, "model": "samples.affiliation",
- "fields": {
- "users": [],
- "contact": "group 5",
- "name": "affiliation 5",
- "email": "pk5@example.com"
- }
- },
- {"pk": 153, "model": "experiments.flowcell",
- "fields": {
- "paired_end": true,
- "run_date": "2009-09-11T22:12:13-0800",
- "read_length": 75,
- "notes": "",
- "advanced_run": false,
- "control_lane": 2,
- "cluster_station": 3,
- "sequencer": 2,
- "flowcell_id": "303TUAAXX"
- }
- },
- {"pk": 1193, "model": "experiments.lane",
- "fields": {
- "comment": "No change in cluster numbers, despite slight increase in pM",
- "library": "10981",
- "cluster_estimate": 129000,
- "flowcell": 153,
- "lane_number": 1,
- "pM": "8"
- }
- },
- {"pk": 1197, "model": "experiments.lane",
- "fields": {
- "comment": "stuff",
- "library": "11016",
- "cluster_estimate": 140000,
- "flowcell": 153,
- "lane_number": 5,
- "pM": "7",
- "status": 2
- }
- },
- {"pk": "10981", "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_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": [
- 2
- ],
- "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": "11016",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 325,
- "library_name": "Paired End Pfl #3 MP 7/24/9 a",
- "creation_date": "2009-08-06",
- "cell_line": 1,
- "library_species": 9,
- "library_type": 2,
- "made_by": "Lorian",
- "affiliations": [
- 3
- ],
- "replicate": 1,
- "condition": 1,
- "hidden": false,
- "stopping_point": "1Aa",
- "tags": [],
- "made_for": "",
- "amplified_from_sample": "11003",
- "notes": "7/31/2009 16:08:22\tColor: Blue",
- "undiluted_concentration": "35.5",
- "successful_pM": null,
- "experiment_type": 8,
- "antibody": null
- }
- },
- {
- "pk": "11039",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_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": [
- 1,
- 2,
- 4
- ],
- "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": "11003",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 325,
- "library_name": "Paired End Pfl #3 MP 7/24/9",
- "creation_date": "2009-08-05",
- "cell_line": 1,
- "library_species": 8,
- "library_type": 2,
- "made_by": "Lorian",
- "affiliations": [
- 4
- ],
- "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
- }
- },
- {
- "pk": "11005",
- "model": "samples.library",
- "fields": {
- "ten_nM_dilution": false,
- "gel_cut_size": 325,
- "library_name": "null cell line",
- "creation_date": "2009-08-05",
- "cell_line": null,
- "library_species": 8,
- "library_type": 2,
- "made_by": "Lorian",
- "affiliations": [
- 4
- ],
- "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
- }
- }
-]
+++ /dev/null
-import types
-import logging
-import urlparse
-from django.db import models
-from django.contrib.auth.models import User, UserManager
-from django.core import urlresolvers
-from django.db.models.signals import pre_save, post_save
-from django.db import connection
-from htsworkflow.frontend.reports.libinfopar import *
-
-logger = logging.getLogger(__name__)
-
-class Antibody(models.Model):
- antigene = models.CharField(max_length=500, db_index=True)
- # New field Aug/20/08
- # SQL to add column:
- # alter table fctracker_antibody add column "nickname" varchar(20) NULL;
- nickname = models.CharField(
- max_length=20,
- blank=True,
- null=True,
- db_index=True
- )
- catalog = models.CharField(max_length=50, blank=True, null=True)
- antibodies = models.CharField(max_length=500, db_index=True)
- source = models.CharField(max_length=500, blank=True, null=True, db_index=True)
- biology = models.TextField(blank=True, null=True)
- notes = models.TextField(blank=True, null=True)
- def __unicode__(self):
- return u'%s - %s' % (self.antigene, self.antibodies)
- class Meta:
- verbose_name_plural = "antibodies"
- ordering = ["antigene"]
-
-class Cellline(models.Model):
- cellline_name = models.CharField(max_length=100, unique=True, db_index=True)
- nickname = models.CharField(max_length=20,
- blank=True,
- null=True,
- db_index=True)
-
- notes = models.TextField(blank=True)
- def __unicode__(self):
- return unicode(self.cellline_name)
-
- class Meta:
- ordering = ["cellline_name"]
-
-class Condition(models.Model):
- condition_name = models.CharField(
- max_length=2000, unique=True, db_index=True)
- nickname = models.CharField(max_length=20,
- blank=True,
- null=True,
- db_index=True,
- verbose_name = 'Short Name')
- notes = models.TextField(blank=True)
-
- def __unicode__(self):
- return unicode(self.condition_name)
-
- class Meta:
- ordering = ["condition_name"]
-
-
-class ExperimentType(models.Model):
- name = models.CharField(max_length=50, unique=True)
-
- def __unicode__(self):
- return unicode(self.name)
-
-class Tag(models.Model):
- tag_name = models.CharField(max_length=100, db_index=True,blank=False,null=False)
- TAG_CONTEXT = (
- #('Antibody','Antibody'),
- #('Cellline', 'Cellline'),
- #('Condition', 'Condition'),
- ('Library', 'Library'),
- ('ANY','ANY'),
- )
- context = models.CharField(max_length=50,
- choices=TAG_CONTEXT, default='Library')
-
- def __unicode__(self):
- return u'%s' % (self.tag_name)
-
- class Meta:
- ordering = ["context","tag_name"]
-
-class Species(models.Model):
- scientific_name = models.CharField(max_length=256,
- unique=False,
- db_index=True
- )
- common_name = models.CharField(max_length=256, blank=True)
- #use_genome_build = models.CharField(max_length=100, blank=False, null=False)
-
- def __unicode__(self):
- return u'%s (%s)' % (self.scientific_name, self.common_name)
-
- class Meta:
- verbose_name_plural = "species"
- ordering = ["scientific_name"]
-
- @models.permalink
- def get_absolute_url(self):
- return ('htsworkflow.frontend.samples.views.species', [str(self.id)])
-
-class Affiliation(models.Model):
- name = models.CharField(max_length=256, db_index=True, verbose_name='Name')
- contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name')
- email = models.EmailField(null=True,blank=True)
- users = models.ManyToManyField('HTSUser', null=True, blank=True)
- users.admin_order_field = "username"
-
- def __unicode__(self):
- str = unicode(self.name)
- if self.contact is not None and len(self.contact) > 0:
- str += u' ('+self.contact+u')'
- return str
-
- def Users(self):
- users = self.users.all().order_by('username')
- return ", ".join([unicode(a) for a in users ])
-
- class Meta:
- ordering = ["name","contact"]
- unique_together = (("name", "contact"),)
-
-class LibraryType(models.Model):
- name = models.CharField(max_length=255, unique=True,
- verbose_name="Adapter Type")
- is_paired_end = models.BooleanField(default=True,
- help_text="can you do a paired end run with this adapter")
- can_multiplex = models.BooleanField(default=True,
- help_text="Does this adapter provide multiplexing?")
-
- def __unicode__(self):
- return unicode(self.name)
-
- class Meta:
- ordering = ["-id"]
-
-
-class MultiplexIndex(models.Model):
- """Map adapter types to the multiplex sequence"""
- adapter_type = models.ForeignKey(LibraryType)
- multiplex_id = models.CharField(max_length=6, null=False)
- sequence = models.CharField(max_length=12, blank=True, null=True)
-
- class Meta:
- verbose_name_plural = "multiplex indicies"
- unique_together = ('adapter_type', 'multiplex_id')
-
-class Library(models.Model):
- id = models.CharField(max_length=10, primary_key=True)
- library_name = models.CharField(max_length=100, unique=True)
- library_species = models.ForeignKey(Species)
- hidden = models.BooleanField(default=False)
- account_number = models.CharField(max_length=100, null=True, blank=True)
- cell_line = models.ForeignKey(Cellline, blank=True, null=True,
- verbose_name="Background")
- condition = models.ForeignKey(Condition, blank=True, null=True)
- antibody = models.ForeignKey(Antibody,blank=True,null=True)
- affiliations = models.ManyToManyField(
- Affiliation,related_name='library_affiliations',null=True)
- tags = models.ManyToManyField(Tag,related_name='library_tags',
- blank=True,null=True)
- REPLICATE_NUM = [(x,x) for x in range(1,7)]
- replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM,
- blank=True,null=True)
- experiment_type = models.ForeignKey(ExperimentType)
- library_type = models.ForeignKey(LibraryType, blank=True, null=True,
- verbose_name="Adapter Type")
- multiplex_id = models.CharField(max_length=128,
- blank=True, null=True,
- verbose_name="Index ID")
- creation_date = models.DateField(blank=True, null=True)
- made_for = models.CharField(max_length=50, blank=True,
- verbose_name='ChIP/DNA/RNA Made By')
- made_by = models.CharField(max_length=50, blank=True, default="Lorian")
-
- PROTOCOL_END_POINTS = (
- ('?', 'Unknown'),
- ('Sample', 'Raw sample'),
- ('Progress', 'In progress'),
- ('1A', 'Ligation, then gel'),
- ('PCR', 'Ligation, then PCR'),
- ('1Ab', 'Ligation, PCR, then gel'),
- ('1Ac', 'Ligation, gel, then 12x PCR'),
- ('1Aa', 'Ligation, gel, then 18x PCR'),
- ('2A', 'Ligation, PCR, gel, PCR'),
- ('Done', 'Completed'),
- )
- PROTOCOL_END_POINTS_DICT = dict(PROTOCOL_END_POINTS)
- stopping_point = models.CharField(max_length=25,
- choices=PROTOCOL_END_POINTS,
- default='Done')
-
- amplified_from_sample = models.ForeignKey('self',
- related_name='amplified_into_sample',
- blank=True, null=True)
-
- undiluted_concentration = models.DecimalField("Concentration",
- max_digits=5, decimal_places=2, blank=True, null=True,
- help_text=u"Undiluted concentration (ng/\u00b5l)")
- # note \u00b5 is the micro symbol in unicode
- successful_pM = models.DecimalField(max_digits=9,
- decimal_places=1, blank=True, null=True)
- ten_nM_dilution = models.BooleanField(default=False)
- gel_cut_size = models.IntegerField(default=225, blank=True, null=True)
- insert_size = models.IntegerField(blank=True, null=True)
- notes = models.TextField(blank=True)
-
- bioanalyzer_summary = models.TextField(blank=True,default="")
- bioanalyzer_concentration = models.DecimalField(max_digits=5,
- decimal_places=2, blank=True, null=True,
- help_text=u"(ng/\u00b5l)")
- bioanalyzer_image_url = models.URLField(blank=True,default="")
-
- def __unicode__(self):
- return u'#%s: %s' % (self.id, self.library_name)
-
- class Meta:
- verbose_name_plural = "libraries"
- #ordering = ["-creation_date"]
- ordering = ["-id"]
-
- def antibody_name(self):
- str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.label+'</a>'
- return str
- antibody_name.allow_tags = True
-
- def organism(self):
- return self.library_species.common_name
-
- def index_sequences(self):
- """Return a dictionary of multiplex index id to sequence
- Return None if the library can't multiplex,
-
- """
- if self.library_type is None:
- return None
- if not self.library_type.can_multiplex:
- return None
- if self.multiplex_id is None or len(self.multiplex_id) == 0:
- return 'Err: id empty'
- sequences = {}
- multiplex_expressions = self.multiplex_id.split(',')
- for multiplex_term in multiplex_expressions:
- pairs = multiplex_term.split('-')
- if len(pairs) == 1:
- key = pairs[0]
- seq = self._lookup_index(pairs[0])
- elif len(pairs) == 2:
- key = pairs[0] + '-' + pairs[1]
- seq0 = self._lookup_index(pairs[0])
- seq1 = self._lookup_index(pairs[1])
- if seq0 is None or seq1 is None:
- seq = None
- else:
- seq = seq0 + '-' + seq1
- else:
- raise RuntimeError("Too many - seperated sequences")
- if seq is None:
- seq = 'Err: index not found'
- sequences[key] = seq
- return sequences
-
- def _lookup_index(self, multiplex_id):
- try:
- multiplex = MultiplexIndex.objects.get(
- adapter_type = self.library_type.id,
- multiplex_id = multiplex_id)
- return multiplex.sequence
- except MultiplexIndex.DoesNotExist, e:
- return None
-
- def index_sequence_text(self, seperator=' '):
- """Return formatted multiplex index sequences"""
- sequences = self.index_sequences()
- if sequences is None:
- return ""
- if type(sequences) in types.StringTypes:
- return sequences
- multiplex_ids = sequences.keys()
- multiplex_ids.sort()
- return seperator.join(( "%s:%s" %(i,sequences[i]) for i in multiplex_ids))
- index_sequence_text.short_description = "Index"
-
-
- def affiliation(self):
- affs = self.affiliations.all().order_by('name')
- tstr = ''
- ar = []
- for t in affs:
- ar.append(t.__unicode__())
- return '%s' % (", ".join(ar))
-
- def is_archived(self):
- """
- returns True if archived else False
- """
- if self.longtermstorage_set.count() > 0:
- return True
- else:
- return False
-
- def stopping_point_name(self):
- end_points = Library.PROTOCOL_END_POINTS_DICT
- name = end_points.get(self.stopping_point, None)
- if name is None:
- name = "Lookup Error"
- logger.error("protocol stopping point in database didn't match names in library model")
- return name
-
-
- def libtags(self):
- affs = self.tags.all().order_by('tag_name')
- ar = []
- for t in affs:
- ar.append(t.__unicode__())
- return u'%s' % ( ", ".join(ar))
-
- def DataRun(self):
- str ='<a target=_self href="/admin/experiments/datarun/?q='+self.id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>'
- return str
- DataRun.allow_tags = True
-
- def aligned_m_reads(self):
- return getLibReads(self.id)
-
- def aligned_reads(self):
- res = getLibReads(self.id)
-
- # Check data sanity
- if res[2] != "OK":
- return u'<div style="border:solid red 2px">'+res[2]+'</div>'
-
- rc = "%1.2f" % (res[1]/1000000.0)
- # Color Scheme: green is more than 10M, blue is more than 5M, orange is more than 3M and red is less. For RNAseq, all those thresholds should be doubled
- if res[0] > 0:
- bgcolor = '#ff3300' # Red
- rc_thr = [10000000,5000000,3000000]
- if self.experiment_type == 'RNA-seq':
- rc_thr = [20000000,10000000,6000000]
-
- if res[1] > rc_thr[0]:
- bgcolor = '#66ff66' # Green
- else:
- if res[1] > rc_thr[1]:
- bgcolor ='#00ccff' # Blue
- else:
- if res[1] > rc_thr[2]:
- bgcolor ='#ffcc33' # Orange
- tstr = '<div style="background-color:'+bgcolor+';color:black">'
- tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
- tstr += '</div>'
- else: tstr = 'not processed yet'
- return tstr
- aligned_reads.allow_tags = True
-
- def public(self):
- SITE_ROOT = '/'
- summary_url = self.get_absolute_url()
- return '<a href="%s">S</a>' % (summary_url,)
- public.allow_tags = True
-
- @models.permalink
- def get_absolute_url(self):
- return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.id)])
-
- def get_admin_url(self):
- return urlresolvers.reverse('admin:samples_library_change',
- args=(self.id,))
-
-class HTSUser(User):
- """
- Provide some site-specific customization for the django user class
- """
- #objects = UserManager()
-
- class Meta:
- ordering = ['first_name', 'last_name', 'username']
-
- def admin_url(self):
- return '/admin/%s/%s/%d' % (self._meta.app_label, self._meta.module_name, self.id)
-
- def __unicode__(self):
- #return unicode(self.username) + u" (" + unicode(self.get_full_name()) + u")"
- return unicode(self.get_full_name()) + u' (' + unicode(self.username) + ')'
-
-def HTSUserInsertID(sender, instance, **kwargs):
- """
- Force addition of HTSUsers when someone just modifies the auth_user object
- """
- u = HTSUser.objects.filter(pk=instance.id)
- if len(u) == 0:
- cursor = connection.cursor()
- cursor.execute('INSERT INTO samples_htsuser (user_ptr_id) VALUES (%s);' % (instance.id,))
- cursor.close()
-
-post_save.connect(HTSUserInsertID, sender=User)
+++ /dev/null
-from django.conf import settings
-
-import glob
-import os
-import re
-
-s_paren = re.compile("^\w+")
-
-def get_flowcell_result_dict(flowcell_id):
- """
- returns a dictionary following the following pattern for
- a given flowcell_id:
-
-
- d['C1-33']['summary'] # Summary.htm file path
- d['C1-33']['eland_results'][5] # C1-33 lane 5 file eland results file path
- d['C1-33']['run_xml'] # run_*.xml file path
- d['C1-33']['scores'] # scores.tar.gz file path
- """
- flowcell_id = flowcell_id.strip()
-
- d = {}
-
- ################################
- # Flowcell Directory
- fc_dir = glob.glob(os.path.join(settings.RESULT_HOME_DIR, flowcell_id))
-
- # Not found
- if len(fc_dir) == 0:
- return None
-
- # No duplicates!
- assert len(fc_dir) <= 1
-
- # Found fc dir
- fc_dir = fc_dir[0]
-
- ################################
- # C#-## dirs
- c_dir_list = glob.glob(os.path.join(fc_dir, 'C*'))
-
- # Not found
- if len(c_dir_list) == 0:
- return d
-
- for c_dir_path in c_dir_list:
- summary_file = glob.glob(os.path.join(c_dir_path, 'Summary.htm'))
- pathdir, c_dir = os.path.split(c_dir_path)
-
- # Create sub-dictionary
- d[c_dir] = {}
-
-
- ###############################
- # Summary.htm file
-
- # Not found
- if len(summary_file) == 0:
- d[c_dir]['summary'] = None
-
- # Found
- else:
- # No duplicates!
- assert len(summary_file) == 1
-
- summary_file = summary_file[0]
- d[c_dir]['summary'] = summary_file
-
- ###############################
- # Result files
-
- d[c_dir]['eland_results'] = {}
-
- result_filepaths = glob.glob(os.path.join(c_dir_path, 's_*_eland_*'))
-
- for filepath in result_filepaths:
-
- junk, result_name = os.path.split(filepath)
-
- #lanes 1-8, single digit, therefore s_#; # == index 2
- lane = int(result_name[2])
- d[c_dir]['eland_results'][lane] = filepath
-
- ###############################
- # run*.xml file
- run_xml_filepath = glob.glob(os.path.join(c_dir_path, 'run_*.xml'))
-
- if len(run_xml_filepath) == 0:
- d[c_dir]['run_xml'] = None
- else:
- # No duplicates
- assert len(run_xml_filepath) == 1
-
- d[c_dir]['run_xml'] = run_xml_filepath[0]
-
- ###############################
- # scores.tar.gz
- # restrict to only compressed files, so in case there are *.md5 files
- # we don't get confused.
- scores_filepath = []
- for pattern in ['scores*.tar.bz2', 'scores*.tar.gz', 'scores*.tgz']:
- scores_filepath += glob.glob(os.path.join(c_dir_path, pattern))
-
- if len(scores_filepath) == 0:
- d[c_dir]['scores'] = None
- else:
- # No duplicates
- assert len(scores_filepath) == 1
-
- d[c_dir]['scores'] = scores_filepath[0]
-
- return d
-
-
-def cn_mTobp(cn_m):
- """
- Converts CN-M (i.e. C1-33, C1-26, C4-28) cycle information into
- number of base pairs.
- """
- pass
-
-
+++ /dev/null
-import datetime
-
-try:
- import json
-except ImportError, e:
- import simplejson as json
-
-from django.test import TestCase
-from django.test.utils import setup_test_environment, \
- teardown_test_environment
-from django.db import connection
-from django.conf import settings
-
-from htsworkflow.frontend.samples.models import \
- Affiliation, \
- ExperimentType, \
- Species, \
- Library
-
-from htsworkflow.frontend.samples.views import \
- library_dict, \
- library_json
-
-from htsworkflow.frontend.auth import apidata
-from htsworkflow.util.conversion import unicode_or_none
-from htsworkflow.util.ethelp import validate_xhtml
-
-class LibraryTestCase(TestCase):
- fixtures = ['initial_data.json',
- 'woldlab.json',
- 'test_samples.json']
-
- def setUp(self):
- create_db(self)
-
- def testOrganism(self):
- self.assertEquals(self.library_10001.organism(), 'human')
-
- def testAffiliations(self):
- self.library_10001.affiliations.add(self.affiliation_alice)
- self.library_10002.affiliations.add(
- self.affiliation_alice,
- self.affiliation_bob
- )
- self.failUnless(len(self.library_10001.affiliations.all()), 1)
- self.failUnless(self.library_10001.affiliation(), 'Alice')
-
- 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 = ['initial_data.json',
- 'woldlab.json',
- 'test_samples.json']
-
- def test_library_info(self):
- for lib in Library.objects.all():
- lib_dict = library_dict(lib.id)
- url = '/samples/library/%s/json' % (lib.id,)
- lib_response = self.client.get(url, apidata)
- 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 "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['cell_line_id'], lib.cell_line_id)
- self.failUnlessEqual(d['cell_line'], unicode_or_none(lib.cell_line))
- self.failUnlessEqual(d['experiment_type'], lib.experiment_type.name)
- self.failUnlessEqual(d['experiment_type_id'], lib.experiment_type_id)
- self.failUnlessEqual(d['gel_cut_size'], lib.gel_cut_size)
- self.failUnlessEqual(d['hidden'], lib.hidden)
- self.failUnlessEqual(d['id'], lib.id)
- self.failUnlessEqual(d['insert_size'], lib.insert_size)
- 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))
- # some specific tests
- if lib.id == '10981':
- # test a case where there is no known status
- lane_set = {u'status': u'Unknown',
- u'paired_end': True,
- u'read_length': 75,
- u'lane_number': 1,
- u'lane_id': 1193,
- u'flowcell': u'303TUAAXX',
- u'status_code': None}
- self.failUnlessEqual(len(d['lane_set']), 1)
- self.failUnlessEqual(d['lane_set'][0], lane_set)
- elif lib.id == '11016':
- # test a case where there is a status
- lane_set = {u'status': 'Good',
- u'paired_end': True,
- u'read_length': 75,
- u'lane_number': 5,
- u'lane_id': 1197,
- u'flowcell': u'303TUAAXX',
- u'status_code': 2}
- self.failUnlessEqual(len(d['lane_set']), 1)
- self.failUnlessEqual(d['lane_set'][0], lane_set)
-
-
- def test_invalid_library_json(self):
- """
- Make sure we get a 404 if we request an invalid library id
- """
- response = self.client.get('/samples/library/nottheone/json', apidata)
- self.failUnlessEqual(response.status_code, 404)
-
-
- def test_invalid_library(self):
- response = self.client.get('/library/nottheone/')
- self.failUnlessEqual(response.status_code, 404)
-
-
- def test_library_no_key(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, 403)
- response = self.client.get('/samples/library/10981/json', apidata)
- self.failUnlessEqual(response.status_code, 200)
-
- def test_library_rdf(self):
- import RDF
- from htsworkflow.util.rdfhelp import get_model, \
- dump_model, \
- fromTypedNode, \
- load_string_into_model, \
- rdfNS, \
- libraryOntology
- model = get_model()
-
- response = self.client.get('/library/10981/')
- self.assertEqual(response.status_code, 200)
- content = response.content
- load_string_into_model(model, 'rdfa', content)
-
- body = """prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
- prefix libns: <http://jumpgate.caltech.edu/wiki/LibraryOntology#>
-
- select ?library ?name ?library_id ?gel_cut ?made_by
- where {
- ?library a libns:library ;
- libns:name ?name ;
- libns:library_id ?library_id ;
- libns:gel_cut ?gel_cut ;
- libns:made_by ?made_by
- }"""
- query = RDF.SPARQLQuery(body)
- for r in query.execute(model):
- self.assertEqual(fromTypedNode(r['library_id']), u'10981')
- self.assertEqual(fromTypedNode(r['name']),
- u'Paired End Multiplexed Sp-BAC')
- self.assertEqual(fromTypedNode(r['gel_cut']), 400)
- self.assertEqual(fromTypedNode(r['made_by']), u'Igor')
-
- state = validate_xhtml(content)
- if state is not None:
- self.assertTrue(state)
-
- # validate a library page.
- from htsworkflow.util.rdfhelp import add_default_schemas
- from htsworkflow.util.rdfinfer import Infer
- add_default_schemas(model)
- inference = Infer(model)
- errmsgs = list(inference.run_validation())
- self.assertEqual(len(errmsgs), 0)
-
- def test_library_index_rdfa(self):
- from htsworkflow.util.rdfhelp import \
- add_default_schemas, get_model, load_string_into_model, \
- dump_model
- from htsworkflow.util.rdfinfer import Infer
-
- model = get_model()
- add_default_schemas(model)
- inference = Infer(model)
-
- response = self.client.get('/library/')
- self.assertEqual(response.status_code, 200)
- load_string_into_model(model, 'rdfa', response.content)
-
- errmsgs = list(inference.run_validation())
- self.assertEqual(len(errmsgs), 0)
-
- body = """prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
- prefix libns: <http://jumpgate.caltech.edu/wiki/LibraryOntology#>
-
- select ?library ?library_id ?name ?species ?species_name
- where {
- ?library a libns:Library .
- OPTIONAL { ?library libns:library_id ?library_id . }
- OPTIONAL { ?library libns:species ?species .
- ?species libns:species_name ?species_name . }
- OPTIONAL { ?library libns:name ?name . }
- }"""
- bindings = set(['library', 'library_id', 'name', 'species', 'species_name'])
- query = RDF.SPARQLQuery(body)
- count = 0
- for r in query.execute(model):
- count += 1
- for name, value in r.items():
- self.assertTrue(name in bindings)
- self.assertTrue(value is not None)
-
- self.assertEqual(count, len(Library.objects.filter(hidden=False)))
-
- state = validate_xhtml(response.content)
- if state is not None: self.assertTrue(state)
-
-
-# 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.
-def create_db(obj):
- obj.species_human = Species.objects.get(pk=8)
- obj.experiment_rna_seq = ExperimentType.objects.get(pk=4)
- obj.affiliation_alice = Affiliation.objects.get(pk=1)
- obj.affiliation_bob = Affiliation.objects.get(pk=2)
-
- Library.objects.all().delete()
- obj.library_10001 = Library(
- id = "10001",
- library_name = 'C2C12 named poorly',
- library_species = obj.species_human,
- experiment_type = obj.experiment_rna_seq,
- creation_date = datetime.datetime.now(),
- made_for = 'scientist unit 2007',
- made_by = 'microfludics system 7321',
- stopping_point = '2A',
- undiluted_concentration = '5.01',
- hidden = False,
- )
- obj.library_10001.save()
- obj.library_10002 = Library(
- id = "10002",
- library_name = 'Worm named poorly',
- library_species = obj.species_human,
- experiment_type = obj.experiment_rna_seq,
- creation_date = datetime.datetime.now(),
- made_for = 'scientist unit 2007',
- made_by = 'microfludics system 7321',
- stopping_point = '2A',
- undiluted_concentration = '5.01',
- hidden = False,
- )
- obj.library_10002.save()
-
-try:
- import RDF
- HAVE_RDF = True
-
- rdfNS = RDF.NS("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
- xsdNS = RDF.NS("http://www.w3.org/2001/XMLSchema#")
- libNS = RDF.NS("http://jumpgate.caltech.edu/wiki/LibraryOntology#")
-except ImportError,e:
- HAVE_RDF = False
-
-
-class TestRDFaLibrary(TestCase):
- fixtures = ['initial_data.json',
- 'woldlab.json',
- 'test_samples.json']
-
- def test_parse_rdfa(self):
- model = get_rdf_memory_model()
- parser = RDF.Parser(name='rdfa')
- url = '/library/10981/'
- lib_response = self.client.get(url)
- self.failIfEqual(len(lib_response.content), 0)
-
- parser.parse_string_into_model(model,
- lib_response.content,
- 'http://localhost'+url)
- # http://jumpgate.caltech.edu/wiki/LibraryOntology#affiliation>
- self.check_literal_object(model, ['Bob'], p=libNS['affiliation'])
- self.check_literal_object(model, ['Multiplexed'], p=libNS['experiment_type'])
- self.check_literal_object(model, ['400'], p=libNS['gel_cut'])
- self.check_literal_object(model, ['Igor'], p=libNS['made_by'])
- self.check_literal_object(model, ['Paired End Multiplexed Sp-BAC'], p=libNS['name'])
- self.check_literal_object(model, ['Drosophila melanogaster'], p=libNS['species_name'])
-
- self.check_uri_object(model,
- [u'http://localhost/lane/1193'],
- p=libNS['has_lane'])
-
- fc_uri = RDF.Uri('http://localhost/flowcell/303TUAAXX/')
- self.check_literal_object(model,
- [u"303TUAAXX"],
- s=fc_uri, p=libNS['flowcell_id'])
-
- def check_literal_object(self, model, values, s=None, p=None, o=None):
- statements = list(model.find_statements(
- RDF.Statement(s,p,o)))
- self.failUnlessEqual(len(statements), len(values),
- "Couln't find %s %s %s" % (s,p,o))
- for s in statements:
- self.failUnless(s.object.literal_value['string'] in values)
-
-
- def check_uri_object(self, model, values, s=None, p=None, o=None):
- statements = list(model.find_statements(
- RDF.Statement(s,p,o)))
- self.failUnlessEqual(len(statements), len(values),
- "Couln't find %s %s %s" % (s,p,o))
- for s in statements:
- self.failUnless(unicode(s.object.uri) in values)
-
-
-
-def get_rdf_memory_model():
- storage = RDF.MemoryStorage()
- model = RDF.Model(storage)
- return model
-
-def suite():
- from unittest import TestSuite, defaultTestLoader
- suite = TestSuite()
- suite.addTests(defaultTestLoader.loadTestsFromTestCase(LibraryTestCase))
- suite.addTests(defaultTestLoader.loadTestsFromTestCase(SampleWebTestCase))
- suite.addTests(defaultTestLoader.loadTestsFromTestCase(TestRDFaLibrary))
- return suite
-
-if __name__ == "__main__":
- from unittest import main
- main(defaultTest="suite")
+++ /dev/null
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns('',
- url(r"^library/(?P<library_id>\w+)/json", 'htsworkflow.frontend.samples.views.library_json'),
- url(r"^species/(?P<species_id>\w+)/json", 'htsworkflow.frontend.samples.views.species_json'),
- url(r"^species/(?P<species_id>\w+)", 'htsworkflow.frontend.samples.views.species'),
- url(r"^antibody/$", 'htsworkflow.frontend.samples.views.antibodies'),
-)
+++ /dev/null
-# Create your views here.
-import StringIO
-import logging
-import os
-import sys
-
-try:
- import json
-except ImportError, e:
- import simplejson as json
-
-from django.views.decorators.csrf import csrf_exempt
-from django.core.exceptions import ObjectDoesNotExist
-from django.http import HttpResponse, HttpResponseRedirect, Http404
-from django.shortcuts import render_to_response, get_object_or_404
-from django.template import RequestContext
-from django.template.loader import get_template
-from django.contrib.auth.decorators import login_required
-from django.conf import settings
-
-from htsworkflow.frontend.auth import require_api_key
-from htsworkflow.frontend.experiments.models import FlowCell, Lane, LANE_STATUS_MAP
-from htsworkflow.frontend.experiments.admin import LaneOptions
-from htsworkflow.frontend.samples.changelist import HTSChangeList
-from htsworkflow.frontend.samples.models import Antibody, Library, Species, HTSUser
-from htsworkflow.frontend.samples.admin import LibraryOptions
-from htsworkflow.frontend.samples.results import get_flowcell_result_dict
-from htsworkflow.frontend.bcmagic.forms import BarcodeMagicForm
-from htsworkflow.pipelines import runfolder
-from htsworkflow.pipelines.eland import ResultLane
-from htsworkflow.pipelines.samplekey import SampleKey
-from htsworkflow.util.conversion import unicode_or_none, parse_flowcell_id
-from htsworkflow.util import makebed
-from htsworkflow.util import opener
-
-
-
-LANE_LIST = [1,2,3,4,5,6,7,8]
-SAMPLES_CONTEXT_DEFAULTS = {
- 'app_name': 'Flowcell/Library Tracker',
- 'bcmagic': BarcodeMagicForm()
-}
-
-LOGGER = logging.getLogger(__name__)
-
-def count_lanes(lane_set):
- single = 0
- paired = 1
- short_read = 0
- medium_read = 1
- long_read = 2
- counts = [[0,0,0,],[0,0,0]]
-
- for lane in lane_set.all():
- if lane.flowcell.paired_end:
- lane_type = paired
- else:
- lane_type = single
- if lane.flowcell.read_length < 40:
- read_type = short_read
- elif lane.flowcell.read_length < 100:
- read_type = medium_read
- else:
- read_type = long_read
- counts[lane_type][read_type] += 1
-
- return counts
-
-def create_library_context(cl):
- """
- Create a list of libraries that includes how many lanes were run
- """
- records = []
- #for lib in library_items.object_list:
- for lib in cl.result_list:
- summary = {}
- summary['library'] = lib
- summary['library_id'] = lib.id
- summary['library_name'] = lib.library_name
- summary['species_name' ] = lib.library_species.scientific_name
- if lib.amplified_from_sample is not None:
- summary['amplified_from'] = lib.amplified_from_sample.id
- else:
- summary['amplified_from'] = ''
- lanes_run = count_lanes(lib.lane_set)
- # suppress zeros
- for row in xrange(len(lanes_run)):
- for col in xrange(len(lanes_run[row])):
- if lanes_run[row][col] == 0:
- lanes_run[row][col] = ''
- summary['lanes_run'] = lanes_run
- summary['is_archived'] = lib.is_archived()
- records.append(summary)
- cl.result_count = unicode(cl.paginator._count)
- return {'library_list': records }
-
-
-def library(request, todo_only=False):
- queryset = Library.objects.filter(hidden__exact=0)
- filters = {'hidden__exact': 0}
- if todo_only:
- filters['lane'] = None
- # build changelist
- fcl = HTSChangeList(request, Library,
- list_filter=['affiliations', 'library_species'],
- search_fields=['id', 'library_name', 'amplified_from_sample__id'],
- list_per_page=200,
- model_admin=LibraryOptions(Library, None),
- extra_filters=filters
- )
-
- context = { 'cl': fcl, 'title': 'Library Index', 'todo_only': todo_only}
- context.update(create_library_context(fcl))
- t = get_template('samples/library_index.html')
- c = RequestContext(request, context)
- return HttpResponse( t.render(c) )
-
-
-def library_not_run(request):
- return library(request, todo_only=True)
-
-
-def library_to_flowcells(request, lib_id):
- """
- Display information about all the flowcells a library has been run on.
- """
- try:
- lib = Library.objects.get(id=lib_id)
- except:
- raise Http404('Library %s does not exist' % (lib_id,))
-
- flowcell_list = []
- flowcell_run_results = {} # aka flowcells we're looking at
- for lane in lib.lane_set.all():
- fc = lane.flowcell
- flowcell_id, id = parse_flowcell_id(fc.flowcell_id)
- if flowcell_id not in flowcell_run_results:
- flowcell_run_results[flowcell_id] = get_flowcell_result_dict(flowcell_id)
- flowcell_list.append((fc.flowcell_id, lane.lane_number))
-
- flowcell_list.sort()
- lane_summary_list = []
- eland_results = []
- for fc, lane_number in flowcell_list:
- lane_summary, err_list = _summary_stats(fc, lane_number, lib_id)
- lane_summary_list.extend(lane_summary)
-
- eland_results.extend(_make_eland_results(fc, lane_number, flowcell_run_results))
-
- context = {
- 'page_name': 'Library Details',
- 'lib': lib,
- 'eland_results': eland_results,
- 'lane_summary_list': lane_summary_list,
- }
- context.update(SAMPLES_CONTEXT_DEFAULTS)
-
- return render_to_response(
- 'samples/library_detail.html',
- context,
- context_instance = RequestContext(request))
-
-def lanes_for(request, username=None):
- """
- Generate a report of recent activity for a user
- """
- query = {}
- if username is not None:
- user = HTSUser.objects.get(username=username)
- query.update({'library__affiliations__users__id':user.id})
- fcl = HTSChangeList(request, Lane,
- list_filter=[],
- search_fields=['flowcell__flowcell_id', 'library__id', 'library__library_name'],
- list_per_page=200,
- model_admin=LaneOptions,
- queryset=Lane.objects.filter(**query)
- )
-
- context = { 'lanes': fcl, 'title': 'Lane Index'}
-
- return render_to_response(
- 'samples/lanes_for.html',
- context,
- context_instance = RequestContext(request)
- )
-
-
-def summaryhtm_fc_cnm(request, flowcell_id, cnm):
- """
- returns a Summary.htm file if it exists.
- """
- fc_id, status = parse_flowcell_id(flowcell_id)
- d = get_flowcell_result_dict(fc_id)
-
- if d is None:
- return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
-
- if cnm not in d:
- return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
-
- summary_filepath = d[cnm]['summary']
-
- if summary_filepath is None:
- return HttpResponse('<b>Summary.htm for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
-
- f = open(summary_filepath, 'r')
-
- return HttpResponse(f)
-
-
-def result_fc_cnm_eland_lane(request, flowcell_id, cnm, lane):
- """
- returns an eland_file upon calling.
- """
- fc_id, status = parse_flowcell_id(flowcell_id)
- d = get_flowcell_result_dict(fc_id)
-
- if d is None:
- return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
-
- if cnm not in d:
- return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
-
- erd = d[cnm]['eland_results']
- lane = int(lane)
-
- if lane not in erd:
- return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
-
- filepath = erd[lane]
-
- #f = opener.autoopen(filepath, 'r')
- # return HttpResponse(f, content_type="application/x-elandresult")
-
- f = open(filepath, 'r')
- return HttpResponse(f, content_type='application/x-bzip2')
-
-
-
-def bedfile_fc_cnm_eland_lane_ucsc(request, fc_id, cnm, lane):
- """
- returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane (ucsc compatible)
- """
- return bedfile_fc_cnm_eland_lane(request, fc_id, cnm, lane, ucsc_compatible=True)
-
-
-def bedfile_fc_cnm_eland_lane(request, flowcell_id, cnm, lane, ucsc_compatible=False):
- """
- returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane
- """
- fc_id, status = parse_flowcell_id(flowcell_id)
- d = get_flowcell_result_dict(fc_id)
-
- if d is None:
- return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
-
- if cnm not in d:
- return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
-
- erd = d[cnm]['eland_results']
- lane = int(lane)
-
- if lane not in erd:
- return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
-
- filepath = erd[lane]
-
- # Eland result file
- fi = opener.autoopen(filepath, 'r')
- # output memory file
-
- name, description = makebed.make_description( fc_id, lane )
-
- bedgen = makebed.make_bed_from_eland_generator(fi, name, description)
-
- if ucsc_compatible:
- return HttpResponse(bedgen)
- else:
- return HttpResponse(bedgen, content_type="application/x-bedfile")
-
-
-def _summary_stats(flowcell_id, lane_id, library_id):
- """
- Return the summary statistics for a given flowcell, lane, and end.
- """
- fc_id, status = parse_flowcell_id(flowcell_id)
- fc_result_dict = get_flowcell_result_dict(fc_id)
-
- summary_list = []
- err_list = []
-
- if fc_result_dict is None:
- err_list.append('Results for Flowcell %s not found.' % (fc_id))
- return (summary_list, err_list)
-
- for cycle_width in fc_result_dict:
- xmlpath = fc_result_dict[cycle_width]['run_xml']
-
- if xmlpath is None:
- err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cycle_width))
- continue
-
- run = runfolder.load_pipeline_run_xml(xmlpath)
- # skip if we don't have available metadata.
- if run.gerald is None or run.gerald.summary is None:
- continue
-
- gerald_summary = run.gerald.summary.lane_results
- key = SampleKey(lane=lane_id, sample='s')
- eland_results = list(run.gerald.eland_results.find_keys(key))
- key = SampleKey(lane=lane_id, sample=library_id)
- eland_results.extend(run.gerald.eland_results.find_keys(key))
- for key in eland_results:
- eland_summary = run.gerald.eland_results.results[key]
- # add information to lane_summary
- eland_summary.flowcell_id = flowcell_id
-
- read = key.read-1 if key.read is not None else 0
- try:
- eland_summary.clusters = gerald_summary[read][key.lane].cluster
- except (IndexError, KeyError) as e:
- eland_summary.clustes = None
- eland_summary.cycle_width = cycle_width
- if hasattr(eland_summary, 'genome_map'):
- eland_summary.summarized_reads = runfolder.summarize_mapped_reads(
- eland_summary.genome_map,
- eland_summary.mapped_reads)
-
- # grab some more information out of the flowcell db
- flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
- #pm_field = 'lane_%d_pM' % (lane_id)
- lanes = flowcell.lane_set.filter(lane_number=lane_id)
- eland_summary.flowcell = flowcell
- eland_summary.lanes = lanes
-
- summary_list.append(eland_summary)
-
- #except Exception, e:
- # summary_list.append("Summary report needs to be updated.")
- # LOGGER.error("Exception: " + str(e))
-
- return (summary_list, err_list)
-
-
-def get_eland_result_type(pathname):
- """
- Guess the eland result file type from the filename
- """
- path, filename = os.path.split(pathname)
- if 'extended' in filename:
- return 'extended'
- elif 'multi' in filename:
- return 'multi'
- elif 'result' in filename:
- return 'result'
- else:
- return 'unknown'
-
-def _make_eland_results(flowcell_id, lane_number, interesting_flowcells):
- fc_id, status = parse_flowcell_id(flowcell_id)
- cur_fc = interesting_flowcells.get(fc_id, None)
- if cur_fc is None:
- return []
-
- flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
- lanes = flowcell.lane_set.filter(lane_number=lane_number)
- # Loop throw storage devices if a result has been archived
- storage_id_list = []
- if cur_fc is not None:
- for lts in flowcell.longtermstorage_set.all():
- for sd in lts.storage_devices.all():
- # Use barcode_id if it exists
- if sd.barcode_id is not None and sd.barcode_id != '':
- storage_id_list.append(sd.barcode_id)
- # Otherwise use UUID
- else:
- storage_id_list.append(sd.uuid)
-
- # Formatting for template use
- if len(storage_id_list) == 0:
- storage_ids = None
- else:
- storage_ids = ', '.join([ '<a href="/inventory/%s/">%s</a>' % (s,s) for s in storage_id_list ])
-
- results = []
- for cycle in cur_fc.keys():
- result_path = cur_fc[cycle]['eland_results'].get(lanes[0], None)
- result_link = make_result_link(fc_id, cycle, lanes[0], result_path)
- results.append({'flowcell_id': fc_id,
- 'flowcell': flowcell,
- 'run_date': flowcell.run_date,
- 'cycle': cycle,
- 'lane': lanes[0],
- 'summary_url': make_summary_url(flowcell_id, cycle),
- 'result_url': result_link[0],
- 'result_label': result_link[1],
- 'bed_url': result_link[2],
- 'storage_ids': storage_ids
- })
- return results
-
-def make_summary_url(flowcell_id, cycle_name):
- url = '/results/%s/%s/summary/' % (flowcell_id, cycle_name)
- return url
-
-def make_result_link(flowcell_id, cycle_name, lane, eland_result_path):
- if eland_result_path is None:
- return ("", "", "")
-
- result_type = get_eland_result_type(eland_result_path)
- result_url = '/results/%s/%s/eland_result/%s' % (flowcell_id, cycle_name, lane)
- result_label = 'eland %s' % (result_type,)
- bed_url = None
- if result_type == 'result':
- bed_url_pattern = '/results/%s/%s/bedfile/%s'
- bed_url = bed_url_pattern % (flowcell_id, cycle_name, lane)
-
- return (result_url, result_label, bed_url)
-
-def _files(flowcell_id, lane):
- """
- Sets up available files for download
- """
- lane = int(lane)
-
- flowcell_id, id = parse_flowcell_id(flowcell_id)
- d = get_flowcell_result_dict(flowcell_id)
-
- if d is None:
- return ''
-
- output = []
-
- # c_name == 'CN-M' (i.e. C1-33)
- for c_name in d:
-
- if d[c_name]['summary'] is not None:
- output.append('<a href="/results/%s/%s/summary/">summary(%s)</a>' \
- % (flowcell_id, c_name, c_name))
-
- erd = d[c_name]['eland_results']
- if lane in erd:
- result_type = get_eland_result_type(erd[lane])
- result_url_pattern = '<a href="/results/%s/%s/eland_result/%s">eland %s(%s)</a>'
- output.append(result_url_pattern % (flowcell_id, c_name, lane, result_type, c_name))
- if result_type == 'result':
- bed_url_pattern = '<a href="/results/%s/%s/bedfile/%s">bedfile(%s)</a>'
- output.append(bed_url_pattern % (flowcell_id, c_name, lane, c_name))
-
- if len(output) == 0:
- return ''
-
- return '(' + '|'.join(output) + ')'
-
-def library_id_to_admin_url(request, lib_id):
- lib = Library.objects.get(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(id = library_id)
- except Library.DoesNotExist, e:
- return None
-
- #lane_info = lane_information(lib.lane_set)
- lane_info = []
- for lane in lib.lane_set.all():
- lane_info.append( {'flowcell':lane.flowcell.flowcell_id,
- 'lane_number': lane.lane_number,
- 'lane_id': lane.id,
- 'paired_end': lane.flowcell.paired_end,
- 'read_length': lane.flowcell.read_length,
- 'status_code': lane.status,
- 'status': LANE_STATUS_MAP[lane.status]} )
-
- 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,
- 'cell_line_id': lib.cell_line_id,
- 'cell_line': unicode_or_none(lib.cell_line),
- 'experiment_type': lib.experiment_type.name,
- 'experiment_type_id': lib.experiment_type_id,
- 'gel_cut_size': lib.gel_cut_size,
- 'hidden': lib.hidden,
- 'id': lib.id,
- 'insert_size': lib.insert_size,
- 'lane_set': lane_info,
- 'library_id': lib.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': unicode_or_none(lib.successful_pM),
- 'undiluted_concentration': unicode_or_none(lib.undiluted_concentration)
- }
- if lib.library_type_id is None:
- info['library_type'] = None
- else:
- info['library_type'] = lib.library_type.name
- return info
-
-@csrf_exempt
-def library_json(request, library_id):
- """
- Return a json formatted library dictionary
- """
- require_api_key(request)
- # 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, content_type='application/json')
-
-@csrf_exempt
-def species_json(request, species_id):
- """
- Return information about a species.
- """
- raise Http404
-
-def species(request, species_id):
- species = get_object_or_404(Species, id=species_id)
-
- context = RequestContext(request,
- { 'species': species })
-
- return render_to_response("samples/species_detail.html", context)
-
-def antibodies(request):
- context = RequestContext(request,
- {'antibodies': Antibody.objects.order_by('antigene')})
- return render_to_response("samples/antibody_index.html", context)
-
-@login_required
-def user_profile(request):
- """
- Information about the user
- """
- context = {
- 'page_name': 'User Profile',
- 'media': '',
- #'bcmagic': BarcodeMagicForm(),
- #'select': 'settings',
- }
- context.update(SAMPLES_CONTEXT_DEFAULTS)
- return render_to_response('registration/profile.html', context,
- context_instance=RequestContext(request))
+++ /dev/null
-.strikeout { text-decoration: line-through; }
-
+++ /dev/null
-#header {
- background: #7F99BE url(/static/img/layout-browser-hd-bg.gif) repeat-x center;
-}
-#header h1 {
- font-size: 16px;
- color: #fff;
- font-weight: normal;
- padding: 5px 10px;
-}
-
-#left_bar {
- position: absolute;
- top: 5px;
- left: 5px;
- width: 172px;
- height: auto;
- min-height: 600px;
-}
-
-#main {
- position: relative;
- /* background: #BBBBFF; */
- width:auto;
- min-width:120px;
- padding: 10px;
- margin:0px 0px 0px 175px;
- min-height:600px;
-}
-
-.icon_button {
- border-style: solid;
- border-width: 1px;
- padding: 1px;
- margin: 0px 0px -2px 2px;
-}
-
-div.msg {
- color: white;
- background: #880000;
-}
-
-div.htswdetail {
- clear: both;
- margin: 0;
- padding: 0;
-}
-div.htswdetail table, div.htswdetail td {
- border-style: solid;
-}
-div.htswdetail table {
- border-width: 0 0 1px 1px;
- border-spacing: 0;
- border-collapse: collapse;
-}
-div.htswdetail td {
- margin: 0;
- padding: 3px;
- border-width: 1px 1px 0 0;
-}
-div.htswdetail thead {
- text-align: center;
-}
-div.htswdetail tbody {
- text-align: left;
- }
-div.htswdetail h1,
-div.htswdetail h2
-{
- font-size: 150%;
-}
-
-div.htswdetail h3 {
- font-size: 125%;
- margin: 0;
-}
-
-div.htswdetail h4,
-div.htswdetail h5,
-div.htswdetail ul,
-div.htswdetail ol,
-div.htswdetail li
-{
- list-style: none;
- margin: 0;
-}
-
-div.htswdetail ul,
-div.htswdetail ol
-{
- margin-bottom: .5em;
-}
-
-/* style library detail headers */
-div#librarydetail {
- margin: 0;
- padding: 0;
-}
-div#librarydetail table, div#librarydetail td {
- border-style: solid;
-}
-div#librarydetail table {
- border-width: 0 0 1px 1px;
- border-spacing: 0;
- border-collapse: collapse;
-}
-div#librarydetail td {
- margin: 0;
- padding: 3px;
- border-width: 1px 1px 0 0;
-}
-div#librarydetail thead {
- text-align: center;
- }
-div#librarydetail tbody {
- text-align: right;
-}
-div#librarydetail h1,
-div#librarydetail h2
-{
- font-size: 150%;
-}
-
-div#librarydetail h3 {
- font-size: 125%;
- margin: 0;
-}
-
-div#librarydetail h4,
-div#librarydetail h5,
-div#librarydetail ul,
-div#librarydetail ol,
-div#librarydetail li
-{
- list-style: none;
- margin: 0;
-}
-
-div#librarydetail ul,
-div#librarydetail ol
-{
- margin-bottom: .5em;
-}
-
-div.library_identity {
- clear: left; float: left; margin: 5px; }
-div.library_sample_detail { float: left; margin: 5px; }
-div.library_library_detail { float: left; margin: 5px; }
-div.library_statistics { clear: both; border: 1px; }
-
-div.flowcell_identity { clear: left; float: left; margin: 5px;}
-div.flowcell_lane_detail { float: left; margin: 5px; }
\ No newline at end of file
+++ /dev/null
-/*
- DJANGO Admin
- by Wilson Miner wilson@lawrence.com
-*/
-
-/* Block IE 5 */
-@import "null.css?\"\{";
-
-/* Import other styles */
-@import url('global.css');
-@import url('layout.css');
-
-/* Import patch for IE 6 Windows */
-/*\*/ @import "patch-iewin.css"; /**/
+++ /dev/null
-@import url('base.css');
-
-/* CHANGELISTS */
-#changelist { margin-bottom: 0pm; }
-#changelist table { display: block; }
-#changelist table.filtered { overflow-y: scroll; }
-.change-list .filtered table { border-right:1px solid #ddd; }
-.change-list .filtered { min-height:400px; }
-.change-list .filtered { background:white url(../img/changelist-bg.gif) top right repeat-y !important; }
-.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { width:auto !important; }
-.change-list .filtered table tbody th { padding-right:1em; }
-#changelist .toplinks { border-bottom:1px solid #ccc !important; }
-#changelist .paginator { color:#666; border-top:1px solid #eee; border-bottom:1px solid #eee; background:white url(../img/nav-bg.gif) 0 180% repeat-x; overflow:hidden; }
-.change-list .filtered .paginator { border-right:1px solid #ddd; }
-
-/* CHANGELIST TABLES */
-#changelist table thead th { white-space:nowrap; }
-#changelist table tbody td { border-left: 1px solid #ddd; }
-#changelist table tfoot { color: #666; }
-#changelist tbody { }
-
-/* TOOLBAR */
-#changelist #toolbar { padding:3px; border-bottom:1px solid #ddd; background:#e1e1e1 url(../img/nav-bg.gif) top left repeat-x; color:#666; }
-#changelist #toolbar form input { font-size:11px; padding:1px 2px; }
-#changelist #toolbar form #searchbar { padding:2px; }
-#changelist #changelist-search img { vertical-align:middle; }
-
-/* FILTER COLUMN */
-/*position:absolute; top:0; right:0; z-index:1000; */
-#changelist-filter { float: right;
- width: 20em;
- border-left:1px solid #ddd; margin:0;
- background:#efefef;
- overflow-y: scroll; }
-#changelist-filter h2 { font-size:11px; padding:2px 5px; border-bottom:1px solid #ddd; }
-#changelist-filter h3 { font-size:12px; margin-bottom:0; }
-#changelist-filter ul { padding-left:0;margin-left:10px; }
-#changelist-filter li { list-style-type:none; margin-left:0; padding-left:0; }
-#changelist-filter a { color:#999; }
-#changelist-filter a:hover { color:#036; }
-#changelist-filter li.selected { border-left:5px solid #ccc; padding-left:5px;margin-left:-10px; }
-#changelist-filter li.selected a { color:#5b80b2 !important; }
-
-/* DATE DRILLDOWN */
-.change-list ul.toplinks { display:block; background:white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x; border-top:1px solid white; float:left; padding:0 !important; margin:0 !important; width:100%; }
-.change-list ul.toplinks li { float: left; width: 9em; padding:3px 6px; font-weight: bold; list-style-type:none; }
-.change-list ul.toplinks .date-back a { color:#999; }
-.change-list ul.toplinks .date-back a:hover { color:#036; }
-
-/* PAGINATOR */
-.paginator { font-size:11px; padding-top:10px; padding-bottom:10px; line-height:22px; margin:0; border-top:1px solid #ddd; }
-.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
-.paginator a.showall { padding:0 !important; border:none !important; }
-.paginator a.showall:hover { color:#036 !important; background:transparent !important; }
-.paginator .end { border-width:2px !important; margin-right:6px; }
-.paginator .this-page { padding:2px 6px; font-weight:bold; font-size:13px; vertical-align:top; }
-.paginator a:hover { color:white; background:#5b80b2; border-color:#036; }
+++ /dev/null
-table, td {
- border-style: solid;
-}
-table {
- border-width: 0 0 1px 1px;
- border-spacing: 0;
- border-collapse: collapse;
-}
-thead {
- text-align: center;
-}
-td {
- margin: 0;
- padding: 4px;
- border-width: 1px 1px 0 0;
-}
-td.cell_list a {
- display: block;
-}
-
+++ /dev/null
-/* DASHBOARD */
-
-.dashboard .module table th {
- width: 100%;
-}
-
-.dashboard .module table td {
- white-space: nowrap;
-}
-
-.dashboard .module table td a {
- display: block;
- padding-right: .6em;
-}
-
-/* RECENT ACTIONS MODULE */
-
-.module ul.actionlist {
- margin-left: 0;
-}
-
-ul.actionlist li {
- list-style-type: none;
-}
-
-ul.actionlist li {
- overflow: hidden;
- text-overflow: ellipsis;
- -o-text-overflow: ellipsis;
-}
+++ /dev/null
-@import url('changelists.css');
-@import url('click-table.css');
+++ /dev/null
-@import url('base.css');
-@import url('widgets.css');
-
-/* FORM ROWS */
-.form-row { overflow:hidden; padding:8px 12px; font-size:11px; border-bottom:1px solid #eee; }
-.form-row img, .form-row input { vertical-align:middle; }
-form .form-row p { padding-left:0; font-size:11px; }
-
-/* FORM LABELS */
-form h4 { margin:0 !important; padding:0 !important; border:none !important; }
-label { font-weight:normal !important; color:#666; font-size:12px; }
-.required label, label.required { font-weight:bold !important; color:#333 !important; }
-
-/* RADIO BUTTONS */
-form ul.radiolist li { list-style-type:none; }
-form ul.radiolist label { float:none; display:inline; }
-form ul.inline { margin-left:0; padding:0; }
-form ul.inline li { float:left; padding-right:7px; }
-
-/* ALIGNED FIELDSETS */
-.aligned label { display:block; padding:3px 10px 0 0; float:left; width:8em; }
-.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField { width:350px; }
-form .aligned p, form .aligned ul { margin-left:7em; padding-left:30px; }
-form .aligned table p { margin-left:0; padding-left:0; }
-form .aligned p.help { padding-left:38px; }
-.aligned .vCheckboxLabel { float:none !important; display:inline; padding-left:4px; }
-.colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField { width:610px; }
-.checkbox-row p.help { margin-left:0; padding-left:0 !important; }
-fieldset .field-box { float:left; margin-right: 20px; }
-
-/* WIDE FIELDSETS */
-.wide label { width:15em !important; }
-form .wide p { margin-left:15em; }
-form .wide p.help { padding-left:38px; }
-.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField { width:450px; }
-
-/* COLLAPSED FIELDSETS */
-fieldset.collapsed * { display:none; }
-fieldset.collapsed h2, fieldset.collapsed { display:block !important; }
-fieldset.collapsed h2 { background-image:url(../img/nav-bg.gif); background-position:bottom left; color:#999; }
-fieldset.collapsed .collapse-toggle { padding:3px 5px !important; background:transparent; display:inline !important;}
-
-/* MONOSPACE TEXTAREAS */
-fieldset.monospace textarea { font-family:"Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace; }
-
-/* SUBMIT ROW */
-.submit-row { padding:5px 7px; text-align:right; background:white url(../img/nav-bg.gif) 0 100% repeat-x; border:1px solid #ccc; margin:5px 0; overflow:hidden; }
-.submit-row input { margin:0 0 0 5px; }
-.submit-row p { margin:0.3em; }
-.submit-row p.deletelink-box { float: left; }
-.submit-row .deletelink { background:url(../img/icon_deletelink.gif) 0 50% no-repeat; padding-left:14px; }
-
-/* CUSTOM FORM FIELDS */
-.vSelectMultipleField { vertical-align:top !important; }
-.vCheckboxField { border:none; }
-.vDateField, .vTimeField { margin-right:2px; }
-.vURLField { width:30em; }
-.vLargeTextField, .vXMLLargeTextField { width:48em; }
-.flatpages-flatpage #id_content { height:40.2em; }
-.module table .vPositiveSmallIntegerField { width:2.2em; }
-.vTextField { width:20em; }
-.vIntegerField { width:5em; }
-.vForeignKeyRawIdAdminField { width: 5em; }
-
-/* INLINES */
-.inline-group {padding:0; border:1px solid #ccc; margin:10px 0;}
-.inline-group .aligned label { width: 8em; }
-
-.inline-related {position:relative;}
-.inline-related h3 {margin: 0; color:#666; padding:3px 5px; font-size:11px; background:#e1e1e1 url(../img/nav-bg.gif) top left repeat-x; border-bottom:1px solid #ddd;}
-.inline-related h3 span.delete {padding-left:20px; position:absolute; top:2px; right:10px;}
-.inline-related h3 span.delete label {margin-left:2px; font-size: 11px;}
-.inline-related fieldset {margin: 0; background:#fff; border: none; }
-.inline-related fieldset.module h3 { margin:0; padding:2px 5px 3px 5px; font-size:11px; text-align:left; font-weight:bold; background:#bcd; color:#fff; }
-.inline-related.tabular fieldset.module table {width:100%;}
-.last-related fieldset {border: none;}
-
-.inline-group .tabular tr.has_original td {padding-top:2em;}
-.inline-group .tabular tr td.original { padding:2px 0 0 0; width:0; _position:relative; }
-.inline-group .tabular th.original {width:0px; padding:0;}
-.inline-group .tabular td.original p {position:absolute; left:0; height:1.1em; padding:2px 7px; overflow:hidden; font-size:9px; font-weight:bold; color:#666; _width:700px; }
-.inline-group ul.tools {padding:0; margin: 0; list-style:none;}
-.inline-group ul.tools li {display:inline; padding:0 5px;}
-.inline-group ul.tools a.add {background:url(../img/icon_addlink.gif) 0 50% no-repeat; padding-left:14px;}
+++ /dev/null
-body { margin:0; padding:0; font-size:14px; font-family:"Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; }
-
-/* LINKS */
-a:link, a:visited { color: #5b80b2; text-decoration:none; }
-a:hover { color: #036; }
-a img { border:none; }
-a.section:link, a.section:visited { color: white; text-decoration:none; }
-
-/* GLOBAL DEFAULTS */
-p, ol, ul, dl { margin:.2em 0 .8em 0; }
-p { padding:0; line-height:140%; }
-
-h1,h2,h3,h4,h5 { font-weight:bold; }
-h1 { font-size:18px; color:#666; padding:0 6px 0 0; margin:0 0 .2em 0; }
-h2 { font-size:16px; margin:1em 0 .5em 0; }
-h2.subhead { font-weight:normal;margin-top:0; }
-h3 { font-size:14px; margin:.8em 0 .3em 0; color:#666; font-weight:bold; }
-h4 { font-size:12px; margin:1em 0 .8em 0; padding-bottom:3px; }
-h5 { font-size:10px; margin:1.5em 0 .5em 0; color:#666; text-transform:uppercase; letter-spacing:1px; }
-
-ul li { list-style-type:square; padding:1px 0; }
-ul.plainlist { margin-left:0 !important; }
-ul.plainlist li { list-style-type:none; }
-li ul { margin-bottom:0; }
-li, dt, dd { font-size:11px; line-height:14px; }
-dt { font-weight:bold; margin-top:4px; }
-dd { margin-left:0; }
-
-form { margin:0; padding:0; }
-fieldset { margin:0; padding:0; }
-
-blockquote { font-size:11px; color:#777; margin-left:2px; padding-left:10px; border-left:5px solid #ddd; }
-code, pre { font-family:"Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; background:inherit; color:#666; font-size:11px; }
-pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
-code strong { color:#930; }
-hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
-
-/* TEXT STYLES & MODIFIERS */
-.small { font-size:11px; }
-.tiny { font-size:10px; }
-p.tiny { margin-top:-2px; }
-.mini { font-size:9px; }
-p.mini { margin-top:-3px; }
-.help, p.help { font-size:10px !important; color:#999; }
-p img, h1 img, h2 img, h3 img, h4 img, td img { vertical-align:middle; }
-.quiet, a.quiet:link, a.quiet:visited { color:#999 !important;font-weight:normal !important; }
-.quiet strong { font-weight:bold !important; }
-.float-right { float:right; }
-.float-left { float:left; }
-.clear { clear:both; }
-.align-left { text-align:left; }
-.align-right { text-align:right; }
-.example { margin:10px 0; padding:5px 10px; background:#efefef; }
-.nowrap { white-space:nowrap; }
-
-/* TABLES */
-table { border-collapse:collapse; border-color:#ccc; }
-td, th { font-size:11px; line-height:13px; border-bottom:1px solid #eee; vertical-align:top; padding:5px; font-family:"Lucida Grande", Verdana, Arial, sans-serif; }
-th { text-align:left; font-size:12px; font-weight:bold; }
-thead th,
-tfoot td { color:#666; padding:2px 5px; font-size:11px; background:#e1e1e1 url(../img/nav-bg.gif) top left repeat-x; border-left:1px solid #ddd; border-bottom:1px solid #ddd; }
-tfoot td { border-bottom:none; border-top:1px solid #ddd; }
-thead th:first-child,
-tfoot td:first-child { border-left:none !important; }
-thead th.optional { font-weight:normal !important; }
-fieldset table { border-right:1px solid #eee; }
-tr.row-label td { font-size:9px; padding-top:2px; padding-bottom:0; border-bottom:none; color:#666; margin-top:-1px; }
-tr.alt { background:#f6f6f6; }
-.row1 { background:#EDF3FE; }
-.row2 { background:white; }
-
-/* SORTABLE TABLES */
-thead th a:link, thead th a:visited { color:#666; display:block; }
-table thead th.sorted { background-position:bottom left !important; }
-table thead th.sorted a { padding-right:13px; }
-table thead th.ascending a { background:url(../img/arrow-down.gif) right .4em no-repeat; }
-table thead th.descending a { background:url(../img/arrow-up.gif) right .4em no-repeat; }
-
-/* ORDERABLE TABLES */
-table.orderable tbody tr td:hover { cursor:move; }
-table.orderable tbody tr td:first-child { padding-left:14px; background-image:url(../img/nav-bg-grabber.gif); background-repeat:repeat-y; }
-table.orderable-initalized .order-cell, body>tr>td.order-cell { display:none; }
-
-/* FORM DEFAULTS */
-input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
-textarea { vertical-align:top !important; }
-input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
-
-/* FORM BUTTONS */
-.button, input[type=submit], input[type=button], .submit-row input { background:white url(../img/nav-bg.gif) bottom repeat-x; padding:3px; color:black; border:1px solid #bbb; border-color:#ddd #aaa #aaa #ddd; }
-.button:active, input[type=submit]:active, input[type=button]:active { background-image:url(../img/nav-bg-reverse.gif); background-position:top; }
-.button.default, input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; background:#7CA0C7 url(../img/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; float:right; }
-.button.default:active, input[type=submit].default:active { background-image:url(../img/default-bg-reverse.gif); background-position:top; }
-
-/* MODULES */
-.module { border:1px solid #ccc; margin-bottom:5px; background:white; }
-.module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; }
-.module blockquote { margin-left:12px; }
-.module ul, .module ol { margin-left:1.5em; }
-.module h3 { margin-top:.6em; }
-.module h2, .module caption, .inline-group h2 { margin:0; padding:2px 5px 3px 5px; font-size:11px; text-align:left; font-weight:bold; background:#7CA0C7 url(../img/default-bg.gif) top left repeat-x; color:white; }
-.module table { border-collapse: collapse; }
-
-/* MESSAGES & ERRORS */
-ul.messagelist { padding:0 0 5px 0; margin:0; }
-ul.messagelist li { font-size:12px; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border-bottom:1px solid #ddd; color:#666; background:#ffc url(../img/icon_success.gif) 5px .3em no-repeat; }
-.errornote { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:red;background:#ffc url(../img/icon_error.gif) 5px .3em no-repeat; }
-ul.errorlist { margin:0 !important; padding:0 !important; }
-.errorlist li { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:white; background:red url(../img/icon_alert.gif) 5px .3em no-repeat; }
-td ul.errorlist { margin:0 !important; padding:0 !important; }
-td ul.errorlist li { margin:0 !important; }
-.errors { background:#ffc; }
-.errors input, .errors select { border:1px solid red; }
-div.system-message { background: #ffc; margin: 10px; padding: 6px 8px; font-size: .8em; }
-div.system-message p.system-message-title { padding:4px 5px 4px 25px; margin:0; color:red; background:#ffc url(../img/icon_error.gif) 5px .3em no-repeat; }
-.description { font-size:12px; padding:5px 0 0 12px; }
-
-/* BREADCRUMBS */
-div.breadcrumbs { background:white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x; padding:2px 8px 3px 8px; font-size:11px; color:#999; border-top:1px solid white; border-bottom:1px solid #ccc; text-align:left; }
-
-/* ACTION ICONS */
-.addlink { padding-left:12px; background:url(../img/icon_addlink.gif) 0 .2em no-repeat; }
-.changelink { padding-left:12px; background:url(../img/icon_changelink.gif) 0 .2em no-repeat; }
-.deletelink { padding-left:12px; background:url(../img/icon_deletelink.gif) 0 .25em no-repeat; }
-a.deletelink:link, a.deletelink:visited { color:#CC3434; }
-a.deletelink:hover { color:#993333; }
-
-/* OBJECT TOOLS */
-.object-tools { font-size:10px; font-weight:bold; font-family:Arial,Helvetica,sans-serif; padding-left:0; float:right; position:relative; margin-top:-2.4em; margin-bottom:-2em; }
-.form-row .object-tools { margin-top:5px; margin-bottom:5px; float:none; height:2em; padding-left:3.5em; }
-.object-tools li { display:block; float:left; background:url(../img/tool-left.gif) 0 0 no-repeat; padding:0 0 0 8px; margin-left:2px; height:16px; }
-.object-tools li:hover { background:url(../img/tool-left_over.gif) 0 0 no-repeat; }
-.object-tools a:link, .object-tools a:visited { display:block; float:left; color:white; padding:.1em 14px .1em 8px; height:14px; background:#999 url(../img/tool-right.gif) 100% 0 no-repeat; }
-.object-tools a:hover, .object-tools li:hover a { background:#5b80b2 url(../img/tool-right_over.gif) 100% 0 no-repeat; }
-.object-tools a.viewsitelink, .object-tools a.golink { background:#999 url(../img/tooltag-arrowright.gif) top right no-repeat; padding-right:28px; }
-.object-tools a.viewsitelink:hover, .object-tools a.golink:hover { background:#5b80b2 url(../img/tooltag-arrowright_over.gif) top right no-repeat; }
-.object-tools a.addlink { background:#999 url(../img/tooltag-add.gif) top right no-repeat; padding-right:28px; }
-.object-tools a.addlink:hover { background:#5b80b2 url(../img/tooltag-add_over.gif) top right no-repeat; }
-
-/* OBJECT HISTORY */
-table#change-history { width:100%; }
-table#change-history tbody th { width:16em; }
+++ /dev/null
-#header {
- background: #7F99BE url(/static/img/layout-browser-hd-bg.gif) repeat-x center;
-}
-#header h1 {
- font-size: 16px;
- color: #fff;
- font-weight: normal;
- padding: 5px 10px;
-}
-
-#left_bar {
- position: absolute;
- top: 5px;
- left: 5px;
- width: 172px;
- height: auto;
- min-height: 600px;
-
-
-}
-
-#main {
- position: relative;
- /* background: #BBBBFF; */
- width:auto;
- min-width:120px;
- padding: 10px;
- margin:0px 0px 0px 175px;
- min-height:600px;
-}
-
-div.msg {
- color: white;
- background: #880000;
-}
\ No newline at end of file
+++ /dev/null
-/* PAGE STRUCTURE */
-#container { position:relative; width:100%; min-width:760px; padding:0; }
-#content { margin:10px 15px; }
-#header { width:100%; }
-#content-main { float:left; width:100%; }
-#content-related { float:right; width:18em; position:relative; margin-right:-19em; }
-#footer { clear:both; padding:10px; }
-
-/* COLUMN TYPES */
-.colMS { margin-right:20em !important; }
-.colSM { margin-left:20em !important; }
-.colSM #content-related { float:left; margin-right:0; margin-left:-19em; }
-.colSM #content-main { float:right; }
-.popup .colM { width:95%; }
-.subcol { float:left; width:46%; margin-right:15px; }
-.dashboard #content { width:500px; }
-
-/* HEADER */
-#header { background:#417690; color:#ffc; overflow:hidden; }
-#header a:link, #header a:visited { color:white; }
-#header a:hover { text-decoration:underline; }
-#branding h1 { padding:0 10px; font-size:18px; margin:8px 0; font-weight:normal; color:#f4f379; }
-#branding h2 { padding:0 10px; font-size:14px; margin:-8px 0 8px 0; font-weight:normal; color:#ffc; }
-#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
-
-/* SIDEBAR */
-#content-related h3 { font-size:12px; color:#666; margin-bottom:3px; }
-#content-related h4 { font-size:11px; }
-#content-related .module h2 { background:#eee url(../img/nav-bg.gif) bottom left repeat-x; color:#666; }
+++ /dev/null
-/* Nothing to see here. Dummy file to feed to the high pass filter which hides CSS from IE5/win. Details: http://tantek.com/CSS/Examples/highpass.html */
\ No newline at end of file
+++ /dev/null
-* html #container { position:static; } /* keep header from flowing off the page */
-* html .colMS #content-related { margin-right:0; margin-left:10px; position:static; } /* put the right sidebars back on the page */
-* html .colSM #content-related { margin-right:10px; margin-left:-115px; position:static; } /* put the left sidebars back on the page */
-* html .form-row { height:1%; }
-* html .dashboard #content { width:768px; } /* proper fixed width for dashboard in IE6 */
-* html .dashboard #content-main { width:535px; } /* proper fixed width for dashboard in IE6 */
-* html #changelist-filter ul { margin-right:-10px; } /* fix right margin for changelist filters in IE6 */
-* html .change-list .filtered { height:400px; } /* IE ignores min-height, but treats height as if it were min-height */
\ No newline at end of file
+++ /dev/null
-#id_account_number { width: 50em; }
\ No newline at end of file
+++ /dev/null
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-This copyright and license notice covers the following images:
- * hdd_unmount.png
-************************************************************************
-
-TITLE: Crystal Project Icons
-AUTHOR: Everaldo Coelho
-SITE: http://www.everaldo.com
-CONTACT: everaldo@everaldo.com
-
-Copyright (c) 2006-2007 Everaldo Coelho.
+++ /dev/null
-//-----------------------------------------------
-// Barcode Magic JavaScript
-// Authors: Brandon W. King
-// Feb. 2009
-//-----------------------------------------------
-
-//---------------------------------------
-// BCMagic Core Processing AJAX Callback
-//---------------------------------------
-//var bcmagic_process_callback = function(data, textStatus) {
-var bcmagic_process_callback = function(response, opt) {
- //FIXME: temp bypass hack
- var textStatus = 'success';
- if (textStatus != 'success')
- {
- bcmagic_message('AJAX Status: '+textStatus);
- return;
- }
-
- var data = Ext.decode(response.responseText);
-
- for (key in data)
- {
- if (key == 'mode')
- {
- if (data['mode'] == 'clear')
- {
- bcmagic_status('','');
- }
- else if (data['mode'] == 'redirect')
- {
- if ('url' in data)
- {
- bcmagic_redirect(data['url']);
- }
- else
- {
- bcmagic_status('Error', 'No redirect URL provided by server');
- }
- }
- else if (data['mode'] == 'autofill')
- {
- bcmagic_autofill(data['field'], data['value'])
- }
- else {
- bcmagic_message('Message recieved!');
- bcmagic_status(data['mode'], data['status']);
- }
-
- }
- if (key == 'msg')
- {
- bcmagic_message(data['msg']);
- }
- }
-}
-
-var bcmagic_callback = function(data, textStatus)
-{
- if (textStatus != 'success')
- bcmagic_message('Failed!');
- else
- bcmagic_message('Success!');
-}
-
-var bcmagic_process = function(){
- var magic = Ext.get("bcmagic_input_field");
- var text = magic.getValue();
- magic.dom.value = '';
- magic.focus();
-
- //var bcm_mode = $("#id_bcm_mode");
- //var mode = bcm_mode.attr('value');
- var mode = 'default';
-
- // Show what we have captured
- bcmagic_message('Sent command to server');
- //$.post('/bcmagic/magic/', {'text': text, 'bcm_mode': mode}, bcmagic_process_callback, 'json');
- Ext.Ajax.request({
- url: '/bcmagic/magic/',
- success: bcmagic_process_callback,
- failure: function (r, o) { quick_msg('Some AJAX Fail!'); },
- params: {'text': text, 'bcm_mode': mode}
- });
-}
-
-var bcmagic_keyhandler = function(e) {
- //Process upon enter key as input.
- if (e.which == 13)
- bcmagic_process();
-}
-
-//---------------------------------------
-// Utility Functions
-//---------------------------------------
-var bcmagic_message = function(text)
-{
- // Show message
- //$("#bcm_msg").html(text);
- quick_msg(text);
-
- // clear message after 3000ms
- /*
- setTimeout(function() {
- $("#bcm_msg").html('');
- }, 3000);
- */
-}
-
-var bcmagic_status = function(state, text)
-{
- //var msg = $('#bcm_status');
- if (state.length > 0 || text.length > 0)
- quick_msg(state+': '+text);
- //else
- // msg.html('');
-}
-
-
-var bcmagic_redirect = function(url)
-{
- bcmagic_message('Redirecting to:' + url);
- window.location = url;
-}
-
-var bcmagic_autofill = function(field, val)
-{
- var txtbox = $('#'+field);
- txtbox.attr('value', val);
-
- var input_fields = $('form input').not(':hidden').not('[type=submit]');
-
- // Count the number of text fields which have been filled in.
- var count = 0;
- input_fields.each( function(){
- if(this.value.length > 0){
- count = count + 1;
- }
- });
-
- // If the number of text fields filled in is equal to the number of input_fields in the form, submit the form!
- if (count == input_fields.length)
- {
- bcmagic_status('Form Full', 'Form is now full and ready to process');
- form = $('form');
- form.submit();
- form.reset();
-
- }
- else
- {
- bcmagic_status('Form Fill Count', 'Count(' + count +') - Total(' + input_fields.length + ')');
- }
-}
-
-//---------------------------------------
-// Main Ready Function
-//---------------------------------------
-/*$(document).ready(function() {
-
- // Grab initial focus on magic text input
- $("#id_magic").focus();
-
- // Set some initial text
- //$("#id_magic").attr('value','Moo cow!');
-
- // Trigger when enterkey is pressed
- $("#id_magic").keypress(bcmagic_keyhandler)
-});*/
\ No newline at end of file
+++ /dev/null
-
-var inventory_item_dblclick_handler = function(grid, row_index, e){
- //quick_msg('Choose Row: ' + row_index);
- var rec = grid.getStore().getAt(row_index);
- //quick_msg('UUID: ' + rec.get('uuid'));
- goto_url('/inventory/'+rec.get('uuid')+'/');
-}
-
-var getInventoryDataGrid = function(){
-
- var Item = Ext.data.Record.create([
- { name: 'uuid' },
- { name: 'barcode_id'},
- { name: 'model_id'},
- { name: 'part_number'},
- { name: 'lot_number'},
- { name: 'vendor'},
- { name: 'creation_date'/*, type: 'date', dateFormat: 'n/j h:ia'*/},
- { name: 'modified_date'/*, type: 'date', dateFormat: 'n/j h:ia'*/},
- { name: 'location'},
- { name: 'status'},
- { name: 'flowcells'},
- { name: 'type'}
- ]);
-
- var inventoryReader = new Ext.data.JsonReader(
- {
- totalProperty: "results",
- root: "rows",
- idProperty: "uuid"
- },
- Item
- );
-
- /*
- var inventoryStore = new Ext.data.JsonStore({
- autoDestory: true,
- url: '/inventory/data/items/',
- storeId: 'item_store',
-
- });
- */
-
- var grid = new Ext.grid.GridPanel({
- store: new Ext.data.GroupingStore({
- reader: inventoryReader,
- url: '/inventory/data/items/',
- storeId: 'item_group_store',
- groupField: 'type',
- sortInfo: { field: 'creation_date', direction: "DESC"},
- autoLoad: true
- }),
-
- columns: [
- {id: 'uuid', header:"UUID", width: 32, sortable: true, dataIndex: 'uuid'},
- {header: 'Barcode ID', width: 20, sortable: true, dataIndex: 'barcode_id'},
- {header: 'Location', width: 20, sortable: true, dataIndex: 'location'},
- {header: 'Model', width: 20, sortable: true, dataIndex: 'model_id'},
- {header: 'Part #', width: 20, sortable: true, dataIndex: 'part_number', hidden: true},
- {header: 'Lot #', width: 20, sortable: true, dataIndex: 'lot_number', hidden: true},
- {header: 'Vendor', width: 20, sortable: true, dataIndex: 'vendor'},
- {header: 'Creation Date', width: 20, sortable: true, dataIndex: 'creation_date'/*, renderer: Ext.util.Format.dateRenderer('Y/m/d')*/},
- {header: 'Modified Date', width: 20, sortable: true, dataIndex: 'modified_date', hidden: true/*, renderer: Ext.util.Format.dateRenderer('Y/m/d')*/},
- {header: 'Status', width: 20, sortable: true, dataIndex: 'status', hidden: true},
- {header: 'Stored Flowcells', width: 20, sortable: true, dataIndex: 'flowcells'},
- {header: 'Type', width: 20, sortable: true, dataIndex: 'type', hidden: true}
- ],
-
- view: new Ext.grid.GroupingView({
- forceFit: true,
- groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
- }),
-
- frame: true,
- width: 'auto',
- //height: 500,
- //autoHeight: true,
- collapsible: false,
- title: "Inventory Index",
- iconCls: 'icon-grid',
- id: 'inventory_item_panel',
- stateId: 'inventory_item_panel_state',
- stateful: true
- //renderTo: 'grid_target'
- });
-
- grid.on('rowdblclick', inventory_item_dblclick_handler);
-
- return grid;
-}
\ No newline at end of file
+++ /dev/null
-/**\r
- * jQuery.timers - Timer abstractions for jQuery\r
- * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)\r
- * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).\r
- * Date: 2008/08/26\r
- *\r
- * @author Blair Mitchelmore\r
- * @version 1.0.0\r
- *\r
- **/\r
-\r
-jQuery.fn.extend({\r
- everyTime: function(interval, label, fn, times, belay) {\r
- return this.each(function() {\r
- jQuery.timer.add(this, interval, label, fn, times, belay);\r
- });\r
- },\r
- oneTime: function(interval, label, fn) {\r
- return this.each(function() {\r
- jQuery.timer.add(this, interval, label, fn, 1);\r
- });\r
- },\r
- stopTime: function(label, fn) {\r
- return this.each(function() {\r
- jQuery.timer.remove(this, label, fn);\r
- });\r
- }\r
-});\r
-\r
-jQuery.extend({\r
- timer: {\r
- guid: 1,\r
- global: {},\r
- regex: /^([0-9]+)\s*(.*s)?$/,\r
- powers: {\r
- // Yeah this is major overkill...\r
- 'ms': 1,\r
- 'cs': 10,\r
- 'ds': 100,\r
- 's': 1000,\r
- 'das': 10000,\r
- 'hs': 100000,\r
- 'ks': 1000000\r
- },\r
- timeParse: function(value) {\r
- if (value == undefined || value == null)\r
- return null;\r
- var result = this.regex.exec(jQuery.trim(value.toString()));\r
- if (result[2]) {\r
- var num = parseInt(result[1], 10);\r
- var mult = this.powers[result[2]] || 1;\r
- return num * mult;\r
- } else {\r
- return value;\r
- }\r
- },\r
- add: function(element, interval, label, fn, times, belay) {\r
- var counter = 0;\r
- \r
- if (jQuery.isFunction(label)) {\r
- if (!times) \r
- times = fn;\r
- fn = label;\r
- label = interval;\r
- }\r
- \r
- interval = jQuery.timer.timeParse(interval);\r
-\r
- if (typeof interval != 'number' || isNaN(interval) || interval <= 0)\r
- return;\r
-\r
- if (times && times.constructor != Number) {\r
- belay = !!times;\r
- times = 0;\r
- }\r
- \r
- times = times || 0;\r
- belay = belay || false;\r
- \r
- if (!element.$timers) \r
- element.$timers = {};\r
- \r
- if (!element.$timers[label])\r
- element.$timers[label] = {};\r
- \r
- fn.$timerID = fn.$timerID || this.guid++;\r
- \r
- var handler = function() {\r
- if (belay && this.inProgress) \r
- return;\r
- this.inProgress = true;\r
- if ((++counter > times && times !== 0) || fn.call(element, counter) === false)\r
- jQuery.timer.remove(element, label, fn);\r
- this.inProgress = false;\r
- };\r
- \r
- handler.$timerID = fn.$timerID;\r
- \r
- if (!element.$timers[label][fn.$timerID]) \r
- element.$timers[label][fn.$timerID] = window.setInterval(handler,interval);\r
- \r
- if ( !this.global[label] )\r
- this.global[label] = [];\r
- this.global[label].push( element );\r
- \r
- },\r
- remove: function(element, label, fn) {\r
- var timers = element.$timers, ret;\r
- \r
- if ( timers ) {\r
- \r
- if (!label) {\r
- for ( label in timers )\r
- this.remove(element, label, fn);\r
- } else if ( timers[label] ) {\r
- if ( fn ) {\r
- if ( fn.$timerID ) {\r
- window.clearInterval(timers[label][fn.$timerID]);\r
- delete timers[label][fn.$timerID];\r
- }\r
- } else {\r
- for ( var fn in timers[label] ) {\r
- window.clearInterval(timers[label][fn]);\r
- delete timers[label][fn];\r
- }\r
- }\r
- \r
- for ( ret in timers[label] ) break;\r
- if ( !ret ) {\r
- ret = null;\r
- delete timers[label];\r
- }\r
- }\r
- \r
- for ( ret in timers ) break;\r
- if ( !ret ) \r
- element.$timers = null;\r
- }\r
- }\r
- }\r
-});\r
-\r
-if (jQuery.browser.msie)\r
- jQuery(window).one("unload", function() {\r
- var global = jQuery.timer.global;\r
- for ( var label in global ) {\r
- var els = global[label], i = els.length;\r
- while ( --i )\r
- jQuery.timer.remove(els[i], label);\r
- }\r
- });\r
+++ /dev/null
-//-----------------------------------------------
-// Barcode Magic JavaScript
-// Authors: Brandon W. King
-// Feb. 2009
-//-----------------------------------------------
-
-//---------------------------------------
-// BCMagic Core Processing AJAX Callback
-//---------------------------------------
-var bcmagic_process_callback = function(data, textStatus) {
- if (textStatus != 'success')
- {
- bcmagic_message('AJAX Status: '+textStatus);
- return;
- }
-
- for (key in data)
- {
- if (key == 'mode')
- {
- if (data['mode'] == 'clear')
- {
- bcmagic_status('','');
- }
- else if (data['mode'] == 'redirect')
- {
- if ('url' in data)
- {
- bcmagic_redirect(data['url']);
- }
- else
- {
- bcmagic_status('Error', 'No redirect URL provided by server');
- }
- }
- else if (data['mode'] == 'autofill')
- {
- bcmagic_autofill(data['field'], data['value'])
- }
- else {
- bcmagic_message('Message recieved!');
- bcmagic_status(data['mode'], data['status']);
- }
-
- }
- if (key == 'msg')
- {
- bcmagic_message(data['msg']);
- }
- }
-}
-
-var bcmagic_callback = function(data, textStatus)
-{
- if (textStatus != 'success')
- bcmagic_message('Failed!');
- else
- bcmagic_message('Success!');
-}
-
-var bcmagic_process = function(){
- var magic = $("#id_magic");
- var text = magic.attr('value');
- magic.attr('value', '');
-
- var bcm_mode = $("#id_bcm_mode");
- var mode = bcm_mode.attr('value');
-
- // Show what we have captured
- bcmagic_message('Sent command to server');
- $.post('/bcmagic/magic/', {'text': text, 'bcm_mode': mode}, bcmagic_process_callback, 'json');
-}
-
-var bcmagic_keyhandler = function(e) {
- //Process upon enter key as input.
- if (e.which == 13)
- bcmagic_process();
-}
-
-//---------------------------------------
-// Utility Functions
-//---------------------------------------
-var bcmagic_message = function(text)
-{
- // Show message
- $("#bcm_msg").html(text);
-
- // clear message after 3000ms
- setTimeout(function() {
- $("#bcm_msg").html('');
- }, 3000);
-}
-
-var bcmagic_status = function(state, text)
-{
- var msg = $('#bcm_status');
- if (state.length > 0 || text.length > 0)
- msg.html('<b>'+state+':</b> '+text);
- else
- msg.html('');
-}
-
-
-var bcmagic_redirect = function(url)
-{
- bcmagic_message('Redirecting to:' + url);
- window.location = url;
-}
-
-var bcmagic_autofill = function(field, val)
-{
- var txtbox = $('#'+field);
- txtbox.attr('value', val);
-
- var input_fields = $('form input').not(':hidden').not('[type=submit]');
-
- // Count the number of text fields which have been filled in.
- var count = 0;
- input_fields.each( function(){
- if(this.value.length > 0){
- count = count + 1;
- }
- });
-
- // If the number of text fields filled in is equal to the number of input_fields in the form, submit the form!
- if (count == input_fields.length)
- {
- bcmagic_status('Form Full', 'Form is now full and ready to process');
- form = $('form');
- form.submit();
- form.reset();
-
- }
- else
- {
- bcmagic_status('Form Fill Count', 'Count(' + count +') - Total(' + input_fields.length + ')');
- }
-}
-
-//---------------------------------------
-// Main Ready Function
-//---------------------------------------
-/*$(document).ready(function() {
-
- // Grab initial focus on magic text input
- $("#id_magic").focus();
-
- // Set some initial text
- //$("#id_magic").attr('value','Moo cow!');
-
- // Trigger when enterkey is pressed
- $("#id_magic").keypress(bcmagic_keyhandler)
-});*/
\ No newline at end of file
+++ /dev/null
-<html>
- <head>
- <title>404 - Not Found</title>
- </head>
- <body>
- <h1>404 - Not Found</h1>
- <p>The URL you tried to reach does not appear to exist,
- if you have reason to believe this in error, please try again later.</p>
- </body>
-</html>
-
+++ /dev/null
-{% extends "admin/change_form.html" %}
-{% load i18n %}
-
-{% block after_field_sets %}
-
-<p>{% trans "First, enter a username and password. Then, you'll be able to edit more user options." %}</p>
-
-<fieldset class="module aligned">
-
-<div class="form-row">
- {{ form.username.errors }}
- {# TODO: get required class on label_tag #}
- <label for="id_username" class="required">{% trans 'Username' %}:</label> {{ form.username }}
- <p class="help">{{ form.username.help_text }}</p>
-</div>
-
-<div class="form-row">
- {{ form.first_name.errors }}
- {{ form.last_name.errors }}
- {# TODO: get required class on label_tag #}
- <div class="field-box">
- <label for="first_name" >{% trans 'First Name' %}:</label> {{ form.first_name }}
- <p class="help">{{ form.first_name.help_text }}</p>
- </div>
- <div class="field-box">
- <label for="last_name" >{% trans 'Last Name' %}:</label> {{ form.last_name }}
- <p class="help">{{ form.last_name.help_text }}</p>
- </div>
-</div>
-
-<div class="form-row">
- {{ form.password1.errors }}
- {# TODO: get required class on label_tag #}
- <label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
-</div>
-
-<div class="form-row">
- {{ form.password2.errors }}
- {# TODO: get required class on label_tag #}
- <label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
- <p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
-</div>
-
-<script type="text/javascript">document.getElementById("id_username").focus();</script>
-
-</fieldset>
-{% endblock %}
+++ /dev/null
-{% extends "admin/base.html" %}
-{% load i18n %}
-
-{% block title %}
-{{ title }}|{%trans "dev site admin" %}
-{% endblock %}
-
-{% block branding %}
-<h1 id="site-name" style="background-color:#cccccc;color:black">
- {%block sitename %}
- {% trans 'HTS Workflow Dev Server' %}
- {%endblock%}
-</h1>
-{% endblock %}
-
-{% block nav-global %}{% endblock %}
+++ /dev/null
-{% extends "admin/change_form.html" %}
-{% load i18n %}
-{% block object-tools %}
-{% if change %}{% if not is_popup %}
- <ul class="object-tools">
- <li><a href="../../../../{{ app_label }}/started/{{ object_id }}/">{% trans "Started Email" %}</a></li>
- <li><a href="history/" class="historylink">{% trans "History" %}</a></li>
- {% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
- </ul>
-{% endif %}{% endif %}
-{% endblock %}
+++ /dev/null
-{% extends "admin/base_site.html" %}
-{% load i18n %}
-
-{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% load staticfiles %}{% static "css/dashboard.css" %}"/>{% endblock %}
-
-{% block coltype %}colMS{% endblock %}
-
-{% block bodyclass %}dashboard{% endblock %}
-
-{% block breadcrumbs %}{% endblock %}
-
-{% block content %}
-<div id="content-main">
-
-<div class='module'>
-<table>
-<caption>Frequently Used</caption>
-<tr>
-<th scope="row"><a href="/admin/samples/library/">Libraries</a></th>
-<td><a href="/admin/samples/library/add/" class="addlink">{% trans 'Add' %}</a></td>
-</tr>
-<tr>
-<th scope="row"><a href="/admin/experiments/flowcell/">Flowcells</a></th>
-<td><a href="/admin/experiments/flowcell/add/" class="addlink">{% trans 'Add' %}</a></td>
-</tr>
-</table></div>
-
-<div class='module'>
-<table>
-<caption>Label Printing</caption>
-<tr>
-<th scope="row"><a href="/admin/labels/labelcontent/">Label Contents</a></th>
-<td><a href="/admin/labels/labelcontent/add/" class="addlink">{% trans 'Add' %}</a></td>
-</tr>
-<tr>
-<th scope="row"><a href="/admin/labels/labeltemplate/">Label Templates</a></th>
-<td><a href="/admin/labels/labeltemplate/add/" class="addlink">{% trans 'Add' %}</a></td>
-</tr>
-</table></div><BR>
-
-{% if app_list %}
- {% for app in app_list %}
- <div class="module">
- <table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}">
- <caption><a href="{{ app.app_url }}" class="section">{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}</a></caption>
- {% for model in app.models %}
- <tr>
- {% if model.perms.change %}
- <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
- {% else %}
- <th scope="row">{{ model.name }}</th>
- {% endif %}
-
- {% if model.perms.add %}
- <td><a href="{{ model.admin_url }}add/" class="addlink">{% trans 'Add' %}</a></td>
- {% else %}
- <td> </td>
- {% endif %}
- </tr>
- {% endfor %}
- </table>
- </div>
- {% endfor %}
-{% else %}
- <p>{% trans "You don't have permission to edit anything." %}</p>
-{% endif %}
-</div>
-{% endblock %}
-
-{% block sidebar %}
-<div id="content-related">
- <div class="module" id="recent-actions-module">
- <h2>{% trans 'Recent Actions' %}</h2>
- <h3>{% trans 'My Actions' %}</h3>
- {% load log %}
- {% get_admin_log 10 as admin_log for_user user %}
- {% if not admin_log %}
- <p>{% trans 'None available' %}</p>
- {% else %}
- <ul class="actionlist">
- {% for entry in admin_log %}
- <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">
- {% if entry.is_deletion %}
- {{ entry.object_repr }}
- {% else %}
- <a href="{{ entry.get_admin_url }}">{{ entry.object_repr }}</a>
- {% endif %}
- <br/>
- {% if entry.content_type %}
- <span class="mini quiet">{% filter capfirst %}{% trans entry.content_type.name %}{% endfilter %}</span>
- {% else %}
- <span class="mini quiet">{% trans 'Unknown content' %}</span>
- {% endif %}
- </li>
- {% endfor %}
- </ul>
- {% endif %}
- </div>
-</div>
-{% endblock %}
+++ /dev/null
-<!--overrride pagination-->
-{% load admin_list %}
-{% load i18n %}
-<p class="paginator">
-{% if pagination_required %}
-{% for i in page_range %}
- {% paginator_number cl i %}
-{% endfor %}
-{% endif %}
-{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %}
-{% if show_all_url %}  <a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %}
-{% if cl.formset and cl.result_count %}<input type="submit" name="_save" class="default" value="{% trans 'Save' %}"/>{% endif %}
-</p>
+++ /dev/null
-{% load i18n %}<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
- "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
- version="XHTML+RDFa 1.0"
- xmlns:xml="http://www.w3.org/XML/1998/namespace"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
- xmlns:libns="http://jumpgate.caltech.edu/wiki/LibraryOntology#"
- xmlns:invns="http://jumpgate.caltech.edu/wiki/InventoryOntology#"
- xml:lang="en"
->
-<!--base.html-->
-<head>
- <title>{% block title %}{{ app_name }} - {{ page_name }}{% endblock %}</title>
-
-{% block additional_css %}
- {% load staticfiles %}
- {% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% static "css/rtl.css" %}{% endblock %}" />{% endif %}
- {% block extrastyle %}{% endblock %}
- {% block extrahead %}{% endblock %}
- {% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
- <link rel="stylesheet" type="text/css" href="{% static "css/data-browse-index.css" %}" />
-{% endblock %}
-
-</head>
-<body>
-<!-- Container -->
- {% if not is_popup %}
-
- <div id="header">
- <div id="branding">
- {% block branding %}{% endblock %}
- </div>
- <div id="user-tools">
- {% if user.is_authenticated %}
- {% trans 'Welcome,' %}
- <strong>{% firstof user.first_name user.username %}</strong>.
- {% block userlinks %}
- {% url "django.admindocs.docroot" as docsroot %}
- {% if docsroot %}
- <a href="{{ docsroot }}">{% trans 'Documentation' %}</a> /
- {% endif %}
- <a href="{{root_path}}/accounts/password_change/">{% trans 'Change password' %}</a> /
- <a href="{{root_path}}/accounts/logout/">{% trans 'Log out' %}</a>
- {% endblock %}
- {% else %}
- <a href="{{root_path}}/accounts/login/?next={{thispage}}">{% trans 'Log in' %}</a>
- {% endif %}
- </div>
- {% block nav-global %}{% endblock %}
- </div>
- {% endif %}
- {% block breadcrumbs %}{% endblock %}
- {% if messages %}
- <ul class="messagelist">{% for message in messages %}<li>{{ message }}</li>{% endfor %}</ul>
- {% endif %}
-
- <!-- Content -->
- <div id="content" class="{% block coltype %}colM{% endblock %}">
- {% block pretitle %}{% endblock %}
- {% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
- {% block content %}
- {% block object-tools %}{% endblock %}
- {{ content }}
- {% endblock %}
- {% block sidebar %}{% endblock %}
- </div>
- <!-- END Content -->
-
- {% block footer %}<div id="footer"></div>{% endblock %}
-<!-- END Container -->
-</body>
-</html>
+++ /dev/null
-{% extends "base.html" %}
-{% load staticfiles %}
-{% load i18n %}
-
-<link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}" />
-
-{% block title %}{{ sitename }}{% endblock %}
-
-{% block branding %}
-<h1 id="site-name">HTSWorkflow</h1>
-{% endblock %}
-
-{% block nav-global %}{% endblock %}
+++ /dev/null
-<div id="bcm_msg"></div>
-{{ bcmagic }}<br />
-<div id="bcm_status"></div>
+++ /dev/null
-{% if run_f %}
- <ul>
- RUN FOLDER: <li>{{ run_f.run_folder }}</li>
- </ul>
-{% else %}
- <p>Run folder not found.</p>
-{% endif %}
+++ /dev/null
-{% extends "base.html" %}
-{% load i18n %}
-
-{% block breadcrumbs %}
-<div class="breadcrumbs">
- <a href="/admin">{% trans 'Home' %}</a> ›
- <a href="/admin/experiments">Experiments</a> ›
- <a href="/admin/experiments/flowcell">flowcell</a> ›
- <a href="{{ flowcell.get_admin_url }}">{{ flowcell.flowcell_id }}</a>
-</div>
-{% endblock %}
-
-{% block content %}
-{% if warnings %}
-<hr/>
-<p>
-{% for user_admin_url, username in warnings %}
-Warning: User <a href="{{ user_admin_url}}">{{ username }}</a> has no
-email address <br/>
-{% endfor %}
-{% endif %}
-</p>
-{% for to, subject, body, sending in emails %}
-<hr/>
-{% if sending %}<b>Message:</b> {{ sending }}<br/>{% endif %}
-<b>From:</b> {{ from }}<br/>
-<b>To:</b> {{ to }}<br/>
-<b>Subject:</b> {{ subject }}<br/>
-<pre>
-{{ body }}
-</pre>
-{% endfor %}<hr/>
-<form method="get">
-<label for="bcc">BCC {% for m in site_managers %}{{ m }} {% endfor %}</label>
-<input type="checkbox" id="bcc" name="bcc" checked="on"/><br/>
-<input type="hidden" name="send" value="1"/>
-<input type="submit" value="Send Email"/>
-{% endblock %}
\ No newline at end of file
+++ /dev/null
-<html><head><title>{{ fc.flowcell_id }} - GA SEQUENCING (SOLEXA) LOG</title>
-<style type="text/css">
-<!--
-TD
- {
- color:black;
- font-size:9pt;
- font-face:Arial;
- }
--->
-</style>
-</head><body>
-{% if fc %}
-<table border="1" cellspacing="1">
-<tr><td colspan=2 nowrap><b>GA SEQUENCING (SOLEXA) LOG</b></td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td>Date Run Started</td><td colspan=2>{{ fc.run_date }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td>Cluster station used</td><td colspan=2 nowrap>{{ fc.cluster_station.name }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td>GA used</td><td colspan=2 nowrap>{{ fc.sequencer.name }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-
-<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td>Flowcell number</td><td colspan=2 nowrap>{{ fc.flowcell_id }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td>Number of Tiles per Lane</td><td>100</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td>Number of Cycles</td><td>{{ fc.read_length }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td><font point-size="9" face="Arial"><b>SAMPLE INFORMATION</b><font></td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
-<tr><td> </td><td>FC#</td><td> </td><td> </td><td> </td><td> </td><td> </td><td colspan=2 nowrap>FC bar code</td></tr>
-
-<tr><td valign=middle nowrap>Lane</td>
-{% for lane in fc.lane_set.all %}
-<td>{{ lane.lane_number }}</td>
-{% endfor %}
-</tr>
-<tr><td valign=middle nowrap>Solexa Library Number</td>
-{% for lane in fc.lane_set.all %}
-<td bgcolor=#CCFFCC>{{ lane.library.id }}</td>
-{% endfor %}
-</tr>
-
-<tr><td valign=middle nowrap>Sample Name</td>
-{% for lane in fc.lane_set.all %}
-<td bgcolor=#CCFFCC>{{ lane.library.library_name }}</td>
-{% endfor %}
-</tr>
-
-<tr><td valign=middle nowrap>Organism</td>
-{% for lane in fc.lane_set.all %}
-<td bgcolor=#CCFFCC>{{ lane.library.library_species.scientific_name }}</td>
-{% endfor %}
-</tr>
-
-<tr><td valign=middle nowrap>Submitter</td>
-{% for lane in fc.lane_set.all %}
-<td bgcolor=#CCFFCC>{{ lane.library.made_for }}</td>
-{% endfor %}
-</tr>
-
-
-<tr><td valign=middle nowrap>First time run?</td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td></tr>
-
-<tr><td valign=middle nowrap>Gel Cut Size (bp)</td>
-{% for lane in fc.lane_set.all %}
-<td bgcolor=#CCFFCC>{{ lane.library.gel_cut_size }}</td>
-{% endfor %}
-</tr>
-
-<tr><td valign=middle nowrap>Template Concentration (ng/ul)</td>
-{% for lane in fc.lane_set.all %}
-<td bgcolor=#CCFFCC>{{ lane.library.undiluted_concentration }}</td>
-{% endfor %}
-</tr>
-
-<tr><td valign=middle nowrap>Run Concentration (pM)</td>
-{% for lane in fc.lane_set.all %}
-<td bgcolor=#CCFFCC>{{ lane.pM }}</td>
-{% endfor %}
-</tr>
-
-</table>
-
-{% else %}
- <p>Flowcell object missing. Can't create sheet.</p>
-{% endif %}
-
-</body></html
+++ /dev/null
-{% extends "base_site.html" %}
-{% load staticfiles %}
-{% load humanize i18n %}
-{% block extrahead %}
- <!-- App Stuff -->
- <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}" />
- <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
-
- {% block additional_javascript %}
- {% endblock %}
-{% endblock %}
-
-{% block content %}
-<div>
- {% include "experiments/flowcell_header.html" %}
- <div class="htswdetail" typeof="libns:IlluminaFlowcell" resource="{{flowcell.get_absolute_url}}">
- <h2>Lanes</h2>
- <table>
- <thead>
- <tr>
- <td>Lane</td>
- <td>Library ID</td>
- <td>Library Name</td>
- <td>Species</td>
- <td>Comment</td>
- </tr>
- </thead>
- <tbody>
- {% for lane in lanes %}
- <tr>
- <td rel="libns:has_lane">
- <a href="{{lane.get_absolute_url}}" typeof="libns:IlluminaLane">
- <span property="libns:lane_number">{{lane.lane_number}}</span>
- </a>
- </td>
- <td rel="libns:library"
- about="{{lane.get_absolute_url}}"
- resource="{{lane.library.get_absolute_url}}">
- <a typeof="libns:Library" href="{{lane.library.get_absolute_url}}">
- <span property="libns:library_id"
- >{{lane.library.id}}</span></a>
- {% if user.is_staff %}
- <a href="{{lane.library.get_admin_url}}">
- <img class="icon_button"
- src="{% static "admin/img/icon_changelink.gif" %}"/>
- </a>{% endif %}
- </td>
- <td>
- <a href="{{lane.library.get_absolute_url}}">
- <span property="libns:name"
- about="{{lane.library.get_absolute_url}}"
- >{{lane.library.library_name}}</span>
- </a>
- </td>
- <td about="{{lane.library.get_absolute_url}}" rel="libns:species">
- <a href="{{lane.library.library_species.get_absolute_url}}"
- typeof="libns:Species">
- <span property="libns:species_name">{{ lane.library.library_species.scientific_name }}</span></a>
- </td>
- <td about="{{lane.get_absolute_url}}">
- <span property="libns:comment">{{lane.comment}}</span>
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- <div class="htsw_flowcell_ivc">
- {% for run in flowcell.datarun_set.all %}
- <h2>Run {{ run.runfolder_name }}</h2>
- {% if run.lane_files %}
- <table>
- <thead>
- <tr>
- <td>Lane</td>
- <td>IVC All</td>
- <td>IVC Call</td>
- <td>IVC Percent Base</td>
- <td>IVC Percent Base All</td>
- <td>IVC Percent Base Called</td>
- </tr>
- </thead>
- <tbody>
- {% for lane_id, lane_file_set in run.lane_files.items %}
- {% if lane_file_set.ivc_all %}
- <tr>
- <td>{{ lane_id }}</td>
- <td>
- <a href="{{ lane_file_set.ivc_all.get_absolute_url }}">
- <img height="84" width="126" alt="Lane {{lane_id }} IVC All"
- src="{{ lane_file_set.ivc_all.get_absolute_url }}"/></a>
- </td>
- <td>
- <a href="{{ lane_file_set.ivc_call.get_absolute_url }}">
- <img height="84" width="126" alt="Lane {{lane_id }} IVC Call"
- src="{{ lane_file_set.ivc_call.get_absolute_url }}"/>
- </a>
- </td>
- <td>
- <a href="{{ lane_file_set.ivc_percent_base.get_absolute_url }}">
- <img height="84" width="126" alt="Lane {{lane_id }} IVC % Base"
- src="{{ lane_file_set.ivc_percent_base.get_absolute_url }}"/>
- </a>
- </td>
- <td>
- <a href="{{ lane_file_set.ivc_percent_all.get_absolute_url }}">
- <img height="84" width="126" alt="Lane {{lane_id }} IVC % Base All"
- src="{{ lane_file_set.ivc_percent_all.get_absolute_url }}"/>
- </a>
- </td>
- <td>
- <a href="{{ lane_file_set.ivc_percent_call.get_absolute_url }}">
- <img height="84" width="126"
- alt="Lane {{lane_id }} IVC % Base Called"
- src="{{ lane_file_set.ivc_percent_call.get_absolute_url }}"/>
- </a>
- </td>
- </tr>
- {% endif %}
- {% endfor %}
- </tbody>
- </table>
- {% endif %}
- {% endfor %}
- </div>
- </div>
-</div>
-<!-- end flowcell_detail -->
-{% endblock %}
+++ /dev/null
-{% load staticfiles %}
-<div class="flowcell_identity" typeof="libns:IlluminaFlowcell" resource="{{flowcell.get_absolute_url}}">
- <h2>About this Flowcell</h2>
- <b>Flowcell</b>:
- <a href="{{flowcell.get_absolute_url}}"><span property="libns:flowcell_id">{{flowcell.flowcell_id}}</span></a>{% if user.is_staff %}<a href="{{flowcell.get_admin_url}}"><img class="icon_button" src="{% static "admin/img/icon_changelink.gif" %}" alt="Edit"/></a>{% endif%}
- <br/>
- <div rel="libns:sequenced_by">
- <div typeof="libns:Sequencer"
- about="{{flowcell.sequencer.get_absolute_url}}">
- <b>Instrument</b>:
- <span property="libns:sequencer_name">{{ flowcell.sequencer.name }}</span>
- {% if flowcell.sequencer.instrument_name %}
- (<span property="libns:sequencer_instrument">{{ flowcell.sequencer.instrument_name}}</span>)
- {% endif %}
- <br/>
- <b>Instrument Model</b>:
- <span property="libns:sequencer_model">{{flowcell.sequencer.model}}</span>
- <br/>
- </div>
- </div>
- {% for datarun in flowcell.datarun_set.all %}
- <b>Image Analysis</b>:
- <span property="libns:image_software">{{datarun.image_software}}</span>
- <span property="libns:image_version">{{datarun.image_version}}</span><br/>
- <b>Base Caller</b>:
- <span property="libns:basecall_software">{{datarun.basecall_software}}</span>
- <span property="libns:basecall_version">{{datarun.basecall_version}}</span><br/>
- <b>Alignment</b>:
- <span property="libns:alignment_software">{{datarun.alignment_software}}</span>
- <span property="libns:alignment_version">{{datarun.alignment_version}}</span><br/>
- {% endfor %}
- <b>Run Date</b>:
- <span property="libns:date" content="{{flowcell.run_date|date:'Y-m-d\TH:i:s'}}" datatype="xsd:dateTime">{{ flowcell.run_date }}</span><br/>
- <b>Type</b>:
- <span property="libns:flowcell_type">{{flowcell.flowcell_type}}</span><br/>
- <b>Read Length</b>:
- <span property="libns:read_length" datatype="xsd:integer">{{flowcell.read_length}}</span><br/>
- <b>Control Lane</b>:
- <span property="libns:control_lane">{{flowcell.control_lane}}</span><br/>
-
- <b>Notes</b>:
- <pre property="libns:flowcell_notes">{{flowcell.notes}}</pre>
- </div>
+++ /dev/null
-{% extends "base_site.html" %}
-{% load humanize i18n %}
-{% load staticfiles %}
-{% block extrahead %}
- <!-- App Stuff -->
- <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}"/>
- <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
-
- {% block additional_javascript %}
- {% endblock %}
-{% endblock %}
-
-{% block content %}
-<div id="lane_detail" class="htswdetail" typeof="libns:IlluminaLane" resource="{{lane.get_absolute_url}}">
- <div rel="libns:flowcell" resource="{{flowcell.get_absolute_url}}">
- {% include "experiments/flowcell_header.html" %}
- </div>
- <div class="flowcell_lane_detail">
- <h2>About this lane</h2>
- <b>Lane</b>:
- <span property="libns:lane_number">{{lane.lane_number}}</span><br/>
- <b>pM</b>:
- <span property="libns:pM" datatype="xsd:decimal">{{ lane.pM }}</span><br/>
- {% if lane.cluster_estimate %}
- <b>Cluster Estimate</b>:
- <span property="libns:cluster_estimate" datatype="xsd:decimal"
- content="{{lane.cluster_estimate}}">{{ lane.cluster_estimate|intcomma }}</span><br/>{% endif %}
- {% if lane.status %}
- <b>Lane Status</b>:
- <span property="libns:status">{{ lane.status }}</span><br/>{% endif %}
- {% if lane.comment %}
- <b>Comments</b>:
- <span property="libns:comment">{{ lane.comment }}</span><br/>{% endif %}
- </div>
- <hr/>
- {% include "sample_header.html" %}
- <hr/>
- <div class="htsw_flowcell_ivc">
- {% for run in flowcell.datarun_set.all %}
- <h2>Run {{ run.runfolder_name }}</h2>
- <table>
- <thead>
- <tr>
- <td>Lane</td>
- <td>IVC All</td>
- <td>IVC Call</td>
- <td>IVC Percent Base</td>
- <td>IVC Percent Base All</td>
- <td>IVC Percent Base Called</td>
- </tr>
- </thead>
- <tbody>
- {% for run, lane_number, lane_file_set in filtered_dataruns %}
- {% if lane_file_set.ivc_all %}
- <tr>
- <td>{{lane_number}}</td>
- <td>
- <a href="{{ lane_file_set.ivc_all.get_absolute_url }}">
- <img height="84" width="126" alt="Lane {{lane_id }} IVC All"
- src="{{ lane_file_set.ivc_all.get_absolute_url }}"/></a>
- </td>
- <td>
- <a href="{{ lane_file_set.ivc_call.get_absolute_url }}">
- <img height="84" width="126" alt="Lane {{lane_id }} IVC Call"
- src="{{ lane_file_set.ivc_call.get_absolute_url }}"/>
- </a>
- </td>
- <td>
- <a href="{{ lane_file_set.ivc_percent_base.get_absolute_url }}">
- <img height="84" width="126" alt="Lane {{lane_id }} IVC % Base"
- src="{{ lane_file_set.ivc_percent_base.get_absolute_url }}"/>
- </a>
- </td>
- <td>
- <a href="{{ lane_file_set.ivc_percent_all.get_absolute_url }}">
- <img height="84" width="126" alt="Lane {{lane_id }} IVC % Base All"
- src="{{ lane_file_set.ivc_percent_all.get_absolute_url }}"/>
- </a>
- </td>
- <td>
- <a href="{{ lane_file_set.ivc_percent_call.get_absolute_url }}">
- <img height="84" width="126"
- alt="Lane {{lane_id }} IVC % Base Called"
- src="{{ lane_file_set.ivc_percent_call.get_absolute_url }}"/>
- </a>
- </td>
- </tr>
- {% else %}
- <tr><td colspan="6">No data</td></tr>
- {% endif %}
- {% endfor %}
- </tbody>
- </table>
- {% endfor %}
- </div>
-</div>
-
-{% endblock %}
+++ /dev/null
-{% if data_run_list %}
- <table>
- {% for run in data_run_list %}
- <tr>
- <td>{{run.run_folder}}</td>
- <td><a href="fcsheet/{{run.fcid}}">sheet</td>
- <td><a href="started/{{run.fcid}}">started email</td>
- <td><a href="finished/{{run.fcid}}">finished email</td>
- </tr>
- {% endfor %}
- </table>
-{% else %}
- <p>No data runs are available.</p>
-{% endif %}
+++ /dev/null
-{% extends "base_site.html" %}
-{% load humanize i18n %}
-{% load staticfiles %}
-{% block extrahead %}
- <!-- App Stuff -->
- <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}" />
- <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
-
- {% block additional_javascript %}
- {% endblock %}
-{% endblock %}
-
-{% block content %}
- <h1>Sequencer</h1>
- <dl about="{{sequencer.get_absolute_url}}" typeof="libns:sequencer">
- <dt>Name</dt>
- <dl property="libns:sequencer_name">{{sequencer.name}}</dl>
- <dt>Instrument Name</dt>
- <dl property="libns:insrument_name">{{sequencer.instrument_name}}</dl>
- <dt>Model</dt>
- <dl property="libns:model">{{sequencer.model}}</dl>
- <dt>Comment</dt>
- <dl></dl>
- </dl>
-{% endblock %}
+++ /dev/null
-<p>
-The following libraries are on the flowcell {{ flowcell.flowcell_id }}
-which is a {{ flowcell.read_length }} base pair {% if flowcell.paired_end %}paired end{% else %}single ended{% endif %} flowcell.
-</p>
-<p>{% for lane in lanes %}
-Lane #{{ lane.lane_number }} :
-<a href="https://jumpgate.caltech.edu/library/{{lane.library.id}}">
-{{ lane.library.id }}</a>
-{{ lane.library.library_name }}<br/>
-{% endfor %}</p>
-<p>
-The data should be available at the following link when
-the pipeline finishes, probably in about {{ finish_low.days }} to {{ finish_high.days }}
-days from {{ now|date:"D, M d Y" }}
-</p>
-<p>
-<a href="https://jumpgate.caltech.edu/runfolders/{{ flowcell.sequencer}}/">
-https://jumpgate.caltech.edu/runfolders/{{ flowcell.sequencer }}
-</a></p>
+++ /dev/null
-The following libraries are on the flowcell {{ flowcell.flowcell_id }}
-which is a {{ flowcell.read_length }} base pair {% if flowcell.paired_end %}paired end{% else %}single ended{% endif %} flowcell.
-
-Lane : (Library Id) Library Name (Cluster Estimate)
-{% for lane in lanes %}
-Lane #{{ lane.lane_number }} : ({{ lane.library.id }}) {{ lane.library.library_name }} ({{ lane.cluster_estimate }})
- https://jumpgate.caltech.edu/library/{{ lane.library.id }}
-{% endfor %}
-
-The raw data should be available at the following link when the
-pipeline finishes, probably in about {{ finish_low.days }} to {{ finish_high.days }}
-days from {{ now|date:"D, M d Y" }}
-
-https://jumpgate.caltech.edu/runfolders/{{ flowcell.sequencer}}
-
-Username: gec
-Password: gecilluminadata
-
-- Jumpgate
+++ /dev/null
-^FX=========================
-^FX Harddrive Location Tracking Label
-^FX 300x375 dots
-^FX=========================
-
-^XA
-^LH 0,25
-
-^FO0,0
-^CF0,35
-^FB375,1,,C
-^FD{{ item.item_type.name }}:^FS
-
-^FX -------Text contains HD serial #-------------
-^FO15,75
-^CF0,42
-^FB325,3,,C
-^FD{% if use_uuid %}{{ item.uuid }}{% else %}{{ item.barcode_id }}{% endif %}^FS
-
-^FX -------Barcode contains HD serial #-----------
-^FO150,200
-^BXN,3,200
-^FD{% if use_uuid %}invu|{{ item.uuid }}{% else %}invb|{{ item.barcode_id }}{% endif %}^FS
-
-^XZ
+++ /dev/null
-^FX=========================
-^FX 3"x3" Label
-^FX=========================
-^XA
-
-
-^FX======== Left Side ===========
-
-^FX------------
-^FX ^LH changes the 0,0 point of all subsequent location references
-^FX------------
-
-^LH0,50
-
-^FX ---Header---
-
-^FO25,0
-^CF0,50
-^FB250,2,,C
-^FD{{ item.barcode_id }}^FS
-
-^FX ---Column 1: Flowcells---
-
-^FX-----------------
-^FX FB command for automatic text formatting:
-^FX ^FB[dot width of area], [max # of lines], [change line spacing], [justification: L, C, R, J], [hanging indent]
-^FX-----------------
-
-^CF0,30,30
-^FO75,125
-^FB275,19,,L
-^FD{% for flowcell in flowcell_id_list %}{{ flowcell }}{% if not forloop.last %}\&{% endif %}{% endfor %}^FS
-^FX ---Date---
-
-^FO0,725
-^CF0,35
-^FB300,2,,C
-^FD{{ oldest_rundate|date:"YMd" }} - {{ latest_rundate|date:"YMd" }}^FS
-
-^FX ---Barcode---
-
-^FO135,795
-^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS
-
-^FX======== Right Side ===========
-
-^LH300,60
-
-^FX ---Header---
-
-^FO0,0
-^CF0,50
-^FB600,2,,C
-^FD{{ barcode_id }}^FS
-
-^FX ---Dividing line---
-
-^FX---------------
-^FX GB command:
-^FX ^GB[box width], [box height], [border thickness], [color: B, W], [corner rounding: 0-8]^FS
-^FX---------------
-
-^FO0,100
-^GB0,600,10^FS
-
-^FX ---Column 2: Libraries 1-20---
-
-^CF0,30,30
-^FO75,100
-^FB100,20,,L
-^FD{% for lib_id in library_id_list_1_to_20 %}{{ lib_id }}{% if not forloop.last %}\&{% endif %}{% endfor %}^FS
-
-^FX ---Column 3: Libraries 21-40---
-
-^CF0,30,30
-^FO200,100
-^FB100,20,,L
-^FD{% for lib_id in library_id_list_21_to_40 %}{{ lib_id }}{% if not forloop.last %}\&{% endif %}{% endfor %}^FS
-
-^FX ---Column 4: Libraries 41-60---
-
-^CF0,30,30
-^FO325,100
-^FB100,20,,L
-^FD{% for lib_id in library_id_list_41_to_60 %}{{ lib_id }}{% if not forloop.last %}\&{% endif %}{% endfor %}^FS
-
-^FX ---Column 5: Libraries 61-80---
-
-^CF0,30,30
-^FO450,100
-^FB100,20,,L
-^FD{% for lib_id in library_id_list_61_to_80 %}{{ lib_id }}{% if not forloop.last %}\&{% endif %}{% endfor %}^FS
-
-^FX ---Date---
-
-^FO0,715
-^CF0,35
-^FB600,2,,C
-^FDRun Dates: {{ oldest_rundate|date:"YMd" }}-{{ latest_rundate|date:"YMd" }}^FS
-
-^FX ---Barcode---
-
-^FO255,785
-^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS
-
-^LH0,0
-^FX ---End---
-^XZ
\ No newline at end of file
+++ /dev/null
-{% extends "base_site.html" %}
-{% load admin_list i18n %}
-{% block extrahead %}
- <script type="text/javascript">
- $(document).ready(function() {
- $(window).resize(function() {
- var window_height = $(window).height();
- var position = $("#changelist table").position();
- height = window_height - position.top;
- $("#changelist table.filtered").height(height);
- $("#changelist-filter").height(height);
- });
- $(window).resize();
- });
- </script>
-{% endblock %}
-{% block bodyclass %}change-list{% endblock %}
-{% block coltype %}flex{% endblock %}
-{% block content %}
-<div id="inventory-index-div" >
- <div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
- {% block search %}{% search_form item_changelist %}{% endblock %}
-
- {% block pagination %}{% pagination item_changelist %}{% endblock %}
-
- {% block filters %}
- {% if item_changelist.has_filters %}
- <div id="changelist-filter">
- <h2 >{% trans 'Filter' %}</h2>
- {% for spec in item_changelist.filter_specs %}
- {% admin_list_filter cl spec %}
- {% endfor %}
- </div>
- {% endif %}
- {% endblock %}
- {% block summary_stats %}
- <table class="{% if cl.has_filters %} filtered{% endif %}">
- <thead >
- <tr >
- <td >UUID</td>
- <td >Barcode ID</td>
- <td >Location</td>
- <td >Model</td>
- <td >Vendor</td>
- <td >Created</td>
- <td >Contains</td>
- </tr>
- </thead>
- <tbody >
- {% for item in item_changelist.get_query_set %}
- <tr >
- <td >{{ item.uuid }}</td>
- <td >{{ item.barcode_id}}</td>
- <td >{{ item.location }}</td>
- <td >{{ item.item_type }}</td>
- <td ></td>
- <td >{{ item.creation_date }}</td>
- <td >
- {% for content in item.longtermstorage_set.all %}
- {{ content.flowcell }}
- {% endfor %}
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- {% endblock %}
-</div>
-{% endblock %}
+++ /dev/null
-{% extends "base_site.html" %}
-{% load admin_list i18n %}
-{% block extrahead %}
- <script type="text/javascript">
- $(document).ready(function() {
- $(window).resize(function() {
- var window_height = $(window).height();
- var position = $("#changelist table").position();
- height = window_height - position.top;
- $("#changelist table.filtered").height(height);
- $("#changelist-filter").height(height);
- });
- $(window).resize();
- });
- </script>
-{% endblock %}
-{% block bodyclass %}change-list{% endblock %}
-{% block coltype %}flex{% endblock %}
-{% block content %}
-<div id="inventory-index-div" >
- <div class="module{% if item_changelist.has_filters %} filtered{% endif %}" id="changelist">
- {% block search %}{% search_form item_changelist %}{% endblock %}
-
- {% block pagination %}{% pagination item_changelist %}{% endblock %}
-
- {% block filters %}
- {% if item_changelist.has_filters %}
- <div id="changelist-filter">
- <h2 >{% trans 'Filter' %}</h2>
- {% for spec in item_changelist.filter_specs %}
- {% admin_list_filter item_changelist spec %}
- {% endfor %}
- </div>
- {% endif %}
- {% endblock %}
- {% block summary_stats %}
- <table class="{% if item_changelist.has_filters %} filtered{% endif %}">
- <thead >
- <tr >
- <td >Name</td>
- <td >Description</td>
- </tr>
- </thead>
- <tbody >
- {% for itemtype in item_changelist.result_list %}
- <tr >
- <td ><a href="/inventory/it/{{ itemtype.name }}/">{{ itemtype.name }}</a></td>
- <td >{{ itemtype.description }}</td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- {% endblock %}
-</div>
-{% endblock %}
+++ /dev/null
-{% extends "base_site.html" %}
-{% load admin_list i18n %}
-{% block extrahead %}
- <script type="text/javascript">
- $(document).ready(function() {
- $(window).resize(function() {
- var window_height = $(window).height();
- var position = $("#changelist table").position();
- height = window_height - position.top;
- $("#changelist table.filtered").height(height);
- $("#changelist-filter").height(height);
- });
- $(window).resize();
- });
- </script>
-{% endblock %}
-{% block bodyclass %}change-list{% endblock %}
-{% block coltype %}flex{% endblock %}
-{% block content %}
-<div id="inventory-index-div" >
- <div class="module{% if item_changelist.has_filters %} filtered{% endif %}" id="changelist">
- {% block search %}{% search_form item_changelist %}{% endblock %}
-
- {% block pagination %}{% pagination item_changelist %}{% endblock %}
-
- {% block filters %}
- {% if item_changelist.has_filters %}
- <div id="changelist-filter">
- <h2 >{% trans 'Filter' %}</h2>
- {% for spec in item_changelist.filter_specs %}
- {% admin_list_filter item_changelist spec %}
- {% endfor %}
- </div>
- {% endif %}
- {% endblock %}
- {% block summary_stats %}
- <table class="{% if item_changelist.has_filters %} filtered{% endif %}">
- <thead >
- <tr >
- <td >UUID</td>
- <td >Barcode ID</td>
- <td >Location</td>
- <td >Model</td>
- <td >Vendor</td>
- <td >Created</td>
- <td >Contains</td>
- </tr>
- </thead>
- <tbody >
- {% for item in item_changelist.result_list %}
- <tr about="{{ item.get_absolute_url }}">
- <td ><a href="{{ item.get_absolute_url}}" rel="invns:uuid">{{ item.uuid }}</a></td>
- <td ><a href="/inventory/{{ item.barcode_id }}/" rel="invns:barcode">{{ item.barcode_id }}</a></td>
- <td property="invns:location">{{ item.location }}</td>
- <td property="invns:item_type">{{ item.item_type }}</td>
- <td ></td>
- <td property="invnfs:creation_date" content="{{item.creation_date|date:'Y-m-d\TH:i:s'}}" datatype="xsd:dateTime">{{ item.creation_date }}</td>
- <td class="cell_list" >
- {% for content in item.longtermstorage_set.all %}
- <a href="{{content.flowcell.get_absolute_url}}" rel="libns:flowcell_id">{{ content.flowcell }}</a>
- {% endfor %}
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- {% endblock %}
- </div>
-</div>
-{% endblock %}
+++ /dev/null
-{% extends "base_site.html" %}
-
-{% block content %}
-{% if item %}
- <h2>Item Summary:</h2>
- <a href="{% url "htsworkflow.frontend.inventory.views.index" %}{{item.uuid}}/print/">Print</a><br />
- <br />
- <b>UUID:</b> <span property="invns:uuid">{{item.uuid}}</span><br />
- <b>Barcode ID:</b> <span property="invns:barcode">{{ item.barcode_id }}</span><br />
- <b>Type:</b> <span property="invns:item_type">{{ item.item_type.name }}</span><br />
- <br />
- <b>Location:</b> <span property="invns:location">{{ item.location.name }}</span><br />
- <b>Status: </b> {% if item.status %}<span property="invns:status">{{ item.status.name }}</span>{% else %}N/A{% endif %}<br />
- <br />
- {% if item.item_info.model_id %}
- <b>Model ID:</b> <span property="invns:model">{{ item.item_info.model_id }}</span><br />
- {% endif %}
- {% if item.item_info.part_number %}
- <b>Part Number:</b> <span property="invns:part_number">{{ item.item_info.part_number }}</span><br />
- {% endif %}
- {% if item.item_info.lot_number %}
- <b>Lot Number:</b> <span property="invns:lot_number">{{ item.item_info.lot_number }}</span><br />
- {% endif %}
- <br />
- {% if item.item_info.url %}
- <b>Item Website:</b> <a href="{{ item.item_info.url }}" rel="invns:vendor_link">Link</a><br />
- {% endif %}
- <b>Vendor:</b> {% if item.item_info.vendor.url %}<a href="{{ item.item_info.vendor.url }}">{% endif %}{{ item.item_info.vendor.name }}{% if item.item_info.vendor.url %}</a>{% endif %}<br />
- <b>Purchase Date:</b>{% if item.item_info.purchase_date %}{{ item.item_info.purchase_date }}{% else %}N/A{% endif %}<br />
- <b>Warenty (Months):</b>{% if item.item_info.warenty_months %}{{item.item_info.warenty_months}}{% else %}N/A{% endif %}<br />
- <br />
- <b>Item Info Notes:</b>
- <p>
- {% if item.item_info.notes %}{{ item.item_info.notes }}{% else %}No notes found{% endif %}
- </p>
- <br />
- <b>Item Specific Notes:</b>
- <p>
- {% if item.notes %}{{ item.notes }}{% else %}No notes found{% endif %}
- </p>
- <br />
- <center><div id="lts-grid"></div></center>
-
-{% else %}
- <h3>Item with UUID of {{ uuid }} not found.</h3>
-{% endif %}
-{% endblock %}
+++ /dev/null
-{% extends "base_site.html" %}
-{% load i18n %}
-
-{% block additional_css %}{% load staticfiles %}{{ block.super }}
-<link rel="stylesheet" type="text/css" href="{% static "css/base.css" %}"/>
-<link rel="stylesheet" type="text/css" href="{% static "css/login.css" %}"/>
-{% endblock %}
-
-{% block title %}Login{% endblock %}
-{% block bodyclass %}login{% endblock %}
-
-{% block content %}
-{% if error_message %}
-<p class="errornote">{{ error_message }}</p>
-{% endif %}
-<div id="container">
- <h1>Login</h1>
-<form action="{{ app_path }}" method="post" id="login-form">
- {% csrf_token %}
- <div class="form-row">
- <label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
- </div>
- <div class="form-row">
- <label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
- <input type="hidden" name="this_is_the_login_form" value="1" />
- </div>
- <div class="submit-row">
- <label> </label><input type="submit" value="{% trans 'Log in' %}" />
- </div>
-</form>
-
-<script type="text/javascript">
-document.getElementById('id_username').focus()
-</script>
-</div>
-{% endblock %}
+++ /dev/null
-{% extends "base_site.html" %}
-
-{% block content %}
-<table>
- <tr><td>User Name:</td><td>{{ user.username }}</td></tr>
- <tr><td>Full Name:</td><td>{{ user.get_full_name }}</td></tr>
- <tr><td>E-mail:</td><td>{{ user.email }}</td></tr>
-</table>
-{% endblock %}
+++ /dev/null
-{% extends "admin/base_site.html" %}
-
-{% if main %}
-{% block content %}
-
- {{ main|safe }}
-
-{% endblock %}
-{% else %}
- <p>No content. Can't create report.</p>
-{% endif %}
+++ /dev/null
-{% load staticfiles %}
-<div id="librarydetail"
- about="{{lib.get_absolute_url}}"
- typeof="libns:Library">
- <div class="library_identity">
- <h2>Library Name</h2>
- <b>Library ID</b>:
- <a href="{{lib.get_absolute_url}}"><span property="libns:library_id">{{ lib.id }}</span></a>
- {% if user.is_staff %}<a href="{{lib.get_admin_url}}"><img class="icon_button" src="{% static "admin/img/icon_changelink.gif" %}" alt="Edit"/></a>{% endif %}
- <br />
- <b>Name</b>:
- <span property="libns:name">{{ lib.library_name }}</span>
- <br/>
- <b>Affiliations</b>:
- <ul>
- {% for individual in lib.affiliations.all %}
- <li property="libns:affiliation" content="{{individual.name}}">
- {{ individual.name }} ( {{ individual.contact }} )
- </li>
- {% endfor %}
- </ul>
- </div>
- <div class="library_sample_detail">
- <h2>Sample Details</h2>
- <b>Species</b>:
- <span property="libns:species_name" content="{{lib.library_species.scientific_name}}"><a href="{{lib.library_species.get_absolute_url}}">{{ lib.library_species.scientific_name }}</a></span>
- <br/>
- <b>Experiment Type</b>:
- <span property="libns:experiment_type">{{ lib.experiment_type }}</span>
- <br/>
- {% if lib.antibody %}
- <b>Antibody</b>:
- <span property="libns:antibody">{{ lib.antibody.antibodies }}</span>
- {% if lib.antibody.antibodies.nickname %}
- (<span property="libns:antibody_term">{{ lib.antibody.nickname }}</span>)
- {% endif %}
- <br/>
- {% endif %}
- {% if lib.cell_line %}
- <b>Background or Cell Line</b>:
- <span property="libns:cell_line">{{ lib.cell_line }}</span>
- <br/>
- {% endif %}
- {% if lib.condition %}
- <b>Condition</b>:
- <span property="libns:condition">{{ lib.condition.condition_name }}</span>
- {% if lib.condition.nickname %}
- (<span property="libns:condition_term">{{ lib.condition.nickname }}</span>)
- {% endif %}
- <br/>
- {% endif %}
- {% if lib.replicate %}
- <b>Replicate</b>:
- <span property="libns:replicate">{{ lib.replicate }}</span>
- <br/>
- {% endif %}
- </div>
- <div class="library_library_detail">
- <h2>Library Details</h2>
- <b>Library Type</b>:
- <span property="libns:library_type">{{ lib.library_type }}</span>
- <br/>
- <b>Multiplex Index</b>:
- <span property="libns:multiplex_index">{{ lib.index_sequence_text }}</span>
- <br/>
- <b>Creation Date</b>
- <span property="libns:date" content="{{lib.creation_date|date:'Y-m-d'}}T00:00:00" datatype="xsd:dateTime">{{ lib.creation_date }}</span>
- <br/>
- <b>Made By</b>:
- <span property="libns:made_by">{{ lib.made_by }}</span>
- <br/>
- {% if lib.gel_cut_size %}
- <b>Gel Cut Size</b>:
- <span property="libns:gel_cut" datatype="xsd:integer">{{ lib.gel_cut_size }}</span>
- <br/>
- {% endif %}
- {% if lib.insert_size %}
- <b>Insert Size</b>:
- <span property="libns:insert_size" datatype="xsd:integer">{{ lib.insert_size }}</span>
- <br/>
- {% endif %}
- {% if lib.undiluted_concentration %}
- <b>Concentration</b>:
- <span property="libns:concentration">{{ lib.undiluted_concentration }} ng/µl</span>
- <br/>
- {% endif %}
- {% if lib.stopping_point_name %}
- <b>Protocol Stopping Point</b>
- <span property="libns:stopping_point">{{ lib.stopping_point_name }}</span>
- <br/>
- {% endif %}
- </div>
-</div>
+++ /dev/null
-{% extends "base_site.html" %}
-{% load admin_list i18n %}
-
-{% block bodyclass %}change-list{% endblock %}
-{% block coltype %}flex{% endblock %}
-
-{% block content %}
-<div id="antibody-index-div">
-{% block body %}
-<table >
- <thead >
- <tr >
- <td >Antigene</td>
- <td >Nickname</td>
- <td >Antibodies</td>
- <td >Catalog</td>
- <td >Source</td>
- </tr>
- </thead>
- <tbody >
- {% for antibody in antibodies %}
- <tr >
- <td >
- {{ antibody.antigene }}
- </td>
- <td >
- {{ antibody.nickname }}
- </td>
- <td >
- {{ antibody.antibodies }}
- </td>
- <td >
- {{ antibody.catalog }}
- </td>
- <td >
- {{ antibody.source }}
- </td>
- </tr>
- {% endfor %}
- </tbody>
-</table>
-</div>
-{% endblock %}
-{% endblock %}
+++ /dev/null
-{% extends "base_site.html" %}
-{% load admin_list i18n %}
-
-{% block bodyclass %}change-list{% endblock %}
-{% block coltype %}flex{% endblock %}
-
-{% block content %}
-<div id="lanes-index-div">
- <div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
- {% block search %}{% search_form lanes %}{% endblock %}
-
- {% block filters %}
- {% if lanes.has_filters %}
- <div id="changelist-filter">
- <h2 >{% trans 'Filter' %}</h2>
- {% for spec in lanes.filter_specs %}
- {% admin_list_filter lanes spec %}
- {% endfor %}
- </div>
- {% endif %}
- {% endblock %}
-
-
- {% block pagination %}{% pagination lanes %}{% endblock %}
-
-{% block body %}
-<table >
- <thead >
- <tr >
- <td >Run Date</td>
- <td >Flowcell Type</td>
- <td >Cycles</td>
- <td >Flowcell ID</td>
- <td >Lane</td>
- <td >Library ID</td>
- <td >Library Name</td>
- </tr>
- </thead>
- <tbody >
- {% for lane in lanes.query_set %}
- <tr >
- <td >
- {{ lane.flowcell.run_date|date:"Y-M-d" }}
- </td>
- <td >
- {{ lane.flowcell.flowcell_type }}
- </td>
- <td >
- {{ lane.flowcell.read_length }}
- </td>
- <td >
- {{ lane.flowcell.flowcell_id }}
- </td>
- <td >
- {{ lane.lane_number }}
- </td>
- <td >
- <a href="/library/{{ lane.library_id }}">{{ lane.library_id }}</a>
- </td>
- <td >
- <a href="/library/{{ lane.library_id }}">{{ lane.library.library_name }}</a>
- </td>
- </tr>
- {% endfor %}
- </tbody>
-</table>
-</div>
-{% endblock %}
-{% endblock %}
+++ /dev/null
-{% extends "base_site.html" %}
-{% load staticfiles %}
-{% load humanize i18n %}
-{% block extrahead %}
- <!-- App Stuff -->
- <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}"/>
- <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
-
- {% block additional_javascript %}
- {% endblock %}
-{% endblock %}
-
-{% block content %}
- {% include "sample_header.html" %}
- <hr/>
- <div class="library_statistics">
- <h2>Raw Result Files</h2>
- <table>
- <thead>
- <tr>
- <td>Run Start Date</td>
- <td>Cycle</td>
- <td>Flowcell</td>
- <td>Lane</td>
- <td>Summary</td>
- <td>Eland</td>
- <td>Bed</td>
- <td>Archived</td>
- </tr>
- </thead>
- <tbody>
- {% if eland_results %}
- {% for result in eland_results %}
- <tr about="{{result.flowcell.get_absolute_url}}">
- <td property="libns:date" content="{{result.run_date|date:'Y-m-d\TH:i:s'}}" datatype="xsd:dateTime">{{ result.run_date|date}}</td>
- <td>{{ result.cycle }}</td>
- <td><a href="{{result.flowcell.get_absolute_url}}"><span property="libns:flowcell_id">{{ result.flowcell_id }}</span></a>{% if user.is_staff %}<a href="{{result.flowcell.get_admin_url}}"><img class="icon_button" src="{% static "admin/img/icon_changelink.gif" %}" alt="Edit"/></a>{% endif%}</td>
- <td>{{ result.lane.lane_number }}</td>
- <td><a href="{{ result.summary_url }}">Summary</a></td>
- <td><a href="{{ result.result_url }}">{{ result.result_label }}</a></td>
- <td>
- {% if result.bed_url %}
- <a href="{{ result.bed_url }}">Bed</a>
- {% endif %}
- </td>
- <td>
- {% if result.storage_ids %}
- {{ result.storage_ids|safe }}
- {% endif %}
- </td>
- </tr>
- {% endfor %}
- {% else %}
- <tr><td colspan="8">No data</td></tr>
- {% endif %}
- </tbody>
- </table>
-
- <h2>Lane Summary Statistics</h2>
- {% block summary_stats %}
- <table>
- <thead>
- <tr>
- <td colspan="7"></td>
- <td colspan="2">No Match</td>
- <td colspan="2">QC Failed</td>
- <td colspan="4">Unique</td>
- <td colspan="4">Repeat</td>
- </tr>
- <tr>
- <td>Cycles</td>
- <td>Flowcell</td>
- <td>Lane</td>
- <td>End</td>
- <td>Cluster / Tile</td>
- <td>pM</td>
- <td>Raw Reads</td>
- <td>total</td>
- <td>%</td>
- <td>total</td>
- <td>%</td>
- <td>0 mismatch</td>
- <td>1 mismatch</td>
- <td>2 mismatch</td>
- <td>Total</td>
- <td>0 mismatch</td>
- <td>1 mismatch</td>
- <td>2 mismatch</td>
- <td>Total</td>
- </tr>
- </thead>
- <tbody>
- {% if lane_summary_list %}
- {# ls short for lane summary #}
- {% for ls in lane_summary_list %}
- <tr about="{{ls.lane.get_absolute_url}}">
- <td>{{ ls.cycle_width }}</td>
- <td><a href="{{ls.flowcell.get_absolute_url}}">{{ ls.flowcell_id }}</a>
- </td>
- <td><a href="{{ls.lane.get_absolute_url}}">{{ ls.lane_id }}</a></td>
- <td>{% if ls.end %}{{ ls.end }}{% endif %}</td>
- <td>{{ ls.clusters.0|intcomma }}</td>
- <td>{{ ls.successful_pm }}</td>
- <td>{{ ls.reads|intcomma }}</td>
- <td>{{ ls.no_match|intcomma }}</td>
- <td>{{ ls.no_match_percent|stringformat:".2f" }}</td>
- <td>{{ ls.qc_failed|intcomma }}</td>
- <td>{{ ls.qc_failed_percent|stringformat:".2f" }}</td>
- <td>{{ ls.match_codes.U0|intcomma }}</td>
- <td>{{ ls.match_codes.U1|intcomma }}</td>
- <td>{{ ls.match_codes.U2|intcomma }}</td>
- <td {% if ls.unique_reads %}property="libns:total_unique_locations" content="{{ls.unique_reads}}" datatype="xsd:decimal"{% endif %}>{{ ls.unique_reads|intcomma }}</td>
- <td>{{ ls.match_codes.R0|intcomma }}</td>
- <td>{{ ls.match_codes.R1|intcomma }}</td>
- <td>{{ ls.match_codes.R2|intcomma }}</td>
- <td>{{ ls.repeat_reads|intcomma }}</td>
- </tr>
- {% endfor %}
- {% else %}
- <tr><td colspan="20">No data</td></tr>
- {% endif %}
- </tbody>
- </table>
-
- <h2>Flowcell Notes</h2>
- <table>
- <thead>
- <tr>
- <td>Flowcell ID</td>
- <td>Lane</td>
- <td>Comment</td>
- </tr>
- </thead>
- {% if lib.lane_set.all %}
- <tbody>
- {% for lane in lib.lane_set.all %}
- <tr rel="libns:has_lane"
- about="{{lib.get_absolute_url}}"
- resource="{{lane.get_absolute_url}}">
- <td>
- <a typeof="libns:IlluminaFlowcell" href="{{lane.flowcell.get_absolute_url}}">
- <span property="libns:flowcell_id"
- >{{lane.flowcell.flowcell_id}}</span></a>
- {% if user.is_staff %}
- <a href="{{lane.flowcell.get_admin_url}}">
- <img class="icon_button"
- src="{% static "admin/img/icon_changelink.gif" %}" alt="Edit"/>
- </a>
- {% endif%}
- </td>
- <td typeof="libns:IlluminaLane" about="{{lane.get_absolute_url}}">
- <span rel="libns:flowcell" resource="{{lane.flowcell.get_absolute_url}}"></span>
- <a href="{{lane.get_absolute_url}}">
- <span property="libns:lane_number"
- >{{ lane.lane_number }}</span>
- </a></td>
- <td>{{ lane.comment }}</td>
- </tr>
- {% endfor %}
- </tbody>
- {% endif %}
- </table>
- <br/>
- <hr/>
- <h2>Count of multi-reads</h2>
- {% for eland_lane in lane_summary_list %}
- {% if eland_lane.summarized_reads %}
- <h3>{{eland_lane.cycle_width}} {{ eland_lane.flowcell_id }} lane {{ eland_lane.lane_id }}
- {% if eland_lane.end %} end {{ eland_lane.end }}{% endif %}
- </h3>
- <ul about="{{eland_lane.lane.get_absolute_url}}">
- {% for name, counts in eland_lane.summarized_reads.items %}
- <li rel="libns:has_mappings">
- <b property="libns:mapped_to">{{ name }}</b>:
- <span property="libns:reads" content="{{counts}}" datatype="xsd:integer">{{ counts|intcomma }}</span></li>
- {% endfor %}
- </ul>
- {% endif %}
- {% endfor %}
- {% endblock %}
- </div>
-{% endblock %}
+++ /dev/null
-{% extends "base_site.html" %}
-{% load admin_list i18n %}
-{% load staticfiles %}
-{% block extrahead %}
- <!-- App Stuff -->
- <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}"/>
-
- {% block additional_javascript %}
- <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
- <script type="text/javascript" src="{% static "js/htsw.js" %}"></script>
- <script type="text/javascript">
- $(document).ready(function() {
- $(window).resize(function() {
- var window_height = $(window).height();
- var position = $("#changelist table").position();
- height = window_height - position.top;
- $("#changelist table.filtered").height(height);
- $("#changelist-filter").height(height);
- });
- $(window).resize();
- });
- </script>
- {% endblock %}
-{% endblock %}
-{% block bodyclass %}change-list{% endblock %}
-{% block coltype %}flex{% endblock %}
-
-{% block content %}
-<div id="library_header_link">
-{% if todo_only %}<a href="..">All</a>{% else %}<a href="not_run/">Not run</a>
-{% endif %}
-</div>
-<div id="library-index-div" >
- <div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
- {% block search %}{% search_form cl %}{% endblock %}
-
- {% block pagination %}{% pagination cl %}{% endblock %}
-
- {% block filters %}
- {% if cl.has_filters %}
- <div id="changelist-filter">
- <h2 >{% trans 'Filter' %}</h2>
- {% for spec in cl.filter_specs %}
- {% admin_list_filter cl spec %}
- {% endfor %}
- </div>
- {% endif %}
- {% endblock %}
- {% block summary_stats %}
- <table class="{% if cl.has_filters %} filtered{% endif %}">
- <thead >
- <tr >
- <td >Parent</td>
- <td >Library ID</td>
- <td >Species</td>
- <td >Library Name</td>
- <td colspan="3" >Single</td>
- <td colspan="3" >Paired</td>
- <td >HD</td>
- </tr>
- <tr >
- <td colspan="4"></td>
- <td><40</td>
- <td><100</td>
- <td>100+</td>
- <td><40</td>
- <td><100</td>
- <td>100+</td>
- <td></td>
- </tr>
- </thead>
- <tbody >
- {% for lib in library_list %}
- <tr typeof="libns:Library" about="{{lib.library.get_absolute_url}}">
- <td ><a href="{{lib.library.get_absolute_url}}">{{ lib.amplified_from }}</a></td>
- <td ><a href="{{lib.library.get_absolute_url}}"><span property="libns:library_id">{{ lib.library_id }}</span></a></td>
- <td rel="libns:species">
- <a typeof="libns:Species"
- href="{{lib.library.library_species.get_absolute_url}}">
- <span property="libns:species_name">{{ lib.species_name }}</span>
- </a>
- </td>
- <td >
- <a href="{{ lib.library.get_absolute_url }}">
- <span property="libns:name">{{ lib.library_name }}</span>
- </a>
- </td>
- <td bgcolor="#00BFFF">{{ lib.lanes_run.0.0 }}</td>
- <td bgcolor="#00BFFF">{{ lib.lanes_run.0.1 }}</td>
- <td bgcolor="#00BFFF">{{ lib.lanes_run.0.2 }}</td>
- <td bgcolor="#66CDAA">{{ lib.lanes_run.1.0 }}</td>
- <td bgcolor="#66CDAA">{{ lib.lanes_run.1.1 }}</td>
- <td bgcolor="#66CDAA">{{ lib.lanes_run.1.2 }}</td>
- {% if lib.is_archived %}
- <td ><img src="{% static "img/hdd_unmount.png" %}" alt="Archived" /></td>
- {% else %}
- <td ></td>
- {% endif %}
- </tr>
- {% endfor %}
- </tbody>
- </table>
- </div>
- {% endblock %}
-</div>
-{% endblock %}
+++ /dev/null
-{% extends "base_site.html" %}
-{% load staticfiles %}
-{% load humanize i18n %}
-{% block extrahead %}
- <!-- App Stuff -->
- <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}" />
- <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
-
- {% block additional_javascript %}
- {% endblock %}
-{% endblock %}
-
-{% block content %}
-<div id="genome_detail">
- <h2>About this Genome</h2>
- <b>Common Name</b>:
- <span property="libns:species_name">{{ species.common_name}}</span><br/>
- <b>Scientific Name</b>:
- <span property="libns:species_name">{{ species.scientific_name}}</span><br/>
-</div>
-{% endblock %}
+++ /dev/null
-{% load staticfiles %}
-{% load i18n %}
-{% if cl.search_fields %}
-<div id="toolbar"><form id="changelist-search" action="" method="get">
-<div><!-- DIV needed for valid HTML -->
-<label for="searchbar"><img src="{% static "img/admin/icon_searchbox.png" %}" alt="Search" /></label>
-<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" />
-<input type="submit" value="{% trans 'Go' %}" />
-{% if show_result_count %}
- <span class="small quiet">{% blocktrans count cl.result_count as counter %}1 result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?{% if cl.is_popup %}pop=1{% endif %}">{% blocktrans with cl.full_result_count as full_result_count %}{{ full_result_count }} total{% endblocktrans %}</a>)</span>
-{% endif %}
-{% for pair in cl.params.items %}
- {% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0 }}" value="{{ pair.1 }}"/>{% endifnotequal %}
-{% endfor %}
-</div>
-</form></div>
-<script type="text/javascript">document.getElementById("searchbar").focus();</script>
-{% endif %}
+++ /dev/null
-from django.conf.urls import include, patterns, url
-from django.contrib import admin
-import django
-admin.autodiscover()
-
-from django.conf import settings
-
-urlpatterns = patterns('',
- url('^accounts/login/$', 'django.contrib.auth.views.login'),
- url('^accounts/logout/$', 'django.contrib.auth.views.logout'),
- url('^accounts/logout_then_login/$', 'django.contrib.auth.views.logout_then_login'),
- url('^accounts/password_change/$', 'django.contrib.auth.views.password_change'),
- url('^accounts/password_change_done/$', 'django.contrib.auth.views.password_change_done'),
- #url('^accounts/profile/$', 'htsworkflow.frontend.samples.views.user_profile'),
- # Base:
- url(r'^eland_config/', include('htsworkflow.frontend.eland_config.urls')),
- ### MOVED Admin from here ###
- # Experiments:
- url(r'^experiments/', include('htsworkflow.frontend.experiments.urls')),
- ### Flowcell:
- url(r'^lane/(?P<lane_pk>\w+)',
- 'htsworkflow.frontend.experiments.views.flowcell_lane_detail'),
- url(r'^flowcell/(?P<flowcell_id>\w+)/((?P<lane_number>\w+)/)?$',
- 'htsworkflow.frontend.experiments.views.flowcell_detail'),
- ## AnalysTrack:
- ##(r'^analysis/', include('htsworkflow.frontend.analysis.urls')),
- ## Inventory urls
- url(r'^inventory/', include('htsworkflow.frontend.inventory.urls')),
- ## Report Views:
- ##url(r'^reports/', include('htsworkflow.frontend.reports.urls')),
- ## Library browser
- url(r'^library/$', 'htsworkflow.frontend.samples.views.library'),
- url(r'^library/not_run/$',
- 'htsworkflow.frontend.samples.views.library_not_run'),
- url(r'^library/(?P<lib_id>\w+)/$',
- 'htsworkflow.frontend.samples.views.library_to_flowcells'),
- url(r'^lanes_for/$', 'htsworkflow.frontend.samples.views.lanes_for'),
- url(r'^lanes_for/(?P<username>\w+)', 'htsworkflow.frontend.samples.views.lanes_for'),
- ### library id to admin url
- url(r'^library_id_to_admin_url/(?P<lib_id>\w+)/$',
- 'htsworkflow.frontend.samples.views.library_id_to_admin_url'),
- ### sample / library information
- url(r'^samples/', include('htsworkflow.frontend.samples.urls')),
- url(r'^sequencer/(?P<sequencer_id>\w+)',
- 'htsworkflow.frontend.experiments.views.sequencer'),
- ## Raw result files
- #url(r'^results/(?P<flowcell_id>\w+)/(?P<cnm>C[0-9]+-[0-9]+)/summary/',
- #'htsworkflow.frontend.samples.views.summaryhtm_fc_cnm'),
- #url(r'^results/(?P<flowcell_id>\w+)/(?P<cnm>C[0-9]+-[0-9]+)/eland_result/(?P<lane>[1-8])',
- #'htsworkflow.frontend.samples.views.result_fc_cnm_eland_lane'),
- #url(r'^results/(?P<fc_id>\w+)/(?P<cnm>C[1-9]-[0-9]+)/bedfile/(?P<lane>[1-8])/ucsc',
- #'htsworkflow.frontend.samples.views.bedfile_fc_cnm_eland_lane_ucsc'),
- #url(r'^results/(?P<fc_id>\w+)/(?P<cnm>C[1-9]-[0-9]+)/bedfile/(?P<lane>[1-8])',
- #'htsworkflow.frontend.samples.views.bedfile_fc_cnm_eland_lane'),
- url(r'^bcmagic/', include('htsworkflow.frontend.bcmagic.urls')),
-
- url(r'^admin/', include(admin.site.urls)),
-)
except ImportError, e:
import simplejson as json
-from htsworkflow.frontend.auth import apidata
+from htsworkflow.auth import apidata
from htsworkflow.util import api
from htsworkflow.util import alphanum
from htsworkflow.util.url import normalize_url
from django.test import TestCase
-from htsworkflow.frontend.auth import apidata
+from htsworkflow.auth import apidata
from htsworkflow.pipelines.retrieve_config import \
format_gerald_config, \
getCombinedOptions, \
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
-BASE_DIR = os.path.dirname(os.path.dirname(__file__))
+import sys
+DJANGO_ROOT = os.path.dirname(__file__)
+PROJECT_ROOT = os.path.dirname(DJANGO_ROOT)
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/
# Application definition
AUTHENTICATION_BACKENDS = (
- 'htsworkflow.frontend.samples.auth_backend.HTSUserModelBackend', )
+ 'samples.auth_backend.HTSUserModelBackend', )
CUSTOM_USER_MODEL = 'samples.HTSUser'
INSTALLED_APPS = (
'django.contrib.staticfiles',
'django.contrib.humanize',
- 'htsworkflow.frontend.eland_config',
- 'htsworkflow.frontend.samples',
- 'htsworkflow.frontend.experiments',
- 'htsworkflow.frontend.bcmagic',
- 'htsworkflow.frontend.inventory',
- 'htsworkflow.frontend.labels',
+ 'eland_config',
+ 'samples',
+ 'experiments',
+ 'bcmagic',
+ 'inventory',
+ 'labels',
)
MIDDLEWARE_CLASSES = (
)
TEMPLATE_DIRS = (
- os.path.join(BASE_DIR, 'htsworkflow', 'frontend', 'templates'),
- os.path.join(BASE_DIR, 'htsworkflow', 'templates'),
+ os.path.join(DJANGO_ROOT, 'templates'),
)
-ROOT_URLCONF = 'htsworkflow.frontend.urls'
+ROOT_URLCONF = 'htsworkflow.urls'
WSGI_APPLICATION = 'wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': os.path.join(BASE_DIR, 'fctracker.db'),
+ 'NAME': os.path.join(PROJECT_ROOT, 'fctracker.db'),
}
}
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.6/howto/static-files/
STATICFILES_DIRS = (
- os.path.join(BASE_DIR, 'htsworkflow', 'frontend', 'static'),
+ os.path.join(DJANGO_ROOT, 'static'),
)
STATIC_URL = '/static/'
# How often to recheck the result archive
RESCAN_DELAY=1
# Update this in settings_local to point to your flowcell result directory
-RESULT_HOME_DIR = os.path.join(BASE_DIR, 'test', 'result', 'flowcells')
+RESULT_HOME_DIR = os.path.join(PROJECT_ROOT, 'test', 'result', 'flowcells')
# configure who is sending email and who should get BCCs of announcments
NOTIFICATION_SENDER = "noreply@example.com"
--- /dev/null
+.strikeout { text-decoration: line-through; }
+
--- /dev/null
+#header {
+ background: #7F99BE url(/static/img/layout-browser-hd-bg.gif) repeat-x center;
+}
+#header h1 {
+ font-size: 16px;
+ color: #fff;
+ font-weight: normal;
+ padding: 5px 10px;
+}
+
+#left_bar {
+ position: absolute;
+ top: 5px;
+ left: 5px;
+ width: 172px;
+ height: auto;
+ min-height: 600px;
+}
+
+#main {
+ position: relative;
+ /* background: #BBBBFF; */
+ width:auto;
+ min-width:120px;
+ padding: 10px;
+ margin:0px 0px 0px 175px;
+ min-height:600px;
+}
+
+.icon_button {
+ border-style: solid;
+ border-width: 1px;
+ padding: 1px;
+ margin: 0px 0px -2px 2px;
+}
+
+div.msg {
+ color: white;
+ background: #880000;
+}
+
+div.htswdetail {
+ clear: both;
+ margin: 0;
+ padding: 0;
+}
+div.htswdetail table, div.htswdetail td {
+ border-style: solid;
+}
+div.htswdetail table {
+ border-width: 0 0 1px 1px;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+div.htswdetail td {
+ margin: 0;
+ padding: 3px;
+ border-width: 1px 1px 0 0;
+}
+div.htswdetail thead {
+ text-align: center;
+}
+div.htswdetail tbody {
+ text-align: left;
+ }
+div.htswdetail h1,
+div.htswdetail h2
+{
+ font-size: 150%;
+}
+
+div.htswdetail h3 {
+ font-size: 125%;
+ margin: 0;
+}
+
+div.htswdetail h4,
+div.htswdetail h5,
+div.htswdetail ul,
+div.htswdetail ol,
+div.htswdetail li
+{
+ list-style: none;
+ margin: 0;
+}
+
+div.htswdetail ul,
+div.htswdetail ol
+{
+ margin-bottom: .5em;
+}
+
+/* style library detail headers */
+div#librarydetail {
+ margin: 0;
+ padding: 0;
+}
+div#librarydetail table, div#librarydetail td {
+ border-style: solid;
+}
+div#librarydetail table {
+ border-width: 0 0 1px 1px;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+div#librarydetail td {
+ margin: 0;
+ padding: 3px;
+ border-width: 1px 1px 0 0;
+}
+div#librarydetail thead {
+ text-align: center;
+ }
+div#librarydetail tbody {
+ text-align: right;
+}
+div#librarydetail h1,
+div#librarydetail h2
+{
+ font-size: 150%;
+}
+
+div#librarydetail h3 {
+ font-size: 125%;
+ margin: 0;
+}
+
+div#librarydetail h4,
+div#librarydetail h5,
+div#librarydetail ul,
+div#librarydetail ol,
+div#librarydetail li
+{
+ list-style: none;
+ margin: 0;
+}
+
+div#librarydetail ul,
+div#librarydetail ol
+{
+ margin-bottom: .5em;
+}
+
+div.library_identity {
+ clear: left; float: left; margin: 5px; }
+div.library_sample_detail { float: left; margin: 5px; }
+div.library_library_detail { float: left; margin: 5px; }
+div.library_statistics { clear: both; border: 1px; }
+
+div.flowcell_identity { clear: left; float: left; margin: 5px;}
+div.flowcell_lane_detail { float: left; margin: 5px; }
\ No newline at end of file
--- /dev/null
+/*
+ DJANGO Admin
+ by Wilson Miner wilson@lawrence.com
+*/
+
+/* Block IE 5 */
+@import "null.css?\"\{";
+
+/* Import other styles */
+@import url('global.css');
+@import url('layout.css');
+
+/* Import patch for IE 6 Windows */
+/*\*/ @import "patch-iewin.css"; /**/
--- /dev/null
+@import url('base.css');
+
+/* CHANGELISTS */
+#changelist { margin-bottom: 0pm; }
+#changelist table { display: block; }
+#changelist table.filtered { overflow-y: scroll; }
+.change-list .filtered table { border-right:1px solid #ddd; }
+.change-list .filtered { min-height:400px; }
+.change-list .filtered { background:white url(../img/changelist-bg.gif) top right repeat-y !important; }
+.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { width:auto !important; }
+.change-list .filtered table tbody th { padding-right:1em; }
+#changelist .toplinks { border-bottom:1px solid #ccc !important; }
+#changelist .paginator { color:#666; border-top:1px solid #eee; border-bottom:1px solid #eee; background:white url(../img/nav-bg.gif) 0 180% repeat-x; overflow:hidden; }
+.change-list .filtered .paginator { border-right:1px solid #ddd; }
+
+/* CHANGELIST TABLES */
+#changelist table thead th { white-space:nowrap; }
+#changelist table tbody td { border-left: 1px solid #ddd; }
+#changelist table tfoot { color: #666; }
+#changelist tbody { }
+
+/* TOOLBAR */
+#changelist #toolbar { padding:3px; border-bottom:1px solid #ddd; background:#e1e1e1 url(../img/nav-bg.gif) top left repeat-x; color:#666; }
+#changelist #toolbar form input { font-size:11px; padding:1px 2px; }
+#changelist #toolbar form #searchbar { padding:2px; }
+#changelist #changelist-search img { vertical-align:middle; }
+
+/* FILTER COLUMN */
+/*position:absolute; top:0; right:0; z-index:1000; */
+#changelist-filter { float: right;
+ width: 20em;
+ border-left:1px solid #ddd; margin:0;
+ background:#efefef;
+ overflow-y: scroll; }
+#changelist-filter h2 { font-size:11px; padding:2px 5px; border-bottom:1px solid #ddd; }
+#changelist-filter h3 { font-size:12px; margin-bottom:0; }
+#changelist-filter ul { padding-left:0;margin-left:10px; }
+#changelist-filter li { list-style-type:none; margin-left:0; padding-left:0; }
+#changelist-filter a { color:#999; }
+#changelist-filter a:hover { color:#036; }
+#changelist-filter li.selected { border-left:5px solid #ccc; padding-left:5px;margin-left:-10px; }
+#changelist-filter li.selected a { color:#5b80b2 !important; }
+
+/* DATE DRILLDOWN */
+.change-list ul.toplinks { display:block; background:white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x; border-top:1px solid white; float:left; padding:0 !important; margin:0 !important; width:100%; }
+.change-list ul.toplinks li { float: left; width: 9em; padding:3px 6px; font-weight: bold; list-style-type:none; }
+.change-list ul.toplinks .date-back a { color:#999; }
+.change-list ul.toplinks .date-back a:hover { color:#036; }
+
+/* PAGINATOR */
+.paginator { font-size:11px; padding-top:10px; padding-bottom:10px; line-height:22px; margin:0; border-top:1px solid #ddd; }
+.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
+.paginator a.showall { padding:0 !important; border:none !important; }
+.paginator a.showall:hover { color:#036 !important; background:transparent !important; }
+.paginator .end { border-width:2px !important; margin-right:6px; }
+.paginator .this-page { padding:2px 6px; font-weight:bold; font-size:13px; vertical-align:top; }
+.paginator a:hover { color:white; background:#5b80b2; border-color:#036; }
--- /dev/null
+table, td {
+ border-style: solid;
+}
+table {
+ border-width: 0 0 1px 1px;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+thead {
+ text-align: center;
+}
+td {
+ margin: 0;
+ padding: 4px;
+ border-width: 1px 1px 0 0;
+}
+td.cell_list a {
+ display: block;
+}
+
--- /dev/null
+/* DASHBOARD */
+
+.dashboard .module table th {
+ width: 100%;
+}
+
+.dashboard .module table td {
+ white-space: nowrap;
+}
+
+.dashboard .module table td a {
+ display: block;
+ padding-right: .6em;
+}
+
+/* RECENT ACTIONS MODULE */
+
+.module ul.actionlist {
+ margin-left: 0;
+}
+
+ul.actionlist li {
+ list-style-type: none;
+}
+
+ul.actionlist li {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ -o-text-overflow: ellipsis;
+}
--- /dev/null
+@import url('changelists.css');
+@import url('click-table.css');
--- /dev/null
+@import url('base.css');
+@import url('widgets.css');
+
+/* FORM ROWS */
+.form-row { overflow:hidden; padding:8px 12px; font-size:11px; border-bottom:1px solid #eee; }
+.form-row img, .form-row input { vertical-align:middle; }
+form .form-row p { padding-left:0; font-size:11px; }
+
+/* FORM LABELS */
+form h4 { margin:0 !important; padding:0 !important; border:none !important; }
+label { font-weight:normal !important; color:#666; font-size:12px; }
+.required label, label.required { font-weight:bold !important; color:#333 !important; }
+
+/* RADIO BUTTONS */
+form ul.radiolist li { list-style-type:none; }
+form ul.radiolist label { float:none; display:inline; }
+form ul.inline { margin-left:0; padding:0; }
+form ul.inline li { float:left; padding-right:7px; }
+
+/* ALIGNED FIELDSETS */
+.aligned label { display:block; padding:3px 10px 0 0; float:left; width:8em; }
+.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField { width:350px; }
+form .aligned p, form .aligned ul { margin-left:7em; padding-left:30px; }
+form .aligned table p { margin-left:0; padding-left:0; }
+form .aligned p.help { padding-left:38px; }
+.aligned .vCheckboxLabel { float:none !important; display:inline; padding-left:4px; }
+.colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField { width:610px; }
+.checkbox-row p.help { margin-left:0; padding-left:0 !important; }
+fieldset .field-box { float:left; margin-right: 20px; }
+
+/* WIDE FIELDSETS */
+.wide label { width:15em !important; }
+form .wide p { margin-left:15em; }
+form .wide p.help { padding-left:38px; }
+.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField { width:450px; }
+
+/* COLLAPSED FIELDSETS */
+fieldset.collapsed * { display:none; }
+fieldset.collapsed h2, fieldset.collapsed { display:block !important; }
+fieldset.collapsed h2 { background-image:url(../img/nav-bg.gif); background-position:bottom left; color:#999; }
+fieldset.collapsed .collapse-toggle { padding:3px 5px !important; background:transparent; display:inline !important;}
+
+/* MONOSPACE TEXTAREAS */
+fieldset.monospace textarea { font-family:"Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace; }
+
+/* SUBMIT ROW */
+.submit-row { padding:5px 7px; text-align:right; background:white url(../img/nav-bg.gif) 0 100% repeat-x; border:1px solid #ccc; margin:5px 0; overflow:hidden; }
+.submit-row input { margin:0 0 0 5px; }
+.submit-row p { margin:0.3em; }
+.submit-row p.deletelink-box { float: left; }
+.submit-row .deletelink { background:url(../img/icon_deletelink.gif) 0 50% no-repeat; padding-left:14px; }
+
+/* CUSTOM FORM FIELDS */
+.vSelectMultipleField { vertical-align:top !important; }
+.vCheckboxField { border:none; }
+.vDateField, .vTimeField { margin-right:2px; }
+.vURLField { width:30em; }
+.vLargeTextField, .vXMLLargeTextField { width:48em; }
+.flatpages-flatpage #id_content { height:40.2em; }
+.module table .vPositiveSmallIntegerField { width:2.2em; }
+.vTextField { width:20em; }
+.vIntegerField { width:5em; }
+.vForeignKeyRawIdAdminField { width: 5em; }
+
+/* INLINES */
+.inline-group {padding:0; border:1px solid #ccc; margin:10px 0;}
+.inline-group .aligned label { width: 8em; }
+
+.inline-related {position:relative;}
+.inline-related h3 {margin: 0; color:#666; padding:3px 5px; font-size:11px; background:#e1e1e1 url(../img/nav-bg.gif) top left repeat-x; border-bottom:1px solid #ddd;}
+.inline-related h3 span.delete {padding-left:20px; position:absolute; top:2px; right:10px;}
+.inline-related h3 span.delete label {margin-left:2px; font-size: 11px;}
+.inline-related fieldset {margin: 0; background:#fff; border: none; }
+.inline-related fieldset.module h3 { margin:0; padding:2px 5px 3px 5px; font-size:11px; text-align:left; font-weight:bold; background:#bcd; color:#fff; }
+.inline-related.tabular fieldset.module table {width:100%;}
+.last-related fieldset {border: none;}
+
+.inline-group .tabular tr.has_original td {padding-top:2em;}
+.inline-group .tabular tr td.original { padding:2px 0 0 0; width:0; _position:relative; }
+.inline-group .tabular th.original {width:0px; padding:0;}
+.inline-group .tabular td.original p {position:absolute; left:0; height:1.1em; padding:2px 7px; overflow:hidden; font-size:9px; font-weight:bold; color:#666; _width:700px; }
+.inline-group ul.tools {padding:0; margin: 0; list-style:none;}
+.inline-group ul.tools li {display:inline; padding:0 5px;}
+.inline-group ul.tools a.add {background:url(../img/icon_addlink.gif) 0 50% no-repeat; padding-left:14px;}
--- /dev/null
+body { margin:0; padding:0; font-size:14px; font-family:"Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; }
+
+/* LINKS */
+a:link, a:visited { color: #5b80b2; text-decoration:none; }
+a:hover { color: #036; }
+a img { border:none; }
+a.section:link, a.section:visited { color: white; text-decoration:none; }
+
+/* GLOBAL DEFAULTS */
+p, ol, ul, dl { margin:.2em 0 .8em 0; }
+p { padding:0; line-height:140%; }
+
+h1,h2,h3,h4,h5 { font-weight:bold; }
+h1 { font-size:18px; color:#666; padding:0 6px 0 0; margin:0 0 .2em 0; }
+h2 { font-size:16px; margin:1em 0 .5em 0; }
+h2.subhead { font-weight:normal;margin-top:0; }
+h3 { font-size:14px; margin:.8em 0 .3em 0; color:#666; font-weight:bold; }
+h4 { font-size:12px; margin:1em 0 .8em 0; padding-bottom:3px; }
+h5 { font-size:10px; margin:1.5em 0 .5em 0; color:#666; text-transform:uppercase; letter-spacing:1px; }
+
+ul li { list-style-type:square; padding:1px 0; }
+ul.plainlist { margin-left:0 !important; }
+ul.plainlist li { list-style-type:none; }
+li ul { margin-bottom:0; }
+li, dt, dd { font-size:11px; line-height:14px; }
+dt { font-weight:bold; margin-top:4px; }
+dd { margin-left:0; }
+
+form { margin:0; padding:0; }
+fieldset { margin:0; padding:0; }
+
+blockquote { font-size:11px; color:#777; margin-left:2px; padding-left:10px; border-left:5px solid #ddd; }
+code, pre { font-family:"Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; background:inherit; color:#666; font-size:11px; }
+pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
+code strong { color:#930; }
+hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
+
+/* TEXT STYLES & MODIFIERS */
+.small { font-size:11px; }
+.tiny { font-size:10px; }
+p.tiny { margin-top:-2px; }
+.mini { font-size:9px; }
+p.mini { margin-top:-3px; }
+.help, p.help { font-size:10px !important; color:#999; }
+p img, h1 img, h2 img, h3 img, h4 img, td img { vertical-align:middle; }
+.quiet, a.quiet:link, a.quiet:visited { color:#999 !important;font-weight:normal !important; }
+.quiet strong { font-weight:bold !important; }
+.float-right { float:right; }
+.float-left { float:left; }
+.clear { clear:both; }
+.align-left { text-align:left; }
+.align-right { text-align:right; }
+.example { margin:10px 0; padding:5px 10px; background:#efefef; }
+.nowrap { white-space:nowrap; }
+
+/* TABLES */
+table { border-collapse:collapse; border-color:#ccc; }
+td, th { font-size:11px; line-height:13px; border-bottom:1px solid #eee; vertical-align:top; padding:5px; font-family:"Lucida Grande", Verdana, Arial, sans-serif; }
+th { text-align:left; font-size:12px; font-weight:bold; }
+thead th,
+tfoot td { color:#666; padding:2px 5px; font-size:11px; background:#e1e1e1 url(../img/nav-bg.gif) top left repeat-x; border-left:1px solid #ddd; border-bottom:1px solid #ddd; }
+tfoot td { border-bottom:none; border-top:1px solid #ddd; }
+thead th:first-child,
+tfoot td:first-child { border-left:none !important; }
+thead th.optional { font-weight:normal !important; }
+fieldset table { border-right:1px solid #eee; }
+tr.row-label td { font-size:9px; padding-top:2px; padding-bottom:0; border-bottom:none; color:#666; margin-top:-1px; }
+tr.alt { background:#f6f6f6; }
+.row1 { background:#EDF3FE; }
+.row2 { background:white; }
+
+/* SORTABLE TABLES */
+thead th a:link, thead th a:visited { color:#666; display:block; }
+table thead th.sorted { background-position:bottom left !important; }
+table thead th.sorted a { padding-right:13px; }
+table thead th.ascending a { background:url(../img/arrow-down.gif) right .4em no-repeat; }
+table thead th.descending a { background:url(../img/arrow-up.gif) right .4em no-repeat; }
+
+/* ORDERABLE TABLES */
+table.orderable tbody tr td:hover { cursor:move; }
+table.orderable tbody tr td:first-child { padding-left:14px; background-image:url(../img/nav-bg-grabber.gif); background-repeat:repeat-y; }
+table.orderable-initalized .order-cell, body>tr>td.order-cell { display:none; }
+
+/* FORM DEFAULTS */
+input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
+textarea { vertical-align:top !important; }
+input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
+
+/* FORM BUTTONS */
+.button, input[type=submit], input[type=button], .submit-row input { background:white url(../img/nav-bg.gif) bottom repeat-x; padding:3px; color:black; border:1px solid #bbb; border-color:#ddd #aaa #aaa #ddd; }
+.button:active, input[type=submit]:active, input[type=button]:active { background-image:url(../img/nav-bg-reverse.gif); background-position:top; }
+.button.default, input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; background:#7CA0C7 url(../img/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; float:right; }
+.button.default:active, input[type=submit].default:active { background-image:url(../img/default-bg-reverse.gif); background-position:top; }
+
+/* MODULES */
+.module { border:1px solid #ccc; margin-bottom:5px; background:white; }
+.module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; }
+.module blockquote { margin-left:12px; }
+.module ul, .module ol { margin-left:1.5em; }
+.module h3 { margin-top:.6em; }
+.module h2, .module caption, .inline-group h2 { margin:0; padding:2px 5px 3px 5px; font-size:11px; text-align:left; font-weight:bold; background:#7CA0C7 url(../img/default-bg.gif) top left repeat-x; color:white; }
+.module table { border-collapse: collapse; }
+
+/* MESSAGES & ERRORS */
+ul.messagelist { padding:0 0 5px 0; margin:0; }
+ul.messagelist li { font-size:12px; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border-bottom:1px solid #ddd; color:#666; background:#ffc url(../img/icon_success.gif) 5px .3em no-repeat; }
+.errornote { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:red;background:#ffc url(../img/icon_error.gif) 5px .3em no-repeat; }
+ul.errorlist { margin:0 !important; padding:0 !important; }
+.errorlist li { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:white; background:red url(../img/icon_alert.gif) 5px .3em no-repeat; }
+td ul.errorlist { margin:0 !important; padding:0 !important; }
+td ul.errorlist li { margin:0 !important; }
+.errors { background:#ffc; }
+.errors input, .errors select { border:1px solid red; }
+div.system-message { background: #ffc; margin: 10px; padding: 6px 8px; font-size: .8em; }
+div.system-message p.system-message-title { padding:4px 5px 4px 25px; margin:0; color:red; background:#ffc url(../img/icon_error.gif) 5px .3em no-repeat; }
+.description { font-size:12px; padding:5px 0 0 12px; }
+
+/* BREADCRUMBS */
+div.breadcrumbs { background:white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x; padding:2px 8px 3px 8px; font-size:11px; color:#999; border-top:1px solid white; border-bottom:1px solid #ccc; text-align:left; }
+
+/* ACTION ICONS */
+.addlink { padding-left:12px; background:url(../img/icon_addlink.gif) 0 .2em no-repeat; }
+.changelink { padding-left:12px; background:url(../img/icon_changelink.gif) 0 .2em no-repeat; }
+.deletelink { padding-left:12px; background:url(../img/icon_deletelink.gif) 0 .25em no-repeat; }
+a.deletelink:link, a.deletelink:visited { color:#CC3434; }
+a.deletelink:hover { color:#993333; }
+
+/* OBJECT TOOLS */
+.object-tools { font-size:10px; font-weight:bold; font-family:Arial,Helvetica,sans-serif; padding-left:0; float:right; position:relative; margin-top:-2.4em; margin-bottom:-2em; }
+.form-row .object-tools { margin-top:5px; margin-bottom:5px; float:none; height:2em; padding-left:3.5em; }
+.object-tools li { display:block; float:left; background:url(../img/tool-left.gif) 0 0 no-repeat; padding:0 0 0 8px; margin-left:2px; height:16px; }
+.object-tools li:hover { background:url(../img/tool-left_over.gif) 0 0 no-repeat; }
+.object-tools a:link, .object-tools a:visited { display:block; float:left; color:white; padding:.1em 14px .1em 8px; height:14px; background:#999 url(../img/tool-right.gif) 100% 0 no-repeat; }
+.object-tools a:hover, .object-tools li:hover a { background:#5b80b2 url(../img/tool-right_over.gif) 100% 0 no-repeat; }
+.object-tools a.viewsitelink, .object-tools a.golink { background:#999 url(../img/tooltag-arrowright.gif) top right no-repeat; padding-right:28px; }
+.object-tools a.viewsitelink:hover, .object-tools a.golink:hover { background:#5b80b2 url(../img/tooltag-arrowright_over.gif) top right no-repeat; }
+.object-tools a.addlink { background:#999 url(../img/tooltag-add.gif) top right no-repeat; padding-right:28px; }
+.object-tools a.addlink:hover { background:#5b80b2 url(../img/tooltag-add_over.gif) top right no-repeat; }
+
+/* OBJECT HISTORY */
+table#change-history { width:100%; }
+table#change-history tbody th { width:16em; }
--- /dev/null
+#header {
+ background: #7F99BE url(/static/img/layout-browser-hd-bg.gif) repeat-x center;
+}
+#header h1 {
+ font-size: 16px;
+ color: #fff;
+ font-weight: normal;
+ padding: 5px 10px;
+}
+
+#left_bar {
+ position: absolute;
+ top: 5px;
+ left: 5px;
+ width: 172px;
+ height: auto;
+ min-height: 600px;
+
+
+}
+
+#main {
+ position: relative;
+ /* background: #BBBBFF; */
+ width:auto;
+ min-width:120px;
+ padding: 10px;
+ margin:0px 0px 0px 175px;
+ min-height:600px;
+}
+
+div.msg {
+ color: white;
+ background: #880000;
+}
\ No newline at end of file
--- /dev/null
+/* PAGE STRUCTURE */
+#container { position:relative; width:100%; min-width:760px; padding:0; }
+#content { margin:10px 15px; }
+#header { width:100%; }
+#content-main { float:left; width:100%; }
+#content-related { float:right; width:18em; position:relative; margin-right:-19em; }
+#footer { clear:both; padding:10px; }
+
+/* COLUMN TYPES */
+.colMS { margin-right:20em !important; }
+.colSM { margin-left:20em !important; }
+.colSM #content-related { float:left; margin-right:0; margin-left:-19em; }
+.colSM #content-main { float:right; }
+.popup .colM { width:95%; }
+.subcol { float:left; width:46%; margin-right:15px; }
+.dashboard #content { width:500px; }
+
+/* HEADER */
+#header { background:#417690; color:#ffc; overflow:hidden; }
+#header a:link, #header a:visited { color:white; }
+#header a:hover { text-decoration:underline; }
+#branding h1 { padding:0 10px; font-size:18px; margin:8px 0; font-weight:normal; color:#f4f379; }
+#branding h2 { padding:0 10px; font-size:14px; margin:-8px 0 8px 0; font-weight:normal; color:#ffc; }
+#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
+
+/* SIDEBAR */
+#content-related h3 { font-size:12px; color:#666; margin-bottom:3px; }
+#content-related h4 { font-size:11px; }
+#content-related .module h2 { background:#eee url(../img/nav-bg.gif) bottom left repeat-x; color:#666; }
--- /dev/null
+/* Nothing to see here. Dummy file to feed to the high pass filter which hides CSS from IE5/win. Details: http://tantek.com/CSS/Examples/highpass.html */
\ No newline at end of file
--- /dev/null
+* html #container { position:static; } /* keep header from flowing off the page */
+* html .colMS #content-related { margin-right:0; margin-left:10px; position:static; } /* put the right sidebars back on the page */
+* html .colSM #content-related { margin-right:10px; margin-left:-115px; position:static; } /* put the left sidebars back on the page */
+* html .form-row { height:1%; }
+* html .dashboard #content { width:768px; } /* proper fixed width for dashboard in IE6 */
+* html .dashboard #content-main { width:535px; } /* proper fixed width for dashboard in IE6 */
+* html #changelist-filter ul { margin-right:-10px; } /* fix right margin for changelist filters in IE6 */
+* html .change-list .filtered { height:400px; } /* IE ignores min-height, but treats height as if it were min-height */
\ No newline at end of file
--- /dev/null
+#id_account_number { width: 50em; }
\ No newline at end of file
--- /dev/null
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+This copyright and license notice covers the following images:
+ * hdd_unmount.png
+************************************************************************
+
+TITLE: Crystal Project Icons
+AUTHOR: Everaldo Coelho
+SITE: http://www.everaldo.com
+CONTACT: everaldo@everaldo.com
+
+Copyright (c) 2006-2007 Everaldo Coelho.
--- /dev/null
+//-----------------------------------------------
+// Barcode Magic JavaScript
+// Authors: Brandon W. King
+// Feb. 2009
+//-----------------------------------------------
+
+//---------------------------------------
+// BCMagic Core Processing AJAX Callback
+//---------------------------------------
+//var bcmagic_process_callback = function(data, textStatus) {
+var bcmagic_process_callback = function(response, opt) {
+ //FIXME: temp bypass hack
+ var textStatus = 'success';
+ if (textStatus != 'success')
+ {
+ bcmagic_message('AJAX Status: '+textStatus);
+ return;
+ }
+
+ var data = Ext.decode(response.responseText);
+
+ for (key in data)
+ {
+ if (key == 'mode')
+ {
+ if (data['mode'] == 'clear')
+ {
+ bcmagic_status('','');
+ }
+ else if (data['mode'] == 'redirect')
+ {
+ if ('url' in data)
+ {
+ bcmagic_redirect(data['url']);
+ }
+ else
+ {
+ bcmagic_status('Error', 'No redirect URL provided by server');
+ }
+ }
+ else if (data['mode'] == 'autofill')
+ {
+ bcmagic_autofill(data['field'], data['value'])
+ }
+ else {
+ bcmagic_message('Message recieved!');
+ bcmagic_status(data['mode'], data['status']);
+ }
+
+ }
+ if (key == 'msg')
+ {
+ bcmagic_message(data['msg']);
+ }
+ }
+}
+
+var bcmagic_callback = function(data, textStatus)
+{
+ if (textStatus != 'success')
+ bcmagic_message('Failed!');
+ else
+ bcmagic_message('Success!');
+}
+
+var bcmagic_process = function(){
+ var magic = Ext.get("bcmagic_input_field");
+ var text = magic.getValue();
+ magic.dom.value = '';
+ magic.focus();
+
+ //var bcm_mode = $("#id_bcm_mode");
+ //var mode = bcm_mode.attr('value');
+ var mode = 'default';
+
+ // Show what we have captured
+ bcmagic_message('Sent command to server');
+ //$.post('/bcmagic/magic/', {'text': text, 'bcm_mode': mode}, bcmagic_process_callback, 'json');
+ Ext.Ajax.request({
+ url: '/bcmagic/magic/',
+ success: bcmagic_process_callback,
+ failure: function (r, o) { quick_msg('Some AJAX Fail!'); },
+ params: {'text': text, 'bcm_mode': mode}
+ });
+}
+
+var bcmagic_keyhandler = function(e) {
+ //Process upon enter key as input.
+ if (e.which == 13)
+ bcmagic_process();
+}
+
+//---------------------------------------
+// Utility Functions
+//---------------------------------------
+var bcmagic_message = function(text)
+{
+ // Show message
+ //$("#bcm_msg").html(text);
+ quick_msg(text);
+
+ // clear message after 3000ms
+ /*
+ setTimeout(function() {
+ $("#bcm_msg").html('');
+ }, 3000);
+ */
+}
+
+var bcmagic_status = function(state, text)
+{
+ //var msg = $('#bcm_status');
+ if (state.length > 0 || text.length > 0)
+ quick_msg(state+': '+text);
+ //else
+ // msg.html('');
+}
+
+
+var bcmagic_redirect = function(url)
+{
+ bcmagic_message('Redirecting to:' + url);
+ window.location = url;
+}
+
+var bcmagic_autofill = function(field, val)
+{
+ var txtbox = $('#'+field);
+ txtbox.attr('value', val);
+
+ var input_fields = $('form input').not(':hidden').not('[type=submit]');
+
+ // Count the number of text fields which have been filled in.
+ var count = 0;
+ input_fields.each( function(){
+ if(this.value.length > 0){
+ count = count + 1;
+ }
+ });
+
+ // If the number of text fields filled in is equal to the number of input_fields in the form, submit the form!
+ if (count == input_fields.length)
+ {
+ bcmagic_status('Form Full', 'Form is now full and ready to process');
+ form = $('form');
+ form.submit();
+ form.reset();
+
+ }
+ else
+ {
+ bcmagic_status('Form Fill Count', 'Count(' + count +') - Total(' + input_fields.length + ')');
+ }
+}
+
+//---------------------------------------
+// Main Ready Function
+//---------------------------------------
+/*$(document).ready(function() {
+
+ // Grab initial focus on magic text input
+ $("#id_magic").focus();
+
+ // Set some initial text
+ //$("#id_magic").attr('value','Moo cow!');
+
+ // Trigger when enterkey is pressed
+ $("#id_magic").keypress(bcmagic_keyhandler)
+});*/
\ No newline at end of file
--- /dev/null
+
+var inventory_item_dblclick_handler = function(grid, row_index, e){
+ //quick_msg('Choose Row: ' + row_index);
+ var rec = grid.getStore().getAt(row_index);
+ //quick_msg('UUID: ' + rec.get('uuid'));
+ goto_url('/inventory/'+rec.get('uuid')+'/');
+}
+
+var getInventoryDataGrid = function(){
+
+ var Item = Ext.data.Record.create([
+ { name: 'uuid' },
+ { name: 'barcode_id'},
+ { name: 'model_id'},
+ { name: 'part_number'},
+ { name: 'lot_number'},
+ { name: 'vendor'},
+ { name: 'creation_date'/*, type: 'date', dateFormat: 'n/j h:ia'*/},
+ { name: 'modified_date'/*, type: 'date', dateFormat: 'n/j h:ia'*/},
+ { name: 'location'},
+ { name: 'status'},
+ { name: 'flowcells'},
+ { name: 'type'}
+ ]);
+
+ var inventoryReader = new Ext.data.JsonReader(
+ {
+ totalProperty: "results",
+ root: "rows",
+ idProperty: "uuid"
+ },
+ Item
+ );
+
+ /*
+ var inventoryStore = new Ext.data.JsonStore({
+ autoDestory: true,
+ url: '/inventory/data/items/',
+ storeId: 'item_store',
+
+ });
+ */
+
+ var grid = new Ext.grid.GridPanel({
+ store: new Ext.data.GroupingStore({
+ reader: inventoryReader,
+ url: '/inventory/data/items/',
+ storeId: 'item_group_store',
+ groupField: 'type',
+ sortInfo: { field: 'creation_date', direction: "DESC"},
+ autoLoad: true
+ }),
+
+ columns: [
+ {id: 'uuid', header:"UUID", width: 32, sortable: true, dataIndex: 'uuid'},
+ {header: 'Barcode ID', width: 20, sortable: true, dataIndex: 'barcode_id'},
+ {header: 'Location', width: 20, sortable: true, dataIndex: 'location'},
+ {header: 'Model', width: 20, sortable: true, dataIndex: 'model_id'},
+ {header: 'Part #', width: 20, sortable: true, dataIndex: 'part_number', hidden: true},
+ {header: 'Lot #', width: 20, sortable: true, dataIndex: 'lot_number', hidden: true},
+ {header: 'Vendor', width: 20, sortable: true, dataIndex: 'vendor'},
+ {header: 'Creation Date', width: 20, sortable: true, dataIndex: 'creation_date'/*, renderer: Ext.util.Format.dateRenderer('Y/m/d')*/},
+ {header: 'Modified Date', width: 20, sortable: true, dataIndex: 'modified_date', hidden: true/*, renderer: Ext.util.Format.dateRenderer('Y/m/d')*/},
+ {header: 'Status', width: 20, sortable: true, dataIndex: 'status', hidden: true},
+ {header: 'Stored Flowcells', width: 20, sortable: true, dataIndex: 'flowcells'},
+ {header: 'Type', width: 20, sortable: true, dataIndex: 'type', hidden: true}
+ ],
+
+ view: new Ext.grid.GroupingView({
+ forceFit: true,
+ groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
+ }),
+
+ frame: true,
+ width: 'auto',
+ //height: 500,
+ //autoHeight: true,
+ collapsible: false,
+ title: "Inventory Index",
+ iconCls: 'icon-grid',
+ id: 'inventory_item_panel',
+ stateId: 'inventory_item_panel_state',
+ stateful: true
+ //renderTo: 'grid_target'
+ });
+
+ grid.on('rowdblclick', inventory_item_dblclick_handler);
+
+ return grid;
+}
\ No newline at end of file
--- /dev/null
+/**\r
+ * jQuery.timers - Timer abstractions for jQuery\r
+ * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)\r
+ * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).\r
+ * Date: 2008/08/26\r
+ *\r
+ * @author Blair Mitchelmore\r
+ * @version 1.0.0\r
+ *\r
+ **/\r
+\r
+jQuery.fn.extend({\r
+ everyTime: function(interval, label, fn, times, belay) {\r
+ return this.each(function() {\r
+ jQuery.timer.add(this, interval, label, fn, times, belay);\r
+ });\r
+ },\r
+ oneTime: function(interval, label, fn) {\r
+ return this.each(function() {\r
+ jQuery.timer.add(this, interval, label, fn, 1);\r
+ });\r
+ },\r
+ stopTime: function(label, fn) {\r
+ return this.each(function() {\r
+ jQuery.timer.remove(this, label, fn);\r
+ });\r
+ }\r
+});\r
+\r
+jQuery.extend({\r
+ timer: {\r
+ guid: 1,\r
+ global: {},\r
+ regex: /^([0-9]+)\s*(.*s)?$/,\r
+ powers: {\r
+ // Yeah this is major overkill...\r
+ 'ms': 1,\r
+ 'cs': 10,\r
+ 'ds': 100,\r
+ 's': 1000,\r
+ 'das': 10000,\r
+ 'hs': 100000,\r
+ 'ks': 1000000\r
+ },\r
+ timeParse: function(value) {\r
+ if (value == undefined || value == null)\r
+ return null;\r
+ var result = this.regex.exec(jQuery.trim(value.toString()));\r
+ if (result[2]) {\r
+ var num = parseInt(result[1], 10);\r
+ var mult = this.powers[result[2]] || 1;\r
+ return num * mult;\r
+ } else {\r
+ return value;\r
+ }\r
+ },\r
+ add: function(element, interval, label, fn, times, belay) {\r
+ var counter = 0;\r
+ \r
+ if (jQuery.isFunction(label)) {\r
+ if (!times) \r
+ times = fn;\r
+ fn = label;\r
+ label = interval;\r
+ }\r
+ \r
+ interval = jQuery.timer.timeParse(interval);\r
+\r
+ if (typeof interval != 'number' || isNaN(interval) || interval <= 0)\r
+ return;\r
+\r
+ if (times && times.constructor != Number) {\r
+ belay = !!times;\r
+ times = 0;\r
+ }\r
+ \r
+ times = times || 0;\r
+ belay = belay || false;\r
+ \r
+ if (!element.$timers) \r
+ element.$timers = {};\r
+ \r
+ if (!element.$timers[label])\r
+ element.$timers[label] = {};\r
+ \r
+ fn.$timerID = fn.$timerID || this.guid++;\r
+ \r
+ var handler = function() {\r
+ if (belay && this.inProgress) \r
+ return;\r
+ this.inProgress = true;\r
+ if ((++counter > times && times !== 0) || fn.call(element, counter) === false)\r
+ jQuery.timer.remove(element, label, fn);\r
+ this.inProgress = false;\r
+ };\r
+ \r
+ handler.$timerID = fn.$timerID;\r
+ \r
+ if (!element.$timers[label][fn.$timerID]) \r
+ element.$timers[label][fn.$timerID] = window.setInterval(handler,interval);\r
+ \r
+ if ( !this.global[label] )\r
+ this.global[label] = [];\r
+ this.global[label].push( element );\r
+ \r
+ },\r
+ remove: function(element, label, fn) {\r
+ var timers = element.$timers, ret;\r
+ \r
+ if ( timers ) {\r
+ \r
+ if (!label) {\r
+ for ( label in timers )\r
+ this.remove(element, label, fn);\r
+ } else if ( timers[label] ) {\r
+ if ( fn ) {\r
+ if ( fn.$timerID ) {\r
+ window.clearInterval(timers[label][fn.$timerID]);\r
+ delete timers[label][fn.$timerID];\r
+ }\r
+ } else {\r
+ for ( var fn in timers[label] ) {\r
+ window.clearInterval(timers[label][fn]);\r
+ delete timers[label][fn];\r
+ }\r
+ }\r
+ \r
+ for ( ret in timers[label] ) break;\r
+ if ( !ret ) {\r
+ ret = null;\r
+ delete timers[label];\r
+ }\r
+ }\r
+ \r
+ for ( ret in timers ) break;\r
+ if ( !ret ) \r
+ element.$timers = null;\r
+ }\r
+ }\r
+ }\r
+});\r
+\r
+if (jQuery.browser.msie)\r
+ jQuery(window).one("unload", function() {\r
+ var global = jQuery.timer.global;\r
+ for ( var label in global ) {\r
+ var els = global[label], i = els.length;\r
+ while ( --i )\r
+ jQuery.timer.remove(els[i], label);\r
+ }\r
+ });\r
--- /dev/null
+//-----------------------------------------------
+// Barcode Magic JavaScript
+// Authors: Brandon W. King
+// Feb. 2009
+//-----------------------------------------------
+
+//---------------------------------------
+// BCMagic Core Processing AJAX Callback
+//---------------------------------------
+var bcmagic_process_callback = function(data, textStatus) {
+ if (textStatus != 'success')
+ {
+ bcmagic_message('AJAX Status: '+textStatus);
+ return;
+ }
+
+ for (key in data)
+ {
+ if (key == 'mode')
+ {
+ if (data['mode'] == 'clear')
+ {
+ bcmagic_status('','');
+ }
+ else if (data['mode'] == 'redirect')
+ {
+ if ('url' in data)
+ {
+ bcmagic_redirect(data['url']);
+ }
+ else
+ {
+ bcmagic_status('Error', 'No redirect URL provided by server');
+ }
+ }
+ else if (data['mode'] == 'autofill')
+ {
+ bcmagic_autofill(data['field'], data['value'])
+ }
+ else {
+ bcmagic_message('Message recieved!');
+ bcmagic_status(data['mode'], data['status']);
+ }
+
+ }
+ if (key == 'msg')
+ {
+ bcmagic_message(data['msg']);
+ }
+ }
+}
+
+var bcmagic_callback = function(data, textStatus)
+{
+ if (textStatus != 'success')
+ bcmagic_message('Failed!');
+ else
+ bcmagic_message('Success!');
+}
+
+var bcmagic_process = function(){
+ var magic = $("#id_magic");
+ var text = magic.attr('value');
+ magic.attr('value', '');
+
+ var bcm_mode = $("#id_bcm_mode");
+ var mode = bcm_mode.attr('value');
+
+ // Show what we have captured
+ bcmagic_message('Sent command to server');
+ $.post('/bcmagic/magic/', {'text': text, 'bcm_mode': mode}, bcmagic_process_callback, 'json');
+}
+
+var bcmagic_keyhandler = function(e) {
+ //Process upon enter key as input.
+ if (e.which == 13)
+ bcmagic_process();
+}
+
+//---------------------------------------
+// Utility Functions
+//---------------------------------------
+var bcmagic_message = function(text)
+{
+ // Show message
+ $("#bcm_msg").html(text);
+
+ // clear message after 3000ms
+ setTimeout(function() {
+ $("#bcm_msg").html('');
+ }, 3000);
+}
+
+var bcmagic_status = function(state, text)
+{
+ var msg = $('#bcm_status');
+ if (state.length > 0 || text.length > 0)
+ msg.html('<b>'+state+':</b> '+text);
+ else
+ msg.html('');
+}
+
+
+var bcmagic_redirect = function(url)
+{
+ bcmagic_message('Redirecting to:' + url);
+ window.location = url;
+}
+
+var bcmagic_autofill = function(field, val)
+{
+ var txtbox = $('#'+field);
+ txtbox.attr('value', val);
+
+ var input_fields = $('form input').not(':hidden').not('[type=submit]');
+
+ // Count the number of text fields which have been filled in.
+ var count = 0;
+ input_fields.each( function(){
+ if(this.value.length > 0){
+ count = count + 1;
+ }
+ });
+
+ // If the number of text fields filled in is equal to the number of input_fields in the form, submit the form!
+ if (count == input_fields.length)
+ {
+ bcmagic_status('Form Full', 'Form is now full and ready to process');
+ form = $('form');
+ form.submit();
+ form.reset();
+
+ }
+ else
+ {
+ bcmagic_status('Form Fill Count', 'Count(' + count +') - Total(' + input_fields.length + ')');
+ }
+}
+
+//---------------------------------------
+// Main Ready Function
+//---------------------------------------
+/*$(document).ready(function() {
+
+ // Grab initial focus on magic text input
+ $("#id_magic").focus();
+
+ // Set some initial text
+ //$("#id_magic").attr('value','Moo cow!');
+
+ // Trigger when enterkey is pressed
+ $("#id_magic").keypress(bcmagic_keyhandler)
+});*/
\ No newline at end of file
--- /dev/null
+<html>
+ <head>
+ <title>404 - Not Found</title>
+ </head>
+ <body>
+ <h1>404 - Not Found</h1>
+ <p>The URL you tried to reach does not appear to exist,
+ if you have reason to believe this in error, please try again later.</p>
+ </body>
+</html>
+
--- /dev/null
+{% extends "admin/change_form.html" %}
+{% load i18n %}
+
+{% block after_field_sets %}
+
+<p>{% trans "First, enter a username and password. Then, you'll be able to edit more user options." %}</p>
+
+<fieldset class="module aligned">
+
+<div class="form-row">
+ {{ form.username.errors }}
+ {# TODO: get required class on label_tag #}
+ <label for="id_username" class="required">{% trans 'Username' %}:</label> {{ form.username }}
+ <p class="help">{{ form.username.help_text }}</p>
+</div>
+
+<div class="form-row">
+ {{ form.first_name.errors }}
+ {{ form.last_name.errors }}
+ {# TODO: get required class on label_tag #}
+ <div class="field-box">
+ <label for="first_name" >{% trans 'First Name' %}:</label> {{ form.first_name }}
+ <p class="help">{{ form.first_name.help_text }}</p>
+ </div>
+ <div class="field-box">
+ <label for="last_name" >{% trans 'Last Name' %}:</label> {{ form.last_name }}
+ <p class="help">{{ form.last_name.help_text }}</p>
+ </div>
+</div>
+
+<div class="form-row">
+ {{ form.password1.errors }}
+ {# TODO: get required class on label_tag #}
+ <label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
+</div>
+
+<div class="form-row">
+ {{ form.password2.errors }}
+ {# TODO: get required class on label_tag #}
+ <label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
+ <p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
+</div>
+
+<script type="text/javascript">document.getElementById("id_username").focus();</script>
+
+</fieldset>
+{% endblock %}
--- /dev/null
+{% extends "admin/base.html" %}
+{% load i18n %}
+
+{% block title %}
+{{ title }}|{%trans "dev site admin" %}
+{% endblock %}
+
+{% block branding %}
+<h1 id="site-name" style="background-color:#cccccc;color:black">
+ {%block sitename %}
+ {% trans 'HTS Workflow Dev Server' %}
+ {%endblock%}
+</h1>
+{% endblock %}
+
+{% block nav-global %}{% endblock %}
--- /dev/null
+{% extends "admin/change_form.html" %}
+{% load i18n %}
+{% block object-tools %}
+{% if change %}{% if not is_popup %}
+ <ul class="object-tools">
+ <li><a href="../../../../{{ app_label }}/started/{{ object_id }}/">{% trans "Started Email" %}</a></li>
+ <li><a href="history/" class="historylink">{% trans "History" %}</a></li>
+ {% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
+ </ul>
+{% endif %}{% endif %}
+{% endblock %}
--- /dev/null
+{% extends "admin/base_site.html" %}
+{% load i18n %}
+
+{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% load staticfiles %}{% static "css/dashboard.css" %}"/>{% endblock %}
+
+{% block coltype %}colMS{% endblock %}
+
+{% block bodyclass %}dashboard{% endblock %}
+
+{% block breadcrumbs %}{% endblock %}
+
+{% block content %}
+<div id="content-main">
+
+<div class='module'>
+<table>
+<caption>Frequently Used</caption>
+<tr>
+<th scope="row"><a href="/admin/samples/library/">Libraries</a></th>
+<td><a href="/admin/samples/library/add/" class="addlink">{% trans 'Add' %}</a></td>
+</tr>
+<tr>
+<th scope="row"><a href="/admin/experiments/flowcell/">Flowcells</a></th>
+<td><a href="/admin/experiments/flowcell/add/" class="addlink">{% trans 'Add' %}</a></td>
+</tr>
+</table></div>
+
+<div class='module'>
+<table>
+<caption>Label Printing</caption>
+<tr>
+<th scope="row"><a href="/admin/labels/labelcontent/">Label Contents</a></th>
+<td><a href="/admin/labels/labelcontent/add/" class="addlink">{% trans 'Add' %}</a></td>
+</tr>
+<tr>
+<th scope="row"><a href="/admin/labels/labeltemplate/">Label Templates</a></th>
+<td><a href="/admin/labels/labeltemplate/add/" class="addlink">{% trans 'Add' %}</a></td>
+</tr>
+</table></div><BR>
+
+{% if app_list %}
+ {% for app in app_list %}
+ <div class="module">
+ <table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}">
+ <caption><a href="{{ app.app_url }}" class="section">{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}</a></caption>
+ {% for model in app.models %}
+ <tr>
+ {% if model.perms.change %}
+ <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
+ {% else %}
+ <th scope="row">{{ model.name }}</th>
+ {% endif %}
+
+ {% if model.perms.add %}
+ <td><a href="{{ model.admin_url }}add/" class="addlink">{% trans 'Add' %}</a></td>
+ {% else %}
+ <td> </td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
+ {% endfor %}
+{% else %}
+ <p>{% trans "You don't have permission to edit anything." %}</p>
+{% endif %}
+</div>
+{% endblock %}
+
+{% block sidebar %}
+<div id="content-related">
+ <div class="module" id="recent-actions-module">
+ <h2>{% trans 'Recent Actions' %}</h2>
+ <h3>{% trans 'My Actions' %}</h3>
+ {% load log %}
+ {% get_admin_log 10 as admin_log for_user user %}
+ {% if not admin_log %}
+ <p>{% trans 'None available' %}</p>
+ {% else %}
+ <ul class="actionlist">
+ {% for entry in admin_log %}
+ <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">
+ {% if entry.is_deletion %}
+ {{ entry.object_repr }}
+ {% else %}
+ <a href="{{ entry.get_admin_url }}">{{ entry.object_repr }}</a>
+ {% endif %}
+ <br/>
+ {% if entry.content_type %}
+ <span class="mini quiet">{% filter capfirst %}{% trans entry.content_type.name %}{% endfilter %}</span>
+ {% else %}
+ <span class="mini quiet">{% trans 'Unknown content' %}</span>
+ {% endif %}
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </div>
+</div>
+{% endblock %}
--- /dev/null
+<!--overrride pagination-->
+{% load admin_list %}
+{% load i18n %}
+<p class="paginator">
+{% if pagination_required %}
+{% for i in page_range %}
+ {% paginator_number cl i %}
+{% endfor %}
+{% endif %}
+{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %}
+{% if show_all_url %}  <a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %}
+{% if cl.formset and cl.result_count %}<input type="submit" name="_save" class="default" value="{% trans 'Save' %}"/>{% endif %}
+</p>
--- /dev/null
+{% load i18n %}<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
+ "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ version="XHTML+RDFa 1.0"
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
+ xmlns:libns="http://jumpgate.caltech.edu/wiki/LibraryOntology#"
+ xmlns:invns="http://jumpgate.caltech.edu/wiki/InventoryOntology#"
+ xml:lang="en"
+>
+<!--base.html-->
+<head>
+ <title>{% block title %}{{ app_name }} - {{ page_name }}{% endblock %}</title>
+
+{% block additional_css %}
+ {% load staticfiles %}
+ {% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% static "css/rtl.css" %}{% endblock %}" />{% endif %}
+ {% block extrastyle %}{% endblock %}
+ {% block extrahead %}{% endblock %}
+ {% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
+ <link rel="stylesheet" type="text/css" href="{% static "css/data-browse-index.css" %}" />
+{% endblock %}
+
+</head>
+<body>
+<!-- Container -->
+ {% if not is_popup %}
+
+ <div id="header">
+ <div id="branding">
+ {% block branding %}{% endblock %}
+ </div>
+ <div id="user-tools">
+ {% if user.is_authenticated %}
+ {% trans 'Welcome,' %}
+ <strong>{% firstof user.first_name user.username %}</strong>.
+ {% block userlinks %}
+ {% url "django.admindocs.docroot" as docsroot %}
+ {% if docsroot %}
+ <a href="{{ docsroot }}">{% trans 'Documentation' %}</a> /
+ {% endif %}
+ <a href="{{root_path}}/accounts/password_change/">{% trans 'Change password' %}</a> /
+ <a href="{{root_path}}/accounts/logout/">{% trans 'Log out' %}</a>
+ {% endblock %}
+ {% else %}
+ <a href="{{root_path}}/accounts/login/?next={{thispage}}">{% trans 'Log in' %}</a>
+ {% endif %}
+ </div>
+ {% block nav-global %}{% endblock %}
+ </div>
+ {% endif %}
+ {% block breadcrumbs %}{% endblock %}
+ {% if messages %}
+ <ul class="messagelist">{% for message in messages %}<li>{{ message }}</li>{% endfor %}</ul>
+ {% endif %}
+
+ <!-- Content -->
+ <div id="content" class="{% block coltype %}colM{% endblock %}">
+ {% block pretitle %}{% endblock %}
+ {% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
+ {% block content %}
+ {% block object-tools %}{% endblock %}
+ {{ content }}
+ {% endblock %}
+ {% block sidebar %}{% endblock %}
+ </div>
+ <!-- END Content -->
+
+ {% block footer %}<div id="footer"></div>{% endblock %}
+<!-- END Container -->
+</body>
+</html>
--- /dev/null
+{% extends "base.html" %}
+{% load staticfiles %}
+{% load i18n %}
+
+<link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}" />
+
+{% block title %}{{ sitename }}{% endblock %}
+
+{% block branding %}
+<h1 id="site-name">HTSWorkflow</h1>
+{% endblock %}
+
+{% block nav-global %}{% endblock %}
--- /dev/null
+<div id="bcm_msg"></div>
+{{ bcmagic }}<br />
+<div id="bcm_status"></div>
--- /dev/null
+{% if run_f %}
+ <ul>
+ RUN FOLDER: <li>{{ run_f.run_folder }}</li>
+ </ul>
+{% else %}
+ <p>Run folder not found.</p>
+{% endif %}
--- /dev/null
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block breadcrumbs %}
+<div class="breadcrumbs">
+ <a href="/admin">{% trans 'Home' %}</a> ›
+ <a href="/admin/experiments">Experiments</a> ›
+ <a href="/admin/experiments/flowcell">flowcell</a> ›
+ <a href="{{ flowcell.get_admin_url }}">{{ flowcell.flowcell_id }}</a>
+</div>
+{% endblock %}
+
+{% block content %}
+{% if warnings %}
+<hr/>
+<p>
+{% for user_admin_url, username in warnings %}
+Warning: User <a href="{{ user_admin_url}}">{{ username }}</a> has no
+email address <br/>
+{% endfor %}
+{% endif %}
+</p>
+{% for to, subject, body, sending in emails %}
+<hr/>
+{% if sending %}<b>Message:</b> {{ sending }}<br/>{% endif %}
+<b>From:</b> {{ from }}<br/>
+<b>To:</b> {{ to }}<br/>
+<b>Subject:</b> {{ subject }}<br/>
+<pre>
+{{ body }}
+</pre>
+{% endfor %}<hr/>
+<form method="get">
+<label for="bcc">BCC {% for m in site_managers %}{{ m }} {% endfor %}</label>
+<input type="checkbox" id="bcc" name="bcc" checked="on"/><br/>
+<input type="hidden" name="send" value="1"/>
+<input type="submit" value="Send Email"/>
+{% endblock %}
\ No newline at end of file
--- /dev/null
+<html><head><title>{{ fc.flowcell_id }} - GA SEQUENCING (SOLEXA) LOG</title>
+<style type="text/css">
+<!--
+TD
+ {
+ color:black;
+ font-size:9pt;
+ font-face:Arial;
+ }
+-->
+</style>
+</head><body>
+{% if fc %}
+<table border="1" cellspacing="1">
+<tr><td colspan=2 nowrap><b>GA SEQUENCING (SOLEXA) LOG</b></td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>Date Run Started</td><td colspan=2>{{ fc.run_date }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>Cluster station used</td><td colspan=2 nowrap>{{ fc.cluster_station.name }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>GA used</td><td colspan=2 nowrap>{{ fc.sequencer.name }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+
+<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>Flowcell number</td><td colspan=2 nowrap>{{ fc.flowcell_id }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>Number of Tiles per Lane</td><td>100</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>Number of Cycles</td><td>{{ fc.read_length }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td><font point-size="9" face="Arial"><b>SAMPLE INFORMATION</b><font></td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td> </td><td>FC#</td><td> </td><td> </td><td> </td><td> </td><td> </td><td colspan=2 nowrap>FC bar code</td></tr>
+
+<tr><td valign=middle nowrap>Lane</td>
+{% for lane in fc.lane_set.all %}
+<td>{{ lane.lane_number }}</td>
+{% endfor %}
+</tr>
+<tr><td valign=middle nowrap>Solexa Library Number</td>
+{% for lane in fc.lane_set.all %}
+<td bgcolor=#CCFFCC>{{ lane.library.id }}</td>
+{% endfor %}
+</tr>
+
+<tr><td valign=middle nowrap>Sample Name</td>
+{% for lane in fc.lane_set.all %}
+<td bgcolor=#CCFFCC>{{ lane.library.library_name }}</td>
+{% endfor %}
+</tr>
+
+<tr><td valign=middle nowrap>Organism</td>
+{% for lane in fc.lane_set.all %}
+<td bgcolor=#CCFFCC>{{ lane.library.library_species.scientific_name }}</td>
+{% endfor %}
+</tr>
+
+<tr><td valign=middle nowrap>Submitter</td>
+{% for lane in fc.lane_set.all %}
+<td bgcolor=#CCFFCC>{{ lane.library.made_for }}</td>
+{% endfor %}
+</tr>
+
+
+<tr><td valign=middle nowrap>First time run?</td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td></tr>
+
+<tr><td valign=middle nowrap>Gel Cut Size (bp)</td>
+{% for lane in fc.lane_set.all %}
+<td bgcolor=#CCFFCC>{{ lane.library.gel_cut_size }}</td>
+{% endfor %}
+</tr>
+
+<tr><td valign=middle nowrap>Template Concentration (ng/ul)</td>
+{% for lane in fc.lane_set.all %}
+<td bgcolor=#CCFFCC>{{ lane.library.undiluted_concentration }}</td>
+{% endfor %}
+</tr>
+
+<tr><td valign=middle nowrap>Run Concentration (pM)</td>
+{% for lane in fc.lane_set.all %}
+<td bgcolor=#CCFFCC>{{ lane.pM }}</td>
+{% endfor %}
+</tr>
+
+</table>
+
+{% else %}
+ <p>Flowcell object missing. Can't create sheet.</p>
+{% endif %}
+
+</body></html
--- /dev/null
+{% extends "base_site.html" %}
+{% load staticfiles %}
+{% load humanize i18n %}
+{% block extrahead %}
+ <!-- App Stuff -->
+ <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}" />
+ <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
+
+ {% block additional_javascript %}
+ {% endblock %}
+{% endblock %}
+
+{% block content %}
+<div>
+ {% include "experiments/flowcell_header.html" %}
+ <div class="htswdetail" typeof="libns:IlluminaFlowcell" resource="{{flowcell.get_absolute_url}}">
+ <h2>Lanes</h2>
+ <table>
+ <thead>
+ <tr>
+ <td>Lane</td>
+ <td>Library ID</td>
+ <td>Library Name</td>
+ <td>Species</td>
+ <td>Comment</td>
+ </tr>
+ </thead>
+ <tbody>
+ {% for lane in lanes %}
+ <tr>
+ <td rel="libns:has_lane">
+ <a href="{{lane.get_absolute_url}}" typeof="libns:IlluminaLane">
+ <span property="libns:lane_number">{{lane.lane_number}}</span>
+ </a>
+ </td>
+ <td rel="libns:library"
+ about="{{lane.get_absolute_url}}"
+ resource="{{lane.library.get_absolute_url}}">
+ <a typeof="libns:Library" href="{{lane.library.get_absolute_url}}">
+ <span property="libns:library_id"
+ >{{lane.library.id}}</span></a>
+ {% if user.is_staff %}
+ <a href="{{lane.library.get_admin_url}}">
+ <img class="icon_button"
+ src="{% static "admin/img/icon_changelink.gif" %}"/>
+ </a>{% endif %}
+ </td>
+ <td>
+ <a href="{{lane.library.get_absolute_url}}">
+ <span property="libns:name"
+ about="{{lane.library.get_absolute_url}}"
+ >{{lane.library.library_name}}</span>
+ </a>
+ </td>
+ <td about="{{lane.library.get_absolute_url}}" rel="libns:species">
+ <a href="{{lane.library.library_species.get_absolute_url}}"
+ typeof="libns:Species">
+ <span property="libns:species_name">{{ lane.library.library_species.scientific_name }}</span></a>
+ </td>
+ <td about="{{lane.get_absolute_url}}">
+ <span property="libns:comment">{{lane.comment}}</span>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ <div class="htsw_flowcell_ivc">
+ {% for run in flowcell.datarun_set.all %}
+ <h2>Run {{ run.runfolder_name }}</h2>
+ {% if run.lane_files %}
+ <table>
+ <thead>
+ <tr>
+ <td>Lane</td>
+ <td>IVC All</td>
+ <td>IVC Call</td>
+ <td>IVC Percent Base</td>
+ <td>IVC Percent Base All</td>
+ <td>IVC Percent Base Called</td>
+ </tr>
+ </thead>
+ <tbody>
+ {% for lane_id, lane_file_set in run.lane_files.items %}
+ {% if lane_file_set.ivc_all %}
+ <tr>
+ <td>{{ lane_id }}</td>
+ <td>
+ <a href="{{ lane_file_set.ivc_all.get_absolute_url }}">
+ <img height="84" width="126" alt="Lane {{lane_id }} IVC All"
+ src="{{ lane_file_set.ivc_all.get_absolute_url }}"/></a>
+ </td>
+ <td>
+ <a href="{{ lane_file_set.ivc_call.get_absolute_url }}">
+ <img height="84" width="126" alt="Lane {{lane_id }} IVC Call"
+ src="{{ lane_file_set.ivc_call.get_absolute_url }}"/>
+ </a>
+ </td>
+ <td>
+ <a href="{{ lane_file_set.ivc_percent_base.get_absolute_url }}">
+ <img height="84" width="126" alt="Lane {{lane_id }} IVC % Base"
+ src="{{ lane_file_set.ivc_percent_base.get_absolute_url }}"/>
+ </a>
+ </td>
+ <td>
+ <a href="{{ lane_file_set.ivc_percent_all.get_absolute_url }}">
+ <img height="84" width="126" alt="Lane {{lane_id }} IVC % Base All"
+ src="{{ lane_file_set.ivc_percent_all.get_absolute_url }}"/>
+ </a>
+ </td>
+ <td>
+ <a href="{{ lane_file_set.ivc_percent_call.get_absolute_url }}">
+ <img height="84" width="126"
+ alt="Lane {{lane_id }} IVC % Base Called"
+ src="{{ lane_file_set.ivc_percent_call.get_absolute_url }}"/>
+ </a>
+ </td>
+ </tr>
+ {% endif %}
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endif %}
+ {% endfor %}
+ </div>
+ </div>
+</div>
+<!-- end flowcell_detail -->
+{% endblock %}
--- /dev/null
+{% load staticfiles %}
+<div class="flowcell_identity" typeof="libns:IlluminaFlowcell" resource="{{flowcell.get_absolute_url}}">
+ <h2>About this Flowcell</h2>
+ <b>Flowcell</b>:
+ <a href="{{flowcell.get_absolute_url}}"><span property="libns:flowcell_id">{{flowcell.flowcell_id}}</span></a>{% if user.is_staff %}<a href="{{flowcell.get_admin_url}}"><img class="icon_button" src="{% static "admin/img/icon_changelink.gif" %}" alt="Edit"/></a>{% endif%}
+ <br/>
+ <div rel="libns:sequenced_by">
+ <div typeof="libns:Sequencer"
+ about="{{flowcell.sequencer.get_absolute_url}}">
+ <b>Instrument</b>:
+ <span property="libns:sequencer_name">{{ flowcell.sequencer.name }}</span>
+ {% if flowcell.sequencer.instrument_name %}
+ (<span property="libns:sequencer_instrument">{{ flowcell.sequencer.instrument_name}}</span>)
+ {% endif %}
+ <br/>
+ <b>Instrument Model</b>:
+ <span property="libns:sequencer_model">{{flowcell.sequencer.model}}</span>
+ <br/>
+ </div>
+ </div>
+ {% for datarun in flowcell.datarun_set.all %}
+ <b>Image Analysis</b>:
+ <span property="libns:image_software">{{datarun.image_software}}</span>
+ <span property="libns:image_version">{{datarun.image_version}}</span><br/>
+ <b>Base Caller</b>:
+ <span property="libns:basecall_software">{{datarun.basecall_software}}</span>
+ <span property="libns:basecall_version">{{datarun.basecall_version}}</span><br/>
+ <b>Alignment</b>:
+ <span property="libns:alignment_software">{{datarun.alignment_software}}</span>
+ <span property="libns:alignment_version">{{datarun.alignment_version}}</span><br/>
+ {% endfor %}
+ <b>Run Date</b>:
+ <span property="libns:date" content="{{flowcell.run_date|date:'Y-m-d\TH:i:s'}}" datatype="xsd:dateTime">{{ flowcell.run_date }}</span><br/>
+ <b>Type</b>:
+ <span property="libns:flowcell_type">{{flowcell.flowcell_type}}</span><br/>
+ <b>Read Length</b>:
+ <span property="libns:read_length" datatype="xsd:integer">{{flowcell.read_length}}</span><br/>
+ <b>Control Lane</b>:
+ <span property="libns:control_lane">{{flowcell.control_lane}}</span><br/>
+
+ <b>Notes</b>:
+ <pre property="libns:flowcell_notes">{{flowcell.notes}}</pre>
+ </div>
--- /dev/null
+{% extends "base_site.html" %}
+{% load humanize i18n %}
+{% load staticfiles %}
+{% block extrahead %}
+ <!-- App Stuff -->
+ <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}"/>
+ <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
+
+ {% block additional_javascript %}
+ {% endblock %}
+{% endblock %}
+
+{% block content %}
+<div id="lane_detail" class="htswdetail" typeof="libns:IlluminaLane" resource="{{lane.get_absolute_url}}">
+ <div rel="libns:flowcell" resource="{{flowcell.get_absolute_url}}">
+ {% include "experiments/flowcell_header.html" %}
+ </div>
+ <div class="flowcell_lane_detail">
+ <h2>About this lane</h2>
+ <b>Lane</b>:
+ <span property="libns:lane_number">{{lane.lane_number}}</span><br/>
+ <b>pM</b>:
+ <span property="libns:pM" datatype="xsd:decimal">{{ lane.pM }}</span><br/>
+ {% if lane.cluster_estimate %}
+ <b>Cluster Estimate</b>:
+ <span property="libns:cluster_estimate" datatype="xsd:decimal"
+ content="{{lane.cluster_estimate}}">{{ lane.cluster_estimate|intcomma }}</span><br/>{% endif %}
+ {% if lane.status %}
+ <b>Lane Status</b>:
+ <span property="libns:status">{{ lane.status }}</span><br/>{% endif %}
+ {% if lane.comment %}
+ <b>Comments</b>:
+ <span property="libns:comment">{{ lane.comment }}</span><br/>{% endif %}
+ </div>
+ <hr/>
+ {% include "sample_header.html" %}
+ <hr/>
+ <div class="htsw_flowcell_ivc">
+ {% for run in flowcell.datarun_set.all %}
+ <h2>Run {{ run.runfolder_name }}</h2>
+ <table>
+ <thead>
+ <tr>
+ <td>Lane</td>
+ <td>IVC All</td>
+ <td>IVC Call</td>
+ <td>IVC Percent Base</td>
+ <td>IVC Percent Base All</td>
+ <td>IVC Percent Base Called</td>
+ </tr>
+ </thead>
+ <tbody>
+ {% for run, lane_number, lane_file_set in filtered_dataruns %}
+ {% if lane_file_set.ivc_all %}
+ <tr>
+ <td>{{lane_number}}</td>
+ <td>
+ <a href="{{ lane_file_set.ivc_all.get_absolute_url }}">
+ <img height="84" width="126" alt="Lane {{lane_id }} IVC All"
+ src="{{ lane_file_set.ivc_all.get_absolute_url }}"/></a>
+ </td>
+ <td>
+ <a href="{{ lane_file_set.ivc_call.get_absolute_url }}">
+ <img height="84" width="126" alt="Lane {{lane_id }} IVC Call"
+ src="{{ lane_file_set.ivc_call.get_absolute_url }}"/>
+ </a>
+ </td>
+ <td>
+ <a href="{{ lane_file_set.ivc_percent_base.get_absolute_url }}">
+ <img height="84" width="126" alt="Lane {{lane_id }} IVC % Base"
+ src="{{ lane_file_set.ivc_percent_base.get_absolute_url }}"/>
+ </a>
+ </td>
+ <td>
+ <a href="{{ lane_file_set.ivc_percent_all.get_absolute_url }}">
+ <img height="84" width="126" alt="Lane {{lane_id }} IVC % Base All"
+ src="{{ lane_file_set.ivc_percent_all.get_absolute_url }}"/>
+ </a>
+ </td>
+ <td>
+ <a href="{{ lane_file_set.ivc_percent_call.get_absolute_url }}">
+ <img height="84" width="126"
+ alt="Lane {{lane_id }} IVC % Base Called"
+ src="{{ lane_file_set.ivc_percent_call.get_absolute_url }}"/>
+ </a>
+ </td>
+ </tr>
+ {% else %}
+ <tr><td colspan="6">No data</td></tr>
+ {% endif %}
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endfor %}
+ </div>
+</div>
+
+{% endblock %}
--- /dev/null
+{% if data_run_list %}
+ <table>
+ {% for run in data_run_list %}
+ <tr>
+ <td>{{run.run_folder}}</td>
+ <td><a href="fcsheet/{{run.fcid}}">sheet</td>
+ <td><a href="started/{{run.fcid}}">started email</td>
+ <td><a href="finished/{{run.fcid}}">finished email</td>
+ </tr>
+ {% endfor %}
+ </table>
+{% else %}
+ <p>No data runs are available.</p>
+{% endif %}
--- /dev/null
+{% extends "base_site.html" %}
+{% load humanize i18n %}
+{% load staticfiles %}
+{% block extrahead %}
+ <!-- App Stuff -->
+ <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}" />
+ <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
+
+ {% block additional_javascript %}
+ {% endblock %}
+{% endblock %}
+
+{% block content %}
+ <h1>Sequencer</h1>
+ <dl about="{{sequencer.get_absolute_url}}" typeof="libns:sequencer">
+ <dt>Name</dt>
+ <dl property="libns:sequencer_name">{{sequencer.name}}</dl>
+ <dt>Instrument Name</dt>
+ <dl property="libns:insrument_name">{{sequencer.instrument_name}}</dl>
+ <dt>Model</dt>
+ <dl property="libns:model">{{sequencer.model}}</dl>
+ <dt>Comment</dt>
+ <dl></dl>
+ </dl>
+{% endblock %}
--- /dev/null
+<p>
+The following libraries are on the flowcell {{ flowcell.flowcell_id }}
+which is a {{ flowcell.read_length }} base pair {% if flowcell.paired_end %}paired end{% else %}single ended{% endif %} flowcell.
+</p>
+<p>{% for lane in lanes %}
+Lane #{{ lane.lane_number }} :
+<a href="https://jumpgate.caltech.edu/library/{{lane.library.id}}">
+{{ lane.library.id }}</a>
+{{ lane.library.library_name }}<br/>
+{% endfor %}</p>
+<p>
+The data should be available at the following link when
+the pipeline finishes, probably in about {{ finish_low.days }} to {{ finish_high.days }}
+days from {{ now|date:"D, M d Y" }}
+</p>
+<p>
+<a href="https://jumpgate.caltech.edu/runfolders/{{ flowcell.sequencer}}/">
+https://jumpgate.caltech.edu/runfolders/{{ flowcell.sequencer }}
+</a></p>
--- /dev/null
+The following libraries are on the flowcell {{ flowcell.flowcell_id }}
+which is a {{ flowcell.read_length }} base pair {% if flowcell.paired_end %}paired end{% else %}single ended{% endif %} flowcell.
+
+Lane : (Library Id) Library Name (Cluster Estimate)
+{% for lane in lanes %}
+Lane #{{ lane.lane_number }} : ({{ lane.library.id }}) {{ lane.library.library_name }} ({{ lane.cluster_estimate }})
+ https://jumpgate.caltech.edu/library/{{ lane.library.id }}
+{% endfor %}
+
+The raw data should be available at the following link when the
+pipeline finishes, probably in about {{ finish_low.days }} to {{ finish_high.days }}
+days from {{ now|date:"D, M d Y" }}
+
+https://jumpgate.caltech.edu/runfolders/{{ flowcell.sequencer}}
+
+Username: gec
+Password: gecilluminadata
+
+- Jumpgate
--- /dev/null
+^FX=========================
+^FX Harddrive Location Tracking Label
+^FX 300x375 dots
+^FX=========================
+
+^XA
+^LH 0,25
+
+^FO0,0
+^CF0,35
+^FB375,1,,C
+^FD{{ item.item_type.name }}:^FS
+
+^FX -------Text contains HD serial #-------------
+^FO15,75
+^CF0,42
+^FB325,3,,C
+^FD{% if use_uuid %}{{ item.uuid }}{% else %}{{ item.barcode_id }}{% endif %}^FS
+
+^FX -------Barcode contains HD serial #-----------
+^FO150,200
+^BXN,3,200
+^FD{% if use_uuid %}invu|{{ item.uuid }}{% else %}invb|{{ item.barcode_id }}{% endif %}^FS
+
+^XZ
--- /dev/null
+^FX=========================
+^FX 3"x3" Label
+^FX=========================
+^XA
+
+
+^FX======== Left Side ===========
+
+^FX------------
+^FX ^LH changes the 0,0 point of all subsequent location references
+^FX------------
+
+^LH0,50
+
+^FX ---Header---
+
+^FO25,0
+^CF0,50
+^FB250,2,,C
+^FD{{ item.barcode_id }}^FS
+
+^FX ---Column 1: Flowcells---
+
+^FX-----------------
+^FX FB command for automatic text formatting:
+^FX ^FB[dot width of area], [max # of lines], [change line spacing], [justification: L, C, R, J], [hanging indent]
+^FX-----------------
+
+^CF0,30,30
+^FO75,125
+^FB275,19,,L
+^FD{% for flowcell in flowcell_id_list %}{{ flowcell }}{% if not forloop.last %}\&{% endif %}{% endfor %}^FS
+^FX ---Date---
+
+^FO0,725
+^CF0,35
+^FB300,2,,C
+^FD{{ oldest_rundate|date:"YMd" }} - {{ latest_rundate|date:"YMd" }}^FS
+
+^FX ---Barcode---
+
+^FO135,795
+^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS
+
+^FX======== Right Side ===========
+
+^LH300,60
+
+^FX ---Header---
+
+^FO0,0
+^CF0,50
+^FB600,2,,C
+^FD{{ barcode_id }}^FS
+
+^FX ---Dividing line---
+
+^FX---------------
+^FX GB command:
+^FX ^GB[box width], [box height], [border thickness], [color: B, W], [corner rounding: 0-8]^FS
+^FX---------------
+
+^FO0,100
+^GB0,600,10^FS
+
+^FX ---Column 2: Libraries 1-20---
+
+^CF0,30,30
+^FO75,100
+^FB100,20,,L
+^FD{% for lib_id in library_id_list_1_to_20 %}{{ lib_id }}{% if not forloop.last %}\&{% endif %}{% endfor %}^FS
+
+^FX ---Column 3: Libraries 21-40---
+
+^CF0,30,30
+^FO200,100
+^FB100,20,,L
+^FD{% for lib_id in library_id_list_21_to_40 %}{{ lib_id }}{% if not forloop.last %}\&{% endif %}{% endfor %}^FS
+
+^FX ---Column 4: Libraries 41-60---
+
+^CF0,30,30
+^FO325,100
+^FB100,20,,L
+^FD{% for lib_id in library_id_list_41_to_60 %}{{ lib_id }}{% if not forloop.last %}\&{% endif %}{% endfor %}^FS
+
+^FX ---Column 5: Libraries 61-80---
+
+^CF0,30,30
+^FO450,100
+^FB100,20,,L
+^FD{% for lib_id in library_id_list_61_to_80 %}{{ lib_id }}{% if not forloop.last %}\&{% endif %}{% endfor %}^FS
+
+^FX ---Date---
+
+^FO0,715
+^CF0,35
+^FB600,2,,C
+^FDRun Dates: {{ oldest_rundate|date:"YMd" }}-{{ latest_rundate|date:"YMd" }}^FS
+
+^FX ---Barcode---
+
+^FO255,785
+^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS
+
+^LH0,0
+^FX ---End---
+^XZ
\ No newline at end of file
--- /dev/null
+{% extends "base_site.html" %}
+{% load admin_list i18n %}
+{% block extrahead %}
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $(window).resize(function() {
+ var window_height = $(window).height();
+ var position = $("#changelist table").position();
+ height = window_height - position.top;
+ $("#changelist table.filtered").height(height);
+ $("#changelist-filter").height(height);
+ });
+ $(window).resize();
+ });
+ </script>
+{% endblock %}
+{% block bodyclass %}change-list{% endblock %}
+{% block coltype %}flex{% endblock %}
+{% block content %}
+<div id="inventory-index-div" >
+ <div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
+ {% block search %}{% search_form item_changelist %}{% endblock %}
+
+ {% block pagination %}{% pagination item_changelist %}{% endblock %}
+
+ {% block filters %}
+ {% if item_changelist.has_filters %}
+ <div id="changelist-filter">
+ <h2 >{% trans 'Filter' %}</h2>
+ {% for spec in item_changelist.filter_specs %}
+ {% admin_list_filter cl spec %}
+ {% endfor %}
+ </div>
+ {% endif %}
+ {% endblock %}
+ {% block summary_stats %}
+ <table class="{% if cl.has_filters %} filtered{% endif %}">
+ <thead >
+ <tr >
+ <td >UUID</td>
+ <td >Barcode ID</td>
+ <td >Location</td>
+ <td >Model</td>
+ <td >Vendor</td>
+ <td >Created</td>
+ <td >Contains</td>
+ </tr>
+ </thead>
+ <tbody >
+ {% for item in item_changelist.get_query_set %}
+ <tr >
+ <td >{{ item.uuid }}</td>
+ <td >{{ item.barcode_id}}</td>
+ <td >{{ item.location }}</td>
+ <td >{{ item.item_type }}</td>
+ <td ></td>
+ <td >{{ item.creation_date }}</td>
+ <td >
+ {% for content in item.longtermstorage_set.all %}
+ {{ content.flowcell }}
+ {% endfor %}
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endblock %}
+</div>
+{% endblock %}
--- /dev/null
+{% extends "base_site.html" %}
+{% load admin_list i18n %}
+{% block extrahead %}
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $(window).resize(function() {
+ var window_height = $(window).height();
+ var position = $("#changelist table").position();
+ height = window_height - position.top;
+ $("#changelist table.filtered").height(height);
+ $("#changelist-filter").height(height);
+ });
+ $(window).resize();
+ });
+ </script>
+{% endblock %}
+{% block bodyclass %}change-list{% endblock %}
+{% block coltype %}flex{% endblock %}
+{% block content %}
+<div id="inventory-index-div" >
+ <div class="module{% if item_changelist.has_filters %} filtered{% endif %}" id="changelist">
+ {% block search %}{% search_form item_changelist %}{% endblock %}
+
+ {% block pagination %}{% pagination item_changelist %}{% endblock %}
+
+ {% block filters %}
+ {% if item_changelist.has_filters %}
+ <div id="changelist-filter">
+ <h2 >{% trans 'Filter' %}</h2>
+ {% for spec in item_changelist.filter_specs %}
+ {% admin_list_filter item_changelist spec %}
+ {% endfor %}
+ </div>
+ {% endif %}
+ {% endblock %}
+ {% block summary_stats %}
+ <table class="{% if item_changelist.has_filters %} filtered{% endif %}">
+ <thead >
+ <tr >
+ <td >Name</td>
+ <td >Description</td>
+ </tr>
+ </thead>
+ <tbody >
+ {% for itemtype in item_changelist.result_list %}
+ <tr >
+ <td ><a href="/inventory/it/{{ itemtype.name }}/">{{ itemtype.name }}</a></td>
+ <td >{{ itemtype.description }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endblock %}
+</div>
+{% endblock %}
--- /dev/null
+{% extends "base_site.html" %}
+{% load admin_list i18n %}
+{% block extrahead %}
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $(window).resize(function() {
+ var window_height = $(window).height();
+ var position = $("#changelist table").position();
+ height = window_height - position.top;
+ $("#changelist table.filtered").height(height);
+ $("#changelist-filter").height(height);
+ });
+ $(window).resize();
+ });
+ </script>
+{% endblock %}
+{% block bodyclass %}change-list{% endblock %}
+{% block coltype %}flex{% endblock %}
+{% block content %}
+<div id="inventory-index-div" >
+ <div class="module{% if item_changelist.has_filters %} filtered{% endif %}" id="changelist">
+ {% block search %}{% search_form item_changelist %}{% endblock %}
+
+ {% block pagination %}{% pagination item_changelist %}{% endblock %}
+
+ {% block filters %}
+ {% if item_changelist.has_filters %}
+ <div id="changelist-filter">
+ <h2 >{% trans 'Filter' %}</h2>
+ {% for spec in item_changelist.filter_specs %}
+ {% admin_list_filter item_changelist spec %}
+ {% endfor %}
+ </div>
+ {% endif %}
+ {% endblock %}
+ {% block summary_stats %}
+ <table class="{% if item_changelist.has_filters %} filtered{% endif %}">
+ <thead >
+ <tr >
+ <td >UUID</td>
+ <td >Barcode ID</td>
+ <td >Location</td>
+ <td >Model</td>
+ <td >Vendor</td>
+ <td >Created</td>
+ <td >Contains</td>
+ </tr>
+ </thead>
+ <tbody >
+ {% for item in item_changelist.result_list %}
+ <tr about="{{ item.get_absolute_url }}">
+ <td ><a href="{{ item.get_absolute_url}}" rel="invns:uuid">{{ item.uuid }}</a></td>
+ <td ><a href="/inventory/{{ item.barcode_id }}/" rel="invns:barcode">{{ item.barcode_id }}</a></td>
+ <td property="invns:location">{{ item.location }}</td>
+ <td property="invns:item_type">{{ item.item_type }}</td>
+ <td ></td>
+ <td property="invnfs:creation_date" content="{{item.creation_date|date:'Y-m-d\TH:i:s'}}" datatype="xsd:dateTime">{{ item.creation_date }}</td>
+ <td class="cell_list" >
+ {% for content in item.longtermstorage_set.all %}
+ <a href="{{content.flowcell.get_absolute_url}}" rel="libns:flowcell_id">{{ content.flowcell }}</a>
+ {% endfor %}
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endblock %}
+ </div>
+</div>
+{% endblock %}
--- /dev/null
+{% extends "base_site.html" %}
+
+{% block content %}
+{% if item %}
+ <h2>Item Summary:</h2>
+ <a href="{% url "inventory.views.index" %}{{item.uuid}}/print/">Print</a><br />
+ <br />
+ <b>UUID:</b> <span property="invns:uuid">{{item.uuid}}</span><br />
+ <b>Barcode ID:</b> <span property="invns:barcode">{{ item.barcode_id }}</span><br />
+ <b>Type:</b> <span property="invns:item_type">{{ item.item_type.name }}</span><br />
+ <br />
+ <b>Location:</b> <span property="invns:location">{{ item.location.name }}</span><br />
+ <b>Status: </b> {% if item.status %}<span property="invns:status">{{ item.status.name }}</span>{% else %}N/A{% endif %}<br />
+ <br />
+ {% if item.item_info.model_id %}
+ <b>Model ID:</b> <span property="invns:model">{{ item.item_info.model_id }}</span><br />
+ {% endif %}
+ {% if item.item_info.part_number %}
+ <b>Part Number:</b> <span property="invns:part_number">{{ item.item_info.part_number }}</span><br />
+ {% endif %}
+ {% if item.item_info.lot_number %}
+ <b>Lot Number:</b> <span property="invns:lot_number">{{ item.item_info.lot_number }}</span><br />
+ {% endif %}
+ <br />
+ {% if item.item_info.url %}
+ <b>Item Website:</b> <a href="{{ item.item_info.url }}" rel="invns:vendor_link">Link</a><br />
+ {% endif %}
+ <b>Vendor:</b> {% if item.item_info.vendor.url %}<a href="{{ item.item_info.vendor.url }}">{% endif %}{{ item.item_info.vendor.name }}{% if item.item_info.vendor.url %}</a>{% endif %}<br />
+ <b>Purchase Date:</b>{% if item.item_info.purchase_date %}{{ item.item_info.purchase_date }}{% else %}N/A{% endif %}<br />
+ <b>Warenty (Months):</b>{% if item.item_info.warenty_months %}{{item.item_info.warenty_months}}{% else %}N/A{% endif %}<br />
+ <br />
+ <b>Item Info Notes:</b>
+ <p>
+ {% if item.item_info.notes %}{{ item.item_info.notes }}{% else %}No notes found{% endif %}
+ </p>
+ <br />
+ <b>Item Specific Notes:</b>
+ <p>
+ {% if item.notes %}{{ item.notes }}{% else %}No notes found{% endif %}
+ </p>
+ <br />
+ <center><div id="lts-grid"></div></center>
+
+{% else %}
+ <h3>Item with UUID of {{ uuid }} not found.</h3>
+{% endif %}
+{% endblock %}
--- /dev/null
+{% extends "base_site.html" %}
+{% load i18n %}
+
+{% block additional_css %}{% load staticfiles %}{{ block.super }}
+<link rel="stylesheet" type="text/css" href="{% static "css/base.css" %}"/>
+<link rel="stylesheet" type="text/css" href="{% static "css/login.css" %}"/>
+{% endblock %}
+
+{% block title %}Login{% endblock %}
+{% block bodyclass %}login{% endblock %}
+
+{% block content %}
+{% if error_message %}
+<p class="errornote">{{ error_message }}</p>
+{% endif %}
+<div id="container">
+ <h1>Login</h1>
+<form action="{{ app_path }}" method="post" id="login-form">
+ {% csrf_token %}
+ <div class="form-row">
+ <label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
+ </div>
+ <div class="form-row">
+ <label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
+ <input type="hidden" name="this_is_the_login_form" value="1" />
+ </div>
+ <div class="submit-row">
+ <label> </label><input type="submit" value="{% trans 'Log in' %}" />
+ </div>
+</form>
+
+<script type="text/javascript">
+document.getElementById('id_username').focus()
+</script>
+</div>
+{% endblock %}
--- /dev/null
+{% extends "base_site.html" %}
+
+{% block content %}
+<table>
+ <tr><td>User Name:</td><td>{{ user.username }}</td></tr>
+ <tr><td>Full Name:</td><td>{{ user.get_full_name }}</td></tr>
+ <tr><td>E-mail:</td><td>{{ user.email }}</td></tr>
+</table>
+{% endblock %}
--- /dev/null
+{% extends "admin/base_site.html" %}
+
+{% if main %}
+{% block content %}
+
+ {{ main|safe }}
+
+{% endblock %}
+{% else %}
+ <p>No content. Can't create report.</p>
+{% endif %}
--- /dev/null
+{% load staticfiles %}
+<div id="librarydetail"
+ about="{{lib.get_absolute_url}}"
+ typeof="libns:Library">
+ <div class="library_identity">
+ <h2>Library Name</h2>
+ <b>Library ID</b>:
+ <a href="{{lib.get_absolute_url}}"><span property="libns:library_id">{{ lib.id }}</span></a>
+ {% if user.is_staff %}<a href="{{lib.get_admin_url}}"><img class="icon_button" src="{% static "admin/img/icon_changelink.gif" %}" alt="Edit"/></a>{% endif %}
+ <br />
+ <b>Name</b>:
+ <span property="libns:name">{{ lib.library_name }}</span>
+ <br/>
+ <b>Affiliations</b>:
+ <ul>
+ {% for individual in lib.affiliations.all %}
+ <li property="libns:affiliation" content="{{individual.name}}">
+ {{ individual.name }} ( {{ individual.contact }} )
+ </li>
+ {% endfor %}
+ </ul>
+ </div>
+ <div class="library_sample_detail">
+ <h2>Sample Details</h2>
+ <b>Species</b>:
+ <span property="libns:species_name" content="{{lib.library_species.scientific_name}}"><a href="{{lib.library_species.get_absolute_url}}">{{ lib.library_species.scientific_name }}</a></span>
+ <br/>
+ <b>Experiment Type</b>:
+ <span property="libns:experiment_type">{{ lib.experiment_type }}</span>
+ <br/>
+ {% if lib.antibody %}
+ <b>Antibody</b>:
+ <span property="libns:antibody">{{ lib.antibody.antibodies }}</span>
+ {% if lib.antibody.antibodies.nickname %}
+ (<span property="libns:antibody_term">{{ lib.antibody.nickname }}</span>)
+ {% endif %}
+ <br/>
+ {% endif %}
+ {% if lib.cell_line %}
+ <b>Background or Cell Line</b>:
+ <span property="libns:cell_line">{{ lib.cell_line }}</span>
+ <br/>
+ {% endif %}
+ {% if lib.condition %}
+ <b>Condition</b>:
+ <span property="libns:condition">{{ lib.condition.condition_name }}</span>
+ {% if lib.condition.nickname %}
+ (<span property="libns:condition_term">{{ lib.condition.nickname }}</span>)
+ {% endif %}
+ <br/>
+ {% endif %}
+ {% if lib.replicate %}
+ <b>Replicate</b>:
+ <span property="libns:replicate">{{ lib.replicate }}</span>
+ <br/>
+ {% endif %}
+ </div>
+ <div class="library_library_detail">
+ <h2>Library Details</h2>
+ <b>Library Type</b>:
+ <span property="libns:library_type">{{ lib.library_type }}</span>
+ <br/>
+ <b>Multiplex Index</b>:
+ <span property="libns:multiplex_index">{{ lib.index_sequence_text }}</span>
+ <br/>
+ <b>Creation Date</b>
+ <span property="libns:date" content="{{lib.creation_date|date:'Y-m-d'}}T00:00:00" datatype="xsd:dateTime">{{ lib.creation_date }}</span>
+ <br/>
+ <b>Made By</b>:
+ <span property="libns:made_by">{{ lib.made_by }}</span>
+ <br/>
+ {% if lib.gel_cut_size %}
+ <b>Gel Cut Size</b>:
+ <span property="libns:gel_cut" datatype="xsd:integer">{{ lib.gel_cut_size }}</span>
+ <br/>
+ {% endif %}
+ {% if lib.insert_size %}
+ <b>Insert Size</b>:
+ <span property="libns:insert_size" datatype="xsd:integer">{{ lib.insert_size }}</span>
+ <br/>
+ {% endif %}
+ {% if lib.undiluted_concentration %}
+ <b>Concentration</b>:
+ <span property="libns:concentration">{{ lib.undiluted_concentration }} ng/µl</span>
+ <br/>
+ {% endif %}
+ {% if lib.stopping_point_name %}
+ <b>Protocol Stopping Point</b>
+ <span property="libns:stopping_point">{{ lib.stopping_point_name }}</span>
+ <br/>
+ {% endif %}
+ </div>
+</div>
--- /dev/null
+{% extends "base_site.html" %}
+{% load admin_list i18n %}
+
+{% block bodyclass %}change-list{% endblock %}
+{% block coltype %}flex{% endblock %}
+
+{% block content %}
+<div id="antibody-index-div">
+{% block body %}
+<table >
+ <thead >
+ <tr >
+ <td >Antigene</td>
+ <td >Nickname</td>
+ <td >Antibodies</td>
+ <td >Catalog</td>
+ <td >Source</td>
+ </tr>
+ </thead>
+ <tbody >
+ {% for antibody in antibodies %}
+ <tr >
+ <td >
+ {{ antibody.antigene }}
+ </td>
+ <td >
+ {{ antibody.nickname }}
+ </td>
+ <td >
+ {{ antibody.antibodies }}
+ </td>
+ <td >
+ {{ antibody.catalog }}
+ </td>
+ <td >
+ {{ antibody.source }}
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+</div>
+{% endblock %}
+{% endblock %}
--- /dev/null
+{% extends "base_site.html" %}
+{% load admin_list i18n %}
+
+{% block bodyclass %}change-list{% endblock %}
+{% block coltype %}flex{% endblock %}
+
+{% block content %}
+<div id="lanes-index-div">
+ <div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
+ {% block search %}{% search_form lanes %}{% endblock %}
+
+ {% block filters %}
+ {% if lanes.has_filters %}
+ <div id="changelist-filter">
+ <h2 >{% trans 'Filter' %}</h2>
+ {% for spec in lanes.filter_specs %}
+ {% admin_list_filter lanes spec %}
+ {% endfor %}
+ </div>
+ {% endif %}
+ {% endblock %}
+
+
+ {% block pagination %}{% pagination lanes %}{% endblock %}
+
+{% block body %}
+<table >
+ <thead >
+ <tr >
+ <td >Run Date</td>
+ <td >Flowcell Type</td>
+ <td >Cycles</td>
+ <td >Flowcell ID</td>
+ <td >Lane</td>
+ <td >Library ID</td>
+ <td >Library Name</td>
+ </tr>
+ </thead>
+ <tbody >
+ {% for lane in lanes.query_set %}
+ <tr >
+ <td >
+ {{ lane.flowcell.run_date|date:"Y-M-d" }}
+ </td>
+ <td >
+ {{ lane.flowcell.flowcell_type }}
+ </td>
+ <td >
+ {{ lane.flowcell.read_length }}
+ </td>
+ <td >
+ {{ lane.flowcell.flowcell_id }}
+ </td>
+ <td >
+ {{ lane.lane_number }}
+ </td>
+ <td >
+ <a href="/library/{{ lane.library_id }}">{{ lane.library_id }}</a>
+ </td>
+ <td >
+ <a href="/library/{{ lane.library_id }}">{{ lane.library.library_name }}</a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+</div>
+{% endblock %}
+{% endblock %}
--- /dev/null
+{% extends "base_site.html" %}
+{% load staticfiles %}
+{% load humanize i18n %}
+{% block extrahead %}
+ <!-- App Stuff -->
+ <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}"/>
+ <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
+
+ {% block additional_javascript %}
+ {% endblock %}
+{% endblock %}
+
+{% block content %}
+ {% include "sample_header.html" %}
+ <hr/>
+ <div class="library_statistics">
+ <h2>Raw Result Files</h2>
+ <table>
+ <thead>
+ <tr>
+ <td>Run Start Date</td>
+ <td>Cycle</td>
+ <td>Flowcell</td>
+ <td>Lane</td>
+ <td>Summary</td>
+ <td>Eland</td>
+ <td>Bed</td>
+ <td>Archived</td>
+ </tr>
+ </thead>
+ <tbody>
+ {% if eland_results %}
+ {% for result in eland_results %}
+ <tr about="{{result.flowcell.get_absolute_url}}">
+ <td property="libns:date" content="{{result.run_date|date:'Y-m-d\TH:i:s'}}" datatype="xsd:dateTime">{{ result.run_date|date}}</td>
+ <td>{{ result.cycle }}</td>
+ <td><a href="{{result.flowcell.get_absolute_url}}"><span property="libns:flowcell_id">{{ result.flowcell_id }}</span></a>{% if user.is_staff %}<a href="{{result.flowcell.get_admin_url}}"><img class="icon_button" src="{% static "admin/img/icon_changelink.gif" %}" alt="Edit"/></a>{% endif%}</td>
+ <td>{{ result.lane.lane_number }}</td>
+ <td><a href="{{ result.summary_url }}">Summary</a></td>
+ <td><a href="{{ result.result_url }}">{{ result.result_label }}</a></td>
+ <td>
+ {% if result.bed_url %}
+ <a href="{{ result.bed_url }}">Bed</a>
+ {% endif %}
+ </td>
+ <td>
+ {% if result.storage_ids %}
+ {{ result.storage_ids|safe }}
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ {% else %}
+ <tr><td colspan="8">No data</td></tr>
+ {% endif %}
+ </tbody>
+ </table>
+
+ <h2>Lane Summary Statistics</h2>
+ {% block summary_stats %}
+ <table>
+ <thead>
+ <tr>
+ <td colspan="7"></td>
+ <td colspan="2">No Match</td>
+ <td colspan="2">QC Failed</td>
+ <td colspan="4">Unique</td>
+ <td colspan="4">Repeat</td>
+ </tr>
+ <tr>
+ <td>Cycles</td>
+ <td>Flowcell</td>
+ <td>Lane</td>
+ <td>End</td>
+ <td>Cluster / Tile</td>
+ <td>pM</td>
+ <td>Raw Reads</td>
+ <td>total</td>
+ <td>%</td>
+ <td>total</td>
+ <td>%</td>
+ <td>0 mismatch</td>
+ <td>1 mismatch</td>
+ <td>2 mismatch</td>
+ <td>Total</td>
+ <td>0 mismatch</td>
+ <td>1 mismatch</td>
+ <td>2 mismatch</td>
+ <td>Total</td>
+ </tr>
+ </thead>
+ <tbody>
+ {% if lane_summary_list %}
+ {# ls short for lane summary #}
+ {% for ls in lane_summary_list %}
+ <tr about="{{ls.lane.get_absolute_url}}">
+ <td>{{ ls.cycle_width }}</td>
+ <td><a href="{{ls.flowcell.get_absolute_url}}">{{ ls.flowcell_id }}</a>
+ </td>
+ <td><a href="{{ls.lane.get_absolute_url}}">{{ ls.lane_id }}</a></td>
+ <td>{% if ls.end %}{{ ls.end }}{% endif %}</td>
+ <td>{{ ls.clusters.0|intcomma }}</td>
+ <td>{{ ls.successful_pm }}</td>
+ <td>{{ ls.reads|intcomma }}</td>
+ <td>{{ ls.no_match|intcomma }}</td>
+ <td>{{ ls.no_match_percent|stringformat:".2f" }}</td>
+ <td>{{ ls.qc_failed|intcomma }}</td>
+ <td>{{ ls.qc_failed_percent|stringformat:".2f" }}</td>
+ <td>{{ ls.match_codes.U0|intcomma }}</td>
+ <td>{{ ls.match_codes.U1|intcomma }}</td>
+ <td>{{ ls.match_codes.U2|intcomma }}</td>
+ <td {% if ls.unique_reads %}property="libns:total_unique_locations" content="{{ls.unique_reads}}" datatype="xsd:decimal"{% endif %}>{{ ls.unique_reads|intcomma }}</td>
+ <td>{{ ls.match_codes.R0|intcomma }}</td>
+ <td>{{ ls.match_codes.R1|intcomma }}</td>
+ <td>{{ ls.match_codes.R2|intcomma }}</td>
+ <td>{{ ls.repeat_reads|intcomma }}</td>
+ </tr>
+ {% endfor %}
+ {% else %}
+ <tr><td colspan="20">No data</td></tr>
+ {% endif %}
+ </tbody>
+ </table>
+
+ <h2>Flowcell Notes</h2>
+ <table>
+ <thead>
+ <tr>
+ <td>Flowcell ID</td>
+ <td>Lane</td>
+ <td>Comment</td>
+ </tr>
+ </thead>
+ {% if lib.lane_set.all %}
+ <tbody>
+ {% for lane in lib.lane_set.all %}
+ <tr rel="libns:has_lane"
+ about="{{lib.get_absolute_url}}"
+ resource="{{lane.get_absolute_url}}">
+ <td>
+ <a typeof="libns:IlluminaFlowcell" href="{{lane.flowcell.get_absolute_url}}">
+ <span property="libns:flowcell_id"
+ >{{lane.flowcell.flowcell_id}}</span></a>
+ {% if user.is_staff %}
+ <a href="{{lane.flowcell.get_admin_url}}">
+ <img class="icon_button"
+ src="{% static "admin/img/icon_changelink.gif" %}" alt="Edit"/>
+ </a>
+ {% endif%}
+ </td>
+ <td typeof="libns:IlluminaLane" about="{{lane.get_absolute_url}}">
+ <span rel="libns:flowcell" resource="{{lane.flowcell.get_absolute_url}}"></span>
+ <a href="{{lane.get_absolute_url}}">
+ <span property="libns:lane_number"
+ >{{ lane.lane_number }}</span>
+ </a></td>
+ <td>{{ lane.comment }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ {% endif %}
+ </table>
+ <br/>
+ <hr/>
+ <h2>Count of multi-reads</h2>
+ {% for eland_lane in lane_summary_list %}
+ {% if eland_lane.summarized_reads %}
+ <h3>{{eland_lane.cycle_width}} {{ eland_lane.flowcell_id }} lane {{ eland_lane.lane_id }}
+ {% if eland_lane.end %} end {{ eland_lane.end }}{% endif %}
+ </h3>
+ <ul about="{{eland_lane.lane.get_absolute_url}}">
+ {% for name, counts in eland_lane.summarized_reads.items %}
+ <li rel="libns:has_mappings">
+ <b property="libns:mapped_to">{{ name }}</b>:
+ <span property="libns:reads" content="{{counts}}" datatype="xsd:integer">{{ counts|intcomma }}</span></li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ {% endfor %}
+ {% endblock %}
+ </div>
+{% endblock %}
--- /dev/null
+{% extends "base_site.html" %}
+{% load admin_list i18n %}
+{% load staticfiles %}
+{% block extrahead %}
+ <!-- App Stuff -->
+ <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}"/>
+
+ {% block additional_javascript %}
+ <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
+ <script type="text/javascript" src="{% static "js/htsw.js" %}"></script>
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $(window).resize(function() {
+ var window_height = $(window).height();
+ var position = $("#changelist table").position();
+ height = window_height - position.top;
+ $("#changelist table.filtered").height(height);
+ $("#changelist-filter").height(height);
+ });
+ $(window).resize();
+ });
+ </script>
+ {% endblock %}
+{% endblock %}
+{% block bodyclass %}change-list{% endblock %}
+{% block coltype %}flex{% endblock %}
+
+{% block content %}
+<div id="library_header_link">
+{% if todo_only %}<a href="..">All</a>{% else %}<a href="not_run/">Not run</a>
+{% endif %}
+</div>
+<div id="library-index-div" >
+ <div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
+ {% block search %}{% search_form cl %}{% endblock %}
+
+ {% block pagination %}{% pagination cl %}{% endblock %}
+
+ {% block filters %}
+ {% if cl.has_filters %}
+ <div id="changelist-filter">
+ <h2 >{% trans 'Filter' %}</h2>
+ {% for spec in cl.filter_specs %}
+ {% admin_list_filter cl spec %}
+ {% endfor %}
+ </div>
+ {% endif %}
+ {% endblock %}
+ {% block summary_stats %}
+ <table class="{% if cl.has_filters %} filtered{% endif %}">
+ <thead >
+ <tr >
+ <td >Parent</td>
+ <td >Library ID</td>
+ <td >Species</td>
+ <td >Library Name</td>
+ <td colspan="3" >Single</td>
+ <td colspan="3" >Paired</td>
+ <td >HD</td>
+ </tr>
+ <tr >
+ <td colspan="4"></td>
+ <td><40</td>
+ <td><100</td>
+ <td>100+</td>
+ <td><40</td>
+ <td><100</td>
+ <td>100+</td>
+ <td></td>
+ </tr>
+ </thead>
+ <tbody >
+ {% for lib in library_list %}
+ <tr typeof="libns:Library" about="{{lib.library.get_absolute_url}}">
+ <td ><a href="{{lib.library.get_absolute_url}}">{{ lib.amplified_from }}</a></td>
+ <td ><a href="{{lib.library.get_absolute_url}}"><span property="libns:library_id">{{ lib.library_id }}</span></a></td>
+ <td rel="libns:species">
+ <a typeof="libns:Species"
+ href="{{lib.library.library_species.get_absolute_url}}">
+ <span property="libns:species_name">{{ lib.species_name }}</span>
+ </a>
+ </td>
+ <td >
+ <a href="{{ lib.library.get_absolute_url }}">
+ <span property="libns:name">{{ lib.library_name }}</span>
+ </a>
+ </td>
+ <td bgcolor="#00BFFF">{{ lib.lanes_run.0.0 }}</td>
+ <td bgcolor="#00BFFF">{{ lib.lanes_run.0.1 }}</td>
+ <td bgcolor="#00BFFF">{{ lib.lanes_run.0.2 }}</td>
+ <td bgcolor="#66CDAA">{{ lib.lanes_run.1.0 }}</td>
+ <td bgcolor="#66CDAA">{{ lib.lanes_run.1.1 }}</td>
+ <td bgcolor="#66CDAA">{{ lib.lanes_run.1.2 }}</td>
+ {% if lib.is_archived %}
+ <td ><img src="{% static "img/hdd_unmount.png" %}" alt="Archived" /></td>
+ {% else %}
+ <td ></td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div>
+ {% endblock %}
+</div>
+{% endblock %}
--- /dev/null
+{% extends "base_site.html" %}
+{% load staticfiles %}
+{% load humanize i18n %}
+{% block extrahead %}
+ <!-- App Stuff -->
+ <link type="text/css" rel="stylesheet" href="{% static "css/app.css" %}" />
+ <script type="text/javascript" src="{% static "js/jquery.min.js" %}"></script>
+
+ {% block additional_javascript %}
+ {% endblock %}
+{% endblock %}
+
+{% block content %}
+<div id="genome_detail">
+ <h2>About this Genome</h2>
+ <b>Common Name</b>:
+ <span property="libns:species_name">{{ species.common_name}}</span><br/>
+ <b>Scientific Name</b>:
+ <span property="libns:species_name">{{ species.scientific_name}}</span><br/>
+</div>
+{% endblock %}
--- /dev/null
+{% load staticfiles %}
+{% load i18n %}
+{% if cl.search_fields %}
+<div id="toolbar"><form id="changelist-search" action="" method="get">
+<div><!-- DIV needed for valid HTML -->
+<label for="searchbar"><img src="{% static "img/admin/icon_searchbox.png" %}" alt="Search" /></label>
+<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" />
+<input type="submit" value="{% trans 'Go' %}" />
+{% if show_result_count %}
+ <span class="small quiet">{% blocktrans count cl.result_count as counter %}1 result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?{% if cl.is_popup %}pop=1{% endif %}">{% blocktrans with cl.full_result_count as full_result_count %}{{ full_result_count }} total{% endblocktrans %}</a>)</span>
+{% endif %}
+{% for pair in cl.params.items %}
+ {% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0 }}" value="{{ pair.1 }}"/>{% endifnotequal %}
+{% endfor %}
+</div>
+</form></div>
+<script type="text/javascript">document.getElementById("searchbar").focus();</script>
+{% endif %}
--- /dev/null
+from django.conf.urls import include, patterns, url
+from django.contrib import admin
+import django
+admin.autodiscover()
+
+from django.conf import settings
+
+urlpatterns = patterns('',
+ url('^accounts/', include('django.contrib.auth.urls')),
+ # Base:
+ url(r'^eland_config/', include('eland_config.urls')),
+ # Experiments:
+ url(r'^experiments/', include('experiments.urls')),
+ url(r'^lane/(?P<lane_pk>\w+)',
+ 'experiments.views.flowcell_lane_detail'),
+ url(r'^flowcell/(?P<flowcell_id>\w+)/((?P<lane_number>\w+)/)?$',
+ 'experiments.views.flowcell_detail'),
+ url(r'^inventory/', include('inventory.urls')),
+ url(r'^library/', include('samples.urls')),
+ url(r'^lanes_for/$', 'samples.views.lanes_for'),
+ url(r'^lanes_for/(?P<username>\w+)', 'samples.views.lanes_for'),
+ ### library id to admin url
+ url(r'^library_id_to_admin_url/(?P<lib_id>\w+)/$',
+ 'samples.views.library_id_to_admin_url'),
+ ### sample / library information
+ url(r'^samples/', include('samples.urls')),
+ url(r'^sequencer/(?P<sequencer_id>\w+)',
+ 'experiments.views.sequencer'),
+
+ url(r'^admin/', include(admin.site.urls)),
+)
"""
compute a bedfile name and description from the django database
"""
- from htsworkflow.frontend.experiments import models as experiments
+ from htsworkflow.experiments import models as experiments
lane = int(lane)
if lane < 1 or lane > 8:
--- /dev/null
+from __future__ import absolute_import, print_function
+
+from django.contrib import admin
+
+from .models import Item, ItemInfo, ItemType, Vendor, Location, LongTermStorage, ItemStatus, ReagentFlowcell, ReagentLibrary, PrinterTemplate
+
+class ItemAdmin(admin.ModelAdmin):
+ save_as = True
+ save_on_top = True
+ list_display = ('uuid', 'barcode_id','item_type', 'item_info', 'location', 'force_use_uuid', 'creation_date')
+ list_filter = (
+ 'item_type', 'status'
+ )
+ search_fields = [
+ 'barcode_id',
+ 'uuid',
+ 'status__name',
+ 'item_type__name',
+ 'location__name',
+ 'notes'
+ ]
+
+class ItemInfoAdmin(admin.ModelAdmin):
+ save_as = True
+ save_on_top = True
+
+class ItemTypeAdmin(admin.ModelAdmin):
+ pass
+
+class VendorAdmin(admin.ModelAdmin):
+ pass
+
+class LocationAdmin(admin.ModelAdmin):
+ pass
+
+class LongTermStorageAdmin(admin.ModelAdmin):
+ pass
+
+class ItemStatusAdmin(admin.ModelAdmin):
+ pass
+
+class ReagentFlowcellAdmin(admin.ModelAdmin):
+ pass
+
+class ReagentLibraryAdmin(admin.ModelAdmin):
+ pass
+
+class PrinterTemplateAdmin(admin.ModelAdmin):
+ list_display = ('item_type', 'printer', 'default')
+
+admin.site.register(Item, ItemAdmin)
+admin.site.register(ItemInfo, ItemInfoAdmin)
+admin.site.register(ItemType, ItemTypeAdmin)
+admin.site.register(Vendor, VendorAdmin)
+admin.site.register(Location, LocationAdmin)
+admin.site.register(LongTermStorage, LongTermStorageAdmin)
+admin.site.register(ItemStatus, ItemStatusAdmin)
+#admin.site.register(ReagentFlowcell, ReagentFlowcellAdmin)
+#admin.site.register(ReagentLibrary, ReagentLibraryAdmin)
+admin.site.register(PrinterTemplate, PrinterTemplateAdmin)
+
--- /dev/null
+from __future__ import absolute_import, print_function
+
+from .models import Item
+
+from django.core.exceptions import ObjectDoesNotExist
+
+def item_search(search):
+ """
+ Searches
+ """
+ hits = []
+ try:
+ item = Item.objects.get(uuid=search)
+ except ObjectDoesNotExist:
+ item = None
+
+ if item is not None:
+ hits.append((str(item), item.get_absolute_url()))
+
+ try:
+ item = Item.objects.get(barcode_id=search)
+ except ObjectDoesNotExist:
+ item = None
+
+ if item is not None:
+ hits.append((str(item), item.get_absolute_url()))
+
+ return hits
--- /dev/null
+[
+ {"pk": 1,
+ "model": "inventory.itemtype",
+ "fields": {"name": "Hard Drive"}
+ },
+ {"pk": 2,
+ "model": "inventory.itemtype",
+ "fields": {"name": "Illumina SR Cluster Generation Reagents"}
+ },
+ {"pk": 3,
+ "model": "inventory.itemtype",
+ "fields": {"name": "Illumina Library Creation Reagents"}
+ },
+ {"pk": 4,
+ "model": "inventory.itemtype",
+ "fields": {"name": "Illumina Sequencing Reagents"}
+ },
+ {"pk": 5,
+ "model": "inventory.itemtype",
+ "fields": {"name": "Illumina PE Cluster Generation Reagents"}
+ },
+ {"pk": 6,
+ "model": "inventory.itemtype",
+ "fields": {"name": "Library"}
+ }
+]
--- /dev/null
+[
+ {"pk": 1,
+ "model": "bcmagic.printer",
+ "fields": {"name": "ZM400 1.25x1",
+ "label_height": 1.0,
+ "notes": "Everyday use labels",
+ "label_width": 1.25,
+ "label_shape": "Square",
+ "model": "Zebra ZM400",
+ "ip_address": "131.215.34.116"}},
+ {"pk": 2,
+ "model": "bcmagic.printer",
+ "fields": {"name": "ZM400 3x3",
+ "label_height": 3.0,
+ "notes": "Larger everyday use labels",
+ "label_width": 3.0,
+ "label_shape": "Square",
+ "model": "Zebra ZM400",
+ "ip_address": "131.215.34.117"}},
+ { "model": "experiments.Sequencer",
+ "pk": 7,
+ "fields": {
+ "name": "First sequencer",
+ "instrument_name": "USI-EAS99",
+ "serial_number": "",
+ "model": "Illumina Genome Analyzer I",
+ "active": false,
+ "isdefault": false,
+ "comment": "my first sequencer"
+ }
+ },
+ { "model": "experiments.ClusterStation",
+ "pk": 1,
+ "fields": {
+ "name": "Station",
+ "isdefault": true
+ }
+ },
+ {
+ "pk": 1,
+ "model": "inventory.vendor",
+ "fields": {
+ "url": "http://www.newegg.com/",
+ "name": "newegg.com"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "inventory.location",
+ "fields": {
+ "uuid": "e344a4a2522211de99b00015172ce556",
+ "notes": "",
+ "location_description": "Office 1",
+ "name": "Dev Office"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "inventory.iteminfo",
+ "fields": {
+ "model_id": "WD10EADS-00L5B1",
+ "vendor": 1,
+ "lot_number": "",
+ "url": "http://www.newegg.com/Product/Product.aspx?Item=N82E16822136317&Tpk=WD10EADS",
+ "warranty_months": 24,
+ "notes": "",
+ "part_number": "",
+ "purchase_date": "2009-05-19",
+ "qty_purchased": 17
+ }
+ },
+ {
+ "pk": 1,
+ "model": "inventory.itemtype",
+ "fields": {
+ "name": "Hard Drive",
+ "description": null
+ }
+ },
+ {
+ "pk": 1,
+ "model": "inventory.itemstatus",
+ "fields": {
+ "notes": "",
+ "name": "Used"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "inventory.itemstatus",
+ "fields": {
+ "notes": "",
+ "name": "Unused"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "inventory.item",
+ "fields": {
+ "status": null,
+ "modified_date": "2009-08-10T16:58:44-0800",
+ "uuid": "8a90b6ce522311de99b00015172ce556",
+ "barcode_id": "WCAU49183397",
+ "notes": "",
+ "item_info": 1,
+ "force_use_uuid": false,
+ "item_type": 1,
+ "location": 1,
+ "creation_date": "2009-06-05T15:52:26-0800"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "inventory.item",
+ "fields": {
+ "status": null,
+ "modified_date": "2009-06-16T11:38:24-0800",
+ "uuid": "b0792d425aa411de99b00015172ce556",
+ "barcode_id": "WCAU49042470",
+ "notes": "",
+ "item_info": 1,
+ "force_use_uuid": false,
+ "item_type": 1,
+ "location": 1,
+ "creation_date": "2009-06-16T11:37:04-0800"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "inventory.printertemplate",
+ "fields": {
+ "default": false,
+ "item_type": 1,
+ "printer": 2,
+ "template": "^FX=========================\r\n^FX 3\"x3\" Label\r\n^FX=========================\r\n^XA\r\n\r\n\r\n^FX======== Left Side ===========\r\n\r\n^FX------------\r\n^FX ^LH changes the 0,0 point of all subsequent location references\r\n^FX------------\r\n\r\n^LH0,50\r\n\r\n^FX ---Header---\r\n\r\n^FO25,0\r\n^CF0,50\r\n^FB250,2,,C\r\n^FD{{ item.barcode_id }}^FS\r\n\r\n^FX ---Column 1: Flowcells---\r\n\r\n^FX-----------------\r\n^FX FB command for automatic text formatting:\r\n^FX ^FB[dot width of area], [max # of lines], [change line spacing], [justification: L, C, R, J], [hanging indent]\r\n^FX-----------------\r\n\r\n^CF0,30,30\r\n^FO75,125\r\n^FB275,19,,L\r\n^FD{% for flowcell in flowcell_id_list %}{{ flowcell }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n^FX ---Date---\r\n\r\n^FO0,725\r\n^CF0,35\r\n^FB300,2,,C\r\n^FD{{ oldest_rundate|date:\"YMd\" }} - {{ latest_rundate|date:\"YMd\" }}^FS\r\n\r\n^FX ---Barcode---\r\n\r\n^FO135,795\r\n^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS\r\n\r\n^FX======== Right Side ===========\r\n\r\n^LH300,60\r\n\r\n^FX ---Header---\r\n\r\n^FO0,0\r\n^CF0,50\r\n^FB600,2,,C\r\n^FD{{ barcode_id }}^FS\r\n\r\n^FX ---Dividing line---\r\n\r\n^FX---------------\r\n^FX GB command:\r\n^FX ^GB[box width], [box height], [border thickness], [color: B, W], [corner rounding: 0-8]^FS\r\n^FX---------------\r\n\r\n^FO0,100\r\n^GB0,600,10^FS\r\n\r\n^FX ---Column 2: Libraries 1-20---\r\n\r\n^CF0,30,30\r\n^FO75,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_1_to_20 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 3: Libraries 21-40---\r\n\r\n^CF0,30,30\r\n^FO200,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_21_to_40 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 4: Libraries 41-60---\r\n\r\n^CF0,30,30\r\n^FO325,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_41_to_60 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 5: Libraries 61-80---\r\n\r\n^CF0,30,30\r\n^FO450,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_61_to_80 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Date---\r\n\r\n^FO0,715\r\n^CF0,35\r\n^FB600,2,,C\r\n^FDRun Dates: {{ oldest_rundate|date:\"YMd\" }}-{{ latest_rundate|date:\"YMd\" }}^FS\r\n\r\n^FX ---Barcode---\r\n\r\n^FO255,785\r\n^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS\r\n\r\n^LH0,0\r\n^FX ---End---\r\n^XZ\r\n"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "inventory.printertemplate",
+ "fields": {
+ "default": true,
+ "item_type": 2,
+ "printer": 1,
+ "template": "^FX=========================\r\n^FX Harddrive Location Tracking Label\r\n^FX 300x375 dots\r\n^FX=========================\r\n\r\n^XA\r\n^LH 0,25\r\n\r\n^FO0,0\r\n^CF0,35\r\n^FB375,1,,C\r\n^FD{{ item.item_type.name }}:^FS\r\n\r\n^FX -------Text contains HD serial #-------------\r\n^FO15,75\r\n^CF0,42\r\n^FB325,3,,C\r\n^FD{% if use_uuid %}{{ item.uuid }}{% else %}{{ item.barcode_id }}{% endif %}^FS\r\n\r\n^FX -------Barcode contains HD serial #-----------\r\n^FO150,200\r\n^BXN,3,200\r\n^FD{% if use_uuid %}invu|{{ item.uuid }}{% else %}invb|{{ item.barcode_id }}{% endif %}^FS\r\n\r\n^XZ\r\n"
+ }
+ },
+ {
+ "pk": 3,
+ "model": "inventory.printertemplate",
+ "fields": {
+ "default": false,
+ "item_type": 6,
+ "printer": 1,
+ "template": "^XA\r\n\r\n^FX ---SIDE LABEL---\r\n^LH 190,40\r\n^CF 0,30\r\n\r\n^FX------Sideways ID------\r\n^FO 0,25\r\n^TB R,100,40\r\n^FD{{ library.id }}^FS\r\n^FX------Sideways Line------\r\n^FO 50,0\r\n^GB 5,200,5^FS\r\n\r\n^FX-------Name----------\r\n^FO 65,20\r\n^FB 325,4\r\n^FD{{ library.library_name }}^FS\r\n\r\n^FX ---TOP LABEL---\r\n^LH 12,28\r\n^CF 0,30\r\n\r\n^FX----ID #----\r\n^FO 5,25\r\n^FB 145,1,,C\r\n^FD{{ library.id }}^FS\r\n\r\n^FX----Name----\r\n^CF 0,16\r\n^FO 13,47\r\n^TB N,130,30\r\n^FD{{ library.library_name }}^FS\r\n\r\n^FX--------Barcode--------\r\n^FO 50,80\r\n^BXN ,3,200\r\n^FDl|0000000{{ library.id }}|woldlab^FS\r\n\r\n{% if not library.hidden %}\r\n^FX-----Border-------\r\n^FO 0,0\r\n^GC 150,10\r\n^FX ---End---\r\n{% endif %}\r\n^XZ\r\n"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "inventory.longtermstorage",
+ "fields": {
+ "libraries": [
+ "10001",
+ "10002",
+ "10003"
+ ],
+ "modified_date": "2009-06-01T00:00:00-0800",
+ "storage_devices": [
+ 1
+ ],
+ "flowcell": 1,
+ "creation_date": "2009-06-01T00:00:00-0800"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "inventory.longtermstorage",
+ "fields": {
+ "libraries": [
+ "10001",
+ "10002",
+ "10003"
+ ],
+ "modified_date": "2009-06-01T00:00:00-0800",
+ "storage_devices": [
+ 1
+ ],
+ "flowcell": 2,
+ "creation_date": "2009-06-01T00:00:00-0800"
+ }
+ },
+ {"pk": 1, "model": "experiments.flowcell",
+ "fields": {
+ "paired_end": true,
+ "run_date": "2009-09-11T22:12:13-0800",
+ "read_length": 75,
+ "notes": "",
+ "advanced_run": false,
+ "control_lane": 2,
+ "flowcell_id": "11ONEAAXX"
+ }
+ },
+ {"pk": 2, "model": "experiments.flowcell",
+ "fields": {
+ "paired_end": false,
+ "run_date": "2010-09-11T22:12:13-0800",
+ "read_length": 75,
+ "notes": "",
+ "advanced_run": false,
+ "control_lane": 2,
+ "flowcell_id": "22TWOAAXX"
+ }
+ },
+ {"pk": 3, "model": "experiments.flowcell",
+ "fields": {
+ "paired_end": false,
+ "run_date": "2010-09-11T22:12:13-0800",
+ "read_length": 75,
+ "notes": "",
+ "advanced_run": false,
+ "control_lane": 2,
+ "flowcell_id": "33THRAAXX (failed)"
+ }
+ },
+ {"pk": "10001", "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 400,
+ "library_name": "10001",
+ "creation_date": "2009-07-21",
+ "cell_line": 1,
+ "library_species": 2,
+ "library_type": null,
+ "made_by": "Igor",
+ "affiliations": [
+ 1
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "Done",
+ "tags": [],
+ "made_for": "Test",
+ "amplified_from_sample": null,
+ "notes": "",
+ "undiluted_concentration": "1",
+ "successful_pM": null,
+ "experiment_type": 10,
+ "antibody": null
+ }
+ },
+ {"pk": "10002", "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 400,
+ "library_name": "10002",
+ "creation_date": "2009-07-21",
+ "cell_line": 1,
+ "library_species": 2,
+ "library_type": null,
+ "made_by": "Igor",
+ "affiliations": [
+ 1
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "Done",
+ "tags": [],
+ "made_for": "Test",
+ "amplified_from_sample": null,
+ "notes": "",
+ "undiluted_concentration": "1",
+ "successful_pM": null,
+ "experiment_type": 10,
+ "antibody": null
+ }
+ },
+ {"pk": "10003", "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 400,
+ "library_name": "10003",
+ "creation_date": "2009-07-21",
+ "cell_line": 1,
+ "library_species": 2,
+ "library_type": null,
+ "made_by": "Igor",
+ "affiliations": [
+ 1
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "Done",
+ "tags": [],
+ "made_for": "Test",
+ "amplified_from_sample": null,
+ "notes": "",
+ "undiluted_concentration": "1",
+ "successful_pM": null,
+ "experiment_type": 10,
+ "antibody": null
+ }
+ },
+ {"pk": 1, "model": "experiments.lane",
+ "fields": {
+ "comment": "10001 lane 1",
+ "library": "10001",
+ "cluster_estimate": 100000,
+ "flowcell": 1,
+ "lane_number": 1,
+ "pM": "8"
+ }
+ },
+ {"pk": 2, "model": "experiments.lane",
+ "fields": {
+ "comment": "10002 lane 2",
+ "library": "10002",
+ "cluster_estimate": 100000,
+ "flowcell": 1,
+ "lane_number": 2,
+ "pM": "8"
+ }
+ },
+ {"pk": 3, "model": "experiments.lane",
+ "fields": {
+ "comment": "10003 lane 3",
+ "library": "10003",
+ "cluster_estimate": 100000,
+ "flowcell": 1,
+ "lane_number": 3,
+ "pM": "8"
+ }
+ },
+ {"pk": 4, "model": "experiments.lane",
+ "fields": {
+ "comment": "10004 lane 4",
+ "library": "10001",
+ "cluster_estimate": 100000,
+ "flowcell": 2,
+ "lane_number": 4,
+ "pM": "8"
+ }
+ },
+ {"pk": 5, "model": "experiments.lane",
+ "fields": {
+ "comment": "10001 lane 1",
+ "library": "10001",
+ "cluster_estimate": 100000,
+ "flowcell": 2,
+ "lane_number": 1,
+ "pM": "8"
+ }
+ },
+ {"pk": 6, "model": "experiments.lane",
+ "fields": {
+ "comment": "10001 lane 1",
+ "library": "10003",
+ "cluster_estimate": 100000,
+ "flowcell": 2,
+ "lane_number": 2,
+ "pM": "8"
+ }
+ },
+ {"pk": 7, "model": "experiments.lane",
+ "fields": {
+ "comment": "10003 lane 8",
+ "library": "10003",
+ "cluster_estimate": 100000,
+ "flowcell": 2,
+ "lane_number": 8,
+ "pM": "8"
+ }
+ },
+ {"pk": 8, "model": "experiments.lane",
+ "fields": {
+ "comment": "10002 lane 8",
+ "library": "10001",
+ "cluster_estimate": 100000,
+ "flowcell": 2,
+ "lane_number": 8,
+ "pM": "8"
+ }
+ },
+ {"pk": 9, "model": "experiments.lane",
+ "fields": {
+ "comment": "10004 lane 4",
+ "library": "10001",
+ "cluster_estimate": 100000,
+ "flowcell": 3,
+ "lane_number": 4,
+ "pM": "8"
+ }
+ },
+ {"pk": 10, "model": "experiments.lane",
+ "fields": {
+ "comment": "10001 lane 1",
+ "library": "10001",
+ "cluster_estimate": 100000,
+ "flowcell": 3,
+ "lane_number": 1,
+ "pM": "8"
+ }
+ },
+ {"pk": 11, "model": "experiments.lane",
+ "fields": {
+ "comment": "10001 lane 1",
+ "library": "10003",
+ "cluster_estimate": 100000,
+ "flowcell": 3,
+ "lane_number": 2,
+ "pM": "8"
+ }
+ },
+ {"pk": 12, "model": "experiments.lane",
+ "fields": {
+ "comment": "10003 lane 8",
+ "library": "10003",
+ "cluster_estimate": 100000,
+ "flowcell": 3,
+ "lane_number": 8,
+ "pM": "8"
+ }
+ },
+ {"pk": 13, "model": "experiments.lane",
+ "fields": {
+ "comment": "10002 lane 8",
+ "library": "10001",
+ "cluster_estimate": 100000,
+ "flowcell": 3,
+ "lane_number": 8,
+ "pM": "8"
+ }
+ }
+]
--- /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-01T00:00:01-0800",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
+ "email": "",
+ "date_joined": "2009-01-01T00:01:01-0800"
+ }
+ },
+ {"pk": 5, "model": "samples.htsuser",
+ "fields" : {}
+ },
+ {"pk": 6, "model": "auth.user",
+ "fields": {
+ "username": "admintest",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": false,
+ "is_staff": true,
+ "last_login": "2009-01-01T00:00:01-0800",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
+ "email": "",
+ "date_joined": "2009-01-01T00:01:01-0800"
+ }
+ },
+ {"pk": 6, "model": "samples.htsuser",
+ "fields" : {}
+ },
+ {"pk": 7, "model": "auth.user",
+ "fields": {
+ "username": "supertest",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": true,
+ "is_staff": true,
+ "last_login": "2009-01-01T00:00:01-0800",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
+ "email": "",
+ "date_joined": "2009-01-01T00:01:01-0800"
+ }
+ },
+ {"pk": 7, "model": "samples.htsuser",
+ "fields" : {}
+ },
+ {"pk": 1, "model": "samples.affiliation",
+ "fields": {
+ "users": [5],
+ "contact": "group 1",
+ "name": "affiliation 1",
+ "email": "pk1@example.com"
+ }
+ },
+ {"pk": 2, "model": "samples.affiliation",
+ "fields": {
+ "users": [6],
+ "contact": "group 2",
+ "name": "affiliation 2",
+ "email": "pk2@example.com"
+ }
+ },
+ {"pk": 3, "model": "samples.affiliation",
+ "fields": {
+ "users": [],
+ "contact": "group 3",
+ "name": "affiliation 3",
+ "email": "pk3@example.com"
+ }
+ },
+ {"pk": 4, "model": "samples.affiliation",
+ "fields": {
+ "users": [],
+ "contact": "group 4",
+ "name": "affiliation 4",
+ "email": "pk1@example.com"
+ }
+ },
+ {"pk": 5, "model": "samples.affiliation",
+ "fields": {
+ "users": [],
+ "contact": "group 5",
+ "name": "affiliation 5",
+ "email": "pk5@example.com"
+ }
+ }
+]
--- /dev/null
+[{"pk": 1,
+ "model": "inventory.printertemplate",
+ "fields": {"default": false,
+ "item_type": 1,
+ "printer": 2,
+ "template": "^FX=========================\r\n^FX 3\"x3\" Label\r\n^FX=========================\r\n^XA\r\n\r\n\r\n^FX======== Left Side ===========\r\n\r\n^FX------------\r\n^FX ^LH changes the 0,0 point of all subsequent location references\r\n^FX------------\r\n\r\n^LH0,50\r\n\r\n^FX ---Header---\r\n\r\n^FO25,0\r\n^CF0,50\r\n^FB250,2,,C\r\n^FD{{ item.barcode_id }}^FS\r\n\r\n^FX ---Column 1: Flowcells---\r\n\r\n^FX-----------------\r\n^FX FB command for automatic text formatting:\r\n^FX ^FB[dot width of area], [max # of lines], [change line spacing], [justification: L, C, R, J], [hanging indent]\r\n^FX-----------------\r\n\r\n^CF0,30,30\r\n^FO75,125\r\n^FB275,19,,L\r\n^FD{% for flowcell in flowcell_id_list %}{{ flowcell }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n^FX ---Date---\r\n\r\n^FO0,725\r\n^CF0,35\r\n^FB300,2,,C\r\n^FD{{ oldest_rundate|date:\"YMd\" }} - {{ latest_rundate|date:\"YMd\" }}^FS\r\n\r\n^FX ---Barcode---\r\n\r\n^FO135,795\r\n^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS\r\n\r\n^FX======== Right Side ===========\r\n\r\n^LH300,60\r\n\r\n^FX ---Header---\r\n\r\n^FO0,0\r\n^CF0,50\r\n^FB600,2,,C\r\n^FD{{ barcode_id }}^FS\r\n\r\n^FX ---Dividing line---\r\n\r\n^FX---------------\r\n^FX GB command:\r\n^FX ^GB[box width], [box height], [border thickness], [color: B, W], [corner rounding: 0-8]^FS\r\n^FX---------------\r\n\r\n^FO0,100\r\n^GB0,600,10^FS\r\n\r\n^FX ---Column 2: Libraries 1-20---\r\n\r\n^CF0,30,30\r\n^FO75,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_1_to_20 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 3: Libraries 21-40---\r\n\r\n^CF0,30,30\r\n^FO200,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_21_to_40 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 4: Libraries 41-60---\r\n\r\n^CF0,30,30\r\n^FO325,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_41_to_60 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Column 5: Libraries 61-80---\r\n\r\n^CF0,30,30\r\n^FO450,100\r\n^FB100,20,,L\r\n^FD{% for lib_id in library_id_list_61_to_80 %}{{ lib_id }}{% if not forloop.last %}\\&{% endif %}{% endfor %}^FS\r\n\r\n^FX ---Date---\r\n\r\n^FO0,715\r\n^CF0,35\r\n^FB600,2,,C\r\n^FDRun Dates: {{ oldest_rundate|date:\"YMd\" }}-{{ latest_rundate|date:\"YMd\" }}^FS\r\n\r\n^FX ---Barcode---\r\n\r\n^FO255,785\r\n^BXN,3,200^FDinvb|{{ item.barcode_id }}^FS\r\n\r\n^LH0,0\r\n^FX ---End---\r\n^XZ\r\n"}},
+ {"pk": 2,
+ "model": "inventory.printertemplate",
+ "fields": {"default": true,
+ "item_type": 2,
+ "printer": 1,
+ "template": "^FX=========================\r\n^FX Harddrive Location Tracking Label\r\n^FX 300x375 dots\r\n^FX=========================\r\n\r\n^XA\r\n^LH 0,25\r\n\r\n^FO0,0\r\n^CF0,35\r\n^FB375,1,,C\r\n^FD{{ item.item_type.name }}:^FS\r\n\r\n^FX -------Text contains HD serial #-------------\r\n^FO15,75\r\n^CF0,42\r\n^FB325,3,,C\r\n^FD{% if use_uuid %}{{ item.uuid }}{% else %}{{ item.barcode_id }}{% endif %}^FS\r\n\r\n^FX -------Barcode contains HD serial #-----------\r\n^FO150,200\r\n^BXN,3,200\r\n^FD{% if use_uuid %}invu|{{ item.uuid }}{% else %}invb|{{ item.barcode_id }}{% endif %}^FS\r\n\r\n^XZ\r\n"}}
+]
--- /dev/null
+from __future__ import absolute_import, print_function
+
+import logging
+
+from django.db import models
+from django.db.models.signals import pre_save
+
+from samples.models import Library
+from experiments.models import FlowCell
+from bcmagic.models import Printer
+
+LOGGER = logging.getLogger(__name__)
+
+try:
+ import uuid
+except ImportError, e:
+ # Some systems are using python 2.4, which doesn't have uuid
+ # this is a stub
+ LOGGER.warning('Real uuid is not available, initializing fake uuid module')
+ class uuid:
+ def uuid1(self):
+ self.hex = None
+ return self
+
+def _assign_uuid(sender, instance, **kwargs):
+ """
+ Assigns a UUID to model on save
+ """
+ #print 'Entered _assign_uuid'
+ if instance.uuid is None or len(instance.uuid) != 32:
+ instance.uuid = uuid.uuid1().hex
+
+def _switch_default(sender, instance, **kwargs):
+ """
+ When new instance has default == True, uncheck all other defaults
+ """
+ if instance.default:
+ other_defaults = PrinterTemplate.objects.filter(default=True)
+
+ for other in other_defaults:
+ other.default = False
+ other.save()
+
+
+class Vendor(models.Model):
+ name = models.CharField(max_length=256)
+ url = models.URLField(blank=True, null=True)
+
+ def __unicode__(self):
+ return u"%s" % (self.name)
+
+
+class Location(models.Model):
+
+ name = models.CharField(max_length=256, unique=True)
+ location_description = models.TextField()
+
+ uuid = models.CharField(max_length=32, blank=True, help_text="Leave blank for automatic UUID generation", editable=False)
+
+ notes = models.TextField(blank=True, null=True)
+
+ def __unicode__(self):
+ if len(self.location_description) > 16:
+ return u"%s: %s" % (self.name, self.location_description[0:16]+u"...")
+ else:
+ return u"%s: %s" % (self.name, self.location_description)
+
+pre_save.connect(_assign_uuid, sender=Location)
+
+
+class ItemInfo(models.Model):
+ model_id = models.CharField(max_length=256, blank=True, null=True)
+ part_number = models.CharField(max_length=256, blank=True, null=True)
+ lot_number = models.CharField(max_length=256, blank=True, null=True)
+
+ url = models.URLField(blank=True, null=True)
+
+ qty_purchased = models.IntegerField(default=1)
+
+ vendor = models.ForeignKey(Vendor)
+ purchase_date = models.DateField(blank=True, null=True)
+ warranty_months = models.IntegerField(blank=True, null=True)
+
+ notes = models.TextField(blank=True, null=True)
+
+ def __unicode__(self):
+ name = u''
+ if self.model_id:
+ name += u"model:%s " % (self.model_id)
+ if self.part_number:
+ name += u"part:%s " % (self.part_number)
+ if self.lot_number:
+ name += u"lot:%s " % (self.lot_number)
+
+ return u"%s: %s" % (name, self.purchase_date)
+
+ class Meta:
+ verbose_name_plural = "Item Info"
+
+
+class ItemType(models.Model):
+
+ name = models.CharField(max_length=64, unique=True)
+ description = models.TextField(blank=True, null=True)
+
+ def __unicode__(self):
+ return u"%s" % (self.name)
+
+class ItemStatus(models.Model):
+ name = models.CharField(max_length=64, unique=True)
+ notes = models.TextField(blank=True, null=True)
+
+ def __unicode__(self):
+ return self.name
+
+ class Meta:
+ verbose_name_plural = "Item Status"
+
+
+class Item(models.Model):
+
+ item_type = models.ForeignKey(ItemType)
+
+ #Automatically assigned uuid; used for barcode if one is not provided in
+ # barcode_id
+ uuid = models.CharField(max_length=32, blank=True, help_text="Leave blank for automatic UUID generation", unique=True, editable=False)
+
+ # field for existing barcodes; used instead of uuid if provided
+ barcode_id = models.CharField(max_length=256, blank=True, null=True)
+ force_use_uuid = models.BooleanField(default=False)
+
+ item_info = models.ForeignKey(ItemInfo)
+
+ location = models.ForeignKey(Location)
+
+ status = models.ForeignKey(ItemStatus, blank=True, null=True)
+
+ creation_date = models.DateTimeField(auto_now_add=True)
+ modified_date = models.DateTimeField(auto_now=True)
+
+ notes = models.TextField(blank=True, null=True)
+
+ def __unicode__(self):
+ if self.barcode_id is None or len(self.barcode_id) == 0:
+ return u"invu|%s" % (self.uuid)
+ else:
+ return u"invb|%s" % (self.barcode_id)
+
+ def get_absolute_url(self):
+ return '/inventory/%s/' % (self.uuid)
+
+pre_save.connect(_assign_uuid, sender=Item)
+
+
+class PrinterTemplate(models.Model):
+ """
+ Maps templates to printer to use
+ """
+ item_type = models.ForeignKey(ItemType)
+ printer = models.ForeignKey(Printer)
+
+ default = models.BooleanField(default=False)
+
+ template = models.TextField()
+
+ def __unicode__(self):
+ if self.default:
+ return u'%s %s' % (self.item_type.name, self.printer.name)
+ else:
+ return u'%s %s (default)' % (self.item_type.name, self.printer.name)
+
+pre_save.connect(_switch_default, sender=PrinterTemplate)
+
+
+class LongTermStorage(models.Model):
+
+ flowcell = models.ForeignKey(FlowCell)
+ libraries = models.ManyToManyField(Library)
+
+ storage_devices = models.ManyToManyField(Item)
+
+ creation_date = models.DateTimeField(auto_now_add=True)
+ modified_date = models.DateTimeField(auto_now=True)
+
+ def __unicode__(self):
+ return u"%s: %s" % (str(self.flowcell), ', '.join([ str(s) for s in self.storage_devices.iterator() ]))
+
+ class Meta:
+ verbose_name_plural = "Long Term Storage"
+
+
+
+class ReagentBase(models.Model):
+
+ reagent = models.ManyToManyField(Item)
+
+ creation_date = models.DateTimeField(auto_now_add=True)
+ modified_date = models.DateTimeField(auto_now=True)
+
+ class Meta:
+ abstract = True
+
+
+class ReagentFlowcell(ReagentBase):
+ """
+ Links reagents and flowcells
+ """
+ flowcell = models.ForeignKey(FlowCell)
+
+ def __unicode__(self):
+ return u"%s: %s" % (str(self.flowcell), ', '.join([ str(s) for s in self.reagent.iterator() ]))
+
+
+class ReagentLibrary(ReagentBase):
+ """
+ Links libraries and flowcells
+ """
+ library = models.ForeignKey(Library)
+
+ def __unicode__(self):
+ return u"%s: %s" % (str(self.library), ', '.join([ str(s) for s in self.reagent.iterator() ]))
--- /dev/null
+from __future__ import absolute_import, print_function
+
+import RDF
+
+from django.test import TestCase
+from django.test.utils import setup_test_environment, \
+ teardown_test_environment
+from django.db import connection
+from django.conf import settings
+
+from django.contrib.auth.models import User
+from django.core import urlresolvers
+
+from .models import Item, Vendor
+from htsworkflow.util.rdfhelp import get_model, load_string_into_model, get_serializer, inventoryOntology, libraryOntology, fromTypedNode
+
+def localhostNode(url):
+ return RDF.Node(RDF.Uri('http://localhost%s' % (url,)))
+
+class InventoryTestCase(TestCase):
+ fixtures = ['initial_data', 'test_user', 'test_harddisks']
+
+ def test_fixture(self):
+ # make sure that some of our test data is was loaded
+ # since there was no error message when I typoed the test fixture
+ hd1 = Item.objects.get(pk=1)
+ self.failUnlessEqual(hd1.uuid, '8a90b6ce522311de99b00015172ce556')
+
+ user = User.objects.get(pk=5)
+ self.failUnlessEqual(user.username, 'test')
+
+ def test_item(self):
+ url = '/inventory/8a90b6ce522311de99b00015172ce556/'
+ self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
+ response = self.client.get(url)
+ self.failUnlessEqual(response.status_code, 200)
+
+ model = get_model()
+ load_string_into_model(model, 'rdfa', response.content, url)
+
+ itemNode = RDF.Node(RDF.Uri(url))
+ item_type = fromTypedNode(model.get_target(itemNode, inventoryOntology['item_type']))
+ self.failUnlessEqual(item_type, u'Hard Drive')
+
+ def test_itemindex(self):
+ url = '/inventory/it/Hard Drive/'
+ indexNode = localhostNode(url)
+ diskNode = localhostNode('/inventory/8a90b6ce522311de99b00015172ce556/')
+ self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
+
+ flowcells = self.get_flowcells_from_content(url, indexNode, diskNode)
+ self.failUnlessEqual(len(flowcells), 2)
+ self.failUnless('http://localhost/flowcell/11ONEAAXX/' in flowcells)
+ self.failUnless('http://localhost/flowcell/22TWOAAXX/' in flowcells)
+
+ def test_add_disk(self):
+ url = '/inventory/it/Hard Drive/'
+ #url_disk = '/inventory/8a90b6ce522311de99b00015172ce556/'
+ url_disk = '/inventory/b0792d425aa411de99b00015172ce556/'
+ indexNode = localhostNode(url)
+ diskNode = localhostNode(url_disk)
+ self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
+
+ flowcells = self.get_flowcells_from_content(url, indexNode, diskNode)
+ self.failUnlessEqual(len(flowcells), 0)
+
+ # step two link the flowcell
+ flowcell = '22TWOAAXX'
+ serial = 'WCAU49042470'
+ link_url = urlresolvers.reverse(
+ 'inventory.views.link_flowcell_and_device',
+ args=(flowcell, serial))
+ link_response = self.client.get(link_url)
+ self.failUnlessEqual(link_response.status_code, 200)
+
+ flowcells = self.get_flowcells_from_content(url, indexNode, diskNode)
+ self.failUnlessEqual(len(flowcells), 1)
+ self.failUnlessEqual('http://localhost/flowcell/%s/' % (flowcell),
+ flowcells[0])
+
+ def test_add_disk_failed_flowcell(self):
+ url = '/inventory/it/Hard Drive/'
+ #url_disk = '/inventory/8a90b6ce522311de99b00015172ce556/'
+ url_disk = '/inventory/b0792d425aa411de99b00015172ce556/'
+ indexNode = localhostNode(url)
+ diskNode = localhostNode(url_disk)
+ self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
+
+ flowcells = self.get_flowcells_from_content(url, indexNode, diskNode)
+ self.failUnlessEqual(len(flowcells), 0)
+
+ # step two link the flowcell
+ flowcell = '33THRAAXX'
+ serial = 'WCAU49042470'
+ link_url = urlresolvers.reverse(
+ 'inventory.views.link_flowcell_and_device',
+ args=(flowcell, serial))
+ link_response = self.client.get(link_url)
+ self.failUnlessEqual(link_response.status_code, 200)
+
+ flowcells = self.get_flowcells_from_content(url, indexNode, diskNode)
+ self.failUnlessEqual(len(flowcells), 1)
+ self.failUnlessEqual('http://localhost/flowcell/%s/' % (flowcell),
+ flowcells[0])
+
+
+ def get_flowcells_from_content(self, url, rootNode, diskNode):
+ model = get_model()
+
+ response = self.client.get(url)
+ self.failUnlessEqual(response.status_code, 200)
+
+ load_string_into_model(model, 'rdfa', response.content, rootNode.uri)
+ targets = model.get_targets(diskNode, libraryOntology['flowcell_id'])
+ flowcells = [ str(x.uri) for x in targets]
+ return flowcells
+
+def suite():
+ from unittest import TestSuite, defaultTestLoader
+ suite = TestSuite()
+ suite.addTests(defaultTestLoader.loadTestsFromTestCase(InventoryTestCase))
+ return suite
+
+if __name__ == "__main__":
+ from unittest import main
+ main(defaultTest="suite")
--- /dev/null
+from django.conf.urls import patterns
+
+urlpatterns = patterns('',
+ # DATA
+ (r'^data/items/$', 'inventory.views.data_items'),
+ # REMOTE LINKING
+ (r'^lts/link/(?P<flowcell>.+)/(?P<serial>.+)/$', 'inventory.views.link_flowcell_and_device'),
+
+ # INDEX
+ (r'^it/(?P<name>.+)/$', 'inventory.views.itemtype_index'),
+ (r'^(?P<uuid>[a-fA-F0-9]{32})/$', 'inventory.views.item_summary_by_uuid'),
+ (r'^(?P<uuid>[a-fA-F0-9]{32})/print/$', 'inventory.views.item_print'),
+ (r'^(?P<barcode_id>.+)/$', 'inventory.views.item_summary_by_barcode'),
+ (r'^all_index/$', 'inventory.views.all_index'),
+ (r'^$', 'inventory.views.index')
+ )
--- /dev/null
+from __future__ import absolute_import, print_function
+
+from django.conf import settings
+from django.contrib.auth.decorators import login_required
+from django.core.exceptions import ObjectDoesNotExist
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import render_to_response
+from django.template import RequestContext, Template
+from django.template.loader import get_template
+
+from samples.changelist import HTSChangeList
+from .models import Item, LongTermStorage, ItemType
+from .admin import ItemAdmin, ItemTypeAdmin
+from .bcmagic import item_search
+from experiments.models import FlowCell
+from bcmagic.plugin import register_search_plugin
+from bcmagic.forms import BarcodeMagicForm
+from bcmagic.utils import print_zpl_socket
+
+register_search_plugin('Inventory Item', item_search)
+
+try:
+ import json
+except ImportError, e:
+ import simplejson as json
+
+INVENTORY_CONTEXT_DEFAULTS = {
+ 'app_name': 'Inventory Tracker',
+ 'bcmagic': BarcodeMagicForm()
+}
+
+def __flowcell_rundate_sort(x, y):
+ """
+ Sort by rundate
+ """
+ if x.run_date > y.run_date:
+ return 1
+ elif x.run_date == y.run_date:
+ return 0
+ else:
+ return -1
+
+def __expand_longtermstorage_context(context, item):
+ """
+ Expand information for LongTermStorage
+ """
+ flowcell_list = []
+ flowcell_id_list = []
+ library_id_list = []
+
+ for lts in item.longtermstorage_set.all():
+ flowcell_list.append(lts.flowcell)
+ flowcell_id_list.append(lts.flowcell.flowcell_id)
+ library_id_list.extend([ lib.id for lib in lts.libraries.all() ])
+
+ flowcell_list.sort(__flowcell_rundate_sort)
+ context['oldest_rundate'] = flowcell_list[0].run_date
+ context['latest_rundate'] = flowcell_list[-1].run_date
+
+ context['flowcell_id_list'] = flowcell_id_list
+ context['library_id_list_1_to_20'] = library_id_list[0:20]
+ context['library_id_list_21_to_40'] = library_id_list[20:40]
+ context['library_id_list_41_to_60'] = library_id_list[40:60]
+ context['library_id_list_61_to_80'] = library_id_list[60:80]
+
+
+EXPAND_CONTEXT = {
+ 'Hard Drive': __expand_longtermstorage_context
+}
+
+#INVENTORY_ITEM_PRINT_DEFAULTS = {
+# 'Hard Drive': 'inventory/hard_drive_shell.zpl',
+# 'default': 'inventory/default.zpl',
+# 'host': settings.BCPRINTER_PRINTER1_HOST
+#}
+
+def getPrinterTemplateByType(item_type):
+ """
+ returns template to use given item_type
+ """
+ assert item_type.printertemplate_set.count() < 2
+
+ # Get the template for item_type
+ if item_type.printertemplate_set.count() > 0:
+ printer_template = item_type.printertemplate_set.all()[0]
+ return printer_template
+ # Get default
+ else:
+ try:
+ printer_template = PrinterTemplate.objects.get(default=True)
+ except ObjectDoesNotExist:
+ msg = "No template for item type (%s) and no default template found" % (item_type.name)
+ raise ValueError, msg
+
+ return printer_template
+
+
+@login_required
+def data_items(request):
+ """
+ Returns items in json format
+ """
+ item_list = Item.objects.all()
+ d = { 'results': len(item_list) }
+ rows = []
+
+ for item in item_list:
+ item_d = {}
+ item_d['uuid'] = item.uuid
+ item_d['barcode_id'] = item.barcode_id
+ item_d['model_id'] = item.item_info.model_id
+ item_d['part_number'] = item.item_info.part_number
+ item_d['lot_number'] = item.item_info.lot_number
+ item_d['vendor'] = item.item_info.vendor.name
+ item_d['creation_date'] = item.creation_date.strftime('%Y-%m-%d %H:%M:%S')
+ item_d['modified_date'] = item.modified_date.strftime('%Y-%m-%d %H:%M:%S')
+ item_d['location'] = item.location.name
+
+ # Item status if exists
+ if item.status is None:
+ item_d['status'] = ''
+ else:
+ item_d['status'] = item.status.name
+
+ # Stored flowcells on device
+ if item.longtermstorage_set.count() > 0:
+ item_d['flowcells'] = ','.join([ lts.flowcell.flowcell_id for lts in item.longtermstorage_set.all() ])
+ else:
+ item_d['flowcells'] = ''
+
+ item_d['type'] = item.item_type.name
+ rows.append(item_d)
+
+ d['rows'] = rows
+
+ return HttpResponse(json.dumps(d), content_type="application/javascript")
+
+@login_required
+def all_index(request):
+ """
+ Inventory Index View
+ """
+ # build changelist
+ item_changelist = HTSChangeList(request, Item,
+ list_filter=[],
+ search_fields=[],
+ list_per_page=200,
+ model_admin=ItemAdmin(Item, None)
+ )
+
+ context_dict = {
+ 'item_changelist': item_changelist,
+ 'page_name': 'Inventory Index'
+ }
+ context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
+
+ return render_to_response('inventory/inventory_all_index.html',
+ context_dict,
+ context_instance=RequestContext(request))
+
+@login_required
+def index(request):
+ """
+ Inventory Index View
+ """
+ # build changelist
+ item_changelist = HTSChangeList(request, ItemType,
+ list_filter=[],
+ search_fields=['name', 'description'],
+ list_per_page=50,
+ model_admin=ItemTypeAdmin(ItemType, None)
+ )
+
+ context_dict = {
+ 'item_changelist': item_changelist,
+ 'page_name': 'Inventory Index'
+ }
+ context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
+ return render_to_response('inventory/inventory_index.html',
+ context_dict,
+ context_instance=RequestContext(request))
+
+@login_required
+def itemtype_index(request, name):
+ """
+ Inventory Index View
+ """
+
+ name = name.replace('%20', ' ')
+
+ itemtype = ItemType.objects.get(name=name)
+
+ # build changelist
+ item_changelist = HTSChangeList(request, Item,
+ list_filter=[],
+ search_fields=[],
+ list_per_page=200,
+ model_admin=ItemAdmin(Item, None)
+ )
+
+ context_dict = {
+ 'item_changelist': item_changelist,
+ 'page_name': 'Inventory Index'
+ }
+ context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
+
+ return render_to_response('inventory/inventory_itemtype_index.html',
+ context_dict,
+ context_instance=RequestContext(request))
+
+
+@login_required
+def item_summary_by_barcode(request, barcode_id, msg=''):
+ """
+ Display a summary for an item by barcode
+ """
+ try:
+ item = Item.objects.get(barcode_id=barcode_id)
+ except ObjectDoesNotExist, e:
+ item = None
+
+ return item_summary_by_uuid(request, None, msg, item)
+
+
+@login_required
+def item_summary_by_uuid(request, uuid, msg='', item=None):
+ """
+ Display a summary for an item
+ """
+ # Use item instead of looking it up if it is passed.
+ if item is None:
+ try:
+ item = Item.objects.get(uuid=uuid)
+ except ObjectDoesNotExist, e:
+ item = None
+
+ context_dict = {
+ 'page_name': 'Item Summary',
+ 'item': item,
+ 'uuid': uuid,
+ 'msg': msg
+ }
+ context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
+
+ return render_to_response('inventory/inventory_summary.html',
+ context_dict,
+ context_instance=RequestContext(request))
+
+
+
+
+
+
+def __expand_context(context, item):
+ """
+ If EXPAND_CONTEXT dictionary has item.item_type.name function registered, use it to expand context
+ """
+ if item.item_type.name in EXPAND_CONTEXT:
+ expand_func = EXPAND_CONTEXT[item.item_type.name]
+ expand_func(context, item)
+
+def _item_print(item, request):
+ """
+ Prints an item given a type of item label to print
+ """
+ #FIXME: Hard coding this for now... need to abstract later.
+ context = {'item': item}
+ __expand_context(context, item)
+
+ # Print using barcode_id
+ if not item.force_use_uuid and (item.barcode_id is None or len(item.barcode_id.strip())):
+ context['use_uuid'] = False
+ msg = 'Printing item with barcode id: %s' % (item.barcode_id)
+ # Print using uuid
+ else:
+ context['use_uuid'] = True
+ msg = 'Printing item with UUID: %s' % (item.uuid)
+
+ printer_template = getPrinterTemplateByType(item.item_type)
+
+ c = RequestContext(request, context)
+ t = Template(printer_template.template)
+ print_zpl_socket(t.render(c), host=printer_template.printer.ip_address)
+
+ return msg
+
+@login_required
+def item_print(request, uuid):
+ """
+ Print a label for a given item
+ """
+ try:
+ item = Item.objects.get(uuid=uuid)
+ except ObjectDoesNotExist, e:
+ item = None
+ msg = "Item with UUID %s does not exist" % (uuid)
+
+ if item is not None:
+ msg = _item_print(item, request)
+
+ return item_summary_by_uuid(request, uuid, msg)
+
+
+def link_flowcell_and_device(request, flowcell, serial):
+ """
+ Updates database records of a flowcell being archived on a device with a particular serial #
+ """
+ assert flowcell is not None
+ assert serial is not None
+
+ LTS_UPDATED = False
+ SD_UPDATED = False
+ LIBRARY_UPDATED = False
+
+ ###########################################
+ # Retrieve Storage Device
+ try:
+ sd = Item.objects.get(barcode_id=serial)
+ except ObjectDoesNotExist, e:
+ msg = "Item with barcode_id of %s not found." % (serial)
+ raise ObjectDoesNotExist(msg)
+
+ ###########################################
+ # Retrieve FlowCell
+ try:
+ fc = FlowCell.objects.get(flowcell_id__startswith=flowcell)
+ except ObjectDoesNotExist, e:
+ msg = "FlowCell with flowcell_id of %s not found." % (flowcell)
+ raise ObjectDoesNotExist(msg)
+
+ ###########################################
+ # Retrieve or create LongTermStorage Object
+ count = fc.longtermstorage_set.count()
+ lts = None
+ if count > 1:
+ msg = "There really should only be one longtermstorage object per flowcell"
+ raise ValueError, msg
+ elif count == 1:
+ # lts already attached to flowcell
+ lts = fc.longtermstorage_set.all()[0]
+ else:
+ lts = LongTermStorage()
+ # Attach flowcell
+ lts.flowcell = fc
+ # Need a primary keey before linking to storage devices
+ lts.save()
+ LTS_UPDATED = True
+
+
+ ############################################
+ # Link Storage to Flowcell
+
+ # Add a link to this storage device if it is not already linked.
+ if sd not in lts.storage_devices.all():
+ lts.storage_devices.add(sd)
+ SD_UPDATED = True
+
+ ###########################################
+ # Add Library Links to LTS
+
+ for lane in fc.lane_set.all():
+ if lane.library not in lts.libraries.all():
+ lts.libraries.add(lane.library)
+ LIBRARY_UPDATED = True
+
+ # Save Changes
+ lts.save()
+
+ msg = ['Success:']
+ if LTS_UPDATED or SD_UPDATED or LIBRARY_UPDATED:
+ msg.append(' LongTermStorage (LTS) Created: %s' % (LTS_UPDATED))
+ msg.append(' Storage Device Linked to LTS: %s' % (SD_UPDATED))
+ msg.append(' Libraries updated in LTS: %s' % (LIBRARY_UPDATED))
+ else:
+ msg.append(' No Updates Needed.')
+
+ return HttpResponse('\n'.join(msg))
--- /dev/null
+from django.template import Context, Template
+from django.contrib import admin
+
+from .models import LabelContent, LabelTemplate, LabelPrinter
+from inventory.models import PrinterTemplate
+from bcmagic.utils import print_zpl_socket
+
+class LabelContentOptions(admin.ModelAdmin):
+ save_as = True
+ save_on_top = True
+ search_fields = (
+ 'title',
+ 'subtitle',
+ 'text',
+ 'barcode',
+ 'creator',
+ )
+ list_display = ('title','subtitle','text','barcode','template','creator')
+ list_filter = ('template','creator',)
+ fieldsets = (
+ (None, {
+ 'fields': (('title','subtitle','text','barcode'),
+ ('template','creator'))
+
+ }),
+ )
+ actions = ['action_print_labels']
+
+ def action_print_labels(self, request, queryset):
+ """
+ Django action which prints labels for the selected set of labels from the
+ Django Admin interface.
+ """
+
+ zpl_list = []
+ #Iterate over selected labels to print
+ for label in queryset.all():
+
+ template_used = LabelTemplate.objects.get(name=label.template.name)
+ # ZPL Template
+ t = Template(template_used.ZPL_code)
+
+ # Django Template Context
+ c = Context({'label': label})
+
+ # Send rendered template to the printer that the template
+ # object has been attached to in the database.
+ zpl_list.append(t.render(c))
+
+ print_zpl_socket(zpl_list, host=template_used.printer.ip_address)
+
+ self.message_user(request, "%s labels printed." % (len(queryset)))
+
+ action_print_labels.short_description = "Print Selected Labels"
+
+class LabelTemplateOptions(admin.ModelAdmin):
+ save_as = True
+ save_on_top = True
+ list_display = ('name', 'printer', 'ZPL_code')
+
+class LabelPrinterOptions(admin.ModelAdmin):
+ list_display = ('name', 'ip_address', 'labels')
+
+admin.site.register(LabelContent, LabelContentOptions)
+admin.site.register(LabelTemplate, LabelTemplateOptions)
+admin.site.register(LabelPrinter, LabelPrinterOptions)
+
--- /dev/null
+from django.db import models
+
+class LabelPrinter(models.Model):
+ """
+ Barcode Printer Information
+ """
+ name = models.CharField(max_length=256)
+ model = models.CharField(max_length=64, default='ZM400')
+ ip_address = models.IPAddressField()
+ labels = models.CharField(max_length=200)
+ notes = models.TextField(null=True, blank=True)
+
+ def __unicode__(self):
+ return u'%s: %s' % (self.name, self.labels)
+
+class LabelTemplate(models.Model):
+ """
+ Maps templates to printer to use
+ """
+ name = models.CharField(max_length=200)
+ description = models.TextField(null=True, blank=True)
+ printer = models.ForeignKey(LabelPrinter)
+
+ ZPL_code = models.TextField('template')
+
+ def __unicode__(self):
+ return '%s %s' % (self.name, self.printer.name)
+
+class LabelContent(models.Model):
+ title = models.CharField(max_length=200, null=True, blank=True)
+ subtitle = models.CharField(max_length=200, null=True, blank=True)
+ text = models.CharField(max_length=200, null=True, blank=True)
+ barcode = models.CharField(max_length=200, null=True, blank=True)
+ template = models.ForeignKey(LabelTemplate)
+ creator = models.CharField(max_length=200)
--- /dev/null
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
+def suite():
+ from unittest import TestSuite, defaultTestLoader
+ suite = TestSuite()
+ suite.addTests(defaultTestLoader.loadTestsFromTestCase(SimpleTest))
+ return suite
+
+if __name__ == "__main__":
+ from unittest import main
+ main(defaultTest="suite")
--- /dev/null
+# Create your views here.
--- /dev/null
+from __future__ import absolute_import, print_function
+
+from django.contrib import admin
+from django.contrib.admin import widgets
+from django.contrib.auth.models import User
+from django.contrib.auth.admin import UserAdmin
+from django.contrib.auth.forms import UserCreationForm, UserChangeForm
+from django.template import Context, Template
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+from django.forms import TextInput, Textarea
+
+from .models import \
+ Antibody, Cellline, Condition, ExperimentType, HTSUser, \
+ LibraryType, MultiplexIndex, Species, Affiliation, Library, Tag
+from experiments.models import Lane
+from inventory.models import PrinterTemplate
+from bcmagic.utils import print_zpl_socket
+
+# Let's disable those pesky delete everything by accident features.
+admin.site.disable_action('delete_selected')
+
+class AffiliationOptions(admin.ModelAdmin):
+ list_display = ('name','contact','email')
+ fieldsets = (
+ (None, {
+ 'fields': (('name','contact','email','users'))
+ }),
+ )
+
+ # some post 1.0.2 version of django has formfield_overrides
+ # which would replace this code with:
+ # formfield_overrids = {
+ # models.ManyToMany: { 'widget': widgets.FilteredSelectMultiple }
+ # }
+ def formfield_for_dbfield(self, db_field, **kwargs):
+ if db_field.name == 'users':
+ kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
+ rv = super(AffiliationOptions, self).formfield_for_dbfield(db_field, **kwargs)
+ # print db_field.name, kwargs
+ return rv
+
+class AntibodyOptions(admin.ModelAdmin):
+ search_fields = ('antigene','nickname','catalog','antibodies','source','biology','notes')
+ list_display = ('antigene','nickname','antibodies','catalog','source','biology','notes')
+ list_filter = ('antibodies','source')
+ fieldsets = (
+ (None, {
+ 'fields': (('antigene','nickname','antibodies'),('catalog','source'),('biology'),('notes'))
+ }),
+ )
+
+class CelllineOptions(admin.ModelAdmin):
+ list_display = ('cellline_name', 'notes')
+ search_fields = ('cellline_name', 'nickname', 'notes')
+ fieldsets = (
+ (None, {
+ 'fields': (('cellline_name','nickname',),('notes'),)
+ }),
+ )
+
+class ConditionOptions(admin.ModelAdmin):
+ list_display = (('condition_name'), ('notes'),)
+ fieldsets = (
+ (None, {
+ 'fields': (('condition_name'),('nickname'),('notes'),)
+ }),
+ )
+
+class ExperimentTypeOptions(admin.ModelAdmin):
+ model = ExperimentType
+ #list_display = ('name',)
+ #fieldsets = ( (None, { 'fields': ('name',) }), )
+
+class HTSUserCreationForm(UserCreationForm):
+ class Meta:
+ model = HTSUser
+ fields = ("username",'first_name','last_name')
+
+class HTSUserChangeForm(UserChangeForm):
+ class Meta:
+ model = HTSUser
+ fields = ("username",'first_name','last_name')
+
+class HTSUserOptions(UserAdmin):
+ form = HTSUserChangeForm
+ add_form = HTSUserCreationForm
+
+class LaneLibraryInline(admin.StackedInline):
+ model = Lane
+ extra = 0
+
+class Library_Inline(admin.TabularInline):
+ model = Library
+
+class LibraryTypeOptions(admin.ModelAdmin):
+ list_display = ['name', 'is_paired_end', 'can_multiplex']
+ model = LibraryType
+
+class MultiplexIndexOptions(admin.ModelAdmin):
+ model = MultiplexIndex
+ list_display = ['adapter_type', 'multiplex_id', 'sequence']
+
+class LibraryOptions(admin.ModelAdmin):
+ class Media:
+ css = {
+ "all": ("css/wide_account_number.css",)
+ }
+
+ date_hierarchy = "creation_date"
+ save_as = True
+ save_on_top = True
+ search_fields = (
+ 'id',
+ 'library_name',
+ 'cell_line__cellline_name',
+ 'library_species__scientific_name',
+ 'library_species__common_name',
+ )
+ list_display = (
+ 'id',
+ 'library_name',
+ 'index_sequence_text',
+ 'affiliation',
+ 'undiluted_concentration',
+ 'gel_cut_size',
+ 'creation_date',
+ )
+ list_filter = (
+ 'hidden',
+ 'experiment_type',
+ 'library_type',
+ #'cell_line',
+ 'stopping_point',
+ 'made_by',
+ 'library_species',
+ 'affiliations',
+ )
+ list_display_links = ('id', 'library_name',)
+ fieldsets = (
+ (None, {
+ 'fields': (
+ ('id','library_name','hidden'),
+ ('library_species', 'experiment_type'),
+ ('library_type', 'multiplex_id'),
+ )
+ }),
+ ('Experiment Detail:', {
+ 'fields': (('cell_line', 'replicate',),
+ ('condition',),
+ ('antibody', ),
+ ),
+ 'classes': ('collapse',),
+ }),
+ ('Creation Information:', {
+ 'fields' : (('made_by', 'creation_date', 'stopping_point'),
+ ('amplified_from_sample'),
+ ('gel_cut_size', 'insert_size',
+ 'undiluted_concentration'),
+ ('bioanalyzer_concentration','bioanalyzer_image_url'),
+ ('bioanalyzer_summary'),
+ ('notes'))
+ }),
+ ('Library/Project Affiliation:', {
+ 'fields' : (('account_number', 'affiliations'),)
+ }),
+ )
+ inlines = [
+ LaneLibraryInline,
+ ]
+ actions = ['action_print_library_labels']
+
+ def action_print_library_labels(self, request, queryset):
+ """
+ Django action which prints labels for the selected set of labels from the
+ Django Admin interface.
+ """
+
+ #Probably should ask if the user really meant to print all selected
+ # libraries if the count is above X. X=10 maybe?
+
+ # Grab the library template
+ #FIXME: Hardcoding library template name. Not a good idea... *sigh*.
+ EVIL_HARDCODED_LIBRARY_TEMPLATE_NAME = "Library"
+
+ try:
+ template = PrinterTemplate.objects.get(item_type__name=EVIL_HARDCODED_LIBRARY_TEMPLATE_NAME)
+ except PrinterTemplate.DoesNotExist:
+ self.message_user(request, "Could not find a library template with ItemType.name of '%s'" % \
+ (EVIL_HARDCODED_LIBRARY_TEMPLATE_NAME))
+ return
+
+ # ZPL Template
+ t = Template(template.template)
+
+ zpl_list = []
+ #Iterate over selected labels to print
+ for library in queryset.all():
+
+ # Django Template Context
+ c = Context({'library': library})
+
+ # Send rendered template to the printer that the template
+ # object has been attached to in the database.
+ zpl_list.append(t.render(c))
+
+ print_zpl_socket(zpl_list, host=template.printer.ip_address)
+
+ self.message_user(request, "%s labels printed." % (len(queryset)))
+
+ action_print_library_labels.short_description = "Print Labels"
+
+ def formfield_for_dbfield(self, db_field, **kwargs):
+ # Override Field type
+ if db_field.name in ('affiliations', 'tags'):
+ kwargs['widget'] = widgets.FilteredSelectMultiple(
+ db_field.verbose_name,
+ (db_field.name in self.filter_vertical)
+ )
+ field = super(LibraryOptions, self).formfield_for_dbfield(db_field,
+ **kwargs)
+ # Override field attributes
+ if db_field.name == "bioanalyzer_summary":
+ field.widget.attrs["rows"] = "3"
+ return field
+
+class SpeciesOptions(admin.ModelAdmin):
+ fieldsets = (
+ (None, {
+ 'fields': (('scientific_name', 'common_name'),)
+ }),
+ )
+
+class TagOptions(admin.ModelAdmin):
+ list_display = ('tag_name', 'context')
+ fieldsets = (
+ (None, {
+ 'fields': ('tag_name', 'context')
+ }),
+ )
+
+admin.site.register(Library, LibraryOptions)
+admin.site.register(Affiliation, AffiliationOptions)
+admin.site.register(Antibody, AntibodyOptions)
+admin.site.register(Cellline, CelllineOptions)
+admin.site.register(Condition, ConditionOptions)
+admin.site.register(ExperimentType, ExperimentTypeOptions)
+#admin.site.register(HTSUser, HTSUserOptions)
+admin.site.register(LibraryType, LibraryTypeOptions)
+admin.site.register(MultiplexIndex, MultiplexIndexOptions)
+admin.site.register(Species, SpeciesOptions)
+#admin.site.register(Tag, TagOptions)
--- /dev/null
+from __future__ import absolute_import, print_function
+
+from django.conf import settings
+from django.contrib.auth.backends import ModelBackend
+from django.core.exceptions import ImproperlyConfigured
+from django.db.models import get_model
+
+import sys
+
+class HTSUserModelBackend(ModelBackend):
+ def authenticate(self, username=None, password=None):
+ try:
+ user = self.user_class.objects.get(username=username)
+ if user.check_password(password):
+ return user
+ #except self.user_class.DoesNotExist:
+ except Exception, e:
+ print >>sys.stderr, e
+ return None
+
+ def get_user(self, user_id):
+ try:
+ return self.user_class.objects.get(pk=user_id)
+ #except self.user_class.DoesNotExist:
+ except Exception, e:
+ print >>sys.stderr, e
+ return None
+
+ @property
+ def user_class(self):
+ if not hasattr(self, '_user_class'):
+ self._user_class = get_model(*settings.CUSTOM_USER_MODEL.split('.',2))
+ if not self._user_class:
+ raise ImproperlyConfigured('Could not get custom user model')
+ return self._user_class
+
--- /dev/null
+from __future__ import absolute_import, print_function
+
+import django
+from django.contrib.admin.views.main import ChangeList
+
+class HTSChangeList(ChangeList):
+ def __init__(self, request, model, list_filter, search_fields,
+ list_per_page, model_admin, extra_filters=None):
+ """Simplification of the django model filter view
+
+ The new parameter "extra_filter" should be a mapping
+ of that will be passed as keyword arguments to
+ queryset.filter
+ """
+ self.extra_filters = extra_filters
+
+ args = {
+ 'request': request, #request
+ 'model': model, #model
+ 'list_display': [], # list_display
+ 'list_display_links': None, # list_display_links
+ 'list_filter': list_filter, #list_filter
+ 'date_hierarchy': None, # date_hierarchy
+ 'search_fields': search_fields, #search_fields
+ 'list_select_related': None, # list_select_related,
+ 'list_per_page': list_per_page, #list_per_page
+ 'list_editable': None, # list_editable
+ 'model_admin': model_admin #model_admin
+ }
+ if django.VERSION[0] >= 1 and django.VERSION[1] >= 4:
+ args['list_max_show_all'] = 20000, #list_max_show_all
+ super(HTSChangeList, self).__init__(**args)
+
+ self.is_popup = False
+ # I removed to field in the first version
+
+ self.multi_page = True
+ self.can_show_all = False
+
+ def get_queryset(self, request=None):
+ args = {}
+ if django.VERSION[0] >= 1 and django.VERSION[1] >= 4:
+ args['request'] = request #list_max_show_all
+
+ qs = super(HTSChangeList, self).get_query_set(**args)
+ if self.extra_filters:
+ new_qs = qs.filter(**self.extra_filters)
+ if new_qs is not None:
+ qs = new_qs
+ return qs
--- /dev/null
+[
+ {
+ "model": "samples.Cellline",
+ "pk": 1,
+ "fields": {
+ "cellline_name": "Unknown",
+ "notes": "Unknown"
+ }
+ },
+ {
+ "model": "samples.Cellline",
+ "pk": 2,
+ "fields": {
+ "cellline_name": "C2C12",
+ "notes": ""
+ }
+ },
+ {
+ "model": "samples.Cellline",
+ "pk": 3,
+ "fields": {
+ "cellline_name": "C2C12 60 hrs",
+ "notes": "Unknown"
+ }
+ },
+ { "pk": 1, "model": "samples.Condition",
+ "fields": {
+ "condition_name": "Unknown",
+ "nickname": "",
+ "notes": "Unknown"
+ }
+ },
+ {
+ "model": "samples.LibraryType",
+ "pk": 1,
+ "fields": {
+ "name": "Single End (non-multiplexed)",
+ "can_multiplex": false,
+ "is_paired_end": false
+ }
+ },
+ {
+ "model": "samples.LibraryType",
+ "pk": 2,
+ "fields": {
+ "name": "Paired End (non-multiplexed)",
+ "can_multiplex": false,
+ "is_paired_end": true
+ }
+ },
+ {
+ "model": "samples.LibraryType",
+ "pk": 5,
+ "fields": {
+ "name": "Barcoded Illumina",
+ "can_multiplex": true,
+ "is_paired_end": true
+ }
+ },
+ {
+ "model": "samples.LibraryType",
+ "pk": 7,
+ "fields": {
+ "name": "Barcoded Small RNA",
+ "can_multiplex": true,
+ "is_paired_end": true
+ }
+ },
+ {
+ "model": "samples.LibraryType",
+ "pk": 8,
+ "fields": {
+ "name": "Nextera",
+ "can_multiplex": true,
+ "is_paired_end": true
+ }
+ },
+ {
+ "model": "samples.LibraryType",
+ "pk": 9,
+ "fields": {
+ "name": "Dual Index Illumina",
+ "can_multiplex": true,
+ "is_paired_end": true
+ }
+ },
+ {
+ "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": 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": 6,
+ "fields": {
+ "scientific_name": "Arabidopsis thaliana"
+ }
+ },
+ {
+ "model": "samples.Species",
+ "pk": 8,
+ "fields": {
+ "scientific_name": "Homo sapiens",
+ "common_name": "human"
+ }
+ },
+ {
+ "model": "samples.Species",
+ "pk": 9,
+ "fields": {
+ "scientific_name": "Mus musculus",
+ "common_name": "mouse"
+ }
+ },
+ {
+ "model": "samples.Species",
+ "pk": 10,
+ "fields": {
+ "scientific_name": "Strongylocentrotus purpuratus"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 1,
+ "adapter_type": 8,
+ "sequence": "ATCACG"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 2,
+ "adapter_type": 8,
+ "sequence": "CGATGT"
+ }
+ },
+ {
+ "pk": 3,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 3,
+ "adapter_type": 8,
+ "sequence": "TTAGGC"
+ }
+ },
+ {
+ "pk": 4,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 4,
+ "adapter_type": 8,
+ "sequence": "TGACCA"
+ }
+ },
+ {
+ "pk": 5,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 5,
+ "adapter_type": 8,
+ "sequence": "ACAGTG"
+ }
+ },
+ {
+ "pk": 6,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 6,
+ "adapter_type": 8,
+ "sequence": "GCCAAT"
+ }
+ },
+ {
+ "pk": 7,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 7,
+ "adapter_type": 8,
+ "sequence": "CAGATC"
+ }
+ },
+ {
+ "pk": 8,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 8,
+ "adapter_type": 8,
+ "sequence": "ACTTGA"
+ }
+ },
+ {
+ "pk": 9,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 9,
+ "adapter_type": 8,
+ "sequence": "GATCAG"
+ }
+ },
+ {
+ "pk": 10,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 10,
+ "adapter_type": 8,
+ "sequence": "TAGCTT"
+ }
+ },
+ {
+ "pk": 11,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 11,
+ "adapter_type": 8,
+ "sequence": "GGCTAC"
+ }
+ },
+ {
+ "pk": 12,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 12,
+ "adapter_type": 8,
+ "sequence": "CTTGTA"
+ }
+ },
+ {
+ "pk": 13,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 1,
+ "adapter_type": 7,
+ "sequence": "ATCACG"
+ }
+ },
+ {
+ "pk": 14,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 2,
+ "adapter_type": 7,
+ "sequence": "CGATGT"
+ }
+ },
+ {
+ "pk": 15,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 3,
+ "adapter_type": 7,
+ "sequence": "TTAGGC"
+ }
+ },
+ {
+ "pk": 16,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 4,
+ "adapter_type": 7,
+ "sequence": "TGACCA"
+ }
+ },
+ {
+ "pk": 17,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 5,
+ "adapter_type": 7,
+ "sequence": "ACAGTG"
+ }
+ },
+ {
+ "pk": 18,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 6,
+ "adapter_type": 7,
+ "sequence": "GCCAAT"
+ }
+ },
+ {
+ "pk": 19,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 7,
+ "adapter_type": 7,
+ "sequence": "CAGATC"
+ }
+ },
+ {
+ "pk": 20,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 8,
+ "adapter_type": 7,
+ "sequence": "ACTTGA"
+ }
+ },
+ {
+ "pk": 21,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 9,
+ "adapter_type": 7,
+ "sequence": "GATCAG"
+ }
+ },
+ {
+ "pk": 22,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 10,
+ "adapter_type": 7,
+ "sequence": "TAGCTT"
+ }
+ },
+ {
+ "pk": 23,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 11,
+ "adapter_type": 7,
+ "sequence": "GGCTAC"
+ }
+ },
+ {
+ "pk": 24,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 12,
+ "adapter_type": 7,
+ "sequence": "CTTGTA"
+ }
+ },
+ {
+ "pk": 25,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 13,
+ "adapter_type": 7,
+ "sequence": "AGTCAA"
+ }
+ },
+ {
+ "pk": 26,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 14,
+ "adapter_type": 7,
+ "sequence": "AGTTCC"
+ }
+ },
+ {
+ "pk": 27,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 15,
+ "adapter_type": 7,
+ "sequence": "ATGTCA"
+ }
+ },
+ {
+ "pk": 28,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 16,
+ "adapter_type": 7,
+ "sequence": "CCGTCC"
+ }
+ },
+ {
+ "pk": 29,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 17,
+ "adapter_type": 7,
+ "sequence": "GTAGAG"
+ }
+ },
+ {
+ "pk": 30,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 18,
+ "adapter_type": 7,
+ "sequence": "GTCCGC"
+ }
+ },
+ {
+ "pk": 31,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 19,
+ "adapter_type": 7,
+ "sequence": "GTGAAA"
+ }
+ },
+ {
+ "pk": 32,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 20,
+ "adapter_type": 7,
+ "sequence": "GTGGCC"
+ }
+ },
+ {
+ "pk": 33,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 21,
+ "adapter_type": 7,
+ "sequence": "GTTTCG"
+ }
+ },
+ {
+ "pk": 34,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 22,
+ "adapter_type": 7,
+ "sequence": "CGTACG"
+ }
+ },
+ {
+ "pk": 35,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 23,
+ "adapter_type": 7,
+ "sequence": "GAGTGG"
+ }
+ },
+ {
+ "pk": 36,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 24,
+ "adapter_type": 7,
+ "sequence": "GGTAGC"
+ }
+ },
+ {
+ "pk": 37,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 25,
+ "adapter_type": 7,
+ "sequence": "ACTGAT"
+ }
+ },
+ {
+ "pk": 38,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 26,
+ "adapter_type": 7,
+ "sequence": "ATGAGC"
+ }
+ },
+ {
+ "pk": 39,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 27,
+ "adapter_type": 7,
+ "sequence": "ATTCCT"
+ }
+ },
+ {
+ "pk": 40,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 28,
+ "adapter_type": 7,
+ "sequence": "CAAAAG"
+ }
+ },
+ {
+ "pk": 41,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 29,
+ "adapter_type": 7,
+ "sequence": "CAACTA"
+ }
+ },
+ {
+ "pk": 42,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 30,
+ "adapter_type": 7,
+ "sequence": "CACCGG"
+ }
+ },
+ {
+ "pk": 43,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 31,
+ "adapter_type": 7,
+ "sequence": "CACGAT"
+ }
+ },
+ {
+ "pk": 44,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 32,
+ "adapter_type": 7,
+ "sequence": "CACTCA"
+ }
+ },
+ {
+ "pk": 45,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 33,
+ "adapter_type": 7,
+ "sequence": "CAGGCG"
+ }
+ },
+ {
+ "pk": 46,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 34,
+ "adapter_type": 7,
+ "sequence": "CATGGC"
+ }
+ },
+ {
+ "pk": 47,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 35,
+ "adapter_type": 7,
+ "sequence": "CATTTT"
+ }
+ },
+ {
+ "pk": 48,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 36,
+ "adapter_type": 7,
+ "sequence": "CCAACA"
+ }
+ },
+ {
+ "pk": 49,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 37,
+ "adapter_type": 7,
+ "sequence": "CGGAAT"
+ }
+ },
+ {
+ "pk": 50,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 38,
+ "adapter_type": 7,
+ "sequence": "CTAGCT"
+ }
+ },
+ {
+ "pk": 51,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 39,
+ "adapter_type": 7,
+ "sequence": "CTATAC"
+ }
+ },
+ {
+ "pk": 52,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 40,
+ "adapter_type": 7,
+ "sequence": "CTCAGA"
+ }
+ },
+ {
+ "pk": 53,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 41,
+ "adapter_type": 7,
+ "sequence": "GACGAC"
+ }
+ },
+ {
+ "pk": 54,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 42,
+ "adapter_type": 7,
+ "sequence": "TAATCG"
+ }
+ },
+ {
+ "pk": 55,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 43,
+ "adapter_type": 7,
+ "sequence": "TACAGC"
+ }
+ },
+ {
+ "pk": 56,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 44,
+ "adapter_type": 7,
+ "sequence": "TATAAT"
+ }
+ },
+ {
+ "pk": 57,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 45,
+ "adapter_type": 7,
+ "sequence": "TCATTC"
+ }
+ },
+ {
+ "pk": 58,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 46,
+ "adapter_type": 7,
+ "sequence": "TCCCGA"
+ }
+ },
+ {
+ "pk": 59,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 47,
+ "adapter_type": 7,
+ "sequence": "TCGAAG"
+ }
+ },
+ {
+ "pk": 60,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 48,
+ "adapter_type": 7,
+ "sequence": "TCGGCA"
+ }
+ },
+ {
+ "pk": 61,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 1,
+ "adapter_type": 5,
+ "sequence": "ATCACG"
+ }
+ },
+ {
+ "pk": 62,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 2,
+ "adapter_type": 5,
+ "sequence": "CGATGT"
+ }
+ },
+ {
+ "pk": 63,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 3,
+ "adapter_type": 5,
+ "sequence": "TTAGGC"
+ }
+ },
+ {
+ "pk": 64,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 4,
+ "adapter_type": 5,
+ "sequence": "TGACCA"
+ }
+ },
+ {
+ "pk": 65,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 5,
+ "adapter_type": 5,
+ "sequence": "ACAGTG"
+ }
+ },
+ {
+ "pk": 66,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 6,
+ "adapter_type": 5,
+ "sequence": "GCCAAT"
+ }
+ },
+ {
+ "pk": 67,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 7,
+ "adapter_type": 5,
+ "sequence": "CAGATC"
+ }
+ },
+ {
+ "pk": 68,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 8,
+ "adapter_type": 5,
+ "sequence": "ACTTGA"
+ }
+ },
+ {
+ "pk": 69,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 9,
+ "adapter_type": 5,
+ "sequence": "GATCAG"
+ }
+ },
+ {
+ "pk": 70,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 10,
+ "adapter_type": 5,
+ "sequence": "TAGCTT"
+ }
+ },
+ {
+ "pk": 71,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 11,
+ "adapter_type": 5,
+ "sequence": "GGCTAC"
+ }
+ },
+ {
+ "pk": 72,
+ "model": "samples.MultiplexIndex",
+ "fields": {
+ "multiplex_id": 12,
+ "adapter_type": 5,
+ "sequence": "CTTGTA"
+ }
+ },
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N501",
+ "sequence": "TAGATCGC"},
+ "model": "samples.multiplexindex",
+ "pk": 74
+ },
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N502",
+ "sequence": "CTCTCTAT"},
+ "model": "samples.multiplexindex",
+ "pk": 75},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N503",
+ "sequence": "TATCCTCT"},
+ "model": "samples.multiplexindex",
+ "pk": 76},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N504",
+ "sequence": "AGAGTAGA"},
+ "model": "samples.multiplexindex",
+ "pk": 77},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N505",
+ "sequence": "GTAAGGAG"},
+ "model": "samples.multiplexindex",
+ "pk": 78},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N506",
+ "sequence": "ACTGCATA"},
+ "model": "samples.multiplexindex",
+ "pk": 79},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N507",
+ "sequence": "AAGGAGTA"},
+ "model": "samples.multiplexindex",
+ "pk": 80},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N508",
+ "sequence": "CTAAGCCT"},
+ "model": "samples.multiplexindex",
+ "pk": 81},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N701",
+ "sequence": "TAAGGCGA"},
+ "model": "samples.multiplexindex",
+ "pk": 82},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N702",
+ "sequence": "CGTACTAG"},
+ "model": "samples.multiplexindex",
+ "pk": 83},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N703",
+ "sequence": "AGGCAGAA"},
+ "model": "samples.multiplexindex",
+ "pk": 84},
+ {"fields": {"adapter_type": 9, "multiplex_id": "N704", "sequence": "TCCTGA"},
+ "model": "samples.multiplexindex",
+ "pk": 85},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N705",
+ "sequence": "GGACTCCT"},
+ "model": "samples.multiplexindex",
+ "pk": 86},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N706",
+ "sequence": "TAGGCATG"},
+ "model": "samples.multiplexindex",
+ "pk": 87},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N707",
+ "sequence": "CTCTCTAC"},
+ "model": "samples.multiplexindex",
+ "pk": 88},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N708",
+ "sequence": "CAGAGAGG"},
+ "model": "samples.multiplexindex",
+ "pk": 89},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N709",
+ "sequence": "GCTACGCT"},
+ "model": "samples.multiplexindex",
+ "pk": 90},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N710",
+ "sequence": "CGAGGCTG"},
+ "model": "samples.multiplexindex",
+ "pk": 91},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N711",
+ "sequence": "AAGAGGCA"},
+ "model": "samples.multiplexindex",
+ "pk": 92},
+ {"fields": {"adapter_type": 9,
+ "multiplex_id": "N712",
+ "sequence": "GTAGAGGA"},
+ "model": "samples.multiplexindex",
+ "pk": 93}
+]
--- /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-01T00:00:01-0800",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$foo$5e4eefec1144a04becfb7da79244f07c487fc345",
+ "email": "",
+ "date_joined": "2009-01-01T00:01:01-0800"
+ }
+ },
+ {"pk": 1, "model": "samples.affiliation",
+ "fields": {
+ "users": [5],
+ "name": "Alice",
+ "contact": "Lab Boss",
+ "email": "alice@some.where.else."
+ }
+ },
+ {"pk": 2, "model": "samples.affiliation",
+ "fields": { "name": "Bob",
+ "contact": "Other Lab Boss",
+ "email": "bob@some.where.else"
+ }
+ },
+ {"pk": 3, "model": "samples.affiliation",
+ "fields": {
+ "users": [],
+ "contact": "group 3",
+ "name": "affiliation 3",
+ "email": "pk3@example.com"
+ }
+ },
+ {"pk": 4, "model": "samples.affiliation",
+ "fields": {
+ "users": [],
+ "contact": "group 4",
+ "name": "affiliation 4",
+ "email": "pk1@example.com"
+ }
+ },
+ {"pk": 5, "model": "samples.affiliation",
+ "fields": {
+ "users": [],
+ "contact": "group 5",
+ "name": "affiliation 5",
+ "email": "pk5@example.com"
+ }
+ },
+ {"pk": 153, "model": "experiments.flowcell",
+ "fields": {
+ "paired_end": true,
+ "run_date": "2009-09-11T22:12:13-0800",
+ "read_length": 75,
+ "notes": "",
+ "advanced_run": false,
+ "control_lane": 2,
+ "cluster_station": 3,
+ "sequencer": 2,
+ "flowcell_id": "303TUAAXX"
+ }
+ },
+ {"pk": 1193, "model": "experiments.lane",
+ "fields": {
+ "comment": "No change in cluster numbers, despite slight increase in pM",
+ "library": "10981",
+ "cluster_estimate": 129000,
+ "flowcell": 153,
+ "lane_number": 1,
+ "pM": "8"
+ }
+ },
+ {"pk": 1197, "model": "experiments.lane",
+ "fields": {
+ "comment": "stuff",
+ "library": "11016",
+ "cluster_estimate": 140000,
+ "flowcell": 153,
+ "lane_number": 5,
+ "pM": "7",
+ "status": 2
+ }
+ },
+ {"pk": "10981", "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_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": [
+ 2
+ ],
+ "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": "11016",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 325,
+ "library_name": "Paired End Pfl #3 MP 7/24/9 a",
+ "creation_date": "2009-08-06",
+ "cell_line": 1,
+ "library_species": 9,
+ "library_type": 2,
+ "made_by": "Lorian",
+ "affiliations": [
+ 3
+ ],
+ "replicate": 1,
+ "condition": 1,
+ "hidden": false,
+ "stopping_point": "1Aa",
+ "tags": [],
+ "made_for": "",
+ "amplified_from_sample": "11003",
+ "notes": "7/31/2009 16:08:22\tColor: Blue",
+ "undiluted_concentration": "35.5",
+ "successful_pM": null,
+ "experiment_type": 8,
+ "antibody": null
+ }
+ },
+ {
+ "pk": "11039",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_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": [
+ 1,
+ 2,
+ 4
+ ],
+ "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": "11003",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 325,
+ "library_name": "Paired End Pfl #3 MP 7/24/9",
+ "creation_date": "2009-08-05",
+ "cell_line": 1,
+ "library_species": 8,
+ "library_type": 2,
+ "made_by": "Lorian",
+ "affiliations": [
+ 4
+ ],
+ "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
+ }
+ },
+ {
+ "pk": "11005",
+ "model": "samples.library",
+ "fields": {
+ "ten_nM_dilution": false,
+ "gel_cut_size": 325,
+ "library_name": "null cell line",
+ "creation_date": "2009-08-05",
+ "cell_line": null,
+ "library_species": 8,
+ "library_type": 2,
+ "made_by": "Lorian",
+ "affiliations": [
+ 4
+ ],
+ "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
+ }
+ }
+]
--- /dev/null
+import types
+import logging
+import urlparse
+from django.db import models
+from django.contrib.auth.models import User, UserManager
+from django.core import urlresolvers
+from django.db.models.signals import pre_save, post_save
+from django.db import connection
+
+logger = logging.getLogger(__name__)
+
+class Antibody(models.Model):
+ antigene = models.CharField(max_length=500, db_index=True)
+ # New field Aug/20/08
+ # SQL to add column:
+ # alter table fctracker_antibody add column "nickname" varchar(20) NULL;
+ nickname = models.CharField(
+ max_length=20,
+ blank=True,
+ null=True,
+ db_index=True
+ )
+ catalog = models.CharField(max_length=50, blank=True, null=True)
+ antibodies = models.CharField(max_length=500, db_index=True)
+ source = models.CharField(max_length=500, blank=True, null=True, db_index=True)
+ biology = models.TextField(blank=True, null=True)
+ notes = models.TextField(blank=True, null=True)
+ def __unicode__(self):
+ return u'%s - %s' % (self.antigene, self.antibodies)
+ class Meta:
+ verbose_name_plural = "antibodies"
+ ordering = ["antigene"]
+
+class Cellline(models.Model):
+ cellline_name = models.CharField(max_length=100, unique=True, db_index=True)
+ nickname = models.CharField(max_length=20,
+ blank=True,
+ null=True,
+ db_index=True)
+
+ notes = models.TextField(blank=True)
+ def __unicode__(self):
+ return unicode(self.cellline_name)
+
+ class Meta:
+ ordering = ["cellline_name"]
+
+class Condition(models.Model):
+ condition_name = models.CharField(
+ max_length=2000, unique=True, db_index=True)
+ nickname = models.CharField(max_length=20,
+ blank=True,
+ null=True,
+ db_index=True,
+ verbose_name = 'Short Name')
+ notes = models.TextField(blank=True)
+
+ def __unicode__(self):
+ return unicode(self.condition_name)
+
+ class Meta:
+ ordering = ["condition_name"]
+
+
+class ExperimentType(models.Model):
+ name = models.CharField(max_length=50, unique=True)
+
+ def __unicode__(self):
+ return unicode(self.name)
+
+class Tag(models.Model):
+ tag_name = models.CharField(max_length=100, db_index=True,blank=False,null=False)
+ TAG_CONTEXT = (
+ #('Antibody','Antibody'),
+ #('Cellline', 'Cellline'),
+ #('Condition', 'Condition'),
+ ('Library', 'Library'),
+ ('ANY','ANY'),
+ )
+ context = models.CharField(max_length=50,
+ choices=TAG_CONTEXT, default='Library')
+
+ def __unicode__(self):
+ return u'%s' % (self.tag_name)
+
+ class Meta:
+ ordering = ["context","tag_name"]
+
+class Species(models.Model):
+ scientific_name = models.CharField(max_length=256,
+ unique=False,
+ db_index=True
+ )
+ common_name = models.CharField(max_length=256, blank=True)
+ #use_genome_build = models.CharField(max_length=100, blank=False, null=False)
+
+ def __unicode__(self):
+ return u'%s (%s)' % (self.scientific_name, self.common_name)
+
+ class Meta:
+ verbose_name_plural = "species"
+ ordering = ["scientific_name"]
+
+ @models.permalink
+ def get_absolute_url(self):
+ return ('samples.views.species', [str(self.id)])
+
+class Affiliation(models.Model):
+ name = models.CharField(max_length=256, db_index=True, verbose_name='Name')
+ contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name')
+ email = models.EmailField(null=True,blank=True)
+ users = models.ManyToManyField('HTSUser', null=True, blank=True)
+ users.admin_order_field = "username"
+
+ def __unicode__(self):
+ str = unicode(self.name)
+ if self.contact is not None and len(self.contact) > 0:
+ str += u' ('+self.contact+u')'
+ return str
+
+ def Users(self):
+ users = self.users.all().order_by('username')
+ return ", ".join([unicode(a) for a in users ])
+
+ class Meta:
+ ordering = ["name","contact"]
+ unique_together = (("name", "contact"),)
+
+class LibraryType(models.Model):
+ name = models.CharField(max_length=255, unique=True,
+ verbose_name="Adapter Type")
+ is_paired_end = models.BooleanField(default=True,
+ help_text="can you do a paired end run with this adapter")
+ can_multiplex = models.BooleanField(default=True,
+ help_text="Does this adapter provide multiplexing?")
+
+ def __unicode__(self):
+ return unicode(self.name)
+
+ class Meta:
+ ordering = ["-id"]
+
+
+class MultiplexIndex(models.Model):
+ """Map adapter types to the multiplex sequence"""
+ adapter_type = models.ForeignKey(LibraryType)
+ multiplex_id = models.CharField(max_length=6, null=False)
+ sequence = models.CharField(max_length=12, blank=True, null=True)
+
+ class Meta:
+ verbose_name_plural = "multiplex indicies"
+ unique_together = ('adapter_type', 'multiplex_id')
+
+class Library(models.Model):
+ id = models.CharField(max_length=10, primary_key=True)
+ library_name = models.CharField(max_length=100, unique=True)
+ library_species = models.ForeignKey(Species)
+ hidden = models.BooleanField(default=False)
+ account_number = models.CharField(max_length=100, null=True, blank=True)
+ cell_line = models.ForeignKey(Cellline, blank=True, null=True,
+ verbose_name="Background")
+ condition = models.ForeignKey(Condition, blank=True, null=True)
+ antibody = models.ForeignKey(Antibody,blank=True,null=True)
+ affiliations = models.ManyToManyField(
+ Affiliation,related_name='library_affiliations',null=True)
+ tags = models.ManyToManyField(Tag,related_name='library_tags',
+ blank=True,null=True)
+ REPLICATE_NUM = [(x,x) for x in range(1,7)]
+ replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM,
+ blank=True,null=True)
+ experiment_type = models.ForeignKey(ExperimentType)
+ library_type = models.ForeignKey(LibraryType, blank=True, null=True,
+ verbose_name="Adapter Type")
+ multiplex_id = models.CharField(max_length=128,
+ blank=True, null=True,
+ verbose_name="Index ID")
+ creation_date = models.DateField(blank=True, null=True)
+ made_for = models.CharField(max_length=50, blank=True,
+ verbose_name='ChIP/DNA/RNA Made By')
+ made_by = models.CharField(max_length=50, blank=True, default="Lorian")
+
+ PROTOCOL_END_POINTS = (
+ ('?', 'Unknown'),
+ ('Sample', 'Raw sample'),
+ ('Progress', 'In progress'),
+ ('1A', 'Ligation, then gel'),
+ ('PCR', 'Ligation, then PCR'),
+ ('1Ab', 'Ligation, PCR, then gel'),
+ ('1Ac', 'Ligation, gel, then 12x PCR'),
+ ('1Aa', 'Ligation, gel, then 18x PCR'),
+ ('2A', 'Ligation, PCR, gel, PCR'),
+ ('Done', 'Completed'),
+ )
+ PROTOCOL_END_POINTS_DICT = dict(PROTOCOL_END_POINTS)
+ stopping_point = models.CharField(max_length=25,
+ choices=PROTOCOL_END_POINTS,
+ default='Done')
+
+ amplified_from_sample = models.ForeignKey('self',
+ related_name='amplified_into_sample',
+ blank=True, null=True)
+
+ undiluted_concentration = models.DecimalField("Concentration",
+ max_digits=5, decimal_places=2, blank=True, null=True,
+ help_text=u"Undiluted concentration (ng/\u00b5l)")
+ # note \u00b5 is the micro symbol in unicode
+ successful_pM = models.DecimalField(max_digits=9,
+ decimal_places=1, blank=True, null=True)
+ ten_nM_dilution = models.BooleanField(default=False)
+ gel_cut_size = models.IntegerField(default=225, blank=True, null=True)
+ insert_size = models.IntegerField(blank=True, null=True)
+ notes = models.TextField(blank=True)
+
+ bioanalyzer_summary = models.TextField(blank=True,default="")
+ bioanalyzer_concentration = models.DecimalField(max_digits=5,
+ decimal_places=2, blank=True, null=True,
+ help_text=u"(ng/\u00b5l)")
+ bioanalyzer_image_url = models.URLField(blank=True,default="")
+
+ def __unicode__(self):
+ return u'#%s: %s' % (self.id, self.library_name)
+
+ class Meta:
+ verbose_name_plural = "libraries"
+ #ordering = ["-creation_date"]
+ ordering = ["-id"]
+
+ def antibody_name(self):
+ str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.label+'</a>'
+ return str
+ antibody_name.allow_tags = True
+
+ def organism(self):
+ return self.library_species.common_name
+
+ def index_sequences(self):
+ """Return a dictionary of multiplex index id to sequence
+ Return None if the library can't multiplex,
+
+ """
+ if self.library_type is None:
+ return None
+ if not self.library_type.can_multiplex:
+ return None
+ if self.multiplex_id is None or len(self.multiplex_id) == 0:
+ return 'Err: id empty'
+ sequences = {}
+ multiplex_expressions = self.multiplex_id.split(',')
+ for multiplex_term in multiplex_expressions:
+ pairs = multiplex_term.split('-')
+ if len(pairs) == 1:
+ key = pairs[0]
+ seq = self._lookup_index(pairs[0])
+ elif len(pairs) == 2:
+ key = pairs[0] + '-' + pairs[1]
+ seq0 = self._lookup_index(pairs[0])
+ seq1 = self._lookup_index(pairs[1])
+ if seq0 is None or seq1 is None:
+ seq = None
+ else:
+ seq = seq0 + '-' + seq1
+ else:
+ raise RuntimeError("Too many - seperated sequences")
+ if seq is None:
+ seq = 'Err: index not found'
+ sequences[key] = seq
+ return sequences
+
+ def _lookup_index(self, multiplex_id):
+ try:
+ multiplex = MultiplexIndex.objects.get(
+ adapter_type = self.library_type.id,
+ multiplex_id = multiplex_id)
+ return multiplex.sequence
+ except MultiplexIndex.DoesNotExist, e:
+ return None
+
+ def index_sequence_text(self, seperator=' '):
+ """Return formatted multiplex index sequences"""
+ sequences = self.index_sequences()
+ if sequences is None:
+ return ""
+ if type(sequences) in types.StringTypes:
+ return sequences
+ multiplex_ids = sequences.keys()
+ multiplex_ids.sort()
+ return seperator.join(( "%s:%s" %(i,sequences[i]) for i in multiplex_ids))
+ index_sequence_text.short_description = "Index"
+
+
+ def affiliation(self):
+ affs = self.affiliations.all().order_by('name')
+ tstr = ''
+ ar = []
+ for t in affs:
+ ar.append(t.__unicode__())
+ return '%s' % (", ".join(ar))
+
+ def is_archived(self):
+ """
+ returns True if archived else False
+ """
+ if self.longtermstorage_set.count() > 0:
+ return True
+ else:
+ return False
+
+ def stopping_point_name(self):
+ end_points = Library.PROTOCOL_END_POINTS_DICT
+ name = end_points.get(self.stopping_point, None)
+ if name is None:
+ name = "Lookup Error"
+ logger.error("protocol stopping point in database didn't match names in library model")
+ return name
+
+
+ def libtags(self):
+ affs = self.tags.all().order_by('tag_name')
+ ar = []
+ for t in affs:
+ ar.append(t.__unicode__())
+ return u'%s' % ( ", ".join(ar))
+
+ def DataRun(self):
+ str ='<a target=_self href="/admin/experiments/datarun/?q='+self.id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>'
+ return str
+ DataRun.allow_tags = True
+
+ def aligned_m_reads(self):
+ return getLibReads(self.id)
+
+ def aligned_reads(self):
+ res = getLibReads(self.id)
+
+ # Check data sanity
+ if res[2] != "OK":
+ return u'<div style="border:solid red 2px">'+res[2]+'</div>'
+
+ rc = "%1.2f" % (res[1]/1000000.0)
+ # Color Scheme: green is more than 10M, blue is more than 5M, orange is more than 3M and red is less. For RNAseq, all those thresholds should be doubled
+ if res[0] > 0:
+ bgcolor = '#ff3300' # Red
+ rc_thr = [10000000,5000000,3000000]
+ if self.experiment_type == 'RNA-seq':
+ rc_thr = [20000000,10000000,6000000]
+
+ if res[1] > rc_thr[0]:
+ bgcolor = '#66ff66' # Green
+ else:
+ if res[1] > rc_thr[1]:
+ bgcolor ='#00ccff' # Blue
+ else:
+ if res[1] > rc_thr[2]:
+ bgcolor ='#ffcc33' # Orange
+ tstr = '<div style="background-color:'+bgcolor+';color:black">'
+ tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
+ tstr += '</div>'
+ else: tstr = 'not processed yet'
+ return tstr
+ aligned_reads.allow_tags = True
+
+ def public(self):
+ SITE_ROOT = '/'
+ summary_url = self.get_absolute_url()
+ return '<a href="%s">S</a>' % (summary_url,)
+ public.allow_tags = True
+
+ @models.permalink
+ def get_absolute_url(self):
+ return ('samples.views.library_to_flowcells', [str(self.id)])
+
+ def get_admin_url(self):
+ return urlresolvers.reverse('admin:samples_library_change',
+ args=(self.id,))
+
+class HTSUser(User):
+ """
+ Provide some site-specific customization for the django user class
+ """
+ #objects = UserManager()
+
+ class Meta:
+ ordering = ['first_name', 'last_name', 'username']
+
+ def admin_url(self):
+ return '/admin/%s/%s/%d' % (self._meta.app_label, self._meta.module_name, self.id)
+
+ def __unicode__(self):
+ #return unicode(self.username) + u" (" + unicode(self.get_full_name()) + u")"
+ return unicode(self.get_full_name()) + u' (' + unicode(self.username) + ')'
+
+def HTSUserInsertID(sender, instance, **kwargs):
+ """
+ Force addition of HTSUsers when someone just modifies the auth_user object
+ """
+ u = HTSUser.objects.filter(pk=instance.id)
+ if len(u) == 0:
+ cursor = connection.cursor()
+ cursor.execute('INSERT INTO samples_htsuser (user_ptr_id) VALUES (%s);' % (instance.id,))
+ cursor.close()
+
+post_save.connect(HTSUserInsertID, sender=User)
--- /dev/null
+from django.conf import settings
+
+import glob
+import os
+import re
+
+s_paren = re.compile("^\w+")
+
+def get_flowcell_result_dict(flowcell_id):
+ """
+ returns a dictionary following the following pattern for
+ a given flowcell_id:
+
+
+ d['C1-33']['summary'] # Summary.htm file path
+ d['C1-33']['eland_results'][5] # C1-33 lane 5 file eland results file path
+ d['C1-33']['run_xml'] # run_*.xml file path
+ d['C1-33']['scores'] # scores.tar.gz file path
+ """
+ flowcell_id = flowcell_id.strip()
+
+ d = {}
+
+ ################################
+ # Flowcell Directory
+ fc_dir = glob.glob(os.path.join(settings.RESULT_HOME_DIR, flowcell_id))
+
+ # Not found
+ if len(fc_dir) == 0:
+ return None
+
+ # No duplicates!
+ assert len(fc_dir) <= 1
+
+ # Found fc dir
+ fc_dir = fc_dir[0]
+
+ ################################
+ # C#-## dirs
+ c_dir_list = glob.glob(os.path.join(fc_dir, 'C*'))
+
+ # Not found
+ if len(c_dir_list) == 0:
+ return d
+
+ for c_dir_path in c_dir_list:
+ summary_file = glob.glob(os.path.join(c_dir_path, 'Summary.htm'))
+ pathdir, c_dir = os.path.split(c_dir_path)
+
+ # Create sub-dictionary
+ d[c_dir] = {}
+
+
+ ###############################
+ # Summary.htm file
+
+ # Not found
+ if len(summary_file) == 0:
+ d[c_dir]['summary'] = None
+
+ # Found
+ else:
+ # No duplicates!
+ assert len(summary_file) == 1
+
+ summary_file = summary_file[0]
+ d[c_dir]['summary'] = summary_file
+
+ ###############################
+ # Result files
+
+ d[c_dir]['eland_results'] = {}
+
+ result_filepaths = glob.glob(os.path.join(c_dir_path, 's_*_eland_*'))
+
+ for filepath in result_filepaths:
+
+ junk, result_name = os.path.split(filepath)
+
+ #lanes 1-8, single digit, therefore s_#; # == index 2
+ lane = int(result_name[2])
+ d[c_dir]['eland_results'][lane] = filepath
+
+ ###############################
+ # run*.xml file
+ run_xml_filepath = glob.glob(os.path.join(c_dir_path, 'run_*.xml'))
+
+ if len(run_xml_filepath) == 0:
+ d[c_dir]['run_xml'] = None
+ else:
+ # No duplicates
+ assert len(run_xml_filepath) == 1
+
+ d[c_dir]['run_xml'] = run_xml_filepath[0]
+
+ ###############################
+ # scores.tar.gz
+ # restrict to only compressed files, so in case there are *.md5 files
+ # we don't get confused.
+ scores_filepath = []
+ for pattern in ['scores*.tar.bz2', 'scores*.tar.gz', 'scores*.tgz']:
+ scores_filepath += glob.glob(os.path.join(c_dir_path, pattern))
+
+ if len(scores_filepath) == 0:
+ d[c_dir]['scores'] = None
+ else:
+ # No duplicates
+ assert len(scores_filepath) == 1
+
+ d[c_dir]['scores'] = scores_filepath[0]
+
+ return d
+
+
+def cn_mTobp(cn_m):
+ """
+ Converts CN-M (i.e. C1-33, C1-26, C4-28) cycle information into
+ number of base pairs.
+ """
+ pass
+
+
--- /dev/null
+from __future__ import absolute_import, print_function
+
+import datetime
+
+try:
+ import json
+except ImportError, e:
+ import simplejson as json
+
+from django.test import TestCase
+from django.test.utils import setup_test_environment, \
+ teardown_test_environment
+from django.db import connection
+from django.conf import settings
+
+from .models import Affiliation, ExperimentType, Species, Library
+
+from .views import library_dict, library_json
+
+from htsworkflow.auth import apidata
+from htsworkflow.util.conversion import unicode_or_none
+from htsworkflow.util.ethelp import validate_xhtml
+
+class LibraryTestCase(TestCase):
+ fixtures = ['initial_data.json',
+ 'woldlab.json',
+ 'test_samples.json']
+
+ def setUp(self):
+ create_db(self)
+
+ def testOrganism(self):
+ self.assertEquals(self.library_10001.organism(), 'human')
+
+ def testAffiliations(self):
+ self.library_10001.affiliations.add(self.affiliation_alice)
+ self.library_10002.affiliations.add(
+ self.affiliation_alice,
+ self.affiliation_bob
+ )
+ self.failUnless(len(self.library_10001.affiliations.all()), 1)
+ self.failUnless(self.library_10001.affiliation(), 'Alice')
+
+ 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 = ['initial_data.json',
+ 'woldlab.json',
+ 'test_samples.json']
+
+ def test_library_info(self):
+ for lib in Library.objects.all():
+ lib_dict = library_dict(lib.id)
+ url = '/samples/library/%s/json' % (lib.id,)
+ lib_response = self.client.get(url, apidata)
+ 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 "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['cell_line_id'], lib.cell_line_id)
+ self.failUnlessEqual(d['cell_line'], unicode_or_none(lib.cell_line))
+ self.failUnlessEqual(d['experiment_type'], lib.experiment_type.name)
+ self.failUnlessEqual(d['experiment_type_id'], lib.experiment_type_id)
+ self.failUnlessEqual(d['gel_cut_size'], lib.gel_cut_size)
+ self.failUnlessEqual(d['hidden'], lib.hidden)
+ self.failUnlessEqual(d['id'], lib.id)
+ self.failUnlessEqual(d['insert_size'], lib.insert_size)
+ 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))
+ # some specific tests
+ if lib.id == '10981':
+ # test a case where there is no known status
+ lane_set = {u'status': u'Unknown',
+ u'paired_end': True,
+ u'read_length': 75,
+ u'lane_number': 1,
+ u'lane_id': 1193,
+ u'flowcell': u'303TUAAXX',
+ u'status_code': None}
+ self.failUnlessEqual(len(d['lane_set']), 1)
+ self.failUnlessEqual(d['lane_set'][0], lane_set)
+ elif lib.id == '11016':
+ # test a case where there is a status
+ lane_set = {u'status': 'Good',
+ u'paired_end': True,
+ u'read_length': 75,
+ u'lane_number': 5,
+ u'lane_id': 1197,
+ u'flowcell': u'303TUAAXX',
+ u'status_code': 2}
+ self.failUnlessEqual(len(d['lane_set']), 1)
+ self.failUnlessEqual(d['lane_set'][0], lane_set)
+
+
+ def test_invalid_library_json(self):
+ """
+ Make sure we get a 404 if we request an invalid library id
+ """
+ response = self.client.get('/samples/library/nottheone/json', apidata)
+ self.failUnlessEqual(response.status_code, 404)
+
+
+ def test_invalid_library(self):
+ response = self.client.get('/library/nottheone/')
+ self.failUnlessEqual(response.status_code, 404)
+
+
+ def test_library_no_key(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, 403)
+ response = self.client.get('/samples/library/10981/json', apidata)
+ self.failUnlessEqual(response.status_code, 200)
+
+ def test_library_rdf(self):
+ import RDF
+ from htsworkflow.util.rdfhelp import get_model, \
+ dump_model, \
+ fromTypedNode, \
+ load_string_into_model, \
+ rdfNS, \
+ libraryOntology
+ model = get_model()
+
+ response = self.client.get('/library/10981/')
+ self.assertEqual(response.status_code, 200)
+ content = response.content
+ load_string_into_model(model, 'rdfa', content)
+
+ body = """prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+ prefix libns: <http://jumpgate.caltech.edu/wiki/LibraryOntology#>
+
+ select ?library ?name ?library_id ?gel_cut ?made_by
+ where {
+ ?library a libns:library ;
+ libns:name ?name ;
+ libns:library_id ?library_id ;
+ libns:gel_cut ?gel_cut ;
+ libns:made_by ?made_by
+ }"""
+ query = RDF.SPARQLQuery(body)
+ for r in query.execute(model):
+ self.assertEqual(fromTypedNode(r['library_id']), u'10981')
+ self.assertEqual(fromTypedNode(r['name']),
+ u'Paired End Multiplexed Sp-BAC')
+ self.assertEqual(fromTypedNode(r['gel_cut']), 400)
+ self.assertEqual(fromTypedNode(r['made_by']), u'Igor')
+
+ state = validate_xhtml(content)
+ if state is not None:
+ self.assertTrue(state)
+
+ # validate a library page.
+ from htsworkflow.util.rdfhelp import add_default_schemas
+ from htsworkflow.util.rdfinfer import Infer
+ add_default_schemas(model)
+ inference = Infer(model)
+ errmsgs = list(inference.run_validation())
+ self.assertEqual(len(errmsgs), 0)
+
+ def test_library_index_rdfa(self):
+ from htsworkflow.util.rdfhelp import \
+ add_default_schemas, get_model, load_string_into_model, \
+ dump_model
+ from htsworkflow.util.rdfinfer import Infer
+
+ model = get_model()
+ add_default_schemas(model)
+ inference = Infer(model)
+
+ response = self.client.get('/library/')
+ self.assertEqual(response.status_code, 200)
+ load_string_into_model(model, 'rdfa', response.content)
+
+ errmsgs = list(inference.run_validation())
+ self.assertEqual(len(errmsgs), 0)
+
+ body = """prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+ prefix libns: <http://jumpgate.caltech.edu/wiki/LibraryOntology#>
+
+ select ?library ?library_id ?name ?species ?species_name
+ where {
+ ?library a libns:Library .
+ OPTIONAL { ?library libns:library_id ?library_id . }
+ OPTIONAL { ?library libns:species ?species .
+ ?species libns:species_name ?species_name . }
+ OPTIONAL { ?library libns:name ?name . }
+ }"""
+ bindings = set(['library', 'library_id', 'name', 'species', 'species_name'])
+ query = RDF.SPARQLQuery(body)
+ count = 0
+ for r in query.execute(model):
+ count += 1
+ for name, value in r.items():
+ self.assertTrue(name in bindings)
+ self.assertTrue(value is not None)
+
+ self.assertEqual(count, len(Library.objects.filter(hidden=False)))
+
+ state = validate_xhtml(response.content)
+ if state is not None: self.assertTrue(state)
+
+
+# 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.
+def create_db(obj):
+ obj.species_human = Species.objects.get(pk=8)
+ obj.experiment_rna_seq = ExperimentType.objects.get(pk=4)
+ obj.affiliation_alice = Affiliation.objects.get(pk=1)
+ obj.affiliation_bob = Affiliation.objects.get(pk=2)
+
+ Library.objects.all().delete()
+ obj.library_10001 = Library(
+ id = "10001",
+ library_name = 'C2C12 named poorly',
+ library_species = obj.species_human,
+ experiment_type = obj.experiment_rna_seq,
+ creation_date = datetime.datetime.now(),
+ made_for = 'scientist unit 2007',
+ made_by = 'microfludics system 7321',
+ stopping_point = '2A',
+ undiluted_concentration = '5.01',
+ hidden = False,
+ )
+ obj.library_10001.save()
+ obj.library_10002 = Library(
+ id = "10002",
+ library_name = 'Worm named poorly',
+ library_species = obj.species_human,
+ experiment_type = obj.experiment_rna_seq,
+ creation_date = datetime.datetime.now(),
+ made_for = 'scientist unit 2007',
+ made_by = 'microfludics system 7321',
+ stopping_point = '2A',
+ undiluted_concentration = '5.01',
+ hidden = False,
+ )
+ obj.library_10002.save()
+
+try:
+ import RDF
+ HAVE_RDF = True
+
+ rdfNS = RDF.NS("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
+ xsdNS = RDF.NS("http://www.w3.org/2001/XMLSchema#")
+ libNS = RDF.NS("http://jumpgate.caltech.edu/wiki/LibraryOntology#")
+except ImportError,e:
+ HAVE_RDF = False
+
+
+class TestRDFaLibrary(TestCase):
+ fixtures = ['initial_data.json',
+ 'woldlab.json',
+ 'test_samples.json']
+
+ def test_parse_rdfa(self):
+ model = get_rdf_memory_model()
+ parser = RDF.Parser(name='rdfa')
+ url = '/library/10981/'
+ lib_response = self.client.get(url)
+ self.failIfEqual(len(lib_response.content), 0)
+
+ parser.parse_string_into_model(model,
+ lib_response.content,
+ 'http://localhost'+url)
+ # http://jumpgate.caltech.edu/wiki/LibraryOntology#affiliation>
+ self.check_literal_object(model, ['Bob'], p=libNS['affiliation'])
+ self.check_literal_object(model, ['Multiplexed'], p=libNS['experiment_type'])
+ self.check_literal_object(model, ['400'], p=libNS['gel_cut'])
+ self.check_literal_object(model, ['Igor'], p=libNS['made_by'])
+ self.check_literal_object(model, ['Paired End Multiplexed Sp-BAC'], p=libNS['name'])
+ self.check_literal_object(model, ['Drosophila melanogaster'], p=libNS['species_name'])
+
+ self.check_uri_object(model,
+ [u'http://localhost/lane/1193'],
+ p=libNS['has_lane'])
+
+ fc_uri = RDF.Uri('http://localhost/flowcell/303TUAAXX/')
+ self.check_literal_object(model,
+ [u"303TUAAXX"],
+ s=fc_uri, p=libNS['flowcell_id'])
+
+ def check_literal_object(self, model, values, s=None, p=None, o=None):
+ statements = list(model.find_statements(
+ RDF.Statement(s,p,o)))
+ self.failUnlessEqual(len(statements), len(values),
+ "Couln't find %s %s %s" % (s,p,o))
+ for s in statements:
+ self.failUnless(s.object.literal_value['string'] in values)
+
+
+ def check_uri_object(self, model, values, s=None, p=None, o=None):
+ statements = list(model.find_statements(
+ RDF.Statement(s,p,o)))
+ self.failUnlessEqual(len(statements), len(values),
+ "Couln't find %s %s %s" % (s,p,o))
+ for s in statements:
+ self.failUnless(unicode(s.object.uri) in values)
+
+
+
+def get_rdf_memory_model():
+ storage = RDF.MemoryStorage()
+ model = RDF.Model(storage)
+ return model
+
+def suite():
+ from unittest import TestSuite, defaultTestLoader
+ suite = TestSuite()
+ suite.addTests(defaultTestLoader.loadTestsFromTestCase(LibraryTestCase))
+ suite.addTests(defaultTestLoader.loadTestsFromTestCase(SampleWebTestCase))
+ suite.addTests(defaultTestLoader.loadTestsFromTestCase(TestRDFaLibrary))
+ return suite
+
+if __name__ == "__main__":
+ from unittest import main
+ main(defaultTest="suite")
--- /dev/null
+from django.conf.urls import patterns, url
+
+urlpatterns = patterns('samples.views',
+ # View livrary list
+ url(r'^$', 'library'),
+ url(r'^not_run/$', 'library_not_run'),
+ url(r'^(?P<lib_id>\w+)/$',
+ 'library_to_flowcells'),
+
+ url(r"^library/(?P<library_id>\w+)/json$", 'library_json'),
+ url(r"^species/(?P<species_id>\w+)/json$", 'species_json'),
+ url(r"^species/(?P<species_id>\w+)$", 'species'),
+ url(r"^antibody/$", 'antibodies'),
+)
--- /dev/null
+from __future__ import absolute_import, print_function
+
+# Create your views here.
+import StringIO
+import logging
+import os
+import sys
+
+try:
+ import json
+except ImportError, e:
+ import simplejson as json
+
+from django.views.decorators.csrf import csrf_exempt
+from django.core.exceptions import ObjectDoesNotExist
+from django.http import HttpResponse, HttpResponseRedirect, Http404
+from django.shortcuts import render_to_response, get_object_or_404
+from django.template import RequestContext
+from django.template.loader import get_template
+from django.contrib.auth.decorators import login_required
+from django.conf import settings
+
+from htsworkflow.auth import require_api_key
+from experiments.models import FlowCell, Lane, LANE_STATUS_MAP
+from experiments.admin import LaneOptions
+from .changelist import HTSChangeList
+from .models import Antibody, Library, Species, HTSUser
+from .admin import LibraryOptions
+from .results import get_flowcell_result_dict
+from bcmagic.forms import BarcodeMagicForm
+from htsworkflow.pipelines import runfolder
+from htsworkflow.pipelines.eland import ResultLane
+from htsworkflow.pipelines.samplekey import SampleKey
+from htsworkflow.util.conversion import unicode_or_none, parse_flowcell_id
+from htsworkflow.util import makebed
+from htsworkflow.util import opener
+
+
+
+LANE_LIST = [1,2,3,4,5,6,7,8]
+SAMPLES_CONTEXT_DEFAULTS = {
+ 'app_name': 'Flowcell/Library Tracker',
+ 'bcmagic': BarcodeMagicForm()
+}
+
+LOGGER = logging.getLogger(__name__)
+
+def count_lanes(lane_set):
+ single = 0
+ paired = 1
+ short_read = 0
+ medium_read = 1
+ long_read = 2
+ counts = [[0,0,0,],[0,0,0]]
+
+ for lane in lane_set.all():
+ if lane.flowcell.paired_end:
+ lane_type = paired
+ else:
+ lane_type = single
+ if lane.flowcell.read_length < 40:
+ read_type = short_read
+ elif lane.flowcell.read_length < 100:
+ read_type = medium_read
+ else:
+ read_type = long_read
+ counts[lane_type][read_type] += 1
+
+ return counts
+
+def create_library_context(cl):
+ """
+ Create a list of libraries that includes how many lanes were run
+ """
+ records = []
+ #for lib in library_items.object_list:
+ for lib in cl.result_list:
+ summary = {}
+ summary['library'] = lib
+ summary['library_id'] = lib.id
+ summary['library_name'] = lib.library_name
+ summary['species_name' ] = lib.library_species.scientific_name
+ if lib.amplified_from_sample is not None:
+ summary['amplified_from'] = lib.amplified_from_sample.id
+ else:
+ summary['amplified_from'] = ''
+ lanes_run = count_lanes(lib.lane_set)
+ # suppress zeros
+ for row in xrange(len(lanes_run)):
+ for col in xrange(len(lanes_run[row])):
+ if lanes_run[row][col] == 0:
+ lanes_run[row][col] = ''
+ summary['lanes_run'] = lanes_run
+ summary['is_archived'] = lib.is_archived()
+ records.append(summary)
+ cl.result_count = unicode(cl.paginator._count)
+ return {'library_list': records }
+
+
+def library(request, todo_only=False):
+ queryset = Library.objects.filter(hidden__exact=0)
+ filters = {'hidden__exact': 0}
+ if todo_only:
+ filters['lane'] = None
+ # build changelist
+ fcl = HTSChangeList(request, Library,
+ list_filter=['affiliations', 'library_species'],
+ search_fields=['id', 'library_name', 'amplified_from_sample__id'],
+ list_per_page=200,
+ model_admin=LibraryOptions(Library, None),
+ extra_filters=filters
+ )
+
+ context = { 'cl': fcl, 'title': 'Library Index', 'todo_only': todo_only}
+ context.update(create_library_context(fcl))
+ t = get_template('samples/library_index.html')
+ c = RequestContext(request, context)
+ return HttpResponse( t.render(c) )
+
+
+def library_not_run(request):
+ return library(request, todo_only=True)
+
+
+def library_to_flowcells(request, lib_id):
+ """
+ Display information about all the flowcells a library has been run on.
+ """
+ try:
+ lib = Library.objects.get(id=lib_id)
+ except:
+ raise Http404('Library %s does not exist' % (lib_id,))
+
+ flowcell_list = []
+ flowcell_run_results = {} # aka flowcells we're looking at
+ for lane in lib.lane_set.all():
+ fc = lane.flowcell
+ flowcell_id, id = parse_flowcell_id(fc.flowcell_id)
+ if flowcell_id not in flowcell_run_results:
+ flowcell_run_results[flowcell_id] = get_flowcell_result_dict(flowcell_id)
+ flowcell_list.append((fc.flowcell_id, lane.lane_number))
+
+ flowcell_list.sort()
+ lane_summary_list = []
+ eland_results = []
+ for fc, lane_number in flowcell_list:
+ lane_summary, err_list = _summary_stats(fc, lane_number, lib_id)
+ lane_summary_list.extend(lane_summary)
+
+ eland_results.extend(_make_eland_results(fc, lane_number, flowcell_run_results))
+
+ context = {
+ 'page_name': 'Library Details',
+ 'lib': lib,
+ 'eland_results': eland_results,
+ 'lane_summary_list': lane_summary_list,
+ }
+ context.update(SAMPLES_CONTEXT_DEFAULTS)
+
+ return render_to_response(
+ 'samples/library_detail.html',
+ context,
+ context_instance = RequestContext(request))
+
+def lanes_for(request, username=None):
+ """
+ Generate a report of recent activity for a user
+ """
+ query = {}
+ if username is not None:
+ user = HTSUser.objects.get(username=username)
+ query.update({'library__affiliations__users__id':user.id})
+ fcl = HTSChangeList(request, Lane,
+ list_filter=[],
+ search_fields=['flowcell__flowcell_id', 'library__id', 'library__library_name'],
+ list_per_page=200,
+ model_admin=LaneOptions,
+ queryset=Lane.objects.filter(**query)
+ )
+
+ context = { 'lanes': fcl, 'title': 'Lane Index'}
+
+ return render_to_response(
+ 'samples/lanes_for.html',
+ context,
+ context_instance = RequestContext(request)
+ )
+
+
+def summaryhtm_fc_cnm(request, flowcell_id, cnm):
+ """
+ returns a Summary.htm file if it exists.
+ """
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ d = get_flowcell_result_dict(fc_id)
+
+ if d is None:
+ return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
+
+ if cnm not in d:
+ return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
+
+ summary_filepath = d[cnm]['summary']
+
+ if summary_filepath is None:
+ return HttpResponse('<b>Summary.htm for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
+
+ f = open(summary_filepath, 'r')
+
+ return HttpResponse(f)
+
+
+def result_fc_cnm_eland_lane(request, flowcell_id, cnm, lane):
+ """
+ returns an eland_file upon calling.
+ """
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ d = get_flowcell_result_dict(fc_id)
+
+ if d is None:
+ return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
+
+ if cnm not in d:
+ return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
+
+ erd = d[cnm]['eland_results']
+ lane = int(lane)
+
+ if lane not in erd:
+ return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
+
+ filepath = erd[lane]
+
+ #f = opener.autoopen(filepath, 'r')
+ # return HttpResponse(f, content_type="application/x-elandresult")
+
+ f = open(filepath, 'r')
+ return HttpResponse(f, content_type='application/x-bzip2')
+
+
+
+def bedfile_fc_cnm_eland_lane_ucsc(request, fc_id, cnm, lane):
+ """
+ returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane (ucsc compatible)
+ """
+ return bedfile_fc_cnm_eland_lane(request, fc_id, cnm, lane, ucsc_compatible=True)
+
+
+def bedfile_fc_cnm_eland_lane(request, flowcell_id, cnm, lane, ucsc_compatible=False):
+ """
+ returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane
+ """
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ d = get_flowcell_result_dict(fc_id)
+
+ if d is None:
+ return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
+
+ if cnm not in d:
+ return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
+
+ erd = d[cnm]['eland_results']
+ lane = int(lane)
+
+ if lane not in erd:
+ return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
+
+ filepath = erd[lane]
+
+ # Eland result file
+ fi = opener.autoopen(filepath, 'r')
+ # output memory file
+
+ name, description = makebed.make_description( fc_id, lane )
+
+ bedgen = makebed.make_bed_from_eland_generator(fi, name, description)
+
+ if ucsc_compatible:
+ return HttpResponse(bedgen)
+ else:
+ return HttpResponse(bedgen, content_type="application/x-bedfile")
+
+
+def _summary_stats(flowcell_id, lane_id, library_id):
+ """
+ Return the summary statistics for a given flowcell, lane, and end.
+ """
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ fc_result_dict = get_flowcell_result_dict(fc_id)
+
+ summary_list = []
+ err_list = []
+
+ if fc_result_dict is None:
+ err_list.append('Results for Flowcell %s not found.' % (fc_id))
+ return (summary_list, err_list)
+
+ for cycle_width in fc_result_dict:
+ xmlpath = fc_result_dict[cycle_width]['run_xml']
+
+ if xmlpath is None:
+ err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cycle_width))
+ continue
+
+ run = runfolder.load_pipeline_run_xml(xmlpath)
+ # skip if we don't have available metadata.
+ if run.gerald is None or run.gerald.summary is None:
+ continue
+
+ gerald_summary = run.gerald.summary.lane_results
+ key = SampleKey(lane=lane_id, sample='s')
+ eland_results = list(run.gerald.eland_results.find_keys(key))
+ key = SampleKey(lane=lane_id, sample=library_id)
+ eland_results.extend(run.gerald.eland_results.find_keys(key))
+ for key in eland_results:
+ eland_summary = run.gerald.eland_results.results[key]
+ # add information to lane_summary
+ eland_summary.flowcell_id = flowcell_id
+
+ read = key.read-1 if key.read is not None else 0
+ try:
+ eland_summary.clusters = gerald_summary[read][key.lane].cluster
+ except (IndexError, KeyError) as e:
+ eland_summary.clustes = None
+ eland_summary.cycle_width = cycle_width
+ if hasattr(eland_summary, 'genome_map'):
+ eland_summary.summarized_reads = runfolder.summarize_mapped_reads(
+ eland_summary.genome_map,
+ eland_summary.mapped_reads)
+
+ # grab some more information out of the flowcell db
+ flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
+ #pm_field = 'lane_%d_pM' % (lane_id)
+ lanes = flowcell.lane_set.filter(lane_number=lane_id)
+ eland_summary.flowcell = flowcell
+ eland_summary.lanes = lanes
+
+ summary_list.append(eland_summary)
+
+ #except Exception, e:
+ # summary_list.append("Summary report needs to be updated.")
+ # LOGGER.error("Exception: " + str(e))
+
+ return (summary_list, err_list)
+
+
+def get_eland_result_type(pathname):
+ """
+ Guess the eland result file type from the filename
+ """
+ path, filename = os.path.split(pathname)
+ if 'extended' in filename:
+ return 'extended'
+ elif 'multi' in filename:
+ return 'multi'
+ elif 'result' in filename:
+ return 'result'
+ else:
+ return 'unknown'
+
+def _make_eland_results(flowcell_id, lane_number, interesting_flowcells):
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ cur_fc = interesting_flowcells.get(fc_id, None)
+ if cur_fc is None:
+ return []
+
+ flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
+ lanes = flowcell.lane_set.filter(lane_number=lane_number)
+ # Loop throw storage devices if a result has been archived
+ storage_id_list = []
+ if cur_fc is not None:
+ for lts in flowcell.longtermstorage_set.all():
+ for sd in lts.storage_devices.all():
+ # Use barcode_id if it exists
+ if sd.barcode_id is not None and sd.barcode_id != '':
+ storage_id_list.append(sd.barcode_id)
+ # Otherwise use UUID
+ else:
+ storage_id_list.append(sd.uuid)
+
+ # Formatting for template use
+ if len(storage_id_list) == 0:
+ storage_ids = None
+ else:
+ storage_ids = ', '.join([ '<a href="/inventory/%s/">%s</a>' % (s,s) for s in storage_id_list ])
+
+ results = []
+ for cycle in cur_fc.keys():
+ result_path = cur_fc[cycle]['eland_results'].get(lanes[0], None)
+ result_link = make_result_link(fc_id, cycle, lanes[0], result_path)
+ results.append({'flowcell_id': fc_id,
+ 'flowcell': flowcell,
+ 'run_date': flowcell.run_date,
+ 'cycle': cycle,
+ 'lane': lanes[0],
+ 'summary_url': make_summary_url(flowcell_id, cycle),
+ 'result_url': result_link[0],
+ 'result_label': result_link[1],
+ 'bed_url': result_link[2],
+ 'storage_ids': storage_ids
+ })
+ return results
+
+def make_summary_url(flowcell_id, cycle_name):
+ url = '/results/%s/%s/summary/' % (flowcell_id, cycle_name)
+ return url
+
+def make_result_link(flowcell_id, cycle_name, lane, eland_result_path):
+ if eland_result_path is None:
+ return ("", "", "")
+
+ result_type = get_eland_result_type(eland_result_path)
+ result_url = '/results/%s/%s/eland_result/%s' % (flowcell_id, cycle_name, lane)
+ result_label = 'eland %s' % (result_type,)
+ bed_url = None
+ if result_type == 'result':
+ bed_url_pattern = '/results/%s/%s/bedfile/%s'
+ bed_url = bed_url_pattern % (flowcell_id, cycle_name, lane)
+
+ return (result_url, result_label, bed_url)
+
+def _files(flowcell_id, lane):
+ """
+ Sets up available files for download
+ """
+ lane = int(lane)
+
+ flowcell_id, id = parse_flowcell_id(flowcell_id)
+ d = get_flowcell_result_dict(flowcell_id)
+
+ if d is None:
+ return ''
+
+ output = []
+
+ # c_name == 'CN-M' (i.e. C1-33)
+ for c_name in d:
+
+ if d[c_name]['summary'] is not None:
+ output.append('<a href="/results/%s/%s/summary/">summary(%s)</a>' \
+ % (flowcell_id, c_name, c_name))
+
+ erd = d[c_name]['eland_results']
+ if lane in erd:
+ result_type = get_eland_result_type(erd[lane])
+ result_url_pattern = '<a href="/results/%s/%s/eland_result/%s">eland %s(%s)</a>'
+ output.append(result_url_pattern % (flowcell_id, c_name, lane, result_type, c_name))
+ if result_type == 'result':
+ bed_url_pattern = '<a href="/results/%s/%s/bedfile/%s">bedfile(%s)</a>'
+ output.append(bed_url_pattern % (flowcell_id, c_name, lane, c_name))
+
+ if len(output) == 0:
+ return ''
+
+ return '(' + '|'.join(output) + ')'
+
+def library_id_to_admin_url(request, lib_id):
+ lib = Library.objects.get(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(id = library_id)
+ except Library.DoesNotExist, e:
+ return None
+
+ #lane_info = lane_information(lib.lane_set)
+ lane_info = []
+ for lane in lib.lane_set.all():
+ lane_info.append( {'flowcell':lane.flowcell.flowcell_id,
+ 'lane_number': lane.lane_number,
+ 'lane_id': lane.id,
+ 'paired_end': lane.flowcell.paired_end,
+ 'read_length': lane.flowcell.read_length,
+ 'status_code': lane.status,
+ 'status': LANE_STATUS_MAP[lane.status]} )
+
+ 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,
+ 'cell_line_id': lib.cell_line_id,
+ 'cell_line': unicode_or_none(lib.cell_line),
+ 'experiment_type': lib.experiment_type.name,
+ 'experiment_type_id': lib.experiment_type_id,
+ 'gel_cut_size': lib.gel_cut_size,
+ 'hidden': lib.hidden,
+ 'id': lib.id,
+ 'insert_size': lib.insert_size,
+ 'lane_set': lane_info,
+ 'library_id': lib.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': unicode_or_none(lib.successful_pM),
+ 'undiluted_concentration': unicode_or_none(lib.undiluted_concentration)
+ }
+ if lib.library_type_id is None:
+ info['library_type'] = None
+ else:
+ info['library_type'] = lib.library_type.name
+ return info
+
+@csrf_exempt
+def library_json(request, library_id):
+ """
+ Return a json formatted library dictionary
+ """
+ require_api_key(request)
+ # 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, content_type='application/json')
+
+@csrf_exempt
+def species_json(request, species_id):
+ """
+ Return information about a species.
+ """
+ raise Http404
+
+def species(request, species_id):
+ species = get_object_or_404(Species, id=species_id)
+
+ context = RequestContext(request,
+ { 'species': species })
+
+ return render_to_response("samples/species_detail.html", context)
+
+def antibodies(request):
+ context = RequestContext(request,
+ {'antibodies': Antibody.objects.order_by('antigene')})
+ return render_to_response("samples/antibody_index.html", context)
+
+@login_required
+def user_profile(request):
+ """
+ Information about the user
+ """
+ context = {
+ 'page_name': 'User Profile',
+ 'media': '',
+ #'bcmagic': BarcodeMagicForm(),
+ #'select': 'settings',
+ }
+ context.update(SAMPLES_CONTEXT_DEFAULTS)
+ return render_to_response('registration/profile.html', context,
+ context_instance=RequestContext(request))