Skip to content

Operation/centroiding#118

Merged
capetillo merged 8 commits intomainfrom
operation/centroiding
Apr 24, 2026
Merged

Operation/centroiding#118
capetillo merged 8 commits intomainfrom
operation/centroiding

Conversation

@capetillo
Copy link
Copy Markdown
Contributor

@capetillo capetillo commented Apr 23, 2026

FEATURE: Centroiding

Background:
BANZAI does not have a centroid for all targets. To find centroids for the excluded target, we obtained the logic from AstroimageJ, which uses the Howell method to obtain the centroid.

Implementation
The user clicks on a position and sends the clicked x and y as well as radius, r_back1 (the inner annulus), r_back2 (outer annulus) to the backend. These are first scaled into FITS pixel space and then the local background is estimated from the annulus around the selected source, and iteratively refines the source center using the flux-weighted signal in the centroid window.
The /centroiding endpoint returns x and y as the centroid position. It also returns background, which is the average per pixel signal in that surrounding area, and peak, which is the brightest source signal above that background.
When the FITS header contains a valid WCS solution, we eturn ra and dec by converting the centroided FITS pixel position into sky coordinates. Otherwise those fields are null.
If plane background removal is enabled in the frontend, centroiding does not assume the background is the same everywhere near the source. It fits a simple tilted plane to the pixels in the background annulus and subtracts that changing background model during centroiding.

NOTE
I couldn't find a small FITS file so I couldn't write a test for that

@capetillo capetillo requested a review from jnation3406 April 23, 2026 20:20
@talister
Copy link
Copy Markdown
Member

@capetillo What we've done for testing this sort of stuff is make a postage stamp cutout around a random star of interest and write this to a new FIST file for testing e.g.

from astropy.io import fits

hdul = fits.open('some file.fits')
cutout = hdul['SCI'].section[200:300, 200:300]

new_hdul = fits.PrimaryHDU(cutout, hdul[0].header)

new_hdul.writeto('cutout.fits', checksum = True)

This will make a 100x100 cutout around (250,250) - alter this to center on the object of interest in your test data FITS file

Copy link
Copy Markdown
Contributor

@jnation3406 jnation3406 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't comment on the math but seems fine. I'm not sure I like the super verbose line per param of function definitions but its a personal preference thing so if you like it it's fine.

radius: float,
r_back1: float,
r_back2: float,
*,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is some advanced pythoning, I had to lookup what this does.

@capetillo capetillo merged commit 81f41d6 into main Apr 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants