def toggle_copy_mode(self, button): state_messages = { 0: 'Copy mode off', 1: 'Copy mode on | x-value', 2: 'Copy mode on | y-value', } if button.get_active(): if button.get_label() == 'x': self.cmode_state = 1 self.mpl_cursor = Cursor( self.axis, lw=1, c='red', linestyle='--' ) self.cid = self.canvas.mpl_connect( 'button_press_event', self.get_coord_click ) elif button.get_label() == 'y': self.cmode_state = 2 self.mpl_cursor = Cursor( self.axis, lw=1, c='red', linestyle='--' ) self.cid = self.canvas.mpl_connect( 'button_press_event', self.get_coord_click ) else: # copy mode off self.cmode_state = 0 self.mpl_cursor = None self.canvas.mpl_disconnect(self.cid) self.statusbar.push( self.statusbar.get_context_id('cmode_state'), state_messages[self.cmode_state] )
def __init__(self, fid): if not Plot._is_flat_iter(fid.data): raise ValueError('data must be flat iterable.') if fid.data == [] or fid.data == None: raise ValueError('data must exist.') self.fid = fid self.fig = pylab.figure(figsize=[15, 7.5]) self.phases = numpy.array([0.0, 0.0]) self.y = 0.0 self.ax = self.fig.add_subplot(111) self.ax.plot(self.fid.data, color='k', linewidth=1.0) self.ax.hlines(0, 0, len(self.fid.data)-1) self.ax.set_xlim([0, len(self.fid.data)]) xtcks = numpy.linspace(0,1,10)*len(self.fid.data) xtcks[-1] = xtcks[-1]-1 self.ax.set_xticks(xtcks) self.ax.set_xlabel('PPM (%.2f MHz)'%(self.fid._params['reffrq'])) self.ax.set_xticklabels([numpy.round(self.fid._ppm[int(i)], 1) for i in xtcks]) ylims = numpy.array([-6, 6])*numpy.array([max(self.ax.get_ylim())]*2) self.ax.set_ylim(ylims) self.ax.grid() self.visible = True self.canvas = self.ax.figure.canvas self.canvas.mpl_connect('motion_notify_event', self.onmove) self.canvas.mpl_connect('button_press_event', self.press) self.canvas.mpl_connect('button_release_event', self.release) self.pressv = None self.buttonDown = False self.prev = (0, 0) self.ax.text(0.05 *self.ax.get_xlim()[1],0.7 *self.ax.get_ylim()[1],'phasing\nleft - zero-order\nright - first order') cursor = Cursor(self.ax, useblit=True, color='k', linewidth=0.5) cursor.horizOn = False pylab.show()
def getting_correspondences(i, r): inp = (plt.figure(1)).add_subplot(1, 1, 1) inp.imshow(i) inp = Cursor(inp, useblit=True, color='red', linewidth=1) ref = (plt.figure(2)).add_subplot(1, 1, 1) ref.imshow(r) ref = Cursor(ref, useblit=True, color='blue', linewidth=1) i = 0 input_points = np.empty((2,0)) ref_points = np.empty((2,0)) try: while True: plt.figure(1) input_point = plt.ginput(n = 1, timeout = 0) input0 = input_point[0][0] input1 = input_point[0][1] plt.annotate(str(i),(input0, input1)) plt.plot(input0, input1, 'bo') input_points = np.hstack((input_points,np.array([[input0], [input1]]))) plt.figure(2) ref_point = plt.ginput(n = 1, timeout = 0) ref0 = ref_point[0][0] ref1 = ref_point[0][1] plt.annotate(str(i),(ref0, ref1)) plt.plot(ref0, ref_point[0][1], 'go') ref_points = np.hstack((ref_points,np.array([[ref0],[ref1]]))) i += 1 except KeyboardInterrupt: return input_points, ref_points
def my_bode_diagram(self, analysis=None, aim_curve_data=None, model=None): """绘图函数,利用Circuit.simulator.ac分析结果,进行matplotlib绘图,曲线为analysis.output端口响应数据""" figure = plt.figure(1, (12, 6), clear=False) plt.title("my notch filter") ax1 = plt.subplot(211) ax2 = plt.subplot(212, sharex=ax1) if analysis: if model == 'one_op': gain = 20 * np.log10(np.absolute(analysis.output)) phase = (np.angle(analysis.output, deg=False) * 180 / np.pi) else: gain = 20 * np.log10(np.absolute(analysis.op02_out)), phase = (np.angle(analysis.op02_out, deg=False) * 180 / np.pi), frequency = analysis.frequency self.my_plotter(ax1, frequency, gain[0], 'gain', {'marker': None}) self.my_plotter(ax2, frequency, phase[0], 'phase', {'marker': None}) # 如果用户导入excel参考数据,绘制参考数据 if aim_curve_data: self.my_plotter(ax1, aim_curve_data.x_frequency, aim_curve_data.f_gain, 'gain', {'marker': None}) self.my_plotter(ax2, aim_curve_data.x_frequency, aim_curve_data.phase_num, 'phase', {'marker': None}) plt.legend(('simulation result', 'Ideal filter'), loc='upper right') cursor = Cursor(ax1, useblit=True, color='g', linewidth=1) cursor1 = Cursor(ax2, useblit=True, color='g', linewidth=1) plt.tight_layout(pad=2, w_pad=2, h_pad=2) figure.show()
def _interactive(self): if self._ax and self.interactive: self._cursor = Cursor(self._ax, horizOn=False, vertOn=False) self._cursor.connect_event('button_press_event', self._onclick) self._cursor.connect_event('motion_notify_event', self._onmove) elif self._cursor: self._cursor.disconnect_events() self._cursor = None
def onmove(self,event): #if self.active(): if (event.button == 1): #self.y = event.y #self.x = event.x self.xdata = self.canvas.xdata self.ydata = self.canvas.ydata Cursor.onmove(self, event)
def onmove(self, event): #if self.active(): if (event.button == 1): #self.y = event.y #self.x = event.x self.xdata = self.canvas.xdata self.ydata = self.canvas.ydata Cursor.onmove(self, event)
def plot_scatter(fig, x, y, x2, y2, binnum): '''docstring for plot_test''' fig.canvas.set_window_title(u'交易鸟瞰图') # definitions for the axes left, width = 0.1, 0.65 bottom, height = 0.1, 0.65 bottom_h = left_h = left+width+0.02 rect_scatter = [left, bottom, width, height] rect_histx = [left, bottom_h, width, 0.2] rect_histy = [left_h, bottom, 0.2, height] # start with a rectangular Figure axScatter = plt.axes(rect_scatter) axHistx = plt.axes(rect_histx) axHisty = plt.axes(rect_histy) cursor = Cursor(axScatter, useblit=True, color='red', linewidth=1 ) axScatter.plot(x, y, 'o', color = 'red') axScatter.plot(x2, y2, 'o', color = 'blue') # now determine nice limits by hand: xmax = np.max(x+x2) xmin = np.min(x+x2) binwidth = xmax / binnum lim = ( int(xmax/binwidth) + 1) * binwidth bins = np.arange(-lim, lim + binwidth, binwidth) axHistx.hist(x+x2, bins=bins) ymax = np.max(y+y2) ymin = np.min(y+y2) binwidth = ymax/binnum lim = ( int(ymax/binwidth) + 1) * binwidth bins = np.arange(-lim, lim + binwidth, binwidth) axHisty.hist(y, bins=bins, orientation='horizontal', color = 'red' ) axHisty.hist(y2, bins=bins, orientation='horizontal', color = 'blue' ) xymax = np.max( [np.max(np.fabs(x+x2)), np.max(np.fabs(y+y2))] ) lim = ( int(xymax/binwidth) + 1) * binwidth axScatter.axhline(color='black') #axScatter.set_xlim( (-xmin-10, xmax+10)) #axScatter.set_ylim((-ymin-10, ymax+10)) axHistx.set_xlim( axScatter.get_xlim() ) axHisty.set_ylim( axScatter.get_ylim() ) #axHisty.set_xlabel(u"盈亏分布", fontproperties = font_big) #axHistx.set_ylabel(u"周期分布", fontproperties = font_big) #axScatter.set_xlabel(u"盈亏和周期分布", fontproperties = font_big) axHisty.set_xlabel(u"Profit Distribution") axHistx.set_ylabel(u"Period Distribution") axScatter.set_xlabel(u"Profit and Period Distribution") axScatter.grid(True) axHistx.grid(True) axHisty.grid(True) c = Cursor(axScatter, useblit=True, color='red', linewidth=1, vertOn = True, horizOn = True) return [axScatter, axHistx, axHisty], [c]
def guided_ringdown_fit(data_x, data_y): """ Guided fit of a ringdown. Takes *data_x* and *data_y* as ``pint`` Quantities with dimensions of time and voltage, respectively. Plots the data and asks user to manually crop to select the region to fit. It then does a rough linear fit to find initial parameters and performs a nonlinear fit. Finally, it plots the data with the curve fit overlayed and returns the full-width at half-max (FWHM) with units. """ # Have user choose crop points plt.plot(data_x, data_y) cursor = Cursor(plt.gca(), useblit=True) cursor.horizOn = False (x1, y1), (x2, y2) = _ginput(2) plt.close() # Crop the data i1 = searchsorted(data_x.magnitude, x1) i2 = searchsorted(data_x.magnitude, x2) data_x = data_x[i1:i2] data_y = data_y[i1:i2] # Set t0 = 0 so that the amplitude 'a' doesn't blow up if we # have a large time offset t = data_x - data_x[0] amp = data_y / u.V def decay(x, a, b, c): return a * exp(b * x) + c # Do linear fit to get initial parameter estimate a0, b0, c0 = _linear_fit_decay(t.magnitude, amp.to('').magnitude) # Do nonlinear fit popt, pcov = curve_fit(decay, t.magnitude, amp.magnitude, p0=[a0, b0, c0], maxfev=2000) a, b, c = popt tau = Q_(-1 / b, t.units) FWHM = (1 / (2 * pi * tau)).to('MHz') fit = a * exp(-t / tau) + c t.ito('ns') plt.plot(t, fit, 'b-', lw=2, zorder=3) plt.plot(t, amp, 'gx') plt.title('Ringdown fit') plt.xlabel('Time (ns)') plt.ylabel('Transmission (arb. units)') plt.legend(['Fitted Curve', 'Data Trace']) plt.show() return FWHM
def _interactive(self): if self._ax and self.interactive: self._cursor = Cursor(self._ax, horizOn=True, vertOn=True, color='blue') self._cursor.connect_event('button_press_event', self._onclick) elif self._cursor: self._cursor.disconnect_events() self._cursor = None
def cursor(self): """Initialize the cursors on matplotlib graphs""" self.cursor1 = Cursor(self.plot1, useblit=True, color='red', linewidth=1) self.cursor2 = Cursor(self.plot2, useblit=True, color='red', linewidth=1)
def __init__(self, imagen, stokeim=0, stokeplot=0): # Stoke in plot: globals()['stokeplot'] = stokeplot # Stoke in imshow: globals()['stokeim'] = stokeim print('Click derecho para borrar todo.') self.z = imagen[:, stokeim, :, 0] lenTime = imagen.shape[0] lenStokes = imagen.shape[1] lenSlit = imagen.shape[2] lenLambda = imagen.shape[3] self.x = np.arange(lenSlit) self.y = np.arange(lenTime) self.fig = plt.figure(figsize=(8, 6)) #Doing some layout with subplots: self.fig.subplots_adjust(0.08, 0.08, 0.98, 0.98, 0.1) self.overview = plt.subplot2grid((2, 2), (0, 0), rowspan=1, colspan=3) self.overview.imshow(self.z, cmap='gray', origin='lower', interpolation='None') plt.ylabel('Time Axis') plt.xlabel('Slit Axis') plt.ylim((0, lenTime - 1)) plt.xlim((0, lenSlit - 1)) self.overview.autoscale(1, 'both', 1) self.mini_subplot = plt.subplot2grid((2, 2), (1, 0), rowspan=1, colspan=3) plt.ylabel('Stokes value') plt.xlabel('Lambda') plt.grid(True) plt.ylim((0, 1.2)) plt.xlim((0, imagen.shape[3] - 1)) #Adding widgets, to not be gc'ed, they are put in a list: cursor = Cursor(self.overview, useblit=True, color='black', linewidth=1) cursor2 = Cursor(self.mini_subplot, useblit=True, color='black', linewidth=1) self._widgets = [cursor, cursor2] #connect events self.fig.canvas.mpl_connect('button_press_event', self.click)
def guided_ringdown_fit(data_x, data_y): """ Guided fit of a ringdown. Takes *data_x* and *data_y* as ``pint`` Quantities with dimensions of time and voltage, respectively. Plots the data and asks user to manually crop to select the region to fit. It then does a rough linear fit to find initial parameters and performs a nonlinear fit. Finally, it plots the data with the curve fit overlayed and returns the full-width at half-max (FWHM) with units. """ # Have user choose crop points plt.plot(data_x, data_y) cursor = Cursor(plt.gca(), useblit=True) cursor.horizOn = False (x1, y1), (x2, y2) = _ginput(2) plt.close() # Crop the data i1 = searchsorted(data_x.magnitude, x1) i2 = searchsorted(data_x.magnitude, x2) data_x = data_x[i1:i2] data_y = data_y[i1:i2] # Set t0 = 0 so that the amplitude 'a' doesn't blow up if we # have a large time offset t = data_x - data_x[0] amp = data_y / u.V def decay(x, a, b, c): return a*exp(b*x) + c # Do linear fit to get initial parameter estimate a0, b0, c0 = _linear_fit_decay(t.magnitude, amp.to('').magnitude) # Do nonlinear fit popt, pcov = curve_fit(decay, t.magnitude, amp.magnitude, p0=[a0, b0, c0], maxfev=2000) a, b, c = popt tau = Q_(-1/b, t.units) FWHM = (1 / (2*pi*tau)).to('MHz') fit = a * exp(-t/tau) + c t.ito('ns') plt.plot(t, fit, 'b-', lw=2, zorder=3) plt.plot(t, amp, 'gx') plt.title('Ringdown fit') plt.xlabel('Time (ns)') plt.ylabel('Transmission (arb. units)') plt.legend(['Fitted Curve', 'Data Trace']) plt.show() return FWHM
def generate_wvt4(binlist,signal,var,scalearray,displayWVT=False): ## generates a WVT and StoN map from signal and var maps and displays the WVT ## and allows you to interact with graph and see the scalelengths wvt=np.zeros_like(signal,dtype=float) ston=np.zeros_like(signal,dtype=float) for bindex in range(len(binlist)): sig=calculate_signal(binlist[bindex],signal) StoN=calculate_SN(binlist[bindex],signal,var) for point in binlist[bindex]: wvt[point[0]][point[1]]=sig/len(binlist[bindex]) if sig==0: ston[point[0]][point[1]]=0 else: ston[point[0]][point[1]]=StoN if displayWVT: fig,ax=plt.subplots() def onclick(event): x1,y1=event.xdata,event.ydata for bint in range(len(binlist)): if (int(y1+.5),int(x1+.5)) in binlist[bint]: binn=binlist[bint] print("other pixels in this bin: ") for tup in binn: print("x: "+str(tup[1])+", y:"+str(tup[0])) print("StoN is for this bin: "+str(ston[binn[0][0]][binn[0][1]])) print("scale for this bin: "+str(scalearray[bint])) break cursor=Cursor(ax, horizOn=False,vertOn=False,color='red',linewidth=2.0) fig.canvas.mpl_connect('button_press_event',onclick) image=ax.imshow(wvt,cmap="cubehelix") fig.colorbar(image) plt.show() return wvt, ston
def start_drawing(kind): if kind == 'poly': self._drawing_tool = PolyDrawer(self.ax, oncreated=create_gate, lineprops=dict(color='k', marker='o')) elif kind == 'quad': self._drawing_tool = Cursor(self.ax, vertOn=1, horizOn=1) elif kind == 'horizontal threshold': self._drawing_tool = Cursor(self.ax, vertOn=0, horizOn=1) elif kind == 'vertical threshold': self._drawing_tool = Cursor(self.ax, vertOn=1, horizOn=0) if isinstance(self._drawing_tool, Cursor): def finish_drawing(event): self._drawing_tool.clear(None) return create_gate([(event.xdata, event.ydata)]) self._drawing_tool.connect_event('button_press_event', finish_drawing)
def insert_body(l_split, b_split, X, Y, major_xticks, major_yticks): fig_split = plt.figure(1) fig_split.canvas.set_window_title('Litmod Split Body') ax_split = fig_split.add_subplot(111) cursor = Cursor(ax_split, useblit=True, color='white', linewidth=0.5) plt.subplots_adjust(bottom=0.2) done_option = plt.axes([0.1, 0.05, 0.1, 0.075]) ax_split.set_xlim((-2, 2)) ax_split.set_ylim((-2, 2)) ax_split.set_xlim((0, X)) ax_split.set_ylim((-Y, 0)) ax_split.set_yticks(major_yticks) ax_split.set_xticks(major_xticks) ax_split.grid(True) poly = Polygon(list(zip(l_split, b_split)), lw=1) ax_split.add_patch(poly) #ax_split.plot(l_split,b_split,marker='o', markerfacecolor='r', animated=True) p = Split_axis(fig_split, ax_split, done_option) done = Button(done_option, 'done', color="black") done.on_clicked(p.done) print "axis along which to split" print p.tx, p.ty plt.show() exit()
def afficher(self, ma_liste): # Variables utiles x = np.array(range(len(ma_liste))) y = np.array(ma_liste) y_max = max(y) y_min = min(y) y_mean = np.mean(y) #localtime = time.asctime(time.localtime(time.time())) localtime = time.localtime(time.time()) localtime_str = str(localtime.tm_year) + '_' + str( localtime.tm_mon) + '_' + str(localtime.tm_mday) + '_' + str( localtime.tm_hour) + 'h' + str(localtime.tm_min) + 'm' + str( localtime.tm_sec) + 's' # Initialisation du graphique plt.axis([0, len(ma_liste) + 10, 0, int(max(y)) + 10]) plt.xlabel("Nombre d'images") plt.ylabel("Quantite de mouvement") plt.tight_layout() plt.plot(x, y) subplot3 = self.fig.add_subplot(self.gs[1, 1]) cursor = Cursor(self.subplot1, useblit=True, color='red', linewidth=2) plt.title("Statistiques : ") plt.axis([0, 100, 0, 100]) plt.axis("off") plt.text(20, 80, "min : " + str(y_min)) plt.text(20, 60, "max : " + str(y_max)) plt.text(20, 40, "moyenne : " + str(y_mean)) plt.show() self.fig.savefig('resultats/' + str(localtime_str) + '.pdf') plt.close()
def __init__(self, parent): wx.Panel.__init__(self, parent) self.figure = Figure() self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self, -1, self.figure) # set axis to default to x-scale self.xscale = "linear" self.yscale = "linear" # this controls the layout # self.figure.tight_layout() self.chart_toolbar = MyCustomToolbar(self.canvas) tw, th = self.chart_toolbar.GetSizeTuple() fw, fh = self.canvas.GetSizeTuple() self.chart_toolbar.SetSize(wx.Size(fw, th)) self.chart_toolbar.Realize() self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 0, wx.LEFT | wx.TOP | wx.BOTTOM | wx.GROW) self.sizer.Add(self.chart_toolbar, 1, wx.LEFT | wx.BOTTOM | wx.TOP | wx.GROW) self.SetSizerAndFit(self.sizer) self.Fit() # self.Layout() Cursor(self.axes, useblit=True, color='red', linewidth=1)
def run(self): plt.style.use('dark_background') self.fig, self.ax2 = plt.subplots(facecolor='#07000d') self.ax1 = self.ax2.twinx() self.ax2.set_facecolor('#07000d') plt.title(self.title_str) #scatter = ax1.scatter(x_line[win_start:win_end+1], price_line[win_start:win_end+1], s=50) self.ax1.spines['bottom'].set_color("#5998ff") self.ax1.spines['top'].set_color("#5998ff") self.ax1.spines['left'].set_color("#5998ff") self.ax1.spines['right'].set_color("#5998ff") self.fig.canvas.mpl_connect('key_press_event', self.on_press) #dbclick = self.fig.canvas.mpl_connect('button_press_event', self.on_click2) click = self.fig.canvas.mpl_connect('button_release_event', self.on_click) self.fig.canvas.mpl_connect('scroll_event', self.on_scroll) #cursor = Cursor(ax1, useblit=True, color='#9ffeb0', linewidth=1) self.cursor = Cursor(self.ax1, useblit=True, color='cyan', linewidth=1) #cursor = Cursor(ax1) #plt.connect('motion_notify_event', cursor.mouse_move) self.draw() plt.show() #self.save_label(label_dir, self.symbol) save_dump(self.data_dict, self.data_dict_file)
def record(self, event): print('RECORD') self.abcd = [] self.cursor = Cursor(axes, useblit=True, color='red', linewidth=1) if self.cid: fig.canvas.mpl_disconnect(self.cid) self.cid = fig.canvas.mpl_connect('button_press_event', self.get_click)
def DrawCurve(self, splist): self.axes = self.canvas.figure.gca() self.axes.set_position([0.05, 0.05, 0.85, 0.9]) self.axes.cla() freq = self.data[0] markevery = int(freq.shape[0] / 10) + 1 cnt = 0 for sp in splist: legend = sp line = Line2D(freq, self.data[self.GetSPindex(sp)], label=sp, c=self.GenColor(cnt), marker=self.GenMarker(cnt), markersize=8, markevery=markevery) self.axes.add_line(line) cnt += 1 self.axes.legend(bbox_to_anchor=(1, 1), loc="upper left") self.axes.set_title(self.axes_title) self.axes.set_xlabel(self.axes_xlabel) self.axes.set_ylabel(self.axes_ylabel) self.axes.grid(True, linestyle='-', linewidth=1) #Open grid self.axes.set_cursor_props(1, "r") # self.axes.autoscale_view() self.canvas.draw() cursor = Cursor(self.axes, useblit=True, color='red', linewidth=1)
def _connect_callbacks(self): """ Connects all of the callbacks for the motion and click events """ self._disconnect_callbacks() self._cur = Cursor(self._im_ax, useblit=True, color='red', linewidth=2) self._move_cid = self._fig.canvas.mpl_connect('motion_notify_event', self._move_cb) self._click_cid = self._fig.canvas.mpl_connect('button_press_event', self._click_cb) self._clear_cid = self._fig.canvas.mpl_connect('draw_event', self._clear) self._fig.tight_layout() self._fig.canvas.draw_idle()
def add_mask(self, line, span=3): ax, _, _ = self.plot_spec(line, span, out=True) ax.set_title( 'Choose two points to mask bad data \n (press enter to exit if no data need to be masked)', color='red') cursor = Cursor(plt.gca(), horizOn=False, color='r', lw=1) idx = np.array([]) while True: pos = plt.ginput(2, 0) if pos != []: mask_x = np.array(pos)[:, 0] idx_temp = np.where((self.spec.restframe > min(mask_x)) & (self.spec.restframe < max(mask_x))) idx = np.append(idx, idx_temp).astype('int') key = input( 'press e to save mask and exit \n press c to cancel mask \n press any key to continue masking' ) if key != 'e': continue else: self.spec.flux[idx] = 1 # ax = self.plot_spec(line,span) # ax.set_title('Masked spectrum') break else: plt.close() break return
def main(self): self.createAllVertex() self.createAllEdges() #Criar o grafico file_name = "map.osm.txt" x = list() y = list() with open(file_name) as fp: for line in fp: points = re.findall(r'[-+]?\d+.\d+', line) x.append(float(points[1])) y.append(float(points[2])) #print(points) #plt.plot(x, y, 'ro') fig, ax = plt.subplots() p, = plt.plot(x, y, 'o') cursor = Cursor(ax, horizOn=True, vertOn=True, color='green', linewidth=2.0) c1 = fig.canvas.mpl_connect('button_press_event', self.onclick) plt.show()
def addCanvas(self): self.figure_gain_matching = Figure() self.figure_gain_matching.set_facecolor(color='#FcF9F6') self.canvas_gain_matching = FigureCanvas(self.figure_gain_matching) self.figure_gain_matching.ax = self.figure_gain_matching.add_subplot( 111) self.toolbar_gain_matching = NavigationToolbar( self.canvas_gain_matching, self, coordinates=True) self.plot_gain_matching.addWidget(self.toolbar_gain_matching) self.plot_gain_matching.addWidget(self.canvas_gain_matching) self.canvas_gain_matching.draw_idle() self.figure_xia_all_graphs = Figure() self.figure_xia_all_graphs.set_facecolor(color='#FcF9F6') self.canvas_xia_all_graphs = FigureCanvas(self.figure_xia_all_graphs) self.figure_xia_all_graphs.ax = self.figure_xia_all_graphs.add_subplot( 111) self.toolbar_xia_all_graphs = NavigationToolbar( self.canvas_xia_all_graphs, self, coordinates=True) self.plot_xia_all_graphs.addWidget(self.toolbar_xia_all_graphs) self.plot_xia_all_graphs.addWidget(self.canvas_xia_all_graphs) self.canvas_xia_all_graphs.draw_idle() self.cursor_xia_all_graphs = Cursor(self.figure_xia_all_graphs.ax, useblit=True, color='green', linewidth=0.75) self.figure_xia_all_graphs.ax.clear()
def __init__(self, root_dir, save_dir): self.bndboxes = [] self.locations = ['x', 'y', 'w', 'h'] self.root_dir = root_dir self.save_dir = save_dir self.got_data = False self.fig = plt.figure() self.fig.canvas.mpl_connect('button_press_event', self.onclick) self.fig.canvas.mpl_connect( 'key_press_event', self.on_key) # link this name to this function self.ax = self.fig.add_subplot(111) cursor = Cursor(self.ax, useblit=True, color='red', linewidth=1) #rec = RectangleSelector(self.ax, onselect=self.onclick, drawtype='box', useblit=True, spancoords='pixels', # interactive=True)#, minspanx=5, minspany=5) self.files = get_img_files(root_dir) print(self.files) if len(self.files) == 0: print( 'Make sure all of your images are in a folder called \'{}\' within this one.' .format(self.root_dir), '\nIf you\'re sure they are, then you\'ve already labelled all of these images.' ) self.set_up_image() plt.ion() plt.show(block=True)
def draw(list_, xlabel=None, ylabel=None, x_coords=None, y_coords=None, x_axis=None, y_axis=None, sr=22050, hop_length=512, fmin=None, fmax=None, bins_per_octave=12, **kwargs): data = np.array(list_) axes = specshow(data, x_axis='time', y_axis='time', cmap='Blues') plt.xlabel(xlabel.decode('utf-8')) plt.ylabel(ylabel.decode('utf-8')) #axes.set_xlabel('[sec]') #axes.set_ylabel('[sec]') plt.colorbar() # set useblit = True on gtkagg for enhanced performance cursor = Cursor(axes, useblit=True, color='red', linewidth=1) print("##### heatmap showing...") plt.show()
def run(self, file_path): txt = np.loadtxt(file_path, dtype=str)[:] max_group = [] min_group = [] for i in range(len(txt)): data = txt[i, 2:].astype(np.float32) max_group.append(np.max(data)) min_group.append(np.min(data)) print(len(max_group)) # start_time = self.currenttime.strftime("%H:%M:%S") # print(start_time) #生成一个matplotli认得的days序列 delay = datetime.timedelta(seconds=2) end_time_ = self.currenttime + delay * (len(max_group) - 1) import matplotlib time_range_2 = matplotlib.dates.drange(self.currenttime, end_time_, delay) # 为了解决薛定谔的drange,根据drange尺寸决定要不要丢掉一个y if not len(time_range_2) == len(max_group): max_group = max_group[:len(time_range_2)] min_group = min_group[:len(time_range_2)] fig, ax = plt.subplots() plt.xlabel('时间') plt.ylabel('电压/v') ax.plot_date(time_range_2, max_group, linestyle='-', marker='') ax.plot_date(time_range_2, min_group, linestyle='-', marker='') date_format = matplotlib.dates.DateFormatter('%H:%M:%S') ax.xaxis.set_major_formatter(date_format, ) # 生成游标 cursor = Cursor(ax, useblit=True, color='red', linewidth=2) plt.show()
def plot(self): ax_list = [] i = 0 for p_cell in self.plotcell_lst: p_data = p_cell.data p_dates = p_cell.dates p_color = p_cell.color if (i == 0): ax_list.append(self.figure1.add_axes(self.plotRects[i])) else: if not p_cell.overlay: ax_list.append( self.figure1.add_axes(self.plotRects[i], sharex=ax_list[0])) else: i = i - 1 ax_list[i].plot(p_dates, p_data, p_color) i = i + 1 for label in ax_list[len(ax_list) - 1].get_xticklabels(): label.set_rotation(30) label.set_horizontalalignment('right') for x in ax_list: Cursor(x, useblit=True, color='red', linewidth=1) plt.Artist() plt.show()
def __init__(self, z, verbatims=None, labels=None): """ Shows a given array in a 2d-viewer. Input: z, an 2d array. x,y coordinters are optional. """ self.z = z self.verbatims = verbatims self.labels = labels self.fig = plt.figure() # Doing some layout with subplots: self.fig.subplots_adjust(0.05, 0.05, 0.98, 0.98, 0.1) self.overview = plt.subplot2grid((8, 4), (0, 0), rowspan=7, colspan=4) self.draw() # Adding widgets, to not be gc'ed, they are put in a list: cursor = Cursor(self.overview, useblit=True, color='black', linewidth=2) but_ax = plt.subplot2grid((8, 4), (7, 0), colspan=1) reset_button = Button(but_ax, 'Reset') self._widgets = [cursor, reset_button] # connect events reset_button.on_clicked(self.clear_xy_subplots) self.fig.canvas.mpl_connect('button_press_event', self.click)
def _init_ui(self, data, aspect): self._fig.canvas.mpl_connect('button_release_event', self.on_select_point) self._fig.canvas.mpl_connect('scroll_event', self.on_zoom) self._fig.canvas.mpl_connect('button_release_event', self.on_change_intensity) self._fig.canvas.mpl_connect('motion_notify_event', self.on_change_intensity) self._axes = self._fig.add_axes([0, 0, 1, 0.9], frameon=True) self._axes.axis('off') self.view = self._axes.imshow(data, cmap=self._params.cmap, interpolation=self._params.interp, vmin=self._params.vmin, vmax=self._params.vmax, alpha=self._params.alpha) self._axes.set_aspect(aspect) if self._crosshair: self.cursor = Cursor(self._axes, useblit=True, color='r', linewidth=1) self.points = self._axes.plot([], [], '.r', markersize=7)[0]
def __init__(self, array): self.array = array self.xSize = self.array.shape[1] self.ySize = self.array.shape[0] self.cursorLocation = [50, 50] self.fig, self.ax = plt.subplots() line = self.ax.imshow(self.array, aspect='equal', interpolation='none') divider = make_axes_locatable(self.ax) self.cax = divider.append_axes("right", size="5%", pad=0.05) self.caxb = divider.append_axes("bottom", size="10%", pad=0.05) self.caxl = divider.append_axes("left", size="10%", pad=0.05) self.caxl.xaxis.tick_top() bar = self.fig.colorbar(line, cax=self.cax, orientation='vertical') self.enterEvent = self.fig.canvas.mpl_connect('axes_enter_event', self.on_enter) self.leaveEvent = self.fig.canvas.mpl_connect('axes_leave_event', self.on_leave) self.moveEvent = self.fig.canvas.mpl_connect('motion_notify_event', self.on_move) self.cursor = Cursor(self.ax, useblit=False, color='red', linewidth=2) self.fig.subplots_adjust(wspace=0) self.fig.tight_layout() axprev = plt.axes([0.7, 0.85, 0.1, 0.075]) axnext = plt.axes([0.81, 0.85, 0.1, 0.075]) bnext = Button(axnext, 'Next') plt.show()
def showT(self): #用普通最小二乘法计算周期 listn = [] #log n 的一组值 listRs = [] #对应的log R/S的值 listV = [] for i in xrange(10, self.N / 2 + 1): #!!!!!!!!!除2还是4 #canshu.append([i, self.getRS(i)]) rs = self.getRS(i) listn.append(math.log(i, 10)) # n 取4到N/4 !!!!!!!!!!!!!!!!以10为底。 rs = self.getRS(i) listRs.append(math.log(rs, 10)) #n对应的R/S listV.append(rs / math.sqrt(i)) logn = np.array(listn) logrs = np.array(listRs) v = np.array(listV) plt.plot(logn, logrs, 'b', label='log(R/S)') plt.plot(logn, v, 'r', label='V') plt.legend(loc='best') #绘制图例 cursor = Cursor(plt.gca(), horizOn=True, color='y', lw=1) #光标 #plt.axis([0,40,0,40]) ###横纵坐标的范围,先横后纵 #plt.title(u'Hurst:'+str(round(k,3))) #标题,显示Hurst指数,取3位小数 plt.show()
def plotDataframes(target_df, check_df, daterange, plotTitle, render, show, filename): fig, ax = plt.subplots(figsize=(12, 4)) plt.plot(target_df, label='Target') plt.plot(check_df, label='Historical') plt.axvspan(daterange[0], daterange[1], alpha=0.05, color='black') plt.axvspan(daterange[2], daterange[3], alpha=0.05, color='black') ax.set_xlim([daterange[0], daterange[3]]) hCursor = Cursor(ax, useblit=True, linewidth=0.5, color='C0', linestyle='dashed', dashes=[10, 10]) plt.title(plotTitle) plt.legend(loc=1) if render is True: fig.savefig(filename, bbox_inches='tight') if show is False: plt.close() if show is True: plt.show()
def _interactive(self): if self._ax and self.interactive: self._cursor = Cursor(self._ax, horizOn = False, vertOn = False) self._cursor.connect_event('button_press_event', self._onclick) self._cursor.connect_event('motion_notify_event', self._onmove) elif self._cursor: self._cursor.disconnect_events() self._cursor = None
def choose_windows(spectrum, wstart, wend): """ Choose the windows interactively Parameters ---------- spectrum: array; Bi-dimensional array containing the spectrum. First column should be wavelength and the second, flux. wstart: int, float; Starting wavelength. wend: int, float; Ending wavelength. """ #Define function that will obtain the cursor x position def onselect(vmin, vmax): """ Function that will obtain the cursor x position""" windows.append(float(Decimal("%.2f" % vmin))) windows.append(float(Decimal("%.2f" % vmax))) plot_windows(windows) plt.draw() #Create a plot so the user can choose the windows windows = [] #Set an empty window axis = plt.subplot(111) axis.plot(spectrum[:, 0], spectrum[:, 1], 'k-') axis.hlines(1, wstart, wend, color = 'b', linestyles = 'dashed') axis.set_xlim([wstart, wend]) axis.set_ylim([min(subselect_spectra \ (spectrum, wstart, wend)[1]) - 0.2, 1.05]) axis.set_xlabel(r'Wavelength $(\AA)$') axis.set_ylabel('Normalized Flux') span = SpanSelector(axis, onselect, 'horizontal', minspan = 0.05) # Plot a vertical line at cursor position cursor = Cursor(axis, useblit = True, color = 'red', linewidth = 1 ) cursor.horizOn = False plt.show() plt.clf() return windows
def _interactive(self): if self._ax and self.interactive: self._cursor = Cursor(self._ax, horizOn = True, vertOn = True, color = 'blue') self._cursor.connect_event('button_press_event', self._onclick) elif self._cursor: self._cursor.disconnect_events() self._cursor = None
def on_pixelhunting_toggled(self, button): if button.get_active(): self._cursor = Cursor(self.plot2d.axis, useblit=False, color='white', lw=1) self._cursor.connect_event('button_press_event', self.on_cursorclick) while self.plot2d.toolbar.mode != '': # turn off zoom, pan, etc. modes. self.plot2d.toolbar.zoom() else: self._cursor.disconnect_events() self._cursor = None self._undo_stack.append(self.mask) self.plot2d.replot(keepzoom=False)
def _connect_callbacks(self): """ Connects all of the callbacks for the motion and click events """ self._disconnect_callbacks() self._cur = Cursor(self._im_ax, useblit=True, color='red', linewidth=2) self._move_cid = self._fig.canvas.mpl_connect('motion_notify_event', self._move_cb) self._click_cid = self._fig.canvas.mpl_connect('button_press_event', self._click_cb) self._clear_cid = self._fig.canvas.mpl_connect('draw_event', self._clear) self._fig.tight_layout() self._fig.canvas.draw()
class MaskEditor(ToolWindow, DoubleFileChooserDialog): def __init__(self, *args, **kwargs): self.mask = None self._undo_stack = [] self._im = None self._selector = None self._cursor = None self.exposureloader = None self.plot2d = None ToolWindow.__init__(self, *args, **kwargs) DoubleFileChooserDialog.__init__( self, self.widget, 'Open mask file...', 'Save mask file...', [('Mask files', '*.mat'), ('All files', '*')], self.instrument.config['path']['directories']['mask'], os.path.abspath(self.instrument.config['path']['directories']['mask']), ) def init_gui(self, *args, **kwargs): self.exposureloader = ExposureLoader(self.instrument) self.builder.get_object('loadexposure_expander').add(self.exposureloader) self.exposureloader.connect('open', self.on_loadexposure) self.plot2d = PlotImageWidget() self.builder.get_object('plotbox').pack_start(self.plot2d.widget, True, True, 0) self.builder.get_object('toolbar').set_sensitive(False) def on_loadexposure(self, exposureloader: ExposureLoader, im: Exposure): if self.mask is None: self.mask = im.mask self._im = im self.plot2d.set_image(im.intensity) self.plot2d.set_mask(self.mask) self.builder.get_object('toolbar').set_sensitive(True) def on_new(self, button): if self._im is None or self.mask is None: return False self.mask = np.ones_like(self.mask) self.plot2d.set_mask(self.mask) self.set_last_filename(None) def on_open(self, button): filename = self.get_open_filename() if filename is not None: mask = loadmat(filename) self.mask = mask[[k for k in mask.keys() if not k.startswith('__')][0]] self.plot2d.set_mask(self.mask) def on_save(self, button): filename = self.get_last_filename() if filename is None: return self.on_saveas(button) maskname = os.path.splitext(os.path.split(filename)[1])[0] savemat(filename, {maskname: self.mask}) def on_saveas(self, button): filename = self.get_save_filename(None) if filename is not None: self.on_save(button) def suggest_filename(self): return 'mask_dist_{0.year:d}{0.month:02d}{0.day:02d}.mat'.format(datetime.date.today()) def on_selectcircle_toggled(self, button): if button.get_active(): self.set_sensitive(False, 'Ellipse selection not ready', ['new_button', 'save_button', 'saveas_button', 'open_button', 'undo_button', 'selectrectangle_button', 'selectpolygon_button', 'pixelhunting_button', 'loadexposure_expander', 'close_button', self.plot2d.toolbar, self.plot2d.settings_expander]) while self.plot2d.toolbar.mode != '': # turn off zoom, pan, etc. modes. self.plot2d.toolbar.zoom() self._selector = EllipseSelector(self.plot2d.axis, self.on_ellipse_selected, rectprops={'facecolor': 'white', 'edgecolor': 'none', 'alpha': 0.7, 'fill': True, 'zorder': 10}, button=[1, ], interactive=False, lineprops={'zorder': 10}) self._selector.state.add('square') self._selector.state.add('center') else: assert isinstance(self._selector, EllipseSelector) self._selector.set_active(False) self._selector.set_visible(False) self._selector = None self.plot2d.replot(keepzoom=False) self.set_sensitive(True) def on_ellipse_selected(self, pos1, pos2): # pos1 and pos2 are mouse button press and release events, with xdata and ydata carrying # the two opposite corners of the bounding box of the circle. These are NOT the exact # button presses and releases! row = np.arange(self.mask.shape[0])[:, np.newaxis] column = np.arange(self.mask.shape[1])[np.newaxis, :] row0 = 0.5 * (pos1.ydata + pos2.ydata) col0 = 0.5 * (pos1.xdata + pos2.xdata) r2 = ((pos2.xdata - pos1.xdata) ** 2 + (pos2.ydata - pos1.ydata) ** 2) / 8 tobemasked = (row - row0) ** 2 + (column - col0) ** 2 <= r2 self._undo_stack.append(self.mask) if self.builder.get_object('mask_button').get_active(): self.mask &= ~tobemasked elif self.builder.get_object('unmask_button').get_active(): self.mask |= tobemasked elif self.builder.get_object('invertmask_button').get_active(): self.mask[tobemasked] = ~self.mask[tobemasked] else: pass self.builder.get_object('selectcircle_button').set_active(False) self.plot2d.set_mask(self.mask) def on_selectrectangle_toggled(self, button): if button.get_active(): self.set_sensitive(False, 'Rectangle selection not ready', ['new_button', 'save_button', 'saveas_button', 'open_button', 'undo_button', 'selectcircle_button', 'selectpolygon_button', 'pixelhunting_button', 'loadexposure_expander', 'close_button', self.plot2d.toolbar, self.plot2d.settings_expander]) while self.plot2d.toolbar.mode != '': # turn off zoom, pan, etc. modes. self.plot2d.toolbar.zoom() self._selector = RectangleSelector(self.plot2d.axis, self.on_rectangle_selected, rectprops={'facecolor': 'white', 'edgecolor': 'none', 'alpha': 0.7, 'fill': True, 'zorder': 10}, button=[1, ], interactive=False, lineprops={'zorder': 10}) else: self._selector.set_active(False) self._selector.set_visible(False) self._selector = None self.plot2d.replot(keepzoom=False) self.set_sensitive(True) def on_rectangle_selected(self, pos1, pos2): # pos1 and pos2 are mouse button press and release events, with xdata and ydata # carrying the two opposite corners of the bounding box of the rectangle. These # are NOT the exact button presses and releases! row = np.arange(self.mask.shape[0])[:, np.newaxis] column = np.arange(self.mask.shape[1])[np.newaxis, :] tobemasked = ((row >= min(pos1.ydata, pos2.ydata)) & (row <= max(pos1.ydata, pos2.ydata)) & (column >= min(pos1.xdata, pos2.xdata)) & (column <= max(pos1.xdata, pos2.xdata))) self._undo_stack.append(self.mask) if self.builder.get_object('mask_button').get_active(): self.mask = self.mask & (~tobemasked) elif self.builder.get_object('unmask_button').get_active(): self.mask = self.mask | tobemasked elif self.builder.get_object('invertmask_button').get_active(): self.mask[tobemasked] = ~self.mask[tobemasked] else: pass self.builder.get_object('selectrectangle_button').set_active(False) self.plot2d.set_mask(self.mask) def on_selectpolygon_toggled(self, button): if button.get_active(): self.set_sensitive(False, 'Polygon selection not ready', ['new_button', 'save_button', 'saveas_button', 'open_button', 'undo_button', 'selectrectangle_button', 'selectcircle_button', 'pixelhunting_button', 'loadexposure_expander', 'close_button', self.plot2d.toolbar, self.plot2d.settings_expander]) while self.plot2d.toolbar.mode != '': # turn off zoom, pan, etc. modes. self.plot2d.toolbar.zoom() self._selector = LassoSelector(self.plot2d.axis, self.on_polygon_selected, lineprops={'color': 'white', 'zorder': 10}, button=[1, ], ) else: self._selector.set_active(False) self._selector.set_visible(False) self._selector = None self.plot2d.replot(keepzoom=False) self.set_sensitive(True) def on_polygon_selected(self, vertices): path = Path(vertices) col, row = np.meshgrid(np.arange(self.mask.shape[1]), np.arange(self.mask.shape[0])) points = np.vstack((col.flatten(), row.flatten())).T tobemasked = path.contains_points(points).reshape(self.mask.shape) self._undo_stack.append(self.mask) if self.builder.get_object('mask_button').get_active(): self.mask = self.mask & (~tobemasked) elif self.builder.get_object('unmask_button').get_active(): self.mask = self.mask | tobemasked elif self.builder.get_object('invertmask_button').get_active(): self.mask[tobemasked] = ~self.mask[tobemasked] else: pass self.plot2d.set_mask(self.mask) self.builder.get_object('selectpolygon_button').set_active(False) def on_mask_toggled(self, button): pass def on_unmask_toggled(self, button): pass def on_invertmask_toggled(self, button): pass def on_pixelhunting_toggled(self, button): if button.get_active(): self._cursor = Cursor(self.plot2d.axis, useblit=False, color='white', lw=1) self._cursor.connect_event('button_press_event', self.on_cursorclick) while self.plot2d.toolbar.mode != '': # turn off zoom, pan, etc. modes. self.plot2d.toolbar.zoom() else: self._cursor.disconnect_events() self._cursor = None self._undo_stack.append(self.mask) self.plot2d.replot(keepzoom=False) def on_cursorclick(self, event): if (event.inaxes == self.plot2d.axis) and (self.plot2d.toolbar.mode == ''): self.mask[round(event.ydata), round(event.xdata)] ^= True self._cursor.disconnect_events() self._cursor = None self.plot2d.replot(keepzoom=True) self.on_pixelhunting_toggled(self.builder.get_object('pixelhunting_button')) def cleanup(self): super().cleanup() self._undo_stack = [] def on_undo(self, button): try: self.mask = self._undo_stack.pop() except IndexError: return self.plot2d.set_mask(self.mask)
def __init__(self, ax, useblit=True, **lineprops): Cursor.__init__(self, ax, useblit=useblit,picker=5, **lineprops) #self.y = y #self.x = x self.xdata = self.canvas.xdata self.ydata = self.canvas.ydata
class FCGateManager(EventGenerator): """Manages gate creation widgets and gates.""" def __init__(self, ax, callback_list=None): self.gates = [] self.fig = ax.figure self.ax = ax self._plt_data = None self.active_gate = None self.sample = None self.canvas = self.fig.canvas self.key_handler_cid = self.canvas.mpl_connect('key_press_event', lambda event: key_press_handler(event, self.canvas, self)) self.pick_event_cid = self.canvas.mpl_connect('pick_event', self.pick_event_handler) self.gate_num = 1 self.current_channels = 'd1', 'd2' self.add_callback(callback_list) def disconnect_events(self): self.canvas.mpl_disconnect(self.key_handler_cid) self.canvas.mpl_disconnect(self.pick_event_cid) def pick_event_handler(self, event): """ Handles pick events """ info = {'options': self.get_available_channels(), 'guiEvent': event.mouseevent.guiEvent, } if hasattr(self, 'xlabel_artist') and (event.artist == self.xlabel_artist): info['axis_num'] = 0 self.callback(Event('axis_click', info)) if hasattr(self, 'ylabel_artist') and (event.artist == self.ylabel_artist): info['axis_num'] = 1 self.callback(Event('axis_click', info)) def add_gate(self, gate): self.gates.append(gate) self.set_active_gate(gate) def remove_active_gate(self): if self.active_gate is not None: self.gates.remove(self.active_gate) self.active_gate.remove() self.active_gate = None def set_active_gate(self, gate): if self.active_gate is None: self.active_gate = gate gate.activate() elif self.active_gate is not gate: self.active_gate.inactivate() self.active_gate = gate gate.activate() def _get_next_gate_name(self): gate_name = 'gate{0}'.format(self.gate_num) self.gate_num += 1 return gate_name def _handle_gate_events(self, event): self.set_active_gate(event.info['caller']) def create_gate_widget(self, kind): def clean_drawing_tools(): self._drawing_tool.disconnect_events() self.canvas.draw_idle() self._drawing_tool = None def create_gate(*args): cancelled = False # TODO allow drawing tool to cancel verts = args[0] ch = self.current_channels verts = [dict(zip(ch, v)) for v in verts] if kind == 'poly': gate_type = PolyGate elif 'threshold' in kind or 'quad' in kind: gate_type = ThresholdGate # FIXME: This is very specific implementation if 'vertical' in kind: verts = [{ch[0]: v[ch[0]]} for v in verts] elif 'horizontal' in kind: if len(ch) == 1: cancelled = True else: verts = [{ch[1]: v[ch[1]]} for v in verts] if not cancelled: gate = BaseGate(verts, gate_type, name=self._get_next_gate_name(), callback_list=self._handle_gate_events) gate.spawn(ch, self.ax) self.add_gate(gate) clean_drawing_tools() def start_drawing(kind): if kind == 'poly': self._drawing_tool = PolyDrawer(self.ax, oncreated=create_gate, lineprops=dict(color='k', marker='o')) elif kind == 'quad': self._drawing_tool = Cursor(self.ax, vertOn=1, horizOn=1) elif kind == 'horizontal threshold': self._drawing_tool = Cursor(self.ax, vertOn=0, horizOn=1) elif kind == 'vertical threshold': self._drawing_tool = Cursor(self.ax, vertOn=1, horizOn=0) if isinstance(self._drawing_tool, Cursor): def finish_drawing(event): self._drawing_tool.clear(None) return create_gate([(event.xdata, event.ydata)]) self._drawing_tool.connect_event('button_press_event', finish_drawing) start_drawing(kind) #################### ### Loading Data ### #################### def load_fcs(self, filepath=None, parent=None): ax = self.ax if parent is None: parent = self.fig.canvas if filepath is None: from FlowCytometryTools.gui import dialogs filepath = dialogs.open_file_dialog('Select an FCS file to load', 'FCS files (*.fcs)|*.fcs', parent=parent) if filepath is not None: self.sample = FCMeasurement('temp', datafile=filepath) print('WARNING: Data is raw (not transformation).') self._sample_loaded_event() def load_measurement(self, measurement): self.sample = measurement.copy() self._sample_loaded_event() def _sample_loaded_event(self): if self.sample is not None: self.current_channels = list(self.sample.channel_names[0:2]) self.set_axes(self.current_channels, self.ax) def get_available_channels(self): return self.sample.channel_names def change_axis(self, axis_num, channel_name): """ TODO: refactor that and set_axes what to do with ax? axis_num: int axis number channel_name: str new channel to plot on that axis """ current_channels = list(self.current_channels) if len(current_channels) == 1: if axis_num == 0: new_channels = channel_name, else: new_channels = current_channels[0], channel_name else: new_channels = list(current_channels) new_channels[axis_num] = channel_name self.set_axes(new_channels, self.ax) def set_axes(self, channels, ax): """ channels : iterable of string each value corresponds to a channel names names must be unique """ # To make sure displayed as hist if len(set(channels)) == 1: channels = channels[0], self.current_channels = channels # Remove existing gates for gate in self.gates: gate.remove_spawned_gates() ## # Has a clear axis command inside!! # which will "force kill" spawned gates self.plot_data() for gate in self.gates: sgate = gate.spawn(channels, ax) gate._refresh_activation() def close(self): for gate in self.gates: gate.remove() self.disconnect_events() #################### ### Plotting Data ## #################### def plot_data(self): """Plots the loaded data""" # Clear the plot before plotting onto it self.ax.cla() if self.sample is None: return if self.current_channels is None: self.current_channels = self.sample.channel_names[:2] channels = self.current_channels channels_to_plot = channels[0] if len(channels) == 1 else channels self.sample.plot(channels_to_plot, ax=self.ax) xaxis = self.ax.get_xaxis() yaxis = self.ax.get_yaxis() self.xlabel_artist = xaxis.get_label() self.ylabel_artist = yaxis.get_label() self.xlabel_artist.set_picker(5) self.ylabel_artist.set_picker(5) self.fig.canvas.draw() def get_generation_code(self): """Return python code that generates all drawn gates.""" if len(self.gates) < 1: code = '' else: import_list = set([gate._gencode_gate_class for gate in self.gates]) import_list = 'from FlowCytometryTools import ' + ', '.join(import_list) code_list = [gate.get_generation_code() for gate in self.gates] code_list.sort() code_list = '\n'.join(code_list) code = import_list + 2 * '\n' + code_list self.callback(Event('generated_code', {'code': code})) return code
class CrossSection(object): """ Class to manage the axes, artists and properties associated with showing a 2D image, a cross-hair cursor and two parasite axes which provide horizontal and vertical cross sections of image. You will likely need to call `CrossSection.init_artists(init_image)` after creating this object. Parameters ---------- fig : matplotlib.figure.Figure The figure object to build the class on, will clear current contents init_image : 2d ndarray The initial image cmap : str, colormap, or None color map to use. Defaults to gray norm : Normalize or None Normalization function to use limit_func : callable, optional function that takes in the image and returns clim values auto_redraw : bool, optional interpolation : str, optional Interpolation method to use. List of valid options can be found in CrossSection2DView.interpolation Properties ---------- interpolation : str The stringly-typed pixel interpolation. See _INTERPOLATION attribute of this cross_section_2d module cmap : str The colormap to use for rendering the image """ def __init__(self, fig, cmap=None, norm=None, limit_func=None, auto_redraw=True, interpolation=None): self._cursor_position_cbs = [] if interpolation is None: interpolation = _INTERPOLATION[0] self._interpolation = interpolation # used to determine if setting properties should force a re-draw self._auto_redraw = auto_redraw # clean defaults if limit_func is None: limit_func = fullrange_limit_factory() if cmap is None: cmap = 'gray' # stash the color map self._cmap = cmap # let norm pass through as None, mpl defaults to linear which is fine if norm is None: norm = Normalize() self._norm = norm # save a copy of the limit function, we will need it later self._limit_func = limit_func # this is used by the widget logic self._active = True self._dirty = True self._cb_dirty = True # work on setting up the mpl axes self._fig = fig # blow away what ever is currently on the figure fig.clf() # Configure the figure in our own image # # +----------------------+ # | H cross section | # +----------------------+ # +---+ +----------------------+ # | V | | | # | | | | # | x | | | # | s | | Main Axes | # | e | | | # | c | | | # | t | | | # | i | | | # | o | | | # | n | | | # +---+ +----------------------+ # make the main axes self._im_ax = fig.add_subplot(1, 1, 1) self._im_ax.set_aspect('equal') self._im_ax.xaxis.set_major_locator(NullLocator()) self._im_ax.yaxis.set_major_locator(NullLocator()) self._imdata = None self._im = self._im_ax.imshow([[]], cmap=self._cmap, norm=self._norm, interpolation=self._interpolation, aspect='equal', vmin=0, vmax=1) # make it dividable divider = make_axes_locatable(self._im_ax) # set up all the other axes # (set up the horizontal and vertical cuts) self._ax_h = divider.append_axes('top', .5, pad=0.1, sharex=self._im_ax) self._ax_h.yaxis.set_major_locator(LinearLocator(numticks=2)) self._ax_v = divider.append_axes('left', .5, pad=0.1, sharey=self._im_ax) self._ax_v.xaxis.set_major_locator(LinearLocator(numticks=2)) self._ax_cb = divider.append_axes('right', .2, pad=.5) # add the color bar self._cb = fig.colorbar(self._im, cax=self._ax_cb) # add the cursor place holder self._cur = None # turn off auto-scale for the horizontal cut self._ax_h.autoscale(enable=False) # turn off auto-scale scale for the vertical cut self._ax_v.autoscale(enable=False) # create line artists self._ln_v, = self._ax_v.plot([], [], 'k-', animated=True, visible=False) self._ln_h, = self._ax_h.plot([], [], 'k-', animated=True, visible=False) # backgrounds for blitting self._ax_v_bk = None self._ax_h_bk = None # stash last-drawn row/col to skip if possible self._row = None self._col = None # make attributes for callback ids self._move_cid = None self._click_cid = None self._clear_cid = None def add_cursor_position_cb(self, callback): """ Add a callback for the cursor position in the main axes Parameters ---------- callback : callable(cc, rr) Function that gets called when the cursor position moves to a new row or column on main axes """ self._cursor_position_cbs.append(fun) # set up the call back for the updating the side axes def _move_cb(self, event): if not self._active: return if event is None: x = self._col y = self._row self._col = None self._row = None else: # short circuit on other axes if event.inaxes is not self._im_ax: return x, y = event.xdata, event.ydata numrows, numcols = self._imdata.shape if x is not None and y is not None: self._ln_h.set_visible(True) self._ln_v.set_visible(True) col = int(x + 0.5) row = int(y + 0.5) if row != self._row or col != self._col: if 0 <= col < numcols and 0 <= row < numrows: self._col = col self._row = row for cb in self._cursor_position_cbs: cb(col, row) for data, ax, bkg, art, set_fun in zip( (self._imdata[row, :], self._imdata[:, col]), (self._ax_h, self._ax_v), (self._ax_h_bk, self._ax_v_bk), (self._ln_h, self._ln_v), (self._ln_h.set_ydata, self._ln_v.set_xdata)): self._fig.canvas.restore_region(bkg) set_fun(data) ax.draw_artist(art) self._fig.canvas.blit(ax.bbox) def _click_cb(self, event): if event.inaxes is not self._im_ax: return self.active = not self.active if self.active: self._cur.onmove(event) self._move_cb(event) @auto_redraw def _connect_callbacks(self): """ Connects all of the callbacks for the motion and click events """ self._disconnect_callbacks() self._cur = Cursor(self._im_ax, useblit=True, color='red', linewidth=2) self._move_cid = self._fig.canvas.mpl_connect('motion_notify_event', self._move_cb) self._click_cid = self._fig.canvas.mpl_connect('button_press_event', self._click_cb) self._clear_cid = self._fig.canvas.mpl_connect('draw_event', self._clear) self._fig.tight_layout() self._fig.canvas.draw() def _disconnect_callbacks(self): """ Disconnects all of the callbacks """ if self._fig.canvas is None: # no canvas -> can't do anything about the call backs which # should not exist self._move_cid = None self._clear_cid = None self._click_cid = None return for atr in ('_move_cid', '_clear_cid', '_click_cid'): cid = getattr(self, atr, None) if cid is not None: self._fig.canvas.mpl_disconnect(cid) setattr(self, atr, None) # clean up the cursor if self._cur is not None: self._cur.disconnect_events() del self._cur self._cur = None @auto_redraw def _init_artists(self, init_image): """ Update the CrossSection with a new base-image. This function takes care of setting up all of the details about the image size in the limits/artist extent of the image and the secondary data in the cross-section parasite plots. Parameters ---------- init_image : ndarray An image to serve as the new 'base' image. """ im_shape = init_image.shape # first deal with the image axis # update the image, `update_artists` takes care of # updating the actual artist self._imdata = init_image # update the extent of the image artist self._im.set_extent([-0.5, im_shape[1] + .5, im_shape[0] + .5, -0.5]) # update the limits of the image axes to match the exent self._im_ax.set_xlim([-.05, im_shape[1] + .5]) self._im_ax.set_ylim([im_shape[0] + .5, -0.5]) # update the format coords printer numrows, numcols = im_shape # note, this is a closure over numrows and numcols def format_coord(x, y): # adjust xy -> col, row col = int(x + 0.5) row = int(y + 0.5) # make sure the point falls in the array if col >= 0 and col < numcols and row >= 0 and row < numrows: # if it does, grab the value z = self._imdata[row, col] return "X: {x:d} Y: {y:d} I: {i:.2f}".format(x=col, y=row, i=z) else: return "X: {x:d} Y: {y:d}".format(x=col, y=row) # replace the current format_coord function self._im_ax.format_coord = format_coord # net deal with the parasite axes and artist self._ln_v.set_data(np.zeros(im_shape[0]), np.arange(im_shape[0])) self._ax_v.set_ylim([0, im_shape[0]]) self._ln_h.set_data(np.arange(im_shape[1]), np.zeros(im_shape[1])) self._ax_h.set_xlim([0, im_shape[1]]) # if we have a cavas, then connect/set up junk if self._fig.canvas is not None: self._connect_callbacks() # mark as dirty self._dirty = True def _clear(self, event): self._ax_v_bk = self._fig.canvas.copy_from_bbox(self._ax_v.bbox) self._ax_h_bk = self._fig.canvas.copy_from_bbox(self._ax_h.bbox) self._ln_h.set_visible(False) self._ln_v.set_visible(False) # this involves reaching in and touching the guts of the # cursor widget. The problem is that the mpl widget # skips updating it's saved background if the widget is inactive if self._cur: self._cur.background = self._cur.canvas.copy_from_bbox( self._cur.canvas.figure.bbox) @property def interpolation(self): return self._interpolation @property def active(self): return self._active @active.setter def active(self, val): self._active = val self._cur.active = val @auto_redraw def update_interpolation(self, interpolation): """ Set the interpolation method """ self._dirty = True self._im.set_interpolation(interpolation) @auto_redraw def update_cmap(self, cmap): """ Set the color map used """ # TODO: this should stash new value, not apply it self._cmap = cmap self._dirty = True @auto_redraw def update_image(self, image): """ Set the image data The input data does not necessarily have to be the same shape as the original image """ if self._imdata is None or self._imdata.shape != image.shape: self._init_artists(image) self._imdata = image self._move_cb(None) self._dirty = True @auto_redraw def update_norm(self, norm): """ Update the way that matplotlib normalizes the image """ self._norm = norm self._dirty = True self._cb_dirty = True @auto_redraw def update_limit_func(self, limit_func): """ Set the function to use to determine the color scale """ # set the new function to use for computing the color limits self._limit_func = limit_func self._dirty = True def _update_artists(self): """ Updates the figure by re-drawing """ # if the figure is not dirty, short-circuit if not (self._dirty or self._cb_dirty): return # this is a tuple which is the max/min used in the color mapping. # these values are also used to set the limits on the value # axes of the parasite axes # value_limits vlim = self._limit_func(self._imdata) # set the color bar limits self._im.set_clim(vlim) self._norm.vmin, self._norm.vmax = vlim # set the cross section axes limits self._ax_v.set_xlim(*vlim[::-1]) self._ax_h.set_ylim(*vlim) # set the imshow data self._im.set_data(self._imdata) self._im.set_cmap(self._cmap) self._im.set_norm(self._norm) # TODO if cb_dirty, remake the colorbar, I think this is # why changing the norm does not play well self._dirty = False self._cb_dirty = False def _draw(self): self._fig.canvas.draw() @auto_redraw def autoscale_horizontal(self, enable): self._ax_h.autoscale(enable=enable) @auto_redraw def autoscale_vertical(self, enable): self._ax_v.autoscale(enable=False)
class QuadSelection(cytoflow.views.ScatterplotView): """Plots, and lets the user interact with, a quadrant gate. Attributes ---------- op : Instance(Range2DOp) The instance of Range2DOp that we're viewing / editing huefacet : Str The conditioning variable to plot multiple colors subset : Str The string passed to `Experiment.query()` to subset the data before plotting interactive : Bool is this view interactive? Ie, can the user set the threshold with a mouse click? Notes ----- We inherit `xfacet` and `yfacet` from `cytoflow.views.ScatterplotView`, but they must both be unset! Examples -------- In an IPython notebook with `%matplotlib notebook` >>> q = flow.QuadOp(name = "Quad", ... xchannel = "V2-A", ... ychannel = "Y2-A")) >>> qv = q.default_view() >>> qv.interactive = True >>> qv.plot(ex2) """ id = Constant('edu.mit.synbio.cytoflow.views.quad') friendly_id = Constant("Quadrant Selection") op = Instance(IOperation) name = DelegatesTo('op') xchannel = DelegatesTo('op') ychannel = DelegatesTo('op') interactive = Bool(False, transient = True) # internal state. _ax = Any(transient = True) _hline = Instance(Line2D, transient = True) _vline = Instance(Line2D, transient = True) _cursor = Instance(Cursor, transient = True) def plot(self, experiment, **kwargs): """Plot the underlying scatterplot and then plot the selection on top of it.""" if not experiment: raise util.CytoflowOpError("No experiment specified") if not experiment: raise util.CytoflowViewError("No experiment specified") if self.xfacet: raise util.CytoflowViewError("RangeSelection.xfacet must be empty or `Undefined`") if self.yfacet: raise util.CytoflowViewError("RangeSelection.yfacet must be empty or `Undefined`") super(QuadSelection, self).plot(experiment, **kwargs) self._ax = plt.gca() self._draw_lines() self._interactive() @on_trait_change('op.xthreshold, op.ythreshold', post_init = True) def _draw_lines(self): if not self._ax: return if self._hline and self._hline in self._ax.lines: self._hline.remove() if self._vline and self._vline in self._ax.lines: self._vline.remove() if self.op.xthreshold and self.op.ythreshold: self._hline = plt.axhline(self.op.ythreshold, linewidth = 3, color = 'blue') self._vline = plt.axvline(self.op.xthreshold, linewidth = 3, color = 'blue') plt.draw_if_interactive() @on_trait_change('interactive', post_init = True) def _interactive(self): if self._ax and self.interactive: self._cursor = Cursor(self._ax, horizOn = True, vertOn = True, color = 'blue') self._cursor.connect_event('button_press_event', self._onclick) elif self._cursor: self._cursor.disconnect_events() self._cursor = None def _onclick(self, event): """Update the threshold location""" self.op.xthreshold = event.xdata self.op.ythreshold = event.ydata
s.values.pop(s.gamma) s.values.pop(s.v) def my_selector(event): draw_arrow(event.xdata ,event.ydata) plt.draw() def click(label): global lab_frame_toggle global force_toggle if label == "vehicle frame": lab_frame_toggle = not lab_frame_toggle else: force_toggle= not force_toggle lab_frame_toggle=False force_toggle=False rax = plt.axes([0.03, 0.1, 0.2, 0.15]) check = CheckButtons(rax, ('vehicle frame','show force'), (False,False)) check.on_clicked(click) # set useblit = True on gtkagg for enhanced performance cursor = Cursor(ax, useblit=True) cursor.horizOn=False cursor.vertOn=False plt.ion() plt.connect('button_press_event', my_selector) #plt.connect('motion_notify_event', my_selector) plt.show()
class PolygonSelection(HasStrictTraits): """Plots, and lets the user interact with, a 2D selection. Attributes ---------- polygon : Instance(numpy.ndarray) The polygon vertices view : Instance(IView) the IView that this view is wrapping. I suggest that if it's another ISelectionView, that its `interactive` property remain False. >.> interactive : Bool is this view interactive? Ie, can the user set the polygon verticies with mouse clicks? """ id = "edu.mit.synbio.cytoflow.views.polygon" friendly_id = "Polygon Selection" view = Instance(IView, transient = True) interactive = Bool(False, transient = True) vertices = List((Float, Float)) # internal state. _cursor = Instance(Cursor, transient = True) _path = Instance(mpl.path.Path, transient = True) _patch = Instance(mpl.patches.PathPatch, transient = True) _line = Instance(mpl.lines.Line2D, transient = True) _drawing = Bool(transient = True) def plot(self, experiment, **kwargs): """Plot self.view, and then plot the selection on top of it.""" self.view.plot(experiment, **kwargs) self._draw_poly() def is_valid(self, experiment): """If the decorated view is valid, we are too.""" return self.view.is_valid(experiment) @on_trait_change('vertices') def _draw_poly(self): ca = plt.gca() if self._patch and self._patch in ca.patches: self._patch.remove() if self._drawing or not self.vertices or len(self.vertices) < 3 \ or any([len(x) != 2 for x in self.vertices]): return patch_vert = np.concatenate((np.array(self.vertices), np.array((0,0), ndmin = 2))) self._patch = \ mpl.patches.PathPatch(mpl.path.Path(patch_vert, closed = True), edgecolor="black", linewidth = 1.5, fill = False) ca.add_patch(self._patch) plt.gcf().canvas.draw() @on_trait_change('interactive') def _interactive(self): if self.interactive: ax = plt.gca() self._cursor = Cursor(ax, horizOn = False, vertOn = False) self._cursor.connect_event('button_press_event', self._onclick) self._cursor.connect_event('motion_notify_event', self._onmove) else: self._cursor.disconnect_events() self._cursor = None def _onclick(self, event): """Update selection traits""" if(self._cursor.ignore(event)): return if event.dblclick: self._drawing = False self.vertices = map(tuple, self._path.vertices) self._path = None return ca = plt.gca() self._drawing = True if self._patch and self._patch in ca.patches: self._patch.remove() if self._path: vertices = np.concatenate((self._path.vertices, np.array((event.xdata, event.ydata), ndmin = 2))) else: vertices = np.array((event.xdata, event.ydata), ndmin = 2) self._path = mpl.path.Path(vertices, closed = False) self._patch = mpl.patches.PathPatch(self._path, edgecolor = "black", fill = False) ca.add_patch(self._patch) plt.gcf().canvas.draw() def _onmove(self, event): if(self._cursor.ignore(event) or not self._drawing or not self._path or self._path.vertices.shape[0] == 0 or not event.xdata or not event.ydata): return ca = plt.gca() if not ca: return if self._line and self._line in ca.lines: self._line.remove() xdata = [self._path.vertices[-1, 0], event.xdata] ydata = [self._path.vertices[-1, 1], event.ydata] self._line = mpl.lines.Line2D(xdata, ydata, linewidth = 1, color = "black") ca.add_line(self._line) plt.gcf().canvas.draw()
class PolygonSelection(cytoflow.views.ScatterplotView): """Plots, and lets the user interact with, a 2D polygon selection. Attributes ---------- op : Instance(PolygonOp) The operation on which this selection view is operating huefacet : Str The conditioning variable to show multiple colors on this plot subset : Str The string for subsetting the plot interactive : Bool is this view interactive? Ie, can the user set the polygon verticies with mouse clicks? Notes ----- We inherit `xfacet` and `yfacet` from `cytoflow.views.ScatterPlotView`, but they must both be unset! Examples -------- In an IPython notebook with `%matplotlib notebook` >>> s = flow.ScatterplotView(xchannel = "V2-A", ... ychannel = "Y2-A") >>> poly = s.default_view() >>> poly.plot(ex2) >>> poly.interactive = True """ id = Constant('edu.mit.synbio.cytoflow.views.polygon') friendly_id = Constant("Polygon Selection") op = Instance(IOperation) name = DelegatesTo('op') xchannel = DelegatesTo('op') ychannel = DelegatesTo('op') interactive = Bool(False, transient = True) # internal state. _ax = Any(transient = True) _cursor = Instance(Cursor, transient = True) _path = Instance(mpl.path.Path, transient = True) _patch = Instance(mpl.patches.PathPatch, transient = True) _line = Instance(mpl.lines.Line2D, transient = True) _drawing = Bool(transient = True) _last_draw_time = Float(0.0, transient = True) _last_click_time = Float(0.0, transient = True) def plot(self, experiment, **kwargs): """Plot self.view, and then plot the selection on top of it.""" if not experiment: raise util.CytoflowViewError("No experiment specified") if self.xfacet: raise util.CytoflowViewError("RangeSelection.xfacet must be empty or `Undefined`") if self.yfacet: raise util.CytoflowViewError("RangeSelection.yfacet must be empty or `Undefined`") super(PolygonSelection, self).plot(experiment, **kwargs) self._ax = plt.gca() self._draw_poly() self._interactive() @on_trait_change('op.vertices', post_init = True) def _draw_poly(self): if not self._ax: return if self._patch and self._patch in self._ax.patches: self._patch.remove() if self._drawing or not self.op.vertices or len(self.op.vertices) < 3 \ or any([len(x) != 2 for x in self.op.vertices]): return patch_vert = np.concatenate((np.array(self.op.vertices), np.array((0,0), ndmin = 2))) self._patch = \ mpl.patches.PathPatch(mpl.path.Path(patch_vert, closed = True), edgecolor="black", linewidth = 1.5, fill = False) self._ax.add_patch(self._patch) plt.draw_if_interactive() @on_trait_change('interactive', post_init = True) def _interactive(self): if self._ax and self.interactive: self._cursor = Cursor(self._ax, horizOn = False, vertOn = False) self._cursor.connect_event('button_press_event', self._onclick) self._cursor.connect_event('motion_notify_event', self._onmove) elif self._cursor: self._cursor.disconnect_events() self._cursor = None def _onclick(self, event): """Update selection traits""" if not self._ax: return if(self._cursor.ignore(event)): return # we have to check the wall clock time because the IPython notebook # doesn't seem to register double-clicks if event.dblclick or (time.clock() - self._last_click_time < 0.5): self._drawing = False self.op.vertices = map(tuple, self._path.vertices) self.op._xscale = plt.gca().get_xscale() self.op._yscale = plt.gca().get_yscale() self._path = None return self._last_click_time = time.clock() self._drawing = True if self._patch and self._patch in self._ax.patches: self._patch.remove() if self._path: vertices = np.concatenate((self._path.vertices, np.array((event.xdata, event.ydata), ndmin = 2))) else: vertices = np.array((event.xdata, event.ydata), ndmin = 2) self._path = mpl.path.Path(vertices, closed = False) self._patch = mpl.patches.PathPatch(self._path, edgecolor = "black", fill = False) self._ax.add_patch(self._patch) plt.draw_if_interactive() def _onmove(self, event): if not self._ax: return if(self._cursor.ignore(event) or not self._drawing or not self._path or self._path.vertices.shape[0] == 0 or not event.xdata or not event.ydata): return # only draw 5 times/sec if(time.clock() - self._last_draw_time < 0.2): return self._last_draw_time = time.clock() if self._line and self._line in self._ax.lines: self._line.remove() xdata = [self._path.vertices[-1, 0], event.xdata] ydata = [self._path.vertices[-1, 1], event.ydata] self._line = mpl.lines.Line2D(xdata, ydata, linewidth = 1, color = "black") self._ax.add_line(self._line) plt.gcf().canvas.draw()
class ThresholdSelection(cytoflow.views.HistogramView): """ Plots, and lets the user interact with, a threshold on the X axis. TODO - beautify! Attributes ---------- op : Instance(ThresholdOp) the ThresholdOp we're working on. huefacet : Str The conditioning variable to show multiple colors on this plot subset : Str the string passed to Experiment.subset() defining the subset we plot interactive : Bool is this view interactive? Notes ----- We inherit `xfacet` and `yfacet` from `cytoflow.views.HistogramView`, but they must both be unset! Examples -------- In an IPython notebook with `%matplotlib notebook` >>> t = flow.ThresholdOp(name = "Threshold", ... channel = "Y2-A") >>> tv = t.default_view() >>> tv.plot(ex2) >>> tv.interactive = True >>> # .... draw a threshold on the plot >>> ex3 = thresh.apply(ex2) """ id = Constant('edu.mit.synbio.cytoflow.views.threshold') friendly_id = Constant("Threshold Selection") op = Instance(IOperation) name = DelegatesTo('op') channel = DelegatesTo('op') interactive = Bool(False, transient = True) # internal state _ax = Any(transient = True) _line = Instance(Line2D, transient = True) _cursor = Instance(Cursor, transient = True) def plot(self, experiment, **kwargs): """Plot the histogram and then plot the threshold on top of it.""" if not experiment: raise util.CytoflowViewError("No experiment specified") if self.xfacet: raise util.CytoflowViewError("ThresholdSelection.xfacet must be empty") if self.yfacet: raise util.CytoflowViewError("ThresholdSelection.yfacet must be empty") super(ThresholdSelection, self).plot(experiment, **kwargs) self._ax = plt.gca() self._draw_threshold() self._interactive() @on_trait_change('op.threshold', post_init = True) def _draw_threshold(self): if not self._ax or not self.op.threshold: return if self._line: # when used in the GUI, _draw_threshold gets called *twice* without # the plot being updated inbetween: and then the line can't be # removed from the plot, because it was never added. so check # explicitly first. this is likely to be an issue in other # interactive plots, too. if self._line and self._line in self._ax.lines: self._line.remove() self._line = None if self.op.threshold: self._line = plt.axvline(self.op.threshold, linewidth=3, color='blue') plt.draw_if_interactive() @on_trait_change('interactive', post_init = True) def _interactive(self): if self._ax and self.interactive: self._cursor = Cursor(self._ax, horizOn=False, vertOn=True, color='blue') self._cursor.connect_event('button_press_event', self._onclick) elif self._cursor: self._cursor.disconnect_events() self._cursor = None def _onclick(self, event): """Update the threshold location""" self.op.threshold = event.xdata
def __init__(self, fig, init_image, cmap=None, norm=None, clim_percentile=None): """ Sets up figure with cross section viewer Parameters ---------- fig : matplotlib.figure.Figure The figure object to build the class on, will clear current contents init_image : 2d ndarray The initial image cmap : str, colormap, or None color map to use. Defaults to gray clim_percentile : float or None percentile away from 0, 100 to put the max/min limits at ie, clim_percentile=5 -> vmin=5th percentile vmax=95th percentile norm : Normalize or None Normalization function to us """ self._active = True self._clim_pct = clim_percentile if cmap is None: cmap = 'gray' # this needs to respect percentile self.vmin, self.vmax = _compute_limit(init_image, self._clim_pct) # stash the figure self.fig = fig # clean it self.fig.clf() # make the main axes self._im_ax = fig.add_subplot(1, 1, 1) self._im_ax.set_aspect('equal') self._im_ax.xaxis.set_major_locator(NullLocator()) self._im_ax.yaxis.set_major_locator(NullLocator()) self._imdata = init_image self._im = self._im_ax.imshow(init_image, cmap=cmap, norm=norm, interpolation='none', aspect='equal') # make it dividable divider = make_axes_locatable(self._im_ax) # set up all the other axes self._ax_h = divider.append_axes('top', .5, pad=0.1, sharex=self._im_ax) self._ax_h.yaxis.set_major_locator(NullLocator()) self._ax_v = divider.append_axes('left', .5, pad=0.1, sharey=self._im_ax) self._ax_v.xaxis.set_major_locator(NullLocator()) self._ax_cb = divider.append_axes('right', .2, pad=.5) # add the color bar self._cb = fig.colorbar(self._im, cax=self._ax_cb) # print out the pixel value def format_coord(x, y): numrows, numcols = self._imdata.shape col = int(x+0.5) row = int(y+0.5) if col >= 0 and col < numcols and row >= 0 and row < numrows: z = self._imdata[row, col] return "X: {x:d} Y: {y:d} I: {i:.2f}".format(x=col, y=row, i=z) else: return "X: {x:d} Y: {y:d}".format(x=col, y=row) self._im_ax.format_coord = format_coord # add the cursor self.cur = Cursor(self._im_ax, useblit=True, color='red', linewidth=2) self._ax_h.set_ylim(self.vmin, self.vmax) self._ax_h.autoscale(enable=False) self._ax_v.set_xlim(self.vmin, self.vmax) self._ax_v.autoscale(enable=False) # add lines self._ln_v, = self._ax_v.plot(np.zeros(self._imdata.shape[1]), np.arange(self._imdata.shape[1]), 'k-', animated=True, visible=False) self._ln_h, = self._ax_h.plot(np.arange(self._imdata.shape[0]), np.zeros(self._imdata.shape[0]), 'k-', animated=True, visible=False) # backgrounds for blitting self._ax_v_bk = None self._ax_h_bk = None # stash last-drawn row/col to skip if possible self._row = None self._col = None # set up the call back for the updating the side axes def move_cb(event): if not self._active: return # short circuit on other axes if event.inaxes is not self._im_ax: return numrows, numcols = self._imdata.shape x, y = event.xdata, event.ydata if x is not None and y is not None: self._ln_h.set_visible(True) self._ln_v.set_visible(True) col = int(x+0.5) row = int(y+0.5) if row != self._row and col != self._col: if (col >= 0 and col < numcols and row >= 0 and row < numrows): self._col = col self._row = row for data, ax, bkg, art, set_fun in zip( (self._imdata[row, :], self._imdata[:, col]), (self._ax_h, self._ax_v), (self._ax_h_bk, self._ax_v_bk), (self._ln_h, self._ln_v), (self._ln_h.set_ydata, self._ln_v.set_xdata)): self.fig.canvas.restore_region(bkg) set_fun(data) ax.draw_artist(art) self.fig.canvas.blit(ax.bbox) def click_cb(event): if event.inaxes is not self._im_ax: return self.active = not self.active if self.active: self.cur.onmove(event) move_cb(event) self.move_cid = self.fig.canvas.mpl_connect('motion_notify_event', move_cb) self.click_cid = self.fig.canvas.mpl_connect('button_press_event', click_cb) self.clear_cid = self.fig.canvas.mpl_connect('draw_event', self.clear) self.fig.tight_layout() self.fig.canvas.draw()
def __init__( self, axes, **args ): Cursor.__init__( self, axes, **args )
def onmove(self, event): self.visible = True self.vertOn = True self.horizOn = True Cursor.onmove( self, event )
def __init__(self,ax,pos,statusBar,transForm,**kwargs): Cursor.__init__(self,ax,**kwargs) self.statusBar=statusBar self.pos=pos self.transForm=transForm self.statusBar.showMessage("Cell: " +"%d,"%self.pos[0]+"%d"%self.pos[1])