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

Glue unit conversion in Specviz #2048

Merged
merged 19 commits into from
Apr 4, 2023

Conversation

pllim
Copy link
Contributor

@pllim pllim commented Feb 28, 2023

Description

This pull request is to continue the work of the following but integrating glue unit conversion into Jdaviz instead of a concept notebook. This PR is part of a larger effort and will be merged into a temporary development branch until the full refactor is complete - not all plugins/tests are expected to work/pass yet, but reviewers please do note any issues so that we can add to the list of things to check before eventual merge into main.

The goal of this individual PR is to create the concept of a "global display unit" in jdaviz in the old unit conversion plugin and sync state between that and the internal glue viewer's display units. Once the unit is changed, other plugins/behaviors are expected to break and will be updated in follow-up efforts.

This builds on:

Closes #895
Closes #1187
Closes #1260

TODO

  • Fix traceback when setting viewer.state.x_display_unit = "um": ValueError: value um is not in valid choices: [''] (I see the same error even when I apply Jesse's original converter class from POC: Notebook showing glue unit conversion in Specviz #2022)
  • Resolve confusion at https://github.com/glue-viz/glue/pull/2296/files#r1123283337
  • Fix tests.
  • Handle mention of "TODO(?) unit conversion..." in code comments
  • Re-enable unit conversion plugin and refactor it. Update docs.
  • Fix Unit Conversion dropdown and displays.
  • What about mouseover? Wonky in Specviz2d.
  • What about uncertainty?
  • What about mask?
  • What about redshift?
  • Add use case from new concept notebook as unit test.
  • Port over glue test from glue/viewers/profile/qt/tests/test_data_viewer.py upstream.
  • Check all the vizes.

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.
  • After merge, any internal documentations need updating (e.g., JIRA, Innerspace)?

@pllim pllim added this to the 3.4 milestone Feb 28, 2023
@github-actions github-actions bot added documentation Explanation of code and concepts imviz specviz labels Feb 28, 2023
@pllim
Copy link
Contributor Author

pllim commented Mar 2, 2023

Took me a while to make this work, so I need to write this down:

viewer.state.__class__.x_display_unit.get_choices(viewer.state)

pllim and others added 4 commits March 28, 2023 21:31
Co-authored-by: Jesse Averbukh <javerbukh@gmail.com>
still not quite working yet
[ci skip] [rtd skip]
and add change log. [ci skip] [rtd skip]
but still needs unreleased glue

[ci skip] [rtd skip]
@pllim pllim force-pushed the sticky-unit-conversion branch from 29d8b96 to f64890b Compare March 29, 2023 01:31
pllim added 3 commits March 28, 2023 21:43
[ci skip] [rtd skip]
[ci skip] [rtd skip]
return [u.Unit(unit).name
if u.Unit(unit) == u.Unit("Angstrom")
else u.Unit(unit).long_names[0] if (
hasattr(u.Unit(unit), "long_names") and len(u.Unit(unit).long_names) > 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.

Note: Long name does not round-trip well with the display axis stuff. Let's not use it.


# Get local units.
locally_defined_flux_units = ['Jy', 'mJy', 'uJy',
'W / (m2 Hz)',
'eV / (s m2 Hz)',
'erg / (s cm2)',
'erg / (s cm2 um)',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note: This fails unit conversion in astropy. Do we really need this?

@@ -135,12 +133,10 @@ def test_region_from_subset_3d(cubeviz_helper):


def test_region_from_subset_profile(cubeviz_helper, spectral_cube_wcs):
data = Data(flux=np.ones((128, 128, 256)), label='Test 1D Flux', coords=spectral_cube_wcs)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For the glue display axis to initialize properly, we cannot hack-load like this anymore.

@kecnry
Copy link
Member

kecnry commented Mar 29, 2023

the latest commit updates the implementation to make use of callbacks (so manually calling set_plot_axes is no longer required) and plugin dropdown components (so clicking apply is no longer necessary) and syncs the state between the UI, plugin API, and glue-state. Note that this is still somewhat hardcoded to the single-spectrum-viewer specviz case. We'll either need to generalize the code or disable across other configs until that work can be done.

Screen.Recording.2023-03-29.at.1.47.50.PM.mov

self.spectrum_viewer.set_plot_axes()
if x_unit != self.spectral_unit.selected:
x_u = u.Unit(x_unit)
self.spectral_unit.choices = [x_unit] + create_spectral_equivalencies_list(x_u)
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 overkill to recompute each time - can we get away with only computing it once?

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 started out with hardcoding it altogether but that didn't behave well. You think we can get away with only doing it once, especially in cases like Specviz2d with extraction, or Cubeviz with collapse? If so, when should it trigger?

Copy link
Member

Choose a reason for hiding this comment

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

for the spectral axis, we probably can get away with it (except for the pixel case which we might need to handle separately). For the flux, maybe not - we'll at least need to trigger on changes to reference data as well as changes to the spectral units 🤔 . For now this is the most conservative and I don't expect it to cause any noticeable lagging.

@kecnry kecnry force-pushed the sticky-unit-conversion branch from 03412ba to dd329aa Compare March 29, 2023 19:34
@kecnry
Copy link
Member

kecnry commented Mar 31, 2023

Agreed, I think the simplest way is to force the UI list to our "preferred" representation - the API will still accept any valid string that can be mapped to the choices.

@rosteen
Copy link
Collaborator

rosteen commented Mar 31, 2023

Next two things I've noticed while testing plugins:

  1. It looks like changing from um to Hz and then fitting a constant+gaussian works, but fitting a linear+gaussian fails because the slope parameter of the linear model is still estimated in MJy / sr / um.
  2. While displaying with frequency units, spectral lines will still be plotted at the numerical values corresponding to their wavelengths rather than having that converted to freqency.

@rosteen
Copy link
Collaborator

rosteen commented Mar 31, 2023

Ah, and one more: with spectral units converted to frequency, selecting a spectral region in Line Analysis fails with the following traceback:

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
File ~/opt/anaconda3/envs/viz_dev/lib/python3.11/site-packages/ipywidgets/widgets/widget.py:773, in Widget._handle_msg(self, msg)
    771         if 'buffer_paths' in data:
    772             _put_buffers(state, data['buffer_paths'], msg['buffers'])
--> 773         self.set_state(state)
    775 # Handle a state request.
    776 elif method == 'request_state':

File ~/opt/anaconda3/envs/viz_dev/lib/python3.11/site-packages/ipywidgets/widgets/widget.py:650, in Widget.set_state(self, sync_data)
    645         self._send(msg, buffers=echo_buffers)
    647 # The order of these context managers is important. Properties must
    648 # be locked when the hold_trait_notification context manager is
    649 # released and notifications are fired.
--> 650 with self._lock_property(**sync_data), self.hold_trait_notifications():
    651     for name in sync_data:
    652         if name in self.keys:

File ~/opt/anaconda3/envs/viz_dev/lib/python3.11/contextlib.py:144, in _GeneratorContextManager.__exit__(self, typ, value, traceback)
    142 if typ is None:
    143     try:
--> 144         next(self.gen)
    145     except StopIteration:
    146         return False

File ~/opt/anaconda3/envs/viz_dev/lib/python3.11/site-packages/traitlets/traitlets.py:1502, in HasTraits.hold_trait_notifications(self)
   1500 for changes in cache.values():
   1501     for change in changes:
-> 1502         self.notify_change(change)

File ~/opt/anaconda3/envs/viz_dev/lib/python3.11/site-packages/ipywidgets/widgets/widget.py:701, in Widget.notify_change(self, change)
    698     if name in self.keys and self._should_send_property(name, getattr(self, name)):
    699         # Send new state to front-end
    700         self.send_state(key=name)
--> 701 super().notify_change(change)

File ~/opt/anaconda3/envs/viz_dev/lib/python3.11/site-packages/traitlets/traitlets.py:1517, in HasTraits.notify_change(self, change)
   1515 def notify_change(self, change):
   1516     """Notify observers of a change event"""
-> 1517     return self._notify_observers(change)

File ~/opt/anaconda3/envs/viz_dev/lib/python3.11/site-packages/traitlets/traitlets.py:1564, in HasTraits._notify_observers(self, event)
   1561 elif isinstance(c, EventHandler) and c.name is not None:
   1562     c = getattr(self, c.name)
-> 1564 c(event)

File ~/projects/jdaviz/jdaviz/configs/specviz/plugins/line_analysis/line_analysis.py:338, in LineAnalysis._calculate_statistics(self, *args, **kwargs)
    336 else:
    337     spectrum = extract_region(full_spectrum, sr, return_single_spectrum=True)
--> 338     sr_lower = spectrum.spectral_axis[spectrum.spectral_axis.value >= sr.lower.value][0]
    339     sr_upper = spectrum.spectral_axis[spectrum.spectral_axis.value <= sr.upper.value][-1]
    341 # compute continuum

File ~/opt/anaconda3/envs/viz_dev/lib/python3.11/site-packages/astropy/units/quantity.py:1272, in Quantity.__getitem__(self, key)
   1269     return self._new_view(self.view(np.ndarray)[key], self.unit[key])
   1271 try:
-> 1272     out = super().__getitem__(key)
   1273 except IndexError:
   1274     # We want zero-dimensional Quantity objects to behave like scalars,
   1275     # so they should raise a TypeError rather than an IndexError.
   1276     if self.isscalar:

IndexError: index 0 is out of bounds for axis 0 with size 0

@pllim
Copy link
Contributor Author

pllim commented Mar 31, 2023

I wonder if plugins should disable themselves if they detect the data unit is different from display units... 👀

@kecnry
Copy link
Member

kecnry commented Mar 31, 2023

Once this PR is in, we'll go through each plugin one-by-one to update them before eventually merging the whole thing into main. I expect most plugins to currently break once the units are changed.

@rosteen
Copy link
Collaborator

rosteen commented Mar 31, 2023

"Once the unit is changed, other plugins/behaviors are expected to break and will be updated in follow-up efforts." - almost like that was in the description 😆 . Still, not bad to catalog what's breaking.

@kecnry
Copy link
Member

kecnry commented Mar 31, 2023

Still, not bad to catalog what's breaking.

By all means, feel free, but don't feel like you need to be thorough - that will lead you to insanity! 😂

docs/specviz/plugins.rst Outdated Show resolved Hide resolved
"metadata": {},
"outputs": [],
"source": [
"viewer.state.x_display_unit = \"GHz\""
Copy link
Collaborator

Choose a reason for hiding this comment

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

This fails now, seems like the notebook should refer to Hz instead of GHz:

File ~/projects/jdaviz/jdaviz/core/template_mixin.py:674, in UnitSelectPluginComponent._selected_changed(self, event)
    672 if new_u not in self.unit_choices:
    673     self.selected = event['old']
--> 674     raise ValueError(f"{event['new']} not one of {self.labels}, reverting selection to {event['old']}")  # noqa
    676 # convert to default string representation from the valid choices
    677 ind = self.unit_choices.index(new_u)

ValueError: GHz not one of ['Angstrom', 'Hz', 'erg', 'nm', 'um', 'Ci', 'J', 'Ry', 'cm', 'eV', 'k', 'm'], reverting selection to 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 string compare stuff is annoying like that, you have to include all the possible prefixes or it is going to fail.

I wonder if @astrofrog can make it less annoying but if not, we need to use the "include prefix" option in some of these base 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 pushed a commit which now allows setting any unit accepted by glue via the API. If that unit does not appear in the list of dropdown choices, it will be appended to the end of the available list for the remainder of the session.

For example:

uc = specviz.plugins['Unit Conversion']
uc.open_in_tray()
print(uc.spectral_unit.choices)  #  ['Angstrom', 'Hz', 'erg', 'nm', 'um', 'Ci', 'J', 'Ry', 'cm', 'eV', 'k', 'm']
uc.spectral_unit = 'GHz'
print(uc.spectral_unit.selected)  # GHz
print(uc.spectra_unit.choices)  # ['Angstrom', 'Hz', 'erg', 'nm', 'um', 'Ci', 'J', 'Ry', 'cm', 'eV', 'k', 'm', 'GHz']

Copy link
Collaborator

@rosteen rosteen left a comment

Choose a reason for hiding this comment

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

I left one more comment on the notebook, but I'm going to go ahead and approve. Code looks codely, plugins will be dealt with after this is merged.

* in which case the plugin select component appends that option to its curated list of options going forward.  This allows supporting a large number of options/prefixes without having to show them all in the dropdown.
Copy link
Contributor

@javerbukh javerbukh left a comment

Choose a reason for hiding this comment

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

Sounds like most existing bugs are documented and we are moving to a development branch, so I think this is good to go!

@kecnry kecnry merged commit 63f23d2 into spacetelescope:dev-display-units Apr 4, 2023
kecnry added a commit that referenced this pull request Apr 4, 2023
* basic app-wide display unit in specviz (not all plugins are updated yet)
* unit-aware select component which maps to glue-supported unit strings
* implement use_display_units option for get_data, get_subsets

Co-authored-by: Jesse Averbukh <javerbukh@gmail.com>
Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>
kecnry added a commit that referenced this pull request Apr 17, 2023
* basic app-wide display unit in specviz (not all plugins are updated yet)
* unit-aware select component which maps to glue-supported unit strings
* implement use_display_units option for get_data, get_subsets

Co-authored-by: Jesse Averbukh <javerbukh@gmail.com>
Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>
kecnry added a commit that referenced this pull request Apr 18, 2023
* basic app-wide display unit in specviz (not all plugins are updated yet)
* unit-aware select component which maps to glue-supported unit strings
* implement use_display_units option for get_data, get_subsets

Co-authored-by: Jesse Averbukh <javerbukh@gmail.com>
Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>
kecnry added a commit that referenced this pull request Apr 19, 2023
* basic app-wide display unit in specviz (not all plugins are updated yet)
* unit-aware select component which maps to glue-supported unit strings
* implement use_display_units option for get_data, get_subsets

Co-authored-by: Jesse Averbukh <javerbukh@gmail.com>
Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>
kecnry added a commit that referenced this pull request May 4, 2023
* basic app-wide display unit in specviz (not all plugins are updated yet)
* unit-aware select component which maps to glue-supported unit strings
* implement use_display_units option for get_data, get_subsets

Co-authored-by: Jesse Averbukh <javerbukh@gmail.com>
Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>
rosteen pushed a commit to rosteen/jdaviz that referenced this pull request May 11, 2023
* basic app-wide display unit in specviz (not all plugins are updated yet)
* unit-aware select component which maps to glue-supported unit strings
* implement use_display_units option for get_data, get_subsets

Co-authored-by: Jesse Averbukh <javerbukh@gmail.com>
Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>
rosteen pushed a commit to rosteen/jdaviz that referenced this pull request May 15, 2023
* basic app-wide display unit in specviz (not all plugins are updated yet)
* unit-aware select component which maps to glue-supported unit strings
* implement use_display_units option for get_data, get_subsets

Co-authored-by: Jesse Averbukh <javerbukh@gmail.com>
Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>
rosteen added a commit that referenced this pull request Jun 13, 2023
* Added .ico and .svg files

* app-wide display unit in specviz (#2048)

* basic app-wide display unit in specviz (not all plugins are updated yet)
* unit-aware select component which maps to glue-supported unit strings
* implement use_display_units option for get_data, get_subsets

Co-authored-by: Jesse Averbukh <javerbukh@gmail.com>
Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>

* bump glue-core to necessary version for display units

* change PR number in changelog to main PR

* Display units line analysis (#2128)

* emit event when display unit changed
* update line analysis for unit changes

* cubeviz/slice plugin unit conversion support

(we might want to generalize some of this logic more into the mark's _update_data when adding support for spectral lines as well)

* Display units support for markers plugin (#2130)

* update markers plugin for display units
* move unit-updating logic to mark itself
* LineUncertainties to be unit-aware
* fix support for markers in cubeviz

* display units: fix failing tests (#2132)

* fix error raised when spectrum uncertainty is None
* fix RTD build failure because of missing mixin available in import
* fix test setting display unit now that um is preferred to micron
* add disabled unit conversion plugin to mosviz
* avoid unit-conversion error in cubeviz tests
* bump versions of glue/glue-jupyter
* fix deg intialization in cubeviz slice plugin
* add LinesAutoUnit to __all__ so RTD can find it
* add use_display_units kwarg to get_spectral_regions
* fix setting display units for unitless data
* Apply suggestions from code review

Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com>

* Display units: line lists (#2148)

* BaseSpectrumVerticalLine to inherit unit-support from PluginMark
* convert units on internal rest value
* code cleanup

* remove unit conversion plugin from all bug specviz

* for initial implementation - eventually we'll want to implement across all plugins/viewers

* get_display_unit fallback for configs without unit conversion plugin

* Update glue-core dependency

* Update Subset Tools plugin to use display units (#2195)

* bump glue-core to necessary version for display units

* cubeviz/slice plugin unit conversion support

(we might want to generalize some of this logic more into the mark's _update_data when adding support for spectral lines as well)

* display units: fix failing tests (#2132)

* fix error raised when spectrum uncertainty is None
* fix RTD build failure because of missing mixin available in import
* fix test setting display unit now that um is preferred to micron
* add disabled unit conversion plugin to mosviz
* avoid unit-conversion error in cubeviz tests
* bump versions of glue/glue-jupyter
* fix deg intialization in cubeviz slice plugin
* add LinesAutoUnit to __all__ so RTD can find it
* add use_display_units kwarg to get_spectral_regions
* fix setting display units for unitless data
* Apply suggestions from code review

Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com>

* remove unit conversion plugin from all bug specviz

* for initial implementation - eventually we'll want to implement across all plugins/viewers

* Working on unit conversion handling in subset plugin

* Get subset updating working in non-default units

* Add changelog

* Update jdaviz/configs/default/plugins/subset_plugin/subset_plugin.vue

Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>

---------

Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>
Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com>

* allow downstream apps to set what classes are considered native marks

* Fix unit conversion for PluginMarks and y-limits (#2215)

* Fix unit conversion for PluginMarks and y-limits

* Only use equivalency if it's a spec viewer

* Store wavelength unit on data update

* Remove redundant line

* Better check in marks

* Replace subset_to_apply in docs where possible (#2223)

* Replace subset_to_apply in docs where possible (#2223)

* Avoid trying to convert units of empty marks arrays

* Add open method to automatically detect config and load data

* Update demo notebooks

* Codestyle

* Add autoconfig test coverage

* Revert "Update demo notebooks"

This reverts commit cc513b3.

* Add mention of open to relevant example notebooks

* Prepare to support open via cli

* Remove the need to open file twice for autoconfig detection

* Fix Helper vs App Docstring

* TST: Change PIP_EXTRA_INDEX_URL
because packages moved where they upload nightly builds.

* Display units: model fitting (#2216)

* model component compatibility based on display units
* equation validity based on display units
* allow re-estimating model parameters to update compat checks
* test coverage
* get_data(use_display_units) to pass spectral_density equivalency
* handle whitespace in model equation

* Add clarity for kwargs

* plugin results: support overwriting when data loaded in multiple viewers (#2222)

* reverts removal of call to set_plot_axes when loading data into viewer (#2235)

* fixes a bug in the axes labels on cube viewers in cubeviz as well as setting the correct attributes in lcviz

* Subsume failing identifier test into autoconfig test

* Update subset plugin UI (#2234)

* Update subset plugin UI

* Apply suggestions from code review

Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>

---------

Co-authored-by: Kyle Conroy <kyleconroy@gmail.com>

* Changelog

* Add docs page to explain how to create jdaviz-readable products (#2228)

* Add page for data products

* Update index

* Fix title

* Capital letters

* Address first review comments

* Edit format

* Apply suggestions from code review

Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com>

* Including reference in import_data

* Update docs/create_products.rst

* Update docs/create_products.rst

---------

Co-authored-by: Camilla Pacifici <cpacifici@stsci.edu>
Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com>
Co-authored-by: Ricky O'Steen <39831871+rosteen@users.noreply.github.com>

* FEAT: Load annulus from file
and allow IMPORT DATA to load reg files.

Annulus support provided by glue-viz/glue#2403 and glue-viz/glue-astronomy#92

Add test for exception.

Bump minimum requirements for glue-core and glue-astronomy.

* disallow gaussian smooth output as input

* BUG: Fix ellipse translation
in app.get_subsets()

* DOC: Use pydata-sphinx-theme (#2243)

* DOC: Use pydata-sphinx-theme
that has dark mode, modern design, and mobile friendly

DOC: No longer need tomli

DOC: Now requires sphinx-astropy 1.9.1

* Add cards to index page
with icons

* Remove iframe hardcoding so it scales
in mobile mode

* DOC: Insert small logo next to title
instead of a giant logo above the title

* Add app method to simplify spectral subset (#2237)

* Add app method to simplify spectral subset

Add simplify button to subset plugin

* Fix xor bug exposed by simplify button

* Fix style checks

* Remove print statements

* Add tooltip to simplify button

* Make button appear only if the subset can be simplified

* Make simplify button appear only when applicable

* Apply suggestions from code review

Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com>

* Update changes file

---------

Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com>

* Fix missed conflict

---------

Co-authored-by: Jennifer Kotler <jkotler@esme.stsci.edu>
Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com>
Co-authored-by: Jesse Averbukh <javerbukh@gmail.com>
Co-authored-by: Ricky O'Steen <rosteen@stsci.edu>
Co-authored-by: Ricky O'Steen <39831871+rosteen@users.noreply.github.com>
Co-authored-by: Duy Nguyen <duytnguyendtn.open@gmail.com>
Co-authored-by: Camilla Pacifici <camilla.pacifici@gmail.com>
Co-authored-by: Camilla Pacifici <cpacifici@stsci.edu>
@pllim pllim deleted the sticky-unit-conversion branch July 29, 2024 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants