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

add pixel scale factor to metadata and API translation #2752

Merged
merged 9 commits into from
Mar 25, 2024

Conversation

gibsongreen
Copy link
Contributor

@gibsongreen gibsongreen commented Mar 13, 2024

Description

This pull request is to address storing the scale factor in metadata so that data can be "translated" between surface brightness and flux units. In addition, to add internal API functionality to translate from MJy/sr <-> Jy/pix.

Screen.Recording.2024-03-19.at.1.30.07.PM.mov

Change log entry

  • Is a change log needed? If yes, is it added to CHANGES.rst? If you want to avoid merge conflicts,
    list the proposed change log here for review and add to CHANGES.rst before merge. If no, maintainer
    should add a no-changelog-entry-needed label.

Checklist for package maintainer(s)

This checklist is meant to remind the package maintainer(s) who will review this pull request of some common things to look for. This list is not exhaustive.

  • Are two approvals required? Branch protection rule does not check for the second approval. If a second approval is not necessary, please apply the trivial label.
  • Do the proposed changes actually accomplish desired goals? Also manually run the affected example notebooks, if necessary.
  • Do the proposed changes follow the STScI Style Guides?
  • Are tests added/updated as required? If so, do they follow the STScI Style Guides?
  • Are docs added/updated as required? If so, do they follow the STScI Style Guides?
  • Did the CI pass? If not, are the failures related?
  • Is a milestone set? Set this to bugfix milestone if this is a bug fix and needs to be released ASAP; otherwise, set this to the next major release milestone. Bugfix milestone also needs an accompanying backport label.
  • After merge, any internal documentations need updating (e.g., JIRA, Innerspace)?

@github-actions github-actions bot added cubeviz plugin Label for plugins common to multiple configurations labels Mar 13, 2024
@gibsongreen gibsongreen added this to the 3.9 milestone Mar 13, 2024
Copy link

codecov bot commented Mar 13, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.70%. Comparing base (9edd445) to head (bf012bd).
Report is 12 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2752      +/-   ##
==========================================
- Coverage   88.70%   88.70%   -0.01%     
==========================================
  Files         108      108              
  Lines       16305    16374      +69     
==========================================
+ Hits        14464    14524      +60     
- Misses       1841     1850       +9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

CHANGES.rst Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

So far, none of the diff is user-facing, so it does not need a change log.

@gibsongreen gibsongreen marked this pull request as ready for review March 19, 2024 17:40
@@ -159,7 +160,7 @@ def user_api(self):
expose = ['function', 'spatial_subset', 'aperture',
'add_results', 'collapse_to_spectrum',
'wavelength_dependent', 'reference_wavelength',
'aperture_method']
'aperture_method', 'translate_units']
Copy link
Member

Choose a reason for hiding this comment

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

I'd vote to not expose this to the user yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The list name makes more sense now, will do and make a note of it.

Copy link
Contributor Author

@gibsongreen gibsongreen Mar 19, 2024

Choose a reason for hiding this comment

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

@kecnry how do I hide it from the user, but still enable it to be callable?

Copy link
Member

Choose a reason for hiding this comment

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

remove it from this list, and either access the plugin object directly (if you already have the user API object, just call ._obj on it to get to the actual plugin object).

collapsed_spec._data *= 10e6

# spectral_cube.meta['_pixel_scale_factor'] / 1, where 1 = default scale factor
collapsed_spec._data *= spectral_cube.meta['_pixel_scale_factor']
Copy link
Member

Choose a reason for hiding this comment

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

I think the scale factors will need to be stored in collapsed_spec instead of spectral_cube, since a single spectral cube can be used to extract multiple spectra with different subsets/apertures.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right, that makes a lot more sense instead of the flux data!

Comment on lines 560 to 561
elif collapsed_spec._unit != u.Jy / u.pix and collapsed_spec._unit != u.MJy / u.sr:
raise ValueError(f"Units '{collapsed_spec._unit}' are not MJy/sr nor Jy/pix.")
Copy link
Member

