Interactive numpy array and FITS image viewer with WCS support and centroiding
Project description
jfits
Interactive visualization for numpy arrays and FITS images in astronomy.
About the name: This tool was originally built for my own use and workflows. The j is for Jordan.
Overview
jfits provides interactive visualization tools for astronomical data analysis. View and analyze numpy arrays during your processing workflow without writing to disk. Includes support for FITS files with WCS coordinates, Gaussian centroiding, and 3D IFS cube analysis.
Features
- Interactive display with adjustable vmin/vmax, colormaps, and scaling
- WCS coordinate support with RA/Dec readout on hover
- Circular and elliptical 2D Gaussian centroiding
- 3D cube viewer for IFS data with slice navigation
- Gaussian-weighted spectrum extraction from cubes
- Multiple colormaps: viridis, cividis, inferno, magma, plasma, gray, gray_r
- Log and linear scaling modes
Installation
pip install jfits
Requirements
- Python >= 3.8
- numpy >= 1.20.0
- matplotlib >= 3.3.0
- astropy >= 4.0
- scipy >= 1.7.0
Interactive Backend
jfits requires matplotlib with an interactive backend. Most installations include this by default.
Interactive mode:
For interactive sessions (IPython, terminal, Jupyter with %matplotlib tk):
import matplotlib.pyplot as plt
plt.ion()
With plt.ion() enabled:
- Figures appear immediately without
plt.show() - You can continue working while windows are open
- Figures update automatically when modified
Standalone scripts:
For standalone Python scripts, plt.ion() is not needed. Use the traditional approach:
import jfits
import matplotlib.pyplot as plt
display = jfits.InteractiveDisplay(data)
plt.show() # Blocks until window closed
Backend errors:
If you encounter backend errors:
# Ubuntu/Debian (Tkinter):
sudo apt-get install python3-tk
# Or install Qt backend:
pip install PyQt5
Quick Start
Interactive Session (IPython, Terminal)
import jfits
import numpy as np
import matplotlib.pyplot as plt
# Enable interactive mode
plt.ion()
# Your data processing
data = np.random.randn(512, 512)
processed = data * some_mask + background
# Visualize - window appears immediately
display = jfits.InteractiveDisplay(processed)
# Continue working while window is open
Standalone Script
import jfits
import numpy as np
import matplotlib.pyplot as plt
# Your data processing
data = np.random.randn(512, 512)
processed = data * some_mask + background
# Visualize
display = jfits.InteractiveDisplay(processed)
plt.show() # Blocks until window closed
Viewing FITS Files
import jfits
import matplotlib.pyplot as plt
plt.ion() # For interactive session
# Quick view
display = jfits.quick_view('observation.fits')
# Or load data manually
header, data = jfits.get_fits_array('observation.fits')
display = jfits.InteractiveDisplay(data)
3D Cube Viewing
import jfits
import matplotlib.pyplot as plt
plt.ion() # For interactive session
# Automatic wavelength detection from header
display = jfits.quick_view_cube('ifs_cube.fits')
# Or specify wavelengths manually
import numpy as np
wavelengths = np.linspace(4000, 7000, 100)
display = jfits.InteractiveDisplayCube(
cube_data,
wavelengths=wavelengths,
wavelength_unit='Angstrom'
)
Interactive Controls
2D Display
Left Panel:
- Colormap selection (7 options)
- Log/linear scaling toggle
- Mask color (white/black for NaN pixels)
- Centroid window size (5, 10, 20, 50 pixels)
- Centroid mode (Off, Circular, Elliptical)
Bottom Panel:
- vmax/vmin sliders for display range
- Colorbar showing current mapping
Mouse Interaction:
- Hover to see coordinates and pixel values
- Click (when centroiding enabled) to fit 2D Gaussians
3D Cube Display
All 2D controls plus:
- Slice slider for wavelength/spectral navigation
- Spectrum extraction toggle (extract weighted spectrum at clicked position)
Usage in Jupyter Notebooks
Local Jupyter (Recommended)
# At top of notebook:
%matplotlib tk
import jfits
import numpy as np
# Separate interactive window
data = np.random.randn(256, 256)
display = jfits.InteractiveDisplay(data)
JupyterLab with ipympl
For embedded interactive widgets:
# Install ipympl
pip install ipympl
In notebook:
%matplotlib widget
import jfits
import numpy as np
data = np.random.randn(256, 256)
display = jfits.InteractiveDisplay(data)
Note: ipympl works in JupyterLab only, not classic Jupyter Notebook.
Cloud Notebooks (Colab, Binder)
Use static display:
%matplotlib inline
import jfits
import numpy as np
data = np.random.randn(100, 100)
ax = jfits.Display(data, vmin=0, vmax=1)
Examples
Interactive Processing Workflow
import jfits
import numpy as np
import matplotlib.pyplot as plt
from astropy.io import fits
plt.ion()
# Load data
data = fits.getdata('raw_image.fits')
# Process
background = np.median(data)
data_sub = data - background
# Check result interactively
display = jfits.InteractiveDisplay(data_sub)
# Adjust display parameters with sliders and controls
# Once satisfied, continue processing
Centroiding Example
import jfits
import matplotlib.pyplot as plt
plt.ion()
display = jfits.quick_view('star_field.fits')
# In the display window:
# 1. Select "Circular" or "Elliptical" under centroid
# 2. Adjust centroid window size if needed
# 3. Click on sources to fit Gaussians
# Red contours show fitted model
# Title shows fit parameters (RA/Dec if WCS available)
IFS Cube Analysis
import jfits
import matplotlib.pyplot as plt
plt.ion()
display = jfits.quick_view_cube('muse_cube.fits')
# Workflow:
# 1. Use slice slider to navigate wavelengths
# 2. Enable "show spectrum" (yes)
# 3. Enable centroiding (Circular or Elliptical)
# 4. Click on source
# Separate window opens showing flux vs wavelength
Elliptical Galaxy Fitting
import jfits
import numpy as np
import matplotlib.pyplot as plt
plt.ion()
# Create elliptical galaxy model
data = np.zeros((150, 150))
y, x = np.indices(data.shape)
theta = np.radians(45)
x_rot = np.cos(theta) * (x - 75) - np.sin(theta) * (y - 75)
y_rot = np.sin(theta) * (x - 75) + np.cos(theta) * (y - 75)
data += 1000 * np.exp(-(x_rot**2 / (2*8**2) + y_rot**2 / (2*20**2)))
data += np.random.normal(0, 10, data.shape)
display = jfits.InteractiveDisplay(data)
# Use Elliptical centroiding mode
# Recovers sigma_x ~ 8, sigma_y ~ 20, theta ~ 45 degrees
API Reference
Main Functions
quick_view(filename, **kwargs)
Quick interactive display of 2D FITS file.
Returns: InteractiveDisplay object
quick_view_cube(filename, **kwargs)
Quick interactive display of 3D FITS cube. Automatically detects wavelength axis from header.
Returns: InteractiveDisplayCube object
get_fits_array(filename)
Read FITS file data and header.
Returns: (header, data) or ([headers], [data]) for multi-extension FITS
read_wcs(header)
Extract WCS from FITS header.
Returns: astropy.wcs.WCS object or None
Classes
InteractiveDisplay(arr, wcs=None, **imshowargs)
Interactive 2D image display with full control over parameters and Gaussian centroiding.
Attributes:
ax- Main image axes (matplotlib Axes object)fig- Figure objectcax- Colorbar axeswcs- WCS object (if provided)arr- Image data array
InteractiveDisplayCube(cube, wavelengths=None, wavelength_unit='slice units', **kwargs)
Interactive 3D cube display with slice navigation and spectrum extraction. Inherits all InteractiveDisplay features.
Display(arr, wcs=None, log=False, **imshowargs)
Non-interactive 2D display. Returns matplotlib axes for further customization.
Advanced Usage
Direct Axes Access
The display object exposes matplotlib axes for advanced customization:
import jfits
import numpy as np
import matplotlib.pyplot as plt
plt.ion()
# Create display
data = np.random.randn(200, 200)
display = jfits.InteractiveDisplay(data)
# Add custom contours on the same axes
other_data = process_another_array()
display.ax.contour(
other_data / other_data.max(),
levels=[0.9, 0.7, 0.5, 0.1],
colors='m'
)
# Add custom annotations
display.ax.plot([50, 100], [50, 100], 'r--', linewidth=2, label='Custom line')
display.ax.legend()
# Access figure for saving
display.fig.savefig('my_analysis.png', dpi=150)
Available attributes:
display.ax- Main image axes (for plotting, contours, annotations)display.fig- Figure object (for saving, adjusting layout)display.cax- Colorbar axesdisplay.wcs- WCS object (if provided)display.arr- Image data array
Custom Display Settings
import jfits
import matplotlib.pyplot as plt
plt.ion()
header, data = jfits.get_fits_array('image.fits')
wcs = jfits.read_wcs(header)
display = jfits.InteractiveDisplay(
data,
wcs=wcs,
vmin=100,
vmax=5000
)
Troubleshooting
Backend Errors
Error: "UserWarning: Matplotlib is currently using agg"
Solution:
import matplotlib
matplotlib.use('TkAgg') # Before importing pyplot
import matplotlib.pyplot as plt
Tkinter Not Found
Ubuntu/Debian:
sudo apt-get install python3-tk
macOS: Tkinter is included with Python from python.org
Windows: Reinstall Python with "tcl/tk and IDLE" option checked
Jupyter Widgets Unresponsive
In Jupyter notebooks, interactive widgets require either a separate window (%matplotlib tk) or ipympl (%matplotlib widget). The default inline backend does not support interactive controls.
Platform Support
jfits works on Windows, macOS, and Linux. Matplotlib handles platform-specific rendering automatically. Users need only ensure an interactive backend is installed (typically Tkinter or Qt).
Interactive mode (plt.ion()) is platform-independent and works with all GUI backends.
Contributing
Contributions are welcome. Please fork the repository, create a feature branch, and submit a pull request.
License
MIT License - see LICENSE file for details.
Acknowledgments
Built on matplotlib, numpy, astropy, and scipy.
Contact
Project details
Release history Release notifications | RSS feed
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 jfits-1.0.0.tar.gz.
File metadata
- Download URL: jfits-1.0.0.tar.gz
- Upload date:
- Size: 25.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
058174aec1e7665ca97dc537c67344c14adf7075d804ba1c7148a778caa2c40b
|
|
| MD5 |
1d1e61db12eaf1b04facb2b1c6ccfb6f
|
|
| BLAKE2b-256 |
94fb15b6c24cdb928c33f84a352c158f5673c523b611dcc22e95445789881721
|
File details
Details for the file jfits-1.0.0-py3-none-any.whl.
File metadata
- Download URL: jfits-1.0.0-py3-none-any.whl
- Upload date:
- Size: 17.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1a3d9318b75289626e07153c2f98cf05f61debe4ee212da4ec08b0d677665bb
|
|
| MD5 |
f9f78722a4a8c546c264b6f43521b2cf
|
|
| BLAKE2b-256 |
9bbad9b81023db78764a3a2a5626e3b88a42b18f49b11ea9e52dbd00001e72e2
|