3 from django.db import models
4 from django.contrib.auth.models import User, UserManager
5 from django.core import urlresolvers
6 from django.db.models.signals import pre_save, post_save
7 from django.db import connection
8 from htsworkflow.frontend.reports.libinfopar import *
10 logger = logging.getLogger(__name__)
12 class Antibody(models.Model):
13 antigene = models.CharField(max_length=500, db_index=True)
16 # alter table fctracker_antibody add column "nickname" varchar(20) NULL;
17 nickname = models.CharField(
23 catalog = models.CharField(max_length=50, blank=True, null=True)
24 antibodies = models.CharField(max_length=500, db_index=True)
25 source = models.CharField(max_length=500, blank=True, null=True, db_index=True)
26 biology = models.TextField(blank=True, null=True)
27 notes = models.TextField(blank=True, null=True)
28 def __unicode__(self):
29 return u'%s - %s' % (self.antigene, self.antibodies)
31 verbose_name_plural = "antibodies"
32 ordering = ["antigene"]
34 class Cellline(models.Model):
35 cellline_name = models.CharField(max_length=100, unique=True, db_index=True)
36 nickname = models.CharField(max_length=20,
41 notes = models.TextField(blank=True)
42 def __unicode__(self):
43 return unicode(self.cellline_name)
46 ordering = ["cellline_name"]
48 class Condition(models.Model):
49 condition_name = models.CharField(
50 max_length=2000, unique=True, db_index=True)
51 nickname = models.CharField(max_length=20,
55 verbose_name = 'Short Name')
56 notes = models.TextField(blank=True)
58 def __unicode__(self):
59 return unicode(self.condition_name)
62 ordering = ["condition_name"]
65 class ExperimentType(models.Model):
66 name = models.CharField(max_length=50, unique=True)
68 def __unicode__(self):
69 return unicode(self.name)
71 class Tag(models.Model):
72 tag_name = models.CharField(max_length=100, db_index=True,blank=False,null=False)
74 #('Antibody','Antibody'),
75 #('Cellline', 'Cellline'),
76 #('Condition', 'Condition'),
77 ('Library', 'Library'),
80 context = models.CharField(max_length=50,
81 choices=TAG_CONTEXT, default='Library')
83 def __unicode__(self):
84 return u'%s' % (self.tag_name)
87 ordering = ["context","tag_name"]
89 class Species(models.Model):
90 scientific_name = models.CharField(max_length=256,
94 common_name = models.CharField(max_length=256, blank=True)
95 #use_genome_build = models.CharField(max_length=100, blank=False, null=False)
97 def __unicode__(self):
98 return u'%s (%s)' % (self.scientific_name, self.common_name)
101 verbose_name_plural = "species"
102 ordering = ["scientific_name"]
105 def get_absolute_url(self):
106 return ('htsworkflow.frontend.samples.views.species', [str(self.id)])
108 class Affiliation(models.Model):
109 name = models.CharField(max_length=256, db_index=True, verbose_name='Name')
110 contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name')
111 email = models.EmailField(null=True,blank=True)
112 users = models.ManyToManyField('HTSUser', null=True, blank=True)
113 users.admin_order_field = "username"
115 def __unicode__(self):
116 str = unicode(self.name)
117 if self.contact is not None and len(self.contact) > 0:
118 str += u' ('+self.contact+u')'
122 users = self.users.all().order_by('username')
123 return ", ".join([unicode(a) for a in users ])
126 ordering = ["name","contact"]
127 unique_together = (("name", "contact"),)
129 class LibraryType(models.Model):
130 name = models.CharField(max_length=255, unique=True)
132 def __unicode__(self):
133 return unicode(self.name)
136 class Library(models.Model):
137 id = models.CharField(max_length=10, primary_key=True)
138 library_name = models.CharField(max_length=100, unique=True)
139 library_species = models.ForeignKey(Species)
140 hidden = models.BooleanField()
141 account_number = models.CharField(max_length=100, null=True, blank=True)
142 cell_line = models.ForeignKey(Cellline, blank=True, null=True,
143 verbose_name="Background")
144 condition = models.ForeignKey(Condition, blank=True, null=True)
145 antibody = models.ForeignKey(Antibody,blank=True,null=True)
146 affiliations = models.ManyToManyField(
147 Affiliation,related_name='library_affiliations',null=True)
148 tags = models.ManyToManyField(Tag,related_name='library_tags',
149 blank=True,null=True)
150 REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
151 replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM,
152 blank=True,null=True)
153 experiment_type = models.ForeignKey(ExperimentType)
154 library_type = models.ForeignKey(LibraryType, blank=True, null=True)
155 creation_date = models.DateField(blank=True, null=True)
156 made_for = models.CharField(max_length=50, blank=True,
157 verbose_name='ChIP/DNA/RNA Made By')
158 made_by = models.CharField(max_length=50, blank=True, default="Lorian")
160 PROTOCOL_END_POINTS = (
162 ('Sample', 'Raw sample'),
163 ('Progress', 'In progress'),
164 ('1A', 'Ligation, then gel'),
165 ('PCR', 'Ligation, then PCR'),
166 ('1Ab', 'Ligation, PCR, then gel'),
167 ('1Ac', 'Ligation, gel, then 12x PCR'),
168 ('1Aa', 'Ligation, gel, then 18x PCR'),
169 ('2A', 'Ligation, PCR, gel, PCR'),
170 ('Done', 'Completed'),
172 PROTOCOL_END_POINTS_DICT = dict(PROTOCOL_END_POINTS)
173 stopping_point = models.CharField(max_length=25,
174 choices=PROTOCOL_END_POINTS,
177 amplified_from_sample = models.ForeignKey('self',
178 related_name='amplified_into_sample',
179 blank=True, null=True)
181 undiluted_concentration = models.DecimalField("Concentration",
182 max_digits=5, decimal_places=2, blank=True, null=True,
183 help_text=u"Undiluted concentration (ng/\u00b5l)")
184 # note \u00b5 is the micro symbol in unicode
185 successful_pM = models.DecimalField(max_digits=9,
186 decimal_places=1, blank=True, null=True)
187 ten_nM_dilution = models.BooleanField()
188 gel_cut_size = models.IntegerField(default=225, blank=True, null=True)
189 insert_size = models.IntegerField(blank=True, null=True)
190 notes = models.TextField(blank=True)
192 bioanalyzer_summary = models.TextField(blank=True,default="")
193 bioanalyzer_concentration = models.DecimalField(max_digits=5,
194 decimal_places=2, blank=True, null=True,
195 help_text=u"(ng/\u00b5l)")
196 bioanalyzer_image_url = models.URLField(blank=True,default="")
198 def __unicode__(self):
199 return u'#%s: %s' % (self.id, self.library_name)
202 verbose_name_plural = "libraries"
203 #ordering = ["-creation_date"]
206 def antibody_name(self):
207 str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.label+'</a>'
209 antibody_name.allow_tags = True
212 return self.library_species.common_name
214 def affiliation(self):
215 affs = self.affiliations.all().order_by('name')
219 ar.append(t.__unicode__())
220 return '%s' % (", ".join(ar))
222 def is_archived(self):
224 returns True if archived else False
226 if self.longtermstorage_set.count() > 0:
231 def stopping_point_name(self):
232 end_points = Library.PROTOCOL_END_POINTS_DICT
233 name = end_points.get(self.stopping_point, None)
235 name = "Lookup Error"
236 logger.error("protocol stopping point in database didn't match names in library model")
241 affs = self.tags.all().order_by('tag_name')
244 ar.append(t.__unicode__())
245 return u'%s' % ( ", ".join(ar))
248 str ='<a target=_self href="/admin/experiments/datarun/?q='+self.id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>'
250 DataRun.allow_tags = True
252 def aligned_m_reads(self):
253 return getLibReads(self.id)
255 def aligned_reads(self):
256 res = getLibReads(self.id)
260 return u'<div style="border:solid red 2px">'+res[2]+'</div>'
262 rc = "%1.2f" % (res[1]/1000000.0)
263 # 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
265 bgcolor = '#ff3300' # Red
266 rc_thr = [10000000,5000000,3000000]
267 if self.experiment_type == 'RNA-seq':
268 rc_thr = [20000000,10000000,6000000]
270 if res[1] > rc_thr[0]:
271 bgcolor = '#66ff66' # Green
273 if res[1] > rc_thr[1]:
274 bgcolor ='#00ccff' # Blue
276 if res[1] > rc_thr[2]:
277 bgcolor ='#ffcc33' # Orange
278 tstr = '<div style="background-color:'+bgcolor+';color:black">'
279 tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
281 else: tstr = 'not processed yet'
283 aligned_reads.allow_tags = True
287 summary_url = self.get_absolute_url()
288 return '<a href="%s">S</a>' % (summary_url,)
289 public.allow_tags = True
292 def get_absolute_url(self):
293 return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.id)])
295 def get_admin_url(self):
296 return urlresolvers.reverse('admin:samples_library_change',
301 Provide some site-specific customization for the django user class
303 #objects = UserManager()
306 ordering = ['first_name', 'last_name', 'username']
309 return '/admin/%s/%s/%d' % (self._meta.app_label, self._meta.module_name, self.id)
311 def __unicode__(self):
312 #return unicode(self.username) + u" (" + unicode(self.get_full_name()) + u")"
313 return unicode(self.get_full_name()) + u' (' + unicode(self.username) + ')'
315 def HTSUserInsertID(sender, instance, **kwargs):
317 Force addition of HTSUsers when someone just modifies the auth_user object
319 u = HTSUser.objects.filter(pk=instance.id)
321 cursor = connection.cursor()
322 cursor.execute('INSERT INTO samples_htsuser (user_ptr_id) VALUES (%s);' % (instance.id,))
325 post_save.connect(HTSUserInsertID, sender=User)