class TickerChart(Gtk.Box): __gsignals__ = { 'cursor-time': (GObject.SignalFlags.RUN_FIRST, None, (object, )), } def __init__(self, interval=100, view=20, keep=None, linewidth=1): super().__init__() self.fig = Figure(dpi=72) self.canvas = FigureCanvas(self.fig) self.pack_start(self.canvas, True, True, 0) self.data = {} self.plots = {} self.info = {} self.alternates = set() self.active = None self.axes = [] self.axes.append(self.fig.add_subplot(111)) self.fig.subplots_adjust(left=0.12, right=0.88) self.axes[0].set_xlabel('seconds ago') self.interval = interval # milliseconds self.view_range = view # seconds self.keep_range = keep or (view * 4) # seconds self.linewidth = linewidth self.keep_size = int(self.keep_range * 1000 / self.interval) self.view_step = view // 2 self.deviation = 10 self.view_time = time.time() self.add_data('time') self.paused = False self.show_all() def pause(self): self.paused = True def resume(self): self.paused = False def zoom_out(self): self.view_range = max(self.view_range - self.view_step, self.view_step) self.update() def zoom_in(self): self.view_range = min(self.view_range + self.view_step, self.keep_range) self.update() def incr_margin(self): self.deviation = min(self.deviation + 5, 50) self.update() def decr_margin(self): self.deviation = max(self.deviationi - 5, 5) self.update() def add_data(self, name): if name in self.data: return self.data[name] = numpy.empty(self.keep_size) self.data[name][:] = numpy.nan def resize_data(self): for name, data in list(self.data.items()): self.data[name] = numpy.empty(self.keep_size) if self.max_samples > len(data): self.data[name][-len(data):] = data else: self.data[name] = data[-self.keep_size:] def select_active(self, name): if name in self.alternates: self.active = name self.axes[1].set_ylabel(name) def add_alternate(self, name): self.alternates.add(name) def shift_data(self): for name, data in list(self.data.items()): data[:-1] = data[1:] def add_plot(self, name, color=None, linestyle='-', axis=0, alternate=False): assert axis in [0, 1], 'axis must be 0 or 1' if axis == 1 and len(self.axes) == 1: self.axes.append(self.axes[0].twinx()) if not color: color = COLORS[len(self.plots)] self.plots[name] = Line2D([], [], color=color, linewidth=self.linewidth, linestyle=linestyle) self.axes[axis].add_line(self.plots[name]) self.axes[axis].set_ylabel(name, color=color) self.info[name] = { 'color': color, 'linestyle': linestyle, 'axis': axis } if alternate: self.add_alternate(name) self.select_active(name) self.add_data(name) def clear(self): for name, line in list(self.plots.items()): self.data[name][:] = numpy.nan def update(self): if self.paused: return selector = ~numpy.isnan(self.data['time']) selector[selector] = ((self.data['time'][selector] > (self.view_time - self.view_range)) & (self.data['time'][selector] <= self.view_time)) if selector.sum() < 2: return now = self.data['time'][selector][-1] x_data = self.data['time'][selector] - now xmin, xmax = min(x_data.min(), -self.view_range), x_data.max() extrema = defaultdict(lambda: (numpy.nan, numpy.nan)) for name, line in list(self.plots.items()): if name in self.alternates and name != self.active: continue axis = self.info[name]['axis'] ymin, ymax = extrema[axis] y_data = self.data[name][selector] mn, mx = misc.get_min_max(y_data, ldev=self.deviation, rdev=self.deviation) ymin, ymax = numpy.nanmin([ymin, mn]), numpy.nanmax([ymax, mx]) extrema[axis] = (ymin, ymax) line.set_data(x_data, y_data) for i, (ymin, ymax) in list(extrema.items()): if ymin != ymax: self.axes[i].set_ylim(ymin, ymax) if xmin != xmax: self.axes[i].set_xlim(xmin, xmax) def redraw(self): self.canvas.draw_idle() def animate(self, i): self.update() return list(self.plots.values()) def save(self): dialog = Gtk.FileChooserDialog( "Save Chart ...", dialogs.MAIN_WINDOW, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK)) dialog.set_size_request(600, 300) response = dialog.run() if response == Gtk.ResponseType.OK: img_filename = dialog.get_filename() if os.access(os.path.dirname(img_filename), os.W_OK): self.fig.savefig(img_filename) dialog.destroy()
class Plotter(Gtk.Alignment): def __init__(self, loop=False, buffer_size=2500, xformat='%g', dpi=80): super().__init__() self.set(0.5, 0.5, 1, 1) self.format_x = FormatStrFormatter(xformat) self.ring_buffer = loop self.buffer_size = buffer_size self.colormap = cm.get_cmap('Dark2') self.axis_space = 0.92 self.cursor_line = None self.cursor_points = {} self.plot_scales = {} self.lines = {} self.axis = {} self.data_type = {} self.values = None self.grid_mode = False self.grid_specs = {} self.grid_image = None self.grid_norm = Normalize() self.grid_snake = False self.fig = Figure(figsize=(10, 6), dpi=dpi) self.clear() self.canvas = FigureCanvas(self.fig) # a Gtk.DrawingArea self.canvas.mpl_connect('motion_notify_event', self.on_mouse_motion) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.toolbar = PlotterToolbar(self.canvas, dialogs.MAIN_WINDOW) box.pack_start(self.canvas, True, True, 0) box.pack_start(self.toolbar, False, False, 0) self.add(box) self.show_all() def clear(self, specs=None): """ Clear the plot and configure it for the given specifications. :param specs: dictionary containing configuration parameters """ self.fig.clear() self.fig.subplots_adjust(bottom=0.1, left=0.05, top=0.90, right=self.axis_space) specs = {} if specs is None else specs self.grid_mode = 'grid' in specs.get('scan_type', '') self.data_type = specs.get('data_type') self.values = misc.RecordArray(self.data_type, size=self.buffer_size, loop=self.ring_buffer) self.cursor_line = None self.lines = {} self.grid_snake = specs.get('grid_snake', False) self.grid_specs = {} self.grid_image = None self.grid_norm = Normalize() ax = self.fig.add_subplot(111) ax.yaxis.tick_right() ax.yaxis.set_major_formatter(ScalarFormatter()) self.axis = {'default': ax} if specs: names = self.data_type['names'][1:] scales = specs.get('data_scale') if scales: self.plot_scales = { ('default' if i == 0 else 'axis-{}'.format(i)): scale for i, scale in enumerate(scales) } else: self.plot_scales = { ('default' if i == 0 else 'axis-{}'.format(i)): (name, ) for i, name in enumerate(names) } def get_axis_for(self, name): """ Return the axis for the named line :param name: line name :return: an axis object """ return self.lines[name].axes def add_axis(self, name=None, label=""): """ Add a named axis to the plot with the :param name: axis name :param label: axis label :return: matplotlib axis object """ name = 'axis-{}'.format(len(self.axis)) if not name else name default = self.axis.get('default') index = len(self.axis) + 1 axis_position = 1 / (self.axis_space**(index - 1)) self.fig.subplots_adjust(right=self.axis_space**index) ax = self.fig.add_axes(default.get_position(), sharex=default, frameon=False) ax.spines['right'].set_position(('axes', axis_position)) ax.yaxis.set_major_formatter(ScalarFormatter()) ax.set_frame_on(True) ax.patch.set_visible(False) ax.yaxis.tick_right() ax.yaxis.set_label_position('right') ax.set_ylabel(label) for label in ax.get_xticklabels(): label.set_visible(False) self.axis[name] = ax self.plot_scales[name] = () return ax def add_line(self, xpoints, ypoints, style='-', name='', lw=1, axis="default", alpha=1.0, color=None, redraw=True, markevery=[]): """ Add a named line to the plot :param xpoints: initial x axis values :param ypoints: initial y axis values :param style: matplotlib line style string :param name: line name, optional :param lw: line width :param axis: optional name of axis of add line to :param alpha: line transparency :param color: line color :param redraw: whether to redraw the line or note :param markevery: matplotlit 'markevery' parameter, set to None to show markers at every point """ assert (len(xpoints) == len(ypoints)) if axis not in self.axis: self.add_axis(axis) name = 'line-{}'.format(len(self.lines)) if not name else name color = self.colormap(len(self.lines)) if not color else color self.axis[axis].autoscale(False) xmin_current, xmax_current = self.axis[axis].get_xlim() ymin_current, ymax_current = self.axis[axis].get_ylim() line, = self.axis[axis].plot(xpoints, ypoints, '.', ls=style, lw=lw, markersize=8, label=name, alpha=alpha, markevery=markevery, color=color) # adjust axes limits as necessary xmin, xmax = misc.get_min_max(xpoints, ldev=0, rdev=0) ymin, ymax = misc.get_min_max(ypoints, ldev=1, rdev=1) xmin, xmax = min(xmin, xmin_current), max(xmax, xmax_current) ymin, ymax = min(ymin, ymin_current), max(ymax, ymax_current) line.axes.set_xlim(xmin, xmax) line.axes.set_ylim(ymin, ymax) self.lines[name] = line if name not in self.plot_scales[axis]: self.plot_scales[axis] += (name, ) if len(xpoints) > 1: self.values.add_func(name, xpoints, ypoints) if redraw: self.redraw() def add_point(self, row, redraw=True): """ Add a row of scan points to the data table :param row: sequence of values to add :param redraw: Whether to redraw the plot """ if numpy.nan in row: return self.values.append(row) x_name = self.data_type['names'][0] if self.grid_mode: # no lines for grid mode self.update_grid_data() elif not self.lines: count = 0 for axis, lines in self.plot_scales.items(): if axis != 'default': self.add_axis(name=axis) for line in lines: self.add_line(self.values.data[x_name], self.values.data[line], color=self.colormap(count), name=line, axis=axis, markevery=[-1]) count += 1 else: xmin, xmax = misc.get_min_max(self.values.data[x_name], ldev=0, rdev=0) for axis, lines in self.plot_scales.items(): ymin = ymax = None ax = None for name in lines: line = self.lines[name] line.set_data(self.values.data[x_name], self.values.data[name]) ax = line.axes ylo, yhi = misc.get_min_max(self.values.data[name], ldev=0.5, rdev=0.5) if ymin is None: ymin, ymax = ylo, yhi else: ymin, ymax = min(ymin, ylo), max(ymax, yhi) ymin, ymax = ymin, ymax # adjust axes limits as necessary if ax is not None: offset = (ymax - ymin) * .1 ax.set_ylim(ymin - offset, ymax + offset) ax.set_xlim(xmin, xmax) if len(self.lines) > 1: default = self.axis.get('default') xmin_current, xmax_current = default.get_xlim() default.set_xlim(min(xmin, xmin_current), max(xmax, xmax_current)) if redraw: self.redraw() def new_row(self, index): """ Prepare for A new row of data :param index: row index for next row """ if self.grid_mode and index > 1: # for slew grid scans, data needs to be padded/truncated y_name = self.data_type['names'][1] yo = self.values.data[y_name] x_size = (yo == yo[0]).sum() y_size = index pad = x_size * y_size - yo.shape[0] if pad == 0: return elif pad > 0: for i in range(pad): self.values.append(self.values.data[-1]) # padding elif pad < 0: self.values.length = x_size * y_size self.update_grid_data() def update_grid_data(self): """ Update the grid image values """ x_name, y_name, counts_name = self.data_type['names'][:3] xo = self.values.data[x_name] yo = self.values.data[y_name] counts = self.values.data[counts_name] x_min, x_max = xo.min(), xo.max() y_min, y_max = yo.min(), yo.max() self.grid_norm.autoscale(counts) xsize = (yo == yo[0]).sum() ysize = int(numpy.ceil(yo.shape[0] / xsize)) # pad unfilled values with nan blanks = xsize * ysize - counts.shape[0] if blanks: counts = numpy.pad(counts, (0, blanks), 'constant', constant_values=(numpy.nan, numpy.nan)) count_data = numpy.resize(counts, (ysize, xsize)) # flip alternate rows if self.grid_snake: count_data[1::2, :] = count_data[1::2, ::-1] self.grid_specs.update({ 'x': xo, 'y': yo, 'counts': count_data, }) extent = [ x_min, x_max, y_min, y_max, ] if self.grid_image is None: default = self.axis.get('default') self.grid_image = default.imshow( self.grid_specs['counts'], cmap=cm.get_cmap(GRID_COLORMAP), origin='lower', norm=self.grid_norm, extent=extent, aspect='auto', interpolation=GRID_INTERPOLATION, ) else: self.grid_image.set_data(self.grid_specs['counts']) self.grid_image.set_extent(extent) # set axis limits self.grid_image.axes.set_xlim(extent[:2]) self.grid_image.axes.set_ylim(extent[-2:]) self.redraw() def get_records(self): """ Return the data array manager for the plot """ return self.values def set_labels(self, title="", x_label="", y1_label=""): default = self.axis.get('default') default.set_xlabel(x_label, ha='right', va='top') default.set_ylabel(y1_label) default.xaxis.set_label_coords(1.0, -0.075) def set_time_labels(self, labels, fmt, maj_int, min_int): default = self.axis.get('default') default.xaxis.set_major_locator(MinuteLocator(interval=maj_int)) default.xaxis.set_minor_locator(SecondLocator(interval=min_int)) if len(default.xaxis.get_major_ticks()) < len(labels): labels.pop(0) default.set_xticklabels( [d != ' ' and d.strftime(fmt) or '' for d in labels]) def redraw(self): if not self.grid_mode: lines = list(self.lines.values()) labels = list(self.lines.keys()) self.axis['default'].legend(lines, labels, loc='upper left', bbox_to_anchor=(0, 1.075), ncol=8, fancybox=False, framealpha=0.0, edgecolor='inherit', borderaxespad=0, fontsize=9) self.canvas.draw_idle() def on_mouse_motion(self, event): default = self.axis.get('default') if event.inaxes and self.lines and not self.grid_mode: x, y = event.xdata, event.ydata if self.cursor_line is None: self.cursor_line = default.axvline(x, lw=1, color='#3a7ca8', antialiased=None) for axis, lines in self.plot_scales.items(): for name in lines: y_value = self.values(name, x) ax = self.axis[axis] if name in self.lines: line = self.lines[name] trans = transforms.blended_transform_factory( ax.get_yticklabels()[0].get_transform(), ax.transData) self.cursor_points[name] = ax.text( 1, y_value, "< {}".format(name), color=line.get_color(), transform=trans, ha="left", va="center") else: self.cursor_line.set_xdata(x) for axis, lines in self.plot_scales.items(): for name in lines: if name in self.lines: y_value = self.values(name, x) if name in self.cursor_points: self.cursor_points[name].set_position( (1, y_value)) self.canvas.draw_idle() else: if self.cursor_line: self.cursor_line.remove() self.cursor_line = None for name in list(self.cursor_points.keys()): mark = self.cursor_points.pop(name) mark.remove() self.canvas.draw_idle()
class ConanReportGraphsPresenter(Presenter[Gtk.Stack]): spinner: TemplateChild[Gtk.Spinner] = TemplateChild('spinner') figure_container = TemplateChild('figure_container') # type: TemplateChild[Gtk.Container] _analyses = () @inject def __init__(self, graphs_service: ConanReportGraphsService) -> None: self.graphs_service = graphs_service def after_view_init(self) -> None: self.figure = Figure(tight_layout=False) self.figure_canvas = FigureCanvas(self.figure) self.figure_canvas.props.hexpand = True self.figure_canvas.props.vexpand = True self.figure_canvas.props.visible = True self.figure_container.add(self.figure_canvas) self.figure_canvas_mapped = False self.figure_canvas.connect('map', self.canvas_map) self.figure_canvas.connect('unmap', self.canvas_unmap) self.figure_canvas.connect('size-allocate', self.canvas_size_allocate) left_ca_ax, right_ca_ax = self.figure.subplots(2, 1, sharex='col') left_ca_ax.set_ylabel('Left CA [°]') left_ca_ax.tick_params(axis='x', direction='inout') right_ca_ax.xaxis.set_ticks_position('both') right_ca_ax.set_ylabel('Right CA [°]') right_ca_ax.tick_params(axis='x', direction='inout') left_ca_ax.tick_params(axis='y', left=False, labelleft=False, right=True, labelright=True) right_ca_ax.tick_params(axis='y', left=False, labelleft=False, right=True, labelright=True) # Format the labels to scale to the right units. left_ca_ax.get_yaxis().set_major_formatter( FuncFormatter(lambda x, _: '{:.4g}'.format(math.degrees(x))) ) right_ca_ax.get_yaxis().set_major_formatter( FuncFormatter(lambda x, _: '{:.4g}'.format(math.degrees(x))) ) left_ca_ax.grid(axis='x', linestyle='--', color="#dddddd") left_ca_ax.grid(axis='y', linestyle='-', color="#dddddd") right_ca_ax.grid(axis='x', linestyle='--', color="#dddddd") right_ca_ax.grid(axis='y', linestyle='-', color="#dddddd") self._left_ca_ax = left_ca_ax self._left_ca_line = left_ca_ax.plot([], marker='o', color='#0080ff')[0] self._right_ca_line = right_ca_ax.plot([], marker='o', color='#ff8000')[0] self.graphs_service.connect('notify::left-angle', self.data_changed) self.graphs_service.connect('notify::right-angle', self.data_changed) self.data_changed() def canvas_map(self, *_) -> None: self.figure_canvas_mapped = True self.figure_canvas.draw_idle() def canvas_unmap(self, *_) -> None: self.figure_canvas_mapped = False def canvas_size_allocate(self, *_) -> None: self.figure.tight_layout(pad=2.0, h_pad=0) self.figure.subplots_adjust(hspace=0) @install @GObject.Property def analyses(self) -> Sequence[ConanAnalysisJob]: return self._analyses @analyses.setter def analyses(self, analyses: Iterable[ConanAnalysisJob]) -> None: self._analyses = tuple(analyses) self.graphs_service.analyses = analyses def data_changed(self, *_) -> None: left_angle_data = self.graphs_service.left_angle right_angle_data = self.graphs_service.right_angle if left_angle_data.shape[1] <= 1 or right_angle_data.shape[1] <=1: self.show_waiting_placeholder() return self.hide_waiting_placeholder() self._left_ca_line.set_data(left_angle_data) self._right_ca_line.set_data(right_angle_data) self.update_xlim() self._left_ca_line.axes.relim() self._left_ca_line.axes.margins(y=0.1) self._right_ca_line.axes.relim() self._right_ca_line.axes.margins(y=0.1) self.figure_canvas.draw() def update_xlim(self) -> None: all_xdata = ( *self._left_ca_line.get_xdata(), *self._right_ca_line.get_xdata(), ) if len(all_xdata) <= 1: return xmin = min(all_xdata) xmax = max(all_xdata) if xmin == xmax: return self._left_ca_ax.set_xlim(xmin, xmax) def show_waiting_placeholder(self) -> None: self.host.set_visible_child(self.spinner) self.spinner.start() def hide_waiting_placeholder(self) -> None: self.host.set_visible_child(self.figure_container) self.spinner.stop()
class Calculator(): def __init__(self): self.history_ex = ["","","","","","","","","",""] self.hisotry_page = [0,0,0,0,0,0,0,0,0,0] self.x = [] self.y = [] self.init_gui() def init_gui(self): self.builder = Gtk.Builder() self.builder.add_from_file("finally.glade") self.builder.connect_signals( { "window_destroy" : self.window_destroy, "press_button" : self.press_button, "clear_text" : self.clear_text, "remove_last_char": self.remove_last_char, "calculate" : self.calculate, "switch_page" : self.switch_page, "num_base_change" : self.num_base_change, "fix_cursor" : self.fix_cursor, "enable_textview" : self.enable_textview, "disable_textview": self.disable_textview, "prog_calc" : self.prog_calc, "back_to_future" : self.back_to_future, "plot" : self.plot } ) self.window = self.builder.get_object("main_window") self.window.set_size_request(250,305) self.window.set_title("The Calculator") self.window.set_icon_from_file("/usr/share/pixmaps/thecalculator-icon.png") self.text_buff = self.builder.get_object("class_17").get_buffer() # Access buffer from TextView self.builder.get_object("class_17").grab_focus() self.builder.get_object("radiobutton3").set_active(True) self.num_base_change(self.builder.get_object("radiobutton3")) ############### PLOT FUNCTION ############## sw = self.builder.get_object("scrolledwindow1") sw2 = self.builder.get_object("scrolledwindow2") fig = Figure(figsize=(5,5),dpi=120) self.ax = fig.add_subplot(111) self.x = arange(-3.1415,3.1415,0.01) self.y = sin(self.x) self.ax.plot(self.x,self.y,label="sin(x)") self.ax.set_xlim(-3.2,3.2) self.ax.set_ylim(-1.2,1.2) self.ax.grid(True) fig.set_size_inches(9.5, 5.5, forward=True) fig.tight_layout() self.canvas = FigureCanvas(fig) sw.add_with_viewport(self.canvas) self.canvas.show() toolbar = NavigationToolbar(self.canvas, self.window) sw2.add_with_viewport(toolbar) def plot(self,w,data=None,from_x=-10,to_x=10): text = self.builder.get_object("plot_1").get_text() y_lim = [] # ([+-]?\d*\.\d+|[+-]?\d+) # ([+-]?\d{1,})\) c = search("x_lim=\(([+-]?\d*\.\d+|[+-]?\d+),([+-]?\d*\.\d+|[+-]?\d+)",text) if (c): num1 = float(c.group(1)) num2 = float(c.group(2)) print(num1),print(type(num1)) print(num2),print(type(num2)) if ( num1 < num2 ): print("fees") from_x=num1 to_x=num2 else: from_x=num2 to_x=num1 c = search("y_lim=\(([+-]?\d*\.\d+|[+-]?\d+),([+-]?\d*\.\d+|[+-]?\d+)",text) if (c): num1 = float(c.group(1)) num2 = float(c.group(2)) if ( num1 < num2 ): y_lim.append(num1) y_lim.append(num2) else: y_lim.append(num2) y_lim.append(num1) self.x = [] self.y = [] self.x = arange(from_x,to_x,0.01) for x in self.x: try: string = text.split(",")[0].replace("x",str("(%f)"%(x))) tmp_number = solve_expresion(string) if ( type(tmp_number) != str ): self.y.append(tmp_number) else: self.y.append(None) continue except TypeError: self.y.append(None) except Exception as e: print(e) self.builder.get_object("plot_1").set_text("Invalid synatax, use variable x") self.y = array(self.y) print(len(self.x)) print(len(self.y)) self.ax.plot(self.x,self.y) self.ax.set_xlim(from_x,to_x) if ( len(y_lim) == 2 ): print("ase") self.ax.set_ylim(y_lim[0],y_lim[1]) self.ax.grid(True) self.canvas.draw_idle() # c == None podminka # c = re.match("(from=[-+]?(\d{1,}) to=[-+]?(\d{1,}))|(to=[-+]?(\d{1,}) from=[-+]?(\d{1,}))" #group(0) = founded string #group(1) = fouund first variante #group(2) = number from #group(3) = number to #group(4) = found second variante #group(5) = number to #group(6) = number from def back_to_future(self,w,data=None): if ( w.get_label() != "" ): self.text_buff.set_text(w.get_label()) self.builder.get_object("notebook1").set_current_page(self.hisotry_page[self.history_ex.index(w.get_label())]) def add_to_history(self,expresion,page): if ( expresion in self.history_ex): return if ( len(self.history_ex) == 10 ): del(self.history_ex[0]) del(self.hisotry_page[0]) self.history_ex.append(expresion) self.hisotry_page.append(page) else: self.history_ex.append(expresion) self.hisotry_page.append(page) o = 9 for i in self.history_ex: self.builder.get_object("history_"+str(o)).set_text(i) o-=1 def solve_prog(self,base_string): try: base_dictionary = {"BIN":2,"OCT":8,"DEC":10,"HEX":16} base_string=base_string.replace("xor","^") for i in base_string: if i not in ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","~","^","&","|","+","-","/","*"," ",]: return "Invalid input syntax" insert_base = base_dictionary[self.get_radio_state("in")] output_base = base_dictionary[self.get_radio_state("out")] base_string = prog_transfer(base_string,insert_base) output = eval(base_string, {"__builtins__":None}) if output_base == insert_base: output = output elif output_base == 2: output = bin(int(str(output)))[2:] elif output_base == 8: output = oct(int(str(output)))[2:] elif output_base == 10: output = int(str(output)) elif output_base == 16: output = hex(int(str(output)))[2:] return str(output).upper() except SyntaxError: return "Invalid input syntax" except ValueError: return "Invalid base" except: return "Some Error" def prog_calc(self,w,d=None): text = self.text_buff.get_text(self.text_buff.get_start_iter(),self.text_buff.get_end_iter(),False) if ( text == "" ): return text = text.splitlines() self.text_buff.set_text( text[0] + '\n' + str( self.solve_prog(text[0]) ) ) self.text_buff.place_cursor( self.text_buff.get_iter_at_line_offset(0,len(text[0])) ) def enable_textview(self,w,e): page = self.builder.get_object("notebook1").get_current_page() textview = ("class_17", "science_30", "prog_28") if ( page in [0,1,2] ): if ( e.keyval == Gdk.KEY_Return or e.keyval == Gdk.KEY_KP_Enter): self.builder.get_object( textview[page] ).set_editable(True) if ( page == 2 ): self.prog_calc(w) else: self.calculate(w) def disable_textview(self,w,e): # tuple with name of all textview page = self.builder.get_object("notebook1").get_current_page() textview = ("class_17", "science_30", "prog_28") if ( page in [0,1,2] ): if ( e.keyval == Gdk.KEY_Return or e.keyval == Gdk.KEY_KP_Enter): self.builder.get_object(textview[page]).set_editable(False) def fix_cursor(self,widget,data=None): text = self.text_buff.get_text(self.text_buff.get_start_iter(),self.text_buff.get_end_iter(),False) if ('\n' in text): if ( len(text.splitlines()) > 2): text = text.replace("\n","",1) self.text_buff.set_text(text) text = text.splitlines()[0] if ( self.text_buff.props.cursor_position > len(text) ): self.text_buff.place_cursor( self.text_buff.get_iter_at_line_offset(0,len(text)) ) def calculate(self,widget,data=None): # except for plot text = self.text_buff.get_text(self.text_buff.get_start_iter(),self.text_buff.get_end_iter(),False) if ( text == "" ): return text = text.splitlines() self.text_buff.set_text( text[0] + '\n' + str( solve_expresion(text[0]) ) ) self.text_buff.place_cursor( self.text_buff.get_iter_at_line_offset(0,len(text[0])) ) self.add_to_history(text[0],self.builder.get_object("notebook1").get_current_page()) def num_base_change(self,widget,data=None): if ( widget.get_active() == True): if ( widget.get_label() == "BIN" ): base=2 elif ( widget.get_label() == "OCT" ): base=8 elif ( widget.get_label() == "DEC" ): base=10 elif (widget.get_label() == "HEX" ): base=16 for i in range(16): if ( i < base ): self.builder.get_object("prog_"+str(i)).set_sensitive(True) else: self.builder.get_object("prog_"+str(i)).set_sensitive(False) def get_radio_state(self,group): if ( group == "in" ): g = self.builder.get_object("radiobutton1").get_group() elif ( group == "out" ): g = self.builder.get_object("radiobutton5").get_group() for i in g: if ( i.get_active() ): return i.get_label() def clear_text(self,widget,data=None): self.text_buff.set_text("") def window_destroy(self,widget,data=None): Gtk.main_quit() def remove_last_char(self,widget,data=None): text = self.text_buff.get_text(self.text_buff.get_start_iter(),self.text_buff.get_end_iter(),False) l_text = list(text) cursor_pos = self.text_buff.props.cursor_position-1 del(l_text[cursor_pos]) s = "".join(l_text) self.text_buff.set_text(s) self.text_buff.place_cursor(self.text_buff.get_iter_at_line_offset(0,cursor_pos)) def show_tab(self,name,number_of_item): for i in range(number_of_item+1): self.builder.get_object(name+"_"+str(i)).show() def hide_tab(self,name,number_of_item): for i in range(number_of_item+1): self.builder.get_object(name+"_"+str(i)).hide() # @TODO focus switch textview def switch_page(self,widget,p1,p2): if ( widget.get_current_page() != 4): self.text_buff.set_text("") modes = { "class" : 0, "science" : 1, "prog" : 2, "plot" : 3, "history" : 4, "authors" : 5 } number_of_item = (19,30,29,2,19,0) size = ( (300,330),(450,320),(450,320),(800,600),(480,330),(302,330) ) for i in modes: if ( p2 != modes[i] and i!="authors"): self.hide_tab(i,number_of_item[modes[i]]) else: self.show_tab(i,number_of_item[modes[i]]) self.window.set_size_request(size[p2][0],size[p2][1]) self.window.resize(size[p2][0],size[p2][1]) def press_button(self,widget,data=None): char = widget.get_label() functions = {"√":"sqrt()","x!":"!","ln":"ln()","abs":"||","sin":"sin()","cos":"cos()","tg":"tan()","cotg":"cotg()"} if char in ["0","1","2","3","4","5","6","7","8","9","+","-","/","*",",","e","π","%","^","&","|","xor","~","A","B","C","D","E","F"]: self.text_buff.insert_at_cursor(char) elif char in functions: self.text_buff.insert_at_cursor(functions[char]) if ( char != "x! "): text = self.text_buff.get_text(self.text_buff.get_start_iter(),self.text_buff.get_end_iter(),False) text = text.splitlines() self.text_buff.place_cursor( self.text_buff.get_iter_at_line_offset(0,len(text[0])-1) ) def main(self): self.window.show() Gtk.main()
class AppCanvas(): def __init__(self): self.curvesCounter = 0 self.activeCurve = None self.pointOfRotation = None self.getScaleWidget = None self.getAngleWidget = None fig = plt.figure( figsize=[9, 6], dpi=100, ) self.ax = fig.add_subplot() #plt.axis([0,300,0,200],'scaled') plt.axis([0, 300, 0, 200]) self.canvas = FigureCanvas(fig) def get_canvas(self): return self.canvas def get_ax(self): return self.ax def set_activeCurve(self, activeCurve): self.activeCurve = activeCurve def set_getScaleWidget(self, getScaleWidget): self.getScaleWidget = getScaleWidget def set_getAngleWidget(self, getAngleWidget): self.getAngleWidget = getAngleWidget def pick_curve(self, event): lineName = event.artist.get_label() if lineName == self.activeCurve.linePlot.get_label(): self.drag_curve_active = self.canvas.mpl_connect( 'motion_notify_event', self.drag_curve) self.drop_curve_active = self.canvas.mpl_connect( 'button_release_event', self.drop_curve) self.mouseX = event.mouseevent.xdata self.mouseY = event.mouseevent.ydata #self.activeCurve.set_working_accurancy() def drop_curve(self, event): if self.drag_curve_active != None: if event.inaxes != None: self.activeCurve.move_curve(event.xdata - self.mouseX, event.ydata - self.mouseY) self.canvas.mpl_disconnect(self.drag_curve_active) self.canvas.mpl_disconnect(self.drop_curve_active) #self.activeCurve.set_normal_accurancy() self.canvas.draw_idle() self.drag_curve_active = None self.drop_curve_active = None def drag_curve(self, event): if event.inaxes != None: self.activeCurve.move_curve(event.xdata - self.mouseX, event.ydata - self.mouseY) self.mouseX = event.xdata self.mouseY = event.ydata self.canvas.draw_idle() def resize_curve(self, event): scale = self.getScaleWidget.get_scale_value() self.getScaleWidget.reset_scale_value() if self.activeCurve != None: self.activeCurve.resize_curve(scale / 100.0) self.canvas.draw_idle() def change_line_width(self, event): scale = self.getScaleWidget.get_scale_value() self.getScaleWidget.reset_scale_value() if self.activeCurve != None: self.activeCurve.change_line_width(scale / 100.0) self.canvas.draw_idle() def change_curve(self, event): scale = self.getScaleWidget.get_scale_value() self.getScaleWidget.reset_scale_value() if self.activeCurve != None: self.activeCurve.resize_curve(scale / 100.0) self.canvas.draw_idle() def rotate_curve(self, event): angle = self.getAngleWidget.get_entry_text() if self.pointOfRotation != None: s = self.pointOfRotation[0].get_xdata()[0] t = self.pointOfRotation[0].get_ydata()[0] else: s, t = 0, 0 try: if self.activeCurve != None and int(angle) < 360 and int( angle) > -360: angle = int(angle) if angle < 0: angle += 360 self.activeCurve.rotate_curve(angle, s, t) self.canvas.draw_idle() except: pass def add_point_of_rotation(self, event): self.delete_point_of_rotation() self.pointOfRotation = self.ax.plot([event.xdata], [event.ydata], 'ko') self.canvas.draw_idle() def delete_point_of_rotation(self): if self.pointOfRotation != None: self.pointOfRotation[0].remove() del self.pointOfRotation self.pointOfRotation = None self.canvas.draw_idle() def select_point(self, event): lineName = event.artist.get_label() if lineName == self.activeCurve.pointsPlot.get_label(): self.activeCurve.activate_point(event.mouseevent.xdata, event.mouseevent.ydata) self.canvas.draw_idle() def delete_point(self, event): lineName = event.artist.get_label() if lineName == self.activeCurve.pointsPlot.get_label(): self.activeCurve.delete_point(event.mouseevent.xdata, event.mouseevent.ydata) self.canvas.draw_idle() def add_point(self, event): if self.activeCurve != None and event.inaxes != None: self.activeCurve.add_point(event.xdata, event.ydata) self.canvas.draw_idle() def pick_point(self, event): self.drag_point_active = self.canvas.mpl_connect( 'motion_notify_event', self.drag_point) self.activeCurve.set_working_accurancy() def drop_point(self, event): self.canvas.mpl_disconnect(self.drag_point_active) if self.activeCurve != None: self.activeCurve.disactivate_point() self.activeCurve.set_normal_accurancy() self.canvas.draw_idle() def drag_point(self, event): if event.inaxes != None: self.activeCurve.move_point(event.xdata, event.ydata) self.canvas.draw_idle()
class IFTReportGraphsPresenter(Presenter[Gtk.Stack]): spinner: TemplateChild[Gtk.Spinner] = TemplateChild('spinner') figure_container: TemplateChild[Gtk.Container] = TemplateChild( 'figure_container') _analyses = () @inject def __init__(self, graphs_service: IFTReportGraphsService) -> None: self.graphs_service = graphs_service def after_view_init(self) -> None: figure = Figure(tight_layout=False) self.figure = figure self.figure_canvas = FigureCanvas(figure) self.figure_canvas.props.hexpand = True self.figure_canvas.props.vexpand = True self.figure_canvas.props.visible = True self.figure_container.add(self.figure_canvas) self.figure_canvas_mapped = False self.figure_canvas.connect('map', self.hdl_canvas_map) self.figure_canvas.connect('unmap', self.hdl_canvas_unmap) self.figure_canvas.connect('size-allocate', self.hdl_canvas_size_allocate) self.ift_axes, volume_axes, surface_area_axes = figure.subplots( 3, 1, sharex='col') self.ift_axes.set_ylabel('IFT [mN/m]') self.ift_axes.tick_params(axis='x', direction='inout') volume_axes.xaxis.set_ticks_position('both') volume_axes.tick_params(axis='x', direction='inout') volume_axes.set_ylabel('V [mm³]') surface_area_axes.xaxis.set_ticks_position('both') surface_area_axes.tick_params(axis='x', direction='inout') surface_area_axes.set_ylabel('SA [mm²]') self.ift_axes.tick_params(axis='y', left=False, labelleft=False, right=True, labelright=True) volume_axes.tick_params(axis='y', left=False, labelleft=False, right=True, labelright=True) surface_area_axes.tick_params(axis='y', left=False, labelleft=False, right=True, labelright=True) self.ift_axes.grid(axis='x', linestyle='--', color="#dddddd") volume_axes.grid(axis='x', linestyle='--', color="#dddddd") surface_area_axes.grid(axis='x', linestyle='--', color="#dddddd") self.ift_axes.grid(axis='y', linestyle='-', color="#dddddd") volume_axes.grid(axis='y', linestyle='-', color="#dddddd") surface_area_axes.grid(axis='y', linestyle='-', color="#dddddd") # 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))) 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.graphs_service.connect('notify::ift', self.hdl_model_data_changed) self.graphs_service.connect('notify::volume', self.hdl_model_data_changed) self.graphs_service.connect('notify::surface-area', self.hdl_model_data_changed) self.hdl_model_data_changed() def hdl_canvas_map(self, *_) -> None: self.figure_canvas_mapped = True self.figure_canvas.draw_idle() def hdl_canvas_unmap(self, *_) -> None: self.figure_canvas_mapped = False def hdl_canvas_size_allocate(self, *_) -> None: self.figure.tight_layout(pad=2.0, h_pad=0) self.figure.subplots_adjust(hspace=0) @install @GObject.Property def analyses(self) -> Sequence[PendantAnalysisJob]: return self._analyses @analyses.setter def analyses(self, analyses: Iterable[PendantAnalysisJob]) -> None: self._analyses = tuple(analyses) self.graphs_service.set_analyses(analyses) def hdl_model_data_changed(self, *args) -> None: ift_data = self.graphs_service.ift volume_data = self.graphs_service.volume surface_area_data = self.graphs_service.surface_area if (len(ift_data[0]) <= 1 and len(volume_data[0]) <= 1 and len(surface_area_data[0]) <= 1): self.show_waiting_placeholder() return self.hide_waiting_placeholder() self.set_ift_data(ift_data) self.set_volume_data(volume_data) self.set_surface_area_data(surface_area_data) if self.figure_canvas_mapped: self.figure.tight_layout(pad=2.0, h_pad=0) self.figure.subplots_adjust(hspace=0) self.figure_canvas.draw_idle() def show_waiting_placeholder(self) -> None: self.host.set_visible_child(self.spinner) self.spinner.start() def hide_waiting_placeholder(self) -> None: self.host.set_visible_child(self.figure_container) self.spinner.stop() 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) 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) 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) 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)
class App: def __init__(self): self.xsize, self.ysize = 600, 600 self.xmin, self.xmax = -1.5, 1.5 self.ymin, self.ymax = -1.5, 1.5 self.x, self.y = (-0.4, 0.6) self.n = 2 self.zmax = 4.0 self.niter = 256 self.dpi = 100 self.cmap = 'Set3' self.digits = 12 self.entries = {} # create app interface self.setup_interface() self.display_image() def setup_interface(self): # create main window self.main_window = Gtk.Window(title="Julia Fractals") self.main_window.set_border_width(10) self.main_window.connect("delete-event", Gtk.main_quit) # setup header bar self.setup_header_bar() box = Gtk.Box(orientation='horizontal', spacing=10) self.main_window.add(box) sep = Gtk.Separator(orientation='vertical') box.add(sep) # setup left panel -- container with image parameters self.left_box = Gtk.Box(orientation='vertical', spacing=10) self.setup_left_box() box.add(self.left_box) sep = Gtk.Separator(orientation='vertical') box.add(sep) # setup right panel -- container with image parameters self.right_box = Gtk.Box(orientation='vertical', spacing=10) self.setup_right_box() box.add(self.right_box) for name, entry in self.entries.items(): # copy current values to the defaults setattr(self, name + "_default", getattr(self, name)) self.set_entry_value(entry) sep = Gtk.Separator(orientation='vertical') box.add(sep) # setup image panel -- container with image output self.image_box = Gtk.Box(orientation='vertical') self.setup_image_box() box.add(self.image_box) def setup_header_bar(self): ''' ''' self.hb = Gtk.HeaderBar() self.hb.set_show_close_button(True) self.hb.props.title = "Julia Fractal" self.main_window.set_titlebar(self.hb) self.button_save = Gtk.Button(label='Save') self.button_save.connect("clicked", self.on_button_save_clicked) self.hb.pack_end(self.button_save) def setup_left_box(self): # box for box = Gtk.Box(orientation='vertical', spacing=6) self.left_box.pack_start(box, False, False, 0) sep = Gtk.Separator(orientation='horizontal') box.add(sep) self.namecombo = Gtk.ComboBoxText() self.namecombo.connect("changed", self.on_namecombo_changed) for item in ['Julia', 'Mandelbrot']: self.namecombo.append_text(item) self.namecombo.set_active(0) box.pack_start(self.namecombo, True, True, 0) label = Gtk.Label("z = z**n + C", halign=Gtk.Align.START) box.pack_start(label, True, True, 0) label = Gtk.Label("C = x + yi", halign=Gtk.Align.START) box.pack_start(label, True, True, 0) names = ['n', 'x', 'y', 'zmax', 'niter'] entries = {name: self.create_labeled_entry(name, box, orientation='vertical', spacing=5, xpad=8) for name in names} self.entries.update(entries) sep = Gtk.Separator(orientation='horizontal') box.add(sep) # apply rotation button_apply = Gtk.Button(label='Apply') button_apply.connect("clicked", self.on_button_apply_clicked) self.left_box.pack_start(button_apply, False, False, 0) # reset rotation button_reset = Gtk.Button(label='Reset') button_reset.connect("clicked", self.on_button_reset_clicked) self.left_box.pack_start(button_reset, False, False, 0) def setup_right_box(self): # box for box = Gtk.Box(orientation='vertical', spacing=10) self.right_box.pack_start(box, False, False, 0) sep = Gtk.Separator(orientation='horizontal') box.add(sep) names = ['xmin', 'xmax', 'ymin', 'ymax', 'xsize', 'ysize'] entries = {name: self.create_labeled_entry(name, box, orientation='horizontal') for name in names} self.entries.update(entries) sep = Gtk.Separator(orientation='horizontal') box.add(sep) label = Gtk.Label("Colormap", halign=Gtk.Align.START) box.pack_start(label, True, True, 0) cmapstore = Gtk.ListStore(str, GdkPixbuf.Pixbuf) cmaps = sorted(pl.cm.datad) for item in cmaps: cmapstore.append([item, None]) self.cmapcombo = Gtk.ComboBox.new_with_model(cmapstore) self.cmapcombo.connect("changed", self.on_cmapcombo_changed) self.cmapcombo.set_active(0) renderer = Gtk.CellRendererText() self.cmapcombo.pack_start(renderer, True) self.cmapcombo.add_attribute(renderer, "text", 0) renderer = Gtk.CellRendererPixbuf() self.cmapcombo.pack_start(renderer, False) self.cmapcombo.add_attribute(renderer, "pixbuf", 1) box.pack_start(self.cmapcombo, True, True, 0) def setup_image_box(self): xx = self.xsize / float(self.dpi) # inches yy = self.ysize / float(self.dpi) # inches # TODO: make it resizable self.fig = Figure(figsize=(xx, yy), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea # setup drawing canvas self.canvas.set_size_request(self.xsize, self.ysize) self.canvas.connect('button-press-event' , self.on_canvas_button_press) self.canvas.connect('button-release-event', self.on_canvas_button_release) self.canvas.connect('motion-notify-event' , self.on_canvas_motion_notify) self.image_box.add(self.canvas) def create_labeled_entry(self, name, parent, orientation='horizontal', spacing=10, xpad=0): box = Gtk.Box(orientation=orientation, spacing=spacing) parent.pack_start(box, True, True, 0) label = Gtk.Label(label=name, halign=Gtk.Align.START, xpad=xpad) box.pack_start(label, True, False, 0) entry = Gtk.Entry(name=name) box.pack_start(entry, True, True, 0) return entry def set_entry_value(self, entry): name = entry.get_name() value = getattr(self, name) if int(value) == value: value_str = "{0}".format(value) else: value_str = "{0:.{1}f}".format(value, self.digits).rstrip("0") entry.set_text(value_str) def get_entry_value(self, entry, dtype): text = entry.get_text() try: val = float(text) if dtype == int: val = int(val) except ValueError: val = None return val def on_button_save_clicked(self, widget): pass def on_cmapcombo_changed(self, widget): tree_iter = widget.get_active_iter() if tree_iter != None: model = widget.get_model() name, image = model[tree_iter] self.cmap = name if hasattr(self, 'fig'): self.display_image() self.canvas.draw_idle() def on_namecombo_changed(self, widget): text = widget.get_active_text() print(text) if text == 'Mandelbrot': self.x = 0 self.y = 0 self.set_entry_value(self.entries['x']) self.set_entry_value(self.entries['y']) if hasattr(self, 'fig'): self.update_image() def on_button_apply_clicked(self, widget): self.update_image() def on_button_reset_clicked(self, widget): for name, entry in self.entries.items(): setattr(self, name, getattr(self, name + "_default")) self.set_entry_value(entry) def on_canvas_button_release(self, widget, event): mapping = {1: 0.75, 3: 1.5} if event.button in mapping: if (self.posx1, self.posy1) == (self.posx2, self.posy2): factor = mapping[event.button] xc = np.interp(event.x, [0, self.xsize-1], [self.xmin, self.xmax]) yc = np.interp(event.y, [0, self.ysize-1], [self.ymin, self.ymax]) xlen = factor * (self.xmax - self.xmin) ylen = factor * (self.ymax - self.ymin) self.xmin = xc - xlen/2.0 self.xmax = xc + xlen/2.0 self.ymin = yc - ylen/2.0 self.ymax = yc + ylen/2.0 else: self.xmin = self.posx1 self.xmax = self.posx2 self.ymin = self.posy1 self.ymax = self.posy2 for entry in self.entries.values(): self.set_entry_value(entry) self.update_image() def on_canvas_motion_notify(self, widget, event): self.posx2 = np.interp(event.x, [0, self.xsize-1], [self.xmin, self.xmax]) self.posy2 = np.interp(event.y, [0, self.ysize-1], [self.ymin, self.ymax]) if event.state & Gdk.EventMask.BUTTON_PRESS_MASK: if event.state & Gdk.ModifierType.CONTROL_MASK: self.posy2 = self.posy1 + self.posx2 - self.posx1 if hasattr(self, 'rectangle1'): if self.rectangle1 in self.fig.gca().patches: self.rectangle1.remove() self.rectangle2.remove() self.rectangle1 = Rectangle((self.posx2, (self.ymax + self.ymin) - self.posy2), (self.posx1 - self.posx2), -(self.posy1 - self.posy2), fill=False, edgecolor='white', linewidth=0.5) self.rectangle2 = Rectangle((self.posx2, (self.ymax + self.ymin) - self.posy2), (self.posx1 - self.posx2), -(self.posy1 - self.posy2), fill=False, edgecolor='black', linestyle='dotted', linewidth=0.5) ax = self.fig.gca() ax.add_patch(self.rectangle1) ax.add_patch(self.rectangle2) self.canvas.draw_idle() def on_canvas_button_press(self, widget, event): self.posx1 = np.interp(event.x, [0, self.xsize-1], [self.xmin, self.xmax]) self.posy1 = np.interp(event.y, [0, self.ysize-1], [self.ymin, self.ymax]) self.posx2 = self.posx1 self.posy2 = self.posy1 #self.posx = self.transform_x(event.x) #self.posy = self.transform_y(event.y) def run(self): self.main_window.show_all() Gtk.main() def transform_x(self, xval): return two_point_interp(xval, 0, self.xsize-1, self.xmin, self.xmin) def transform_y(self, yval): return two_point_interp(yval, 0, self.ysize-1, self.ymin, self.ymin) def compute_image(self): C = complex(self.x, self.y) xlim = (self.xmin, self.xmax) ylim = (self.ymin, self.ymax) zz = complex_grid(xlim, ylim, self.xsize, self.ysize) text = self.namecombo.get_active_text() if text == 'Julia': return fractal(zz, C, self.n, self.zmax, self.niter) elif text == 'Mandelbrot': return fractal(C, zz, self.n, self.zmax, self.niter) def display_image(self): # plot and save the image img = self.compute_image() # clear previous figure self.fig.clf() # setup plot ax = Axes(self.fig, [0, 0, 1, 1]) # remove outer border ax.set_axis_off() # disable axis ax.set_xlim((self.xmin, self.xmax)) ax.set_ylim((self.ymin, self.ymax)) ax.set_xticklabels([]) ax.set_yticklabels([]) ax.imshow(img, cmap=pl.get_cmap(self.cmap), interpolation='nearest', extent=[self.xmin, self.xmax, self.ymin, self.ymax], origin='upper', aspect=1.0) self.fig.add_axes(ax) def update_image(self): for name, entry in self.entries.items(): dtype = int if name in ['n', 'niter', 'xsize', 'ysize'] else float val = self.get_entry_value(entry, dtype) if val is not None: setattr(self, name, val) for entry in self.entries.values(): self.set_entry_value(entry) self.display_image() self.canvas.draw_idle()