3 from django.db import models
4 from django.contrib.auth.models import User, UserManager
5 from django.db.models.signals import pre_save, post_save
6 from django.db import connection
7 from htsworkflow.frontend.reports.libinfopar import *
10 # Create your models here.
11 logger = logging.getLogger(__name__)
13 class Antibody(models.Model):
14 antigene = models.CharField(max_length=500, db_index=True)
17 # alter table fctracker_antibody add column "nickname" varchar(20) NULL;
18 nickname = models.CharField(
24 catalog = models.CharField(max_length=50, unique=True, db_index=True)
25 antibodies = models.CharField(max_length=500, db_index=True)
26 source = models.CharField(max_length=500, blank=True, db_index=True)
27 biology = models.TextField(blank=True)
28 notes = models.TextField(blank=True)
29 def __unicode__(self):
30 return u'%s - %s (%s)' % (self.antigene, self.antibodies, self.catalog)
32 verbose_name_plural = "antibodies"
33 ordering = ["antigene"]
35 class Cellline(models.Model):
36 cellline_name = models.CharField(max_length=100, unique=True, db_index=True)
37 nickname = models.CharField(max_length=20,
42 notes = models.TextField(blank=True)
43 def __unicode__(self):
44 return unicode(self.cellline_name)
47 ordering = ["cellline_name"]
49 class Condition(models.Model):
50 condition_name = models.CharField(
51 max_length=2000, unique=True, db_index=True)
52 nickname = models.CharField(max_length=20,
56 verbose_name = 'Short Name')
57 notes = models.TextField(blank=True)
59 def __unicode__(self):
60 return unicode(self.condition_name)
63 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 # new field 2008 Mar 5, alter table samples_library add column "hidden" NOT NULL default 0;
141 hidden = models.BooleanField()
142 # new field 2009 Oct 6, alter table samples_library add column "account_number" varchar(100) NULL
143 account_number = models.CharField(max_length=100, null=True, blank=True)
144 cell_line = models.ForeignKey(Cellline, blank=True, null=True, verbose_name="Background")
145 condition = models.ForeignKey(Condition, blank=True, null=True)
146 antibody = models.ForeignKey(Antibody,blank=True,null=True)
147 # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256) NULL;
148 affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True)
149 # new field Nov/14/08
150 tags = models.ManyToManyField(Tag,related_name='library_tags',blank=True,null=True)
151 # New field Aug/19/08
152 # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
153 REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
154 replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM,blank=True,null=True)
155 experiment_type = models.ForeignKey(ExperimentType)
156 library_type = models.ForeignKey(LibraryType, blank=True, null=True)
157 creation_date = models.DateField(blank=True, null=True)
158 made_for = models.CharField(max_length=50, blank=True,
159 verbose_name='ChIP/DNA/RNA Made By')
160 made_by = models.CharField(max_length=50, blank=True, default="Lorian")
162 PROTOCOL_END_POINTS = (
164 ('Sample', 'Raw sample'),
165 ('Progress', 'In progress'),
166 ('1A', 'Ligation, then gel'),
167 ('PCR', 'Ligation, then PCR'),
168 ('1Ab', 'Ligation, PCR, then gel'),
169 ('1Ac', 'Ligation, gel, then 12x PCR'),
170 ('1Aa', 'Ligation, gel, then 18x PCR'),
171 ('2A', 'Ligation, PCR, gel, PCR'),
172 ('Done', 'Completed'),
174 PROTOCOL_END_POINTS_DICT = dict(PROTOCOL_END_POINTS)
176 stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done')
177 amplified_from_sample = models.ForeignKey('self', blank=True, null=True, related_name='amplified_into_sample')
179 undiluted_concentration = models.DecimalField("Concentration",
180 max_digits=5, decimal_places=2, blank=True, null=True,
181 help_text=u"Undiluted concentration (ng/\u00b5l)")
182 # note \u00b5 is the micro symbol in unicode
183 successful_pM = models.DecimalField(max_digits=9, decimal_places=1, blank=True, null=True)
184 ten_nM_dilution = models.BooleanField()
185 gel_cut_size = models.IntegerField(default=225, blank=True, null=True)
186 insert_size = models.IntegerField(blank=True, null=True)
187 notes = models.TextField(blank=True)
189 bioanalyzer_summary = models.TextField(blank=True,default="")
190 bioanalyzer_concentration = models.DecimalField(max_digits=5,
191 decimal_places=2, blank=True, null=True,
192 help_text=u"(ng/\u00b5l)")
193 bioanalyzer_image_url = models.URLField(blank=True,default="")
195 def __unicode__(self):
196 return u'#%s: %s' % (self.id, self.library_name)
199 verbose_name_plural = "libraries"
200 #ordering = ["-creation_date"]
203 def antibody_name(self):
204 str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.label+'</a>'
206 antibody_name.allow_tags = True
209 return self.library_species.common_name
211 def affiliation(self):
212 affs = self.affiliations.all().order_by('name')
216 ar.append(t.__unicode__())
217 return '%s' % (", ".join(ar))
219 def is_archived(self):
221 returns True if archived else False
223 if self.longtermstorage_set.count() > 0:
228 def stopping_point_name(self):
229 end_points = Library.PROTOCOL_END_POINTS_DICT
230 name = end_points.get(self.stopping_point, None)
232 name = "Lookup Error"
233 logger.error("protocol stopping point in database didn't match names in library model")
238 affs = self.tags.all().order_by('tag_name')
241 ar.append(t.__unicode__())
242 return u'%s' % ( ", ".join(ar))
245 str ='<a target=_self href="/admin/experiments/datarun/?q='+self.id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>'
247 DataRun.allow_tags = True
249 def aligned_m_reads(self):
250 return getLibReads(self.id)
252 def aligned_reads(self):
253 res = getLibReads(self.id)
257 return u'<div style="border:solid red 2px">'+res[2]+'</div>'
259 rc = "%1.2f" % (res[1]/1000000.0)
260 # 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
262 bgcolor = '#ff3300' # Red
263 rc_thr = [10000000,5000000,3000000]
264 if self.experiment_type == 'RNA-seq':
265 rc_thr = [20000000,10000000,6000000]
267 if res[1] > rc_thr[0]:
268 bgcolor = '#66ff66' # Green
270 if res[1] > rc_thr[1]:
271 bgcolor ='#00ccff' # Blue
273 if res[1] > rc_thr[2]:
274 bgcolor ='#ffcc33' # Orange
275 tstr = '<div style="background-color:'+bgcolor+';color:black">'
276 tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
278 else: tstr = 'not processed yet'
280 aligned_reads.allow_tags = True
284 summary_url = self.get_absolute_url()
285 return '<a href="%s">S</a>' % (summary_url,)
286 public.allow_tags = True
289 def get_absolute_url(self):
290 return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.id)])
295 Provide some site-specific customization for the django user class
297 #objects = UserManager()
300 ordering = ['first_name', 'last_name', 'username']
303 return '/admin/%s/%s/%d' % (self._meta.app_label, self._meta.module_name, self.id)
305 def __unicode__(self):
306 #return unicode(self.username) + u" (" + unicode(self.get_full_name()) + u")"
307 return unicode(self.get_full_name()) + u' (' + unicode(self.username) + ')'
309 def HTSUserInsertID(sender, instance, **kwargs):
311 Force addition of HTSUsers when someone just modifies the auth_user object
313 u = HTSUser.objects.filter(pk=instance.id)
315 cursor = connection.cursor()
316 cursor.execute('INSERT INTO samples_htsuser (user_ptr_id) VALUES (%s);' % (instance.id,))
319 post_save.connect(HTSUserInsertID, sender=User)