-
Notifications
You must be signed in to change notification settings - Fork 10
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
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 79cfa6d
synthetic injection pipeline complete, begin bug check
andrew-saydjari 6a53539
injextnamelist rename
andrew-saydjari 6c640c2
verbose increase for troubleshoot
andrew-saydjari a982f57
verbose
andrew-saydjari c880987
is injextnames empty?
andrew-saydjari f4081ef
injextnames
andrew-saydjari f53f80f
eliminate injextnames
andrew-saydjari c9c7a1e
filter is just a letter but fits header is soooo long...
andrew-saydjari ef39ba5
merge extname, name, and key to key
andrew-saydjari 6e0bd34
supress warnings from load nonstd keywords
andrew-saydjari e00e6c3
apparently and ordered dictionary has to be defined... python nonsense
andrew-saydjari a4047b9
zero safe inversion
andrew-saydjari a88b449
redefine cat
andrew-saydjari d36fee2
make sure to add I before the injected run loop
andrew-saydjari 56d40d9
help with I handling
andrew-saydjari efaa5d7
export outmodel to big dig and pass bigdict tothe save fxn
andrew-saydjari 014eeaa
errant colon
andrew-saydjari ad6cbc0
just edit big dict rather than recopy params
andrew-saydjari e2c5ae5
update big dict so we can just pass everything to save fxn
andrew-saydjari 339013a
change mock cat header name
andrew-saydjari a335076
match Eddie's xy convention, I think psfmod.render will need this
andrew-saydjari 6292728
FIX ME number of inject limit
andrew-saydjari 1bbb1b8
different seed for fits compressin test
andrew-saydjari c60c74c
update leda to remove by hand list AKS
andrew-saydjari 3d94e17
verbose
andrew-saydjari 2342157
more verbose
andrew-saydjari a28fcb1
lift assertion threshold
andrew-saydjari f905f9a
fix path from scratch to home
andrew-saydjari 1aa3197
recompute coordinates on reduced list
andrew-saydjari 94a24ee
verbose
andrew-saydjari 3e3e09b
verbose diam_mod
andrew-saydjari 2c251d8
verbose idx_mod and idx
andrew-saydjari 06707ae
verbose idx_bad
andrew-saydjari e3fe4a7
idx and idx_bad orders seem to have been messed up during the last PR
andrew-saydjari f93037b
remove verbose
andrew-saydjari 7d437b8
point to new galmask path
andrew-saydjari e503485
wrap injection write files to clean up deacm_proc
andrew-saydjari 5344ed9
injectfrac fix
andrew-saydjari 3d6fda3
psf_shift now just a simple call
andrew-saydjari 296b8b6
seed rng with date of file for reproducible but different inject tests
andrew-saydjari 065c5b8
save decam_proc
andrew-saydjari 4819321
import os
andrew-saydjari 7841fd9
add overwrite
andrew-saydjari 924b57d
injectfrac consistent naming
andrew-saydjari d13ffcf
silent fits files!
andrew-saydjari c2a5fac
indent
andrew-saydjari 208340f
indent
andrew-saydjari 0e780f0
force injected sources to be positive
andrew-saydjari 91d2c01
verbose
andrew-saydjari f44f7f8
isnan not is_nan...
andrew-saydjari f155079
verbose gain?
andrew-saydjari a06a5d7
seems to be in the psf shift
andrew-saydjari a672a0b
print min to confirm it is small and I can set to zero
andrew-saydjari 126f7bd
more psf stats
andrew-saydjari 04804f6
print key
andrew-saydjari ad23eae
update size to account for negative stars stripped out
andrew-saydjari cf42df3
sample star positions with the date seeded rng
andrew-saydjari 552256b
save the mock catalogue with the Eddie normalization
andrew-saydjari b12f91d
psfmod define
andrew-saydjari 52d2e40
scattering returns 6 values
andrew-saydjari d44a1a8
need to have length x now
andrew-saydjari File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
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" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.