Package: gpac
gpac Python packageTable of contentsOverviewAPIInstallationExamplesPlotting ODEsGetting trajectory data of ODEsChemical reaction networksOverviewThis is a Python package for simulating General-Purpose Analog Computers as defined and studied by Claude Shannon. It's primarily a front-end toscipyandsympymaking it easier to specify systems of ODEs, numerically integrate them, and plot their solutions.This is ostensibly whatpyodesysdoes as well, and that package is much more powerful and configurable than gpac. The purpose of gpac is primarily to be simpler to use for common cases of ODEs, at the cost of being less expressive.Note:Some of the relative links below are intended to be used only on the GitHub page for this project:https://github.com/UC-Davis-molecular-computing/gpac#readmeThey will not work if you are reading this document on PyPI, for example.APIThe API for the package is here:https://gpac.readthedocs.io/InstallationPython 3.7 or above is required. There are two ways you can install thegpacpackage, pip or git:A.pip:The easiest option is to install viapipby typing the following at the command line:pip install gpacB.git:The other option is to clone the git repo. You may need to installgitfirst:https://git-scm.com/book/en/v2/Getting-Started-Installing-GitInstall the dependencies by typing the following at the command line:pip install numpy scipy matplotlib sympyClone this repo by typing the following at the command line:git clone https://github.com/UC-Davis-molecular-computing/gpac.gitAdd the directory into which you cloned the repo (it should be thegpacsubdirectory under your working directory where thegit cloneabove was executed) to your PYTHONPATH environment variable. Seehttps://www.geeksforgeeks.org/pythonpath-environment-variable-in-python/for example if you don't know how to alter PYTHONPATH. After doing this you should be able to import the gpac package in your Python scripts/Jupyter notebooks withimport gpac. Try testing this out in the Python interpreter:$pythonPython3.9.12(main,Apr42022,05:22:27)[MSCv.191664bit(AMD64)]::Anaconda,Inc.onwin32Type"help","copyright","credits"or"license"formoreinformation.>>>importgpac>>>ExamplesSee more examples in the Jupyter notebooknotebook.ipynb.Plotting ODEsODEs are specified by creatingsympysymbols and expressions (or if you like, Python strings), represented as a Python dictodesmapping each variable---a single sympy symbol or Python string---to an expression representing its time derivative, represented as a sympy expression composed of sympy symbols (or for convenience you can also use Python strings, or if the derivative is constant, a Pythonintorfloat).Every symbol that appears in any of the expressionsmustalso be a key in this dict.The initial values are specified as a Python dictinitial_valuesmapping variables (again, sympy symbols or strings) to their initial values (floats). If you leave out a symbol as a key toinitial_values, it is assumed to have initial value 0.Finally, you can specify the times at which to solve for the ODEs as an iterable of floatst_eval. (This is optional; if not specified it uses the time values 0.0, 0.01, 0.02, 0.03, ..., 0.98, 0.99, 1.0)Remaining parameters are optional (see below for examples of them). See API documentation forintegrate_odesandplotfor more details.importsympyimportgpacimportnumpyasnpa,b,c=sympy.symbols('a b c')# ODEs specified as dict mapping each variable to expression describing its derivative.# key representing variable can be a sympy Symbol or string.# value representing derivative can be a sympy Expr, string, or (if constant) int or float.odes={# represents ODEs:a:-a*b+c*a,# d/dt a(t) = -a(t)*b(t) + c(t)*a(t)b:-b*c+a*b,# d/dt b(t) = -b(t)*c(t) + a(t)*b(t)'c':'-c*a + b*c',# d/dt c(t) = -c(t)*a(t) + b(t)*c(t)}initial_values={a:10,b:1,c:1,}t_eval=np.linspace(0,5,200)gpac.plot(odes,initial_values,t_eval=t_eval,figure_size=(12,3),symbols_to_plot=[a,c])Getting trajectory data of ODEsIf you want the data itself from the ODE numerical integration (without plotting it), you can callintegrate_odes(replace the call toplotabove with the following code).t_eval=np.linspace(0,1,5)solution=gpac.integrate_odes(odes,initial_values,t_eval=t_eval)print(f'times ={solution.t}')print(f'a ={solution.y[0]}')print(f'b ={solution.y[1]}')print(f'c ={solution.y[2]}')which printstimes = [0.   0.25 0.5  0.75 1.  ]
a = [10.          4.84701622  0.58753815  0.38765743  3.07392998]
b = [1.         6.84903338 9.63512628 3.03634559 0.38421121]
c = [1.         0.3039504  1.77733557 8.57599698 8.54185881]The valuesolutionreturned byintegrate_odesis the same object returned fromscipy.integrate.solve_ivp.Chemical reaction networksThere are also functionsintegrate_crn_odesandplot_crn, which take as input a description of a set of chemical reactions, derives their ODEs, then integrates/plots them. They both use the functioncrn_to_odes, which converts chemical reactions into ODEs.Seenotebook.ipynbfor examples.Reactions are constructed using operations onSpecieobjects returned from the functionspecies:# plot solution to ODEs of this CRN that computes f(x) = x^2, using the gpac.crn module# 2X -> 2X+Y# Y -> nothingx,y=gpac.species('X Y')rxns=[x+x>>x+x+y,y>>gpac.empty,]initial_values={x:5}t_eval=np.linspace(0,5,100)# plot trajectory of concentrationsgpac.plot_crn(rxns,initial_values,t_eval=t_eval,figure_size=(20,4))Although they appear similar, aSpecieobject (such asxandyreturned from thespeciesfunction above) is different from asympy.Symbolobject. TheSpecieobject is intended to help specify reactions using the notation above with the symbols+,>>, and|(as well as thekandrfunctions for specifying non-unit rate constants, see examplenotebook). However, any of the following objects can be a key in theinitial_valuesparameter toplot_crnandintegrate_crn_odes:Specie,sympy.Symbol, orstr. They will be normalized tosympy.Symbolobjects in keys of the returned dict representing the ODEs.