added: display reads count per Lane, besides total per Flowcell
[htsworkflow.git] / htswfrontend / htswfrontend / exp_track / models.py
1 from django.db import models
2 from htswfrontend.fctracker.models import *
3 from django.core.exceptions import ObjectDoesNotExist
4
5 class FlowCell(models.Model):
6   
7   flowcell_id = models.CharField(max_length=20, unique=True, db_index=True, core=True)
8   run_date = models.DateTimeField(core=True)
9   advanced_run = models.BooleanField(default=False)
10   read_length = models.IntegerField(default=32) #Stanford is currenlty 25
11   
12   lane_1_library = models.ForeignKey(Library, related_name="lane_1_library")
13   lane_2_library = models.ForeignKey(Library, related_name="lane_2_library")
14   lane_3_library = models.ForeignKey(Library, related_name="lane_3_library")
15   lane_4_library = models.ForeignKey(Library, related_name="lane_4_library")
16   lane_5_library = models.ForeignKey(Library, related_name="lane_5_library")
17   lane_6_library = models.ForeignKey(Library, related_name="lane_6_library")
18   lane_7_library = models.ForeignKey(Library, related_name="lane_7_library")
19   lane_8_library = models.ForeignKey(Library, related_name="lane_8_library")
20
21   lane_1_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5)
22   lane_2_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5)
23   lane_3_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5)
24   lane_4_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5)
25   lane_5_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5)
26   lane_6_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5)
27   lane_7_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5)
28   lane_8_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5)
29   
30   lane_1_cluster_estimate = models.IntegerField(blank=True, null=True)
31   lane_2_cluster_estimate = models.IntegerField(blank=True, null=True)
32   lane_3_cluster_estimate = models.IntegerField(blank=True, null=True)
33   lane_4_cluster_estimate = models.IntegerField(blank=True, null=True)
34   lane_5_cluster_estimate = models.IntegerField(blank=True, null=True)
35   lane_6_cluster_estimate = models.IntegerField(blank=True, null=True)
36   lane_7_cluster_estimate = models.IntegerField(blank=True, null=True)
37   lane_8_cluster_estimate = models.IntegerField(blank=True, null=True)
38  
39   # lane_1_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_1_primer")
40   # lane_2_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_2_primer")
41   # lane_3_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_3_primer")
42   # lane_4_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_4_primer")
43   # lane_5_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_5_primer")
44   # lane_6_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_6_primer")
45   # lane_7_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_7_primer")
46   # lane_8_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_8_primer")
47
48   #Machine Names
49   CLUSTER_MAC = (
50       ('M304','Cardinal'),
51       ('R349','R349'),
52       ('Tinkerbell','Tinkerbell'),
53       ('BitBit','BitBit'),
54     )
55   
56   SEQ_MAC = (
57       ('EAS149','Stanford'),
58       ('EAS46','EAS46'),
59       ('EAS45','Paris'),
60       ('Britney','Britney'),
61       ('EAS614','LiLo'),
62     )
63
64   cluster_mac_id = models.CharField(max_length=50, choices=CLUSTER_MAC, default='BitBit')
65   seq_mac_id = models.CharField(max_length=50, choices=SEQ_MAC, verbose_name = 'Sequencer', default='Britney')
66   
67   is_paired_end = models.BooleanField(default=False)
68
69   notes = models.TextField(blank=True)
70
71   def __str__(self):
72     #return '%s (%s)' % (self.flowcell_id, self.run_date) 
73     return '%s' % (self.flowcell_id) 
74
75   def Create_LOG(self):
76     str = ''
77     str +='<a target=_balnk href="/exp_track/'+self.flowcell_id+'" title="Create XLS like sheet for this Flowcell ..." ">Create LOG</a>'
78     try:
79       t = DataRun.objects.get(fcid=self.id)
80       str +='<br/><a target=_self href="/admin/exp_track/datarun/?q='+self.flowcell_id+'" title="Check Data Runs ..." ">DataRun ..</a>'
81     except ObjectDoesNotExist:
82       str += '<br/><span style="color:red">not sequenced</span>'
83
84     if self.is_paired_end:
85       str += '<div><b>Paired End</b></div>'
86
87     return str
88   Create_LOG.allow_tags = True 
89
90   def Lanes(self):
91     return '<div><span style="margin-right:10px">1)%s</span><span style="margin-right:10px">2)%s</span><span style="margin-right:10px">3)%s</span><span style="margin-right:10px">4)%s</span><span style="margin-right:10px">5)%s</span><span style="margin-right:10px">6)%s</span><span style="margin-right:10px">7)%s</span><span style="margin-right:10px">8)%s</span></div>' % (self.lane_1_library,self.lane_2_library,self.lane_3_library,self.lane_4_library,self.lane_5_library,self.lane_6_library,self.lane_7_library,self.lane_8_library)
92   Lanes.allow_tags = True
93
94   class Meta:
95     ordering = ["-run_date"]
96   
97   class Admin:
98     save_on_top = True
99     date_hierarchy = "run_date"
100     save_on_top = True
101     search_fields = ['flowcell_id','seq_mac_id','cluster_mac_id','=lane_1_library__library_id','=lane_2_library__library_id','=lane_3_library__library_id','=lane_4_library__library_id','=lane_5_library__library_id','=lane_6_library__library_id','=lane_7_library__library_id','=lane_8_library__library_id']
102     list_display = ('flowcell_id','seq_mac_id','run_date', 'Create_LOG','Lanes','notes')
103     list_filter = ('seq_mac_id','cluster_mac_id')
104     fields = (
105         (None, {
106             'fields': ('run_date', ('flowcell_id','cluster_mac_id','seq_mac_id','is_paired_end'), ('read_length'),)
107         }),
108         ('Lanes:', {
109             ##'fields' : (('lane_1_library', 'lane_1_pM', 'lane_1_cluster_estimate', 'lane_1_primer'), ('lane_2_library', 'lane_2_pM', 'lane_2_cluster_estimate', 'lane_2_primer'), ('lane_3_library', 'lane_3_pM', 'lane_3_cluster_estimate', 'lane_3_primer'), ('lane_4_library', 'lane_4_pM', 'lane_4_cluster_estimate', 'lane_4_primer'), ('lane_5_library', 'lane_5_pM', 'lane_5_cluster_estimate', 'lane_5_primer'), ('lane_6_library', 'lane_6_pM', 'lane_6_cluster_estimate', 'lane_6_primer'), ('lane_7_library', 'lane_7_pM', 'lane_7_cluster_estimate', 'lane_7_primer'), ('lane_8_library', 'lane_8_pM', 'lane_8_cluster_estimate', 'lane_8_primer'),)
110            'fields' : (('lane_1_library', 'lane_1_pM', 'lane_1_cluster_estimate'), ('lane_2_library', 'lane_2_pM', 'lane_2_cluster_estimate'), ('lane_3_library', 'lane_3_pM', 'lane_3_cluster_estimate'), ('lane_4_library', 'lane_4_pM', 'lane_4_cluster_estimate'), ('lane_5_library', 'lane_5_pM', 'lane_5_cluster_estimate'), ('lane_6_library', 'lane_6_pM', 'lane_6_cluster_estimate'), ('lane_7_library', 'lane_7_pM', 'lane_7_cluster_estimate'), ('lane_8_library', 'lane_8_pM', 'lane_8_cluster_estimate'),)
111         }),
112         (None, {
113             'fields' : ('notes',)
114         }),
115     )
116
117
118 ### -----------------------
119
120 #Global Util vars
121 Dict_SEQ_MAC = dict((row[0], row[1]) for row in FlowCell.SEQ_MAC)
122 Dict_CLUSTER_MAC = dict((row[0], row[1]) for row in FlowCell.CLUSTER_MAC)
123
124
125 class DataRun(models.Model):
126   ConfTemplate = "CONFIG PARAMS WILL BE GENERATED BY THE PIPELINE SCRIPT.\nYOU'LL BE ABLE TO EDIT AFTER IF NEEDED."
127   run_folder = models.CharField(max_length=50,unique=True, db_index=True)
128   fcid = models.ForeignKey(FlowCell,verbose_name="Flowcell Id")
129   config_params = models.TextField(default=ConfTemplate)
130   run_start_time = models.DateTimeField(core=True)
131   RUN_STATUS_CHOICES = (
132       (0, 'Sequencer running'), ##Solexa Data Pipeline Not Yet Started'),
133       (1, 'Data Pipeline Started'),
134       (2, 'Data Pipeline Interrupted'),
135       (3, 'Data Pipeline Finished'),
136       (4, 'CollectReads Started'),
137       (5, 'CollectReads Finished'),
138       (6, 'QC Finished'),
139       (7, 'DONE'),
140     )
141   run_status = models.IntegerField(choices=RUN_STATUS_CHOICES, default=0)
142   run_note = models.TextField(blank=True)
143
144
145   # Global var
146   lrc = []
147   
148   def main_status(self):
149     str = '<div'
150     if self.run_status >= 5:
151       str += ' style="color:green">'
152       str += '<b>'+self.RUN_STATUS_CHOICES[self.run_status][1]+'</b>'
153       str +='<div style="margin-top:10px"><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></div>'
154     else:
155       str += '>'+self.RUN_STATUS_CHOICES[self.run_status][1]
156     str += '</div>'
157
158     ## Check Analysis Server Report 
159     str += '<div style="margin-top:10px">Data:<br/>'
160     res = getLibReads(self.fcid.flowcell_id.__str__(),'ByFC')
161                                                                                                                                                                                                                                                                       
162     if res[3] != 'OK':
163       str += '<div style="margin-top:10px;border:solid red 2px">'+res[3]+'</div>'
164     else:
165       lc = res[0]
166       if(lc>0):
167         rc = "%1.2f" % (res[1]/1000000.0)
168         lrc = ''
169         L = 1
170         for c in res[2]: 
171           lrc += '<div>['+L.__str__()+']: '+ "%1.2f" % (c/1000000.0)+'</div>'  
172           L += 1
173         str += '<div style="color:green"><b>'+lc.__str__()+'</b> lanes<br/><b>'+rc.__str__()+'</b> M reads</div>'
174         str += '<div style="color:#666666"><b>'+lrc+'</b></div>'        
175       else:
176         str += '<div style="color:red">no data yet</div>'
177
178     str += '</div>'
179   
180     return str
181   main_status.allow_tags = True
182
183   ## Util
184   #Dict_SEQ_MAC = dict((row[0], row[1]) for row in FlowCell.SEQ_MAC)
185   
186   def Flowcell_Info(self):
187     str = '<b>'+self.fcid.__str__()+'</b>'
188     str += '  (c: '+Dict_CLUSTER_MAC[self.fcid.cluster_mac_id]+',  s: '+Dict_SEQ_MAC[self.fcid.seq_mac_id]+')'
189     if self.fcid.is_paired_end:
190       str += '<span style="margin-left:10px"><b>Paired End</b></span>'
191     str += '<div style="margin-top:5px;">'    
192     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>'
193     str += '<div id="LanesOf'+self.fcid.__str__()+'" style="display:block;border:solid #cccccc 1px;width:350px">'
194     LanesList = '<div style="'+('background-color:#cccccc;' if 'Bad library' in self.fcid.lane_1_library.libtags() else '')+'">1: '+self.fcid.lane_1_library.__str__()+' ('+self.fcid.lane_1_library.library_species.use_genome_build+')</div> '
195     LanesList += '<div style="'+('background-color:#cccccc;' if 'Bad library' in self.fcid.lane_2_library.libtags() else '')+'">2: '+self.fcid.lane_2_library.__str__()+' ('+self.fcid.lane_2_library.library_species.use_genome_build+')</div>'
196     LanesList += '<div style="'+('background-color:#cccccc;' if 'Bad library' in self.fcid.lane_3_library.libtags() else '')+'">3: '+self.fcid.lane_3_library.__str__()+' ('+self.fcid.lane_3_library.library_species.use_genome_build+')</div>'
197     LanesList += '<div style="'+('background-color:#cccccc;' if 'Bad library' in self.fcid.lane_4_library.libtags() else '')+'">4: '+self.fcid.lane_4_library.__str__()+' ('+self.fcid.lane_4_library.library_species.use_genome_build+')</div>'
198     LanesList += '<div style="'+('background-color:#cccccc;' if 'Bad library' in self.fcid.lane_5_library.libtags() else '')+'">5: '+self.fcid.lane_5_library.__str__()+' ('+self.fcid.lane_5_library.library_species.use_genome_build+')</div>'
199     LanesList += '<div style="'+('background-color:#cccccc;' if 'Bad library' in self.fcid.lane_6_library.libtags() else '')+'">6: '+self.fcid.lane_6_library.__str__()+' ('+self.fcid.lane_6_library.library_species.use_genome_build+')</div>'
200     LanesList += '<div style="'+('background-color:#cccccc;' if 'Bad library' in self.fcid.lane_7_library.libtags() else '')+'">7: '+self.fcid.lane_7_library.__str__()+' ('+self.fcid.lane_7_library.library_species.use_genome_build+')</div>'
201     LanesList += '<div style="'+('background-color:#cccccc;' if 'Bad library' in self.fcid.lane_8_library.libtags() else '')+'">8: '+self.fcid.lane_8_library.__str__()+' ('+self.fcid.lane_8_library.library_species.use_genome_build+')</div>'
202     str += LanesList ## self.fcid.Lanes()
203     str += '</div>'
204     str += '<div><a title="open Flowcell record" href="/admin/exp_track/flowcell/'+self.fcid.id.__str__()+'/" target=_self>Edit Flowcell record</a>'
205     #str += '<span style="color:red;font-size:80%;margin-left:15px;margin-right:3px">New!</span>'
206     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>'
207     str += '</div>'
208     str += '</div>'    
209     return str
210   Flowcell_Info.allow_tags = True
211
212   class Admin:
213     search_fields = ['run_folder','run_note','config_params','=fcid__lane_1_library__library_id','=fcid__lane_2_library__library_id','=fcid__lane_3_library__library_id','=fcid__lane_4_library__library_id','=fcid__lane_5_library__library_id','=fcid__lane_6_library__library_id','=fcid__lane_7_library__library_id','=fcid__lane_8_library__library_id']
214
215     list_display = ('run_folder','Flowcell_Info','run_start_time','main_status','run_note')
216     list_filter = ('run_status','run_start_time')