-
Notifications
You must be signed in to change notification settings - Fork 15
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 airmass dependent Bandpasses #444
Conversation
Thinking more about how to coerce Alternatively, we could refactor to require that @rmjarvis , do you have an opinion here? |
Sorry have been busy with first trip to summit after moving. @rmjarvis did you see Josh's question above? |
I thought you would just specify the config bandpass as being the one without the airmass factor and let the effective bandpass with the atmosphere be emergent from the combination of that with the EnvelopeRatio. But I admit I haven't thought about this enough to understand why that doesn't work for wavelength sampling as Josh implied above. |
Hi Josh, What's your current status on this and what do you still need help/input on? I think we wanted to start the rehearsal production really soon so we should figure out how to do it: You asked above for advice on how to:
Did you get any out of this issue? |
Jim, Eli and I chatted a bit about this last Friday. I think we decided that instead of initially generating photons from the outer envelope bandpass and then probabilistically culling them to match the realized bandpass, we'd instead generate from the good 'ole X=1.2 throughputs and just modify photon fluxes (weights) to get to the appropriate bandpass. That's much easier than trying to coordinate envelope+realized bandpass. The downside is the Poisson statistics don't end up quite right, but since the airmass and QE variations are pretty small, I bet we can live with that. (And it's still better than what we had before). I can probably deliver the above by ~tomorrow. |
Intersting. So, the interpolation would return a weights table? I thought I remembered the Galsim photon list can take a weight for entry, but can't find that now. Will GalSim itself apply the weight? |
Okay, I think this one is ready to look at now. Tests pass for me locally (with branch tickets/DM-42513 of obs_lsst_data). |
Okay, looks like the one CI failure is where it can't find the file that lives on an unmerged branch of obs_lsst_data. Good. |
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.
Thanks, Josh. I have some minor comments/requests having to do with handling the per-CCD QE curve side of things, otherwise lgtm.
@jchiang87 , I think I've addressed all your comments now. Let me know if there's anything else I should look at. @rmjarvis , could you take a peek at this, especially the tests to make sure they address some of the concerns you raised at the last imsim technical meeting? |
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.
Thanks, Josh. LGTM.
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 have a few questions, but this looks fine to me too.
imsim/bandpass.py
Outdated
logger.warning("Warning: Using the old bandpass files from GalSim, not lsst.sims") | ||
file_name = f"LSST_{band}.dat" | ||
bp = galsim.Bandpass(file_name, wave_type='nm') | ||
if sum([camera is not None, det_name is not 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.
Interested implementation of this. I generally prefer
if (camera is not None) != (det_name is not None):
Not sure if that's more or less obvious as to intent, but I figured I put it out there.
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.
Yeah, I like that. Shortened it to if (camera is None) != (det_name is None):
.
imsim/bandpass.py
Outdated
) | ||
|
||
if camera is not None: | ||
old_path = Path(os.getenv("OBS_LSST_DATA_DIR")) |
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 necessarily in the environment? If not, should maybe do something graceful if it isn't. Otherwise I think getenv returns None, and then Path probably takes this to be the current directory, which might lead to something odd happening downstream.
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.
Turns out Path(None)
raises a TypeError. I think it's okay to panic here; user asked for a specific detector bandpass but we're unable to comply. Reraised a ValueError with a more helpful message.
imsim/stamp.py
Outdated
@@ -720,16 +743,32 @@ def draw(self, prof, image, method, offset, config, base, logger): | |||
# In case we had to make a bigger image, just copy the part we need. | |||
image += fft_image[image.bounds] | |||
base['realized_flux'] = fft_image.added_flux | |||
# print(f"{fft_image.added_flux = }") | |||
# print(f"{fft_image.array.sum() = }") |
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.
Probably could remove most of these debugging print statements now.
|
||
# There is also a code path where the xsize,ysize is dictated by the calling routine. | ||
del config['stamp']['size'] | ||
image, _ = galsim.config.BuildStamp(config, obj_num, logger=logger, do_noise=False, | ||
xsize=128, ysize=128) | ||
print(obj_num, image.center, image.array.shape, image.array.sum()) | ||
assert image.array.shape == (128,128) | ||
assert 290_000 < image.array.sum() < 320_000 # 306675 | ||
assert 320_000 < image.array.sum() < 350_000 # 338_265 |
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.
These all changed because of something in the sims code I suppose? New version?
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.
@@ -446,7 +448,127 @@ def new_toplevel_only(self, object_types): | |||
image, _ = galsim.config.BuildStamp(config, obj_num, logger=logger, do_noise=False) | |||
print(obj_num, image.center, image.array.shape, image.array.sum()) | |||
assert image.array.shape == (32, 32) | |||
assert 5 < image.array.sum() < 10 # 8 | |||
assert 7 < image.array.sum() < 13 # 10 |
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.
How about this? Do you understand why this changed?
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 think same as above: real QE measurements are better than the baseline.
Work in progress, looking for feedback.
Adds
airmass
kwarg toRubinBandpass
. Performs linear interpolation of log(throughput) vs airmass X, which seems to be pretty good from investigation in a separate notebook.EnvelopeRatio
photon operator. This takes an "envelope" (X=1.0) bandpass object, and reads the target (X > 1.0) bandpass function from the base config. It then sets photon fluxes to zero with probability1 - bandpass(wavelength)/envelope(wavelength)
, effectively changing the filter from X=1 to X>1 and still getting the Poisson statistics right.I'm still not sure how to:
I'll dig in tomorrow, but any advice appreciated.