| Author | Topic |
Posts: 11
Registered: June 2006
|
|
how to obtain my subclass from ListOf
|
18 Apr '06 11:49
|
 |
|
Hello,
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?
oliver
Oliver Ratmann
85 Burgoyne Road
London N41AB
+44 7956001378
|
|
|
Posts: 287
Registered: September 2003
|
|
Re: how to obtain my subclass from ListOf
|
18 Apr '06 13:47

|
 |
|
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?
|
|
|
Posts: 11
Registered: June 2006
|
|
RE: how to obtain my subclass from ListOf
|
19 Apr '06 13:41

|
 |
|
Dear Ben,
I have understood that the SWIG::director would allow me to override
an existing libsbml method such as libsbml.SpeciesReference.getSpecies().
This might indeed be helpful, thank you for the hint.
However, my original problem is that I add an object whose class is derived from
libsbml.SpeciesReference to the ListOfReactants in libsbml.Reactions. Now calling
reactant= reaction.getReactant(i)
returns me an object (I assume this is a pointer to my object derived from libsbml.SpeciesReference) to
libsbml.SpeciesReference only. But I need this object to be an instance of my subclass.
As I understand further, every Python proxy class has a this attribute holding
a pointer to a C++ address. Is it correct that the Reaction.ListOfReactants
internally stores only that C++ address, i.e. the C++ object corresponding to my
Python reaction?
I conclude that every species reference which is an instance of my subclass
inherits a this attribute, which points to the C++ address of the part
corresponding to the libsbml.SpeciesReference super class. And only this part of
my subclass-object is stored in ListOf. So I loose information using
libsbml.Reaction.addReactant().
I do not want to change the sbml library for compatibility reasons, so I could only
imagine that my object of my subclass must know the address of the C++ proxy which
is generated from the SWIG::director. I could then override 'this' with that
C++ address to track my subclass-object.
However, this sounds very complicated.
What do you think?
oliver
Oliver Ratmann
85 Burgoyne Road
London N41AB
+44 7956001378
-----Original Message-----
From: libsbml-discuss-bounces@caltech.edu on behalf of Ben Bornstein
Sent: Tue 4/18/2006 9:47 PM
To: LibSBML Discussion List
Subject: Re: [libsbml-discuss] how to obtain my subclass from ListOf
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?
|
|
|
Posts: 287
Registered: September 2003
|
|
Re: how to obtain my subclass from ListOf
|
19 Apr '06 17:04

|
 |
|
Hi Oliver,
> I have understood that the SWIG::director would allow me to override
> an existing libsbml method such as
> libsbml.SpeciesReference.getSpecies().
>
> This might indeed be helpful, thank you for the hint.
>
> However, my original problem is that I add an object whose class is
> derived from
> libsbml.SpeciesReference to the ListOfReactants in libsbml.Reactions.
Although it may not be immediately clear, SWIG directors will solve
your problem as well. They allow for Python subclasses to be
completely substitutable for their parent C++ classes.
> I do not want to change the sbml library for compatibility reasons
Right. I was suggesting that if you came-up with a decent solution
that required reasonable and modest modifications to libSBML, I would
be willing to fold those changes back into the library.
> I could only imagine that my object of my subclass must know the
> address of the C++ proxy which is generated from the
> SWIG::director. I could then override 'this' with that C++ address
> to track my subclass-object.
>
> However, this sounds very complicated.
>
> What do you think?
This will work in libSBML 2.3.x but not 3.0. It's not too
complicated. The example program at the end of this message uses a
customized Python dictionary (ObjectRegistry) to map subclassed
libSBML objects to their parent libSBML object based on SWIG 'this'
pointers. In libSBML 3.0, the problem is libSBML copies objects
passed to it rather than simply taking over ownership of the passed-
in object. Copying objects means the 'this' pointers will no longer
match. You could change my example program to use SBase ids (species
for SpeciesReferences) which *should* always be unique. This assumes
however that i) you have an id at the time of object construction,
ii) you don't change an object's id (otherwise, you would have to
update the registry), and iii) you don't store UnitDefinitions or
local Parameters in the registry as they are in separate namespaces
and their ids can legally "conflict" with SBML objects elsewhere.
Again, I think directors are the way to go. In the meantime, the
code below should provide a decent interim solution.
Thanks.
Ben
#!/usr/bin/env python
import libsbml
class ObjectRegistry (dict):
def add (self, obj):
self[obj] = obj
def getKey (self, obj):
if not hasattr(obj, 'this'): raise TypeError('Not a SWIG object')
return hex( obj.this )
def __contains__ (self, key):
return dict.__contains__(self, self.getKey(key))
def __getitem__ (self, key):
return dict.__getitem__(self, self.getKey(key))
def __setitem__ (self, key, value):
dict.__setitem__(self, self.getKey(key), value)
Registry = ObjectRegistry()
class MySpeciesReference (libsbml.SpeciesReference):
def __init__ (self):
libsbml.SpeciesReference.__init__(self)
Registry.add(self)
msr = MySpeciesReference()
r = libsbml.Reaction()
r.addReactant(msr)
sr = r.getReactant(0)
print type(sr)
print type(Registry[sr])
|
|
|
Posts: 11
Registered: June 2006
|
|
RE: how to obtain my subclass from ListOf
|
23 Apr '06 15:06

