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

[BUG] Mosviz: Model Fitting doesn't work in Mosviz #752

Open
PatrickOgle opened this issue Jul 30, 2021 · 7 comments
Open

[BUG] Mosviz: Model Fitting doesn't work in Mosviz #752

PatrickOgle opened this issue Jul 30, 2021 · 7 comments
Labels
bug Something isn't working mosviz

Comments

@PatrickOgle
Copy link
Contributor

PatrickOgle commented Jul 30, 2021

Describe the bug
All attempts to fit a model using the Model Fitting plugin in Mosviz fail, for even
the simplest model (Constant1D), to either the full Dataset or a Subset. The following
traceback is generated:

IndexError                                Traceback (most recent call last)
~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/ipyvue/VueTemplateWidget.py in _handle_event(self, _, content, buffers)
     55                 getattr(self, 'vue_' + event)(data, buffers)
     56             else:
---> 57                 getattr(self, 'vue_' + event)(data)
     58 
     59 

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/jdaviz/configs/default/plugins/model_fitting/model_fitting.py in vue_model_fitting(self, *args, **kwargs)
    359         self._fitted_spectrum = fitted_spectrum
    360 
--> 361         self.vue_register_spectrum({"spectrum": fitted_spectrum})
    362         self.app.fitted_models[self.model_label] = fitted_model
    363 

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/jdaviz/configs/default/plugins/model_fitting/model_fitting.py in vue_register_spectrum(self, event)
    498             # Remove the actual Glue data object from the data_collection
    499             self.data_collection.remove(self.data_collection[label])
--> 500         self.data_collection[label] = spectrum
    501 
    502         self.app.add_data_to_viewer('spectrum-viewer', label)

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data_collection.py in __setitem__(self, key, data)
    391                 self.remove(existing_data)
    392 
--> 393         self.append(data)
    394 
    395     def __iter__(self):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data_collection.py in append(self, data)
     80                 s.register()
     81             msg = DataCollectionAddMessage(self, data)
---> 82             self.hub.broadcast(msg)
     83 
     84         self._sync_link_manager()

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/hub.py in broadcast(self, message)
    213             logging.getLogger(__name__).info("Broadcasting %s", message)
    214             for subscriber, handler in self._find_handlers(message):
--> 215                 handler(message)
    216 
    217     def __getstate__(self):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/jdaviz/app.py in _on_data_added(self, msg)
   1022             the new data.
   1023         """
-> 1024         self._link_new_data()
   1025         data_item = self._create_data_item(msg.data.label)
   1026         self.state.data_items.append(data_item)

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/jdaviz/app.py in _link_new_data(self)
    257                 continue
    258             else:
--> 259                 self.data_collection.add_link(LinkSame(wc_old[0], wc_new[0]))
    260                 break
    261 

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data_collection.py in add_link(self, links)
    160            instances, or a :class:`~glue.core.link_helpers.LinkCollection`
    161         """
--> 162         self._link_manager.add_link(links)
    163 
    164     def remove_link(self, links):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/link_manager.py in add_link(self, link, update_external)
    187                 self._external_links.append(link)
    188                 if update_external:
--> 189                     self.update_externally_derivable_components()
    190 
    191     @contract(link=ComponentLink)

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/link_manager.py in update_externally_derivable_components(self, data)
    240                 d = DerivedComponent(data, link)
    241                 comps[cid] = d
--> 242             data._set_externally_derivable_components(comps)
    243 
    244         # Now update information about pixel-aligned data

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data.py in _set_externally_derivable_components(self, derivable_components)
   1028         if self.hub:
   1029             msg = ExternallyDerivableComponentsChangedMessage(self)
-> 1030             self.hub.broadcast(msg)
   1031 
   1032     def _set_pixel_aligned_data(self, pixel_aligned_data):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/hub.py in broadcast(self, message)
    213             logging.getLogger(__name__).info("Broadcasting %s", message)
    214             for subscriber, handler in self._find_handlers(message):
