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

DECaPS2 commit #3

Merged
merged 62 commits into from
Sep 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
e7523a2
synthetic injection pipeline frame work, scatter stars to come
andrew-saydjari Aug 31, 2021
79cfa6d
synthetic injection pipeline complete, begin bug check
andrew-saydjari Aug 31, 2021
6a53539
injextnamelist rename
andrew-saydjari Sep 1, 2021
6c640c2
verbose increase for troubleshoot
andrew-saydjari Sep 1, 2021
a982f57
verbose
andrew-saydjari Sep 1, 2021
c880987
is injextnames empty?
andrew-saydjari Sep 1, 2021
f4081ef
injextnames
andrew-saydjari Sep 1, 2021
f53f80f
eliminate injextnames
andrew-saydjari Sep 1, 2021
c9c7a1e
filter is just a letter but fits header is soooo long...
andrew-saydjari Sep 1, 2021
ef39ba5
merge extname, name, and key to key
andrew-saydjari Sep 1, 2021
6e0bd34
supress warnings from load nonstd keywords
andrew-saydjari Sep 1, 2021
e00e6c3
apparently and ordered dictionary has to be defined... python nonsense
andrew-saydjari Sep 1, 2021
a4047b9
zero safe inversion
andrew-saydjari Sep 1, 2021
a88b449
redefine cat
andrew-saydjari Sep 1, 2021
d36fee2
make sure to add I before the injected run loop
andrew-saydjari Sep 1, 2021
56d40d9
help with I handling
andrew-saydjari Sep 1, 2021
efaa5d7
export outmodel to big dig and pass bigdict tothe save fxn
andrew-saydjari Sep 1, 2021
014eeaa
errant colon
andrew-saydjari Sep 1, 2021
ad6cbc0
just edit big dict rather than recopy params
andrew-saydjari Sep 1, 2021
e2c5ae5
update big dict so we can just pass everything to save fxn
andrew-saydjari Sep 1, 2021
339013a
change mock cat header name
andrew-saydjari Sep 1, 2021
a335076
match Eddie's xy convention, I think psfmod.render will need this
andrew-saydjari Sep 1, 2021
6292728
FIX ME number of inject limit
andrew-saydjari Sep 1, 2021
1bbb1b8
different seed for fits compressin test
andrew-saydjari Sep 1, 2021
c60c74c
update leda to remove by hand list AKS
andrew-saydjari Sep 1, 2021
3d94e17
verbose
andrew-saydjari Sep 1, 2021
2342157
more verbose
andrew-saydjari Sep 1, 2021
a28fcb1
lift assertion threshold
andrew-saydjari Sep 1, 2021
f905f9a
fix path from scratch to home
andrew-saydjari Sep 1, 2021
1aa3197
recompute coordinates on reduced list
andrew-saydjari Sep 1, 2021
94a24ee
verbose
andrew-saydjari Sep 2, 2021
3e3e09b
verbose diam_mod
andrew-saydjari Sep 2, 2021
2c251d8
verbose idx_mod and idx
andrew-saydjari Sep 2, 2021
06707ae
verbose idx_bad
andrew-saydjari Sep 2, 2021
e3fe4a7
idx and idx_bad orders seem to have been messed up during the last PR
andrew-saydjari Sep 2, 2021
f93037b
remove verbose
andrew-saydjari Sep 2, 2021
7d437b8
point to new galmask path
andrew-saydjari Sep 2, 2021
e503485
wrap injection write files to clean up deacm_proc
andrew-saydjari Sep 2, 2021
5344ed9
injectfrac fix
andrew-saydjari Sep 2, 2021
3d6fda3
psf_shift now just a simple call
andrew-saydjari Sep 2, 2021
296b8b6
seed rng with date of file for reproducible but different inject tests
andrew-saydjari Sep 2, 2021
065c5b8
save decam_proc
andrew-saydjari Sep 2, 2021
4819321
import os
andrew-saydjari Sep 2, 2021
7841fd9
add overwrite
andrew-saydjari Sep 2, 2021
924b57d
injectfrac consistent naming
andrew-saydjari Sep 2, 2021
d13ffcf
silent fits files!
andrew-saydjari Sep 2, 2021
c2a5fac
indent
andrew-saydjari Sep 2, 2021
208340f
indent
andrew-saydjari Sep 2, 2021
0e780f0
force injected sources to be positive
andrew-saydjari Sep 6, 2021
91d2c01
verbose
andrew-saydjari Sep 6, 2021
f44f7f8
isnan not is_nan...
andrew-saydjari Sep 6, 2021
f155079
verbose gain?
andrew-saydjari Sep 6, 2021
a06a5d7
seems to be in the psf shift
andrew-saydjari Sep 6, 2021
a672a0b
print min to confirm it is small and I can set to zero
andrew-saydjari Sep 6, 2021
126f7bd
more psf stats
andrew-saydjari Sep 6, 2021
04804f6
print key
andrew-saydjari Sep 6, 2021
ad23eae
update size to account for negative stars stripped out
andrew-saydjari Sep 6, 2021
cf42df3
sample star positions with the date seeded rng
andrew-saydjari Sep 7, 2021
552256b
save the mock catalogue with the Eddie normalization
andrew-saydjari Sep 7, 2021
b12f91d
psfmod define
andrew-saydjari Sep 7, 2021
52d2e40
scattering returns 6 values
andrew-saydjari Sep 7, 2021
d44a1a8
need to have length x now
andrew-saydjari Sep 7, 2021
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
241 changes: 241 additions & 0 deletions python/decam_inject.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
from astropy.io import fits
from scipy.interpolate import interp1d
import copy
import numpy as np
from functools import partial
import psf as psfmod
import decam_proc
from collections import OrderedDict
import os

