Custom System Image

Loading NeuroAnalyzer and calling each function for the first time in a session takes time, because Julia compiles the code. A custom system image (sysimage) created with PackageCompiler.jl contains NeuroAnalyzer already compiled, which reduces the loading time considerably.

The scripts for creating the sysimage are in the scripts/ folder of the NeuroAnalyzer repository.

1. Install PackageCompiler

PackageCompiler must be installed in your default Julia environment:

julia -e 'using Pkg; Pkg.add("PackageCompiler")'

2. Clone the repository

git clone https://codeberg.org/AdamWysokinski/NeuroAnalyzer.jl
cd NeuroAnalyzer.jl/scripts

(The scripts cannot be run from an installed copy of the package, because package folders installed by Pkg are read-only.)

3. Generate the sysimage

./create_sysimage.sh

The script:

  • creates the scripts/sysimage/ folder with its own Julia environment (Project.toml and Manifest.toml),
  • installs the current stable release of NeuroAnalyzer (the main branch) into it,
  • compiles the sysimage scripts/sysimage/NeuroAnalyzer.so.

Compilation takes a long time (often 10–30 minutes) and needs several GB of RAM. Each run removes and recreates the sysimage/ folder.

On Windows (without Bash), run the Julia script from a new, empty folder:

mkdir sysimage
cd sysimage
julia ..\create_sysimage.jl

4. Start Julia with the sysimage

Use the sysimage together with the environment it was built from:

julia -t auto --project=path/to/scripts/sysimage -J path/to/scripts/sysimage/NeuroAnalyzer.so
using NeuroAnalyzer

NeuroAnalyzer now loads without compilation. For convenience, define a shell alias, e.g.:

alias juliana='julia -t auto --project=$HOME/NeuroAnalyzer.jl/scripts/sysimage -J $HOME/NeuroAnalyzer.jl/scripts/sysimage/NeuroAnalyzer.so'

In Visual Studio Code, the sysimage can be set in the Julia extension settings (julia.additionalArgs, e.g. ["-J", "path/to/NeuroAnalyzer.so"]).

Options

The options are set at the beginning of create_sysimage.jl:

  • CPU target: by default the sysimage is built for a generic CPU (cpu_target = "generic"), so it runs on any computer with the same operating system and processor architecture. Setting cpu_target = "native" optimizes it for the processor it is built on (slightly faster, but it will not run on other CPUs).
  • Development version: to build the sysimage for the development branch, change #main to #devel in the Pkg.add(url = ...) line.
  • Precompiling typical usage: by default, the sysimage contains the compiled package code, but functions are still compiled at their first call with your data types. If a file na_precompile.jl is placed in the scripts/ folder, PackageCompiler runs it during the build and stores all methods it compiles in the sysimage. It should contain a typical workflow, e.g.:
using NeuroAnalyzer
eeg = import_edf("path/to/recording.edf")
NeuroAnalyzer.filter!(eeg; ch = "eeg", fprototype = :fir, ftype = :hp,
                      cutoff = 0.5, bw = 0.5)
reference_avg!(eeg)
ep = epoch(eeg; ep_len = 2)
band_power(ep; ch = "eeg", flim = (8, 12))
NeuroAnalyzer.plot(eeg; ch = "eeg", gui = false)

Notes

  • Julia version: the sysimage works only with the Julia version it was built with; after updating Julia, generate it again.
  • NeuroAnalyzer version: the sysimage contains a fixed version of NeuroAnalyzer and its dependencies. Updating packages in the sysimage environment has no effect until the sysimage is rebuilt; to update NeuroAnalyzer, run create_sysimage.sh again.
  • Operating system and architecture: the sysimage works only on the operating system and processor architecture (e.g. x86-64, ARM64) it was built on.
  • Plugins: plugins are loaded from their folder at startup and are not part of the sysimage.