--> 215                 handler(message)
    216 
    217     def __getstate__(self):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/viewers/common/viewer.py in _update_data(self, message)
    271                 else:
    272                     if layer_artist.layer is message.data:
--> 273                         layer_artist.update()
    274 
    275     def _update_subset(self, message):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue_jupyter/table/viewer.py in update(self)
    157 
    158     def update(self):
--> 159         self._refresh()
    160 
    161     def clear(self):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue_jupyter/table/viewer.py in _refresh(self)
    151 
    152     def _refresh(self):
--> 153         self._table_viewer.redraw()
    154 
    155     def redraw(self):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue_jupyter/table/viewer.py in redraw(self)
    204             self.widget_table.selections = [subset.label for subset in subsets]
    205             self.widget_table.selection_colors = [subset.style.color for subset in subsets]
--> 206         self.widget_table._update()
    207 
    208     def apply_filter(self):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue_jupyter/table/viewer.py in _update(self)
     29     def _update(self):
     30         self._update_columns()
---> 31         self._update_items()
     32         self.total_length = len(self)
     33         self.options = {**self.options, 'totalItems': self.total_length}

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue_jupyter/table/viewer.py in _update_items(self)
     68 
     69     def _update_items(self):
---> 70         self.items = self._get_items()
     71 
     72     @traitlets.default('items')

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue_jupyter/table/viewer.py in _get_items(self)
    127 
    128         view = slice(i1, i2)
--> 129         masks = {k.label: k.to_mask(view) for k in self.data.subsets}
    130 
    131         items = []

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue_jupyter/table/viewer.py in <dictcomp>(.0)
    127 
    128         view = slice(i1, i2)
