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"]
106 class Affiliation(models.Model):
107 name = models.CharField(max_length=256, db_index=True, verbose_name='Name')
108 contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name')
109 email = models.EmailField(null=True,blank=True)
110 users = models.ManyToManyField('HTSUser', null=True, blank=True)
111 users.admin_order_field = "username"
113 def __unicode__(self):
114 str = unicode(self.name)
115 if self.contact is not None and len(self.contact) > 0:
116 str += u' ('+self.contact+u')'
120 users = self.users.all().order_by('username')
121 return ", ".join([unicode(a) for a in users ])
124 ordering = ["name","contact"]
125 unique_together = (("name", "contact"),)
127 class LibraryType(models.Model):
128 name = models.CharField(max_length=255, unique=True)
130 def __unicode__(self):
131 return unicode(self.name)
134 class Library(models.Model):
135 id = models.CharField(max_length=10, primary_key=True)
136 library_name = models.CharField(max_length=100, unique=True)
137 library_species = models.ForeignKey(Species)
138 # new field 2008 Mar 5, alter table samples_library add column "hidden" NOT NULL default 0;
139 hidden = models.BooleanField()
140 # new field 2009 Oct 6, alter table samples_library add column "account_number" varchar(100) NULL
141 account_number = models.CharField(max_length=100, null=True, blank=True)
142 cell_line = models.ForeignKey(Cellline, blank=True, null=True, verbose_name="Background")
143 condition = models.ForeignKey(Condition, blank=True, null=True)
144 antibody = models.ForeignKey(Antibody,blank=True,null=True)
145 # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256) NULL;
146 affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True)
147 # new field Nov/14/08
148 tags = models.ManyToManyField(Tag,related_name='library_tags',blank=True,null=True)
149 # New field Aug/19/08
150 # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
151 REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
152 replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM,default=1)
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)
174 stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done')
175 amplified_from_sample = models.ForeignKey('self', blank=True, null=True, related_name='amplified_into_sample')
177 undiluted_concentration = models.DecimalField("Concentration",
178 max_digits=5, decimal_places=2, blank=True, null=True,
179 help_text=u"Undiluted concentration (ng/\u00b5l)")
180 # note \u00b5 is the micro symbol in unicode
181 successful_pM = models.DecimalField(max_digits=9, decimal_places=1, blank=True, null=True)
182 ten_nM_dilution = models.BooleanField()
183 gel_cut_size = models.IntegerField(default=225, blank=True, null=True)
184 insert_size = models.IntegerField(blank=True, null=True)
185 notes = models.TextField(blank=True)
187 bioanalyzer_summary = models.TextField(blank=True,default="")
188 bioanalyzer_concentration = models.DecimalField(max_digits=5,
189 decimal_places=2, blank=True, null=True,
190 help_text=u"(ng/\u00b5l)")
191 bioanalyzer_image_url = models.URLField(blank=True,default="")
193 def __unicode__(self):
194 return u'#%s: %s' % (self.id, self.library_name)
197 verbose_name_plural = "libraries"
198 #ordering = ["-creation_date"]
201 def antibody_name(self):
202 str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.nickname+'</a>'
204 antibody_name.allow_tags = True
207 return self.library_species.common_name
209 def affiliation(self):
210 affs = self.affiliations.all().order_by('name')
214 ar.append(t.__unicode__())
215 return '%s' % (", ".join(ar))
217 def is_archived(self):
219 returns True if archived else False
221 if self.longtermstorage_set.count() > 0:
226 def stopping_point_name(self):
227 end_points = Library.PROTOCOL_END_POINTS_DICT
228 name = end_points.get(self.stopping_point, None)
230 name = "Lookup Error"
231 logger.error("protocol stopping point in database didn't match names in library model")
236 affs = self.tags.all().order_by('tag_name')
239 ar.append(t.__unicode__())
240 return u'%s' % ( ", ".join(ar))
243 str ='<a target=_self href="/admin/experiments/datarun/?q='+self.id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>'
245 DataRun.allow_tags = True
247 def aligned_m_reads(self):
248 return getLibReads(self.id)
250 def aligned_reads(self):
251 res = getLibReads(self.id)
255 return u'<div style="border:solid red 2px">'+res[2]+'</div>'
257 rc = "%1.2f" % (res[1]/1000000.0)
258 # 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
260 bgcolor = '#ff3300' # Red
261 rc_thr = [10000000,5000000,3000000]
262 if self.experiment_type == 'RNA-seq':
263 rc_thr = [20000000,10000000,6000000]
265 if res[1] > rc_thr[0]:
266 bgcolor = '#66ff66' # Green
268 if res[1] > rc_thr[1]:
269 bgcolor ='#00ccff' # Blue
271 if res[1] > rc_thr[2]:
272 bgcolor ='#ffcc33' # Orange
273 tstr = '<div style="background-color:'+bgcolor+';color:black">'
274 tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
276 else: tstr = 'not processed yet'
278 aligned_reads.allow_tags = True
282 summary_url = self.get_absolute_url()
283 return '<a href="%s">S</a>' % (summary_url,)
284 public.allow_tags = True
287 def get_absolute_url(self):
288 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)