|
 |
|
Hi Ben,
Thank you for your last answer!
I will see if I get the SWIG::directors running.
I have downloaded libsbml2.3.4 some weeks ago, and now reconfigured it
with (so it is still the same version)
./configure --with-expat --with-python --with-swig
I observe that libsbml.py is now different in that all ..Ptr classes are missing?
I have attached the current libsbml.py and the old one, when running
./configure --with-expat --with-python
as libsbml.copy.py
Is there a way to get the ..Ptr classes back, as I make use of them?
olli
Oliver Ratmann
85 Burgoyne Road
London N41AB
+44 7956001378
-----Original Message-----
From: libsbml-discuss-bounces@caltech.edu on behalf of Ben Bornstein
Sent: Thu 4/20/2006 1:04 AM
To: LibSBML Discussion List
Subject: Re: [libsbml-discuss] how to obtain my subclass from ListOf
Hi Oliver,
> I have understood that the SWIG::director would allow me to override
> an existing libsbml method such as
> libsbml.SpeciesReference.getSpecies().
>
> This might indeed be helpful, thank you for the hint.
>
> However, my original problem is that I add an object whose class is
> derived from
> libsbml.SpeciesReference to the ListOfReactants in libsbml.Reactions.
Although it may not be immediately clear, SWIG directors will solve
your problem as well. They allow for Python subclasses to be
completely substitutable for their parent C++ classes.
> I do not want to change the sbml library for compatibility reasons
Right. I was suggesting that if you came-up with a decent solution
that required reasonable and modest modifications to libSBML, I would
be willing to fold those changes back into the library.
> I could only imagine that my object of my subclass must know the
> address of the C++ proxy which is generated from the
> SWIG::director. I could then override 'this' with that C++ address
> to track my subclass-object.
>
> However, this sounds very complicated.
>
> What do you think?
This will work in libSBML 2.3.x but not 3.0. It's not too
complicated. The example program at the end of this message uses a
customized Python dictionary (ObjectRegistry) to map subclassed
libSBML objects to their parent libSBML object based on SWIG 'this'
pointers. In libSBML 3.0, the problem is libSBML copies objects
passed to it rather than simply taking over ownership of the passed-
in object. Copying objects means the 'this' pointers will no longer
match. You could change my example program to use SBase ids (species
for SpeciesReferences) which *should* always be unique. This assumes
however that i) you have an id at the time of object construction,
ii) you don't change an object's id (otherwise, you would have to
update the registry), and iii) you don't store UnitDefinitions or
local Parameters in the registry as they are in separate namespaces
and their ids can legally "conflict" with SBML objects elsewhere.
Again, I think directors are the way to go. In the meantime, the
code below should provide a decent interim solution.
Thanks.
Ben
#!/usr/bin/env python
import libsbml
class ObjectRegistry (dict):
def add (self, obj):
self[obj] = obj
def getKey (self, obj):
if not hasattr(obj, 'this'): raise TypeError('Not a SWIG object')
return hex( obj.this )
def __contains__ (self, key):
return dict.__contains__(self, self.getKey(key))
def __getitem__ (self, key):
return dict.__getitem__(self, self.getKey(key))
def __setitem__ (self, key, value):
dict.__setitem__(self, self.getKey(key), value)
Registry = ObjectRegistry()
class MySpeciesReference (libsbml.SpeciesReference):
def __init__ (self):
libsbml.SpeciesReference.__init__(self)
Registry.add(self)
msr = MySpeciesReference()
r = libsbml.Reaction()
r.addReactant(msr)
sr = r.getReactant(0)
print type(sr)
print type(Registry[sr])
|
|
|
Posts: 287
Registered: September 2003
|
|
|
Posts: 11
Registered: June 2006
|
|
|
Posts: 287
Registered: September 2003
|
|
|
Posts: 11
Registered: June 2006
|
|
RE: how to obtain my subclass from ListOf
|
24 Apr '06 14:59
|
 |
|
Hi Ben,
I use the Ptr only once, to reference a default unit definition, so I create no new ones
but update the Ptr only when the default changes. However, this is not essential.
Did you configure libsbml2.3.4 with swig1.3.29? I get
with ./configure --with-expat --with-swig=$SWIG_DIR --with-python
and make and make install:
make swigfiles
make[4]: Entering directory `/home/olli/build/libsbml-2.3.4/src/bindings/python'
../swig/swigdoc.py python -I../.. ../swig/libsbml.i pydoc.i
/usr/local/bin/swig -I/usr/include/python2.3 -I../swig -I../.. -c++ -python -o libsbml_wrap.cpp libsbml.i
../../math/ASTNodeType.h:64: Error: Type error. Expecting an int
../../math/ASTNodeType.h:65: Error: Type error. Expecting an int
../../math/ASTNodeType.h:66: Error: Type error. Expecting an int
../../math/ASTNodeType.h:67: Error: Type error. Expecting an int
../../math/ASTNodeType.h:69: Error: Type error. Expecting an int
make[4]: *** [swigfiles] Error 5
make[4]: Leaving directory `/home/olli/build/libsbml-2.3.4/src/bindings/python'
by the way, I am experimenting with the following: I parse a SBML file with
the SBML reader, and then convert to my data structure. Since I extend libsbml,
I tried to take the C++ objects as they are and simply add some python attributes.
For example,
def _initSBML(self,iCell,kineticLaw,reagents,products,sbmlReaction):
self.this= kineticLaw.this#copy pointer only, do not create a new C++ object
self.thisown= kineticLaw.thisown
self._formulae= []
self._kineticParametersBaseIdx= None
self.setFormulae(reagents, products, iCell, kineticLaw.getFormula())#I need more than one formula, which are blueprints for a binary representation
this all works fine as long as kineticLaw itself is not destroyed. I somehow
would like to pass the ownership completely, and I guess the C++ instance does
not know about my object which stole the C++ adress from kineticLaw? Are there
any simple recipes, or is a copy the only solution? Note that I do not call the constructor
to lisbml.kineticLaw.
PS: I tried
self.thisown=True
and
self.thisown= True; kineticLaw.thisown=False
as well, but no effect.
Copying pointers would save me from copying all attributes, and possible future extensions to sbml
which I do not know about now.
cheers,
olli
Oliver Ratmann
85 Burgoyne Road
London N41AB
+44 7956001378
-----Original Message-----
From: libsbml-discuss-bounces@caltech.edu on behalf of Ben Bornstein
Sent: Mon 4/24/2006 6:17 PM
To: LibSBML Discussion List
Subject: Re: [libsbml-discuss] how to obtain my subclass from ListOf
Hi Oliver,
> swig1.3.25 however works fine and gives me all --Ptr classes in the
> binding
In what way do you depend on the Ptr classes? Since they are not
present in later versions of SWIG (e.g. 1.3.29), depending on them is
probably not a good idea in the long term.
> I do not know if this is going to hamper my/our efforts to
> implement the SWIG::directors, for the moment I am going to work
> with swig1.3.25
How hard would it be for you to upgrade to SWIG 1.3.29? I'd like to
use it for libSBML 3.0. Also, since directors are rather new, it's
better to work with the latest stable version of SWIG.
Thanks.
Ben
|
|
|
Posts: 287
Registered: September 2003
|
|
Re: how to obtain my subclass from ListOf
|
18 Apr '06 13:47
|
 |
