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(
23 verbose_name = 'Short Name'
25 catalog = models.CharField(max_length=50, unique=True, db_index=True)
26 antibodies = models.CharField(max_length=500, db_index=True)
27 source = models.CharField(max_length=500, blank=True, db_index=True)
28 biology = models.TextField(blank=True)
29 notes = models.TextField(blank=True)
30 def __unicode__(self):
31 return u'%s - %s (%s)' % (self.antigene, self.antibodies, self.catalog)
33 verbose_name_plural = "antibodies"
34 ordering = ["antigene"]
36 class Cellline(models.Model):
37 cellline_name = models.CharField(max_length=100, unique=True, db_index=True)
38 nickname = models.CharField(max_length=20,
42 verbose_name = 'Short Name')
43 notes = models.TextField(blank=True)
44 def __unicode__(self):
45 return unicode(self.cellline_name)
48 ordering = ["cellline_name"]
50 class Condition(models.Model):
51 condition_name = models.CharField(
52 max_length=2000, unique=True, db_index=True)
53 nickname = models.CharField(max_length=20,
57 verbose_name = 'Short Name')
58 notes = models.TextField(blank=True)
60 def __unicode__(self):
61 return unicode(self.condition_name)
64 ordering = ["condition_name"]
66 class ExperimentType(models.Model):
67 name = models.CharField(max_length=50, unique=True)
69 def __unicode__(self):
70 return unicode(self.name)
72 class Tag(models.Model):
73 tag_name = models.CharField(max_length=100, db_index=True,blank=False,null=False)
75 #('Antibody','Antibody'),
76 #('Cellline', 'Cellline'),
77 #('Condition', 'Condition'),
78 ('Library', 'Library'),
81 context = models.CharField(max_length=50,
82 choices=TAG_CONTEXT, default='Library')
84 def __unicode__(self):
85 return u'%s' % (self.tag_name)
88 ordering = ["context","tag_name"]
90 class Species(models.Model):
91 scientific_name = models.CharField(max_length=256,
95 common_name = models.CharField(max_length=256, blank=True)
96 #use_genome_build = models.CharField(max_length=100, blank=False, null=False)
98 def __unicode__(self):
99 return u'%s (%s)' % (self.scientific_name, self.common_name)
102 verbose_name_plural = "species"
103 ordering = ["scientific_name"]
106 def get_absolute_url(self):
107 return ('htsworkflow.frontend.samples.views.species', [str(self.id)])
109 class Affiliation(models.Model):
110 name = models.CharField(max_length=256, db_index=True, verbose_name='Name')
111 contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name')
112 email = models.EmailField(null=True,blank=True)
113 users = models.ManyToManyField('HTSUser', null=True, blank=True)
114 users.admin_order_field = "username"
116 def __unicode__(self):
117 str = unicode(self.name)
118 if self.contact is not None and len(self.contact) > 0:
119 str += u' ('+self.contact+u')'
123 users = self.users.all().order_by('username')
124 return ", ".join([unicode(a) for a in users ])
127 ordering = ["name","contact"]
128 unique_together = (("name", "contact"),)
130 class LibraryType(models.Model):
131 name = models.CharField(max_length=255, unique=True)
133 def __unicode__(self):
134 return unicode(self.name)
137 class Library(models.Model):
138 id = models.CharField(max_length=10, primary_key=True)
139 library_name = models.CharField(max_length=100, unique=True)
140 library_species = models.ForeignKey(Species)
141 # new field 2008 Mar 5, alter table samples_library add column "hidden" NOT NULL default 0;
142 hidden = models.BooleanField()
143 # new field 2009 Oct 6, alter table samples_library add column "account_number" varchar(100) NULL
144 account_number = models.CharField(max_length=100, null=True, blank=True)
145 cell_line = models.ForeignKey(Cellline, blank=True, null=True, verbose_name="Background")
146 condition = models.ForeignKey(Condition, blank=True, null=True)
147 antibody = models.ForeignKey(Antibody,blank=True,null=True)
148 # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256) NULL;
149 affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True)
150 # new field Nov/14/08
151 tags = models.ManyToManyField(Tag,related_name='library_tags',blank=True,null=True)
152 # New field Aug/19/08
153 # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
154 REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
155 replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM,default=1)
156 experiment_type = models.ForeignKey(ExperimentType)
157 library_type = models.ForeignKey(LibraryType, blank=True, null=True)
158 creation_date = models.DateField(blank=True, null=True)
159 made_for = models.CharField(max_length=50, blank=True,
160 verbose_name='ChIP/DNA/RNA Made By')
161 made_by = models.CharField(max_length=50, blank=True, default="Lorian")
163 PROTOCOL_END_POINTS = (
165 ('Sample', 'Raw sample'),
166 ('Progress', 'In progress'),
167 ('1A', 'Ligation, then gel'),
168 ('PCR', 'Ligation, then PCR'),
169 ('1Ab', 'Ligation, PCR, then gel'),
170 ('1Ac', 'Ligation, gel, then 12x PCR'),
171 ('1Aa', 'Ligation, gel, then 18x PCR'),
172 ('2A', 'Ligation, PCR, gel, PCR'),
173 ('Done', 'Completed'),
175 PROTOCOL_END_POINTS_DICT = dict(PROTOCOL_END_POINTS)
177 stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done')
178 amplified_from_sample = models.ForeignKey('self', blank=True, null=True, related_name='amplified_into_sample')
180 undiluted_concentration = models.DecimalField("Concentration",
181 max_digits=5, decimal_places=2, blank=True, null=True,
182 help_text=u"Undiluted concentration (ng/\u00b5l)")
183 # note \u00b5 is the micro symbol in unicode
184 successful_pM = models.DecimalField(max_digits=9, decimal_places=1, blank=True, null=True)
185 ten_nM_dilution = models.BooleanField()
186 gel_cut_size = models.IntegerField(default=225, blank=True, null=True)
187 insert_size = models.IntegerField(blank=True, null=True)
188 notes = models.TextField(blank=True)
190 bioanalyzer_summary = models.TextField(blank=True,default="")
191 bioanalyzer_concentration = models.DecimalField(max_digits=5,
192 decimal_places=2, blank=True, null=True,
193 help_text=u"(ng/\u00b5l)")
194 bioanalyzer_image_url = models.URLField(blank=True,default="")
196 def __unicode__(self):
197 return u'#%s: %s' % (self.id, self.library_name)
200 verbose_name_plural = "libraries"
201 #ordering = ["-creation_date"]
204 def antibody_name(self):
205 str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.nickname+'</a>'
207 antibody_name.allow_tags = True
210 return self.library_species.common_name
212 def affiliation(self):
213 affs = self.affiliations.all().order_by('name')
217 ar.append(t.__unicode__())
218 return '%s' % (", ".join(ar))
220 def is_archived(self):
222 returns True if archived else False
224 if self.longtermstorage_set.count() > 0:
229 def stopping_point_name(self):
230 end_points = Library.PROTOCOL_END_POINTS_DICT
231 name = end_points.get(self.stopping_point, None)
233 name = "Lookup Error"
234 logger.error("protocol stopping point in database didn't match names in library model")
239 affs = self.tags.all().order_by('tag_name')
242 ar.append(t.__unicode__())
243 return u'%s' % ( ", ".join(ar))
246 str ='<a target=_self href="/admin/experiments/datarun/?q='+self.id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>'
248 DataRun.allow_tags = True
250 def aligned_m_reads(self):
251 return getLibReads(self.id)
253 def aligned_reads(self):
254 res = getLibReads(self.id)
258 return u'<div style="border:solid red 2px">'+res[2]+'</div>'
260 rc = "%1.2f" % (res[1]/1000000.0)
261 # 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
263 bgcolor = '#ff3300' # Red
264 rc_thr = [10000000,5000000,3000000]
265 if self.experiment_type == 'RNA-seq':
266 rc_thr = [20000000,10000000,6000000]
268 if res[1] > rc_thr[0]:
269 bgcolor = '#66ff66' # Green
271 if res[1] > rc_thr[1]:
272 bgcolor ='#00ccff' # Blue
274 if res[1] > rc_thr[2]:
275 bgcolor ='#ffcc33' # Orange
276 tstr = '<div style="background-color:'+bgcolor+';color:black">'
277 tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
279 else: tstr = 'not processed yet'
281 aligned_reads.allow_tags = True
285 summary_url = self.get_absolute_url()
286 return '<a href="%s">S</a>' % (summary_url,)
287 public.allow_tags = True
290 def get_absolute_url(self):
291 return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.id)])
296 Provide some site-specific customization for the django user class
298 #objects = UserManager()
301 ordering = ['first_name', 'last_name', 'username']
304 return '/admin/%s/%s/%d' % (self._meta.app_label, self._meta.module_name, self.id)
306 def __unicode__(self):
307 #return unicode(self.username) + u" (" + unicode(self.get_full_name()) + u")"
308 return unicode(self.get_full_name()) + u' (' + unicode(self.username) + ')'
310 def HTSUserInsertID(sender, instance, **kwargs):
312 Force addition of HTSUsers when someone just modifies the auth_user object
314 u = HTSUser.objects.filter(pk=instance.id)
316 cursor = connection.cursor()
317 cursor.execute('INSERT INTO samples_htsuser (user_ptr_id) VALUES (%s);' % (instance.id,))
320 post_save.connect(HTSUserInsertID, sender=User)