-
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
Refactor image/stamp workflow #424
base: main
Are you sure you want to change the base?
Conversation
e58012d
to
c145f0c
Compare
c145f0c
to
1d7fefc
Compare
acbac83
to
9f49df7
Compare
The latest commit aligns photon objects in the photon pooling pipeline with their positions in the original pipeline. |
Almost there, but blocked by GalSim-developers/GalSim#1284. |
daae77c
to
7290a11
Compare
… be made if the full image has an even number of pixels in x and/or y, then apply this offset to photon arrays before merging.
bdaadae
to
b786cb0
Compare
This is finally open for review -- all comments welcome. |
…he functions there its static methods.
…beginning. Previously missed. Ensure conservation of photon object fluxes during batching by adding the modulo to random batches.
…ST_ImageBuilderBase.
46461fb
to
eeb67dc
Compare
…than the (0,0) position.
I think this is ready for re-review now, though CI is failing with an error in |
I think there is actually one more commit incoming. I've realised that in edge cases where nominally bright photon objects' |
…ther photon pooling tests.
OK, that should be it -- code open for review! |
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 William. I think we're close.
I'd still like to have a separate PR that just changes the tests of the expected centers. I think the way to do that is to change the test to mostly your new code, but when calling (the old) XyToV, use sky_pos = img_wcs.toWorld(image_pos)
and local_wcs = img_wcs.local(image_pos)
. I'm not sure what image_pos is exactly, but hopefully you can follow Geri's code to see what the implicit image_pos is there.
imsim/photon_pooling.py
Outdated
offset_adjustment: a PositionD by which to offset each object | ||
""" | ||
for stamp in stamps: | ||
offset = offset_adjustment |
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 should just call this parameter offset
from the start.
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! Doing this now.
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 now obsolete with the big simplification in offsetting the photons by stamp_center. I've removed the two static methods in photon_pooling.py dealing with the offset and it's now dealt with in stamp.py just using stamp_center.
imsim/photon_pooling.py
Outdated
Returns: | ||
images: Tuple of the output stamps. In normal PhotonPooling usage these will actually be | ||
PhotonArrays to be processed into images after they have been pooled following this step. | ||
current_vars: Tuple of variables for each stamp (noise etc). |
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 should be the current noise variance in each image. var=variance, not variable.
It's not really relevant for most imsim usage, but if you draw a RealGalaxy, and especially if you then whiten it, the image gets some noise from that, so this mechanism helps GalSim from adding more noise than requested when adding the rest of the image noise.
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 for pointing this out. Is the actual usage of current_vars
ok?
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.
Yes. Just the doc string is wrong.
imsim/photon_pooling.py
Outdated
batches = [ | ||
[dataclasses.replace(obj, phot_flux=np.floor(obj.phot_flux / nbatch)) for obj in phot_objects] | ||
for _ in range(nbatch)] |
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 nifty (simpler?) way to get the total flux to come out right:
batches = [ | |
[dataclasses.replace(obj, phot_flux=np.floor(obj.phot_flux / nbatch)) for obj in phot_objects] | |
for _ in range(nbatch)] | |
batches = [ | |
[dataclasses.replace(obj, | |
phot_flux=(obj.phot_flux*(i+1))//nbatch - (obj.phot_flux*i)//nbatch) | |
) for obj in phot_objects] | |
for i in range(nbatch)] |
Then you don't need the block below 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.
Very nice -- thanks! Putting this in now.
imsim/stamp.py
Outdated
def build_obj(stamp_config, base, logger): | ||
"""Precompute all data needed to determine the rendering mode of an | ||
object.""" | ||
stamp_type = stamp_config.get('type','LSST_Photons') |
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 think we want to have a default here. Rather we should make sure the user has correctly specified this type. So if stamp_config.get('type', None) != 'LSST_Photons':
... then raise some kind of explanatory errror.
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 -- doing this now.
imsim/stamp.py
Outdated
|
||
max_flux_simple = config.get('max_flux_simple', 100) | ||
faint = self.nominal_flux < max_flux_simple | ||
bandpass = base['bandpass'] |
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.
duplicate
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.
D'oh! Thanks for spotting -- fixed.
imsim/stamp.py
Outdated
img_pos = base["image_pos"] | ||
obj_offset = base["stamp_offset"] | ||
image.photons.x = image.photons.x + img_pos.x - obj_offset.x | ||
image.photons.y = image.photons.y + img_pos.y - obj_offset.y |
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 all this offset stuff could be simpler. Here you add img_pois - stamp_offset. Then later you add 0.5 for even sized images. So the net adjustment is
img_pos - stamp_offset + (0.5 if size%2==0)
I'm pretty sure this combination is equivalent to base["stamp_center"] based on the calculation of stamp_offset here. So I think you can just add stamp_center here and skip the later adjustments. Which honestly makes sense. These photon arrays are meant to be relative to the image center, which here is just the stamp center.
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.
Very nice call. I've just tested and this gives identical output. Making this change now.
imsim/photon_ops.py
Outdated
# positions the photons before they are pooled to be processed together. | ||
if self.shift_photons and self.image_pos is not None: | ||
photon_array.x += self.image_pos.x | ||
photon_array.y += self.image_pos.y |
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.
Per my other comment, these should presumably also shift by stamp_center, not image_pos. Likely not a big difference, but might as well use the correct shift.
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.
Should this also be done at the end of applyTo? e.g.
Lines 111 to 112 in a4c2d97
photon_array.x -= self.image_pos.x | |
photon_array.y -= self.image_pos.y |
main
as it is now.
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.
Yes. I think so.
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.
This is the last thing on my list. It means changing the API to RubinOptics and RubinDiffractionOptics. I think normal use is always through photon op registrations via the photon_op_type
decorator and deserialize_*
functions, which wouldn't need to change, but at least the tests in test_photon_ops.py do directly init the photon operators themselves. Is that ok to change?
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 if we preserve the user-facing code (i.e. how the config file specifies things), then it's ok to make changes to the implementation, even if these are technically API changes. But perhaps @jchiang87 or @cwwalter might want to weigh in about how strictly we want to preserve backwards-compatibility of the Python classes/functions.
tests/test_image.py
Outdated
help="Similar to -k of pytest / unittest: restrict tests to tests starting with the specified prefix.", | ||
default="test_", | ||
) | ||
args = parser.parse_args() |
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 guess if you find it useful, go ahead and keep it. But if you were just copying from that file, I don't think this is necessary to keep.
imsim/photon_ops.py
Outdated
|
||
The transform takes 2 vectors of shape (n,) and returns | ||
a column major vector of shape (n,3). | ||
""" | ||
|
||
def __init__(self, local_wcs, icrf_to_field, sky_pos): | ||
def __init__(self, local_wcs, icrf_to_field, img_wcs): |
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 this doesn't need local_wcs anymore. If we're breaking the API (with the change in the last parameter), might as well clean it up and remove local_wcs as well.
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. This also leaves some of the photon_velocity
methods in RubinOptics
, RubinDiffraction
and RubinDiffractionOptics
with unnecessary local_wcs
and, now I look at them, also rng
. Would you prefer those left alone or removed as well?
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.
Might as well clean up all the obsolete API. If any of them seem like user-facing code, we should make this a deprecation rather than completely break old code. But I think most of these functions are internal, not user facing, so it should be ok.
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 forgot to mention this in the meeting! Yes, everything looks to be internal to the photon ops themselves. rng
can't be removed though, as it turns out, or it breaks RubinDiffractionOptics. Otherwise, tidied up as requested.
Co-authored-by: Mike Jarvis <[email protected]>
…thods in photon_ops.py.
Assuming tests pass, that should be everything above. I've included changes to I'll move on to seeing if I can make the old photon ops tests match the new ones as suggested. |
I've just created PR #484 which corrects the photon op tests to be self-consistent. There were actually a couple of inconsistencies in the tests here too, but working through them now means everything should be in alignment pre- and post-photon pooling. I hope this means that once #484 is merged in, this can be, too. |
No description provided.