Ejemplo n.º 1
0
def _get_data_for_plot(axes, workspace, kwargs, with_dy=False, with_dx=False):
    if isinstance(workspace, mantid.dataobjects.MDHistoWorkspace):
        (normalization, kwargs) = get_normalization(workspace, **kwargs)
        indices, kwargs = get_indices(workspace, **kwargs)
        (x, y, dy) = get_md_data1d(workspace, normalization, indices)
        dx = None
        axis = None
    else:
        axis = MantidAxType(kwargs.pop("axis", MantidAxType.SPECTRUM))
        normalize_by_bin_width, kwargs = get_normalize_by_bin_width(
            workspace, axes, **kwargs)
        workspace_index, distribution, kwargs = get_wksp_index_dist_and_label(
            workspace, axis, **kwargs)
        if axis == MantidAxType.BIN:
            # Overwrite any user specified xlabel
            axes.set_xlabel("Spectrum")
            x, y, dy, dx = get_bins(workspace, workspace_index, with_dy)
        elif axis == MantidAxType.SPECTRUM:
            x, y, dy, dx = get_spectrum(workspace, workspace_index,
                                        normalize_by_bin_width, with_dy,
                                        with_dx)
        else:
            raise ValueError(
                "Axis {} is not a valid axis number.".format(axis))
        indices = None
    return x, y, dy, dx, indices, axis, kwargs
Ejemplo n.º 2
0
def _plot_impl(axes, workspace, args, kwargs):
    """
    Compute data and labels for plot. Used by workspace
    replacement handlers to recompute data. See plot for
    argument details
    """
    if 'LogName' in kwargs:
        (x, y, FullTime, LogName, units,
         kwargs) = get_sample_log(workspace, **kwargs)
        axes.set_ylabel('{0} ({1})'.format(LogName, units))
        axes.set_xlabel('Time (s)')
        if FullTime:
            axes.xaxis_date()
            axes.xaxis.set_major_formatter(
                mdates.DateFormatter('%H:%M:%S\n%b-%d'))
            axes.set_xlabel('Time')
        kwargs['linestyle'] = 'steps-post'
    else:
        normalize_by_bin_width, kwargs = get_normalize_by_bin_width(
            workspace, axes, **kwargs)
        x, y, _, _, indices, axis, kwargs = _get_data_for_plot(
            axes, workspace, kwargs)
        if kwargs.pop('update_axes_labels', True):
            _setLabels1D(axes,
                         workspace,
                         indices,
                         normalize_by_bin_width=normalize_by_bin_width,
                         axis=axis)
    return x, y, args, kwargs
Ejemplo n.º 3
0
    def plot(self, *args, **kwargs):
        """
        If the **mantid** projection is chosen, it can be
        used the same as :py:meth:`matplotlib.axes.Axes.plot` for arrays,
        or it can be used to plot :class:`mantid.api.MatrixWorkspace`
        or :class:`mantid.api.IMDHistoWorkspace`. You can have something like::

            import matplotlib.pyplot as plt
            from mantid import plots

            ...

            fig, ax = plt.subplots(subplot_kw={'projection':'mantid'})
            ax.plot(workspace,'rs',specNum=1) #for workspaces
            ax.plot(x,y,'bo')                 #for arrays
            fig.show()

        For keywords related to workspaces, see :func:`plotfunctions.plot`.
        """
        if helperfunctions.validate_args(*args):
            logger.debug('using plotfunctions')

            autoscale_on_update = kwargs.pop("autoscale_on_update", True)

            def _data_update(artists, workspace, new_kwargs=None):
                # It's only possible to plot 1 line at a time from a workspace
                if new_kwargs:
                    x, y, _, __ = plotfunctions._plot_impl(self, workspace, args,
                                                           new_kwargs)
                else:
                    x, y, _, __ = plotfunctions._plot_impl(self, workspace, args,
                                                           kwargs)
                artists[0].set_data(x, y)
                self.relim()
                if autoscale_on_update:
                    self.autoscale()
                return artists

            workspace = args[0]
            spec_num = self.get_spec_number(workspace, kwargs)
            normalize_by_bin_width, kwargs = get_normalize_by_bin_width(
                workspace, self, **kwargs)
            is_normalized = normalize_by_bin_width or workspace.isDistribution()

            # If we are making the first plot on an axes object
            # i.e. self.lines is empty, axes has default ylim values.
            # Therefore we need to autoscale regardless of autoscale_on_update.
            if self.lines:
                # Otherwise set autoscale to autoscale_on_update.
                self.set_autoscaley_on(autoscale_on_update)

            artist = self.track_workspace_artist(
                workspace, plotfunctions.plot(self, *args, **kwargs),
                _data_update, spec_num, is_normalized)

            self.set_autoscaley_on(True)
            return artist
        else:
            return Axes.plot(self, *args, **kwargs)
