def _fast_threshold_preview(image: np.ndarray, height: int = 15, width: int = 15, slider_width: int = 500, scale: float = 0.25): slider_width = str(slider_width) + 'px' @widgets.interact(h=FloatRangeSlider(min=0., max=1., step=0.01, readout_format='.2f', layout={'width': slider_width}, continuous_update=False), s=FloatRangeSlider(min=0., max=1., step=0.01, readout_format='.2f', layout={'width': slider_width}, continuous_update=False), v=FloatRangeSlider(min=0., max=1., step=0.01, readout_format='.2f', layout={'width': slider_width}, continuous_update=False)) def interact_plot(h=(0.2, 0.4), s=(0.2, 0.4), v=(0.2, 0.4)): out_shape = list(image.shape) out_shape[0] = int(out_shape[0] * scale) out_shape[1] = int(out_shape[1] * scale) i = transform.resize(image, tuple(out_shape)) thresh = threshold_hsv_img(i, h=h, s=s, v=v) @njit def _do_(i, thresh): x_d, y_d, _ = i.shape for x in range(x_d): for y in range(y_d): if thresh[x, y]: i[x, y] = (0, 1, 1) return i i = _do_(i, thresh) plt.figure(figsize=(width, height)) plt.imshow(color.hsv2rgb(i)) return_string = "Selected Values\nHue: {0}\nSaturation: {1}\nValue: {2}\n".format( h, s, v) print(return_string)
def _perfect_threshold_preview(image: np.ndarray, height: int = 15, width: int = 15, slider_width: int = 500): slider_width = str(slider_width) + 'px' @widgets.interact_manual(h=FloatRangeSlider(min=0., max=1., step=0.01, readout_format='.2f', layout={'width': slider_width}), s=FloatRangeSlider(min=0., max=1., step=0.01, readout_format='.2f', layout={'width': slider_width}), v=FloatRangeSlider(min=0., max=1., step=0.01, readout_format='.2f', layout={'width': slider_width})) def interact_plot(h=(0.2, 0.4), s=(0.2, 0.4), v=(0.2, 0.4)): f = FloatProgress(min=0, max=100, step=1, description="Progress:") display(f) x = threshold_hsv_img(image, h=h, s=s, v=v) f.value += 25 i = image.copy() f.value += 25 i[x] = (0, 1, 1) f.value += 25 plt.figure(figsize=(width, height)) plt.imshow(color.hsv2rgb(i)) f.value += 25 return_string = "Selected Values\nHue: {0}\nSaturation: {1}\nValue: {2}\n".format( h, s, v) print(return_string)
def __init__(self, src=None, auto=True, x=None, y=None, **kwargs): super().__init__(**kwargs) self._filters = {} self.box = VBox() self._links = [] self._group_filter = GroupUIFilter() self._trigger = Trigger(self._group_filter, func=self._apply_filter) self._filters = {} self._auto = auto self._auto_filter = None self.show_measure = False # setup controls self._ctrls = HBox() self._menu = widgets.Dropdown( options=self.options, description='Attribute:', value=self.attr, disabled=False, ) self.x_slider = IntRangeSlider(min=0, max=1, value=(0, 1), description='Points:') self.y_slider = FloatRangeSlider(min=0, max=1, value=(0, 1), description='Persistence:', step=0.001) self._ctrls = HBox([self._menu, self.y_slider, self.x_slider]) link((self, 'x_value'), (self.x_slider, 'value')) link((self, 'y_value'), (self.y_slider, 'value')) self._auto_filter = AttrFilter(attr=self._menu.value) if self._auto: self._group_filter.add(self._auto_filter, name='auto') widgets.link((self, 'attr'), (self._menu, 'value')) self.observe(self._auto_update, names=['attr']) # setup view self._links = [ widgets.link((self, 'x'), (self.x_slider, 'value')), widgets.link((self, 'y'), (self.y_slider, 'value')), ] self._update_children() if src is not None: self.src = src if x is not None: self.x = x if y is not None: self.y = y
def show(): step = 0.1 float_range = FloatRangeSlider(value=[0, 5.0], min=xrange[0], max=xrange[1], step=step, description='事象の範囲:', continuous_update=False, readout_format='.1f') def enforce_gap(change): new_min, new_max = change.new old_min, old_max = change.old if new_max - new_min < step: if old_min == new_min: new_max = new_min + step else: new_min = new_max - step float_range.value = (new_min, new_max) float_range.observe(enforce_gap, 'value') interact(plot, float_range=float_range)
def __init__(self): self.dx, self.dy = 0.005, 0.005 self.w_title = HTML("<h3>Область с заданной неравномерностью </h3>") self.w_out5 = Output() self.w_label_var = Label("Допустимая неравномерность:") self.w_var = FloatSlider(1.1, min=1., max=1.5, step=0.005, continuous_update=False, readout_format='.3f') self.w_label_xarea = Label('Границы допустимой области по горизонтали: ') self.w_xarea = FloatRangeSlider(value=[0.2,0.7], min=0, max=1.0, step=0.005, disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.3f') self.w_label_yarea = Label('Границы допустимой области по вертикали: ') self.w_yarea = FloatRangeSlider(value=[0.45,0.55], min=0, max=1.0, step=0.005, disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.3f') self.w_varn = Label() self.btn_var = Button(description ='Пересчитать', button_style='primary', disabled = True) # доработать self.btn_break = Button(description ='Прервать', disabled = True) self.w_message = HTML("") self.w_result = HTML("") self.layout = VBox([self.w_title, self.w_label_var, self.w_var, self.w_label_xarea, self.w_xarea, self.w_label_yarea, self.w_yarea, self.w_varn, self.btn_var, self.w_message, self.w_result, self.w_out5]) self.btn_var.on_click(self.button_var_onclick)
def __init__(self, tree=None, auto=True, **kwargs): super().__init__(**kwargs) self._filters = {} self._treeview = None self._links = [] self._group_filter = GroupUIFilter() self._trigger = Trigger(self._group_filter, func=self._apply_filter) self._filters = {} self._auto = auto self._auto_filter = None # setup controls self._ctrls = HBox() self._menu = widgets.Dropdown( options=self.attr_opts, description='Attribute:', value=self.attr, disabled=False, ) self._x = IntRangeSlider(min=0, max=100, value=(0, 100), description='Points:') self._y = FloatRangeSlider(min=0, max=1, value=(0, 1), description='Persistence:', step=0.001) self._ctrls = HBox([self._menu, self._y, self._x]) self._auto_filter = AttrFilter(attr=self._menu.value) if self._auto: self._group_filter.add(self._auto_filter, name='auto') widgets.link((self._menu, 'value'), (self, 'attr')) self.observe(self._auto_update, names=['attr']) # setup view self._treeview = BaseTreeView(None, attr=self.attr) self._treeview.show_attr = False self._links = [ widgets.link((self, 'attr'), (self._treeview, 'attr')), widgets.link((self._x, 'value'), (self._treeview, 'x')), widgets.link((self._y, 'value'), (self._treeview, 'y')) ] self._update_children() if tree is not None: self.tree = tree
from ipywidgets import FloatSlider, FloatRangeSlider, Dropdown, Select, Box, AppLayout, jslink, Layout, VBox, HBox from ipygany import Scene, IsoColor, TetraMesh, Component, ColorBar, colormaps mesh = TetraMesh.from_vtk( 'benchmarks/005-hemispherical-shell-point-load/hemisperical-shell-points-load.vtu', show_edges=True) u_min = 4.4e-6 u_max = 1.8e-1 # Colorize by height colored_mesh = IsoColor(mesh, input=('u', 'X1'), min=u_min, max=u_max) # Create a slider that will dynamically change the boundaries of the colormap colormap_slider_range = FloatRangeSlider(value=[u_min, u_max], min=u_min, max=u_max, step=(u_max - u_min) / 100.) jslink((colored_mesh, 'range'), (colormap_slider_range, 'value')) # Create a colorbar widget colorbar = ColorBar(colored_mesh) # Colormap choice widget colormap = Dropdown(options=colormaps, description='colormap:') jslink((colored_mesh, 'colormap'), (colormap, 'index')) AppLayout( header=Scene([colored_mesh]), left_sidebar=VBox((colormap, colormap_slider_range)),
def make_widg(self, trait, val): return FloatRangeSlider(value=val, min=trait.min, max=trait.max, step=(trait.max - trait.min) / 200)
def __init__(self): items_layout = Layout (flex = '1 1 auto', width = 'auto') self.w_title = HTML('<h3>Форма электродов</h3>') self.w_l_x = Label('Границы изогнутой части электрода по горизонтали:') self.w_x = FloatRangeSlider(value=[0.5,1.], min=0., max=1., step=0.02, continuous_update=False, readout_format='.3f', layout=items_layout) self.w_l_y = Label('Координаты электрода по вертикали:') self.w_l_y0 = Label('y0') layouth = Layout(height='300px') self.w_y0 = FloatSlider(value=0.6, min=0.5, max=1.0, step=0.001, description='y0', disabled=False, continuous_update=False, orientation='vertical', readout=True, readout_format='.3f', layout=layouth ) self.w_y1 = FloatSlider(value=0.6, min=0.5, max=1.0, step=0.001, description='y1', disabled=False, continuous_update=False, orientation='vertical', readout=True, readout_format='.3f', layout=layouth ) self.w_y2 = FloatSlider(value=0.6, min=0.5, max=1.0, step=0.001, description='y2', disabled=False, continuous_update=False, orientation='vertical', readout=True, readout_format='.3f', layout=layouth ) self.w_y3 = FloatSlider(value=0.6, min=0.5, max=1.0, step=0.001, description='y3', disabled=False, continuous_update=False, orientation='vertical', readout=True, readout_format='.3f', layout=layouth ) self.w_y4 = FloatSlider(value=0.6, min=0.5, max=1.0, step=0.001, description='y4', disabled=False, continuous_update=False, orientation='vertical', readout=True, readout_format='.3f', layout=layouth ) self.out_el = Output() hbox1 = HBox([self.w_y0, self.w_y1, self.w_y2, self.w_y3, self.w_y4], layout=Layout(width='100%')) vbox1 = VBox([self.w_l_x, self.w_x, self.w_l_y, hbox1], layout=Layout(width='50%', padding='5px')) vbox2 = HBox([self.out_el], layout=Layout(width='50%', padding='5px')) hbox = HBox ([vbox1, vbox2], layout=Layout(width='100%')) self.layout = VBox([self.w_title, hbox]) self.interactive_el_form = interactive(self.el_form, x0xm=self.w_x, y0=self.w_y0, y1=self.w_y1, y2=self.w_y2, y3=self.w_y3, y4=self.w_y4)
def __init__(self, volume=None, default_directory=os.getcwd(), title='', enhancement_steps=1000, **kwargs): def on_chosen_path_change(old_path, new_path): self.dataset = FolderDataset(new_path) # TODO: If the path doesn't contain images, display a warning # A widget for changing the image folder self.pathchooser = PathChooser( chosen_path_desc='Image folder:', default_directory=default_directory, on_chosen_path_change=on_chosen_path_change, ) self.pathchooser.layout.margin = '0 0 10px 0' # The number of increments of the min/max slider self.enhancement_steps = enhancement_steps self.scales = { 'x': LinearScale(), 'y': LinearScale(), } # The currently displayed image will be in bytes at `self.image_plot.image.value` self.image_plot = BQImage( image=IPyImage(), scales=self.scales, ) self.figure = Figure( marks=[self.image_plot], padding_x=0, padding_y=0, animation_duration=1000, fig_margin={ 'top': 0, 'right': 0, 'bottom': 0, 'left': 0, }, layout=Layout( grid_area='figure', margin='0', width='320px', height='320px', ), ) # Custom toolbar toolbar_width = '100%' toolbar_margin = '0px 0 2px 0' self.pan_zoom = PanZoom(scales={ 'x': [self.scales['x']], 'y': [self.scales['y']], }, ) self.save_button = Button( description='Save Image', tooltip='Save Image', icon='save', layout=Layout( width=toolbar_width, # flex='1 1 auto', margin=toolbar_margin, ), ) self.save_button.on_click(self.save_current_image) self.hide_button = Button( description='Hide Image', tooltip='Hide Image', icon='eye-slash', layout=Layout( width=toolbar_width, # flex='1 1 auto', margin=toolbar_margin, )) self.hide_button.on_click(self.hide_current_image) self.pan_zoom_toggle_button = ToggleButton( description='Pan / Zoom', tooltip='Pan/Zoom', icon='arrows', layout=Layout( width=toolbar_width, # flex='1 1 auto', margin=toolbar_margin, ), ) self.pan_zoom_toggle_button.observe(self.on_pan_zoom_toggle, names='value') self.reset_pan_zoom_button = Button( description='Undo Zoom', tooltip='Reset pan/zoom', icon='refresh', layout=Layout( width=toolbar_width, # flex='1 1 auto', margin=toolbar_margin, ), ) self.reset_pan_zoom_button.on_click(self.reset_pan_zoom) self.reset_enhancements_button = Button( description='Un-Enhance', tooltip='Reset enhancements', icon='ban', layout=Layout( width=toolbar_width, # flex='1 1 auto', margin=toolbar_margin, ), ) self.reset_enhancements_button.on_click(self.reset_enhancements) self.mini_map = IPyImage(layout=Layout( grid_area='mini-map', margin='0', )) self.mini_map.width = 180 self.mini_map.height = 180 # PERFORMANCE CONCERN # Ideally instead of four observations, this would observe 'scales' on `self.pan_zoom` # However, it doesn't fire updates # Ref: https://github.com/bloomberg/bqplot/issues/800 self.image_plot.scales['x'].observe(self.on_pan_zoom_change('x_min'), names='min') self.image_plot.scales['x'].observe(self.on_pan_zoom_change('x_max'), names='max') self.image_plot.scales['y'].observe(self.on_pan_zoom_change('y_min'), names='min') self.image_plot.scales['y'].observe(self.on_pan_zoom_change('y_max'), names='max') self.plane_toggle = ToggleButtons( options=['yz', 'xz', 'xy'], description='', disabled=False, button_style='', tooltips=[ 'Step in x direction', 'Step in y direction', 'Step in z direction' ], layout=Layout( width='200px', # flex='1 1 auto', margin='7px 0 auto auto', ), ) self.plane_toggle.style.button_width = 'auto' self.plane_toggle.observe(self.on_plane_change, names='value') self.toolbar = VBox( children=[ self.save_button, self.hide_button, self.pan_zoom_toggle_button, self.reset_pan_zoom_button, self.reset_enhancements_button, ], layout=Layout( grid_area='toolbar', margin='0', ), ) # Image enhancements self.min_max_slider = FloatRangeSlider( value=[0, 255], min=0, max=255, step=255 / self.enhancement_steps, description='Min/Max:', orientation='horizontal', readout=True, readout_format='.1f', continuous_update=True, layout=Layout( grid_area='min-max-slider', margin='10px 0 10px -10px', width='100%', ), ) self.min_max_slider.observe(self.on_min_max_change, names='value') self.index_slider = IntSlider( value=0, min=0, max=1, step=1, description='Index:', orientation='horizontal', readout=True, readout_format='d', continuous_update=True, layout=Layout( grid_area='index-slider', margin='8px -20px 10px -36px', width='100%', ), ) self.index_slider.observe(self.on_image_index_change, names='value') # Animation self.play = Play( value=self.index_slider.value, min=self.index_slider.min, max=self.index_slider.max, step=self.index_slider.step, ) jslink((self.play, 'value'), (self.index_slider, 'value')) # Keep 'max' in sync as well self.index_slider.observe(self.on_index_slider_max_change, names='max') self.bottom_bar = HBox( children=[ self.play, self.index_slider, self.plane_toggle, ], layout=Layout( grid_area='bottom-bar', margin=f'10px -20px 0 0', # overflow='hidden', )) # Layout self.gridbox = GridBox(children=[ self.figure, self.toolbar, self.mini_map, self.min_max_slider, self.bottom_bar, ], ) # Initially hidden without data self.gridbox.layout.display = 'none' self._dataset = None if volume is not None: self.dataset = VolumeDataset(volume) # Hide pathchooser when using a volume self.pathchooser.layout.display = 'none' # Call VBox super class __init__ super().__init__( children=[ self.pathchooser, self.gridbox, ], layout=Layout(width='auto'), **kwargs, )
mesh = TetraMesh.from_vtk( 'benchmarks/004-eliptic-membrane/eliptic-membrane.vtu', show_edges=True) sigmayy_min = -3.4e7 sigmayy_max = 9.3e7 # Colorize by height colored_mesh = IsoColor(mesh, input=('S', 'YY'), min=sigmayy_min, max=sigmayy_max) # Create a slider that will dynamically change the boundaries of the colormap colormap_slider_range = FloatRangeSlider(value=[sigmayy_min, sigmayy_max], min=sigmayy_min, max=sigmayy_max, step=(sigmayy_max - sigmayy_min) / 100.) jslink((colored_mesh, 'range'), (colormap_slider_range, 'value')) # Create a colorbar widget colorbar = ColorBar(colored_mesh) # Colormap choice widget colormap = Dropdown(options=colormaps, description='colormap:') jslink((colored_mesh, 'colormap'), (colormap, 'index')) AppLayout( header=Scene([colored_mesh]),
plt.show() if save_but: fig.savefig('./plots/v1_{}.png'.format(df_num[col].name), bbox_inches='tight') # fig.savefig('./plots/v1_{}_{}.png'.format(i,df_num[col].name), bbox_inches='tight') case1 = Checkbox(value=True, description='case1') case2 = Checkbox(value=True, description='case2') case3 = Checkbox(value=True, description='case3') case4 = Checkbox(value=True, description='case4') # xlimit = FloatRangeSlider(continuous_update=False,description='X_limit') xlimit = FloatRangeSlider( value=[df_num.iloc[:, 1].min(), df_num.iloc[:, 1].max()], min=df_num.iloc[:, 1].min(), max=df_num.iloc[:, 1].max(), step=(df_num.iloc[:, 1].max() - df_num.iloc[:, 1].min()) / 100, continuous_update=False, description='X_limit') version = Dropdown(options=[0, 1]) case = Dropdown(options=['CASE1', 'CASE2', 'CASE3', 'CASE4']) save_but = ToggleButton(description='Save Figure') col = Dropdown(options=df_num.columns) out = interactive_output( plot_num_and_save, { 'case1': case1, 'case2': case2, 'case3': case3, 'case4': case4, 'xlimit': xlimit,
def initialize_sliders(self, box_universe=None, box_name=None): if box_universe is not None: self._box_universe = box_universe if box_name is not None: self._box_name = box_name logger.info(f"initialize_sliders( {self._box_name} )") try: self.joint_filters = pandas.DataFrame( numpy.ones_like(self.joint_data, dtype=bool), index=self.joint_data.index, columns=self.joint_data.columns, ) clusterdef = ChainedBox(self._box_universe, self._box_name) self.sliders = [] self.outboxes = [] for i in self.joint_data.columns: i_dtype = self.scope.get_dtype(i) or 'real' if i_dtype == 'real': current_setting = clusterdef.get(i, (None, None)) logger.info(f" initial setting {i} = {current_setting}") current_min = self.joint_data[i].min( ) if current_setting[0] is None else current_setting[0] current_max = self.joint_data[i].max( ) if current_setting[1] is None else current_setting[1] controller = FloatRangeSlider( value=[current_min, current_max], min=self.joint_data[i].min(), max=self.joint_data[i].max(), step=(self.joint_data[i].max() - self.joint_data[i].min()) / 20, disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.2f', description=i, style=slider_style, layout=slider_layout, ) elif i_dtype == 'int': current_setting = clusterdef.get(i, (None, None)) logger.info(f" initial setting {i} = {current_setting}") current_min = self.joint_data[i].min( ) if current_setting[0] is None else current_setting[0] current_max = self.joint_data[i].max( ) if current_setting[1] is None else current_setting[1] controller = IntRangeSlider( value=[current_min, current_max], min=self.joint_data[i].min(), max=self.joint_data[i].max(), #step=(self.joint_data[i].max()-self.joint_data[i].min())/20, disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d', description=i, style=slider_style, layout=slider_layout, ) elif i_dtype == 'cat': cats = self.scope.get_cat_values(i) controller = MultiToggleButtons( description=i, style=slider_style, options=cats, disabled=False, button_style= '', # 'success', 'info', 'warning', 'danger' or '' layout=slider_layout, ) controller.values = cats elif i_dtype == 'bool': cats = [False, True] controller = MultiToggleButtons( description=i, style=slider_style, options=cats, disabled=False, button_style= '', # 'success', 'info', 'warning', 'danger' or '' layout=slider_layout, ) controller.values = cats else: # buttons raise NotImplementedError(f"filters for {i}:{i_dtype}") controller = ToggleButtons( description=i, style=slider_style, options=['Off', 'On', 'Both'], value='Both', disabled=False, button_style= '', # 'success', 'info', 'warning', 'danger' or '' tooltips=['Definitely off', 'Definitely on', 'Maybe'], layout=slider_layout, ) self.sliders.append(controller) self.outboxes.append( Output(layout=Layout( height='1in', width='3in', ), )) for s in range(len(self.sliders)): self.sliders[s].observe(self.replot_many) self.ui_risks = VBox([ HBox([s, ob]) for s, ob in zip(self.sliders, self.outboxes) if s.description in self.data.all_risk_factors_ ], ) self.ui_strategies = VBox([ HBox([s, ob]) for s, ob in zip(self.sliders, self.outboxes) if s.description in self.data.all_strategy_names_ ], ) self.ui_perform = VBox([ HBox([s, ob]) for s, ob in zip(self.sliders, self.outboxes) if s.description in self.data.all_performance_measures_ ], ) self.accordion = Accordion( children=[self.ui_strategies, self.ui_risks, self.ui_perform]) self.accordion.set_title(0, 'Policy Levers') self.accordion.set_title(1, 'Exogenous Uncertainties') self.accordion.set_title(2, 'Performance Measures') #self.footer = Output(layout={ 'border': '1px solid red', } ) self.stack = VBox([ self.header_area, self.accordion, self.footer, ]) self.set_header(clusterdef.names) self.replot_many(None) # initial interactive plots except: logger.exception("error in initialize_sliders") raise
mesh = TetraMesh.from_vtk( 'benchmarks/003-Hertz-contact/very-fine-quad-hex.vtu', show_edges=True) stress_min = 0.0 stress_max = 934 # Colorize by height colored_mesh = IsoColor(mesh, input=('S', 'Mises'), min=stress_min, max=stress_max) # Create a slider that will dynamically change the boundaries of the colormap colormap_slider_range = FloatRangeSlider(value=[stress_min, stress_max], min=stress_min, max=stress_max, step=(stress_max - stress_min) / 100.) jslink((colored_mesh, 'range'), (colormap_slider_range, 'value')) # Create a colorbar widget colorbar = ColorBar(colored_mesh) # Colormap choice widget colormap = Dropdown(options=colormaps, description='colormap:') jslink((colored_mesh, 'colormap'), (colormap, 'index')) AppLayout( header=Scene([colored_mesh]), left_sidebar=VBox((colormap, colormap_slider_range)),
def __init__(self): # размерность задачи items_layout = Layout (flex = '1 1 auto', width = 'auto') self.w_title = HTML('<h3>Параметры задачи</h3>') self.w_l_dim = Label('Размерность задачи:') self.w_dim = ToggleButtons( options=['2', '3'], value = '2', #description=' ', disabled=False, button_style='', # 'success', 'info', 'warning', 'danger' or '' tooltips=['Плоская двухмерная задача', 'Трехмерная осесимметричная задача'], layout=items_layout ) chg.r0=1e-6 self.w_l_r0 = Label('Радиус заряда:') self.w_r0 =SelectionSlider( options=['1e-6', '1e-5', '1e-4', '1e-3', '1e-2'], value='1e-6', #description=' ', disabled=False, continuous_update=False, orientation='horizontal', readout=True, layout=items_layout ) chg.alpha = 0 self.w_l_alpha = Label(r"Параметр регуляризации ($\alpha$):") self.w_alpha =SelectionSlider( options=['0', '1e-6', '1e-4', '1e-2', '1e-1', '0.5', '1.0'], value='0', #description=' ', disabled=False, continuous_update=False, orientation='horizontal', readout=True, layout=items_layout ) chg.n = 100 self.w_l_n = Label('Число разбиений области:') self.w_n = SelectionSlider( options=['20', '50', '100', '200', '400', '500', '1000'], value='100', #description=' ', disabled=False, continuous_update=False, orientation='horizontal', readout=True, layout=items_layout ) chg.minmaxxy=(0., 0, 1.,1.) self.w_l_minmaxxy = Label('Область для расчета и отображения потенциала (x, y):') self.w_minmaxx = FloatRangeSlider(value=[0.,1.], min=0, max=2.0, #description='xmin, xmax', step=0.01, disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.2f', layout=items_layout) self.w_minmaxy = FloatRangeSlider(value=[0.,1.], min=0, max=2.0, #description='ymin, ymax', step=0.02, disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.2f', layout=items_layout) chg.minmaxarea=(0.2, 0.2, 0.9,0.9) self.w_l_minmaxarea = Label('Область для расчета напряженности (x, y):') self.w_minmaxxarea = FloatRangeSlider(value=[0.2,0.9], min=0, max=1.0, #description='xmin, xmax', step=0.01, disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.2f', layout=items_layout) self.w_minmaxyarea = FloatRangeSlider(value=[0.2,0.9], min=0, max=1.2, #description='ymin, ymax', step=0.005, disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.3f', layout=items_layout) self.w_l_na = Label('Разбиений для аппроксимации электродов:') chg.na = 50 self.w_na = IntSlider( value=chg.na, min=20, max=250, step=2, #description=' ', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d', layout=items_layout ) chg.c = None self.l_c = Label('') self.update_label('cond', chg.c, self.l_c) chg.err = None self.l_err = Label('') self.update_label('err', chg.err, self.l_err) chg.E = None self.l_E = Label('') self.update_label('E', chg.E, self.l_E) chg.t = None self.l_t = Label('') self.update_label('t', chg.t, self.l_t) self.l_msg=HTML('<b></b>') self.l_var = Label('Вариант:') self.w_dsc = Textarea(value='', placeholder='Введите пояснения по варианту расчета', description='', disabled=False ) self.btn0 = Button(description ='Пересчитать поле', button_style='primary') self.btn01 = Button(description ='Emax/Emin', button_style='primary', disabled=True) self.out0 = Output() self.btn02 = Button(description='Сохранить', disabled=False) vb01= VBox([self.w_l_dim, self.w_dim, self.w_l_r0, self.w_r0, self.w_l_alpha, self.w_alpha, self.w_l_n, self.w_n, self.w_l_minmaxxy, self.w_minmaxx, self.w_minmaxy, self.w_l_minmaxarea, self.w_minmaxxarea, self.w_minmaxyarea], layout=Layout(width='47%')) vb02 = VBox([self.w_l_na, self.w_na, self.l_var, self.w_dsc, self.l_c, self.l_err, self.l_E , self.l_t, self.l_msg ], layout=Layout(width='47%')) hbox =HBox([vb01, vb02], layout=Layout(justify_content='space-between')) hbox2 = HBox([self.btn0, self.btn01, self.btn02]) self.layout = VBox([self.w_title, hbox, hbox2, self.out0], layout=Layout(width='100%')) # инициализация self.get_data()
def getNotebookBackend(actors2show, zoom, viewup): vp = settings.plotter_instance if zoom == 'tight': zoom=1 # disable it if isinstance(vp.shape, str) or sum(vp.shape) > 2: colors.printc("Multirendering is not supported in jupyter.", c=1) return #################################################################################### # https://github.com/InsightSoftwareConsortium/itkwidgets # /blob/master/itkwidgets/widget_viewer.py if 'itk' in settings.notebookBackend: from itkwidgets import view settings.notebook_plotter = view(actors=actors2show, cmap='jet', ui_collapsed=True, gradient_opacity=False) #################################################################################### elif settings.notebookBackend == 'k3d': try: import k3d # https://github.com/K3D-tools/K3D-jupyter except: print("Cannot find k3d, install with: pip install k3d") return actors2show2 = [] for ia in actors2show: if not ia: continue if isinstance(ia, vtk.vtkAssembly): #unpack assemblies acass = ia.unpack() actors2show2 += acass else: actors2show2.append(ia) # vbb, sizes, _, _ = addons.computeVisibleBounds() # kgrid = vbb[0], vbb[2], vbb[4], vbb[1], vbb[3], vbb[5] settings.notebook_plotter = k3d.plot(axes=[vp.xtitle, vp.ytitle, vp.ztitle], menu_visibility=settings.k3dMenuVisibility, height=settings.k3dPlotHeight, antialias=settings.k3dAntialias, ) # settings.notebook_plotter.grid = kgrid settings.notebook_plotter.lighting = settings.k3dLighting # set k3d camera settings.notebook_plotter.camera_auto_fit = settings.k3dCameraAutoFit settings.notebook_plotter.grid_auto_fit = settings.k3dGridAutoFit settings.notebook_plotter.axes_helper = settings.k3dAxesHelper if settings.plotter_instance and settings.plotter_instance.camera: k3dc = utils.vtkCameraToK3D(settings.plotter_instance.camera) if zoom: k3dc[0] /= zoom k3dc[1] /= zoom k3dc[2] /= zoom settings.notebook_plotter.camera = k3dc # else: # vsx, vsy, vsz = vbb[0]-vbb[1], vbb[2]-vbb[3], vbb[4]-vbb[5] # vss = numpy.linalg.norm([vsx, vsy, vsz]) # if zoom: # vss /= zoom # vfp = (vbb[0]+vbb[1])/2, (vbb[2]+vbb[3])/2, (vbb[4]+vbb[5])/2 # camera target # if viewup == 'z': # vup = (0,0,1) # camera up vector # vpos= vfp[0] + vss/1.9, vfp[1] + vss/1.9, vfp[2]+vss*0.01 # camera position # elif viewup == 'x': # vup = (1,0,0) # vpos= vfp[0]+vss*0.01, vfp[1] + vss/1.5, vfp[2] # camera position # else: # vup = (0,1,0) # vpos= vfp[0]+vss*0.01, vfp[1]+vss*0.01, vfp[2] + vss/1.5 # camera position # settings.notebook_plotter.camera = [vpos[0], vpos[1], vpos[2], # vfp[0], vfp[1], vfp[2], # vup[0], vup[1], vup[2] ] if not vp.axes: settings.notebook_plotter.grid_visible = False for ia in actors2show2: if isinstance(ia, (vtk.vtkCornerAnnotation, vtk.vtkAssembly)): continue kobj = None kcmap= None name = None if hasattr(ia, 'filename'): if ia.filename: name = os.path.basename(ia.filename) if ia.name: name = os.path.basename(ia.name) #####################################################################scalars # work out scalars first, Points Lines are also Mesh objs if isinstance(ia, (Mesh, shapes.Line, Points)): # print('scalars', ia.name, ia.N()) iap = ia.GetProperty() if isinstance(ia, (shapes.Line, Points)): iapoly = ia.polydata() else: iapoly = ia.clone().clean().triangulate().computeNormals().polydata() vtkscals = None color_attribute = None if ia.mapper().GetScalarVisibility(): vtkdata = iapoly.GetPointData() vtkscals = vtkdata.GetScalars() if vtkscals is None: vtkdata = iapoly.GetCellData() vtkscals = vtkdata.GetScalars() if vtkscals is not None: c2p = vtk.vtkCellDataToPointData() c2p.SetInputData(iapoly) c2p.Update() iapoly = c2p.GetOutput() vtkdata = iapoly.GetPointData() vtkscals = vtkdata.GetScalars() if vtkscals is not None: if not vtkscals.GetName(): vtkscals.SetName('scalars') scals_min, scals_max = ia.mapper().GetScalarRange() color_attribute = (vtkscals.GetName(), scals_min, scals_max) lut = ia.mapper().GetLookupTable() lut.Build() kcmap=[] nlut = lut.GetNumberOfTableValues() for i in range(nlut): r,g,b,a = lut.GetTableValue(i) kcmap += [i/(nlut-1), r,g,b] #####################################################################Volume if isinstance(ia, Volume): # print('Volume', ia.name, ia.dimensions()) kx, ky, kz = ia.dimensions() arr = ia.pointdata[0] kimage = arr.reshape(-1, ky, kx) colorTransferFunction = ia.GetProperty().GetRGBTransferFunction() kcmap=[] for i in range(128): r,g,b = colorTransferFunction.GetColor(i/127) kcmap += [i/127, r,g,b] kbounds = numpy.array(ia.imagedata().GetBounds()) \ + numpy.repeat(numpy.array(ia.imagedata().GetSpacing()) / 2.0, 2)\ * numpy.array([-1,1] * 3) kobj = k3d.volume(kimage.astype(numpy.float32), color_map=kcmap, #color_range=ia.imagedata().GetScalarRange(), alpha_coef=10, bounds=kbounds, name=name, ) settings.notebook_plotter += kobj #####################################################################text elif hasattr(ia, 'info') and 'formula' in ia.info.keys(): pos = (ia.GetPosition()[0],ia.GetPosition()[1]) kobj = k3d.text2d(ia.info['formula'], position=pos) settings.notebook_plotter += kobj #####################################################################Mesh elif isinstance(ia, Mesh) and ia.N() and len(ia.faces()): # print('Mesh', ia.name, ia.N(), len(ia.faces())) kobj = k3d.vtk_poly_data(iapoly, name=name, # color=_rgb2int(iap.GetColor()), color_attribute=color_attribute, color_map=kcmap, opacity=iap.GetOpacity(), wireframe=(iap.GetRepresentation()==1)) if iap.GetInterpolation() == 0: kobj.flat_shading = True settings.notebook_plotter += kobj #####################################################################Points elif isinstance(ia, Points): # print('Points', ia.name, ia.N()) kcols=[] if color_attribute is not None: scals = utils.vtk2numpy(vtkscals) kcols = k3d.helpers.map_colors(scals, kcmap, [scals_min,scals_max]).astype(numpy.uint32) # sqsize = numpy.sqrt(numpy.dot(sizes, sizes)) kobj = k3d.points(ia.points().astype(numpy.float32), color=_rgb2int(iap.GetColor()), colors=kcols, opacity=iap.GetOpacity(), shader=settings.k3dPointShader, point_size=iap.GetPointSize(), name=name, ) settings.notebook_plotter += kobj #####################################################################Lines elif ia.polydata(False).GetNumberOfLines(): # print('Line', ia.name, ia.N(), len(ia.faces()), # ia.polydata(False).GetNumberOfLines(), len(ia.lines()), # color_attribute, [vtkscals]) # kcols=[] # if color_attribute is not None: # scals = utils.vtk2numpy(vtkscals) # kcols = k3d.helpers.map_colors(scals, kcmap, # [scals_min,scals_max]).astype(numpy.uint32) # sqsize = numpy.sqrt(numpy.dot(sizes, sizes)) for i, ln_idx in enumerate(ia.lines()): if i>200: print('WARNING: K3D nr of line segments is limited to 200.') break pts = ia.points()[ln_idx] kobj = k3d.line(pts.astype(numpy.float32), color=_rgb2int(iap.GetColor()), opacity=iap.GetOpacity(), shader=settings.k3dLineShader, # width=iap.GetLineWidth()*sqsize/1000, name=name, ) settings.notebook_plotter += kobj #################################################################################### elif settings.notebookBackend == 'panel' and hasattr(vp, 'window') and vp.window: import panel # https://panel.pyviz.org/reference/panes/VTK.html vp.renderer.ResetCamera() settings.notebook_plotter = panel.pane.VTK(vp.window, width=int(vp.size[0]/1.5), height=int(vp.size[1]/2)) #################################################################################### elif 'ipyvtk' in settings.notebookBackend and hasattr(vp, 'window') and vp.window: from ipyvtklink.viewer import ViewInteractiveWidget vp.renderer.ResetCamera() settings.notebook_plotter = ViewInteractiveWidget(vp.window) #################################################################################### elif 'ipygany' in settings.notebookBackend: from ipygany import PolyMesh, Scene, IsoColor, RGB, Component from ipygany import Alpha, ColorBar, colormaps, PointCloud from ipywidgets import FloatRangeSlider, Dropdown, VBox, AppLayout, jslink bgcol = colors.rgb2hex(colors.getColor(vp.backgrcol)) actors2show2 = [] for ia in actors2show: if not ia: continue if isinstance(ia, vedo.Assembly): #unpack assemblies assacts = ia.unpack() for ja in assacts: if isinstance(ja, vedo.Assembly): actors2show2 += ja.unpack() else: actors2show2.append(ja) else: actors2show2.append(ia) pmeshes = [] colorbar = None for obj in actors2show2: # print("ipygany processing:", [obj], obj.name) if isinstance(obj, vedo.shapes.Line): lg = obj.diagonalSize()/1000 * obj.GetProperty().GetLineWidth() vmesh = vedo.shapes.Tube(obj.points(), r=lg, res=4).triangulate() vmesh.c(obj.c()) faces = vmesh.faces() # todo: Lines elif isinstance(obj, Mesh): vmesh = obj.triangulate() faces = vmesh.faces() elif isinstance(obj, Points): vmesh = obj faces = [] elif isinstance(obj, Volume): vmesh = obj.isosurface() faces = vmesh.faces() elif isinstance(obj, vedo.TetMesh): vmesh = obj.tomesh(fill=False) faces = vmesh.faces() else: print("ipygany backend: cannot process object type", [obj]) continue vertices = vmesh.points() scals = vmesh.inputdata().GetPointData().GetScalars() if scals and not colorbar: # there is an active array, only pick the first aname = scals.GetName() arr = vmesh.pointdata[aname] parr = Component(name=aname, array=arr) if len(faces): pmesh = PolyMesh(vertices=vertices, triangle_indices=faces, data={aname: [parr]}) else: pmesh = PointCloud(vertices=vertices, data={aname: [parr]}) rng = scals.GetRange() colored_pmesh = IsoColor(pmesh, input=aname, min=rng[0], max=rng[1]) if obj.scalarbar: colorbar = ColorBar(colored_pmesh) colormap_slider_range = FloatRangeSlider(value=rng, min=rng[0], max=rng[1], step=(rng[1] - rng[0]) / 100.) jslink((colored_pmesh, 'range'), (colormap_slider_range, 'value')) colormap = Dropdown( options=colormaps, description='Colormap:' ) jslink((colored_pmesh, 'colormap'), (colormap, 'index')) else: if len(faces): pmesh = PolyMesh(vertices=vertices, triangle_indices=faces) else: pmesh = PointCloud(vertices=vertices) if vmesh.alpha() < 1: colored_pmesh = Alpha(RGB(pmesh, input=tuple(vmesh.color())), input=vmesh.alpha()) else: colored_pmesh = RGB(pmesh, input=tuple(vmesh.color())) pmeshes.append(colored_pmesh) if colorbar: scene = AppLayout( left_sidebar=Scene(pmeshes, background_color=bgcol), right_sidebar=VBox((colormap_slider_range, #not working colorbar, colormap)), pane_widths=[2, 0, 1], ) else: scene = Scene(pmeshes, background_color=bgcol) settings.notebook_plotter = scene #################################################################################### elif '2d' in settings.notebookBackend.lower() and hasattr(vp, 'window') and vp.window: import PIL.Image try: import IPython except ImportError: raise Exception('IPython not available.') from vedo.io import screenshot settings.screeshotLargeImage = True nn = screenshot(returnNumpy=True, scale=settings.screeshotScale+2) pil_img = PIL.Image.fromarray(nn) settings.notebook_plotter = IPython.display.display(pil_img) return settings.notebook_plotter
def interactive_numerical_plot(df_num, df_Y): """Plot Interactive KDE graph. Allow user to choose variable, set xlim and save figure. df_Y only allow binary class Parameters ---------- df_num : DataFrame df_Y : Series Returns ------- None """ from ipywidgets import HBox, Checkbox, FloatRangeSlider, VBox, ToggleButton, interactive_output, Dropdown from IPython.display import display def plot_num_and_save(xlimit, save_but, col, clip_box, clip_limit): nonlocal df_num, df_Y plt.close('all') if clip_box: clip_df_num = df_num.copy() clip_df_num.loc[clip_df_num[col] > clip_limit[1], col] = np.nan clip_df_num.loc[clip_df_num[col] < clip_limit[0], col] = np.nan else: clip_df_num = df_num # for i,col in zip(range(clip_df_num[col].shape[1]),clip_df_num[col]): fig, ax = plt.subplots(1, 1, figsize=(10, 5)) sns.kdeplot(clip_df_num[col][df_Y == 0], label='label0').set_title(clip_df_num[col].name) sns.kdeplot(clip_df_num[col][df_Y == 1], label='label1') ax.set_xlim(xlimit[0], xlimit[1]) plt.show() if save_but: fig.savefig('./plots/{}.png'.format(clip_df_num[col].name), bbox_inches='tight') xlimit = FloatRangeSlider( value=[df_num.iloc[:, 1].min(), df_num.iloc[:, 1].max()], min=df_num.iloc[:, 1].min(), max=df_num.iloc[:, 1].max(), step=(df_num.iloc[:, 1].max() - df_num.iloc[:, 1].min()) / 100, continuous_update=False, description='X_limit') save_but = ToggleButton(description='Save Figure') col = Dropdown(options=df_num.columns.tolist()) clip_box = Checkbox(value=False, description='Clip ?') clip_limit = FloatRangeSlider( value=[df_num.iloc[:, 1].min(), df_num.iloc[:, 1].max()], min=df_num.iloc[:, 1].min(), max=df_num.iloc[:, 1].max(), step=(df_num.iloc[:, 1].max() - df_num.iloc[:, 1].min()) / 100, continuous_update=False, description='X_limit') out = interactive_output( plot_num_and_save, { 'xlimit': xlimit, 'save_but': save_but, 'col': col, 'clip_box': clip_box, 'clip_limit': clip_limit }) # save_but = Button(description='Save Fig') vbox1 = VBox([xlimit, save_but, col, clip_box, clip_limit]) ui = HBox([vbox1, out]) display(ui) def on_click(change): change['owner'].value = False def on_click_case(change): try: xlimit.min = df_num[change['new']].min() xlimit.max = df_num[change['new']].max() clip_limit.min = df_num[change['new']].min() clip_limit.max = df_num[change['new']].max() except: xlimit.max = df_num[change['new']].max() xlimit.min = df_num[change['new']].min() clip_limit.max = df_num[change['new']].max() clip_limit.min = df_num[change['new']].min() xlimit.step = (df_num[change['new']].max() - df_num[change['new']].min()) / 100 xlimit.value = [ df_num[change['new']].min(), df_num[change['new']].max() ] clip_limit.step = (df_num[change['new']].max() - df_num[change['new']].min()) / 100 clip_limit.value = [ df_num[change['new']].min(), df_num[change['new']].max() ] save_but.observe(on_click, 'value') col.observe(on_click_case, 'value')
def _default_plotter(self, clim=None, mask_background=False, **kwargs): """ Plot three orthogonal views. This is called by nifti_plotter, you shouldn't call it directly. """ data_array = self.data if not ((data_array.ndim == 3) or (data_array.ndim == 4)): raise ValueError('Input image should be 3D or 4D') # mask the background if mask_background: # TODO: add the ability to pass 'mne' to use a default brain mask # TODO: split this out into a different function if data_array.ndim == 3: labels, n_labels = scipy.ndimage.measurements.label( (np.round(data_array) == 0)) else: # 4D labels, n_labels = scipy.ndimage.measurements.label( (np.round(data_array).max(axis=3) == 0)) mask_labels = [ lab for lab in range(1, n_labels + 1) if (np.any(labels[[0, -1], :, :] == lab) | np.any(labels[:, [0, -1], :] == lab) | np.any(labels[:, :, [0, -1]] == lab)) ] if data_array.ndim == 3: data_array = np.ma.masked_where(np.isin(labels, mask_labels), data_array) else: data_array = np.ma.masked_where( np.broadcast_to( np.isin(labels, mask_labels)[:, :, :, np.newaxis], data_array.shape), data_array) # init sliders for the various dimensions for dim, label in enumerate(['x', 'y', 'z']): if label not in kwargs.keys(): kwargs[label] = IntSlider(value=(data_array.shape[dim] - 1) / 2, min=0, max=data_array.shape[dim] - 1, description=self.directions[dim], continuous_update=True) if (data_array.ndim == 3) or (data_array.shape[3] == 1): kwargs['t'] = fixed(0) # time is fixed else: # 4D if self.plottype == 'image': desc = 'time' elif self.plottype == 'projection': desc = 'Azim_angle' else: desc = 't' kwargs['t'] = IntSlider(value=data_array.shape[3] // 2, min=0, max=data_array.shape[3] - 1, description=desc, continuous_update=True) if clim is None: clim = (0, data_array.max()) kwargs['clim'] = FloatRangeSlider( value=clim, min=0, max=clim[1], step=0.05, description='Contrast', disabled=False, continuous_update=True, orientation='horizontal', readout=True, readout_format='.1f', ) interact(self._plot_slices, data=fixed(data_array), **kwargs)
class SliceViewer(VBox): def __init__(self, volume=None, default_directory=os.getcwd(), title='', enhancement_steps=1000, **kwargs): def on_chosen_path_change(old_path, new_path): self.dataset = FolderDataset(new_path) # TODO: If the path doesn't contain images, display a warning # A widget for changing the image folder self.pathchooser = PathChooser( chosen_path_desc='Image folder:', default_directory=default_directory, on_chosen_path_change=on_chosen_path_change, ) self.pathchooser.layout.margin = '0 0 10px 0' # The number of increments of the min/max slider self.enhancement_steps = enhancement_steps self.scales = { 'x': LinearScale(), 'y': LinearScale(), } # The currently displayed image will be in bytes at `self.image_plot.image.value` self.image_plot = BQImage( image=IPyImage(), scales=self.scales, ) self.figure = Figure( marks=[self.image_plot], padding_x=0, padding_y=0, animation_duration=1000, fig_margin={ 'top': 0, 'right': 0, 'bottom': 0, 'left': 0, }, layout=Layout( grid_area='figure', margin='0', width='320px', height='320px', ), ) # Custom toolbar toolbar_width = '100%' toolbar_margin = '0px 0 2px 0' self.pan_zoom = PanZoom(scales={ 'x': [self.scales['x']], 'y': [self.scales['y']], }, ) self.save_button = Button( description='Save Image', tooltip='Save Image', icon='save', layout=Layout( width=toolbar_width, # flex='1 1 auto', margin=toolbar_margin, ), ) self.save_button.on_click(self.save_current_image) self.hide_button = Button( description='Hide Image', tooltip='Hide Image', icon='eye-slash', layout=Layout( width=toolbar_width, # flex='1 1 auto', margin=toolbar_margin, )) self.hide_button.on_click(self.hide_current_image) self.pan_zoom_toggle_button = ToggleButton( description='Pan / Zoom', tooltip='Pan/Zoom', icon='arrows', layout=Layout( width=toolbar_width, # flex='1 1 auto', margin=toolbar_margin, ), ) self.pan_zoom_toggle_button.observe(self.on_pan_zoom_toggle, names='value') self.reset_pan_zoom_button = Button( description='Undo Zoom', tooltip='Reset pan/zoom', icon='refresh', layout=Layout( width=toolbar_width, # flex='1 1 auto', margin=toolbar_margin, ), ) self.reset_pan_zoom_button.on_click(self.reset_pan_zoom) self.reset_enhancements_button = Button( description='Un-Enhance', tooltip='Reset enhancements', icon='ban', layout=Layout( width=toolbar_width, # flex='1 1 auto', margin=toolbar_margin, ), ) self.reset_enhancements_button.on_click(self.reset_enhancements) self.mini_map = IPyImage(layout=Layout( grid_area='mini-map', margin='0', )) self.mini_map.width = 180 self.mini_map.height = 180 # PERFORMANCE CONCERN # Ideally instead of four observations, this would observe 'scales' on `self.pan_zoom` # However, it doesn't fire updates # Ref: https://github.com/bloomberg/bqplot/issues/800 self.image_plot.scales['x'].observe(self.on_pan_zoom_change('x_min'), names='min') self.image_plot.scales['x'].observe(self.on_pan_zoom_change('x_max'), names='max') self.image_plot.scales['y'].observe(self.on_pan_zoom_change('y_min'), names='min') self.image_plot.scales['y'].observe(self.on_pan_zoom_change('y_max'), names='max') self.plane_toggle = ToggleButtons( options=['yz', 'xz', 'xy'], description='', disabled=False, button_style='', tooltips=[ 'Step in x direction', 'Step in y direction', 'Step in z direction' ], layout=Layout( width='200px', # flex='1 1 auto', margin='7px 0 auto auto', ), ) self.plane_toggle.style.button_width = 'auto' self.plane_toggle.observe(self.on_plane_change, names='value') self.toolbar = VBox( children=[ self.save_button, self.hide_button, self.pan_zoom_toggle_button, self.reset_pan_zoom_button, self.reset_enhancements_button, ], layout=Layout( grid_area='toolbar', margin='0', ), ) # Image enhancements self.min_max_slider = FloatRangeSlider( value=[0, 255], min=0, max=255, step=255 / self.enhancement_steps, description='Min/Max:', orientation='horizontal', readout=True, readout_format='.1f', continuous_update=True, layout=Layout( grid_area='min-max-slider', margin='10px 0 10px -10px', width='100%', ), ) self.min_max_slider.observe(self.on_min_max_change, names='value') self.index_slider = IntSlider( value=0, min=0, max=1, step=1, description='Index:', orientation='horizontal', readout=True, readout_format='d', continuous_update=True, layout=Layout( grid_area='index-slider', margin='8px -20px 10px -36px', width='100%', ), ) self.index_slider.observe(self.on_image_index_change, names='value') # Animation self.play = Play( value=self.index_slider.value, min=self.index_slider.min, max=self.index_slider.max, step=self.index_slider.step, ) jslink((self.play, 'value'), (self.index_slider, 'value')) # Keep 'max' in sync as well self.index_slider.observe(self.on_index_slider_max_change, names='max') self.bottom_bar = HBox( children=[ self.play, self.index_slider, self.plane_toggle, ], layout=Layout( grid_area='bottom-bar', margin=f'10px -20px 0 0', # overflow='hidden', )) # Layout self.gridbox = GridBox(children=[ self.figure, self.toolbar, self.mini_map, self.min_max_slider, self.bottom_bar, ], ) # Initially hidden without data self.gridbox.layout.display = 'none' self._dataset = None if volume is not None: self.dataset = VolumeDataset(volume) # Hide pathchooser when using a volume self.pathchooser.layout.display = 'none' # Call VBox super class __init__ super().__init__( children=[ self.pathchooser, self.gridbox, ], layout=Layout(width='auto'), **kwargs, ) @property def dataset(self): """ Get the dataset that the SliceViewer is displaying. """ return self._dataset @dataset.setter def dataset(self, dataset): """ Set the dataset that the SliceViewer is displaying. """ if dataset: # TODO: set initial pan_zoom_scales # image_as_array = dataset[0] # width, height = image_as_array.shape # self.get_initial_pan_zoom_scales() self.index_slider.max = len(dataset) - 1 # self.play.max = self.index_slider.max # Could be simpler with 0 margins, but for now is written generically self.plane_toggle.disabled = not isinstance(dataset, VolumeDataset) self.gridbox.layout = Layout( width='auto', # height='500px', grid_gap='0px 10px', # grid_template_columns='auto auto auto', grid_template_columns=f'{self.figure_size[0]}px 180px', # grid_template_rows=f'134px {self.figure_size[1] - 110}px 52px 52px', grid_template_rows=f'140px 180px 36px 60px', grid_template_areas=''' "figure toolbar" "figure mini-map" "min-max-slider min-max-slider" "bottom-bar bottom-bar" ''', ) self.gridbox.layout.display = None else: self.gridbox.layout.display = 'none' self._dataset = dataset # Crucially, this also calls self.redraw self.reset_enhancements() @property def figure_size(self): """ Get the figure layout width and height as integers. """ width = int(self.figure.layout.width[:-2]) height = int(self.figure.layout.height[:-2]) return [width, height] @figure_size.setter def figure_size(self, size): """ Set the figure layout width and height with the provided list. """ width, height = size self.figure.layout.width = f'{width}px' self.figure.layout.height = f'{height}px' @property def current_image(self): """ Get the current image from backing `self.dataset` according to `self.index_slider`. It should be a normalized numpy array. """ return self.dataset[self.index_slider.value] @property def value_range(self): """ Get the value ranges of the unormalized dataset. """ low = getattr(self.dataset, 'min', 0) high = getattr(self.dataset, 'max', 255) return [low, high] @output.capture() def get_current_image_name(self): """ Return the name of the current image selected according to `self.index_slider`. """ if not self.dataset: return '' else: index = self.index_slider.value image_names = getattr(self.dataset, 'image_names', []) if image_names: return image_names[index] else: return f'sliceviewer-image-{index}.jpg' @output.capture() def get_current_scales(self): """ Get the current image_plot scales in a plain dictionary. """ scales = self.image_plot.scales plain_scales = { 'x': [scales['x'].min, scales['x'].max], 'y': [scales['y'].min, scales['y'].max], } # Coerce None to 0 plain_scales['x'] = [x if x else 0 for x in plain_scales['x']] plain_scales['y'] = [y if y else 0 for y in plain_scales['y']] return plain_scales @output.capture() def redraw(self, image_as_array=None): """ Redraw main image and mini-map. Defaults to enhanced current image. """ # Main image if image_as_array is None: image_as_array = self.enhance_image(self.current_image) image = PIL_to_bytes(numpy_to_PIL(image_as_array)) self.image_plot.image = IPyImage(value=image) # Mini-map self.redraw_mini_map(image_as_array=image_as_array) @output.capture() def redraw_mini_map(self, image_as_array=None, scales=None): """ Redraw the mini-map. Defaults to enhanced current image. """ if image_as_array is None: image_as_array = self.enhance_image(self.current_image) if scales is None: scales = self.get_current_scales() mini_map = self.draw_mini_map(image_as_array, scales) self.mini_map.value = PIL_to_bytes(numpy_to_PIL(mini_map)) @output.capture() def on_image_index_change(self, change): """ Load and display the new image. """ enhanced = self.enhance_image(self.current_image) self.redraw(image_as_array=enhanced) @output.capture() def on_index_slider_max_change(self, change): """ Sync play.max with index_slider.max and reset index slider. """ self.play.max = change.new @output.capture() def get_initial_pan_zoom_scales(self): """ Calculate the necessary pan_zoom scales to fill-in the main viewport when the input image is not square. """ raise NotImplementedError @output.capture() def on_pan_zoom_toggle(self, change): """ Update the `self.figure` interaction. """ if change.new: self.figure.interaction = self.pan_zoom else: self.figure.interaction = None @output.capture() def reset_pan_zoom(self, button): """ Reset figure/plot scales. """ self.image_plot.scales['x'].min = None self.image_plot.scales['x'].max = None self.image_plot.scales['y'].min = None self.image_plot.scales['y'].max = None self.redraw_mini_map() @output.capture() def draw_mini_map(self, image_as_array, scales): """ Draw a mini version of image_as_array with a rectangle indicating pan/zoom location. """ # Commented code is preparation for non-square image # canvas_as_array = draw_checkerboard_canvas( # height=int(self.mini_map.height), # width=int(self.mini_map.width), # ) # offsets, image_as_array = get_offsets_and_resize_for_canvas( # image_as_array, # canvas_as_array, # ) shape = image_as_array.shape # Convert grayscale to RGB mini_map = to_rgb(image_as_array) # Draw a red square indicating the zoom location xs = [int(x * shape[1]) for x in scales['x']] ys = [int((1.0 - y) * shape[0]) for y in scales['y']] # Make sure values are in range def clamp(values, low, high): temp = [v if v > low else low for v in values] return [v if v < high else high for v in temp] # This will give a border width of 2 pixels xs.extend([x + 1 for x in xs]) ys.extend([y - 1 for y in ys]) xs = clamp(xs, 0, shape[1] - 2) ys = clamp(ys, 0, shape[0] - 2) for x in xs + [x + 1 for x in xs]: for y in range(ys[1], ys[0] + 1): # Color these locations full-on red mini_map[y][x][0] = 1.0 for y in ys + [y + 1 for y in ys]: for x in range(xs[0], xs[1] + 1): # Color these locations full-on red mini_map[y][x][0] = 1.0 return mini_map # Commented code is preparation for non-square image # canvas_as_array = to_rgb(canvas_as_array) # canvas_as_array[offsets[0]:, offsets[1]:] = mini_map # return canvas_as_array @output.capture() def on_pan_zoom_change(self, change_type): """ Return a function that produces new scales when the user pans or zooms. :param change_type: One of ['x_min', 'x_max', 'y_min', 'y_max'] """ def handle_case(change): if change.new == None: return scales = self.get_current_scales() cases = { 'x_min': { 'x': [change.new, scales['x'][1]], 'y': scales['y'], }, 'x_max': { 'x': [scales['x'][0], change.new], 'y': scales['y'], }, 'y_min': { 'x': scales['x'], 'y': [change.new, scales['y'][1]], }, 'y_max': { 'x': scales['x'], 'y': [scales['y'][0], change.new], }, } new_scales = cases[change_type] self.redraw_mini_map(scales=new_scales) return handle_case @output.capture() def reset_enhancements(self, button=None): """ Reset all of the image enhancement sliders. """ [low, high] = self.value_range self.min_max_slider.min = low self.min_max_slider.max = high self.min_max_slider.value = [low, high] self.min_max_slider.step = (high - low) / self.enhancement_steps self.redraw() @output.capture() def save_current_image(self, button): """ Save the current image with any processing applied. """ directory = getattr(self.dataset, 'directory', os.getcwd()) processed_directory = os.path.join(directory, 'ipysliceviewer') if not os.path.exists(processed_directory): os.makedirs(processed_directory) filepath = os.path.join(processed_directory, self.get_current_image_name()) with open(filepath, 'wb') as f: f.write(self.image_plot.image.value) @output.capture() def hide_current_image(self, button): """ Hide the current image and remember this as a setting. This is like a soft form of deleting the image. """ # Need more thought on how this should be remembered across restarts for the current dataset # Rough idea: text file or similar containing SliceViewer settings, just need to figure out # a good naming scheme for datasets - possibly can take name from Experimenter or SliceViewer's own text box raise NotImplementedError @output.capture() def enhance_image(self, image_as_array): """ Apply enhancement sliders to image_as_array and return as a numpy array """ # These values are not normalized even though the image above is # (this allows the user to work with the input range) new_min, new_max = self.min_max_slider.value # So, we'll convert them before using them to scale the normalized image [low, high] = self.value_range def rescale(x, low, high): return (x - low) / (high - low) new_min = rescale(new_min, low, high) new_max = rescale(new_max, low, high) processed_image = rescale(to_rgb(image_as_array), new_min, new_max) processed_image = np.clip(processed_image, 0, 1) return processed_image @output.capture() def on_min_max_change(self, change): """ Handle changes to the min/max slider. """ self.redraw() @output.capture() def on_plane_change(self, change): """ Called when the slice plane is toggled. """ if hasattr(self.dataset, 'plane'): self.dataset.plane = change.new old_max = self.index_slider.max new_max = len(self.dataset) - 1 self.index_slider.max = new_max self.index_slider.value = min(self.index_slider.value, new_max) # Guarantee the image updates even if index does not change self.redraw()
import pyvista as pv from ipywidgets import FloatSlider, FloatRangeSlider, Dropdown, Select, Box, AppLayout, jslink, Layout, VBox, HBox from ipygany import Scene, IsoColor, TetraMesh, Component, ColorBar, colormaps mesh = TetraMesh.from_vtk('benchmarks/002-cook-membrane/elmer.vtu', show_edges=True) dispy_min = 0.0 dispy_max = 32.5 # Colorize by height colored_mesh = IsoColor(mesh, input=('U', 'D2'), min=dispy_min, max=dispy_max) # Create a slider that will dynamically change the boundaries of the colormap colormap_slider_range = FloatRangeSlider(value=[dispy_min, dispy_max], min=dispy_min, max=dispy_max, step=(dispy_max - dispy_min) / 100.) jslink((colored_mesh, 'range'), (colormap_slider_range, 'value')) # Create a colorbar widget colorbar = ColorBar(colored_mesh) # Colormap choice widget colormap = Dropdown(options=colormaps, description='colormap:') jslink((colored_mesh, 'colormap'), (colormap, 'index')) AppLayout( header=Scene([colored_mesh]), left_sidebar=VBox((colormap, colormap_slider_range)),
def create_parameter_widgets(self, augmentation_name): """ augmentation_name - name of the augmentation you want to test """ function = partial(self.test_aug, augmentation_name=augmentation_name) ui_s = [] widget_dict = {} for param_name, values in self.aug_dict[augmentation_name].items(): if values[-2] == "width": lower = values[1] upper = self.shape[1] elif values[-2] == "height": lower = values[1] upper = self.shape[0] elif values[-2] == "channels-1": lower = values[1] upper = self.channels - 1 elif values[-1] == "max": lower = values[1] upper = max(self.shape) else: lower = values[1] upper = values[2] if values[-1] == "odd" and values[0] in ["int" "int_range"]: step = 2 elif values[-1] != "odd" and (values[0] == "int" or values[0] == "int_range"): step = 1 elif values[0] == "float" or values[0] == "float_range": step = 0.01 if values[0] == "int": widget = IntSlider( min=lower, max=upper, step=step, orientation="horizontal", # description=f'{param_name}:', continuous_update=False, ) widget_ = IntText( description="", continuous_update=False, readout=True, readout_format="d", ) widgets.link((widget, "value"), (widget_, "value")) widgets_linked = VBox([widget, widget_]) widgets_linked_with_description = HBox( [Label(param_name), widgets_linked]) ui_s.append(widgets_linked_with_description) setattr(widgets_linked_with_description, "value", widget.value) elif values[0] == "int_range": widget = IntRangeSlider( value=[1, 1] if values[-1] == "odd" else [0, 0], min=lower, max=upper, step=step, # description=f'{param_name}:', disabled=False, continuous_update=False, orientation="horizontal", readout=True, readout_format="d", ) widget_with_description = HBox([Label(param_name), widget]) setattr(widget_with_description, "value", widget.value) ui_s.append(widget_with_description) elif values[0] == "float": widget = FloatSlider( value=0, min=lower, max=upper, step=step, # description=f'{param_name}:', disabled=False, continuous_update=False, orientation="horizontal", readout=True, readout_format=".2f", ) widget_ = FloatText( description="", continuous_update=False, readout=True, readout_format=".2f", ) widgets.link((widget, "value"), (widget_, "value")) widgets_linked = VBox([widget, widget_]) widgets_linked_with_description = HBox( [Label(param_name), widgets_linked]) ui_s.append(widgets_linked_with_description) setattr(widgets_linked_with_description, "value", widget.value) elif values[0] == "float_range": widget = FloatRangeSlider( value=[0, 0], min=lower, max=upper, step=step, disabled=False, continuous_update=False, orientation="horizontal", readout=True, readout_format=".2f", ) widget_with_description = HBox([Label(param_name), widget]) ui_s.append(widget_with_description) setattr(widget_with_description, "value", widget.value) elif values[0] == "str" or values[0] == "bool": widget = RadioButtons(options=[*values[1]], value=values[1][1], disabled=False) widget_with_description = HBox([Label(param_name), widget]) setattr(widget_with_description, "value", widget.value) ui_s.append(widget_with_description) # ui_s.append(widget) widget_dict[f"{param_name}"] = widget out = interactive_output(function, widget_dict) display(*ui_s, out)
def single_run(data_dir="", id=""): if not os.path.exists(data_dir): raise FileNotFoundError("No directory found named: " + data_dir) run_summary = RunSummary(data_dir=data_dir, id=id) sedov_solution = SedovSolution(E_0, run_summary.overview.background_density, run_summary.overview.metallicity) #### PASS TO PLOTTER #### num_checkpoints = len(run_summary.filenames) # log_R_max = round(np.log10(run_summary.df["Radius"].max()), 2) # log_R_min = max(log_R_max-4, # round(np.log10(run_summary.df["Radius"].min()), 2)+1) R_min = run_summary.df["Radius"].min() R_min = 0 R_max = run_summary.df["Radius"].max() if type(single_run.previous_widget) is widgets.Box: single_run.previous_widget.close() w = interactive( plotter, run_summary=fixed(run_summary), sedov_solution=fixed(sedov_solution), xlim=FloatRangeSlider( min=R_min, max=R_max, step=0.01 * (R_max - R_min), value=(R_min, R_max), ), checkpoint_index=IntSlider(min=0, max=num_checkpoints - 1, step=0, value=num_checkpoints - 1), y_axis_variable=Dropdown(options=cols_plot, value="Density"), x_axis_variable=RadioButtons(options=["Radius", "M_int", "zones"]), label=fixed("numeric"), density_in_mH_cm3=fixed(False), verbose=fixed(True), ) w1 = widgets.Button(description=u"\u23EA") def show_first(b): checkpoint_slider = w.children[5] checkpoint_slider.value = checkpoint_slider.min w1.on_click(show_first) wl = widgets.Button(description=u"\u276E") def show_prev(b): checkpoint_slider = w.children[5] if checkpoint_slider.value > checkpoint_slider.min: checkpoint_slider.value -= 1 wl.on_click(show_prev) w2 = widgets.Button(description=u"\u25BA") # w2.stop = False def play(b): checkpoint_slider = w.children[5] for i in range(checkpoint_slider.value + 1, checkpoint_slider.max + 1): plt.gcf() checkpoint_slider.value = i # plt.show() # time.sleep(.1) # if b.stop: # break w2.on_click(play) # wp = widgets.Button(description=u"p") # def pause(b): # w2.stop=True # wp.on_click(pause) wr = widgets.Button(description=u"\u276F") def show_next(b): checkpoint_slider = w.children[5] if checkpoint_slider.value < checkpoint_slider.max: checkpoint_slider.value += 1 wr.on_click(show_next) w3 = widgets.Button(description=u"\u23E9") def show_last(b): checkpoint_slider = w.children[5] checkpoint_slider.value = checkpoint_slider.max w3.on_click(show_last) w_buttons = widgets.HBox(children=[w1, wl, w2, wr, w3]) w.children = tuple([_w for _w in w.children] + [w_buttons]) single_run.previous_widget = w display(w) # display(w_buttons) return run_summary