def write_injFiles(imfn, ivarfn, dqfn, outfn, inject, injextnamelist, filt, pixsz,
wcutoff, verbose, resume, date, overwrite, injectfrac=0.1):
# Updated the completed ccds
hdulist = fits.open(outfn)
extnamesdone = []
injnamescat = []
for hdu in hdulist:
if hdu.name == 'PRIMARY':
continue
ext, exttype = hdu.name.split('_')
if exttype != 'CAT':
continue
if ext[-1] == 'I':
injnamescat.append(ext)
else:
extnamesdone.append(ext)
hdulist.close()

# Prepare injection CCD for loop ext list
if injextnamelist is not None:
if verbose:
s = ("Only injecting CCD subset: [%s]" %
', '.join(injextnamelist))
print(s)

if extnamesdone is not None:
injextnames = [n for n in extnamesdone]
else:
raise ValueError('No CCDs are done. Please fit at least one CCD before injection test.')
if injextnamelist is not None:
injextnames = [n for n in injextnames if n in injextnamelist]
injextnames = [n for n in injextnames if n != 'PRIMARY']
if inject != -1:
rng = np.random.default_rng(int(date))
injextnames = rng.choice(injextnames, inject, replace=False)

# create files with injected sources in the decapsi directory
## this might need to be more robust if we port to a different cluster/user
imfnI = injectRename(imfn)
ivarfnI = injectRename(ivarfn)
dqfnI = injectRename(dqfn)

# intialize the injected images
prihdr = fits.getheader(imfn, extname='PRIMARY')
if not resume or not os.path.exists(imfnI):
fits.writeto(imfnI, None, prihdr, overwrite=overwrite)

prihdr = fits.getheader(ivarfn, extname='PRIMARY')
if not resume or not os.path.exists(ivarfnI):
fits.writeto(ivarfnI, None, prihdr, overwrite=overwrite)

prihdr = fits.getheader(dqfn, extname='PRIMARY')
if not resume or not os.path.exists(dqfnI):
fits.writeto(dqfnI, None, prihdr, overwrite=overwrite)

