Пример #1
0
 def plot_qe(self, Ei, label_text, hold=False):
     """ Plots the Q-E diagram """
     from scipy import constants
     E2q, meV2J = (2. * constants.m_n / (constants.hbar**2),
                   constants.e / 1000.)
     en = np.linspace(-Ei / 5., Ei, 100)
     q2 = []
     if self.engine.name == 'HYSPEC':
         if abs(self.hyspecS2) <= 30:
             self.engine.detector.tthlims = [0, abs(self.hyspecS2) + 30]
         else:
             self.engine.detector.tthlims = [
                 abs(self.hyspecS2) - 30,
                 abs(self.hyspecS2) + 30
             ]
         label_text += '_S2={}'.format(self.hyspecS2)
     for tth in self.engine.detector.tthlims:
         q = np.sqrt(E2q * (2 * Ei - en - 2 * np.sqrt(Ei * (Ei - en)) *
                            np.cos(np.deg2rad(tth))) * meV2J) / 1e10
         q2.append(np.concatenate((np.flipud(q), q)))
     self._set_overplot(hold, 'qeaxes')
     self.qeaxes_xlim = max(np.max(q2), self.qeaxes_xlim)
     line, = self.qeaxes.plot(
         np.hstack(q2),
         np.concatenate((np.flipud(en), en)).tolist() *
         len(self.engine.detector.tthlims))
     line.set_label(label_text)
     self.qeaxes.set_xlim([0, self.qeaxes_xlim])
     legend_set_draggable(self.qeaxes.legend(), True)
     self.qeaxes.set_xlabel(r'$|Q| (\mathrm{\AA}^{-1})$')
     self.qeaxes.set_ylabel('Energy Transfer (meV)')
     self.qecanvas.draw()
Пример #2
0
 def _plot_data_workbench(self, fig_window, data):
     external_axes = fig_window.axes
     for plot_info in data:
         external_axis = external_axes[plot_info.axis]
         external_axis.plot(plot_info.workspace,
                            specNum=plot_info.specNume,
                            distribution=not plot_info.normalised)
         legend_set_draggable(external_axis.legend(), True)
     fig_window.show()
Пример #3
0
    def test_legend_set_draggable(self):
        legend = create_autospec(Legend)
        args = (None, False, 'loc')
        legend_set_draggable(legend, *args)

        if hasattr(Legend, 'set_draggable'):
            legend.set_draggable.assert_called_with(*args)
        else:
            legend.draggable.assert_called_with(*args)
Пример #4
0
 def plot_flux_hz(self):
     """
     Plots the flux vs freq in the middle tab
     """
     inst = self.engine.instname
     chop = self.engine.getChopper()
     ei = float(self.widgets['EiEdit']['Edit'].text())
     overplot = self.widgets['HoldCheck'].isChecked()
     # Do not recalculate if one of the plots has the same parametersc
     _, labels = self.frqaxes2.get_legend_handles_labels()
     searchStr = '([A-Z]+) "(.+)" Ei = ([0-9.-]+) meV'
     if labels and (overplot or len(labels) == 1):
         for prevtitle in labels:
             prevInst, prevChop, prevEi = re.search(searchStr,
                                                    prevtitle).groups()
             if inst == prevInst and chop == prevChop and abs(
                     ei - float(prevEi)) < 0.01:
                 return
     freq0 = self.engine.getFrequency()
     rep = self.engine.moderator.source_rep
     maxfreq = self.engine.chopper_system.max_frequencies
     freqs = range(
         rep, (maxfreq[0] if hasattr(maxfreq, '__len__') else maxfreq) + 1,
         rep)
     flux = np.zeros(len(freqs))
     elres = np.zeros(len(freqs))
     for ie, freq in enumerate(freqs):
         if hasattr(freq0, '__len__'):
             self.setFreq(manual_freq=[freq] + freq0[1:])
         else:
             self.setFreq(manual_freq=freq)
         with warnings.catch_warnings(record=True):
             warnings.simplefilter('always', UserWarning)
             flux[ie] = self.engine.getFlux(ei)
             elres[ie] = self.engine.getResolution(0., ei)[0]
     if overplot:
         if matplotlib.compare_versions('2.1.0', matplotlib.__version__):
             self.frqaxes1.hold(True)
             self.frqaxes2.hold(True)
     else:
         self.frqaxes1.clear()
         self.frqaxes2.clear()
     self.setFreq(manual_freq=freq0)
     self.frqaxes1.set_xlabel('Chopper Frequency (Hz)')
     self.frqaxes1.set_ylabel('Flux (n/cm$^2$/s)')
     line, = self.frqaxes1.plot(freqs, flux, 'o-')
     self.frqaxes1.set_xlim([0, np.max(freqs)])
     self.frqaxes2.set_xlabel('Chopper Frequency (Hz)')
     self.frqaxes2.set_ylabel('Elastic Resolution FWHM (meV)')
     line, = self.frqaxes2.plot(freqs, elres, 'o-')
     line.set_label('%s "%s" Ei = %5.3f meV' % (inst, chop, ei))
     lg = self.frqaxes2.legend()
     legend_set_draggable(lg, True)
     self.frqaxes2.set_xlim([0, np.max(freqs)])
     self.frqcanvas.draw()
