def newView(self,
                type="scatter",
                components=[],
                title="New View",
                **kwargs):
        only_subsets = kwargs.get('only_subsets', False)
        only_view = kwargs.get('only_view', False)
        if (self.parent is not None):
            kwargs.setdefault('modal', self.parent.modal)
        if (self.debug is not None):
            kwargs.setdefault('debug', self.debug)

        gp = None
        mode = "tab-after"
        if (len(self.active_views.values()) == 0):
            mode = "split-bottom"
        kwargs.setdefault('mode', mode)

        if only_view is False:
            gp = self.factory.createGluePlot(type, self.data, components,
                                             title, **kwargs)
        else:
            data = Data(label=self.data.label)
            for c in components:
                data.add_component(self.data[c, self.selection], label=c)
                data.get_component(c).color = self.data.get_component(c).color

            if (data.size > 0):
                gp = self.factory.createGluePlot(type, data, components, title,
                                                 **kwargs)

        if gp is not None:
            if only_view is False:
                gp.setParent(self)
                key = id(gp.window)
                self.active_views[key] = gp
                self.views[key] = {
                    'type': type,
                    'components': components,
                    'title': title,
                    'kwargs': kwargs
                }
                if isinstance(gp.window, Floatview):
                    gp.window.observe(
                        lambda changes: GlueManager.removeViewIfDisposed(
                            self, gp.window), 'uid')
                    self.parent.updateHistory()
        return gp
Exemple #2
0
    def vue_fit_model_to_cube(self, *args, **kwargs):

        if self._warn_if_no_equation():
            return
        data = self.app.data_collection[self._selected_data_label]

        # First, ensure that the selected data is cube-like. It is possible
        # that the user has selected a pre-existing 1d data object.
        if data.ndim != 3:
            snackbar_message = SnackbarMessage(
                f"Selected data {self._selected_data_label} is not cube-like",
                color='error',
                sender=self)
            self.hub.broadcast(snackbar_message)
            return

        # Get the primary data component
        attribute = data.main_components[0]
        component = data.get_component(attribute)
        temp_values = data.get_data(attribute)

        # Transpose the axis order
        values = np.moveaxis(temp_values, 0, -1) * u.Unit(component.units)

        # We manually create a Spectrum1D object from the flux information
        #  in the cube we select
        wcs = data.coords.sub([WCSSUB_SPECTRAL])
        spec = Spectrum1D(flux=values, wcs=wcs)

        # TODO: in vuetify >2.3, timeout should be set to -1 to keep open
        #  indefinitely
        snackbar_message = SnackbarMessage("Fitting model to cube...",
                                           loading=True,
                                           timeout=0,
                                           sender=self)
        self.hub.broadcast(snackbar_message)

        # Retrieve copy of the models with proper "fixed" dictionaries
        # TODO: figure out why this was causing the parallel fitting to fail
        #models_to_fit = self._reinitialize_with_fixed()
        models_to_fit = self._initialized_models.values()

        fitted_model, fitted_spectrum = fit_model_to_spectrum(
            spec, models_to_fit, self.model_equation, run_fitter=True)

        # Save fitted 3D model in a way that the cubeviz
        # helper can access it.
        self.app._fitted_3d_model = fitted_model

        # Transpose the axis order back
        values = np.moveaxis(fitted_spectrum.flux.value, -1, 0)

        count = max(
            map(lambda s: int(next(iter(re.findall("\d$", s)), 0)),
                self.data_collection.labels)) + 1

        label = f"{self.model_label} [Cube] {count}"

        # Create new glue data object
        output_cube = Data(label=label, coords=data.coords)
        output_cube['flux'] = values
        output_cube.get_component('flux').units = \
            fitted_spectrum.flux.unit.to_string()

        # Add to data collection
        self.app.data_collection.append(output_cube)

        snackbar_message = SnackbarMessage("Finished cube fitting",
                                           color='success',
                                           loading=False,
                                           sender=self)
        self.hub.broadcast(snackbar_message)
