HexMaps
Hexagonal-grid Multi-data Analysis and Processing Software
Explore the docs »
View Demo
·
Report Bug
·
Request Feature
About the Project
HexMaps is a Python package for homogenizing and analysing multi-wavelength astronomical datasets on hexagonal grids. It is ideally suited for combining a heterogeneous set of 2D maps and 3D spectral cubes observed at different angular resolutions and pixel scales into a single, science-ready table for sightline-by-sightline analysis.
Given a set of input data, HexMaps:
- Regrids all maps and cubes onto a common hexagonal sampling grid at a user-specified angular resolution, convolving each dataset to a common beam.
- Processes each spectral cube: builds an S/N mask from a reference line, then computes moment maps (integrated intensity, mean velocity, line width, peak temperature, rms, equivalent width) and shuffled spectra for every line.
- Writes FITS output: PPV-native moment maps, optionally convolved cubes, and 2D band images — all on the same pixel grid as the overlay cube.
The primary deliverable is an Astropy .ecsv table with one row per
hexagonal sightline, containing all spectra, moment maps, and 2D map values
side by side. This makes line-ratio analysis, radial profile extraction, and
spectral stacking straightforward with standard Python tools.
HexMaps is the successor to PyStructure (PhangsTeam), refactored into a pip-installable package with a clean CLI, an INI-style single configuration file, and a modular stage architecture.
Getting Started
Prerequisites
HexMaps requires Python ≥ 3.10. All Python dependencies are installed automatically by pip:
astropy numpy pandas scipy matplotlib
reproject radio_beam spectral_cube scikit-image
Installation
# From PyPI
pip install astro-hexmaps
# From GitHub — latest version
pip install git+https://github.com/lukas-neumann-astro/astro-HexMaps.git
# Editable / development install
git clone https://github.com/lukas-neumann-astro/astro-HexMaps.git
cd astro-HexMaps
pip install -e ".[dev]"
Usage
1 — Initialise a working directory
# Creates config.txt, keys/, and run_hexmaps.py in the current folder
hexmaps --init
# Or target a specific directory
hexmaps --init --workdir ~/my_project
cd ~/my_project
This copies template configuration files into your working directory. The installed package is never modified.
2 — Download the example dataset (optional)
To try the pipeline immediately with real data, download the bundled NGC 5194 example dataset (~46 MB):
hexmaps --download-example --workdir ~/my_project
This fetches the input FITS files (CO(2–1) cube, CO(1–0) cube, SPIRE 250 µm
map and associated files) into ~/my_project/data/. The bundled config.txt
is already configured to use these files. Use --force to re-download
existing files.
You can also download the example Jupyter notebook separately:
hexmaps --download-notebook --workdir ~/my_project
3 — Edit your configuration
| File | What to configure | How often |
|---|---|---|
config.txt |
data directory (data_dir), optional root directory (root_dir), target list, overlay cube, maps/cubes, target resolution, masking, output flags |
every run |
keys/target_definitions.txt |
sky coordinates, distance, inclination per target | only when adding new targets |
keys/hfs_lines.txt (optional) |
Hyperfine structure line definitions | rarely |
config.txt replaces the PyStructure.conf file of the old PyStructure.
Migrating from PyStructure? Use the conversion scripts:
python conversion_from_pystructure/config_conversion.py PyStructure.conf config.txt python conversion_from_pystructure/target_definitions_conversion.py geometry.txt keys/target_definitions.txt python conversion_from_pystructure/hfs_lines_conversion.py hfs_lines.txt keys/hfs_lines.txt
4 — Run
# Default: regrid + products (writes .ecsv database)
hexmaps --conf config.txt
# All stages including FITS output
hexmaps --conf config.txt --stages all
# Single target
hexmaps --conf config.txt --targets ngc5194
# Also write a log file
hexmaps --conf config.txt --log_file run.log
Or from Python:
import hexmaps as hm
handler = hm.PipelineHandler(conf_path="config.txt")
handler.run_all() # regrid + products
handler.run_stages(["regrid", "products", "fits"]) # include FITS output
handler.run_stages(["fits"], targets=["ngc5194"]) # re-run one stage only
For more examples, please refer to the Documentation.
Repository Layout
astro-HexMaps/ ← git repository root (pip install this)
├── hexmaps/ ← installable package
│ ├── handler_keys.py reads & validates config and key files
│ ├── handler_targets.py target geometry lookups
│ ├── handler_pipeline.py PipelineHandler: stage orchestration
│ ├── stage_regrid.py hex grid + convolution + sampling → .ecsv
│ ├── stage_products.py spectral masking, moments, shuffled spectra
│ ├── stage_fits.py FITS moment maps / cubes / band images
│ ├── utils_fits.py FITS/WCS helpers (convolution, reprojection)
│ ├── utils_table.py table I/O, spectral shuffle, moments
│ ├── hexmaps_analysis.py HexMapsAnalysis class (importable as part of package)
│ ├── logger.py centralised stage-labelled logger
│ ├── init_workdir.py --init scaffolding
│ ├── download_example.py --download-example and --download-notebook
│ ├── cli.py hexmaps console-script entry point
│ ├── test_hexmaps.py unit and integration tests
│ └── templates/ template files copied by --init
│ ├── config.txt
│ ├── run_hexmaps.py
│ └── keys/
│ ├── target_definitions.txt
│ └── hfs_lines.txt
├── config.txt ← example / template config file
├── keys/
│ ├── target_definitions.txt ← target geometry table (PHANGS example)
│ └── hfs_lines.txt ← hyperfine structure definitions
├── analysis/
│ └── hexmaps_example.ipynb example analysis notebook
├── conversion_from_pystructure/ ← migration scripts from old PyStructure
│ ├── config_conversion.py
│ ├── target_definitions_conversion.py
│ └── hfs_lines_conversion.py
├── data/ ← example FITS input (NGC 5194)
├── docs/ ← Sphinx / Read the Docs source
├── images/ ← README images (logo, screenshot)
├── run_hexmaps.py ← example run script
└── pyproject.toml
Pipeline Stages
The pipeline runs three stages always in this order:
| Stage | Module | Default | Description |
|---|---|---|---|
regrid |
stage_regrid.py |
✓ | Generate the hexagonal sampling grid; convolve and sample all maps & cubes onto it; write the .ecsv database |
products |
stage_products.py |
✓ | Build the S/N mask; compute moment maps (mom0/1/2, Tpeak, rms, EW) and shuffled spectra |
fits |
stage_fits.py |
optional | Compute PPV-native moment maps on the convolved cubes; write FITS images |
The default run (hexmaps --conf config.txt) executes regrid + products only.
Add --stages all to also run the fits stage.
Reading the Output
from hexmaps.utils_table import load_hexmaps
import matplotlib.pyplot as plt
table = load_hexmaps("output/ngc5194_hexmaps_27p0as_2025_01_01.ecsv")
plt.figure(figsize=(5, 5))
plt.scatter(table["RA"], table["DEC"],
c=table["MOM0_12CO21"], marker="h", s=60, cmap="inferno")
plt.gca().invert_xaxis()
plt.xlabel("R.A. [deg]"); plt.ylabel("Dec. [deg]")
plt.show()
For richer quicklook plots use the HexMapsAnalysis class, which is now
part of the installed package:
from hexmaps import HexMapsAnalysis
db = HexMapsAnalysis("output/ngc5194_hexmaps_27p0as_2025_01_01.ecsv")
db.quickplot_map("12CO21")
db.quickplot_spectrum("12CO21")
# Recover provenance information embedded at run time
print(db.get_config()) # recover config.txt used for this run
print(db.get_log()) # recover the full pipeline log
hdr = db.get_input_header("12CO21") # recover raw FITS header of input cube
print(db.list_input_headers()) # list all embedded headers
Roadmap
- Extended testing and bug fixes
- Tutorials
- Additional analysis utilities in
hexmaps_analysis.py - Various feature updates (e.g. chunking for large datasets)
See the open issues for a full list of proposed features and known issues.
Contributing
Contributions are greatly appreciated! If you have a suggestion that would make this better, please fork the repository and create a pull request. You can also open an issue with the tag "enhancement".
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
Distributed under the MIT License — see LICENSE for details.
Contact
Dr. Jakob den Brok — jadenbrok@mpia.de
Dr. Lukas Neumann — lukas.neumann@eso.org
Project Link: https://github.com/PhangsTeam/astro-HexMaps
Acknowledgements
HexMaps builds on the original PyStructure IDL scripts developed within the PHANGS collaboration. The routines have been updated, improved, and fully rewritten in Python.
The code has been employed in several peer-reviewed publications including den Brok et al. (2021, 2022, 2023, 2025), Eibensteiner et al. (2022, 2023), Neumann et al. (2023), Stuber et al. (2025), and others. See the documentation for the full list.
Metadata
Release files for astro-hexmaps 5.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| astro_hexmaps-5.0.2.tar.gz | 115.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| astro_hexmaps-5.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 238.8 kB
Release files / astro_hexmaps-5.0.2.tar.gz
| Download URL | astro_hexmaps-5.0.2.tar.gz |
|---|---|
| Size | 115.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
949650bfa053e3773974600198e43c4b83748fc85ba0429c36f4a186315be288
|
|
BLAKE2b-256 checksum How to use checksums |
9ae13ee6f846302e9d6bb6887a9edc4fe1dc22b62e1792b2e39b65a32042f9de
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.0
|
Release files / astro_hexmaps-5.0.2-py3-none-any.whl
| Download URL | astro_hexmaps-5.0.2-py3-none-any.whl |
|---|---|
| Size | 123.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4b77d2399312f313a9bcf356378819e18f66b166855ccc6d0d37f012576c1ec7
|
|
BLAKE2b-256 checksum How to use checksums |
44b5d0c890bd005554e0e0f2e2c16b294402a6cb3330a0b254a61027bd22fe45
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.0
|