A library for generating Line Integral Convolutions
| Platform | Name |
|---|---|
| GitHub | LineIntegralConvolutions |
| PyPI | line-integral-convolutions |
| Python (import) | vegtamr (Odin's alias while wandering Hel) |
Line Integral Convolutions (LICs) are an amazing way to visualise 2D vector fields, and are widely used in many different fields (e.g., weather modelling, plasma physics, etc.), however I couldn't find a simple, up-to-date implementation, so I wrote my own. I hope it can now also help you on your own vector field fueled journey!
Here is the LIC code applied to a couple of example vector fields:
- Left: modified version of the Lotka-Volterra equations
- Right: a swirling pattern
Getting setup
You can now install the LIC package directly from PyPI or clone the Github repository if you'd like to play around with the source code.
Option 1: Install from PyPI (for general use)
If you only need to use the package, you can install it via pip:
pip install line-integral-convolutions
After installing, import the library as follows:
from vegtamr import lic
Inside this module, you will want to use the lic.compute_lic_with_postprocessing function. See below for details on how to get the most out of it.
Option 2: Clone the GitHub repository (for development)
1. Clone the repo:
git clone git@github.com:AstroKriel/LineIntegralConvolutions.git
cd LineIntegralConvolutions
2. Create a development environment with uv:
uv sync
This will install dependencies listed in pyproject.toml into a virtual environment managed by uv.
With uv you get clean package management and reproducibility, where the only trade-off is a few extra keystrokes when running scripts:
uv run demos/demo-lic.py
A small price to pay for sanity! Alternatively, you can activate the environment with source .venv/bin/activate and run python3 demos/demo-lic.py.
3. Use your local checkout from another project (optional):
uv sync (step 2) already gives you an editable install inside this repo's own .venv, so edits are picked up immediately when you work from here. If you want to use this edited clone in a different project, you will need to install it as an editable dependency from that project:
uv add --editable /path/to/vegtamr
Quick start
compute_lic_with_postprocessing is the main entry point for generating LICs. It manages all the internal calls and offers optional postprocessing: filtering and intensity equalisation. In practice, this is the only function you’ll need to call!
Here’s a quick example:
import matplotlib.pyplot as mpl_plot
from vegtamr import lic
from vegtamr.utils import vfields, plots
## generate a sample vector field
num_cells = 500
vfield_config = vfields.vfield_swirls(num_cells)
vfield = vfield_config.vfield
streamlength = vfield_config.streamlength
## apply the lic
sfield = lic.compute_lic_with_postprocessing(
vfield=vfield,
streamlength=streamlength, # brush stroke length
num_lic_passes=3, # number of brush strokes
use_filter=True,
filter_sigma=5e-2 * num_cells, # tube thickness
use_equalize=True,
backend="rust",
)
## and now plot!
fig, ax = mpl_plot.subplots()
plots.plot_lic(
ax=ax,
sfield=sfield,
vfield=vfield,
cmap_name="pink",
)
mpl_plot.show()
There are a number of parameters for you to experiment with; the effect of streamlength and postprocessing is demonstrated by demos/demo-streamlength.py, which produces the following image:
In practice you will want to choose a streamlength close to the correlation length (in cells) of the structures you are trying to highlight. Depending on the effect you're aiming for, you can also play around with turning on the highpass filter (use_filter), changing its size (filter_sigma; controls the thickness of tubes), and turning on intensity equalization (use_equalize).
You can also control the width of the brush strokes by smoothing the initial field that seeds the LIC, via seed_smoothing_sigma; this is demonstrated by demos/demo-seed-smoothing.py, which produces the following image:
By default seed_smoothing_sigma scales with the size of the domain, but you are free to tweak the value as you please; note, pushing it too high starts to introduce artefacts near saddle points.
Note: If you want a darker look without touching the underlying data,
plot_licalso acceptscmap_range, e.g.cmap_range=(0.0, 0.75); this restricts which portion of the colormap is used, so the full value range maps smoothly to the restricted color range without clipping.
File structure
LineIntegralConvolutions/ # project root
├── src/
│ └── vegtamr/ # package root (named after Odin's alias, "Wanderer")
│ ├── __init__.py
│ ├── py.typed # marker for type checkers (PEP 561)
│ ├── lic/
│ │ ├── __init__.py
│ │ ├── _api.py # public-facing API
│ │ ├── _core.py # core algorithms
│ │ ├── _parallel_by_row.py # parallel implementation
│ │ ├── _postprocess.py # filtering + equalisation
│ │ └── _serial.py # serial implementation
│ └── utils/
│ ├── __init__.py
│ ├── plots.py # plotting helpers
│ └── vfields.py # example vector fields
├── demos/ # example scripts
│ ├── demo-lic.py # simple demo
│ ├── demo-streamlength.py # demo of how streamlength and postprocessing affect LIC output
│ └── demo-seed-smoothing.py # demo of how seed_smoothing_sigma affects LIC output
├── gallery/ # reference images
├── pyproject.toml # project metadata and dependencies
├── uv.lock # lock file (used by uv to pin dependencies)
├── LICENSE # terms of use and distribution
└── README.md # this file
Acknowledgements
Both the fast (pre-compiled Rust) LIC backend, rLIC (which this repo uses by default), and the histogram-equalization backend, ahe, were implemented by Dr. Clément Robert (@neutrinoceros). Special thanks also go to Dr. James Beattie (@AstroJames) for highlighting how iteration, high-pass filtering, and histogram normalisation improve the final result. Finally, Dr. Philip Mocz (@pmocz) provided lots of helpful suggestions in restructuring and improving the codebase.
License
This project is licensed under the MIT License; see the LICENSE file for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file line_integral_convolutions-2.1.0.tar.gz.
File metadata
- Download URL: line_integral_convolutions-2.1.0.tar.gz
- Upload date:
- Size: 13.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b4e238ce9b9fddbb726272eb9acfc362b483eab1ba11f82302b9bcc593f38293
|
|
| MD5 |
552435080a0a5876e61e2fd29b81ae4a
|
|
| BLAKE2b-256 |
86a2bfda9d6840e972729017427e5e7d274a22109fbc4a61c05be255e55a70f6
|
File details
Details for the file line_integral_convolutions-2.1.0-py3-none-any.whl.
File metadata
- Download URL: line_integral_convolutions-2.1.0-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5f938512c2097b35fad262a228af7e9628a84a6d70fefe86f5e9d6ead44f1d6
|
|
| MD5 |
0ae8c6ef1e7ef2f3420019a7fccce0d9
|
|
| BLAKE2b-256 |
2b0056c1210718af8fc6efb892e21f2a7b32e9228286edd99900827e7c316385
|