|
Hi Oliver,
LibSBML is written in C++. The Python binding is produced by
wrapping the C++ code using SWIG. Unfortunately, a side-effect of
this wrapping is that you cannot subclass libSBML objects in Python
and expect the subclasses to be completely substitutable for the
parent class when objects cross the Python / C++ interface. This
problem isn't unique to libSBML or SWIG. For example, until Python
2.2 (if I recall the version number correctly) it was not possible to
subclass built-in Python data structures.
I can think of of one good solution and two workarounds:
1. Use SWIG directors to create subclasses of the
builtin libSBML objects:
http://www.swig.org/Doc1.3/Python.html#directors
I attempted to do this at the recent SBML Hackathon
for Colin Gillespie, but couldn't get the directors
to work quite right. I think using directors is
possible, but it looks like they're going to require
some experimentation and focused work.
If you would like to go this route, I'd be happy
to help you.
2. Maintain a parallel structure that delegates to,
rather than inherits from, the libSBML objects.
This is rather inelegant and requires alot more
work on your part. For example:
class MySpeciesReference:
def __init__ (self):
self.sr = libsbml.SpeciesReference()
def getSpecies (self):
return self.sr.getSpecies()
...
class MyReaction:
def __init__ (self):
self.r = libsbml.Reaction()
self.reactants = [ ]
...
def addReactant (self, mySR):
self.r.addReactant(mySR.sr)
self.reactants.append(mySR)
...
It might be tolerable to do this for SpeciesReference
and Reaction, but probably not for every libSBML
object.
3. Hack the SBase C++ object to store (get and set) a
void pointer to user / application specific data.
Once this is in place, you could modify the SWIG
interface to store the address of a Python object
in that void pointer slot.
This is basically solution (2) turned on its head.
The advantage is that you don't need to recreate
the libSBML class hierarchy. Instead you just
tack your objects onto libSBML objects and get
them as needed.
SWIG directors really are the way to go, unfortunately libSBML Python
just isn't there yet. It's on my to do list, but I can't really make
any promises as to when it might be working.
Sorry I couldn't be more helpful.
Thanks.
Ben
On Apr 18, 2006, at 11:49 AM, Ratmann, Oliver wrote:
> I am working with the python binding to libsbml, and I have
> subclassed 'SpeciesReference'
>
> my
>
> class _Reaction(libsbml.Reaction):
> def __init__(self,reagents,products,rateLaw):
> libsbml.Reaction.__init__(self)
>
> if rateLaw.testNumbers(reagents,products):
> for reagent in reagents:
> self.addReactant(reagent)
> for product in products:
> self.addProduct(reagent)
>
> then easily takes my species references, but when I get
> this species reference back from
>
> self.getReactant(r)
>
> they only point to <class 'libsbml.SpeciesReferencePtr'>, and not
> to my subclass.
> The effect is that
> self.getReactant(r).getStoichiometry()
> works fine, but
> self.getReactant(r).getSpeciesIdx()
> does not because the latter method is known only to the subclass.
>
> This makes it difficult for me to work with libsbml.Reaction,
> what can I do?
|