class GUI: def __init__(self): self.b = Gtk.Builder() gui_xml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'calibrate_camera_extrinsics_gui.xml') self.b.add_from_file(gui_xml_path) self.window = self.b.get_object("window") self.window.set_title('CamExtrinsicCalibrator') self.f = matplotlib.figure.Figure() self.ax = self.f.add_subplot(111) self.f.subplots_adjust(left=0.01, right=0.99, bottom=0.01, top=0.99, hspace=0, wspace=0) self.canvas = FigureCanvas(self.f) self.b.get_object("alignment_img").add(self.canvas) self.image_display_mode = None self.window.show_all() def display_image(self, model): label = self.b.get_object("label_image") label.set_text(model.image_path) img = model.get_image(self.image_display_mode) if len(img.shape) == 2: img2 = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) else: img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) self.ax.imshow(img2) self.canvas.draw()
class PlotCanvas(object): def __init__(self, title, label, unit, color): # super(PlotCanvas, self).__init__() self.fig = Figure() self.ax = self.fig.add_subplot(111) self.ax.set_title(title) self.ax.grid(True) self.canvas = FigureCanvas(self.fig) self.canvas.set_size_request(400, 300) self.canvas.show() self.data = [] self.line, = self.ax.plot([], self.data) self.line.set_label(label) self.line.set_color(color) # self.ax.set_xlabel("# de Muestras") # self.ax.set_ylabel(f"[{unit}]") self.ax.legend(loc='upper right') def update_draw(self, *args): # print(args[0]) self.data.append(args[0]) # print(self.data) self.line.set_data(range(len(self.data)), self.data) # self.l_data.set_ydata(self.data) self.ax.relim() self.ax.autoscale_view(True, True, True) # print(self.l_data) try: self.canvas.draw() except Exception as e: print(e)
class Map: def __init__(self, viewport: Gtk.Viewport): self._viewport = viewport figure = Figure() self._canvas = FigureCanvas(figure) self._viewport.add(self._canvas) self._viewport.show_all() def draw_cities(self, cities, tour=False): x = np.array([city.x for city in cities], dtype=np.float) y = np.array([city.y for city in cities], dtype=np.float) figure = self._canvas.figure axis = figure.subplots(1, 1) axis.get_xaxis().set_visible(False) axis.get_yaxis().set_visible(False) axis.clear() axis.scatter(x, y, color='red', linewidth=0.5) if tour: x = np.append(x, x[0]) y = np.append(y, y[0]) axis.plot(x, y, linewidth=0.5) self._canvas.draw()
class History: def __init__(self, viewport): self._viewport = viewport figure = Figure() self._canvas = FigureCanvas(figure) self._viewport.add(self._canvas) self._viewport.show_all() def draw(self, ga_history, pso_history): x_ga = np.array([i + 1 for i in range(len(ga_history))], dtype=np.int) y_ga = np.array(ga_history, dtype=np.float) x_pso = np.array([i + 1 for i in range(len(pso_history))], dtype=np.int) y_pso = np.array(pso_history, dtype=np.float) figure = self._canvas.figure axis = figure.subplots(1, 1) axis.clear() ga, = axis.plot(x_ga, y_ga) pso, = axis.plot(x_pso, y_pso) axis.legend((ga, pso), ('GA', 'PSO')) self._canvas.draw() time.sleep(1e-2) try: figure.clf() except: pass
class Plot(Gtk.Frame): def __init__(self, sp, refs): Gtk.Frame.__init__(self) self.f = Figure() self.canvas = FigureCanvas(self.f) self.add(self.canvas) self.set_size_request(1024, 600) self.f.subplots_adjust(left=0.07, right=0.98, bottom=0.05, top=0.95, hspace=0.2, wspace=0.2) # self.buffer = self.canvas.get_snapshot() def decorate(self, axis, title=None, ylab=None, legend=None): # font_prop = fm.FontProperties(fname='Humor-Sans-1.0.ttf', size=14) if title is not None: axis.set_title(title) # , fontproperties=font_prop) if ylab is not None: axis.yaxis.set_label_text(ylab) # , fontproperties=font_prop) if legend is not None: axis.legend(legend) # , prop=font_prop) axis.xaxis.grid(color='k', linestyle='-', linewidth=0.2) axis.yaxis.grid(color='k', linestyle='-', linewidth=0.2) def update(self, sp, refs): title = [r'$\phi$', r'$\theta$', r'$\psi$'] legend = ['Ref1', 'Ref2', 'Setpoint'] for i in range(0, 3): axis = self.f.add_subplot(331 + i) axis.clear() for ref in refs: axis.plot(sp.time, pu.deg_of_rad(ref.euler[:, i])) axis.plot(sp.time, pu.deg_of_rad(sp.euler[:, i])) self.decorate(axis, title[i], *(('deg', legend) if i == 0 else (None, None))) title = [r'$p$', r'$q$', r'$r$'] for i in range(0, 3): axis = self.f.add_subplot(334 + i) axis.clear() for ref in refs: axis.plot(sp.time, pu.deg_of_rad(ref.vel[:, i])) self.decorate(axis, title[i], 'deg/s' if i == 0 else None) title = [r'$\dot{p}$', r'$\dot{q}$', r'$\dot{r}$'] for i in range(0, 3): axis = self.f.add_subplot(337 + i) axis.clear() for ref in refs: axis.plot(sp.time, pu.deg_of_rad(ref.accel[:, i])) self.decorate(axis, title[i], 'deg/s2' if i == 0 else None) self.canvas.draw()
class ResidualsPlotView(View['ResidualsPlotPresenter', Gtk.Widget]): def _do_init(self) -> Gtk.Widget: from matplotlib.backends.backend_gtk3agg import FigureCanvasGTK3Agg as FigureCanvas from matplotlib.figure import Figure self._widget = Gtk.Grid() figure = Figure(tight_layout=True) self._figure_canvas = FigureCanvas(figure) self._figure_canvas.props.hexpand = True self._figure_canvas.props.vexpand = True self._figure_canvas.show() self._widget.add(self._figure_canvas) self._axes = figure.add_subplot(1, 1, 1) # Set tick labels font size for item in (*self._axes.get_xticklabels(), *self._axes.get_yticklabels()): item.set_fontsize(8) self.presenter.view_ready() return self._widget def set_data(self, residuals: np.ndarray) -> None: axes = self._axes axes.clear() if residuals is None or len(residuals) == 0: axes.set_axis_off() self._figure_canvas.draw() return axes.set_axis_on() axes.plot(residuals[:, 0], residuals[:, 1], color='#0080ff', marker='o', linestyle='') self._figure_canvas.draw() def _do_destroy(self) -> None: self._widget.destroy()
class ImgPltNode(GtkNodes.Node): __gtype_name__ = 'PltNode' def __init__(self, *args, **kwds): super().__init__(*args, **kwds) self.set_label("Image Plot") self.connect("node_func_clicked", self.remove) # create input socket lbl = Gtk.Label.new("Input") lbl.set_xalign(0.0) node_socket_input = self.item_add(lbl, GtkNodes.NodeSocketIO.SINK) node_socket_input.connect("socket_incoming", self.node_socket_incoming) # the compatibility key node_socket_input.set_key(1234) node_socket_input.set_rgba(get_rgba('darkturquoise')) f = Figure(figsize=(5, 4), dpi=100) self.a = f.add_subplot(111) sw = Gtk.ScrolledWindow() sw.set_border_width(10) self.canvas = FigureCanvas(f) sw.add(self.canvas) sw.set_size_request(200, 200) self.item_add(sw, GtkNodes.NodeSocketIO.DISABLE) self.set_child_packing(sw, True, True, 0, Gtk.PackType.END) def node_socket_incoming(self, socket, payload): img = pickle.loads(payload) self.a.imshow(img) self.canvas.draw() def remove(self, node): self.destroy()
class OdPredictorGui(Gtk.HBox): def __init__(self): super().__init__() self.controls = ControlPanel() self.controls.connect('new-params', self.on_new_params) self.fig = Figure(facecolor='#e9e9e9') self.axes = self.fig.add_subplot(1, 1, 1) self.canvas = FigureCanvas(self.fig) self.canvas.set_size_request(300, 300) self.pack_start(self.controls, False, False, 0) self.pack_start(self.canvas, True, True, 0) self.on_new_params() def on_new_params(self, *args): predictor = self.controls.get_params() predictor.plot_time_estimate(self.axes) self.fig.tight_layout(pad=1.0) self.canvas.draw()
class PopUpImage(object): def __init__(self, xdata, ydata, xlabel, ylabel, title): self.popupwin=Gtk.Window() self.popupwin.set_size_request(600,550) self.popupwin.set_position(Gtk.WindowPosition.CENTER) self.popupwin.set_border_width(10) self.xdata = xdata self.ydata = ydata vbox = Gtk.VBox() self.fig=Figure(dpi=100) self.ax = self.fig.add_subplot(111) self.canvas = FigureCanvas(self.fig) self.main_figure_navBar = NavigationToolbar(self.canvas, self) self.cursor = Cursor(self.ax, color='k', linewidth=1, useblit=True) self.canvas.mpl_connect("button_press_event",self.on_press) self.ax.set_xlabel(xlabel, fontsize = 18) self.ax.set_ylabel(ylabel, fontsize = 18) self.ax.set_title(title, fontsize = 18) self.ax.plot(self.xdata, self.ydata, 'b-', lw=2) self.textes = [] self.plots = [] vbox.pack_start(self.main_figure_navBar, False, False, 0) vbox.pack_start(self.canvas, True, True, 2) self.popupwin.add(vbox) self.popupwin.connect("destroy", self.dest) self.popupwin.show_all() def dest(self,widget): self.popupwin.destroy() def on_press(self, event): if event.inaxes == self.ax and event.button==3: self.clear_notes() xc = event.xdata #***** Find the closest x value ***** residuel = self.xdata - xc residuel = N.abs(residuel) j = N.argmin(residuel) #y = self.ydata[i-1:i+1] #yc= y.max() #j = N.where(self.ydata == yc) #j = j[0][0] xc= self.xdata[j] x_fit = self.xdata[j-3:j+3] y_fit = self.ydata[j-3:j+3] fitted_param, fitted_data = fit(x_fit, y_fit, xc, True) x_fit = N.linspace(x_fit.min(), x_fit.max(), 200) y_fit = psdVoigt(fitted_param, x_fit) period = fitted_param['xc'].value std_err= fitted_param['xc'].stderr p = self.ax.plot(x_fit, y_fit,'r-') p2 = self.ax.axvline(period,color='green',lw=2) txt=self.ax.text(0.05, 0.9, 'Period = %.4f +- %.4f (nm)'%(period, std_err), transform = self.ax.transAxes, color='red') self.textes.append(txt) self.plots.append(p[0]) self.plots.append(p2) elif event.inaxes == self.ax and event.button==2: dif = N.diff(self.ydata) dif = dif/dif.max() p3 = self.ax.plot(dif,'r-') self.plots.append(p3[0]) self.canvas.draw() def clear_notes(self): if len(self.textes)>0: for t in self.textes: t.remove() if len(self.plots)>0: for p in self.plots: p.remove() self.textes = [] self.plots = []
class KMeans(Gtk.Window): def __init__(self): Gtk.Window.__init__(self) self.set_title("k srednich") self.connect('destroy', Gtk.main_quit) self.main_view = Gtk.HBox() self.plot_view = Gtk.VBox() self.box = Gtk.VBox(homogeneous=False, spacing=0) self.filew = "" button1 = Gtk.Button("Wybierz plik") button1.connect("clicked", self.on_file_clicked) self.box.add(button1) reset_button = Gtk.Button("Resetuj") reset_button.connect("clicked", self.reset) self.box.add(reset_button) self.cluster_label = Gtk.Label("Liczba skupien:") self.box.add(self.cluster_label) adjustment = Gtk.Adjustment(1, 1, 20, 1, 1, 0) self.h_scale = Gtk.Scale( orientation=Gtk.Orientation.HORIZONTAL, adjustment=adjustment) self.h_scale.set_digits(0) self.h_scale.set_hexpand(True) self.h_scale.set_valign(Gtk.Align.START) self.h_scale.connect("value-changed", self.scale_moved) self.box.add(self.h_scale) metric_label = Gtk.Label("Wybierz rodzaj metryki:") name_store = Gtk.ListStore(int, str) name_store.append([1, "Euklidesowa"]) name_store.append([2, "Miejska"]) name_combo = Gtk.ComboBox.new_with_model_and_entry(name_store) name_combo.connect("changed", self.on_name_combo_changed) name_combo.set_entry_text_column(1) self.box.add(metric_label) self.box.add(name_combo) self.centroid_button = Gtk.Button("Wybierz centroidy") self.centroid_button.set_sensitive(False) self.centroid_button.connect("clicked", self.run_kmeans) self.group_button = Gtk.Button("Grupuj") self.group_button.set_sensitive(False) self.group_button.connect("clicked", self.group) self.scale_plot = Gtk.Button("Skaluj") self.scale_plot.set_sensitive(False) self.scale_plot.connect("clicked", self.scaled) self.box.add(self.centroid_button) self.box.add(self.group_button) self.box.add(self.scale_plot) self.data = "" self.cluster_count = "" self.metric_id = "" self.filename = "" self.plot_area = "" self.cluster = "" self.color_random = "" self.figure = "" self.cluster_centers = [] self.plot_canvas = "" self.main_data_canvas = "" self.main_view.add(self.box) self.main_view.add(self.plot_view) self.add(self.main_view) self.couting = 0 self.is_random_center = 0 self.show_all() def scaled(self, event): plt.scatter(*zip(*self.data), c=self.color_random[self.cluster]) plt.scatter(*zip(*self.cluster_centers), s=500, c=self.color_random, marker='v') plt.show() def run_kmeans(self, event): self.kmeans(self.cluster_count, self.data) def group(self, event): self.couting += 1 if self.couting % 2 == 0: print "Parzysta" self.kmeans(self.cluster_count, self.data) # self.plot_area.scatter(*zip(*self.data)) self.plot_area.clear() self.plot_area.scatter(*zip(*self.data)) self.plot_area.scatter(*zip(*self.cluster_centers), s=500, c=self.color_random, marker='v') self.plot_canvas.draw() self.plot_view.show_all() else: print "Nieparzysta" self.plot_area.scatter(*zip(*self.data), c=self.color_random[self.cluster]) self.plot_area.scatter(*zip(*self.cluster_centers), s=500, c=self.color_random, marker='v') self.plot_canvas.draw() self.plot_view.show_all() def on_name_combo_changed(self, combo): tree_iter = combo.get_active_iter() if tree_iter != None: model = combo.get_model() row_id, name = model[tree_iter][:2] self.metric_id = row_id # 1 euklidesowa # 2 miejsca print("Selected: ID=%d, name=%s" % (row_id, name)) else: entry = combo.get_child() print("Entered: %s" % entry.get_text()) def scale_moved(self, event): self.cluster_count = self.h_scale.get_value() def on_file_clicked(self, widget): print "clikc" dialog = Gtk.FileChooserDialog("Please choose a file", self, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) response = dialog.run() if response == Gtk.ResponseType.OK: print("Open clicked") print("File selected: " + dialog.get_filename()) self.filename = dialog.get_filename() dialog.destroy() self.openfile(self.filename) elif response == Gtk.ResponseType.CANCEL: print("Cancel clicked") def openfile(self, filename): with open(filename) as csvfile: self.data = [(float(x), float(y)) for x, y in csv.reader(csvfile, delimiter=",")] self.load_data_from_file() def load_data_from_file(self): self.centroid_button.set_sensitive(True) self.group_button.set_sensitive(True) self.scale_plot.set_sensitive(True) f = Figure(figsize=(5, 4), dpi=100) a = f.add_subplot(111) a.scatter(*zip(*self.data)) self.main_data_canvas = FigureCanvas(f) self.plot_view.add(self.main_data_canvas) self.plot_view.show_all() self.resize(1000,400) def euclides_distance(self, p1, p2): dist = 0.0 for i in xrange(0, len(p2)): dist += (p1[i] - p2[i]) ** 2 return math.sqrt(dist) def manhattan_distance(self, x, y): return sum(abs(a - b) for a, b in zip(x, y)) def kmeans(self, k, data): self.color_random = np.arange(k) # wymiar danych dim = len(data[0]) # lista zer cluster = [0] * len(data) # lista -1 prev_cluster = [-1] * len(data) i = 0 max_iter = 1000 if self.is_random_center == 0: for i in xrange(0, int(k)): self.cluster_centers += [random.choice(data)] self.is_random_center = 1 # while (cluster != prev_cluster) or i > max_iter: prev_cluster = list(cluster) i += 1 print "Iteracja numer" # print "Cluster {}".format(cluster) for x in xrange(0, len(data)): min_dist = float("inf") # sprawdzenie minimalnego dystansu miedzy srodkami for y in xrange(0, len(self.cluster_centers)): distance = "" if self.metric_id == 2: distance = self.manhattan_distance(data[x], self.cluster_centers[y]) else: distance = self.euclides_distance(data[x], self.cluster_centers[y]) if distance < min_dist: min_dist = distance cluster[x] = y # aktualizacja srodkow for k in xrange(0, len(self.cluster_centers)): new_center = dim * [0] members = 0 for p in xrange(0, len(data)): if cluster[p] == k: # ten punkt nalezy do klastra for j in xrange(0, dim): new_center[j] += data[p][j] # print "Nowy srodek {}".format(new_center[j]) members += 1 for j in xrange(0, dim): if members != 0: new_center[j] = new_center[j] / float(members) self.cluster_centers[k] = new_center print self.cluster_centers self.cluster = cluster if self.couting == 0: print "Rysuje" self.figure = Figure(figsize=(5, 4), dpi=100) self.plot_area = self.figure.add_subplot(111) self.plot_area.scatter(*zip(*data)) self.plot_area.scatter(*zip(*self.cluster_centers), s=500, c=self.color_random, marker='v') self.plot_canvas = FigureCanvas(self.figure) self.plot_canvas.draw() self.plot_canvas.show_all() self.plot_view.add(self.plot_canvas) self.plot_view.show() self.plot_view.show_all() def reset(self, event): self.plot_view.remove(self.plot_canvas) self.plot_view = Gtk.VBox() self.plot_view.show_all() self.couting = 0 self.is_random_center = 0
class LockinGui(object): _window_title = "Lock-in Spectrum" _heartbeat = 100 # ms delay at which the plot/gui is refreshed, and the gamepad moves the stage def __init__(self): self.savedir = "./Spectra/" self.path = "./" self.settings = Settings() self.x_step = .0 self.y_step = .0 self.step_distance = 1 # in um try: self.stage = PIStage.E545(self.settings.stage_ip,self.settings.stage_port) except: self.stage = None self.stage = PIStage.Dummy() print("Could not initialize PIStage, using Dummy instead") GObject.threads_init() # only GObject.idle_add() is in the background thread self.window = Gtk.Window(title=self._window_title) # self.window.set_resizable(False) self.window.set_border_width(3) self.grid = Gtk.Grid() self.grid.set_row_spacing(5) self.grid.set_column_spacing(5) self.window.add(self.grid) # Buttons for spectrum stack self.button_live = Gtk.Button(label="Liveview") self.button_live.set_tooltip_text("Start/Stop Liveview of Spectrum") self.button_stop = Gtk.Button(label="Stop") self.button_stop.set_tooltip_text("Stop any ongoing Action") self.button_stop.set_sensitive(False) self.button_aquire = Gtk.Button(label="Aquire Spectrum") self.button_aquire.set_tooltip_text("Start/Stop aquiring Lock-In Spectrum") self.button_direction = Gtk.Button(label="Set Direction") self.button_direction.set_tooltip_text("Set Direction of Stage Movement") self.button_settings = Gtk.Button(label="Settings") self.button_settings.set_tooltip_text("Set Integration Time and Number of Samples") self.button_search = Gtk.Button(label="Search for Max") self.button_search.set_tooltip_text("Search for position with maximum Intensity") self.button_save = Gtk.Button(label="Save Data") self.button_save.set_tooltip_text("Save all spectral Data in .csv") self.button_dark = Gtk.Button(label="Take Dark Spectrum") self.button_dark.set_tooltip_text("Take dark spectrum which will substracted from spectrum") self.button_lamp = Gtk.Button(label="Take Lamp Spectrum") self.button_lamp.set_tooltip_text("Take lamp spectrum to normalize spectrum") self.button_normal = Gtk.Button(label="Take Normal Spectrum") self.button_normal.set_tooltip_text("Start/Stop taking a normal spectrum") self.button_bg = Gtk.Button(label="Take Background Spectrum") self.button_bg.set_tooltip_text("Start/Stop taking a Background spectrum") self.button_series = Gtk.Button(label="Take Time Series") self.button_series.set_tooltip_text("Start/Stop taking a Time Series of Spectra") self.button_reset = Gtk.Button(label="Reset") self.button_reset.set_tooltip_text("Reset all spectral data (if not saved data is lost!)") self.button_loaddark = Gtk.Button(label="Load Dark Spectrum") self.button_loaddark.set_tooltip_text("Load Dark Spectrum from file") self.button_loadlamp = Gtk.Button(label="Load Lamp Spectrum") self.button_loadlamp.set_tooltip_text("Load Lamp Spectrum from file") # Stage Control Buttons self.button_xup = Gtk.Button(label="x+") self.button_xdown = Gtk.Button(label="x-") self.button_yup = Gtk.Button(label="y+") self.button_ydown = Gtk.Button(label="y-") self.button_zup = Gtk.Button(label="z+") self.button_zdown = Gtk.Button(label="z-") self.button_stepup = Gtk.Button(label="+") self.button_stepdown = Gtk.Button(label="-") self.label_stepsize = Gtk.Label(label=str(self.settings.stepsize)) self.button_moverel = Gtk.Button(label="Move Stage rel.") self.button_moveabs = Gtk.Button(label="Move Stage abs.") # Stage position labels self.label_x = Gtk.Label() self.label_y = Gtk.Label() self.label_z = Gtk.Label() self.show_pos() # Connect Buttons self.window.connect("delete-event", self.quit) self.button_aquire.connect("clicked", self.on_lockin_clicked) self.button_direction.connect("clicked", self.on_direction_clicked) self.button_live.connect("clicked", self.on_live_clicked) self.button_stop.connect("clicked", self.on_stop_clicked) self.button_settings.connect("clicked", self.on_settings_clicked) self.button_search.connect("clicked", self.on_search_clicked) self.button_save.connect("clicked", self.on_save_clicked) self.button_dark.connect("clicked", self.on_dark_clicked) self.button_lamp.connect("clicked", self.on_lamp_clicked) self.button_normal.connect("clicked", self.on_normal_clicked) self.button_bg.connect("clicked", self.on_bg_clicked) self.button_series.connect("clicked", self.on_series_clicked) self.button_reset.connect("clicked", self.on_reset_clicked) self.button_loaddark.connect("clicked", self.on_loaddark_clicked) self.button_loadlamp.connect("clicked", self.on_loadlamp_clicked) # Connect Stage Control Buttons self.button_xup.connect("clicked", self.on_xup_clicked) self.button_xdown.connect("clicked", self.on_xdown_clicked) self.button_yup.connect("clicked", self.on_yup_clicked) self.button_ydown.connect("clicked", self.on_ydown_clicked) self.button_zup.connect("clicked", self.on_zup_clicked) self.button_zdown.connect("clicked", self.on_zdown_clicked) self.button_stepup.connect("clicked", self.on_stepup_clicked) self.button_stepdown.connect("clicked", self.on_stepdown_clicked) self.button_moverel.connect("clicked", self.on_moverel_clicked) self.button_moveabs.connect("clicked", self.on_moveabs_clicked) # Stage Control Button Table self.table_stagecontrol = Gtk.Table(3, 4, True) self.table_stagecontrol.attach(self.button_xup, 0, 1, 1, 2) self.table_stagecontrol.attach(self.button_xdown, 2, 3, 1, 2) self.table_stagecontrol.attach(self.button_yup, 1, 2, 0, 1) self.table_stagecontrol.attach(self.button_ydown, 1, 2, 2, 3) self.table_stagecontrol.attach(self.button_zup, 3, 4, 0, 1) self.table_stagecontrol.attach(self.button_zdown, 3, 4, 2, 3) # Stage Stepsize Table self.table_stepsize = Gtk.Table(1, 3, True) self.table_stepsize.attach(self.button_stepup, 0, 1, 0, 1) self.table_stepsize.attach(self.label_stepsize, 1, 2, 0, 1) self.table_stepsize.attach(self.button_stepdown, 2, 3, 0, 1) self.status = Gtk.Label(label="Initialized") self.progress = Gtk.ProgressBar() self._progress_fraction = 0 self.progress.set_fraction(self._progress_fraction) # Box for control of taking single spectra self.SpectrumBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=3) self.SpectrumBox.add(Gtk.Separator()) self.SpectrumBox.add(self.button_live) self.SpectrumBox.add(Gtk.Separator()) self.SpectrumBox.add(Gtk.Label("Lock-In Spectrum")) self.SpectrumBox.add(self.button_aquire) self.SpectrumBox.add(self.button_direction) self.SpectrumBox.add(Gtk.Separator()) self.SpectrumBox.add(Gtk.Label(label="Additional Spectra")) self.SpectrumBox.add(self.button_dark) self.SpectrumBox.add(self.button_lamp) self.SpectrumBox.add(self.button_normal) self.SpectrumBox.add(self.button_bg) self.SpectrumBox.add(self.button_series) self.SpectrumBox.add(Gtk.Separator()) self.SpectrumBox.add(Gtk.Label(label="Miscellaneous")) self.SpectrumBox.add(self.button_save) self.SpectrumBox.add(self.button_settings) self.SpectrumBox.add(self.button_reset) self.SpectrumBox.add(self.button_loaddark) self.SpectrumBox.add(self.button_loadlamp) self.SpectrumBox.add(Gtk.Separator()) # Switch corrected Spectrum yes/no self.button_corronoff = Gtk.Switch() self.label_corronoff = Gtk.Label('Correct Spectrum') self.corronoff_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=3) self.corronoff_box.set_homogeneous(True) self.corronoff_box.add(self.label_corronoff) self.corronoff_box.add(self.button_corronoff) # box for Stage control self.stage_hbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=3) # self.stage_hbox.add(Gtk.Separator()) self.stage_hbox.add(self.corronoff_box) self.stage_hbox.add(self.button_search) self.stage_hbox.add(Gtk.Label(label="Stage Control")) self.stage_hbox.add(self.table_stagecontrol) self.stage_hbox.add(Gtk.Label(label="Set Stepsize [um]")) self.stage_hbox.add(self.table_stepsize) self.stage_hbox.add(self.button_moverel) self.stage_hbox.add(self.button_moveabs) self.labels_hbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=3) self.labels_hbox.add(self.label_x) self.labels_hbox.add(self.label_y) self.labels_hbox.add(self.label_z) # Buttons for scanning stack self.button_add_position = Gtk.Button('Add Position to List') self.button_spangrid = Gtk.Button('Span Grid') self.button_searchonoff = Gtk.Switch() self.label_searchonoff = Gtk.Label('Search Max.') self.searchonoff_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=3) self.searchonoff_box.set_homogeneous(True) self.searchonoff_box.add(self.label_searchonoff) self.searchonoff_box.add(self.button_searchonoff) self.button_lockinonoff = Gtk.Switch() self.label_lockinonoff = Gtk.Label('Use Lock-In') self.lockinonoff_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=3) self.lockinonoff_box.set_homogeneous(True) self.lockinonoff_box.add(self.label_lockinonoff) self.lockinonoff_box.add(self.button_lockinonoff) self.button_scan_start = Gtk.Button('Start Scan') self.scan_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=3) self.button_scan_add = Gtk.ToolButton(Gtk.STOCK_ADD) self.button_scan_remove = Gtk.ToolButton(Gtk.STOCK_REMOVE) self.button_scan_clear = Gtk.ToolButton(Gtk.STOCK_DELETE) self.scan_hbox.set_homogeneous(True) self.scan_hbox.add(self.button_scan_add) self.scan_hbox.add(self.button_scan_remove) self.scan_hbox.add(self.button_scan_clear) # Treeview for showing/settings scanning grid self.scan_store = Gtk.ListStore(float, float) self.scan_view = Gtk.TreeView(model=self.scan_store) self.scan_xrenderer = Gtk.CellRendererText() self.scan_xrenderer.set_property("editable", True) self.scan_xcolumn = Gtk.TreeViewColumn("x", self.scan_xrenderer, text=0) self.scan_xcolumn.set_min_width(100) self.scan_xcolumn.set_alignment(0.5) self.scan_view.append_column(self.scan_xcolumn) self.scan_yrenderer = Gtk.CellRendererText() self.scan_yrenderer.set_property("editable", True) self.scan_ycolumn = Gtk.TreeViewColumn("y", self.scan_yrenderer, text=1) self.scan_ycolumn.set_min_width(100) self.scan_ycolumn.set_alignment(0.5) self.scan_view.append_column(self.scan_ycolumn) self.scan_scroller = Gtk.ScrolledWindow() self.scan_scroller.set_vexpand(True) self.scan_scroller.add(self.scan_view) self.scan_store.append([10.0, 10.0]) self.scan_store.append([10.1, 10.0]) self.scan_store.append([10.0, 10.1]) #Connections for scanning stack self.button_add_position.connect("clicked", self.on_add_position_clicked) self.button_spangrid.connect("clicked", self.on_spangrid_clicked) self.button_scan_start.connect("clicked", self.on_scan_start_clicked) self.button_scan_add.connect("clicked", self.on_scan_add) self.button_scan_remove.connect("clicked", self.on_scan_remove) self.button_scan_clear.connect("clicked", self.on_scan_clear) self.scan_xrenderer.connect("edited", self.on_scan_xedited) self.scan_yrenderer.connect("edited", self.on_scan_yedited) #Box for control of scanning self.ScanningBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=3) self.ScanningBox.add(Gtk.Separator()) self.ScanningBox.add(self.button_add_position) self.ScanningBox.add(self.button_spangrid) self.ScanningBox.add(self.searchonoff_box) self.ScanningBox.add(self.lockinonoff_box) self.ScanningBox.add(Gtk.Separator()) self.ScanningBox.add(Gtk.Label("Scanning Positions")) self.ScanningBox.add(self.scan_hbox) self.ScanningBox.add(self.scan_scroller) self.ScanningBox.add(Gtk.Separator()) self.ScanningBox.add(self.button_scan_start) # MPL stuff self.figure = Figure() self.ax = self.figure.add_subplot(1, 1, 1) self.ax.grid(True) self.ax.set_xlabel("Wavelength [nm]") self.ax.set_ylabel("Intensity") self.ax.set_xlim([400, 900]) self.canvas = FigureCanvas(self.figure) self.canvas.set_hexpand(True) self.canvas.set_vexpand(True) self.canvas.set_size_request(700, 700) self.stack = Gtk.Stack() self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT) self.stack.set_transition_duration(500) self.stack.add_titled(self.SpectrumBox, "spec", "Spectra") self.stack.add_titled(self.ScanningBox, "scan", "Scanning") self.stack_switcher = Gtk.StackSwitcher() self.stack_switcher.set_stack(self.stack) self.SideBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=3) self.SideBox.add(self.stack_switcher) self.ScanningBox.add(Gtk.Separator()) self.SideBox.add(self.button_stop) self.SideBox.add(self.stack) self.SideBox.add(self.stage_hbox) self.SideBox.add(self.labels_hbox) self.grid.add(self.canvas) self.grid.attach_next_to(self.SideBox, self.canvas, Gtk.PositionType.RIGHT, 1, 1) self.grid.attach_next_to(self.progress, self.canvas, Gtk.PositionType.BOTTOM, 1, 1) self.grid.attach_next_to(self.status, self.SideBox, Gtk.PositionType.BOTTOM, 1, 1) self.window.show_all() self.spectrum = Spectrum(self.stage, self.settings, self.status, self.progress, self.enable_buttons, self.disable_buttons) # logger class which coordinates the spectrometer and the stage spec = self.spectrum.get_spec() # get an initial spectrum for display self._wl = self.spectrum.get_wl() # get the wavelengths print(self._wl) self.lines = [] self.lines.extend(self.ax.plot(self._wl, spec, "-")) self.lines.extend(self.ax.plot(self._wl, self.spectrum.smooth(spec), "-", c="black")) # plot initial spectrum #Dialogs self.settings_dialog = dialogs.SettingsDialog(self.window, self.settings) self.direction_dialog = dialogs.DirectionDialog(self.window, self.settings) self.moveabs_dialog = dialogs.MoveAbsDialog(self.window, self.stage) self.moverel_dialog = dialogs.MoveRelDialog(self.window, self.stage) self.spangrid_dialog = dialogs.SpanGridDialog(self.window) self.prefix_dialog = dialogs.PrefixDialog(self.window) self.pad = None try: #pass self.pad = Gamepad(True) except: print("Could not initialize Gamepad") def quit(self, *args): """ Function for quitting the program, will also stop the worker thread :param args: """ self.spectrum = None self.pad = None Gtk.main_quit(*args) def disable_buttons(self): # self.stack_switcher.set_sensitive(False) self.scan_hbox.set_sensitive(False) self.SpectrumBox.set_sensitive(False) self.stage_hbox.set_sensitive(False) self.ScanningBox.set_sensitive(False) self.button_stop.set_sensitive(True) def enable_buttons(self): # self.stack_switcher.set_sensitive(True) self.scan_hbox.set_sensitive(True) self.SpectrumBox.set_sensitive(True) self.stage_hbox.set_sensitive(True) self.ScanningBox.set_sensitive(True) self.button_stop.set_sensitive(False) def _on_pad_change(self, io, condition): a, b, x, y, ax, ay = self.pad.receiver.recv() if a: self.on_stepdown_clicked(None) if b: self.on_add_position_clicked(None) if x: self.on_search_clicked(None) if y: self.on_stepup_clicked(None) self.x_step = float((ax - 128)) if abs(self.x_step) > 8: self.x_step = self.x_step / 128 * self.settings.stepsize else: self.x_step = 0.0 self.y_step = float((ay - 128)) if abs(self.y_step) > 8: self.y_step = self.y_step / 128 * self.settings.stepsize else: self.y_step = 0.0 # print('x_step: {0:3.2f} um y_step: {1:3.2f} um'.format( self.x_step, self.y_step)) return True def _pad_make_step(self): if self.pad is not None: if abs(self.x_step) > 0.0001: if abs(self.y_step) > 0.0001: self.stage.moverel(dx=self.x_step, dy=self.y_step) else: self.stage.moverel(dx=self.x_step) elif abs(self.y_step) > 0.001: self.stage.moverel(dy=self.y_step) return True # ##---------------- button connect functions ---------- def on_scan_start_clicked(self, widget): prefix = self.prefix_dialog.rundialog() if prefix is not None: try: # os.path.exists(prefix) os.mkdir(self.savedir+prefix) except: print("Error creating directory ./" + prefix) path = self.savedir + prefix + '/' self.status.set_label('Scanning') self.spectrum.make_scan(self.scan_store, path, self.button_searchonoff.get_active(), self.button_lockinonoff.get_active()) self.disable_buttons() def on_add_position_clicked(self, widget): self.stage.query_pos() pos = self.stage.last_pos() self.scan_store.append([pos[0], pos[1]]) def on_spangrid_clicked(self, widget): iterator = self.scan_store.get_iter_first() grid = self.spangrid_dialog.rundialog() if (len(self.scan_store) >= 3) & ((grid[0] is not 0) | (grid[1] is not 0)): a = self.scan_store[iterator][:] iterator = self.scan_store.iter_next(iterator) b = self.scan_store[iterator][:] iterator = self.scan_store.iter_next(iterator) c = self.scan_store[iterator][:] if abs(b[0]) > abs(c[0]): grid_vec_1 = [b[0] - a[0], b[1] - a[1]] grid_vec_2 = [c[0] - a[0], c[1] - a[1]] else: grid_vec_2 = [b[0] - a[0], b[1] - a[1]] grid_vec_1 = [c[0] - a[0], c[1] - a[1]] self.scan_store.clear() for x in range(int(grid[0])): for y in range(int(grid[1])): vec_x = a[0] + grid_vec_1[0] * x + grid_vec_2[0] * y vec_y = a[1] + grid_vec_1[1] * x + grid_vec_2[1] * y self.scan_store.append([vec_x, vec_y]) def on_stop_clicked(self, widget): self.spectrum.stop_process() self.enable_buttons() self.status.set_label('Stopped') def on_reset_clicked(self, widget): self.spectrum.reset() self.spectrum.dark = None self.spectrum.lamp = None self.spectrum.lockin = None self.spectrum.mean = None def on_lockin_clicked(self, widget): self.status.set_label('Acquiring ...') self.spectrum.take_lockin() self.disable_buttons() def on_direction_clicked(self, widget): self.direction_dialog.rundialog() def on_live_clicked(self, widget): self.status.set_label('Liveview') self.spectrum.take_live() self.disable_buttons() def on_search_clicked(self, widget): self.status.set_text("Searching Max.") self.spectrum.search_max() self.disable_buttons() def on_save_clicked(self, widget): self.status.set_label("Saving Data ...") self.save_data() def on_settings_clicked(self, widget): self.settings_dialog.rundialog() self.ax.set_xlim([self.settings.min_wl, self.settings.max_wl]) #self.spectrum.reset() def on_dark_clicked(self, widget): self.status.set_label('Taking Dark Spectrum') self.spectrum.take_dark() self.disable_buttons() def on_lamp_clicked(self, widget): self.status.set_label('Taking Lamp Spectrum') self.spectrum.take_lamp() self.disable_buttons() def on_normal_clicked(self, widget): self.status.set_label('Taking Normal Spectrum') self.spectrum.take_normal() self.disable_buttons() def on_bg_clicked(self, widget): self.status.set_label('Taking Background Spectrum') self.spectrum.take_bg() self.disable_buttons() def on_series_clicked(self, widget): self.status.set_label('Taking Time Series') prefix = self.prefix_dialog.rundialog() if prefix is not None: try: # os.path.exists(prefix) os.mkdir(self.savedir+prefix) except: print("Error creating directory ./" + prefix) path = self.savedir + prefix + '/' else: self.status.set_text("Error") self.spectrum.take_series(path) self.disable_buttons() def on_loaddark_clicked(self, widget): buf = self._load_spectrum_from_file() if not buf is None: self.spectrum.dark = buf def on_loadlamp_clicked(self, widget): buf = self._load_spectrum_from_file() if not buf is None: self.spectrum.lamp = buf # ##---------------- END button connect functions ---------- def _load_spectrum_from_file(self): dialog = Gtk.FileChooserDialog("Please choose a file", self.window, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) data = None filter_text = Gtk.FileFilter() filter_text.set_name("CSV Spectrum files") filter_text.add_pattern("*.csv") dialog.add_filter(filter_text) dialog.set_current_folder(os.path.dirname(os.path.abspath(__file__))) response = dialog.run() if response == Gtk.ResponseType.OK: data = pandas.DataFrame(pandas.read_csv(dialog.get_filename())) data = data['intensity'] elif response == Gtk.ResponseType.CANCEL: data = None dialog.destroy() return data # ## ----------- scan Listview connect functions def on_scan_xedited(self, widget, path, number): self.scan_store[path][0] = float(number.replace(',', '.')) # self.plotpoints() def on_scan_yedited(self, widget, path, number): self.scan_store[path][1] = float(number.replace(',', '.')) # self.plotpoints() def on_scan_add(self, widget): self.scan_store.append() def on_scan_remove(self, widget): select = self.scan_view.get_selection() model, treeiter = select.get_selected() if treeiter is not None: self.scan_store.remove(treeiter) def on_scan_clear(self, widget): self.scan_store.clear() # ## ----------- END scan Listview connect functions # ##---------------- Stage Control Button Connect functions ---------- def show_pos(self): pos = self.stage.last_pos() # print(pos) self.label_x.set_text("x: {0:+8.4f}".format(pos[0])) self.label_y.set_text("y: {0:+8.4f}".format(pos[1])) self.label_z.set_text("z: {0:+8.4f}".format(pos[2])) def on_xup_clicked(self, widget): self.stage.moverel(dx=self.settings.stepsize) self.show_pos() def on_xdown_clicked(self, widget): self.stage.moverel(dx=-self.settings.stepsize) self.show_pos() def on_yup_clicked(self, widget): self.stage.moverel(dy=self.settings.stepsize) self.show_pos() def on_ydown_clicked(self, widget): self.stage.moverel(dy=-self.settings.stepsize) self.show_pos() def on_zup_clicked(self, widget): self.stage.moverel(dz=self.settings.stepsize) self.show_pos() def on_zdown_clicked(self, widget): self.stage.moverel(dz=-self.settings.stepsize) self.show_pos() def on_stepup_clicked(self, widget): self.settings.stepsize *= 10 if self.settings.stepsize > 10: self.settings.stepsize = 10.0 self.label_stepsize.set_text(str(self.settings.stepsize)) self.settings.save() def on_stepdown_clicked(self, widget): self.settings.stepsize /= 10 if self.settings.stepsize < 0.001: self.settings.stepsize = 0.001 self.label_stepsize.set_text(str(self.settings.stepsize)) self.settings.save() def on_moverel_clicked(self, widget): self.moverel_dialog.rundialog() self.show_pos() def on_moveabs_clicked(self, widget): self.moveabs_dialog.rundialog() self.show_pos() # ##---------------- END Stage Control Button Connect functions ------ def run(self): """ run main gtk thread """ try: GLib.timeout_add(self._heartbeat, self._update_plot) GLib.timeout_add(self._heartbeat, self._pad_make_step) GLib.io_add_watch(self.spectrum.conn_for_main, GLib.IO_IN | GLib.IO_PRI, self.spectrum.callback, args=(self.spectrum,)) if self.pad is not None: GLib.io_add_watch(self.pad.receiver, GLib.IO_IN | GLib.IO_PRI, self._on_pad_change, args=(self,)) Gtk.main() except KeyboardInterrupt: pass def _update_plot(self): spec = self.spectrum.get_spec(self.button_corronoff.get_active()) self.lines[0].set_ydata(spec) self.lines[1].set_ydata(self.spectrum.smooth(spec)) #self.ax.set_ylim(min(spec[262:921]), max(spec[262:921])) self.ax.autoscale_view(None, False, True) self.canvas.draw() self.show_pos() return True def save_data(self): prefix = self.prefix_dialog.rundialog() if prefix is not None: try: # os.path.exists(prefix) os.mkdir(self.savedir+prefix) except: print("Error creating directory ./" + prefix) path = self.savedir + prefix + '/' self.spectrum.save_data(path) self.status.set_text("Data saved") else: self.status.set_text("Could not save data")
class Editor(gtk.Dialog): X = 0 Y = 1 def get_globals(self): if self.globals_src: return self.globals_src() return self.globals def __init__(self, channels, title='Edit Scaling', parent=None, target=None, model=False, add_undo=None, globals_src=None, globals=globals()): self.add_undo = add_undo self.channels = channels self.globals_src = None if globals_src: assert callable(globals_src), 'expected callable globals_src' self.globals_src = globals_src self.globals = globals self.handlers = dict() self.chan = None flags = gtk.DialogFlags.DESTROY_WITH_PARENT if model: flags |= gtk.DialogFlags.MODAL super(Editor, self).__init__(title, parent, flags) self.set_default_size(550, 600) self.set_border_width(10) self.pause_update = False V = self.view = gtk.TreeView() V.set_property('rules-hint', True) V.get_selection().set_mode(gtk.SelectionMode.MULTIPLE) self.sheet_cb = spreadsheet.Callbacks(V, ('', '')) self.sheet_cb.connect('clean', lambda: self.set_pause(True), lambda: self.set_pause(False)) self.renderers = R = { 'x': GCRT(), 'y': GCRT(), } R['x'].set_property('editable', True) R['y'].set_property('editable', True) C = { 'x': GTVC('Voltage (V)', R['x'], text=Editor.X), 'y': GTVC('Output (V)', R['y'], text=Editor.Y), } V.append_column(C['x']) V.append_column(C['y']) self.C = C V.set_size_request(200, 100) # create the scrolled window for the spreadsheet sw = gtk.ScrolledWindow() sw.set_policy(gtk.PolicyType.AUTOMATIC, gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(gtk.ShadowType.IN) sw.add(V) # Create the plotting canvas f = Figure(figsize=(5, 4), dpi=100) self.axes = f.add_subplot(111) self.canvas = FigureCanvas(f) # a gtk.DrawingArea self.canvas.set_size_request(300, 100) toolbar = NavigationToolbar(self.canvas, self) self.plot_offset_label = gtk.Label('Plot Offset [V]:') self.channel_select = gtk.ComboBox.new_with_model(channels) cbr = gtk.CellRendererText() self.channel_select.clear() self.channel_select.pack_start(cbr, True) self.channel_select.add_attribute(cbr, 'text', channels.LABEL) self.channel_select.connect( 'changed', lambda c: self._set_channel(self.channels[c.get_active()])) # This ensures you can't select digital channels def is_sensitive(celllayout, cell, model, i, *user_args): if model[i][model.DEVICE].lower().startswith('digital/'): cell.set_property('sensitive', False) cell.set_property('visible', False) else: cell.set_property('sensitive', True) cell.set_property('visible', True) self.channel_select.set_cell_data_func(cbr, is_sensitive) self.units = gtk.Entry() self.units.set_width_chars(8) def update_units_label(entry): T = self.units.get_text() # just a simple test to see if the units evaluate eval(T, self.get_globals()) C['y'].set_title('Output ({})'.format(T)) self.axes.set_ylabel('Output ({})'.format(T)) self.canvas.draw() if self.chan and self.chan[self.channels.UNITS] != T: self.chan[self.channels.UNITS] = T self.update_plot() self.units.connect('activate', update_units_label) self.units.set_text('V') self.offset = gtk.Entry() self.offset.set_width_chars(10) def update_offset(entry): T = self.offset.get_text() # just a simple test to see if the units evaluate if not T: T = None elif T.partition('#')[0].strip(): eval(T, self.get_globals()) if self.chan and self.chan[self.channels.OFFSET] != T: self.chan[self.channels.OFFSET] = T self.update_plot() self.offset.connect('activate', update_offset) self.order = gtk.SpinButton() self.order.set_range(1, 5) self.order.set_increments(1, 2) def update_order(entry): if self.chan: self.chan[self.channels. INTERP_ORDER] = self.order.get_value_as_int() self.update_plot() self.order.connect('value-changed', update_order) self.order.set_value(1) self.smoothing = gtk.SpinButton(digits=3) self.smoothing.set_range(0, 10000000) self.smoothing.set_increments(0.5, 1) def update_smoothing(entry): if self.chan: self.chan[self.channels. INTERP_SMOOTHING] = self.smoothing.get_value() self.update_plot() self.smoothing.connect('value-changed', update_smoothing) self.smoothing.set_value(0) self.enforce_scale_offset = \ NumberEntryEnforcer(self, self.channels.PLOT_SCALE_OFFSET, True) self.scale_offset = gtk.Entry() self.scale_offset.set_text('0.0') self.scale_offset.set_width_chars(15) self.scale_offset.connect('changed', self.enforce_scale_offset) self.scale_offset.connect('activate', self.enforce_scale_offset.activate) self.scale_offset.set_tooltip_text( 'Specify an offset for the waveform plot') self.enforce_scale_factor = \ NumberEntryEnforcer(self, self.channels.PLOT_SCALE_FACTOR, True) self.scale_factor = gtk.Entry() self.scale_factor.set_text('1.0') self.scale_factor.set_width_chars(15) self.scale_factor.connect('changed', self.enforce_scale_factor) self.scale_factor.connect('activate', self.enforce_scale_factor.activate) self.scale_factor.set_tooltip_text( 'Specify a scaling factor for the waveform plot') ubox = gtk.HBox() ubox.pack_start(self.channel_select, True, True, 0) ubox.pack_start(gtk.Label('Output Scale/Units: '), True, True, 0) ubox.pack_start(self.units, True, True, 0) pbox = gtk.HBox() pbox.pack_start(gtk.Label('Interpolation: Order:'), True, True, 0) pbox.pack_start(self.order, True, True, 0) pbox.pack_start(gtk.Label('Smoothing:'), True, True, 0) pbox.pack_start(self.smoothing, True, True, 0) obox = gtk.HBox() obox.pack_start(gtk.Label('Output Offset/Units:'), True, True, 0) obox.pack_start(self.offset, True, True, 0) sbox = gtk.HBox() sbox.pack_start(self.plot_offset_label, True, True, 0) sbox.pack_start(self.scale_offset, True, True, 0) sbox.pack_start(gtk.Label('Plot Scale:'), True, True, 0) sbox.pack_start(self.scale_factor, True, True, 0) bottom = gtk.VBox() bottom.pack_start(ubox, False, False, 0) bottom.pack_start(pbox, False, False, 0) bottom.pack_start(obox, False, False, 0) bottom.pack_start(sbox, False, False, 0) bottom.pack_start(sw, True, True, 0) body = gtk.VPaned() body.pack1(self.canvas, True) body.pack2(bottom, True) self.vbox.pack_start(toolbar, False, False, 0) self.vbox.pack_start(body, True, True, 0) self.show_all() # default to first channel self.set_channel() def set_channel(self, label=None): """Determines the new channel and sets it""" if not (self.channels and len(self.channels)): return if label == None: return if label != self.channels[self.channel_select.get_active()]: for i in range(len(self.channels)): if label == self.channels[i][self.channels.LABEL]: self.channel_select.set_active(i) # we rely on the channel_select callback to finish this return raise KeyError('Could not determine channel') def _set_channel(self, chan): #disconnect handlers from old model if self.chan: for i in self.handlers['store']: self.chan[self.channels.SCALING].disconnect(i) for i in self.handlers['x']: self.renderers['x'].disconnect(i) for i in self.handlers['y']: self.renderers['y'].disconnect(i) if not (self.channels and len(self.channels)): return self.set_pause(True) self.chan = None self.view.set_model(None) # set new model if chan[self.channels.SCALING] is None: chan[self.channels.SCALING] = gtk.ListStore(str, str) if not chan[self.channels.UNITS]: chan[self.channels.UNITS] = 'V' if chan[self.channels.INTERP_ORDER] < 1: chan[self.channels.INTERP_ORDER] = 1 devname = chan[self.channels.DEVICE].lower() if devname.startswith('analog/'): self.C['x'].set_title('Voltage (V)') self.plot_offset_label.set_text('Plot Offset [V]:') elif devname.startswith('dds/'): self.C['x'].set_title('Frequency (Hz)') self.plot_offset_label.set_text('Plot Offset [Hz]:') # INTERP_SMOOTHING defaults to zero already self.units.set_text(chan[self.channels.UNITS]) self.units.activate() self.offset.set_text(chan[self.channels.OFFSET] or '') self.order.set_value(chan[self.channels.INTERP_ORDER]) self.smoothing.set_value(chan[self.channels.INTERP_SMOOTHING]) self.scale_offset.set_text(fstr(chan[self.channels.PLOT_SCALE_OFFSET])) self.scale_factor.set_text( fstr(chan[self.channels.PLOT_SCALE_FACTOR], '1.0')) store = chan[self.channels.SCALING] self.view.set_model(store) #connect handlers to new model self.handlers['store'] = [ store.connect('row-changed', lambda m, p, i: self.update_plot()), store.connect('row-deleted', lambda m, p: self.update_plot()), store.connect('row-inserted', lambda m, p, i: self.update_plot()), ] self.handlers['x'] = self.sheet_cb.connect_column( self.renderers['x'], setitem=(set_item, store, Editor.X, self.add_undo, True)) self.handlers['y'] = self.sheet_cb.connect_column( self.renderers['y'], setitem=(set_item, store, Editor.Y, self.add_undo)) self.chan = chan self.set_pause(False) # clear the plot entirely first to avoid keeping a plot with no data-table self.axes.clear() self.canvas.draw() self.update_plot() def plot(self, *args, **kwargs): """Send the data to matplotlib""" self.axes.clear() self.axes.plot(*args, **kwargs) pylab.setp(self.axes.get_xticklabels(), fontsize=8) pylab.setp(self.axes.get_yticklabels(), fontsize=8) self.axes.grid(True) self.axes.set_xlabel('Voltage (V)') self.axes.set_ylabel('Output ({})'.format(self.units.get_text())) self.canvas.draw() def set_pause(self, arg): """Do not send to plotter just because a signal handler was called""" self.pause_update = bool(arg) def update_plot(self): if self.pause_update: return D = calculate(self.chan[self.channels.SCALING], self.chan[self.channels.UNITS], self.chan[self.channels.OFFSET], self.get_globals()) if len(D): if len(D) > 1: s = UnivariateSpline( D[:, 0], D[:, 1], k=self.order.get_value_as_int(), s=self.smoothing.get_value(), ) xs = np.linspace(D[0, 0], D[-1, 0], 100 * len(D)) self.plot(D[:, 0], D[:, 1], 'o', xs, s(xs)) else: self.plot(D[:, 0], D[:, 1], 'o')
class MyWindow(Gtk.Window): def __init__(self): """View initializer.""" super().__init__() self.set_title("Kości") self.set_default_size(500, 800) self.generalLayout = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.add(self.generalLayout) self.left = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.right = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self._createMenu() self.generalLayout.add(self.left) self.generalLayout.add(self.right) self._createPlot() self._createDisplay() self._createList() self._createLabels() self._createButtons() self._createRadio() self.connect("destroy", Gtk.main_quit) self.show_all() def _createPlot(self): self.fig = plt.Figure(figsize=(5, 4), dpi=100) self.ax = self.fig.add_subplot() self.canvas = FigureCanvas(self.fig) # a Gtk.DrawingArea self.canvas.set_size_request(800, 600) self.left.add(self.canvas) #ax.plot(t, s) def _createDisplay(self): """Create the display.""" self.display = Gtk.Label("") #self.display.setFixedeight(50) #self.display.setAlignment(Qt.AlignLeft) #self.display.setReadOnly(True) self.left.add(self.display) def _createLabels(self): """Create the buttons.""" self.labels = {} self.names = {} labelsLayout = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) labels = { "liczba ścian": (0, 0), "kości": (0, 1), "próg sukcesu": (0, 2), "wymagana liczba sukcesów": (0, 3), "modyfikator": (0, 4), } for lblText, pos in labels.items(): self.labels[lblText] = Gtk.Entry() self.labels[lblText].set_text(lblText) self.names[lblText] = Gtk.Label(lblText + ":") #self.labels[lblText].setValidator(QIntValidator()) #self.labels[lblText].setFixedSize(40, 40) labelsLayout.add(self.names[lblText]) labelsLayout.add(self.labels[lblText]) if lblText == "wymagana liczba sukcesów": self.check = Gtk.CheckButton() labelsLayout.add(self.check) self.right.add(labelsLayout) def _createButtons(self): """Create the buttons.""" self.buttons = {} buttonsLayout = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) buttons = { "oblicz": (0, 0), "rzuć": (0, 1), "dodaj element łańcucha": (0, 2), } for btnText, pos in buttons.items(): self.buttons[btnText] = Gtk.Button(label=btnText) #self.buttons[btnText].setFixedSize(15, 40) buttonsLayout.add(self.buttons[btnText]) self.right.add(buttonsLayout) def _createList(self): self.cb = Gtk.ComboBoxText() self.cb.append_text("Krok 1") self.right.add(self.cb) def _createMenu(self): mb = Gtk.MenuBar() menu1 = Gtk.Menu() file = Gtk.MenuItem("Menu") file.set_submenu(menu1) acgroup = Gtk.AccelGroup() self.add_accel_group(acgroup) self.info = Gtk.MenuItem("Informacje") self.clear = Gtk.MenuItem("Wyczyść") menu1.append(self.info) menu1.append(self.clear) self.info.connect("activate", self.information) mb.append(file) vbox = Gtk.VBox(False, 2) vbox.pack_start(mb, False, False, 0) self.generalLayout.add(vbox) def _createRadio(self): self.radios = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.rb = [] self.rb.append(Gtk.RadioButton(label="Brak przerzutu")) self.rb.append(Gtk.RadioButton(label="Przerzut jedynek")) self.rb.append(Gtk.RadioButton(label="Przerzut nieudanych")) self.rb.append(Gtk.RadioButton(label="Przerzut x kości")) self.x_name = Gtk.Label("x: ") self.x_input = Gtk.Entry() self.x_input.set_text(str(0)) self.radios.pack_start(self.rb[0], True, True, 0) self.radios.pack_start(self.rb[1], True, True, 0) self.radios.pack_start(self.rb[2], True, True, 0) self.radios.pack_start(self.rb[3], True, True, 0) self.radios.add(self.x_name) self.radios.add(self.x_input) self.rb[1].join_group(self.rb[0]) self.rb[2].join_group(self.rb[0]) self.rb[3].join_group(self.rb[0]) self.right.add(self.radios) def setDisplayText(self, text): """Set display's text.""" self.display.set_text(text) def displayText(self): """Get display's text.""" return self.display.text() def clearDisplay(self): """Clear the display.""" self.setDisplayText("") def information(self, source): msg = Gtk.MessageDialog( parent=self, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.INFO, buttons=Gtk.ButtonsType.OK, message_format= "Aplikacja ma być ułatwieniem dla osób grających w gry planszowe, rpg i bitewne. Jej zadaniem jest obliczanie prawdopodobieństw uzyskania wskazanych wyników rzutów kośćmi oraz dokonywanie symulacji takich rzutów" ) msg.run() msg.destroy() def plot(self, source, roller): self.ax.cla() data = roller.calculate() x = list(range(len(data))) self.ax.bar(x, data) self.canvas.draw() def showRollResult(self, button, roller): result = roller.roll() success = "" if result[2]: success = " Rzut udany!" else: success = " Rzut nieudany" self.setDisplayText("Wyniki rzutu:" + str(result[0]) + " Sukcesy:" + str(result[1]) + success) def addStep(self, source, chain): roller = dice.rolling_step() chain.add_step(roller) self.cb.append_text("Krok " + str(chain.num_of_steps())) def changeStep(self, source, chain): index = self.cb.get_active() self.labels["liczba ścian"].set_text(str(chain.steps[index].sides)) self.labels["kości"].set_text(str(chain.steps[index].amount_of_dice)) self.labels["próg sukcesu"].set_text(str(chain.steps[index].success)) self.labels["wymagana liczba sukcesów"].set_text( str(chain.steps[index].needed_successes)) self.labels["modyfikator"].set_text(str(chain.steps[index].modifier)) self.x_input.set_text(str((chain.steps[index].dice_for_reroll))) self.check.set_active(chain.steps[index].success_required) self.rb[int(chain.steps[index].rerolls)].set_active(True) def updateDice(self, source, event, chain): numOnly(source) chain.steps[self.cb.get_active()].amount_of_dice = int( self.labels["kości"].get_text()) def updateSides(self, source, event, chain): numOnly(source) chain.steps[self.cb.get_active()].sides = int( self.labels["liczba ścian"].get_text()) def updateSuccess(self, source, event, chain): numOnly(source) chain.steps[self.cb.get_active()].success = int( self.labels["próg sukcesu"].get_text()) def updateNeededSuccesses(self, source, event, chain): numOnly(source) chain.steps[self.cb.get_active()].needed_successes = int( self.labels["wymagana liczba sukcesów"].get_text()) def updateModifier(self, source, event, chain): numOnly(source) chain.steps[self.cb.get_active()].modifier = int( self.labels["modyfikator"].get_text()) def updateDiceToReroll(self, source, event, chain): numOnly(source) chain.steps[self.cb.get_active()].dice_for_reroll = int( self.x_input.get_text()) def updateRerolls(self, source, chain): if self.rb[0].get_active(): chain.steps[self.cb.get_active()].rerolls = dice.Rerolls.none if self.rb[1].get_active(): chain.steps[self.cb.get_active()].rerolls = dice.Rerolls.ones if self.rb[2].get_active(): chain.steps[self.cb.get_active()].rerolls = dice.Rerolls.all if self.rb[3].get_active(): chain.steps[self.cb.get_active()].rerolls = dice.Rerolls.dice def updateSuccessRequired(self, source, chain): chain.steps[self.cb.get_active()].success_required = not chain.steps[ self.cb.get_active()].success_required def clearChain(self, source, chain): chain.steps = [] chain.steps.append(dice.rolling_step()) self.cb.remove_all() self.cb.append_text("Krok 1") self.cb.set_active(0)
class ChessAnalogWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="CHESS Analog") self.set_default_size(800, 600) self.dev = None # number of plot points to plot at any one time. self.fifo_size = 1000 # Buffer for plot data self.analog_data = [] #self.analog_data = [32*collections.deque(self.fifo_size*[0], self.fifo_size)] # Init plot data container for i in range(NUM_CHANNELS): self.analog_data.append(collections.deque(self.fifo_size*[0], self.fifo_size)) self.x = collections.deque(self.fifo_size*[0], self.fifo_size) # Buffer for reading from file device. self.data_buf = "" self.connect("destroy", self.on_destroy) # Initialize the DAQ card if (self.pci_6033e_init(DEVICE) < 0): warn_dialog("Could not initialize comedi device -- closing") # Quit if we can't get the daq... Gtk.main_quit() print("Comedi device successfully initialized \n\n") self.master_vbox = Gtk.Box(spacing = 2, orientation = 'vertical') self.master_hbox = Gtk.Box(spacing = 2) #self.master_vbox.pack_start(self.master_hbox, True, True, 0) self.add(self.master_vbox) self.action_acq = Gtk.ToggleAction("Acquire", "Acquire", "Get the datas", None) self.action_acq.connect("toggled", self.acquire_cb) toolbar_action_group = Gtk.ActionGroup("toolbar_actions") toolbar_action_group.add_action(self.action_acq) # UI Stuff uimanager = Gtk.UIManager() # Throws exception if something went wrong uimanager.add_ui_from_string(UI_INFO) uimanager.insert_action_group(toolbar_action_group) toolbar = uimanager.get_widget("/ToolBar") self.master_vbox.pack_start(toolbar, False, False, 0) self.liststore = Gtk.ListStore(str, float) for i in range(32): self.liststore.append([str(i), 0]) self.treeview = Gtk.TreeView(model=self.liststore) chan_text = Gtk.CellRendererText() column_text = Gtk.TreeViewColumn("Channel", chan_text, text=0) self.treeview.append_column(column_text) meas_text = Gtk.CellRendererText() mcolumn_text = Gtk.TreeViewColumn("Measurement", meas_text, text=1) self.treeview.append_column(mcolumn_text) self.master_vbox.pack_start(self.master_hbox, True, True, 0) #self.add(treeview) self.master_hbox.pack_start(self.treeview, False, False, 0) #self.liststore[31][1] = 18000 #GObject.timeout_add(200, self.my_timer) self.timer_id = None self.plot_id = None self.f = Figure(figsize=(8,6), dpi=100) self.a = self.f.add_subplot(111) #self.line, = self.a.plot([], [], marker = 'x') #self.line, = self.a.plot([], []) #self.plt = self.a.plot([0, 1], [0, 3], marker = 'x') self.a.xaxis.set_animated(True) self.a.yaxis.set_animated(True) #self.a.set_xlim([0,5]) self.a.set_xlim([self.fifo_size/SCAN_FREQ, 0]) self.a.set_ylim([0,70000]) self.a.grid(True) #self.a.set_xscale('log') #self.a.set_xlim((10.0, 30000.0)) #self.a.set_ylim((-90.0, 3.0)) self.a.set_xlabel("Time") self.a.set_ylabel("Voltage") self.lastx = 0 self.my_line, = self.a.plot([], [], animated = True) self.my_line2, = self.a.plot([], [], animated = True) self.canvas = FigureCanvas(self.f) # Clean background self.clean_bg = self.canvas.copy_from_bbox(self.f.bbox) self.background = self.canvas.copy_from_bbox(self.get_bg_bbox(self.a)) self.old_size = self.a.bbox.width, self.a.bbox.height self.canvas.draw() self.do_redraw = False #self.plot_timer = self.canvas.new_timer(interval = 42) # self.anim = ma.FuncAnimation(self.f, # self.update_plots, # event_source = self.plot_timer, # init_func = self.init_blit_plot, # repeat = False, # blit = True) #print(dir(self.anim)) #self.anim._stop() #self.plot_timer.stop() self.master_hbox.pack_start(self.canvas, True, True, 0) #self.plot_timer.stop() self.connect("check-resize", self.win_resize) def acquire_cb(self, state): #print("acq callback") #print(state) if (self.action_acq.get_active()): # This is commented because it seems that comedi_cancel() # clears stale data in the fd and card? #data = os.read(self.fd, BUF_SIZE) #print("LEN DATA: %d" % len(data)) # Start comedi command ret = c.comedi_command(self.dev, self.cmd) if (ret != 0): self.warn_dialog("PCI-6033E cannot collect data! Error: %d" % ret) print(c.comedi_strerror(c.comedi_errno())) return(False) #self.timer_id = GObject.timeout_add(100, self.my_timer) # Make these timeouts configurable... self.plotter_id = GObject.timeout_add(250, self.update_plots) self.plot_id = GObject.timeout_add(500, self.num_data_timer) self.timer_id = GObject.timeout_add(20, self.pci_6033e_get_data) #self.plot_timer.start() self.action_acq.set_label("Halt") else: self.action_acq.set_label("Acquire") if (self.timer_id): if (c.comedi_cancel(self.dev, SUBDEVICE) < 0): print("failed to cancel comedi command...") GObject.source_remove(self.timer_id) if (self.plot_id): GObject.source_remove(self.plot_id) if (self.plotter_id): GObject.source_remove(self.plotter_id) #self.plot_timer.stop() # Empty stale data self.data_buf = "" # print(self.x) # print(self.analog_data[0]) # Get the bounding box def get_bg_bbox(self, axe): # just pad x0 by three.... return axe.bbox.padded(-3) def num_data_timer(self): # Print numerical data to treeview for i in range(32): # datal.append(c.comedi_to_phys(j, crange, maxdata)) self.liststore[i][1] = c.comedi_to_phys(self.analog_data[i][-1], self.comedi_range, (self.comedi_maxdata + 1)) return(True) def pci_6033e_get_data(self): # Run the command # ret = c.comedi_command(self.dev, self.cmd) # if (ret != 0): # self.warn_dialog("PCI-6033E cannot collect data! Error: %d" % ret) # print(c.comedi_strerror(c.comedi_errno())) # return(False) data_tup = () data = "" # Format string for struct.unpack() format = '32H' # See if we can read anything from fd (timeout 0.05 seconds). ret = select.select([self.fd], [], [], 0.05) if (not ret[0]): # Poll the device to try and get some data. cret = c.comedi_poll(self.dev, SUBDEVICE) if (cret < 0): print("comedi poll fail: %d" % ret) else: # Read some data! data = os.read(self.fd, BUF_SIZE) self.data_buf += data if (len(data) > 0): bytes_read = len(data) #print("Read %d bytes" % bytes_read) # Number of rows of data in the chunk r = math.floor(len(self.data_buf)/(self.comedi_num_chans*WORD_SIZE)) for i in range(int(r)): #print(len(data[64*i:64*(i+1)])) data_tup = data_tup + struct.unpack(format, self.data_buf[64*i:64*(i+1)]) #print(data_tup) #data_tup = () #print(len(data)) for n, point in enumerate(data_tup): self.analog_data[n%self.comedi_num_chans].append(point) for i in range(int(r)): self.x.append(self.x[-1] + 1.0/SCAN_FREQ) self.data_buf = self.data_buf[len(data_tup*2):] #print("LEFTOVER DATA:") #print(len(self.data_buf)) return(True) def pci_6033e_init(self, dev_name): self.dev = c.comedi_open(dev_name) if not(self.dev): self.warn_dialog("Unable to open device: " + dev_name) return(-1) ret = c.comedi_lock(self.dev, SUBDEVICE) if (ret < 0): self.warn_dialog("Could not lock comedi device") return(-1) # get a file-descriptor for use later self.fd = c.comedi_fileno(self.dev) if (self.fd <= 0): self.warn_dialog("Error obtaining Comedi device file descriptor") c.comedi_close(self.dev) return(-1) # Channel range (0-5V) if (c.comedi_range_is_chan_specific(self.dev, SUBDEVICE) != 0): self.warn_dialog("Comedi range is channel specific!") c.comedi_close(self.dev) return(-1) self.comedi_range = c.comedi_get_range(self.dev, SUBDEVICE, 0, CHAN_RANGE) self.comedi_maxdata = c.comedi_get_maxdata(self.dev, SUBDEVICE, 0) board_name = c.comedi_get_board_name(self.dev) if (board_name != "pci-6033e"): print("Opened wrong device!") # Prepare channels, gains, refs self.comedi_num_chans = NUM_CHANNELS chans = range(self.comedi_num_chans) gains = [0]*self.comedi_num_chans aref = [c.AREF_GROUND]*self.comedi_num_chans chan_list = c.chanlist(self.comedi_num_chans) # Configure all the channels! for i in range(self.comedi_num_chans): chan_list[i] = c.cr_pack(chans[i], gains[i], aref[i]) # The comedi command self.cmd = c.comedi_cmd_struct() # 1.0e9 because this number is in nanoseconds for some reason period = int(1.0e9/float(SCAN_FREQ)) # Init cmd ret = c.comedi_get_cmd_generic_timed(self.dev, SUBDEVICE, self.cmd, self.comedi_num_chans, period) if (ret): self.warn_dialog("Could not initiate command") c.comedi_close(self.dev) return(-1) # Populate command self.cmd.chanlist = chan_list self.cmd.chanlist_len = self.comedi_num_chans self.cmd.scan_end_arg = self.comedi_num_chans self.cmd.stop_src = c.TRIG_NONE self.cmd.stop_arg = 0 print("real timing: %d ns" % self.cmd.convert_arg) print("Real scan freq: %d Hz" % (1.0/(float(self.cmd.convert_arg)*32.0*1.0e-9))) #print("period: %d ns" % period) print_cmd(self.cmd) # Test command out. ret = c.comedi_command_test(self.dev, self.cmd) if (ret < 0): self.warn_dialog("Comedi command test failed!") c.comedi_close(self.dev) return(-1) print("Command test passed") return(0) # Die gracefully... def on_destroy(self, widget): if (self.dev): c.comedi_close(self.dev) print("Comedi device closed...") Gtk.main_quit() # Oy! def warn_dialog(self, message): dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, "OHNOES!") dialog.format_secondary_text(message) response = dialog.run() # if response == Gtk.ResponseType.OK: # print "WARN dialog closed by clicking OK button" dialog.destroy() def del_px_data(self, d_x): xpx_old, ypx_old = self.a.transData.transform((0, 0)) xpx_new, ypx_new = self.a.transData.transform((d_x, 0)) return(xpx_new - xpx_old) def update_plots(self): if (self.do_redraw): #print("redraw") self.a.clear() self.a.grid(True) self.canvas.draw() self.clean_bg = self.canvas.copy_from_bbox(self.f.bbox) self.background = self.canvas.copy_from_bbox(self.get_bg_bbox(self.a)) self.do_redraw = False self.a.set_xlim([self.x[-1] - self.fifo_size/SCAN_FREQ - 1, self.x[-1] + 1]) # Restore the blank background self.canvas.restore_region(self.clean_bg) xarr = np.array(self.x) analog_arr = np.array(self.analog_data[0]) analog_arr2 = np.array(self.analog_data[18]) #lastx_ind = np.where(np.array(self.x) > self.lastx) lastx_ind = np.where(xarr > self.lastx) #lastx_ind = itertools.islice(self.lastx #print(lastx_ind[0]) lastx_ind = lastx_ind[0] # Offset in time x_offset = abs(xarr[-1] - self.lastx) # Find the equivalent offset in display pixels pixel_offset = self.del_px_data(x_offset) dx_pixel = np.floor(pixel_offset) # Compute and redraw saved background (moved over). x1, y1, x2, y2 = self.background.get_extents() self.canvas.restore_region(self.background, bbox = (x1 + dx_pixel, y1, x2, y2), xy = (x1 - dx_pixel, y1)) # if (len(lastx_ind) > 0): # lastx_ind = np.array(itertools.islice(self.x, lastx_ind[0], self.fifo_size)) # else: # lastx_ind = np.array(self.x) # #print(lastx_ind) self.my_line.set_xdata(xarr[lastx_ind]) self.my_line.set_ydata(analog_arr[lastx_ind]) self.a.draw_artist(self.my_line) #self.canvas.draw() self.my_line2.set_xdata(xarr[lastx_ind]) self.my_line2.set_ydata(analog_arr2[lastx_ind]) self.a.draw_artist(self.my_line2) self.background = self.canvas.copy_from_bbox(self.get_bg_bbox(self.a)) # Draw the axes (and grids if applicable) self.a.draw_artist(self.a.xaxis) self.a.draw_artist(self.a.yaxis) self.canvas.blit(self.f.bbox) self.lastx = self.x[-1] #self.canvas.draw() return(True) # def init_blit_plot(self): # l = self.line.set_data([], []) # return(l) def win_resize(self, win): #print("RESIZE!") # Don't do this here, instead activate a "needs redraw" class # var that instructs update_plot to do a full redraw. self.do_redraw = True
class CampaignGraph(object): title = 'Unknown' _graph_id = None table_subscriptions = [] def __init__(self, config, parent, size_request=None): self.config = config self.parent = parent self.figure, ax = pyplot.subplots() self.axes = self.figure.get_axes() self.canvas = FigureCanvas(self.figure) self.manager = None if size_request: self.canvas.set_size_request(*size_request) self.canvas.mpl_connect('button_press_event', self.mpl_signal_canvas_button_pressed) self.canvas.show() self.navigation_toolbar = NavigationToolbar(self.canvas, self.parent) self.navigation_toolbar.hide() self.popup_menu = Gtk.Menu.new() menu_item = Gtk.MenuItem.new_with_label('Export') menu_item.connect('activate', self.signal_activate_popup_menu_export) self.popup_menu.append(menu_item) menu_item = Gtk.MenuItem.new_with_label('Refresh') menu_item.connect('activate', lambda action: self.refresh()) self.popup_menu.append(menu_item) menu_item = Gtk.CheckMenuItem.new_with_label('Show Toolbar') menu_item.connect('toggled', self.signal_toggled_popup_menu_show_toolbar) self.popup_menu.append(menu_item) self.popup_menu.show_all() @classmethod def get_graph_id(klass): return klass._graph_id def make_window(self): if self.manager == None: self.manager = FigureManager(self.canvas, 0) window = self.manager.window window.set_transient_for(self.parent) window.set_title(self.title) return window def mpl_signal_canvas_button_pressed(self, event): if event.button != 3: return pos_func = lambda m, d: (event.x, event.y, True) self.popup_menu.popup(None, None, None, None, event.button, Gtk.get_current_event_time()) return True def signal_activate_popup_menu_export(self, action): dialog = gui_utilities.UtilityFileChooser('Export Graph', self.parent) file_name = self.config['campaign_name'] + '.png' response = dialog.run_quick_save(file_name) dialog.destroy() if not response: return destination_file = response['target_filename'] self.figure.savefig(destination_file, format='png') def signal_toggled_popup_menu_show_toolbar(self, widget): if widget.get_property('active'): self.navigation_toolbar.show() else: self.navigation_toolbar.hide() def load_graph(self): self.refresh() def refresh(self, info_cache=None): info_cache = (info_cache or {}) if not self.parent.rpc: return info_cache for table in self.table_subscriptions: if not table in info_cache: info_cache[table] = list(self.parent.rpc.remote_table('campaign/' + table, self.config['campaign_id'])) map(lambda ax: ax.clear(), self.axes) self._load_graph(info_cache) self.canvas.draw() return info_cache
class MainView(MainViewInterface): @inject def __init__(self, presenter: MainPresenter, edit_speed_profile_view: EditSpeedProfileView, preferences_view: PreferencesView, builder: MainBuilder, settings_interactor: SettingsInteractor, ) -> None: _LOG.debug('init MainView') self._presenter: MainPresenter = presenter self._edit_speed_profile_view = edit_speed_profile_view self._preferences_view = preferences_view self._presenter.main_view = self self._builder: Gtk.Builder = builder self._settings_interactor = settings_interactor self._init_widgets() def _init_widgets(self) -> None: self._app_indicator: Optional[AppIndicator3.Indicator] = None self._window = self._builder.get_object("application_window") self._edit_speed_profile_view.set_transient_for(self._window) self._preferences_view.set_transient_for(self._window) self._main_menu: Gtk.Menu = self._builder.get_object("main_menu") self._main_infobar: Gtk.InfoBar = self._builder.get_object("main_infobar") self._main_infobar.connect("response", lambda b, _: b.set_revealed(False)) self._main_infobar_label: Gtk.Label = self._builder.get_object("main_infobar_label") self._main_infobar.set_revealed(False) self._statusbar: Gtk.Statusbar = self._builder.get_object('statusbar') self._context = self._statusbar.get_context_id(APP_PACKAGE_NAME) self._cooling_fan_duty: Gtk.Label = self._builder.get_object('cooling_fan_duty') self._cooling_fan_rpm: Gtk.Label = self._builder.get_object('cooling_fan_rpm') self._cooling_liquid_temp: Gtk.Label = self._builder.get_object('cooling_liquid_temp') self._cooling_pump_rpm: Gtk.Label = self._builder.get_object('cooling_pump_rpm') self._firmware_version: Gtk.Label = self._builder.get_object('firmware_version') self._cooling_fan_combobox: Gtk.ComboBox = self._builder.get_object('cooling_fan_profile_combobox') self._cooling_fan_liststore: Gtk.ListStore = self._builder.get_object('cooling_fan_profile_liststore') self._cooling_pump_combobox: Gtk.ComboBox = self._builder.get_object('cooling_pump_profile_combobox') self._cooling_pump_liststore: Gtk.ListStore = self._builder.get_object('cooling_pump_profile_liststore') cooling_fan_scrolled_window: Gtk.ScrolledWindow = self._builder.get_object('cooling_fan_scrolled_window') cooling_pump_scrolled_window: Gtk.ScrolledWindow = self._builder.get_object('cooling_pump_scrolled_window') self._cooling_fan_apply_button: Gtk.Button = self._builder.get_object('cooling_fan_apply_button') self._cooling_pump_apply_button: Gtk.Button = self._builder.get_object('cooling_pump_apply_button') self._cooling_fan_edit_button: Gtk.Button = self._builder.get_object('cooling_fan_edit_button') self._cooling_pump_edit_button: Gtk.Button = self._builder.get_object('cooling_pump_edit_button') self._cooling_fixed_speed_popover: Gtk.Popover = self._builder.get_object('cooling_fixed_speed_popover') self._cooling_fixed_speed_adjustment: Gtk.Adjustment = \ self._builder.get_object('cooling_fixed_speed_adjustment') self._cooling_fixed_speed_scale: Gtk.Scale = self._builder.get_object('cooling_fixed_speed_scale') self._about_dialog: Gtk.AboutDialog = self._builder.get_object("about_dialog") self._init_about_dialog() self._legacy_firmware_dialog: Gtk.MessageDialog = self._builder.get_object("legacy_firmware_dialog") self._legacy_firmware_dialog.connect('response', lambda dialog, _: dialog.hide()) self._init_plot_charts(cooling_fan_scrolled_window, cooling_pump_scrolled_window) def _init_about_dialog(self) -> None: self._about_dialog.set_program_name(APP_NAME) self._about_dialog.set_version(APP_VERSION) self._about_dialog.set_website(APP_SOURCE_URL) self._about_dialog.connect("delete-event", hide_on_delete) def show(self) -> None: self._presenter.on_start() self._init_app_indicator() def _init_app_indicator(self) -> None: if AppIndicator3: # Setting icon name in new() as '', because new() wants an icon path self._app_indicator = AppIndicator3.Indicator \ .new(APP_ID, '', AppIndicator3.IndicatorCategory.HARDWARE) # Set the actual icon by name. If the App is not installed system-wide, the icon won't show up, # otherwise it will show up correctly. The set_icon_full() function needs a description for accessibility # purposes. I gave it the APP_NAME. self._app_indicator.set_icon_full(APP_ICON_NAME_SYMBOLIC, APP_NAME) if self._settings_interactor.get_bool('settings_show_app_indicator'): self._app_indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE) else: self._app_indicator.set_status(AppIndicator3.IndicatorStatus.PASSIVE) self._app_indicator.set_menu(self._main_menu) def show_main_infobar_message(self, message: str, markup: bool = False) -> None: if markup: self._main_infobar_label.set_markup(message) else: self._main_infobar_label.set_label(message) self._main_infobar.set_revealed(True) def toggle_window_visibility(self) -> None: if self._window.props.visible: self._window.hide() else: self._window.show() def show_add_speed_profile_dialog(self, channel: ChannelType) -> None: _LOG.debug("view show_add_speed_profile_dialog %s", channel.name) def show_fixed_speed_profile_popover(self, profile: SpeedProfile) -> None: if profile.channel == ChannelType.FAN.value: self._cooling_fixed_speed_popover.set_relative_to(self._cooling_fan_edit_button) self._cooling_fixed_speed_adjustment.set_lower(FAN_MIN_DUTY) self._cooling_fixed_speed_adjustment.set_upper(MAX_DUTY) elif profile.channel == ChannelType.PUMP.value: self._cooling_fixed_speed_popover.set_relative_to(self._cooling_pump_edit_button) self._cooling_fixed_speed_adjustment.set_lower(PUMP_MIN_DUTY) self._cooling_fixed_speed_adjustment.set_upper(MAX_DUTY) else: raise ValueError("Unknown channel: %s" % profile.channel) self._cooling_fixed_speed_scale.set_name(profile.channel) self._cooling_fixed_speed_adjustment.set_value(profile.steps[0].duty) self._cooling_fixed_speed_popover.show_all() def dismiss_and_get_value_fixed_speed_popover(self) -> Tuple[int, str]: self._cooling_fixed_speed_popover.hide() return self._cooling_fixed_speed_scale.get_value(), self._cooling_fixed_speed_scale.get_name() def show_about_dialog(self) -> None: self._about_dialog.show() def show_legacy_firmware_dialog(self) -> None: self._legacy_firmware_dialog.show() def show_error_message_dialog(self, title: str, message: str) -> None: dialog = Gtk.MessageDialog(self._window, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, title) dialog.format_secondary_text(message) dialog.run() dialog.destroy() def set_statusbar_text(self, text: str) -> None: self._statusbar.remove_all(self._context) self._statusbar.push(self._context, text) def refresh_status(self, status: Optional[Status]) -> None: _LOG.debug('view status') if status: self._cooling_fan_rpm.set_markup("<span size=\"xx-large\">%s</span> RPM" % status.fan_rpm) self._cooling_fan_duty.set_markup("<span size=\"xx-large\">%s</span> %%" % ('-' if status.fan_duty is None else "%.0f" % status.fan_duty)) self._cooling_liquid_temp.set_markup("<span size=\"xx-large\">%s</span> °C" % status.liquid_temperature) self._cooling_pump_rpm.set_markup("<span size=\"xx-large\">%s</span> RPM" % status.pump_rpm) self._firmware_version.set_label("firmware %s - %s %s" % (status.firmware_version, APP_NAME, APP_VERSION)) if self._app_indicator: if self._settings_interactor.get_bool('settings_show_app_indicator'): self._app_indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE) else: self._app_indicator.set_status(AppIndicator3.IndicatorStatus.PASSIVE) if self._settings_interactor.get_bool('settings_app_indicator_show_water_temp'): self._app_indicator.set_label(" %s°C" % status.liquid_temperature, " XX°C") else: self._app_indicator.set_label("", "") def refresh_chart(self, profile: Optional[SpeedProfile] = None, channel_to_reset: Optional[str] = None) -> None: if profile is None and channel_to_reset is None: raise ValueError("Both parameters are None!") if channel_to_reset is not None: self._plot_chart(channel_to_reset, {}) else: self._plot_chart(profile.channel, get_speed_profile_data(profile)) def refresh_profile_combobox(self, channel: ChannelType, data: List[Tuple[int, str]], active: Optional[int]) -> None: if channel is ChannelType.FAN: self._cooling_fan_liststore.clear() for item in data: self._cooling_fan_liststore.append([item[0], item[1]]) self._cooling_fan_combobox.set_model(self._cooling_fan_liststore) self._cooling_fan_combobox.set_sensitive(len(self._cooling_fan_liststore) > 1) if active is not None: self._cooling_fan_combobox.set_active(active) else: self.refresh_chart(channel_to_reset=channel.value) elif channel is ChannelType.PUMP: self._cooling_pump_liststore.clear() for item in data: self._cooling_pump_liststore.append([item[0], item[1]]) self._cooling_pump_combobox.set_model(self._cooling_pump_liststore) self._cooling_pump_combobox.set_sensitive(len(self._cooling_pump_liststore) > 1) if active is not None: self._cooling_pump_combobox.set_active(active) else: self.refresh_chart(channel_to_reset=channel.value) else: raise ValueError("Unknown channel: %s" % channel.name) def set_apply_button_enabled(self, channel: ChannelType, enabled: bool) -> None: if channel is ChannelType.FAN: self._cooling_fan_apply_button.set_sensitive(enabled) elif channel is ChannelType.PUMP: self._cooling_pump_apply_button.set_sensitive(enabled) else: raise ValueError("Unknown channel: %s" % channel.name) def set_edit_button_enabled(self, channel: ChannelType, enabled: bool) -> None: if channel is ChannelType.FAN: self._cooling_fan_edit_button.set_sensitive(enabled) elif channel is ChannelType.PUMP: self._cooling_pump_edit_button.set_sensitive(enabled) else: raise ValueError("Unknown channel: %s" % channel.name) # pylint: disable=attribute-defined-outside-init def _init_plot_charts(self, fan_scrolled_window: Gtk.ScrolledWindow, pump_scrolled_window: Gtk.ScrolledWindow) -> None: self._fan_figure = Figure(figsize=(8, 6), dpi=72, facecolor='#00000000') self._fan_canvas = FigureCanvas(self._fan_figure) # a Gtk.DrawingArea+ self._fan_axis = self._fan_figure.add_subplot(111) self._fan_line, = init_plot_chart( fan_scrolled_window, self._fan_figure, self._fan_canvas, self._fan_axis ) self._pump_figure = Figure(figsize=(8, 6), dpi=72, facecolor='#00000000') self._pump_canvas = FigureCanvas(self._pump_figure) # a Gtk.DrawingArea+ self._pump_axis = self._pump_figure.add_subplot(111) self._pump_line, = init_plot_chart( pump_scrolled_window, self._pump_figure, self._pump_canvas, self._pump_axis ) def _plot_chart(self, channel_name: str, data: Dict[int, int]) -> None: sorted_data = OrderedDict(sorted(data.items())) temperature = list(sorted_data.keys()) duty = list(sorted_data.values()) if channel_name == ChannelType.FAN.value: self._fan_line.set_xdata(temperature) self._fan_line.set_ydata(duty) self._fan_canvas.draw() self._fan_canvas.flush_events() elif channel_name == ChannelType.PUMP.value: self._pump_line.set_xdata(temperature) self._pump_line.set_ydata(duty) self._pump_canvas.draw() self._pump_canvas.flush_events() else: raise ValueError("Unknown channel: %s" % channel_name)
class Window(object): def __init__(self): self.builder = Gtk.Builder() self.builder.add_from_file('gui.glade') self.window = self.builder.get_object('window1') self.builder.connect_signals(self) figure_box = self.builder.get_object('scrolledwindow1') self.builder.get_object('spinbuttonphi_s').set_increments(0.005, 0.1) self.builder.get_object('spinbuttonphi_p').set_increments(0.005, 0.1) self.builder.get_object('spinbuttonL_b').set_increments(0.001, 0.1) self.simple_ext = False self.freeze_plot = False self.paramp = LJPA(I_c=self.builder.get_object('spinbuttonI_c').get_value()*1e-6, phi_dc=self.builder.get_object('spinbuttonphi_dc').get_value(), phi_ac=self.builder.get_object('spinbuttonphi_p').get_value(), phi_s=self.builder.get_object('spinbuttonphi_s').get_value(), theta_p=self.builder.get_object('spinbuttontheta_p').get_value(), C=self.builder.get_object('spinbuttonC').get_value()*1e-12, L_s=self.builder.get_object('spinbuttonL_s').get_value()*1e-12, f_p=self.builder.get_object('spinbuttonf_p').get_value()*1e9) self.parameters = {'I_c' : self.builder.get_object('spinbuttonI_c').get_value()*1e-6, 'phi_dc' : self.builder.get_object('spinbuttonphi_dc').get_value(), 'phi_ac' : self.builder.get_object('spinbuttonphi_p').get_value(), 'phi_s' : self.builder.get_object('spinbuttonphi_s').get_value(), 'theta_p' : self.builder.get_object('spinbuttontheta_p').get_value(), 'C' : self.builder.get_object('spinbuttonC').get_value()*1e-12, 'L_s' : self.builder.get_object('spinbuttonL_s').get_value()*1e-12, 'f_p' : self.builder.get_object('spinbuttonf_p').get_value()*1e9} self.builder.get_object('entry1').set_text(str(self.parameters)) # Start of Matplotlib specific code self.fig, (self.ax1, self.ax2, self.ax3, self.ax4) = plt.subplots(4, 1, sharex=True) # figure = Figure()#figsize=(8, 6), dpi=71) # self.ax = figure.add_subplot(111) f = self.get_frequency() z = self.get_impedance(f) re = np.real(z) im = np.imag(z) r = 20.*np.log10(abs((z - 50.)/(z + 50.))) self.line_r, = self.ax1.plot(f/1e9, r) self.line_20, = self.ax1.plot([f[0]/1e9, f[-1.]/1e9], [20., 20.], 'r--') self.line_re, = self.ax2.plot(f/1e9, re) self.line_50, = self.ax2.plot([f[0]/1e9, f[-1.]/1e9], [-50., -50.], 'r--') self.line_im, = self.ax3.plot(f/1e9, im) self.line_0, = self.ax3.plot([f[0]/1e9, f[-1.]/1e9], [0., 0.], 'r--') self.line_abs, = self.ax4.plot(f/1e9, abs(z)) self.line_00, = self.ax4.plot([f[0]/1e9, f[-1.]/1e9], [0., 0.], 'r--') self.ax1.set_ylabel('Gain [dB]') self.ax2.set_ylabel('Re(Z)') self.ax3.set_ylabel('Im(Z)') self.ax4.set_ylabel('|Z|') self.ax4.set_xlabel('Frequency [GHz]') self.canvas = FigureCanvas(self.fig) self.canvas.set_size_request(800, 600) figure_box.add_with_viewport(self.canvas) toolbar_box = self.builder.get_object('scrolledwindow2') toolbar = NavigationToolbar(self.canvas, self.window) toolbar_box.add_with_viewport(toolbar) self.window.show_all() Gtk.main() def get_frequency(self): return np.linspace(self.builder.get_object('spinbuttonf_s_start').get_value(), self.builder.get_object('spinbuttonf_s_stop').get_value(), self.builder.get_object('spinbuttonf_s_nb_point').get_value())*1e9 def get_impedance(self, f): if self.builder.get_object('checkbutton3').get_active(): return self.paramp.impedance(f, simple_ext=self.simple_ext) else: return self.paramp.impedance(f) def checkbutton1_toggled(self, checkbutton): if checkbutton.get_active(): self.builder.get_object('box11').set_sensitive(True) self.builder.get_object('box20').set_sensitive(False) self.paramp.f_p = self.builder.get_object('spinbuttonf_p').get_value()*1e9 else: self.builder.get_object('box11').set_sensitive(False) self.builder.get_object('box20').set_sensitive(True) self.paramp.f_p = None self.update_plot() def checkbutton3_toggled(self, checkbutton): if checkbutton.get_active(): self.simple_ext = True else: self.simple_ext = False self.update_plot() def checkbutton2_toggled(self, checkbutton): if checkbutton.get_active(): self.builder.get_object('box21').set_sensitive(True) self.builder.get_object('box25').set_sensitive(True) self.builder.get_object('box26').set_sensitive(True) self.builder.get_object('box27').set_sensitive(True) self.builder.get_object('checkbutton3').set_sensitive(True) self.builder.get_object('box31').set_sensitive(True) self.builder.get_object('box30').set_sensitive(True) self.builder.get_object('box29').set_sensitive(True) self.builder.get_object('box28').set_sensitive(True) self.builder.get_object('box13').set_sensitive(True) self.builder.get_object('box8').set_sensitive(True) self.builder.get_object('label35').set_sensitive(True) self.builder.get_object('label31').set_sensitive(True) self.builder.get_object('button1').set_sensitive(True) self.paramp = KLJPA(I_c=self.builder.get_object('spinbuttonI_c').get_value()*1e-6, phi_dc=self.builder.get_object('spinbuttonphi_dc').get_value(), phi_ac=self.builder.get_object('spinbuttonphi_p').get_value(), phi_s=self.builder.get_object('spinbuttonphi_s').get_value(), theta_p=self.builder.get_object('spinbuttontheta_p').get_value(), C=self.builder.get_object('spinbuttonC').get_value()*1e-12, L_s=self.builder.get_object('spinbuttonL_s').get_value()*1e-12, f_p=self.builder.get_object('spinbuttonf_p').get_value()*1e9, Z_l=self.builder.get_object('spinbuttonz_l').get_value(), l=self.builder.get_object('spinbuttonl').get_value()*1e-2, g_m=self.builder.get_object('spinbuttong_m').get_value(), C_l=1.66e-10, L_l=4.21e-7, L_b=self.builder.get_object('spinbuttonL_b').get_value()*1e-9) self.builder.get_object('entry1').set_text(str(self.parameters)) else: self.builder.get_object('box21').set_sensitive(False) self.builder.get_object('box25').set_sensitive(False) self.builder.get_object('box26').set_sensitive(False) self.builder.get_object('box27').set_sensitive(False) self.builder.get_object('checkbutton3').set_sensitive(False) self.builder.get_object('box31').set_sensitive(False) self.builder.get_object('box30').set_sensitive(False) self.builder.get_object('box29').set_sensitive(False) self.builder.get_object('box28').set_sensitive(False) self.builder.get_object('box13').set_sensitive(False) self.builder.get_object('box8').set_sensitive(False) self.builder.get_object('label35').set_sensitive(False) self.builder.get_object('label31').set_sensitive(False) self.builder.get_object('button1').set_sensitive(False) self.paramp = LJPA(I_c=self.builder.get_object('spinbuttonI_c').get_value()*1e-6, phi_dc=self.builder.get_object('spinbuttonphi_dc').get_value(), phi_ac=self.builder.get_object('spinbuttonphi_p').get_value(), phi_s=self.builder.get_object('spinbuttonphi_s').get_value(), theta_p=self.builder.get_object('spinbuttontheta_p').get_value(), C=self.builder.get_object('spinbuttonC').get_value()*1e-12, L_s=self.builder.get_object('spinbuttonL_s').get_value()*1e-12, f_p=self.builder.get_object('spinbuttonf_p').get_value()*1e9) self.update_plot() def button2_clicked(self, button): p = eval(self.builder.get_object('entry1').get_text()) self.freeze_plot = True self.builder.get_object('spinbuttonI_c').set_value(p['I_c']*1e6) self.builder.get_object('spinbuttonphi_dc').set_value(p['phi_dc']) self.builder.get_object('spinbuttonphi_p').set_value(p['phi_ac']) self.builder.get_object('spinbuttonphi_s').set_value(p['phi_s']) self.builder.get_object('spinbuttontheta_p').set_value(p['theta_p']) self.builder.get_object('spinbuttonC').set_value(p['C']*1e12) self.builder.get_object('spinbuttonL_s').set_value(p['L_s']*1e12) self.builder.get_object('spinbuttonf_p').set_value(p['f_p']*1e-9) self.builder.get_object('spinbuttonz_l').set_value(p['Z_l']) self.builder.get_object('spinbuttonl').set_value(p['l']*1e2) self.builder.get_object('spinbuttong_m').set_value(p['g_m']) self.builder.get_object('spinbuttonL_b').set_value(p['L_b']*1e9) self.freeze_plot = False self.update_plot() def spinbuttonC_changed(self, spinbutton): self.paramp.C = spinbutton.get_value()*1e-12 self.update_plot() def spinbuttonI_c_changed(self, spinbutton): self.paramp.I_c = spinbutton.get_value()*1e-6 self.update_plot() def spinbuttonL_s_changed(self, spinbutton): self.paramp.L_s = spinbutton.get_value()*1e-12 self.update_plot() def spinbuttonf_p_changed(self, spinbutton): self.paramp.f_p = spinbutton.get_value()*1e9 self.update_plot() def spinbuttonphi_p_changed(self, spinbutton): self.paramp.phi_ac = spinbutton.get_value() self.update_plot() def spinbuttontheta_p_changed(self, spinbutton): self.paramp.theta_p = spinbutton.get_value() self.update_plot() def spinbuttonphi_s_changed(self, spinbutton): self.paramp.phi_s = spinbutton.get_value()*1e-3 self.update_plot() def spinbuttonphi_dc_changed(self, spinbutton): self.paramp.phi_dc = spinbutton.get_value() self.update_plot() def spinbuttonl_changed(self, spinbutton): self.paramp.l = spinbutton.get_value()*1e-2 self.update_plot() def spinbuttonz_l_changed(self, spinbutton): self.paramp.zl = spinbutton.get_value() self.update_plot() def spinbuttong_m_changed(self, spinbutton): self.paramp.gm = spinbutton.get_value() self.update_plot() def spinbuttonL_b_changed(self, spinbutton): self.paramp.L_b = spinbutton.get_value()*1e-9 self.update_plot() def spinbuttonf_s_nb_point_changed(self, spinbutton): self.update_plot() def spinbuttonf_s_start_changed(self, spinbutton): self.update_plot() def spinbuttonf_s_stop_changed(self, spinbutton): self.update_plot() def update_plot(self, x=None, y=None): if not self.freeze_plot: if x is not None and y is not None: f = x z = y else: f = self.get_frequency() z = self.get_impedance(f) re = np.real(z) im = np.imag(z) r = 20.*np.log10(abs((z - 50.)/(z + 50.))) self.line_r.set_data(f/1e9, r) self.line_20.set_data(f/1e9, r) self.line_re.set_data(f/1e9, re) self.line_50.set_data([f[0]/1e9, f[-1.]/1e9], [-50., -50.]) self.line_im.set_data(f/1e9, im) self.line_0.set_data([f[0]/1e9, f[-1.]/1e9], [0., 0.]) self.line_abs.set_data(f/1e9, abs(z)) self.line_00.set_data([f[0]/1e9, f[-1.]/1e9], [0., 0.]) for ax in (self.ax1, self.ax2, self.ax3, self.ax4): ax.relim() ax.autoscale_view() self.line_20.set_data([f[0]/1e9, f[-1.]/1e9], [20., 20.]) self.canvas.draw() if self.builder.get_object('checkbutton2').get_active(): self.parameters = {'I_c' : self.builder.get_object('spinbuttonI_c').get_value()*1e-6, 'phi_dc' : self.builder.get_object('spinbuttonphi_dc').get_value(), 'phi_ac' : self.builder.get_object('spinbuttonphi_p').get_value(), 'phi_s' : self.builder.get_object('spinbuttonphi_s').get_value(), 'theta_p' : self.builder.get_object('spinbuttontheta_p').get_value(), 'C' : self.builder.get_object('spinbuttonC').get_value()*1e-12, 'L_s' : self.builder.get_object('spinbuttonL_s').get_value()*1e-12, 'f_p' : self.builder.get_object('spinbuttonf_p').get_value()*1e9, 'Z_l' : self.builder.get_object('spinbuttonz_l').get_value(), 'l' : self.builder.get_object('spinbuttonl').get_value()*1e-2, 'g_m' : self.builder.get_object('spinbuttong_m').get_value(), 'C_l' : 1.66e-10, 'L_l' : 4.21e-7, 'L_b' : self.builder.get_object('spinbuttonL_b').get_value()*1e-9} else: self.parameters = {'I_c' : self.builder.get_object('spinbuttonI_c').get_value()*1e-6, 'phi_dc' : self.builder.get_object('spinbuttonphi_dc').get_value(), 'phi_ac' : self.builder.get_object('spinbuttonphi_p').get_value(), 'phi_s' : self.builder.get_object('spinbuttonphi_s').get_value(), 'theta_p' : self.builder.get_object('spinbuttontheta_p').get_value(), 'C' : self.builder.get_object('spinbuttonC').get_value()*1e-12, 'L_s' : self.builder.get_object('spinbuttonL_s').get_value()*1e-12, 'f_p' : self.builder.get_object('spinbuttonf_p').get_value()*1e9} self.builder.get_object('entry1').set_text(str(self.parameters)) def optimization(self, button): self.iteration = 0 def func(x, names, f): x = abs(x) for value, name in zip(x, names): if name == 'c': self.paramp.C = value*1e-12 if name == 'Ic': self.paramp.I_c = value*1e-6 if name == 'Ls': self.paramp.L_s = value*1e-12 if name == 'l': self.paramp.l = value*1e-2 if name == 'zl': self.paramp.zl = value if name == 'gm': self.paramp.gm = value*1e-1 if name == 'lb': self.paramp.L_b = value*1e-1 if name == 'fp': self.paramp.f_p = value*1e9 if name == 'phi_ac': self.paramp.phi_ac = value*1e-1 if name == 'phi_dc': self.paramp.phi_dc = value*1e-1 z = self.get_impedance(f) re = np.real(z) im = np.imag(z) re_condition = np.sum(((re + 50.)/re)**2.) im_condition = np.sum((im/100.)**2.) y = np.sum(((re + 50.)/re)**2. + (im/100.)**2.) self.iteration += 1 print '' print 'Iteration: ', self.iteration for value, name in zip(x, names): if name == 'c': print 'C: '+str(round(self.paramp.C*1e12, 3)) if name == 'Ic': print 'Ic: '+str(round(self.paramp.I_c*1e6, 3)) if name == 'Ls': print 'L_s: '+str(round(self.paramp.L_s*1e12, 3)) if name == 'l': print 'l: '+str(round(self.paramp.l*1e2, 3)) if name == 'zl': print 'zl: '+str(round(self.paramp.zl, 3)) if name == 'gm': print 'gm: '+str(round(self.paramp.gm, 3)) if name == 'lb': print 'L_b: '+str(round(self.paramp.L_b*1e9, 3)) if name == 'fp': print 'f_p: '+str(round(self.paramp.f_p*1e-9, 3)) if name == 'phi_ac': print 'phi_ac: '+str(round(self.paramp.phi_ac, 3)) if name == 'phi_dc': print 'phi_dc: '+str(round(self.paramp.phi_dc, 3)) print 'Real part: '+str(round(re_condition, 3))+', imaginary part: '+str(round(im_condition, 3))+', least square: '+str(round(y, 3)) print '' return y names = ['c', 'Ic', 'Ls', 'l', 'zl', 'gm', 'lb', 'fp', 'phi_ac', 'phi_dc'] values = [self.builder.get_object('spinbuttonC').get_value(), self.builder.get_object('spinbuttonI_c').get_value(), self.builder.get_object('spinbuttonL_s').get_value(), self.builder.get_object('spinbuttonl').get_value(), self.builder.get_object('spinbuttonz_l').get_value(), self.builder.get_object('spinbuttong_m').get_value()*10., self.builder.get_object('spinbuttonL_b').get_value()*10., self.builder.get_object('spinbuttonf_p').get_value(), self.builder.get_object('spinbuttonphi_p').get_value()*10., self.builder.get_object('spinbuttonphi_dc').get_value()*10.] bounds = ((2., 8.), (2., 6.), (20., 30.), (0.5, 4.), (3., 20.), (0.01, 5), (0.01, 20.), (5., 20.), (0.1, 9.), (1., 4.)) variables = [] if self.builder.get_object('checkbutton_optimized_c').get_active(): variables.append('c') if self.builder.get_object('checkbutton_optimized_Ic').get_active(): variables.append('Ic') if self.builder.get_object('checkbutton_optimized_ls').get_active(): variables.append('Ls') if self.builder.get_object('checkbutton_optimized_l').get_active(): variables.append('l') if self.builder.get_object('checkbutton_optimized_zl').get_active(): variables.append('zl') if self.builder.get_object('checkbutton_optimized_gm').get_active(): variables.append('gm') if self.builder.get_object('checkbutton_optimized_lb').get_active(): variables.append('lb') if self.builder.get_object('checkbutton_optimized_fp').get_active(): variables.append('fp') if self.builder.get_object('checkbutton_optimized_phi_ac').get_active(): variables.append('phi_ac') if self.builder.get_object('checkbutton_optimized_phi_dc').get_active(): variables.append('phi_dc') names_to_optimized = [] values_to_optimized = [] bounds_to_optimized = [] for name, value, bound in zip(names, values, bounds): if name in variables: names_to_optimized.append(name) values_to_optimized.append(value) bounds_to_optimized.append(bound) f = np.linspace(self.builder.get_object('spinbutton1').get_value(), self.builder.get_object('spinbutton2').get_value(), self.builder.get_object('spinbutton3').get_value())*1e9 self.freeze_plot = True results = minimize(func, values_to_optimized, args=(names_to_optimized, f), # method='TNC', method='SLSQP', # method='L-BFGS-B', bounds=bounds_to_optimized) values_optimized = results.x self.freeze_plot = False for value, name in zip(values_optimized, names_to_optimized): if name == 'c': self.builder.get_object('spinbuttonC').set_value(value) if name == 'Ic': self.builder.get_object('spinbuttonI_c').set_value(value) if name == 'Ls': self.builder.get_object('spinbuttonL_s').set_value(value) if name == 'l': self.builder.get_object('spinbuttonl').set_value(value) if name == 'zl': self.builder.get_object('spinbuttonz_l').set_value(value) if name == 'gm': self.builder.get_object('spinbuttong_m').set_value(value/10.) if name == 'lb': self.builder.get_object('spinbuttonL_b').set_value(value/10.) if name == 'fp': self.builder.get_object('spinbuttonf_p').set_value(value) if name == 'phi_ac': self.builder.get_object('spinbuttonphi_p').set_value(value/10.) if name == 'phi_dc': self.builder.get_object('spinbuttonphi_dc').set_value(value/10.) self.update_plot() print 'Done' return True def quit(self, event): Gtk.main_quit()
class PlotWindow(Gtk.Window): __gsignals__ = { 'click_on_plot': (GObject.SIGNAL_RUN_FIRST, None, (float, )) } def __init__(self): super().__init__(title="Yaw Pitch Roll Plot") self.window_closed = False self.connect('destroy', self.on_destroy) self.f = Figure(figsize=(5, 4), dpi=100) self.canvas = FigureCanvas(self.f) self.f.canvas.mpl_connect('pick_event', self.on_pick) vbox = Gtk.VBox() self.add(vbox) vbox.pack_start(self.canvas, True, True, 0) toolbar = NavigationToolbar(self.canvas, self) vbox.pack_start(toolbar, False, False, 0) self.set_size_request(750, 600) self.axarr = None self.video_length_plots = [None] * 4 self.yaw_time = None self.pitch_time = None self.roll_time = None self.height_time = None self.start_time_stamp = None self.video_list = None self.show_all() def on_destroy(self, *_): self.window_closed = True def plot(self, time_stamps, data, video_list): self.video_list = video_list self.start_time_stamp = time_stamps[0] time = [t - time_stamps[0] for t in time_stamps] yaw, pitch, roll, height = zip(*data) self.axarr = self.f.subplots(nrows=2, ncols=2) self.plot_yaw(self.axarr, yaw, time) self.plot_pitch(self.axarr, pitch, time) self.plot_roll(self.axarr, roll, time) self.plot_height(self.axarr, height, time) @staticmethod def shift_yaw(yaw): new_yaw = [] last_point = 0 shift = 0 for point in yaw: if (last_point > 150 and point < -150) or (last_point < -150 and point > 150): if point < 0: shift += 360 else: shift -= 360 new_point = point + shift last_point = point new_yaw.append(new_point) return new_yaw def plot_yaw(self, axarr, yaw, time): new_yaw = self.shift_yaw(yaw) for offset in range(-10 * 360, 10 * 360 + 1, 360): yaw_with_offset = [x + offset for x in new_yaw] axarr[0, 0].plot(time, yaw_with_offset, 'blue') axarr[0, 0].set_ylim([-200, 200]) axarr[0, 0].set_xlim([0, time[-1]]) axarr[0, 0].set_xlabel('Seconds') axarr[0, 0].set_ylabel('Degrees') axarr[0, 0].xaxis.set_ticks(np.arange(0, time[-1], 60)) for video in self.video_list: axarr[0, 0].axvspan(xmin=video[0] - self.start_time_stamp, xmax=video[1] - self.start_time_stamp, color='#bbbbbb', picker=1) self.yaw_time = axarr[0, 0].axvline(x=0, color='red', linewidth=2) axarr[0, 0].set_title('Yaw') def plot_pitch(self, axarr, pitch, time): axarr[0, 1].plot(time, pitch, 'blue') axarr[0, 1].set_ylim([-100, 30]) axarr[0, 1].set_xlim([0, time[-1]]) axarr[0, 1].set_xlabel('Seconds') axarr[0, 1].set_ylabel('Degrees') axarr[0, 1].xaxis.set_ticks(np.arange(0, time[-1], 60)) for video in self.video_list: axarr[0, 1].axvspan(xmin=video[0] - self.start_time_stamp, xmax=video[1] - self.start_time_stamp, color='#bbbbbb', picker=1) self.pitch_time = axarr[0, 1].axvline(x=0, color='red', linewidth=2) axarr[0, 1].set_title('Pitch') def plot_roll(self, axarr, roll, time): axarr[1, 1].plot(time, roll, 'blue') axarr[1, 1].set_ylim([-180, 180]) axarr[1, 1].set_xlim([0, time[-1]]) axarr[1, 1].set_xlabel('Seconds') axarr[1, 1].set_ylabel('Degrees') axarr[1, 1].xaxis.set_ticks(np.arange(0, time[-1], 60)) for video in self.video_list: axarr[1, 1].axvspan(xmin=video[0] - self.start_time_stamp, xmax=video[1] - self.start_time_stamp, color='#bbbbbb', picker=1) self.roll_time = axarr[1, 1].axvline(x=0, color='red', linewidth=2) axarr[1, 1].set_title('Roll') def plot_height(self, axarr, height, time): axarr[1, 0].plot(time, height, 'blue') axarr[1, 0].set_xlim([0, time[-1]]) axarr[1, 0].set_xlabel('Seconds') axarr[1, 0].set_ylabel('Meters') axarr[1, 0].xaxis.set_ticks(np.arange(0, time[-1], 60)) ylim = axarr[1, 0].get_ylim() for video in self.video_list: axarr[1, 0].axvspan(xmin=video[0] - self.start_time_stamp, xmax=video[1] - self.start_time_stamp, color='#bbbbbb', picker=1) self.height_time = axarr[1, 0].axvline(x=0, color='red', linewidth=2) axarr[1, 0].set_ylim(ylim) axarr[1, 0].set_title('Height') def update_plot(self, time): self.yaw_time.set_xdata(time) self.pitch_time.set_xdata(time) self.roll_time.set_xdata(time) self.height_time.set_xdata(time) self.canvas.draw() self.canvas.flush_events() def update_video_length_plot(self, video_start, video_length): for plot in self.video_length_plots: if plot: plot.remove() self.video_length_plots = [ self.axarr[x, y].axvspan(xmin=video_start, xmax=video_start + video_length, ymin=0, ymax=0.1, color='#99ff99') for x, y in product(range(2), range(2)) ] def on_pick(self, event): video_start = np.min(event.artist.get_xy(), axis=0)[0] self.emit('click_on_plot', video_start)
class PlotNode(GtkNodes.Node): __gtype_name__ = 'PlotNode' def __init__(self, *args, **kwds): super().__init__(*args, **kwds) self.val_1 = 0 self.val_2 = 4 self.val_3 = 12 self.set_label("Plot") self.connect("node_func_clicked", self.remove) # create node input socket 1 lbl = Gtk.Label.new("Input 1") lbl.set_xalign(0.1) node_socket_input = self.item_add(lbl, GtkNodes.NodeSocketIO.SINK) node_socket_input.connect("socket_incoming", self.node_socket_incoming, 1) # create nodeinput socket 2 lbl = Gtk.Label.new("Input 2") lbl.set_xalign(0.1) node_socket_input = self.item_add(lbl, GtkNodes.NodeSocketIO.SINK) node_socket_input.connect("socket_incoming", self.node_socket_incoming, 2) # create nodeinput socket 3 lbl = Gtk.Label.new("Input 3") lbl.set_xalign(0.1) node_socket_input = self.item_add(lbl, GtkNodes.NodeSocketIO.SINK) node_socket_input.connect("socket_incoming", self.node_socket_incoming, 3) f = Figure(figsize=(5, 4), dpi=100) self.a = f.add_subplot(111) sw = Gtk.ScrolledWindow() sw.set_border_width(10) self.canvas = FigureCanvas(f) sw.add(self.canvas) sw.set_size_request(200, 200) self.item_add(sw, GtkNodes.NodeSocketIO.DISABLE) self.set_child_packing(sw, True, True, 0, Gtk.PackType.START) def plot(self, combobox): x = np.linspace(self.val_1, self.val_2, self.val_3) y = np.cos(x**2 / 3 + 4) tck, u = interpolate.splprep(np.array((x, y)), s=0) unew = np.arange(0, 1.01, 0.01) out = interpolate.splev(unew, tck) self.a.clear() self.a.plot(out[0], out[1], color='orange') self.a.plot(x, y, 'o') self.canvas.draw() def node_socket_incoming(self, socket, payload, datasource): x = struct.Struct("d") val = x.unpack(payload)[0] if datasource == 1: self.val_1 = int(val) elif datasource == 2: self.val_2 = int(val) elif datasource == 3: if (val > 10): self.val_3 = int(val) self.plot(self) def remove(self, node): self.destroy()
class ImgSrcNode(GtkNodes.Node): __gtype_name__ = 'SrcNode' def __init__(self, *args, **kwds): super().__init__(*args, **kwds) self.set_label("Image Source") self.connect("node_func_clicked", self.remove) self.img = misc.face() f = Figure(figsize=(5, 4), dpi=100) self.a = f.add_subplot(111) sw = Gtk.ScrolledWindow() sw.set_border_width(10) self.canvas = FigureCanvas(f) sw.add(self.canvas) sw.set_size_request(200, 200) self.item_add(sw, GtkNodes.NodeSocketIO.DISABLE) self.set_child_packing(sw, True, True, 0, Gtk.PackType.START) self.draw_image() # create local node settings sources = ["face", "ascent"] self.combobox = Gtk.ComboBoxText() self.combobox.set_entry_text_column(0) for src in sources: self.combobox.append_text(src) self.combobox.set_active(0) self.combobox.connect("changed", self.change_image) # internal node items are type DISABLE self.item_add(self.combobox, GtkNodes.NodeSocketIO.DISABLE) # create node output socket lbl = Gtk.Label.new("Image") lbl.set_xalign(1.0) self.node_socket_output = self.item_add(lbl, GtkNodes.NodeSocketIO.SOURCE) self.node_socket_output.connect("socket_connect", self.node_socket_connect) # the compatibility key self.node_socket_output.set_key(1234) self.node_socket_output.set_rgba(get_rgba('darkturquoise')) def draw_image(self): self.a.imshow(self.img) self.canvas.draw() def change_image(self, combobox): src = self.combobox.get_active_text() if src == "face": self.img = misc.face() elif src == "ascent": self.img = misc.ascent() self.draw_image() self.node_socket_output.write(pickle.dumps(self.img)) def node_socket_connect(self, sink, source): self.node_socket_output.write(pickle.dumps(self.img)) def remove(self, node): self.destroy()
class GraphView(): """Class for displaying graph""" def __init__(self, box, xlim, ylim, title='', xlabel='', ylabel='', inactivate=False): self.box = box self.xlim = xlim self.ylim = ylim self.title = title self.xlabel = xlabel self.ylabel = ylabel self.inactivate = inactivate self.models = [] self.model = None self.colors = ('r', 'b', 'g', 'c', 'm', 'y', 'k', 'w') self.signal1_id = None self.signal2_id = None self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.hbox_int = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.scrolled_window = Gtk.ScrolledWindow() self.figure = Figure(figsize=(1, 1)) self.canvas = FigureCanvas(self.figure) # a Gtk.DrawingArea self.box.set_size_request(100, 300) self.name_widget = Gtk.Label('<i>' + self.title + '</i>', xalign=0.5) self.name_widget.set_use_markup(True) self.name_widget.props.margin_top = 6 self.name_widget.props.margin_bottom = 6 self.xlabel_widget = Gtk.Label('<i>' + self.xlabel + '</i>', xalign=0.5) self.xlabel_widget.set_use_markup(True) self.ylabel_widget = Gtk.Label('<i>' + self.ylabel + '</i>', xalign=0.5) self.ylabel_widget.set_use_markup(True) self.ylabel_widget.set_angle(90) self.box.pack_start(self.vbox, True, True, 0) if title: self.vbox.pack_start(self.name_widget, False, False, 0) if ylabel: self.hbox_int.pack_start(self.ylabel_widget, False, False, 0) self.hbox_int.pack_start(self.scrolled_window, True, True, 0) self.vbox.pack_start(self.hbox_int, True, True, 0) if xlabel: self.vbox.pack_start(self.xlabel_widget, False, False, 0) self.scrolled_window.add(self.canvas) self.plot = self.figure.add_subplot(111) self.plot_curves() # Functions def add_plot(self, graph_model): self.models.append(GraphModel(graph_model)) if len(self.models) == 1: self.model = self.models[0] self.plot_curves() def add_plots(self, graph_models): for model in graph_models: self.add_plot(model) def clear_plots(self): self.models.clear() self.model = None def set_active_model(self, index): if index < len(self.models): self.model = self.models[index] def cycle_active_graph(self): index = self.models.index(self.model) if index < len(self.models) - 1: self.model = self.models[index + 1] else: self.model = self.models[0] def plot_curves(self): if self.inactivate == False: self.signal1_id = self.box.connect('button_press_event', self.on_click_box) self.signal2_id = self.canvas.mpl_connect('button_press_event', self.on_click) else: if self.signal1_id: self.box.disconnect(self.signal1_id) self.signal1_id = None if self.signal2_id: self.canvas.mpl_disconnect(self.signal2_id) self.signal2_id = None self.plot.clear() for tick in self.plot.get_xticklabels(): tick.set_fontname(misc.GRAPH_FONT_FACE) tick.set_fontsize(misc.GRAPH_FONT_SIZE) for tick in self.plot.get_yticklabels(): tick.set_fontname(misc.GRAPH_FONT_FACE) tick.set_fontsize(misc.GRAPH_FONT_SIZE) self.plot.set_xlim(self.xlim[0], self.xlim[1]) if len(self.xlim) == 4 and self.xlim[3] == 'log': self.plot.set_xscale('log') self.plot.set_ylim(self.ylim[0], self.ylim[1]) self.plot.grid(True, which='major') self.plot.minorticks_on() self.plot.grid(True, which='minor', alpha=0.2) for slno, model in enumerate(self.models): color = self.colors[slno % len(self.colors)] self.plot.plot(model.xval, model.yval, marker="o", color=color) self.canvas.draw() # Callbacks def on_click_box(self, widget, event): self.canvas.grab_focus() def on_click(self, event): if self.model and event.xdata and event.ydata: x = round(event.xdata / self.xlim[2], 0) * self.xlim[2] y = round(event.ydata / self.ylim[2], 0) * self.ylim[2] if event.button == MouseButtons.LEFT_BUTTON: self.model.add_point(x, y) elif event.button == MouseButtons.MIDDLE_BUTTON: self.cycle_active_graph() else: self.model.remove_point(x, y) self.plot_curves()
class GraphsView(View['GraphsPresenter', Gtk.Widget]): def _do_init(self) -> Gtk.Widget: self._widget = Gtk.Stack(margin=5) self._waiting_placeholder = Gtk.Label() self._waiting_placeholder.set_markup('<b>No data</b>') self._widget.add(self._waiting_placeholder) figure = Figure(tight_layout=True) self._figure_canvas = FigureCanvas(figure) self._figure_canvas.props.hexpand = True self._figure_canvas.props.vexpand = True self._widget.add(self._figure_canvas) self._ift_axes = figure.add_subplot(3, 1, 1) self._ift_axes.set_ylabel('IFT (mN/m)') volume_axes = figure.add_subplot(3, 1, 2, sharex=self._ift_axes) volume_axes.xaxis.set_ticks_position('both') volume_axes.set_ylabel('Vol. (mm³)') surface_area_axes = figure.add_subplot(3, 1, 3, sharex=self._ift_axes) surface_area_axes.xaxis.set_ticks_position('both') surface_area_axes.set_ylabel('Sur. (mm²)') # Format the labels to scale to the right units. self._ift_axes.get_yaxis().set_major_formatter( ticker.FuncFormatter(lambda x, pos: '{:.4g}'.format(x * 1e3))) volume_axes.get_yaxis().set_major_formatter( ticker.FuncFormatter(lambda x, pos: '{:.4g}'.format(x * 1e9))) surface_area_axes.get_yaxis().set_major_formatter( ticker.FuncFormatter(lambda x, pos: '{:.4g}'.format(x * 1e6))) for lbl in (*self._ift_axes.get_xticklabels(), *volume_axes.get_xticklabels()): lbl.set_visible(False) self._ift_line = self._ift_axes.plot([], marker='o', color='red')[0] self._volume_line = volume_axes.plot([], marker='o', color='blue')[0] self._surface_area_line = surface_area_axes.plot([], marker='o', color='green')[0] self._widget.show_all() self.presenter.view_ready() return self._widget def show_waiting_placeholder(self) -> None: self._widget.set_visible_child(self._waiting_placeholder) def hide_waiting_placeholder(self) -> None: self._widget.set_visible_child(self._figure_canvas) def set_ift_data(self, data: Sequence[Tuple[float, float]]) -> None: if len(data[0]) <= 1: return self._ift_line.set_data(data) self._update_xlim() self._ift_axes.relim() self._ift_axes.margins(y=0.1) self._figure_canvas.draw() def set_volume_data(self, data: Sequence[Tuple[float, float]]) -> None: if len(data[0]) <= 1: return self._volume_line.set_data(data) self._update_xlim() self._volume_line.axes.relim() self._volume_line.axes.margins(y=0.1) self._figure_canvas.draw() def set_surface_area_data(self, data: Sequence[Tuple[float, float]]) -> None: if len(data[0]) <= 1: return self._surface_area_line.set_data(data) self._update_xlim() self._surface_area_line.axes.relim() self._surface_area_line.axes.margins(y=0.1) self._figure_canvas.draw() def _update_xlim(self) -> None: all_xdata = ( *self._ift_line.get_xdata(), *self._volume_line.get_xdata(), *self._surface_area_line.get_xdata(), ) if len(all_xdata) <= 1: return xmin = min(all_xdata) xmax = max(all_xdata) if xmin == xmax: return self._ift_axes.set_xlim(xmin, xmax) def _do_destroy(self) -> None: self._widget.destroy()
class EditFanProfileView(EditFanProfileViewInterface): @inject def __init__(self, presenter: EditFanProfilePresenter, builder: EditFanProfileBuilder, ) -> None: LOG.debug('init EditFanProfileView') self._presenter: EditFanProfilePresenter = presenter self._presenter.view = self self._builder: Gtk.Builder = builder self._builder.connect_signals(self._presenter) self._init_widgets() def _init_widgets(self) -> None: self._dialog: Gtk.Dialog = self._builder.get_object('dialog') self._delete_profile_button: Gtk.Button = self._builder \ .get_object('delete_profile_button') self._profile_name_entry: Gtk.Entry = self._builder \ .get_object('profile_name_entry') self._liststore: Gtk.ListStore = self._builder.get_object('liststore') self._temperature_adjustment: Gtk.Adjustment = self._builder \ .get_object('temperature_adjustment') self._duty_adjustment: Gtk.Adjustment = self._builder \ .get_object('duty_adjustment') self._temperature_scale: Gtk.Scale = self._builder \ .get_object('temperature_scale') self._duty_scale: Gtk.Scale = self._builder \ .get_object('duty_scale') self._controls_grid: Gtk.Grid = self._builder.get_object('controls_grid') self._treeselection: Gtk.TreeSelection = self._builder.get_object('treeselection') self._treeview: Gtk.TreeView = self._builder.get_object('treeview') self._add_step_button: Gtk.Button = self._builder.get_object('add_step_button') self._save_step_button: Gtk.Button = self._builder \ .get_object('save_step_button') self._delete_step_button: Gtk.Button = self._builder \ .get_object('delete_step_button') self._init_plot_charts() def set_transient_for(self, window: Gtk.Window) -> None: self._dialog.set_transient_for(window) # pylint: disable=attribute-defined-outside-init def _init_plot_charts(self, ) -> None: self._chart_figure = Figure(figsize=(8, 6), dpi=72, facecolor='#00000000') self._chart_canvas = FigureCanvas(self._chart_figure) # a Gtk.DrawingArea+ self._chart_axis = self._chart_figure.add_subplot(111) self._chart_line, = init_plot_chart( self._builder.get_object('scrolled_window'), self._chart_figure, self._chart_canvas, self._chart_axis ) def _plot_chart(self, data: Dict[int, int]) -> None: sorted_data = OrderedDict(sorted(data.items())) temperature = list(sorted_data.keys()) duty = list(sorted_data.values()) self._chart_line.set_xdata(temperature) self._chart_line.set_ydata(duty) self._chart_canvas.draw() self._chart_canvas.flush_events() def show(self, profile: FanProfile) -> None: self._treeselection.unselect_all() self._profile_name_entry.set_text(profile.name) self.refresh_liststore(profile) self.refresh_controls() self._dialog.show_all() def hide(self) -> None: self._dialog.hide() def get_profile_name(self) -> str: return str(self._profile_name_entry.get_text()) def get_temperature(self) -> int: return int(self._temperature_adjustment.get_value()) def get_duty(self) -> int: return int(self._duty_adjustment.get_value()) def has_a_step_selected(self) -> bool: return self._treeselection.get_selected()[1] is not None def refresh_liststore(self, profile: FanProfile) -> None: self._liststore.clear() for step in profile.steps: self._liststore.append([step.id, step.temperature, step.duty]) if profile.steps: if profile.steps[-1].temperature == MAX_TEMP or profile.steps[-1].duty == FAN_MAX_DUTY: self._add_step_button.set_sensitive(False) else: self._add_step_button.set_sensitive(True) else: self._add_step_button.set_sensitive(True) self._plot_chart(get_fan_profile_data(profile)) def refresh_controls(self, step: Optional[SpeedStep] = None, unselect_list: bool = False) -> None: if unselect_list: self._treeselection.unselect_all() if step is None: self._controls_grid.set_sensitive(False) else: prev_steps = (SpeedStep .select() .where(SpeedStep.profile == step.profile, SpeedStep.temperature < step.temperature) .order_by(SpeedStep.temperature.desc()) .limit(1)) next_steps = (SpeedStep .select() .where(SpeedStep.profile == step.profile, SpeedStep.temperature > step.temperature) .order_by(SpeedStep.temperature) .limit(1)) if not prev_steps: self._temperature_adjustment.set_lower(MIN_TEMP) self._duty_adjustment.set_lower(FAN_MIN_DUTY) else: LOG.debug(f"prev = {prev_steps[0].temperature}") self._temperature_adjustment.set_lower(prev_steps[0].temperature + 1) self._duty_adjustment.set_lower(prev_steps[0].duty) if not next_steps: self._temperature_adjustment.set_upper(MAX_TEMP) self._duty_adjustment.set_upper(FAN_MAX_DUTY) else: self._temperature_adjustment.set_upper(next_steps[0].temperature - 1) self._duty_adjustment.set_upper(next_steps[0].duty) self._controls_grid.set_sensitive(True) self._temperature_scale.clear_marks() self._temperature_scale.add_mark(step.temperature, Gtk.PositionType.BOTTOM) self._temperature_adjustment.set_value(step.temperature) self._duty_scale.clear_marks() self._duty_scale.add_mark(step.duty, Gtk.PositionType.BOTTOM) self._duty_adjustment.set_value(step.duty)
class plotwidget(object): def __init__(self, data_queue): self.plottype = 'normal' self.fig = Figure(figsize=(5, 5), dpi=100) self.ax = self.fig.add_subplot(111, aspect='equal') self.ax.set_xlabel('X', size=12) self.ax.set_ylabel('Y', size=12) #self.ax.yaxis.set_label_coords() self.fig.subplots_adjust(left=0.15, top=0.85) self.ax.axis([0, 255, 0, 255]) self.x_vals = np.empty(0, np.uint16) self.y_vals = np.empty(0, np.uint16) self.t_vals = np.empty(0, np.uint16) self.intensity = np.empty(0, np.uint16) self.length = np.empty(0, np.uint16) self.i = 0 self.occupancy_array = np.array([[0, 0, 0]]) self.occ_length = [] self.j = 0 self.old_elements = np.array([[0, 0]]) self.occupancy = [] self.integration_length = 500 self.color_depth = 10 cmap = self.fading_colormap(5) self.data_queue = data_queue self.scatter = self.ax.scatter(self.x_vals, self.y_vals, c=[], s=1, marker='s', cmap=cmap, vmin=0, vmax=1) self.canvas = FigureCanvas(self.fig) self.canvas.set_size_request(500, 500) self.ax.plot() def fading_colormap(self, steps=5): # This creates a fading colormap of 'steps' steps. Each step is more transparent, # so if plotted correctly the data appers to be fading out. if steps <= 0: self.colorsteps = 1 print( 'ERROR: Minimum number of colorsteps is 1. Colorsteps have been set to 1.' ) else: self.colorsteps = steps i = 1 viridis = cm.get_cmap('viridis', 256) newcmap = viridis(np.linspace(0, 1, 256)) newmap1 = np.tile(newcmap, (self.colorsteps, 1)) while (i < self.colorsteps): newmap1[(i - 1) * 256:(i * 256), -1] = np.linspace(i * 1 / self.colorsteps, i * 1 / self.colorsteps, 256) i = i + 1 cmap = ListedColormap(newmap1) return cmap def get_new_vals(self): #Get values from Chip #t need to between 0 and 1 then the calculation 1 - (t / self.colorsteps) needs #to be done in order to distribute is correctly over the colormap x = np.empty(0, np.uint16) y = np.empty(0, np.uint16) t = np.empty(0, np.uint16) if not self.data_queue.empty(): x_new, y_new, t_new = self.data_queue.get() x = np.append(x, x_new) y = np.append(y, y_new) t = np.append(t, t_new) if len(t) > 0: self.t_vals = np.append(self.t_vals, t) max_value = np.amax( self.t_vals) # This has to be changed to a more general way t = t / max_value return x, y, t def update_plot(self): #Plot the fading plot with new data. new_xvals, new_yvals, new_tvals = self.get_new_vals() self.x_vals = np.append(self.x_vals, new_xvals) self.y_vals = np.append(self.y_vals, new_yvals) self.length = np.append(self.length, new_xvals.size) #Cut plotting arrays to n_colorsteps Timeblocks if self.i < (self.colorsteps): self.i = self.i + 1 elif self.i == (self.colorsteps): number = np.arange(self.length[0]) self.length = np.delete(self.length, 0) self.x_vals = np.delete(self.x_vals, number) self.y_vals = np.delete(self.y_vals, number) self.t_vals = np.delete(self.t_vals, number) self.intensity = np.delete(self.intensity, number) elif self.i > (self.colorsteps): while self.i >= (self.colorsteps): number = np.arange(self.length[0]) self.length = np.delete(self.length, 0) self.x_vals = np.delete(self.x_vals, number) self.y_vals = np.delete(self.y_vals, number) self.t_vals = np.delete(self.t_vals, number) self.intensity = np.delete(self.intensity, number) self.i = self.i - 1 #Add to plot and change intensity self.scatter.set_offsets(np.c_[self.x_vals, self.y_vals]) self.intensity = np.concatenate( (np.array(self.intensity) - (1 / self.colorsteps), new_tvals)) self.scatter.set_array(self.intensity) self.canvas.draw() return True def update_occupancy_plot(self): new_xvals, new_yvals, new_tvals = self.get_new_vals() new_elements = np.c_[new_xvals, new_yvals] self.occ_length.append(new_elements.shape[0]) self.old_elements = np.append(self.old_elements, new_elements, axis=0) #count hited pixel for new_element in new_elements: pos = np.argwhere( np.all(self.occupancy_array[:, :2] == new_element, axis=1) == True) if pos.size == 0: # add new element self.occupancy_array = np.append(self.occupancy_array, [np.append(new_element, 1)], axis=0) elif pos.size == 1: #increment element at pos x = pos[0, 0] self.occupancy_array[pos[0, 0], 2] = (self.occupancy_array[pos[0, 0], 2] + 1) else: print('Error') #remove hitted pixel if self.j <= (self.integration_length): self.j = self.j + 1 elif self.j == (self.integration_length + 1): number = self.occ_length[0] self.occ_length.pop(0) k = 0 while k < number: k = k + 1 pos = np.argwhere( np.all(self.occupancy_array[:, :2] == self.old_elements[1], axis=1) == True) self.old_elements = np.delete(self.old_elements, 1, axis=0) if self.occupancy_array[pos[0, 0], 2] == 1: #Remove item if no count left self.occupancy_array = np.delete(self.occupancy_array, pos[0, 0], axis=0) elif self.occupancy_array[pos[0, 0], 2] > 1: #decrement element at pos self.occupancy_array[pos[0, 0], 2] = ( self.occupancy_array[pos[0, 0], 2] - 1) else: print('Error') elif self.j > (self.integration_length + 1): while self.j > (self.integration_length + 1): number = self.occ_length[0] self.occ_length.pop(0) k = 0 while k < number: k = k + 1 pos = np.argwhere( np.all(self.occupancy_array[:, :2] == self.old_elements[1], axis=1) == True) self.old_elements = np.delete(self.old_elements, 1, axis=0) if self.occupancy_array[pos[0, 0], 2] == 1: #Remove item if no count left self.occupancy_array = np.delete(self.occupancy_array, pos[0, 0], axis=0) elif self.occupancy_array[pos[0, 0], 2] > 1: #Decrement element at pos self.occupancy_array[pos[0, 0], 2] = ( self.occupancy_array[pos[0, 0], 2] - 1) else: print('Error') self.j = self.j - 1 self.scatter.set_offsets(self.occupancy_array[:, :2]) self.occupancy = self.occupancy_array[:, 2:] self.scatter.set_array(np.squeeze(self.occupancy)) self.canvas.draw() return True def reset_occupancy(self): self.occupancy_array = np.array([[0, 0, 0]]) self.occ_length = [] self.j = 0 self.old_elements = np.array([[0, 0]]) self.occupancy = [] return True def change_colormap(self, colormap, vmin=0, vmax=1): x_vals = [] y_vals = [] cmap = colormap vmin = vmin vmax = vmax if self.plottype == 'occupancy': self.color_depth = vmax self.ax.remove() self.ax = self.fig.add_subplot(111, aspect='equal') self.ax.set_xlabel('X', size=12) self.ax.set_ylabel('Y', size=12) self.ax.axis([0, 255, 0, 255]) self.scatter = self.ax.scatter(x_vals, y_vals, c=[], s=1, marker='s', cmap=cmap, vmin=vmin, vmax=vmax) self.ax.plot() return True def get_iteration_depth(self, function='normal'): function = function if function == 'normal': return self.colorsteps elif function == 'occupancy': return self.integration_length elif function == 'occupancy.color': return self.color_depth else: print( 'Unknown argument. Use "normal", "occupancy" or "occupancy.color' ) return False def get_plottype(self): return self.plottype def set_plottype(self, plottype): self.plottype = plottype return True def set_occupancy_length(self, length): self.integration_length = length return True def set_color_depth(self, color_depth): self.color_depth = color_depth return True def set_color_steps(self, color_steps): self.colorsteps = color_steps return True
class myInterface(): def __init__(self, port, baud): print("Welcome to the MakeMeFly interface :D\nEnjoy your trip!") self.port=port self.baud=baud self.s=Serial(self.port, self.baud, timeout=0.5) self.inhibited=False; self.dataLock=Lock() self.printDataLock=Lock() self.bufLock=Lock() self.serialLock=Lock() self.saveStuffLock=Lock() self.buf=[] self.builder=Gtk.Builder() self.builder.add_from_file('Plotter_IF.glade') self.builder.connect_signals(self) self.squareWave=[] self.outputUp=[] self.outputDown=[] self.sw=0 self.co=0 self.ou=0 self.od=0 self.gb=0 self.gp=0 self.ur=0 self.dr=0 self.bM=0 self.bm=0 self.l=[] self.gainBase=[] self.gainPos=[] self.upRate=[] self.downRate=[] self.BMax=0 self.BMin=0 self.level=[] self.nData=1000 self.BData=deque(maxlen=1000) self.filteredValueData=deque(maxlen=1000) self.coilBData=deque(maxlen=1000) self.BData.append(0) self.filteredValueData.append(0) self.coilBData.append(0) self.XData=[0.0004*x for x in range(0,1000)] self.window=self.builder.get_object("mainWindow") self.builder.get_object("sqWaveImage").set_from_stock("gtk-no", Gtk.IconSize.BUTTON) #Start of Matplotlib specific code ########################################################################## self.figure = Figure(figsize=(8,6), dpi=71) self.axisB = self.figure.add_subplot(311) self.axisB.set_xlabel('Time (ticks)') self.axisB.set_ylabel('Measured magnetic field') self.axisBC = self.figure.add_subplot(313) self.axisBC.set_xlabel('Time (ticks)') self.axisBC.set_ylabel('Emulated magnetic field') self.axisFV = self.figure.add_subplot(312) self.axisFV.set_xlabel('Time (ticks)') self.axisFV.set_ylabel('Filtered magnetic field') self.plotCanvas = PlotCanvas(self.figure) # a Gtk.DrawingArea self.plotCanvas.set_size_request(500,600) a=[0] self.plotB=self.axisB.plot(a)[0] self.plotBC=self.axisBC.plot(a)[0] self.plotFV=self.axisFV.plot(a)[0] self.plotCanvas.draw() self.builder.get_object("plotGrid").attach(self.plotCanvas, 0,2,1,1) self.window.show_all() self.window.connect("destroy", Gtk.main_quit) self.newBytes=Condition() self.recvThread=Thread(target=self.recvBytes) self.recvThread.start() self.consumeDataThread=Thread(target=self.consumeData) self.consumeDataThread.start() def getNext(self, requested): while(len(self.buf)<requested): self.newBytes.acquire() self.newBytes.wait() self.newBytes.release() self.bufLock.acquire() values=self.buf[:requested] self.buf=self.buf[requested:] self.bufLock.release() return values def updateIF(self, a,b): self.dataLock.acquire() sw=self.sw ou=self.ou od=self.od co=self.co gb=self.gb gp=self.gp ur=self.ur dr=self.dr bmax=self.bM bmin=self.bm l=self.l self.dataLock.release() if(gb!=self.gainBase): self.gainBase=gb self.builder.get_object("gainBaseLabel").set_label("Base power: "+str(self.gainBase)) if(gp!=self.gainPos): self.gainPos=gp self.builder.get_object("gainPosLabel").set_label("Position gain: "+str(self.gainPos)) if(ur!=self.upRate): self.upRate=ur self.builder.get_object("upRateLabel").set_label("Charging step: "+str(self.upRate)) if(bmax!=self.BMax): self.BMax=bmax self.builder.get_object("BMaxLabel").set_label("ON field: "+str(self.BMax)) if(bmin!=self.BMin): self.BMin=bmin self.builder.get_object("BMinLabel").set_label("Base field: "+str(self.BMin)) if(dr!=self.downRate): self.downRate=dr self.builder.get_object("downRateLabel").set_label("Discharging step: "+str(self.downRate)) if(l!=self.level): self.level=l self.builder.get_object("levelLabel").set_label("Level: "+str(self.level)) if(sw!=self.squareWave): self.squareWave=sw if(sw): self.builder.get_object("sqWaveImage").set_from_stock("gtk-yes", Gtk.IconSize.BUTTON) self.builder.get_object("sqWaveLabel").set_label("SquareWave: ON") else: self.builder.get_object("sqWaveImage").set_from_stock("gtk-no", Gtk.IconSize.BUTTON) self.builder.get_object("sqWaveLabel").set_label("SquareWave: OFF") if(ou!=self.outputUp): self.outputUp=ou if(ou): self.builder.get_object("outputUpImage").set_from_stock("gtk-yes", Gtk.IconSize.BUTTON) self.builder.get_object("outputUpLabel").set_label("Output up: ON") else: self.builder.get_object("outputUpImage").set_from_stock("gtk-no", Gtk.IconSize.BUTTON) self.builder.get_object("outputUpLabel").set_label("Output up: OFF") if(od!=self.outputDown): self.outputDown=od if(od): self.builder.get_object("outputDownImage").set_from_stock("gtk-yes", Gtk.IconSize.BUTTON) self.builder.get_object("outputDownLabel").set_label("Output down: ON") else: self.builder.get_object("outputDownImage").set_from_stock("gtk-no", Gtk.IconSize.BUTTON) self.builder.get_object("outputDownLabel").set_label("Output down: OFF") if(od!=self.outputDown): self.outputDown=od if(od): self.builder.get_object("outputDownImage").set_from_stock("gtk-yes", Gtk.IconSize.BUTTON) self.builder.get_object("outputDownLabel").set_label("Output down: ON") else: self.builder.get_object("outputDownImage").set_from_stock("gtk-no", Gtk.IconSize.BUTTON) self.builder.get_object("outputDownLabel").set_label("Output down: OFF") self.printDataLock.acquire() #Note for the reader: #While I was writing this code, a thief came into my house and tried stealing my car; I bravely run to him shouting and made him run away. Don't expect this code to be clean anymore. # (True story!) self.axisB.set_xbound(lower=0,upper=len(self.BData)) self.axisB.set_ybound(lower=min(self.BData), upper=len(self.BData)) self.plotB.set_xdata(np.arange(len(self.BData))) self.plotB.set_ydata(np.array(self.BData)) #self.plotB.set_xdata(self.XData[:n]) #self.plotB.set_ydata(self.BData) self.axisBC.set_xbound(lower=0,upper=len(self.coilBData)) self.axisBC.set_ybound(lower=min(self.coilBData), upper=len(self.coilBData)) self.plotBC.set_xdata(np.arange(len(self.coilBData))) self.plotBC.set_ydata(np.array(self.coilBData)) self.axisFV.set_xbound(lower=0,upper=len(self.filteredValueData)) self.axisFV.set_ybound(lower=min(self.filteredValueData), upper=len(self.filteredValueData)) self.plotFV.set_xdata(np.arange(len(self.filteredValueData))) self.plotFV.set_ydata(np.array(self.filteredValueData)) self.plotCanvas.draw() self.printDataLock.release() def consumeData(self): while(not self.inhibited): #Waits for sync while(True): if(self.getNext(1)==[0x4C]): if(self.getNext(1)==[0x56]): if(self.getNext(1)==[0x54]): break data=self.getNext(14) self.dataLock.acquire() self.l=int(data[0])*16; self.gp=float(data[2]*256+data[1]+(-65536 if data[2] & 0x80 else 0))/10000.0 self.gb=float(data[4]*256+data[3]+(-65536 if data[4] & 0x80 else 0))/1000.0+1 self.ur=float(data[6]*256+data[5]+(-65536 if data[6] & 0x80 else 0))/10000.0 self.dr=float(data[8]*256+data[7]+(-65536 if data[8] & 0x80 else 0))/10000.0 self.bM=(data[10]*256+data[9]) self.bm=(data[12]*256+data[11]) state=data[13] self.sw=state & 0x01 self.ou=state & 0x02 self.od=state & 0x04 self.co=state & 0x08 self.dataLock.release() if((self.ou and self.co) or (self.od and not self.co)): values=self.getNext(6) filteredValue=float(values[1]*256+data[0]+(-65536 if data[1] & 0x80 else 0))/256.0 coilB=float(values[3]*256+data[2]+(-65536 if data[1] & 0x80 else 0))/256.0 B=float(values[5]*256+data[4]+(-65536 if data[1] & 0x80 else 0))/256.0 #print(str(filteredValue)+" "+str(coilB)+" "+str(B)) self.printDataLock.acquire() self.BData.append(B) self.coilBData.append(coilB) self.filteredValueData.append(filteredValue) self.printDataLock.release() def recvBytes(self): self.s.flushInput() a=[x for x in range(256)] while(True): n=self.s.readinto(a) self.bufLock.acquire() self.buf.extend(a[:n]) if(len(self.buf)>1000): self.buf=self.buf[-500:] self.bufLock.release() self.newBytes.acquire() self.newBytes.notify() self.newBytes.release() def updateNData(self,a): value=int(self.builder.get_object("nDataInput").get_text()) print("New data: " + str(value)) if(value>65536 or value<0): print("Invalid value") else: if(value!=self.nData): self.nData=value self.printDataLock.acquire() bd=self.BData fd=self.filteredValueData cbd=self.coilBData self.XData=[0.0004*x for x in range(0,value)] self.axisB.set_xbound(lower=self.XData[0], upper=self.XData[-1]) self.BData=deque(maxlen=value) self.BData.extend(bd) self.filteredValueData=deque(maxlen=value) self.filteredValueData.extend(fd) self.coilBData=deque(maxlen=value) self.coilBData.extend(cbd) self.printDataLock.release() def changeSquareWave(self,a): print("SquareWave change") self.serialLock.acquire() self.s.write([ord('s') ,0x0A,0x0D]) self.s.flush() self.serialLock.release() def changeOutputUp(self,a): print("Change output up") self.serialLock.acquire() self.s.write([ord('O'),0x0A,0x0D]) self.s.flush() self.serialLock.release() def changeOutputDown(self,a): print("Change output down") self.serialLock.acquire() self.s.write([ord('o') ,0x0A,0x0D]) self.s.flush() self.serialLock.release() def gainBaseUp(self,a): print("Gain base up") self.serialLock.acquire() self.s.write([ord('P') ,0x0A,0x0D]) self.s.flush() self.serialLock.release() def gainBaseDown(self,a): print("Gain base down") self.serialLock.acquire() self.s.write([ord('p') ,0x0A,0x0D]) self.s.flush() self.serialLock.release() def gainPosUp(self,a): print("Gain pos up") self.serialLock.acquire() self.s.write([ord('G') ,0x0A,0x0D]) self.s.flush() self.serialLock.release() def gainPosDown(self,a): print("Gain pos down") self.serialLock.acquire() self.s.write([ord('g') ,0x0A,0x0D]) self.s.flush() self.serialLock.release() def upRateUp(self,a): print("Up rate up") self.serialLock.acquire() self.s.write([ord('U') ,0x0A,0x0D]) self.s.flush() self.serialLock.release() def upRateDown(self,a): print("Up rate down") self.serialLock.acquire() self.s.write([ord('u') ,0x0A,0x0D]) self.s.flush() self.serialLock.release() def downRateUp(self,a): print("Down rate up") self.serialLock.acquire() self.s.write([ord('D') ,0x0A,0x0D]) self.s.flush() self.serialLock.release() def downRateDown(self,a): print("Down rate down") self.serialLock.acquire() self.s.write([ord('d') ,0x0A,0x0D]) self.s.flush() self.serialLock.release() def saveStuff(self,a): print("Saving data to FLASH memory") self.inhibited=True self.saveStuffLock.acquire() self.serialLock.acquire() self.s.write([ord('W') ,0x0A,0x0D]) while(True): if(self.getNext(1)==[ord('A')]): if(self.getNext(1)==[ord('C')]): if(self.getNext(1)==[ord('K')]): break print("Success!") self.inhibited=False self.serialLock.release() self.saveStuffLock.release()
class MainView(MainViewInterface): @inject def __init__( self, presenter: MainPresenter, edit_fan_profile_view: EditFanProfileView, edit_overclock_profile_view: EditOverclockProfileView, historical_data_view: HistoricalDataView, preferences_view: PreferencesView, builder: MainBuilder, settings_interactor: SettingsInteractor, ) -> None: LOG.debug('init MainView') self._presenter: MainPresenter = presenter self._edit_fan_profile_view = edit_fan_profile_view self._edit_overclock_profile_view = edit_overclock_profile_view self._historical_data_view = historical_data_view self._preferences_view = preferences_view self._presenter.main_view = self self._builder: Gtk.Builder = builder self._settings_interactor = settings_interactor self._first_refresh = True self._init_widgets() def _init_widgets(self) -> None: self._app_indicator: Optional[AppIndicator3.Indicator] = None self._window = self._builder.get_object("application_window") self._edit_fan_profile_view.set_transient_for(self._window) self._edit_overclock_profile_view.set_transient_for(self._window) self._historical_data_view.set_transient_for(self._window) self._preferences_view.set_transient_for(self._window) self._main_menu: Gtk.Menu = self._builder.get_object("main_menu") self._main_infobar: Gtk.InfoBar = self._builder.get_object( "main_infobar") self._main_infobar.connect("response", lambda b, _: b.set_revealed(False)) self._main_infobar_label: Gtk.Label = self._builder.get_object( "main_infobar_label") self._main_infobar.set_revealed(False) self._statusbar: Gtk.Statusbar = self._builder.get_object('statusbar') self._context = self._statusbar.get_context_id(APP_PACKAGE_NAME) self._app_version: Gtk.Label = self._builder.get_object('app_version') self._app_version.set_label(f"{APP_NAME} v{APP_VERSION}") self._about_dialog: Gtk.AboutDialog = self._builder.get_object( "about_dialog") self._init_about_dialog() self._info_name_entry: Gtk.Entry = self._builder.get_object( 'info_name_entry') self._info_vbios_entry: Gtk.Entry = self._builder.get_object( 'info_vbios_entry') self._info_driver_entry: Gtk.Entry = self._builder.get_object( 'info_driver_entry') self._info_pcie_entry: Gtk.Entry = self._builder.get_object( 'info_pcie_entry') self._info_cuda_entry: Gtk.Entry = self._builder.get_object( 'info_cuda_entry') self._info_uuid_entry: Gtk.Entry = self._builder.get_object( 'info_uuid_entry') self._info_memory_entry: Gtk.Entry = self._builder.get_object( 'info_memory_entry') self._info_memory_interface_entry: Gtk.Entry = self._builder.get_object( 'info_memory_interface_entry') self._info_memory_usage_entry: Gtk.Entry = self._builder.get_object( 'info_memory_usage_entry') self._info_gpu_usage_entry: Gtk.Entry = self._builder.get_object( 'info_gpu_usage_entry') self._info_encoder_usage_entry: Gtk.Entry = self._builder.get_object( 'info_encoder_usage_entry') self._info_decoder_usage_entry: Gtk.Entry = self._builder.get_object( 'info_decoder_usage_entry') self._power_draw_entry: Gtk.Entry = self._builder.get_object( 'power_draw_entry') self._power_limit_entry: Gtk.Entry = self._builder.get_object( 'power_limit_entry') self._power_default_entry: Gtk.Entry = self._builder.get_object( 'power_default_entry') self._power_min_entry: Gtk.Entry = self._builder.get_object( 'power_min_entry') self._power_enforced_entry: Gtk.Entry = self._builder.get_object( 'power_enforced_entry') self._power_max_entry: Gtk.Entry = self._builder.get_object( 'power_max_entry') self._clocks_graphics_current_entry: Gtk.Entry = self._builder.get_object( 'clocks_graphics_current_entry') self._clocks_graphics_max_entry: Gtk.Entry = self._builder.get_object( 'clocks_graphics_max_entry') self._clocks_sm_current_entry: Gtk.Entry = self._builder.get_object( 'clocks_sm_current_entry') self._clocks_sm_max_entry: Gtk.Entry = self._builder.get_object( 'clocks_sm_max_entry') self._clocks_memory_current_entry: Gtk.Entry = self._builder.get_object( 'clocks_memory_current_entry') self._clocks_memory_max_entry: Gtk.Entry = self._builder.get_object( 'clocks_memory_max_entry') self._clocks_video_current_entry: Gtk.Entry = self._builder.get_object( 'clocks_video_current_entry') self._clocks_video_max_entry: Gtk.Entry = self._builder.get_object( 'clocks_video_max_entry') self._overclock_gpu_offset_entry: Gtk.Entry = self._builder.get_object( 'overclock_gpu_offset_entry') self._overclock_mem_offset_entry: Gtk.Entry = self._builder.get_object( 'overclock_mem_offset_entry') self._info_memory_usage_levelbar: Gtk.LevelBar = self._builder.get_object( 'info_memory_usage_levelbar') self._info_gpu_usage_levelbar: Gtk.LevelBar = self._builder.get_object( 'info_gpu_usage_levelbar') self._info_encoder_usage_levelbar: Gtk.LevelBar = self._builder.get_object( 'info_encoder_usage_levelbar') self._info_decoder_usage_levelbar: Gtk.LevelBar = self._builder.get_object( 'info_decoder_usage_levelbar') self._temp_gpu_value: Gtk.Label = self._builder.get_object( 'temp_gpu_value') self._temp_max_gpu_value: Gtk.Label = self._builder.get_object( 'temp_max_gpu_value') self._temp_slowdown_value: Gtk.Label = self._builder.get_object( 'temp_slowdown_value') self._temp_shutdown_value: Gtk.Label = self._builder.get_object( 'temp_shutdown_value') self._fan_duty: Tuple = (self._builder.get_object('fan_duty_0'), self._builder.get_object('fan_duty_1'), self._builder.get_object('fan_duty_2'), self._builder.get_object('fan_duty_3'), self._builder.get_object('fan_duty_4')) self._fan_rpm: Tuple = (self._builder.get_object('fan_rpm_0'), self._builder.get_object('fan_rpm_1'), self._builder.get_object('fan_rpm_2'), self._builder.get_object('fan_rpm_3'), self._builder.get_object('fan_rpm_4')) self._fan_warning_label: Gtk.Label = self._builder.get_object( 'fan_warning_label') self._overclock_warning_label: Gtk.Label = self._builder.get_object( 'overclock_warning_label') self._fan_profile_frame: Gtk.Frame = self._builder.get_object( 'fan_profile_frame') self._overclock_frame: Gtk.Frame = self._builder.get_object( 'overclock_frame') self._power_limit_scale: Gtk.Scale = self._builder.get_object( 'power_limit_scale') self._power_limit_adjustment: Gtk.Adjustment = self._builder.get_object( 'power_limit_adjustment') self._fan_apply_button: Gtk.Button = self._builder.get_object( 'fan_apply_button') self._overclock_apply_button: Gtk.Button = self._builder.get_object( 'overclock_apply_button') self._power_limit_apply_button: Gtk.Button = self._builder.get_object( 'power_limit_apply_button') self._fan_liststore: Gtk.ListStore = self._builder.get_object( 'fan_profile_liststore') self._overclock_liststore: Gtk.ListStore = self._builder.get_object( 'overclock_profile_liststore') self._fan_combobox: Gtk.ComboBox = self._builder.get_object( 'fan_profile_combobox') self._overclock_combobox: Gtk.ComboBox = self._builder.get_object( 'overclock_profile_combobox') fan_scrolled_window: Gtk.ScrolledWindow = self._builder.get_object( 'fan_scrolled_window') self._fan_edit_button: Gtk.Button = self._builder.get_object( 'fan_edit_button') self._overclock_edit_button: Gtk.Button = self._builder.get_object( 'overclock_edit_button') self._init_plot_charts(fan_scrolled_window) if not is_dazzle_version_supported(): self._builder.get_object("historical_data_button").set_sensitive( False) def _init_about_dialog(self) -> None: self._about_dialog.set_program_name(APP_NAME) self._about_dialog.set_version(APP_VERSION) self._about_dialog.set_website(APP_SOURCE_URL) self._about_dialog.connect("delete-event", hide_on_delete) self._about_dialog.connect("response", hide_on_delete) def show(self) -> None: self._presenter.on_start() self._init_app_indicator() def _init_app_indicator(self) -> None: if AppIndicator3: # Setting icon name in new() as '', because new() wants an icon path self._app_indicator = AppIndicator3.Indicator \ .new(APP_ID, '', AppIndicator3.IndicatorCategory.HARDWARE) # Set the actual icon by name. If the app is not installed system-wide, the icon won't show up, # otherwise it will show up correctly. The set_icon_full() function needs a description for accessibility # purposes. I gave it the APP_NAME (should be 'gwe', maybe change it to 'GreenWithEnvy' in the future) self._app_indicator.set_icon_full(APP_ICON_NAME_SYMBOLIC, APP_NAME) if self._settings_interactor.get_bool( 'settings_show_app_indicator'): self._app_indicator.set_status( AppIndicator3.IndicatorStatus.ACTIVE) else: self._app_indicator.set_status( AppIndicator3.IndicatorStatus.PASSIVE) self._app_indicator.set_menu(self._main_menu) def show_main_infobar_message(self, message: str, markup: bool = False) -> None: if markup: self._main_infobar_label.set_markup(message) else: self._main_infobar_label.set_label(message) self._main_infobar.set_revealed(True) def toggle_window_visibility(self) -> None: if self._window.props.visible: self._window.hide() else: self._window.show() def get_power_limit(self) -> Tuple[int, int]: return 0, self._power_limit_adjustment.get_value() def show_about_dialog(self) -> None: self._about_dialog.show() def set_statusbar_text(self, text: str) -> None: self._statusbar.remove_all(self._context) self._statusbar.push(self._context, text) def refresh_status(self, status: Optional[Status], gpu_index: int) -> None: LOG.debug('view status') if status: gpu_status = status.gpu_status_list[gpu_index] if self._first_refresh: self._first_refresh = False self._set_entry_text(self._info_name_entry, gpu_status.info.name) self._set_entry_text(self._info_vbios_entry, gpu_status.info.vbios) self._set_entry_text(self._info_driver_entry, gpu_status.info.driver) self._set_entry_text(self._info_cuda_entry, "{}", gpu_status.info.cuda_cores) self._set_entry_text(self._info_uuid_entry, gpu_status.info.uuid) self._set_entry_text(self._info_memory_interface_entry, "{} bit", gpu_status.info.memory_interface) self._set_entry_text(self._power_min_entry, "{} W", gpu_status.power.minimum) self._set_entry_text(self._power_max_entry, "{} W", gpu_status.power.maximum) self._set_label_markup(self._temp_max_gpu_value, "<span size=\"large\">{}</span> °C", gpu_status.temp.maximum) self._set_label_markup(self._temp_slowdown_value, "<span size=\"large\">{}</span> °C", gpu_status.temp.slowdown) self._set_label_markup(self._temp_shutdown_value, "<span size=\"large\">{}</span> °C", gpu_status.temp.shutdown) self._overclock_frame.set_sensitive( gpu_status.overclock.available) self._overclock_warning_label.set_visible( not gpu_status.overclock.available) self._fan_profile_frame.set_sensitive( gpu_status.fan.control_allowed) self._fan_warning_label.set_visible( not gpu_status.fan.control_allowed) self._remove_level_bar_offsets(self._info_gpu_usage_levelbar) self._remove_level_bar_offsets( self._info_memory_usage_levelbar) self._remove_level_bar_offsets( self._info_encoder_usage_levelbar) self._remove_level_bar_offsets( self._info_decoder_usage_levelbar) minimum = gpu_status.power.minimum maximum = gpu_status.power.maximum default = gpu_status.power.default if minimum is not None and maximum is not None and default is not None and minimum != maximum: limit = gpu_status.power.limit self._power_limit_adjustment.set_lower(minimum) self._power_limit_adjustment.set_upper(maximum) self._power_limit_adjustment.set_value(limit) self._power_limit_scale.clear_marks() self._power_limit_scale.add_mark(default, Gtk.PositionType.BOTTOM, f"{default:.0f}") self._power_limit_scale.set_sensitive(True) self._power_limit_apply_button.set_sensitive(True) else: self._power_limit_scale.set_sensitive(False) self._power_limit_apply_button.set_sensitive(False) self._set_entry_text(self._info_pcie_entry, "{}x Gen{} @ {}x Gen{}", gpu_status.info.pcie_max_link, gpu_status.info.pcie_max_generation, gpu_status.info.pcie_current_link, gpu_status.info.pcie_current_generation) self._set_entry_text(self._info_memory_entry, "{} MiB / {} MiB", gpu_status.info.memory_used, gpu_status.info.memory_total) self._set_entry_text(self._info_memory_usage_entry, "{}%", gpu_status.info.memory_usage) self._set_entry_text(self._info_gpu_usage_entry, "{}%", gpu_status.info.gpu_usage) self._set_entry_text(self._info_encoder_usage_entry, "{}%", gpu_status.info.encoder_usage) self._set_entry_text(self._info_decoder_usage_entry, "{}%", gpu_status.info.decoder_usage) self._set_entry_text(self._power_draw_entry, "{:.2f} W", gpu_status.power.draw) self._set_entry_text(self._power_limit_entry, "{:.0f} W", gpu_status.power.limit) self._set_entry_text(self._power_default_entry, "{:.0f} W", gpu_status.power.default) self._set_entry_text(self._power_enforced_entry, "{:.0f} W", gpu_status.power.enforced) self._set_entry_text(self._clocks_graphics_current_entry, "{} MHz", gpu_status.clocks.graphic_current) self._set_entry_text(self._clocks_graphics_max_entry, "{} MHz", gpu_status.clocks.graphic_max) self._set_entry_text(self._clocks_sm_current_entry, "{} MHz", gpu_status.clocks.sm_current) self._set_entry_text(self._clocks_sm_max_entry, "{} MHz", gpu_status.clocks.sm_max) self._set_entry_text(self._clocks_memory_current_entry, "{} MHz", gpu_status.clocks.memory_current) self._set_entry_text(self._clocks_memory_max_entry, "{} MHz", gpu_status.clocks.memory_max) self._set_entry_text(self._clocks_video_current_entry, "{} MHz", gpu_status.clocks.video_current) self._set_entry_text(self._clocks_video_max_entry, "{} MHz", gpu_status.clocks.video_max) self._set_level_bar(self._info_gpu_usage_levelbar, gpu_status.info.gpu_usage) self._set_level_bar(self._info_memory_usage_levelbar, gpu_status.info.memory_usage) self._set_level_bar(self._info_encoder_usage_levelbar, gpu_status.info.encoder_usage) self._set_level_bar(self._info_decoder_usage_levelbar, gpu_status.info.decoder_usage) if gpu_status.overclock.available: self._set_entry_text(self._overclock_gpu_offset_entry, "{} MHz", gpu_status.overclock.gpu_offset) self._set_entry_text(self._overclock_mem_offset_entry, "{} MHz", gpu_status.overclock.memory_offset) self._set_label_markup(self._temp_gpu_value, "<span size=\"xx-large\">{}</span> °C", gpu_status.temp.gpu) for index, value in enumerate(self._fan_duty): if gpu_status.fan.fan_list and index < len( gpu_status.fan.fan_list): self._set_label_markup(value, "<span size=\"large\">{}</span> %", gpu_status.fan.fan_list[index][0]) self._set_label_markup( self._fan_rpm[index], "<span size=\"large\">{}</span> RPM", gpu_status.fan.fan_list[index][1]) else: value.set_visible(False) self._fan_rpm[index].set_visible(False) if self._app_indicator: if self._settings_interactor.get_bool( 'settings_show_app_indicator'): self._app_indicator.set_status( AppIndicator3.IndicatorStatus.ACTIVE) else: self._app_indicator.set_status( AppIndicator3.IndicatorStatus.PASSIVE) if self._settings_interactor.get_bool( 'settings_app_indicator_show_gpu_temp' ) and gpu_status.temp.gpu: self._app_indicator.set_label(f" {gpu_status.temp.gpu}°C", " XX°C") else: self._app_indicator.set_label("", "") @staticmethod def _set_entry_text(label: Gtk.Entry, text: Optional[str], *args: Any) -> None: if text is not None and None not in args: label.set_sensitive(True) label.set_text(text.format(*args)) else: label.set_sensitive(False) label.set_text('') @staticmethod def _set_label_markup(label: Gtk.Label, markup: Optional[str], *args: Any) -> None: if markup is not None and None not in args: label.set_sensitive(True) label.set_markup(markup.format(*args)) else: label.set_sensitive(False) label.set_markup('') @staticmethod def _remove_level_bar_offsets(levelbar: Gtk.LevelBar) -> None: levelbar.remove_offset_value("low") levelbar.remove_offset_value("high") levelbar.remove_offset_value("full") levelbar.remove_offset_value("alert") @staticmethod def _set_level_bar(levelbar: Gtk.LevelBar, value: Optional[int]) -> None: if value is not None: levelbar.set_value(value / 100) levelbar.set_sensitive(True) else: levelbar.set_value(0) levelbar.set_sensitive(False) def refresh_chart(self, profile: Optional[FanProfile] = None, reset: bool = False) -> None: if profile is None and reset is None: raise ValueError("Both parameters are note!") if reset: self._plot_chart({}) else: self._plot_chart(get_fan_profile_data(profile)) def refresh_fan_profile_combobox(self, data: List[Tuple[int, str]], active: Optional[int]) -> None: self._fan_liststore.clear() for item in data: self._fan_liststore.append([item[0], item[1]]) self._fan_combobox.set_model(self._fan_liststore) self._fan_combobox.set_sensitive(len(self._fan_liststore) > 1) if active is not None: self._fan_combobox.set_active(active) else: self.refresh_chart(reset=True) def set_apply_fan_profile_button_enabled(self, enabled: bool) -> None: self._fan_apply_button.set_sensitive(enabled) def set_edit_fan_profile_button_enabled(self, enabled: bool) -> None: self._fan_edit_button.set_sensitive(enabled) def set_apply_overclock_profile_button_enabled(self, enabled: bool) -> None: self._overclock_apply_button.set_sensitive(enabled) def set_edit_overclock_profile_button_enabled(self, enabled: bool) -> None: self._overclock_edit_button.set_sensitive(enabled) def refresh_overclock_profile_combobox(self, data: List[Tuple[int, str]], active: Optional[int]) -> None: self._overclock_liststore.clear() for item in data: self._overclock_liststore.append([item[0], item[1]]) self._overclock_combobox.set_model(self._overclock_liststore) self._overclock_combobox.set_sensitive( len(self._overclock_liststore) > 1) if active is not None: self._overclock_combobox.set_active(active) # pylint: disable=attribute-defined-outside-init def _init_plot_charts(self, fan_scrolled_window: Gtk.ScrolledWindow) -> None: self._fan_figure = Figure(figsize=(8, 6), dpi=72, facecolor='#00000000') self._fan_canvas = FigureCanvas(self._fan_figure) # a Gtk.DrawingArea+ self._fan_axis = self._fan_figure.add_subplot(111) self._fan_line, = init_plot_chart(fan_scrolled_window, self._fan_figure, self._fan_canvas, self._fan_axis) def _plot_chart(self, data: Dict[int, int]) -> None: sorted_data = OrderedDict(sorted(data.items())) temperature = list(sorted_data.keys()) duty = list(sorted_data.values()) self._fan_line.set_xdata(temperature) self._fan_line.set_ydata(duty) self._fan_canvas.draw() self._fan_canvas.flush_events()
class Main: going = False iterc = 5 bars = None def __init__(self): self.win = Gtk.Window() self.win.connect("delete-event", Gtk.main_quit) self.win.set_default_size(720, 480) self.fig = Figure(figsize=(10, 10), dpi=100) self.ax = self.fig.add_subplot() self.canvas = FigureCanvas(self.fig) sw = Gtk.ScrolledWindow() sw.set_border_width(10) sw.add(self.canvas) upperside = Gtk.ButtonBox(orientation=Gtk.Orientation.VERTICAL) self.fill_btnbox(upperside, TIMINGS) lowerside = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.spin = Gtk.SpinButton() self.spin.set_range(1, 2**16) #TODO: find out how to remove upper bound self.spin.set_increments(1, 10) self.spin.set_value(self.iterc) self.spin.connect("value-changed", self._on_spin) lowerside.pack_end(self.spin, False, True, 0) lowerside.pack_end(Gtk.Label.new("↓Iterations↓"), False, True, 0) self.progr2 = Gtk.ProgressBar() lowerside.pack_end(self.progr2, False, True, 2) self.progr1 = Gtk.ProgressBar() lowerside.pack_end(self.progr1, False, True, 2) sidebar = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) sidebar.pack_start(upperside, False, True, 10) sidebar.pack_start(lowerside, True, True, 2) self.box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.box.pack_start(sidebar, False, True, 2) self.box.pack_start(sw, True, True, 0) self.win.add(self.box) self.win.show_all() self.progr1.set_opacity(0) self.progr2.set_opacity(0) def measure(self, todos: Iterable[Timing]) -> Tuple[List[str], List[float]]: self.set_progress(0) names = [] vals = [] todolen = len(todos) for i, todo in enumerate(reversed(todos)): self.set_progress(i / todolen) t = Timer(*todo) t.evaluate() names.append(t.name) vals.append(t.value) self.set_progress(1.0) return names, vals def fill_btnbox(self, btnbox: Gtk.ButtonBox, timings: Dict[str, Timing]): for name in timings.keys(): btn = Gtk.Button(label=name) btn.connect("button-press-event", self._on_start) btnbox.pack_start(btn, False, True, 0) def set_progress(self, fraction: float, upper: bool = False): if upper: progr = self.progr1 else: progr = self.progr2 progr.set_fraction(fraction) if not upper: while Gtk.events_pending(): Gtk.main_iteration_do(False) def set_bars(self, cache: Dict[str, List[float]]): names = tuple(cache.keys()) means = [] errs = ([], []) for samples in cache.values(): m = mean(samples) errs[0].append(m - min(samples)) errs[1].append(max(samples) - m) means.append(m) if self.bars: self.ax.clear() self.ax.xaxis.set_major_formatter(MPLFormatter("%0.2fµs")) self.bars = self.ax.barh(names, means, xerr=errs, capsize=80 / len(cache)) self.fig.tight_layout() self.canvas.draw() def _on_start(self, widget: Gtk.Button, event: Gdk.EventButton) -> bool: if self.going: return True self.going = True self.spin.set_range(self.iterc, self.iterc) self.progr1.set_opacity(1) self.progr2.set_opacity(1) self.set_progress(0, True) self.set_progress(0, False) timings = TIMINGS[widget.get_label()] cache = {timing[0]: [] for timing in timings} iterc = self.iterc for i in range(1, iterc + 1): for name, val in zip(*self.measure(timings)): cache[name].append(val) self.set_bars(cache) self.set_progress(i / iterc, True) self.progr1.set_opacity(0) self.progr2.set_opacity(0) self.going = False self.spin.set_range(1, 2**16) return True def _on_spin(self, widget: Gtk.SpinButton) -> bool: self.iterc = int(widget.get_value()) return True
class DropFitView(View['DropFitPresenter', Gtk.Widget]): def _do_init(self) -> Gtk.Widget: from matplotlib.backends.backend_gtk3agg import FigureCanvasGTK3Agg as FigureCanvas from matplotlib.figure import Figure from matplotlib.image import AxesImage self._widget = Gtk.Grid() figure = Figure(tight_layout=True) self._figure_canvas = FigureCanvas(figure) self._figure_canvas.props.hexpand = True self._figure_canvas.props.vexpand = True self._figure_canvas.show() self._widget.add(self._figure_canvas) # Axes self._axes = figure.add_subplot(1, 1, 1) self._axes.set_aspect('equal', 'box') self._axes.xaxis.tick_top() for item in (*self._axes.get_xticklabels(), *self._axes.get_yticklabels()): item.set_fontsize(8) self._axes_bg_image = AxesImage(ax=self._axes) # Placeholder transparent 1x1 image (rgba format) self._axes_bg_image.set_data(np.zeros((1, 1, 4))) self._axes.add_image(self._axes_bg_image) self._profile_extract_line = self._axes.plot([], linestyle='-', color='#0080ff', linewidth=1.5)[0] self._profile_fit_line = self._axes.plot([], linestyle='-', color='#ff0080', linewidth=1)[0] self.presenter.view_ready() return self._widget def set_drop_image(self, image: Optional[np.ndarray]) -> None: if image is None: self._axes.set_axis_off() self._axes_bg_image.set_data(np.zeros((1, 1, 4))) self._figure_canvas.draw() return self._axes.set_axis_on() # Use a scaled down image so it draws faster. thumb_size = (min(400, image.shape[1]), min(400, image.shape[0])) image_thumb = cv2.resize(image, dsize=thumb_size) self._axes_bg_image.set_data(image_thumb) self._axes_bg_image.set_extent((0, image.shape[1], image.shape[0], 0)) self._figure_canvas.draw() def set_drop_profile_extract(self, profile: Optional[np.ndarray]) -> None: if profile is None: self._profile_fit_line.set_visible(False) self._figure_canvas.draw() return self._profile_fit_line.set_data(profile.T) self._profile_fit_line.set_visible(True) self._figure_canvas.draw() def set_drop_profile_fit(self, profile: Optional[np.ndarray]) -> None: if profile is None: self._profile_extract_line.set_visible(False) self._figure_canvas.draw() return self._profile_extract_line.set_data(profile.T) self._profile_extract_line.set_visible(True) self._figure_canvas.draw() def _do_destroy(self) -> None: self._widget.destroy()
class PlotWindow(Gtk.Window): def __init__(self): super(PlotWindow, self).__init__() self.connect('destroy', Gtk.main_quit) self.box = Gtk.Box(spacing=6, orientation=Gtk.Orientation(1)) self.add(self.box) self.switch = Gtk.Switch() self.switch.connect("notify::active", self.on_switch_toggled) self.switch.set_active(False) self.box.pack_start(self.switch, True, True, 0) self.progress = Gtk.ProgressBar(show_text=True) self.box.pack_start(self.progress, True, True, 0) # global line, ax, canvas self.fig = Figure() self.ax = self.fig.add_subplot(111) self.ax.set_xlim(0, 30) self.ax.set_ylim([0, 255]) self.ax.set_autoscale_on(False) self.data = [] self.l_data, = self.ax.plot([], self.data, label='MagY') self.ax.legend() self.canvas = FigureCanvas(self.fig) self.canvas.set_size_request(800, 600) self.canvas.show() self.box.pack_start(self.canvas, True, True, 0) # self.line, = self.ax.plot([1, 2, 3], [1, 2, 10]) port = '/dev/ttyACM0' baud = 9600 self.arduino = ArdTest(self, port, baud) # arduino.open_conn() def on_switch_toggled(self, switch, gparam): if switch.get_active(): state = "on" self.arduino.open_conn() else: state = "off" self.arduino.close() print("Switch was turned", state) def update_progress(self, ok, bad): self.progress.pulse() self.progress.set_text(str(ok) + ' OK, ' + str(bad) + ' BAD') return False def update_plot(self, result): # print(threading.current_thread().getName()) # self.line.set_ydata([1, result, 10]) # self.ax.draw_artist(self.line) # self.canvas.draw() self.data.append(result) # print(self.data) self.l_data.set_data(range(len(self.data)), self.data) # print(self.l_data) try: self.canvas.draw() except Exception as e: print(e) return False
class SMCPlotGui: """ PYGtk GUI class wrapper for displaying SMC gridded data """ def __init__(self, filename=None): # initialise some variables: self.ncfn = filename self.pc = None self.cfacs = None self.proj = None self.src_proj = None self.lon1=None self.lon2=None self.lat1=None self.lat2=None ############### ## GTK setup ## ############### # create new window self.win = Gtk.Window(Gtk.WindowType.TOPLEVEL) ###################### # setup window ###################### self.win.set_border_width(10) self.win.set_default_size(1200, 500) self.win.set_title('SMC Gridded Data Plotter') ###################### # add the GTK canvas: ###################### self.fig = plt.Figure(figsize=(4,3), dpi=100) self.canvas = FigureCanvas(self.fig) ################ # Add menu bar # ################ menu_bar = Gtk.MenuBar() file_menu = Gtk.Menu() open_item = Gtk.MenuItem("Open") exit_item = Gtk.MenuItem("Exit") file_menu.append(open_item) file_menu.append(exit_item) open_item.connect("activate", self.load_event) root_menu = Gtk.MenuItem("File") root_menu.set_submenu(file_menu); menu_bar.append(root_menu) ########### # Controls ########## # buttons: btnPlot = Gtk.Button('Update Plot') btnPrev = Gtk.Button('Prev Time') btnNext = Gtk.Button('Next Time') # Field combo box: store = Gtk.ListStore(str,str) self.cbox_field = Gtk.ComboBox.new_with_model_and_entry(store) cell = Gtk.CellRendererText() self.cbox_field.pack_start(cell, True) self.cbox_field.add_attribute(cell, 'text', 1) self.cbox_field.set_entry_text_column(1) store.append(['hs','sig wave heihgt']) # Times combo box: store = Gtk.ListStore(int,str) self.cbox_times = Gtk.ComboBox.new_with_model_and_entry(store) cell = Gtk.CellRendererText() self.cbox_times.pack_start(cell, True) self.cbox_times.add_attribute(cell, 'text', 1) self.cbox_times.set_entry_text_column(1) #for i in range(1,61): # store.append([i-1, 'T+%03d' % i]) # Domain combo box: store = Gtk.ListStore(str,float,float,float,float) self.cbox_domains = Gtk.ComboBox.new_with_model_and_entry(store) cell = Gtk.CellRendererText() self.cbox_domains.pack_start(cell, True) self.cbox_domains.add_attribute(cell, 'text', 0) store.append(['Full Domain (could be slow)', -999.9, -999.9, -999.9, -999.9]) store.append(['UK', 35.0, 70.0, -15.0, 10.0]) store.append(['South West UK', 49.4, 51.5, -6.7, -1.6]) store.append(['Mediterranean', 29.5, 46.5, -6.0, 36.5]) store.append(['North Atlantic', 20.0, 70.0, -90, 30]) store.append(['West Pacific', -70.0, 70.0, 120, 200]) store.append(['East Pacific', -70.0, 70.0, -160, -68]) store.append(['Arabian Gulf', 23.0, 30.5, 47.5, 59.5]) store.append(['Caspian Sea', 36.0, 47.5, 46.0, 55.5]) store.append(['Black Sea', 40.5, 47.1, 27.0, 42.0]) store.append(['Caribbean', 10.0, 27.5, -86.5, -58.5]) store.append(['South China Sea', -9.5, 24.0, 98.0, 128.0]) store.append(['Australasia', -48, 0.0, 105.0, 179.0]) store.append(['New Zealand', -50, -30, 160.0, 182.0]) self.cbox_domains.set_entry_text_column(0) self.cbox_domains.set_active(1) # Projections: store = Gtk.ListStore(object, str) self.cbox_proj = Gtk.ComboBox.new_with_model_and_entry(store) cell = Gtk.CellRendererText() self.cbox_proj.pack_start(cell, True) self.cbox_proj.add_attribute(cell, 'text', 1) self.cbox_proj.set_entry_text_column(1) store.append([ccrs.PlateCarree(), 'Plate Carree']) store.append([ccrs.RotatedPole(pole_latitude=37.5, pole_longitude=177.5),'Euro Rotated Pole']) store.append([ccrs.Robinson(), 'Robinson']) store.append([ccrs.Mercator(), 'Mercator']) store.append([ccrs.Geostationary(), 'Geostationary']) store.append([ccrs.PlateCarree(central_longitude=180), 'Plate Carree (central_longitude=180)']) self.cbox_proj.set_active(0) # coastlines: store = Gtk.ListStore(object, str) self.cbox_coast = Gtk.ComboBox.new_with_model_and_entry(store) cell = Gtk.CellRendererText() self.cbox_coast.pack_start(cell, True) self.cbox_coast.add_attribute(cell, 'text', 1) self.cbox_coast.set_entry_text_column(1) store.append([None, 'None']) store.append(['10m', 'High res (10m)']) store.append(['50m', 'Medium res (50m)']) store.append(['110m', 'Low res (110m)']) self.cbox_coast.set_active(3) self.coast = '110m' # lat/lon ranges: self.inLat1 = Gtk.Entry(); self.inLat2 = Gtk.Entry(); self.inLon1 = Gtk.Entry(); self.inLon2 = Gtk.Entry(); self.domain_changed_event(self.cbox_domains) # update with default domain # Cell size selection cellsbox = Gtk.HBox(homogeneous=False, spacing=5) self.chkf1 = Gtk.CheckButton("1") self.chkf2 = Gtk.CheckButton("2") self.chkf3 = Gtk.CheckButton("3") self.chkf4 = Gtk.CheckButton("4") cellsbox.pack_end(self.chkf4, True, True, 0) cellsbox.pack_end(self.chkf3, True, True, 0) cellsbox.pack_end(self.chkf2, True, True, 0) cellsbox.pack_end(self.chkf1, True, True, 0) # Colour range box: crangebox = Gtk.HBox(homogeneous=False, spacing=5) self.cmin = Gtk.Entry() self.cmax = Gtk.Entry() self.cauto = Gtk.CheckButton('Auto') crangebox.pack_start(self.cmin, True, True, 0) crangebox.pack_start(self.cmax, True, True, 0) crangebox.pack_start(self.cauto, True, True, 0) self.cauto.set_active(True) self.cmin.set_sensitive(False) self.cmax.set_sensitive(False) self.cauto.connect('toggled', self.cauto_changed_event) ## controls layout grid = Gtk.Table(rows=8, columns=3) grid.attach(Gtk.Label(label='Field'), 0, 1, 0, 1, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(Gtk.Label(label='Time'), 0, 1, 1, 2, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(Gtk.Label(label='Projection'),0, 1, 2, 3, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(Gtk.Label(label='Coastline'), 0, 1, 3, 4, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(Gtk.Label(label='Domain '), 0, 1, 4, 5, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(Gtk.Label(label='Lat Range'), 0, 1, 5, 6, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(Gtk.Label(label='Lon Range'), 0, 1, 6, 7, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(Gtk.Label(label='Cell Factor'), 0, 1, 7, 8, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(Gtk.Label(label='Colour range'),0, 1, 8, 9, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(self.cbox_field, 1, 3, 0, 1, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(self.cbox_times, 1, 3, 1, 2 ,yoptions=Gtk.AttachOptions.SHRINK) grid.attach(self.cbox_proj, 1, 3, 2, 3 ,yoptions=Gtk.AttachOptions.SHRINK) grid.attach(self.cbox_coast, 1, 3, 3, 4 ,yoptions=Gtk.AttachOptions.SHRINK) grid.attach(self.cbox_domains, 1, 3, 4, 5 ,yoptions=Gtk.AttachOptions.SHRINK) grid.attach(self.inLat1, 1, 2, 5, 6, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(self.inLat2, 2, 3, 5, 6, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(self.inLon1, 1, 2, 6, 7, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(self.inLon2, 2, 3, 6, 7, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(cellsbox, 1, 3, 7, 8, yoptions=Gtk.AttachOptions.SHRINK) grid.attach(crangebox, 1, 3, 8, 9, yoptions=Gtk.AttachOptions.SHRINK) #grid.attach(btnPlot, 0, 1, 8, 9, yoptions=Gtk.AttachOptions.SHRINK, xoptions=Gtk.AttachOptions.SHRINK) # Hbox for plot buttons btn_hbox = Gtk.HBox(homogeneous=False, spacing=5) btn_hbox.pack_start(btnPrev, True, False, 0) btn_hbox.pack_start(btnPlot, True, False, 0) btn_hbox.pack_start(btnNext, True, False, 0) ## File details text view txt = Gtk.TextBuffer() txt.set_text('Please load a file') self.tv_file_details = Gtk.TextView.new_with_buffer(txt) vbox = Gtk.VBox(spacing=5) vbox.pack_start(grid, False, True, 0) vbox.pack_start(btn_hbox, False, True, 0) vbox.pack_end(self.tv_file_details, True, True, 0) # plot controls from matplotlib.backends.backend_gtk3 import NavigationToolbar2GTK3 as NavigationToolbar toolbar = NavigationToolbar(self.canvas, self.win) #vbox.pack_end(toolbar, False, False) # Top level layout box: topbox = Gtk.VBox() topbox.pack_start(menu_bar, False, True, 0) box = Gtk.HBox(homogeneous=False, spacing=5) topbox.pack_end(box, True, True, 0) # canvas/toolbar layout plotbox = Gtk.VBox(homogeneous=False, spacing=0) plotbox.pack_start(self.canvas, True, True, 0) plotbox.pack_end(toolbar, False, False, 0) box.pack_start(plotbox, True, True, 0) box.pack_end(vbox, False, False, 0) self.win.add(topbox) ################### # connect signals: ################### # destroy/delete: self.win.connect("delete_event", self.delete_event) self.win.connect("destroy", self.destroy) btnPlot.connect("clicked", self.plot_event) btnNext.connect("clicked", self.next_time_event) btnPrev.connect("clicked", self.prev_time_event) self.cbox_domains.connect('changed', self.domain_changed_event) # show window self.win.show_all() #### Load file, if passed in: if self.ncfn is not None: self.loadfile(self.ncfn) def get_cbox_selection(self, combobox, col=0): model = combobox.get_model() active = combobox.get_active() if active < 0: return None return model[active][col] def delete_event(self, widget, event, data=None): # returning false after a delete event destroys the widget, # returning true means you don't want to destroy the widget. return False def cauto_changed_event(self, widget, data=None): # update the lat/lon boxes: active = widget.get_active() self.cmin.set_sensitive(not active) self.cmax.set_sensitive(not active) def domain_changed_event(self, widget, data=None): # update the lat/lon boxes: model = widget.get_model() active = widget.get_active() if active < 0: return for i,o in enumerate([self.inLat1, self.inLat2, self.inLon1, self.inLon2]): val = model[active][i+1] if val < -900.0: val = '' else: val = str(val) o.set_text(val) def destroy(self, widget, data=None): Gtk.main_quit() def load_event(self, widget, data=None): # pop up a file selectro dialog and load the file if self.selectfile(): self.loadfile(self.ncfn) def selectfile(self): dlg = Gtk.FileChooserDialog(title='Select a SMC netCDF file', action=Gtk.FileChooserAction.OPEN, buttons=(Gtk.STOCK_CANCEL,Gtk.ResponseType.CANCEL,Gtk.STOCK_OPEN,Gtk.ResponseType.OK)) dlg.set_default_response(Gtk.ResponseType.OK) ret = dlg.run() if ret == Gtk.ResponseType.OK: self.ncfn = dlg.get_filename() dlg.destroy() return (ret == Gtk.ResponseType.OK) def loadfile(self, fn): self.d = nc.Dataset(fn, mode='r') if self.d.dimensions.has_key('seapoint'): seapoint_dim = 'seapoint' else: seapoint_dim = 'seapoints' # populate text bxo with file details txt = self.tv_file_details.get_buffer() txt.set_text('File details:\n' + '\tNo. sea points: %d\n' % len(self.d.dimensions[seapoint_dim]) + '\tNo. times: %d\n' % len(self.d.dimensions['time'])) # update the fields combobox store = self.cbox_field.get_model() store.clear() store.append(['grid', 'Grid mesh only']) for varname,var in self.d.variables.items(): if var.ndim == 2 and hasattr(var,'long_name'): store.append([varname, var.long_name]) if var.ndim == 3 and hasattr(var,'long_name'): store.append(["ens_"+varname, var.long_name + " (ens)"]) self.cbox_field.set_active(0) # find location of uwnd or vwnd and insert a wspd option (this will calculate # a wind speed field from uwnd and vwnd): i=store.get_iter_first() while i is not None: varname = store.get_value(i,0) if varname in ['uwnd','vwnd']: # insert new field here: store.insert_before(i, ['wspd_derived', 'wind speed (derived)']) break i = store.iter_next(i) # update times text box: store = self.cbox_times.get_model() store.clear() t = self.d.variables['time'] t = nc.num2date(t[:], t.units) for itime, fctime in enumerate(t): store.append([itime, "%s (T+%03d)" % (fctime.strftime("%d/%m/%Y %H:%M"), itime+1)]) self.cbox_times.set_active(0) # get model extents: try: self.minlat = float(self.d.southernmost_latitude) self.maxlat = float(self.d.northernmost_latitude) self.minlon = float(self.d.westernmost_longitude) self.maxlon = float(self.d.easternmost_longitude) except: self.minlat = -90 self.maxlat = 90 self.minlon = 0 self.maxlon = 360 return def plot_event(self, widget, data=None): self.plotfield() def next_time_event(self, widget, data=None): # move to next timestep and replot itime = self.get_cbox_selection(self.cbox_times) if itime is None: return itime = itime + 1 ntimes = len(self.cbox_times.get_model()) if itime >= ntimes: itime = 0 self.cbox_times.set_active(itime); self.plot_event(None) def prev_time_event(self, widget, data=None): # move to next timestep and replot itime = self.get_cbox_selection(self.cbox_times) if itime is None: return itime = itime - 1 ntimes = len(self.cbox_times.get_model()) if itime < 0: itime = ntimes - 1 self.cbox_times.set_active(itime); self.plot_event(None) def getfloat(self, string): try: return float(string) except ValueError: return None def plotfield(self): # get reference to details text view and clear it txt = self.tv_file_details.get_buffer() start_iter = txt.get_start_iter() end_iter = txt.get_end_iter() txt.delete(start_iter, end_iter) end_iter = txt.get_end_iter() # get required field, time, etc: var = self.get_cbox_selection(self.cbox_field) if var.startswith('ens_'): var = var[4:] ens = True else: ens = False itime = self.get_cbox_selection(self.cbox_times) # get lat/lon ranges lat1 = self.getfloat(self.inLat1.get_text()) lat2 = self.getfloat(self.inLat2.get_text()) lon1 = self.getfloat(self.inLon1.get_text()) lon2 = self.getfloat(self.inLon2.get_text()) # get celfacs: cfacs=[] if self.chkf1.get_active(): cfacs.append(1) if self.chkf2.get_active(): cfacs.append(2) if self.chkf3.get_active(): cfacs.append(4) if self.chkf4.get_active(): cfacs.append(8) if len(cfacs) == 0: cfacs = None if cfacs != self.cfacs: self.pc = None self.cfacs = cfacs if(lat1 != self.lat1 or lat2 != self.lat2 or lon1 != self.lon1 or lon2 != self.lon2 ): self.pc = None self.lat1 = lat1 self.lat2 = lat2 self.lon1 = lon1 self.lon2 = lon2 proj = self.get_cbox_selection(self.cbox_proj) if self.proj != proj: self.proj = proj self.pc = None self.fig.clf() self.ax = self.fig.add_subplot(111, projection=self.proj) sm = plt.cm.ScalarMappable(norm=plt.Normalize()) sm._A=[] self.cbar = plt.colorbar(sm, ax=self.ax, orientation='horizontal', fraction=0.05, shrink=0.8, pad=0.04) coast = self.get_cbox_selection(self.cbox_coast) if self.coast != coast: newcoast = True self.coast = coast else: newcoast = False ax = self.ax # determin extents: if isinstance(proj, ccrs.Geostationary) or ( lon1 is None and lon2 is None and lat1 is None and lat2 is None): ax.set_global() global_extent = True else: if lon1 is None: lon1 = self.minlon if lon2 is None: lon2 = self.maxlon if lat1 is None: lat1 = self.minlat if lat2 is None: lat2 = self.maxlat global_extent = False ## check source projection of requested variable: chkvar = var if var == 'wspd_derived': chkvar = 'uwnd' if var == 'grid': chkvar = 'hs' if hasattr(self.d.variables[chkvar], "grid_mapping"): # get rotated pole projection: mapname = self.d.variables[chkvar].grid_mapping gmap = self.d.variables[mapname] plat = gmap.grid_north_pole_latitude plon = gmap.grid_north_pole_longitude src_proj = ccrs.RotatedPole(pole_latitude=plat, pole_longitude=plon) else: src_proj = None if self.src_proj != src_proj: # source projection changed need to update patches: self.pc = None self.src_proj = src_proj # If patch collection not yet calculated, then build it now and add it to # the axis along with the coastlines: if self.pc is None: txt.insert(end_iter, "Domain has changed - recalculating patches...") while Gtk.events_pending(): Gtk.main_iteration_do(True) self.pc = smc.generate_patch_collection(self.d, lon1=self.lon1, lon2=self.lon2, lat1=self.lat1, lat2=self.lat2, target_crs=self.proj, cfacs=cfacs, source_crs=self.src_proj) end_iter = txt.get_end_iter() txt.insert(end_iter, "Done\n") while Gtk.events_pending(): Gtk.main_iteration_do(True) end_iter = txt.get_end_iter() txt.insert(end_iter, "Adding patches to axes\n"); print("Adding patches to axes\n") while Gtk.events_pending(): Gtk.main_iteration_do(True) ax.cla() self.cm = ax.add_collection(self.pc.pcol) if not global_extent: ax.set_extent((lon1, lon2, lat1, lat2), crs=ccrs.PlateCarree()) if self.coast is not None: end_iter = txt.get_end_iter() txt.insert(end_iter, "Adding coastline\n"); while Gtk.events_pending(): Gtk.main_iteration_do(True) ax.coastlines(resolution=self.coast) elif newcoast: # coastline changed; clear axis and redraw: ax.cla() end_iter = txt.get_end_iter() txt.insert(end_iter, "Adding patches to axes\n"); while Gtk.events_pending(): Gtk.main_iteration_do(True) self.cm = ax.add_collection(self.pc.pcol) if not global_extent: ax.set_extent((lon1, lon2, lat1, lat2), crs=ccrs.PlateCarree()) if self.coast is not None: end_iter = txt.get_end_iter() txt.insert(end_iter, "Adding coastline\n"); while Gtk.events_pending(): Gtk.main_iteration_do(True) ax.coastlines(resolution=self.coast) # update the patch face colours with the new data: end_iter = txt.get_end_iter() txt.insert(end_iter, "Updating patches...\n"); while Gtk.events_pending(): Gtk.main_iteration_do(True) if var == 'grid': # special case - just plot grid mesh: self.pc.pcol.set_facecolor('#EAEAEA') self.pc.pcol.set_edgecolor('#5E5E5E') self.pc.pcol.set_linewidth(0.5) cmin = 0 cmax = 1 else: # load field and set face colours if var == 'wspd_derived': end_iter = txt.get_end_iter() txt.insert(end_iter, "Deriving wind speed from uwnd and vwnd fields\n") fld = self.d.variables['uwnd'] fld2 = self.d.variables['vwnd'] dat = np.sqrt( np.power(fld[itime,:][self.pc.mask], 2) + np.power(fld2[itime,:][self.pc.mask], 2) ) else: fld = self.d.variables[var] if ens: dat = fld[0,itime,:][self.pc.mask] # just get member 0 else: dat = fld[itime,:][self.pc.mask] if self.cauto.get_active(): cmin = dat.min() cmax = dat.max() self.cmin.set_text("%.2f" % cmin) self.cmax.set_text("%.2f" % cmax) else: cmin = self.getfloat(self.cmin.get_text()) cmax = self.getfloat(self.cmax.get_text()) clrs = smc.generate_color_array(dat, cmin=cmin, cmax=cmax) self.pc.pcol.set_facecolor(clrs) self.pc.pcol.set_edgecolor(clrs) self.pc.pcol.set_linewidth(0.5) # update colorbar mappable with new range: self.cbar.mappable.set_clim(cmin, cmax) ## update title fldname = self.get_cbox_selection(self.cbox_field, 1) time = self.get_cbox_selection(self.cbox_times, 1) ax.set_title("%s @ %s" % (fldname, time), fontsize=12) # update canvas self.canvas.draw() end_iter = txt.get_end_iter() txt.insert(end_iter, "Done.\n"); while Gtk.events_pending(): Gtk.main_iteration_do(True) def main(self): Gtk.main()
class GUI: def __init__(self): self.last_dir = os.getcwd() self.b = Gtk.Builder() gui_xml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_blob_detector_gui.xml') self.b.add_from_file(gui_xml_path) self.window = self.b.get_object("window") self.window.set_title('BlobDetector') self.f = matplotlib.figure.Figure() self.ax = self.f.add_subplot(111) self.f.subplots_adjust(left=0.01, right=0.99, bottom=0.01, top=0.99, hspace=0, wspace=0) self.canvas = FigureCanvas(self.f) self.b.get_object("alignment_img").add(self.canvas) grid = self.b.get_object("grid_params") j = 0 self.detector_params_toggle_buttons = {} self.detector_params_entries = {} for p in detector_params_desc: if isinstance(p, dict): button = Gtk.CheckButton(label=p['name']) grid.attach(button, 0, j, 1, 1) self.detector_params_toggle_buttons[p['name']]= button j+=1 for sp in p['params']: label = Gtk.Label(label='{}'.format(sp)) label.set_justify(Gtk.Justification.LEFT) grid.attach(label, 0, j, 1, 1) if 0: adj = Gtk.Adjustment(0, 0, 100, 5, 10, 0) scale = Gtk.Scale(orientation=Gtk.Orientation.HORIZONTAL, adjustment=adj) grid.attach(scale, 1, j, 2, 1) else: entry = Gtk.Entry() grid.attach(entry, 1, j, 2, 1) self.detector_params_entries[sp] = entry #print sp j+=1 else: label = Gtk.Label(label=f'{p}') label.set_justify(Gtk.Justification.LEFT) grid.attach(label, 0, j, 1, 1) entry = Gtk.Entry() grid.attach(entry, 1, j, 2, 1) self.detector_params_entries[p] = entry j+=1 scale = self.b.get_object("scale_gamma") adj_args = {'value':1, 'lower':0.1, 'upper':2., 'step_increment':0.05, 'page_increment':0.1, 'page_size':0} adj = Gtk.Adjustment(**adj_args) scale.set_adjustment(adj) self.image_display_mode = 'Original' self.window.show_all() def display_image(self, model): label = self.b.get_object("label_image") label.set_text(model.image_path) img = model.get_image(self.image_display_mode) if len(img.shape) == 2: img2 = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) else: img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) self.ax.imshow(img2) self.canvas.draw() def display_params(self ,params): for p in smocap.Detector.param_names: a = getattr(params, p) if isinstance(a, bool): self.detector_params_toggle_buttons[p].set_active(a) else: self.detector_params_entries[p].set_text(str(a)) def display_detector_res(self, keypoints): textview = self.b.get_object("textview1") textbuffer = textview.get_buffer() txt = "{} keypoints\n\n".format(len(keypoints)) for kp in keypoints: txt += '\tpos: {:.2f} {:.2f}\n'.format(*kp.pt) txt += '\tsize: {:.2f}\n'.format(kp.size) #txt += '\tangle: {}\n'.format(kp.angle) #txt += '\tresp: {}\n'.format(kp.response) #txt += '\toctave: {}\n'.format(kp.octave) txt += '\n' textbuffer.set_text(txt) def request_path(self, action): dialog = Gtk.FileChooserDialog("Please choose a file", self.window, action, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) dialog.set_current_folder(self.last_dir) ret = dialog.run() file_path = dialog.get_filename() if ret == Gtk.ResponseType.OK else None dialog.destroy() if file_path is not None: self.last_dir = os.path.dirname(file_path) return file_path def set_image_display_mode(self, model, display_mode): self.image_display_mode = display_mode self.display_image(model)
class wykres_1(Gtk.Window, pomiar): def __init__(self): pomiar.__init__(self) Gtk.Window.__init__(self, title="Okno Pomiarowe") self.vpaned = Gtk.VPaned() self.set_default_size(800,600) #self.move(200,100) self.vbox = Gtk.VBox() self.box = Gtk.Box(spacing=6) self.set_border_width(20) self.button = Gtk.Button(label="Pomiar Amoniaku") self.button.connect("clicked", self.on_pomiar_clicked) self.box.pack_start(self.button, True, True, 5) self.button = Gtk.Button(label = "Pomiar Wody" ) self.button.connect("clicked", self.on_pomiar_clicked) self.box.pack_start(self.button, True, True, 5) self.button = Gtk.Button(label = "Pomiar Temperatury" ) self.button.connect("clicked", self.on_pomiar_clicked) self.box.pack_start(self.button,True, True, 5) self.i = datetime.datetime.now() #self.i_strip = datetime.datetime.now().strftime("%y-%m-%d-%H-%M-%S") self.x = [date2num(self.i)] print("Data teraz: ") print(self.x) self.f = plt.figure() self.f.autofmt_xdate() self.a = self.f.add_subplot(3,1,1) n1 = pomiar() self.amn_1 = n1.amoniak() self.wda_1 = n1.woda() self.tmp_1 = n1.temperatura() # print("Tutaj:", z) #print(type(z)) #self.p = float(z) #print(self.p) self.a.plot_date(self.x, self.amn_1, tz=None, color='green', linestyle = ':', marker='o', markerfacecolor='blue', markersize=2) self.a.grid(True) #self.a.set_xlim(-3,22) self.a.set_ylim(-1,20) self.a.set_xlabel('Czas') self.a.set_ylabel('Amoniak [ppm]') self.b = self.f.add_subplot(312) self.b.plot_date(self.x,self.wda_1, tz=None, color='green', linestyle = ':', marker='o', markerfacecolor='blue', markersize=2) self.b.grid(True) self.b.set_xlabel('Czas') self.b.set_ylabel('Woda [ppm]') #self.a.set_animated(True) xfmt = md.DateFormatter('%m-%d-%H:%M:%S') #print(xfmt) self.c = self.f.add_subplot(313) self.c.plot_date(self.x,self.tmp_1,tz=None, color='green', linestyle = ':', marker='o', markerfacecolor='blue', markersize=2) self.c.grid(True) #self.a.set_xlim(-3,22) self.c.set_ylim(20,23) self.c.set_xlabel('Czas') self.c.set_ylabel(u'Temperatura [\u00B0C]') #self.c.set_xlim(0,self.x) plt.setp(self.c.xaxis.set_major_formatter(xfmt)) #plt.setp(self.c.xaxis.get_majorticklabels(), rotation=30) plt.setp(self.a.xaxis.set_major_formatter(xfmt)) # plt.setp(self.a.xaxis.get_majorticklabels(), rotation=30) plt.setp(self.b.xaxis.set_major_formatter(xfmt)) #plt.setp(self.b.xaxis.set_major_locator(md.HourLocator())) plt.setp(self.a.xaxis.set_major_locator(MaxNLocator(4))) plt.setp(self.b.xaxis.set_major_locator(MaxNLocator(4))) plt.setp(self.c.xaxis.set_major_locator(MaxNLocator(4))) #self.c.relim() # relim() #self.c.autoscale_view() #plt.gcf() #plt.ion() # plt.setp(self.b.xaxis.get_majorticklabels(), rotation=30) #self.b.subplot_adjust(bottom = 0.5) # Add canvas to vbox self.canvas = FigureCanvas(self.f) # a Gtk.DrawingArea self.vbox.pack_start(self.canvas, True, True, 5) # Create toolbar self.toolbar = NavigationToolbar(self.canvas,self) self.vbox.pack_start(self.toolbar, False, False, 5) self.add(self.vpaned) self.vpaned.add(self.box) self.vpaned.add(self.vbox) self.show_all() self.s = GObject.timeout_add(6000,self.wykres) #GObject.idle_add(self.wykres) def on_pomiar_clicked(self,button): print("Dziala") stop = ("7B49080000EA4A7D") stop_d = stop.decode("hex") print(stop_d) ser.close() ser.open() ser.flushInput() ser.flushOutput() ser.write(stop_d) GObject.source_remove(self.s) self.destroy() def wykres(self): i_1 = datetime.datetime.now() #i_strip = datetime.datetime.now().strftime("%y-%m-%d-%H-%M-%S") #print("Czas datetime" ) #print(i_1) x1 = [date2num(i_1)] print("Czas teraz: ") print(x1) nowy_pomiar = pomiar() #print("Czas kiedys: " ) print(self.x) amon_1 = nowy_pomiar.amoniak() tmp = nowy_pomiar.temperatura() wda = nowy_pomiar.woda() amoniak = ("Pomiar amoniaku: " + amon_1 + " \t " + "Woda: " + wda + " \t " + "Temperatura celi: " + tmp ) z = str(amoniak) self.set_title(z) self.a.plot_date(x1,amon_1,tz = None, color='green', linestyle = '-', marker='o', markerfacecolor='blue', markersize=3) self.b = self.f.add_subplot(312) self.b.plot_date(x1,wda, tz=None, color='green', linestyle = ':', marker='o', markerfacecolor='blue', markersize=3) self.b.grid(True) self.b.set_xlabel('Czas') self.b.set_ylabel('Woda [ppm]') self.c = self.f.add_subplot(313) self.c.plot_date(x1,tmp,tz=None, color='green', linestyle = ':', marker='o', markerfacecolor='blue', markersize=3 ) self.c.grid(True) #self.a.set_xlim(-3,22) self.c.set_ylim(5,55) self.c.set_xlabel('Czas') self.c.set_ylabel(u'Temperatura [\u00B0C]') self.a.set_xlim((i_1 - timedelta(minutes=8), i_1 + timedelta(seconds=15)) ) self.b.set_xlim((i_1 - timedelta(minutes=8), i_1 + timedelta(seconds=15)) ) self.c.set_xlim((i_1 - timedelta(minutes=8), i_1 + timedelta(seconds=15)) ) #self.a.xticks(x1,i_1,rotation=45) # self.a.xaxis.set_minor_formatter(dates.DateFormatter('%d%a')) #self.a.setp(rotation=30) time.sleep(1) self.canvas.draw() #self.show_all() return True
class Ui(): def __init__(self, profile): self.profile = profile self.builder = Gtk.Builder() prog_path = Path(__file__).parent self.builder.add_from_file(str(prog_path / 'ui.glade')) self.builder.connect_signals(self) for obj in self.builder.get_objects(): try: setattr(self, Gtk.Buildable.get_name(obj), obj) except: pass self.f = Figure() self.canvas = FigureCanvas(self.f) self.figure_holder.pack_start(self.canvas, True, True, 5) self.profile_data_x = [0] self.profile_data_y = [25] for (rate, target, time) in self.profile: t = (target - self.profile_data_y[-1]) / rate self.profile_data_x.append(self.profile_data_x[-1] + t) self.profile_data_y.append(target) self.profile_data_x.append(self.profile_data_x[-1] + time) self.profile_data_y.append(target) self.recorded_data_x = [0] self.recorded_data_y = [25] self.replot() self.stop_button.set_sensitive(False) self.start_button.set_sensitive(False) print(self.connect_button.get_label()) self.main_window.show_all() self.oven = None self.running = False self.start_t = None GLib.idle_add(lambda: self.idle()) def quit(self, *args): if self.oven: self.oven.stop() exit() def idle(self): if self.oven: t = self.oven.process() if isinstance(t, float): if self.running: self.recorded_data_x.append(time.time() - self.start_t) self.recorded_data_y.append(t) else: self.recorded_data_x = [0] self.recorded_data_y = [t] self.replot() return True def replot(self): self.f.clear() ax = self.f.add_subplot(1, 1, 1) ax.plot(self.profile_data_x, self.profile_data_y) ax.plot(self.recorded_data_x, self.recorded_data_y, 'x') self.canvas.draw() def connect_clicked(self, *args): if self.oven is None: try: self.oven = oven.Oven(self.tty_entry.get_text()) except: d = Gtk.MessageDialog( self.main_window, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "Could not open tty {}".format(self.tty_entry.get_text())) d.run() d.destroy() import traceback traceback.print_exc() return self.connect_button.set_label('gtk-disconnect') self.start_button.set_sensitive(True) else: self.oven.stop() self.oven = None self.connect_button.set_label('gtk-connect') self.start_button.set_sensitive(False) self.stop_button.set_sensitive(False) def start_clicked(self, *args): if self.oven.start(self.profile): self.start_t = time.time() self.running = True self.start_button.set_sensitive(False) self.stop_button.set_sensitive(True) def stop_clicked(self, *args): self.oven.stop() self.running = False self.start_button.set_sensitive(True) self.stop_button.set_sensitive(False)
class MainWindow(object): """Clase manejadora de la ventana principal. """ def __init__(self): self.builder = Gtk.Builder() self.builder.set_translation_domain(LANG_DOM) self.builder.add_from_file(UI_FILE) self.builder.connect_signals(self) self.win=self.builder.get_object('window1') self.graf_box=self.builder.get_object('graf_box') self.statusbar = self.builder.get_object('statusbar') self.statusbar.push(1,_('Last access: ')) self.ui_label={} for label in labels: self.ui_label[label]=self.builder.get_object(label) fig = Figure() self.plot1 = fig.add_subplot(111) self.plot2 = fig.add_subplot(212) self.plot3 = fig.add_subplot(313) self.plot3.set_position([0.055,0.06,0.93,0.24]) self.plot2.set_position([0.055,0.38,0.93,0.24]) self.plot1.set_position([0.055,0.69,0.93,0.24]) self.canvas = FigureCanvas(fig) self.graf_box.pack_start(self.canvas,True,True,0) self.win.show_all() if self.get_params(): self.update_ui() GObject.timeout_add_seconds(180,self.update_ui) def get_params(self): #Obtener parametros de programa params=DataStore.ParamStore(APP_DIR,PARAM_FILE) self.dir_data=params.get('paths','dir_data') if self.dir_data==None: dialog = Gtk.FileChooserDialog(_("Select pywws data folder:"), self.win, Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,Gtk.STOCK_OK, Gtk.ResponseType.OK)) response = dialog.run() if response == Gtk.ResponseType.OK: self.dir_data = dialog.get_filename() params.set('paths','dir_data',self.dir_data) params.flush() else: self.dir_data='' dialog.destroy() if not os.path.exists(self.dir_data): dialog = Gtk.MessageDialog(self.win,0, Gtk.MessageType.ERROR,Gtk.ButtonsType.CANCEL, _("pywws data folder does not exist.")) dialog.run() dialog.destroy() return False return True def update_ui(self): self.statusbar.pop(1) pywws_data=get_pywws_data(self.dir_data) if pywws_data==None: self.statusbar.push(1,_('Error accessing pywws data.')) return True idx=pywws_data['a']['idx'].replace(tzinfo=TimeZone.utc).astimezone(TimeZone.Local) self.statusbar.push(1,_('Last access: ')+idx.strftime('%c').decode('utf-8')) for label in labels: tipo_k,pywws_k,strfmt=_parse_label(label) self.ui_label[label].set_label(strfmt.format(pywws_data[tipo_k][pywws_k])) #plotting val=[],[],[],[],[],[],[] for d in pywws_data['g']: val[0].append(d['idx']) val[1].append(d['temp_out']) val[2].append(d['temp_in']) val[3].append(d['hum_out']) val[4].append(d['hum_in']) for d in pywws_data['h']: val[5].append(d['idx']) val[6].append(d['rain']) self.plot1.clear() self.plot2.clear() self.plot3.clear() self.plot1.plot(val[0],val[1],label=_('Outdoor Temp.')) self.plot1.plot(val[0],val[2],label=_('Indoor Temp.')) self.plot2.plot(val[0],val[3],label=_('Outdoor Hum.'),color='red') self.plot2.plot(val[0],val[4],label=_('Indoor Hum.'),color='magenta') self.plot3.plot(val[5],val[6],label=_('Rain')) self.plot1.set_title(_('Last 24 hours.'),fontsize=10) self.plot1.set_ylabel(_('ᴼC'),fontsize=10) self.plot2.set_ylabel(_('%'),fontsize=10) self.plot3.set_ylabel(_('mm'),fontsize=10) for plot in (self.plot1,self.plot2,self.plot3): plot.tick_params(labelsize=9) plot.xaxis.set_major_formatter(dates.DateFormatter('%H:%M',TimeZone.Local)) plot.xaxis.set_major_locator(dates.HourLocator()) plot.grid(True) plot.legend(loc='best',prop={'size':10}) self.canvas.draw() return True def on_window_destroy(self,win): Gtk.main_quit() def run(self): Gtk.main()