|
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?
|
|
|
Posts: 11
Registered: June 2006
|
|
RE: how to obtain my subclass from ListOf
|
19 Apr '06 13:41
|
 |
|
Dear Ben,
I have understood that the SWIG::director would allow me to override
an existing libsbml method such as libsbml.SpeciesReference.getSpecies().
This might indeed be helpful, thank you for the hint.
However, my original problem is that I add an object whose class is derived from
libsbml.SpeciesReference to the ListOfReactants in libsbml.Reactions. Now calling
reactant= reaction.getReactant(i)
returns me an object (I assume this is a pointer to my object derived from libsbml.SpeciesReference) to
libsbml.SpeciesReference only. But I need this object to be an instance of my subclass.
As I understand further, every Python proxy class has a this attribute holding
a pointer to a C++ address. Is it correct that the Reaction.ListOfReactants
internally stores only that C++ address, i.e. the C++ object corresponding to my
Python reaction?
I conclude that every species reference which is an instance of my subclass
inherits a this attribute, which points to the C++ address of the part
corresponding to the libsbml.SpeciesReference super class. And only this part of
my subclass-object is stored in ListOf. So I loose information using
libsbml.Reaction.addReactant().
I do not want to change the sbml library for compatibility reasons, so I could only
imagine that my object of my subclass must know the address of the C++ proxy which
is generated from the SWIG::director. I could then override 'this' with that
C++ address to track my subclass-object.
However, this sounds very complicated.
What do you think?
oliver
Oliver Ratmann
85 Burgoyne Road
London N41AB
+44 7956001378
-----Original Message-----
From: libsbml-discuss-bounces@caltech.edu on behalf of Ben Bornstein
Sent: Tue 4/18/2006 9:47 PM
To: LibSBML Discussion List
Subject: Re: [libsbml-discuss] how to obtain my subclass from ListOf
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?
|
|
|
Posts: 287
Registered: September 2003
|
|
Re: how to obtain my subclass from ListOf
|
19 Apr '06 17:04
|
 |
|
Hi Oliver,
> I have understood that the SWIG::director would allow me to override
> an existing libsbml method such as
> libsbml.SpeciesReference.getSpecies().
>
> This might indeed be helpful, thank you for the hint.
>
> However, my original problem is that I add an object whose class is
> derived from
> libsbml.SpeciesReference to the ListOfReactants in libsbml.Reactions.
Although it may not be immediately clear, SWIG directors will solve
your problem as well. They allow for Python subclasses to be
completely substitutable for their parent C++ classes.
> I do not want to change the sbml library for compatibility reasons
Right. I was suggesting that if you came-up with a decent solution
that required reasonable and modest modifications to libSBML, I would
be willing to fold those changes back into the library.
> I could only imagine that my object of my subclass must know the
> address of the C++ proxy which is generated from the
> SWIG::director. I could then override 'this' with that C++ address
> to track my subclass-object.
>
> However, this sounds very complicated.
>
> What do you think?
This will work in libSBML 2.3.x but not 3.0. It's not too
complicated. The example program at the end of this message uses a
customized Python dictionary (ObjectRegistry) to map subclassed
libSBML objects to their parent libSBML object based on SWIG 'this'
pointers. In libSBML 3.0, the problem is libSBML copies objects
passed to it rather than simply taking over ownership of the passed-
in object. Copying objects means the 'this' pointers will no longer
match. You could change my example program to use SBase ids (species
for SpeciesReferences) which *should* always be unique. This assumes
however that i) you have an id at the time of object construction,
ii) you don't change an object's id (otherwise, you would have to
update the registry), and iii) you don't store UnitDefinitions or
local Parameters in the registry as they are in separate namespaces
and their ids can legally "conflict" with SBML objects elsewhere.
Again, I think directors are the way to go. In the meantime, the
code below should provide a decent interim solution.
Thanks.
Ben
#!/usr/bin/env python
import libsbml
class ObjectRegistry (dict):
def add (self, obj):
self[obj] = obj
def getKey (self, obj):
if not hasattr(obj, 'this'): raise TypeError('Not a SWIG object')
return hex( obj.this )
def __contains__ (self, key):
return dict.__contains__(self, self.getKey(key))
def __getitem__ (self, key):
return dict.__getitem__(self, self.getKey(key))
def __setitem__ (self, key, value):
dict.__setitem__(self, self.getKey(key), value)
Registry = ObjectRegistry()
class MySpeciesReference (libsbml.SpeciesReference):
def __init__ (self):
libsbml.SpeciesReference.__init__(self)
Registry.add(self)
msr = MySpeciesReference()
r = libsbml.Reaction()
r.addReactant(msr)
sr = r.getReactant(0)
print type(sr)
print type(Registry[sr])
|
|
|
Posts: 11
Registered: June 2006
|
|
RE: how to obtain my subclass from ListOf
|
23 Apr '06 15:06
|
 |
|
Hi Ben,
Thank you for your last answer!
I will see if I get the SWIG::directors running.
I have downloaded libsbml2.3.4 some weeks ago, and now reconfigured it
with (so it is still the same version)
./configure --with-expat --with-python --with-swig
I observe that libsbml.py is now different in that all ..Ptr classes are missing?
I have attached the current libsbml.py and the old one, when running
./configure --with-expat --with-python
as libsbml.copy.py
Is there a way to get the ..Ptr classes back, as I make use of them?
olli
Oliver Ratmann
85 Burgoyne Road
London N41AB
+44 7956001378
-----Original Message-----
From: libsbml-discuss-bounces@caltech.edu on behalf of Ben Bornstein
Sent: Thu 4/20/2006 1:04 AM
To: LibSBML Discussion List
Subject: Re: [libsbml-discuss] how to obtain my subclass from ListOf
Hi Oliver,
> I have understood that the SWIG::director would allow me to override
> an existing libsbml method such as
> libsbml.SpeciesReference.getSpecies().
>
> This might indeed be helpful, thank you for the hint.
>
> However, my original problem is that I add an object whose class is
> derived from
> libsbml.SpeciesReference to the ListOfReactants in libsbml.Reactions.
Although it may not be immediately clear, SWIG directors will solve
your problem as well. They allow for Python subclasses to be
completely substitutable for their parent C++ classes.
> I do not want to change the sbml library for compatibility reasons
Right. I was suggesting that if you came-up with a decent solution
that required reasonable and modest modifications to libSBML, I would
be willing to fold those changes back into the library.
> I could only imagine that my object of my subclass must know the
> address of the C++ proxy which is generated from the
> SWIG::director. I could then override 'this' with that C++ address
> to track my subclass-object.
>
> However, this sounds very complicated.
>
> What do you think?
This will work in libSBML 2.3.x but not 3.0. It's not too
complicated. The example program at the end of this message uses a
customized Python dictionary (ObjectRegistry) to map subclassed
libSBML objects to their parent libSBML object based on SWIG 'this'
pointers. In libSBML 3.0, the problem is libSBML copies objects
passed to it rather than simply taking over ownership of the passed-
in object. Copying objects means the 'this' pointers will no longer
match. You could change my example program to use SBase ids (species
for SpeciesReferences) which *should* always be unique. This assumes
however that i) you have an id at the time of object construction,
ii) you don't change an object's id (otherwise, you would have to
update the registry), and iii) you don't store UnitDefinitions or
local Parameters in the registry as they are in separate namespaces
and their ids can legally "conflict" with SBML objects elsewhere.
Again, I think directors are the way to go. In the meantime, the
code below should provide a decent interim solution.
Thanks.
Ben
#!/usr/bin/env python
import libsbml
class ObjectRegistry (dict):
def add (self, obj):
self[obj] = obj
def getKey (self, obj):
if not hasattr(obj, 'this'): raise TypeError('Not a SWIG object')
return hex( obj.this )
def __contains__ (self, key):
return dict.__contains__(self, self.getKey(key))
def __getitem__ (self, key):
return dict.__getitem__(self, self.getKey(key))
def __setitem__ (self, key, value):
dict.__setitem__(self, self.getKey(key), value)
Registry = ObjectRegistry()
class MySpeciesReference (libsbml.SpeciesReference):
def __init__ (self):
libsbml.SpeciesReference.__init__(self)
Registry.add(self)
msr = MySpeciesReference()
r = libsbml.Reaction()
r.addReactant(msr)
sr = r.getReactant(0)
print type(sr)
print type(Registry[sr])
|
|
|
Posts: 287
Registered: September 2003
|
|
|
Posts: 11
Registered: June 2006
|
|
|
Posts: 287
Registered: September 2003
|
|
|
Posts: 11
Registered: June 2006
|
|
RE: how to obtain my subclass from ListOf
|
24 Apr '06 14:59
|
 |
