Updated Library view to show an icon if a record exists showing that the library...
[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='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   
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, unique=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, null=True)
124   condition = models.ForeignKey(Condition, null=True)
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, related_name='amplified_into_sample')  
153   
154   undiluted_concentration = models.DecimalField("Concentration", 
155       max_digits=5, decimal_places=2, 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"] 
169     ordering = ["-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 is_archived(self):
188     """
189     returns True if archived else False
190     """
191     if self.longtermstorage_set.count() > 0:
192         return True
193     else:
194         return False
195
196   def libtags(self):
197     affs = self.tags.all().order_by('tag_name')
198     ar = []
199     for t in affs:
200       ar.append(t.__unicode__())
201     return u'%s' % ( ", ".join(ar))
202
203   def DataRun(self):
204     str ='<a target=_self href="/admin/experiments/datarun/?q='+self.library_id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>' 
205     return str
206   DataRun.allow_tags = True
207
208   def aligned_m_reads(self):
209     return getLibReads(self.library_id)
210
211   def aligned_reads(self):
212     res = getLibReads(self.library_id)
213
214     # Check data sanity
215     if res[2] != "OK":
216       return u'<div style="border:solid red 2px">'+res[2]+'</div>'
217
218     rc = "%1.2f" % (res[1]/1000000.0)
219     # 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
220     if res[0] > 0:
221       bgcolor = '#ff3300'  # Red
222       rc_thr = [10000000,5000000,3000000]
223       if self.experiment_type == 'RNA-seq':
224         rc_thr = [20000000,10000000,6000000]
225
226       if res[1] > rc_thr[0]:
227         bgcolor = '#66ff66'  # Green
228       else:
229         if res[1] > rc_thr[1]:
230           bgcolor ='#00ccff'  # Blue
231         else:
232            if res[1] > rc_thr[2]: 
233              bgcolor ='#ffcc33'  # Orange
234       tstr = '<div style="background-color:'+bgcolor+';color:black">'
235       tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
236       tstr += '</div>'
237     else: tstr = 'not processed yet' 
238     return tstr
239   aligned_reads.allow_tags = True
240
241   def public(self):
242     SITE_ROOT = '/'
243     summary_url = self.get_absolute_url()
244     return '<a href="%s">S</a>' % (summary_url,)
245   public.allow_tags = True
246
247   @models.permalink
248   def get_absolute_url(self):
249     return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.library_id)])