-
Notifications
You must be signed in to change notification settings - Fork 12
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
Implementing Calibrated Contrast Measurements #91
Conversation
The SpaceTelescope(Data) class that was in pyklippipeline.py has now been removed. Instead, I have ported this over to pyKLIP itself under a new Important: We shouldn't merge this spaceKLIP branch until we are happy with the pyKLIP file / have merged things into pyKLIP's EDIT: Don't worry about failing checks at the moment, they are related to the code wanting to use the older version of pyKLIP. |
Companion injection and recovery is now coded up, based on fitting 2D Gaussians to estimate the peak flux of injected sources after KLIP subtraction. For MIRI this is probably okay, but perhaps we should do something smarter for NIRCam in the future. |
Okay calibrated contrast curves can now be calculated. I won't merge in just yet, as I think further thought needs to go into retrieved throughputs >1. Plus, it would be great if a few people could test this first. @mperrin, @kammerje, I know you are on vacation right now, but perhaps when you get back you could review what I've done. |
@AarynnCarter FYI I'm back from vacation, still playing catchup on many things. I see & acknowledge your request for me to take a look at this, and will try to do so within the next ~2 weeks (i.e. before the conference in a couple weeks here). Is this "ready to go" from your perspective? I see it's still a Draft PR. And can you remind me if there's a plan yet for timing re the related pyKLIP branch merges etc? |
@mperrin This should be good for review, yes. I might add some minor bug fixes in if needed. This is a somewhat complicated PR as we'll need to make sure pyKLIP is updated first, so once you think it's good to go I will coordinate with Jason so that everything gets updated together. |
@AarynnCarter Add logging for calibrated contrast steps |
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.
Apologies for the delay in this -- I started this review many weeks ago but got interrupted and didn't get back to it until now.
The comments are mostly suggestions for clarification, possible improvement in parts. I don't see any show stoppers to merging this, but I think a round of revisions would be beneficial, so this review is for now just a "comment", neither an approve nor a formal request for changes.
@@ -4,5 +4,6 @@ jdaviz | |||
jwst | |||
matplotlib | |||
numpy | |||
pysynphot |
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.
I would urge you to reconsider this dependency, since pysynphot
is deprecated and no longer actively developed. Instead synphot
should be preferred as the current tool, with similar but slightly different API after a refactoring. synphot
is actively developed and supported.
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.
And yes, this is an annoyance from upstream, but wanted to make sure you were aware.
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.
Looks like this is tied to the psf.py
file, which is built upon WebbPSF_ext. I 100% agree we should change, but don't want to bloat this PR further / I think this will need a careful hand to make sure we don't break anything. Instead, I've made a new issue so that we don't lose track.
spaceKLIP/analysistools.py
Outdated
@@ -121,6 +124,16 @@ def raw_contrast(self, | |||
output_dir = os.path.join(self.database.output_dir, subdir) | |||
if not os.path.exists(output_dir): | |||
os.makedirs(output_dir) | |||
|
|||
# Copy the starfile that will be used into this directory | |||
starfile_type = starfile.split('.')[-1] |
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.
minor: use os.path.splitext
for this.
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.
Changed.
spaceKLIP/analysistools.py
Outdated
new_starfile_path = output_dir+'/user_starfile.'+starfile_type | ||
header = '#'+starfile.split('/')[-1] + ' /// {}'.format(spectral_type)+'\n' | ||
with open(new_starfile_path, 'w') as new_starfile: | ||
with open(starfile, 'r') as orig_starfile: | ||
new_starfile.write(header) | ||
for line in orig_starfile.readlines(): | ||
new_starfile.write(line) |
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.
Minor: I see what you're doing here, I guess, but this seems kinda a low-level kludge, to copy a data file line by line just to append a comment text at the start. This is a minor point and I'm OK if you want to leave as-is, it just strikes me as an unnecessary complication, and from a code style perspective is an interruption that breaks up the conceptual flow, and breaks layers of abstraction. Consider encapsulating this sort of thing into utility functions.
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.
Moved function to utils.py, streamlined it a bit, and added an error flag if the file can't be found.
nanmask[nanmask<0.5] = 1 | ||
|
||
# Downsample, remove padding, and mask data | ||
nanmask = nanmask[::samp,::samp] |
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.
I don't follow the logic here about oversampling. You make the mask oversampled by 15x, but here you downsample to every 15th sample, without any averaging at all. So what is the point of the upsampling? The vast majority of the upsampled pixels (1 - (1/15)**2, so 99.1%!) are discarded without ever being used.
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.
The sampling is for the nanmask, so there isn't really any averaging to do. A pixel should either be == 1 (not masked) or == np.nan (masked). I found that by upsampling the array initially, the rectangles that I apply can be better centered in the image, perhaps I could adjust how the rectangles are being made to remove the need to upsample but it seems to work right now and it's relatively quick.
However, by looking at this I spotted that some pixels, despite being surrounded by NaNs, weren't being masked. I've added a new utility function to catch these and fix them.
@@ -269,6 +339,7 @@ def raw_contrast(self, | |||
ax.plot(seps[k], cons[k], color=colors[k % mod], alpha=0.3) | |||
ax.plot(seps[k], cons_mask[k], color=colors[k % mod], label=klmodes[k] + ' KL') | |||
ax.set_yscale('log') | |||
ax.set_ylim([None,1]) |
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.
A general comment on the raw_contrast plots (not this particular line of code): When running in a notebook, it would be nice if the PDF plots are displayed in the notebook, as well as saved to disk. At minimum, the text in the function that writes out like Contrast results saved to [filename etc]
should also state that PDF plots were saved into that directory.
The point here is to help make it more discoverable and obvious to users that these files now exist, and where to find them...
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.
I'm not familiar enough with notebooks to understand why things aren't being plotted there, maybe that's best left for a future improvement? I did add a quick adjustment to the print statement that mentions plots have been saved.
spaceKLIP/analysistools.py
Outdated
plt.savefig(save_string + '_calcon.pdf', | ||
bbox_inches='tight', dpi=300) | ||
|
||
pass |
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.
pass
is unnecessary here
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.
Removed
spaceKLIP/analysistools.py
Outdated
raw_dataset : pyKLIP dataset | ||
A pyKLIP dataset which companions will be injected into and KLIP | ||
will be performed on. | ||
true_companions : |
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.
doc string missing info for true_companions
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.
Fixed
spaceKLIP/analysistools.py
Outdated
|
||
Returns | ||
------- | ||
TBD |
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.
???
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.
Added
spaceKLIP/imagetools.py
Outdated
head_pri['XOFFSET'] = xoffset | ||
head_pri['YOFFSET'] = yoffset | ||
head_pri['XOFFSET'] = xoffset / 1e3 #Should be saved in arcseconds for FITS file | ||
head_pri['YOFFSET'] = yoffset / 1e3 #Should be saved in arcseconds for FITS file |
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.
Ideally this ought to include a FITS header comment giving the units!
head_pri['XOFFSET'] = (xoffset, '[arcsec] X offset in arcseconds')
head_pri['YOFFSET'] = (yoffset, '[arcsec] Y offset in arcseconds')
(See FITS standard, section 4.3.2)
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.
/ 1e3
was conflicted with the develop branch and has been removed (hence the reason I was confused why it was there). Totally agree on FITS header comments, but this is an issue that extends beyond the XOFFSET and YOFFSET values - we haven't done the best job at including these. I'll make a separate issue to address this code wide.
spaceKLIP/imagetools.py
Outdated
@@ -1988,9 +1991,10 @@ def align_frames(self, | |||
f = plt.figure(figsize=(6.4, 4.8)) | |||
ax = plt.gca() | |||
for index, j in enumerate(ww_sci): | |||
ax.scatter(shifts_all[index][:, 0] * self.database.obs[key]['PIXSCALE'][j], shifts_all[index][:, 1] * self.database.obs[key]['PIXSCALE'][j], s=5, color=colors[index], marker='o', label='PA = %.0f deg' % self.database.obs[key]['ROLL_REF'][j]) | |||
ax.scatter(shifts_all[index][:, 0] * self.database.obs[key]['PIXSCALE'][j], shifts_all[index][:, 1] * self.database.obs[key]['PIXSCALE'][j], s=5, color=colors[index%10], marker='o', label='PA = %.0f deg' % self.database.obs[key]['ROLL_REF'][j]) |
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.
(code style) This line is really dense and hard to read... Consider reformatting over a couple of lines
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.
Done
Latest commit Resolves #119 |
… some minor docstring fixes
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.
Reviewed, tested extensively, some debugging and additional enhancements to plots added. Discussed in Slack with @AarynnCarter and @kammerje.
Working; looks good to me. 👍
Putting together all the code necessary to perform calibrated contrast measurements.
Resolves #79, Resolves #85
Started by implementing the MIRI FQPM masking, this is improved from original spaceKLIP and uses rectangles instead of pizza slices.