Exemple #3
0
    def vue_fit_model_to_cube(self, *args, **kwargs):

        if self._warn_if_no_equation():
            return

        if self.selected_data in self.app.data_collection.labels:
            data = self.app.data_collection[self.selected_data]
        else:  # User selected some subset from spectrum viewer, just use original cube
            data = self.app.data_collection[0]

        # First, ensure that the selected data is cube-like. It is possible
        # that the user has selected a pre-existing 1d data object.
        if data.ndim != 3:
            snackbar_message = SnackbarMessage(
                f"Selected data {self.selected_data} is not cube-like",
                color='error',
                sender=self)
            self.hub.broadcast(snackbar_message)
            return

        # Get the primary data component
        attribute = data.main_components[0]
        component = data.get_component(attribute)
        temp_values = data.get_data(attribute)

        # Transpose the axis order
        values = np.moveaxis(temp_values, 0, -1) * u.Unit(component.units)

        # We manually create a Spectrum1D object from the flux information
        #  in the cube we select
        wcs = data.coords.sub([WCSSUB_SPECTRAL])
        spec = Spectrum1D(flux=values, wcs=wcs)

        # TODO: in vuetify >2.3, timeout should be set to -1 to keep open
        #  indefinitely
        snackbar_message = SnackbarMessage("Fitting model to cube...",
                                           loading=True,
                                           timeout=0,
                                           sender=self)
        self.hub.broadcast(snackbar_message)

        # Retrieve copy of the models with proper "fixed" dictionaries
        models_to_fit = self._reinitialize_with_fixed()

        try:
            fitted_model, fitted_spectrum = fit_model_to_spectrum(
                spec,
                models_to_fit,
                self.model_equation,
                run_fitter=True,
                window=self._window)
        except ValueError:
            snackbar_message = SnackbarMessage("Cube fitting failed",
                                               color='error',
                                               loading=False,
                                               sender=self)
            self.hub.broadcast(snackbar_message)
            raise

        # Save fitted 3D model in a way that the cubeviz
        # helper can access it.
        for m in fitted_model:
            temp_label = "{} ({}, {})".format(self.model_label, m["x"], m["y"])
            self.app.fitted_models[temp_label] = m["model"]

        # Transpose the axis order back
        values = np.moveaxis(fitted_spectrum.flux.value, -1, 0)

        count = max(
            map(lambda s: int(next(iter(re.findall(r"\d$", s)), 0)),
                self.data_collection.labels)) + 1

        label = f"{self.model_label} [Cube] {count}"

        # Create new glue data object
        output_cube = Data(label=label, coords=data.coords)
        output_cube['flux'] = values
        output_cube.get_component('flux').units = \
            fitted_spectrum.flux.unit.to_string()

        # Add to data collection
        self.app.add_data(output_cube, label)
        if self.selected_viewer != 'None':
            # replace the contents in the selected viewer with the results from this plugin
            self.app.add_data_to_viewer(self.viewer_to_id.get(
                self.selected_viewer),
                                        label,
                                        clear_other_data=True)

        snackbar_message = SnackbarMessage("Finished cube fitting",
                                           color='success',
                                           loading=False,
                                           sender=self)
        self.hub.broadcast(snackbar_message)
Exemple #4
0
    def vue_fit_model_to_cube(self, *args, **kwargs):

        if self._warn_if_no_equation():
            return
        if self._selected_data_label in self.app.data_collection.labels:
            data = self.app.data_collection[self._selected_data_label]
        else:  # User selected some subset from spectrum viewer, just use original cube
            data = self.app.data_collection[0]

        # First, ensure that the selected data is cube-like. It is possible
        # that the user has selected a pre-existing 1d data object.
        if data.ndim != 3:
            snackbar_message = SnackbarMessage(
                f"Selected data {self._selected_data_label} is not cube-like",
                color='error',
                sender=self)
            self.hub.broadcast(snackbar_message)
            return

        # Get the primary data component
        attribute = data.main_components[0]
        component = data.get_component(attribute)
        temp_values = data.get_data(attribute)

        # Transpose the axis order
        values = np.moveaxis(temp_values, 0, -1) * u.Unit(component.units)

        # We manually create a Spectrum1D object from the flux information
        #  in the cube we select
        wcs = data.coords.sub([WCSSUB_SPECTRAL])
        spec = Spectrum1D(flux=values, wcs=wcs)

        # TODO: in vuetify >2.3, timeout should be set to -1 to keep open
        #  indefinitely
        snackbar_message = SnackbarMessage("Fitting model to cube...",
                                           loading=True,
                                           timeout=0,
                                           sender=self)
        self.hub.broadcast(snackbar_message)

        # Retrieve copy of the models with proper "fixed" dictionaries
        # TODO: figure out why this was causing the parallel fitting to fail
        # models_to_fit = self._reinitialize_with_fixed()
        models_to_fit = list(self._initialized_models.values())

        # Remove units to work around current specutils/astropy modeling limitations
        # TODO: Keep units once astropy/specutils can handle them for all models
        removed_units = {}
        unitless_models = []

        for m in models_to_fit:
            removed_units[m.name] = {}
            if type(m) == models.Polynomial1D:
                temp_model = m.__class__(name=m.name, degree=m.degree)
            else:
                temp_model = m.__class__(name=m.name)
            for pname in m.param_names:
                p = getattr(m, pname)
                removed_units[m.name][pname] = p.unit
                setattr(temp_model, pname, p.value)
            unitless_models.append(temp_model)
        models_to_fit = unitless_models

        try:
            fitted_model, fitted_spectrum = fit_model_to_spectrum(
                spec,
                models_to_fit,
                self.model_equation,
                run_fitter=True,
                window=self._window)
        except ValueError:
            snackbar_message = SnackbarMessage("Cube fitting failed",
                                               color='error',
                                               loading=False,
                                               sender=self)
            self.hub.broadcast(snackbar_message)
            raise

        # Save fitted 3D model in a way that the cubeviz
        # helper can access it.
        for m in fitted_model:
            temp_label = "{} ({}, {})".format(self.model_label, m["x"], m["y"])
            self.app.fitted_models[temp_label] = m["model"]

        # Transpose the axis order back
        values = np.moveaxis(fitted_spectrum.flux.value, -1, 0)

        count = max(
            map(lambda s: int(next(iter(re.findall(r"\d$", s)), 0)),
                self.data_collection.labels)) + 1

        label = f"{self.model_label} [Cube] {count}"

        # Create new glue data object
        output_cube = Data(label=label, coords=data.coords)
        output_cube['flux'] = values
        output_cube.get_component('flux').units = \
            fitted_spectrum.flux.unit.to_string()

        # Add to data collection
        self.app.data_collection.append(output_cube)

        snackbar_message = SnackbarMessage("Finished cube fitting",
                                           color='success',
                                           loading=False,
                                           sender=self)
        self.hub.broadcast(snackbar_message)