<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">All,<div class=""><br class=""></div><div class="">I’ve been using the BioSQL schema with Bioperl and would like to start doing the same with Biopython, but there’s a limitation I’d like to fix. Here’s the relevant table in the BioSQL schema, seqfeature:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp;Column &nbsp; &nbsp; | &nbsp; &nbsp; &nbsp; &nbsp; Type &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Modifiers &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| Storage &nbsp;| Stats target | Description&nbsp;</font></div><div class=""><font face="Courier New" class="">----------------+-----------------------+---------------------------------------------------------+----------+--------------+-------------</font></div><div class=""><font face="Courier New" class="">&nbsp;seqfeature_id &nbsp;| integer &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | not null default nextval('seqfeature_pk_seq'::regclass) | plain &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp;</font></div><div class=""><font face="Courier New" class="">&nbsp;bioentry_id &nbsp; &nbsp;| integer &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | not null &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| plain &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp;</font></div><div class=""><font face="Courier New" class="">&nbsp;type_term_id &nbsp; | integer &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | not null &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| plain &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp;</font></div><div class=""><font face="Courier New" class="">&nbsp;source_term_id | integer &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | not null &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| plain &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp;</font></div><div class=""><font face="Courier New" class="">&nbsp;display_name &nbsp; | character varying(64) | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | extended | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp;</font></div><div class=""><font face="Courier New" class="">&nbsp;rank &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | integer &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | not null default 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| plain &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp;</font></div></div><div class=""><br class=""></div><div class="">Note that required field, source_term_id. In the work I’ve been doing with Bioperl I’ve been setting this “source term” to different values (e.g. &nbsp;“NCBI”) depending on where the tag/value data in the feature comes from.&nbsp;</div><div class=""><br class=""></div><div class="">But here’s the code that makes a persistent feature, from BioSQL/Loader.py:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Courier New" class="">&nbsp; &nbsp; def _load_seqfeature_basic(self, feature_type, feature_rank, bioentry_id):</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; """Load the first tables of a seqfeature and returns the id (PRIVATE).</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; This loads the "key" of the seqfeature (ie. CDS, gene) and</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; the basic seqfeature table itself.</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; """</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; ontology_id = self._get_ontology_id('SeqFeature Keys')</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; seqfeature_key_id = self._get_term_id(feature_type,</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ontology_id=ontology_id)</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; # XXX source is always EMBL/GenBank/SwissProt here; it should depend on</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; # the record (how?)</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; source_cat_id = self._get_ontology_id('SeqFeature Sources')</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; source_term_id = self._get_term_id('EMBL/GenBank/SwissProt',</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ontology_id=source_cat_id)</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; sql = r"INSERT INTO seqfeature (bioentry_id, type_term_id, " \</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r"source_term_id, rank) VALUES (%s, %s, %s, %s)"</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; self.adaptor.execute(sql, (bioentry_id, seqfeature_key_id,</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;source_term_id, feature_rank + 1))</font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; seqfeature_id = self.adaptor.last_id('seqfeature')</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">&nbsp; &nbsp; &nbsp; &nbsp; return seqfeature_id</font></div><div class=""><br class=""></div><div class="">This code always sets the source term to “&nbsp;<span class="" style="font-family: 'Courier New';">EMBL/GenBank/SwissProt</span>”, and it can not be set to anything else. A better idea is to have a method to set and get this, e.g. source(), just as you can set the “type” of the feature. The way to do this is to subclass SeqFeature to make DBSeqFeature, just as Seq is subclassed to make DBSeq and SeqRecord is subclassed to make DBSeqRecord in BioSQL/Seq.py.</div><div class=""><br class=""></div><div class="">So I propose to fork, code, and send a pull request for this. What do you think?</div><div class=""><br class=""></div><div class="">Thanks again,</div><div class=""><br class=""></div><div apple-content-edited="true" class=""><span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px;"><div class="">Brian O.</div></span></div></div></body></html>