X-Git-Url: http://woldlab.caltech.edu/gitweb/?p=htsworkflow.git;a=blobdiff_plain;f=htsworkflow%2Ffrontend%2Fsamples%2Fmodels.py;h=d1ab6607e775562370838069031f8400a5659593;hp=531edc6c84d0e417683e609218ac75ba2f18a1fa;hb=bc27b813d0cdd3513323434405ee2ec5126490e5;hpb=0123277f86af843d47170d56d217f45e7d7cb4a6 diff --git a/htsworkflow/frontend/samples/models.py b/htsworkflow/frontend/samples/models.py index 531edc6..d1ab660 100644 --- a/htsworkflow/frontend/samples/models.py +++ b/htsworkflow/frontend/samples/models.py @@ -12,12 +12,12 @@ logger = logging.getLogger(__name__) class Antibody(models.Model): antigene = models.CharField(max_length=500, db_index=True) # New field Aug/20/08 - # SQL to add column: + # SQL to add column: # alter table fctracker_antibody add column "nickname" varchar(20) NULL; nickname = models.CharField( max_length=20, blank=True, - null=True, + null=True, db_index=True ) catalog = models.CharField(max_length=50, blank=True, null=True) @@ -35,9 +35,9 @@ class Cellline(models.Model): cellline_name = models.CharField(max_length=100, unique=True, db_index=True) nickname = models.CharField(max_length=20, blank=True, - null=True, + null=True, db_index=True) - + notes = models.TextField(blank=True) def __unicode__(self): return unicode(self.cellline_name) @@ -50,7 +50,7 @@ class Condition(models.Model): max_length=2000, unique=True, db_index=True) nickname = models.CharField(max_length=20, blank=True, - null=True, + null=True, db_index=True, verbose_name = 'Short Name') notes = models.TextField(blank=True) @@ -61,34 +61,34 @@ class Condition(models.Model): class Meta: ordering = ["condition_name"] - + class ExperimentType(models.Model): name = models.CharField(max_length=50, unique=True) def __unicode__(self): return unicode(self.name) -class Tag(models.Model): - tag_name = models.CharField(max_length=100, db_index=True,blank=False,null=False) - TAG_CONTEXT = ( - #('Antibody','Antibody'), - #('Cellline', 'Cellline'), - #('Condition', 'Condition'), - ('Library', 'Library'), - ('ANY','ANY'), - ) - context = models.CharField(max_length=50, - choices=TAG_CONTEXT, default='Library') - - def __unicode__(self): - return u'%s' % (self.tag_name) - - class Meta: - ordering = ["context","tag_name"] - +class Tag(models.Model): + tag_name = models.CharField(max_length=100, db_index=True,blank=False,null=False) + TAG_CONTEXT = ( + #('Antibody','Antibody'), + #('Cellline', 'Cellline'), + #('Condition', 'Condition'), + ('Library', 'Library'), + ('ANY','ANY'), + ) + context = models.CharField(max_length=50, + choices=TAG_CONTEXT, default='Library') + + def __unicode__(self): + return u'%s' % (self.tag_name) + + class Meta: + ordering = ["context","tag_name"] + class Species(models.Model): - scientific_name = models.CharField(max_length=256, - unique=False, + scientific_name = models.CharField(max_length=256, + unique=False, db_index=True ) common_name = models.CharField(max_length=256, blank=True) @@ -96,7 +96,7 @@ class Species(models.Model): def __unicode__(self): return u'%s (%s)' % (self.scientific_name, self.common_name) - + class Meta: verbose_name_plural = "species" ordering = ["scientific_name"] @@ -104,18 +104,18 @@ class Species(models.Model): @models.permalink def get_absolute_url(self): return ('htsworkflow.frontend.samples.views.species', [str(self.id)]) - + class Affiliation(models.Model): name = models.CharField(max_length=256, db_index=True, verbose_name='Name') - contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name') + contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name') email = models.EmailField(null=True,blank=True) users = models.ManyToManyField('HTSUser', null=True, blank=True) users.admin_order_field = "username" - + def __unicode__(self): str = unicode(self.name) if self.contact is not None and len(self.contact) > 0: - str += u' ('+self.contact+u')' + str += u' ('+self.contact+u')' return str def Users(self): @@ -127,11 +127,28 @@ class Affiliation(models.Model): unique_together = (("name", "contact"),) class LibraryType(models.Model): - name = models.CharField(max_length=255, unique=True) + name = models.CharField(max_length=255, unique=True, + name="Adapter Type") + is_paired_end = models.BooleanField(default=True, + help_text="can you do a paired end run with this adapter") + can_multiplex = models.BooleanField(default=True, + help_text="Does this adapter provide multiplexing?") def __unicode__(self): - return unicode(self.name) + return unicode(self.name) + + class Meta: + ordering = ["-id"] + +class MultiplexIndex(models.Model): + """Map adapter types to the multiplex sequence""" + adapter_type = models.ForeignKey(LibraryType) + multiplex_id = models.CharField(max_length=3, null=False) + sequence = models.CharField(max_length=12, blank=True, null=True) + + class Meta: + unique_together = ('adapter_type', 'multiplex_id') class Library(models.Model): id = models.CharField(max_length=10, primary_key=True) @@ -149,14 +166,18 @@ class Library(models.Model): blank=True,null=True) REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4)) replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM, - blank=True,null=True) + blank=True,null=True) experiment_type = models.ForeignKey(ExperimentType) - library_type = models.ForeignKey(LibraryType, blank=True, null=True) + library_type = models.ForeignKey(LibraryType, blank=True, null=True, + verbose_name="Adapter Type") + multiplex_id = models.CharField(max_length=128, + blank=True, null=True, + verbose_name="Index ID") creation_date = models.DateField(blank=True, null=True) - made_for = models.CharField(max_length=50, blank=True, + made_for = models.CharField(max_length=50, blank=True, verbose_name='ChIP/DNA/RNA Made By') made_by = models.CharField(max_length=50, blank=True, default="Lorian") - + PROTOCOL_END_POINTS = ( ('?', 'Unknown'), ('Sample', 'Raw sample'), @@ -173,14 +194,14 @@ class Library(models.Model): stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done') - + amplified_from_sample = models.ForeignKey('self', related_name='amplified_into_sample', blank=True, null=True) - - undiluted_concentration = models.DecimalField("Concentration", + + undiluted_concentration = models.DecimalField("Concentration", max_digits=5, decimal_places=2, blank=True, null=True, - help_text=u"Undiluted concentration (ng/\u00b5l)") + help_text=u"Undiluted concentration (ng/\u00b5l)") # note \u00b5 is the micro symbol in unicode successful_pM = models.DecimalField(max_digits=9, decimal_places=1, blank=True, null=True) @@ -190,27 +211,59 @@ class Library(models.Model): notes = models.TextField(blank=True) bioanalyzer_summary = models.TextField(blank=True,default="") - bioanalyzer_concentration = models.DecimalField(max_digits=5, + bioanalyzer_concentration = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True, help_text=u"(ng/\u00b5l)") bioanalyzer_image_url = models.URLField(blank=True,default="") - + def __unicode__(self): return u'#%s: %s' % (self.id, self.library_name) - + class Meta: verbose_name_plural = "libraries" - #ordering = ["-creation_date"] + #ordering = ["-creation_date"] ordering = ["-id"] - + def antibody_name(self): - str =''+self.antibody.label+'' + str =''+self.antibody.label+'' return str antibody_name.allow_tags = True def organism(self): return self.library_species.common_name + def index_sequences(self): + """Return a dictionary of multiplex index id to sequence + Return None if the library can't multiplex, + + """ + if self.library_type is None: + return None + if not self.library_type.can_multiplex: + return None + if self.multiplex_id is None or len(self.multiplex_id) == 0: + return 'Err: id empty' + sequences = {} + multiplex_ids = self.multiplex_id.split(',') + for multiplex_id in multiplex_ids: + try: + multiplex = MultiplexIndex.objects.get( + adapter_type = self.library_type.id, + multiplex_id = multiplex_id) + sequences[multiplex_id] = multiplex.sequence + except MultiplexIndex.DoesNotExist, e: + sequences[multiplex_id] = 'Err: index not found' + return sequences + + def index_sequence_text(self, seperator=' '): + """Return formatted multiplex index sequences""" + sequences = self.index_sequences() + multiplex_ids = sequences.keys() + multiplex_ids.sort() + return seperator.join(( "%s:%s" %(i,sequences[i]) for i in multiplex_ids)) + index_sequence_text.short_description = "Index" + + def affiliation(self): affs = self.affiliations.all().order_by('name') tstr = '' @@ -218,7 +271,7 @@ class Library(models.Model): for t in affs: ar.append(t.__unicode__()) return '%s' % (", ".join(ar)) - + def is_archived(self): """ returns True if archived else False @@ -235,7 +288,7 @@ class Library(models.Model): name = "Lookup Error" logger.error("protocol stopping point in database didn't match names in library model") return name - + def libtags(self): affs = self.tags.all().order_by('tag_name') @@ -245,7 +298,7 @@ class Library(models.Model): return u'%s' % ( ", ".join(ar)) def DataRun(self): - str ='Data Run' + str ='Data Run' return str DataRun.allow_tags = True @@ -273,21 +326,21 @@ class Library(models.Model): if res[1] > rc_thr[1]: bgcolor ='#00ccff' # Blue else: - if res[1] > rc_thr[2]: + if res[1] > rc_thr[2]: bgcolor ='#ffcc33' # Orange tstr = '
' tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads' tstr += '
' - else: tstr = 'not processed yet' + else: tstr = 'not processed yet' return tstr aligned_reads.allow_tags = True - + def public(self): SITE_ROOT = '/' summary_url = self.get_absolute_url() return 'S' % (summary_url,) public.allow_tags = True - + @models.permalink def get_absolute_url(self): return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.id)]) @@ -311,7 +364,7 @@ class HTSUser(User): def __unicode__(self): #return unicode(self.username) + u" (" + unicode(self.get_full_name()) + u")" return unicode(self.get_full_name()) + u' (' + unicode(self.username) + ')' - + def HTSUserInsertID(sender, instance, **kwargs): """ Force addition of HTSUsers when someone just modifies the auth_user object @@ -321,5 +374,5 @@ def HTSUserInsertID(sender, instance, **kwargs): cursor = connection.cursor() cursor.execute('INSERT INTO samples_htsuser (user_ptr_id) VALUES (%s);' % (instance.id,)) cursor.close() - + post_save.connect(HTSUserInsertID, sender=User)