--> 129         masks = {k.label: k.to_mask(view) for k in self.data.subsets}
    130 
    131         items = []

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/subset.py in to_mask(self, view)
    180 
    181         """
--> 182         return self.data.get_mask(self.subset_state, view=view)
    183 
    184     @contract(value=bool)

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data.py in get_mask(self, subset_state, view)
   1383     def get_mask(self, subset_state, view=None):
   1384         try:
-> 1385             return subset_state.to_mask(self, view=view)
   1386         except IncompatibleAttribute:
   1387             return get_mask_with_key_joins(self, self._key_joins, subset_state, view=view)

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/subset.py in to_mask(self, data, view)
    771     @contract(data='isinstance(Data)', view='array_view')
    772     def to_mask(self, data, view=None):
--> 773         x = data[self.att, view]
    774         result = (x >= self.lo) & (x <= self.hi)
    775         return result

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data.py in __getitem__(self, key)
    569                 raise IncompatibleAttribute(_k)
    570 
--> 571         return self.get_data(key, view=view)
    572 
    573     def _ipython_key_completions_(self):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data.py in get_data(self, cid, view)
   1362 
   1363         if view is not None:
-> 1364             result = comp[view]
   1365         else:
   1366             result = comp.data

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/component.py in __getitem__(self, key)
    196 
    197     def __getitem__(self, key):
--> 198         return self._link.compute(self._data, key)
    199 
    200 

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/component_link.py in compute(self, data, view)
    164 
    165         # First we get the values of all the 'from' components.
--> 166         args = [data[join_component_view(f, view)] for f in self._from]
    167 
    168         # We keep track of the original shape of the arguments

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/component_link.py in <listcomp>(.0)
    164 
    165         # First we get the values of all the 'from' components.
--> 166         args = [data[join_component_view(f, view)] for f in self._from]
    167 
    168         # We keep track of the original shape of the arguments

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data.py in __getitem__(self, key)
    569                 raise IncompatibleAttribute(_k)
    570 
--> 571         return self.get_data(key, view=view)
    572 
    573     def _ipython_key_completions_(self):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data.py in get_data(self, cid, view)
   1362 
   1363         if view is not None:
-> 1364             result = comp[view]
   1365         else:
   1366             result = comp.data

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/component.py in __getitem__(self, key)
    196 
    197     def __getitem__(self, key):
--> 198         return self._link.compute(self._data, key)
    199 
    200 

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/component_link.py in compute(self, data, view)
    164 
    165         # First we get the values of all the 'from' components.
--> 166         args = [data[join_component_view(f, view)] for f in self._from]
    167 
    168         # We keep track of the original shape of the arguments

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/component_link.py in <listcomp>(.0)
    164 
    165         # First we get the values of all the 'from' components.
--> 166         args = [data[join_component_view(f, view)] for f in self._from]
    167 
    168         # We keep track of the original shape of the arguments

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data.py in __getitem__(self, key)
    569                 raise IncompatibleAttribute(_k)
    570 
--> 571         return self.get_data(key, view=view)
    572 
    573     def _ipython_key_completions_(self):

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/data.py in get_data(self, cid, view)
   1362 
   1363         if view is not None:
-> 1364             result = comp[view]
   1365         else:
   1366             result = comp.data

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/component.py in __getitem__(self, key)
    196 
    197     def __getitem__(self, key):
--> 198         return self._link.compute(self._data, key)
    199 
    200 

~/miniconda3/envs/jwebbinar7/lib/python3.8/site-packages/glue/core/component_link.py in compute(self, data, view)
    167 
    168         # We keep track of the original shape of the arguments
--> 169         original_shape = args[0].shape
    170         logger.debug("shape of first argument: %s", original_shape)
    171 

IndexError: list index out of range

To Reproduce
Steps to reproduce the behavior:

  1. Go to Model Fitting
  2. Click on 1DSpectrum (or Subset)
  3. Add a constant model component 'C'
  4. Enter 'C' in the Model Equation Editor
  5. Press 'Fit'

Expected behavior
The model should be fitted and plotted in the spectrum viewer

Screenshots
N/A
Desktop (please complete the following information):

  • OS: OSX 10.15.7
  • Browser: safari
  • Jupyter: [run "jupyter --version"]
    jupyter core : 4.7.1
    jupyter-notebook : 6.4.0
    qtconsole : 5.1.1
    ipython : 7.25.0
    ipykernel : 6.0.3
    jupyter client : 6.1.12
    jupyter lab : not installed
    nbconvert : 6.1.0
    ipywidgets : 7.6.3
    nbformat : 5.1.3
    traitlets : 5.0.5

Package versions (please complete the following information):

macOS-10.15.7-x86_64-i386-64bit
Python 3.8.10 | packaged by conda-forge | (default, May 10 2021, 22:58:09)
[Clang 11.1.0 ]
Numpy 1.21.1
astropy 4.3
specutils 1.3
spectral-cube 0.5.0
pyyaml 5.4.1
click 8.0.1
asteval 0.9.25
idna 2.10
traitlets 5.0.5
bqplot 0.12.30
bqplot-image-gl 1.4.3
glue-core 1.0.1
glue-jupyter 0.7
glue-astronomy 0.2
echo 0.5
ipyvue 1.5.0
ipyvuetify 1.8.0
ipysplitpanes 0.2.0
ipygoldenlayout 0.4.0
voila 0.2.10
vispy 0.7.3
Jdaviz 1.2.dev365+ge29b827

Additional context (e.g. data files)
ERS NIRSpec MOS PRISM dataset with cutouts, jwst 1.1.0-processed

Model fitting works in Specviz and Cubeviz, but has never been attempted for an x1d in Mosviz.

🐱

@PatrickOgle PatrickOgle added bug Something isn't working mosviz labels Jul 30, 2021
@duytnguyendtn
Copy link
Collaborator

This traceback looks similar to one we caught in #762. We should revisit this issue once that is merged

@rosteen
Copy link
Collaborator

rosteen commented Aug 26, 2021

It looks like this error is because the linking code in app.py attempts to link to the first dataset when new data is loaded, which means it's trying to link the fitted spectrum to an image. @astrofrog pointed out recently that the linking there could cause problems and well, here's a problem!

I don't think this will be solved by #762, will probably require a couple extra lines of code in app.py to do the linking more intelligently. There's a comment that it "Link[s] to the first dataset with compatible coordinates", but it really links to the first dataset with any world coordinates. We should change it to do what the comment says!

@pllim
Copy link
Contributor

pllim commented Aug 26, 2021

Perhaps #811 can shed some light on this as well?

@rosteen
Copy link
Collaborator

rosteen commented Aug 26, 2021

Maybe. I just tested with #762 and auto-link set to False and this still errors, with a (I think) slightly different trace. This looks like the error is cause by the glue-astronomy translator trying to get the mask attribute of the subset I'm fitting, but I haven't delved too deep into it yet.

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
~/opt/anaconda3/envs/viz_dev/lib/python3.9/site-packages/ipyvue/VueTemplateWidget.py in _handle_event(self, _, content, buffers)
     55                 getattr(self, 'vue_' + event)(data, buffers)
     56             else:
---> 57                 getattr(self, 'vue_' + event)(data)
     58 
     59 

~/projects/jdaviz/jdaviz/configs/default/plugins/model_fitting/model_fitting.py in vue_model_fitting(self, *args, **kwargs)
    359         self._fitted_spectrum = fitted_spectrum
    360 
--> 361         self.vue_register_spectrum({"spectrum": fitted_spectrum})
    362         self.app.fitted_models[self.model_label] = fitted_model
    363 

~/projects/jdaviz/jdaviz/configs/default/plugins/model_fitting/model_fitting.py in vue_register_spectrum(self, event)
    500         self.data_collection[label] = spectrum
    501 
--> 502         self.app.add_data_to_viewer('spectrum-viewer', label)

~/projects/jdaviz/jdaviz/app.py in add_data_to_viewer(self, viewer_reference, data_path, clear_other_data, ext)
    677         if data_id is not None:
    678             data_ids.append(data_id)
--> 679             self._update_selected_data_items(viewer_item['id'], data_ids)
    680         else:
    681             raise ValueError(

~/projects/jdaviz/jdaviz/app.py in _update_selected_data_items(self, viewer_id, selected_items)
    992                                               viewer_id=viewer_id,
    993                                               sender=self)
--> 994             self.hub.broadcast(add_data_message)
    995 
    996         # Remove any deselected data objects from viewer

~/projects/glue/glue/core/hub.py in broadcast(self, message)
    213             logging.getLogger(__name__).info("Broadcasting %s", message)
    214             for subscriber, handler in self._find_handlers(message):
--> 215                 handler(message)
    216 
    217     def __getstate__(self):

~/projects/jdaviz/jdaviz/configs/default/plugins/line_lists/line_lists.py in _on_viewer_data_changed(self, msg)
     95 
     96         try:
---> 97             viewer_data = self.app.get_viewer('spectrum-viewer').data()
     98         except TypeError:
     99             warn_message = SnackbarMessage("Line list plugin could not retrieve data from viewer",

~/projects/jdaviz/jdaviz/configs/specviz/plugins/viewers.py in data(self, cls)
     69                         handler, _ = data_translator.get_handler_for(_class)
     70                         try:
---> 71                             layer_data = handler.to_object(layer_data,
     72                                                            statistic=statistic)
     73                         except IncompatibleAttribute:

~/opt/anaconda3/envs/viz_dev/lib/python3.9/site-packages/glue_astronomy/translators/spectrum1d.py in to_object(self, data_or_subset, attribute, statistic)
    142             return data_kwargs
    143 
--> 144         data_kwargs = parse_attributes(
    145             [attribute] if not hasattr(attribute, '__len__') else attribute)
    146 

~/opt/anaconda3/envs/viz_dev/lib/python3.9/site-packages/glue_astronomy/translators/spectrum1d.py in parse_attributes(attributes)
    109                     mask = None
    110                 else:
--> 111                     mask = data.get_mask(subset_state=subset_state)
    112                     mask = ~mask
    113 

~/projects/glue/glue/core/data.py in get_mask(self, subset_state, view)
   1383     def get_mask(self, subset_state, view=None):
   1384         try:
-> 1385             return subset_state.to_mask(self, view=view)
   1386         except IncompatibleAttribute:
   1387             return get_mask_with_key_joins(self, self._key_joins, subset_state, view=view)

~/projects/glue/glue/core/subset.py in to_mask(self, data, view)
    771     @contract(data='isinstance(Data)', view='array_view')
    772     def to_mask(self, data, view=None):
--> 773         x = data[self.att, view]
    774         result = (x >= self.lo) & (x <= self.hi)
    775         return result

~/projects/glue/glue/core/data.py in __getitem__(self, key)
    569                 raise IncompatibleAttribute(_k)
    570 
--> 571         return self.get_data(key, view=view)
    572 
    573     def _ipython_key_completions_(self):

~/projects/glue/glue/core/data.py in get_data(self, cid, view)
   1364             result = comp[view]
   1365         else:
-> 1366             result = comp.data
   1367 
   1368         return result

~/projects/glue/glue/core/component.py in data(self)
    188     def data(self):
    189         """ Return the numerical data as a numpy array """
--> 190         return self._link.compute(self._data)
    191 
    192     @property

~/projects/glue/glue/core/component_link.py in compute(self, data, view)
    164 
    165         # First we get the values of all the 'from' components.
--> 166         args = [data[join_component_view(f, view)] for f in self._from]
    167 
    168         # We keep track of the original shape of the arguments

~/projects/glue/glue/core/component_link.py in <listcomp>(.0)
    164 
    165         # First we get the values of all the 'from' components.
--> 166         args = [data[join_component_view(f, view)] for f in self._from]
    167 
    168         # We keep track of the original shape of the arguments

~/projects/glue/glue/core/data.py in __getitem__(self, key)
    569                 raise IncompatibleAttribute(_k)
    570 
--> 571         return self.get_data(key, view=view)
    572 
    573     def _ipython_key_completions_(self):

~/projects/glue/glue/core/data.py in get_data(self, cid, view)
   1364             result = comp[view]
   1365         else:
-> 1366             result = comp.data
   1367 
   1368         return result

~/projects/glue/glue/core/component.py in data(self)
    188     def data(self):
    189         """ Return the numerical data as a numpy array """
--> 190         return self._link.compute(self._data)
    191 
    192     @property

~/projects/glue/glue/core/component_link.py in compute(self, data, view)
    167 
    168         # We keep track of the original shape of the arguments
--> 169         original_shape = args[0].shape
    170         logger.debug("shape of first argument: %s", original_shape)
    171 

IndexError: list index out of range

@pllim
Copy link
Contributor

pllim commented Aug 26, 2021

For future reference, I tried patching glue-astronomy in glue-viz/glue-astronomy#39 (to fix Cubeviz) but Tom said glue-astronomy is doing the right thing by raising exception, so it is up to Jdaviz to catch it.

@rosteen
Copy link
Collaborator

rosteen commented Sep 9, 2021

@PatrickOgle As I mentioned offline, I still see an error with some of the older simulated NIRSPEC data, but with the most recent simulated dataset the model fitting appears to work fine. Are you ok with closing this issue given that it seems to have been a now-fixed problem with the old simulated data?

@PatrickOgle
Copy link
Contributor Author

I will have to see it work in my Jwebbinar notebook to be convinced...

@spacetelescope spacetelescope deleted a comment from stscijgbot-jwql Jul 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working mosviz
Projects
None yet
Development

No branches or pull requests

4 participants