1 # Create your views here.
2 from htsworkflow.frontend.experiments.models import FlowCell
3 from htsworkflow.frontend.samples.changelist import ChangeList
4 from htsworkflow.frontend.samples.models import Library
5 from htsworkflow.frontend.samples.results import get_flowcell_result_dict, parse_flowcell_id
6 from htsworkflow.frontend.bcmagic.forms import BarcodeMagicForm
7 from htsworkflow.pipelines.runfolder import load_pipeline_run_xml
8 from htsworkflow.pipelines import runfolder
9 from htsworkflow.pipelines.eland import ResultLane
10 from htsworkflow.frontend import settings
11 from htsworkflow.util import makebed
12 from htsworkflow.util import opener
14 from django.core.exceptions import ObjectDoesNotExist
15 from django.http import HttpResponse, HttpResponseRedirect
16 from django.shortcuts import render_to_response
17 from django.template import RequestContext
18 from django.template.loader import get_template
19 from django.contrib.auth.decorators import login_required
25 LANE_LIST = [1,2,3,4,5,6,7,8]
26 SAMPLES_CONTEXT_DEFAULTS = {
27 'app_name': 'Flowcell/Library Tracker',
28 'bcmagic': BarcodeMagicForm()
31 def create_library_context(cl):
33 Create a list of libraries that includes how many lanes were run
36 #for lib in library_items.object_list:
37 for lib in cl.result_list:
39 summary['library_id'] = lib.library_id
40 summary['library_name'] = lib.library_name
41 summary['species_name' ] = lib.library_species.scientific_name
42 if lib.amplified_from_sample is not None:
43 summary['amplified_from'] = lib.amplified_from_sample.library_id
45 summary['amplified_from'] = ''
47 for lane_id in LANE_LIST:
48 lane = getattr(lib, 'lane_%d_library' % (lane_id,))
49 lanes_run += len( lane.all() )
50 summary['lanes_run'] = lanes_run
51 summary['is_archived'] = lib.is_archived()
52 records.append(summary)
53 cl.result_count = unicode(cl.paginator._count) + u" libraries"
54 return {'library_list': records }
58 fcl = ChangeList(request, Library,
59 list_filter=['affiliations', 'library_species'],
60 search_fields=['library_id', 'library_name', 'amplified_from_sample__library_id'],
62 queryset=Library.objects.filter(hidden__exact=0)
65 context = { 'cl': fcl, 'title': 'Library Index'}
66 context.update(create_library_context(fcl))
67 t = get_template('samples/library_index.html')
68 c = RequestContext(request, context)
71 'page_name': 'Library Index',
72 'east_region_config_div': 'changelist-filter',
75 app_context.update(SAMPLES_CONTEXT_DEFAULTS)
77 app_t = get_template('flowcell_libraries_app.html')
78 app_c = RequestContext(request, app_context)
79 return HttpResponse( app_t.render(app_c) )
81 def library_to_flowcells(request, lib_id):
83 Display information about all the flowcells a library has been run on.
87 lib = Library.objects.get(library_id=lib_id)
89 return HttpResponse("Library %s does not exist" % (lib_id))
92 interesting_flowcells = {} # aka flowcells we're looking at
93 for lane in LANE_LIST:
94 lane_library = getattr(lib, 'lane_%d_library' % (lane,))
95 for fc in lane_library.all():
96 flowcell_id, id = parse_flowcell_id(fc.flowcell_id)
97 if flowcell_id not in interesting_flowcells:
98 interesting_flowcells[flowcell_id] = get_flowcell_result_dict(flowcell_id)
99 flowcell_list.append((fc.flowcell_id, lane))
103 lane_summary_list = []
105 for fc, lane in flowcell_list:
106 lane_summary, err_list = _summary_stats(fc, lane)
108 eland_results.extend(_make_eland_results(fc, lane, interesting_flowcells))
109 lane_summary_list.extend(lane_summary)
112 'page_name': 'Library Details',
114 'eland_results': eland_results,
115 'lane_summary_list': lane_summary_list,
117 context.update(SAMPLES_CONTEXT_DEFAULTS)
119 return render_to_response(
120 'samples/library_detail.html',
122 context_instance = RequestContext(request))
124 def summaryhtm_fc_cnm(request, flowcell_id, cnm):
126 returns a Summary.htm file if it exists.
128 fc_id, status = parse_flowcell_id(flowcell_id)
129 d = get_flowcell_result_dict(fc_id)
132 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
135 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
137 summary_filepath = d[cnm]['summary']
139 if summary_filepath is None:
140 return HttpResponse('<b>Summary.htm for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
142 f = open(summary_filepath, 'r')
144 return HttpResponse(f)
147 def result_fc_cnm_eland_lane(request, flowcell_id, cnm, lane):
149 returns an eland_file upon calling.
151 fc_id, status = parse_flowcell_id(flowcell_id)
152 d = get_flowcell_result_dict(fc_id)
155 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
158 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
160 erd = d[cnm]['eland_results']
164 return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
168 #f = opener.autoopen(filepath, 'r')
169 # return HttpResponse(f, mimetype="application/x-elandresult")
171 f = open(filepath, 'r')
172 return HttpResponse(f, mimetype='application/x-bzip2')
176 def bedfile_fc_cnm_eland_lane_ucsc(request, fc_id, cnm, lane):
178 returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane (ucsc compatible)
180 return bedfile_fc_cnm_eland_lane(request, fc_id, cnm, lane, ucsc_compatible=True)
183 def bedfile_fc_cnm_eland_lane(request, flowcell_id, cnm, lane, ucsc_compatible=False):
185 returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane
187 fc_id, status = parse_flowcell_id(flowcell_id)
188 d = get_flowcell_result_dict(fc_id)
191 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
194 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
196 erd = d[cnm]['eland_results']
200 return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
205 fi = opener.autoopen(filepath, 'r')
208 name, description = makebed.make_description( fc_id, lane )
210 bedgen = makebed.make_bed_from_eland_generator(fi, name, description)
213 return HttpResponse(bedgen)
215 return HttpResponse(bedgen, mimetype="application/x-bedfile")
218 def _summary_stats(flowcell_id, lane_id):
220 Return the summary statistics for a given flowcell, lane, and end.
222 fc_id, status = parse_flowcell_id(flowcell_id)
223 fc_result_dict = get_flowcell_result_dict(fc_id)
228 if fc_result_dict is None:
229 err_list.append('Results for Flowcell %s not found.' % (fc_id))
230 return (summary_list, err_list)
232 for cycle_width in fc_result_dict:
233 xmlpath = fc_result_dict[cycle_width]['run_xml']
236 err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cycle_width))
239 run = load_pipeline_run_xml(xmlpath)
240 gerald_summary = run.gerald.summary.lane_results
241 for end in range(len(gerald_summary)):
242 end_summary = run.gerald.eland_results.results[end]
243 if end_summary.has_key(lane_id):
244 eland_summary = run.gerald.eland_results.results[end][lane_id]
246 eland_summary = ResultLane(lane_id=lane_id, end=end)
247 # add information to lane_summary
248 eland_summary.flowcell_id = flowcell_id
249 eland_summary.clusters = gerald_summary[end][lane_id].cluster
250 eland_summary.cycle_width = cycle_width
251 if hasattr(eland_summary, 'genome_map'):
252 eland_summary.summarized_reads = runfolder.summarize_mapped_reads(
253 eland_summary.genome_map,
254 eland_summary.mapped_reads)
256 # grab some more information out of the flowcell db
257 flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
258 pm_field = 'lane_%d_pM' % (lane_id)
259 eland_summary.successful_pm = getattr(flowcell, pm_field)
261 summary_list.append(eland_summary)
263 #except Exception, e:
264 # summary_list.append("Summary report needs to be updated.")
265 # logging.error("Exception: " + str(e))
267 return (summary_list, err_list)
269 def _summary_stats_old(flowcell_id, lane):
271 return a dictionary of summary stats for a given flowcell_id & lane.
273 fc_id, status = parse_flowcell_id(flowcell_id)
274 fc_result_dict = get_flowcell_result_dict(fc_id)
280 if fc_result_dict is None:
281 err_list.append('Results for Flowcell %s not found.' % (fc_id))
282 return (dict_list, err_list, summary_list)
284 for cnm in fc_result_dict:
286 xmlpath = fc_result_dict[cnm]['run_xml']
289 err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cnm))
292 tree = ElementTree.parse(xmlpath).getroot()
293 results = runfolder.PipelineRun(pathname='', xml=tree)
295 lane_report = runfolder.summarize_lane(results.gerald, lane)
296 summary_list.append(os.linesep.join(lane_report))
298 summary_list.append("Summary report needs to be updated.")
299 logging.error("Exception: " + str(e))
301 print "----------------------------------"
302 print "-- DOES NOT SUPPORT PAIRED END ---"
303 print "----------------------------------"
304 lane_results = results.gerald.summary[0][lane]
309 d['average_alignment_score'] = lrs.average_alignment_score
310 d['average_first_cycle_intensity'] = lrs.average_first_cycle_intensity
311 d['cluster'] = lrs.cluster
313 d['flowcell'] = flowcell_id
315 d['percent_error_rate'] = lrs.percent_error_rate
316 d['percent_intensity_after_20_cycles'] = lrs.percent_intensity_after_20_cycles
317 d['percent_pass_filter_align'] = lrs.percent_pass_filter_align
318 d['percent_pass_filter_clusters'] = lrs.percent_pass_filter_clusters
320 #FIXME: function finished, but need to take advantage of
321 # may need to take in a list of lanes so we only have to
322 # load the xml file once per flowcell rather than once
326 return (dict_list, err_list, summary_list)
329 def get_eland_result_type(pathname):
331 Guess the eland result file type from the filename
333 path, filename = os.path.split(pathname)
334 if 'extended' in filename:
336 elif 'multi' in filename:
338 elif 'result' in filename:
343 def _make_eland_results(flowcell_id, lane, interesting_flowcells):
344 fc_id, status = parse_flowcell_id(flowcell_id)
345 cur_fc = interesting_flowcells.get(fc_id, None)
349 flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
350 # Loop throw storage devices if a result has been archived
352 if cur_fc is not None:
353 for lts in flowcell.longtermstorage_set.all():
354 for sd in lts.storage_devices.all():
355 # Use barcode_id if it exists
356 if sd.barcode_id is not None and sd.barcode_id != '':
357 storage_id_list.append(sd.barcode_id)
360 storage_id_list.append(sd.uuid)
362 # Formatting for template use
363 if len(storage_id_list) == 0:
366 storage_ids = ', '.join([ '<a href="/inventory/%s/">%s</a>' % (s,s) for s in storage_id_list ])
369 for cycle in cur_fc.keys():
370 result_path = cur_fc[cycle]['eland_results'].get(lane, None)
371 result_link = make_result_link(fc_id, cycle, lane, result_path)
372 results.append({'flowcell_id': fc_id,
375 'summary_url': make_summary_url(flowcell_id, cycle),
376 'result_url': result_link[0],
377 'result_label': result_link[1],
378 'bed_url': result_link[2],
379 'storage_ids': storage_ids
383 def make_summary_url(flowcell_id, cycle_name):
384 url = '/results/%s/%s/summary/' % (flowcell_id, cycle_name)
387 def make_result_link(flowcell_id, cycle_name, lane, eland_result_path):
388 if eland_result_path is None:
391 result_type = get_eland_result_type(eland_result_path)
392 result_url = '/results/%s/%s/eland_result/%s' % (flowcell_id, cycle_name, lane)
393 result_label = 'eland %s' % (result_type,)
395 if result_type == 'result':
396 bed_url_pattern = '/results/%s/%s/bedfile/%s'
397 bed_url = bed_url_pattern % (flowcell_id, cycle_name, lane)
399 return (result_url, result_label, bed_url)
401 def _files(flowcell_id, lane):
403 Sets up available files for download
407 flowcell_id, id = parse_flowcell_id(flowcell_id)
408 d = get_flowcell_result_dict(flowcell_id)
415 # c_name == 'CN-M' (i.e. C1-33)
418 if d[c_name]['summary'] is not None:
419 output.append('<a href="/results/%s/%s/summary/">summary(%s)</a>' \
420 % (flowcell_id, c_name, c_name))
422 erd = d[c_name]['eland_results']
424 result_type = get_eland_result_type(erd[lane])
425 result_url_pattern = '<a href="/results/%s/%s/eland_result/%s">eland %s(%s)</a>'
426 output.append(result_url_pattern % (flowcell_id, c_name, lane, result_type, c_name))
427 if result_type == 'result':
428 bed_url_pattern = '<a href="/results/%s/%s/bedfile/%s">bedfile(%s)</a>'
429 output.append(bed_url_pattern % (flowcell_id, c_name, lane, c_name))
434 return '(' + '|'.join(output) + ')'
436 def library_id_to_admin_url(request, lib_id):
437 lib = Library.objects.get(library_id=lib_id)
438 return HttpResponseRedirect('/admin/samples/library/%s' % (lib.id,))
441 def user_profile(request):
443 Information about the user
446 'page_name': 'User Profile',
448 #'bcmagic': BarcodeMagicForm(),
449 #'select': 'settings',
451 context.update(SAMPLES_CONTEXT_DEFAULTS)
452 return render_to_response('registration/profile.html', context,
453 context_instance=RequestContext(request))