def errorbar(axes, workspace, *args, **kwargs): """ Same as the cli PlotCut but returns the relevant axes object. """ from mslice.app.presenters import get_cut_plotter_presenter cur_fig = plt.gcf() cur_canvas = cur_fig.canvas _check_workspace_name(workspace) workspace = get_workspace_handle(workspace) if not isinstance(workspace, HistogramWorkspace): raise RuntimeError("Incorrect workspace type.") presenter = get_cut_plotter_presenter() plot_over = kwargs.pop('plot_over', True) intensity_range = kwargs.pop('intensity_range', (None, None)) label = kwargs.pop('label', None) label = workspace.name if label is None else label en_conversion_allowed = kwargs.pop('en_conversion', True) cut_axis, int_axis = tuple(workspace.axes) # Checks that current cut has consistent units with previous if plot_over: cached_cuts = presenter.get_cache(axes) if cached_cuts: if (cut_axis.units != cached_cuts[0].cut_axis.units): raise RuntimeError('Cut axes not consistent with current plot. ' 'Expected {}, got {}'.format(cached_cuts[0].cut_axis.units, cut_axis.units)) # Checks whether we should do an energy unit conversion if 'DeltaE' in cut_axis.units and cut_axis.e_unit != cached_cuts[0].cut_axis.e_unit: if en_conversion_allowed: _rescale_energy_cut_plot(presenter, cached_cuts, cut_axis.e_unit) else: raise RuntimeError('Wrong energy unit for cut. ' 'Expected {}, got {}'.format(cached_cuts[0].cut_axis.e_unit, cut_axis.e_unit)) plotfunctions.errorbar(axes, workspace.raw_ws, label=label, *args, **kwargs) axes.set_ylim(*intensity_range) if intensity_range is not None else axes.autoscale() intensity_min, intensity_max = axes.get_ylim() if cur_canvas.manager.window.action_toggle_legends.isChecked(): leg = axes.legend(fontsize='medium') leg.draggable() axes.set_xlabel(get_display_name(cut_axis), picker=CUT_PICKER_TOL_PTS) axes.set_ylabel(CUT_INTENSITY_LABEL, picker=CUT_PICKER_TOL_PTS) if not plot_over: cur_canvas.set_window_title(workspace.name) cur_canvas.manager.update_grid() if not cur_canvas.manager.has_plot_handler(): cur_canvas.manager.add_cut_plot(presenter, workspace.name) cur_fig.canvas.draw() axes.pchanged() # This call is to let the waterfall callback know to update cut = Cut(cut_axis, int_axis, intensity_min, intensity_max, workspace.norm_to_one, width='') cut.workspace_name = workspace.parent presenter.save_cache(axes, cut, plot_over) return axes.lines
def _data_update(artists, workspace): # 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 container_new = plotfunctions.errorbar(self, workspace, **kwargs) self.containers.insert(orig_idx, container_new) self.containers.pop() # update line properties to match original orig_flat, new_flat = cbook.flatten(container_orig), cbook.flatten(container_new) for artist_orig, artist_new in zip(orig_flat, new_flat): artist_new.update_from(artist_orig) # ax.relim does not support collections... self._update_line_limits(container_new[0]) self.autoscale() return container_new
def _data_update(artists, workspace): # 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 container_new = plotfunctions.errorbar(self, workspace, **kwargs) self.containers.insert(orig_idx, container_new) self.containers.pop() # update line properties to match original orig_flat, new_flat = cbook.flatten( container_orig), cbook.flatten(container_new) for artist_orig, artist_new in zip(orig_flat, new_flat): artist_new.update_from(artist_orig) # ax.relim does not support collections... self._update_line_limits(container_new[0]) self.autoscale() return container_new
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') def _data_update(artists, workspace): # 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 container_new = plotfunctions.errorbar(self, workspace, **kwargs) self.containers.insert(orig_idx, container_new) self.containers.pop() # update line properties to match original orig_flat, new_flat = cbook.flatten( container_orig), cbook.flatten(container_new) for artist_orig, artist_new in zip(orig_flat, new_flat): artist_new.update_from(artist_orig) # ax.relim does not support collections... self._update_line_limits(container_new[0]) self.autoscale() return container_new workspace = args[0] spec_num = self._get_spec_number(workspace, kwargs) return self.track_workspace_artist(workspace, plotfunctions.errorbar( self, *args, **kwargs), _data_update, spec_num=spec_num) else: return Axes.errorbar(self, *args, **kwargs)
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
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') def _data_update(artists, workspace): # 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 container_new = plotfunctions.errorbar(self, workspace, **kwargs) self.containers.insert(orig_idx, container_new) self.containers.pop() # update line properties to match original orig_flat, new_flat = cbook.flatten(container_orig), cbook.flatten(container_new) for artist_orig, artist_new in zip(orig_flat, new_flat): artist_new.update_from(artist_orig) # ax.relim does not support collections... self._update_line_limits(container_new[0]) self.autoscale() return container_new workspace = args[0] spec_num = self._get_spec_number(workspace, kwargs) return self.track_workspace_artist(workspace, plotfunctions.errorbar(self, *args, **kwargs), _data_update, spec_num=spec_num) else: return Axes.errorbar(self, *args, **kwargs)
def test_1d_errorbars(self): fig, ax = plt.subplots() funcs.errorbar(ax, self.ws2d_histo, 'rs', specNum=1) funcs.errorbar(ax, self.ws2d_histo, specNum=2, linewidth=6) funcs.errorbar(ax, self.ws_MD_1d, 'bo')
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)