# GSoC 2019: Testing an API

Published:

This is a really short update. Here are a couple things I have been working on since the last blog post.

1) Continuing to write the API so that it is intuitive

2) Writing unit tests

3) Benchmarking

When I last made a blog post about the API, users were to pass the ode parameters and initial conditions as a single vector. That was just to get things off the ground. Now that API is working, I can go back and make that a little more user friendly. The ODEModel (the meat and potatoes of the API) inherits from the theano.Op class, so in the make_node method I changed


def make_node(self, x):
x = theano.tensor.as_tensor_variable(x)

return theano.Apply(self, [x], [x.type()])


to

    def make_node(self, odeparams, initial_condition):

if np.ndim(odeparams)>1:
odeparams = np.ravel(odeparams)
if np.ndim(initial_condition) > 1:
odeparams = np.ravel(initial_condition)

odeparams = tt.as_tensor_variable(odeparams)
initial_condition = tt.as_tensor_variable(initial_condition)
x = tt.concatenate([odeparams,initial_condition])

return theano.Apply(self, [x], [x.type()])


The little bit of logic at the beginning is to get around some shape problems with theano. So now to use the API, instead of doing

  all_params = pm.math.stack([<parameters here>, <initial conditions here>])
forward = ode_model(all_params)


you can do


forward = ode_model(odeparams = [<parameters here>], initial_condition = [<initial conditions here>])


which I think is much better. Explicit is better than implicit. This change actually makes some models run much faster which is interesting.