1 # Create your views here.
8 import simplejson as json
10 from htsworkflow.frontend.auth import require_api_key
11 from htsworkflow.frontend.experiments.models import FlowCell
12 from htsworkflow.frontend.samples.changelist import ChangeList
13 from htsworkflow.frontend.samples.models import Library
14 from htsworkflow.frontend.samples.results import get_flowcell_result_dict, parse_flowcell_id
15 from htsworkflow.frontend.bcmagic.forms import BarcodeMagicForm
16 from htsworkflow.pipelines.runfolder import load_pipeline_run_xml
17 from htsworkflow.pipelines import runfolder
18 from htsworkflow.pipelines.eland import ResultLane
19 from htsworkflow.frontend import settings
20 from htsworkflow.util import makebed
21 from htsworkflow.util import opener
23 from django.core.exceptions import ObjectDoesNotExist
24 from django.http import HttpResponse, HttpResponseRedirect, Http404
25 from django.shortcuts import render_to_response
26 from django.template import RequestContext
27 from django.template.loader import get_template
28 from django.contrib.auth.decorators import login_required
30 LANE_LIST = [1,2,3,4,5,6,7,8]
31 SAMPLES_CONTEXT_DEFAULTS = {
32 'app_name': 'Flowcell/Library Tracker',
33 'bcmagic': BarcodeMagicForm()
36 def create_library_context(cl):
38 Create a list of libraries that includes how many lanes were run
41 #for lib in library_items.object_list:
42 for lib in cl.result_list:
44 summary['library_id'] = lib.id
45 summary['library_name'] = lib.library_name
46 summary['species_name' ] = lib.library_species.scientific_name
47 if lib.amplified_from_sample is not None:
48 summary['amplified_from'] = lib.amplified_from_sample.id
50 summary['amplified_from'] = ''
52 #for lane_id in LANE_LIST:
53 # lane = getattr(lib, 'lane_%d_library' % (lane_id,))
54 # lanes_run += len( lane.all() )
55 lanes_run = lib.lane_set.count()
56 summary['lanes_run'] = lanes_run
57 summary['is_archived'] = lib.is_archived()
58 records.append(summary)
59 cl.result_count = unicode(cl.paginator._count) + u" libraries"
60 return {'library_list': records }
64 fcl = ChangeList(request, Library,
65 list_filter=['affiliations', 'library_species'],
66 search_fields=['id', 'library_name', 'amplified_from_sample__id'],
68 queryset=Library.objects.filter(hidden__exact=0)
71 context = { 'cl': fcl, 'title': 'Library Index'}
72 context.update(create_library_context(fcl))
73 t = get_template('samples/library_index.html')
74 c = RequestContext(request, context)
77 'page_name': 'Library Index',
78 'east_region_config_div': 'changelist-filter',
81 app_context.update(SAMPLES_CONTEXT_DEFAULTS)
83 app_t = get_template('flowcell_libraries_app.html')
84 app_c = RequestContext(request, app_context)
85 return HttpResponse( app_t.render(app_c) )
87 def library_to_flowcells(request, lib_id):
89 Display information about all the flowcells a library has been run on.
93 lib = Library.objects.get(id=lib_id)
95 return HttpResponse("Library %s does not exist" % (lib_id))
98 interesting_flowcells = {} # aka flowcells we're looking at
99 #for lane in LANE_LIST:
100 for lane in lib.lane_set.all():
101 #lane_library = getattr(lib, 'lane_%d_library' % (lane,))
102 #for fc in lane_library.all():
104 flowcell_id, id = parse_flowcell_id(fc.flowcell_id)
105 if flowcell_id not in interesting_flowcells:
106 interesting_flowcells[flowcell_id] = get_flowcell_result_dict(flowcell_id)
107 flowcell_list.append((fc.flowcell_id, lane.lane_number))
111 lane_summary_list = []
113 for fc, lane_number in flowcell_list:
114 lane_summary, err_list = _summary_stats(fc, lane_number)
116 eland_results.extend(_make_eland_results(fc, lane_number, interesting_flowcells))
117 lane_summary_list.extend(lane_summary)
120 'page_name': 'Library Details',
122 'eland_results': eland_results,
123 'lane_summary_list': lane_summary_list,
125 context.update(SAMPLES_CONTEXT_DEFAULTS)
127 return render_to_response(
128 'samples/library_detail.html',
130 context_instance = RequestContext(request))
132 def summaryhtm_fc_cnm(request, flowcell_id, cnm):
134 returns a Summary.htm file if it exists.
136 fc_id, status = parse_flowcell_id(flowcell_id)
137 d = get_flowcell_result_dict(fc_id)
140 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
143 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
145 summary_filepath = d[cnm]['summary']
147 if summary_filepath is None:
148 return HttpResponse('<b>Summary.htm for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
150 f = open(summary_filepath, 'r')
152 return HttpResponse(f)
155 def result_fc_cnm_eland_lane(request, flowcell_id, cnm, lane):
157 returns an eland_file upon calling.
159 fc_id, status = parse_flowcell_id(flowcell_id)
160 d = get_flowcell_result_dict(fc_id)
163 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
166 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
168 erd = d[cnm]['eland_results']
172 return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
176 #f = opener.autoopen(filepath, 'r')
177 # return HttpResponse(f, mimetype="application/x-elandresult")
179 f = open(filepath, 'r')
180 return HttpResponse(f, mimetype='application/x-bzip2')
184 def bedfile_fc_cnm_eland_lane_ucsc(request, fc_id, cnm, lane):
186 returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane (ucsc compatible)
188 return bedfile_fc_cnm_eland_lane(request, fc_id, cnm, lane, ucsc_compatible=True)
191 def bedfile_fc_cnm_eland_lane(request, flowcell_id, cnm, lane, ucsc_compatible=False):
193 returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane
195 fc_id, status = parse_flowcell_id(flowcell_id)
196 d = get_flowcell_result_dict(fc_id)
199 return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
202 return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
204 erd = d[cnm]['eland_results']
208 return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
213 fi = opener.autoopen(filepath, 'r')
216 name, description = makebed.make_description( fc_id, lane )
218 bedgen = makebed.make_bed_from_eland_generator(fi, name, description)
221 return HttpResponse(bedgen)
223 return HttpResponse(bedgen, mimetype="application/x-bedfile")
226 def _summary_stats(flowcell_id, lane_id):
228 Return the summary statistics for a given flowcell, lane, and end.
230 fc_id, status = parse_flowcell_id(flowcell_id)
231 fc_result_dict = get_flowcell_result_dict(fc_id)
236 if fc_result_dict is None:
237 err_list.append('Results for Flowcell %s not found.' % (fc_id))
238 return (summary_list, err_list)
240 for cycle_width in fc_result_dict:
241 xmlpath = fc_result_dict[cycle_width]['run_xml']
244 err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cycle_width))
247 run = load_pipeline_run_xml(xmlpath)
248 gerald_summary = run.gerald.summary.lane_results
249 for end in range(len(gerald_summary)):
250 end_summary = run.gerald.eland_results.results[end]
251 if end_summary.has_key(lane_id):
252 eland_summary = run.gerald.eland_results.results[end][lane_id]
254 eland_summary = ResultLane(lane_id=lane_id, end=end)
255 # add information to lane_summary
256 eland_summary.flowcell_id = flowcell_id
257 if len(gerald_summary) > end and gerald_summary[end].has_key(lane_id):
258 eland_summary.clusters = gerald_summary[end][lane_id].cluster
260 eland_summary.clusters = None
261 eland_summary.cycle_width = cycle_width
262 if hasattr(eland_summary, 'genome_map'):
263 eland_summary.summarized_reads = runfolder.summarize_mapped_reads(
264 eland_summary.genome_map,
265 eland_summary.mapped_reads)
267 # grab some more information out of the flowcell db
268 flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
269 #pm_field = 'lane_%d_pM' % (lane_id)
270 lane_obj = flowcell.lane_set.get(lane_number=lane_id)
271 eland_summary.successful_pm = lane_obj.pM
273 summary_list.append(eland_summary)
275 #except Exception, e:
276 # summary_list.append("Summary report needs to be updated.")
277 # logging.error("Exception: " + str(e))
279 return (summary_list, err_list)
281 def _summary_stats_old(flowcell_id, lane):
283 return a dictionary of summary stats for a given flowcell_id & lane.
285 fc_id, status = parse_flowcell_id(flowcell_id)
286 fc_result_dict = get_flowcell_result_dict(fc_id)
292 if fc_result_dict is None:
293 err_list.append('Results for Flowcell %s not found.' % (fc_id))
294 return (dict_list, err_list, summary_list)
296 for cnm in fc_result_dict:
298 xmlpath = fc_result_dict[cnm]['run_xml']
301 err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cnm))
304 tree = ElementTree.parse(xmlpath).getroot()
305 results = runfolder.PipelineRun(pathname='', xml=tree)
307 lane_report = runfolder.summarize_lane(results.gerald, lane)
308 summary_list.append(os.linesep.join(lane_report))
310 summary_list.append("Summary report needs to be updated.")
311 logging.error("Exception: " + str(e))
313 print "----------------------------------"
314 print "-- DOES NOT SUPPORT PAIRED END ---"
315 print "----------------------------------"
316 lane_results = results.gerald.summary[0][lane]
321 d['average_alignment_score'] = lrs.average_alignment_score
322 d['average_first_cycle_intensity'] = lrs.average_first_cycle_intensity
323 d['cluster'] = lrs.cluster
325 d['flowcell'] = flowcell_id
327 d['percent_error_rate'] = lrs.percent_error_rate
328 d['percent_intensity_after_20_cycles'] = lrs.percent_intensity_after_20_cycles
329 d['percent_pass_filter_align'] = lrs.percent_pass_filter_align
330 d['percent_pass_filter_clusters'] = lrs.percent_pass_filter_clusters
332 #FIXME: function finished, but need to take advantage of
333 # may need to take in a list of lanes so we only have to
334 # load the xml file once per flowcell rather than once
338 return (dict_list, err_list, summary_list)
341 def get_eland_result_type(pathname):
343 Guess the eland result file type from the filename
345 path, filename = os.path.split(pathname)
346 if 'extended' in filename:
348 elif 'multi' in filename:
350 elif 'result' in filename:
355 def _make_eland_results(flowcell_id, lane, interesting_flowcells):
356 fc_id, status = parse_flowcell_id(flowcell_id)
357 cur_fc = interesting_flowcells.get(fc_id, None)
361 flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
362 # Loop throw storage devices if a result has been archived
364 if cur_fc is not None:
365 for lts in flowcell.longtermstorage_set.all():
366 for sd in lts.storage_devices.all():
367 # Use barcode_id if it exists
368 if sd.barcode_id is not None and sd.barcode_id != '':
369 storage_id_list.append(sd.barcode_id)
372 storage_id_list.append(sd.uuid)
374 # Formatting for template use
375 if len(storage_id_list) == 0:
378 storage_ids = ', '.join([ '<a href="/inventory/%s/">%s</a>' % (s,s) for s in storage_id_list ])
381 for cycle in cur_fc.keys():
382 result_path = cur_fc[cycle]['eland_results'].get(lane, None)
383 result_link = make_result_link(fc_id, cycle, lane, result_path)
384 results.append({'flowcell_id': fc_id,
387 'summary_url': make_summary_url(flowcell_id, cycle),
388 'result_url': result_link[0],
389 'result_label': result_link[1],
390 'bed_url': result_link[2],
391 'storage_ids': storage_ids
395 def make_summary_url(flowcell_id, cycle_name):
396 url = '/results/%s/%s/summary/' % (flowcell_id, cycle_name)
399 def make_result_link(flowcell_id, cycle_name, lane, eland_result_path):
400 if eland_result_path is None:
403 result_type = get_eland_result_type(eland_result_path)
404 result_url = '/results/%s/%s/eland_result/%s' % (flowcell_id, cycle_name, lane)
405 result_label = 'eland %s' % (result_type,)
407 if result_type == 'result':
408 bed_url_pattern = '/results/%s/%s/bedfile/%s'
409 bed_url = bed_url_pattern % (flowcell_id, cycle_name, lane)
411 return (result_url, result_label, bed_url)
413 def _files(flowcell_id, lane):
415 Sets up available files for download
419 flowcell_id, id = parse_flowcell_id(flowcell_id)
420 d = get_flowcell_result_dict(flowcell_id)
427 # c_name == 'CN-M' (i.e. C1-33)
430 if d[c_name]['summary'] is not None:
431 output.append('<a href="/results/%s/%s/summary/">summary(%s)</a>' \
432 % (flowcell_id, c_name, c_name))
434 erd = d[c_name]['eland_results']
436 result_type = get_eland_result_type(erd[lane])
437 result_url_pattern = '<a href="/results/%s/%s/eland_result/%s">eland %s(%s)</a>'
438 output.append(result_url_pattern % (flowcell_id, c_name, lane, result_type, c_name))
439 if result_type == 'result':
440 bed_url_pattern = '<a href="/results/%s/%s/bedfile/%s">bedfile(%s)</a>'
441 output.append(bed_url_pattern % (flowcell_id, c_name, lane, c_name))
446 return '(' + '|'.join(output) + ')'
448 def library_id_to_admin_url(request, lib_id):
449 lib = Library.objects.get(id=lib_id)
450 return HttpResponseRedirect('/admin/samples/library/%s' % (lib.id,))
452 def library_dict(library_id):
454 Given a library id construct a dictionary containing important information
455 return None if nothing was found
458 lib = Library.objects.get(id = library_id)
459 except Library.DoesNotExist, e:
464 # 'aligned_reads': lib.aligned_reads,
465 #'amplified_into_sample': lib.amplified_into_sample, # into is a colleciton...
466 #'amplified_from_sample_id': lib.amplified_from_sample,
467 #'antibody_name': lib.antibody_name(), # we have no antibodies.
468 'antibody_id': lib.antibody_id,
469 'avg_lib_size': lib.avg_lib_size,
470 'cell_line': lib.cell_line.cellline_name,
471 'cell_line_id': lib.cell_line_id,
472 'experiment_type': lib.experiment_type.name,
473 'experiment_type_id': lib.experiment_type_id,
475 'library_id': lib.id,
476 'library_name': lib.library_name,
477 'library_species': lib.library_species.scientific_name,
478 'library_species_id': lib.library_species_id,
479 #'library_type': lib.library_type.name,
480 'library_type_id': lib.library_type_id,
481 'made_for': lib.made_for,
482 'made_by': lib.made_by,
484 'replicate': lib.replicate,
485 'stopping_point': lib.stopping_point,
486 'successful_pM': lib.successful_pM,
487 'undiluted_concentration': unicode(lib.undiluted_concentration)
489 if lib.library_type_id is None:
490 info['library_type'] = None
492 info['library_type'] = lib.library_type.name
495 def library_json(request, library_id):
497 Return a json formatted library dictionary
499 require_api_key(request)
500 # what validation should we do on library_id?
502 lib = library_dict(library_id)
506 lib_json = json.dumps(lib)
507 return HttpResponse(lib_json, mimetype='application/json')
509 def species_json(request, species_id):
511 Return information about a species.
516 def user_profile(request):
518 Information about the user
521 'page_name': 'User Profile',
523 #'bcmagic': BarcodeMagicForm(),
524 #'select': 'settings',
526 context.update(SAMPLES_CONTEXT_DEFAULTS)
527 return render_to_response('registration/profile.html', context,
528 context_instance=RequestContext(request))