Add a custom (inherited) user object named HTSUser to the samples 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, UserManager
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='Name')
103   contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name')  
104   email = models.EmailField(null=True,blank=True)
105   users = models.ManyToManyField('HTSUser', null=True)
106   users.admin_order_field = "username"
107   
108   def __unicode__(self):
109     str = unicode(self.name)
110     if self.contact is not None and len(self.contact) > 0:
111       str += u' ('+self.contact+u')' 
112     return str
113
114   def Users(self):
115       users = self.users.all().order_by('username')
116       return ", ".join([unicode(a) for a in users ])
117
118   class Meta:
119     ordering = ["name","contact"]
120     unique_together = (("name", "contact"),)
121
122 class LibraryType(models.Model):
123   name = models.CharField(max_length=255, unique=True)
124
125   def __unicode__(self):
126     return unicode(self.name)
127
128 class Library(models.Model):
129   id = models.AutoField(primary_key=True)
130   library_id = models.CharField(max_length=30, db_index=True, unique=True)
131   library_name = models.CharField(max_length=100, unique=True)
132   library_species = models.ForeignKey(Species)
133   # new field 2008 Mar 5, alter table samples_library add column "hidden" NOT NULL default 0;
134   hidden = models.BooleanField()
135   cell_line = models.ForeignKey(Cellline, blank=True, null=True, verbose_name="Background")
136   condition = models.ForeignKey(Condition, blank=True, null=True)
137   antibody = models.ForeignKey(Antibody,blank=True,null=True)
138   # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256)  NULL;
139   affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True)
140   # new field Nov/14/08
141   tags = models.ManyToManyField(Tag,related_name='library_tags',blank=True,null=True)
142   # New field Aug/19/08
143   # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
144   REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
145   replicate =  models.PositiveSmallIntegerField(choices=REPLICATE_NUM,default=1) 
146   experiment_type = models.ForeignKey(ExperimentType)
147   library_type = models.ForeignKey(LibraryType, blank=True, null=True)
148   creation_date = models.DateField(blank=True, null=True)
149   made_for = models.CharField(max_length=50, blank=True, 
150       verbose_name='ChIP/DNA/RNA Made By')
151   made_by = models.CharField(max_length=50, blank=True, default="Lorian")
152   
153   PROTOCOL_END_POINTS = (
154       ('?', 'Unknown'),
155       ('Sample', 'Raw sample'),
156       ('Progress', 'In progress'),
157       ('1A', 'Ligation, then gel'),
158       ('PCR', 'Ligation, then PCR'),
159       ('1Ab', 'Ligation, PCR, then gel'),
160       ('1Aa', 'Ligation, gel, then PCR'),
161       ('2A', 'Ligation, PCR, gel, PCR'),
162       ('Done', 'Completed'),
163     )
164   stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done')
165   amplified_from_sample = models.ForeignKey('self', blank=True, null=True, related_name='amplified_into_sample')  
166   
167   undiluted_concentration = models.DecimalField("Concentration", 
168       max_digits=5, decimal_places=2, blank=True, null=True,
169       help_text=u"Undiluted concentration (ng/\u00b5l)") 
170       # note \u00b5 is the micro symbol in unicode
171   successful_pM = models.DecimalField(max_digits=9, decimal_places=1, blank=True, null=True)
172   ten_nM_dilution = models.BooleanField()
173   avg_lib_size = models.IntegerField(default=225, blank=True, null=True)
174   notes = models.TextField(blank=True)
175   
176   def __unicode__(self):
177     return u'#%s: %s' % (self.library_id, self.library_name)
178   
179   class Meta:
180     verbose_name_plural = "libraries"
181     #ordering = ["-creation_date"] 
182     ordering = ["-library_id"]
183   
184   def antibody_name(self):
185     str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.nickname+'</a>' 
186     return str
187   antibody_name.allow_tags = True
188
189   def organism(self):
190     return self.library_species.common_name
191
192   def affiliation(self):
193     affs = self.affiliations.all().order_by('name')
194     tstr = ''
195     ar = []
196     for t in affs:
197         ar.append(t.__unicode__())
198     return '%s' % (", ".join(ar))
199     
200   def is_archived(self):
201     """
202     returns True if archived else False
203     """
204     if self.longtermstorage_set.count() > 0:
205         return True
206     else:
207         return False
208
209   def libtags(self):
210     affs = self.tags.all().order_by('tag_name')
211     ar = []
212     for t in affs:
213       ar.append(t.__unicode__())
214     return u'%s' % ( ", ".join(ar))
215
216   def DataRun(self):
217     str ='<a target=_self href="/admin/experiments/datarun/?q='+self.library_id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>' 
218     return str
219   DataRun.allow_tags = True
220
221   def aligned_m_reads(self):
222     return getLibReads(self.library_id)
223
224   def aligned_reads(self):
225     res = getLibReads(self.library_id)
226
227     # Check data sanity
228     if res[2] != "OK":
229       return u'<div style="border:solid red 2px">'+res[2]+'</div>'
230
231     rc = "%1.2f" % (res[1]/1000000.0)
232     # 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
233     if res[0] > 0:
234       bgcolor = '#ff3300'  # Red
235       rc_thr = [10000000,5000000,3000000]
236       if self.experiment_type == 'RNA-seq':
237         rc_thr = [20000000,10000000,6000000]
238
239       if res[1] > rc_thr[0]:
240         bgcolor = '#66ff66'  # Green
241       else:
242         if res[1] > rc_thr[1]:
243           bgcolor ='#00ccff'  # Blue
244         else:
245            if res[1] > rc_thr[2]: 
246              bgcolor ='#ffcc33'  # Orange
247       tstr = '<div style="background-color:'+bgcolor+';color:black">'
248       tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
249       tstr += '</div>'
250     else: tstr = 'not processed yet' 
251     return tstr
252   aligned_reads.allow_tags = True
253
254   def public(self):
255     SITE_ROOT = '/'
256     summary_url = self.get_absolute_url()
257     return '<a href="%s">S</a>' % (summary_url,)
258   public.allow_tags = True
259
260   @models.permalink
261   def get_absolute_url(self):
262     return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.library_id)])
263
264 class HTSUser(User):
265     """
266     Provide some site-specific customization for the django user class
267     """
268     #objects = UserManager()
269
270     class Meta:
271         ordering = ['username']
272