Added 'lanes_for' which will show recent flowcell lanes ordered by date,
[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)], 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 ### -----------------------
93 class DataRun(models.Model):
94   ConfTemplate = "CONFIG PARAMS WILL BE GENERATED BY THE PIPELINE SCRIPT.\nYOU'LL BE ABLE TO EDIT AFTER IF NEEDED."
95   run_folder = models.CharField(max_length=50,unique=True, db_index=True)
96   fcid = models.ForeignKey(FlowCell,verbose_name="Flowcell Id")
97   config_params = models.TextField(default=ConfTemplate)
98   run_start_time = models.DateTimeField()
99   RUN_STATUS_CHOICES = (
100       (0, 'Sequencer running'), ##Solexa Data Pipeline Not Yet Started'),
101       (1, 'Data Pipeline Started'),
102       (2, 'Data Pipeline Interrupted'),
103       (3, 'Data Pipeline Finished'),
104       (4, 'CollectReads Started'),
105       (5, 'CollectReads Finished'),
106       (6, 'QC Finished'),
107       (7, 'DONE'),
108     )
109   run_status = models.IntegerField(choices=RUN_STATUS_CHOICES, default=0)
110   run_note = models.TextField(blank=True)
111
112
113   def main_status(self):
114     str = '<div'
115     if self.run_status >= 5:
116       str += ' style="color:green">'
117       str += '<b>'+self.RUN_STATUS_CHOICES[self.run_status][1]+'</b>'
118       str += '<br/><br/>' #<span style="color:red;font-size:80%;">New!</span>'
119       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>'
120     else:
121       str += '>'+self.RUN_STATUS_CHOICES[self.run_status][1]
122
123     str += '</div>'
124     return str
125   main_status.allow_tags = True
126
127   main_status.allow_tags = True
128   
129   def Flowcell_Info(self):
130     str = '<b>'+self.fcid.__str__()+'</b>'
131     str += '  (c: '+self.fcid.cluster_mac_id+',  s: '+self.fcid.seq_mac_id+')'
132     str += '<div style="margin-top:5px;">'    
133     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>'
134     str += '<div id="LanesOf'+self.fcid.__str__()+'" style="display:block;border:solid #cccccc 1px;width:350px">'
135     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+')'
136     str += LanesList ## self.fcid.Lanes()
137     str += '</div>'
138     str += '<div><a title="open Flowcell record" href="/admin/exp_track/flowcell/'+self.fcid.id.__str__()+'/" target=_self>Edit Flowcell record</a>'
139     #str += '<span style="color:red;font-size:80%;margin-left:15px;margin-right:3px">New!</span>'
140     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>'
141     str += '</div>'
142     str += '</div>'    
143     return str
144   Flowcell_Info.allow_tags = True
145
146
147 class Lane(models.Model):
148   flowcell = models.ForeignKey(FlowCell)
149   lane_number = models.IntegerField(choices=[(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8)])
150   library = models.ForeignKey(Library)
151   pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
152   cluster_estimate = models.IntegerField(blank=True, null=True)
153   comment = models.TextField(null=True, blank=True)