Qorona turns a global coronal MHD solution into eclipse-like synthetic imagery. Its primary product is a line-of-sight integral of the magnetic squashing factor Q⊥, the quantity that lights up the thin loops, streamers, and current sheets seen at a total solar eclipse. The result is rendered for morphological comparison against eclipse and coronagraph observations.
coronal MHD solution ──▶ read ──▶ resample ──▶ Q⊥ volume ──▶ LOS render ──▶ synthetic eclipse image
Install
With pip you install the latest release; it is the quickest way to get the qorona command:
pip install qorona
With conda you clone the repository and build the provided environment from its root, giving you
the development version (main) as an editable checkout, e.g. to develop or add a model reader:
git clone https://github.com/RayanDhib/Qorona.git
cd Qorona
conda env create -f environment.yml
conda activate qorona
Minimal install (advanced, optional)
Two dependencies have graceful fallbacks and can be left out for a smaller footprint. Qorona detects their absence and degrades automatically, so this is an off-road choice, not the default:
- numba: drop for a pure-NumPy build/render (identical output, much slower).
- pillow: drop to skip the on-image stamp (the run still completes and prints its provenance).
pip install qorona --no-deps
pip install numpy scipy astropy sunpy rich click # hard core; add back numba / pillow as wanted
Example data
The quickstart uses hmi_lmax50.CFmesh.xz (~165 MB), an HMI-driven COCONUT corona MHD solution.
It is distributed as a release asset, not committed to the repo: download it
into data/ before running the commands below. Qorona reads the compressed .xz directly, with no
manual decompression step.
Quickstart
Qorona splits the pipeline at its natural cost seam: the Q⊥ volume is expensive and viewpoint-independent (bake it once), while a render off that volume is cheap (do it for many cameras). Three commands follow from that:
# 1. Inspect a solution (model, mesh, variables, boundaries), no rendering.
qorona info data/hmi_lmax50.CFmesh.xz --timestamp 2025-10-09T18:19:52
# 2. Bake the viewpoint-independent Q⊥ volume once (the minutes-scale stage).
qorona build data/hmi_lmax50.CFmesh.xz -o data/hmi_lmax50.qor \
--timestamp 2025-10-09T18:19:52 --outer-radius 8
# 3. Render any number of viewpoints off that volume (seconds each).
qorona render data/hmi_lmax50.qor -o data/eclipse.png --fov 8 --longitude 317 --latitude 6.2
qorona render data/hmi_lmax50.qor -o data/polarity.png --fov 8 --longitude 317 --latitude 6.2 --polarity-mode hue
qorona render data/hmi_lmax50.qor -o data/sun.png --fov 3 --longitude 317 --latitude 6.2 --occult opaque --preset small-fov --step 0.002
Or do it all in one shot:
qorona run data/hmi_lmax50.CFmesh.xz -o data/eclipse.png \
--timestamp 2025-10-09T18:19:52 --fov 8 --longitude 317 --save-volume data/hmi_lmax50.qor
For a field-line view:
qorona fieldlines data/hmi_lmax50.CFmesh.xz -o data/fieldlines.png --fov 8 --longitude 317
For a Q-map (a longitude/latitude shell of signed-log Q⊥ at a fixed radius, the
viewpoint-independent sibling of render), bake with the outer radius at the map radius:
qorona build data/hmi_lmax50.CFmesh.xz -o data/hmi_lmax50_r3.qor \
--timestamp 2025-10-09T18:19:52 --outer-radius 3
qorona qmap data/hmi_lmax50_r3.qor -o data/qmap.png --radius 3
Every command prints a polished end-of-run summary of its parameters and metrics, and the rendered
PNG carries a corner stamp (CR · timestamp · sub-observer angles · roll · FOV) for reproducibility. Run
qorona <command> --help for the full flag list (grid resolution, builder, weighting preset,
occultation, display mode, and more); the defaults reproduce the published whole-corona Q⊥ render.
GPU acceleration
Volume builds are CUDA-accelerated end to end, with no extra Qorona dependency: the kernels ride
the default-install numba and activate whenever it sees a CUDA-capable NVIDIA GPU (driver + CUDA
toolkit). Nothing to configure: qorona build already uses the GPU when one is present.
qorona build ... --device gpu # force the GPU (errors if none is usable)
qorona build ... --device cpu # multi-core CPU path (the reference)
qorona build ... --device gpu --precision float64 # all-double reference (~2× slower than mixed)
--device auto(default) picks the GPU when present; the CPU kernels remain the reference implementation and produce the same images.--precision mixed(default) runs the field interpolation in float32 and everything else in float64, log-invisible against thefloat64reference.float32is an experimental fully-float32 paint variant. GPU-only knob; the CPU path always computes in float64.- Device memory adapts to free VRAM (the Q⊥ accumulation tiles itself), so the same command runs on small cards and at very high resolutions alike.
- The resolved backend and precision are stamped into the volume's provenance and the end-of-run summary.
Indicative volume-build timings (RTX 4080 vs 32-core CPU, mixed precision; not a benchmark):
| Q⊥ volume | GPU | CPU |
|---|---|---|
| Quickstart, 384×360×720 (100 M vox) | ~75 s | ~9 min |
| High-res, 512×800×1600 (655 M vox) | ~3 min | not practical |
On a cluster
Qorona installs from PyPI into a plain virtual environment; no conda needed:
module purge # optional; stops other modules leaking packages via PYTHONPATH
module load python # any Python ≥ 3.11
python -m venv ~/envs/qorona && source ~/envs/qorona/bin/activate
pip install qorona
On GPU nodes, load the site's CUDA module (module load cuda) so numba finds the toolkit;
--device gpu errors loudly if the GPU is unusable rather than silently falling back. Two flags
are made for batch jobs: --workers pins the kernel threads to your allocation (numba otherwise
takes every core it sees), and --quiet keeps job logs readable:
qorona build <solution> -o <solution>.qor --device gpu --workers $SLURM_CPUS_PER_TASK --quiet
How it works
The pipeline processes a single MHD snapshot through four stages, each isolated behind a clean interface so a new input model is added by writing one reader and a new viewpoint costs only a render:
- Read & resample the native solution onto an internal regular spherical grid.
- Trace magnetic field lines and transport deviation vectors along them.
- Squashing factor: assemble Q⊥ boundary-to-boundary and bake it into a viewpoint-independent
volume (cached to a dependency-free
.qor). - Render: integrate log₁₀ Q⊥ along the line of sight on an orthographic plane-of-sky camera, with depth colouring and eclipse occultation.
The reference output is the line-of-sight squashing-factor render of the corona's fine structure.
Supported models
Qorona is model-agnostic: each coronal model and file format sits behind a common reader interface, so the whole pipeline runs on any solution once a reader exists.
Currently supported: COCONUT (COOLFluiD .CFmesh).
Support for other coronal MHD models can be added by writing a single reader against that interface. A contributor guide is planned.
License
GPL-3.0-or-later. See LICENSE.
Metadata
Release files for qorona 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| qorona-0.3.0.tar.gz | 216.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qorona-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 445.8 kB
Release files / qorona-0.3.0.tar.gz
| Download URL | qorona-0.3.0.tar.gz |
|---|---|
| Size | 216.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d00ec050a98bfafac1e9f5f708ab393fab9ea94efbccadc99916314abd808c82
|
|
BLAKE2b-256 checksum How to use checksums |
76ff585cc394facddfd92f3e2235477401e1d3b5398c448444a87ce51261c7b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / qorona-0.3.0-py3-none-any.whl
| Download URL | qorona-0.3.0-py3-none-any.whl |
|---|---|
| Size | 229.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
83ddfc96dbcc9257c76541a20c8cf833ba5a322d65908c177695e42bae0eb10c
|
|
BLAKE2b-256 checksum How to use checksums |
26cb568fd1b25baa797dcbf0fe92af1122bbba16cb751438e4795d67b864e436
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|