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 import settings
8 from htsworkflow.frontend.reports.libinfopar import *
11 # Create your models here.
12 logger = logging.getLogger(__name__)
14 class Antibody(models.Model):
15 antigene = models.CharField(max_length=500, db_index=True)
18 # alter table fctracker_antibody add column "nickname" varchar(20) NULL;
19 nickname = models.CharField(
24 verbose_name = 'Short Name'
26 catalog = models.CharField(max_length=50, unique=True, db_index=True)
27 antibodies = models.CharField(max_length=500, db_index=True)
28 source = models.CharField(max_length=500, blank=True, db_index=True)
29 biology = models.TextField(blank=True)
30 notes = models.TextField(blank=True)
31 def __unicode__(self):
32 return u'%s - %s (%s)' % (self.antigene, self.antibodies, self.catalog)
34 verbose_name_plural = "antibodies"
35 ordering = ["antigene"]
37 class Cellline(models.Model):
38 cellline_name = models.CharField(max_length=100, unique=True, db_index=True)
39 nickname = models.CharField(max_length=20,
43 verbose_name = 'Short Name')
44 notes = models.TextField(blank=True)
45 def __unicode__(self):
46 return unicode(self.cellline_name)
49 ordering = ["cellline_name"]
51 class Condition(models.Model):
52 condition_name = models.CharField(
53 max_length=2000, unique=True, db_index=True)
54 nickname = models.CharField(max_length=20,
58 verbose_name = 'Short Name')
59 notes = models.TextField(blank=True)
61 def __unicode__(self):
62 return unicode(self.condition_name)
65 ordering = ["condition_name"]
67 class ExperimentType(models.Model):
68 name = models.CharField(max_length=50, unique=True)
70 def __unicode__(self):
71 return unicode(self.name)
73 class Tag(models.Model):
74 tag_name = models.CharField(max_length=100, db_index=True,blank=False,null=False)
76 #('Antibody','Antibody'),
77 #('Cellline', 'Cellline'),
78 #('Condition', 'Condition'),
79 ('Library', 'Library'),
82 context = models.CharField(max_length=50,
83 choices=TAG_CONTEXT, default='Library')
85 def __unicode__(self):
86 return u'%s' % (self.tag_name)
89 ordering = ["context","tag_name"]
91 class Species(models.Model):
92 scientific_name = models.CharField(max_length=256,
96 common_name = models.CharField(max_length=256, blank=True)
97 #use_genome_build = models.CharField(max_length=100, blank=False, null=False)
99 def __unicode__(self):
100 return u'%s (%s)' % (self.scientific_name, self.common_name)
103 verbose_name_plural = "species"
104 ordering = ["scientific_name"]
107 def get_absolute_url(self):
108 return ('htsworkflow.frontend.samples.views.species', [str(self.id)])
110 class Affiliation(models.Model):
111 name = models.CharField(max_length=256, db_index=True, verbose_name='Name')
112 contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name')
113 email = models.EmailField(null=True,blank=True)
114 users = models.ManyToManyField('HTSUser', null=True, blank=True)
115 users.admin_order_field = "username"
117 def __unicode__(self):
118 str = unicode(self.name)
119 if self.contact is not None and len(self.contact) > 0:
120 str += u' ('+self.contact+u')'
124 users = self.users.all().order_by('username')
125 return ", ".join([unicode(a) for a in users ])
128 ordering = ["name","contact"]
129 unique_together = (("name", "contact"),)
131 class LibraryType(models.Model):
132 name = models.CharField(max_length=255, unique=True)
134 def __unicode__(self):
135 return unicode(self.name)
138 class Library(models.Model):
139 id = models.CharField(max_length=10, primary_key=True)
140 library_name = models.CharField(max_length=100, unique=True)
141 library_species = models.ForeignKey(Species)
142 # new field 2008 Mar 5, alter table samples_library add column "hidden" NOT NULL default 0;
143 hidden = models.BooleanField()
144 # new field 2009 Oct 6, alter table samples_library add column "account_number" varchar(100) NULL
145 account_number = models.CharField(max_length=100, null=True, blank=True)
146 cell_line = models.ForeignKey(Cellline, blank=True, null=True, verbose_name="Background")
147 condition = models.ForeignKey(Condition, blank=True, null=True)
148 antibody = models.ForeignKey(Antibody,blank=True,null=True)
149 # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256) NULL;
150 affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True)
151 # new field Nov/14/08
152 tags = models.ManyToManyField(Tag,related_name='library_tags',blank=True,null=True)
153 # New field Aug/19/08
154 # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
155 REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
156 replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM,default=1)
157 experiment_type = models.ForeignKey(ExperimentType)
158 library_type = models.ForeignKey(LibraryType, blank=True, null=True)
159 creation_date = models.DateField(blank=True, null=True)
160 made_for = models.CharField(max_length=50, blank=True,
161 verbose_name='ChIP/DNA/RNA Made By')
162 made_by = models.CharField(max_length=50, blank=True, default="Lorian")
164 PROTOCOL_END_POINTS = (
166 ('Sample', 'Raw sample'),
167 ('Progress', 'In progress'),
168 ('1A', 'Ligation, then gel'),
169 ('PCR', 'Ligation, then PCR'),
170 ('1Ab', 'Ligation, PCR, then gel'),
171 ('1Ac', 'Ligation, gel, then 12x PCR'),
172 ('1Aa', 'Ligation, gel, then 18x PCR'),
173 ('2A', 'Ligation, PCR, gel, PCR'),
174 ('Done', 'Completed'),
176 PROTOCOL_END_POINTS_DICT = dict(PROTOCOL_END_POINTS)
178 stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done')
179 amplified_from_sample = models.ForeignKey('self', blank=True, null=True, related_name='amplified_into_sample')
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, decimal_places=1, blank=True, null=True)
186 ten_nM_dilution = models.BooleanField()
187 gel_cut_size = models.IntegerField(default=225, blank=True, null=True)
188 insert_size = models.IntegerField(blank=True, null=True)
189 notes = models.TextField(blank=True)
191 bioanalyzer_summary = models.TextField(blank=True,default="")
192 bioanalyzer_concentration = models.DecimalField(max_digits=5,
193 decimal_places=2, blank=True, null=True,
194 help_text=u"(ng/\u00b5l)")
195 bioanalyzer_image_url = models.URLField(blank=True,default="")
197 def __unicode__(self):
198 return u'#%s: %s' % (self.id, self.library_name)
201 verbose_name_plural = "libraries"
202 #ordering = ["-creation_date"]
205 def antibody_name(self):
206 str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.nickname+'</a>'
208 antibody_name.allow_tags = True
211 return self.library_species.common_name
213 def affiliation(self):
214 affs = self.affiliations.all().order_by('name')
218 ar.append(t.__unicode__())
219 return '%s' % (", ".join(ar))
221 def is_archived(self):
223 returns True if archived else False
225 if self.longtermstorage_set.count() > 0:
230 def stopping_point_name(self):
231 end_points = Library.PROTOCOL_END_POINTS_DICT
232 name = end_points.get(self.stopping_point, None)
234 name = "Lookup Error"
235 logger.error("protocol stopping point in database didn't match names in library model")
240 affs = self.tags.all().order_by('tag_name')
243 ar.append(t.__unicode__())
244 return u'%s' % ( ", ".join(ar))
247 str ='<a target=_self href="/admin/experiments/datarun/?q='+self.id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>'
249 DataRun.allow_tags = True
251 def aligned_m_reads(self):
252 return getLibReads(self.id)
254 def aligned_reads(self):
255 res = getLibReads(self.id)
259 return u'<div style="border:solid red 2px">'+res[2]+'</div>'
261 rc = "%1.2f" % (res[1]/1000000.0)
262 # 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
264 bgcolor = '#ff3300' # Red
265 rc_thr = [10000000,5000000,3000000]
266 if self.experiment_type == 'RNA-seq':
267 rc_thr = [20000000,10000000,6000000]
269 if res[1] > rc_thr[0]:
270 bgcolor = '#66ff66' # Green
272 if res[1] > rc_thr[1]:
273 bgcolor ='#00ccff' # Blue
275 if res[1] > rc_thr[2]:
276 bgcolor ='#ffcc33' # Orange
277 tstr = '<div style="background-color:'+bgcolor+';color:black">'
278 tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
280 else: tstr = 'not processed yet'
282 aligned_reads.allow_tags = True
286 summary_url = self.get_absolute_url()
287 return '<a href="%s">S</a>' % (summary_url,)
288 public.allow_tags = True
291 def get_absolute_url(self):
292 return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.id)])
297 Provide some site-specific customization for the django user class
299 #objects = UserManager()
302 ordering = ['first_name', 'last_name', 'username']
305 return '/admin/%s/%s/%d' % (self._meta.app_label, self._meta.module_name, self.id)
307 def __unicode__(self):
308 #return unicode(self.username) + u" (" + unicode(self.get_full_name()) + u")"
309 return unicode(self.get_full_name()) + u' (' + unicode(self.username) + ')'
311 def HTSUserInsertID(sender, instance, **kwargs):
313 Force addition of HTSUsers when someone just modifies the auth_user object
315 u = HTSUser.objects.filter(pk=instance.id)
317 cursor = connection.cursor()
318 cursor.execute('INSERT INTO samples_htsuser (user_ptr_id) VALUES (%s);' % (instance.id,))
321 post_save.connect(HTSUserInsertID, sender=User)