import warnings
with warnings.catch_warnings(record=True) as wlist:
hdulist = fits.open(dqfnI)
injnamesdone = []
for hdu in hdulist:
if hdu.name == 'PRIMARY':
continue
injnamesdone.append(hdu.name)
hdulist.close()
# suppress endless nonstandard keyword warnings on read
for warning in wlist:
if 'following header keyword' in str(warning.message):
continue
else:
print(warning)

injextnamesI = [i+"I" for i in injextnames]
injextnamesI = [i for i in injextnamesI if i not in injnamescat]

injextnames = [i for i in injextnames if i not in injnamesdone]

rng = np.random.default_rng(int(date))
for key in injextnames:
scatter_stars(outfn, imfn, ivarfn, dqfn, key, filt, pixsz, wcutoff, verbose, rng, injectfrac=injectfrac)

return imfnI, ivarfnI, dqfnI, injextnamesI

#seed on date here too
def scatter_stars(outfn, imfn, ivarfn, dqfn, key, filt, pixsz, wcutoff, verbose, rng, injectfrac=0.1):

## imports
hdr = fits.getheader(outfn,key+"_HDR")
gain = hdr['GAINCRWD']

f = fits.open(outfn)
table = f[key+"_CAT"].data
flux_stars = table["flux"]
flags_stars = table["flags"]
f.close()

psfmodel = load_psfmodel(outfn, key, filt[0], pixsz=pixsz)

import warnings
with warnings.catch_warnings(record=True) as wlist:
im = fits.getdata(imfn, extname=key).copy()
wt = fits.getdata(ivarfn, extname=key).copy()
dq = fits.getdata(dqfn, extname=key).copy()
# suppress endless nonstandard keyword warnings on read
for warning in wlist:
if 'following header keyword' in str(warning.message):
continue
else:
print(warning)

nx, ny = im.shape

# this requres stars to be "good" and in a reasonable flux range (0 flux to 17th mag)
maskf = ((flags_stars==1) | (flags_stars==2097153)) & (flux_stars>0) & (flux_stars<158489.3192461114);
Copy link
Owner

Choose a reason for hiding this comment

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

Is this 17th mag assuming some nominal zero point for a particular band? This number is oddly specific.

Copy link
Collaborator Author

@andrew-saydjari andrew-saydjari Sep 9, 2021

Choose a reason for hiding this comment

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

LOL, that is exactly what it is. It is 17th mag in g-band using the mean zero point from DECaPS 1. I don't think the actual number matters, that is just how I picked it.

Copy link
Owner

Choose a reason for hiding this comment

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

Let's clarify both these numbers after your run. i.e., 150000 to me better expresses the concept of "not too bright" than 158489; the corresponding comment might be that 17th mag in g roughly corresponds to 160k counts.

I'd usually write your flag cut as something like (flags & ~decam_proc.extrabits['diffuse']) == 2**0, but that's just stylistic. It would be good form to refer to the diffuse bit by name rather than by that decimal.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure. Good code comments all.

nstars=np.round(injectfrac*flux_stars[maskf].shape[0]).astype(int)

flux_samples = sample_stars(flux_stars[maskf],nstars,rng)
nstars = flux_samples.shape[0]
# stay 33 pixels away from edge for injections
centxl = rng.uniform(33,nx-33,nstars)
centyl = rng.uniform(33,ny-33,nstars)
xcenl = centxl.astype(int)
ycenl = centyl.astype(int)
mhn = 255 # this is the radius of the model stamp
mszn = 511 # this is the size of the model stamp
mock_cat = np.zeros((nstars,6))
new_flux = np.zeros((nx, ny))
for i in range(nstars):
amp = flux_samples[i]
centx = centxl[i]
centy = centyl[i]
xcen = xcenl[i]
ycen = ycenl[i]

psf_shift = psfmodel(centx,centy,stampsz=511)
draw = rng.poisson(lam=amp*gain*psf_shift)/gain

