class SelectFromCollection(object): """Use the lasso selector tool.""" def __init__(self, ax, collection, alpha_other=0.3): """The lasso.""" self.canvas = ax.figure.canvas self.collection = collection self.alpha_other = alpha_other self.xys = collection.get_offsets() self.fcl = collection.get_facecolors() if not self.fcl.any(): raise ValueError('Collection must have a facecolor') elif len(self.fcl) == 1: self.fcl = np.tile(self.fcl, (len(self.xys), 1)) self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] def onselect(self, verts): """Begin lasso.""" path = Path(verts) self.ind = np.nonzero(path.contains_points(self.xys))[0] self.fcl[:, -1] = self.alpha_other self.fcl[self.ind, -1] = 1 self.collection.set_facecolors(self.fcl) self.canvas.draw_idle() def disconnect(self): """End lasso.""" self.lasso.disconnect_events() self.fcl[:, -1] = 1 self.collection.set_facecolors(self.fcl) self.canvas.draw_idle()
class SelectFromCollection(object): def __init__(self, ax, collection, alpha_other=0.3): self.canvas = ax.figure.canvas self.collection = collection self.alpha_other = alpha_other self.xys = collection.get_offsets() self.Npts = len(self.xys) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, (self.Npts, 1)) self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] def onselect(self, verts): path = Path(verts) self.ind = np.nonzero(path.contains_points(self.xys))[0] self.fc[:, -1] = self.alpha_other self.fc[self.ind, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle() def disconnect(self): self.lasso.disconnect_events() self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle()
class SelectFromCollection(object): """Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool highlights selected points by fading them out (i.e., reducing their alpha values). If your collection has alpha < 1, this tool will permanently alter them. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 < = float < = 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, ax, collection,parent): '''Docstring''' self.ax = ax self.canvas = ax.figure.canvas self.collection = collection self.xys = collection self.Npts = len(self.xys) self.parent = parent self.lasso = LassoSelector(ax, onselect = self.onselect) self.ind = [] def onselect(self, verts): '''Docstring''' if self.parent._active == "ZOOM" or self.parent._active == "PAN": return path = Path(verts) self.ind.extend(np.nonzero([path.contains_point(xy) for xy in self.xys])[0]) self.ind = list(np.unique(self.ind)) for line in self.ax.axes.lines: if line.get_gid() == 'node': line.remove() self.ax.plot(self.xys[self.ind,0], self.xys[self.ind,1], 'r.', gid='node') self.canvas.draw_idle() def disconnect(self): '''Docstring''' self.lasso.disconnect_events() self.canvas.draw_idle()
class SelectFromCollection(object): """Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool fades out the points that are not part of the selection (i.e., reduces their alpha values). If your collection has alpha < 1, this tool will permanently alter the alpha values. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, ax, collection, cb_onselect, alpha_other=0.3): self.canvas = ax.figure.canvas self.collection = collection self.alpha_other = alpha_other self.xys = collection.get_offsets() self.Npts = len(self.xys) self.cb_onselect = cb_onselect # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, (self.Npts, 1)) self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] hello = True def onselect(self, verts): path = Path(verts) self.ind = np.nonzero(path.contains_points(self.xys))[0] self.cb_onselect(self) self.fc[:, -1] = 1 self.fc[self.ind, -1] = 0.5 self.collection.set_facecolors(self.fc) self.canvas.draw_idle() def disconnect(self): self.lasso.disconnect_events() self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle()
class SelectFromCollection(object): """Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool fades out the points that are not part of the selection (i.e., reduces their alpha values). If your collection has alpha < 1, this tool will permanently alter the alpha values. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, ax, collection, alpha_other=0.3): self.canvas = ax.figure.canvas self.collection = collection self.alpha_other = alpha_other self.xys = collection.get_offsets() self.Npts = len(self.xys) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, (self.Npts, 1)) self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] def onselect(self, verts): path = Path(verts) self.ind = np.nonzero(path.contains_points(self.xys))[0] self.fc[:, -1] = self.alpha_other self.fc[self.ind, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle() def disconnect(self): self.lasso.disconnect_events() self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle()
class SelectFromCollection: """ Select indices from a matplotlib collection using `LassoSelector`. Modified from https://matplotlib.org/gallery/widgets/lasso_selector_demo_sgskip.html Selected indices are saved in the `ind` attribute. This tool fades out the points that are not part of the selection (i.e., reduces their alpha values). If your collection has alpha < 1, this tool will permanently alter the alpha values. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). """ def __init__(self, ax, collection, alpha_other=0.3, on_select=None): self.canvas = ax.figure.canvas self.collection = collection self.alpha_other = alpha_other self.xys = collection.get_offsets() self.n_pts = len(self.xys) self._on_select = on_select # Ensure that we have separate colors for each object self.facecolors = collection.get_facecolors() if not len(self.facecolors): raise ValueError('Collection must have a facecolor') if len(self.facecolors) == 1: self.facecolors = np.tile(self.facecolors, (self.n_pts, 1)) self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] def onselect(self, verts): try: path = Path(verts) self.ind = np.nonzero(path.contains_points(self.xys))[0] self.facecolors[:, -1] = self.alpha_other self.facecolors[self.ind, -1] = 1 self.collection.set_facecolors(self.facecolors) self.canvas.draw_idle() if self._on_select is not None: self._on_select(self.ind) except Exception: pass def disconnect(self): self.lasso.disconnect_events() self.facecolors[:, -1] = 1 self.collection.set_facecolors(self.facecolors) self.canvas.draw_idle()
class SelectFromImage(object): """ Class used to draw the lassos on the images with two methods: - onselect: save the pixels inside the selection - disconnect: stop drawing lassos on the image Copied with permission from CoastSat (KV, 2020) https://github.com/kvos/CoastSat """ # initialize lasso selection class def __init__(self, ax, implot, color=[1, 1, 1]): self.canvas = ax.figure.canvas self.implot = implot self.array = implot.get_array() xv, yv = np.meshgrid(np.arange(self.array.shape[1]), np.arange(self.array.shape[0])) self.pix = np.vstack((xv.flatten(), yv.flatten())).T self.ind = [] self.im_bool = np.zeros((self.array.shape[0], self.array.shape[1])) self.color = color self.lasso = LassoSelector(ax, onselect=self.onselect) def onselect(self, verts): # find pixels contained in the lasso p = path.Path(verts) self.ind = p.contains_points(self.pix, radius=1) # color selected pixels array_list = [] for k in range(self.array.shape[2]): array2d = self.array[:, :, k] lin = np.arange(array2d.size) new_array2d = array2d.flatten() new_array2d[lin[self.ind]] = self.color[k] array_list.append(new_array2d.reshape(array2d.shape)) self.array = np.stack(array_list, axis=2) self.implot.set_data(self.array) self.canvas.draw_idle() # update boolean image with selected pixels vec_bool = self.im_bool.flatten() vec_bool[lin[self.ind]] = 1 self.im_bool = vec_bool.reshape(self.im_bool.shape) def disconnect(self): self.lasso.disconnect_events()
class SelectFromCollection(object): def __init__(self, ax, collection, alpha_other=0.2): self.canvas = ax.figure.canvas self.collection = collection self.alpha_other = alpha_other self.xys = collection.get_offsets() self.Npts = len(self.xys) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, self.Npts).reshape(self.Npts, -1) self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] def onselect(self, verts): path = Path(verts) self.ind = np.nonzero([path.contains_point(xy) for xy in self.xys])[0] # This is an older code that would reset the colors and the alpha values for the # selected objects #self.fc[:, -1] = self.alpha_other #self.fc[self.ind, -1] = 1 #print self.fc[self.ind] #self.collection.set_facecolors(self.fc) # However currently, we plot the points that are selected with black dots. n_points = len(self.ind) ax.scatter(outlier_z_spec, outlier_z_phot, s=30, c=outlier_snr_colors, edgecolor='None') zspec, zphot = make_into_points(self.xys[self.ind]) ax.scatter(zspec, zphot, s=5, color='black') # And now we plot the inset. plot_point_properties(self.xys[self.ind]) self.canvas.draw_idle() def disconnect(self): self.lasso.disconnect_events() self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle()
class Draw_Lasso(object): def __init__(self, x, y, canvas, figure, data, xlabel, ylabel): self.canvas = canvas self.ax = figure self.ax.clear() self.collection = data self.xlabel = xlabel self.ylabel = ylabel self.xys = self.collection.get_offsets() self.x = x self.y = y self.ax.scatter(x, y, color='blue') self.ind = [] self.lasso = LassoSelector(self.ax, onselect=self.onselect) def onselect(self, verts): print(self.lasso) path = Path(verts) self.ind = np.nonzero([path.contains_point(xy) for xy in self.xys])[0] colors_array = [] for i in range(len(self.x)): if i in self.ind: colors_array.append('red') else: ## points not in ellipse colors_array.append('blue') background = self.canvas.copy_from_bbox(self.ax.bbox) # then during mouse move self.canvas.restore_region(background) self.ax.clear() self.ax.scatter(self.x, self.y, c=colors_array, linewidths=0.3, s=8) self.ax.set_xlabel(self.xlabel) self.ax.set_ylabel(self.ylabel) self.ax.draw_artist(self.ax) self.canvas.blit(self.ax.bbox) # only after mouse has stopped moving self.canvas.draw_idle() def disconnect(self): ## Disable the lasso self.lasso.disconnect_events() self.canvas.draw_idle()
class PointSelector: def __init__(self, tracker, ax, collection, alpha, alpha_other=0.2): self.tracker = tracker self.ax = ax self.collection = collection self.fc = collection.get_facecolors() self.alpha = alpha self.alpha_other = alpha_other self.lasso = LassoSelector(ax, onselect=self.on_select) self.is_connected = True self.toggle() def on_select(self, verts): path = Path(verts) xy = self.collection.get_offsets() self.tracker.picked = list(np.nonzero(path.contains_points(xy))[0]) self.fc[:, -1] = self.alpha_other self.fc[self.tracker.picked, -1] = self.alpha self.collection.set_color(self.fc) self.tracker.display_traces() self.tracker.fig.canvas.draw_idle( ) # Force wx backend to redraw the figure def toggle(self, *args): if self.is_connected: self.disconnect() else: self.reconnect() def disconnect(self): self.lasso.disconnect_events() self.is_connected = False self.tracker.picked = [] self.tracker.picked_pair = [] self.fc[:, -1] = self.alpha self.collection.set_color(self.fc) self.tracker.display_traces(only_picked=False) self.tracker.fig.canvas.draw_idle( ) # Force wx backend to redraw the figure def reconnect(self): self.lasso.connect_default_events() self.is_connected = True
class ExpressionLasso(object): def __init__(self, ax): self.lasso = LassoSelector(ax, onselect=self.onselect) self.fig, self.ax = plt.subplots(3, 5) self.ax = np.array(self.ax).reshape(-1) def onselect(self, verts): p = Path(verts) ind = p.contains_points(transformed) selected_data = concatenated_data[ind] mean_arr = np.zeros(len(hdata.marker_order)) for i, marker in enumerate(hdata.marker_order): mean_arr[i] = np.mean(selected_data[:, i]) for j, i in enumerate(mean_arr.argsort()[-15:][::-1]): self.ax[j].cla() self.ax[j].hist(selected_data[:, i]) self.ax[j].set_title(hdata.marker_order[i]) def disconnect(self): self.lasso.disconnect_events()
class Lasso: """Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool fades out the points that are not part of the selection (i.e., reduces their alpha values). If your collection has alpha < 1, this tool will permanently alter the alpha values. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, ax, button=3): self.canvas = ax.figure.canvas self.Npts = len(self.xys) self.lasso = LassoSelector(ax, onselect=self.onselect, button=[button]) self.ind = [] def onselect(self, verts): path = Path(verts) self.ind = np.nonzero(path.contains_points(self.xys))[0] self.canvas.draw_idle() def disconnect(self): self.lasso.disconnect_events() self.canvas.draw_idle()
class SelectFromCollection(object): """Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool fades out the points that are not part of the selection (i.e., reduces their alpha values). If your collection has alpha < 1, this tool will permanently alter the alpha values. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. """ def __init__(self, ax, collections): self.canvas = ax.figure.canvas self.collections = collections self.wrappers = list(CollectionWrapper(x) for x in collections) self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] def onselect(self, verts): for w in self.wrappers: w.onselect(verts) self.canvas.draw_idle() def disconnect(self): self.lasso.disconnect_events() for w in self.wrappers: w.disconnect() self.canvas.draw_idle()
class SelectFromImage(object): # initialize lasso selection class def __init__(self, ax, implot, color=[1, 1, 1]): self.canvas = ax.figure.canvas self.implot = implot self.array = implot.get_array() xv, yv = np.meshgrid(np.arange(self.array.shape[1]), np.arange(self.array.shape[0])) self.pix = np.vstack((xv.flatten(), yv.flatten())).T self.ind = [] self.im_bool = np.zeros((self.array.shape[0], self.array.shape[1])) self.color = color self.lasso = LassoSelector(ax, onselect=self.onselect) def onselect(self, verts): # find pixels contained in the lasso p = path.Path(verts) self.ind = p.contains_points(self.pix, radius=1) # color selected pixels array_list = [] for k in range(self.array.shape[2]): array2d = self.array[:, :, k] lin = np.arange(array2d.size) new_array2d = array2d.flatten() new_array2d[lin[self.ind]] = self.color[k] array_list.append(new_array2d.reshape(array2d.shape)) self.array = np.stack(array_list, axis=2) self.implot.set_data(self.array) self.canvas.draw_idle() # update boolean image with selected pixels vec_bool = self.im_bool.flatten() vec_bool[lin[self.ind]] = 1 self.im_bool = vec_bool.reshape(self.im_bool.shape) def disconnect(self): self.lasso.disconnect_events()
class ScatterplotWidget(object): def __init__(self, df, scatter_ax, map_ax, alpha_other=0.3, selection_color=[1., 0., 0., 1.], selection_size=3): self.canvas = scatter_ax.figure.canvas self.selection_color = selection_color self.alpha_other = alpha_other self.selection_size = selection_size self.scatter_ax = scatter_ax self.map_ax = map_ax self.create_buttons() self.table_widget = qgrid.show_grid(df, show_toolbar=False, grid_options={ 'editable': False, 'forceFitColumns': False }) self.init_df(df) def init_df(self, df): self.exclude = set() self.mean_line = None self.initial_df = df.set_index(['lon', 'lat']) self.df = df.reset_index().drop_duplicates( ['lon', 'lat', 'time']).set_index(['lon', 'lat']) collection = self.scatter_ax.scatter(self.df.time, self.df.temperature, 1) self.lola = lola = df.drop_duplicates( ['lon', 'lat']).reset_index().set_index(['lon', 'lat']) lola['index'] = np.arange(len(lola)) map_collection = self.map_ax.scatter(lola.index.get_level_values(0), lola.index.get_level_values(1), s=1, transform=ccrs.PlateCarree()) self.collection = collection self.map_collection = map_collection self.xys = collection.get_offsets() self.Npts = len(self.xys) self.map_xys = map_collection.get_offsets() self.map_Npts = len(self.map_xys) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, (self.Npts, 1)) # Ensure that we have separate colors for each object self.map_fc = map_collection.get_facecolors() if len(self.map_fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.map_fc) == 1: self.map_fc = np.tile(self.map_fc, (self.map_Npts, 1)) self.lasso = LassoSelector(self.scatter_ax, onselect=self.onselect) self.map_lasso = LassoSelector(self.map_ax, onselect=self.map_onselect) self.plot_band_mean() self.ind = [] self.map_ind = [] self.refresh_table() @property def band_mean(self): df = self.initial_df if self.exclude: df = df[~df.TSid.isin(self.exclude)] cell_means = df.groupby(['clon', 'clat', 'time']).temperature.mean() band_mean = cell_means.groupby('time').mean() return band_mean def plot_band_mean(self): band_mean = self.band_mean if self.mean_line is not None: self.mean_line.remove() self.mean_line = self.collection.axes.plot(band_mean.index, band_mean.values, c='magenta', lw=4)[0] def onselect(self, verts): path = Path(verts) self.update_points(np.nonzero(path.contains_points(self.xys))[0]) selected = self.df.iloc[self.ind] self.update_map(self.lola.loc[selected.index, 'index'].values) self.refresh_table() self.canvas.draw_idle() def update_points(self, ind): if not len(self.ind) or not self.select_intersection: self.ind = ind else: self.ind = ind[np.isin(ind, self.ind)] if self.select_whole_series: s = pd.Series(np.arange(len(self.df)), index=self.df.index) self.ind = s.loc[np.unique(self.df.iloc[self.ind].index)].values fc = self.fc.copy() fc[:, -1] = self.alpha_other fc[self.ind, :] = [self.selection_color] self.collection.set_facecolors(fc) sizes = np.ones(len(fc)) sizes[self.ind] = self.selection_size self.collection.set_sizes(sizes) def map_onselect(self, verts): path = Path(verts) self.update_map(np.nonzero(path.contains_points(self.map_xys))[0]) selected = self.lola.iloc[self.map_ind] self.update_points(self.df.loc[selected.index, 'index'].values) self.refresh_table() self.canvas.draw_idle() @property def select_whole_series(self): return self.btn_whole_line.value @property def select_intersection(self): return self.btn_intersect.value @property def show_all_samples(self): return self.btn_show_all_rows.value def create_buttons(self): self.btn_whole_line = widgets.ToggleButton( description='Whole series', tooltip= 'Select the whole time-series for the selected points in the time-age-scatter plot' ) self.btn_intersect = widgets.ToggleButton( description="Intersection", tooltip="Keep only the intersection with the current selection") self.btn_show_all_rows = widgets.ToggleButton( description="Show all rows", tooltip="Show all rows of the corresponding grid cell") self.btn_exclude_selection = widgets.Button( description="Exclude in mean", tooltip=("Exclude the selected time-series in the calculation of " "the band mean")) self.btn_exclude_selection.on_click(self.exclude_selection) self.btn_include_selection = widgets.Button( description="Include in mean", tooltip=("Include the selected time-series (or all if nothing is " "selected) in the calculation of the band mean")) self.btn_include_selection.on_click(self.include_selection) self.btn_reset = widgets.Button(description="Reset", tooltip="Clear the selection") self.btn_reset.on_click(self.clear_selection) self.btn_refresh_table = widgets.Button( description="Refresh table", tooltip="Refresh the table with the current selection") self.btn_refresh_table.on_click(self.refresh_table) self.btn_export_selection = widgets.Button( description="Export to", tooltip="Export the selection to an Excel file") self.btn_export_selection.on_click(self.export_selection) self.txt_export = widgets.Text( value='selection.xlsx', placeholder='Enter a filename', ) self.btn_copy_ids = widgets.Button( description="Copy IDs", tooltip="Copy the selected TSids to clipboard") self.btn_copy_ids.on_click(self.copy_ids) self.btn_copy_datasets = widgets.Button( description="Copy datasetNames", tooltip="Copy selected LiPD datasets names to clipboard") self.btn_copy_datasets.on_click(self.copy_dataset_names) self.btn_copy_table = widgets.Button( description="Copy table", tooltip="Copy the entire table to clipboard") self.btn_copy_table.on_click(self.copy_all) self.out_download = widgets.Output() self.vbox = widgets.VBox([ widgets.HBox([self.btn_whole_line, self.btn_intersect]), widgets.HBox( [self.btn_exclude_selection, self.btn_include_selection]), widgets.HBox([ self.btn_reset, self.btn_refresh_table, self.btn_show_all_rows ]), widgets.HBox([ self.btn_export_selection, self.txt_export, self.out_download ]), widgets.HBox([ self.btn_copy_ids, self.btn_copy_datasets, self.btn_copy_table ]), ]) def include_selection(self, *args, **kwargs): if not len(self.ind): self.exclude.clear() self.plot_band_mean() else: self.exclude.difference_update(self.df.iloc[self.ind].TSid) self.plot_band_mean() self.canvas.draw_idle() def exclude_selection(self, *args, **kwargs): if not len(self.ind): pass else: self.exclude.update(self.df.iloc[self.ind].TSid) self.plot_band_mean() self.canvas.draw_idle() def export_selection(self, *args, **kwargs): target_file = self.txt_export.value if not len(self.ind): selection = self.initial_df else: selection = self.initial_df.loc[self.df.iloc[ self.ind].index.drop_duplicates()] selection.to_excel(target_file) self.out_download.clear_output() self.out_download.clear_output() self.out_download.append_display_data( HTML(f"<a href='{target_file}' target='_blank' " f" title='Download the selection'>" f" Download {target_file}" f"</a>")) @property def selection(self): return self.table_widget.get_changed_df() def copy_ids(self, *args, **kwargs): self.copy_columns('TSid') def copy_dataset_names(self, *args, **kwargs): self.copy_columns('dataSetName') def copy_all(self, *args, **kwargs): self.selection.to_clipboard(index=False, header=True) def copy_columns(self, *cols): cols = list(cols) selection = self.selection.drop_duplicates(cols)[cols] selection.to_clipboard(index=False, header=False) def clear_selection(self, *args, **kwargs): ind = np.array([], dtype=int) self.update_points(ind) self.update_map(ind) self.collection.set_facecolors(self.fc) self.map_collection.set_facecolors(self.map_fc) self.refresh_table() def refresh_table(self, *args, **kwargs): ind = np.unique(self.map_ind) selected = self.lola.iloc[ind if len(ind) else slice(None)] if self.show_all_samples: selected = self.initial_df.loc[selected.index] self.table_widget.df = selected def update_map(self, ind): if not len(self.ind) or not self.select_intersection: self.map_ind = ind else: self.map_ind = ind[np.isin(ind, self.map_ind)] fc = self.map_fc.copy() fc[:, -1] = self.alpha_other fc[self.map_ind, :] = [self.selection_color] self.map_collection.set_facecolors(fc) sizes = np.ones(len(fc)) sizes[self.map_ind] = self.selection_size self.map_collection.set_sizes(sizes) def disconnect(self): self.lasso.disconnect_events() self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.map_lasso.disconnect_events() self.map_fc[:, -1] = 1 self.collection.set_facecolors(self.map_fc)
# plt.grid(True) # plt.xlim(xmin = 0) #, xmax = 325) # plt.ylim(ymax = 0) #, ymax = 375) lasso = LassoSelector(ax = ax, onselect = onselect, useblit = True, lineprops = dict(color = 'yellow', linewidth = 7, linestyle = 'dashed', marker = 'None')) print "Press any key to finish mask selection" while True: buttonpressed = plt.waitforbuttonpress(timeout = -1) if buttonpressed: break lasso.disconnect_events() fig.canvas.manager.set_window_title('Mask selection DONE') plt.show() # <codecell> %%script python # --bg --err stderror_pipe --out stdout_pipe import sys import numpy as np print sys.argv print 'Python version: %s' % sys.version import matplotlib as mpl
class SelectFromCollection(object): """Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool fades out the points that are not part of the selection (i.e., reduces their alpha values). If your collection has alpha < 1, this tool will permanently alter the alpha values. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, ax, img): self.canvas = ax.figure.canvas self.ax = ax dx, dy = img.shape xv, yv = np.meshgrid(np.arange(dx), np.arange(dy), indexing='ij') self.pix = np.vstack((yv.flatten(), xv.flatten())).T self.array = np.zeros((dx, dy)) self.msk = ax.imshow(self.array, vmin=0, vmax=1, cmap='Blues', alpha=0.5) lineprops = {'color': 'red', 'linewidth': 4, 'alpha': 0.4} self.lasso = LassoSelector(ax, onselect=self.onselect, lineprops=lineprops, useblit=False) self.ind = [] self.verts = [] self.array_list = [] def onselect(self, verts): def updateArray(array, indices): lin = np.arange(array.size) newArray = array.flatten() newArray[lin[indices]] = 1 return newArray.reshape(array.shape) p = Path(verts) self.verts.append(verts) self.ind = p.contains_points(self.pix, radius=1) tmp = updateArray(self.array, self.ind) self.array_list.append(tmp) x, y = np.array(verts).T self.ax.plot(x, y, '-', lw=2) self.msk.set_data(tmp) self.canvas.draw_idle() def disconnect(self): self.lasso.disconnect_events() self.canvas.draw_idle()
class SelectFromCollection(object): def __init__(self, ax, collection, alpha_other=0.3): # xys = [] # Npts = [] # fc = [] # ec = [] # ind = [] # # for i in range(0,len(collection)): # # xysSingle = collection[i].get_offsets().data # NptsSingle = len(xysSingle) # fcSingle = np.tile(collection[i].get_facecolors(),(NptsSingle,1)) # ecSingle = np.tile(collection[i].get_edgecolors(),(NptsSingle,1)) # indSingle = [] # # xys.append(xysSingle) # Npts.append(NptsSingle) # fc.append(fcSingle) # ec.append(ecSingle) # ind.append(indSingle) # # # endFor # # self.xys = xys # self.Npts = Npts # self.fc = fc # self.ec = ec # self.ind = ind self.canvas = ax.figure.canvas self.collection = collection self.ax = ax self.alpha_other = alpha_other self.xys = collection.get_offsets().data self.Npts = len(self.xys) self.baseColor = collection.get_facecolors() self.fc = [] self.fc = np.tile(collection.get_facecolors(), (self.Npts, 1)) self.ind = [] self.lasso = LassoSelector(ax, onselect=self.onselect) self.active = True def onselect(self, verts): # Get vertices of lasso path = Path(verts) # for i in range(0,len(self.collection)): # self.fc[i] = self.ec[i] # self.ind[i] = np.nonzero(path.contains_points(self.xys[i]))[0] # self.fc[i][self.ind[i],0] = 1 # self.fc[i][self.ind[i],1] = 0 # self.fc[i][self.ind[i],2] = 0 # self.collection[i].set_edgecolors(self.fc[i][:,:]) # # endFor self.ind = [] self.ind = np.nonzero(path.contains_points(self.xys))[0] fc = self.fc fc[:, :] = self.baseColor fc[self.ind, 0] = 1 fc[self.ind, 1] = 0 fc[self.ind, 2] = 0 self.collection.set_edgecolors(fc) self.canvas.blit(self.ax.bbox) self.active = True def disconnect(self): self.lasso.disconnect_events() # for i in range(0,len(self.collection)): # self.collection[i].set_edgecolors(self.ec[i][:,:]) # # endFor self.ind = [] self.collection.set_edgecolors(self.baseColor) self.canvas.blit(self.ax.bbox) self.active = False def revert(self): # for i in range(0,len(self.collection)): # self.collection[i].set_edgecolors(self.ec[i][:,:]) # # endFor self.ind = [] self.collection.set_edgecolors(self.baseColor) self.canvas.blit(self.ax.bbox) self.active = True
class SelectFromCollection(object): ''' Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool fades out the points that are not part of the selection (i.e., reduces their alpha values). If your collection has alpha < 1, this tool will permanently alter the alpha values. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. ''' def __init__(self, passToLasso, ax, collection, alpha_other=0.3): self.passToLasso = passToLasso self.ax = ax self.fig = self.ax.figure self.canvas = self.fig.canvas self.collection = collection self.alpha_other = alpha_other self.is_subtract = True self.pt2Data = None self.pts = collection.get_offsets() self.Npts = len(self.pts) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, (self.Npts, 1)) # All points are initially selected. self.fc[:, -1] = 1 # 1 corresponds to "filled in" instead of translucent self.collection.set_facecolors(self.fc) self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] # Register the callback functions and store the associated connection ID's. self.press_cid = self.fig.canvas.mpl_connect("key_press_event", self.key_press) self.release_cid = self.fig.canvas.mpl_connect("key_release_event", self.key_release) title = '''Select points you would like to remove.\n Hold down the left mouse button to use the lasso selector.\n Hold Shift to unremove points.\n Press Enter to confirm your selection.''' ax.set_title(title) def onselect(self, verts): path = Path(verts) self.ind = np.nonzero(path.contains_points(self.pts))[0] # Subtract or add selections depending on whether shift is pressed or not. if self.is_subtract: self.fc[self.ind, -1] = self.alpha_other else: self.fc[self.ind, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle() def disconnect(self): self.lasso.disconnect_events() self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle() self.canvas.mpl_disconnect(self.press_cid) self.canvas.mpl_disconnect(self.release_cid) def key_press(self, event): if event.key == "shift": self.is_subtract = False elif event.key == "enter": # Remove the points that were selected from the contour by the user. pt2Data = self.passToLasso.pt2Data pt2Data.RVFW_CS = ut.deleteHelper(pt2Data.RVFW_CS, self.ind, axis=0) # Deconstruct the lasso selector. self.disconnect() self.ax.set_title("") self.canvas.draw() self.parent_widg.close() # Finish up the masks2Contours process. masks2Contours.slice2ContoursPt2( pt2Data=pt2Data, sliceIndex=self.passToLasso.sliceIndex, numLASlices=self.passToLasso.numLAslices) def key_release(self, event): if event.key == "shift": self.is_subtract = True
class regions(object): ''' A class used for manual inspection and processing of all picks for the user. Examples: regions.chooseRectangles(): - lets the user choose several rectangular regions in the plot regions.plotTracesInActiveRegions(): - creates plots (shot.plot_traces) for all traces in the active regions (i.e. chosen by e.g. chooseRectangles) regions.setAllActiveRegionsForDeletion(): - highlights all shots in a the active regions for deletion regions.deleteAllMarkedPicks(): - deletes the picks (pick flag set to False) for all shots set for deletion regions.deselectSelection(number): - deselects the region of number = number ''' def __init__(self, ax, cbar, survey, qt_interface=False): self.ax = ax self.cbar = cbar self.cbv = 'log10SNR' self._xlim0 = self.ax.get_xlim() self._ylim0 = self.ax.get_ylim() self._xlim = self.ax.get_xlim() self._ylim = self.ax.get_ylim() self.survey = survey self.shot_dict = self.survey.getShotDict() self._x0 = [] self._y0 = [] self._x1 = [] self._y1 = [] self._polyx = [] self._polyy = [] self._allpicks = None self.shots_found = {} self.shots_for_deletion = {} self._generateList() self.qt_interface = qt_interface if not qt_interface: self.buttons = {} self._addButtons() self.addTextfield() self.drawFigure() def _generateList(self): allpicks = [] for shot in self.shot_dict.values(): for traceID in shot.getTraceIDlist(): allpicks.append( (shot.getDistance(traceID), shot.getPickIncludeRemoved(traceID), shot.getShotnumber(), traceID, shot.getPickFlag(traceID))) allpicks.sort() self._allpicks = allpicks def getShotDict(self): return self.shot_dict def getShotsForDeletion(self): return self.shots_for_deletion def _onselect_clicks(self, eclick, erelease): '''eclick and erelease are matplotlib events at press and release''' print('region selected x0, y0 = (%3s, %3s), x1, y1 = (%3s, %3s)' % (eclick.xdata, eclick.ydata, erelease.xdata, erelease.ydata)) x0 = min(eclick.xdata, erelease.xdata) x1 = max(eclick.xdata, erelease.xdata) y0 = min(eclick.ydata, erelease.ydata) y1 = max(eclick.ydata, erelease.ydata) shots, numtraces = self.findTracesInShotDict((x0, x1), (y0, y1)) self.printOutput('Found %d traces in rectangle: %s' % (numtraces, shots)) key = self.getKey() self.shots_found[key] = { 'shots': shots, 'selection': 'rect', 'xvalues': (x0, x1), 'yvalues': (y0, y1) } self.markRectangle((x0, x1), (y0, y1), key) if not self.qt_interface: self.disconnectRect() def _onselect_verts(self, verts): x = verts[0][0] y = verts[0][1] self._polyx.append(x) self._polyy.append(y) self.drawPolyLine() def _onpress(self, event): if event.button == 3: self.disconnectPoly() self.printOutput('Disconnected polygon selection') def addTextfield(self, xpos=0, ypos=0.95, width=1, height=0.03): ''' Adds an ax for text output to the plot. ''' self.axtext = self.ax.figure.add_axes([xpos, ypos, width, height]) self.axtext.xaxis.set_visible(False) self.axtext.yaxis.set_visible(False) def writeInTextfield(self, text=None): self.setXYlim(self.ax.get_xlim(), self.ax.get_ylim()) self.axtext.clear() self.axtext.text(0.01, 0.5, text, verticalalignment='center', horizontalalignment='left') self.drawFigure() def _addButtons(self): xpos1 = 0.13 xpos2 = 0.6 dx = 0.06 self.addButton('Rect', self.chooseRectangles, xpos=xpos1, color='white') self.addButton('Poly', self.choosePolygon, xpos=xpos1 + dx, color='white') self.addButton('Plot', self.plotTracesInActiveRegions, xpos=xpos1 + 2 * dx, color='yellow') self.addButton('SNR', self.refreshLog10SNR, xpos=xpos1 + 3 * dx, color='cyan') self.addButton('PE', self.refreshPickerror, xpos=xpos1 + 4 * dx, color='cyan') self.addButton('SPE', self.refreshSPE, xpos=xpos1 + 5 * dx, color='cyan') self.addButton('DesLst', self.deselectLastSelection, xpos=xpos2 + dx, color='green') self.addButton('SelAll', self.setAllActiveRegionsForDeletion, xpos=xpos2 + 2 * dx) self.addButton('DelAll', self.deleteAllMarkedPicks, xpos=xpos2 + 3 * dx, color='red') def addButton(self, name, action, xpos, ypos=0.91, color=None): from matplotlib.widgets import Button self.buttons[name] = { 'ax': None, 'button': None, 'action': action, 'xpos': xpos } ax = self.ax.figure.add_axes([xpos, ypos, 0.05, 0.03]) button = Button(ax, name, color=color, hovercolor='grey') button.on_clicked(action) self.buttons[name]['ax'] = ax self.buttons[name]['button'] = button self.buttons[name]['xpos'] = xpos def getKey(self): if self.shots_found.keys() == []: key = 1 else: key = max(self.getShotsFound().keys()) + 1 return key def drawPolyLine(self): self.setXYlim(self.ax.get_xlim(), self.ax.get_ylim()) x = self._polyx y = self._polyy if len(x) >= 2 and len(y) >= 2: self.ax.plot(x[-2:], y[-2:], 'k', alpha=0.1, linewidth=1) self.drawFigure() def drawLastPolyLine(self): self.setXYlim(self.ax.get_xlim(), self.ax.get_ylim()) x = self._polyx y = self._polyy if len(x) >= 2 and len(y) >= 2: self.ax.plot((x[-1], x[0]), (y[-1], y[0]), 'k', alpha=0.1) self.drawFigure() def finishPolygon(self): self.drawLastPolyLine() x = self._polyx y = self._polyy self._polyx = [] self._polyy = [] key = self.getKey() self.markPolygon(x, y, key=key) shots, numtraces = self.findTracesInPoly(x, y) self.shots_found[key] = { 'shots': shots, 'selection': 'poly', 'xvalues': x, 'yvalues': y } self.printOutput('Found %d traces in polygon: %s' % (numtraces, shots)) def printOutput(self, text): print(text) self.writeInTextfield(text) def chooseRectangles(self, event=None): ''' Activates matplotlib widget RectangleSelector. ''' from matplotlib.widgets import RectangleSelector if hasattr(self, '_cidPoly'): self.disconnectPoly() self.printOutput( 'Select rectangle is active. Press and hold left mousebutton.') self._cidRect = None self._cidRect = self.ax.figure.canvas.mpl_connect( 'button_press_event', self._onpress) self._rectangle = RectangleSelector(self.ax, self._onselect_clicks) return self._rectangle def choosePolygon(self, event=None): ''' Activates matplotlib widget LassoSelector. ''' from matplotlib.widgets import LassoSelector if hasattr(self, '_cidRect'): self.disconnectRect() self.printOutput( 'Select polygon is active. Add points with leftclick. Finish with rightclick.' ) self._cidPoly = None self._cidPoly = self.ax.figure.canvas.mpl_connect( 'button_press_event', self._onpress) self._lasso = LassoSelector(self.ax, self._onselect_verts) return self._lasso def disconnectPoly(self, event=None): if not hasattr(self, '_cidPoly'): self.printOutput('no poly selection found') return self.ax.figure.canvas.mpl_disconnect(self._cidPoly) del self._cidPoly self.finishPolygon() self._lasso.disconnect_events() print('disconnected poly selection\n') def disconnectRect(self, event=None): if not hasattr(self, '_cidRect'): self.printOutput('no rectangle selection found') return self.ax.figure.canvas.mpl_disconnect(self._cidRect) del self._cidRect self._rectangle.disconnect_events() print('disconnected rectangle selection\n') def deselectLastSelection(self, event=None): if self.shots_found.keys() == []: self.printOutput('No selection found.') return key = max(self.shots_found.keys()) self.deselectSelection(key) self.refreshFigure() def deselectSelection(self, key, color='green', alpha=0.1): if key not in self.shots_found.keys(): self.printOutput('No selection found.') return if color is not None: if self.shots_found[key]['selection'] == 'rect': self.markRectangle(self.shots_found[key]['xvalues'], self.shots_found[key]['yvalues'], key=key, color=color, alpha=alpha, linewidth=1) elif self.shots_found[key]['selection'] == 'poly': self.markPolygon(self.shots_found[key]['xvalues'], self.shots_found[key]['yvalues'], key=key, color=color, alpha=alpha, linewidth=1) value = self.shots_found.pop(key) self.printOutput('Deselected selection number %d' % key) def findTracesInPoly(self, x, y, picks='normal', highlight=True): def dotproduct(v1, v2): return sum((a * b for a, b in zip(v1, v2))) def getlength(v): return math.sqrt(dotproduct(v, v)) def getangle(v1, v2): return np.rad2deg( math.acos( dotproduct(v1, v2) / (getlength(v1) * getlength(v2)))) def insidePoly(x, y, pickX, pickY): angle = 0 epsilon = 1e-07 for index in range(len(x)): xval1 = x[index - 1] yval1 = y[index - 1] xval2 = x[index] yval2 = y[index] angle += getangle([xval1 - pickX, yval1 - pickY], [xval2 - pickX, yval2 - pickY]) if 360 - epsilon <= angle <= 360 + epsilon: ### IMPROVE THAT?? return True if len(x) == 0 or len(y) == 0: self.printOutput('No polygon defined.') return shots_found = {} numtraces = 0 x0 = min(x) x1 = max(x) y0 = min(y) y1 = max(y) shots, numtracesrect = self.findTracesInShotDict((x0, x1), (y0, y1), highlight=False) for shotnumber in shots.keys(): shot = self.shot_dict[shotnumber] for traceID in shots[shotnumber]: if shot.getPickFlag(traceID): pickX = shot.getDistance(traceID) pickY = shot.getPick(traceID) if insidePoly(x, y, pickX, pickY): if shotnumber not in shots_found.keys(): shots_found[shotnumber] = [] shots_found[shotnumber].append(traceID) if highlight == True: self.highlightPick(shot, traceID) numtraces += 1 self.drawFigure() return shots_found, numtraces def findTracesInShotDict(self, xtup, ytup, picks='normal', highlight=True): ''' Returns traces corresponding to a certain area in the plot with all picks over the distances. ''' x0, x1 = xtup y0, y1 = ytup shots_found = {} numtraces = 0 if picks == 'normal': pickflag = False elif picks == 'includeCutOut': pickflag = None for line in self._allpicks: dist, pick, shotnumber, traceID, flag = line if flag == pickflag: continue ### IMPROVE THAT if (x0 <= dist <= x1 and y0 <= pick <= y1): if shotnumber not in shots_found.keys(): shots_found[shotnumber] = [] shots_found[shotnumber].append(traceID) if highlight == True: self.highlightPick(self.shot_dict[shotnumber], traceID) numtraces += 1 self.drawFigure() return shots_found, numtraces def highlightPick(self, shot, traceID, annotations=True): ''' Highlights a single pick for a shot(object)/shotnumber and traceID. If annotations == True: Displays shotnumber and traceID in the plot. ''' if type(shot) == int: shot = self.survey.getShotDict()[shot] if not shot.getPickFlag(traceID): return self.ax.scatter(shot.getDistance(traceID), shot.getPick(traceID), s=50, marker='o', facecolors='none', edgecolors='m', alpha=1) if annotations == True: self.ax.annotate(s='s%s|t%s' % (shot.getShotnumber(), traceID), xy=(shot.getDistance(traceID), shot.getPick(traceID)), fontsize='xx-small') def highlightAllActiveRegions(self): ''' Highlights all picks in all active regions. ''' for key in self.shots_found.keys(): for shotnumber in self.shots_found[key]['shots'].keys(): for traceID in self.shots_found[key]['shots'][shotnumber]: self.highlightPick(self.shot_dict[shotnumber], traceID) self.drawFigure() def plotTracesInActiveRegions(self, event=None, keys='all', maxfigures=20, qt=False, qtMainwindow=None): ''' Plots all traces in the active region or for all specified keys. :param: keys :type: int or list :param: maxfigures, maximum value of figures opened :type: int ''' if qt: from PySide import QtGui from asp3d.gui.windows import Repicking_window repickingQt = [] ntraces = 0 traces2plot = [] if keys == 'all': keys = self.shots_found.keys() elif type(keys) == int: keys = [keys] if len(self.shots_found) > 0: for shot in self.shot_dict.values(): for key in keys: for shotnumber in self.shots_found[key]['shots']: if shot.getShotnumber() == shotnumber: for traceID in self.shots_found[key]['shots'][ shotnumber]: ntraces += 1 if ntraces > maxfigures: print( 'Maximum number of figures ({}) reached. Figure #{} for shot #{} ' 'will not be opened.'.format( maxfigures, ntraces, shot.getShotnumber())) break traces2plot.append([shot, traceID]) else: self.printOutput('No picks defined in that region(s)') return if ntraces > maxfigures and qt: reply = QtGui.QMessageBox.question( qtMainwindow, 'Message', 'Maximum number of opened figures is ' '{}. Do you want to continue without plotting all ' '{} figures?'.format(maxfigures, ntraces), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No) if not reply == QtGui.QMessageBox.Yes: return for shot, traceID in traces2plot: if qt: repickingQt.append( Repicking_window(qtMainwindow, shot, traceID)) else: shot.plot_traces(traceID) if qt: return repickingQt def setAllActiveRegionsForDeletion(self, event=None): keys = [] for key in self.shots_found.keys(): keys.append(key) self.setRegionForDeletion(keys) def setRegionForDeletion(self, keys): if type(keys) == int: keys = [keys] for key in keys: for shotnumber in self.shots_found[key]['shots'].keys(): if shotnumber not in self.shots_for_deletion: self.shots_for_deletion[shotnumber] = [] for traceID in self.shots_found[key]['shots'][shotnumber]: if traceID not in self.shots_for_deletion[shotnumber]: self.shots_for_deletion[shotnumber].append(traceID) self.deselectSelection(key, color='red', alpha=0.2) self.deselectSelection(key, color='red', alpha=0.2) self.printOutput('Set region(s) %s for deletion' % keys) def markAllActiveRegions(self): for key in self.shots_found.keys(): if self.shots_found[key]['selection'] == 'rect': self.markRectangle(self.shots_found[key]['xvalues'], self.shots_found[key]['yvalues'], key=key) if self.shots_found[key]['selection'] == 'poly': self.markPolygon(self.shots_found[key]['xvalues'], self.shots_found[key]['yvalues'], key=key) def markRectangle(self, xtup, ytup, key=None, color='grey', alpha=0.1, linewidth=1): ''' Mark a rectangular region on the axes. ''' from matplotlib.patches import Rectangle x0, x1 = xtup y0, y1 = ytup self.ax.add_patch( Rectangle((x0, y0), x1 - x0, y1 - y0, alpha=alpha, facecolor=color, linewidth=linewidth)) if key is not None: self.ax.text(x0 + (x1 - x0) / 2, y0 + (y1 - y0) / 2, str(key)) self.drawFigure() def markPolygon(self, x, y, key=None, color='grey', alpha=0.1, linewidth=1): from matplotlib.patches import Polygon poly = Polygon(np.array(zip(x, y)), color=color, alpha=alpha, lw=linewidth) self.ax.add_patch(poly) if key is not None: self.ax.text( min(x) + (max(x) - min(x)) / 2, min(y) + (max(y) - min(y)) / 2, str(key)) self.drawFigure() def clearShotsForDeletion(self): ''' Clears the list of shots marked for deletion. ''' self.shots_for_deletion = {} print('Cleared all shots that were set for deletion.') def getShotsFound(self): return self.shots_found def deleteAllMarkedPicks(self, event=None): ''' Deletes all shots set for deletion. ''' if len(self.getShotsForDeletion()) is 0: self.printOutput('No shots set for deletion.') return for shot in self.getShotDict().values(): for shotnumber in self.getShotsForDeletion(): if shot.getShotnumber() == shotnumber: for traceID in self.getShotsForDeletion()[shotnumber]: shot.removePick(traceID) print( "Deleted the pick for traceID %s on shot number %s" % (traceID, shotnumber)) self.clearShotsForDeletion() self.refreshFigure() def highlightPicksForShot(self, shot, annotations=False): ''' Highlight all picks for a given shot. ''' if type(shot) is int: shot = self.survey.getShotDict()[shot.getShotnumber()] for traceID in shot.getTraceIDlist(): if shot.getPickFlag(traceID): self.highlightPick(shot, traceID, annotations) self.drawFigure() def setXYlim(self, xlim, ylim): self._xlim, self._ylim = xlim, ylim def refreshLog10SNR(self, event=None): cbv = 'log10SNR' self.cbv = cbv self.refreshFigure(self, colorByVal=cbv) def refreshPickerror(self, event=None): cbv = 'pickerror' self.cbv = cbv self.refreshFigure(self, colorByVal=cbv) def refreshSPE(self, event=None): cbv = 'spe' self.cbv = cbv self.refreshFigure(self, colorByVal=cbv) def refreshFigure(self, event=None, colorByVal=None): if colorByVal == None: colorByVal = self.cbv else: self.cbv = colorByVal self.printOutput('Refreshing figure...') self.ax.clear() self.ax = self.survey.plotAllPicks(ax=self.ax, cbar=self.cbar, refreshPlot=True, colorByVal=colorByVal) self.setXYlim(self.ax.get_xlim(), self.ax.get_ylim()) self.markAllActiveRegions() self.highlightAllActiveRegions() self.drawFigure() self.printOutput('Done!') def drawFigure(self, resetAxes=True): if resetAxes == True: self.ax.set_xlim(self._xlim) self.ax.set_ylim(self._ylim) self.ax.figure.canvas.draw()
class CollectionSelector(object): """Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool highlights selected points by fading them out (i.e., reducing their alpha values). If your collection has alpha < 1, this tool will permanently alter them. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, ax, collection, color_other="k", onselection=None): self.canvas = ax.figure.canvas self.collection = collection self.color_other = colorConverter.to_rgba(color_other) self.xys = collection.get_offsets() self.Npts = len(self.xys) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError("Collection must have a facecolor") elif len(self.fc) == 1: self.fc = np.tile(self.fc, self.Npts).reshape(self.Npts, -1) self.sfc = self.fc.copy() self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] self.onselection = onselection def updateselection(self): self.sfc[:, :] = self.fc[:, :] if len(self.ind) > 0: self.sfc[self.ind, :] = self.color_other self.collection.set_facecolors(self.sfc) self.canvas.draw_idle() def selectall(self): self.ind = range(self.Npts) self.updateselection() def reset(self): self.ind = [] self.updateselection() def onselect(self, verts): path = Path(verts) self.ind = list(np.nonzero([path.contains_point(xy) for xy in self.xys])[0]) self.updateselection() if self.onselection is not None: self.onselection(self.ind) def disconnect(self): self.lasso.disconnect_events() # self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle()
class SelectFromCollection(object): """Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool highlights selected points by fading them out (i.e., reducing their alpha values). If your collection has alpha < 1, this tool will permanently alter them. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, ax, collection,selected_color=(0,0,1,1),unselected_color=(1,0,0,1)): self.canvas = ax.figure.canvas self.collection = collection self.unselected_color = unselected_color self.selected_color = selected_color self.shift_is_held = False self.xys = collection.get_offsets() self.Npts = len(self.xys) self.canvas.mpl_connect('key_press_event', self.on_key_press) self.canvas.mpl_connect('key_release_event', self.on_key_release) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, self.Npts).reshape(self.Npts, -1) lineprops = dict(color='black', linestyle='-',linewidth = 2, alpha=1) self.lasso = LassoSelector(ax, onselect=self.onselect,lineprops=lineprops) self.ind = [] def on_key_press(self, event): if event.key == 'shift': self.shift_is_held = True def on_key_release(self, event): if event.key == 'shift': self.shift_is_held = False def onselect(self, verts): path = Path(verts) old_ind = self.ind self.ind = np.nonzero([path.contains_point(xy) for xy in self.xys])[0] if self.shift_is_held: self.ind = np.unique(np.append(self.ind, old_ind)) self.fc[:, :] = self.unselected_color self.fc[self.ind, :] = self.selected_color self.collection.set_facecolors(self.fc) self.canvas.draw_idle() def disconnect(self): self.lasso.disconnect_events() self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle()
class SelectFromCollection(object): """ This is an adapted bit of code that prints out information about the lasso'd data points. This code was originally written in plane_hunt.py and is being adapted for use with 2d histograms. Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. """ def __init__(self, ax, collection, eventids, runnum, total_hpol_delays,total_vpol_delays,alpha_other=0.3): self.canvas = ax.figure.canvas self.eventids = eventids self.runnum = runnum self.id = numpy.array(list(zip(self.runnum,self.eventids))) self.collection = collection self.alpha_other = alpha_other self.xys = collection.get_offsets() self.Npts = len(self.xys) self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] self.total_hpol_delays = total_hpol_delays self.total_vpol_delays = total_vpol_delays def onselect(self, verts): path = Path(verts) self.ind = numpy.nonzero(path.contains_points(self.xys))[0] print('Selected run/eventids:') print(repr(self.id[self.ind])) txtToClipboard(repr(self.id[self.ind])) event_info = self.id[self.ind] #print(event_info) print('Coordinates:') print(repr(self.xys[self.ind])) self.canvas.draw_idle() self.alignSelectedEvents() def plotTimeDelays(self,times,total_hpol_delays,total_vpol_delays): ''' This is intended to reproduce the plot that Kaeli used to make, with the time delays being plotted all on the same plot. ''' times = times - times[0] for pol in ['Hpol','Vpol']: _fig = plt.figure() _fig.canvas.set_window_title('%s Delays'%pol) plt.minorticks_on() plt.grid(b=True, which='major', color='k', linestyle='-') plt.grid(b=True, which='minor', color='tab:gray', linestyle='--',alpha=0.5) plt.title(pol) plt.ylabel('Time Delay (ns)') plt.xlabel('Readout Time (s)') for pair_index, pair in enumerate([[0,1],[0,2],[0,3],[1,2],[1,3],[2,3]]): if pol == 'Hpol': y = total_hpol_delays[:,pair_index] else: y = total_vpol_delays[:,pair_index] #plt.plot(times, y,linestyle = '--',alpha=0.5) plt.scatter(times, y,label='A%i and A%i'%(pair[0],pair[1])) plt.legend(loc='upper right') def alignSelectedEvents(self, plot_aligned_wf=False,save_template=False,plot_timedelays=True): ''' My plan is for this to be called when some events are circled in the plot. It will take those wf, align them, and plot the averaged waveforms. No filters will be applied. ''' if plot_timedelays == True: runs, counts = numpy.unique(self.id[self.ind][:,0],return_counts=True) run = runs[numpy.argmax(counts)] print('Only calculating template from run with most points circled: run %i with %i events circled'%(run,max(counts))) eventids = self.id[self.ind][:,1][self.id[self.ind][:,0] == run] coords = self.xys[self.ind] self.plotTimeDelays(self.xys[self.ind][:,0]*60,self.total_hpol_delays[self.ind],self.total_vpol_delays[self.ind]) _reader = Reader(datapath,run) crit_freq_low_pass_MHz = None low_pass_filter_order = None crit_freq_high_pass_MHz = None# 45 high_pass_filter_order = None# 12 waveform_index_range = (None,None) final_corr_length = 2**18 tct = TemplateCompareTool(_reader, final_corr_length=final_corr_length, crit_freq_low_pass_MHz=crit_freq_low_pass_MHz, crit_freq_high_pass_MHz=crit_freq_high_pass_MHz, low_pass_filter_order=low_pass_filter_order, high_pass_filter_order=high_pass_filter_order, waveform_index_range=waveform_index_range, plot_filters=False,apply_phase_response=True) tdc = TimeDelayCalculator(_reader, final_corr_length=final_corr_length, crit_freq_low_pass_MHz=crit_freq_low_pass_MHz, crit_freq_high_pass_MHz=crit_freq_high_pass_MHz, low_pass_filter_order=low_pass_filter_order, high_pass_filter_order=high_pass_filter_order, waveform_index_range=waveform_index_range, plot_filters=False,apply_phase_response=True) self.cor = Correlator(_reader, upsample=2**15, n_phi=360, n_theta=360, waveform_index_range=(None,None),crit_freq_low_pass_MHz=crit_freq_low_pass_MHz, crit_freq_high_pass_MHz=crit_freq_high_pass_MHz, low_pass_filter_order=low_pass_filter_order, high_pass_filter_order=high_pass_filter_order, plot_filter=False,apply_phase_response=True) if True: print('TRYING TO MAKE CORRELATOR PLOT.') print(eventids) self.cor.animatedMap(eventids, 'both', '', plane_zenith=None,plane_az=None,hilbert=False, max_method=None,center_dir='E',save=False,dpi=300) times, averaged_waveforms = tct.averageAlignedSignalsPerChannel( eventids, align_method=0, template_eventid=eventids[0], plot=plot_aligned_wf,event_type=None) resampled_averaged_waveforms_original_length = numpy.zeros((8,len(_reader.t()))) for channel in range(8): resampled_averaged_waveforms_original_length[channel] = scipy.interpolate.interp1d(times,averaged_waveforms[channel],kind='cubic',bounds_error=False,fill_value=0)(reader.t()) if False: for channel in range(8): plt.figure() plt.title(str(channel)) for eventid in eventids: tct.setEntry(eventid) plt.plot(tct.t(),tct.wf(channel),label=str(eventid),alpha=0.8) plt.legend() plt.xlabel('t (ns)') plt.ylabel('adu') if save_template == True: filename_index = 0 filename = './generated_event_template_%i.csv'%filename_index existing_files = numpy.array(glob.glob('./*.csv')) while numpy.isin(filename,existing_files): filename_index += 1 filename = './generated_event_template_%i.csv'%filename_index numpy.savetxt(filename,resampled_averaged_waveforms_original_length, delimiter=",") print('Genreated template saved as:\n%s'%filename) tdc.calculateMultipleTimeDelays(eventids, align_method=8,hilbert=False,plot=True, colors=numpy.array(coords)[:,0]) return resampled_averaged_waveforms_original_length def disconnect(self): self.lasso.disconnect_events() self.canvas.draw_idle()
class CollectionSelector(object): """Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool highlights selected points by fading them out (i.e., reducing their alpha values). If your collection has alpha < 1, this tool will permanently alter them. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, ax, collection, color_other='k', onselection=None): self.canvas = ax.figure.canvas self.collection = collection self.color_other = colorConverter.to_rgba(color_other) self.xys = collection.get_offsets() self.Npts = len(self.xys) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, self.Npts).reshape(self.Npts, -1) self.sfc = self.fc.copy() self.lasso = LassoSelector(ax, onselect=self.onselect) self.ind = [] self.onselection = onselection def updateselection(self): self.sfc[:, :] = self.fc[:, :] if len(self.ind) > 0: self.sfc[self.ind, :] = self.color_other self.collection.set_facecolors(self.sfc) self.canvas.draw_idle() def selectall(self): self.ind = range(self.Npts) self.updateselection() def reset(self): self.ind = [] self.updateselection() def onselect(self, verts): path = Path(verts) self.ind = list( np.nonzero([path.contains_point(xy) for xy in self.xys])[0]) self.updateselection() if self.onselection is not None: self.onselection(self.ind) def disconnect(self): self.lasso.disconnect_events() #self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle()
class SelectFromCollection(object): def __init__(self, ax, collection, mmc, img): self.colornormalizer = Normalize(vmin=0, vmax=1, clip=False) self.scat = plt.scatter(img[:, 0], img[:, 1], c=mmc.classvec) plt.gray() plt.setp(ax.get_yticklabels(), visible=False) ax.yaxis.set_tick_params(size=0) plt.setp(ax.get_xticklabels(), visible=False) ax.xaxis.set_tick_params(size=0) self.img = img self.canvas = ax.figure.canvas self.collection = collection #self.alpha_other = alpha_other self.mmc = mmc self.prevnewclazz = None self.xys = collection self.Npts = len(self.xys) self.lockedset = set([]) self.lasso = LassoSelector(ax, onselect=self.onselect)#, lineprops = {:'prism'}) self.lasso.disconnect_events() self.lasso.connect_event('button_press_event', self.lasso.onpress) self.lasso.connect_event('button_release_event', self.onrelease) self.lasso.connect_event('motion_notify_event', self.lasso.onmove) self.lasso.connect_event('draw_event', self.lasso.update_background) self.lasso.connect_event('key_press_event', self.onkeypressed) #self.lasso.connect_event('button_release_event', self.onrelease) self.ind = [] self.slider_axis = plt.axes(slider_coords, visible = False) self.slider_axis2 = plt.axes(obj_fun_display_coords, visible = False) self.in_selection_slider = None newws = list(set(range(len(self.collection))) - self.lockedset) self.mmc.new_working_set(newws) self.lasso.line.set_visible(False) def onselect(self, verts): self.path = Path(verts) self.ind = np.nonzero(self.path.contains_points(self.xys))[0] print 'Selected '+str(len(self.ind))+' points' newws = list(set(self.ind) - self.lockedset) self.mmc.new_working_set(newws) self.redrawall() def onpress(self, event): if self.lasso.ignore(event) or event.inaxes != self.ax: return self.lasso.line.set_data([[], []]) self.lasso.verts = [(event.xdata, event.ydata)] self.lasso.line.set_visible(True) def onrelease(self, event): if self.lasso.ignore(event): return if self.lasso.verts is not None: if event.inaxes == self.lasso.ax: self.lasso.verts.append((event.xdata, event.ydata)) self.lasso.onselect(self.lasso.verts) self.lasso.verts = None def onkeypressed(self, event): print 'You pressed', event.key if event.key == '1': print 'Assigned all selected points to class 1' newclazz = 1 mmc.claim_all_points_in_working_set(newclazz) if event.key == '0': print 'Assigned all selected points to class 0' newclazz = 0 mmc.claim_all_points_in_working_set(newclazz) if event.key == 'a': print 'Selected all points' newws = list(set(range(len(self.collection))) - self.lockedset) self.mmc.new_working_set(newws) self.lasso.line.set_visible(False) if event.key == 'c': changecount = mmc.cyclic_descent_in_working_set() print 'Performed ', changecount, 'cyclic descent steps' if event.key == 'l': print 'Locked the class labels of selected points' self.lockedset = self.lockedset | set(self.ind) newws = list(set(self.ind) - self.lockedset) self.mmc.new_working_set(newws) #print newws if event.key == 'u': print 'Unlocked the selected points' self.lockedset = self.lockedset - set(self.ind) newws = list(set(self.ind) - self.lockedset) self.mmc.new_working_set(newws) self.redrawall() def redrawall(self, newslider = True): if newslider: nozeros = np.nonzero(self.mmc.classvec_ws)[0] self.slider_axis.cla() del self.slider_axis del self.slider_axis2 self.slider_axis = plt.axes(slider_coords) self.slider_axis2 = plt.axes(obj_fun_display_coords) steepness_vector = mmc.compute_steepness_vector() X = [steepness_vector, steepness_vector] #right = left+width #self.slider_axis2.imshow(X, interpolation='bicubic', cmap=plt.get_cmap("Oranges"), alpha=1) self.slider_axis2.imshow(X, cmap=plt.get_cmap("Oranges")) self.slider_axis2.set_aspect('auto') plt.setp(self.slider_axis2.get_yticklabels(), visible=False) self.slider_axis2.yaxis.set_tick_params(size=0) del self.in_selection_slider self.in_selection_slider = None self.in_selection_slider = Slider(self.slider_axis, 'Fraction slider', 0., len(mmc.working_set), valinit=len(nozeros)) def sliderupdate(val): val = int(val) nonzeroc = len(np.nonzero(self.mmc.classvec_ws)[0]) if val > nonzeroc: claims = val - nonzeroc newclazz = 1 elif val < nonzeroc: claims = nonzeroc - val newclazz = 0 else: return print 'Claimed', claims, 'points for class', newclazz #val, nonzeroc, claims self.claims = claims mmc.claim_n_points(claims, newclazz) steepness_vector = mmc.compute_steepness_vector() X = [steepness_vector, steepness_vector] self.slider_axis2.imshow(X, cmap=plt.get_cmap("Oranges")) self.slider_axis2.set_aspect('auto') self.redrawall(newslider = False) #HACK! self.prevnewclazz = newclazz self.in_selection_slider.on_changed(sliderupdate) oneclazz = np.nonzero(self.mmc.classvec)[0] col_row = self.collection[oneclazz] rowcs, colcs = col_row[:, 1], col_row[:, 0] #self.img[rowcs, colcs, :] = 0 #self.img[rowcs, colcs, 0] = 255 zeroclazz = np.nonzero(self.mmc.classvec - 1)[0] col_row = self.collection[zeroclazz] rowcs, colcs = col_row[:, 1], col_row[:, 0] #self.img[rowcs, colcs, :] = img_orig[rowcs, colcs, :] #self.imdata.set_data(self.img) scatcolors = self.scat.get_facecolors() scatcolors[:,0] = mmc.classvec scatcolors[:,1] = mmc.classvec scatcolors[:,2] = mmc.classvec self.scat.set_facecolors(scatcolors) if self.lasso.useblit: self.lasso.canvas.restore_region(self.lasso.background) self.lasso.ax.draw_artist(self.lasso.line) self.lasso.canvas.blit(self.lasso.ax.bbox) else: self.lasso.canvas.draw_idle() plt.draw() print_instructions() def disconnect(self): self.lasso.disconnect_events() self.canvas.draw_idle()
class PointBrowser: """ Click on a point to select and highlight it -- the data that generated the point will be shown in the lower axes. Use the 'n' and 'b' keys to browse through the next and previous points """ np = __import__('numpy') def __init__(self, xs, ys, ax, line, fig, outl): print("INIT") self.fig = fig self.xs = xs self.ys = ys self.ax = ax self.line = line self.outl_ind = 0 self.pan_index = -1 self.jump_step = 600 self.outl = outl[0] self.deleted = [] self.bulk_deleted = [] self.onDataEnd = EventHook() # print("self.outl", self.outl) if self.outl.any(): self.lastind = self.outl[self.outl_ind] # print("self.outl_ind", self.outl_ind) else: self.lastind = 0 self.text = self.ax.text(0.7, 0.95, 'selected: none', bbox=dict(facecolor='red', alpha=0.5), transform=self.ax.transAxes, va='top') self.selected, = self.ax.plot([self.xs[self.lastind]], [self.ys[self.lastind]], 'o', ms=12, alpha=0.4, color='red', visible=True) # pts = self.ax.scatter(self.xs, self.ys, s=30, facecolors='none') self.collection = self.ax.scatter(self.xs, self.ys, s=30, facecolors='none') self.xys = self.collection.get_offsets() self.lasso = LassoSelector(self.ax, onselect=self.onselect, button=3) def onpress(self, event): # print("ON PRESS") if self.lastind is None: return jump_step = 600 # undo deletions made if event.key == 'ctrl+z' and self.deleted: # print("UNDO DELETIONS") index, data = self.deleted.pop().popitem() self.xs[index] = data[0] self.ys[index] = data[1] # update UNDONE marker index self.lastind = index self.update(event=event) if event.key == 'ctrl+b' and self.bulk_deleted: for data in self.bulk_deleted: for key, value in data.items(): self.xs[key] = value[0] self.ys[key] = value[1] self.bulk_deleted = [] # update UNDONE marker index # self.lastind = index self.on_bulk_delete() self.show_home_view() # return if event.key not in ('n', 'b', 'd', 'right', 'left', '0', 'ctrl+z', 'ctrl+b'): return if event.key == '0': self.show_home_view() if event.key == 'right' or event.key == 'left': if event.key == 'right': self.pan_index = self.pan_index + 1 else: self.pan_index = self.pan_index - 1 self.onpan(self.pan_index) if event.key == 'd': # print('Delete') self.ondelete(self.lastind) self.ys[self.lastind] = 9999 if (self.lastind in self.outl): self.outl_ind = self.next_pointer(self.ys, self.outl, self.outl_ind, +1) # # skip over deleted values in outliers # while self.ys[self.outl[self.outl_ind]]==9999: # self.outl_ind += 1 # if self.outl_ind > len(self.outl)-1: # break if (self.lastind in self.outl): if event.key == 'n': self.outl_ind = self.next_pointer(self.ys, self.outl, self.outl_ind, +1) if event.key == 'b': self.outl_ind = self.next_pointer(self.ys, self.outl, self.outl_ind, -1) self.outl_ind = self.np.clip(self.outl_ind, 0, len(self.outl) - 1) self.lastind = self.outl[self.outl_ind] else: if event.key == 'n' or event.key == 'd': self.lastind = self.next_pointer_all(self.ys, self.lastind, +1) # while self.ys[self.lastind]==9999: # self.lastind += 1 # if self.lastind > len(self.ys)-1: # break if event.key == 'b': self.lastind = self.next_pointer_all(self.ys, self.lastind, -1) # if(self.outl_ind>-1): # if(self.lastind in self.outl): # self.lastind = self.outl[self.outl_ind] # else: # if event.key == 'n' or event.key == 'd': # self.lastind += 1 # if event.key == 'b': # self.lastind -= 1 # else: # self.lastind = 0 self.lastind = self.np.clip(self.lastind, 0, len(self.xs) - 1) # if event.key != '0': # self.pan_index = self.lastind // self.jump_step # self.onpan(self.pan_index) # print("NK ", self.lastind, self.outl) # print("outl_indl ", self.outl_ind) # self.lastind = self.np.clip(self.lastind, 0, len(self.xs) - 1) self.update(event=event) def onpick(self, event): # print("ON PICK CALLED") # print(event.artist) if event.artist != self.line or event.mouseevent.button != 1: return True N = len(event.ind) if not N: return True # the click locations x = event.mouseevent.xdata y = event.mouseevent.ydata # # print("y", y) # print("event.ind", event.ind) # print("self.ys[event.ind]", self.ys[event.ind]) # print("x", x) # print("self.xs[event.ind]", self.xs[event.ind]) distances = self.np.hypot(x - event.ind, y - self.ys[event.ind]) # print("distances", distances) indmin = distances.argmin() dataind = event.ind[indmin] # this_artist = event.artist #the picked object is available as event.artist # print(this_artist) #For debug just to show you which object is picked # plt.gca().picked_object = this_artist # On mouse click pan and zoom to the clicked section self.pan_index = dataind // self.jump_step self.onpan(self.pan_index) self.lastind = dataind self.update(event=None) def update(self, event=None): # print("UPDATE IS CALLED") if self.lastind is None: return dataind = self.lastind # index of an outlier needs to be updated if (dataind in self.outl): self.outl_ind = self.np.argwhere(self.outl == dataind)[0][0] # print("UPDATED OUTLIER INDEX", self.outl_ind) # pan the view to the highlighted point if event: if (event.key != '0' and event.key != 'left' and event.key != 'right'): self.pan_index = self.lastind // self.jump_step self.onpan(self.pan_index) # print("outlier index", self.outl_ind) # print("LAST index", self.lastind) self.selected.set_visible(True) self.selected.set_data(self.xs[dataind], self.ys[dataind]) # self.text.set_text('selected: %d' % dataind + 'Value: %d' % self.ys[dataind] ) self.text.set_text( 'selected date: %s' % self.np.datetime_as_string(self.xs[dataind], unit='m') + ' Value: %s' % self.ys[dataind]) nines_ind = self.np.where(self.ys == 9999) nonines_data = self.ys.copy() nonines_data[nines_ind] = float('nan') self.line.set_ydata(nonines_data) self.fig.canvas.draw() # print('UPDATE CALLED') def on_sensor_change_update(self): # print("MY_UPDATE IS CALLED") nines_ind = self.np.where(self.ys == 9999) nonines_data = self.ys.copy() nonines_data[nines_ind] = float('nan') self.line.set_ydata(nonines_data) self.show_home_view() self.ax.figure.canvas.flush_events() self.fig.canvas.draw() def show_home_view(self): self.ax.autoscale(enable=True, axis='x', tight=True) self.ax.set_xlim([self.xs[0], self.xs[-1]]) self.ax.set_ylim( self.np.nanmin(self.ys) - 50, self.np.nanmax(self.np.ma.masked_equal(self.ys, 9999, copy=False)) + 50) self.ax.margins(0.05, 0.05) self.pan_index = -1 def ondelete(self, ind): # do not append if item already deleted if (self.ys[ind] != 9999): # print("On Delete Called on index", ind) self.deleted.append({ind: [self.xs[ind], self.ys[ind]]}) def onpan(self, p_index): # print("ON PAN") pan_lim = len(self.xs) // self.jump_step # check for the edge case when the remainder of the division is 0 # i.e. the number of data points divided by the jump step is a whole number if (len(self.xs) % self.jump_step == 0): pan_lim = pan_lim - 1 if (self.pan_index > pan_lim): self.onDataEnd.fire("You've panned through all of the data") self.pan_index = self.np.clip( self.pan_index, 0, pan_lim) # Limit pan index from growing larger than needed p_index = self.pan_index left = self.jump_step * p_index right = self.jump_step * p_index + self.jump_step if (right > len(self.xs) + self.jump_step): return # limiting left and right range to the size of the data if (right > len(self.xs) - 1): right = len(self.xs) - 1 left = right - self.jump_step if (left < 0): left = 0 right = left + self.jump_step self.pan_index = 0 # define time range self.ax.set_xlim(self.xs[left], self.xs[right]) # find Y range but exclude 9999s and nans # 50 for padding self.ax.set_ylim( self.np.nanmin(self.ys[left:right]) - 50, self.np.nanmax( self.np.ma.masked_equal(self.ys[left:right], 9999, copy=False)) + 50) def onselect(self, verts): path = Path(verts) self.ind = self.np.nonzero(path.contains_points(self.xys))[0] for i in self.ind: self.bulk_deleted.append({i: [self.xs[i], self.ys[i]]}) self.ys[i] = 9999 # self.ondelete(i) self.on_bulk_delete() def disconnect(self): self.lasso.disconnect_events() def on_bulk_delete(self): self.text.set_text('bulk items deleted') nines_ind = self.np.where(self.ys == 9999) nonines_data = self.ys.copy() nonines_data[nines_ind] = float('nan') self.line.set_ydata(nonines_data) self.fig.canvas.draw() def getDeleted(self): return self.deleted def next_pointer(self, data_ar, outl_ar, pointer, inc): if (data_ar[outl_ar[pointer]] != 9999): pointer += inc if pointer > len(outl_ar) - 1: pointer = len(outl_ar) - 1 self.onDataEnd.fire( "This was the last outlier. You can click the same channel again to find smaller outliers" ) # skip over deleted values while data_ar[outl_ar[pointer]] == 9999: # print("skipping data", data_ar[outl_ar[pointer]]) # print("skipping index", pointer) # print("POINTER", pointer) # print("LEN of OUTLIER ARRAy", len(outl_ar)) pointer += inc if pointer > len(outl_ar) - 1: pointer = len(outl_ar) - 1 self.onDataEnd.fire( "This was the last outlier. You can click the same channel again to find smaller outliers" ) break return pointer def next_pointer_all(self, data_ar, pointer, inc): if (data_ar[pointer] != 9999 and not self.np.isnan(data_ar[pointer])): pointer += inc if pointer > len(data_ar) - 1: pointer = len(data_ar) - 1 self.onDataEnd.fire("This was the last data point") while (data_ar[pointer] == 9999 or self.np.isnan(data_ar[pointer])): pointer += inc if pointer > len(data_ar) - 1: pointer = len(data_ar) - 1 self.onDataEnd.fire("This was the last data point") break return pointer # offset all the data starting with from the beginning up to the provided date def offset_data(self, time, offset): """ time -> ISO date.time string (e.g. '2005-02-25T03:30') offset -> Integer """ indices = self.np.where(self.xs <= self.np.datetime64(time)) # Do not add offset if the data point is 9999 indices = self.np.where(self.ys[indices[0]] < 9999) self.ys[indices[0]] = self.ys[indices[0]] + offset self.update() @property def data(self): return self.ys
class SelectFromCollection(object): """Select indices from a matplotlib collection using `LassoSelector`. Selected indices are saved in the `ind` attribute. This tool fades out the points that are not part of the selection (i.e., reduces their alpha values). If your collection has alpha < 1, this tool will permanently alter the alpha values. Note that this tool selects collection objects based on their *origins* (i.e., `offsets`). Parameters ---------- ax : :class:`~matplotlib.axes.Axes` Axes to interact with. collection : :class:`matplotlib.collections.Collection` subclass Collection you want to select from. alpha_other : 0 <= float <= 1 To highlight a selection, this tool sets all selected points to an alpha value of 1 and non-selected points to `alpha_other`. """ def __init__(self, value1, value2, alpha_other=0.3): #get_ipython().run_line_magic('matplotlib', 'qt') self.collection_of_point = [] plt.figure() self.axis1 = value1 self.axis2 = value2 ax_SelectFromCollection = plt.subplot(111) collection = ax_SelectFromCollection.scatter(self.axis1, self.axis2, s=50) self.canvas = ax_SelectFromCollection.figure.canvas self.collection = collection self.alpha_other = alpha_other self.xys = collection.get_offsets() self.Npts = len(self.xys) # Ensure that we have separate colors for each object self.fc = collection.get_facecolors() if len(self.fc) == 0: raise ValueError('Collection must have a facecolor') elif len(self.fc) == 1: self.fc = np.tile(self.fc, (self.Npts, 1)) self.lasso = LassoSelector(ax_SelectFromCollection, onselect=self.onselect) self.ind = [] #fig = plt.figure() #ax_SelectFromCollection = plt.subplot(111) #while len(self.collection_of_point) == 0: def accept(event): if event.key == "enter": print("Selected points:") print(self.xys[self.ind]) self.collection_of_point.append(self.xys[self.ind]) self.disconnect() ax_SelectFromCollection.set_title("") self.canvas.draw() self.canvas.mpl_connect("key_press_event", accept) ax_SelectFromCollection.set_title( "Press enter to accept selected points.") #plt.show() def onselect(self, verts): path = Path(verts) self.ind = np.nonzero(path.contains_points(self.xys))[0] self.fc[:, -1] = self.alpha_other self.fc[self.ind, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle() def disconnect(self): self.lasso.disconnect_events() self.fc[:, -1] = 1 self.collection.set_facecolors(self.fc) self.canvas.draw_idle()