astropy / photutils

Astropy package for source detection and photometry. Maintainer: @larrybradley
https://photutils.readthedocs.io
BSD 3-Clause "New" or "Revised" License
242 stars 134 forks source link

SourceCatalog returns nan for centroids when data is negative. #1407

Closed brantr closed 2 years ago

brantr commented 2 years ago

I noticed that 'xcentroid' and 'ycentroid' were returning nan values for forced photometry in a region of an image where oversubtraction had made all pixel values near a source slightly negative.

The source for SourceCatalog states:

"Negative data values within the source segment are set to zero when calculating morphological properties based on image moments."

I can confirm the nan values disappear if I adjust the data to have some positive pixel values, so I assume that when computing moments all negative pixel values are being zeroed and then a divide by zero occurs.

Besides the nans being not helpful and also silently introduced, I think there are example use cases where this behavior is incorrect. Is there a fundamental reason why introducing nans here is preferred over computing the barycenters using negative pixel values?

larrybradley commented 2 years ago

Yes, that's what is happening. Negative pixels become zeros and if then if all the pixels are zero the total "mass" is zero, which is in the denominator of the moment calculation. I don't remember all the reasons for setting negative pixels to zero, but I do recall that with the negative values the image moments (used for centroids and shape measurements) sometimes gave very odd results (e.g., negative second-order moments (variances)). I have a vague memory that SourceExtractor also zeros out negative values, but I need to check that. Can you provide an example use case where this behavior is incorrect?

brantr commented 2 years ago

Thanks for the response and for confirming.

I think any time the local aperture flux could consist of all negative pixels, then the behavior of inducing a NaN is perhaps not ideal since the "correct" answer is calculable. Here are specific situations where computing at least the barycenter would be helpful:

1) Forced photometry on a dropout source where the background has been over-subtracted 2) Forced photometry in a region where a high surface brightness model of a nearby galaxy has been subtracted off 3) Forced "photometry" on a complex lensing model with negative magnification locally (admittedly niche/a bit of a stretch)

I could buy that this is a bit of an aesthetic choice and you would decide not to change the behavior. I personally encountered this issue in part of a pipeline where NaNs appeared without warning and it took some time to track down. In any case, I appreciate the response.

larrybradley commented 2 years ago

Thanks, @brantr, for the explanation. When performing forced photometry, you've already determined from a detection image the source centroid and shape parameters (like SourceExtractor dual-image mode). Do you really want to re-measure the moment-based centroids and shape parameters on each separate filter image? There may not even be a source there (e.g., dropouts) in other filter images. I'm curious -- how are you using those values?

I calculate the moment-based properties from the detection image, and then calculate only the photometry (e.g., isophotal, kron, aperture) on the other images (again this is effectively the same as SourceExtractor dual-image mode). When creating a table from SourceCatalog.to_table(), you can pass a list of column names to extract only the photometric values (e.g., segment_flux, segment_fluxerr, kron_flux, etc.) that you want. To use the source centroids and shape parameters from the detection image with other images, you should pass the detection SourceCatalog into the detection_cat keyword value of the other filter SourceCatalog objects. Currently detection_cat must be a SourceCatalog object, but soon a simple table of detection centroid and shape measurements will also be allowed. Does that make sense?

larrybradley commented 2 years ago

SourceExtractor avoids this issue because the moment-based centroid and shape parameters are only measured from the detection image. Because the detection threshold is always non-negative, a detected source therefore will never have any negative pixels in its source segment (in the detection image). Only the pixels within the source segment are used for the centroids and shape measurements.

EDIT: you might be able to input a negative SourceExtractor threshold by setting THRESH_TYPE ABSOLUTE and DETECT_THRESH < 0, but that would be unusual

brantr commented 2 years ago

Hi @larrybradley Thanks. I get how this works in photutils and that when doing forced photometry properties of sources are defined based on the detection image. I am passing the detection catalog to detection_cat keyword when doing forced photometry.

I am specifically interested in the case where over subtraction of the background leads to a region of negative flux but there may be a very faint source present (e.g., a veto filter for a dropout).

I can of course recompute the statistics myself from the segmentation from the detection image applied to the image where I'm doing forced photometry. But I only have to do this because of the decision to zero out the negative fluxes.

Thanks for responding, I appreciate it. I'll close this issue.