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