Make the public library browsing page support several features from
[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   # new field 2008 Mar 5, alter table samples_library add column "hidden" NOT NULL default 0;
122   hidden = models.BooleanField()
123   cell_line = models.ForeignKey(Cellline)
124   condition = models.ForeignKey(Condition)
125   antibody = models.ForeignKey(Antibody,blank=True,null=True)
126   # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256)  NULL;
127   affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True)
128   # new field Nov/14/08
129   tags = models.ManyToManyField(Tag,related_name='library_tags',blank=True,null=True)
130   # New field Aug/19/08
131   # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
132   REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
133   replicate =  models.PositiveSmallIntegerField(choices=REPLICATE_NUM,default=1) 
134   experiment_type = models.ForeignKey(ExperimentType)
135   creation_date = models.DateField(blank=True, null=True)
136   made_for = models.CharField(max_length=50, blank=True, 
137       verbose_name='ChIP/DNA/RNA Made By')
138   made_by = models.CharField(max_length=50, blank=True, default="Lorian")
139   
140   PROTOCOL_END_POINTS = (
141       ('?', 'Unknown'),
142       ('Sample', 'Raw sample'),
143       ('Progress', 'In progress'),
144       ('1A', 'Ligation, then gel'),
145       ('PCR', 'Ligation, then PCR'),
146       ('1Ab', 'Ligation, PCR, then gel'),
147       ('1Aa', 'Ligation, gel, then PCR'),
148       ('2A', 'Ligation, PCR, gel, PCR'),
149       ('Done', 'Completed'),
150     )
151   stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done')
152   amplified_from_sample = models.ForeignKey('self', blank=True, null=True)  
153   
154   undiluted_concentration = models.DecimalField("Concentration", 
155       max_digits=5, decimal_places=2, default=0, blank=True, null=True,
156       help_text=u"Undiluted concentration (ng/\u00b5l)") 
157       # note \u00b5 is the micro symbol in unicode
158   successful_pM = models.DecimalField(max_digits=9, decimal_places=1, blank=True, null=True)
159   ten_nM_dilution = models.BooleanField()
160   avg_lib_size = models.IntegerField(default=225, blank=True, null=True)
161   notes = models.TextField(blank=True)
162   
163   def __unicode__(self):
164     return u'#%s: %s' % (self.library_id, self.library_name)
165   
166   class Meta:
167     verbose_name_plural = "libraries"
168     ordering = ["-creation_date"] #["-library_id"]
169   
170   def antibody_name(self):
171     str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.nickname+'</a>' 
172     return str
173   antibody_name.allow_tags = True
174
175   def organism(self):
176     return self.library_species.common_name
177
178   def affiliation(self):
179     affs = self.affiliations.all().order_by('name')
180     tstr = ''
181     ar = []
182     for t in affs:
183         ar.append(t.__unicode__())
184     return '%s' % (", ".join(ar))
185
186   def libtags(self):
187     affs = self.tags.all().order_by('tag_name')
188     ar = []
189     for t in affs:
190       ar.append(t.__unicode__())
191     return u'%s' % ( ", ".join(ar))
192
193   def DataRun(self):
194     str ='<a target=_self href="/admin/experiments/datarun/?q='+self.library_id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>' 
195     return str
196   DataRun.allow_tags = True
197
198   def aligned_m_reads(self):
199     return getLibReads(self.library_id)
200
201   def aligned_reads(self):
202     res = getLibReads(self.library_id)
203
204     # Check data sanity
205     if res[2] != "OK":
206       return u'<div style="border:solid red 2px">'+res[2]+'</div>'
207
208     rc = "%1.2f" % (res[1]/1000000.0)
209     # 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
210     if res[0] > 0:
211       bgcolor = '#ff3300'  # Red
212       rc_thr = [10000000,5000000,3000000]
213       if self.experiment_type == 'RNA-seq':
214         rc_thr = [20000000,10000000,6000000]
215
216       if res[1] > rc_thr[0]:
217         bgcolor = '#66ff66'  # Green
218       else:
219         if res[1] > rc_thr[1]:
220           bgcolor ='#00ccff'  # Blue
221         else:
222            if res[1] > rc_thr[2]: 
223              bgcolor ='#ffcc33'  # Orange
224       tstr = '<div style="background-color:'+bgcolor+';color:black">'
225       tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
226       tstr += '</div>'
227     else: tstr = 'not processed yet' 
228     return tstr
229   aligned_reads.allow_tags = True
230
231   def public(self):
232     SITE_ROOT = '/'
233     summary_url = self.get_absolute_url()
234     return '<a href="%s">S</a>' % (summary_url,)
235   public.allow_tags = True
236
237   @models.permalink
238   def get_absolute_url(self):
239     return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.id)])