-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12 from ReactionMechanismGenerator/juliacall
Switch from pyjulia to juliacall
- Loading branch information
Showing
11 changed files
with
442 additions
and
325 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
juliaup update | ||
python -c "from pyrms import rms" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#for conda build | ||
package: | ||
name: pyrms | ||
version: {{ environ.get('GIT_DESCRIBE_TAG', '') }} | ||
|
||
source: | ||
path: ../ | ||
|
||
build: | ||
number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }} | ||
script_env: | ||
- JULIAUP_DEPOT_PATH=$PREFIX/share/juliaup | ||
- JULIA_DEPOT_PATH=$PREFIX/share/julia | ||
- JULIA_CONDAPKG_ENV=$PREFIX | ||
|
||
requirements: | ||
host: | ||
- pyjuliacall | ||
- rmgmolecule >=0.3 | ||
- rdkit >=2015.09.2 | ||
- setuptools | ||
- juliaup | ||
- numpy | ||
run: | ||
- pydot >=2.0 | ||
- yaml | ||
- pyjuliacall | ||
- rmgmolecule >=0.3 | ||
- rdkit >=2015.09.2 | ||
- juliaup | ||
- jupyter | ||
- matplotlib | ||
- nose | ||
test: | ||
imports: | ||
- pyrms | ||
commands: | ||
- nosetests pyrms/rmsTest.py # [unix] | ||
about: | ||
home: http://github.com/ReactionMechanismGenerator/pyrms | ||
license: MIT | ||
summary: "A program for simulating and analyzing kinetic models of chemical reaction mechanisms." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
name: CI | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
tags: '*' | ||
pull_request: | ||
workflow_dispatch: | ||
|
||
jobs: | ||
test: | ||
runs-on: ${{ matrix.os }} | ||
defaults: | ||
run: | ||
shell: bash -l {0} | ||
strategy: | ||
matrix: | ||
os: | ||
- ubuntu-latest | ||
architecture: [x64] | ||
python-version: ['3.9'] | ||
fail-fast: false | ||
name: Test ${{ matrix.os }} ${{ matrix.architecture }} | ||
Python ${{ matrix.python-version }} | ||
steps: | ||
- uses: actions/checkout@v1 | ||
- name: Setup python | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
architecture: ${{ matrix.architecture }} | ||
- name: Setup Conda Environment | ||
uses: conda-incubator/setup-miniconda@v3 | ||
with: | ||
activate-environment: rms_env | ||
environment-file: environment.yml | ||
miniforge-variant: Mambaforge | ||
miniforge-version: "latest" | ||
python-version: ${{ matrix.python-version }} | ||
use-mamba: true | ||
- name: Install packages | ||
run: | | ||
python -m pip install pytest nbmake | ||
python -m pip install -e . | ||
- name: Conda Info | ||
run: | | ||
mamba info | ||
mamba list | ||
- name: Run test | ||
run: | | ||
nosetests pyrms/rmsTest.py | ||
pytest --nbmake Ipython/pyrms_example.ipynb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
name: pyrms_env | ||
channels: | ||
- defaults | ||
- mjohnson541 | ||
- conda-forge | ||
dependencies: | ||
- juliaup | ||
- nose | ||
- pyjuliacall | ||
- rmgmolecule >= 0.3 | ||
- rdkit | ||
- pydot >= 2.0 | ||
- matplotlib | ||
- numpy | ||
- jupyter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,45 @@ | ||
import os | ||
import subprocess | ||
import shutil | ||
from subprocess import run | ||
# juliacall must be loaded after `_ensure_julia_installed()` is run, | ||
# so this import is in `load_julia_packages()` | ||
# from juliacall import Main | ||
|
||
def install(): | ||
def _find_julia(): | ||
return shutil.which("julia") | ||
|
||
def _ensure_julia_installed(): | ||
if not _find_julia(): | ||
print("No Julia version found. Installing Julia.") | ||
run("juliaup update") | ||
if not _find_julia(): | ||
raise RuntimeError( | ||
"Julia installed with jill but `julia` binary cannot be found in the path" | ||
) | ||
|
||
# TODO: upstream this function or an alternative into juliacall | ||
def load_julia_packages(*names): | ||
""" | ||
Install Julia packages required for diffeqpy. | ||
Load Julia packages and return references to them, automatically installing julia and | ||
the packages as necessary. | ||
""" | ||
import julia | ||
import diffeqpy | ||
julia.install() | ||
diffeqpy.install() | ||
from julia.api import Julia | ||
jl = Julia(compiled_modules=False) | ||
from julia import Pkg | ||
Pkg.add("ReactionMechanismSimulator") | ||
from julia import ReactionMechanismSimulator | ||
# This is terrifying to many people. However, it seems SciML takes pragmatic approach. | ||
_ensure_julia_installed() | ||
|
||
script = """import Pkg | ||
Pkg.activate(\"pyrms\", shared=true) | ||
try | ||
import {0} | ||
catch e | ||
e isa ArgumentError || throw(e) | ||
Pkg.add([{1}]) | ||
import {0} | ||
end | ||
{0}""".format(", ".join(names), ", ".join(f'"{name}"' for name in names)) | ||
|
||
# Unfortunately, `seval` doesn't support multi-line strings | ||
# https://github.com/JuliaPy/PythonCall.jl/issues/433 | ||
script = script.replace("\n", ";") | ||
|
||
# Must be loaded after `_ensure_julia_installed()` | ||
from juliacall import Main | ||
return Main.seval(script) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,9 @@ | ||
import os | ||
import sys | ||
from IPython.display import Image | ||
import IPython.display | ||
from . import load_julia_packages | ||
rms, _, = load_julia_packages("ReactionMechanismSimulator", "PythonCall") | ||
from juliacall import Main | ||
|
||
from julia import Main | ||
from julia import ReactionMechanismSimulator | ||
sys.modules[__name__] = rms | ||
|
||
from julia.ReactionMechanismSimulator import makefluxdiagrams | ||
|
||
def pygetfluxdiagram(bsol,t,centralspecieslist=[],superimpose=False, | ||
maximumnodecount=50, maximumedgecount=50, concentrationtol=1e-6, speciesratetolerance=1e-6, | ||
maximumnodepenwidth=10.0,maximumedgepenwidth=10.0,radius=1,centralreactioncount=-1,outputdirectory="fluxdiagrams", | ||
colorscheme="viridis"): | ||
|
||
fd = makefluxdiagrams(bsol,[t], centralspecieslist=centralspecieslist,superimpose=superimpose, | ||
maximumnodecount=maximumnodecount, maximumedgecount=maximumedgecount, concentrationtol=concentrationtol, | ||
speciesratetolerance=speciesratetolerance,maximumnodepenwidth=maximumnodepenwidth, | ||
maximumedgepenwidth=maximumedgepenwidth,radius=radius,centralreactioncount=centralreactioncount, | ||
outputdirectory=outputdirectory,colorscheme=colorscheme) | ||
|
||
IPython.display.display(IPython.display.Image(os.path.join(fd.outputdirectory,"flux_diagram_1.png"))) | ||
|
||
ReactionMechanismSimulator.getfluxdiagram = pygetfluxdiagram | ||
|
||
# These functions force the returned object to be a jlwrap object, | ||
# to avoid the solution object gets converted into list of lists | ||
_threadedsensitivities_inds = Main.pyfunctionret(ReactionMechanismSimulator.threadedsensitivities, Main.Any, Main.PyAny, Main.PyAny) | ||
_threadedsensitivities = Main.pyfunctionret(ReactionMechanismSimulator.threadedsensitivities, Main.Any, Main.PyAny) | ||
# Allow us the get the solution object in the julia wrapped object without | ||
# it being converted into list of lists | ||
get = Main.pyfunctionret(Main.get, Main.Any, Main.PyAny, Main.PyAny, Main.PyAny) | ||
def pythreadedsensitivities(react, inds=None, | ||
odesolver=Main.nothing, senssolver=Main.nothing, | ||
odekwargs={"abstol": 1e-20, "reltol": 1e-6}, | ||
senskwargs={"abstol": 1e-6, "reltol": 1e-3}): | ||
if inds is not None: | ||
# the sol_dict returned here is a jlwrap object and is not easy to access the contents | ||
sol_dict = _threadedsensitivities_inds(react, inds, | ||
odesolver=odesolver, senssolver=senssolver, | ||
odekwargs=odekwargs, senskwargs=senskwargs) | ||
# pysol_dict is the python dictionary, but the solution object got turned into list of lists | ||
pysol_dict = Main.PyObject(sol_dict) | ||
# this remakes the dictionary with the values as julia wrapped object ODEsolution, | ||
# but at the same time allows the user to access it normally like a dictionary | ||
return {key: get(sol_dict, key, Main.Any) for key in pysol_dict.keys()} | ||
else: | ||
sol = _threadedsensitivities(react, | ||
odesolver=odesolver, senssolver=senssolver, | ||
odekwargs=odekwargs, senskwargs=senskwargs) | ||
return sol | ||
|
||
ReactionMechanismSimulator.threadedsensitivities = pythreadedsensitivities | ||
|
||
for item in dir(ReactionMechanismSimulator): | ||
try: | ||
locals()[item] = getattr(ReactionMechanismSimulator,item) | ||
except AttributeError: | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.