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] Cubeviz: Model fitting broken with spectral+spatial subsets #1530

Closed
rosteen opened this issue Jul 29, 2022 · 0 comments · Fixed by #1531
Closed

[BUG] Cubeviz: Model fitting broken with spectral+spatial subsets #1530

rosteen opened this issue Jul 29, 2022 · 0 comments · Fixed by #1531
Labels
bug Something isn't working cubeviz 🔥 Critical

Comments

@rosteen
Copy link
Collaborator

rosteen commented Jul 29, 2022

It looks like a recent change broke model fitting in Cubeviz when you choose both a spectral and spatial subset (could have been linking or data menu changes). The traceback is:

AttributeError                            Traceback (most recent call last)
File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/ipyvue/VueTemplateWidget.py:60, in Events._handle_event(self, _, content, buffers)
     58     getattr(self, "vue_" + event)(data, buffers)
     59 else:
---> 60     getattr(self, "vue_" + event)(data)

File ~/projects/jdaviz/jdaviz/configs/default/plugins/model_fitting/model_fitting.py:436, in ModelFitting.vue_apply(self, event)
    434     self.vue_fit_model_to_cube()
    435 else:
--> 436     self.vue_model_fitting()

File ~/projects/jdaviz/jdaviz/configs/default/plugins/model_fitting/model_fitting.py:472, in ModelFitting.vue_model_fitting(self, *args, **kwargs)
    469 self._fitted_spectrum = fitted_spectrum
    471 self.app.fitted_models[self.results_label] = fitted_model
--> 472 self.vue_register_spectrum({"spectrum": fitted_spectrum})
    474 # Update component model parameters with fitted values
    475 if type(self._fitted_model) == QuantityModel:

File ~/projects/jdaviz/jdaviz/configs/default/plugins/model_fitting/model_fitting.py:577, in ModelFitting.vue_register_spectrum(self, event)
    571 else:
    572     model, spectrum = fit_model_to_spectrum(self._spectrum1d,
    573                                             self._initialized_models.values(),
    574                                             self.model_equation,
    575                                             window=self._window)
--> 577 self.add_results.add_results_from_plugin(spectrum)
    578 self._set_default_results_label()

File ~/projects/jdaviz/jdaviz/core/template_mixin.py:1329, in AddResults.add_results_from_plugin(self, data_item)
   1324 self.app.add_data(data_item, self.label)
   1326 if self.add_to_viewer_selected != 'None':
   1327     # replace the contents in the selected viewer with the results from this plugin
   1328     # TODO: switch to an instance/classname check?
-> 1329     self.app.add_data_to_viewer(self.viewer.selected_id,
   1330                                 self.label, clear_other_data=False)
   1332     if replace:
   1333         data_id = next((x['id'] for x in self.app.state.data_items
   1334                         if x['name'] == self.label), None)

File ~/projects/jdaviz/jdaviz/app.py:954, in Application.add_data_to_viewer(self, viewer_reference, data_path, clear_other_data, ext)
    952 if data_id is not None:
    953     selected_data_items[data_id] = 'visible'
--> 954     self._update_selected_data_items(viewer_item['id'], selected_data_items)
    955 else:
    956     raise ValueError(
    957         f"No data item found with label '{data_label}'. Label must be one "
    958         "of:\n\t" + "\n\t".join([
    959             data_item['name'] for data_item in self.state.data_items]))

File ~/projects/jdaviz/jdaviz/app.py:1295, in Application._update_selected_data_items(self, viewer_id, selected_items)
   1290 viewer.add_data(data, percentile=95)
   1292 add_data_message = AddDataMessage(data, viewer,
   1293                                   viewer_id=viewer_id,
   1294                                   sender=self)
-> 1295 self.hub.broadcast(add_data_message)
   1297 for layer in viewer.layers:
   1298     if layer.layer.data.label == label:

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/glue/core/hub.py:215, in Hub.broadcast(self, message)
    213 logging.getLogger(__name__).info("Broadcasting %s", message)
    214 for subscriber, handler in self._find_handlers(message):
--> 215     handler(message)

File ~/projects/jdaviz/jdaviz/configs/default/plugins/line_lists/line_lists.py:144, in LineListTool._on_viewer_data_changed(self, msg)
    142 label = msg.data.label
    143 try:
--> 144     viewer_data = self.app.get_data_from_viewer('spectrum-viewer').get(label)
    145 except TypeError:
    146     warn_message = SnackbarMessage("Line list plugin could not retrieve data from viewer",
    147                                    sender=self, color="error")

File ~/projects/jdaviz/jdaviz/app.py:647, in Application.get_data_from_viewer(self, viewer_reference, data_label, cls, include_subsets)
    645 handler, _ = data_translator.get_handler_for(cls)
    646 try:
--> 647     layer_data = handler.to_object(layer_data,
    648                                    statistic=statistic)
    649 except IncompatibleAttribute:
    650     continue

