1 # Create your views here.
10 import simplejson as json
12 from htsworkflow.frontend.auth import require_api_key
13 from htsworkflow.frontend.experiments.models import FlowCell
14 from htsworkflow.frontend.samples.changelist import ChangeList
15 from htsworkflow.frontend.samples.models import Library
16 from htsworkflow.frontend.samples.results import get_flowcell_result_dict, parse_flowcell_id
17 from htsworkflow.frontend.bcmagic.forms import BarcodeMagicForm
18 from htsworkflow.pipelines.runfolder import load_pipeline_run_xml
19 from htsworkflow.pipelines import runfolder
20 from htsworkflow.pipelines.eland import ResultLane
21 from htsworkflow.frontend import settings
22 from htsworkflow.util import makebed
23 from htsworkflow.util import opener
25 from django.core.exceptions import ObjectDoesNotExist
26 from django.http import HttpResponse, HttpResponseRedirect, Http404
27 from django.shortcuts import render_to_response
28 from django.template import RequestContext
29 from django.template.loader import get_template
30 from django.contrib.auth.decorators import login_required
32 LANE_LIST = [1,2,3,4,5,6,7,8]
33 SAMPLES_CONTEXT_DEFAULTS = {
34 'app_name': 'Flowcell/Library Tracker',
35 'bcmagic': BarcodeMagicForm()
38 def create_library_context(cl):
40 Create a list of libraries that includes how many lanes were run
43 #for lib in library_items.object_list:
44 for lib in cl.result_list:
46 summary['library_id'] = lib.id
47 summary['library_name'] = lib.library_name
48 summary['species_name' ] = lib.library_species.scientific_name
49 if lib.amplified_from_sample is not None:
50 summary['amplified_from'] = lib.amplified_from_sample.id
52 summary['amplified_from'] = ''
54 #for lane_id in LANE_LIST:
55 # lane = getattr(lib, 'lane_%d_library' % (lane_id,))
56 # lanes_run += len( lane.all() )
57 lanes_run = lib.lane_set.count()
58 summary['lanes_run'] = lanes_run
59 summary['is_archived'] = lib.is_archived()
60 records.append(summary)
61 cl.result_count = unicode(cl.paginator._count) + u" libraries"
62 return {'library_list': records }
66 fcl = ChangeList(request, Library,
67 list_filter=['affiliations', 'library_species'],
68 search_fields=['id', 'library_name', 'amplified_from_sample__id'],
70 queryset=Library.objects.filter(hidden__exact=0)
73 context = { 'cl': fcl, 'title': 'Library Index'}
74 context.update(create_library_context(fcl))
75 t = get_template('samples/library_index.html')
76 c = RequestContext(request, context)
79 'page_name': 'Library Index',
80 'east_region_config_div': 'changelist-filter',
83 app_context.update(SAMPLES_CONTEXT_DEFAULTS)
85 app_t = get_template('flowcell_libraries_app.html')
86 app_c = RequestContext(request, app_context)
87 return HttpResponse( app_t.render(app_c) )
89 def library_to_flowcells(request, lib_id):
91 Display information about all the flowcells a library has been run on.
95 lib = Library.objects.get(id=lib_id)
97 return HttpResponse("Library %s does not exist" % (lib_id))
100 flowcell_run_results = {} # aka flowcells we're looking at
101 for lane in lib.lane_set.all():
103 flowcell_id, id = parse_flowcell_id(fc.flowcell_id)
104 if flowcell_id not in flowcell_run_results:
105 flowcell_run_results[flowcell_id] = get_flowcell_result_dict(flowcell_id)
106 flowcell_list.append((fc.flowcell_id, lane.lane_number))
109 lane_summary_list = []
111 for fc, lane_number in flowcell_list:
112 lane_summary, err_list = _summary_stats(fc, lane_number)
114 eland_results.extend(_make_eland_results(fc, lane_number, flowcell_run_results))
115 lane_summary_list.extend(lane_summary)
118 'page_name': 'Library Details',
120 'eland_results': eland_results,
121 'lane_summary_list': lane_summary_list,
123 context.update(SAMPLES_CONTEXT_DEFAULTS)
125 return render_to_response(
126 'samples/library_detail.html',
128 context_instance = RequestContext(request))
130 def summaryhtm_fc_cnm(request, flowcell_id, cnm):
132 returns a Summary.htm file if it exists.
134 fc_id, status = parse_flowcell_id(flowcell_id)
135 d = get_flowcell_result_dict(fc_id)
138 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
141 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
143 summary_filepath = d[cnm]['summary']
145 if summary_filepath is None:
146 return HttpResponse('<b>Summary.htm for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
148 f = open(summary_filepath, 'r')
150 return HttpResponse(f)
153 def result_fc_cnm_eland_lane(request, flowcell_id, cnm, lane):
155 returns an eland_file upon calling.
157 fc_id, status = parse_flowcell_id(flowcell_id)
158 d = get_flowcell_result_dict(fc_id)
161 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
164 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
166 erd = d[cnm]['eland_results']
170 return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
174 #f = opener.autoopen(filepath, 'r')
175 # return HttpResponse(f, mimetype="application/x-elandresult")
177 f = open(filepath, 'r')
178 return HttpResponse(f, mimetype='application/x-bzip2')
182 def bedfile_fc_cnm_eland_lane_ucsc(request, fc_id, cnm, lane):
184 returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane (ucsc compatible)
186 return bedfile_fc_cnm_eland_lane(request, fc_id, cnm, lane, ucsc_compatible=True)
189 def bedfile_fc_cnm_eland_lane(request, flowcell_id, cnm, lane, ucsc_compatible=False):
191 returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane
193 fc_id, status = parse_flowcell_id(flowcell_id)
194 d = get_flowcell_result_dict(fc_id)
197 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
200 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
202 erd = d[cnm]['eland_results']
206 return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
211 fi = opener.autoopen(filepath, 'r')
214 name, description = makebed.make_description( fc_id, lane )
216 bedgen = makebed.make_bed_from_eland_generator(fi, name, description)
219 return HttpResponse(bedgen)
221 return HttpResponse(bedgen, mimetype="application/x-bedfile")
224 def _summary_stats(flowcell_id, lane_id):
226 Return the summary statistics for a given flowcell, lane, and end.
228 fc_id, status = parse_flowcell_id(flowcell_id)
229 fc_result_dict = get_flowcell_result_dict(fc_id)
234 if fc_result_dict is None:
235 err_list.append('Results for Flowcell %s not found.' % (fc_id))
236 return (summary_list, err_list)
238 for cycle_width in fc_result_dict:
239 xmlpath = fc_result_dict[cycle_width]['run_xml']
242 err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cycle_width))
245 run = load_pipeline_run_xml(xmlpath)
246 gerald_summary = run.gerald.summary.lane_results
247 for end in range(len(gerald_summary)):
248 end_summary = run.gerald.eland_results.results[end]
249 if end_summary.has_key(lane_id):
250 eland_summary = run.gerald.eland_results.results[end][lane_id]
252 eland_summary = ResultLane(lane_id=lane_id, end=end)
253 # add information to lane_summary
254 eland_summary.flowcell_id = flowcell_id
255 if len(gerald_summary) > end and gerald_summary[end].has_key(lane_id):
256 eland_summary.clusters = gerald_summary[end][lane_id].cluster
258 eland_summary.clusters = None
259 eland_summary.cycle_width = cycle_width
260 if hasattr(eland_summary, 'genome_map'):
261 eland_summary.summarized_reads = runfolder.summarize_mapped_reads(
262 eland_summary.genome_map,
263 eland_summary.mapped_reads)
265 # grab some more information out of the flowcell db
266 flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
267 #pm_field = 'lane_%d_pM' % (lane_id)
268 lane_obj = flowcell.lane_set.get(lane_number=lane_id)
269 eland_summary.successful_pm = lane_obj.pM
271 summary_list.append(eland_summary)
273 #except Exception, e:
274 # summary_list.append("Summary report needs to be updated.")
275 # logging.error("Exception: " + str(e))
277 return (summary_list, err_list)
279 def _summary_stats_old(flowcell_id, lane):
281 return a dictionary of summary stats for a given flowcell_id & lane.
283 fc_id, status = parse_flowcell_id(flowcell_id)
284 fc_result_dict = get_flowcell_result_dict(fc_id)
290 if fc_result_dict is None:
291 err_list.append('Results for Flowcell %s not found.' % (fc_id))
292 return (dict_list, err_list, summary_list)
294 for cnm in fc_result_dict:
296 xmlpath = fc_result_dict[cnm]['run_xml']
299 err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cnm))
302 tree = ElementTree.parse(xmlpath).getroot()
303 results = runfolder.PipelineRun(pathname='', xml=tree)
305 lane_report = runfolder.summarize_lane(results.gerald, lane)
306 summary_list.append(os.linesep.join(lane_report))
308 summary_list.append("Summary report needs to be updated.")
309 logging.error("Exception: " + str(e))
311 print >>sys.stderr, "----------------------------------"
312 print >>sys.stderr, "-- DOES NOT SUPPORT PAIRED END ---"
313 print >>sys.stderr, "----------------------------------"
314 lane_results = results.gerald.summary[0][lane]
319 d['average_alignment_score'] = lrs.average_alignment_score
320 d['average_first_cycle_intensity'] = lrs.average_first_cycle_intensity
321 d['cluster'] = lrs.cluster
323 d['flowcell'] = flowcell_id
325 d['percent_error_rate'] = lrs.percent_error_rate
326 d['percent_intensity_after_20_cycles'] = lrs.percent_intensity_after_20_cycles
327 d['percent_pass_filter_align'] = lrs.percent_pass_filter_align
328 d['percent_pass_filter_clusters'] = lrs.percent_pass_filter_clusters
330 #FIXME: function finished, but need to take advantage of
331 # may need to take in a list of lanes so we only have to
332 # load the xml file once per flowcell rather than once
336 return (dict_list, err_list, summary_list)
339 def get_eland_result_type(pathname):
341 Guess the eland result file type from the filename
343 path, filename = os.path.split(pathname)
344 if 'extended' in filename:
346 elif 'multi' in filename:
348 elif 'result' in filename:
353 def _make_eland_results(flowcell_id, lane, interesting_flowcells):
354 fc_id, status = parse_flowcell_id(flowcell_id)
355 cur_fc = interesting_flowcells.get(fc_id, None)
359 flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
360 # Loop throw storage devices if a result has been archived
362 if cur_fc is not None:
363 for lts in flowcell.longtermstorage_set.all():
364 for sd in lts.storage_devices.all():
365 # Use barcode_id if it exists
366 if sd.barcode_id is not None and sd.barcode_id != '':
367 storage_id_list.append(sd.barcode_id)
370 storage_id_list.append(sd.uuid)
372 # Formatting for template use
373 if len(storage_id_list) == 0:
376 storage_ids = ', '.join([ '<a href="/inventory/%s/">%s</a>' % (s,s) for s in storage_id_list ])
379 for cycle in cur_fc.keys():
380 result_path = cur_fc[cycle]['eland_results'].get(lane, None)
381 result_link = make_result_link(fc_id, cycle, lane, result_path)
382 results.append({'flowcell_id': fc_id,
383 'run_date': flowcell.run_date,
386 'summary_url': make_summary_url(flowcell_id, cycle),
387 'result_url': result_link[0],
388 'result_label': result_link[1],
389 'bed_url': result_link[2],
390 'storage_ids': storage_ids
394 def make_summary_url(flowcell_id, cycle_name):
395 url = '/results/%s/%s/summary/' % (flowcell_id, cycle_name)
398 def make_result_link(flowcell_id, cycle_name, lane, eland_result_path):
399 if eland_result_path is None:
402 result_type = get_eland_result_type(eland_result_path)
403 result_url = '/results/%s/%s/eland_result/%s' % (flowcell_id, cycle_name, lane)
404 result_label = 'eland %s' % (result_type,)
406 if result_type == 'result':
407 bed_url_pattern = '/results/%s/%s/bedfile/%s'
408 bed_url = bed_url_pattern % (flowcell_id, cycle_name, lane)
410 return (result_url, result_label, bed_url)
412 def _files(flowcell_id, lane):
414 Sets up available files for download
418 flowcell_id, id = parse_flowcell_id(flowcell_id)
419 d = get_flowcell_result_dict(flowcell_id)
426 # c_name == 'CN-M' (i.e. C1-33)
429 if d[c_name]['summary'] is not None:
430 output.append('<a href="/results/%s/%s/summary/">summary(%s)</a>' \
431 % (flowcell_id, c_name, c_name))
433 erd = d[c_name]['eland_results']
435 result_type = get_eland_result_type(erd[lane])
436 result_url_pattern = '<a href="/results/%s/%s/eland_result/%s">eland %s(%s)</a>'
437 output.append(result_url_pattern % (flowcell_id, c_name, lane, result_type, c_name))
438 if result_type == 'result':
439 bed_url_pattern = '<a href="/results/%s/%s/bedfile/%s">bedfile(%s)</a>'
440 output.append(bed_url_pattern % (flowcell_id, c_name, lane, c_name))
445 return '(' + '|'.join(output) + ')'
447 def library_id_to_admin_url(request, lib_id):
448 lib = Library.objects.get(id=lib_id)
449 return HttpResponseRedirect('/admin/samples/library/%s' % (lib.id,))
451 def library_dict(library_id):
453 Given a library id construct a dictionary containing important information
454 return None if nothing was found
457 lib = Library.objects.get(id = library_id)
458 except Library.DoesNotExist, e:
461 #lane_info = lane_information(lib.lane_set)
463 for lane in lib.lane_set.all():
464 lane_info.append( {'flowcell':lane.flowcell.flowcell_id,
465 'lane_number': lane.lane_number} )
469 # 'aligned_reads': lib.aligned_reads,
470 #'amplified_into_sample': lib.amplified_into_sample, # into is a colleciton...
471 #'amplified_from_sample_id': lib.amplified_from_sample,
472 #'antibody_name': lib.antibody_name(), # we have no antibodies.
473 'antibody_id': lib.antibody_id,
474 'avg_lib_size': lib.avg_lib_size,
475 'cell_line': lib.cell_line.cellline_name,
476 'cell_line_id': lib.cell_line_id,
477 'experiment_type': lib.experiment_type.name,
478 'experiment_type_id': lib.experiment_type_id,
480 'lane_set': lane_info,
481 'library_id': lib.id,
482 'library_name': lib.library_name,
483 'library_species': lib.library_species.scientific_name,
484 'library_species_id': lib.library_species_id,
485 #'library_type': lib.library_type.name,
486 'library_type_id': lib.library_type_id,
487 'made_for': lib.made_for,
488 'made_by': lib.made_by,
490 'replicate': lib.replicate,
491 'stopping_point': lib.stopping_point,
492 'successful_pM': unicode(lib.successful_pM),
493 'undiluted_concentration': unicode(lib.undiluted_concentration)
495 if lib.library_type_id is None:
496 info['library_type'] = None
498 info['library_type'] = lib.library_type.name
501 def library_json(request, library_id):
503 Return a json formatted library dictionary
505 require_api_key(request)
506 # what validation should we do on library_id?
508 lib = library_dict(library_id)
512 lib_json = json.dumps(lib)
513 return HttpResponse(lib_json, mimetype='application/json')
515 def species_json(request, species_id):
517 Return information about a species.
522 def user_profile(request):
524 Information about the user
527 'page_name': 'User Profile',
529 #'bcmagic': BarcodeMagicForm(),
530 #'select': 'settings',
532 context.update(SAMPLES_CONTEXT_DEFAULTS)
533 return render_to_response('registration/profile.html', context,
534 context_instance=RequestContext(request))