upper limit NaN fix; ECF & EEF values update

This commit is contained in:
2025-05-13 15:38:03 +03:00
parent d46e5e5fa6
commit ffaa663fdd
3 changed files with 222 additions and 21 deletions

View File

@@ -5,6 +5,7 @@
import healpy as hp
import astropy.units as u
from astropy.coordinates import SkyCoord
import numpy as np
import scipy.special as sp
from astropy.stats import poisson_conf_interval
@@ -18,6 +19,22 @@ from django.shortcuts import get_object_or_404
from uplim.models import Pixel
# SANITIZE RESPONSE DATA BEFORE JSON CONVERSION FOR DEBUGGING NANS
# now NaNs are converted to 'null' beforehand
# ****************************************************************
def sanitize(obj):
if isinstance(obj, dict):
return {k: sanitize(v) for k, v in obj.items()}
if isinstance(obj, (list, tuple)):
return [sanitize(v) for v in obj]
# handle numpy scalars
if isinstance(obj, np.generic):
v = obj.item()
return None if (np.isnan(v) or np.isinf(v)) else v
if isinstance(obj, float):
return None if (np.isnan(obj) or np.isinf(obj)) else obj
return obj
# SURVEY PARAMETER PARSER
@@ -233,7 +250,7 @@ class UpperLimitView(APIView):
N = sum(obj.counts for obj in source_pixels)
Nnpix = len(source_pixels)
Bcounts = sum(obj.counts for obj in annulus_pixels)
Bnpix = len(annulus_pixels)
@@ -247,9 +264,11 @@ class UpperLimitView(APIView):
# CONSTANTS
# **************************************************************
EEF = .9 # eclosed energy fraction, .5 for hpd, .9 for w90
ECF = 4e-11 # energy conversion factor
#EEF = .9 # eclosed energy fraction, .5 for hpd, .9 for w90
#ECF = 4e-11 # energy conversion factor
EEF = .80091 # use values from the paper
ECF = 3.3423184e-11
# BAYESIAN IMPLEMENTATION VIA POISSON_CONF_INTERVAL
@@ -268,7 +287,7 @@ class UpperLimitView(APIView):
bayesian_rate_ul = bayesian_count_ul / t / EEF # count rate limits
bayesian_rate_ll = bayesian_count_ll / t / EEF
bayesian_flux_ul = bayesian_rate_ul * ECF # flux limits
bayesian_flux_ul = bayesian_rate_ul * ECF # flux limits
bayesian_flux_ll = bayesian_rate_ll * ECF
# CLASSICAL IMPLEMENTATION VIA GAMMAINCCINV
@@ -277,28 +296,32 @@ class UpperLimitView(APIView):
classic_count_ul = sp.gammainccinv(N+1, 1 - confidence_level) - B
classic_count_ll = sp.gammainccinv(N, confidence_level) - B
classic_count_ll = max(classic_count_ll, 0)
if not np.isfinite(classic_count_ll) or classic_count_ll < 0:
classic_count_ll = 0.0
classic_rate_ul = classic_count_ul / t / EEF # count rate limits
classic_rate_ll = classic_count_ll / t / EEF
classic_flux_ul = classic_rate_ul * ECF # flux limits
classic_flux_ul = classic_rate_ul * ECF # flux limits
classic_flux_ll = classic_rate_ll * ECF
# FLUX ESTIMATION
# ****************************************************************
S = N - B # counts as simply counts within aperture
S = N - B # counts as simply counts within aperture
# with the background estimate subtracted
CR = S / t / EEF # count rate
CR = S / t / EEF # count rate
FL = CR * ECF # conversion to flux
Flux = max(FL, 0) # flux cannot be lower than zero
# RESULT ASSEMBLY
# ****************************************************************
return Response({
result = {
'ClassicUpperLimit' : classic_count_ul,
'ClassicLowerLimit' : classic_count_ll,
@@ -316,6 +339,8 @@ class UpperLimitView(APIView):
'FluxEstimate' : Flux,
# raw counts and exposure omitted from the response
# 'N' : N,
# 'Nnpix' : Nnpix,
# 'Bcounts' : Bcounts,
@@ -324,4 +349,8 @@ class UpperLimitView(APIView):
# 'tsum' : tsum,
# 't' : t
}, status=status.HTTP_200_OK)
}
clean = sanitize(result) # calling sanitize() to convert NaN to null
return Response(clean, status=status.HTTP_200_OK)