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
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
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)
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)
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)