Calling Julia and CMBLensing.jl directly from Python is very transparent. This is made possible by the PyJulia package. You can install it into your Python environment with, e.g.:
$ pip install --user julia
Important: If your Python executable is statically-linked (this is quite often the case, e.g. its the default on Ubuntu and Conda) you need one extra step. Basically, instead of running
ipython at the command line to launch your interpreter, run
python-jl -m IPython, respectively. If you use Jupyter, you'll need to edit your
kernel.json file (you can find its location via
jupyter kernelspec list) and change it to use
The wrapper script
python-jl does some special initializion but otherwise drops you into the Python/IPython interpreter that you are familiar with.
The PyJulia docs also give instructions on how to install a dynamically-linked Python executable which is the most ideal solution, and only slightly more work than above.
Once PyJulia is installed, you can access any Julia package
Foo from the Python package
julia.Foo, and everything pretty much works the same.
julia.Base.cos(1) # <--- this is Julia's cosine function
You can also run arbitrary Julia code with the
%julia cell magic (this is helpful if you want to use Julia language features or syntax which don't exist in Python):
Initializing Julia interpreter. This may take some time...
1:10 is not valid Python syntax, but we can do:
The cell magic lets you interpolate values from Python into the Julia expression, which can be a convenient way to pass values back and forth:
x = %julia 1 + 2
%julia 2 * $x
The most robust way to call CMBLensing.jl from Python is just to wrap everything in Julia magic and interpolate things back and forth as-needed. Lets try and follow the Lensing a flat-sky map example from Python. First, we load the package:
%%julia using CMBLensing
Next, we simulate some data:
%%julia @unpack f,ϕ = load_sim( θpix = 2, Nside = 256, T = Float32, pol = :I );
Similarly, the rest of the commands from that example will work in Python if just called via Julia magic.
At any point, you can do whatever you'd like with any of the results stored in Julia variables, e.g. transferring the simulated maps back as Python arrays,
f = %julia f[:Ix] f
array([[ 2.14433079e+01, 8.06890488e+00, -3.99856567e-02, ..., 2.51326046e+01, 3.13734188e+01, 3.02906036e+01], [ 4.04219818e+00, -1.25433235e+01, -1.90803986e+01, ..., 4.11496353e+01, 3.92035675e+01, 2.37450237e+01], [-2.11511803e+00, -1.81152878e+01, -2.11349697e+01, ..., 6.36235733e+01, 5.35934296e+01, 2.39154549e+01], ..., [ 8.01032104e+01, 1.04477966e+02, 1.14797546e+02, ..., 6.55126572e+01, 6.84007721e+01, 6.75415344e+01], [ 6.25369949e+01, 7.11719055e+01, 7.58213806e+01, ..., 3.14495430e+01, 4.60028687e+01, 5.58389359e+01], [ 4.29686203e+01, 3.72884407e+01, 3.37383156e+01, ..., 1.77531166e+01, 3.34146500e+01, 4.34189987e+01]], dtype=float32)
You can also pass variables back to Julia, e.g.
%julia g = FlatMap($f);
You can also call Julia directly without magic, which sometimes offers more flexibility, although has some limitations.
To do so, first import CMBLensing. into Python. In Julia,
using CMBLensing imports all of the CMBLensing symbols into the current namespace. In Python this is:
from julia.CMBLensing import *
If we want to call
load_sim as before, we must take into account a few things:
- You won't be able to use the
@unpackmacro since macros on arbitrary code don't exist in Python.
Float32isn't imported into Python by default, so you'll need to specify the module.
:Pis invalid syntax in Python, you should use a string
Given all of that, the call will look like:
sim = load_sim( θpix = 2, Nside = 256, T = julia.Base.Float32, pol = "P" )
If we wish to grab the lensing potential from the result, there's an additional consideration. Python does not differentiate between the characters
ϕ (\phi) and
φ (\varphi), and maps both of them back to
φ (\varphi) in Julia, which unfortunately is the wrong one for CMBLensing (which instead makes extensive use of the variable name
ϕ (\phi)). Thus, calling
sim.ϕ from Python does not work. Instead, we have to do that part in Julia:
ϕ = %julia $sim.ϕ
To plot, we need to use the plot function from Julia's PyPlot, since this will know about plotting CMBLensing objects.
from julia.PyPlot import plot
┌ Warning: No working GUI backend found for matplotlib └ @ PyPlot ~/.julia/packages/PyPlot/XaELc/src/init.jl:165
For non-CMBLensing objects, this plot function will just pass-through to matplotlib, so will not affect affect your session otherwise.