File ~/projects/glue-astronomy/glue_astronomy/translators/spectrum1d.py:289, in Specutils1DHandler.to_object(self, data_or_subset, attribute, statistic)
    284         data_kwargs.update({attribute_label: values,
    285                            'mask': mask})
    287     return data_kwargs
--> 289 data_kwargs = parse_attributes(
    290     [attribute] if not hasattr(attribute, '__len__') else attribute)
    292 return Spectrum1D(**data_kwargs, **kwargs)

File ~/projects/glue-astronomy/glue_astronomy/translators/spectrum1d.py:256, in Specutils1DHandler.to_object.<locals>.parse_attributes(attributes)
    254     mask = None
    255 else:
--> 256     mask = data.get_mask(subset_state=subset_state)
    257     mask = ~mask
    259 # Collapse values and mask to profile

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/glue/core/data.py:1404, in Data.get_mask(self, subset_state, view)
   1402 def get_mask(self, subset_state, view=None):
   1403     try:
-> 1404         return subset_state.to_mask(self, view=view)
   1405     except IncompatibleAttribute:
   1406         return get_mask_with_key_joins(self, self._key_joins, subset_state, view=view)

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/glue/core/subset.py:547, in RoiSubsetStateNd.to_mask(self, data, view)
    545 raw_comps = []
    546 for att in self._atts:
--> 547     raw_comps.append(data[att, view])
    548 res_shape = raw_comps[0].shape
    549 if not self.roi.defined():

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/glue/core/data.py:579, in BaseCartesianData.__getitem__(self, key)
    576     if key is None:
    577         raise IncompatibleAttribute(_k)
--> 579 return self.get_data(key, view=view)

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/glue/core/data.py:1385, in Data.get_data(self, cid, view)
   1383     result = comp[view]
   1384 else:
-> 1385     result = comp.data
   1387 return result

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/glue/core/component.py:200, in DerivedComponent.data(self)
    197 @property
    198 def data(self):
    199     """Return the numerical data as a numpy array"""
--> 200     return self._link.compute(self._data)

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/glue/core/component_link.py:187, in ComponentLink.compute(self, data, view)
    184 args = np.broadcast_arrays(*args)
    186 # We call the actual linking function
--> 187 result = self._using(*args)
    189 # We call asarray since link functions may return Python scalars in some cases
    190 result = np.asarray(result)

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/glue/core/component_link.py:395, in CoordinateComponentLink.using(self, *args)
    393     return pixel2world_single_axis(self.coords, *args2[::-1], world_axis=self.ndim - 1 - self.index)
    394 else:
--> 395     return world2pixel_single_axis(self.coords, *args2[::-1], pixel_axis=self.ndim - 1 - self.index)

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/glue/core/coordinate_helpers.py:102, in world2pixel_single_axis(wcs, pixel_axis, *world)
     99         world_new.append(w.flat[0])
    100 world = np.broadcast_arrays(*world_new)
--> 102 result = wcs.world_to_pixel_values(*world)
    104 return broadcast_to(result[pixel_axis], original_shape)

File ~/projects/glue-astronomy/glue_astronomy/translators/spectrum1d.py:80, in PaddedSpectrumWCS.world_to_pixel_values(self, *world_arrays)
     76 def world_to_pixel_values(self, *world_arrays):
     77     # The ravel and reshape are needed because of
     78     # https://github.com/astropy/astropy/issues/12154
     79     wx = np.array(world_arrays[0])
---> 80     pixel_arrays = [self.spectral_wcs.world_to_pixel_values(wx.ravel()).reshape(wx.shape),
     81                     *world_arrays[1:]]
     82     return tuple(pixel_arrays)

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/gwcs/api.py:142, in GWCSAPIMixin.world_to_pixel_values(self, *world_arrays)
    138 world_arrays = self._add_units_input(world_arrays, self.backward_transform, self.output_frame)
    140 result = self.invert(*world_arrays, with_units=False)
--> 142 return self._remove_quantity_output(result, self.input_frame)

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/gwcs/api.py:81, in GWCSAPIMixin._remove_quantity_output(self, result, frame)
     78     if self.output_frame.naxes == 1:
     79         result = [result]
---> 81     result = tuple(r.to_value(unit) for r, unit in zip(result, frame.unit))
     83 # If we only have one output axes, we shouldn't return a tuple.
     84 if self.output_frame.naxes == 1 and isinstance(result, tuple):

File ~/opt/anaconda3/envs/viz_dev/lib/python3.10/site-packages/gwcs/api.py:81, in <genexpr>(.0)
     78     if self.output_frame.naxes == 1:
     79         result = [result]
---> 81     result = tuple(r.to_value(unit) for r, unit in zip(result, frame.unit))
     83 # If we only have one output axes, we shouldn't return a tuple.
     84 if self.output_frame.naxes == 1 and isinstance(result, tuple):

AttributeError: 'numpy.ndarray' object has no attribute 'to_value'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working cubeviz 🔥 Critical
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant