Forums

F.A.Q. F.A.Q.    Register Register    Login Login    Home Home
Search Search
SBML Discussions » sbml-interoperability » how to obtain my subclass from ListOf
Show: Today's Posts  :: Message Navigator
Switch to threaded view of this topic Create a new topic Submit Reply
AuthorTopic
oliver.ratmann


Posts: 11
Registered:
June 2006
how to obtain my subclass from ListOf 18 Apr '06 11:49 Go to next message

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


      
Ben Bornstein


Posts: 287
Registered:
September 2003
Re: how to obtain my subclass from ListOf 18 Apr '06 13:47 Go to previous messageGo to next message

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?

      
oliver.ratmann


Posts: 11
Registered:
June 2006
RE: how to obtain my subclass from ListOf 19 Apr '06 13:41 Go to previous messageGo to next message

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?


      
Ben Bornstein


Posts: 287
Registered:
September 2003
Re: how to obtain my subclass from ListOf 19 Apr '06 17:04 Go to previous messageGo to next message

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])

      
oliver.ratmann


Posts: 11
Registered:
June 2006
RE: how to obtain my subclass from ListOf 23 Apr '06 15:06 Go to previous messageGo to next message

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])




      
Ben Bornstein


Posts: 287
Registered:
September 2003
Re: how to obtain my subclass from ListOf 23 Apr '06 16:31 Go to previous messageGo to next message

Hi Oliver,

> ./configure --with-expat --with-python --with-swig
>
> I observe that libsbml.py is now different in that all ..Ptr
> classes are missing?
> Is there a way to get the ..Ptr classes back, as I make use of them?

Did you change the version of SWIG you were using? Configuring --
with-swig reruns SWIG which recreates the generated wrapper code.
Unfortunately, even a minor change in SWIG version number can lead to
dramatically different wrapper code. To get the Ptr classes back,
start with a fresh copy of libSBML 2.3.4 and omit the --with-swig
configure option or make sure you're using SWIG 1.3.24.

Ben

      
oliver.ratmann


Posts: 11
Registered:
June 2006
RE: how to obtain my subclass from ListOf 24 Apr '06 06:45 Go to previous messageGo to next message

Dear Ben,

1) I have spotted that you bounced my last email from the mailing list; would you prefer that I contact
you directly on a certain email address?

2) I tried to configure libsbml2.3.4 with swig1.3.24 which does not work.
what version are you using? (error below)

I further tried to include the relevant --Ptr classes into the swig i file, because they are not in there
but that fails because there are no respective header files, so I assume the --Ptr classes are generated on
the run.

thank you
olli

olliver:/home/olli/build/libsbml-2.3.4# ./configure --with-expat --with-swig=$SWIG_DIR --with-python
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking for g++... g++
checking for C++ compiler default output file name... a.out
checking whether the C++ compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C++ compiler... yes
checking whether g++ accepts -g... yes
checking for gcc... gcc
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking how to run the C preprocessor... gcc -E
checking for ranlib... ranlib
checking for a BSD-compatible install... /usr/bin/install -c
checking whether make sets $(MAKE)... yes
checking for autoconf... /usr/bin/autoconf
checking for aclocal... aclocal
checking for ar... /usr/bin/ar
checking for swig... /usr/local/share/swig/1.3.24/bin/swig
./configure: line 1: /usr/local/share/swig/1.3.24/bin/swig: No such file or directory
checking swig version... expr: syntax error
expr: syntax error
expr: syntax error

checking requested swig version (1.3.24)... ./configure: line 3517: test: -ge: unary operator expected
no
configure: error: installed version of swig is too old!

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 12:31 AM
To: LibSBML Discussion List
Subject: Re: [libsbml-discuss] how to obtain my subclass from ListOf

Hi Oliver,

> ./configure --with-expat --with-python --with-swig
>
> I observe that libsbml.py is now different in that all ..Ptr
> classes are missing?
> Is there a way to get the ..Ptr classes back, as I make use of them?

Did you change the version of SWIG you were using? Configuring --
with-swig reruns SWIG which recreates the generated wrapper code.
Unfortunately, even a minor change in SWIG version number can lead to
dramatically different wrapper code. To get the Ptr classes back,
start with a fresh copy of libSBML 2.3.4 and omit the --with-swig
configure option or make sure you're using SWIG 1.3.24.

Ben



      
Ben Bornstein


Posts: 287
Registered:
September 2003
Re: how to obtain my subclass from ListOf 24 Apr '06 10:06 Go to previous messageGo to next message

Hi Oliver,


> 1) I have spotted that you bounced my last email from the mailing
> list; would you prefer that I contact you directly on a certain
> email address?

I don't recall bouncing a message. Perhaps I was clicking too fast
and hit the wrong button by mistake. Sorry.


> 2) I tried to configure libsbml2.3.4 with swig1.3.24 which does not
> work.
> what version are you using? (error below)

The language bindings for LibSBML 2.3.4 were created with SWIG 1.3.24.


Ben

      
oliver.ratmann


Posts: 11
Registered:
June 2006
RE: how to obtain my subclass from ListOf 24 Apr '06 14:59 Go to previous message

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



      
Ben Bornstein


Posts: 287
Registered:
September 2003
Re: how to obtain my subclass from ListOf 18 Apr '06 13:47 Go to previous message

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?

      
oliver.ratmann


Posts: 11
Registered:
June 2006
RE: how to obtain my subclass from ListOf 19 Apr '06 13:41 Go to previous message

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?


      
Ben Bornstein


Posts: 287
Registered:
September 2003
Re: how to obtain my subclass from ListOf 19 Apr '06 17:04 Go to previous message

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])

      
oliver.ratmann


Posts: 11
Registered:
June 2006
RE: how to obtain my subclass from ListOf 23 Apr '06 15:06 Go to previous message

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])




      
Ben Bornstein


Posts: 287
Registered:
September 2003
Re: how to obtain my subclass from ListOf 23 Apr '06 16:31 Go to previous message

Hi Oliver,

> ./configure --with-expat --with-python --with-swig
>
> I observe that libsbml.py is now different in that all ..Ptr
> classes are missing?
> Is there a way to get the ..Ptr classes back, as I make use of them?

Did you change the version of SWIG you were using? Configuring --
with-swig reruns SWIG which recreates the generated wrapper code.
Unfortunately, even a minor change in SWIG version number can lead to
dramatically different wrapper code. To get the Ptr classes back,
start with a fresh copy of libSBML 2.3.4 and omit the --with-swig
configure option or make sure you're using SWIG 1.3.24.

Ben

      
oliver.ratmann


Posts: 11
Registered:
June 2006
RE: how to obtain my subclass from ListOf 24 Apr '06 06:45 Go to previous message

Dear Ben,

1) I have spotted that you bounced my last email from the mailing list; would you prefer that I contact
you directly on a certain email address?

2) I tried to configure libsbml2.3.4 with swig1.3.24 which does not work.
what version are you using? (error below)

I further tried to include the relevant --Ptr classes into the swig i file, because they are not in there
but that fails because there are no respective header files, so I assume the --Ptr classes are generated on
the run.

thank you
olli

olliver:/home/olli/build/libsbml-2.3.4# ./configure --with-expat --with-swig=$SWIG_DIR --with-python
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking for g++... g++
checking for C++ compiler default output file name... a.out
checking whether the C++ compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C++ compiler... yes
checking whether g++ accepts -g... yes
checking for gcc... gcc
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking how to run the C preprocessor... gcc -E
checking for ranlib... ranlib
checking for a BSD-compatible install... /usr/bin/install -c
checking whether make sets $(MAKE)... yes
checking for autoconf... /usr/bin/autoconf
checking for aclocal... aclocal
checking for ar... /usr/bin/ar
checking for swig... /usr/local/share/swig/1.3.24/bin/swig
./configure: line 1: /usr/local/share/swig/1.3.24/bin/swig: No such file or directory
checking swig version... expr: syntax error
expr: syntax error
expr: syntax error

checking requested swig version (1.3.24)... ./configure: line 3517: test: -ge: unary operator expected
no
configure: error: installed version of swig is too old!

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 12:31 AM
To: LibSBML Discussion List
Subject: Re: [libsbml-discuss] how to obtain my subclass from ListOf

Hi Oliver,

> ./configure --with-expat --with-python --with-swig
>
> I observe that libsbml.py is now different in that all ..Ptr
> classes are missing?
> Is there a way to get the ..Ptr classes back, as I make use of them?

Did you change the version of SWIG you were using? Configuring --
with-swig reruns SWIG which recreates the generated wrapper code.
Unfortunately, even a minor change in SWIG version number can lead to
dramatically different wrapper code. To get the Ptr classes back,
start with a fresh copy of libSBML 2.3.4 and omit the --with-swig
configure option or make sure you're using SWIG 1.3.24.

Ben



      
Ben Bornstein


Posts: 287
Registered:
September 2003
Re: how to obtain my subclass from ListOf 24 Apr '06 10:06 Go to previous message

Hi Oliver,


> 1) I have spotted that you bounced my last email from the mailing
> list; would you prefer that I contact you directly on a certain
> email address?

I don't recall bouncing a message. Perhaps I was clicking too fast
and hit the wrong button by mistake. Sorry.


> 2) I tried to configure libsbml2.3.4 with swig1.3.24 which does not
> work.
> what version are you using? (error below)

The language bindings for LibSBML 2.3.4 were created with SWIG 1.3.24.


Ben

      
oliver.ratmann


Posts: 11
Registered:
June 2006
RE: how to obtain my subclass from ListOf 24 Apr '06 14:59 Go to previous message

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



      
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic:Bug with setLevel in libsbml with the python bindings.
Next Topic:RE: how to obtain my subclass from ListOf PLSE BOUNCE
Go to forum:
-=] Back to Top [=-

Powered by FUDforum. (Copyright Advanced Internet Designs Inc.)

Please use our issue tracking system for any questions or suggestions about this website.