better handle the case when Affilations.contact is None
[htsworkflow.git] / htsworkflow / frontend / samples / models.py
1 from django.db import models
2 from django.contrib.auth.models import User
3 from htsworkflow.frontend import settings
4 from htsworkflow.frontend.reports.libinfopar import *
5
6 # Create your models here.
7
8 class Antibody(models.Model):
9     antigene = models.CharField(max_length=500, db_index=True)
10     # New field Aug/20/08
11     # SQL to add column: 
12     # alter table fctracker_antibody add column "nickname" varchar(20) NULL;
13     nickname = models.CharField(
14         max_length=20,
15         blank=True,
16         null=True, 
17         db_index=True,
18         verbose_name = 'Short Name'
19     )
20     catalog = models.CharField(max_length=50, unique=True, db_index=True)
21     antibodies = models.CharField(max_length=500, db_index=True)
22     source = models.CharField(max_length=500, blank=True, db_index=True)
23     biology = models.TextField(blank=True)
24     notes = models.TextField(blank=True)
25     def __unicode__(self):
26         return u'%s - %s (%s)' % (self.antigene, self.antibodies, self.catalog)
27     class Meta:
28         verbose_name_plural = "antibodies"
29         ordering = ["antigene"]
30
31 class Cellline(models.Model):
32     cellline_name = models.CharField(max_length=100, unique=True, db_index=True)
33     nickname = models.CharField(max_length=20,
34         blank=True,
35         null=True, 
36         db_index=True,
37         verbose_name = 'Short Name')
38     notes = models.TextField(blank=True)
39     def __unicode__(self):
40         return unicode(self.cellline_name)
41
42     class Meta:
43         ordering = ["cellline_name"]
44
45 class Condition(models.Model):
46     condition_name = models.CharField(
47         max_length=2000, unique=True, db_index=True)
48     nickname = models.CharField(max_length=20,
49         blank=True,
50         null=True, 
51         db_index=True,
52         verbose_name = 'Short Name')
53     notes = models.TextField(blank=True)
54
55     def __unicode__(self):
56         return unicode(self.condition_name)
57
58     class Meta:
59         ordering = ["condition_name"]
60
61 class Tag(models.Model): 
62   tag_name = models.CharField(max_length=100, db_index=True,blank=False,null=False) 
63   TAG_CONTEXT = ( 
64       #('Antibody','Antibody'), 
65       #('Cellline', 'Cellline'), 
66       #('Condition', 'Condition'), 
67       ('Library', 'Library'), 
68       ('ANY','ANY'), 
69   ) 
70   context = models.CharField(max_length=50, 
71       choices=TAG_CONTEXT, default='Library') 
72  
73   def __unicode__(self): 
74     return u'%s' % (self.tag_name) 
75  
76   class Meta: 
77     ordering = ["context","tag_name"] 
78  
79 class Species(models.Model):
80   scientific_name = models.CharField(max_length=256, 
81       unique=False, 
82       db_index=True
83   )
84   common_name = models.CharField(max_length=256, blank=True)
85   #use_genome_build = models.CharField(max_length=100, blank=False, null=False)
86
87   def __unicode__(self):
88     return u'%s (%s)' % (self.scientific_name, self.common_name)
89   
90   class Meta:
91     verbose_name_plural = "species"
92     ordering = ["scientific_name"]
93   
94 class Affiliation(models.Model):
95   name = models.CharField(max_length=256, db_index=True, verbose_name='Group Name')
96   contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Contact Name')  
97   email = models.EmailField(null=True,blank=True)
98   
99   def __unicode__(self):
100     str = unicode(self.name)
101     if self.contact is not None and len(self.contact) > 0:
102       str += u' ('+self.contact+u')' 
103     return str
104
105   class Meta:
106     ordering = ["name","contact"]
107     unique_together = (("name", "contact"),)
108
109 class Library(models.Model):
110   id = models.AutoField(primary_key=True)
111   library_id = models.CharField(max_length=30, db_index=True)
112   library_name = models.CharField(max_length=100, unique=True)
113   library_species = models.ForeignKey(Species)
114   cell_line = models.ForeignKey(Cellline)
115   condition = models.ForeignKey(Condition)
116   antibody = models.ForeignKey(Antibody,blank=True,null=True)
117   # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256)  NULL;
118   affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True)
119   # new field Nov/14/08
120   tags = models.ManyToManyField(Tag,related_name='library_tags',blank=True,null=True)
121   # New field Aug/19/08
122   # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
123   REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
124   replicate =  models.PositiveSmallIntegerField(choices=REPLICATE_NUM,default=1) 
125
126   EXPERIMENT_TYPES = (
127       ('INPUT_RXLCh','INPUT_RXLCh'),
128       ('ChIP-seq', 'ChIP-seq'),
129       ('Sheared', 'Sheared'),
130       ('RNA-seq', 'RNA-seq'),
131       ('Methyl-seq', 'Methyl-seq'),
132       ('DIP-seq', 'DIP-seq'),
133     ) 
134   experiment_type = models.CharField(max_length=50, choices=EXPERIMENT_TYPES,
135                                      default='RNA-seq')
136   
137   creation_date = models.DateField(blank=True, null=True)
138   made_for = models.CharField(max_length=50, blank=True, 
139       verbose_name='ChIP/DNA/RNA Made By')
140   made_by = models.CharField(max_length=50, blank=True, default="Lorian")
141   
142   PROTOCOL_END_POINTS = (
143       ('?', 'Unknown'),
144       ('Sample', 'Raw sample'),
145       ('Progress', 'In progress'),
146       ('1A', 'Ligation, then gel'),
147       ('PCR', 'Ligation, then PCR'),
148       ('1Ab', 'Ligation, PCR, then gel'),
149       ('1Aa', 'Ligation, gel, then PCR'),
150       ('2A', 'Ligation, PCR, gel, PCR'),
151       ('Done', 'Completed'),
152     )
153   stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done')
154   amplified_from_sample = models.ForeignKey('self', blank=True, null=True)  
155   
156   undiluted_concentration = models.DecimalField("Concentration", 
157       max_digits=5, decimal_places=2, default=0, blank=True, null=True,
158       help_text="Undiluted concentration (ng/ul)")
159   successful_pM = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
160   ten_nM_dilution = models.BooleanField()
161   avg_lib_size = models.IntegerField(default=225, blank=True, null=True)
162   notes = models.TextField(blank=True)
163   
164   def __unicode__(self):
165     return u'#%s: %s' % (self.library_id, self.library_name)
166   
167   class Meta:
168     verbose_name_plural = "libraries"
169     ordering = ["-creation_date"] #["-library_id"]
170   
171   def antibody_name(self):
172     str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.nickname+'</a>' 
173     return str
174   antibody_name.allow_tags = True
175
176   def organism(self):
177     return self.library_species.common_name
178
179   def affiliation(self):
180     affs = self.affiliations.all().order_by('name')
181     tstr = ''
182     ar = []
183     for t in affs:
184         ar.append(t.__unicode__())
185     return '%s' % (", ".join(ar))
186
187   def libtags(self):
188     affs = self.tags.all().order_by('tag_name')
189     ar = []
190     for t in affs:
191       ar.append(t.__unicode__())
192     return u'%s' % ( ", ".join(ar))
193
194   def DataRun(self):
195     str ='<a target=_self href="/admin/experiments/datarun/?q='+self.library_id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>' 
196     return str
197   DataRun.allow_tags = True
198
199   def aligned_m_reads(self):
200     return getLibReads(self.library_id)
201
202   def aligned_reads(self):
203     res = getLibReads(self.library_id)
204
205     # Check data sanity
206     if res[2] != "OK":
207       return u'<div style="border:solid red 2px">'+res[2]+'</div>'
208
209     rc = "%1.2f" % (res[1]/1000000.0)
210     # Color Scheme: green is more than 10M, blue is more than 5M, orange is more than 3M and red is less. For RNAseq, all those thresholds should be doubled
211     if res[0] > 0:
212       bgcolor = '#ff3300'  # Red
213       rc_thr = [10000000,5000000,3000000]
214       if self.experiment_type == 'RNA-seq':
215         rc_thr = [20000000,10000000,6000000]
216
217       if res[1] > rc_thr[0]:
218         bgcolor = '#66ff66'  # Green
219       else:
220         if res[1] > rc_thr[1]:
221           bgcolor ='#00ccff'  # Blue
222         else:
223            if res[1] > rc_thr[2]: 
224              bgcolor ='#ffcc33'  # Orange
225       tstr = '<div style="background-color:'+bgcolor+';color:black">'
226       tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
227       tstr += '</div>'
228     else: tstr = 'not processed yet' 
229     return tstr
230   aligned_reads.allow_tags = True
231