Add pages to show information about a particular flowcell.
[htsworkflow.git] / htsworkflow / frontend / experiments / models.py
1 import logging
2
3 from django.core.exceptions import ObjectDoesNotExist
4 from django.core import urlresolvers
5 from django.db import models
6
7 from htsworkflow.frontend.samples.models import *
8 from htsworkflow.frontend.settings import options
9
10 class ClusterStation(models.Model):
11   name = models.CharField(max_length=50, unique=True)
12
13   def __unicode__(self):
14     return unicode(self.name)
15
16 class Sequencer(models.Model):
17   name = models.CharField(max_length=50, unique=True)
18
19   def __unicode__(self):
20     return unicode(self.name)
21
22 default_pM = 5
23 try:
24   default_pM = int(options.get('frontend', 'default_pm'))
25 except ValueError,e:
26   logging.error("invalid value for frontend.default_pm")
27
28 class FlowCell(models.Model):
29   
30   flowcell_id = models.CharField(max_length=20, unique=True, db_index=True)
31   run_date = models.DateTimeField()
32   advanced_run = models.BooleanField(default=False)
33   paired_end = models.BooleanField(default=False)
34   read_length = models.IntegerField(default=32) #Stanford is currenlty 25
35   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)
36
37   cluster_station = models.ForeignKey(ClusterStation, default=3)
38   sequencer = models.ForeignKey(Sequencer, default=1)
39   
40   notes = models.TextField(blank=True)
41
42   def __unicode__(self):
43       return unicode(self.flowcell_id) 
44
45   def Create_LOG(self):
46     str = ''
47     str +='<a target=_balnk href="/experiments/'+self.flowcell_id+'" title="Create XLS like sheet for this Flowcell ..." ">Create LOG</a>'
48     try:
49       t = DataRun.objects.get(fcid=self.id)
50       str +='<br/><a target=_self href="/admin/experiments/datarun/?q='+self.flowcell_id+'" title="Check Data Runs ..." ">DataRun ..</a>'
51     except ObjectDoesNotExist:
52       str += '<br/><span style="color:red">not sequenced</span>'
53     return str
54   Create_LOG.allow_tags = True 
55
56   def Lanes(self):
57     library_url = '/admin/samples/library/%s' 
58     html = ['<table>']
59     #for i in range(1,9):
60     for lane in self.lane_set.all():
61         cluster_estimate = lane.cluster_estimate
62         if cluster_estimate is not None:
63             cluster_estimate = "%s k" % ((int(cluster_estimate)/1000), )
64         else:
65             cluster_estimate = 'None'
66         library_id = lane.library_id
67         library = lane.library
68         element = '<tr><td>%d</td><td><a href="%s">%s</a></td><td>%s</td></tr>'
69         expanded_library_url = library_url %(library_id,)
70         html.append(element % (lane.lane_number, expanded_library_url, library, cluster_estimate))
71     html.append('</table>')
72     return "\n".join(html)
73   Lanes.allow_tags = True
74
75   class Meta:
76     ordering = ["-run_date"]
77
78   def get_admin_url(self):
79     # that's the django way... except it didn't work
80     #return urlresolvers.reverse('admin_experiments_FlowCell_change', args=(self.id,))
81     return '/admin/experiments/flowcell/%s/' % (self.id,)
82
83   def flowcell_type(self):
84     """
85     Convert our boolean 'is paired' flag to a name
86     """
87     if self.paired_end:
88       return u"Paired"
89     else:
90       return u"Single"
91
92   @models.permalink
93   def get_absolute_url(self):
94       return ('htsworkflow.frontend.experiments.views.flowcell_detail',
95               [str(self.flowcell_id)])
96     
97 ### -----------------------
98 class DataRun(models.Model):
99   ConfTemplate = "CONFIG PARAMS WILL BE GENERATED BY THE PIPELINE SCRIPT.\nYOU'LL BE ABLE TO EDIT AFTER IF NEEDED."
100   run_folder = models.CharField(max_length=50,unique=True, db_index=True)
101   fcid = models.ForeignKey(FlowCell,verbose_name="Flowcell Id")
102   config_params = models.TextField(default=ConfTemplate)
103   run_start_time = models.DateTimeField()
104   RUN_STATUS_CHOICES = (
105       (0, 'Sequencer running'), ##Solexa Data Pipeline Not Yet Started'),
106       (1, 'Data Pipeline Started'),
107       (2, 'Data Pipeline Interrupted'),
108       (3, 'Data Pipeline Finished'),
109       (4, 'CollectReads Started'),
110       (5, 'CollectReads Finished'),
111       (6, 'QC Finished'),
112       (7, 'DONE'),
113     )
114   run_status = models.IntegerField(choices=RUN_STATUS_CHOICES, default=0)
115   run_note = models.TextField(blank=True)
116
117
118   def main_status(self):
119     str = '<div'
120     if self.run_status >= 5:
121       str += ' style="color:green">'
122       str += '<b>'+self.RUN_STATUS_CHOICES[self.run_status][1]+'</b>'
123       str += '<br/><br/>' #<span style="color:red;font-size:80%;">New!</span>'
124       str +='<br/><a target=_balnk href="'+settings.TASKS_PROJS_SERVER+'/Flowcells/'+self.fcid.flowcell_id+'/'+self.fcid.flowcell_id+'_QC_Summary.html" title="View QC Summaries of this run ..." ">View QC Page</a>'
125     else:
126       str += '>'+self.RUN_STATUS_CHOICES[self.run_status][1]
127
128     str += '</div>'
129     return str
130   main_status.allow_tags = True
131
132   main_status.allow_tags = True
133   
134   def Flowcell_Info(self):
135     str = '<b>'+self.fcid.__str__()+'</b>'
136     str += '  (c: '+self.fcid.cluster_mac_id+',  s: '+self.fcid.seq_mac_id+')'
137     str += '<div style="margin-top:5px;">'    
138     str +='<a title="View Lane List here ..."  onClick="el = document.getElementById(\'LanesOf'+self.fcid.__str__()+'\');if(el) (el.style.display==\'none\'?el.style.display=\'block\':el.style.display=\'none\')" style="cursor:pointer;color: #5b80b2;">View/hide lanes</a>'
139     str += '<div id="LanesOf'+self.fcid.__str__()+'" style="display:block;border:solid #cccccc 1px;width:350px">'
140     LanesList = '1: '+self.fcid.lane_1_library.__str__()+' ('+self.fcid.lane_1_library.library_species.use_genome_build+')<br/>2: '+self.fcid.lane_2_library.__str__()+' ('+self.fcid.lane_2_library.library_species.use_genome_build+')<br/>3: '+self.fcid.lane_3_library.__str__()+' ('+self.fcid.lane_3_library.library_species.use_genome_build+')<br/>4: '+self.fcid.lane_4_library.__str__()+' ('+self.fcid.lane_4_library.library_species.use_genome_build+')<br/>5: '+self.fcid.lane_5_library.__str__()+' ('+self.fcid.lane_5_library.library_species.use_genome_build+')<br/>6: '+self.fcid.lane_6_library.__str__()+' ('+self.fcid.lane_6_library.library_species.use_genome_build+')<br/>7: '+self.fcid.lane_7_library.__str__()+' ('+self.fcid.lane_7_library.library_species.use_genome_build+')<br/>8: '+self.fcid.lane_8_library.__str__()+' ('+self.fcid.lane_8_library.library_species.use_genome_build+')'
141     str += LanesList ## self.fcid.Lanes()
142     str += '</div>'
143     str += '<div><a title="open Flowcell record" href="/admin/exp_track/flowcell/'+self.fcid.id.__str__()+'/" target=_self>Edit Flowcell record</a>'
144     #str += '<span style="color:red;font-size:80%;margin-left:15px;margin-right:3px">New!</span>'
145     str +='<a style="margin-left:15px;" target=_balnk href="/exp_track/'+self.fcid.flowcell_id+'" title="View XLS like sheet for this Flowcell LOG ..." ">GA LOG Page</a>'
146     str += '</div>'
147     str += '</div>'    
148     return str
149   Flowcell_Info.allow_tags = True
150
151 LANE_STATUS_CODES = [(0, 'Failed'),
152                     (1, 'Marginal'),
153                     (2, 'Good'),]
154 LANE_STATUS_MAP = dict((int(k),v) for k,v in LANE_STATUS_CODES )
155 LANE_STATUS_MAP[None] = "Unknown"
156
157 class Lane(models.Model):
158   flowcell = models.ForeignKey(FlowCell)
159   lane_number = models.IntegerField(choices=[(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8)])
160   library = models.ForeignKey(Library)
161   pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
162   cluster_estimate = models.IntegerField(blank=True, null=True)                                       
163   status = models.IntegerField(choices=LANE_STATUS_CODES, null=True, blank=True) 
164   comment = models.TextField(null=True, blank=True)
165
166   @models.permalink
167   def get_absolute_url(self):
168        return ('htsworkflow.frontend.experiments.views.flowcell_lane_detail',
169                [str(self.flowcell.flowcell_id), str(self.lane_number)])