added FlowcellId data status (by read count from libinfo). Now data status is reporte...
[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   def main_status(self):
146     str = '<div'
147     if self.run_status >= 5:
148       str += ' style="color:green">'
149       str += '<b>'+self.RUN_STATUS_CHOICES[self.run_status][1]+'</b>'
150       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>'
151     else:
152       str += '>'+self.RUN_STATUS_CHOICES[self.run_status][1]
153     str += '</div>'
154
155     ## Check Analysis Server Report 
156     str += '<div style="margin-top:10px">Data analyzed:<br/>'
157     res = getLibReads(self.fcid.flowcell_id.__str__(),'ByFC')
158                                                                                                                                                                                                                                                                           
159     if res[2] != 'OK':
160       str += '<div style="margin-top:10px;border:solid red 2px">'+res[2]+'</div>'
161     else:
162       lc = res[0]
163       if(lc>0):
164         rc = "%1.2f" % (res[1]/1000000.0)
165         str += '<div style="color:green"><b>'+lc.__str__()+'</b> lanes<br/><b>'+rc.__str__()+'</b> M reads</div>'
166       else:
167         str += '<div style="color:red">no data yet</div>'
168
169     str += '</div>'
170   
171     return str
172   main_status.allow_tags = True
173
174   ## Util
175   #Dict_SEQ_MAC = dict((row[0], row[1]) for row in FlowCell.SEQ_MAC)
176   
177   def Flowcell_Info(self):
178     str = '<b>'+self.fcid.__str__()+'</b>'
179     str += '  (c: '+Dict_CLUSTER_MAC[self.fcid.cluster_mac_id]+',  s: '+Dict_SEQ_MAC[self.fcid.seq_mac_id]+')'
180     if self.fcid.is_paired_end:
181       str += '<span style="margin-left:10px"><b>Paired End</b></span>'
182     str += '<div style="margin-top:5px;">'    
183     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>'
184     str += '<div id="LanesOf'+self.fcid.__str__()+'" style="display:block;border:solid #cccccc 1px;width:350px">'
185     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> '
186     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>'
187     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>'
188     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>'
189     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>'
190     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>'
191     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>'
192     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>'
193     str += LanesList ## self.fcid.Lanes()
194     str += '</div>'
195     str += '<div><a title="open Flowcell record" href="/admin/exp_track/flowcell/'+self.fcid.id.__str__()+'/" target=_self>Edit Flowcell record</a>'
196     #str += '<span style="color:red;font-size:80%;margin-left:15px;margin-right:3px">New!</span>'
197     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>'
198     str += '</div>'
199     str += '</div>'    
200     return str
201   Flowcell_Info.allow_tags = True
202
203   class Admin:
204     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']
205
206     list_display = ('run_folder','Flowcell_Info','run_start_time','main_status','run_note')
207     list_filter = ('run_status','run_start_time')