Hexagonal-grid Multi-data Analysis and Processing Software
Explore the docs »
View Demo
·
Report Bug
·
Request Feature
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.
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
# From PyPI (once published)
pip install astro-hexmaps
# From GitHub — latest version
pip install git+https://github.com/PhangsTeam/astro-HexMaps.git
# Editable / development install
git clone https://github.com/PhangsTeam/astro-HexMaps.git
cd astro-HexMaps
pip install -e ".[dev]"# Creates config.txt, keys/, and run_hexmaps.py in the current folder
hexmaps --init
# Or target a specific directory
hexmaps --init --workdir ~/my_survey
cd ~/my_surveyThis copies template configuration files into your working directory. The installed package is never modified.
To try the pipeline immediately with real data, download the bundled NGC 5194 example dataset (~46 MB):
hexmaps --download-example --workdir ~/my_surveyThis fetches the input FITS files (CO(2–1) cube, CO(1–0) cube, SPIRE 250 µm map
and associated uncertainty files) into ~/my_survey/data/. The bundled
config.txt is already configured to use these files, so you can run the
pipeline straight away after downloading. Use --force to re-download
existing files.
| File | What to configure | How often |
|---|---|---|
config.txt |
data directory, source 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
# Default: regrid + products (writes .ecsv database)
hexmaps --conf config.txt
# All stages including FITS output
hexmaps --conf config.txt --stages all
# Single source
hexmaps --conf config.txt --targets ngc5194
# Also write a log file
hexmaps --conf config.txt --log_file run.logOr 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 onlyFor more examples, please refer to the Documentation.
astro-HexMaps/ ← git repository root (pip install this)
├── hexmaps/ ← installable package
│ ├── handler_keys.py reads & validates config and key files
│ ├── handler_sources.py source 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
│ ├── logger.py centralised stage-labelled logger
│ ├── init_workdir.py --init scaffolding
│ ├── download_example.py --download-example data fetcher
│ ├── 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 ← source geometry table (NGC 5194 example)
│ └── hfs_lines.txt ← hyperfine structure definitions
├── analysis/
│ ├── hexmaps_analysis.py HexMapsAnalysis class: quicklook plots
│ └── 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
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.
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_deg"], table["dec_deg"],
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:
import sys; sys.path.append("analysis/")
from hexmaps_analysis 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- PyPI release
- Expanded documentation and tutorials
- Additional analysis utilities in
hexmaps_analysis.py - Various feature updates (e.g. "island-method" masking, chunking for large datasets)
See the open issues for a full list of proposed features and known issues.
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
Distributed under the MIT License — see LICENSE for details.
Dr. Jakob den Brok — jadenbrok@mpia.de
Dr. Lukas Neumann — lukas.neumann@eso.org
Project Link: https://github.com/PhangsTeam/astro-HexMaps
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.