Choose a reason for hiding this comment

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

can this not be generalized to any flux or surface brightness units?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should be doable and generalizing here is a better idea

Comment on lines 538 to 542
# per https://jwst-docs.stsci.edu/jwst-near-infrared-camera/nircam-performance/nircam-absolute-flux-calibration-and-zeropoints # noqa
# MJy/sr is default, to measure photometry in MJy, convert the image to units
# of MJy/pixel by multiplying by the average area of a pixel in sr, a constant
# provided in the FITS header keyword PIXAR_SR
collapsed_spec._data *= spectral_cube.meta['PIXAR_SR']
Copy link
Member

Choose a reason for hiding this comment

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

should this, and the original unit, be absorbed into the scale factor so we can just multiply or divide by a quantity?

@gibsongreen gibsongreen added the no-changelog-entry-needed changelog bot directive label Mar 19, 2024
@@ -343,6 +345,11 @@ def collapse_to_spectrum(self, add_data=True, **kwargs):
sender=self)
self.hub.broadcast(snackbar_message)

# per https://jwst-docs.stsci.edu/jwst-near-infrared-camera/nircam-performance/nircam-absolute-flux-calibration-and-zeropoints # noqa
if 'PIXAR_SR' in spectral_cube.meta:
pix_scale_factor = self.aperture.scale_factor * 10e6 * spectral_cube.meta['PIXAR_SR']
Copy link
Member

Choose a reason for hiding this comment

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

where does the 10^6 come from? Does that make assumptions on units (converting between MJy and Jy maybe)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had made the assumption based on conversations from the hack day and the meetings with Patrick that yes MJy to Jy would need scientific notation conversion, I'll remove it from here and the specification in the translate_units() function

Copy link
Member

Choose a reason for hiding this comment

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

it would, but we're going to want to have the flexibility to change between any prefix. Ideally this would take the new units, but if that's too difficult, we can do that as a followup and just assume the same units (except the sr) otherwise.

Comment on lines 531 to 538
# MJy/sr -> Jy/pix
if collapsed_spec._unit == u.MJy / u.sr:
collapsed_spec._data *= collapsed_spec.meta['_pixel_scale_factor']
collapsed_spec._unit = u.Jy / u.pix
# Jy/pix -> MJy/sr
elif collapsed_spec._unit == u.Jy / u.pix:
collapsed_spec._data /= collapsed_spec.meta['_pixel_scale_factor']
collapsed_spec._unit = u.MJy / u.sr
Copy link
Member

Choose a reason for hiding this comment

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

I still think we want this to be generalized to any surface brightness -> flux units, basically just adding or removing the steradians but keeping the same base units otherwise (which probably means we don't need the 10^6 in the factor).

Comment on lines 532 to 536
u.MJy / u.sr: u.MJy / u.pix,
u.Jy / u.sr: u.Jy / u.pix,
u.erg / (u.cm**2*u.s*u.AA*u.sr): u.erg / (u.cm**2*u.s*u.AA),
u.erg / (u.s*u.cm**2*u.sr): u.erg / (u.s*u.cm**2),
u.W / (u.m**2*u.Hz*u.sr): u.W / (u.m**2*u.Hz)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The dictionary will probably have to go when translating to any sb/flux. If there's eventually a drop down for the user to select their desired units, the path forward for this becomes clear.

Copy link
Member

Choose a reason for hiding this comment

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

can we just multiply or divide by u.sr directly?

@@ -343,6 +345,11 @@ def collapse_to_spectrum(self, add_data=True, **kwargs):
sender=self)
self.hub.broadcast(snackbar_message)

# per https://jwst-docs.stsci.edu/jwst-near-infrared-camera/nircam-performance/nircam-absolute-flux-calibration-and-zeropoints # noqa
if 'PIXAR_SR' in spectral_cube.meta:
Copy link
Member

