1 # Create your views here.
8 import simplejson as json
10 from htsworkflow.frontend.experiments.models import FlowCell
11 from htsworkflow.frontend.samples.changelist import ChangeList
12 from htsworkflow.frontend.samples.models import Library
13 from htsworkflow.frontend.samples.results import get_flowcell_result_dict, parse_flowcell_id
14 from htsworkflow.frontend.bcmagic.forms import BarcodeMagicForm
15 from htsworkflow.pipelines.runfolder import load_pipeline_run_xml
16 from htsworkflow.pipelines import runfolder
17 from htsworkflow.pipelines.eland import ResultLane
18 from htsworkflow.frontend import settings
19 from htsworkflow.util import makebed
20 from htsworkflow.util import opener
22 from django.core.exceptions import ObjectDoesNotExist
23 from django.http import HttpResponse, HttpResponseRedirect, Http404
24 from django.shortcuts import render_to_response
25 from django.template import RequestContext
26 from django.template.loader import get_template
27 from django.contrib.auth.decorators import login_required
29 LANE_LIST = [1,2,3,4,5,6,7,8]
30 SAMPLES_CONTEXT_DEFAULTS = {
31 'app_name': 'Flowcell/Library Tracker',
32 'bcmagic': BarcodeMagicForm()
35 def create_library_context(cl):
37 Create a list of libraries that includes how many lanes were run
40 #for lib in library_items.object_list:
41 for lib in cl.result_list:
43 summary['library_id'] = lib.library_id
44 summary['library_name'] = lib.library_name
45 summary['species_name' ] = lib.library_species.scientific_name
46 if lib.amplified_from_sample is not None:
47 summary['amplified_from'] = lib.amplified_from_sample.library_id
49 summary['amplified_from'] = ''
51 #for lane_id in LANE_LIST:
52 # lane = getattr(lib, 'lane_%d_library' % (lane_id,))
53 # lanes_run += len( lane.all() )
54 lanes_run = lib.lane_set.count()
55 summary['lanes_run'] = lanes_run
56 summary['is_archived'] = lib.is_archived()
57 records.append(summary)
58 cl.result_count = unicode(cl.paginator._count) + u" libraries"
59 return {'library_list': records }
63 fcl = ChangeList(request, Library,
64 list_filter=['affiliations', 'library_species'],
65 search_fields=['library_id', 'library_name', 'amplified_from_sample__library_id'],
67 queryset=Library.objects.filter(hidden__exact=0)
70 context = { 'cl': fcl, 'title': 'Library Index'}
71 context.update(create_library_context(fcl))
72 t = get_template('samples/library_index.html')
73 c = RequestContext(request, context)
76 'page_name': 'Library Index',
77 'east_region_config_div': 'changelist-filter',
80 app_context.update(SAMPLES_CONTEXT_DEFAULTS)
82 app_t = get_template('flowcell_libraries_app.html')
83 app_c = RequestContext(request, app_context)
84 return HttpResponse( app_t.render(app_c) )
86 def library_to_flowcells(request, lib_id):
88 Display information about all the flowcells a library has been run on.
92 lib = Library.objects.get(library_id=lib_id)
94 return HttpResponse("Library %s does not exist" % (lib_id))
97 interesting_flowcells = {} # aka flowcells we're looking at
98 #for lane in LANE_LIST:
99 for lane in lib.lane_set.all():
100 #lane_library = getattr(lib, 'lane_%d_library' % (lane,))
101 #for fc in lane_library.all():
103 flowcell_id, id = parse_flowcell_id(fc.flowcell_id)
104 if flowcell_id not in interesting_flowcells:
105 interesting_flowcells[flowcell_id] = get_flowcell_result_dict(flowcell_id)
106 flowcell_list.append((fc.flowcell_id, lane.lane_number))
110 lane_summary_list = []
112 for fc, lane_number in flowcell_list:
113 lane_summary, err_list = _summary_stats(fc, lane_number)
115 eland_results.extend(_make_eland_results(fc, lane_number, interesting_flowcells))
116 lane_summary_list.extend(lane_summary)
119 'page_name': 'Library Details',
121 'eland_results': eland_results,
122 'lane_summary_list': lane_summary_list,
124 context.update(SAMPLES_CONTEXT_DEFAULTS)
126 return render_to_response(
127 'samples/library_detail.html',
129 context_instance = RequestContext(request))
131 def summaryhtm_fc_cnm(request, flowcell_id, cnm):
133 returns a Summary.htm file if it exists.
135 fc_id, status = parse_flowcell_id(flowcell_id)
136 d = get_flowcell_result_dict(fc_id)
139 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
142 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
144 summary_filepath = d[cnm]['summary']
146 if summary_filepath is None:
147 return HttpResponse('<b>Summary.htm for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
149 f = open(summary_filepath, 'r')
151 return HttpResponse(f)
154 def result_fc_cnm_eland_lane(request, flowcell_id, cnm, lane):
156 returns an eland_file upon calling.
158 fc_id, status = parse_flowcell_id(flowcell_id)
159 d = get_flowcell_result_dict(fc_id)
162 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
165 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
167 erd = d[cnm]['eland_results']
171 return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
175 #f = opener.autoopen(filepath, 'r')
176 # return HttpResponse(f, mimetype="application/x-elandresult")
178 f = open(filepath, 'r')
179 return HttpResponse(f, mimetype='application/x-bzip2')
183 def bedfile_fc_cnm_eland_lane_ucsc(request, fc_id, cnm, lane):
185 returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane (ucsc compatible)
187 return bedfile_fc_cnm_eland_lane(request, fc_id, cnm, lane, ucsc_compatible=True)
190 def bedfile_fc_cnm_eland_lane(request, flowcell_id, cnm, lane, ucsc_compatible=False):
192 returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane
194 fc_id, status = parse_flowcell_id(flowcell_id)
195 d = get_flowcell_result_dict(fc_id)
198 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
201 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
203 erd = d[cnm]['eland_results']
207 return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
212 fi = opener.autoopen(filepath, 'r')
215 name, description = makebed.make_description( fc_id, lane )
217 bedgen = makebed.make_bed_from_eland_generator(fi, name, description)
220 return HttpResponse(bedgen)
222 return HttpResponse(bedgen, mimetype="application/x-bedfile")
225 def _summary_stats(flowcell_id, lane_id):
227 Return the summary statistics for a given flowcell, lane, and end.
229 fc_id, status = parse_flowcell_id(flowcell_id)
230 fc_result_dict = get_flowcell_result_dict(fc_id)
235 if fc_result_dict is None:
236 err_list.append('Results for Flowcell %s not found.' % (fc_id))
237 return (summary_list, err_list)
239 for cycle_width in fc_result_dict:
240 xmlpath = fc_result_dict[cycle_width]['run_xml']
243 err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cycle_width))
246 run = load_pipeline_run_xml(xmlpath)
247 gerald_summary = run.gerald.summary.lane_results
248 for end in range(len(gerald_summary)):
249 end_summary = run.gerald.eland_results.results[end]
250 if end_summary.has_key(lane_id):
251 eland_summary = run.gerald.eland_results.results[end][lane_id]
253 eland_summary = ResultLane(lane_id=lane_id, end=end)
254 # add information to lane_summary
255 eland_summary.flowcell_id = flowcell_id
256 if len(gerald_summary) > end and gerald_summary[end].has_key(lane_id):
257 eland_summary.clusters = gerald_summary[end][lane_id].cluster
259 eland_summary.clusters = None
260 eland_summary.cycle_width = cycle_width
261 if hasattr(eland_summary, 'genome_map'):
262 eland_summary.summarized_reads = runfolder.summarize_mapped_reads(
263 eland_summary.genome_map,
264 eland_summary.mapped_reads)
266 # grab some more information out of the flowcell db
267 flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
268 #pm_field = 'lane_%d_pM' % (lane_id)
269 lane_obj = flowcell.lane_set.get(lane_number=lane_id)
270 eland_summary.successful_pm = lane_obj.pM
272 summary_list.append(eland_summary)
274 #except Exception, e:
275 # summary_list.append("Summary report needs to be updated.")
276 # logging.error("Exception: " + str(e))
278 return (summary_list, err_list)
280 def _summary_stats_old(flowcell_id, lane):
282 return a dictionary of summary stats for a given flowcell_id & lane.
284 fc_id, status = parse_flowcell_id(flowcell_id)
285 fc_result_dict = get_flowcell_result_dict(fc_id)
291 if fc_result_dict is None:
292 err_list.append('Results for Flowcell %s not found.' % (fc_id))
293 return (dict_list, err_list, summary_list)
295 for cnm in fc_result_dict:
297 xmlpath = fc_result_dict[cnm]['run_xml']
300 err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cnm))
303 tree = ElementTree.parse(xmlpath).getroot()
304 results = runfolder.PipelineRun(pathname='', xml=tree)
306 lane_report = runfolder.summarize_lane(results.gerald, lane)
307 summary_list.append(os.linesep.join(lane_report))
309 summary_list.append("Summary report needs to be updated.")
310 logging.error("Exception: " + str(e))
312 print "----------------------------------"
313 print "-- DOES NOT SUPPORT PAIRED END ---"
314 print "----------------------------------"
315 lane_results = results.gerald.summary[0][lane]
320 d['average_alignment_score'] = lrs.average_alignment_score
321 d['average_first_cycle_intensity'] = lrs.average_first_cycle_intensity
322 d['cluster'] = lrs.cluster
324 d['flowcell'] = flowcell_id
326 d['percent_error_rate'] = lrs.percent_error_rate
327 d['percent_intensity_after_20_cycles'] = lrs.percent_intensity_after_20_cycles
328 d['percent_pass_filter_align'] = lrs.percent_pass_filter_align
329 d['percent_pass_filter_clusters'] = lrs.percent_pass_filter_clusters
331 #FIXME: function finished, but need to take advantage of
332 # may need to take in a list of lanes so we only have to
333 # load the xml file once per flowcell rather than once
337 return (dict_list, err_list, summary_list)
340 def get_eland_result_type(pathname):
342 Guess the eland result file type from the filename
344 path, filename = os.path.split(pathname)
345 if 'extended' in filename:
347 elif 'multi' in filename:
349 elif 'result' in filename:
354 def _make_eland_results(flowcell_id, lane, interesting_flowcells):
355 fc_id, status = parse_flowcell_id(flowcell_id)
356 cur_fc = interesting_flowcells.get(fc_id, None)
360 flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
361 # Loop throw storage devices if a result has been archived
363 if cur_fc is not None:
364 for lts in flowcell.longtermstorage_set.all():
365 for sd in lts.storage_devices.all():
366 # Use barcode_id if it exists
367 if sd.barcode_id is not None and sd.barcode_id != '':
368 storage_id_list.append(sd.barcode_id)
371 storage_id_list.append(sd.uuid)
373 # Formatting for template use
374 if len(storage_id_list) == 0:
377 storage_ids = ', '.join([ '<a href="/inventory/%s/">%s</a>' % (s,s) for s in storage_id_list ])
380 for cycle in cur_fc.keys():
381 result_path = cur_fc[cycle]['eland_results'].get(lane, None)
382 result_link = make_result_link(fc_id, cycle, lane, result_path)
383 results.append({'flowcell_id': fc_id,
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(library_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(library_id = library_id)
458 except Library.DoesNotExist, e:
463 # 'aligned_reads': lib.aligned_reads,
464 #'amplified_into_sample': lib.amplified_into_sample, # into is a colleciton...
465 #'amplified_from_sample_id': lib.amplified_from_sample,
466 #'antibody_name': lib.antibody_name(), # we have no antibodies.
467 'antibody_id': lib.antibody_id,
468 'avg_lib_size': lib.avg_lib_size,
469 'cell_line': lib.cell_line.cellline_name,
470 'cell_line_id': lib.cell_line_id,
471 'experiment_type': lib.experiment_type.name,
472 'experiment_type_id': lib.experiment_type_id,
474 'library_id': lib.library_id,
475 'library_name': lib.library_name,
476 'library_species': lib.library_species.scientific_name,
477 'library_species_id': lib.library_species_id,
478 #'library_type': lib.library_type.name,
479 'library_type_id': lib.library_type_id,
480 'made_for': lib.made_for,
481 'made_by': lib.made_by,
483 'replicate': lib.replicate,
484 'stopping_point': lib.stopping_point,
485 'successful_pM': lib.successful_pM,
486 'undiluted_concentration': unicode(lib.undiluted_concentration)
488 if lib.library_type_id is None:
489 info['library_type'] = None
491 info['library_type'] = lib.library_type.name
495 def library_json(request, library_id):
497 Return a json formatted library dictionary
499 # what validation should we do on library_id?
501 lib = library_dict(library_id)
505 lib_json = json.dumps(lib)
506 return HttpResponse(lib_json, mimetype='application/json')
509 def user_profile(request):
511 Information about the user
514 'page_name': 'User Profile',
516 #'bcmagic': BarcodeMagicForm(),
517 #'select': 'settings',
519 context.update(SAMPLES_CONTEXT_DEFAULTS)
520 return render_to_response('registration/profile.html', context,
521 context_instance=RequestContext(request))