Skip to main content

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.

Python Version License

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 object
  • cax - Colorbar axes
  • wcs - 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 axes
  • display.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

Issues: https://github.com/yourusername/jfits/issues

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jfits-1.0.0.tar.gz (25.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jfits-1.0.0-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

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

Hashes for jfits-1.0.0.tar.gz
Algorithm Hash digest
SHA256 058174aec1e7665ca97dc537c67344c14adf7075d804ba1c7148a778caa2c40b
MD5 1d1e61db12eaf1b04facb2b1c6ccfb6f
BLAKE2b-256 94fb15b6c24cdb928c33f84a352c158f5673c523b611dcc22e95445789881721

See more details on using hashes here.

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

Hashes for jfits-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b1a3d9318b75289626e07153c2f98cf05f61debe4ee212da4ec08b0d677665bb
MD5 f9f78722a4a8c546c264b6f43521b2cf
BLAKE2b-256 9bbad9b81023db78764a3a2a5626e3b88a42b18f49b11ea9e52dbd00001e72e2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page