3 from django.db import models
4 from django.contrib.auth.models import User, UserManager
5 from django.core import urlresolvers
6 from django.db.models.signals import pre_save, post_save
7 from django.db import connection
8 from htsworkflow.frontend.reports.libinfopar import *
10 logger = logging.getLogger(__name__)
12 class Antibody(models.Model):
13 antigene = models.CharField(max_length=500, db_index=True)
16 # alter table fctracker_antibody add column "nickname" varchar(20) NULL;
17 nickname = models.CharField(
23 catalog = models.CharField(max_length=50, unique=True, db_index=True)
24 antibodies = models.CharField(max_length=500, db_index=True)
25 source = models.CharField(max_length=500, blank=True, db_index=True)
26 biology = models.TextField(blank=True)
27 notes = models.TextField(blank=True)
28 def __unicode__(self):
29 return u'%s - %s (%s)' % (self.antigene, self.antibodies, self.catalog)
31 verbose_name_plural = "antibodies"
32 ordering = ["antigene"]
34 class Cellline(models.Model):
35 cellline_name = models.CharField(max_length=100, unique=True, db_index=True)
36 nickname = models.CharField(max_length=20,
41 notes = models.TextField(blank=True)
42 def __unicode__(self):
43 return unicode(self.cellline_name)
46 ordering = ["cellline_name"]
48 class Condition(models.Model):
49 condition_name = models.CharField(
50 max_length=2000, unique=True, db_index=True)
51 nickname = models.CharField(max_length=20,
55 verbose_name = 'Short Name')
56 notes = models.TextField(blank=True)
58 def __unicode__(self):
59 return unicode(self.condition_name)
62 ordering = ["condition_name"]
64 class ExperimentType(models.Model):
65 name = models.CharField(max_length=50, unique=True)
67 def __unicode__(self):
68 return unicode(self.name)
70 class Tag(models.Model):
71 tag_name = models.CharField(max_length=100, db_index=True,blank=False,null=False)
73 #('Antibody','Antibody'),
74 #('Cellline', 'Cellline'),
75 #('Condition', 'Condition'),
76 ('Library', 'Library'),
79 context = models.CharField(max_length=50,
80 choices=TAG_CONTEXT, default='Library')
82 def __unicode__(self):
83 return u'%s' % (self.tag_name)
86 ordering = ["context","tag_name"]
88 class Species(models.Model):
89 scientific_name = models.CharField(max_length=256,
93 common_name = models.CharField(max_length=256, blank=True)
94 #use_genome_build = models.CharField(max_length=100, blank=False, null=False)
96 def __unicode__(self):
97 return u'%s (%s)' % (self.scientific_name, self.common_name)
100 verbose_name_plural = "species"
101 ordering = ["scientific_name"]
104 def get_absolute_url(self):
105 return ('htsworkflow.frontend.samples.views.species', [str(self.id)])
107 class Affiliation(models.Model):
108 name = models.CharField(max_length=256, db_index=True, verbose_name='Name')
109 contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name')
110 email = models.EmailField(null=True,blank=True)
111 users = models.ManyToManyField('HTSUser', null=True, blank=True)
112 users.admin_order_field = "username"
114 def __unicode__(self):
115 str = unicode(self.name)
116 if self.contact is not None and len(self.contact) > 0:
117 str += u' ('+self.contact+u')'
121 users = self.users.all().order_by('username')
122 return ", ".join([unicode(a) for a in users ])
125 ordering = ["name","contact"]
126 unique_together = (("name", "contact"),)
128 class LibraryType(models.Model):
129 name = models.CharField(max_length=255, unique=True)
131 def __unicode__(self):
132 return unicode(self.name)
135 class Library(models.Model):
136 id = models.CharField(max_length=10, primary_key=True)
137 library_name = models.CharField(max_length=100, unique=True)
138 library_species = models.ForeignKey(Species)
139 # new field 2008 Mar 5, alter table samples_library add column "hidden" NOT NULL default 0;
140 hidden = models.BooleanField()
141 # new field 2009 Oct 6, alter table samples_library add column "account_number" varchar(100) NULL
142 account_number = models.CharField(max_length=100, null=True, blank=True)
143 cell_line = models.ForeignKey(Cellline, blank=True, null=True, verbose_name="Background")
144 condition = models.ForeignKey(Condition, blank=True, null=True)
145 antibody = models.ForeignKey(Antibody,blank=True,null=True)
146 # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256) NULL;
147 affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True)
148 # new field Nov/14/08
149 tags = models.ManyToManyField(Tag,related_name='library_tags',blank=True,null=True)
150 # New field Aug/19/08
151 # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
152 REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
153 replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM,blank=True,null=True)
154 experiment_type = models.ForeignKey(ExperimentType)
155 library_type = models.ForeignKey(LibraryType, blank=True, null=True)
156 creation_date = models.DateField(blank=True, null=True)
157 made_for = models.CharField(max_length=50, blank=True,
158 verbose_name='ChIP/DNA/RNA Made By')
159 made_by = models.CharField(max_length=50, blank=True, default="Lorian")
161 PROTOCOL_END_POINTS = (
163 ('Sample', 'Raw sample'),
164 ('Progress', 'In progress'),
165 ('1A', 'Ligation, then gel'),
166 ('PCR', 'Ligation, then PCR'),
167 ('1Ab', 'Ligation, PCR, then gel'),
168 ('1Ac', 'Ligation, gel, then 12x PCR'),
169 ('1Aa', 'Ligation, gel, then 18x PCR'),
170 ('2A', 'Ligation, PCR, gel, PCR'),
171 ('Done', 'Completed'),
173 PROTOCOL_END_POINTS_DICT = dict(PROTOCOL_END_POINTS)
175 stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done')
176 amplified_from_sample = models.ForeignKey('self', blank=True, null=True, related_name='amplified_into_sample')
178 undiluted_concentration = models.DecimalField("Concentration",
179 max_digits=5, decimal_places=2, blank=True, null=True,
180 help_text=u"Undiluted concentration (ng/\u00b5l)")
181 # note \u00b5 is the micro symbol in unicode
182 successful_pM = models.DecimalField(max_digits=9, decimal_places=1, blank=True, null=True)
183 ten_nM_dilution = models.BooleanField()
184 gel_cut_size = models.IntegerField(default=225, blank=True, null=True)
185 insert_size = models.IntegerField(blank=True, null=True)
186 notes = models.TextField(blank=True)
188 bioanalyzer_summary = models.TextField(blank=True,default="")
189 bioanalyzer_concentration = models.DecimalField(max_digits=5,
190 decimal_places=2, blank=True, null=True,
191 help_text=u"(ng/\u00b5l)")
192 bioanalyzer_image_url = models.URLField(blank=True,default="")
194 def __unicode__(self):
195 return u'#%s: %s' % (self.id, self.library_name)
198 verbose_name_plural = "libraries"
199 #ordering = ["-creation_date"]
202 def antibody_name(self):
203 str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.label+'</a>'
205 antibody_name.allow_tags = True
208 return self.library_species.common_name
210 def affiliation(self):
211 affs = self.affiliations.all().order_by('name')
215 ar.append(t.__unicode__())
216 return '%s' % (", ".join(ar))
218 def is_archived(self):
220 returns True if archived else False
222 if self.longtermstorage_set.count() > 0:
227 def stopping_point_name(self):
228 end_points = Library.PROTOCOL_END_POINTS_DICT
229 name = end_points.get(self.stopping_point, None)
231 name = "Lookup Error"
232 logger.error("protocol stopping point in database didn't match names in library model")
237 affs = self.tags.all().order_by('tag_name')
240 ar.append(t.__unicode__())
241 return u'%s' % ( ", ".join(ar))
244 str ='<a target=_self href="/admin/experiments/datarun/?q='+self.id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>'
246 DataRun.allow_tags = True
248 def aligned_m_reads(self):
249 return getLibReads(self.id)
251 def aligned_reads(self):
252 res = getLibReads(self.id)
256 return u'<div style="border:solid red 2px">'+res[2]+'</div>'
258 rc = "%1.2f" % (res[1]/1000000.0)
259 # 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
261 bgcolor = '#ff3300' # Red
262 rc_thr = [10000000,5000000,3000000]
263 if self.experiment_type == 'RNA-seq':
264 rc_thr = [20000000,10000000,6000000]
266 if res[1] > rc_thr[0]:
267 bgcolor = '#66ff66' # Green
269 if res[1] > rc_thr[1]:
270 bgcolor ='#00ccff' # Blue
272 if res[1] > rc_thr[2]:
273 bgcolor ='#ffcc33' # Orange
274 tstr = '<div style="background-color:'+bgcolor+';color:black">'
275 tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
277 else: tstr = 'not processed yet'
279 aligned_reads.allow_tags = True
283 summary_url = self.get_absolute_url()
284 return '<a href="%s">S</a>' % (summary_url,)
285 public.allow_tags = True
288 def get_absolute_url(self):
289 return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.id)])
291 def get_admin_url(self):
292 return urlresolvers.reverse('admin:samples_library_change',
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)