Пример #5
0
    def _do_plot(self, selected_columns, selected_x, plot_type):
        if self._is_error_plot(plot_type):
            yerr = self.presenter.model.marked_columns.find_yerr(
                selected_columns)
            # remove the Y error columns if they are in the selection for plotting
            # this prevents them from being treated as Y columns
            for err_col in yerr.values():
                try:
                    selected_columns.remove(err_col)
                except ValueError:
                    # the column is not contained within the selected one
                    pass
            if len(yerr) != len(selected_columns):
                column_headers = self.presenter.model.original_column_headers()
                self.presenter.view.show_warning(
                    self.NO_ASSOCIATED_YERR_FOR_EACH_Y_MESSAGE.format(",".join(
                        [column_headers[col] for col in selected_columns])))
                return
        x = self.presenter.model.get_column(selected_x)

        fig, ax = self.plot.subplots(subplot_kw={"projection": "mantid"})
        if fig.canvas.manager is not None:
            fig.canvas.manager.set_window_title(
                self.presenter.model.get_name())
        ax.set_xlabel(self.presenter.model.get_column_header(selected_x))
        ax.wsName = self.presenter.model.get_name()

        plot_func = self._get_plot_function_from_type(ax, plot_type)
        kwargs = {}
        for column in selected_columns:
            # if the errors are being plotted, retrieve the data for the column
            if self._is_error_plot(plot_type):
                yerr_column = yerr[column]
                yerr_column_data = self.presenter.model.get_column(yerr_column)
                kwargs["yerr"] = yerr_column_data

            y = self.presenter.model.get_column(column)
            column_label = self.presenter.model.get_column_header(column)
            try:
                plot_func(x,
                          y,
                          label=self.COLUMN_DISPLAY_LABEL.format(column_label),
                          **kwargs)
            except ValueError as e:
                error_message = self.PLOT_FUNCTION_ERROR_MESSAGE.format(e)
                logger.error(error_message)
                self.presenter.view.show_warning(
                    error_message, self.INVALID_DATA_WINDOW_TITLE)
                return

            ax.set_ylabel(column_label)
        legend_set_draggable(ax.legend(), True)
        fig.show()
Пример #6
0
    def create_legend(cls, props, ax):
        if not props:
            legend_set_draggable(ax.legend(), True)
            return

        if int(matplotlib.__version__[0]) >= 2:
            legend = ax.legend(
                ncol=props['columns'],
                prop={'size': props['entries_size']},
                numpoints=props['markers'],
                markerfirst=props['marker_position'] == "Left of Entries",
                frameon=props['box_visible'],
                fancybox=props['round_edges'],
                shadow=props['shadow'],
                framealpha=props['transparency'],
                facecolor=props['background_color'],
                edgecolor=props['edge_color'],
                title=props['title'],
                borderpad=props['border_padding'],
                labelspacing=props['label_spacing'],
                handlelength=props['marker_size'],
                handletextpad=props['marker_label_padding'],
                columnspacing=props['column_spacing'])
        else:
            legend = ax.legend(
                ncol=props['columns'],
                prop={'size': props['entries_size']},
                numpoints=props['markers'],
                markerfirst=props['marker_position'] == "Left of Entries",
                frameon=props['box_visible'],
                fancybox=props['round_edges'],
                shadow=props['shadow'],
                framealpha=props['transparency'],
                title=props['title'],
                borderpad=props['border_padding'],
                labelspacing=props['label_spacing'],
                handlelength=props['marker_size'],
                handletextpad=props['marker_label_padding'],
                columnspacing=props['column_spacing'])

        title = legend.get_title()
        title.set_fontname(props['title_font'])
        title.set_fontsize(props['title_size'])
        title.set_color(props['title_color'])

        for text in legend.get_texts():
            text.set_fontname(props['entries_font'])
            text.set_fontsize(props['entries_size'])
            text.set_color(props['entries_color'])

        legend.set_visible(props['visible'])
        legend_set_draggable(legend, True)
