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