def prepare_axis(fig: plt.Figure, plot_mode: PlotMode = PlotMode.xy, subplot_arg: int = 111) -> plt.Axes: """ prepares an axis according to the plot mode (for trajectory plotting) :param fig: matplotlib figure object :param plot_mode: PlotMode :param subplot_arg: optional if using subplots - the subplot id (e.g. '122') :return: the matplotlib axis """ if plot_mode == PlotMode.xyz: ax = fig.add_subplot(subplot_arg, projection="3d") else: ax = fig.add_subplot(subplot_arg) if plot_mode in {PlotMode.xy, PlotMode.xz, PlotMode.xyz}: xlabel = "$x$ (m)" elif plot_mode in {PlotMode.yz, PlotMode.yx}: xlabel = "$y$ (m)" else: xlabel = "$z$ (m)" if plot_mode in {PlotMode.xy, PlotMode.zy, PlotMode.xyz}: ylabel = "$y$ (m)" elif plot_mode in {PlotMode.zx, PlotMode.yx}: ylabel = "$x$ (m)" else: ylabel = "$z$ (m)" ax.set_xlabel(xlabel) ax.set_ylabel(ylabel) if plot_mode == PlotMode.xyz: ax.set_zlabel('$z$ (m)') if SETTINGS.plot_invert_xaxis: plt.gca().invert_xaxis() if SETTINGS.plot_invert_yaxis: plt.gca().invert_yaxis() return ax
def plot_with_overlay(img, probas_, fig: plt.Figure = None, figsize=None, **kwargs): if fig is None: fig: plt.Figure = plt.figure(figsize=figsize) ax = fig.add_subplot(1, 3, 1) ax.imshow(img) ax.set_title("Initial image") ax.axis('off') ax = fig.add_subplot(1, 3, 2) ax.imshow(probas_) ax.set_title("Proba map") ax.axis('off') ax = fig.add_subplot(1, 3, 3) ax.imshow(img, extent=[0, 1, 0, 1]) prob_overlay = make_overlay(probas_) ax.imshow(prob_overlay, extent=[0, 1, 0, 1]) ax.set_title("Overlay") ax.axis('off') fig.tight_layout()
def __abc_smc_plotting(fig: plt.Figure, y_obs: [[float]], priors: ["stats.Distribution"], fitting_model: Models.Model, model_hat: Models.Model, accepted_params: [[float]], weights: [float]) -> plt.Figure: n_params = (fitting_model.n_params - 2) if ( type(fitting_model) is Models.SIRModel) else fitting_model.n_params n_rows = max([1, np.lcm(n_params, fitting_model.dim_obs)]) gs = fig.add_gridspec(n_rows, 2) # plot fitted model row_step = n_rows // fitting_model.dim_obs for i in range(fitting_model.dim_obs): ax = fig.add_subplot(gs[i * row_step:(i + 1) * row_step, -1]) y_obs_dim = [y[i] for y in y_obs] Plotting.plot_accepted_observations(ax, fitting_model.x_obs, y_obs_dim, [], model_hat, dim=i) row_step = n_rows // n_params if (type(fitting_model) is Models.SIRModel): for i in range(2, fitting_model.n_params): ax = fig.add_subplot(gs[(i - 2) * row_step:(i - 2 + 1) * row_step, 0]) name = "theta_{}".format(i) accepted_parameter_values = [theta[i] for theta in accepted_params] Plotting.plot_parameter_posterior( ax, name, accepted_parameter_values, predicted_val=model_hat.params[i], prior=priors[i], dim=i, weights=weights) else: for i in range(fitting_model.n_params): ax = fig.add_subplot(gs[i * row_step:(i + 1) * row_step, 0]) name = "theta_{}".format(i) parameter_values = [theta[i] for theta in accepted_params] Plotting.plot_parameter_posterior( ax, name, accepted_parameter_values, predicted_val=model_hat.params[i], prior=priors[i], dim=i, weights=weights) return fig
class Mainwindow(QMainWindow): def __init__(self, parent=None): super(Mainwindow, self).__init__(parent) centralWidget = QWidget() self.setCentralWidget(centralWidget) self.fig = Figure() self.axes = self.fig.add_subplot(111) self.canvas = FigureCanvas(self.fig) self.gridLayout = QGridLayout(centralWidget) self.gridLayout.addWidget(self.canvas) self.btn_plot = QCheckBox("Plot") self.btn_line = QCheckBox("Line") self.gridLayout.addWidget(self.btn_plot, 1, 0, 1, 1) self.gridLayout.addWidget(self.btn_line, 2, 0, 1, 1) self.btn_plot.clicked.connect(self.btnPlot) self.btn_line.clicked.connect(self.btnLine) self.Graphics = Graphics(self.axes) def btnPlot(self): self.Graphics.drawPlot(self.btn_plot.isChecked()) def btnLine(self): self.Graphics.drawLine(self.btn_line.isChecked())
def __plotfit(self, x, y, interplationXdata, fitData, figKwargs: dict = None, fig: Figure = None, ax: Axes = None, showLegend=True, **axKwargs) -> Tuple[Figure, Axes]: """ 绘制源数据和拟合曲线 """ if not fig: fig = plt.figure(**figKwargs) # type:Figure if not ax: ax = fig.add_subplot() # type:Axes ax.plot(x, y, 'r.', interplationXdata, fitData) ax.set(**axKwargs) if showLegend: ax.legend(['original data', 'fitted curve']) # 鼠标点击画布时显示绘制点 fig.canvas.mpl_connect('button_release_event', lambda e: self.__mouseRealseEvent(e, fig, ax)) return (fig, ax)
def _matrix_bar_plot(mat: np.ndarray, z_label: str, fig: plt.Figure, plt_position: int, kets: Sequence[str] = None, title: str = None, ylim: Tuple[int, int] = (-1, 1)) -> None: num_rows, num_cols = mat.shape indices = np.meshgrid(range(num_cols), range(num_rows)) x_indices = np.array(indices[1]).flatten() y_indices = np.array(indices[0]).flatten() z_indices = np.zeros(mat.size) dx = np.ones(mat.size) * 0.3 dy = np.ones(mat.size) * 0.3 ax1 = fig.add_subplot(plt_position, projection='3d') # type: Axes3D dz = mat.flatten() ax1.bar3d(x_indices, y_indices, z_indices, dx, dy, dz, color='#ff0080', alpha=1.0) ax1.set_zlabel(z_label) ax1.set_zlim3d(ylim[0], ylim[1]) if kets is not None: plt.xticks(np.arange(num_cols) + 0.15, kets) plt.yticks(np.arange(num_rows) + 0.15, kets) if title is not None: ax1.set_title(title)
def __init__(self, state: pib.Particle_in_Box_State, fig: plt.Figure, gs=None, pos=[0, 0]) -> None: self._light_color = cs.hls_to_rgb(235 / 360, 0.9, 1) self._dark_color = cs.hls_to_rgb(235 / 360, 0.37, 1) self.fig = fig if gs == None: self.axis = fig.add_subplot() else: self.axis = fig.add_subplot(gs[pos[0], pos[1]]) self._state = state self.expectation_value = False self.res = 300
def initfigs(labelframe): close('all') # destroy all widgets in fram/tab and close all figures for widget in labelframe.winfo_children(): widget.destroy() fig = Figure(frameon=False) axes = [fig.add_subplot(2, 2, i+1) for i in range(4)] xlabs = ['turns', 'time / (ms)', 'time / (ms))', r'square amplitude / $(mm^2)$'] ylabs = ['ADC counts', 'betatron amplitude / (mm)', 'frequency / (kHz)', 'frequency / (kHz)'] stylesets = [['-b'], ['-b', '-r'], ['-b', '-r'], ['-b', '-r']] lines = [] for ax, xlab, ylab, styles in zip(axes, xlabs, ylabs, stylesets): lines.append([ax.plot([], [], style)[0] for style in styles]) ax.set_xlabel(xlab) ax.set_ylabel(ylab) ax.grid(True) canvas = FigureCanvasTkAgg(fig, master=labelframe) canvas._tkcanvas.config(highlightthickness=0) toolbar = NavigationToolbar2TkAgg(canvas, labelframe) canvas.get_tk_widget().pack() toolbar.pack() return fig, axes, lines
def add_dotplots(self, table: pandas.DataFrame, figure: plt.Figure) -> Dict[str, plt.Axes]: """ Adds the individual scatterplots to the figure. """ grid = plt.GridSpec(8, 8) # , hspace = 1) ylimits = (0, table['auc_e'].max() + 100) figure_axes = dict() for label in self.treatment_group_order: logger.info(f"Adding '{label}' to the plot.") categories = self.treatment_groups[label] _t = table[table['condition'].isin(categories)] current_ax = figure.add_subplot(grid[:-1, self.indicies[label]]) current_ax = self.dotplot(table=_t, x='condition', y='auc_e', hue='strain', ax=current_ax) current_ax = self.meanplot(table=_t, x='condition', y='auc_e', hue='strain', ax=current_ax) self.format_subplot(current_ax, label, ylimits=ylimits) figure_axes[label] = current_ax return figure_axes
def discrete_scatterplot(data: pd.DataFrame, x: str, y: str, z: str or None, label: str, cmap: str, size: int or str or None, fig: plt.Figure, **kwargs): """ Scatterplot with discrete label Parameters ---------- data: Pandas.DataFrame x: str y: str z: str, optional label: str cmap: str size: int or str, optional fig: Matplotlib.Figure kwargs: Additional keyword arguments passed to Matplotlib.Axes.scatter call Returns ------- Matplotlib.Axes """ colours = cycle(plt.get_cmap(cmap).colors) data[label] = data[label].astype(str) if z is not None: ax = fig.add_subplot(111, projection="3d") for (l, df), c in zip(data.groupby(label), colours): s = size if isinstance(size, str): s = df[size].values ax.scatter(df[x].values, df[y].values, df[z].values, s=s, color=c, label=l, **kwargs) return ax ax = fig.add_subplot(111) for (l, df), c in zip(data.groupby(label), colours): s = size if isinstance(size, str): s = df[size].values ax.scatter(df[x].values, df[y].values, color=c, label=l, s=s, **kwargs) return ax
def cont_scatterplot(data: pd.DataFrame, x: str, y: str, z: str or None, label: str, cmap: str, size: int or str or None, fig: plt.Figure, cbar_kwargs: dict, **kwargs): """ Scatterplot with continuous label Parameters ---------- data: Pandas.DataFrame x: str y: str z: str, optional label: str cmap: str size: int or str, optional fig: Matplotlib.Figure cbar_kwargs: dict Keyword arguments passed to colorbar kwargs: Additional keyword arguments passed to Matplotlib.Axes.scatter call Returns ------- Matplotlib.Axes """ if isinstance(size, str): size = data[size].values if z is not None: ax = fig.add_subplot(111, projection="3d") im = ax.scatter(data[x].values, data[y].values, data[z].values, c=data[label].values, s=size, cmap=cmap, **kwargs) else: ax = fig.add_subplot(111) im = ax.scatter(data[x].values, data[y].values, c=data[label].values, s=size, cmap=cmap, **kwargs) fig.colorbar(im, ax=ax, **cbar_kwargs) return ax
def map_plot(fig: Figure, source: Origin, reciever: Station, position=221, resolution="110m"): """ Plot a map with a great-circle between source and reciever """ source_lon, source_lat = source.longitude % 360, source.latitude reciever_lon, reciever_lat = reciever.longitude % 360, reciever.latitude proj = ccrs.Mollweide(central_longitude=(source_lon + reciever_lon) / 2) ax = fig.add_subplot(position, projection=proj) ax.set_global() borders = cfeature.NaturalEarthFeature(cfeature.BORDERS.category, cfeature.BORDERS.name, resolution, edgecolor='none', facecolor='none') land = cfeature.NaturalEarthFeature(cfeature.LAND.category, cfeature.LAND.name, resolution, edgecolor='face', facecolor='none') ocean = cfeature.NaturalEarthFeature(cfeature.OCEAN.category, cfeature.OCEAN.name, resolution, edgecolor='face', facecolor='none') # ax.set_axis_bgcolor('1.0') ax.add_feature(ocean, facecolor='1.0') ax.add_feature(land, facecolor='0.8') ax.add_feature(borders, edgecolor='0.75') ax.coastlines(resolution=resolution, color='0.4') ax.gridlines(xlocs=range(-180, 181, 30), ylocs=range(-90, 91, 30)) source_scatter = ax.scatter(source_lon, source_lat, marker="o", s=100, c="red", zorder=10, transform=ccrs.Geodetic(), label="Source") reciever_scatter = ax.scatter(reciever_lon, reciever_lat, marker="v", s=100, c="blue", zorder=10, transform=ccrs.Geodetic(), label="Receiver") # Plot great circle ax.plot([source_lon, reciever_lon], [source_lat, reciever_lat], "k", transform=ccrs.Geodetic()) ax.legend() return fig, ax
def covid_numbers_world(self): """ Gets the numbers of covid-19 cases in the world""" # Create new list to save cases, add every case to the overall list of cases list_to_display = [] end = 3 list_to_display.append("Confirmed cases: " + str(covid_case.get_total_confirmed_cases()) + '\n' + '\n') list_to_display.append("Active cases: " + str(covid_case.get_total_active_cases()) + '\n' + '\n') list_to_display.append("Total recovered: " + str(covid_case.get_total_recovered()) + '\n' + '\n') list_to_display.append("Total deaths: " + str(covid_case.get_total_deaths()) + '\n' + '\n') # Formatting text display into Text Widget for i in range(len(list_to_display)): if i == end: self.text1.config(state=DISABLED) else: for text in list_to_display: self.text1.tag_configure("center", justify='center') self.text1.tag_add("center", "1.0", "end") self.text1.insert(END, text) cases = ['Confirmed', 'Active', 'Recovered', 'Deaths'] numbers = [ covid_case.get_total_confirmed_cases(), covid_case.get_total_active_cases(), covid_case.get_total_recovered(), covid_case.get_total_deaths() ] # Creating figure figure = Figure(figsize=(5, 4), dpi=80) # Plot the graph inside the figure plot = figure.add_subplot(1, 1, 1) plot.bar(cases, numbers) plot.set_title("Worldwide", fontsize=12) plot.set_xlabel('Cases', fontsize=10) plot.set_ylabel('Numbers', fontsize=10) # Creating canvas fig_to_canvas = FigureCanvasTkAgg(figure, self.canvas1) fig_to_canvas.draw() get_the_drawing = fig_to_canvas.get_tk_widget() get_the_drawing.pack(fill=BOTH, expand=True)
def __init__(self, fig: plt.Figure, directed=False): fig.clear() self.fig = fig self.can = fig.canvas self.ax = fig.add_subplot(aspect="equal") self.directed = directed self.ui_nodes: List[NodeUi] = [] self.selected = None return
def __init__(self, parent=None, width=5.0, height=4.0, dpi=100): fig = Figure((width, height), dpi=dpi) self.axes = fig.add_subplot(1, 1, 1) FigureCanvas.__init__(self, fig) self.setParent(parent) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.updateGeometry() self.plot()
def get_new_axis(self, figure: plt.Figure, gridspecsubplot: int) -> plt.axes: ax = figure.add_subplot(gridspecsubplot) ax.tick_params(axis='x', colors='gray') ax.tick_params(axis='y', colors='gray') if self.show_x_axis: ax.xaxis.tick_top() else: plt.xticks([]) plt.box(on=None) return ax
def plot_cfg_barplot(fig: plt.Figure, commit_report: tp.Optional[CommitReport], draw_cf: bool, cr_meta: tp.Optional[CommitReportMeta]) -> None: """Generates a bar plot that visualizes the IN/OUT control-flow/data-flow edges of regions.""" if commit_report is None: return ylimit = None if draw_cf: data = generate_inout_cfg_cf(commit_report, cr_meta) color_palette = sns.color_palette(["#004949", "#920000"]) if cr_meta is not None: ylimit = cr_meta.cf_ylimit else: data = generate_inout_cfg_df(commit_report, cr_meta) color_palette = sns.color_palette(["#006DDB", "#920000"]) if cr_meta is not None: ylimit = cr_meta.df_ylimit if data.empty: LOG.error("CommitReport has no CF interactions") return data['Region'] = data['Region'].apply(lambda x: x[0:6]) plt.figure(fig.number) plt.clf() if ylimit is not None: plt.ylim(0, ylimit) bar_p = sns.barplot(x="Region", y="Amount", hue="Direction", data=data, palette=color_palette) for label in bar_p.get_xticklabels(): label.set_rotation(90) label.set_family("monospace") fig.add_subplot(bar_p)
def show_simplicial_complex(self, x: ndarray, y: ndarray, C, f: plt.Figure, rows, cols, i, titl): ambient_dim = x.shape[1] if ambient_dim == 2: ax = f.add_subplot(rows, cols, i) elif ambient_dim == 3: ax = Axes3D(f) self._complex_fig_common(ax, x, y, C, titl) return 1
def approach_layout(self): begin_stop_var = tk.IntVar() begin_stop_var.set(0) frame_param = tk.Frame(self.tab_approach, bg='grey', width=500, height=1080) frame_param.pack(side='left', fill='y', expand='no') frame_figure = tk.Frame(self.tab_approach, bg='beige', width=1400, height=1080, padx=4) frame_figure.pack(expand='yes', fill='both') #开始进针,快速退针,直接退出进针 plot_fig_var = tk.IntVar() plot_fig_var.set(0) begin_button = tk.Button( frame_param, text='begin', width=10, command=lambda: function.approach_thread( self.max_sigin, self.device, self.daq, canvas, aix1, begin_stop_var, self.setpoint, plot_fig_var)) begin_button.grid(row=1, column=1) fast_quit_button = tk.Button(frame_param, text='fast_q/100nm', width=10, command=lambda: function.fast_quit()) fast_quit_button.grid(row=2, column=1) quit_button = tk.Button(frame_param, text='quit', width=10, command=lambda: function.quit_approach( self.device, self.daq, begin_stop_var)) quit_button.grid(row=3, column=1) ##创建画布和轴 fig = Figure(figsize=(5, 5), dpi=100) canvas = FigureCanvasTkAgg(figure=fig, master=frame_figure) aix1 = fig.add_subplot(111) canvas.get_tk_widget().pack(side='top', fill='both', expand=1) canvas.draw() toobar = NavigationToolbar2Tk(canvas, frame_figure) toobar.update() ##测试 list = [1, 2, 3, 4, 5] aix1.plot(list, list)
def createTab1(self): topframe = tk.Frame(self.tab1, height=80) #contentframe = tk.Frame(tab1) topframe.pack(side=tk.TOP) #contentframe.pack(side = tk.TOP) OrdersButton = tk.Menubutton(topframe, text='Orders') #OrdersButton.pack() ordersMenu = tk.Menu(OrdersButton, tearoff=False) ordersMenu.add_command(label='EDA1', command=self.oeda1) ordersMenu.add_command(label='EDA2', command=self.oeda2) ordersMenu.add_command(label='EDA3', command=self.oeda3) ordersMenu.add_command(label='EDA4', command=self.oeda4) OrdersButton.config(menu=ordersMenu) ProductsButton = tk.Menubutton(topframe, text='Products') #ProductsButton.pack() productsMenu = tk.Menu(ProductsButton, tearoff=False) productsMenu.add_command(label='EDA1', command=self.peda1) productsMenu.add_command(label='EDA2', command=self.peda2) productsMenu.add_command(label='EDA3', command=self.peda3) productsMenu.add_command(label='EDA4', command=self.peda4) ProductsButton.config(menu=productsMenu) OrdersButton.grid(row=0, column=0, sticky=tk.W) ProductsButton.grid(row=0, column=1) fig1 = Figure(figsize=(5, 4), dpi=100) self.ax1 = fig1.add_subplot(111) self.canvas1 = FigureCanvasTkAgg(fig1, master=self.tab1) self.canvas1.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=1) self.canvas1._tkcanvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1) fig2 = Figure(figsize=(5, 4), dpi=100) self.ax2 = fig2.add_subplot(111) self.canvas2 = FigureCanvasTkAgg(fig2, master=self.tab1) self.canvas2.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.canvas2._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
def latticeplot(optic, diagnostics, size=None): ymin, ymax = 0, 100 fig = Figure(frameon=False) if size is not None: fig.set_figwidth(size[0]) fig.set_figheight(size[1]) ax = fig.add_subplot(111) drawlattice(ax, optic, diagnostics, [ymin, ymax], .3, checkconf=False) s = cumsum(optic[1, :]) ax.set_xlim(0, s[-1]) ax.set_ylim(ymin, ymax) ax.axis('off') ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) return fig
def a(): #fig = matplotlib.pyplot.Figure() f = Figure(figsize=(5,4), dpi=100) ax = f.add_subplot(111) # create matplotlib canvas using `fig` and assign to widget `top` #canvas = FigureCanvasTkAgg(fig,master=root) # get canvas as tkinter widget and put in widget `top` #canvas.get_tk_widget().place(x=350,y=200) # create toolbar #toolbar = NavigationToolbar2TkAgg(canvas,top) #toolbar.update() #canvas._tkcanvas.pack() data1=[] for i in range(1,11): workbook = xlrd.open_workbook('data1.xlsx') worksheet = workbook.sheet_by_index(0) data2 = worksheet.cell(i, 0).value print data2 data1.append(data2) #data = { # 'Gender':[1, 2, 3,4,5,6,7,8,9,10], # 'data1' , # } #df = pd.DataFrame(data) #x = 'Gender' #y = 'data1' #new_df = df[[x, y]].groupby(x).sum() # create first place for plot #ax = fig.add_subplot(111) # draw on this plot #new_df.plot(kind='bar', legend=False, ax=ax) ind = (1532,1533,1534,1535,1536,1537,1538,1539,1540,1541) # the x locations for the groups width = .4 print data1 rects1 = ax.bar(ind , data1 , width) canvas = FigureCanvasTkAgg(f, master=root) canvas.show() canvas.get_tk_widget().place(x=350,y=250)
def ray_plot(fig: Figure, source: Origin, reciever: Station, phases: list = None, position=223): """ Use TauP to make a plot of predicted ray-paths. """ phases = phases or DEFAULT_PHASES ax = fig.add_subplot(position, projection="polar") degrees_dist = locations2degrees(reciever.latitude, reciever.longitude, source.latitude, source.longitude) arrivals = MODEL.get_ray_paths(source_depth_in_km=source.depth / 1000.0, distance_in_degree=degrees_dist, phase_list=phases) arrivals.plot_rays(ax=ax, legend=True, show=False) return fig, ax
def c(): f = Figure(figsize=(5,4), dpi=100) ax = f.add_subplot(111) data1=[] for i in range(1,5): workbook = xlrd.open_workbook('data1.xlsx') worksheet = workbook.sheet_by_index(0) data2 = worksheet.cell(i, 0).value print data2 data1.append(data2) #data = { ind = ('western','eastern','northern','southern') # the x locations for the groups width = .5 rects1 = ax.bar(ind, data1, width) canvas = FigureCanvasTkAgg(f, master=root) canvas.show() canvas.get_tk_widget().place(x=350,y=250)
def __init__(self, parent=None, width=5, height=4, dpi=100): fig = Figure(figsize=(width, height), dpi=dpi) # self.axes = fig.add_subplot(111,projection='3d') self.axes = fig.add_subplot(111) #self.axes.hold(True) self.compute_initial_figure() # FigureCanvas.__init__(self, fig) self.setParent(parent) self.fig = fig FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding) FigureCanvas.updateGeometry(self)
def createTab3(self): self.ft2 = tkFont.Font(size=18) tk.Label(self.tab3, text='Select Model:').pack() self.models = ttk.Combobox(self.tab3, values=[ 'Logistic Regression', 'k-NearestNeighbor', 'Random Forest' ]) self.models.pack() tk.Button(self.tab3, text='Show Result', command=self.show_result).pack() fig3 = Figure(figsize=(5, 4), dpi=100) self.ax1 = fig3.add_subplot(111) self.canvas3 = FigureCanvasTkAgg(fig3, master=self.tab3) self.canvas3.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.canvas3._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1) self.modelText = tk.Text(self.tab3) self.modelText.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
def saveplot(self,filename,**kwargs): dpi = kwargs.pop('dpi',72) format = kwargs.pop('format','png') backend_canvas = kwargs.pop('backend_canvas',FigureCanvasAgg) ins_orig = mpl.rcParams['svg.image_noscale'] mpl.rcParams['svg.image_noscale'] = True fig = Figure() canvas = backend_canvas(fig) ax = fig.add_subplot(111) self.plot(axes=ax,**kwargs) fig.savefig(filename,dpi=dpi,format=format) # Put svg image config back to original #mpl.rcParams['svg.embed_char_paths'] = ecp_orig mpl.rcParams['svg.image_noscale'] = ins_orig return filename
def update_image(self): """ Update the canvas with the next image in the sequence Returns ------- None. """ fig = Figure(figsize=(5, 5)) self.ax = fig.add_subplot(111) self.imname = self.images[self.img_idx] self.image = imread(self.imname) try: self.ax.imshow(self.image, cmap='viridis') except TypeError: self.current_slice = 0 self.max_slice = self.image.shape[0] - 1 self.ax.imshow(self.image[self.current_slice], cmap='viridis') self.ax.axis("off") self.canvas = FigureCanvasTkAgg(fig, master=self.master) self.canvas.get_tk_widget().pack()
def draw_calibration(cls, profile: IRProfile, geo_mapper: GeoMapper, farm: Station, matrix: TransformMatrix, fig: plt.Figure): """ return a figure to show the calibration results, mainly for results verification :param profile: an ir profile to calibrate :param geo_mapper: geo mapper of the ir profile :param farm: a station that the profile will calibrate to :param matrix: affine transformation matrix (a, b, d, e, xoff, yoff) :param fig: a matplotlib figure to draw :return: None """ ax = fig.add_subplot(111) ax.set_aspect("equal") profile_polygons = list() for group in profile.panel_groups: poly = group.polygon utms = [geo_mapper.pixel2utm(row=x[0], col=x[1]) for x in poly] profile_polygons.append(Polygon([(x[0], x[1]) for x in utms])) profile_polygons = MultiPolygon(profile_polygons) # plot profile polygons for p in profile_polygons: cls._plot_polygon(ax, p, color="r") gps = geo_mapper.pixel2gps(int(profile.height/2), int(profile.width/2)) # ground truth panel group polygon group_poly = MultiPolygon([group.polygon for group in farm.panel_groups if group.distance_to_gps(gps) < 20]) for p in group_poly: cls._plot_polygon(ax, p, color="b") # transformed polygons out = affine_transform(profile_polygons, matrix) for p in out: cls._plot_polygon(ax, p, color="g")
def inflate(self, figure: plt.Figure, n_subplots: int, subplot_kwargs: tp.Dict[str, tp.Any]) \ -> tp.Iterable[plt.Axes]: orientation = self._orientation get_subplot_positional_args = self.__subplot_args_by_orientation[ orientation] prev_subplot = None for subplot_ix in range(n_subplots): subplot_positional_args = get_subplot_positional_args( n_subplots, subplot_ix) # noinspection SpellCheckingInspection subplot = figure.add_subplot( *subplot_positional_args, **{ **subplot_kwargs, 'sharex': prev_subplot if self.share_x else None, 'sharey': prev_subplot if self.share_y else None }) yield subplot prev_subplot = subplot
def ax(self, fig: plt.Figure = None) -> axes.Axes: """ Plots calculated moving ranges (y axis) versus the index of the dataframe (x axis) Examples -------- Example 1, minimal mR control chart ---------------------------------- >>> import matplotlib.pyplot as plt >>> from datasense import control_charts as cc >>> figsize = (8, 6) >>> graph_name = 'graph_mr.svg' >>> data = ds.random_data( >>> distribution='norm', >>> size=42, >>> loc=69, >>> scale=13 >>> ) >>> data = pd.DataFrame( >>> data=data, >>> columns=['X'] >>> ) >>> fig = plt.figure(figsize=figsize) >>> mr = cc.mR(data=data) >>> ax = mr.ax(fig) >>> fig.savefig(fname=graph_name) Example 2, complete mR control chart ----------------------------------- >>> import matplotlib.pyplot as plt >>> from datasense import control_charts as cc >>> figsize = (8, 6) >>> graph_name = 'graph_mr.svg' >>> data = ds.random_data( >>> distribution='norm', >>> size=42, >>> loc=69, >>> scale=13 >>> ) >>> data = pd.DataFrame( >>> data=data, >>> columns=['X'] >>> ) >>> mr = cc.mR(data=data) >>> ax = mr.ax(fig) >>> cc.draw_rule(mr, ax, *cc.points_one(mr), '1') >>> ax.set_title( >>> label=mr_chart_title, >>> fontweight='bold' >>> ) >>> ax.set_ylabel(ylabel=mr_chart_ylabel) >>> ax.set_xlabel(xlabel=mr_chart_xlabel) >>> fig.savefig(fname=graph_name) """ if fig is None: fig = plt.figure() ax = fig.add_subplot(111) _despine(ax) ax.plot(self.y.index, self.y, marker='o', markersize=3, color=colour2) # TODO? ax.set_xlim(0, len(self._df.columns)) ax.axhline(y=self.mean, color=colour3) ax.axhline(y=self.ucl, color=colour1) ax.axhline(y=self.lcl, color=colour1) return ax
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.hsv_color = colorsys.rgb_to_hsv(0.0, 0.0, 1.0) self.hex_color = '#0000ff' self.color_list = ["red","blue","green","orange","purple"] self.parent = parent print "Loading model..." self.lux = Lux() fp = open(curdir+"/gauss_model.pkl"); self.gm = pickle.load(fp); fp.close() fp = open(curdir+"/memoized_binomial_data.pkl"); self.curve_data = pickle.load(fp); fp.close() fp = open(curdir+"/sampling_normalizer.pkl"); self.normalizer = pickle.load(fp); fp.close() print "Creating UI" self.initUI() self.update_output() self.replot() def update_output(self): (h, s, v) = self.hsv_color self.hsv_var.set("Hue: \t %2.1f \nSat:\t %2.1f \nValue:\t %2.1f" % (h*360,s*100,v*100)) items = self.lux.full_posterior((h * 360, s * 100, v * 100)) self.current_post = items desc = [ '{:<25} ({:.3f})\n'.format(items[i][0], items[i][1]) for i in range(25) ] self.display.config(state=NORMAL) self.display.delete(0, END) for i in range(25): self.display.insert(END, '{:<20} ({:.3f})'.format(items[i][0], items[i][1])) self.display.select_set(0, 0) def plot_lux_model(self, params,ax1,label,support,dim): cur_color='black' mu1,sh1,sc1,mu2,sh2,sc2 = params left_stach=gam_dist(sh1,scale=sc1); lbounds=left_stach.interval(0.99) right_stach=gam_dist(sh2,scale=sc2); rbounds=right_stach.interval(0.99) lx=np.linspace(mu1,-180); rx=np.linspace(mu2,360) s=3; ax1.plot(rx, [right_stach.sf(abs(y-mu2)) for y in rx],linewidth=s,c=cur_color); ax1.plot([1.01*mu1,0.99*mu2], [1.,1.], linewidth=s,c=cur_color) return ax1.plot(lx,[left_stach.sf(abs(y-mu1)) for y in lx],c=cur_color, linewidth=s); def plot_gm_model(self, params, ax, label, support): s=3 x = np.linspace(support[0],support[1],360) return ax.plot(x,norm.pdf(x,params[0],params[1]),c='red', linewidth=s), norm.pdf([params[0]],params[0],[params[1]])[0] def initUI(self): self.parent.title("Interactive LUX visualization") self.pack(fill=BOTH, expand=1) self.color_frame = Frame(self, border=1) self.color_frame.pack(side=LEFT) probe_title_var = StringVar(); probe_title_label = Label(self.color_frame, textvariable=probe_title_var, justify=CENTER, font = "Helvetica 16 bold italic") probe_title_var.set("Color Probe X"); probe_title_label.pack(side=TOP) self.hsv_var = StringVar() self.hsv_label = Label(self.color_frame, textvariable=self.hsv_var,justify=LEFT) h,s,v = self.hsv_color self.hsv_var.set("Hue: %2.1f \nSaturation: %2.1f \nValue: %2.1f" % (h*360,s*100,v*100)) self.hsv_label.pack(side=TOP) self.frame = Frame(self.color_frame, border=1, relief=SUNKEN, width=200, height=200) self.frame.pack(side=TOP) self.frame.config(bg=self.hex_color) self.frame.bind("<Button-1>",self.onChoose) self.btn = Button(self.color_frame, text="Select Color", command=self.onChoose) self.btn.pack(side=TOP) posterior_title_var = StringVar(); posterior_title_label = Label(self.color_frame, textvariable=posterior_title_var, justify=CENTER, font = "Helvetica 16 bold italic") posterior_title_var.set("\n\nLUX's Posterior"); posterior_title_label.pack(side=TOP) Label(self.color_frame, text="Double click to show details \n(Wait time dependent on computer)").pack(side=TOP) my_font = tkFont.Font(family="Courier", size=10) self.display = Listbox(self.color_frame, border=1, relief=SUNKEN, width=30, height=25, font=my_font) self.display.pack(side=TOP,fill=Y,expand=1) self.display.bind("<Double-Button-1>",self.onSelect) self.display_btn = Button(self.color_frame, text="Show details", command=self.onSelect) self.display_btn.pack(side=TOP) self.update_output() self.fig = Figure(figsize=(10,4), dpi=100) self.canvas = FigureCanvasTkAgg(self.fig, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=LEFT, fill=BOTH, expand=1) self.canvas._tkcanvas.pack(side='top', fill='both', expand=1) def replot(self): def gb(x,i,t): #t is max value, i in number of bins, x is the thing to be binned if x==t: return i-1 elif x==0.0: return 0 return int(floor(float(x)*i/t)) hsv_title = [] j=self.display.curselection()[0] name = self.current_post[j][0] mult = lambda x: reduce(operator.mul, x) g_labels = []; lux_labels=[]; all_g_params=[] for i in range(3): def align_yaxis(ax1, v1, ax2, v2): """adjust ax2 ylimit so that v2 in ax2 is aligned to v1 in ax1""" _, y1 = ax1.transData.transform((0, v1)) _, y2 = ax2.transData.transform((0, v2)) inv = ax2.transData.inverted() _, dy = inv.transform((0, 0)) - inv.transform((0, y1-y2)) miny, maxy = ax2.get_ylim() ax2.set_ylim(miny, maxy+dy) subplot = self.fig.add_subplot(4,1,i+1) dim_label = ["H", "S","V"][i] subplot.set_ylabel(r"$P(k^{true}_{%s}|x)$" % ["H", "S","V"][i] ) curve_data = self.curve_data[name][i] scale = lambda x,a=0.3,b=0.9: (b-a)*(x)+a p_x = lambda x: self.normalizer[i][gb(x,len(self.normalizer[i]),[360,100,100][i])] max_p_x = max(self.normalizer[i]) #1 is white, 0 is black. so we want highly probable thigns to be black.. if self.lux.get_adj(self.current_post[j][0]): support = [[-180,180], [0,100],[0,100]][i] pp = lambda x,i: x-360 if i==0 and x>180 else x hacky_solution = [360,100,100][i] w = 1.5 if i==0 else 1 conv = lambda x: x*support[1]/len(curve_data) bar_colors = ["%s" % (scale(1-p_x(conv(x))/max_p_x)) for x in range(len(curve_data))] bar1 = subplot.bar([pp(atan2(sin((x*hacky_solution/len(curve_data))*pi/180),cos((x*hacky_solution/len(curve_data))*pi/180))*180/pi,i) for x in range(len(curve_data))],[x/max(curve_data) for x in curve_data], label="%s data" % j,ec="black",width=w,linewidth=0,color=bar_colors) else: support = [[0,360], [0,100],[0,100]][i] w = 1.5 if i==0 else 1 conv = lambda x: x*support[1]/len(curve_data) bar_colors = ["%s" % (scale(1-p_x(conv(x))/max_p_x)) for x in range(len(curve_data))] bar1 = subplot.bar([x*support[1]/len(curve_data) for x in range(len(curve_data))],[x/max(curve_data) for x in curve_data], label="%s data" % name[0],ec="black",width=w,linewidth=0,color=bar_colors) pp = lambda x,*args: x point = pp(self.hsv_color[i]*[360,100,100][i],i) hsv_title.append(point) probeplot = subplot.plot([point,point], [0,1],linewidth=3,c='blue',label="Probe") #for j in range(5): lux_plot = self.plot_lux_model(self.lux.get_params(self.current_post[j][0])[i], subplot, self.current_post[j][0],support, i) subplot2 = subplot.twinx() gm_plot,gm_height = self.plot_gm_model([pp(g_param,i) for g_param in self.gm[self.current_post[j][0]][0][i]], subplot2, self.current_post[j][0], support) extra = Rectangle((0, 0), 1, 1, fc="w", fill=False, edgecolor='none', linewidth=0) subplot.legend([extra], [["Hue", "Saturation", "Value"][i]],loc=2,frameon=False) if i==0: legend_set=lux_plot+[extra,extra,extra]+gm_plot+[extra,extra,extra] lux_params = self.lux.get_params(self.current_post[j][0])[i] g_params = [pp(g_param,i) for g_param in self.gm[self.current_post[j][0]][0][i]] all_g_params.append(g_params) g_labels.append(r"$\mu^{%s}=$%2.2f, $\sigma^{%s}$=%2.2f" % (dim_label, g_params[0],dim_label,g_params[1])) #lux_labels.append(r"$\mu^{L,%s}=$%2.2f, $E[\tau^{L,%s}]$=%2.2f, $\alpha^{L,%s}$=%2.2f, $\beta^{L,%s}$=%2.2f, $\mu^{U,%s}=$%2.2f, $E[\tau^{L,%s}]$=%2.2f, $\alpha^{U,%s}$=%2.2f, $\beta^{U,%s}$=%2.2f" % (dim_label, lux_params[0],dim_label, (lux_params[0]-lux_params[1]*lux_params[2]),dim_label,lux_params[1],dim_label, lux_params[2],dim_label,lux_params[3],dim_label,(lux_params[3]+lux_params[4]*lux_params[5]),dim_label, lux_params[4],dim_label,lux_params[5])) lux_labels.append(r"$\mu^{L,%s}=$%2.2f, $\alpha^{L,%s}$=%2.2f, $\beta^{L,%s}$=%2.2f, $\mu^{U,%s}=$%2.2f, $\alpha^{U,%s}$=%2.2f, $\beta^{U,%s}$=%2.2f" % (dim_label, lux_params[0],dim_label, lux_params[1],dim_label, lux_params[2],dim_label,lux_params[3],dim_label,lux_params[4],dim_label,lux_params[5])) subplot.set_xlim(support[0],support[1]) subplot.set_ylim(0,1.05) subplot2.set_xlim(support[0],support[1]) subplot2.set_ylabel(r"$P(x|Gaussian_{%s})$" % ["H", "S","V"][i]) align_yaxis(subplot, 1., subplot2, gm_height) leg_loc =(0.9,0.2) datum = [x*[360,100,100][i] for i,x in enumerate(self.hsv_color)]; phi_value = self.lux.get_phi(datum,self.current_post[j][0]) #gauss_value = mult([norm.pdf(datum[i],all_g_params[i][0],all_g_params[i][1]) for i in range(3)]) leg=self.fig.legend(probeplot+legend_set, ["Probe X"]+ [r"$\mathbf{\phi}_{%s}(X)=\mathbf{%2.5f}$; $\mathbf{\alpha}=\mathbf{%2.4f}$" % (self.current_post[j][0],phi_value,self.lux.get_avail(self.current_post[j][0]))]+lux_labels+ [r"$Normal^{Hue}_{%s}$; $prior(%s)=%2.4f$" % (self.current_post[j][0],self.current_post[j][0], self.gm[self.current_post[j][0]][2])]+[g_labels[0]+"; "+g_labels[1]+"; "+g_labels[2]] , loc=8, handletextpad=4,labelspacing=0.1) self.fig.suptitle("%s" % name, size=30) print "done replotting" def onChoose(self, *args): try: ((red,green,blue), hx) = tkColorChooser.askcolor() except: print "I think you hit cancel" return self.hex_color = hx self.hsv_color = colorsys.rgb_to_hsv(red/255.0, green/255.0, blue/255.0) self.frame.config(bg=hx) self.update_output() self.fig.clear() self.replot() self.canvas.draw() def onSelect(self, *args): self.fig.clear() self.replot() self.canvas.draw()
class DoubleSliderTestApp: def __init__(self, width, height): self.root = Tk.Tk() self.root.wm_title("Double Slider Test") self.plot = Figure(figsize = (width+1, height+2), dpi=72) self.axes = self.plot.add_subplot(111) self.canvas = FigureCanvasTkAgg(self.plot, master=self.root) self.canvas.get_tk_widget().grid(row=0) self.nav_plot = Figure(figsize = (width+1, 2), dpi=72) self.nav_axes = self.nav_plot.add_subplot(111) self.nav_canvas = FigureCanvasTkAgg(self.nav_plot, master=self.root) self.nav_canvas.get_tk_widget().grid(row=1) self.nav_plot.subplots_adjust(bottom=0.2) self.agg_canvas = self.nav_canvas.get_tk_widget() self.slider = DoubleSlider(self.root, round=lambda x: round(x, 2), left_bound=2.0, right_bound=3.0) self.slider.grid(row=2, sticky=Tk.W+Tk.E+Tk.N+Tk.S) data = [(2.0, 0.6), (2.1, 0.9), (2.2, 0.7), (2.3, 0.8), (2.4, 0.5), (2.6, 0.2), (2.7, 0.3), (2.8, 0.6), (2.9, 0.4), (3.0, 0.1)] self.axes.set_xbound(2.0, 3.0) self.axes.add_collection(LineCollection([data])) self.nav_axes.set_xbound(2.0, 3.0) self.nav_axes.add_collection(LineCollection([data])) def run(self): self.plot.canvas.draw() self.nav_plot.canvas.draw() left_pad = self.nav_plot.subplotpars.left * self.nav_plot.get_figwidth() * self.nav_plot.dpi right_pad = (1-self.nav_plot.subplotpars.right) * self.nav_plot.get_figwidth() * self.nav_plot.dpi self.slider.config(left_padding=left_pad, right_padding=right_pad) def update_limits(left, right): self.agg_canvas.delete("OVERLAY") trans = blended_transform_factory(self.nav_axes.transData, self.nav_axes.transAxes) corner1 = trans.transform_point([left, 1]).tolist() corner2 = trans.transform_point([self.slider.left_bound, 0]).tolist() self.agg_canvas.create_rectangle([corner1, corner2], stipple="gray25", fill="gray",tags="OVERLAY") corner3 = trans.transform_point((right, 1)).tolist() corner4 = trans.transform_point((self.slider.right_bound, 0)).tolist() self.agg_canvas.create_rectangle([corner3, corner4], stipple="gray25", fill="gray",tags="OVERLAY") self.axes.set_xbound(left, right) self.plot.canvas.draw() self.slider.config(on_change=update_limits) self.slider.init() self.root.mainloop()
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.hsv_color = colorsys.rgb_to_hsv(0.0, 0.0, 1.0) self.hex_color = '#0000ff' self.color_list = ["red","blue","green","orange","purple"] self.parent = parent print "Getting Model" self.lux = lux.LUX("lux.xml") print "Creating UI" self.initUI() self.update_output() def update_output(self): (h, s, v) = self.hsv_color items = self.lux.full_posterior((h * 360, s * 100, v * 100)) self.current_post = items desc = [ '{} ({:.3f})\n'.format(items[i][0], items[i][1]) for i in range(25) ] self.display.config(state=NORMAL) self.display.delete(1.0, END) self.display.insert(END, ''.join(desc)) self.display.config(state=DISABLED) def make_plotter(self, params,ax1,label,cur_color,support): mu1,sh1,sc1,mu2,sh2,sc2 = params left_stach=gam_dist(sh1,scale=sc1); lbounds=left_stach.interval(0.99) right_stach=gam_dist(sh2,scale=sc2); rbounds=right_stach.interval(0.99) lx=np.linspace(mu1,-180); rx=np.linspace(mu2,360) s=3; #cur_color='black' ax1.plot(rx, [1-right_stach.cdf(abs(y-mu2)) for y in rx],linewidth=s,c=cur_color); ax1.plot([1.01*mu1,0.99*mu2], [1,1], linewidth=s,c=cur_color) return ax1.plot(lx,[1-left_stach.cdf(abs(y-mu1)) for y in lx],c=cur_color, label=r"$\phi^{Hue}_{%s}$" % label,linewidth=s); def initUI(self): self.parent.title("Interactive LUX visualization") self.pack(fill=BOTH, expand=1) self.color_frame = Frame(self, border=1) self.color_frame.pack(side=LEFT) self.frame = Frame(self.color_frame, border=1, relief=SUNKEN, width=100, height=100) #self.frame.place(x=160, y=30) self.frame.pack(side=TOP) self.frame.config(bg=self.hex_color) self.btn = Button(self.color_frame, text="Select Color", command=self.onChoose) self.btn.pack(side=TOP) #self.btn.place(x=30, y=30) self.display = Text(self, border=1, relief=SUNKEN, width=30, height=5) #self.display.place(x=280, y=30) self.display.pack(side=LEFT,fill=Y,expand=1) self.update_output() self.fig = Figure(figsize=(10,4), dpi=100) self.replot() self.canvas = FigureCanvasTkAgg(self.fig, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=LEFT, fill=BOTH, expand=1) self.canvas._tkcanvas.pack(side='top', fill='both', expand=1) def replot(self): hsv_title = [] for i in range(3): if self.lux.get_adj(self.current_post[0][0]): support = [[-180,180], [0,100],[0,100]][i] pp = lambda x,i: x-360 if i==0 and x>180 else x else: support = [[0,360], [0,100],[0,100]][i] pp = lambda x,*args: x subplot = self.fig.add_subplot(3,1,i+1) subplot.set_xlim(support[0],support[1]) subplot.set_ylabel("%s" % ["Hue", "Saturation","Value"][i]) point = pp(self.hsv_color[i]*[360,100,100][i],i) hsv_title.append(point) probeplot = subplot.plot([point,point], [0,1],linewidth=3,c='black',label="Probe") legend_set = [] for j in range(5): test = self.make_plotter(self.lux.get_params(self.current_post[j][0])[i], subplot, self.current_post[j][0],self.color_list[j],support) if type(test)==type([]): legend_set+=test else: legend_set.append(test) self.fig.legend(legend_set, [r"$\phi_{%s}$; $\alpha=%2.4f$" % (x[0],self.lux.get_avail(x[0])) for x in self.current_post[:5]], loc=1) self.fig.suptitle("HSV (%2.2f,%2.2f,%2.2f) top 5 Phi curves" % (hsv_title[0],hsv_title[1],hsv_title[2])) def onChoose(self): ((red,green,blue), hx) = tkColorChooser.askcolor() self.hex_color = hx self.hsv_color = colorsys.rgb_to_hsv(red/255.0, green/255.0, blue/255.0) self.frame.config(bg=hx) self.update_output() self.fig.clear() self.replot() self.canvas.draw()
class HistoricalViewerApp: line_styles = ["solid"] colors = [ (0.0, 0.0, 1.0, 1.0), #Blue (1.0, 0.0, 0.0, 1.0), #Red (0.0, 1.0, 0.0, 1.0), #Green (1.0, 1.0, 0.0, 1.0) ] def __init__(self, width, height): self.path = config.find_options("general.cfg")['database'] self.descriptors = config.find_graphs("graphs.cfg") self.data = {} self.collections = {} self.nav_collections = {} self.color_map = {} self.connection = sql.connect(self.path, detect_types=(sql.PARSE_COLNAMES|sql.PARSE_DECLTYPES)) self.root = Tk.Tk() self.root.wm_title("Historical Data Viewer") self.intervals = self.connection.execute("SELECT * FROM intervals ORDER BY start;").fetchall() self.intervals = list(reversed(self.intervals)) #Grid layout: # Col 0 Col 1 # +------------+------+ # Row 0 | | ITVL | # | ZOOM | SLCT | # | - -GRAPH- -+------+ # Row 1 | | DATA | # | | SLCT | # +------------+------+ # Row 2 | NAV GRAPH | ZOOM | # | | SLCT | # +------------+------+ #Setup for the Tk/Agg plotting backend self.figure = Figure(figsize = (width+1, height+2), dpi = 100) self.figure.subplots_adjust(bottom=0.15) self.axes = self.figure.add_subplot(111, autoscale_on=True) self.axes.xaxis.labelpad *= 3 self.canvas = FigureCanvasTkAgg(self.figure, master=self.root) self.canvas.get_tk_widget().grid(row=0, column=0, rowspan=2) #Setup for the mini-navigation figure self.nav_figure = Figure(figsize = ((width+1)*1.05, 1.8), dpi = 100) self.nav_figure.subplots_adjust(bottom=0.3) self.nav_axes = self.nav_figure.add_subplot(111, autoscale_on=False) self.nav_axes.xaxis.labelpad *= 2 self.nav_span = self.nav_axes.axvspan(0.0,1.0, facecolor='g', alpha=0.5) self.nav_handle1 = self.nav_axes.axvspan(0.00,0.025, facecolor='black', alpha=0.5) self.nav_handle2 = self.nav_axes.axvspan(0.975,1.00, facecolor='black', alpha=0.5) self.nav_canvas = FigureCanvasTkAgg(self.nav_figure, master=self.root) self.nav_canvas.get_tk_widget().grid(row=2, column=0) #Set the z-order to something high so that it works as an overlay self.nav_span.zorder = 1000 self.nav_handle1.zorder = 1001 self.nav_handle2.zorder = 1001 ## self.nav_axes.xaxis.set_major_locator(ticker.NullLocator()) self.nav_axes.yaxis.set_major_locator(ticker.NullLocator()) #Setup for the choosing the interval we want to examine self.interval_frame = Tk.Frame(self.root) self.interval_frame.grid(row=0, column=1, sticky=N+E) picker_label = Tk.Label(self.interval_frame, text="Data Intervals") picker_label.grid(row=0, column=0, sticky=N) self.interval_picker = Tk.Listbox(self.interval_frame, selectmode=Tk.BROWSE, exportselection=0) self.interval_picker.grid(row=1, column=0, sticky=N+W+E) width = 20 for (name, start, end) in self.intervals: string = format_span(start, end) width = max(width, len(string)) self.interval_picker.insert(Tk.END, string) self.interval_picker.config(width=width) self.interval_picker.bind("<Double-Button-1>", self.select_interval) self.interval_scrollbar = Tk.Scrollbar(self.interval_frame, command=self.interval_picker.yview) self.interval_picker.config(yscrollcommand=self.interval_scrollbar.set) self.interval_scrollbar.grid(row=1, column=1, sticky=N+S+W) picker_button = Tk.Button(self.interval_frame, text="Select interval", command=self.select_interval) picker_button.grid(row=2, column=0, sticky=N+W) #----Variables for picking the table from the database-------------- self.source_frame = Tk.Frame(self.root) self.source_frame.config(relief=Tk.GROOVE, borderwidth=2) self.source_frame.grid(row=1, column=1, sticky=N+W+E+S) source_label = Tk.Label(self.source_frame, text="Show/Hide plots") source_label.grid(column=0, columnspan=2, sticky=N) def set_var_callback(cb, data, checkbutton, var=None): if var is None: var = Tk.IntVar() def wrapper_callback(): var.set(var.get()) return cb(data, var.get()) checkbutton.config(variable=var, command=wrapper_callback) self.checkbuttons = [] for i,desc in enumerate(self.descriptors): checkbutton = Tk.Checkbutton(self.source_frame, text=desc.title) toggle = Tk.Checkbutton(self.source_frame, text=" ") color = self.colors[i % len(self.colors)] checkbutton.config(relief=Tk.SUNKEN, indicatoron=False) toggle.config(indicatoron=False, background=tk_color(lighten(color)), highlightbackground=tk_color(color), activebackground=tk_color(color), selectcolor=tk_color(color), state=ACTIVE) var = Tk.IntVar() set_var_callback(self.toggle_source, desc, checkbutton, var) set_var_callback(self.toggle_source, desc, toggle, var) self.color_map[desc.table_name] = color toggle.grid(column=0, row=i+1, sticky=N+W) checkbutton.grid(column=1, row=i+1, sticky=N+W) self.checkbuttons.append(checkbutton) self.style_count = 0 self.min_y = self.descriptors[0].min_y self.max_y = self.descriptors[0].max_y self.grabbing_navbar = False self.grabbing_handle = False self.grab_start = None self.handle_grabbed = None self.grab_reference = None def run(self): self.nav_figure.canvas.mpl_connect("button_press_event", self.mpl_on_press) self.nav_figure.canvas.mpl_connect("button_release_event", self.mpl_on_release) self.nav_figure.canvas.mpl_connect("motion_notify_event", self.mpl_on_motion) self.select_interval(index=0) self.interval_picker.selection_set(first=0) for desc, checkbutton in zip(self.descriptors, self.checkbuttons): checkbutton.select() self.toggle_source(desc, True) self.root.mainloop() def update_bounds(self): size = to_ordinal(self.absolute_end) - to_ordinal(self.absolute_start) x1 = to_ordinal(self.start_date) x2 = to_ordinal(self.end_date) self.axes.set_xbound(x1, x2) self.nav_span.set_xy([[x1, self.min_y], [x1, self.max_y], [x2, self.max_y], [x2, self.min_y], [x1, self.min_y]]) if x1 > x2: x1, x2 = x2, x1 self.nav_handle1.set_xy([[x1, self.min_y], [x1, self.max_y], [x1-size*0.025, self.max_y], [x1-size*0.025, self.min_y], [x1, self.min_y]]) self.nav_handle2.set_xy([[x2, self.min_y], [x2, self.max_y], [x2+size*0.025, self.max_y], [x2+size*0.025, self.min_y], [x2, self.min_y]]) locator = KenLocator(7.8) self.axes.xaxis.set_major_locator(locator) self.axes.xaxis.set_major_formatter(KenFormatter(locator)) self.axes.set_xlabel(format_span(self.start_date, self.end_date)) self.nav_axes.set_xlabel(format_timedelta(self.end_date-self.start_date)) def update_data(self): for identifier in self.data: view = self.data[identifier] view.load(self.absolute_start, self.absolute_end) self.collections[identifier].set_segments([view.export()]) self.nav_collections[identifier].set_segments([view.export()]) def select_interval(self, index=None): #Support direct invocation, invocation by event, and as a command if not isinstance(index, int): if not self.interval_picker.curselection(): return index = int(self.interval_picker.curselection()[0]) name, start, end = self.intervals[index] self.absolute_start = self.start_date = start self.absolute_end = self.end_date = end size = to_ordinal(start) - to_ordinal(end) self.nav_axes.set_xlim(to_ordinal(start)+size*0.025, to_ordinal(end)-size*0.025) locator = KenLocator(7.8) self.nav_axes.xaxis.set_major_locator(locator) self.nav_axes.xaxis.set_major_formatter(KenFormatter(locator)) self.update_data() self.update_bounds() self.redraw() def toggle_source(self, desc, enabled): if desc.table_name in self.data: if enabled: data = self.data[desc.table_name].export() self.axes.set_ylabel(desc.units) else: data = [] self.collections[desc.table_name].set_segments([data]) self.nav_collections[desc.table_name].set_segments([data]) self.redraw() elif enabled: self.axes.set_ylabel(desc.units) self.add_source(desc.table_name, desc.title) self.min_y = min(self.min_y, desc.min_y) self.max_y = max(self.max_y, desc.max_y) self.axes.set_ybound(self.min_y,self.max_y) self.nav_axes.set_ybound(self.min_y, self.max_y) ## self.axes.legend(loc=3) self.redraw() def redraw(self): self.figure.canvas.draw() self.nav_figure.canvas.draw() def add_source(self, identifier, title): view = SQLIntervalView(self.connection, identifier, self.absolute_start, self.absolute_end) self.data[identifier] = view colors = [self.color_map.get(identifier, self.colors[0])] col = DatetimeCollection([view.export()], colors=colors) col.set_label(title) self.collections[identifier] = col col2 = DatetimeCollection([view.export()], colors=colors) self.nav_collections[identifier] = col2 self.axes.add_collection(col) self.nav_axes.add_collection(col2) def mpl_on_press(self, event): if event.button != 1 or self.grabbing_navbar or self.grabbing_handle: return trans = self.nav_axes.transData.inverted() xdata = trans.transform((event.x, event.y))[0] if self.nav_handle1.contains(event)[0]: self.grabbing_handle = True self.handle_grabbed = 1 self.grab_start = xdata self.grab_reference = to_ordinal(min(self.start_date, self.end_date)) elif self.nav_handle2.contains(event)[0]: self.grabbing_handle = True self.handle_grabbed = 2 self.grab_start = xdata self.grab_reference = to_ordinal(max(self.start_date, self.end_date)) elif self.nav_span.contains(event)[0]: self.grabbing_navbar = True self.grab_start = xdata self.grab_reference = (to_ordinal(self.start_date), to_ordinal(self.end_date)) def move_navbar(self, pos): left_end = to_ordinal(self.absolute_start) right_end = to_ordinal(self.absolute_end) x1, x2 = self.grab_reference if x1 > x2: x1, x2 = x2, x1 diff = pos - self.grab_start if diff < 0 and x1 + diff < left_end: self.start_date = self.absolute_start self.end_date = from_ordinal(left_end + (x2 - x1)) elif diff > 0 and x2 + diff > right_end: self.end_date = self.absolute_end self.start_date = from_ordinal(right_end - (x2 - x1)) else: self.start_date = from_ordinal(x1 + diff) self.end_date = from_ordinal(x2 + diff) self.update_bounds() self.redraw() def move_handle(self, pos): left_end = to_ordinal(self.absolute_start) right_end = to_ordinal(self.absolute_end) diff = pos - self.grab_start new_pos = max(min(self.grab_reference + diff, right_end), left_end) new_date = from_ordinal(new_pos) if self.handle_grabbed == 1: if new_date > self.end_date: self.handle_grabbed = 2 self.start_date = self.end_date self.end_date = new_date else: self.start_date = new_date else: if new_date < self.start_date: self.handle_grabbed = 1 self.end_date = self.start_date self.start_date = new_date else: self.end_date = new_date self.update_bounds() self.redraw() def mpl_on_release(self, event): if event.button != 1: return trans = self.nav_axes.transData.inverted() xdata = trans.transform((event.x, event.y))[0] if self.grabbing_navbar: self.grabbing_navbar = False self.move_navbar(xdata) elif self.grabbing_handle: self.grabbing_handle = False self.move_handle(xdata) def mpl_on_motion(self, event): trans = self.nav_axes.transData.inverted() xdata = trans.transform((event.x, event.y))[0] if self.grabbing_navbar: self.move_navbar(xdata) elif self.grabbing_handle: self.move_handle(xdata)
class HistoricalViewerApp: line_styles = ["solid"] colors = [ (0.0, 0.0, 1.0, 1.0), #Blue (1.0, 0.0, 0.0, 1.0), #Red (0.0, 1.0, 0.0, 1.0), #Green (1.0, 1.0, 0.0, 1.0) ] def __init__(self, width, height): self.path = config.find_options("general.cfg")['database'] self.descriptors = config.find_graphs("graphs.cfg") self.data = {} self.collections = {} self.nav_collections = {} self.color_map = {} self.connection = sql.connect(self.path, detect_types=(sql.PARSE_COLNAMES|sql.PARSE_DECLTYPES)) self.root = Tk.Tk() self.root.wm_title("Historical Data Viewer") self.intervals = self.connection.execute("SELECT * FROM intervals ORDER BY start;").fetchall() self.intervals = list(reversed(self.intervals)) #Grid layout: # Col 0 Col 1 # +------------+------+ # Row 0 | | ITVL | # | ZOOM | SLCT | # | - -GRAPH- -+------+ # Row 1 | | DATA | # | | SLCT | # +------------+------+ # Row 2 | NAV GRAPH | ZOOM | # | | SLCT | # +------------+------+ #Setup for the Tk/Agg plotting backend self.figure = Figure(figsize = (width+1, height+2), dpi = 100) self.figure.subplots_adjust(bottom=0.15) self.axes = self.figure.add_subplot(111, autoscale_on=True) #self.axes.xaxis.labelpad *= 3 self.canvas = FigureCanvasTkAgg(self.figure, master=self.root) self.canvas.get_tk_widget().grid(row=0, column=0, rowspan=2) #Setup for the mini-navigation figure self.nav_figure = Figure(figsize = ((width+1)*1.05, 1.8), dpi = 100) #self.nav_figure.subplots_adjust(bottom=0.3) self.nav_axes = self.nav_figure.add_subplot(111, autoscale_on=False) #self.nav_axes.xaxis.labelpad *= 2 self.nav_canvas = FigureCanvasTkAgg(self.nav_figure, master=self.root) self.nav_canvas.get_tk_widget().grid(row=2, column=0) self.nav_axes.yaxis.set_major_locator(ticker.NullLocator()) #Setup for the slider def scale_to_data(left, right, x): return from_ordinal(to_ordinal(left) + x * (to_ordinal(right) - to_ordinal(left))) def data_to_scale(left, right, x): return (to_ordinal(x) - to_ordinal(left)) / (to_ordinal(right) - to_ordinal(left)) self.slider = DoubleSlider(self.root, left_bound=datetime(1999,1,1), right_bound=datetime(1999,1,28), data_to_scale=data_to_scale, scale_to_data=scale_to_data, set_on_drag=False, on_change=self.update_bounds, on_drag=lambda left, right: self.update_bounds(left, right, True)) self.slider.grid(row=3, column=0, sticky=W+E) #Setup for the choosing the interval we want to examine self.interval_frame = Tk.Frame(self.root) self.interval_frame.grid(row=0, column=1, sticky=N+E) picker_label = Tk.Label(self.interval_frame, text="Data Intervals") picker_label.grid(row=0, column=0, sticky=N) self.interval_picker = Tk.Listbox(self.interval_frame, selectmode=Tk.BROWSE, exportselection=0) self.interval_picker.grid(row=1, column=0, sticky=N+W+E) width = 20 for (name, start, end) in self.intervals: string = format_span(start, end) width = max(width, len(string)) self.interval_picker.insert(Tk.END, string) self.interval_picker.config(width=width) self.interval_picker.bind("<Double-Button-1>", self.select_interval) self.interval_scrollbar = Tk.Scrollbar(self.interval_frame, command=self.interval_picker.yview) self.interval_picker.config(yscrollcommand=self.interval_scrollbar.set) self.interval_scrollbar.grid(row=1, column=1, sticky=N+S+W) picker_button = Tk.Button(self.interval_frame, text="Select interval", command=self.select_interval) picker_button.grid(row=2, column=0, sticky=N+W) #----Variables for picking the table from the database-------------- self.source_frame = Tk.Frame(self.root) self.source_frame.config(relief=Tk.GROOVE, borderwidth=2) self.source_frame.grid(row=1, column=1, sticky=N+W+E+S) source_label = Tk.Label(self.source_frame, text="Show/Hide plots") source_label.grid(column=0, columnspan=2, sticky=N) def set_var_callback(cb, data, checkbutton, var=None): if var is None: var = Tk.IntVar() def wrapper_callback(): var.set(var.get()) return cb(data, var.get()) checkbutton.config(variable=var, command=wrapper_callback) self.checkbuttons = [] for i,desc in enumerate(self.descriptors): checkbutton = Tk.Checkbutton(self.source_frame, text=desc.title) toggle = Tk.Checkbutton(self.source_frame, text=" ") color = self.colors[i % len(self.colors)] checkbutton.config(relief=Tk.SUNKEN, indicatoron=False) toggle.config(indicatoron=False, background=tk_color(lighten(color)), highlightbackground=tk_color(color), activebackground=tk_color(color), selectcolor=tk_color(color), state=ACTIVE) var = Tk.IntVar() set_var_callback(self.toggle_source, desc, checkbutton, var) set_var_callback(self.toggle_source, desc, toggle, var) self.color_map[desc.table_name] = color toggle.grid(column=0, row=i+1, sticky=N+W) checkbutton.grid(column=1, row=i+1, sticky=N+W) self.checkbuttons.append(checkbutton) self.style_count = 0 self.min_y = self.descriptors[0].min_y self.max_y = self.descriptors[0].max_y def run(self): left_pad = self.nav_figure.subplotpars.left * self.nav_figure.get_figwidth() * self.nav_figure.dpi right_pad = (1-self.nav_figure.subplotpars.right) * self.nav_figure.get_figwidth() * self.nav_figure.dpi self.slider.config(left_padding=left_pad, right_padding=right_pad) self.figure.canvas.draw() self.nav_figure.canvas.draw() self.slider.init() self.select_interval(index=0) self.interval_picker.selection_set(first=0) for desc, checkbutton in zip(self.descriptors, self.checkbuttons): checkbutton.select() self.toggle_source(desc, True) locator = KenLocator(7.8) self.nav_axes.xaxis.set_major_locator(locator) self.nav_axes.xaxis.set_major_formatter(KenFormatter(locator)) locator = KenLocator(7.8) self.axes.xaxis.set_major_locator(locator) self.axes.xaxis.set_major_formatter(KenFormatter(locator)) self.root.mainloop() def update_bounds(self, left, right, dragging=False): if not dragging: self.axes.set_xbound(to_ordinal(left), to_ordinal(right)) self.axes.set_xlabel(format_span(left, right) + " (" + format_timedelta(right - left) + ")") agg_canvas = self.nav_canvas.get_tk_widget() agg_canvas.delete("OVERLAY") # c1 c3 # +---+---------+---+ # |...| _/\ _ |...| # |...|/ \_/ \|...| # +---+---------+---+ # c2 c4 cx2, cy2 = self.nav_axes.transData.transform_point((to_ordinal(left), self.max_y)).tolist() cx3, cy3 = self.nav_axes.transData.transform_point((to_ordinal(right), self.min_y)).tolist() agg_canvas.create_rectangle([cx2, cy2, cx3, cy3], tags="OVERLAY", stipple = "gray50", fill = "green") ## cx1, cy1 = self.nav_axes.transData.transform_point((to_ordinal(self.slider.left_bound), self.min_y)).tolist() ## cx2, cy2 = self.nav_axes.transData.transform_point((to_ordinal(left), self.max_y)).tolist() ## agg_canvas.create_rectangle([(cx1+1, cy1+2), (cx2, cy2)], ## tags="OVERLAY", ## stipple="gray50", ## fill="red", outline="") ## ## cx3, cy3 = self.nav_axes.transData.transform_point((to_ordinal(right), self.min_y)).tolist() ## cx4, cy4 = self.nav_axes.transData.transform_point((to_ordinal(self.slider.right_bound), self.max_y)).tolist() ## agg_canvas.create_rectangle([(cx3, cy3+2), (cx4, cy4)], ## tags="OVERLAY", ## stipple="gray50", ## fill="red", outline="") if not dragging: self.figure.canvas.draw() self.nav_figure.canvas.draw() def select_interval(self, index=None): #Support direct invocation, invocation by event, and as a command if not isinstance(index, int): if not self.interval_picker.curselection(): return index = int(self.interval_picker.curselection()[0]) name, start, end = self.intervals[index] for identifier in self.data: view = self.data[identifier] view.load(start, end) self.collections[identifier].set_segments([view.export()]) self.collections[identifier].set_antialiased(False) self.nav_collections[identifier].set_segments([view.export()]) self.slider.config(left_bound=start, right_bound=end) self.slider.reset() self.nav_axes.set_xbound(to_ordinal(start), to_ordinal(end)) self.nav_axes.set_xlabel("%s (%s)" % (format_span(start, end), format_timedelta(end - start))) self.redraw() def toggle_source(self, desc, enabled): if desc.table_name in self.data: self.nav_collections[desc.table_name].set_visible(enabled) self.collections[desc.table_name].set_visible(enabled) self.redraw() elif enabled: self.axes.set_ylabel(desc.units) self.add_source(desc.table_name, desc.title) self.min_y = min(self.min_y, desc.min_y) self.max_y = max(self.max_y, desc.max_y) self.axes.set_ybound(self.min_y,self.max_y) self.nav_axes.set_ybound(self.min_y, self.max_y) ## self.axes.legend(loc=3) self.redraw() def redraw(self): self.figure.canvas.draw() self.nav_figure.canvas.draw() def add_source(self, identifier, title): left, right = sorted([self.slider.left_bound, self.slider.right_bound]) view = SQLIntervalView(self.connection, identifier, left, right) self.data[identifier] = view colors = [self.color_map.get(identifier, self.colors[0])] col = DatetimeCollection([view.export()], colors=colors) col.set_label(title) self.collections[identifier] = col col2 = DatetimeCollection([view.export()], colors=colors) self.nav_collections[identifier] = col2 self.axes.add_collection(col) self.nav_axes.add_collection(col2)
def ax(self, fig: plt.Figure = None) -> axes.Axes: """ Plots calculated ranges (y axis) versus the index of the dataframe (x axis) Examples -------- Example 1, minimal R control chart ---------------------------------- >>> import matplotlib.pyplot as plt >>> from datasense import control_charts as cc >>> figsize = (8, 6) >>> graph_name = 'graph_r.svg' >>> X1 = ds.random_data( >>> distribution='norm', >>> size=25, >>> loc=69, >>> scale=13 >>> ) >>> X2 = ds.random_data( >>> distribution='norm', >>> size=25, >>> loc=69, >>> scale=13 >>> ) >>> X3 = ds.random_data( >>> distribution='norm', >>> size=25, >>> loc=69, >>> scale=13 >>> ) >>> X4 = ds.random_data( >>> distribution='norm', >>> size=25, >>> loc=69, >>> scale=13 >>> ) >>> data = pd.DataFrame( >>> data={ >>> 'X1': X1, >>> 'X2': X2, >>> 'X3': X3, >>> 'X4': X4, >>> } >>> ) >>> fig = plt.figure(figsize=(8, 6)) >>> r = cc.R(data=data) >>> ax = r.ax(fig) >>> fig.savefig(fname=graph_r_file_name) Example 2, complete R control chart ----------------------------------- >>> import matplotlib.pyplot as plt >>> from datasense import control_charts as cc >>> figsize = (8, 6) >>> graph_name = 'graph_r.svg' >>> colour='33bbee' >>> X1 = ds.random_data( >>> distribution='norm', >>> size=25, >>> loc=69, >>> scale=13 >>> ) >>> X2 = ds.random_data( >>> distribution='norm', >>> size=25, >>> loc=69, >>> scale=13 >>> ) >>> X3 = ds.random_data( >>> distribution='norm', >>> size=25, >>> loc=69, >>> scale=13 >>> ) >>> X4 = ds.random_data( >>> distribution='norm', >>> size=25, >>> loc=69, >>> scale=13 >>> ) >>> data = pd.DataFrame( >>> data={ >>> 'X1': X1, >>> 'X2': X2, >>> 'X3': X3, >>> 'X4': X4, >>> } >>> ) >>> fig = plt.figure(figsize=(8, 6)) >>> r = cc.R(data=data) >>> ax = r.ax(fig) >>> ax.axhline( >>> y=r.sigmas[+1], >>> linestyle='--', >>> dashes=(5, 5), >>> color=colour, >>> alpha=0.5 >>> ) >>> ax.axhline( >>> y=r.sigmas[-1], >>> linestyle='--', >>> dashes=(5, 5), >>> color=colour, >>> alpha=0.5 >>> ) >>> ax.axhline( >>> y=r.sigmas[+2], >>> linestyle='--', >>> dashes=(5, 5), >>> color=colour, >>> alpha=0.5 >>> ) >>> ax.axhline( >>> y=r.sigmas[-2], >>> linestyle='--', >>> dashes=(5, 5), >>> color=colour, >>> alpha=0.5 >>> ) >>> cc.draw_rule(r, ax, *cc.points_one(r), '1') >>> ax.set_title( >>> label=r_chart_title, >>> fontweight='bold' >>> ) >>> ax.set_ylabel(ylabel=r_chart_ylabel) >>> ax.set_xlabel(xlabel=r_chart_xlabel) >>> fig.savefig(fname=graph_r_file_name) """ if fig is None: fig = plt.figure() ax = fig.add_subplot(111) _despine(ax) ax.plot(self.y.index, self.y, marker='o', markersize=3, color=colour2) ax.axhline(y=self.mean, color=colour3) ax.axhline(y=self.ucl, color=colour1) ax.axhline(y=self.lcl, color=colour1) return ax
class ChartDialog(wx.Dialog): """Chart dialog frontend to matplotlib""" chart_types = [ "plot" ] def __init__(self, parent, *args, **kwargs): wx.Dialog.__init__(self, parent, -1, _("Insert chart"), *args, size=(900, 700), style=wx.RESIZE_BORDER, **kwargs) self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_LIVE_UPDATE) self.splitter.parent = self # Create a CustomTreeCtrl instance self.tree = ChartTree(self.splitter, style=wx.BORDER_SUNKEN) self.figure_panel = FigurePanel(self.splitter) # Dummy figure self.figure = Figure(facecolor='white') ax = self.figure.add_subplot(111) ax.xaxis.set_picker(5) ax.xaxis.name = "xaxis" ax.yaxis.set_picker(5) ax.yaxis.name = "yaxis" plt = ax.plot([(x/10.0)**2 for x in xrange(1000)], picker=5) plt[-1].name = "test" self.figure_panel.update(self.figure) # Split Window self.splitter.SplitVertically(self.tree, self.figure_panel) self.splitter.SetMinimumPaneSize(10) self.splitter.SetSashPosition(400) # Buttons self.button_add = wx.Button(self, wx.ID_ADD) self.button_remove = wx.Button(self, wx.ID_REMOVE) self.button_cancel = wx.Button(self, wx.ID_CANCEL) self.button_ok = wx.Button(self, wx.ID_OK) self.button_add.Bind(wx.EVT_BUTTON, self.OnAdd) self._layout() def _layout(self): """Sizer layout""" left_sizer = wx.FlexGridSizer(cols=1) left_button_sizer = wx.FlexGridSizer(cols=5) left_sizer.Add(self.splitter, 0, wx.EXPAND) left_sizer.Add(left_button_sizer, 0, wx.EXPAND) left_button_sizer.Add(self.button_add, 1, wx.EXPAND | wx.ALL, 4) left_button_sizer.Add(self.button_remove, 1, wx.EXPAND | wx.ALL, 4) left_button_sizer.Add(wx.Panel(self, -1), 1, wx.EXPAND | wx.ALL, 4) left_button_sizer.Add(self.button_cancel, 1, wx.EXPAND | wx.ALL, 4) left_button_sizer.Add(self.button_ok, 1, wx.EXPAND | wx.ALL, 4) left_sizer.AddGrowableRow(0) left_sizer.AddGrowableCol(0) left_button_sizer.AddGrowableCol(2) self.SetSizer(left_sizer) self.Layout() def add_chart(self, chart_type): """Adds chart to figure after current position in the tree""" self.tree.add_chart(chart_type) # Event handlers def OnAdd(self, event): """Add button event handler""" dlg = wx.SingleChoiceDialog(self, _('Add chart to figure'), _('Select chart type'), self.chart_types, wx.CHOICEDLG_STYLE) if dlg.ShowModal() == wx.ID_OK: self.add_chart(dlg.GetStringSelection()) dlg.Destroy()
class MainWindow(QMainWindow): """ Class of Main Window (top) """ _errMsgWindow = None def __init__(self, parent=None): """ Initialization and set up """ # Base class QMainWindow.__init__(self, parent) # Mantid configuration config = ConfigService.Instance() self._instrument = config["default.instrument"] # Central widget self.centralwidget = QWidget(self) # UI Window (from Qt Designer) self.ui = load_ui(__file__, 'MainWindow.ui', baseinstance=self) mpl_layout = QVBoxLayout() self.ui.graphicsView.setLayout(mpl_layout) self.fig = Figure() self.canvas = FigureCanvas(self.fig) self.ui.mainplot = self.fig.add_subplot(111, projection='mantid') mpl_layout.addWidget(self.canvas) # Do initialize plotting vecx, vecy, xlim, ylim = self.computeMock() self.mainline = self.ui.mainplot.plot(vecx, vecy, 'r-') leftx = [xlim[0], xlim[0]] lefty = [ylim[0], ylim[1]] self.leftslideline = self.ui.mainplot.plot(leftx, lefty, 'b--') rightx = [xlim[1], xlim[1]] righty = [ylim[0], ylim[1]] self.rightslideline = self.ui.mainplot.plot(rightx, righty, 'g--') upperx = [xlim[0], xlim[1]] uppery = [ylim[1], ylim[1]] self.upperslideline = self.ui.mainplot.plot(upperx, uppery, 'b--') lowerx = [xlim[0], xlim[1]] lowery = [ylim[0], ylim[0]] self.lowerslideline = self.ui.mainplot.plot(lowerx, lowery, 'g--') self.canvas.mpl_connect('button_press_event', self.on_mouseDownEvent) # Set up horizontal slide (integer) and string value self._leftSlideValue = 0 self._rightSlideValue = 99 self.ui.horizontalSlider.setRange(0, 100) self.ui.horizontalSlider.setValue(self._leftSlideValue) self.ui.horizontalSlider.setTracking(True) self.ui.horizontalSlider.setTickPosition(QSlider.NoTicks) self.ui.horizontalSlider.valueChanged.connect(self.move_leftSlider) self.ui.horizontalSlider_2.setRange(0, 100) self.ui.horizontalSlider_2.setValue(self._rightSlideValue) self.ui.horizontalSlider_2.setTracking(True) self.ui.horizontalSlider_2.setTickPosition(QSlider.NoTicks) self.ui.horizontalSlider_2.valueChanged.connect(self.move_rightSlider) # self.connect(self.ui.lineEdit_3, QtCore.SIGNAL("textChanged(QString)"), # self.set_startTime) self.ui.lineEdit_3.setValidator(QDoubleValidator(self.ui.lineEdit_3)) self.ui.pushButton_setT0.clicked.connect(self.set_startTime) # self.connect(self.ui.lineEdit_4, QtCore.SIGNAL("textChanged(QString)"), # self.set_stopTime) self.ui.lineEdit_4.setValidator(QDoubleValidator(self.ui.lineEdit_4)) self.ui.pushButton_setTf.clicked.connect(self.set_stopTime) # File loader self.scanEventWorkspaces() self.ui.pushButton_refreshWS.clicked.connect(self.scanEventWorkspaces) self.ui.pushButton_browse.clicked.connect(self.browse_File) self.ui.pushButton_load.clicked.connect(self.load_File) self.ui.pushButton_3.clicked.connect(self.use_existWS) # Set up time self.ui.lineEdit_3.setValidator(QDoubleValidator(self.ui.lineEdit_3)) self.ui.lineEdit_4.setValidator(QDoubleValidator(self.ui.lineEdit_4)) # Filter by time self.ui.pushButton_filterTime.clicked.connect(self.filterByTime) # Filter by log value self.ui.lineEdit_5.setValidator(QDoubleValidator(self.ui.lineEdit_5)) self.ui.lineEdit_6.setValidator(QDoubleValidator(self.ui.lineEdit_6)) self.ui.lineEdit_7.setValidator(QDoubleValidator(self.ui.lineEdit_7)) self.ui.lineEdit_8.setValidator(QDoubleValidator(self.ui.lineEdit_8)) self.ui.lineEdit_9.setValidator(QDoubleValidator(self.ui.lineEdit_9)) self.ui.lineEdit_5.textChanged.connect(self.set_minLogValue) self.ui.lineEdit_6.textChanged.connect(self.set_maxLogValue) dirchangeops = ["Both", "Increase", "Decrease"] self.ui.comboBox_4.addItems(dirchangeops) logboundops = ["Centre", "Left"] self.ui.comboBox_5.addItems(logboundops) self.ui.pushButton_4.clicked.connect(self.plotLogValue) self.ui.pushButton_filterLog.clicked.connect(self.filterByLogValue) # Set up help button self.ui.helpBtn.clicked.connect(self.helpClicked) # Set up vertical slide self._upperSlideValue = 99 self._lowerSlideValue = 0 self.ui.verticalSlider.setRange(0, 100) self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.verticalSlider.setTracking(True) self.ui.verticalSlider.valueChanged.connect(self.move_upperSlider) self.ui.verticalSlider_2.setRange(0, 100) self.ui.verticalSlider_2.setValue(self._lowerSlideValue) self.ui.verticalSlider_2.setTracking(True) self.ui.verticalSlider_2.valueChanged.connect(self.move_lowerSlider) # Set up for filtering (advanced setup) self._tofcorrection = False self.ui.checkBox_fastLog.setChecked(False) self.ui.checkBox_filterByPulse.setChecked(False) self.ui.checkBox_from1.setChecked(False) self.ui.checkBox_groupWS.setChecked(True) self.ui.comboBox_tofCorr.currentIndexChanged.connect(self.showHideEi) self.ui.pushButton_refreshCorrWSList.clicked.connect( self._searchTableWorkspaces) self.ui.lineEdit_Ei.setValidator(QDoubleValidator(self.ui.lineEdit_Ei)) self.ui.label_Ei.hide() self.ui.lineEdit_Ei.hide() self.ui.label_Ei_2.hide() self.ui.comboBox_corrWS.hide() self.ui.pushButton_refreshCorrWSList.hide() # Set up for workspaces self._dataWS = None self._sampleLogNames = [] self._sampleLog = None # Side information self.ui.label_mean.hide() self.ui.label_meanvalue.hide() self.ui.label_avg.hide() self.ui.label_timeAvgValue.hide() self.ui.label_freq.hide() self.ui.label_freqValue.hide() self.ui.label_logname.hide() self.ui.label_lognamevalue.hide() self.ui.label_logsize.hide() self.ui.label_logsizevalue.hide() # Default self._defaultdir = os.getcwd() # register startup mantid.UsageService.registerFeatureUsage("Interface", "EventFilter", False) def on_mouseDownEvent(self, event): """ Respond to pick up a value with mouse down event """ x = event.xdata y = event.ydata if x is not None and y is not None: msg = "You've clicked on a bar with coords:\n %f, %f" % (x, y) QMessageBox.information(self, "Click!", msg) def computeMock(self): """ Compute vecx and vecy as mocking """ x0 = 0. xf = 1. dx = 0.1 vecx = [] vecy = [] x = x0 while x < xf: y = 0.0 vecx.append(x) vecy.append(y) x += dx xlim = [x0, xf] ylim = [-1., 1] return (vecx, vecy, xlim, ylim) def move_leftSlider(self): """ Re-setup left range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ newx = self.ui.horizontalSlider.value() if newx <= self._rightSlideValue and newx != self._leftSlideValue: # Allowed value: move the value bar self._leftSlideValue = newx # Move the vertical line xlim = self.ui.mainplot.get_xlim() newx = xlim[0] + newx * (xlim[1] - xlim[0]) * 0.01 leftx = [newx, newx] lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Change value self.ui.lineEdit_3.setText(str(newx)) else: # Reset the value to original value self.ui.horizontalSlider.setValue(self._leftSlideValue) def set_startTime(self): """ Set the starting time and left slide bar """ inps = str(self.ui.lineEdit_3.text()) info_msg = "Starting time = %s" % (inps) Logger("Filter_Events").information(info_msg) xlim = self.ui.mainplot.get_xlim() if inps == "": # Empty. Use default newtime0 = xlim[0] else: newtime0 = float(inps) # Convert to integer slide value ileftvalue = int((newtime0 - xlim[0]) / (xlim[1] - xlim[0]) * 100) debug_msg = "iLeftSlide = %s" % str(ileftvalue) Logger("Filter_Events").debug(debug_msg) # Skip if same as origina if ileftvalue == self._leftSlideValue: return # Set the value if out of range resetT = True if ileftvalue < 0: # Minimum value as 0 ileftvalue = 0 elif ileftvalue > self._rightSlideValue: # Maximum value as right slide value ileftvalue = self._rightSlideValue else: resetT = False if resetT is True: newtime0 = xlim[0] + ileftvalue * (xlim[1] - xlim[0]) * 0.01 info_msg = 'Corrected iLeftSlide = {} (vs. right = {})'.format( ileftvalue, self._rightSlideValue) Logger("Filter_Events").information(info_msg) # Move the slide bar (left) self._leftSlideValue = ileftvalue # Move the vertical line leftx = [newtime0, newtime0] lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Set the value to left slider self.ui.horizontalSlider.setValue(self._leftSlideValue) # Reset the value of line edit if resetT is True: self.ui.lineEdit_3.setText(str(newtime0)) def move_rightSlider(self): """ Re-setup left range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ newx = self.ui.horizontalSlider_2.value() if newx >= self._leftSlideValue and newx != self._rightSlideValue: # Allowed value: move the value bar self._rightSlideValue = newx xlim = self.ui.mainplot.get_xlim() newx = xlim[0] + newx * (xlim[1] - xlim[0]) * 0.01 leftx = [newx, newx] lefty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Change value self.ui.lineEdit_4.setText(str(newx)) else: # Reset the value self.ui.horizontalSlider_2.setValue(self._rightSlideValue) def set_stopTime(self): """ Set the starting time and left slide bar """ inps = str(self.ui.lineEdit_4.text()) Logger("Filter_Events").information('Stopping time = {}'.format(inps)) xlim = self.ui.mainplot.get_xlim() if inps == "": # Empty. Use default newtimef = xlim[1] else: # Parse newtimef = float(inps) # Convert to integer slide value irightvalue = int((newtimef - xlim[0]) / (xlim[1] - xlim[0]) * 100) Logger("Filter_Events").information( 'iRightSlide = {}'.format(irightvalue)) # Return if no change if irightvalue == self._rightSlideValue: return # Correct value resetT = True if irightvalue > 100: irightvalue = 100 elif irightvalue < self._leftSlideValue: irightvalue = self._leftSlideValue else: resetT = False if resetT is True: newtimef = xlim[0] + irightvalue * (xlim[1] - xlim[0]) * 0.01 # Move the slide bar (right) self._rightSlideValue = irightvalue # Move the vertical line rightx = [newtimef, newtimef] righty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=rightx, ydata=righty) self.canvas.draw() # Set the value to left slider self.ui.horizontalSlider_2.setValue(self._rightSlideValue) # Reset to line edit if resetT: self.ui.lineEdit_4.setText(str(newtimef)) def move_lowerSlider(self): """ Re-setup upper range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ inewy = self.ui.verticalSlider_2.value() debug_msg = 'LowerSlFider is set with value {} vs. class variable {}'.format( inewy, self._lowerSlideValue) Logger("Filter_Events").debug(debug_msg) # Return with no change if inewy == self._lowerSlideValue: # No change return if inewy >= self._upperSlideValue: # Out of upper range inewy = self._upperSlideValue - 1 if inewy == 0 and self._lowerSlideValue < 0: setLineEdit = False else: setLineEdit = True # Move the lower vertical bar ylim = self.ui.mainplot.get_ylim() newy = ylim[0] + inewy * (ylim[1] - ylim[0]) * 0.01 lowerx = self.ui.mainplot.get_xlim() lowery = [newy, newy] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) self.canvas.draw() # Set line edit input if setLineEdit is True: # Change value to line edit (5) self.ui.lineEdit_5.setText(str(newy)) # Reset the class variable self._lowerSlideValue = inewy def set_minLogValue(self): """ Set the starting time and left slide bar """ debug_msg = 'Minimum Log Value = {}'.format(self.ui.lineEdit_5.text()) Logger("Filter_Events").debug(debug_msg) ylim = self.ui.mainplot.get_ylim() if str(self.ui.lineEdit_5.text()) == "": # Empty. Default to minY newminY = ylim[0] else: # Non empty. Parse newminY = float(self.ui.lineEdit_5.text()) # Convert to integer slide value iminlogval = int((newminY - ylim[0]) / (ylim[1] - ylim[0]) * 100) Logger("Filter_Events").debug('ilowerSlide = {}'.format(iminlogval)) # Return if no change if iminlogval == self._lowerSlideValue: return # Set value if out of range resetL = True if iminlogval >= self._upperSlideValue: iminlogval = self._upperSlideValue - 1 else: resetL = False if resetL is True: newminY = ylim[0] + iminlogval * (ylim[1] - ylim[0]) * 0.01 # Move the vertical line lowerx = self.ui.mainplot.get_xlim() lowery = [newminY, newminY] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) self.canvas.draw() # Move the slide bar (lower) self._lowerSlideValue = iminlogval debug_msg = 'LineEdit5 set slide to {}'.format(self._lowerSlideValue) Logger("Filter_Events").debug(debug_msg) self.ui.verticalSlider_2.setValue(self._lowerSlideValue) # Reset line Edit if using default if resetL is True: self.ui.lineEdit_5.setText(str(newminY)) def move_upperSlider(self): """ Re-setup upper range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ inewy = self.ui.verticalSlider.value() # Return w/o change if inewy == self._upperSlideValue: return # Set to boundary value if inewy <= self._lowerSlideValue: inewy = self._lowerSlideValue + 1 # Reset line editor? if inewy == 100 and self._upperSlideValue > 100: setLineEdit = False else: setLineEdit = True # Move the upper value bar: upperx and uppery are # real value (float but not (0,100)) of the figure ylim = self.ui.mainplot.get_ylim() newy = ylim[0] + inewy * (ylim[1] - ylim[0]) * 0.01 upperx = self.ui.mainplot.get_xlim() uppery = [newy, newy] setp(self.upperslideline, xdata=upperx, ydata=uppery) self.canvas.draw() # Change value if setLineEdit is True: self.ui.lineEdit_6.setText(str(newy)) self._upperSlideValue = inewy def set_maxLogValue(self): """ Set maximum log value from line-edit """ inps = str(self.ui.lineEdit_6.text()) debug_msg = 'Maximum Log Value = {}'.format(inps) Logger("Filter_Events").debug(debug_msg) ylim = self.ui.mainplot.get_ylim() if inps == "": # Empty. Default to minY newmaxY = ylim[1] else: # Parse newmaxY = float(inps) # Convert to integer slide value imaxlogval = int((newmaxY - ylim[0]) / (ylim[1] - ylim[0]) * 100) debug_msg = 'iUpperSlide = {}'.format(imaxlogval) Logger("Filter_Events").debug(debug_msg) # Return if no change if imaxlogval == self._upperSlideValue: return # Set to default if out of range resetL = True # if imaxlogval >= 100: # imaxlogval = 100 if imaxlogval < self._lowerSlideValue: imaxlogval = self._lowerSlideValue + 1 else: resetL = False # Set newmaxY if necessary if resetL is True: newmaxY = ylim[0] + imaxlogval * (ylim[1] - ylim[0]) * 0.01 # Move the vertical line upperx = self.ui.mainplot.get_xlim() uppery = [newmaxY, newmaxY] setp(self.upperslideline, xdata=upperx, ydata=uppery) self.canvas.draw() # Set the value to upper slider self._upperSlideValue = imaxlogval self.ui.verticalSlider.setValue(self._upperSlideValue) # Set the value to editor if necessary if resetL is True: self.ui.lineEdit_6.setText(str(newmaxY)) def browse_File(self): """ Open a file dialog to get file """ filename = QFileDialog.getOpenFileName( self, 'Input File Dialog', self._defaultdir, "Data (*.nxs *.dat);;All files (*)") if isinstance(filename, tuple): filename = filename[0] self.ui.lineEdit.setText(filename) Logger("Filter_Events").information( 'Selected file: "{}"'.format(filename)) def load_File(self): """ Load the file by file name or run number """ # Get file name from line editor filename = str(self.ui.lineEdit.text()) dataws = self._loadFile(str(filename)) if dataws is None: error_msg = 'Unable to locate run {} in default directory {}.'.format( filename, self._defaultdir) Logger("Filter_Events").error(error_msg) self._setErrorMsg(error_msg) else: self._importDataWorkspace(dataws) self._defaultdir = os.path.dirname(str(filename)) # Reset GUI self._resetGUI(resetfilerun=False) def use_existWS(self): """ Set up workspace to an existing one """ wsname = str(self.ui.comboBox.currentText()) try: dataws = AnalysisDataService.retrieve(wsname) self._importDataWorkspace(dataws) except KeyError: pass # Reset GUI self._resetGUI(resetfilerun=True) def plotLogValue(self): """ Plot log value """ # Get log value logname = str(self.ui.comboBox_2.currentText()) if len(logname) == 0: # return due to the empty one is chozen return samplelog = self._dataWS.getRun().getProperty(logname) vectimes = samplelog.times vecvalue = samplelog.value # check if len(vectimes) == 0: error_msg = "Empty log!" Logger("Filter_Events").error(error_msg) # Convert absolute time to relative time in seconds t0 = self._dataWS.getRun().getProperty("proton_charge").times[0] # append 1 more log if original log only has 1 value tf = self._dataWS.getRun().getProperty("proton_charge").times[-1] vectimes = numpy.append(vectimes, tf) vecvalue = numpy.append(vecvalue, vecvalue[-1]) vecreltimes = (vectimes - t0) / numpy.timedelta64(1, 's') # Set to plot xlim = [vecreltimes.min(), vecreltimes.max()] ylim = [vecvalue.min(), vecvalue.max()] self.ui.mainplot.set_xlim(xlim[0], xlim[1]) self.ui.mainplot.set_ylim(ylim[0], ylim[1]) setp(self.mainline, xdata=vecreltimes, ydata=vecvalue) samunit = samplelog.units if len(samunit) == 0: ylabel = logname else: ylabel = "%s (%s)" % (logname, samunit) self.ui.mainplot.set_ylabel(ylabel, fontsize=13) # assume that all logs are on almost same X-range. Only Y need to be reset setp(self.leftslideline, ydata=ylim) setp(self.rightslideline, ydata=ylim) # reset the log value limit as previous one does not make any sense setp(self.lowerslideline, xdata=xlim, ydata=[ylim[0], ylim[0]]) self._lowerSlideValue = 0 self.ui.verticalSlider_2.setValue(self._lowerSlideValue) self.ui.lineEdit_5.setText("") setp(self.upperslideline, xdata=xlim, ydata=[ylim[1], ylim[1]]) self._upperSlideValue = 100 self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.lineEdit_6.setText("") self.canvas.draw() # Load property's statistic and give suggestion on parallel and fast log timeavg = samplelog.timeAverageValue() numentries = samplelog.size() stat = samplelog.getStatistics() duration = stat.duration mean = stat.mean freq = float(numentries) / float(duration) self.ui.label_mean.show() self.ui.label_meanvalue.show() self.ui.label_avg.show() self.ui.label_timeAvgValue.show() self.ui.label_freq.show() self.ui.label_freqValue.show() self.ui.label_logname.show() self.ui.label_lognamevalue.show() self.ui.label_logsize.show() self.ui.label_logsizevalue.show() self.ui.label_meanvalue.setText("%.5e" % (mean)) self.ui.label_timeAvgValue.setText("%.5e" % (timeavg)) self.ui.label_freqValue.setText("%.5e" % (freq)) self.ui.label_lognamevalue.setText(logname) self.ui.label_logsizevalue.setText(str(numentries)) # Set suggested processing scheme if numentries > HUGE_FAST: self.ui.checkBox_fastLog.setCheckState(True) if numentries > HUGE_PARALLEL: self.ui.checkBox_doParallel.setCheckState(True) else: self.ui.checkBox_doParallel.setCheckState(False) else: self.ui.checkBox_fastLog.setCheckState(False) self.ui.checkBox_doParallel.setCheckState(False) return def _importDataWorkspace(self, dataws): """ Import data workspace for filtering """ if dataws is None: return # Plot time counts errmsg = self._plotTimeCounts(dataws) if errmsg is not None: errmsg = 'Workspace {} has invalid sample logs for splitting. Loading \ failure! \n{}\n'.format(dataws, errmsg) self._setErrorMsg(errmsg) return False # Import log self._sampleLogNames = [""] run = dataws.getRun() plist = run.getProperties() for p in plist: try: times = p.times if len(times) > 1 and numpy.isreal(p.value[0]): self._sampleLogNames.append(p.name) # This is here for FloatArrayProperty. If a log value is of this type it does not have times except AttributeError: pass # ENDFOR(p) # Set up sample log self.ui.comboBox_2.clear() self.ui.comboBox_2.addItems(self._sampleLogNames) # Side information self.ui.label_mean.hide() self.ui.label_meanvalue.hide() self.ui.label_avg.hide() self.ui.label_timeAvgValue.hide() self.ui.label_freq.hide() self.ui.label_freqValue.hide() # Hide 'log name' above the graphic view self.ui.label_logname.hide() self.ui.label_lognamevalue.hide() # Set dataws to class variable self._dataWS = dataws return True def scanEventWorkspaces(self): """ """ wsnames = AnalysisDataService.getObjectNames() eventwsnames = [] for wsname in wsnames: wksp = AnalysisDataService.retrieve(wsname) if wksp.__class__.__name__.count("Event") == 1: eventwsnames.append(wsname) # ENDFOR if len(eventwsnames) > 0: self.ui.comboBox.clear() self.ui.comboBox.addItems(eventwsnames) def _loadFile(self, filename): """ Load file or run File will be loaded to a workspace shown in MantidPlot """ config = ConfigService # Check input file name and output workspace name if filename.isdigit() is True: # Construct a file name from run number runnumber = int(filename) if runnumber <= 0: error_msg = 'Run number cannot be less or equal to zero. User gives {}.'.format( filename) Logger("Filter_Events").error(error_msg) return None else: ishort = config.getInstrument(self._instrument).shortName() filename = '{}_{}'.format(ishort, filename) wsname = filename + "_event" elif filename.count(".") > 0: # A proper file name wsname = os.path.splitext(os.path.split(filename)[1])[0] elif filename.count("_") == 1: # A short one as instrument_runnumber iname = filename.split("_")[0] str_runnumber = filename.split("_")[1] if str_runnumber.isdigit() is True and int(str_runnumber) > 0: # Accepted format ishort = config.getInstrument(iname).shortName() wsname = '{}_{}_event'.format(ishort, str_runnumber) else: # Non-supported error_msg = 'File name / run number in such format {} is not supported.'.format( filename) Logger("Filter_Events").error(error_msg) return None else: # Unsupported format error_msg = 'File name / run number in such format {} is not supported.'.format( filename) Logger("Filter_Events").error(error_msg) return None # Load try: ws = api.Load(Filename=filename, OutputWorkspace=wsname) except RuntimeError as e: ws = None return str(e) return ws def _plotTimeCounts(self, wksp): """ Plot time/counts """ import datetime # Rebin events by pulse time try: # Get run start and run stop if wksp.getRun().hasProperty("run_start"): runstart = wksp.getRun().getProperty("run_start").value else: runstart = wksp.getRun().getProperty("proton_charge").times[0] runstop = wksp.getRun().getProperty("proton_charge").times[-1] runstart = str(runstart).split(".")[0].strip() runstop = str(runstop).split(".")[0].strip() t0 = datetime.datetime.strptime(runstart, "%Y-%m-%dT%H:%M:%S") tf = datetime.datetime.strptime(runstop, "%Y-%m-%dT%H:%M:%S") # Calculate dt = tf - t0 timeduration = dt.days * 3600 * 24 + dt.seconds timeres = float(timeduration) / MAXTIMEBINSIZE if timeres < 1.0: timeres = 1.0 sumwsname = '_Summed_{}'.format(wksp) if AnalysisDataService.doesExist(sumwsname) is False: sumws = api.SumSpectra(InputWorkspace=wksp, OutputWorkspace=sumwsname) sumws = api.RebinByPulseTimes(InputWorkspace=sumws, OutputWorkspace=sumwsname, Params='{}'.format(timeres)) sumws = api.ConvertToPointData(InputWorkspace=sumws, OutputWorkspace=sumwsname) else: sumws = AnalysisDataService.retrieve(sumwsname) except RuntimeError as e: return str(e) vecx = sumws.readX(0) vecy = sumws.readY(0) xmin = min(vecx) xmax = max(vecx) ymin = min(vecy) ymax = max(vecy) # Reset graph self.ui.mainplot.set_xlim(xmin, xmax) self.ui.mainplot.set_ylim(ymin, ymax) self.ui.mainplot.set_xlabel('Time (seconds)', fontsize=13) self.ui.mainplot.set_ylabel('Counts', fontsize=13) # Set up main line setp(self.mainline, xdata=vecx, ydata=vecy) # Reset slide newslidery = [min(vecy), max(vecy)] newleftx = xmin + (xmax - xmin) * self._leftSlideValue * 0.01 setp(self.leftslideline, xdata=[newleftx, newleftx], ydata=newslidery) newrightx = xmin + (xmax - xmin) * self._rightSlideValue * 0.01 setp(self.rightslideline, xdata=[newrightx, newrightx], ydata=newslidery) self.canvas.draw() def filterByTime(self): """ Filter by time """ # Generate event filters kwargs = {} if self.ui.lineEdit_3.text() != "": rel_starttime = float(self.ui.lineEdit_3.text()) kwargs["StartTime"] = str(rel_starttime) if self.ui.lineEdit_4.text() != "": rel_stoptime = float(self.ui.lineEdit_4.text()) kwargs["StopTime"] = str(rel_stoptime) if self.ui.lineEdit_timeInterval.text() != "": interval = float(self.ui.lineEdit_timeInterval.text()) kwargs["TimeInterval"] = interval splitwsname = str(self._dataWS) + "_splitters" splitinfowsname = str(self._dataWS) + "_info" title = str(self.ui.lineEdit_title.text()) fastLog = self.ui.checkBox_fastLog.isChecked() splitws, infows = api.GenerateEventsFilter( InputWorkspace=self._dataWS, UnitOfTime="Seconds", TitleOfSplitters=title, OutputWorkspace=splitwsname, FastLog=fastLog, InformationWorkspace=splitinfowsname, **kwargs) self.splitWksp(splitws, infows) def filterByLogValue(self): """ Filter by log value """ # Generate event filter kwargs = {} samplelog = str(self.ui.comboBox_2.currentText()) if len(samplelog) == 0: error_msg = "No sample log is selected!" Logger("Filter_Events").error(error_msg) return if self.ui.lineEdit_3.text() != "": rel_starttime = float(self.ui.lineEdit_3.text()) kwargs["StartTime"] = str(rel_starttime) if self.ui.lineEdit_4.text() != "": rel_stoptime = float(self.ui.lineEdit_4.text()) kwargs["StopTime"] = str(rel_stoptime) if self.ui.lineEdit_5.text() != "": minlogvalue = float(self.ui.lineEdit_5.text()) kwargs["MinimumLogValue"] = minlogvalue if self.ui.lineEdit_6.text() != "": maxlogvalue = float(self.ui.lineEdit_6.text()) kwargs["MaximumLogValue"] = maxlogvalue if self.ui.lineEdit_7.text() != "": logvalueintv = float(self.ui.lineEdit_7.text()) kwargs["LogValueInterval"] = logvalueintv logvalchangedir = str(self.ui.comboBox_4.currentText()) kwargs["FilterLogValueByChangingDirection"] = logvalchangedir if self.ui.lineEdit_9.text() != "": logvalueintv = float(self.ui.lineEdit_9.text()) kwargs["TimeTolerance"] = logvalueintv logboundtype = str(self.ui.comboBox_5.currentText()) kwargs["LogBoundary"] = logboundtype if self.ui.lineEdit_8.text() != "": logvaluetol = float(self.ui.lineEdit_8.text()) kwargs["LogValueTolerance"] = logvaluetol splitwsname = str(self._dataWS) + "_splitters" splitinfowsname = str(self._dataWS) + "_info" fastLog = self.ui.checkBox_fastLog.isChecked() title = str(self.ui.lineEdit_title.text()) splitws, infows = api.GenerateEventsFilter( InputWorkspace=self._dataWS, UnitOfTime="Seconds", TitleOfSplitters=title, OutputWorkspace=splitwsname, LogName=samplelog, FastLog=fastLog, InformationWorkspace=splitinfowsname, **kwargs) try: self.splitWksp(splitws, infows) except RuntimeError as e: self._setErrorMsg("Splitting Failed!\n %s" % (str(e))) def splitWksp(self, splitws, infows): """ Run FilterEvents """ dogroupws = self.ui.checkBox_groupWS.isChecked() filterbypulse = self.ui.checkBox_filterByPulse.isChecked() startfrom1 = self.ui.checkBox_from1.isChecked() splitsamplelog = self.ui.checkBox_splitLog.isChecked() corr2sample = str(self.ui.comboBox_tofCorr.currentText()) how2skip = str(self.ui.comboBox_skipSpectrum.currentText()) kwargs = {} if corr2sample == "Direct": ei = float(self.ui.lineEdit_Ei.text()) kwargs["IncidentEnergy"] = ei elif corr2sample == "Customized": corrws = str(self.ui.comboBox_corrWS.currentText()) kwargs["DetectorTOFCorrectionWorkspace"] = corrws # Output workspace name outbasewsname = str(self.ui.lineEdit_outwsname.text()) if len(outbasewsname) == 0: outbasewsname = "tempsplitted" self.ui.lineEdit_outwsname.setText(outbasewsname) api.FilterEvents(InputWorkspace=self._dataWS, SplitterWorkspace=splitws, InformationWorkspace=infows, OutputWorkspaceBaseName=outbasewsname, GroupWorkspaces=dogroupws, FilterByPulseTime=filterbypulse, CorrectionToSample=corr2sample, SpectrumWithoutDetector=how2skip, SplitSampleLogs=splitsamplelog, OutputWorkspaceIndexedFrom1=startfrom1, OutputTOFCorrectionWorkspace='TOFCorrTable', **kwargs) def showHideEi(self): """ """ corrtype = str(self.ui.comboBox_tofCorr.currentText()) # Incident energy if corrtype == "Direct": self.ui.label_Ei.show() self.ui.lineEdit_Ei.show() else: self.ui.label_Ei.hide() self.ui.lineEdit_Ei.hide() # Workspace if corrtype == "Customized": self.ui.label_Ei_2.show() self.ui.comboBox_corrWS.show() self.ui.pushButton_refreshCorrWSList.show() # Search for table workspace self._searchTableWorkspaces() else: self.ui.label_Ei_2.hide() self.ui.comboBox_corrWS.hide() self.ui.pushButton_refreshCorrWSList.hide() def _searchTableWorkspaces(self): """ Search table workspaces and add to 'comboBox_corrWS' """ wsnames = AnalysisDataService.getObjectNames() tablewsnames = [] for wsname in wsnames: wksp = AnalysisDataService.retrieve(wsname) if isinstance(wksp, mantid.api.ITableWorkspace): tablewsnames.append(wsname) # ENDFOR self.ui.comboBox_corrWS.clear() if len(tablewsnames) > 0: self.ui.comboBox_corrWS.addItems(tablewsnames) def _setErrorMsg(self, errmsg): """ Clear error message """ self._errMsgWindow = QMessageBox() self._errMsgWindow.setIcon(QMessageBox.Critical) self._errMsgWindow.setWindowTitle('Error') self._errMsgWindow.setStandardButtons(QMessageBox.Ok) self._errMsgWindow.setText(errmsg) result = self._errMsgWindow.exec_() return result def helpClicked(self): from pymantidplot.proxies import showCustomInterfaceHelp showCustomInterfaceHelp("Filter Events") def _resetGUI(self, resetfilerun=False): """ Reset GUI including all text edits and etc. """ if resetfilerun is True: self.ui.lineEdit.clear() # Plot related self.ui.lineEdit_3.clear() self.ui.lineEdit_4.clear() self.ui.horizontalSlider.setValue(0) self.ui.horizontalSlider_2.setValue(100) self.ui.lineEdit_outwsname.clear() self.ui.lineEdit_title.clear() # Filter by log value self.ui.lineEdit_5.clear() self.ui.lineEdit_6.clear() self.ui.verticalSlider_2.setValue(0) self.ui.verticalSlider.setValue(100) ylim = self.ui.mainplot.get_ylim() miny = ylim[0] maxy = ylim[1] xlim = self.ui.mainplot.get_xlim() setp(self.lowerslideline, xdata=xlim, ydata=[miny, miny]) setp(self.upperslideline, xdata=xlim, ydata=[maxy, maxy]) self.ui.lineEdit_7.clear() self.ui.lineEdit_8.clear() self.ui.lineEdit_9.clear() # Filter by time self.ui.lineEdit_timeInterval.clear() # Advanced setup self.ui.comboBox_tofCorr.setCurrentIndex(0) self.ui.lineEdit_Ei.clear() self.ui.checkBox_fastLog.setCheckState(False) self.ui.checkBox_doParallel.setCheckState(False) self.ui.comboBox_skipSpectrum.setCurrentIndex(0) self.ui.checkBox_filterByPulse.setCheckState(False) self.ui.checkBox_from1.setCheckState(False) self.ui.checkBox_groupWS.setCheckState(True) self.ui.checkBox_splitLog.setCheckState(False) self.canvas.draw()
class MainWindow(QMainWindow): """ Class of Main Window (top) """ _errMsgWindow = None def __init__(self, parent=None): """ Initialization and set up """ # Base class QMainWindow.__init__(self, parent) # Mantid configuration config = ConfigService.Instance() self._instrument = config["default.instrument"] # Central widget self.centralwidget = QWidget(self) # UI Window (from Qt Designer) self.ui = load_ui(__file__, 'MainWindow.ui', baseinstance=self) mpl_layout = QVBoxLayout() self.ui.graphicsView.setLayout(mpl_layout) self.fig = Figure() self.canvas = FigureCanvas(self.fig) self.ui.mainplot = self.fig.add_subplot(111, projection='mantid') mpl_layout.addWidget(self.canvas) # Do initialize plotting vecx, vecy, xlim, ylim = self.computeMock() self.mainline = self.ui.mainplot.plot(vecx, vecy, 'r-') leftx = [xlim[0], xlim[0]] lefty = [ylim[0], ylim[1]] self.leftslideline = self.ui.mainplot.plot(leftx, lefty, 'b--') rightx = [xlim[1], xlim[1]] righty = [ylim[0], ylim[1]] self.rightslideline = self.ui.mainplot.plot(rightx, righty, 'g--') upperx = [xlim[0], xlim[1]] uppery = [ylim[1], ylim[1]] self.upperslideline = self.ui.mainplot.plot(upperx, uppery, 'b--') lowerx = [xlim[0], xlim[1]] lowery = [ylim[0], ylim[0]] self.lowerslideline = self.ui.mainplot.plot(lowerx, lowery, 'g--') self.canvas.mpl_connect('button_press_event', self.on_mouseDownEvent) # Set up horizontal slide (integer) and string value self._leftSlideValue = 0 self._rightSlideValue = 99 self.ui.horizontalSlider.setRange(0, 100) self.ui.horizontalSlider.setValue(self._leftSlideValue) self.ui.horizontalSlider.setTracking(True) self.ui.horizontalSlider.setTickPosition(QSlider.NoTicks) self.ui.horizontalSlider.valueChanged.connect(self.move_leftSlider) self.ui.horizontalSlider_2.setRange(0, 100) self.ui.horizontalSlider_2.setValue(self._rightSlideValue) self.ui.horizontalSlider_2.setTracking(True) self.ui.horizontalSlider_2.setTickPosition(QSlider.NoTicks) self.ui.horizontalSlider_2.valueChanged.connect(self.move_rightSlider) # self.connect(self.ui.lineEdit_3, QtCore.SIGNAL("textChanged(QString)"), # self.set_startTime) self.ui.lineEdit_3.setValidator(QDoubleValidator(self.ui.lineEdit_3)) self.ui.pushButton_setT0.clicked.connect(self.set_startTime) # self.connect(self.ui.lineEdit_4, QtCore.SIGNAL("textChanged(QString)"), # self.set_stopTime) self.ui.lineEdit_4.setValidator(QDoubleValidator(self.ui.lineEdit_4)) self.ui.pushButton_setTf.clicked.connect(self.set_stopTime) # File loader self.scanEventWorkspaces() self.ui.pushButton_refreshWS.clicked.connect(self.scanEventWorkspaces) self.ui.pushButton_browse.clicked.connect(self.browse_File) self.ui.pushButton_load.clicked.connect(self.load_File) self.ui.pushButton_3.clicked.connect(self.use_existWS) # Set up time self.ui.lineEdit_3.setValidator(QDoubleValidator(self.ui.lineEdit_3)) self.ui.lineEdit_4.setValidator(QDoubleValidator(self.ui.lineEdit_4)) # Filter by time self.ui.pushButton_filterTime.clicked.connect(self.filterByTime) # Filter by log value self.ui.lineEdit_5.setValidator(QDoubleValidator(self.ui.lineEdit_5)) self.ui.lineEdit_6.setValidator(QDoubleValidator(self.ui.lineEdit_6)) self.ui.lineEdit_7.setValidator(QDoubleValidator(self.ui.lineEdit_7)) self.ui.lineEdit_8.setValidator(QDoubleValidator(self.ui.lineEdit_8)) self.ui.lineEdit_9.setValidator(QDoubleValidator(self.ui.lineEdit_9)) self.ui.lineEdit_5.textChanged.connect(self.set_minLogValue) self.ui.lineEdit_6.textChanged.connect(self.set_maxLogValue) dirchangeops = ["Both", "Increase", "Decrease"] self.ui.comboBox_4.addItems(dirchangeops) logboundops = ["Centre", "Left"] self.ui.comboBox_5.addItems(logboundops) self.ui.pushButton_4.clicked.connect(self.plotLogValue) self.ui.pushButton_filterLog.clicked.connect(self.filterByLogValue) # Set up help button self.ui.helpBtn.clicked.connect(self.helpClicked) # Set up vertical slide self._upperSlideValue = 99 self._lowerSlideValue = 0 self.ui.verticalSlider.setRange(0, 100) self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.verticalSlider.setTracking(True) self.ui.verticalSlider.valueChanged.connect(self.move_upperSlider) self.ui.verticalSlider_2.setRange(0, 100) self.ui.verticalSlider_2.setValue(self._lowerSlideValue) self.ui.verticalSlider_2.setTracking(True) self.ui.verticalSlider_2.valueChanged.connect(self.move_lowerSlider) # Set up for filtering (advanced setup) self._tofcorrection = False self.ui.checkBox_fastLog.setChecked(False) self.ui.checkBox_filterByPulse.setChecked(False) self.ui.checkBox_from1.setChecked(False) self.ui.checkBox_groupWS.setChecked(True) self.ui.comboBox_tofCorr.currentIndexChanged.connect(self.showHideEi) self.ui.pushButton_refreshCorrWSList.clicked.connect(self._searchTableWorkspaces) self.ui.lineEdit_Ei.setValidator(QDoubleValidator(self.ui.lineEdit_Ei)) self.ui.label_Ei.hide() self.ui.lineEdit_Ei.hide() self.ui.label_Ei_2.hide() self.ui.comboBox_corrWS.hide() self.ui.pushButton_refreshCorrWSList.hide() # Set up for workspaces self._dataWS = None self._sampleLogNames = [] self._sampleLog = None # Side information self.ui.label_mean.hide() self.ui.label_meanvalue.hide() self.ui.label_avg.hide() self.ui.label_timeAvgValue.hide() self.ui.label_freq.hide() self.ui.label_freqValue.hide() self.ui.label_logname.hide() self.ui.label_lognamevalue.hide() self.ui.label_logsize.hide() self.ui.label_logsizevalue.hide() # Default self._defaultdir = os.getcwd() # register startup mantid.UsageService.registerFeatureUsage("Interface", "EventFilter", False) def on_mouseDownEvent(self, event): """ Respond to pick up a value with mouse down event """ x = event.xdata y = event.ydata if x is not None and y is not None: msg = "You've clicked on a bar with coords:\n %f, %f" % (x, y) QMessageBox.information(self, "Click!", msg) def computeMock(self): """ Compute vecx and vecy as mocking """ x0 = 0. xf = 1. dx = 0.1 vecx = [] vecy = [] x = x0 while x < xf: y = 0.0 vecx.append(x) vecy.append(y) x += dx xlim = [x0, xf] ylim = [-1., 1] return (vecx, vecy, xlim, ylim) def move_leftSlider(self): """ Re-setup left range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ newx = self.ui.horizontalSlider.value() if newx <= self._rightSlideValue and newx != self._leftSlideValue: # Allowed value: move the value bar self._leftSlideValue = newx # Move the vertical line xlim = self.ui.mainplot.get_xlim() newx = xlim[0] + newx*(xlim[1] - xlim[0])*0.01 leftx = [newx, newx] lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Change value self.ui.lineEdit_3.setText(str(newx)) else: # Reset the value to original value self.ui.horizontalSlider.setValue(self._leftSlideValue) def set_startTime(self): """ Set the starting time and left slide bar """ inps = str(self.ui.lineEdit_3.text()) info_msg = "Starting time = %s" % (inps) Logger("Filter_Events").information(info_msg) xlim = self.ui.mainplot.get_xlim() if inps == "": # Empty. Use default newtime0 = xlim[0] else: newtime0 = float(inps) # Convert to integer slide value ileftvalue = int((newtime0-xlim[0])/(xlim[1] - xlim[0])*100) debug_msg = "iLeftSlide = %s" % str(ileftvalue) Logger("Filter_Events").debug(debug_msg) # Skip if same as origina if ileftvalue == self._leftSlideValue: return # Set the value if out of range resetT = True if ileftvalue < 0: # Minimum value as 0 ileftvalue = 0 elif ileftvalue > self._rightSlideValue: # Maximum value as right slide value ileftvalue = self._rightSlideValue else: resetT = False if resetT is True: newtime0 = xlim[0] + ileftvalue*(xlim[1]-xlim[0])*0.01 info_msg = 'Corrected iLeftSlide = {} (vs. right = {})'.format(ileftvalue, self._rightSlideValue) Logger("Filter_Events").information(info_msg) # Move the slide bar (left) self._leftSlideValue = ileftvalue # Move the vertical line leftx = [newtime0, newtime0] lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Set the value to left slider self.ui.horizontalSlider.setValue(self._leftSlideValue) # Reset the value of line edit if resetT is True: self.ui.lineEdit_3.setText(str(newtime0)) def move_rightSlider(self): """ Re-setup left range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ newx = self.ui.horizontalSlider_2.value() if newx >= self._leftSlideValue and newx != self._rightSlideValue: # Allowed value: move the value bar self._rightSlideValue = newx xlim = self.ui.mainplot.get_xlim() newx = xlim[0] + newx*(xlim[1] - xlim[0])*0.01 leftx = [newx, newx] lefty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Change value self.ui.lineEdit_4.setText(str(newx)) else: # Reset the value self.ui.horizontalSlider_2.setValue(self._rightSlideValue) def set_stopTime(self): """ Set the starting time and left slide bar """ inps = str(self.ui.lineEdit_4.text()) Logger("Filter_Events").information('Stopping time = {}'.format(inps)) xlim = self.ui.mainplot.get_xlim() if inps == "": # Empty. Use default newtimef = xlim[1] else: # Parse newtimef = float(inps) # Convert to integer slide value irightvalue = int((newtimef-xlim[0])/(xlim[1] - xlim[0])*100) Logger("Filter_Events").information('iRightSlide = {}'.format(irightvalue)) # Return if no change if irightvalue == self._rightSlideValue: return # Correct value resetT = True if irightvalue > 100: irightvalue = 100 elif irightvalue < self._leftSlideValue: irightvalue = self._leftSlideValue else: resetT = False if resetT is True: newtimef = xlim[0] + irightvalue*(xlim[1]-xlim[0])*0.01 # Move the slide bar (right) self._rightSlideValue = irightvalue # Move the vertical line rightx = [newtimef, newtimef] righty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=rightx, ydata=righty) self.canvas.draw() # Set the value to left slider self.ui.horizontalSlider_2.setValue(self._rightSlideValue) # Reset to line edit if resetT: self.ui.lineEdit_4.setText(str(newtimef)) def move_lowerSlider(self): """ Re-setup upper range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ inewy = self.ui.verticalSlider_2.value() debug_msg = 'LowerSlFider is set with value {} vs. class variable {}'.format(inewy, self._lowerSlideValue) Logger("Filter_Events").debug(debug_msg) # Return with no change if inewy == self._lowerSlideValue: # No change return if inewy >= self._upperSlideValue: # Out of upper range inewy = self._upperSlideValue - 1 if inewy == 0 and self._lowerSlideValue < 0: setLineEdit = False else: setLineEdit = True # Move the lower vertical bar ylim = self.ui.mainplot.get_ylim() newy = ylim[0] + inewy*(ylim[1] - ylim[0])*0.01 lowerx = self.ui.mainplot.get_xlim() lowery = [newy, newy] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) self.canvas.draw() # Set line edit input if setLineEdit is True: # Change value to line edit (5) self.ui.lineEdit_5.setText(str(newy)) # Reset the class variable self._lowerSlideValue = inewy def set_minLogValue(self): """ Set the starting time and left slide bar """ debug_msg = 'Minimum Log Value = {}'.format(self.ui.lineEdit_5.text()) Logger("Filter_Events").debug(debug_msg) ylim = self.ui.mainplot.get_ylim() if str(self.ui.lineEdit_5.text()) == "": # Empty. Default to minY newminY = ylim[0] else: # Non empty. Parse newminY = float(self.ui.lineEdit_5.text()) # Convert to integer slide value iminlogval = int((newminY-ylim[0])/(ylim[1] - ylim[0])*100) Logger("Filter_Events").debug('ilowerSlide = {}'.format(iminlogval)) # Return if no change if iminlogval == self._lowerSlideValue: return # Set value if out of range resetL = True if iminlogval >= self._upperSlideValue: iminlogval = self._upperSlideValue - 1 else: resetL = False if resetL is True: newminY = ylim[0] + iminlogval * (ylim[1]-ylim[0]) * 0.01 # Move the vertical line lowerx = self.ui.mainplot.get_xlim() lowery = [newminY, newminY] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) self.canvas.draw() # Move the slide bar (lower) self._lowerSlideValue = iminlogval debug_msg = 'LineEdit5 set slide to {}'.format(self._lowerSlideValue) Logger("Filter_Events").debug(debug_msg) self.ui.verticalSlider_2.setValue(self._lowerSlideValue) # Reset line Edit if using default if resetL is True: self.ui.lineEdit_5.setText(str(newminY)) def move_upperSlider(self): """ Re-setup upper range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ inewy = self.ui.verticalSlider.value() # Return w/o change if inewy == self._upperSlideValue: return # Set to boundary value if inewy <= self._lowerSlideValue: inewy = self._lowerSlideValue + 1 # Reset line editor? if inewy == 100 and self._upperSlideValue > 100: setLineEdit = False else: setLineEdit = True # Move the upper value bar: upperx and uppery are # real value (float but not (0,100)) of the figure ylim = self.ui.mainplot.get_ylim() newy = ylim[0] + inewy*(ylim[1] - ylim[0])*0.01 upperx = self.ui.mainplot.get_xlim() uppery = [newy, newy] setp(self.upperslideline, xdata=upperx, ydata=uppery) self.canvas.draw() # Change value if setLineEdit is True: self.ui.lineEdit_6.setText(str(newy)) self._upperSlideValue = inewy def set_maxLogValue(self): """ Set maximum log value from line-edit """ inps = str(self.ui.lineEdit_6.text()) debug_msg = 'Maximum Log Value = {}'.format(inps) Logger("Filter_Events").debug(debug_msg) ylim = self.ui.mainplot.get_ylim() if inps == "": # Empty. Default to minY newmaxY = ylim[1] else: # Parse newmaxY = float(inps) # Convert to integer slide value imaxlogval = int((newmaxY-ylim[0])/(ylim[1] - ylim[0])*100) debug_msg = 'iUpperSlide = {}'.format(imaxlogval) Logger("Filter_Events").debug(debug_msg) # Return if no change if imaxlogval == self._upperSlideValue: return # Set to default if out of range resetL = True # if imaxlogval >= 100: # imaxlogval = 100 if imaxlogval < self._lowerSlideValue: imaxlogval = self._lowerSlideValue + 1 else: resetL = False # Set newmaxY if necessary if resetL is True: newmaxY = ylim[0] + imaxlogval * (ylim[1] - ylim[0]) * 0.01 # Move the vertical line upperx = self.ui.mainplot.get_xlim() uppery = [newmaxY, newmaxY] setp(self.upperslideline, xdata=upperx, ydata=uppery) self.canvas.draw() # Set the value to upper slider self._upperSlideValue = imaxlogval self.ui.verticalSlider.setValue(self._upperSlideValue) # Set the value to editor if necessary if resetL is True: self.ui.lineEdit_6.setText(str(newmaxY)) def browse_File(self): """ Open a file dialog to get file """ filename = QFileDialog.getOpenFileName(self, 'Input File Dialog', self._defaultdir, "Data (*.nxs *.dat);;All files (*)") if isinstance(filename, tuple): filename = filename[0] self.ui.lineEdit.setText(filename) Logger("Filter_Events").information('Selected file: "{}"'.format(filename)) def load_File(self): """ Load the file by file name or run number """ # Get file name from line editor filename = str(self.ui.lineEdit.text()) dataws = self._loadFile(str(filename)) if dataws is None: error_msg = 'Unable to locate run {} in default directory {}.'.format(filename, self._defaultdir) Logger("Filter_Events").error(error_msg) self._setErrorMsg(error_msg) else: self._importDataWorkspace(dataws) self._defaultdir = os.path.dirname(str(filename)) # Reset GUI self._resetGUI(resetfilerun=False) def use_existWS(self): """ Set up workspace to an existing one """ wsname = str(self.ui.comboBox.currentText()) try: dataws = AnalysisDataService.retrieve(wsname) self._importDataWorkspace(dataws) except KeyError: pass # Reset GUI self._resetGUI(resetfilerun=True) def plotLogValue(self): """ Plot log value """ # Get log value logname = str(self.ui.comboBox_2.currentText()) if len(logname) == 0: # return due to the empty one is chozen return samplelog = self._dataWS.getRun().getProperty(logname) vectimes = samplelog.times vecvalue = samplelog.value # check if len(vectimes) == 0: error_msg = "Empty log!" Logger("Filter_Events").error(error_msg) # Convert absolute time to relative time in seconds t0 = self._dataWS.getRun().getProperty("proton_charge").times[0] # append 1 more log if original log only has 1 value tf = self._dataWS.getRun().getProperty("proton_charge").times[-1] vectimes = numpy.append(vectimes, tf) vecvalue = numpy.append(vecvalue, vecvalue[-1]) vecreltimes = (vectimes - t0) / numpy.timedelta64(1, 's') # Set to plot xlim = [vecreltimes.min(), vecreltimes.max()] ylim = [vecvalue.min(), vecvalue.max()] self.ui.mainplot.set_xlim(xlim[0], xlim[1]) self.ui.mainplot.set_ylim(ylim[0], ylim[1]) setp(self.mainline, xdata=vecreltimes, ydata=vecvalue) samunit = samplelog.units if len(samunit) == 0: ylabel = logname else: ylabel = "%s (%s)" % (logname, samunit) self.ui.mainplot.set_ylabel(ylabel, fontsize=13) # assume that all logs are on almost same X-range. Only Y need to be reset setp(self.leftslideline, ydata=ylim) setp(self.rightslideline, ydata=ylim) # reset the log value limit as previous one does not make any sense setp(self.lowerslideline, xdata=xlim, ydata=[ylim[0], ylim[0]]) self._lowerSlideValue = 0 self.ui.verticalSlider_2.setValue(self._lowerSlideValue) self.ui.lineEdit_5.setText("") setp(self.upperslideline, xdata=xlim, ydata=[ylim[1], ylim[1]]) self._upperSlideValue = 100 self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.lineEdit_6.setText("") self.canvas.draw() # Load property's statistic and give suggestion on parallel and fast log timeavg = samplelog.timeAverageValue() numentries = samplelog.size() stat = samplelog.getStatistics() duration = stat.duration mean = stat.mean freq = float(numentries)/float(duration) self.ui.label_mean.show() self.ui.label_meanvalue.show() self.ui.label_avg.show() self.ui.label_timeAvgValue.show() self.ui.label_freq.show() self.ui.label_freqValue.show() self.ui.label_logname.show() self.ui.label_lognamevalue.show() self.ui.label_logsize.show() self.ui.label_logsizevalue.show() self.ui.label_meanvalue.setText("%.5e" % (mean)) self.ui.label_timeAvgValue.setText("%.5e" % (timeavg)) self.ui.label_freqValue.setText("%.5e" % (freq)) self.ui.label_lognamevalue.setText(logname) self.ui.label_logsizevalue.setText(str(numentries)) # Set suggested processing scheme if numentries > HUGE_FAST: self.ui.checkBox_fastLog.setCheckState(True) if numentries > HUGE_PARALLEL: self.ui.checkBox_doParallel.setCheckState(True) else: self.ui.checkBox_doParallel.setCheckState(False) else: self.ui.checkBox_fastLog.setCheckState(False) self.ui.checkBox_doParallel.setCheckState(False) return def _importDataWorkspace(self, dataws): """ Import data workspace for filtering """ if dataws is None: return # Plot time counts errmsg = self._plotTimeCounts(dataws) if errmsg is not None: errmsg = 'Workspace {} has invalid sample logs for splitting. Loading \ failure! \n{}\n'.format(dataws, errmsg) self._setErrorMsg(errmsg) return False # Import log self._sampleLogNames = [""] run = dataws.getRun() plist = run.getProperties() for p in plist: try: times = p.times if len(times) > 1 and numpy.isreal(p.value[0]): self._sampleLogNames.append(p.name) # This is here for FloatArrayProperty. If a log value is of this type it does not have times except AttributeError: pass # ENDFOR(p) # Set up sample log self.ui.comboBox_2.clear() self.ui.comboBox_2.addItems(self._sampleLogNames) # Side information self.ui.label_mean.hide() self.ui.label_meanvalue.hide() self.ui.label_avg.hide() self.ui.label_timeAvgValue.hide() self.ui.label_freq.hide() self.ui.label_freqValue.hide() # Hide 'log name' above the graphic view self.ui.label_logname.hide() self.ui.label_lognamevalue.hide() # Set dataws to class variable self._dataWS = dataws return True def scanEventWorkspaces(self): """ """ wsnames = AnalysisDataService.getObjectNames() eventwsnames = [] for wsname in wsnames: wksp = AnalysisDataService.retrieve(wsname) if wksp.__class__.__name__.count("Event") == 1: eventwsnames.append(wsname) # ENDFOR if len(eventwsnames) > 0: self.ui.comboBox.clear() self.ui.comboBox.addItems(eventwsnames) def _loadFile(self, filename): """ Load file or run File will be loaded to a workspace shown in MantidPlot """ config = ConfigService # Check input file name and output workspace name if filename.isdigit() is True: # Construct a file name from run number runnumber = int(filename) if runnumber <= 0: error_msg = 'Run number cannot be less or equal to zero. User gives {}.'.format(filename) Logger("Filter_Events").error(error_msg) return None else: ishort = config.getInstrument(self._instrument).shortName() filename = '{}_{}'.format(ishort, filename) wsname = filename + "_event" elif filename.count(".") > 0: # A proper file name wsname = os.path.splitext(os.path.split(filename)[1])[0] elif filename.count("_") == 1: # A short one as instrument_runnumber iname = filename.split("_")[0] str_runnumber = filename.split("_")[1] if str_runnumber.isdigit() is True and int(str_runnumber) > 0: # Accepted format ishort = config.getInstrument(iname).shortName() wsname = '{}_{}_event'.format(ishort, str_runnumber) else: # Non-supported error_msg = 'File name / run number in such format {} is not supported.'.format(filename) Logger("Filter_Events").error(error_msg) return None else: # Unsupported format error_msg = 'File name / run number in such format {} is not supported.'.format(filename) Logger("Filter_Events").error(error_msg) return None # Load try: ws = api.Load(Filename=filename, OutputWorkspace=wsname) except RuntimeError as e: ws = None return str(e) return ws def _plotTimeCounts(self, wksp): """ Plot time/counts """ import datetime # Rebin events by pulse time try: # Get run start and run stop if wksp.getRun().hasProperty("run_start"): runstart = wksp.getRun().getProperty("run_start").value else: runstart = wksp.getRun().getProperty("proton_charge").times[0] runstop = wksp.getRun().getProperty("proton_charge").times[-1] runstart = str(runstart).split(".")[0].strip() runstop = str(runstop).split(".")[0].strip() t0 = datetime.datetime.strptime(runstart, "%Y-%m-%dT%H:%M:%S") tf = datetime.datetime.strptime(runstop, "%Y-%m-%dT%H:%M:%S") # Calculate dt = tf-t0 timeduration = dt.days*3600*24 + dt.seconds timeres = float(timeduration)/MAXTIMEBINSIZE if timeres < 1.0: timeres = 1.0 sumwsname = '_Summed_{}'.format(wksp) if AnalysisDataService.doesExist(sumwsname) is False: sumws = api.SumSpectra(InputWorkspace=wksp, OutputWorkspace=sumwsname) sumws = api.RebinByPulseTimes(InputWorkspace=sumws, OutputWorkspace=sumwsname, Params='{}'.format(timeres)) sumws = api.ConvertToPointData(InputWorkspace=sumws, OutputWorkspace=sumwsname) else: sumws = AnalysisDataService.retrieve(sumwsname) except RuntimeError as e: return str(e) vecx = sumws.readX(0) vecy = sumws.readY(0) xmin = min(vecx) xmax = max(vecx) ymin = min(vecy) ymax = max(vecy) # Reset graph self.ui.mainplot.set_xlim(xmin, xmax) self.ui.mainplot.set_ylim(ymin, ymax) self.ui.mainplot.set_xlabel('Time (seconds)', fontsize=13) self.ui.mainplot.set_ylabel('Counts', fontsize=13) # Set up main line setp(self.mainline, xdata=vecx, ydata=vecy) # Reset slide newslidery = [min(vecy), max(vecy)] newleftx = xmin + (xmax-xmin)*self._leftSlideValue*0.01 setp(self.leftslideline, xdata=[newleftx, newleftx], ydata=newslidery) newrightx = xmin + (xmax-xmin)*self._rightSlideValue*0.01 setp(self.rightslideline, xdata=[newrightx, newrightx], ydata=newslidery) self.canvas.draw() def filterByTime(self): """ Filter by time """ # Generate event filters kwargs = {} if self.ui.lineEdit_3.text() != "": rel_starttime = float(self.ui.lineEdit_3.text()) kwargs["StartTime"] = str(rel_starttime) if self.ui.lineEdit_4.text() != "": rel_stoptime = float(self.ui.lineEdit_4.text()) kwargs["StopTime"] = str(rel_stoptime) if self.ui.lineEdit_timeInterval.text() != "": interval = float(self.ui.lineEdit_timeInterval.text()) kwargs["TimeInterval"] = interval splitwsname = str(self._dataWS) + "_splitters" splitinfowsname = str(self._dataWS) + "_info" title = str(self.ui.lineEdit_title.text()) fastLog = self.ui.checkBox_fastLog.isChecked() splitws, infows = api.GenerateEventsFilter(InputWorkspace=self._dataWS, UnitOfTime="Seconds", TitleOfSplitters=title, OutputWorkspace=splitwsname, FastLog=fastLog, InformationWorkspace=splitinfowsname, **kwargs) self.splitWksp(splitws, infows) def filterByLogValue(self): """ Filter by log value """ # Generate event filter kwargs = {} samplelog = str(self.ui.comboBox_2.currentText()) if len(samplelog) == 0: error_msg = "No sample log is selected!" Logger("Filter_Events").error(error_msg) return if self.ui.lineEdit_3.text() != "": rel_starttime = float(self.ui.lineEdit_3.text()) kwargs["StartTime"] = str(rel_starttime) if self.ui.lineEdit_4.text() != "": rel_stoptime = float(self.ui.lineEdit_4.text()) kwargs["StopTime"] = str(rel_stoptime) if self.ui.lineEdit_5.text() != "": minlogvalue = float(self.ui.lineEdit_5.text()) kwargs["MinimumLogValue"] = minlogvalue if self.ui.lineEdit_6.text() != "": maxlogvalue = float(self.ui.lineEdit_6.text()) kwargs["MaximumLogValue"] = maxlogvalue if self.ui.lineEdit_7.text() != "": logvalueintv = float(self.ui.lineEdit_7.text()) kwargs["LogValueInterval"] = logvalueintv logvalchangedir = str(self.ui.comboBox_4.currentText()) kwargs["FilterLogValueByChangingDirection"] = logvalchangedir if self.ui.lineEdit_9.text() != "": logvalueintv = float(self.ui.lineEdit_9.text()) kwargs["TimeTolerance"] = logvalueintv logboundtype = str(self.ui.comboBox_5.currentText()) kwargs["LogBoundary"] = logboundtype if self.ui.lineEdit_8.text() != "": logvaluetol = float(self.ui.lineEdit_8.text()) kwargs["LogValueTolerance"] = logvaluetol splitwsname = str(self._dataWS) + "_splitters" splitinfowsname = str(self._dataWS) + "_info" fastLog = self.ui.checkBox_fastLog.isChecked() title = str(self.ui.lineEdit_title.text()) splitws, infows = api.GenerateEventsFilter(InputWorkspace=self._dataWS, UnitOfTime="Seconds", TitleOfSplitters=title, OutputWorkspace=splitwsname, LogName=samplelog, FastLog=fastLog, InformationWorkspace=splitinfowsname, **kwargs) try: self.splitWksp(splitws, infows) except RuntimeError as e: self._setErrorMsg("Splitting Failed!\n %s" % (str(e))) def splitWksp(self, splitws, infows): """ Run FilterEvents """ dogroupws = self.ui.checkBox_groupWS.isChecked() filterbypulse = self.ui.checkBox_filterByPulse.isChecked() startfrom1 = self.ui.checkBox_from1.isChecked() splitsamplelog = self.ui.checkBox_splitLog.isChecked() corr2sample = str(self.ui.comboBox_tofCorr.currentText()) how2skip = str(self.ui.comboBox_skipSpectrum.currentText()) kwargs = {} if corr2sample == "Direct": ei = float(self.ui.lineEdit_Ei.text()) kwargs["IncidentEnergy"] = ei elif corr2sample == "Customized": corrws = str(self.ui.comboBox_corrWS.currentText()) kwargs["DetectorTOFCorrectionWorkspace"] = corrws # Output workspace name outbasewsname = str(self.ui.lineEdit_outwsname.text()) if len(outbasewsname) == 0: outbasewsname = "tempsplitted" self.ui.lineEdit_outwsname.setText(outbasewsname) api.FilterEvents(InputWorkspace=self._dataWS, SplitterWorkspace=splitws, InformationWorkspace=infows, OutputWorkspaceBaseName=outbasewsname, GroupWorkspaces=dogroupws, FilterByPulseTime=filterbypulse, CorrectionToSample=corr2sample, SpectrumWithoutDetector=how2skip, SplitSampleLogs=splitsamplelog, OutputWorkspaceIndexedFrom1=startfrom1, OutputTOFCorrectionWorkspace='TOFCorrTable', **kwargs) def showHideEi(self): """ """ corrtype = str(self.ui.comboBox_tofCorr.currentText()) # Incident energy if corrtype == "Direct": self.ui.label_Ei.show() self.ui.lineEdit_Ei.show() else: self.ui.label_Ei.hide() self.ui.lineEdit_Ei.hide() # Workspace if corrtype == "Customized": self.ui.label_Ei_2.show() self.ui.comboBox_corrWS.show() self.ui.pushButton_refreshCorrWSList.show() # Search for table workspace self._searchTableWorkspaces() else: self.ui.label_Ei_2.hide() self.ui.comboBox_corrWS.hide() self.ui.pushButton_refreshCorrWSList.hide() def _searchTableWorkspaces(self): """ Search table workspaces and add to 'comboBox_corrWS' """ wsnames = AnalysisDataService.getObjectNames() tablewsnames = [] for wsname in wsnames: wksp = AnalysisDataService.retrieve(wsname) if isinstance(wksp, mantid.api.ITableWorkspace): tablewsnames.append(wsname) # ENDFOR self.ui.comboBox_corrWS.clear() if len(tablewsnames) > 0: self.ui.comboBox_corrWS.addItems(tablewsnames) def _setErrorMsg(self, errmsg): """ Clear error message """ self._errMsgWindow = QMessageBox() self._errMsgWindow.setIcon(QMessageBox.Critical) self._errMsgWindow.setWindowTitle('Error') self._errMsgWindow.setStandardButtons(QMessageBox.Ok) self._errMsgWindow.setText(errmsg) result = self._errMsgWindow.exec_() return result def helpClicked(self): try: from pymantidplot.proxies import showCustomInterfaceHelp showCustomInterfaceHelp("Filter Events") except ImportError: url = ("http://docs.mantidproject.org/nightly/interfaces/{}.html" "".format("Filter Events")) QDesktopServices.openUrl(QUrl(url)) def _resetGUI(self, resetfilerun=False): """ Reset GUI including all text edits and etc. """ if resetfilerun is True: self.ui.lineEdit.clear() # Plot related self.ui.lineEdit_3.clear() self.ui.lineEdit_4.clear() self.ui.horizontalSlider.setValue(0) self.ui.horizontalSlider_2.setValue(100) self.ui.lineEdit_outwsname.clear() self.ui.lineEdit_title.clear() # Filter by log value self.ui.lineEdit_5.clear() self.ui.lineEdit_6.clear() self.ui.verticalSlider_2.setValue(0) self.ui.verticalSlider.setValue(100) ylim = self.ui.mainplot.get_ylim() miny = ylim[0] maxy = ylim[1] xlim = self.ui.mainplot.get_xlim() setp(self.lowerslideline, xdata=xlim, ydata=[miny, miny]) setp(self.upperslideline, xdata=xlim, ydata=[maxy, maxy]) self.ui.lineEdit_7.clear() self.ui.lineEdit_8.clear() self.ui.lineEdit_9.clear() # Filter by time self.ui.lineEdit_timeInterval.clear() # Advanced setup self.ui.comboBox_tofCorr.setCurrentIndex(0) self.ui.lineEdit_Ei.clear() self.ui.checkBox_fastLog.setCheckState(False) self.ui.checkBox_doParallel.setCheckState(False) self.ui.comboBox_skipSpectrum.setCurrentIndex(0) self.ui.checkBox_filterByPulse.setCheckState(False) self.ui.checkBox_from1.setCheckState(False) self.ui.checkBox_groupWS.setCheckState(True) self.ui.checkBox_splitLog.setCheckState(False) self.canvas.draw()