Пример #7
0
 def plot_res(self):
     """
     Plots the resolution in the resolution tab
     """
     overplot = self.widgets['HoldCheck'].isChecked()
     multiplot = self.widgets['MultiRepCheck'].isChecked()
     self._set_overplot(overplot, 'resaxes')
     self._set_overplot(overplot, 'qeaxes')
     inst = self.engine.instname
     freq = self.engine.getFrequency()
     if hasattr(freq, '__len__'):
         freq = freq[0]
     if multiplot:
         if matplotlib.compare_versions('2.1.0', matplotlib.__version__):
             self.resaxes.hold(True)
         for ie, Ei in enumerate(self.eis):
             en = np.linspace(0, 0.95 * Ei, 200)
             if any(self.res[ie]):
                 if not self.flux[ie]:
                     continue
                 line, = self.resaxes.plot(en, self.res[ie])
                 label_text = '%s_%3.2fmeV_%dHz_Flux=%fn/cm2/s' % (
                     inst, Ei, freq, self.flux[ie])
                 line.set_label(label_text)
                 if self.tabs.isTabEnabled(self.qetabID):
                     self.plot_qe(Ei, label_text, hold=True)
                 self.resaxes_xlim = max(Ei, self.resaxes_xlim)
         if matplotlib.compare_versions('2.1.0', matplotlib.__version__):
             self.resaxes.hold(False)
     else:
         ei = self.engine.getEi()
         en = np.linspace(0, 0.95 * ei, 200)
         line, = self.resaxes.plot(en, self.res)
         chopper = self.engine.getChopper()
         label_text = '%s_%s_%3.2fmeV_%dHz_Flux=%fn/cm2/s' % (
             inst, chopper, ei, freq, self.flux)
         line.set_label(label_text)
         if self.tabs.isTabEnabled(self.qetabID):
             self.plot_qe(ei, label_text, overplot)
         self.resaxes_xlim = max(ei, self.resaxes_xlim)
     self.resaxes.set_xlim([0, self.resaxes_xlim])
     legend_set_draggable(self.resaxes.legend(), True)
     self.resaxes.set_xlabel('Energy Transfer (meV)')
     self.resaxes.set_ylabel(r'$\Delta$E (meV FWHM)')
     self.rescanvas.draw()
Пример #8
0
 def plot_flux_ei(self, **kwargs):
     """
     Plots the flux vs Ei in the middle tab
     """
     inst = self.engine.instname
     chop = self.engine.getChopper()
     freq = self.engine.getFrequency()
     overplot = self.widgets['HoldCheck'].isChecked()
     if hasattr(freq, '__len__'):
         freq = freq[0]
     update = kwargs['update'] if 'update' in kwargs.keys() else False
     # Do not recalculate if all relevant parameters still the same.
     _, labels = self.flxaxes2.get_legend_handles_labels()
     searchStr = '([A-Z]+) "(.+)" ([0-9]+) Hz'
     tmpinst = []
     if (labels and (overplot or len(labels) == 1)) or update:
         for prevtitle in labels:
             prevInst, prevChop, prevFreq = re.search(searchStr, prevtitle).groups()
             if update:
                 tmpinst.append(copy.deepcopy(Instrument(self.instruments[prevInst], prevChop, float(prevFreq))))
             else:
                 if inst == prevInst and chop == prevChop and freq == float(prevFreq):
                     return
     ne = 25
     mn = self.minE[inst]
     mx = (self.flxslder.val/100)*self.maxE[inst]
     eis = np.linspace(mn, mx, ne)
     flux = eis*0
     elres = eis*0
     if update:
         self.flxaxes1.clear()
         self.flxaxes2.clear()
         if matplotlib.compare_versions('2.1.0',matplotlib.__version__):
             self.flxaxes1.hold(True)
             self.flxaxes2.hold(True)
         for ii, instrument in enumerate(tmpinst):
             for ie, ei in enumerate(eis):
                 with warnings.catch_warnings(record=True):
                     warnings.simplefilter('always', UserWarning)
                     flux[ie] = instrument.getFlux(ei)
                     elres[ie] = instrument.getResolution(0., ei)[0]
             self.flxaxes1.plot(eis, flux)
             line, = self.flxaxes2.plot(eis, elres)
             line.set_label(labels[ii])
     else:
         for ie, ei in enumerate(eis):
             with warnings.catch_warnings(record=True):
                 warnings.simplefilter('always', UserWarning)
                 flux[ie] = self.engine.getFlux(ei)
                 elres[ie] = self.engine.getResolution(0., ei)[0]
         if overplot:
             if matplotlib.compare_versions('2.1.0',matplotlib.__version__):
                 self.flxaxes1.hold(True)
                 self.flxaxes2.hold(True)
         else:
             self.flxaxes1.clear()
             self.flxaxes2.clear()
         self.flxaxes1.plot(eis, flux)
         line, = self.flxaxes2.plot(eis, elres)
         line.set_label('%s "%s" %d Hz' % (inst, chop, freq))
     self.flxaxes1.set_xlim([mn, mx])
     self.flxaxes2.set_xlim([mn, mx])
     self.flxaxes1.set_xlabel('Incident Energy (meV)')
     self.flxaxes1.set_ylabel('Flux (n/cm$^2$/s)')
     self.flxaxes1.set_xlabel('Incident Energy (meV)')
     self.flxaxes2.set_ylabel('Elastic Resolution FWHM (meV)')
     lg = self.flxaxes2.legend()
     legend_set_draggable(lg, True)
     self.flxcanvas.draw()