new_flux[np.clip(xcen-mhn,a_min=0,a_max=None):np.clip(xcen+mhn+1,a_min=None,a_max=nx),
np.clip(ycen-mhn,a_min=0,a_max=None):np.clip(ycen+mhn+1,a_min=None,a_max=ny)] += draw[
np.clip(mhn-xcen,a_min=0,a_max=None):np.clip(nx-xcen+mhn,a_min=None,a_max=mszn),
np.clip(mhn-ycen,a_min=0,a_max=None):np.clip(ny-ycen+mhn,a_min=None,a_max=mszn)]

mock_cat[i,:] = [centx, centy, np.sum(psfmod.central_stamp(draw,censize=59)), np.sum(draw), np.sum(np.multiply(draw,psf_shift))/np.sum(np.square(psf_shift)), amp]

im += new_flux
wt = (1./(wt + (wt == 0) * 1e14) + np.divide(new_flux,gain))**(-1)

# save our injections
## Eddie thinks we should compare compressing with the
## same or different seed
imfnI = injectRename(imfn)
ivarfnI = injectRename(ivarfn)
dqfnI = injectRename(dqfn)
with warnings.catch_warnings(record=True) as wlist:
hdr = fits.getheader(dqfn, extname=key)
hdr['EXTNAME'] = hdr['EXTNAME'] + 'I'
compkw = {'quantize_method': 1,
'quantize_level': 4,
}
f = fits.open(dqfnI, mode='append')
f.append(fits.CompImageHDU(dq, hdr, **compkw))
f.close(closed=True)

hdr = fits.getheader(ivarfn, extname=key)
hdr['EXTNAME'] = hdr['EXTNAME'] + 'I'
compkw = {'quantize_method': 1,
'quantize_level': 4,
'dither_seed': hdr["ZDITHER0"]+1,
}
f = fits.open(ivarfnI, mode='append')
f.append(fits.CompImageHDU(wt, hdr, **compkw))
f.close(closed=True)

hdr = fits.getheader(imfn, extname=key)
hdr['EXTNAME'] = hdr['EXTNAME'] + 'I'
compkw = {'quantize_method': 1,
'quantize_level': 4,
'dither_seed': hdr["ZDITHER0"]+1,
}
f = fits.open(imfnI, mode='append')
f.append(fits.CompImageHDU(im, hdr, **compkw))
f.close(closed=True)
for warning in wlist:
if 'following header keyword' in str(warning.message):
continue
else:
print(warning)

#mock catalogue export
stars = OrderedDict([('x', mock_cat[:,0]), ('y', mock_cat[:,1]), ('flux', mock_cat[:,2]),
('fluxfull', mock_cat[:,3]), ('psfwt_flux', mock_cat[:,4]), ('amp', mock_cat[:,5])])
dtypenames = list(stars.keys())
dtypeformats = [stars[n].dtype for n in dtypenames]
dtype = dict(names=dtypenames, formats=dtypeformats)
cat = np.fromiter(zip(*stars.values()),
dtype=dtype, count=len(stars['x']))

hducat = fits.BinTableHDU(cat)
hducat.name = hdr['EXTNAME'] + '_MCK'
hdulist = fits.open(outfn, mode='append')
hdulist.append(hducat) # append the cat field for the ccd
hdulist.close(closed=True)
return


def ecdf(x):
xs = np.sort(x)
ys = np.arange(1, len(xs)+1)/float(len(xs))
return xs, ys


def sample_stars(flux_list, nstars, rng):
fx, fy = ecdf(flux_list)
inv_ecdf = interp1d(fy, fx, fill_value="extrapolate")
sampler = rng.uniform(0,1,nstars)
sflux = inv_ecdf(sampler)
return sflux[sflux>0]


def load_psfmodel(outfn, key, filter, pixsz=9):
f = fits.open(outfn)
psfmodel = psfmod.linear_static_wing_from_record(f[key+"_PSF"].data[0],filter=filter)
f.close()
psfmodel.fitfun = partial(psfmod.fit_linear_static_wing, filter=filter, pixsz=pixsz)
return psfmodel


def injectRename(fname):
spltname = fname.split("/")
spltname[3] = "decapsi"
fname = "/".join(spltname)
return fname[:-7]+"I.fits.fz"
Loading