Adding the new Reports component.
[htsworkflow.git] / gaworkflow / frontend / htsw_reports / models.py
1 from django.db import models
2 from django.db.models import Q
3 from django.core.exceptions import ObjectDoesNotExist
4 from datetime import datetime
5 from gaworkflow.frontend.fctracker.models import * 
6 from gaworkflow.frontend.analys_track.models import *
7 from gaworkflow.frontend.exp_track.models import *
8 from string import *
9 import re
10 ##from p1 import LibInfo
11 from libinfopar import *
12
13 ## This is a table based REPORT generator. The goal is to display a Progress Report for all the ENCODE projects, based on Study Name (e.g. NRSF, FOXP2, Methy-Seq on .. etc).
14   
15 class ProgressReport(models.Model):
16   st_sbj = models.ForeignKey(Project,limit_choices_to = Q(project_name__startswith='ENCODE '),related_name='project',db_index=True,verbose_name="Studied Subject")
17   interactome_complete = models.BooleanField(default=False)
18
19   def Study(self):
20     str = self.st_sbj.__str__()
21     str += '<br/><br/>'
22     str += '<a title="open Project record" href="/admin/analys_track/project/'+self.st_sbj.id.__str__()+'/" target=_self style="font-size:85%">Edit Project</a>'
23     return str  
24   Study.allow_tags = True
25
26   def submit_to_DCC(self):
27     varText = ''
28     if self.note_about_DCC:
29       varText += '<br/><u>Note:</u><br/>'+self.note_about_DCC
30     return '%s<br/>%s' % (self.submitted_to_DCC,varText)
31   submit_to_DCC.allow_tags = True
32
33   def submit_to_NCBI(self):
34     varText = ''
35     if self.note_about_NCBI:
36       varText += '<br/><u>Note:</u><br/>'+self.note_about_NCBI 
37     return '%s<br/>%s' % (self.submitted_to_NCBI,varText)
38   submit_to_NCBI.allow_tags = True
39
40   #REPS = ((1,1),(2,2),(3,3))
41   #replicate = models.PositiveSmallIntegerField(choices=REPS,verbose_name='Replicate Number')   
42   
43   ## -- Utility functions
44   def unique(self,s):
45     """Return a list of the elements in s, but without duplicates.
46     For example, unique([1,2,3,1,2,3]) is some permutation of [1,2,3],
47     unique("abcabc") some permutation of ["a", "b", "c"], and
48     unique(([1, 2], [2, 3], [1, 2])) some permutation of
49     [[2, 3], [1, 2]].
50     For best speed, all sequence elements should be hashable.  Then
51     unique() will usually work in linear time.
52     If not possible, the sequence elements should enjoy a total
53     ordering, and if list(s).sort() doesn't raise TypeError it's
54     assumed that they do enjoy a total ordering.  Then unique() will
55     usually work in O(N*log2(N)) time.
56     If that's not possible either, the sequence elements must support
57     equality-testing.  Then unique() will usually work in quadratic
58     time.
59     """
60
61     n = len(s)
62     if n == 0:
63         return []
64
65     # Try using a dict first, as that's the fastest and will usually
66     # work.  If it doesn't work, it will usually fail quickly, so it
67     # usually doesn't cost much to *try* it.  It requires that all the
68     # sequence elements be hashable, and support equality comparison.
69     u = {}
70     try:
71         for x in s:
72             u[x] = 1
73     except TypeError:
74         del u  # move on to the next method
75     else:
76         return u.keys()
77
78     # We can't hash all the elements.  Second fastest is to sort,
79     # which brings the equal elements together; then duplicates are
80     # easy to weed out in a single pass.
81     # NOTE:  Python's list.sort() was designed to be efficient in the
82     # presence of many duplicate elements.  This isn't true of all
83     # sort functions in all languages or libraries, so this approach
84     # is more effective in Python than it may be elsewhere.
85     try:
86         t = list(s)
87         t.sort()
88     except TypeError:
89         del t  # move on to the next method
90     else:
91         assert n > 0
92         last = t[0]
93         lasti = i = 1
94         while i < n:
95             if t[i] != last:
96                 t[lasti] = last = t[i]
97                 lasti += 1
98             i += 1
99         return t[:lasti]
100
101     # Brute force is all that's left.
102     u = []
103     for x in s:
104         if x not in u:
105             u.append(x)
106     return u
107
108
109   ## --- LIBARAY PREPARATION SECTION 
110   def getLibIds(self):
111     ptasks = self.st_sbj.tasks.distinct()
112     arLibs = [] 
113     for t in ptasks:
114       if t.subject1 is not None:
115         arLibs.append(t.subject1.library_id)
116       if t.subject2 is not None:
117         arLibs.append(t.subject2.library_id)
118     arLibs = self.unique(arLibs)
119     return arLibs #.sort()
120
121   def getFCInfo(self,libid):   ## This is the haviest function 
122     arFCLanes = []
123     ##Test return arFCLanes
124     # can't get this to work: FC_L1 = FlowCell.objects.filter(lane_5_library__exact=libid)
125     allFCs = FlowCell.objects.all()
126     for f in allFCs:
127       entry = ''
128       lanes = []
129       #found = False
130 #      for i in range(1,9):
131 #        if eval('f.lane_'+i.__str__()+'_library.library_id==libid'):
132 #          lanes.append(i.__str__())
133 #          found = True
134
135 # maybe a bit faster this way:
136       if f.lane_1_library.library_id==libid:
137           lanes.append('1')
138           #found = True
139       if f.lane_2_library.library_id==libid:
140           lanes.append('2')
141           #found = True
142       if f.lane_3_library.library_id==libid:
143           lanes.append('3')
144           #found = True
145       if f.lane_4_library.library_id==libid:
146           lanes.append('4')
147           #found = True
148       if f.lane_5_library.library_id==libid:
149           lanes.append('5')
150           #found = True
151       if f.lane_6_library.library_id==libid:
152           lanes.append('6')
153           #found = True
154       if f.lane_7_library.library_id==libid:
155           lanes.append('7')
156           #found = True
157       if f.lane_8_library.library_id==libid:
158           lanes.append('8')
159           #found = True
160
161
162       #if found:
163       if len(lanes)>0:
164         rundate = re.sub(pattern="\s.*$",repl="",string=f.run_date.__str__())
165         entry = '<b>'+f.flowcell_id + '</b> Lanes No.: '+','.join(lanes)+' ('+rundate+')' 
166         arFCLanes.append(entry)    
167     if len(arFCLanes)==0:
168       arFCLanes.append('<font color=red>Flowcell not found.</font>')
169     return arFCLanes
170
171   def ab_batch(self):
172     ##  To have the Company's lot number, apearing on the (source) tube, we need to add new Field in Library. 
173     arlibs = self.getLibIds()
174     tstr = '<ul>' ##<u><b>Ab</b> from '+len(arlibs).__str__()+' libs</u>: '
175     arRows = []
176     for l in arlibs:
177       try:
178         rec = Library.objects.get(library_id=l,antibody__isnull=False)
179         arRows.append('<li>'+rec.antibody.antibodies+' for <b>'+rec.antibody.antigene+'</b> (src:'+rec.antibody.source+', cat:'+rec.antibody.catalog+')</li>')
180       except ObjectDoesNotExist:
181         tstr += ""
182     tstr += "".join(self.unique(arRows))+'</ul>'
183     return tstr
184   ab_batch.allow_tags = True
185
186   def cell_line(self):                                                                                           
187     arlibs = self.getLibIds()
188     tstr = '<ul>'
189     arRows = []                                                                                                                                     
190     for l in arlibs:
191       try:
192         rec = Library.objects.get(library_id=l)
193         arRows.append('<li><b>'+rec.cell_line.cellline_name+'</b> ('+rec.condition.condition_name+')</li>')
194       except ObjectDoesNotExist:
195         tstr += ""                                                                                                                               
196     tstr += "".join(self.unique(arRows))+'</ul>'
197     return tstr
198   cell_line.allow_tags = True
199
200   def cell_harvest_batch(self): # <- data now displayed in "cell_line"
201     ## name + date  
202     arlibs = self.getLibIds()
203     tstr = '<ul>'
204     arRows = []
205     for l in arlibs:
206       try:
207         rec = Library.objects.get(library_id=l)
208         arRows.append('<li><b>'+rec.condition.condition_name+'</b></li>')
209       except ObjectDoesNotExist:
210         tstr += ""
211     tstr += "".join(self.unique(arRows))+'</ul>'
212     return tstr
213   cell_harvest_batch.allow_tags = True
214
215   def ChIP_made(self):
216     ## person + date                                                                                                                                                                                                             
217     return '...'
218
219   def library(self):
220     ## Lib Id + Date + Person
221     tstr = '<script>'
222     tstr += 'function togit(eid){'
223     tstr += 'f=document.getElementById(eid);'
224     tstr += 'if(f.style.display==\'none\'){'
225     tstr += 'f.style.display=\'block\';'
226     tstr += '}else{'
227     tstr += 'f.style.display=\'none\';'
228     tstr += '}'
229     tstr += '}'
230     tstr += '</script>'
231     arlibs = self.getLibIds() ##.sort()
232     arlibs = arlibs
233     tstr +='<a href=# onClick="togit(\'libInfo'+self.st_sbj.project_name+'\')">view /hide</a>'
234     tstr += '<div id="libInfo'+self.st_sbj.project_name+'" style="display:block;border:solid #cccccc 1px;width:200px;height:300px;overflow:auto"><ul>'
235     arRows = []
236     for l in arlibs:
237       try:
238         rec = Library.objects.get(library_id=l)
239         arRows.append('<li><b>'+rec.library_id+'</b>: '+rec.library_name+'.<br/>Made By: '+rec.made_by+', On: '+ rec.creation_date.__str__()+'</li>')
240       except ObjectDoesNotExist:
241         tstr += ""
242     tstr += "".join(self.unique(arRows))+'</ul></div>'
243     return tstr
244   library.allow_tags = True
245
246
247   ## -- SEQUENCING SECTION 
248   def sequencing(self):
249     ## FCId + Lane + Date
250     arlibs = self.getLibIds()
251     tstr ='<a href=# onClick="togit(\'seqInfo'+self.st_sbj.project_name+'\')">view /hide</a>'
252     tstr += '<div id="seqInfo'+self.st_sbj.project_name+'" style="display:block;border:solid #cccccc 1px;width:200px;height:300px;overflow:auto"><ul>'    
253     for l in arlibs:
254       tstr += '<li><b>'+l+'</b>:<br/>'+(' / '.join(self.getFCInfo(l)))+'</li>'
255     tstr += '</ul></div>'
256     return tstr
257   sequencing.allow_tags = True
258   
259   def aligned_reads(self):
260     ## Mega reads/lane                                              
261     arlibs = self.getLibIds()
262     tstr = '<a href=# onClick="togit(\'readsInfo'+self.st_sbj.project_name+'\')">view /hide</a>'
263     tstr += '<div id="readsInfo'+self.st_sbj.project_name+'" style="display:block;border:solid #cccccc 1px;width:200px;height:300px;overflow:auto">'
264     tstr += '<table><tr><td>Library Id</td><td>Total Lanes</td><td>M Reads</td></tr>'
265     LanesCnt, ReadsCnt = 0, 0
266     for l in arlibs:      
267       res = getLibReads(l)
268       LanesCnt += res[0]
269       ReadsCnt += res[1]
270       rc = "%1.2f" % (res[1]/1000000.0)
271       tstr += '<tr><td><b>'+l+'</b></td><td>'+res[0].__str__()+'</td></td><td>'+rc+'</td></tr>'
272     tstr += '</table>'
273     #tstr += '<a target=_blank href="http://m304-apple-server.stanford.edu/projects/'+self.st_sbj.id.__str__()+'">Project results page</a>'
274     tstr += '</div>'
275     myNum = (ReadsCnt/1000000.0)
276     myNum  = "%1.2f" % (myNum) 
277     tstr += '<div>Total: <b>'+LanesCnt.__str__()+'</b> lanes and <b>'+myNum+'</b> M Reads</div>'
278     tstr += '<a target=_blank href="http://m304-apple-server.stanford.edu/projects/'+self.st_sbj.id.__str__()+'">Project results page</a>'
279     return tstr
280   aligned_reads.allow_tags = True
281
282   def peak_calling(self):
283     # date + what etc..
284     return 'coming up ..'
285
286   QPCR = models.CharField(max_length=500,blank=True,null=True)    
287   submitted_to_DCC = models.DateTimeField(core=True,blank=True,null=True)
288   submitted_to_NCBI = models.DateTimeField(core=True,blank=True,null=True)
289   note_about_DCC =  models.TextField(blank=True)
290   note_about_NCBI = models.TextField(blank=True)
291   
292   def __str__(self):
293       return '"%s" - %s' % (self.st_sbj,self.interactome_complete)
294
295   class Meta:
296     #verbose_name_plural = "Reports"
297     ordering = ["id"]
298
299   class Admin:
300     list_display = ('Study','ab_batch','cell_line','library','sequencing','aligned_reads','QPCR','submit_to_DCC','submit_to_NCBI','interactome_complete')
301     ## list_filter = ('interactome_complete')
302