Пример #9
0
    def create_legend(cls, props, ax):
        # Imported here to prevent circular import.
        from mantid.plots.datafunctions import get_legend_handles

        loc = ConfigService.getString('plots.legend.Location')
        font_size = float(ConfigService.getString('plots.legend.FontSize'))
        if not props:
            legend_set_draggable(
                ax.legend(handles=get_legend_handles(ax),
                          loc=loc,
                          prop={'size': font_size}), True)
            return

        if 'loc' in props.keys():
            loc = props['loc']

        if int(matplotlib.__version__[0]) >= 2:
            legend = ax.legend(
                handles=get_legend_handles(ax),
                ncol=props['columns'],
                prop={'size': props['entries_size']},
                numpoints=props['markers'],
                markerfirst=props['marker_position'] == "Left of Entries",
                frameon=props['box_visible'],
                fancybox=props['round_edges'],
                shadow=props['shadow'],
                framealpha=props['transparency'],
                facecolor=props['background_color'],
                edgecolor=props['edge_color'],
                title=props['title'],
                borderpad=props['border_padding'],
                labelspacing=props['label_spacing'],
                handlelength=props['marker_size'],
                handletextpad=props['marker_label_padding'],
                columnspacing=props['column_spacing'],
                loc=loc)
        else:
            legend = ax.legend(
                handles=get_legend_handles(ax),
                ncol=props['columns'],
                prop={'size': props['entries_size']},
                numpoints=props['markers'],
                markerfirst=props['marker_position'] == "Left of Entries",
                frameon=props['box_visible'],
                fancybox=props['round_edges'],
                shadow=props['shadow'],
                framealpha=props['transparency'],
                title=props['title'],
                borderpad=props['border_padding'],
                labelspacing=props['label_spacing'],
                handlelength=props['marker_size'],
                handletextpad=props['marker_label_padding'],
                columnspacing=props['column_spacing'],
                loc=loc)

        title = legend.get_title()
        title.set_fontname(props['title_font'])
        title.set_fontsize(props['title_size'])
        title.set_color(props['title_color'])

        for text in legend.get_texts():
            text.set_fontname(props['entries_font'])
            text.set_fontsize(props['entries_size'])
            text.set_color(props['entries_color'])

        legend.set_visible(props['visible'])
        legend_set_draggable(legend, True)
