Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add rho4 to adaptive moments #241

Merged
merged 6 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ omit =
ngmix/admom/*_nb.py
ngmix/gmix/*_nb.py
ngmix/pixels/*_nb.py
ngmix/tests/*
esheldon marked this conversation as resolved.
Show resolved Hide resolved

[report]
exclude_lines =
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/mdet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ jobs:
channel-priority: strict
show-channel-urls: true
miniforge-version: latest
miniforge-variant: Mambaforge

- name: configure conda and install code
shell: bash -l {0}
run: |
mamba config --set always_yes yes
mamba install --quiet \
conda config --set always_yes yes
conda install --quiet \
pip \
setuptools \
numpy \
Expand Down Expand Up @@ -60,7 +59,7 @@ jobs:
popd

pip uninstall ngmix -y
mamba install ngmix==2.0.3 -y
conda install ngmix==2.0.3 -y
pushd mdet_tests
python test_mdet_regression.py v2.0.3
popd
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,12 @@ jobs:
channel-priority: strict
show-channel-urls: true
miniforge-version: latest
miniforge-variant: Mambaforge

- name: configure conda and install code
shell: bash -l {0}
run: |
mamba config --set always_yes yes
mamba install --quiet \
conda config --set always_yes yes
conda install --quiet \
pip \
setuptools \
numpy \
Expand Down
94 changes: 86 additions & 8 deletions ngmix/admom/admom.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,66 @@ def find_cen_admom(
class AdmomResult(dict):
"""
Represent a fit using adaptive moments, and generate images and mixtures
for the best fit
for the best fit. This inherits from dict and has entries for
the results of adaptive moments.

Parameters
----------
obs: observation(s)
Observation, ObsList, or MultiBandObsList
result: dict
the basic fit result, to bad added to this object's keys
the basic fit result, to be added to this object's keys

The entries will include, but not be limited to
-----------------------------------------------
flags: int
flags for processing
flagstr: str
Explanation of flags
numiter: int
number of iterations in adaptive moments algorithm
npix: int
Number of pixels used
flux_flags: int
Flags for flux
flux_flagstr: int
Explanation of flux flags
flux: float
Flux estimate
flux_err: float
Error on flux estimate
T_flags: int
Flags for T
T_flagstr: int
Explanation of T flags
T: float
T for gaussian
T_err: float
Error on T
e1: float
First ellipticity parameter
e1_err: float
Error on first ellipticity parameter
e2: float
Second ellipticity parameter
e2_err: float
Error on second ellipticity parameter
rho4_flags: int
Flags for rho4
rho4_flagstr: int
Explanation of rho4 flags
rho4: float
rho4 for gaussian
rho4_err: float
Error on rho4
pars: array
Array of gaussian pars, size 6 with [v, u, e1, e2, T, flux]
wsum: float
Sum of weights over pixels
sums: array
Array of size 7, holding sums for
sums_cov: array
Covariance sums, shape (7, 7)
"""

def __init__(self, obs, result):
Expand Down Expand Up @@ -368,7 +420,7 @@ def get_result(ares, jac_area, wgt_norm):
if n == 'sums':
res[n] = ares[n].copy()
elif n == 'sums_cov':
res[n] = ares[n].reshape((6, 6)).copy()
res[n] = ares[n].reshape((7, 7)).copy()
else:
res[n] = ares[n]
res["sums_norm"] = ares["wsum"]
Expand All @@ -378,12 +430,16 @@ def get_result(ares, jac_area, wgt_norm):
res["flux_flagstr"] = ""
res["T_flags"] = 0
res["T_flagstr"] = ""
res["rho4_flags"] = 0
res["rho4_flagstr"] = ""

res['flux'] = np.nan
res['flux_mean'] = np.nan
res["flux_err"] = np.nan
res["T"] = np.nan
res["T_err"] = np.nan
res["rho4"] = np.nan
res["rho4_err"] = np.nan
res["s2n"] = np.nan
res["e1"] = np.nan
res["e2"] = np.nan
Expand All @@ -396,6 +452,7 @@ def get_result(ares, jac_area, wgt_norm):
# set things we always set if flags are ok
if res['flags'] == 0:
res['T'] = res['pars'][4]
res['rho4'] = ares['rho4']
flux_sum = res['sums'][5]
res['flux_mean'] = flux_sum/res['wsum']
res['pars'][5] = res['flux_mean']
Expand All @@ -420,8 +477,8 @@ def get_result(ares, jac_area, wgt_norm):
else:
res['flux_flags'] |= res['flags']

# handle flux+T only
if res['flags'] == 0:
# T
if res['sums_cov'][4, 4] > 0 and res['sums_cov'][5, 5] > 0:
if res['sums'][5] > 0:
# the sums include the weight, so need factor of two to correct
Expand All @@ -437,8 +494,28 @@ def get_result(ares, jac_area, wgt_norm):
res["T_flags"] |= ngmix.flags.NONPOS_FLUX
else:
res["T_flags"] |= ngmix.flags.NONPOS_VAR

# rho4
if res['sums_cov'][6, 6] > 0 and res['sums_cov'][5, 5] > 0:
if res['sums'][5] > 0:
res['rho4'] = res['sums'][6] / res['sums'][5]
# the sums include the weight, so need factor of two to correct
res['rho4_err'] = 4*get_ratio_error(
res['sums'][6],
res['sums'][5],
res['sums_cov'][6, 6],
res['sums_cov'][5, 5],
res['sums_cov'][6, 5],
)
else:
# flux <= 0.0
res["rho4_flags"] |= ngmix.flags.NONPOS_FLUX
else:
res["rho4_flags"] |= ngmix.flags.NONPOS_VAR

else:
res['T_flags'] |= res['flags']
res['rho4_flags'] |= res['flags']

# now handle full flags
if not np.all(np.diagonal(res['sums_cov'][2:, 2:]) > 0):
Expand Down Expand Up @@ -486,22 +563,23 @@ def get_result(ares, jac_area, wgt_norm):
res['flagstr'] = ngmix.flags.get_flags_str(res['flags'])
res['flux_flagstr'] = ngmix.flags.get_flags_str(res['flux_flags'])
res['T_flagstr'] = ngmix.flags.get_flags_str(res['T_flags'])
res['rho4_flagstr'] = ngmix.flags.get_flags_str(res['rho4_flags'])

return res


_admom_result_dtype = [
('flags', 'i4'),
('numiter', 'i4'),
('nimage', 'i4'),
('npix', 'i4'),
('wsum', 'f8'),

('sums', 'f8', 6),
('sums_cov', 'f8', (6, 6)),
('sums', 'f8', 7),
('sums_cov', 'f8', (7, 7)),
('pars', 'f8', 6),
('rho4', 'f8'),
# temporary
('F', 'f8', 6),
('F', 'f8', 7),
]

_admom_conf_dtype = [
Expand Down
14 changes: 11 additions & 3 deletions ngmix/admom/admom_nb.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def admom(confarray, wt, pixels, resarray):
res['pars'][3] = 2.0*wt['irc'][0]
res['pars'][4] = wt['icc'][0] + wt['irr'][0]
res['pars'][5] = 1.0
res['rho4'] = res['sums'][6] / res['sums'][5]

break

Expand Down Expand Up @@ -151,19 +152,26 @@ def admom_momsums(wt, pixels, res):
wdata = weight*pixel['val']
w2 = weight*weight

chi2 = (
wt["dcc"][0] * vmod * vmod
+ wt["drr"][0] * umod * umod
- 2.0 * wt["drc"][0] * vmod * umod
)

F[0] = pixel['v']
F[1] = pixel['u']
F[2] = umod*umod - vmod*vmod
F[3] = 2*vmod*umod
F[4] = umod*umod + vmod*vmod
F[5] = 1.0
F[6] = chi2 * chi2

res['wsum'] += weight
res['npix'] += 1

for i in range(6):
for i in range(7):
res['sums'][i] += wdata*F[i]
for j in range(6):
for j in range(7):
res['sums_cov'][i, j] += w2*var*F[i]*F[j]


Expand Down Expand Up @@ -228,8 +236,8 @@ def clear_result(res):
res['sums'][:] = 0.0
res['sums_cov'][:, :] = 0.0
res['pars'][:] = np.nan
res['rho4'] = np.nan

# res['flags']=0
# res['numiter']=0
# res['nimage']=0
# res['F'][:]=0.0
2 changes: 1 addition & 1 deletion ngmix/fitting/leastsqbound.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ def wDfun(x, *args): # wrapped Dfun
retval[1]['ipvt'] - 1)).T
cov_x = None
if info in [1, 2, 3, 4]:
from numpy.dual import inv
from numpy.linalg import inv
from numpy.linalg import LinAlgError
perm = take(eye(n), retval[1]['ipvt'] - 1, 0)
r = triu(transpose(retval[1]['fjac'])[:n, :])
Expand Down
13 changes: 12 additions & 1 deletion ngmix/gmix/gmix_nb.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,18 @@ def g1g2_to_e1e2(g1, g2):
@njit
def get_weighted_sums(wt, pixels, res, maxrad):
"""
do sums for calculating the weighted moments
Do sums for calculating the weighted moments.

Parameters
----------
wt: array
The gaussian mixture with dtype ngmix.gmix.gmix._gauss2d_dtype
pixels: array
Array of pixels
res: array
The result array
maxrad: float
Maximum radius in u, v coordinates
"""

maxrad2 = maxrad ** 2
Expand Down
11 changes: 9 additions & 2 deletions ngmix/tests/test_admom.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,22 @@ def test_admom(g1_true, g2_true, wcs_g1, wcs_g2):
).shear(
g1=g1_true, g2=g2_true
).withFlux(
400)
400,
)
im = obj.drawImage(
nx=image_size,
ny=image_size,
wcs=gs_wcs,
method='no_pixel').array
method='no_pixel',
).array
noise = np.sqrt(np.sum(im**2)) / 1e18
wgt = np.ones_like(im) / noise**2
scale = np.sqrt(gs_wcs.pixelArea())

g1arr = []
g2arr = []
Tarr = []
rho4arr = []
for _ in range(50):
shift = rng.uniform(low=-scale/2, high=scale/2, size=2)
xy = gs_wcs.toImage(galsim.PositionD(shift))
Expand Down Expand Up @@ -75,6 +78,7 @@ def test_admom(g1_true, g2_true, wcs_g1, wcs_g2):
g1arr.append(_g1)
g2arr.append(_g2)
Tarr.append(_T)
rho4arr.append(res['rho4'])

fim = res.make_image()
assert fim.shape == im.shape
Expand All @@ -94,6 +98,9 @@ def test_admom(g1_true, g2_true, wcs_g1, wcs_g2):
if g1_true == 0 and g2_true == 0:
T = np.mean(Tarr)
assert np.abs(T - fwhm_to_T(fwhm)) < 1e-6
rho4_mean = np.mean(rho4arr)
# gaussians have rho4 of 2.0
assert np.abs(rho4_mean - 2) < 1e-5

with pytest.raises(ValueError):
ngmix.admom.run_admom(None, None)
Expand Down
Loading