Julia provides several API interfaces to Python in different packages:
Matplotlib
Pandas
librarysympy
yt
... ]using PyCall
@pyimport math
@pyimport numpy as np
math.sin(math.pi) - sin(pi)
n = pyeval("2^50")
# typeof(n)
Interestingly, Julia arrays are wrapped as NumPy array and shared, not copied.
A = rand(4, 4)
Apy = PyObject(A)
# det(Apy) # not possible, no method det(::PyObject)
np.det(A) # or: det(convert(Float64, Apy))
@pyimport scipy.linalg as la # `@pyimport scipy.linalg` not possible (why?)
Ainv = la.inv(A)
A[1, 1] = 0.0;
Apy
Example: Root finding for a difficult and well-known test function
fn(x) = log(x) + x*x/(2.0*exp(1.0)) - 2.0*x/sqrt(exp(1.0)) + 1.0
This test function is so flat between 1.0 and 3.4 that every root finder except perhaps an arbitrary precision one will not be able to locate this root exactly.
The true root is obviously sqrt(e) = 1.6487212707001282
.
# Pkg.add("Roots")
using Roots
fzero(fn, 1.0, 3.4)
@pyimport scipy.optimize as spo # 1-dim: brentq, brenth, ridder, bisect, newton
spo.brentq(fn, 1.0, 3.4)
Example: Interpolation and integration
using HDF5
HDF5
# h5write("xydata.h5", "xy", [x y])
xy = h5read("xydata.h5", "xy");
x = xy[1:101, 1]; y = xy[1:101, 2];
Imagine there is no good enough spline interpolation available in Julia. We utilize the 'interpolate' module in SciPy and do the integration in Julia.
@pyimport scipy.interpolate as si
f2 = si.interp1d(x, y, kind="cubic")
# f2(xx) ? f2 not recognized as 'callable'
# pycall(f2, Float64, pi)
f2
is a Python object, to evaluate we need to apply pycall
to it.
We visualize the data points and the spline interpolation.
xx = linspace(0, 2*pi, 1000);
yy = pycall(f2, PyAny, xx);
using PyPlot
figure(figsize = (8.0, 4.0))
# plot(xx, yy, "r")
plot(x, y, "b.")
grid()
@pyimport scipy.integrate as spq
spq.quad(f2, 0.0, pi)
Instead, we transform this interpolated Python function back to Julia and integrate it here using a Gauss-Kronrod quadrature.
f22(x) = pycall(f2, PyAny, x)
quadgk(f22, 0, pi)
Example: Gauss' Hypergeometric Function
Julia does not have an implementation of the Hypergeometric function 2F1, but Python has.
@pyimport scipy.special as special
println(special.hyp2f1(1/3, 2/3, 5/6, 27/32)) # 8/5
println(special.hyp2f1(1/4, 1/2, 3/4, 80/81)) # 9/5
These are two of the very few points where the hypergeometric function takes on rational values.
Unfortunately, the Python hypergeometric function is spuriously wrong (not inaccurate, but totally wrong) in the complex plane!
using SymPy
x, y, z = Sym(:x, :y, :z) # or Sym("x y z")
limit(sin(x)/x, x, 0.0)
z = diff(sin(x)/x, x)
z = integrate(sin(x)/x, x, 1, Inf)
float(z)
Julia has a built-in feature to call functions in external shared libraries (C API). The syntax isccall((function symbol, library name) return type, (argument types), arguments...)
c_sin(x) = ccall((:sin,"libm"), Cdouble, (Cdouble,), x)
c_sin(pi/4)
The problem is that this approach will not make functions, defined in Julia, available to the C code.
See the "Rcpp" discussion in R.
The pyjulia
Python module is developing an interface to Julia that works with Python 2 & 3. (pyjulia
is still in an experimental phase).
import julia
j = julia.Julia()
j.eval("2^10") #=> 1024
j.eval("2^100") #=> 0
j.eval("big(2)^100") #=> 1267650600228229401496703205376L
j.sqrt(2.0) #=> 1.4142135623730951
j.help("sqrt")
# Base.sqrt(x)
# Return \sqrt{x}. Throws "DomainError" for negative "Real"
# arguments. Use complex negative arguments instead. The prefix
# operator "√" is equivalent to "sqrt".
from julia import randn as r
r(100)
# works with julia and user-defined packages
import numpy as np
x = np.array([0.0, 1.0])
from julia import NumericalMath
NumericalMath.trapz(x, x)
# 0.5