minor update
[htsworkflow.git] / htswfrontend / htswfrontend / fctracker / models.py
1 from django.db import models
2 from htswfrontend import settings
3 from htswfrontend.htsw_reports.libinfopar import *
4 from htswfrontend.files.models import ImageFile
5
6 class Primer(models.Model):
7   primer_name = models.CharField(max_length=100, db_index=True)
8   primer_seq = models.CharField(max_length=50, blank=True, null=True)
9   notes = models.TextField(blank=True)
10   def __str__(self):
11     return '%s' % (self.primer_name)
12   class Meta:
13     ordering = ["primer_name"]
14   class Admin:
15       list_display = ('primer_name','primer_seq','notes')
16       fields = (
17         (None, {
18             'fields': (('primer_name'),('primer_seq'),('notes'))
19         }),
20        )
21
22 class Antibody(models.Model):
23   antigene = models.CharField(max_length=500, db_index=True)
24   # New field Aug/20/08                                                                                                                                                            
25   # SQL to add column: alter table fctracker_antibody add column "nickname" varchar(20) NULL;
26   nickname = models.CharField(max_length=20,blank=True,null=True, db_index=True,verbose_name = 'Short Name')
27   catalog = models.CharField(max_length=50, unique=True, db_index=True)
28   antibodies = models.CharField(max_length=500, db_index=True)
29   source = models.CharField(max_length=500, blank=True, db_index=True)
30   biology = models.TextField(blank=True)
31   notes = models.TextField(blank=True)
32
33   # added: apr/14/09 
34   imagefiles = models.ManyToManyField(ImageFile,related_name='antibody_imagefiles',filter_interface=models.HORIZONTAL,blank=True, null=True)
35
36   def __str__(self):
37     return '%s - %s (%s)' % (self.antigene, self.antibodies, self.catalog)
38
39   def image_files(self):
40     images = self.imagefiles.all().order_by('file_title')                                                                                  
41     ar = []
42     for t in images:
43         ar.append('<a href="'+'/files/show/'+t.id.__str__()+'" title="View Image" target="_self">'+t.__str__()+'</a>')
44    
45     if len(ar) > 0:
46       return "<div style='max-width:600px'>"+"<br/>".join(ar) +"</div>"
47     else:
48       return ''
49   image_files.allow_tags = True  
50
51   class Meta:
52     verbose_name_plural = "antibodies"
53     ordering = ["antigene"]
54   class Admin:
55       list_display = ('antigene','nickname','antibodies','catalog','source','image_files','biology','notes')
56       list_filter = ('antibodies','source')
57       search_fields = ['antigene','nickname','catalog','antibodies','source','biology','notes']
58       fields = (
59         (None, {
60             'fields': (('antigene','nickname','antibodies'),('catalog','source'),('biology'),('imagefiles'),('notes'))
61         }),
62        )
63
64 class Cellline(models.Model):
65   cellline_name = models.CharField(max_length=100, unique=True, db_index=True)
66   nickname = models.CharField(max_length=20,blank=True,null=True, db_index=True,verbose_name = 'Short Name')
67   notes = models.TextField(blank=True)
68   def __str__(self):
69     return '%s' % (self.cellline_name)
70
71   class Meta:
72     ordering = ["cellline_name"]
73     
74   class Admin:
75       list_display = ('cellline_name','nickname','notes')
76       search_fields = ['cellline_name','nickname','notes']
77       fields = (
78         (None, {
79             'fields': (('cellline_name','nickname'),('notes'),)
80         }),
81        )
82
83 class Condition(models.Model):
84   condition_name = models.CharField(max_length=2000, unique=True, db_index=True)
85   nickname = models.CharField(max_length=20,blank=True,null=True, db_index=True,verbose_name = 'Short Name')
86   notes = models.TextField(blank=True)
87   def __str__(self):
88     return '%s' % (self.condition_name)
89
90   class Meta:
91     ordering = ["condition_name"]
92
93   class Admin:
94       list_display = ('condition_name','nickname','notes')
95       fields = (
96         (None, {
97             'fields': (('condition_name','nickname'),('notes'),)
98         }),
99        )
100
101 class Species(models.Model):
102   scientific_name = models.CharField(max_length=256, unique=False, db_index=True, core=True)
103   common_name = models.CharField(max_length=256, blank=True)
104   use_genome_build = models.CharField(max_length=100, blank=False, null=False)
105
106   def __str__(self):
107     return '%s (%s)|%s' % (self.scientific_name, self.common_name, self.use_genome_build)
108   
109   class Meta:
110     verbose_name_plural = "species"
111     ordering = ["scientific_name"]
112   
113   class Admin:
114       fields = (
115         (None, {
116             'fields': (('scientific_name', 'common_name'), ('use_genome_build'))
117         }),
118       )
119
120 class Affiliation(models.Model):
121   name = models.CharField(max_length=256, db_index=True, core=True,verbose_name='Group Name')
122   contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Contact Name')  
123   email = models.EmailField(null=True,blank=True)
124   
125   def __str__(self):
126     str = self.name
127     if self.contact != '':
128       str += ' ('+self.contact+')' 
129     return str
130
131   class Meta:
132     ordering = ["name","contact"]
133     unique_together = (("name", "contact"),)
134
135   class Admin:
136       list_display = ('name','contact','email')
137       fields = (
138         (None, {
139             'fields': (('name','contact','email'))
140         }),
141       )
142
143 class Tag(models.Model):
144   tag_name = models.CharField(max_length=100,unique=True, db_index=True,core=True,blank=False,null=False)
145   TAG_CONTEXT = (
146       #('Antibody','Antibody'),
147       #('Cellline', 'Cellline'),
148       #('Condition', 'Condition'),
149       ('Library', 'Library'),
150       ('ANY','ANY'),
151     )
152   context = models.CharField(max_length=50, choices=TAG_CONTEXT, default='Library')
153
154   def __str__(self):
155     return '%s' % (self.tag_name)
156
157   class Meta:
158     ordering = ["context","tag_name"]
159
160   class Admin:
161       list_display = ('tag_name','context')
162       fields = (
163         (None, {
164             'fields': ('tag_name','context')
165         }),
166       )
167
168 class Library(models.Model):
169   library_id = models.CharField(max_length=30, unique=True, db_index=True, core=True)
170   library_name = models.CharField(max_length=100, unique=True, core=True)
171   library_species = models.ForeignKey(Species, core=True)
172   cell_line = models.ForeignKey(Cellline,core=True)
173   condition = models.ForeignKey(Condition,core=True)
174   antibody = models.ForeignKey(Antibody,blank=True,null=True,core=True)
175   # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256)  NULL;
176   affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True,filter_interface=models.HORIZONTAL)
177   # New field Nov/14/08
178   tags = models.ManyToManyField(Tag,related_name='library_tags',null=True,blank=True,filter_interface=models.HORIZONTAL)
179   # New field Aug/19/08
180   # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
181   REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
182   replicate =  models.PositiveSmallIntegerField(choices=REPLICATE_NUM,default=1) 
183
184   EXPERIMENT_TYPES = (
185       ('INPUT_RXLCh','INPUT_RXLCh'),
186       ('ChIP-seq', 'ChIP-seq'),
187       ('Sheared', 'Sheared'),
188       ('RNA-seq', 'RNA-seq'),
189       ('Methyl-seq', 'Methyl-seq'),
190       ('DIP-seq', 'DIP-seq'),
191     ) 
192   experiment_type = models.CharField(max_length=50, choices=EXPERIMENT_TYPES, default='ChIP-seq')
193
194   creation_date = models.DateField(blank=True, null=True)
195   made_for = models.CharField(max_length=50, blank=True,verbose_name = 'ChIP/DNA/RNA Made By')
196   made_by = models.CharField(max_length=50, blank=True,verbose_name = 'Library Made By')
197   
198   PROTOCOL_END_POINTS = (
199       ('Completed','Completed'),
200       ('?', 'Unknown'),
201       ('Sample', 'Raw sample'),
202       ('Progress', 'In progress'),
203       ('1A', 'Ligation, then gel'),
204       ('PCR', 'Ligation, then PCR'),
205       ('1Ab', 'Ligation, PCR, then gel'),
206       ('1Aa', 'Ligation, gel, then PCR'),
207       ('2A', 'Ligation, PCR, gel, PCR'),
208     )
209   stopping_point = models.CharField(max_length=50, choices=PROTOCOL_END_POINTS, default='Completed')
210   amplified_from_sample = models.ForeignKey('self', blank=True, null=True)
211   
212   undiluted_concentration = models.DecimalField("Template concentr. (ng/ul)",max_digits=5, decimal_places=2, blank=True, null=True)
213   ten_nM_dilution = models.BooleanField()
214   successful_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=True, null=True)
215   avg_lib_size = models.IntegerField(default=225, blank=True, null=True)
216   notes = models.TextField(blank=True)
217   
218   def __str__(self):
219     return '%s: %s' % (self.library_id, self.library_name)
220   
221   class Meta:
222     verbose_name_plural = "libraries"
223     ordering = ["-creation_date"] #["-library_id"]
224   
225   def antibody_name(self):
226     str ='<a target=_self href="/admin/fctracker/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.nickname+'</a>'
227     return str
228   antibody_name.allow_tags = True
229
230   def org(self):
231     return self.library_species.common_name
232
233   def cond(self):
234     return self.condition.nickname
235
236   def affiliation(self):
237     affs = self.affiliations.all().order_by('name')
238     tstr = ''
239     ar = []
240     for t in affs:
241         ar.append(t.__str__())
242     return '%s' % (", ".join(ar))
243
244   def libtags(self):
245     affs = self.tags.all().order_by('tag_name')
246     tstr = ''
247     ar = []
248     for t in affs:
249         ar.append(t.__str__())
250     return '%s' % (", ".join(ar))
251
252   def DataRun(self):
253     str ='<a target=_self href="/admin/exp_track/datarun/?q='+self.library_id+'" title="Check All Data Runs for This Specific Library ..." ">DataRuns ..</a>'
254     return str
255   DataRun.allow_tags = True
256
257   def aligned_m_reads(self):
258     return getLibReads(self.library_id,'ByLib')
259
260   def aligned_reads(self):
261     res = getLibReads(self.library_id,'ByLib')
262
263     # Check data sanlty                                                                                                                                    
264     if res[2] != 'OK':
265       return '<div style="border:solid red 2px">'+res[2]+'</div>'
266
267     rc = "%1.2f" % (res[1]/1000000.0)
268     # Color Scheme: green is more than 12M, blue is more than 5M, orange is more than 3M and red is less. For RNAseq, all those thresholds should be doubled
269
270     bgcolor = '#FFCDD0'  # Red, the color for minimum read count
271     rc_thr = [12000000,5000000,3000000]
272     if self.experiment_type == 'RNA-seq':
273       rc_thr = [20000000,10000000,6000000]
274
275     if self.libtags().find('Bad library')!=-1:
276       bgcolor = '#cccccc'
277     else:
278       if res[1] > rc_thr[0]:
279         bgcolor = '#66ff66'  # Green                                                                                                                                                                                                      
280       else:
281         if res[1] > rc_thr[1]:
282           bgcolor ='#00ccff'  # Blue                                                                                                                                                                                                  
283         else:
284            if res[1] > rc_thr[2]:
285              bgcolor ='#ffcc33'  # Orange
286
287     tstr = '<div style="background-color:'+bgcolor+';color:black">'
288     if res[0] > 0:  tstr += res[0].__str__()+' Lanes, '+rc+' M'
289     else: tstr += 'not processed yet'
290     tstr += '</div>'
291  
292     return tstr
293   aligned_reads.allow_tags = True
294
295   class Admin:
296     date_hierarchy = "creation_date"
297     save_as = True
298     save_on_top = True
299     ##search_fields = ['library_id','library_name','affiliations__name','affiliations__contact','made_by','made_for','antibody__antigene','antibody__catalog','antibody__antibodies','antibody__source','cell_line__cellline_name','library_species__scientific_name','library_species__common_name','library_species__use_genome_build']
300     search_fields = ['library_id','library_name','cell_line__cellline_name','library_species__scientific_name','library_species__common_name','library_species__use_genome_build']
301     list_display = ('affiliation','library_id','aligned_reads','DataRun','library_name','experiment_type','org','replicate','antibody_name','cell_line','cond','libtags','made_by','creation_date')
302     list_display_links = ('library_id', 'library_name')
303     list_filter = ('experiment_type','affiliations','library_species','tags','made_for', 'made_by','replicate','antibody','cell_line','condition')
304     fields = (
305         (None, {
306             'fields': (('replicate','library_id','library_name'),('library_species'),('experiment_type'),('cell_line','condition','antibody'),)
307         }),
308         ('Creation Information:', {
309             'fields' : (('made_for', 'made_by', 'creation_date'), ('stopping_point', 'amplified_from_sample'), ('avg_lib_size','undiluted_concentration', 'ten_nM_dilution', 'successful_pM'), 'notes',)
310         }),
311         ('Library/Project Affiliation:', {
312             'fields' : (('affiliations'),('tags'),)
313         }),
314         )