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(
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,
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"]
105 class Affiliation(models.Model):
106 name = models.CharField(max_length=256, db_index=True, verbose_name='Name')
107 contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name')
108 email = models.EmailField(null=True,blank=True)
109 users = models.ManyToManyField('HTSUser', null=True, blank=True)
110 users.admin_order_field = "username"
112 def __unicode__(self):
113 str = unicode(self.name)
114 if self.contact is not None and len(self.contact) > 0:
115 str += u' ('+self.contact+u')'
119 users = self.users.all().order_by('username')
120 return ", ".join([unicode(a) for a in users ])
123 ordering = ["name","contact"]
124 unique_together = (("name", "contact"),)
126 class LibraryType(models.Model):
127 name = models.CharField(max_length=255, unique=True)
129 def __unicode__(self):
130 return unicode(self.name)
133 class Library(models.Model):
134 id = models.CharField(max_length=10, primary_key=True)
135 library_name = models.CharField(max_length=100, unique=True)
136 library_species = models.ForeignKey(Species)
137 # new field 2008 Mar 5, alter table samples_library add column "hidden" NOT NULL default 0;
138 hidden = models.BooleanField()
139 # new field 2009 Oct 6, alter table samples_library add column "account_number" varchar(100) NULL
140 account_number = models.CharField(max_length=100, null=True, blank=True)
141 cell_line = models.ForeignKey(Cellline, blank=True, null=True, verbose_name="Background")
142 condition = models.ForeignKey(Condition, blank=True, null=True)
143 antibody = models.ForeignKey(Antibody,blank=True,null=True)
144 # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256) NULL;
145 affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True)
146 # new field Nov/14/08
147 tags = models.ManyToManyField(Tag,related_name='library_tags',blank=True,null=True)
148 # New field Aug/19/08
149 # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
150 REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
151 replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM,blank=True,null=True)
152 experiment_type = models.ForeignKey(ExperimentType)
153 library_type = models.ForeignKey(LibraryType, blank=True, null=True)
154 creation_date = models.DateField(blank=True, null=True)
155 made_for = models.CharField(max_length=50, blank=True,
156 verbose_name='ChIP/DNA/RNA Made By')
157 made_by = models.CharField(max_length=50, blank=True, default="Lorian")
159 PROTOCOL_END_POINTS = (
161 ('Sample', 'Raw sample'),
162 ('Progress', 'In progress'),
163 ('1A', 'Ligation, then gel'),
164 ('PCR', 'Ligation, then PCR'),
165 ('1Ab', 'Ligation, PCR, then gel'),
166 ('1Ac', 'Ligation, gel, then 12x PCR'),
167 ('1Aa', 'Ligation, gel, then 18x PCR'),
168 ('2A', 'Ligation, PCR, gel, PCR'),
169 ('Done', 'Completed'),
171 PROTOCOL_END_POINTS_DICT = dict(PROTOCOL_END_POINTS)
173 stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done')
174 amplified_from_sample = models.ForeignKey('self', blank=True, null=True, related_name='amplified_into_sample')
176 undiluted_concentration = models.DecimalField("Concentration",
177 max_digits=5, decimal_places=2, blank=True, null=True,
178 help_text=u"Undiluted concentration (ng/\u00b5l)")
179 # note \u00b5 is the micro symbol in unicode
180 successful_pM = models.DecimalField(max_digits=9, decimal_places=1, blank=True, null=True)
181 ten_nM_dilution = models.BooleanField()
182 gel_cut_size = models.IntegerField(default=225, blank=True, null=True)
183 insert_size = models.IntegerField(blank=True, null=True)
184 notes = models.TextField(blank=True)
186 bioanalyzer_summary = models.TextField(blank=True,default="")
187 bioanalyzer_concentration = models.DecimalField(max_digits=5,
188 decimal_places=2, blank=True, null=True,
189 help_text=u"(ng/\u00b5l)")
190 bioanalyzer_image_url = models.URLField(blank=True,default="")
192 def __unicode__(self):
193 return u'#%s: %s' % (self.id, self.library_name)
196 verbose_name_plural = "libraries"
197 #ordering = ["-creation_date"]
200 def antibody_name(self):
201 str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.label+'</a>'
203 antibody_name.allow_tags = True
206 return self.library_species.common_name
208 def affiliation(self):
209 affs = self.affiliations.all().order_by('name')
213 ar.append(t.__unicode__())
214 return '%s' % (", ".join(ar))
216 def is_archived(self):
218 returns True if archived else False
220 if self.longtermstorage_set.count() > 0:
225 def stopping_point_name(self):
226 end_points = Library.PROTOCOL_END_POINTS_DICT
227 name = end_points.get(self.stopping_point, None)
229 name = "Lookup Error"
230 logger.error("protocol stopping point in database didn't match names in library model")
235 affs = self.tags.all().order_by('tag_name')
238 ar.append(t.__unicode__())
239 return u'%s' % ( ", ".join(ar))
242 str ='<a target=_self href="/admin/experiments/datarun/?q='+self.id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>'
244 DataRun.allow_tags = True
246 def aligned_m_reads(self):
247 return getLibReads(self.id)
249 def aligned_reads(self):
250 res = getLibReads(self.id)
254 return u'<div style="border:solid red 2px">'+res[2]+'</div>'
256 rc = "%1.2f" % (res[1]/1000000.0)
257 # 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
259 bgcolor = '#ff3300' # Red
260 rc_thr = [10000000,5000000,3000000]
261 if self.experiment_type == 'RNA-seq':
262 rc_thr = [20000000,10000000,6000000]
264 if res[1] > rc_thr[0]:
265 bgcolor = '#66ff66' # Green
267 if res[1] > rc_thr[1]:
268 bgcolor ='#00ccff' # Blue
270 if res[1] > rc_thr[2]:
271 bgcolor ='#ffcc33' # Orange
272 tstr = '<div style="background-color:'+bgcolor+';color:black">'
273 tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
275 else: tstr = 'not processed yet'
277 aligned_reads.allow_tags = True
281 summary_url = self.get_absolute_url()
282 return '<a href="%s">S</a>' % (summary_url,)
283 public.allow_tags = True
286 def get_absolute_url(self):
287 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)