Choose a reason for hiding this comment

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

what happens when 'PIXAR_SR' does not exist? What if instead we just use spectral_cube.meta.get('PIXAR_SR', 1.0)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I updated this instead of the if statement, I think we'd need to calculate the average area of a pixel if PIXAR_SR doesn't exist

Comment on lines 532 to 536
u.MJy / u.sr: u.MJy / u.pix,
u.Jy / u.sr: u.Jy / u.pix,
u.erg / (u.cm**2*u.s*u.AA*u.sr): u.erg / (u.cm**2*u.s*u.AA),
u.erg / (u.s*u.cm**2*u.sr): u.erg / (u.s*u.cm**2),
u.W / (u.m**2*u.Hz*u.sr): u.W / (u.m**2*u.Hz)
Copy link
Member

Choose a reason for hiding this comment

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

can we just multiply or divide by u.sr directly?

Comment on lines 347 to 349
# per https://jwst-docs.stsci.edu/jwst-near-infrared-camera/nircam-performance/nircam-absolute-flux-calibration-and-zeropoints # noqa
pix_scale_factor = self.aperture.scale_factor * spectral_cube.meta.get('PIXAR_SR', 1.0)
collapsed_spec.meta['_pixel_scale_factor'] = pix_scale_factor
Copy link
Member

Choose a reason for hiding this comment

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

I'm torn whether this belong in or outside of the if add_data... but might be useful for comparing if its outside (and then just in case anyone passes that data back into jdaviz)

Suggested change
# per https://jwst-docs.stsci.edu/jwst-near-infrared-camera/nircam-performance/nircam-absolute-flux-calibration-and-zeropoints # noqa
pix_scale_factor = self.aperture.scale_factor * spectral_cube.meta.get('PIXAR_SR', 1.0)
collapsed_spec.meta['_pixel_scale_factor'] = pix_scale_factor
# per https://jwst-docs.stsci.edu/jwst-near-infrared-camera/nircam-performance/nircam-absolute-flux-calibration-and-zeropoints # noqa
pix_scale_factor = self.aperture.scale_factor * spectral_cube.meta.get('PIXAR_SR', 1.0)
collapsed_spec.meta['_pixel_scale_factor'] = pix_scale_factor

Copy link
Member

Choose a reason for hiding this comment

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

oh but this needs to be done before add_results_from_plugin, right now the metadata entry isn't showing up when accessing through viz.get_data(...).

@@ -519,3 +524,13 @@ def _live_update(self, event={}):
for mark in self.marks.values():
mark.update_xy(sp.spectral_axis.value, sp.flux.value)
mark.visible = True

def translate_units(self, collapsed_spec):
Copy link
Member

Choose a reason for hiding this comment

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

this is probably fine for this PR to demonstrate the translation, but when we connect a switch, we'll want to have the ability to change the entry already loaded in the data-collection (preferably in-place without having to re-parse).

Copy link
Member

@kecnry kecnry left a comment

Choose a reason for hiding this comment

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

LGTM - definitely will want science verification on a real workflow but that can be done once the whole thing is functional (in the planned follow-up efforts). Thanks!

@gibsongreen
Copy link
Contributor Author

LGTM - definitely will want science verification on a real workflow but that can be done once the whole thing is functional (in the planned follow-up efforts). Thanks!

I most definitely agree, thank you for all of your productive input!

Copy link
Contributor

@haticekaratay haticekaratay left a comment

Choose a reason for hiding this comment

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

Looks good to me! Thanks for your work!

@gibsongreen gibsongreen added the skip-changelog-checks changelog bot directive label Mar 22, 2024
@kecnry kecnry merged commit d007a4b into spacetelescope:main Mar 25, 2024
18 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cubeviz no-changelog-entry-needed changelog bot directive plugin Label for plugins common to multiple configurations Ready for final review skip-changelog-checks changelog bot directive
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants