[Biopython] extending Motif class

Philip Machanick philip.machanick at gmail.com
Fri Apr 1 03:21:19 UTC 2011


Thanks.

The issue is that parse is not defined in the class but in the module and if
I understand this right, this makes it a metaclass method. More below.

On Fri, Apr 1, 2011 at 11:07 AM, Bartek Wilczynski <bartek at rezolwenta.eu.org
> wrote:

> Hi,
>
> On Fri, Apr 1, 2011 at 1:49 AM, Philip Machanick <
> philip.machanick at gmail.com> wrote:
>
>> I want to add a new scoring function to the Motif class and in true
>> object-oriented spirit would like to do it by deriving a new class rather
>> than hacking the existing code.
>>
>> Well, if you want to keep your code separate from biopython and ba able to
> use it with newer versions than maybe yes, but if you think tha your code
> code be contributed to biopython and useful for other people, than I'd
> consider just contributing via github.
>
>
>> The general structure of my test program (all in 1 file) is:
>>
>> from Bio.Motif import Motif
>>
>> class ScannableMotif(Motif):
>>    def pwm_score_hit(self,sequence,position):
>>    ## stuff to compute my new score
>>
>> That's OK, although I suspect something fishy is hidden in your code here.
> more later.
>
>
>> from Bio import Motif
>>
>
> you shouldn't need to do that
>
>
>> def main ():
>>    for motif in
>> ScannableMotif.parse(open("/Users/philip/tmp/meme.txt"),"MEME"):
>>        for i in range(3):
>>          print
>> motif.pwm_score_hit("CCTGGGGTCCCATTTCTCTTTTCTCTCCTGGGGTCCC",i)
>>
>> is ScannableMotif now a module? or is "parse" a class method? BTW, you can
> parse MEME files with Bio.Motif.parse...
>

At this stage for proof of concept I'm putting this all in the same file as
the main program.


>
>
>> The two different imports appear to be necessary. I need the first to be
>> able to use the base class to derive a new one, and without the second
>> when
>>
> Yes, you need to import the module to subclass Motif
>
>
>> I use metaclass methods, I get
>>
>> TypeError: Error when calling the metaclass bases
>>    module.__init__() takes at most 2 arguments (3 given)
>>
>> I cannot reproduce this error and it is highly unlikely that it is related
> at all to the Biopython code as Bio.Motif does not uses any metaclasses. I
> think you cause it by something in your later code:
>
>
This happens specifically if I use Motif.parse (defined in __inti__.py in
the Motif module directory).


>  The other problem: I can't directly invoke a metaclass method on a derived
>> instance as above. The snippet below works as expected, but looks like a
>> kludge to me. Is there a better way of accessing metaclass methods from a
>> derived class object?
>>
>>    for motif in Motif.parse(open("/Users/philip/tmp/meme.txt"),"MEME"):
>>        motif.__class__ = ScannableMotif # promote to the new class
>>
>
> There you go! don't do this. It is not the way objects "get promoted" to
> other classes, You seem to be playing with some python internals here
>
>        for i in range(3):
>>          print
>> motif.pwm_score_hit("CCTGGGGTCCCATTTCTCTTTTCTCTCCTGGGGTCCC",i)
>>
>> I think I have the class vs. metaclass concept straight but understanding
>> why I need the two different flavours of import would be useful.
>>
> Don't get me wrong, but I don't think you _need_ any metaclasses here. I
> think your problem is that you are trying to change the class of an existing
> instance, which (while probably possible in python) is absolutely not the
> way to go. If your code is able to produce the correct output using the
> complicated imports it's interesting, but probably not the easiest way to
> achieve it. However it's hard to say, what exactly is your goal from the
> code you provided.
>
> But, on the more constructive side of things, if you want to subclass
> Bio.Motif and add a new method to it, you can just do what you did in the
> beginning of your code (provided that you do not mess with m.__class__ or
> something)
> Then, your problem seems to be that the MEME parser fails to return your
> subclass and gives you a Bio.Motif.Motif vanilla class (or MEMEMotif). What
> you can do (if you insist on not adding the method to Bio.Motif.Motif), is
> to write a constructor able to create a ScannableMotif from a "normal"
> motif:
>
> class ScannableMotif(Motif):
>    def new_score_hit(self,sequence,position):
>        return 1 # or something smarter...
>    def __init__(self,m): #just copy it all...
>        self.instances = m.instances
>        self.has_instances=m.has_instances
>        self.counts = m.counts
>        self.has_counts=m.has_counts
>        self.mask = m.mask
>        self._pwm_is_current = False
>        self._log_odds_is_current = False
>        self.alphabet=m.alphabet
>        self.length=m.length
>        self.background=m.background
>        self.beta=m.beta
>
> And then you can do things like:
> m=Bio.Motif.parse(f,"AlignAce")
> s=ScannableMotif(m)
> s.new_score_hit(seq,pos)
>

Thanks, this is more like what I was looking for.


> I hope this helps...
>
>
>
>> --
>>
>> Philip Machanick
>> Rhodes University, Grahamstown 6140, South Africa
>> http://opinion-nation.blogspot.com/
>> +61-7-3871-0963 mobile +61 42 234 6909 skype philipmach
>> _______________________________________________
>> Biopython mailing list  -  Biopython at lists.open-bio.org
>> http://lists.open-bio.org/mailman/listinfo/biopython
>>
>>
>
>
> --
> Bartek Wilczynski
>
>
>


-- 
Philip Machanick (still in Australia for a while; note new mail address)
Rhodes University, Grahamstown 6140, South Africa
http://opinion-nation.blogspot.com/
+61-7-3871-0963 mobile +61 42 234 6909 skype philipmach


More information about the Biopython mailing list