Skip to content

2024-10

Kill zombie processes

Find and kill zombie process(es). Source

ps axo stat,ppid,pid,comm | grep -w defunct

Kill parent process(es)

sudo kill -9 <ppid>

PyPlot.jl tips

Some tips about JuliaPy/PyPlot.jl, the matplotlib (Python) visualization library for Julia. See also docs for matplotlib since PyPlot.jl largely follows matplotlib's API.

How to solve PyPlot.jl installation errors

Since PyPlot.jl depends on the Python package matplotlib, sometimes simply ]add the package will not work due to some quirks in the installation process.

In a local computer, it is recommended to have a clean Conda environment inside Julia to minimize issues. To enforce a local miniconda environment inside Julia, set the PYTHON environment variable to an empty string.

~/.julia/config/startup.jl
ENV["PYTHON"]=""

And then rebuild related packages.

import Pkg
Pkg.build(["PyCall", "Conda", "PyPlot"])

# should download conda and matplotlib and import PyPlot
using PyPlot

How to share the legend box in double y axis

  • Capture line plot objects from both axes.
  • Call legend() for both(all) line plot objects.
import PyPlot as plt
x1 = 1:10

fig, ax1 = plt.subplots()
l1 = ax1.plot(x1, x1)
ax2 = ax1.twinx()
l2= ax2.plot(x1, exp.(x1))
ax1.legend([first(l1), first(l2)], ["x", "exp(x)"])

How to save as TIFF image

Exporting pyplot figures to TIFF images with a higher dpi and LZW compression.

PyPlot.jl

fig.savefig("fig.tif", dpi=300, pil_kwargs=Dict("compression" => "tiff_lzw"))

PythonPlot.jl

using PythonCall
plt.savefig("fig1.tif", dpi=300, pil_kwargs=pydict(Dict("compression" => "tiff_lzw")))

Change default options in PyPlot.jl

Changing mplstyle and rcparams in matplotlib.

Sources:
1. mplstyle and rcparams for matplotlib
2. PyPlot.jl readme
3. mplstyle and rcparams in matplotlib docs.

Python

matplotlib

import matplotlib as mpl
mpl.rcParams["font.sans-serif"] = "Arial"
mpl.rcParams["font.family"] = "sans-serif"
mpl.rcParams["font.size"] = 12

Julia

PyPlot.jl

import PyPlot as plt
rcParams = plt.PyDict(plt.matplotlib."rcParams")
rcParams["font.sans-serif"] = "Arial"
rcParams["font.family"] = "sans-serif"
rcParams["font.size"] = 12

For Plots.jl, there is an internal pyrcparams dictionary for the pyplot(matplotlib) backend.

using Plots
Plots.pyplot()
Plots.pyrcparams["font.size"] = 12
Plots.pyrcparams["font.sans-serif"] = "Arial"
Plots.pyrcparams["font.family"] = "sans-serif"

PythonPlot.jl

import PythonPlot as plt
plt.matplotlib.rcParams["font.size"] = 14

Dealing with DomainErrors

sqrt(x), log(x), and pow(x) will throw DomainError exceptions with negative x, interrupting differential equation solvers. One can use these functions' counterparts in JuliaMath/NaNMath.jl, returning NaN instead of throwing a DomainError. Then, the solvers will reject the solution and retry with a smaller time step.

sqrt(-1.0) # throws DomainError

import NaNMath as nm
nm.sqrt(-1.0) # NaN

Force display format to PNG

In the VSCode plot panel and fredrikekre/Literate.jl notebooks, PNG images are generally smaller than SVG ones. To force plots to be shown as PNG images, you can use tkf/DisplayAs.jl to show objects in a chosen MIME type.

import DisplayAs.PNG
using Plots
plot(rand(6)) |> PNG

If you don't want to add another package dependency, you could directly use display().

using Plots
PNG(img) = display("image/png", img)
plot(rand(6)) |> PNG

Get the ODE Function from an ODE system

f = ODEFunction(sys) could be useful in plotting vector fields.

using ModelingToolkit
using DifferentialEquations

# Independent (time) and dependent (state) variables (x and RHS)
@independent_variables t
@variables x(t) RHS(t)

# Setting parameters in the modeling
@parameters τ

# Differential operator w.r.t. time
D = Differential(t)

# Equations in MTK use the tilde character (`~`) as equality.
# Every MTK system requires a name. The `@named` macro simply ensures that the symbolic name matches the name in the REPL.

@mtkbuild sys = ODESystem([
    RHS  ~ (1 - x)/τ,
    D(x) ~ RHS
])

tend = 2.0
prob = ODEProblem(sys, [x=>0.0], tend, [τ=>1.0])

prob.f([0.0], prob.p, 0.0) # f(u, p, t) returns the value of D(x)

Get 2D indices from a linear index

Use CartesianIndices((nrow, ncol)), from this discourse post.

x = rand((7, 10))
CI = CartesianIndices((7, 10))
for i in 1:length(x)
    r = CI[i][1]
    c = CI[i][2]
    @assert x[i] == x[r, c]
end