Change flowcell admin index page to include a formatted cluster estimate
[htsworkflow.git] / htsworkflow / frontend / experiments / models.py
1 from django.db import models
2 from htsworkflow.frontend.samples.models import *
3 from htsworkflow.frontend.settings import options
4 from django.core.exceptions import ObjectDoesNotExist
5 import logging
6
7 class ClusterStation(models.Model):
8   name = models.CharField(max_length=50, unique=True)
9
10   def __unicode__(self):
11     return unicode(self.name)
12
13 class Sequencer(models.Model):
14   name = models.CharField(max_length=50, unique=True)
15
16   def __unicode__(self):
17     return unicode(self.name)
18
19 default_pM = 5
20 try:
21   default_pM = int(options.get('frontend', 'default_pm'))
22 except ValueError,e:
23   logging.error("invalid value for frontend.default_pm")
24
25 class FlowCell(models.Model):
26   
27   flowcell_id = models.CharField(max_length=20, unique=True, db_index=True)
28   run_date = models.DateTimeField()
29   advanced_run = models.BooleanField(default=False)
30   paired_end = models.BooleanField(default=False)
31   read_length = models.IntegerField(default=32) #Stanford is currenlty 25
32   
33   lane_1_library = models.ForeignKey(Library, related_name="lane_1_library")
34   lane_2_library = models.ForeignKey(Library, related_name="lane_2_library")
35   lane_3_library = models.ForeignKey(Library, related_name="lane_3_library")
36   lane_4_library = models.ForeignKey(Library, related_name="lane_4_library")
37   lane_5_library = models.ForeignKey(Library, related_name="lane_5_library")
38   lane_6_library = models.ForeignKey(Library, related_name="lane_6_library")
39   lane_7_library = models.ForeignKey(Library, related_name="lane_7_library")
40   lane_8_library = models.ForeignKey(Library, related_name="lane_8_library")
41
42   lane_1_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
43   lane_2_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
44   lane_3_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
45   lane_4_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
46   lane_5_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
47   lane_6_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
48   lane_7_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
49   lane_8_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
50   
51   lane_1_cluster_estimate = models.IntegerField(blank=True, null=True)
52   lane_2_cluster_estimate = models.IntegerField(blank=True, null=True)
53   lane_3_cluster_estimate = models.IntegerField(blank=True, null=True)
54   lane_4_cluster_estimate = models.IntegerField(blank=True, null=True)
55   lane_5_cluster_estimate = models.IntegerField(blank=True, null=True)
56   lane_6_cluster_estimate = models.IntegerField(blank=True, null=True)
57   lane_7_cluster_estimate = models.IntegerField(blank=True, null=True)
58   lane_8_cluster_estimate = models.IntegerField(blank=True, null=True)
59  
60   # lane_1_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_1_primer")
61   # lane_2_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_2_primer")
62   # lane_3_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_3_primer")
63   # lane_4_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_4_primer")
64   # lane_5_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_5_primer")
65   # lane_6_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_6_primer")
66   # lane_7_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_7_primer")
67   # lane_8_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_8_primer")
68
69   #cluster_mac_id = models.CharField(max_length=50, choices=CLUSTER_MAC, default='BitBit')
70   #seq_mac_id = models.CharField(max_length=50, choices=SEQ_MAC, verbose_name = 'Sequencer', default='Britney')
71   cluster_station = models.ForeignKey(ClusterStation)
72   sequencer = models.ForeignKey(Sequencer)
73   
74   notes = models.TextField(blank=True)
75
76   def __unicode__(self):
77       return unicode(self.flowcell_id) 
78
79   def Create_LOG(self):
80     str = ''
81     str +='<a target=_balnk href="/experiments/'+self.flowcell_id+'" title="Create XLS like sheet for this Flowcell ..." ">Create LOG</a>'
82     try:
83       t = DataRun.objects.get(fcid=self.id)
84       str +='<br/><a target=_self href="/admin/experiments/datarun/?q='+self.flowcell_id+'" title="Check Data Runs ..." ">DataRun ..</a>'
85     except ObjectDoesNotExist:
86       str += '<br/><span style="color:red">not sequenced</span>'
87     return str
88   Create_LOG.allow_tags = True 
89
90   def Lanes(self):
91     library_url = '/admin/samples/library/%s' 
92     html = ['<table>']
93     for i in range(1,9):
94         cluster_estimate = getattr(self, 'lane_%d_cluster_estimate' % (i,))
95         if cluster_estimate is not None:
96             cluster_estimate = "%s k" % ((int(cluster_estimate)/1000), )
97         else:
98             cluster_estimate = 'None'
99         library_id = getattr(self, 'lane_%d_library_id' % (i,))
100         library = getattr(self, 'lane_%d_library' % i)
101         element = '<tr><td>%d</td><td><a href="%s">%s</a></td><td>%s</td></tr>'
102         expanded_library_url = library_url %(library_id,)
103         html.append(element % (i, expanded_library_url, library, cluster_estimate))
104     html.append('</table>')
105     return "\n".join(html)
106   Lanes.allow_tags = True
107
108   class Meta:
109     ordering = ["-run_date"]
110   
111 ### -----------------------
112 class DataRun(models.Model):
113   ConfTemplate = "CONFIG PARAMS WILL BE GENERATED BY THE PIPELINE SCRIPT.\nYOU'LL BE ABLE TO EDIT AFTER IF NEEDED."
114   run_folder = models.CharField(max_length=50,unique=True, db_index=True)
115   fcid = models.ForeignKey(FlowCell,verbose_name="Flowcell Id")
116   config_params = models.TextField(default=ConfTemplate)
117   run_start_time = models.DateTimeField()
118   RUN_STATUS_CHOICES = (
119       (0, 'Sequencer running'), ##Solexa Data Pipeline Not Yet Started'),
120       (1, 'Data Pipeline Started'),
121       (2, 'Data Pipeline Interrupted'),
122       (3, 'Data Pipeline Finished'),
123       (4, 'CollectReads Started'),
124       (5, 'CollectReads Finished'),
125       (6, 'QC Finished'),
126       (7, 'DONE'),
127     )
128   run_status = models.IntegerField(choices=RUN_STATUS_CHOICES, default=0)
129   run_note = models.TextField(blank=True)
130
131
132   def main_status(self):
133     str = '<div'
134     if self.run_status >= 5:
135       str += ' style="color:green">'
136       str += '<b>'+self.RUN_STATUS_CHOICES[self.run_status][1]+'</b>'
137       str += '<br/><br/>' #<span style="color:red;font-size:80%;">New!</span>'
138       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>'
139     else:
140       str += '>'+self.RUN_STATUS_CHOICES[self.run_status][1]
141
142     str += '</div>'
143     return str
144   main_status.allow_tags = True
145
146   main_status.allow_tags = True
147   
148   def Flowcell_Info(self):
149     str = '<b>'+self.fcid.__str__()+'</b>'
150     str += '  (c: '+self.fcid.cluster_mac_id+',  s: '+self.fcid.seq_mac_id+')'
151     str += '<div style="margin-top:5px;">'    
152     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>'
153     str += '<div id="LanesOf'+self.fcid.__str__()+'" style="display:block;border:solid #cccccc 1px;width:350px">'
154     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+')'
155     str += LanesList ## self.fcid.Lanes()
156     str += '</div>'
157     str += '<div><a title="open Flowcell record" href="/admin/exp_track/flowcell/'+self.fcid.id.__str__()+'/" target=_self>Edit Flowcell record</a>'
158     #str += '<span style="color:red;font-size:80%;margin-left:15px;margin-right:3px">New!</span>'
159     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>'
160     str += '</div>'
161     str += '</div>'    
162     return str
163   Flowcell_Info.allow_tags = True