Пример #10
0
    def _update_plot(self):
        """
        Update the plot. This function overplots the memorized data with the
        currently selected workspace and spectrum index. It keeps a memory of
        the last plot and removes it if is not part of the memorised data.
        """
        selection = self._view.get_selection()
        current_spectrum_index = self._view.get_spectrum_slider_position()
        plotted_data = self._model.get_plotted_data()
        mode = self._view.get_mode()

        figure = self._canvas.figure
        axes = figure.gca()
        artists = axes.get_tracked_artists()

        # remove curves not in plotted_data
        for artist in artists:
            ws, sp = axes.get_artists_workspace_and_workspace_index(artist)
            ws_name = ws.name()
            if (ws_name, sp) not in plotted_data:
                axes.remove_artists_if(lambda a: a == artist)
            else:
                label = artist.get_label()
                try:
                    color = artist.get_color()
                except:
                    color = artist.lines[0].get_color()
                self._view.modify_spectrum_label(ws_name, sp, label, color)

        # add selection to plot
        for ws_name, spectra in selection.items():
            if (current_spectrum_index not in spectra
                    and not self._view.is_spectrum_selection_disabled()):
                spectra.append(current_spectrum_index)
            for sp in spectra:
                if sp == -1:
                    continue
                if (ws_name, sp) not in plotted_data:
                    ws = mtd[ws_name]
                    kwargs = {}
                    if mode == self.SPECTRUM_MODE_TEXT:
                        kwargs["axis"] = MantidAxType.SPECTRUM
                        kwargs["specNum"] = ws.getSpectrumNumbers()[sp]
                    else:
                        kwargs["axis"] = MantidAxType.BIN
                        kwargs["wkspIndex"] = sp

                    if self._error_bars:
                        lines = axes.errorbar(ws, **kwargs)
                        label = lines.get_label()
                        color = lines.lines[0].get_color()
                    else:
                        lines = axes.plot(ws, **kwargs)
                        label = lines[0].get_label()
                        color = lines[0].get_color()
                    self._view.modify_spectrum_label(ws_name, sp, label, color)

        if selection or plotted_data:
            axes.set_axis_on()
            try:
                figure.tight_layout()
            except ValueError:
                pass
            legend = axes.legend()
            if legend:
                legend_set_draggable(legend, True)
        else:
            legend = axes.get_legend()
            if legend:
                legend.remove()
            axes.set_axis_off()
            axes.set_title("")
        self._canvas.draw_idle()
Пример #11
0
    def _show_axis_editor(self, event):
        """
        Decides whether to show a dialog to edit axis information based on the contents of the
        event. Shows a dialog if necessary.
        @param event: the object representing the event
        @return: a flag to denote whether an action was taken e.g. opening a dialog.
        """
        # We assume this is used for editing axis information e.g. labels
        # which are outside of the axes so event.inaxes is no use.
        canvas = self.canvas
        figure = canvas.figure
        axes = figure.get_axes()
        action_taken = False

        def move_and_show(editor):
            nonlocal action_taken
            action_taken = True
            editor.move(QCursor.pos())
            editor.exec_()

        for ax in axes:
            if ax.title.contains(event)[0]:
                move_and_show(LabelEditor(canvas, ax.title))
            elif ax.xaxis.label.contains(event)[0]:
                move_and_show(LabelEditor(canvas, ax.xaxis.label))
            elif ax.yaxis.label.contains(event)[0]:
                move_and_show(LabelEditor(canvas, ax.yaxis.label))
            elif (ax.xaxis.contains(event)[0] or any(
                    tick.contains(event)[0] for tick in ax.get_xticklabels())):
                move_and_show(XAxisEditor(canvas, ax))
            elif (ax.yaxis.contains(event)[0] or any(
                    tick.contains(event)[0] for tick in ax.get_yticklabels())):
                if type(ax) == Axes:
                    move_and_show(ColorbarAxisEditor(canvas, ax))
                else:
                    move_and_show(YAxisEditor(canvas, ax))
            elif hasattr(ax, 'zaxis'):
                if ax.zaxis.label.contains(event)[0]:
                    move_and_show(LabelEditor(canvas, ax.zaxis.label))
                elif (ax.zaxis.contains(event)[0] or any(
                        tick.contains(event)[0]
                        for tick in ax.get_zticklabels())):
                    move_and_show(ZAxisEditor(canvas, ax))
            elif ax.get_legend() is not None and ax.get_legend().contains(
                    event)[0]:
                # We have to set the legend as non draggable else we hold onto the legend
                # until the mouse button is clicked again
                legend_set_draggable(ax.get_legend(), False)
                legend_texts = ax.get_legend().get_texts()
                active_lines = datafunctions.get_legend_handles(ax)

                remove_legend_flag = True  # remove the legend if no curve texts were clicked
                for legend_text, curve in zip(legend_texts, active_lines):
                    if legend_text.contains(event)[0]:
                        remove_legend_flag = False
                        move_and_show(LegendEditor(canvas, legend_text, curve))
                legend_set_draggable(ax.get_legend(), True)

                if remove_legend_flag:
                    action_taken = True
                    legend = ax.get_legend()
                    legend.set_visible(False)
                    canvas.draw()

        return action_taken