|
Hi Ben,
I use the Ptr only once, to reference a default unit definition, so I create no new ones
but update the Ptr only when the default changes. However, this is not essential.
Did you configure libsbml2.3.4 with swig1.3.29? I get
with ./configure --with-expat --with-swig=$SWIG_DIR --with-python
and make and make install:
make swigfiles
make[4]: Entering directory `/home/olli/build/libsbml-2.3.4/src/bindings/python'
../swig/swigdoc.py python -I../.. ../swig/libsbml.i pydoc.i
/usr/local/bin/swig -I/usr/include/python2.3 -I../swig -I../.. -c++ -python -o libsbml_wrap.cpp libsbml.i
../../math/ASTNodeType.h:64: Error: Type error. Expecting an int
../../math/ASTNodeType.h:65: Error: Type error. Expecting an int
../../math/ASTNodeType.h:66: Error: Type error. Expecting an int
../../math/ASTNodeType.h:67: Error: Type error. Expecting an int
../../math/ASTNodeType.h:69: Error: Type error. Expecting an int
make[4]: *** [swigfiles] Error 5
make[4]: Leaving directory `/home/olli/build/libsbml-2.3.4/src/bindings/python'
by the way, I am experimenting with the following: I parse a SBML file with
the SBML reader, and then convert to my data structure. Since I extend libsbml,
I tried to take the C++ objects as they are and simply add some python attributes.
For example,
def _initSBML(self,iCell,kineticLaw,reagents,products,sbmlReaction):
self.this= kineticLaw.this#copy pointer only, do not create a new C++ object
self.thisown= kineticLaw.thisown
self._formulae= []
self._kineticParametersBaseIdx= None
self.setFormulae(reagents, products, iCell, kineticLaw.getFormula())#I need more than one formula, which are blueprints for a binary representation
this all works fine as long as kineticLaw itself is not destroyed. I somehow
would like to pass the ownership completely, and I guess the C++ instance does
not know about my object which stole the C++ adress from kineticLaw? Are there
any simple recipes, or is a copy the only solution? Note that I do not call the constructor
to lisbml.kineticLaw.
PS: I tried
self.thisown=True
and
self.thisown= True; kineticLaw.thisown=False
as well, but no effect.
Copying pointers would save me from copying all attributes, and possible future extensions to sbml
which I do not know about now.
cheers,
olli
Oliver Ratmann
85 Burgoyne Road
London N41AB
+44 7956001378
-----Original Message-----
From: libsbml-discuss-bounces@caltech.edu on behalf of Ben Bornstein
Sent: Mon 4/24/2006 6:17 PM
To: LibSBML Discussion List
Subject: Re: [libsbml-discuss] how to obtain my subclass from ListOf
Hi Oliver,
> swig1.3.25 however works fine and gives me all --Ptr classes in the
> binding
In what way do you depend on the Ptr classes? Since they are not
present in later versions of SWIG (e.g. 1.3.29), depending on them is
probably not a good idea in the long term.
> I do not know if this is going to hamper my/our efforts to
> implement the SWIG::directors, for the moment I am going to work
> with swig1.3.25
How hard would it be for you to upgrade to SWIG 1.3.29? I'd like to
use it for libSBML 3.0. Also, since directors are rather new, it's
better to work with the latest stable version of SWIG.
Thanks.
Ben
|
|
|
|