Ejemplo n.º 4
0
def errorbar(axes, workspace, *args, **kwargs):
    """
    Unpack mantid workspace and render it with matplotlib. ``args`` and
    ``kwargs`` are passed to :py:meth:`matplotlib.axes.Axes.errorbar` after special
    keyword arguments are removed. This will automatically label the
    line according to the spectrum number unless specified otherwise.

    :param axes:      :class:`matplotlib.axes.Axes` object that will do the plotting
    :param workspace: :class:`mantid.api.MatrixWorkspace` or :class:`mantid.api.IMDHistoWorkspace`
                      to extract the data from
    :param specNum:   spectrum number to plot if MatrixWorkspace
    :param wkspIndex: workspace index to plot if MatrixWorkspace
    :param distribution: ``None`` (default) asks the global setting. ``False`` means
                         divide by bin width. ``True`` means do not divide by bin width.
                         Applies only when the the workspace is a MatrixWorkspace histogram.
    :param normalize_by_bin_width: Plot the workspace as a distribution. If None default to global
                                   setting: config['graph1d.autodistribution']
    :param normalization: ``None`` (default) ask the workspace. Applies to MDHisto workspaces. It can override
                          the value from displayNormalizationHisto. It checks only if
                          the normalization is mantid.api.MDNormalization.NumEventsNormalization
    :param axis: Specify which axis will be plotted. Use axis=MantidAxType.BIN to plot a bin,
                  and axis=MantidAxType.SPECTRUM to plot a spectrum.
                  The default value is axis=1, plotting spectra by default.
    :param indices: Specify which slice of an MDHistoWorkspace to use when plotting. Needs to be a tuple
                    and will be interpreted as a list of indices. You need to use ``slice(None)`` to
                    select which dimension to plot. *e.g.* to select the second axis to plot from a
                    3D volume use ``indices=(5, slice(None), 10)`` where the 5/10 are the bins selected
                    for the other 2 axes.
    :param slicepoint: Specify which slice of an MDHistoWorkspace to use when plotting in the dimension units.
                       You need to use ``None`` to select which dimension to plot. *e.g.* to select the second
                       axis to plot from a 3D volume use ``slicepoint=(1.0, None, 2.0)`` where the 1.0/2.0 are
                       the dimension selected for the other 2 axes.

    For matrix workspaces with more than one spectra, either ``specNum`` or ``wkspIndex``
    needs to be specified. Giving both will generate a :class:`RuntimeError`. There is no similar
    keyword for MDHistoWorkspaces. These type of workspaces have to have exactly one non integrated
    dimension
    """
    normalize_by_bin_width, kwargs = get_normalize_by_bin_width(
        workspace, axes, **kwargs)
    x, y, dy, dx, indices, axis, kwargs = _get_data_for_plot(axes,
                                                             workspace,
                                                             kwargs,
                                                             with_dy=True,
                                                             with_dx=False)
    if kwargs.pop('update_axes_labels', True):
        _setLabels1D(axes,
                     workspace,
                     indices,
                     normalize_by_bin_width=normalize_by_bin_width,
                     axis=axis)

    return axes.errorbar(x, y, dy, dx, *args, **kwargs)
Ejemplo n.º 5
0
    def errorbar(self, *args, **kwargs):
        """
        If the **mantid** projection is chosen, it can be
        used the same as :py:meth:`matplotlib.axes.Axes.errorbar` for arrays,
        or it can be used to plot :class:`mantid.api.MatrixWorkspace`
        or :class:`mantid.api.IMDHistoWorkspace`. You can have something like::

            import matplotlib.pyplot as plt
            from mantid import plots

            ...

            fig, ax = plt.subplots(subplot_kw={'projection':'mantid'})
            ax.errorbar(workspace,'rs',specNum=1) #for workspaces
            ax.errorbar(x,y,yerr,'bo')            #for arrays
            fig.show()

        For keywords related to workspaces, see :func:`plotfunctions.errorbar`
        """
        if helperfunctions.validate_args(*args):
            logger.debug('using plotfunctions')

            autoscale_on_update = kwargs.pop("autoscale_on_update", True)

            def _data_update(artists, workspace, new_kwargs=None):
                if self.lines:
                    self.set_autoscaley_on(autoscale_on_update)

                # errorbar with workspaces can only return a single container
                container_orig = artists[0]
                # It is not possible to simply reset the error bars so
                # we have to plot new lines but ensure we don't reorder them on the plot!
                orig_idx = self.containers.index(container_orig)
                container_orig.remove()
                # The container does not remove itself from the containers list
                # but protect this just in case matplotlib starts doing this
                try:
                    self.containers.remove(container_orig)
                except ValueError:
                    pass
                # this gets pushed back onto the containers list
                if new_kwargs:
                    container_new = plotfunctions.errorbar(self, workspace,
                                                           **new_kwargs)
                else:
                    container_new = plotfunctions.errorbar(self, workspace,
                                                           **kwargs)
                self.containers.insert(orig_idx, container_new)
                self.containers.pop()

                # Update joining line
                if container_new[0] and container_orig[0]:
                    container_new[0].update_from(container_orig[0])
                # Update caps
                for orig_caps, new_caps in zip(container_orig[1], container_new[1]):
                    new_caps.update_from(orig_caps)
                # Update bars
                for orig_bars, new_bars in zip(container_orig[2], container_new[2]):
                    new_bars.update_from(orig_bars)

                # Re-plotting in the config dialog will assign this attr
                if hasattr(container_orig, 'errorevery'):
                    setattr(container_new, 'errorevery', container_orig.errorevery)

                # ax.relim does not support collections...
                self._update_line_limits(container_new[0])
                self.set_autoscaley_on(True)
                return container_new

            workspace = args[0]
            spec_num = self.get_spec_number(workspace, kwargs)
            is_normalized, kwargs = get_normalize_by_bin_width(workspace, self,
                                                               **kwargs)

            if self.lines:
                self.set_autoscaley_on(autoscale_on_update)

            artist = self.track_workspace_artist(
                workspace, plotfunctions.errorbar(self, *args, **kwargs),
                _data_update, spec_num, is_normalized)

            self.set_autoscaley_on(True)
            return artist
        else:
            return Axes.errorbar(self, *args, **kwargs)