def interactive_plot(model_name): def _to_png(x): if hasattr(x, 'numpy'): x = x.numpy() x = np.rot90(x.squeeze(), n_rot90) x = np.clip(x, 0., 255.) x = x.astype(np.uint8) x = Image.fromarray(x) x = x.resize(resize, resample=Image.BILINEAR) return x def plot_intervention(intervention, idx, num_samples=32, save_image_dir='', save=False): fig, ax = plt.subplots(1, 4, figsize=(10, 2.5), gridspec_kw=dict(wspace=0, hspace=0)) orig_data = prep_data(calabresi_test[idx]) ms_type = orig_data['type'] del orig_data['type'] x_test = orig_data['x'] og = {k: v.to(device) for k, v in orig_data.items()} pyro.clear_param_store() cond = { k: torch.tensor([[v]]).to(device) for k, v in intervention.items() } counterfactual = loaded_models[model_name].counterfactual( og, cond, num_samples) counterfactual = { k: v.detach().cpu() for k, v in counterfactual.items() } x = counterfactual['x'].squeeze() x_test = x_test.squeeze() diff = (x - x_test).squeeze() if x.ndim == 3: if x.shape[0] == 3: x = x[1] x_test = x_test[1] diff = diff[1] else: raise ValueError(f'Invalid channel size: {x.shape[0]}.') lim = diff.abs().max() ax[1].set_title('Original') ax[1].imshow(np.rot90(x_test, n_rot90), img_cm, **imshow_kwargs) ax[2].set_title(fmt_intervention(intervention)) ax[2].imshow(np.rot90(x, n_rot90), img_cm, **imshow_kwargs) ax[3].set_title('Difference') im = ax[3].imshow(np.rot90(diff, n_rot90), diff_cm, clim=[-lim, lim]) plt.colorbar(im) for axi in ax: axi.axis('off') axi.xaxis.set_major_locator(plt.NullLocator()) axi.yaxis.set_major_locator(plt.NullLocator()) if 'cuda' in str(device): del og, cond torch.cuda.empty_cache() orig_data['type'] = ms_type att_str = ( '$s={sex}$\n$a={age}$\n$b={brain_volume}$\n$v={ventricle_volume}$\n$l={lesion_volume}$\n' '$d={duration}$\n$e={edss}$\n$t={type}$').format( **{ att: value_fmt[att](orig_data[att].item()) for att in variables + ('type', ) }) ax[0].text(0.5, 0.5, att_str, horizontalalignment='center', verticalalignment='center', transform=ax[0].transAxes, fontsize=mpl.rcParams['axes.titlesize']) fig.tight_layout() if save_image_dir and save: x = _to_png(x) x_test = _to_png(x_test) intervention_str = fmt_save(intervention) x.save(os.path.join(save_image_dir, intervention_str + '_cf.png')) x_test.save( os.path.join(save_image_dir, intervention_str + '_orig.png')) plt.savefig(intervention_str + '_full.pdf') plt.show() from ipywidgets import (interactive, IntSlider, FloatSlider, HBox, VBox, Checkbox, Dropdown, Text, Button, BoundedIntText) from IPython.display import display def plot(image, age, sex, brain_volume, ventricle_volume, lesion_volume, duration, edss, do_age, do_sex, do_brain_volume, do_ventricle_volume, do_lesion_volume, do_duration, do_edss, save_image_dir, save): intervention = {} if do_age: intervention['age'] = age if do_sex: intervention['sex'] = sex if do_brain_volume: intervention['brain_volume'] = brain_volume * 1000. if do_ventricle_volume: intervention['ventricle_volume'] = ventricle_volume * 1000. if do_lesion_volume: intervention['lesion_volume'] = lesion_volume * 1000. if do_duration: intervention['duration'] = duration if do_edss: intervention['edss'] = edss plot_intervention(intervention, image, save_image_dir=save_image_dir, save=save) w = interactive( plot, image=BoundedIntText(min=0, max=len(calabresi_test) - 1, description='Image #'), age=FloatSlider(min=20., max=80., step=1., continuous_update=False, description='Age'), do_age=Checkbox(description='do(age)'), sex=Dropdown(options=[('female', 0.), ('male', 1.)], description='Sex'), do_sex=Checkbox(description='do(sex)'), brain_volume=FloatSlider(min=600., max=1800., step=0.5, continuous_update=False, description='Brain Volume (ml):', style={'description_width': 'initial'}), do_brain_volume=Checkbox(description='do(brain_volume)'), ventricle_volume=FloatSlider(min=1e-5, max=88., step=0.1, continuous_update=False, description='Ventricle Volume (ml):', style={'description_width': 'initial'}), do_ventricle_volume=Checkbox(description='do(ventricle_volume)'), lesion_volume=FloatSlider(min=1e-5, max=66., step=0.1, continuous_update=False, description='Lesion Volume (ml):', style={'description_width': 'initial'}), do_lesion_volume=Checkbox(description='do(lesion_volume)'), duration=FloatSlider(min=1e-5, max=24., step=1., continuous_update=False, description='Duration (y):', style={'description_width': 'initial'}), do_duration=Checkbox(description='do(duration)'), edss=FloatSlider(min=1e-5, max=10., step=1., continuous_update=False, description='EDSS:', style={'description_width': 'initial'}), do_edss=Checkbox(description='do(edss)'), save_image_dir=Text(value='', placeholder='Full path', description='Save Image Directory:', style={'description_width': 'initial'}), save=Checkbox(description='Save')) n = len(variables) ui = VBox([ HBox([w.children[0], w.children[-3], w.children[-2]]), # image # and save_image_dir VBox([ HBox([w.children[i], w.children[i + n]]) for i in range(1, n + 1) ]), # vars and intervention checkboxes w.children[-1] ]) # show image display(ui) w.update()
def dsc_config(dsc_value): values = config.read() ds_db = Dropdown( options=["1"], value="1", description='Database:', disabled=False, layout=Layout(width='140px') ) try: with open(f"{config.get_value(['paths','temp'])}tb_prefix", 'r') as f: code_value = f.read() except Exception: code_value = dsc_value ds_code = Combobox( value=code_value, placeholder='abc', options=[m for m in data_options.eu_ms()]+[''], description='AOI code:', ensure_option=False, disabled=False, layout=Layout(width='200px'), tooltip='Lowercase AOI code name for the dataset (5chr max).' ) ds_year = BoundedIntText( value=int(dsy.value), min=1980, max=2100, step=1, description='Dataset year:', disabled=False, layout=Layout(width='180px') ) ds_desc = Text( value=values['ds_conf'][dsc_value]['desc'], description='Description:', disabled=False ) info_map_text = ["Set default map view options. ", "You can get automatically the dataset ", "center coordinates."] lat, lon = values['ds_conf'][dsc_value]['center'].split(",") map_cent_lat = FloatText( value=float(lat), description='Lat:', disabled=False, layout=Layout(width='160px') ) map_cent_lon = FloatText( value=float(lon), description='Lon:', disabled=False, layout=Layout(width='160px') ) map_zoom = BoundedIntText( value=values['ds_conf'][dsc_value]['zoom'], min=0, max=20, step=1, description='Zoom:', disabled=False, layout=Layout(width='140px') ) bt_get_center = Button( layout=Layout(width='40px'), icon='bullseye', tooltip='Get center point from database.' ) ds_box = HBox([ds_code, ds_year, ds_desc]) map_box = HBox([Label("Map center: "), map_cent_lat, map_cent_lon, bt_get_center, map_zoom]) info_config = Label( """Change 'AOI code' value to create a new configuration set or leave the same 'AOI code' value to configure the selected one.""") db = int(values['ds_conf'][dsc_value]['db']) def get_tb_list(): tbls = database.tables(db, None, False) if tbls is None: return [] else: return tbls tb_dc = Dropdown( options=get_tb_list(), value=config.autoselect( values['ds_conf'][dsc_value]['years'][ str(ds_year.value)]['tables']['dias_catalog'], get_tb_list(), False), description='DIAS catalog:', disabled=False ) tb_pr = Dropdown( options=get_tb_list(), value=config.autoselect( values['ds_conf'][dsc_value]['years'][ str(ds_year.value)]['tables']['parcels'], get_tb_list(), False), description='Parcels:', disabled=False ) def get_pr_columns(): try: colms = database.table_columns(tb_pr.value, 1, None) if colms is None: return [] else: return colms except Exception: return [] tc_id = Dropdown( options=get_pr_columns(), value=config.autoselect( values['ds_conf'][dsc_value]['years'][ str(ds_year.value)]['columns']['parcels_id'], get_pr_columns(), False), description='Parcels ID:', disabled=False, layout=Layout(width='180px') ) tc_cn = Dropdown( options=get_pr_columns(), value=config.autoselect( values['ds_conf'][dsc_value]['years'][ str(ds_year.value)]['columns']['crop_names'], get_pr_columns(), False), description='Crop names:', disabled=False, layout=Layout(width='180px') ) tc_cc = Dropdown( options=get_pr_columns(), value=config.autoselect( values['ds_conf'][dsc_value]['years'][ str(ds_year.value)]['columns']['crop_codes'], get_pr_columns(), False), description='Crop codes:', disabled=False, layout=Layout(width='180px') ) def on_tb_pr_change(change): tc_id.options = get_pr_columns() tc_cn.options = get_pr_columns() tc_cc.options = get_pr_columns() tb_pr.observe(on_tb_pr_change, 'value') parcel_box = HBox([tb_pr, tc_id, tc_cn, tc_cc]) tb_s2 = Dropdown( options=get_tb_list(), value=config.autoselect( values['ds_conf'][dsc_value]['years'][ str(ds_year.value)]['tables']['s2'], get_tb_list(), False), description='S2 signatures:', disabled=False ) tb_bs = Dropdown( options=get_tb_list(), value=config.autoselect( values['ds_conf'][dsc_value]['years'][ str(ds_year.value)]['tables']['bs'], get_tb_list(), False), description='Backscattering:', disabled=False ) tb_6c = Dropdown( options=get_tb_list(), value=config.autoselect( values['ds_conf'][dsc_value]['years'][ str(ds_year.value)]['tables']['c6'], get_tb_list(), False), description='6 day coherence:', disabled=False ) wb_save = Button( description='Save', disabled=False, icon='save' ) @bt_get_center.on_click def bt_get_center_on_click(b): import json center_json = json.loads( database.getTableCentroid(tb_pr.value)['center'][0]) map_cent_lat.value = round(center_json['coordinates'][1], 2) map_cent_lon.value = round(center_json['coordinates'][0], 2) map_zoom.value = 10 @wb_save.on_click def wb_save_on_click(b): progress.clear_output() dscode = ds_code.value config.update(['ds_conf', dscode, 'years', str(ds_year.value), 'tables', 'dias_catalog'], str(tb_dc.value)) config.update(['ds_conf', dscode, 'years', str(ds_year.value), 'tables', 'parcels'], str(tb_pr.value)) config.update(['ds_conf', dscode, 'years', str(ds_year.value), 'columns', 'parcels_id'], str(tc_id.value)) config.update(['ds_conf', dscode, 'years', str(ds_year.value), 'columns', 'crop_names'], str(tc_cn.value)) config.update(['ds_conf', dscode, 'years', str(ds_year.value), 'columns', 'crop_codes'], str(tc_cc.value)) config.update(['ds_conf', dscode, 'years', str(ds_year.value), 'tables', 's2'], str(tb_s2.value)) config.update(['ds_conf', dscode, 'years', str(ds_year.value), 'tables', 'bs'], str(tb_bs.value)) config.update(['ds_conf', dscode, 'years', str(ds_year.value), 'tables', 'c6'], str(tb_6c.value)) config.update(['ds_conf', dscode, 'db'], str(ds_db.value)) config.update(['ds_conf', dscode, 'desc'], str(ds_desc.value)) config.update(['ds_conf', dscode, 'center'], f"{map_cent_lat.value},{map_cent_lon.value}") config.update(['ds_conf', dscode, 'zoom'], str(map_zoom.value)) config.update(['set', 'ds_conf'], str(dscode)) config.update(['set', 'ds_year'], str(ds_year.value)) values = config.read() ds_c = values['set']['ds_conf'] ds_y = values['set']['ds_year'] dsc.options = [d for d in values['ds_conf']] dsy.options = [int(y) for y in values['ds_conf'][ds_c]['years']] dsc.value = ds_c dsy.value = int(ds_y) outlog("The configurations are saved.") return VBox([info_config, ds_box, parcel_box, tb_dc, tb_s2, tb_bs, tb_6c, Label(''.join(info_map_text)), map_box, wb_save])
def __init__(self): # micron_units = HTMLMath(value=r"$\mu M$") micron_units = Label( 'micron') # use "option m" (Mac, for micro symbol) # micron_units = Label('microns') # use "option m" (Mac, for micro symbol) constWidth = '180px' # tab_height = '400px' tab_height = '500px' # tab_layout = Layout(width='900px', # border='2px solid black', # tab_layout = Layout(width='850px', # border='2px solid black', # height=tab_height, overflow_y='scroll',) # np_tab_layout = Layout(width='800px', # border='2px solid black', # height='350px', overflow_y='scroll',) # my_domain = [0,0,-10, 2000,2000,10, 20,20,20] # [x,y,zmin, x,y,zmax, x,y,zdelta] # label_domain = Label('Domain ($\mu M$):') label_domain = Label('Domain (micron):') stepsize = 10 disable_domain = False self.xmin = FloatText( step=stepsize, # description='$X_{min}$', description='Xmin', disabled=disable_domain, layout=Layout(width=constWidth), ) self.ymin = FloatText( step=stepsize, description='Ymin', disabled=disable_domain, layout=Layout(width=constWidth), ) self.zmin = FloatText( step=stepsize, description='Zmin', disabled=disable_domain, layout=Layout(width=constWidth), ) self.xmax = FloatText( step=stepsize, description='Xmax', disabled=disable_domain, layout=Layout(width=constWidth), ) self.ymax = FloatText( step=stepsize, description='Ymax', disabled=disable_domain, layout=Layout(width=constWidth), ) self.zmax = FloatText( step=stepsize, description='Zmax', disabled=disable_domain, layout=Layout(width=constWidth), ) # description='$Time_{max}$', self.tmax = BoundedFloatText( min=0., max=100000000, step=stepsize, description='Max Time', layout=Layout(width=constWidth), ) self.xdelta = BoundedFloatText( min=1., description='dx', # '∆x', # Mac: opt-j for delta disabled=disable_domain, layout=Layout(width=constWidth), ) self.ydelta = BoundedFloatText( min=1., description='dy', disabled=True, layout=Layout(width=constWidth), ) self.zdelta = BoundedFloatText( min=1., description='dz', disabled=disable_domain, layout=Layout(width=constWidth), ) def xdelta_cb(b): self.ydelta.value = self.xdelta.value self.zdelta.value = 0.5 * (self.xdelta.value + self.ydelta.value) self.zmin.value = -0.5 * self.zdelta.value self.zmax.value = 0.5 * self.zdelta.value self.xdelta.observe(xdelta_cb) """ self.tdelta = BoundedFloatText( min=0.01, description='$Time_{delta}$', layout=Layout(width=constWidth), ) """ """ self.toggle2D = Checkbox( description='2-D', layout=Layout(width=constWidth), ) def toggle2D_cb(b): if (self.toggle2D.value): #zmin.disabled = zmax.disabled = zdelta.disabled = True zmin.disabled = True zmax.disabled = True zdelta.disabled = True else: zmin.disabled = False zmax.disabled = False zdelta.disabled = False self.toggle2D.observe(toggle2D_cb) """ x_row = HBox([self.xmin, self.xmax, self.xdelta]) y_row = HBox([self.ymin, self.ymax, self.ydelta]) z_row = HBox([self.zmin, self.zmax, self.zdelta]) self.omp_threads = BoundedIntText( min=1, max=4, description='# threads', layout=Layout(width=constWidth), ) # self.toggle_prng = Checkbox( # description='Seed PRNG', style={'description_width': 'initial'}, # e.g. 'initial' '120px' # layout=Layout(width=constWidth), # ) # self.prng_seed = BoundedIntText( # min = 1, # description='Seed', # disabled=True, # layout=Layout(width=constWidth), # ) # def toggle_prng_cb(b): # if (toggle_prng.value): # self.prng_seed.disabled = False # else: # self.prng_seed.disabled = True # self.toggle_prng.observe(toggle_prng_cb) #prng_row = HBox([toggle_prng, prng_seed]) self.toggle_svg = Checkbox( description='Cells', # SVG layout=Layout(width='150px')) # constWidth = '180px' # self.svg_t0 = BoundedFloatText ( # min=0, # description='$T_0$', # layout=Layout(width=constWidth), # ) self.svg_interval = BoundedIntText( min=1, max= 99999999, # TODO: set max on all Bounded to avoid unwanted default description='every', layout=Layout(width='160px'), ) self.mcds_interval = BoundedIntText( min=1, max=99999999, description='every', # disabled=True, layout=Layout(width='160px'), ) # don't let this be > mcds interval def svg_interval_cb(b): if (self.svg_interval.value > self.mcds_interval.value): self.svg_interval.value = self.mcds_interval.value self.svg_interval.observe( svg_interval_cb) # BEWARE: when fill_gui, this sets value = 1 ! # don't let this be < svg interval def mcds_interval_cb(b): if (self.mcds_interval.value < self.svg_interval.value): self.mcds_interval.value = self.svg_interval.value self.mcds_interval.observe( mcds_interval_cb) # BEWARE: see warning above def toggle_svg_cb(b): if (self.toggle_svg.value): # self.svg_t0.disabled = False self.svg_interval.disabled = False else: # self.svg_t0.disabled = True self.svg_interval.disabled = True self.toggle_svg.observe(toggle_svg_cb) self.toggle_mcds = Checkbox( # value=False, description='Subtrates', # Full layout=Layout(width='180px'), ) # self.mcds_t0 = FloatText( # description='$T_0$', # disabled=True, # layout=Layout(width=constWidth), # ) def toggle_mcds_cb(b): if (self.toggle_mcds.value): # self.mcds_t0.disabled = False #False self.mcds_interval.disabled = False else: # self.mcds_t0.disabled = True self.mcds_interval.disabled = True self.toggle_mcds.observe(toggle_mcds_cb) svg_mat_output_row = HBox([ Label('Plots:'), self.toggle_svg, HBox([self.svg_interval, Label('min')]), self.toggle_mcds, HBox([self.mcds_interval, Label('min')]) ]) # to sync, do this # svg_mat_output_row = HBox( [Label('Plots:'), self.svg_interval, Label('min')]) #write_config_row = HBox([write_config_button, write_config_file]) #run_sim_row = HBox([run_button, run_command_str, kill_button]) # run_sim_row = HBox([run_button, run_command_str]) # run_sim_row = HBox([run_button.w]) # need ".w" for the custom RunCommand widget label_blankline = Label('') # toggle_2D_seed_row = HBox([toggle_prng, prng_seed]) # toggle2D box_layout = Layout(border='1px solid') # domain_box = VBox([label_domain,x_row,y_row,z_row], layout=box_layout) domain_box = VBox([label_domain, x_row, y_row], layout=box_layout) self.tab = VBox([ domain_box, # label_blankline, HBox([self.tmax, Label('min')]), self.omp_threads, svg_mat_output_row, # HBox([self.substrate[3], self.diffusion_coef[3], self.decay_rate[3] ]), ]) # output_dir, toggle_2D_seed_
def __init__(self, df: pd.DataFrame, box_col: str = 'box', img_col: str = 'image', text_cols: Union[str, List[str]] = None, text_fmts: Union[Callable, List[Callable]] = None, style_col: str = None): """ :param pd.DataFrame df: `DataFrame` with images and boxes :param str box_col: column in the dataframe that contains boxes :param str img_col: column in the dataframe that contains image paths :param Union[str, List[str]] text_cols: (optional) the column(s) in the dataframe to use for creating the text that is shown on top of a box. When multiple columns are give, the text will be created by a comma-separated list of the contents of the given columns. :param Unions[Callable, List[Callable]] text_fmts: (optional) a callable, or list of callables, that takes the corresponding value from the `text_cols` column(s) as an input and returns the string to print for that value. :param str style_col: the column containing a dict of style attributes. Available attributes are: - `stroke_width`: the stroke width of a box (default 2) - `stroke_color`: the stroke color of a box (default 'red') - `fill_color`: the fill color of a box (default '#00000000') - `hover_fill`: the fill color of a box when it is hovered on (default '#00000088') - `hover_stroke`: the stroke color of a box when it is hovered on (default 'blue') - `active_fill`: the fill color of a box when it is clicked on (default '#ffffff22') - `active_stroke`: the stroke color of a box when it is clicked on (default 'green') - `font_family`: the font family to use for box text (default 'arial'). NOTE: exported text will always be Arial. - `font_size`: the font size in points (default 10) """ if text_cols is None: text_cols = [] if isinstance(text_cols, str): text_cols = [text_cols] if text_fmts is None: text_fmts = [None] * len(text_cols) if isinstance(text_fmts, Callable): text_fmts = [text_fmts] self.text_cols = text_cols self.text_fmts = text_fmts df2 = df.copy() def row2text(row): txts = row[text_cols] return ', '.join([ fmt(txt) if fmt is not None else str(txt) for txt, fmt in zip(txts, self.text_fmts) ]) if style_col is None: style_col = '_dfim_style' df2[style_col] = [DEFAULT_STYLE] * len(df2) else: df2[style_col] = df2[style_col].apply(lambda s: { k: s[k] if k in s else DEFAULT_STYLE[k] for k in DEFAULT_STYLE }) df2['box_text'] = df2.apply(lambda row: row2text(row), axis=1) df2['box_dict'] = df2.apply( lambda row: dict(index=row.name, box=row[box_col], text=row['box_text'], style=row[style_col]) if (box_col in row.index and row[box_col] is not None) else None, axis=1) self.df_img = df2.groupby(img_col).agg(list).reset_index() self.df = df self.img_col = img_col self.box_col = box_col # SELECTION widget self.idx_wgt = BoundedIntText(value=0, min=0, max=len(self.df_img) - 1, step=1, description='Choose index', disabled=False) self.drop_wgt = Dropdown(options=self.df_img[img_col], description='or image', value=None, disabled=False) self.drop_wgt.observe(self.drop_changed, names='value') self.idx_wgt.observe(self.idx_changed, names='value') self.imsel_wgt = VBox([self.idx_wgt, self.drop_wgt]) self.imsel_wgt.layout = Layout(margin='auto') # IMAGE PANE self.img_title = HTML(placeholder='(Image path)') self.img_title.layout = Layout(margin='auto') self.imbox_wgt = ImBoxWidget() self.imbox_wgt.layout = Layout(margin='1em auto') self.imbox_wgt.observe(self.box_changed, names='active_box') self.imbox_wgt.observe(self.img_changed, names='img') # DETAILS PANE self.crop_wgt = CropBoxWidget() self.crop_wgt.layout = Layout(margin='0 1em') self.detail_wgt = DetailsWidget() self.detail_wgt.layout = Layout(margin='auto') self.detail_pane = HBox([self.crop_wgt, self.detail_wgt]) self.detail_pane.layout = Layout(margin='1em auto') # PLAY widget self.play_btns = Play(interval=100, value=0, min=0, max=len(self.df_img) - 1, step=1, description="Play", disabled=False) self.play_slider = widgets.IntSlider(value=0, min=0, max=len(self.df_img) - 1, step=1) widgets.jslink((self.play_btns, 'value'), (self.idx_wgt, 'value')) widgets.jslink((self.play_btns, 'value'), (self.play_slider, 'value')) self.play_wgt = widgets.HBox([self.play_btns, self.play_slider]) self.play_wgt.layout = Layout(margin='auto') # IMAGE EXPORT widget self.imexp_dest = Text(description='Output file', value='output/output.png') self.imexp_btn = Button(description='Export') self.imexp_btn.on_click(self.export_img) self.imexp_wgt = HBox([self.imexp_dest, self.imexp_btn]) # VIDEO EXPORT widget self.videxp_dest = Text(description='Output file', value='output/output.mp4') self.videxp_start = BoundedIntText(value=0, min=0, max=len(self.df_img) - 1, step=1, description='From index', disabled=False) self.videxp_start.observe(self.vididx_changed, names='value') self.videxp_end = BoundedIntText(value=0, min=0, max=len(self.df_img) - 1, step=1, description='Until index', disabled=False) self.videxp_end.observe(self.vididx_changed, names='value') self.videxp_fps = FloatText(value=30, description='FPS') self.videxp_btn = Button(description='Export') self.videxp_btn.on_click(self.export_vid) self.videxp_wgt = VBox([ HBox([self.videxp_start, self.videxp_end]), HBox([self.videxp_dest, self.videxp_fps]), self.videxp_btn ]) self.exp_wgt = Tab(children=[self.imexp_wgt, self.videxp_wgt]) self.exp_wgt.set_title(0, 'Export image') self.exp_wgt.set_title(1, 'Export video') self.exp_wgt.layout = Layout(margin='0 1em') super().__init__([ self.imsel_wgt, VBox([ self.img_title, self.imbox_wgt, self.play_wgt, self.detail_pane ]), self.exp_wgt ]) self.idx_changed({'new': 0})
class SVGTab(object): # myplot = None def __init__(self): tab_height = '520px' tab_layout = Layout( width='800px', # border='2px solid black', height=tab_height, overflow_y='scroll') self.output_dir = '.' max_frames = 505 # first time + 30240 / 60 self.svg_plot = interactive(self.plot_svg, frame=(0, max_frames), continuous_update=False) svg_plot_size = '500px' self.svg_plot.layout.width = svg_plot_size self.svg_plot.layout.height = svg_plot_size self.use_defaults = True self.show_nucleus = 0 # 0->False, 1->True in Checkbox! self.show_edge = 1 # 0->False, 1->True in Checkbox! self.scale_radius = 1.0 self.axes_min = 0.0 self.axes_max = 2000 # hmm, this can change (TODO?) # self.tab = HBox([svg_plot], layout=tab_layout) self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='Max', layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) self.show_nucleus_checkbox = Checkbox( description='nucleus', value=False, disabled=False, layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.show_nucleus_checkbox.observe(self.show_nucleus_cb) self.show_edge_checkbox = Checkbox( description='edge', value=True, disabled=False, layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.show_edge_checkbox.observe(self.show_edge_cb) # row1 = HBox([Label('(select slider: drag or left/right arrows)'), # self.max_frames, VBox([self.show_nucleus_checkbox, self.show_edge_checkbox])]) # self.max_frames, self.show_nucleus_checkbox], layout=Layout(width='500px')) # self.tab = VBox([row1,self.svg_plot], layout=tab_layout) items_auto = [ Label('(select slider: drag or left/right arrows)'), self.max_frames, self.show_nucleus_checkbox, self.show_edge_checkbox, ] #row1 = HBox([Label('(select slider: drag or left/right arrows)'), # max_frames, show_nucleus_checkbox, show_edge_checkbox], # layout=Layout(width='800px')) box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='90%') row1 = Box(children=items_auto, layout=box_layout) self.tab = VBox([row1, self.svg_plot], layout=tab_layout) # self.output_dir_str = os.getenv('RESULTSDIR') + "/pc4nanobio/" def show_nucleus_cb(self, b): global current_frame if (self.show_nucleus_checkbox.value): self.show_nucleus = 1 else: self.show_nucleus = 0 # self.plot_svg(self,current_frame) self.svg_plot.update() def show_edge_cb(self, b): if (self.show_edge_checkbox.value): self.show_edge = 1 else: self.show_edge = 0 self.svg_plot.update() def update_max_frames(self, _b): self.svg_plot.children[0].max = self.max_frames.value def plot_svg(self, frame): # global current_idx, axes_max # print('plot_svg: SVG=', SVG) global current_frame current_frame = frame fname = "snapshot%08d.svg" % frame # fullname = self.output_dir_str + fname # fullname = fname # do this for nanoHUB! (data appears in root dir?) full_fname = os.path.join(self.output_dir, fname) if not os.path.isfile(full_fname): # print("File does not exist: ", fname) # print("File does not exist: ", full_fname) print("No: ", full_fname) return xlist = deque() ylist = deque() rlist = deque() rgb_list = deque() # print('\n---- ' + fname + ':') # tree = ET.parse(fname) tree = ET.parse(full_fname) root = tree.getroot() # print('--- root.tag ---') # print(root.tag) # print('--- root.attrib ---') # print(root.attrib) # print('--- child.tag, child.attrib ---') numChildren = 0 for child in root: # print(child.tag, child.attrib) # print("keys=",child.attrib.keys()) if self.use_defaults and ('width' in child.attrib.keys()): self.axes_max = float(child.attrib['width']) # print("debug> found width --> axes_max =", axes_max) if child.text and "Current time" in child.text: svals = child.text.split() # title_str = "(" + str(current_idx) + ") Current time: " + svals[2] + "d, " + svals[4] + "h, " + svals[7] + "m" # title_str = "Current time: " + svals[2] + "d, " + svals[4] + "h, " + svals[7] + "m" title_str = svals[2] + "d, " + svals[4] + "h, " + svals[7] + "m" # print("width ",child.attrib['width']) # print('attrib=',child.attrib) # if (child.attrib['id'] == 'tissue'): if ('id' in child.attrib.keys()): # print('-------- found tissue!!') tissue_parent = child break # print('------ search tissue') cells_parent = None for child in tissue_parent: # print('attrib=',child.attrib) if (child.attrib['id'] == 'cells'): # print('-------- found cells, setting cells_parent') cells_parent = child break numChildren += 1 num_cells = 0 # print('------ search cells') for child in cells_parent: # print(child.tag, child.attrib) # print('attrib=',child.attrib) for circle in child: # two circles in each child: outer + nucleus # circle.attrib={'cx': '1085.59','cy': '1225.24','fill': 'rgb(159,159,96)','r': '6.67717','stroke': 'rgb(159,159,96)','stroke-width': '0.5'} # print(' --- cx,cy=',circle.attrib['cx'],circle.attrib['cy']) xval = float(circle.attrib['cx']) s = circle.attrib['fill'] # print("s=",s) # print("type(s)=",type(s)) if (s[0:3] == "rgb" ): # if an rgb string, e.g. "rgb(175,175,80)" rgb = list(map(int, s[4:-1].split(","))) rgb[:] = [x / 255. for x in rgb] else: # otherwise, must be a color name rgb_tuple = mplc.to_rgb(mplc.cnames[s]) # a tuple rgb = [x for x in rgb_tuple] # test for bogus x,y locations (rwh TODO: use max of domain?) too_large_val = 10000. if (np.fabs(xval) > too_large_val): print("bogus xval=", xval) break yval = float(circle.attrib['cy']) if (np.fabs(yval) > too_large_val): print("bogus xval=", xval) break rval = float(circle.attrib['r']) # if (rgb[0] > rgb[1]): # print(num_cells,rgb, rval) xlist.append(xval) ylist.append(yval) rlist.append(rval) rgb_list.append(rgb) # For .svg files with cells that *have* a nucleus, there will be a 2nd if (self.show_nucleus == 0): #if (not self.show_nucleus): break num_cells += 1 # if num_cells > 3: # for debugging # print(fname,': num_cells= ',num_cells," --- debug exit.") # sys.exit(1) # break # print(fname,': num_cells= ',num_cells) xvals = np.array(xlist) yvals = np.array(ylist) rvals = np.array(rlist) rgbs = np.array(rgb_list) # print("xvals[0:5]=",xvals[0:5]) # print("rvals[0:5]=",rvals[0:5]) # print("rvals.min, max=",rvals.min(),rvals.max()) # rwh - is this where I change size of render window?? (YES - yipeee!) # plt.figure(figsize=(6, 6)) # plt.cla() title_str += " (" + str(num_cells) + " agents)" # plt.title(title_str) # plt.xlim(axes_min,axes_max) # plt.ylim(axes_min,axes_max) # plt.scatter(xvals,yvals, s=rvals*scale_radius, c=rgbs) fig = plt.figure(figsize=(6, 6)) # axx = plt.axes([0, 0.05, 0.9, 0.9]) # left, bottom, width, height # axx = fig.gca() # print('fig.dpi=',fig.dpi) # = 72 # im = ax.imshow(f.reshape(100,100), interpolation='nearest', cmap=cmap, extent=[0,20, 0,20]) # ax.xlim(axes_min,axes_max) # ax.ylim(axes_min,axes_max) # convert radii to radii in pixels ax2 = fig.gca() N = len(xvals) rr_pix = (ax2.transData.transform(np.vstack([rvals, rvals]).T) - ax2.transData.transform( np.vstack([np.zeros(N), np.zeros(N)]).T)) rpix, _ = rr_pix.T markers_size = (144. * rpix / fig.dpi)**2 # = (2*rpix / fig.dpi * 72)**2 # markers_size = (2*rpix / fig.dpi * 72)**2 markers_size = markers_size / 4000000. # print('max=',markers_size.max()) # ax.scatter(xvals,yvals, s=rvals*self.scale_radius, c=rgbs) # axx.scatter(xvals,yvals, s=markers_size, c=rgbs) if (self.show_edge): plt.scatter(xvals, yvals, s=markers_size, c=rgbs, edgecolor='black', linewidth='0.5') else: plt.scatter(xvals, yvals, s=markers_size, c=rgbs) plt.xlim(self.axes_min, self.axes_max) plt.ylim(self.axes_min, self.axes_max) # ax.grid(False) # axx.set_title(title_str) plt.title(title_str)
class SVGTab(object): # myplot = None def __init__(self): tab_height = '520px' tab_height = '550px' tab_layout = Layout( width='900px', # border='2px solid black', height=tab_height) #, overflow_y='scroll') self.output_dir = '.' # self.output_dir = 'tmpdir' max_frames = 1 self.svg_plot = interactive(self.plot_svg, frame=(0, max_frames), continuous_update=False) svg_plot_size = '500px' self.svg_plot.layout.width = svg_plot_size self.svg_plot.layout.height = svg_plot_size self.use_defaults = True self.show_nucleus = 0 # 0->False, 1->True in Checkbox! self.show_edge = 1 # 0->False, 1->True in Checkbox! self.scale_radius = 1.0 self.axes_min = 0.0 self.axes_max = 2000 # hmm, this can change (TODO?) # self.fig = plt.figure(figsize=(6, 6)) # self.tab = HBox([svg_plot], layout=tab_layout) self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='Max', # layout=Layout(flex='0 1 auto', width='auto'), #Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) self.show_nucleus_checkbox = Checkbox( description='nucleus', value=False, disabled=False, # layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.show_nucleus_checkbox.observe(self.show_nucleus_cb) self.show_edge_checkbox = Checkbox( description='edge', value=True, disabled=False, # layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.show_edge_checkbox.observe(self.show_edge_cb) # row1 = HBox([Label('(select slider: drag or left/right arrows)'), # self.max_frames, VBox([self.show_nucleus_checkbox, self.show_edge_checkbox])]) # self.max_frames, self.show_nucleus_checkbox], layout=Layout(width='500px')) # self.tab = VBox([row1,self.svg_plot], layout=tab_layout) self.help_label = Label('select slider: drag or left/right arrows', layout=Layout(flex='0 1 auto', width='auto')) # layout=Layout(flex='3 1 auto', width='auto')) items_auto = [ self.help_label, self.max_frames, self.show_nucleus_checkbox, self.show_edge_checkbox, ] #row1 = HBox([Label('(select slider: drag or left/right arrows)'), # max_frames, show_nucleus_checkbox, show_edge_checkbox], # layout=Layout(width='800px')) box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='90%') # row1 = Box(children=items_auto, layout=box_layout) #row1 = Box(children=items_auto) row1 = Box([ self.help_label, Box([ self.max_frames, self.show_nucleus_checkbox, self.show_edge_checkbox ], layout=Layout(border='0px solid black', width='60%', height='', align_items='stretch', flex_direction='row', display='flex')) ]) # self.download_button = Download('svg.zip', style='warning', icon='cloud-download', tooltip='Download results', cb=self.download_cb) #self.download_button = Download('svg.zip', style='warning', icon='cloud-download', tooltip='Download results') # self.tab = VBox([row1, self.svg_plot], layout=tab_layout) # self.tab = VBox([row1, self.svg_plot, self.download_button.w], layout=tab_layout) self.tab = VBox([row1, self.svg_plot], layout=tab_layout) # self.output_dir_str = os.getenv('RESULTSDIR') + "/pc4nanobio/" def update_max_frames_expected( self, value): # called when beginning an interactive Run with debug_view: print("update_max_frames_expected: SVG UPDATE", rdir) self.max_frames.value = value # assumes naming scheme: "snapshot%08d.svg" self.svg_plot.children[0].max = self.max_frames.value # self.svg_plot.update() def update(self, rdir): with debug_view: print("svg.py: update(): rdir (->self.output_dir)=", rdir) self.output_dir = rdir if rdir == '': # self.max_frames.value = 0 tmpdir = os.path.abspath('tmpdir') # with debug_view: # print("svg.py: update(): tmpdir=", tmpdir) self.output_dir = tmpdir all_files = sorted(glob.glob(os.path.join(tmpdir, 'snapshot*.svg'))) # with debug_view: # print("svg.py: update(): len(all_files)=", len(all_files)) if len(all_files) > 0: last_file = all_files[-1] self.max_frames.value = int( last_file[-12:-4] ) # assumes naming scheme: "snapshot%08d.svg" self.svg_plot.update() return all_files = sorted(glob.glob(os.path.join(rdir, 'snapshot*.svg'))) with debug_view: print("svg.py: update(): rdir != blank; len(all_files)=", len(all_files)) if len(all_files) > 0: last_file = all_files[-1] self.max_frames.value = int( last_file[-12:-4]) # assumes naming scheme: "snapshot%08d.svg" self.svg_plot.update() def download_cb(self): file_str = os.path.join(self.output_dir, '*.svg') # print('zip up all ',file_str) with zipfile.ZipFile('svg.zip', 'w') as myzip: for f in glob.glob(file_str): myzip.write(f, os.path.basename( f)) # 2nd arg avoids full filename path in the archive def show_nucleus_cb(self, b): global current_frame if (self.show_nucleus_checkbox.value): self.show_nucleus = 1 else: self.show_nucleus = 0 # self.plot_svg(self,current_frame) self.svg_plot.update() def show_edge_cb(self, b): if (self.show_edge_checkbox.value): self.show_edge = 1 else: self.show_edge = 0 self.svg_plot.update() def update_max_frames(self, _b): self.svg_plot.children[0].max = self.max_frames.value def plot_svg(self, frame): # global current_idx, axes_max global current_frame current_frame = frame fname = "snapshot%08d.svg" % frame # fullname = self.output_dir_str + fname # fullname = fname # do this for nanoHUB! (data appears in root dir?) full_fname = os.path.join(self.output_dir, fname) if not os.path.isfile(full_fname): # print("File does not exist: ", fname) # print("File does not exist: ", full_fname) #print("No: ", full_fname) print("Missing output file") # No: snapshot00000000.svg return xlist = deque() ylist = deque() rlist = deque() rgb_list = deque() # print('\n---- ' + fname + ':') # tree = ET.parse(fname) tree = ET.parse(full_fname) root = tree.getroot() # print('--- root.tag ---') # print(root.tag) # print('--- root.attrib ---') # print(root.attrib) # print('--- child.tag, child.attrib ---') numChildren = 0 for child in root: # print(child.tag, child.attrib) # print("keys=",child.attrib.keys()) if self.use_defaults and ('width' in child.attrib.keys()): self.axes_max = float(child.attrib['width']) # print("debug> found width --> axes_max =", axes_max) if child.text and "Current time" in child.text: svals = child.text.split() # title_str = "(" + str(current_idx) + ") Current time: " + svals[2] + "d, " + svals[4] + "h, " + svals[7] + "m" # title_str = "Current time: " + svals[2] + "d, " + svals[4] + "h, " + svals[7] + "m" # title_str = svals[2] + "d, " + svals[4] + "h, " + svals[7] + "m" # mins= round(int(float(xml_root.find(".//current_time").text))) # TODO: check units = mins mins = round(int(float(svals[7]))) # TODO: check units = mins hrs = int(mins / 60) days = int(hrs / 24) title_str = '%dd, %dh, %dm' % (int(days), (hrs % 24), mins - (hrs * 60)) # print("width ",child.attrib['width']) # print('attrib=',child.attrib) # if (child.attrib['id'] == 'tissue'): if ('id' in child.attrib.keys()): # print('-------- found tissue!!') tissue_parent = child break # print('------ search tissue') cells_parent = None for child in tissue_parent: # print('attrib=',child.attrib) if (child.attrib['id'] == 'cells'): # print('-------- found cells, setting cells_parent') cells_parent = child break numChildren += 1 num_cells = 0 # print('------ search cells') for child in cells_parent: # print(child.tag, child.attrib) # print('attrib=',child.attrib) for circle in child: # two circles in each child: outer + nucleus # circle.attrib={'cx': '1085.59','cy': '1225.24','fill': 'rgb(159,159,96)','r': '6.67717','stroke': 'rgb(159,159,96)','stroke-width': '0.5'} # print(' --- cx,cy=',circle.attrib['cx'],circle.attrib['cy']) xval = float(circle.attrib['cx']) s = circle.attrib['fill'] # print("s=",s) # print("type(s)=",type(s)) if (s[0:3] == "rgb" ): # if an rgb string, e.g. "rgb(175,175,80)" rgb = list(map(int, s[4:-1].split(","))) rgb[:] = [x / 255. for x in rgb] else: # otherwise, must be a color name rgb_tuple = mplc.to_rgb(mplc.cnames[s]) # a tuple rgb = [x for x in rgb_tuple] # test for bogus x,y locations (rwh TODO: use max of domain?) too_large_val = 10000. if (np.fabs(xval) > too_large_val): print("bogus xval=", xval) break yval = float(circle.attrib['cy']) if (np.fabs(yval) > too_large_val): print("bogus xval=", xval) break rval = float(circle.attrib['r']) # if (rgb[0] > rgb[1]): # print(num_cells,rgb, rval) xlist.append(xval) ylist.append(yval) rlist.append(rval) rgb_list.append(rgb) # For .svg files with cells that *have* a nucleus, there will be a 2nd if (self.show_nucleus == 0): #if (not self.show_nucleus): break num_cells += 1 # if num_cells > 3: # for debugging # print(fname,': num_cells= ',num_cells," --- debug exit.") # sys.exit(1) # break # print(fname,': num_cells= ',num_cells) xvals = np.array(xlist) yvals = np.array(ylist) rvals = np.array(rlist) rgbs = np.array(rgb_list) # print("xvals[0:5]=",xvals[0:5]) # print("rvals[0:5]=",rvals[0:5]) # print("rvals.min, max=",rvals.min(),rvals.max()) # rwh - is this where I change size of render window?? (YES - yipeee!) # plt.figure(figsize=(6, 6)) # plt.cla() title_str += " (" + str(num_cells) + " agents)" # plt.title(title_str) # plt.xlim(axes_min,axes_max) # plt.ylim(axes_min,axes_max) # plt.scatter(xvals,yvals, s=rvals*scale_radius, c=rgbs) # plt.axes().set_aspect('equal', 'datalim') self.fig = plt.figure(figsize=(6, 6)) #rwh: move to __init__ # plt.figure(figsize=(7, 7)) # axx = plt.axes([0, 0.05, 0.9, 0.9]) # left, bottom, width, height # axx = fig.gca() # print('fig.dpi=',fig.dpi) # = 72 # im = ax.imshow(f.reshape(100,100), interpolation='nearest', cmap=cmap, extent=[0,20, 0,20]) # ax.xlim(axes_min,axes_max) # ax.ylim(axes_min,axes_max) # convert radii to radii in pixels # ax2 = fig.gca() ax2 = self.fig.gca() N = len(xvals) rr_pix = (ax2.transData.transform(np.vstack([rvals, rvals]).T) - ax2.transData.transform( np.vstack([np.zeros(N), np.zeros(N)]).T)) rpix, _ = rr_pix.T # markers_size = (144. * rpix / fig.dpi)**2 # = (2*rpix / fig.dpi * 72)**2 markers_size = (144. * rpix / self.fig.dpi)**2 # = (2*rpix / fig.dpi * 72)**2 # markers_size = (2*rpix / fig.dpi * 72)**2 markers_size = markers_size / 4000000. #print('markers_size.max()=',markers_size.max()) # ax.scatter(xvals,yvals, s=rvals*self.scale_radius, c=rgbs) # axx.scatter(xvals,yvals, s=markers_size, c=rgbs) #rwh - temp fix - Ah, error only occurs when "edges" is toggled on if (self.show_edge): plt.scatter(xvals, yvals, s=markers_size, c=rgbs, edgecolor='black', linewidth=0.5) else: plt.scatter(xvals, yvals, s=markers_size, c=rgbs) plt.xlim(self.axes_min, self.axes_max) plt.ylim(self.axes_min, self.axes_max) # ax.grid(False) # axx.set_title(title_str) plt.title(title_str)
def __init__(self): self.output_dir = '.' # self.output_dir = 'tmpdir' self.figsize_width_substrate = 15.0 # allow extra for colormap self.figsize_height_substrate = 12.5 self.figsize_width_svg = 12.0 self.figsize_height_svg = 12.0 # self.fig = plt.figure(figsize=(self.figsize_width_substrate, self.figsize_height_substrate)) # self.fig = plt.figure() self.fig = None # self.fig = plt.figure(figsize=(7.2,6)) # this strange figsize results in a ~square contour plot self.first_time = True self.modulo = 1 self.use_defaults = True self.svg_delta_t = 1 self.substrate_delta_t = 1 self.svg_frame = 1 self.substrate_frame = 1 self.customized_output_freq = False self.therapy_activation_time = 1000000 self.max_svg_frame_pre_therapy = 1000000 self.max_substrate_frame_pre_therapy = 1000000 self.svg_xmin = 0 # Probably don't want to hardwire these if we allow changing the domain size # self.svg_xrange = 2000 # self.xmin = -1000. # self.xmax = 1000. # self.ymin = -1000. # self.ymax = 1000. # self.x_range = 2000. # self.y_range = 2000. self.show_nucleus = False self.show_edge = True # initial value self.field_index = 4 # self.field_index = self.mcds_field.value + 4 # define dummy size of mesh (set in the tool's primary module) self.numx = 0 self.numy = 0 self.title_str = '' tab_height = '600px' tab_height = '500px' constWidth = '180px' constWidth2 = '150px' tab_layout = Layout( width='900px', # border='2px solid black', height=tab_height, ) #overflow_y='scroll') max_frames = 2 # self.mcds_plot = interactive(self.plot_substrate, frame=(0, max_frames), continuous_update=False) # self.i_plot = interactive(self.plot_plots, frame=(0, max_frames), continuous_update=False) # self.i_plot = interactive(self.plot_substrate0, frame=(0, max_frames), continuous_update=False) self.i_plot = interactive(self.plot_substrate, frame=(0, max_frames), continuous_update=False) self.frame_slider = IntSlider( min=0, max=10, step=1, description='Test:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d', ) # self.frame_slider.observe(self.frame_slider_cb) self.frame_slider.observe(self.plot_substrate) # "plot_size" controls the size of the tab height, not the plot (rf. figsize for that) # NOTE: the Substrates Plot tab has an extra row of widgets at the top of it (cf. Cell Plots tab) svg_plot_size = '700px' svg_plot_size = '600px' svg_plot_size = '700px' svg_plot_size = '900px' self.i_plot.layout.width = svg_plot_size self.i_plot.layout.height = svg_plot_size self.fontsize = 20 # description='# cell frames', self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='# frames', layout=Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) # self.field_min_max = {'dummy': [0., 1.]} # NOTE: manually setting these for now (vs. parsing them out of data/initial.xml) self.field_min_max = { 'director signal': [0., 1.], 'cargo signal': [0., 1.] } # hacky I know, but make a dict that's got (key,value) reversed from the dict in the Dropdown below # self.field_dict = {0:'dummy'} self.field_dict = {0: 'director signal', 1: 'cargo signal'} self.mcds_field = Dropdown( options={ 'director signal': 0, 'cargo signal': 1 }, value=0, # description='Field', layout=Layout(width=constWidth)) # print("substrate __init__: self.mcds_field.value=",self.mcds_field.value) # self.mcds_field.observe(self.mcds_field_cb) self.mcds_field.observe(self.mcds_field_changed_cb) # self.field_cmap = Text( # value='viridis', # description='Colormap', # disabled=True, # layout=Layout(width=constWidth), # ) self.field_cmap = Dropdown( options=['viridis', 'jet', 'YlOrRd'], value='YlOrRd', # description='Field', layout=Layout(width=constWidth)) # self.field_cmap.observe(self.plot_substrate) self.field_cmap.observe(self.mcds_field_cb) self.cmap_fixed = Checkbox( description='Fix', disabled=False, # layout=Layout(width=constWidth2), ) self.save_min_max = Button( description='Save', #style={'description_width': 'initial'}, button_style= 'success', # 'success', 'info', 'warning', 'danger' or '' tooltip='Save min/max for this substrate', disabled=True, layout=Layout(width='90px')) def save_min_max_cb(b): # field_name = self.mcds_field.options[] # field_name = next(key for key, value in self.mcds_field.options.items() if value == self.mcds_field.value) field_name = self.field_dict[self.mcds_field.value] # print(field_name) # self.field_min_max = {'oxygen': [0., 30.], 'glucose': [0., 1.], 'H+ ions': [0., 1.], 'ECM': [0., 1.], 'NP1': [0., 1.], 'NP2': [0., 1.]} self.field_min_max[field_name][0] = self.cmap_min.value self.field_min_max[field_name][1] = self.cmap_max.value # print(self.field_min_max) self.save_min_max.on_click(save_min_max_cb) self.cmap_min = FloatText( description='Min', value=0, step=0.1, disabled=True, layout=Layout(width=constWidth2), ) self.cmap_min.observe(self.mcds_field_cb) self.cmap_max = FloatText( description='Max', value=38, step=0.1, disabled=True, layout=Layout(width=constWidth2), ) self.cmap_max.observe(self.mcds_field_cb) def cmap_fixed_cb(b): if (self.cmap_fixed.value): self.cmap_min.disabled = False self.cmap_max.disabled = False self.save_min_max.disabled = False else: self.cmap_min.disabled = True self.cmap_max.disabled = True self.save_min_max.disabled = True # self.mcds_field_cb() self.cmap_fixed.observe(cmap_fixed_cb) field_cmap_row2 = HBox([self.field_cmap, self.cmap_fixed]) # field_cmap_row3 = HBox([self.save_min_max, self.cmap_min, self.cmap_max]) items_auto = [ self.save_min_max, #layout=Layout(flex='3 1 auto', width='auto'), self.cmap_min, self.cmap_max, ] box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='80%') field_cmap_row3 = Box(children=items_auto, layout=box_layout) #--------------------- self.cell_nucleus_toggle = Checkbox( description='nuclei', disabled=False, value=self.show_nucleus, # layout=Layout(width=constWidth2), ) def cell_nucleus_toggle_cb(b): # self.update() if (self.cell_nucleus_toggle.value): self.show_nucleus = True else: self.show_nucleus = False self.i_plot.update() self.cell_nucleus_toggle.observe(cell_nucleus_toggle_cb) #---- self.cell_edges_toggle = Checkbox( description='edges', disabled=False, value=self.show_edge, # layout=Layout(width=constWidth2), ) def cell_edges_toggle_cb(b): # self.update() if (self.cell_edges_toggle.value): self.show_edge = True else: self.show_edge = False self.i_plot.update() self.cell_edges_toggle.observe(cell_edges_toggle_cb) self.cells_toggle = Checkbox( description='Cells', disabled=False, value=True, # layout=Layout(width=constWidth2), ) def cells_toggle_cb(b): # self.update() self.i_plot.update() if (self.cells_toggle.value): self.cell_edges_toggle.disabled = False self.cell_nucleus_toggle.disabled = False else: self.cell_edges_toggle.disabled = True self.cell_nucleus_toggle.disabled = True self.cells_toggle.observe(cells_toggle_cb) #--------------------- self.substrates_toggle = Checkbox( description='Substrates', disabled=False, value=True, # layout=Layout(width=constWidth2), ) def substrates_toggle_cb(b): if (self.substrates_toggle.value): # seems bass-ackwards self.cmap_fixed.disabled = False self.cmap_min.disabled = False self.cmap_max.disabled = False self.mcds_field.disabled = False self.field_cmap.disabled = False else: self.cmap_fixed.disabled = True self.cmap_min.disabled = True self.cmap_max.disabled = True self.mcds_field.disabled = True self.field_cmap.disabled = True self.substrates_toggle.observe(substrates_toggle_cb) self.grid_toggle = Checkbox( description='grid', disabled=False, value=True, # layout=Layout(width=constWidth2), ) def grid_toggle_cb(b): # self.update() self.i_plot.update() self.grid_toggle.observe(grid_toggle_cb) # field_cmap_row3 = Box([self.save_min_max, self.cmap_min, self.cmap_max]) # mcds_tab = widgets.VBox([mcds_dir, mcds_plot, mcds_play], layout=tab_layout) # mcds_params = VBox([self.mcds_field, field_cmap_row2, field_cmap_row3, self.max_frames]) # mcds_dir # mcds_params = VBox([self.mcds_field, field_cmap_row2, field_cmap_row3,]) # mcds_dir # self.tab = HBox([mcds_params, self.mcds_plot], layout=tab_layout) help_label = Label('select slider: drag or left/right arrows') # row1 = Box([help_label, Box( [self.max_frames, self.mcds_field, self.field_cmap], layout=Layout(border='0px solid black', row1a = Box([self.max_frames, self.mcds_field, self.field_cmap], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) row1b = Box([ self.cells_toggle, self.cell_nucleus_toggle, self.cell_edges_toggle ], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) row1 = HBox([row1a, Label('.....'), row1b]) row2a = Box([self.cmap_fixed, self.cmap_min, self.cmap_max], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) # row2b = Box( [self.substrates_toggle, self.grid_toggle], layout=Layout(border='1px solid black', row2b = Box([ self.substrates_toggle, ], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) # row2 = HBox( [row2a, self.substrates_toggle, self.grid_toggle]) row2 = HBox([row2a, Label('.....'), row2b]) row3 = HBox([ self.frame_slider, ]) if (hublib_flag): self.download_button = Download('mcds.zip', style='warning', icon='cloud-download', tooltip='Download data', cb=self.download_cb) self.download_svg_button = Download( 'svg.zip', style='warning', icon='cloud-download', tooltip='You need to allow pop-ups in your browser', cb=self.download_svg_cb) download_row = HBox([ self.download_button.w, self.download_svg_button.w, Label("Download all cell plots (browser must allow pop-ups).") ]) # box_layout = Layout(border='0px solid') # controls_box = VBox([row1, row2]) # ,width='50%', layout=box_layout) controls_box = VBox([row1, row2, row3]) # ,width='50%', layout=box_layout) # self.tab = VBox([controls_box, self.i_plot, download_row]) # graph = GraphWidget() # iplot([{"x": [1, 2, 3], "y": [3, 1, 6]}]) # self.fig = go.FigureWidget(data=go.Bar(y=[2, 3, 1])) # x = np.random.randn(2000) # y = np.random.randn(2000) self.x = np.random.randn(2) self.y = np.random.randn(2) # iplot([go.Histogram2dContour(x=x, y=y, contours=dict(coloring='heatmap')), # self.fig = go.FigureWidget(data=go.Histogram2dContour(x=x, y=y, contours_showlines=False, contours=dict(coloring='heatmap'))) self.fig = go.FigureWidget(data=go.Histogram2dContour( x=self.x, y=self.y, contours=dict(coloring='heatmap'))) # self.fig = go.FigureWidget( data = [ # { # 'type' : 'Histogram2dContour', # 'x' : self.x, # 'y' : self.y, # 'contours' : { # 'coloring': 'heatmap' # } # }, # { # 'type' : 'scatter', # 'x' : self.x, # 'y' : self.y, # 'line' : { # 'color': 'red', # 'width': 3 # } # } # ], layout={}) # self.fig = go.FigureWidget(data=go.Contour(x=x, y=y, contours=dict(coloring='heatmap'))) # x = np.linspace(-10, 10, 400) # y = np.linspace(-5, 5, 400) # x, y = np.meshgrid(x, y) # a = 1 # b = 2 # z = x**2/a**2 - y**2/b**2 # contour = go.Contour( # z=z # ) # contour.contours.type = 'constraint' # contour.contours.value = 8 # data = [contour] # # self.fig = go.Figure(data=data) # self.fig = go.FigureWidget(data=data) # go.Scatter(x=x, y=y, mode='markers', marker=dict(color='white', size=3, opacity=0.3)), show_link=False) self.fig.update_layout( # square figure layout for plotly? autosize=True, margin=dict(l=20, r=20, t=30, b=20), width=800, height=800, # margin=dict( # l=50, # r=50, # b=100, # t=100, # pad=4 # ), # paper_bgcolor="White", # paper_bgcolor="LightSteelBlue", ) self.tab = VBox([controls_box, self.fig, download_row]) # plotly approach # app_layout = AppLayout( # center= self.fig.canvas, # # footer= self.frame_slider, # pane_heights=[0, 6, 1] # ) # self.tab = app_layout # self.tab = VBox([controls_box, self.fig.canvas, download_row]) # self.fig = plt.figure(figsize=(self.figsize_width_substrate, self.figsize_height_substrate)) else: # self.tab = VBox([row1, row2]) self.tab = VBox([row1, row2, self.i_plot])
def build_options(self): grid = GridspecLayout(4, 2) options_map = {} style = {'description_width': '60%', 'width': 'auto'} # num features num_features = BoundedIntText( value=10, min=0, max=999999, step=1, description='Number of features:', style=style, description_tooltip= 'Maximum number of features present in explanation') options_map['num_features'] = num_features # num samples num_samples = BoundedIntText( value=5000, min=0, max=999999, step=1, description='Number of samples:', style=style, description_tooltip= 'Size of the neighborhood to learn the linear model') options_map['num_samples'] = num_samples # kernel_width kernel_width = BoundedFloatText( value=0.75, min=0, max=999999, step=0.05, description='Kernel width:', style=style, description_tooltip= 'Kernel width for the exponential kernel. Actual value used will be ' 'value * sqrt(num_of_cols_in_train_data)') options_map['kernel_width'] = kernel_width # feature_selection feature_selection = Dropdown( description='Feature selection:', style=style, description_tooltip='Feature selection method\n' ' - forward_selection: iteratively add features to the model, ' 'costly when num_features is high\n' ' - highest_weights: selects the features that have the highest' 'product of absolute weight * original data point when learning with all the features\n' ' - lasso_path: chooses features based on the lasso regularization path\n' ' - none: use all features, ignore Number of features option\n' ' - auto: use forward_selection if num_features <= 6, and highest_weights otherwise', options=[ 'forward_selection', 'highest_weights', 'lasso_path', 'none', 'auto' ], value='auto') options_map['feature_selection'] = feature_selection # discretize_continuous discretize_continuous = Checkbox( description='Discretize continuous', # style=style, value=True, title= 'Whether to discretize all non-categorical features' # This doesn't work... # I don't know how to get a tooltip to checkbox ) options_map['discretize_continuous'] = discretize_continuous # discretizer discretizer = Dropdown( description='Discretizer:', style=style, options=[ 'quartile', 'decile' ], # not supporting entropy, because we don't have training labels :/ value='quartile', description_tooltip= 'Which discretizer to use. Only matters if discretize continuous is True' ) options_map['discretizer'] = discretizer # set up disabling of discretizer dropdown if discretize_continuous is not checked def disable_discretizer(change): discretizer.disabled = not change['new'] discretize_continuous.observe(disable_discretizer, names=['value']) # distance_metric distance_metric = Text( description='Distance metric:', style=style, value='euclidean', description_tooltip= 'What distance metric to use (for calculating weights). ' 'Used as an "distance_metric" argument for sklearn.metrics.pairwise_distances' ) options_map['distance_metric'] = distance_metric # model_regressor model_regressor = UpdatingCombobox( options_keys=self.globals_options, description='Variable with model regressor:', style=style, value='None', description_tooltip= 'sklearn regressor to use in explanation. Defaults to Ridge regression if None. ' 'Must have model_regressor.coef_ and "sample_weight" as a parameter ' 'to model_regressor.fit()\n\n' '(specify the name of the variable with regressor that you have in the notebook)' ) model_regressor.lookup_in_kernel = True options_map['model_regressor'] = model_regressor grid[0, 0] = num_features grid[0, 1] = num_samples grid[1, 0] = kernel_width grid[1, 1] = feature_selection grid[2, 0] = discretize_continuous grid[2, 1] = discretizer grid[3, 0] = distance_metric grid[3, 1] = model_regressor return options_map, grid
def _create_input_widgets(self): self._input["smiles"] = Text(description="SMILES", continuous_update=False) self._input["smiles"].observe(self._show_mol, names="value") display(self._input["smiles"]) self._output["smiles"] = Output(layout={ "border": "1px solid silver", "width": "50%", "height": "180px" }) display(self._output["smiles"]) self._input["stocks"] = [ Checkbox(value=True, description=key, layout={"justify": "left"}) for key in self.finder.stock.items ] box_stocks = VBox( [Label("Stocks")] + self._input["stocks"], layout={"border": "1px solid silver"}, ) self._input["policy"] = widgets.Dropdown( options=self.finder.expansion_policy.items, description="Expansion Policy:", style={"description_width": "initial"}, ) self._input["filter"] = widgets.Dropdown( options=["None"] + self.finder.filter_policy.items, description="Filter Policy:", style={"description_width": "initial"}, ) max_time_box = self._make_slider_input("time_limit", "Time (min)", 1, 120) self._input["time_limit"].value = self.finder.config.time_limit / 60 max_iter_box = self._make_slider_input("iteration_limit", "Max Iterations", 100, 2000) self._input[ "iteration_limit"].value = self.finder.config.iteration_limit self._input["return_first"] = widgets.Checkbox( value=self.finder.config.return_first, description="Return first solved route", ) vbox = VBox([ self._input["policy"], self._input["filter"], max_time_box, max_iter_box, self._input["return_first"], ]) box_options = HBox([box_stocks, vbox]) self._input["C"] = FloatText(description="C", value=self.finder.config.C) self._input["max_transforms"] = BoundedIntText( description="Max steps for substrates", min=1, max=6, value=self.finder.config.max_transforms, style={"description_width": "initial"}, ) self._input["cutoff_cumulative"] = BoundedFloatText( description="Policy cutoff cumulative", min=0, max=1, value=self.finder.config.cutoff_cumulative, style={"description_width": "initial"}, ) self._input["cutoff_number"] = BoundedIntText( description="Policy cutoff number", min=1, max=1000, value=self.finder.config.cutoff_number, style={"description_width": "initial"}, ) self._input["filter_cutoff"] = BoundedFloatText( description="Filter cutoff", min=0, max=1, value=self.finder.config.filter_cutoff, style={"description_width": "initial"}, ) self._input["exclude_target_from_stock"] = widgets.Checkbox( value=self.finder.config.exclude_target_from_stock, description="Exclude target from stock", ) box_advanced = VBox([ self._input["C"], self._input["max_transforms"], self._input["cutoff_cumulative"], self._input["cutoff_number"], self._input["filter_cutoff"], self._input["exclude_target_from_stock"], ]) children = [box_options, box_advanced] tab = widgets.Tab() tab.children = children tab.set_title(0, "Options") tab.set_title(1, "Advanced") display(tab)
def __init__(self, task_type, observations, output_path, name, classes, show_name=True, show_axis=False, fig_size=(10, 10), buttons_vertical=False, custom_display_function=None, is_image=True): if task_type not in self.supported_types: raise Exception(labels_str.warn_task_not_supported) if len(observations) == 0: raise Exception(labels_str.warn_no_images) num_classes = len(classes) if num_classes <= 1: raise Exception(labels_str.warn_little_classes) elif len( classes ) > 2 and task_type.value == TaskType.CLASSIFICATION_BINARY.value: raise Exception(labels_str.warn_binary_only_two) self.is_image = is_image self.key = "path" if self.is_image else "observation" if not self.is_image and custom_display_function is None: raise Exception(labels_str.warn_display_function_needed) self.task_type = task_type self.show_axis = show_axis self.name = name self.show_name = show_name self.output_path = output_path self.file_path = os.path.join(self.output_path, self.name + ".json") print(labels_str.info_ds_output + self.file_path) self.mapping, self.dataset = self.__create_results_dict( self.file_path, classes) self.classes = list(self.mapping["categories_id"].values()) if len( self.classes ) > 2 and task_type.value == TaskType.CLASSIFICATION_BINARY.value: raise Exception(labels_str.warn_binary_only_two + " ".join(self.classes)) self.observations = observations self.max_pos = len(self.observations) - 1 self.pos = 0 self.fig_size = fig_size self.buttons_vertical = buttons_vertical if custom_display_function is None: self.image_display_function = self.__show_image else: self.image_display_function = custom_display_function self.previous_button = self.__create_button(labels_str.str_btn_prev, (self.pos == 0), self.__on_previous_clicked) self.next_button = self.__create_button(labels_str.str_btn_next, (self.pos == self.max_pos), self.__on_next_clicked) self.save_button = self.__create_button(labels_str.str_btn_download, False, self.__on_save_clicked) self.save_function = self.__save_function # save_function buttons = [self.previous_button, self.next_button, self.save_button] label_total = Label(value='/ {}'.format(len(self.observations))) self.text_index = BoundedIntText(value=1, min=1, max=len(self.observations)) self.text_index.layout.width = '80px' self.text_index.layout.height = '35px' self.text_index.observe(self.__selected_index) self.out = Output() self.out.add_class(name) if self.__is_multilabel(): self.checkboxes = [ Checkbox(False, description='{}'.format(self.classes[i]), indent=False) for i in range(len(self.classes)) ] for cb in self.checkboxes: cb.layout.width = '180px' cb.observe(self.__checkbox_changed) self.checkboxes_layout = VBox( children=[cb for cb in self.checkboxes]) else: self.checkboxes = RadioButtons(options=self.classes, disabled=False, indent=False) self.checkboxes.layout.width = '180px' self.checkboxes.observe(self.__checkbox_changed) self.checkboxes_layout = VBox(children=[self.checkboxes]) output_layout = HBox(children=[self.out, self.checkboxes_layout]) if self.buttons_vertical: self.all_widgets = HBox(children=[ VBox(children=[HBox([self.text_index, label_total])] + buttons), output_layout ]) else: self.all_widgets = VBox(children=[ HBox([self.text_index, label_total]), HBox(children=buttons), output_layout ]) ## loading js library to perform html screenshots j_code = """ require.config({ paths: { html2canvas: "https://html2canvas.hertzen.com/dist/html2canvas.min" } }); """ display(Javascript(j_code))
def __init__(self): self.mp4_zip_file = "cells_mp4.zip" self.mp4_file = "cells.mp4" self.instructions = Label( "After a simulation completes, generate a video of cells (from SVG files). Does not work for cached results yet." ) self.feedback = Label(" ") # self.feedback.value = "Converting all svg to jpg..." self.gen_button = Button( description='Generate video', button_style= 'success', # 'success', 'info', 'warning', 'danger' or '' tooltip='Generate a MP4 video of cells', ) self.gen_button.disabled = True self.gen_button.on_click(self.gen_button_cb) fps_style = {'description_width': '35%'} fps_layout = {'width': '85px'} # tooltip='frames per sec', -- tooltip not available for *Text ! self.fps = BoundedIntText(description="fps=", value=5, min=1, max=30, step=1, style=fps_style, layout=fps_layout) size_style = {'description_width': '50%'} size_layout = {'width': '150px'} self.size = BoundedIntText(description="w,h(pixels)=", value=500, min=250, max=1500, step=10, disabled=False, tooltip='width, height of video', style=size_style, layout=size_layout) self.video = HTML(value="", placeholder='', description='', layout=Layout(visibility='hidden')) if (hublib_flag): self.download_mp4_button = Download( self.mp4_zip_file, style='success', icon='cloud-download', tooltip= 'Download mp4 (you need to allow pop-ups in your browser)') self.download_mp4_button.w.disabled = True self.tab = VBox([ self.instructions, HBox([ self.gen_button, self.fps, self.size, self.feedback, self.download_mp4_button.w ]), self.video ]) else: self.tab = VBox([ self.instructions, HBox([self.gen_button, self.fps, self.size, self.feedback]), self.video ])
class DatasetAnnotatorClassification: supported_types = [ TaskType.CLASSIFICATION_BINARY, TaskType.CLASSIFICATION_SINGLE_LABEL, TaskType.CLASSIFICATION_MULTI_LABEL ] def __init__(self, task_type, observations, output_path, name, classes, show_name=True, show_axis=False, fig_size=(10, 10), buttons_vertical=False, custom_display_function=None, is_image=True): if task_type not in self.supported_types: raise Exception(labels_str.warn_task_not_supported) if len(observations) == 0: raise Exception(labels_str.warn_no_images) num_classes = len(classes) if num_classes <= 1: raise Exception(labels_str.warn_little_classes) elif len( classes ) > 2 and task_type.value == TaskType.CLASSIFICATION_BINARY.value: raise Exception(labels_str.warn_binary_only_two) self.is_image = is_image self.key = "path" if self.is_image else "observation" if not self.is_image and custom_display_function is None: raise Exception(labels_str.warn_display_function_needed) self.task_type = task_type self.show_axis = show_axis self.name = name self.show_name = show_name self.output_path = output_path self.file_path = os.path.join(self.output_path, self.name + ".json") print(labels_str.info_ds_output + self.file_path) self.mapping, self.dataset = self.__create_results_dict( self.file_path, classes) self.classes = list(self.mapping["categories_id"].values()) if len( self.classes ) > 2 and task_type.value == TaskType.CLASSIFICATION_BINARY.value: raise Exception(labels_str.warn_binary_only_two + " ".join(self.classes)) self.observations = observations self.max_pos = len(self.observations) - 1 self.pos = 0 self.fig_size = fig_size self.buttons_vertical = buttons_vertical if custom_display_function is None: self.image_display_function = self.__show_image else: self.image_display_function = custom_display_function self.previous_button = self.__create_button(labels_str.str_btn_prev, (self.pos == 0), self.__on_previous_clicked) self.next_button = self.__create_button(labels_str.str_btn_next, (self.pos == self.max_pos), self.__on_next_clicked) self.save_button = self.__create_button(labels_str.str_btn_download, False, self.__on_save_clicked) self.save_function = self.__save_function # save_function buttons = [self.previous_button, self.next_button, self.save_button] label_total = Label(value='/ {}'.format(len(self.observations))) self.text_index = BoundedIntText(value=1, min=1, max=len(self.observations)) self.text_index.layout.width = '80px' self.text_index.layout.height = '35px' self.text_index.observe(self.__selected_index) self.out = Output() self.out.add_class(name) if self.__is_multilabel(): self.checkboxes = [ Checkbox(False, description='{}'.format(self.classes[i]), indent=False) for i in range(len(self.classes)) ] for cb in self.checkboxes: cb.layout.width = '180px' cb.observe(self.__checkbox_changed) self.checkboxes_layout = VBox( children=[cb for cb in self.checkboxes]) else: self.checkboxes = RadioButtons(options=self.classes, disabled=False, indent=False) self.checkboxes.layout.width = '180px' self.checkboxes.observe(self.__checkbox_changed) self.checkboxes_layout = VBox(children=[self.checkboxes]) output_layout = HBox(children=[self.out, self.checkboxes_layout]) if self.buttons_vertical: self.all_widgets = HBox(children=[ VBox(children=[HBox([self.text_index, label_total])] + buttons), output_layout ]) else: self.all_widgets = VBox(children=[ HBox([self.text_index, label_total]), HBox(children=buttons), output_layout ]) ## loading js library to perform html screenshots j_code = """ require.config({ paths: { html2canvas: "https://html2canvas.hertzen.com/dist/html2canvas.min" } }); """ display(Javascript(j_code)) def __create_results_dict(self, file_path, cc): mapping = { "categories_id": {}, "categories_name": {}, "observations": {} } if not os.path.exists(file_path): dataset = {'categories': [], "observations": []} for index, c in enumerate(cc): category = {"supercategory": c, "name": c, "id": index + 1} dataset["categories"].append(category) else: with open(file_path, 'r') as classification_file: dataset = json.load(classification_file) for index, img in enumerate(dataset['observations']): mapping['observations'][img[self.key]] = index for c in dataset['categories']: mapping['categories_id'][c["id"]] = c["name"] mapping['categories_name'][c["name"]] = c["id"] index_categories = len(dataset['categories']) + 1 for c in cc: if not c in mapping['categories_name'].keys(): mapping['categories_id'][index_categories] = c mapping['categories_name'][c] = index_categories category = { "supercategory": c, "name": c, "id": index_categories } dataset["categories"].append(category) index_categories += 1 return mapping, dataset def __checkbox_changed(self, b): if b['owner'].value is None or b['name'] != 'value': return class_name = b['owner'].description value = b['owner'].value current_index = self.mapping["observations"][self.observations[ self.pos]] if self.__is_multilabel(): class_index = self.mapping["categories_name"][class_name] if not class_index in self.dataset["observations"][current_index][ "categories"] and value: self.dataset["observations"][current_index][ "categories"].append(class_index) if class_index in self.dataset["observations"][current_index][ "categories"] and not value: self.dataset["observations"][current_index][ "categories"].remove(class_index) else: class_index = self.mapping["categories_name"][value] self.dataset["observations"][current_index][ "category"] = class_index if self.pos == self.max_pos: self.save_state() def __is_multilabel(self): return TaskType.CLASSIFICATION_MULTI_LABEL.value == self.task_type.value def __create_button(self, description, disabled, function): button = Button(description=description) button.disabled = disabled button.on_click(function) return button def __show_image(self, image_record): if not 'path' in image_record: print("missing path") if not os.path.exists(image_record['path']): print("Image cannot be load" + image_record['path']) img = Image.open(image_record['path']) if self.show_name: print(os.path.basename(image_record['path'])) plt.figure(figsize=self.fig_size) if not self.show_axis: plt.axis('off') plt.imshow(img) plt.show() def save_state(self): with open(self.file_path, 'w') as output_file: json.dump(self.dataset, output_file, indent=4) def __save_function(self, image_path, index): img_name = os.path.basename(image_path).split('.')[0] j_code = """ require(["html2canvas"], function(html2canvas) { var element = $(".p-Widget.jupyter-widgets-output-area.output_wrapper.$it_name$")[0]; console.log(element); html2canvas(element).then(function (canvas) { var myImage = canvas.toDataURL(); var a = document.createElement("a"); a.href = myImage; a.download = "$img_name$.png"; a.click(); a.remove(); }); }); """ j_code = j_code.replace('$it_name$', self.name) j_code = j_code.replace('$img_name$', img_name) tmp_out = Output() with tmp_out: display(Javascript(j_code)) tmp_out.clear_output() def __perform_action(self): if not self.observations[ self.pos] in self.mapping["observations"].keys(): observation = {self.key: self.observations[self.pos]} if self.is_image: observation["file_name"] = os.path.basename( self.observations[self.pos]) observation["id"] = len(self.mapping["observations"]) + 1 if self.__is_multilabel(): observation["categories"] = [] self.dataset["observations"].append(observation) self.mapping["observations"][observation[self.key]] = len( self.dataset["observations"]) - 1 current_index = self.mapping["observations"][self.observations[ self.pos]] self.next_button.disabled = (self.pos == self.max_pos) self.previous_button.disabled = (self.pos == 0) if self.__is_multilabel(): for cb in self.checkboxes: cb.unobserve(self.__checkbox_changed) if not "categories" in self.dataset["observations"][ current_index]: self.dataset["observations"][current_index][ "categories"] = [] categories = self.dataset["observations"][current_index][ "categories"] cb.value = self.mapping["categories_name"][ cb.description] in categories cb.observe(self.__checkbox_changed) else: self.checkboxes.unobserve(self.__checkbox_changed) obs = self.dataset["observations"][current_index] category = obs["category"] if "category" in obs else None if category: for k in self.mapping["categories_name"]: if self.mapping["categories_name"][k] == category: category = k break self.checkboxes.value = category self.checkboxes.observe(self.__checkbox_changed) with self.out: self.out.clear_output() self.image_display_function( self.dataset["observations"][current_index]) self.text_index.unobserve(self.__selected_index) self.text_index.value = self.pos + 1 self.text_index.observe(self.__selected_index) def __on_previous_clicked(self, b): self.save_state() self.pos -= 1 self.__perform_action() def __on_next_clicked(self, b): self.save_state() self.pos += 1 self.__perform_action() def __on_save_clicked(self, b): self.save_state() self.save_function(self.observations[self.pos], self.pos) def __selected_index(self, t): if t['owner'].value is None or t['name'] != 'value': return self.pos = t['new'] - 1 self.__perform_action() def start_classification(self): if self.max_pos < self.pos: print("No available observation") return display(self.all_widgets) self.__perform_action() def print_statistics(self): counter = dict() for c in self.mapping["categories_id"]: counter[c] = 0 for record in self.dataset["observations"]: if self.__is_multilabel(): if "categories" in record: for c in record["categories"]: counter[c] += 1 elif "category" in record: counter[record["category"]] += 1 table = [] for c in counter: table.append([self.mapping["categories_id"][c], counter[c]]) table = sorted(table, key=lambda x: x[0]) print( tabulate(table, headers=[ labels_str.info_class_name, labels_str.info_ann_images ]))
def __init__(self): # tab_height = '520px' # tab_layout = Layout(width='900px', # border='2px solid black', # height=tab_height, overflow_y='scroll') self.output_dir = '.' constWidth = '180px' # self.fig = plt.figure(figsize=(6, 6)) # self.fig = plt.figure(figsize=(7, 7)) config_file = "data/PhysiCell_settings.xml" self.cell_lines = {} self.cell_lines_by_name = {} self.cell_lines_array = ["All"] if os.path.isfile(config_file): try: tree = ET.parse(config_file) except: print("Cannot parse", config_file, "- check it's XML syntax.") return root = tree.getroot() uep = root.find( './/cell_definitions') # find unique entry point (uep) for child in uep.findall('cell_definition'): self.cell_lines[int(child.attrib["ID"])] = child.attrib["name"] self.cell_lines_by_name[child.attrib["name"]] = int( child.attrib["ID"]) self.cell_lines_array.append(child.attrib["name"]) # print(child.attrib['name']) else: print("config.xml does not exist") max_frames = 0 self.svg_plot = interactive(self.create_area_chart, frame=(0, max_frames), percentage=(0.0, 10.0), total=False, cell_line=self.cell_lines_array, continuous_update=False) plot_size = '500px' # small: controls the size of the tab height, not the plot (rf. figsize for that) plot_size = '700px' # medium plot_size = '750px' # medium self.svg_plot.layout.width = '1000px' self.svg_plot.layout.height = '700px' self.use_defaults = True self.axes_min = 0.0 self.axes_max = 2000 # hmm, this can change (TODO?) self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='Max', layout=Layout(width='160px'), # layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) items_auto = [ Label('select slider: drag or left/right arrows'), self.max_frames, ] box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='70%') row1 = Box(children=items_auto, layout=box_layout) self.tab = VBox([row1, self.svg_plot]) self.count_dict = {} self.file_dict = {}
class PhysiBoSSTab(object): def __init__(self): # tab_height = '520px' # tab_layout = Layout(width='900px', # border='2px solid black', # height=tab_height, overflow_y='scroll') self.output_dir = '.' constWidth = '180px' # self.fig = plt.figure(figsize=(6, 6)) # self.fig = plt.figure(figsize=(7, 7)) config_file = "data/PhysiCell_settings.xml" self.cell_lines = {} self.cell_lines_by_name = {} self.cell_lines_array = ["All"] if os.path.isfile(config_file): try: tree = ET.parse(config_file) except: print("Cannot parse", config_file, "- check it's XML syntax.") return root = tree.getroot() uep = root.find( './/cell_definitions') # find unique entry point (uep) for child in uep.findall('cell_definition'): self.cell_lines[int(child.attrib["ID"])] = child.attrib["name"] self.cell_lines_by_name[child.attrib["name"]] = int( child.attrib["ID"]) self.cell_lines_array.append(child.attrib["name"]) # print(child.attrib['name']) else: print("config.xml does not exist") max_frames = 0 self.svg_plot = interactive(self.create_area_chart, frame=(0, max_frames), percentage=(0.0, 10.0), total=False, cell_line=self.cell_lines_array, continuous_update=False) plot_size = '500px' # small: controls the size of the tab height, not the plot (rf. figsize for that) plot_size = '700px' # medium plot_size = '750px' # medium self.svg_plot.layout.width = '1000px' self.svg_plot.layout.height = '700px' self.use_defaults = True self.axes_min = 0.0 self.axes_max = 2000 # hmm, this can change (TODO?) self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='Max', layout=Layout(width='160px'), # layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) items_auto = [ Label('select slider: drag or left/right arrows'), self.max_frames, ] box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='70%') row1 = Box(children=items_auto, layout=box_layout) self.tab = VBox([row1, self.svg_plot]) self.count_dict = {} self.file_dict = {} def update(self, rdir=''): # with debug_view: # print("SVG: update rdir=", rdir) if rdir: self.output_dir = rdir all_files = sorted( glob.glob(os.path.join(self.output_dir, 'snapshot*.svg'))) if len(all_files) > 0: last_file = all_files[-1] self.max_frames.value = int( last_file[-12:-4]) # assumes naming scheme: "snapshot%08d.svg" # self.create_dict(self.max_frames.value, self.output_dir) # self.state_counter(self.max_frames.value) # with debug_view: # print("SVG: added %s files" % len(all_files)) def update_max_frames(self, _b): self.svg_plot.children[0].max = self.max_frames.value #------------------------- def plot_states(self, frame): # global current_idx, axes_max global current_frame current_frame = frame fname = "snapshot%08d.svg" % frame full_fname = os.path.join(self.output_dir, fname) if not os.path.isfile(full_fname): print("Once output files are generated, click the slider.") return tree = ET.parse(full_fname) root = tree.getroot() numChildren = 0 for child in root: if self.use_defaults and ('width' in child.attrib.keys()): self.axes_max = float(child.attrib['width']) if child.text and "Current time" in child.text: svals = child.text.split() title_str = svals[2] + "d, " + svals[4] + "h, " + svals[7] + "m" title_str += " (" + str(num_cells) + " agents)" self.fig = plt.figure(figsize=(15, 15)) plt.xlim(self.axes_min, self.axes_max) plt.ylim(self.axes_min, self.axes_max) plt.title(title_str) def create_dict(self, number_of_files, folder, cells_indexes): "create a dictionary with the states file in the folder 'output', half of the dict is used to calculate the percentage of the node, the other half is for the states" # if not os.path.isfile("%sstates_00000000.csv" % folder): # return self.file_dict = {} if number_of_files > 0: for i in range(0, number_of_files): nodes_dict = {} states_dict = {} with open('%s//states_%08u.csv' % (folder, i), newline='') as csvfile: states_reader = csv.reader(csvfile, delimiter=',') for row in states_reader: if row[0] != 'ID' and (cells_indexes is None or int( row[0]) in cells_indexes): states_dict[row[0]] = row[1] nodes_dict[row[0]] = row[1].replace("--", "").split() self.file_dict["node_step{0}".format(i)] = nodes_dict self.file_dict["state_step{0}".format(i)] = states_dict # print(self.file_dict) # return file_dict def state_counter(self, number_of_files, percentage): "create a dict with the states of the network, it can be used to print states pie chart" self.count_dict = {} temp_dict = {} max_cell = 0 if number_of_files > 0: for i in range(0, number_of_files): state_list = [] for key in self.file_dict["state_step{0}".format(i)]: state_list.append( self.file_dict["state_step{0}".format(i)][key]) state_counts = Counter(state_list) max_cell = max_cell + sum(state_counts.values()) #fix_count_dict = {} #for key, group in itertools.groupby(state_counts, lambda k: 'others' if (state_counts[k]<(0.01* (len(self.file_dict["state_step%s" %(i)])))) else k): #fix_count_dict[key] = sum([state_counts[k] for k in list(group)]) temp_dict["state_count{0}".format(i)] = state_counts self.count_dict = self.filter_states(max_cell, temp_dict, percentage) # return self.count_dict def create_area_chart(self, frame=None, total=False, percentage=(0.0, 100.0), cell_line="All"): "plot an area chart with the evolution of the network states during the simulation" cells_indexes = None if cell_line != "All": cells_indexes = set() for i in range(0, frame): fname = "output%08d_cells_physicell.mat" % i full_fname = os.path.join(self.output_dir, fname) if not os.path.isfile(full_fname): print("Once output files are generated, click the slider." ) # No: output00000000_microenvironment0.mat return info_dict = {} scipy.io.loadmat(full_fname, info_dict) M = info_dict['cells'][[0, 5], :].astype(int) cell_line_index = self.cell_lines_by_name[cell_line] indexes = np.where(M[1, :] == cell_line_index) cells_indexes = cells_indexes.union(set(M[0, indexes][0])) cells_indexes = list(cells_indexes) if len(cells_indexes) == 0: print("There are no %s cells." % cell_line) return self.create_dict(frame, self.output_dir, cells_indexes) self.state_counter(frame, percentage) state_list = [] all_state = [] a = [] for k in self.count_dict: state_list.append(list(self.count_dict[k].keys())) for l in state_list: for state in l: all_state.append(state) all_state = list(dict.fromkeys(all_state)) for state_count in self.count_dict: b = [] for states in all_state: try: b.append(self.count_dict[state_count][states]) except: b.append(0) a.append(b) a = np.array(a) #print(a) a = np.transpose(a) if not total: percent = a / a.sum(axis=0).astype(float) * 100 else: percent = a x = np.arange(len(self.count_dict)) self.fig = plt.figure(figsize=(10, 5), dpi=200) ax = self.fig.add_subplot(111) ax.stackplot(x, percent, labels=all_state) ax.legend(labels=all_state, loc='upper center', bbox_to_anchor=(0.5, -0.05), shadow=True, ncol=2) # ax.legend(labels=all_state, bbox_to_anchor=(1.05, 1), loc='lower center', borderaxespad=0.) ax.set_title('100 % stacked area chart') if not total: ax.set_ylabel('Percent (%)') else: ax.set_ylabel("Total") ax.margins(0, 0) # Set margins to avoid "whitespace" # plt.show() def filter_states(self, max_cell, all_counts, percentage): """max_cell = 0 all_counts = {} for i in range (0, number_of_files): state_list = [] for key in file_dict["state_step{0}".format(i)]: state_list.append(file_dict["state_step{0}".format(i)][key]) state_counts = Counter(state_list) max_cell = max_cell + sum(state_counts.values()) all_counts[i] = state_counts""" copy_all_counts = copy.deepcopy(all_counts) state_list = [] all_state = [] for k in all_counts: state_list.append(list(all_counts[k].keys())) for l in state_list: for state in l: all_state.append(state) all_state = list(dict.fromkeys(all_state)) banned_list = [] for state in all_state: a = 0 for i in all_counts.keys(): try: a = a + all_counts[i][state] except: a = a + 0 if (a < (percentage / 100) * max_cell): banned_list.append(state) for i in all_counts.keys(): del all_counts[i][state] for i in all_counts.keys(): b = 0 for state in banned_list: try: b = b + copy_all_counts[i][state] except: b = b + 0 all_counts[i]["others"] = b return all_counts
class SubstrateTab(object): def __init__(self): self.output_dir = '.' # self.output_dir = 'tmpdir' # self.fig = plt.figure(figsize=(7.2,6)) # this strange figsize results in a ~square contour plot # initial value self.field_index = 4 # self.field_index = self.mcds_field.value + 4 tab_height = '500px' constWidth = '180px' constWidth2 = '150px' tab_layout = Layout(width='900px', # border='2px solid black', height=tab_height, ) #overflow_y='scroll') max_frames = 1 self.mcds_plot = interactive(self.plot_substrate, frame=(0, max_frames), continuous_update=False) svg_plot_size = '700px' self.mcds_plot.layout.width = svg_plot_size self.mcds_plot.layout.height = svg_plot_size self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='Max', layout=Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) self.field_min_max = {'dummy': [0., 1.]} # hacky I know, but make a dict that's got (key,value) reversed from the dict in the Dropdown below self.field_dict = {0:'dummy'} self.mcds_field = Dropdown( options={'dummy': 0}, value=0, # description='Field', layout=Layout(width=constWidth) ) # print("substrate __init__: self.mcds_field.value=",self.mcds_field.value) # self.mcds_field.observe(self.mcds_field_cb) self.mcds_field.observe(self.mcds_field_changed_cb) # self.field_cmap = Text( # value='viridis', # description='Colormap', # disabled=True, # layout=Layout(width=constWidth), # ) self.field_cmap = Dropdown( options=['viridis', 'jet', 'YlOrRd'], value='viridis', # description='Field', layout=Layout(width=constWidth) ) #self.field_cmap.observe(self.plot_substrate) # self.field_cmap.observe(self.plot_substrate) self.field_cmap.observe(self.mcds_field_cb) self.cmap_fixed = Checkbox( description='Fix', disabled=False, # layout=Layout(width=constWidth2), ) self.save_min_max= Button( description='Save', #style={'description_width': 'initial'}, button_style='success', # 'success', 'info', 'warning', 'danger' or '' tooltip='Save min/max for this substrate', disabled=True, layout=Layout(width='90px') ) def save_min_max_cb(b): # field_name = self.mcds_field.options[] # field_name = next(key for key, value in self.mcds_field.options.items() if value == self.mcds_field.value) field_name = self.field_dict[self.mcds_field.value] # print(field_name) # self.field_min_max = {'oxygen': [0., 30.], 'glucose': [0., 1.], 'H+ ions': [0., 1.], 'ECM': [0., 1.], 'NP1': [0., 1.], 'NP2': [0., 1.]} self.field_min_max[field_name][0] = self.cmap_min.value self.field_min_max[field_name][1] = self.cmap_max.value # print(self.field_min_max) self.save_min_max.on_click(save_min_max_cb) self.cmap_min = FloatText( description='Min', value=0, step = 0.1, disabled=True, layout=Layout(width=constWidth2), ) self.cmap_min.observe(self.mcds_field_cb) self.cmap_max = FloatText( description='Max', value=38, step = 0.1, disabled=True, layout=Layout(width=constWidth2), ) self.cmap_max.observe(self.mcds_field_cb) def cmap_fixed_cb(b): if (self.cmap_fixed.value): self.cmap_min.disabled = False self.cmap_max.disabled = False self.save_min_max.disabled = False else: self.cmap_min.disabled = True self.cmap_max.disabled = True self.save_min_max.disabled = True # self.mcds_field_cb() self.cmap_fixed.observe(cmap_fixed_cb) field_cmap_row2 = HBox([self.field_cmap, self.cmap_fixed]) # field_cmap_row3 = HBox([self.save_min_max, self.cmap_min, self.cmap_max]) items_auto = [ self.save_min_max, #layout=Layout(flex='3 1 auto', width='auto'), self.cmap_min, self.cmap_max, ] box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='80%') field_cmap_row3 = Box(children=items_auto, layout=box_layout) # field_cmap_row3 = Box([self.save_min_max, self.cmap_min, self.cmap_max]) # mcds_tab = widgets.VBox([mcds_dir, mcds_plot, mcds_play], layout=tab_layout) mcds_params = VBox([self.mcds_field, field_cmap_row2, field_cmap_row3, self.max_frames]) # mcds_dir # mcds_params = VBox([self.mcds_field, field_cmap_row2, field_cmap_row3,]) # mcds_dir # self.tab = HBox([mcds_params, self.mcds_plot], layout=tab_layout) # self.tab = HBox([mcds_params, self.mcds_plot]) help_label = Label('select slider: drag or left/right arrows') row1 = Box([help_label, Box( [self.max_frames, self.mcds_field, self.field_cmap], layout=Layout(border='0px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex'))] ) row2 = Box([self.cmap_fixed, self.cmap_min, self.cmap_max], layout=Layout(border='0px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) self.download_button = Download('mcds.zip', style='warning', icon='cloud-download', tooltip='Download data', cb=self.download_cb) download_row = HBox([self.download_button.w, Label("Download all substrate data (browser must allow pop-ups).")]) # self.tab = VBox([row1, row2, self.mcds_plot]) self.tab = VBox([row1, row2, self.mcds_plot, download_row]) #--------------------------------------------------- def update_dropdown_fields(self, data_dir): # print('update_dropdown_fields called --------') self.output_dir = data_dir tree = None try: fname = os.path.join(self.output_dir, "initial.xml") tree = ET.parse(fname) # return except: print("Cannot open ",fname," to get names of substrate fields.") return xml_root = tree.getroot() self.field_min_max = {} self.field_dict = {} dropdown_options = {} uep = xml_root.find('.//variables') comment_str = "" field_idx = 0 if (uep): for elm in uep.findall('variable'): # print("-----> ",elm.attrib['name']) self.field_min_max[elm.attrib['name']] = [0., 1.] self.field_dict[field_idx] = elm.attrib['name'] dropdown_options[elm.attrib['name']] = field_idx field_idx += 1 # constWidth = '180px' # print('options=',dropdown_options) self.mcds_field.value=0 self.mcds_field.options=dropdown_options # self.mcds_field = Dropdown( # # options={'oxygen': 0, 'glucose': 1}, # options=dropdown_options, # value=0, # # description='Field', # layout=Layout(width=constWidth) # ) def update_max_frames_expected(self, value): # called when beginning an interactive Run self.max_frames.value = value # assumes naming scheme: "snapshot%08d.svg" self.mcds_plot.children[0].max = self.max_frames.value # def update(self, rdir): def update(self, rdir=''): # with debug_view: # print("substrates: update rdir=", rdir) if rdir: self.output_dir = rdir all_files = sorted(glob.glob(os.path.join(self.output_dir, 'output*.xml'))) if len(all_files) > 0: last_file = all_files[-1] self.max_frames.value = int(last_file[-12:-4]) # assumes naming scheme: "snapshot%08d.svg" # with debug_view: # print("substrates: added %s files" % len(all_files)) # self.output_dir = rdir # if rdir == '': # # self.max_frames.value = 0 # tmpdir = os.path.abspath('tmpdir') # self.output_dir = tmpdir # all_files = sorted(glob.glob(os.path.join(tmpdir, 'output*.xml'))) # if len(all_files) > 0: # last_file = all_files[-1] # self.max_frames.value = int(last_file[-12:-4]) # assumes naming scheme: "output%08d.xml" # self.mcds_plot.update() # return # all_files = sorted(glob.glob(os.path.join(rdir, 'output*.xml'))) # if len(all_files) > 0: # last_file = all_files[-1] # self.max_frames.value = int(last_file[-12:-4]) # assumes naming scheme: "output%08d.xml" # self.mcds_plot.update() def download_cb(self): file_xml = os.path.join(self.output_dir, '*.xml') file_mat = os.path.join(self.output_dir, '*.mat') # print('zip up all ',file_str) with zipfile.ZipFile('mcds.zip', 'w') as myzip: for f in glob.glob(file_xml): myzip.write(f, os.path.basename(f)) # 2nd arg avoids full filename path in the archive for f in glob.glob(file_mat): myzip.write(f, os.path.basename(f)) def update_max_frames(self,_b): self.mcds_plot.children[0].max = self.max_frames.value def mcds_field_changed_cb(self, b): # print("mcds_field_changed_cb: self.mcds_field.value=",self.mcds_field.value) if (self.mcds_field.value == None): return self.field_index = self.mcds_field.value + 4 field_name = self.field_dict[self.mcds_field.value] # print('mcds_field_cb: '+field_name) self.cmap_min.value = self.field_min_max[field_name][0] self.cmap_max.value = self.field_min_max[field_name][1] self.mcds_plot.update() def mcds_field_cb(self, b): #self.field_index = self.mcds_field.value # self.field_index = self.mcds_field.options.index(self.mcds_field.value) + 4 # self.field_index = self.mcds_field.options[self.mcds_field.value] self.field_index = self.mcds_field.value + 4 # field_name = self.mcds_field.options[self.mcds_field.value] # self.cmap_min.value = self.field_min_max[field_name][0] # oxygen, etc # self.cmap_max.value = self.field_min_max[field_name][1] # oxygen, etc # self.field_index = self.mcds_field.value + 4 # print('field_index=',self.field_index) self.mcds_plot.update() def plot_substrate(self, frame): # global current_idx, axes_max, gFileId, field_index fname = "output%08d_microenvironment0.mat" % frame xml_fname = "output%08d.xml" % frame # fullname = output_dir_str + fname # fullname = fname full_fname = os.path.join(self.output_dir, fname) full_xml_fname = os.path.join(self.output_dir, xml_fname) # self.output_dir = '.' # if not os.path.isfile(fullname): if not os.path.isfile(full_fname): # print("File does not exist: ", full_fname) print("Once output files are generated, click the slider.") # No: output00000000_microenvironment0.mat return # tree = ET.parse(xml_fname) tree = ET.parse(full_xml_fname) xml_root = tree.getroot() mins= round(int(float(xml_root.find(".//current_time").text))) # TODO: check units = mins hrs = int(mins/60) days = int(hrs/24) title_str = '%dd, %dh, %dm' % (int(days),(hrs%24), mins - (hrs*60)) info_dict = {} # scipy.io.loadmat(fullname, info_dict) scipy.io.loadmat(full_fname, info_dict) M = info_dict['multiscale_microenvironment'] # global_field_index = int(mcds_field.value) # print('plot_substrate: field_index =',field_index) f = M[self.field_index, :] # 4=tumor cells field, 5=blood vessel density, 6=growth substrate # plt.clf() # my_plot = plt.imshow(f.reshape(400,400), cmap='jet', extent=[0,20, 0,20]) self.fig = plt.figure(figsize=(7.2,6)) # this strange figsize results in a ~square contour plot # fig.set_tight_layout(True) # ax = plt.axes([0, 0.05, 0.9, 0.9 ]) #left, bottom, width, height # ax = plt.axes([0, 0.0, 1, 1 ]) # cmap = plt.cm.viridis # Blues, YlOrBr, ... # im = ax.imshow(f.reshape(100,100), interpolation='nearest', cmap=cmap, extent=[0,20, 0,20]) # ax.grid(False) N = int(math.sqrt(len(M[0,:]))) grid2D = M[0, :].reshape(N,N) xvec = grid2D[0, :] num_contours = 15 # levels = MaxNLocator(nbins=10).tick_values(vmin, vmax) levels = MaxNLocator(nbins=num_contours).tick_values(self.cmap_min.value, self.cmap_max.value) if (self.cmap_fixed.value): my_plot = plt.contourf(xvec, xvec, M[self.field_index, :].reshape(N,N), levels=levels, extend='both', cmap=self.field_cmap.value) else: # my_plot = plt.contourf(xvec, xvec, M[self.field_index, :].reshape(N,N), num_contours, cmap=self.field_cmap.value) my_plot = plt.contourf(xvec, xvec, M[self.field_index, :].reshape(N,N), num_contours, cmap=self.field_cmap.value) plt.title(title_str) plt.colorbar(my_plot) axes_min = 0 axes_max = 2000
def __init__(self, xml_root): # micron_units = HTMLMath(value=r"$\mu M$") micron_units = Label( 'micron') # use "option m" (Mac, for micro symbol) # micron_units = Label('microns') # use "option m" (Mac, for micro symbol) constWidth = '180px' # tab_height = '400px' tab_height = '500px' # tab_layout = Layout(width='900px', # border='2px solid black', # tab_layout = Layout(width='850px', # border='2px solid black', # height=tab_height, overflow_y='scroll',) # np_tab_layout = Layout(width='800px', # border='2px solid black', # height='350px', overflow_y='scroll',) # my_domain = [0,0,-10, 2000,2000,10, 20,20,20] # [x,y,zmin, x,y,zmax, x,y,zdelta] # label_domain = Label('Domain ($\mu M$):') label_domain = Label('Domain (micron):') stepsize = 10 disable_domain = False self.xmin = FloatText( step=stepsize, # description='$X_{min}$', description='Xmin', disabled=disable_domain, layout=Layout(width=constWidth), ) self.ymin = FloatText( step=stepsize, description='Ymin', disabled=disable_domain, layout=Layout(width=constWidth), ) self.zmin = FloatText( step=stepsize, description='Zmin', disabled=disable_domain, layout=Layout(width=constWidth), ) self.xmax = FloatText( step=stepsize, description='Xmax', disabled=disable_domain, layout=Layout(width=constWidth), ) self.ymax = FloatText( step=stepsize, description='Ymax', disabled=disable_domain, layout=Layout(width=constWidth), ) self.zmax = FloatText( step=stepsize, description='Zmax', disabled=disable_domain, layout=Layout(width=constWidth), ) self.toggle_virtual_walls = Checkbox(description='Virtual walls', layout=Layout(width='350px')) # description='$Time_{max}$', self.tmax = BoundedFloatText( min=0., max=100000000, step=stepsize, description='Max Time', layout=Layout(width=constWidth), ) self.xdelta = BoundedFloatText( min=1., description='dx', # '∆x', # Mac: opt-j for delta disabled=disable_domain, layout=Layout(width=constWidth), ) self.ydelta = BoundedFloatText( min=1., description='dy', disabled=disable_domain, layout=Layout(width=constWidth), ) self.zdelta = BoundedFloatText( min=1., description='dz', disabled=disable_domain, layout=Layout(width=constWidth), ) """ self.tdelta = BoundedFloatText( min=0.01, description='$Time_{delta}$', layout=Layout(width=constWidth), ) """ """ self.toggle2D = Checkbox( description='2-D', layout=Layout(width=constWidth), ) def toggle2D_cb(b): if (self.toggle2D.value): #zmin.disabled = zmax.disabled = zdelta.disabled = True zmin.disabled = True zmax.disabled = True zdelta.disabled = True else: zmin.disabled = False zmax.disabled = False zdelta.disabled = False self.toggle2D.observe(toggle2D_cb) """ x_row = HBox([self.xmin, self.xmax, self.xdelta]) y_row = HBox([self.ymin, self.ymax, self.ydelta]) z_row = HBox([self.zmin, self.zmax, self.zdelta]) self.omp_threads = BoundedIntText( min=1, max=4, description='# threads', layout=Layout(width=constWidth), ) # self.toggle_prng = Checkbox( # description='Seed PRNG', style={'description_width': 'initial'}, # e.g. 'initial' '120px' # layout=Layout(width=constWidth), # ) # self.prng_seed = BoundedIntText( # min = 1, # description='Seed', # disabled=True, # layout=Layout(width=constWidth), # ) # def toggle_prng_cb(b): # if (toggle_prng.value): # self.prng_seed.disabled = False # else: # self.prng_seed.disabled = True # self.toggle_prng.observe(toggle_prng_cb) #prng_row = HBox([toggle_prng, prng_seed]) self.toggle_svg = Checkbox( description='Cells', # SVG layout=Layout(width='150px')) # constWidth = '180px' # self.svg_t0 = BoundedFloatText ( # min=0, # description='$T_0$', # layout=Layout(width=constWidth), # ) self.svg_interval = BoundedFloatText( min=0.001, max= 99999999, # TODO: set max on all Bounded to avoid unwanted default description='every', layout=Layout(width='160px'), ) self.mcds_interval = BoundedFloatText( min=0.001, max=99999999, description='every', # disabled=True, layout=Layout(width='160px'), ) # don't let this be > mcds interval def svg_interval_cb(b): if (self.svg_interval.value > self.mcds_interval.value): self.svg_interval.value = self.mcds_interval.value self.svg_interval.observe( svg_interval_cb) # BEWARE: when fill_gui, this sets value = 1 ! # don't let this be < svg interval def mcds_interval_cb(b): if (self.mcds_interval.value < self.svg_interval.value): self.mcds_interval.value = self.svg_interval.value self.mcds_interval.observe( mcds_interval_cb) # BEWARE: see warning above def toggle_svg_cb(b): if (self.toggle_svg.value): # self.svg_t0.disabled = False self.svg_interval.disabled = False else: # self.svg_t0.disabled = True self.svg_interval.disabled = True self.toggle_svg.observe(toggle_svg_cb) self.toggle_mcds = Checkbox( # value=False, description='Subtrates', # Full layout=Layout(width='180px'), ) # self.mcds_t0 = FloatText( # description='$T_0$', # disabled=True, # layout=Layout(width=constWidth), # ) def toggle_mcds_cb(b): if (self.toggle_mcds.value): # self.mcds_t0.disabled = False #False self.mcds_interval.disabled = False else: # self.mcds_t0.disabled = True self.mcds_interval.disabled = True self.toggle_mcds.observe(toggle_mcds_cb) svg_mat_output_row = HBox([ Label('Plots:'), self.toggle_svg, HBox([self.svg_interval, Label('min')]), self.toggle_mcds, HBox([self.mcds_interval, Label('min')]) ]) # to sync, do this # svg_mat_output_row = HBox( [Label('Plots:'), self.svg_interval, Label('min')]) #write_config_row = HBox([write_config_button, write_config_file]) #run_sim_row = HBox([run_button, run_command_str, kill_button]) # run_sim_row = HBox([run_button, run_command_str]) # run_sim_row = HBox([run_button.w]) # need ".w" for the custom RunCommand widget label_blankline = Label('') # toggle_2D_seed_row = HBox([toggle_prng, prng_seed]) # toggle2D def upload_done_cb(w, name): # Do something with the files here... # We just print their names print("%s uploaded" % name) # reset clears and re-enables the widget for more uploads # You may want to do this somewhere else, depending on your GUI w.reset() if (hublib_flag): self.csv_upload = FileUpload( '', 'Upload cells positions (.csv) from your local machine', dir='data', cb=upload_done_cb, maxsize='1M', # layout=Layout(width='350px') ) self.toggle_cells_csv = Checkbox(description='Enable .csv', layout=Layout(width='280px')) # layout=Layout(width='350px') ) def toggle_cells_csv_cb(b): # why can't I disable this widget?! # print('---- toggle_cells_csv_cb') if (hublib_flag): if (self.toggle_cells_csv.value): # self.csv_upload.w.disabled = False self.csv_upload.visible = True else: self.csv_upload.visible = False self.toggle_cells_csv.observe(toggle_cells_csv_cb) box_layout = Layout(border='1px solid') if (hublib_flag): upload_cells_hbox = HBox( [self.csv_upload.w, self.toggle_cells_csv], layout=Layout(border='1px solid', width='420px')) else: upload_cells_hbox = HBox([self.toggle_cells_csv], layout=Layout(border='1px solid', width='420px')) # domain_box = VBox([label_domain,x_row,y_row,z_row], layout=box_layout) uep = xml_root.find(".//options//virtual_wall_at_domain_edge") if uep: domain_box = VBox( [label_domain, x_row, y_row, self.toggle_virtual_walls], layout=box_layout) else: domain_box = VBox([label_domain, x_row, y_row], layout=box_layout) uep = xml_root.find(".//options//virtual_wall_at_domain_edge") if uep: self.tab = VBox([ domain_box, HBox([self.tmax, Label('min')]), self.omp_threads, svg_mat_output_row, label_blankline, # HBox([self.csv_upload.w, self.toggle_cells_csv]), upload_cells_hbox, # HBox([self.substrate[3], self.diffusion_coef[3], self.decay_rate[3] ]), # ], layout=tab_layout) # output_dir, toggle_2D_seed_ ]) else: self.tab = VBox([ domain_box, HBox([self.tmax, Label('min')]), self.omp_threads, svg_mat_output_row, ])
def __init__(self): self.output_dir = '.' # self.output_dir = 'tmpdir' # self.fig = plt.figure(figsize=(7.2,6)) # this strange figsize results in a ~square contour plot # initial value self.field_index = 4 # self.field_index = self.mcds_field.value + 4 tab_height = '500px' constWidth = '180px' constWidth2 = '150px' tab_layout = Layout(width='900px', # border='2px solid black', height=tab_height, ) #overflow_y='scroll') max_frames = 1 self.mcds_plot = interactive(self.plot_substrate, frame=(0, max_frames), continuous_update=False) svg_plot_size = '700px' self.mcds_plot.layout.width = svg_plot_size self.mcds_plot.layout.height = svg_plot_size self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='Max', layout=Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) self.field_min_max = {'dummy': [0., 1.]} # hacky I know, but make a dict that's got (key,value) reversed from the dict in the Dropdown below self.field_dict = {0:'dummy'} self.mcds_field = Dropdown( options={'dummy': 0}, value=0, # description='Field', layout=Layout(width=constWidth) ) # print("substrate __init__: self.mcds_field.value=",self.mcds_field.value) # self.mcds_field.observe(self.mcds_field_cb) self.mcds_field.observe(self.mcds_field_changed_cb) # self.field_cmap = Text( # value='viridis', # description='Colormap', # disabled=True, # layout=Layout(width=constWidth), # ) self.field_cmap = Dropdown( options=['viridis', 'jet', 'YlOrRd'], value='viridis', # description='Field', layout=Layout(width=constWidth) ) #self.field_cmap.observe(self.plot_substrate) # self.field_cmap.observe(self.plot_substrate) self.field_cmap.observe(self.mcds_field_cb) self.cmap_fixed = Checkbox( description='Fix', disabled=False, # layout=Layout(width=constWidth2), ) self.save_min_max= Button( description='Save', #style={'description_width': 'initial'}, button_style='success', # 'success', 'info', 'warning', 'danger' or '' tooltip='Save min/max for this substrate', disabled=True, layout=Layout(width='90px') ) def save_min_max_cb(b): # field_name = self.mcds_field.options[] # field_name = next(key for key, value in self.mcds_field.options.items() if value == self.mcds_field.value) field_name = self.field_dict[self.mcds_field.value] # print(field_name) # self.field_min_max = {'oxygen': [0., 30.], 'glucose': [0., 1.], 'H+ ions': [0., 1.], 'ECM': [0., 1.], 'NP1': [0., 1.], 'NP2': [0., 1.]} self.field_min_max[field_name][0] = self.cmap_min.value self.field_min_max[field_name][1] = self.cmap_max.value # print(self.field_min_max) self.save_min_max.on_click(save_min_max_cb) self.cmap_min = FloatText( description='Min', value=0, step = 0.1, disabled=True, layout=Layout(width=constWidth2), ) self.cmap_min.observe(self.mcds_field_cb) self.cmap_max = FloatText( description='Max', value=38, step = 0.1, disabled=True, layout=Layout(width=constWidth2), ) self.cmap_max.observe(self.mcds_field_cb) def cmap_fixed_cb(b): if (self.cmap_fixed.value): self.cmap_min.disabled = False self.cmap_max.disabled = False self.save_min_max.disabled = False else: self.cmap_min.disabled = True self.cmap_max.disabled = True self.save_min_max.disabled = True # self.mcds_field_cb() self.cmap_fixed.observe(cmap_fixed_cb) field_cmap_row2 = HBox([self.field_cmap, self.cmap_fixed]) # field_cmap_row3 = HBox([self.save_min_max, self.cmap_min, self.cmap_max]) items_auto = [ self.save_min_max, #layout=Layout(flex='3 1 auto', width='auto'), self.cmap_min, self.cmap_max, ] box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='80%') field_cmap_row3 = Box(children=items_auto, layout=box_layout) # field_cmap_row3 = Box([self.save_min_max, self.cmap_min, self.cmap_max]) # mcds_tab = widgets.VBox([mcds_dir, mcds_plot, mcds_play], layout=tab_layout) mcds_params = VBox([self.mcds_field, field_cmap_row2, field_cmap_row3, self.max_frames]) # mcds_dir # mcds_params = VBox([self.mcds_field, field_cmap_row2, field_cmap_row3,]) # mcds_dir # self.tab = HBox([mcds_params, self.mcds_plot], layout=tab_layout) # self.tab = HBox([mcds_params, self.mcds_plot]) help_label = Label('select slider: drag or left/right arrows') row1 = Box([help_label, Box( [self.max_frames, self.mcds_field, self.field_cmap], layout=Layout(border='0px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex'))] ) row2 = Box([self.cmap_fixed, self.cmap_min, self.cmap_max], layout=Layout(border='0px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) self.download_button = Download('mcds.zip', style='warning', icon='cloud-download', tooltip='Download data', cb=self.download_cb) download_row = HBox([self.download_button.w, Label("Download all substrate data (browser must allow pop-ups).")]) # self.tab = VBox([row1, row2, self.mcds_plot]) self.tab = VBox([row1, row2, self.mcds_plot, download_row])
def plot_interactive_multiple_slicing(array, axes, slice_indexes, model_array=None, cmap='viridis', update_colorbar=False, vmin=0., vmax=1., extent=None, clabel='', xlabel='', ylabel='', figsize=None): ''' Plot 2D slices of a ND NumPy array, with the possibility to loop through and visualize the slices @param array: A ND NumPy array @param axes: A list of N - 2 elements that contains the indexes of the axes to slice @param slice_indexes: A list of N - 2 elements that contains the initial slice to show for each axis @param model_array: A 2D NumPy array to compare to the slices @param cmap: A colormap for the array @param update_colorbar: True if the colorbar must be updated between each slice, false otherwise @param v_min: The minimal value of the colorbar if update_colorbar if false and no model is used @param v_max: The maximal value of the colorbar if update_colorbar if false and no model is used @param extent: The spatial extent of the slice @param clabel: A label for the colorbar @param xlabel: A label for the x axis @param ylabel: A label for the y axis @param figsize: A 2D tuple for the figure size ''' assert len(set(axes)) == len(axes), "Axes must be unique" assert len(slice_indexes) == len( axes), "Slice indexes and axes should have the same length" assert array.ndim - len( axes) == 2, "The plotted array should be two-dimensional" s = [slice(None) for i in range(array.ndim)] for axis, slice_index in zip(axes, slice_indexes): s[axis] = slice(slice_index, slice_index + 1) sliced_array = array[s].squeeze() if update_colorbar == False: if model_array is not None: vmin = np.nanmin(model_array) vmax = np.nanmax(model_array) else: vmin = np.nanmin(sliced_array) vmax = np.nanmax(sliced_array) number_plots = 1 if model_array is not None: number_plots = 2 figure, subplots = plt.subplots(1, number_plots, sharex=True, sharey=True, figsize=figsize) subplot = subplots if model_array is not None: subplot = subplots[1] model_raster_map = subplots[0].imshow( np.ma.masked_invalid(model_array), extent=extent, cmap=cmap, interpolation='None', rasterized=True, vmin=vmin, vmax=vmax, zorder=0) subplots[0].set_xlabel(xlabel) subplots[0].set_ylabel(ylabel) raster_map = subplot.imshow(np.ma.masked_invalid(sliced_array), extent=extent, cmap=cmap, interpolation='None', rasterized=True, vmin=vmin, vmax=vmax, zorder=0) raster_map_colorbar = plt.colorbar(raster_map, ax=subplots) raster_map_colorbar.set_label(clabel) if model_array is None: subplot.set_ylabel(ylabel) subplot.set_xlabel(xlabel) plt.show() def update_imshow(new_axis, new_slice_index): s[new_axis] = slice(new_slice_index, new_slice_index + 1) sliced_array = array[s].squeeze() raster_map.set_data(sliced_array) if update_colorbar == True: raster_map.set_clim(vmin=np.nanmin(sliced_array), vmax=np.nanmax(sliced_array)) if model_array is not None: model_raster_map.set_clim(vmin=np.nanmin(sliced_array), vmax=np.nanmax(sliced_array)) for axis, slice_index in zip(axes, slice_indexes): axis_widget = Dropdown(options=[axis], value=axis, description='Axis', disabled=False) slice_widget = BoundedIntText(value=slice_index, min=0, max=array.shape[axis] - 1, step=1, description='Slice', continuous_update=False) widget = interactive(update_imshow, new_axis=axis_widget, new_slice_index=slice_widget) box = HBox(widget.children) display(box)
def __init__(self): tab_height = '520px' tab_height = '550px' tab_layout = Layout( width='900px', # border='2px solid black', height=tab_height) #, overflow_y='scroll') self.output_dir = '.' # self.output_dir = 'tmpdir' max_frames = 1 self.svg_plot = interactive(self.plot_svg, frame=(0, max_frames), continuous_update=False) svg_plot_size = '500px' self.svg_plot.layout.width = svg_plot_size self.svg_plot.layout.height = svg_plot_size self.use_defaults = True self.show_nucleus = 0 # 0->False, 1->True in Checkbox! self.show_edge = 1 # 0->False, 1->True in Checkbox! self.scale_radius = 1.0 self.axes_min = 0.0 self.axes_max = 2000 # hmm, this can change (TODO?) # self.fig = plt.figure(figsize=(6, 6)) # self.tab = HBox([svg_plot], layout=tab_layout) self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='Max', # layout=Layout(flex='0 1 auto', width='auto'), #Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) self.show_nucleus_checkbox = Checkbox( description='nucleus', value=False, disabled=False, # layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.show_nucleus_checkbox.observe(self.show_nucleus_cb) self.show_edge_checkbox = Checkbox( description='edge', value=True, disabled=False, # layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.show_edge_checkbox.observe(self.show_edge_cb) # row1 = HBox([Label('(select slider: drag or left/right arrows)'), # self.max_frames, VBox([self.show_nucleus_checkbox, self.show_edge_checkbox])]) # self.max_frames, self.show_nucleus_checkbox], layout=Layout(width='500px')) # self.tab = VBox([row1,self.svg_plot], layout=tab_layout) self.help_label = Label('select slider: drag or left/right arrows', layout=Layout(flex='0 1 auto', width='auto')) # layout=Layout(flex='3 1 auto', width='auto')) items_auto = [ self.help_label, self.max_frames, self.show_nucleus_checkbox, self.show_edge_checkbox, ] #row1 = HBox([Label('(select slider: drag or left/right arrows)'), # max_frames, show_nucleus_checkbox, show_edge_checkbox], # layout=Layout(width='800px')) box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='90%') # row1 = Box(children=items_auto, layout=box_layout) #row1 = Box(children=items_auto) row1 = Box([ self.help_label, Box([ self.max_frames, self.show_nucleus_checkbox, self.show_edge_checkbox ], layout=Layout(border='0px solid black', width='60%', height='', align_items='stretch', flex_direction='row', display='flex')) ]) # self.download_button = Download('svg.zip', style='warning', icon='cloud-download', tooltip='Download results', cb=self.download_cb) #self.download_button = Download('svg.zip', style='warning', icon='cloud-download', tooltip='Download results') # self.tab = VBox([row1, self.svg_plot], layout=tab_layout) # self.tab = VBox([row1, self.svg_plot, self.download_button.w], layout=tab_layout) self.tab = VBox([row1, self.svg_plot], layout=tab_layout)
def plot_interactive_slicing(array, slice_index, model_array=None, axis=0, cmap='viridis', extent=None, clabel='', xlabel='', ylabel='', figsize=None, update_colorbar=False): ''' Plot 2D slices of a 3D NumPy array, with the possibility to loop through and visualize the slices @param array: A 3D NumPy array @param slice_index: The initial slice to show @param model_array: A 2D NumPy array to compare to the realizations @param axis: The axis perpendicular to the slices @param cmap: A colormap for the array @param extent: The spatial extent of the slice @param clabel: A label for the colorbar @param xlabel: A label for the x axis @param ylabel: A label for the y axis @param figsize: A 2D tuple for the figure size @param update_colorbar: True if the colorbar must be updated between each slice, false otherwise ''' s = [ slice(slice_index, slice_index + 1) if i == axis else slice(None) for i in range(3) ] sliced_array = array[s].squeeze() min_value = 0. max_value = 1. if update_colorbar == False: if model_array is None: min_value, max_value = average_minmax_slices(array, axis=axis) else: min_value = np.nanmin(model_array) max_value = np.nanmax(model_array) else: min_value = np.nanmin(sliced_array) max_value = np.nanmax(sliced_array) number_plots = 1 if model_array is not None: number_plots = 2 figure, subplots = plt.subplots(1, number_plots, sharex=True, sharey=True, figsize=figsize) subplot = subplots if model_array is not None: subplot = subplots[1] model_raster_map = subplots[0].imshow( np.ma.masked_invalid(model_array), extent=extent, cmap=cmap, interpolation='None', rasterized=True, vmin=min_value, vmax=max_value, zorder=0) subplots[0].set_xlabel(xlabel) subplots[0].set_ylabel(ylabel) raster_map = subplot.imshow(np.ma.masked_invalid(sliced_array), extent=extent, cmap=cmap, interpolation='None', rasterized=True, vmin=min_value, vmax=max_value, zorder=0) raster_map_colorbar = plt.colorbar(raster_map, ax=subplots) raster_map_colorbar.set_label(clabel) if model_array is None: subplot.set_ylabel(ylabel) subplot.set_xlabel(xlabel) plt.show() def update_imshow(new_slice_index): s = [ slice(new_slice_index, new_slice_index + 1) if i == axis else slice(None) for i in range(3) ] sliced_array = array[s].squeeze() raster_map.set_data(sliced_array) if update_colorbar == True: raster_map.set_clim(vmin=np.nanmin(sliced_array), vmax=np.nanmax(sliced_array)) if model_array is not None: model_raster_map.set_clim(vmin=np.nanmin(sliced_array), vmax=np.nanmax(sliced_array)) interactive_plot = interact(update_imshow, new_slice_index=BoundedIntText( value=slice_index, min=0, max=array.shape[axis] - 1, step=1, description='Slice', continuous_update=False)) plt.draw()
class ImBox(VBox): """Widget for inspecting images that contain bounding boxes.""" def __init__(self, df: pd.DataFrame, box_col: str = 'box', img_col: str = 'image', text_cols: Union[str, List[str]] = None, text_fmts: Union[Callable, List[Callable]] = None, style_col: str = None): """ :param pd.DataFrame df: `DataFrame` with images and boxes :param str box_col: column in the dataframe that contains boxes :param str img_col: column in the dataframe that contains image paths :param Union[str, List[str]] text_cols: (optional) the column(s) in the dataframe to use for creating the text that is shown on top of a box. When multiple columns are give, the text will be created by a comma-separated list of the contents of the given columns. :param Unions[Callable, List[Callable]] text_fmts: (optional) a callable, or list of callables, that takes the corresponding value from the `text_cols` column(s) as an input and returns the string to print for that value. :param str style_col: the column containing a dict of style attributes. Available attributes are: - `stroke_width`: the stroke width of a box (default 2) - `stroke_color`: the stroke color of a box (default 'red') - `fill_color`: the fill color of a box (default '#00000000') - `hover_fill`: the fill color of a box when it is hovered on (default '#00000088') - `hover_stroke`: the stroke color of a box when it is hovered on (default 'blue') - `active_fill`: the fill color of a box when it is clicked on (default '#ffffff22') - `active_stroke`: the stroke color of a box when it is clicked on (default 'green') - `font_family`: the font family to use for box text (default 'arial'). NOTE: exported text will always be Arial. - `font_size`: the font size in points (default 10) """ if text_cols is None: text_cols = [] if isinstance(text_cols, str): text_cols = [text_cols] if text_fmts is None: text_fmts = [None] * len(text_cols) if isinstance(text_fmts, Callable): text_fmts = [text_fmts] self.text_cols = text_cols self.text_fmts = text_fmts df2 = df.copy() def row2text(row): txts = row[text_cols] return ', '.join([ fmt(txt) if fmt is not None else str(txt) for txt, fmt in zip(txts, self.text_fmts) ]) if style_col is None: style_col = '_dfim_style' df2[style_col] = [DEFAULT_STYLE] * len(df2) else: df2[style_col] = df2[style_col].apply(lambda s: { k: s[k] if k in s else DEFAULT_STYLE[k] for k in DEFAULT_STYLE }) df2['box_text'] = df2.apply(lambda row: row2text(row), axis=1) df2['box_dict'] = df2.apply( lambda row: dict(index=row.name, box=row[box_col], text=row['box_text'], style=row[style_col]) if (box_col in row.index and row[box_col] is not None) else None, axis=1) self.df_img = df2.groupby(img_col).agg(list).reset_index() self.df = df self.img_col = img_col self.box_col = box_col # SELECTION widget self.idx_wgt = BoundedIntText(value=0, min=0, max=len(self.df_img) - 1, step=1, description='Choose index', disabled=False) self.drop_wgt = Dropdown(options=self.df_img[img_col], description='or image', value=None, disabled=False) self.drop_wgt.observe(self.drop_changed, names='value') self.idx_wgt.observe(self.idx_changed, names='value') self.imsel_wgt = VBox([self.idx_wgt, self.drop_wgt]) self.imsel_wgt.layout = Layout(margin='auto') # IMAGE PANE self.img_title = HTML(placeholder='(Image path)') self.img_title.layout = Layout(margin='auto') self.imbox_wgt = ImBoxWidget() self.imbox_wgt.layout = Layout(margin='1em auto') self.imbox_wgt.observe(self.box_changed, names='active_box') self.imbox_wgt.observe(self.img_changed, names='img') # DETAILS PANE self.crop_wgt = CropBoxWidget() self.crop_wgt.layout = Layout(margin='0 1em') self.detail_wgt = DetailsWidget() self.detail_wgt.layout = Layout(margin='auto') self.detail_pane = HBox([self.crop_wgt, self.detail_wgt]) self.detail_pane.layout = Layout(margin='1em auto') # PLAY widget self.play_btns = Play(interval=100, value=0, min=0, max=len(self.df_img) - 1, step=1, description="Play", disabled=False) self.play_slider = widgets.IntSlider(value=0, min=0, max=len(self.df_img) - 1, step=1) widgets.jslink((self.play_btns, 'value'), (self.idx_wgt, 'value')) widgets.jslink((self.play_btns, 'value'), (self.play_slider, 'value')) self.play_wgt = widgets.HBox([self.play_btns, self.play_slider]) self.play_wgt.layout = Layout(margin='auto') # IMAGE EXPORT widget self.imexp_dest = Text(description='Output file', value='output/output.png') self.imexp_btn = Button(description='Export') self.imexp_btn.on_click(self.export_img) self.imexp_wgt = HBox([self.imexp_dest, self.imexp_btn]) # VIDEO EXPORT widget self.videxp_dest = Text(description='Output file', value='output/output.mp4') self.videxp_start = BoundedIntText(value=0, min=0, max=len(self.df_img) - 1, step=1, description='From index', disabled=False) self.videxp_start.observe(self.vididx_changed, names='value') self.videxp_end = BoundedIntText(value=0, min=0, max=len(self.df_img) - 1, step=1, description='Until index', disabled=False) self.videxp_end.observe(self.vididx_changed, names='value') self.videxp_fps = FloatText(value=30, description='FPS') self.videxp_btn = Button(description='Export') self.videxp_btn.on_click(self.export_vid) self.videxp_wgt = VBox([ HBox([self.videxp_start, self.videxp_end]), HBox([self.videxp_dest, self.videxp_fps]), self.videxp_btn ]) self.exp_wgt = Tab(children=[self.imexp_wgt, self.videxp_wgt]) self.exp_wgt.set_title(0, 'Export image') self.exp_wgt.set_title(1, 'Export video') self.exp_wgt.layout = Layout(margin='0 1em') super().__init__([ self.imsel_wgt, VBox([ self.img_title, self.imbox_wgt, self.play_wgt, self.detail_pane ]), self.exp_wgt ]) self.idx_changed({'new': 0}) def box_changed(self, change): if change['new'] is None: self.detail_wgt.data = {} self.crop_wgt.box = None else: new_idx = change['new']['index'] self.detail_wgt.data = dict(self.df.loc[new_idx]) self.crop_wgt.box = change['new']['box'] def img_changed(self, change): new_img = change['new'] self.detail_wgt.data = {} self.crop_wgt.img = new_img self.img_title.value = f'Image path: <a href="{new_img}">{new_img}</a>' self.imexp_dest.value = f'output/{Path(new_img).stem}.png' self.imexp_btn.button_style = '' self.imexp_btn.description = 'Export' self.imexp_btn.disabled = False def drop_changed(self, change): idx = self.df_img[self.df_img[self.img_col] == change['new']].index[0] self.idx = idx self.imbox_wgt.img = self.df_img.loc[idx, self.img_col] self.imbox_wgt.boxes = self.df_img.loc[idx, 'box_dict'] self.idx_wgt.value = idx def idx_changed(self, change): self.idx = change['new'] self.imbox_wgt.img = self.df_img.loc[self.idx, self.img_col] self.imbox_wgt.boxes = self.df_img.loc[self.idx, 'box_dict'] self.drop_wgt.value = self.imbox_wgt.img def vididx_changed(self, change): start = self.videxp_start.value end = self.videxp_end.value self.videxp_dest.value = f'output/{start}_{end}.mp4' self.videxp_btn.button_style = '' self.videxp_btn.description = 'Export' self.videxp_btn.disabled = False def get_pilim_from_idx(self, idx): """Return the processed PIL image that belongs to an image index. """ im = Image.open(self.df_img.loc[idx, self.img_col]) draw = ImageDraw.Draw(im, mode='RGBA') box_dicts = self.df_img.loc[idx, 'box_dict'] for bd in box_dicts: box = bd['box'] draw.rectangle([(box.x_min, box.y_min), (box.x_max, box.y_max)], fill=bd['style']['fill_color'], outline=bd['style']['stroke_color'], width=bd['style']['stroke_width']) fontfile = str(Path(__file__).parent / 'etc/Arial.ttf') # size*4 to make it look more similar to example in widget fontsize = bd['style']['font_size'] * 4 font = ImageFont.truetype(fontfile, size=fontsize) w, h = draw.textsize(bd['text'], font=font) draw.text((box.x_min, box.y_min - h), text=bd['text'], fill=bd['style']['stroke_color'], font=font) return im def export_img(self, button): self.imexp_btn.disabled = True self.imexp_btn.description = 'Exporting...' im = self.get_pilim_from_idx(self.idx) try: im.save(self.imexp_dest.value) self.imexp_btn.button_style = 'success' self.imexp_btn.description = 'Export Successful' except (IOError, KeyError) as e: self.imexp_btn.button_style = 'danger' self.imexp_btn.description = 'Export Failed' logging.exception('Export Failed') def export_vid(self, button): self.videxp_btn.disabled = True self.videxp_btn.description = 'Exporting...' fps = str(self.videxp_fps.value) writer = FFmpegWriter(self.videxp_dest.value, inputdict={'-framerate': fps}) for idx in tqdm(range(self.videxp_start.value, self.videxp_end.value)): im = self.get_pilim_from_idx(idx) writer.writeFrame(np.array(im)) try: writer.close() self.videxp_btn.button_style = 'success' self.videxp_btn.description = 'Export successful' except OSError as e: self.videxp_btn.button_style = 'danger' self.videxp_btn.description = 'Export failed' logging.exception('Export Failed')
class AnnotatorInterface(metaclass=abc.ABCMeta): def __init__(self, dataset, properties_and_values, # properties { name: (MetaPropType, [possible values], optional label)} output_path=None, show_name=False, show_axis=False, fig_size=(10, 10), buttons_vertical=False, ds_name=None, custom_display_function=None, classes_to_annotate=None, validate_function=None, show_reset=True ): for k, v in properties_and_values.items(): if v[0] not in [MetaPropertiesType.UNIQUE, MetaPropertiesType.TEXT]: raise NotImplementedError(f"Cannot use {v[0]}!") self.dataset_orig = dataset self.properties_and_values = properties_and_values self.show_axis = show_axis self.show_reset = show_reset self.show_name = show_name if classes_to_annotate is None: # if classes_to_annotate is None, all the classes would be annotated self.classes_to_annotate = self.dataset_orig.get_categories_names() # otherwise, the only the classes in the list if ds_name is None: self.name = (self.dataset_orig.dataset_root_param.split('/')[-1]).split('.')[0] # get_original_file_name else: self.name = ds_name self.set_output(output_path) print("{} {}".format(labels_str.info_new_ds, self.file_path_for_json)) self.current_pos = 0 self.mapping, self.dataset_annotated = self.create_results_dict(self.file_path_for_json) self.set_objects() self.fig_size = fig_size self.buttons_vertical = buttons_vertical self.current_image = {} label_total = self.create_label_total() # create buttons buttons = self.create_buttons() self.updated = False self.validation_show = HTML(value="") self.out = Output() self.out.add_class("my_canvas_class") self.checkboxes = {} self.radiobuttons = {} self.bounded_text = {} self.box_text = {} labels = self.create_check_radio_boxes() self.validate = not validate_function is None if self.validate: self.validate_function = validate_function self.set_display_function(custom_display_function) output_layout = self.set_check_radio_boxes_layout(labels) self.all_widgets = VBox(children= [HBox([self.text_index, label_total]), HBox(buttons), self.validation_show, HBox([self.out, VBox(output_layout)])]) self.load_js() @abc.abstractmethod def set_objects(self): pass @abc.abstractmethod def set_display_function(self, custom_display_function): pass def set_output(self, output_path): if output_path is None: name = self.dataset_orig.dataset_root_param self.output_directory = name.replace(os.path.basename(name), "") else: self.output_directory = output_path self.file_path_for_json = os.path.join(self.output_directory, self.name + "_ANNOTATED.json") def create_label_total(self): label_total = Label(value='/ {}'.format(len(self.objects))) self.text_index = BoundedIntText(value=1, min=1, max=len(self.objects)) self.text_index.layout.width = '80px' self.text_index.layout.height = '35px' self.text_index.observe(self.selected_index) return label_total def create_buttons(self): # create buttons self.previous_button = self.create_button(labels_str.str_btn_prev, (self.current_pos == 0), self.on_previous_clicked) self.next_button = self.create_button(labels_str.str_btn_next, (self.current_pos == self.max_pos), self.on_next_clicked) self.save_button = self.create_button(labels_str.str_btn_download, False, self.on_save_clicked) self.save_function = self.save_function # save_function if self.show_reset: self.reset_button = self.create_button(labels_str.str_btn_reset, False, self.on_reset_clicked) buttons = [self.previous_button, self.next_button, self.reset_button, self.save_button] else: buttons = [self.previous_button, self.next_button, self.save_button] return buttons def create_check_radio_boxes(self): labels = dict() for k_name, v in self.properties_and_values.items(): if len(v) == 3: label = v[2] elif MetaPropertiesType.TEXT.value == v[0].value and len(v) == 2: label = v[1] else: label = k_name labels[k_name] = label if MetaPropertiesType.UNIQUE.value == v[0].value: # radiobutton self.radiobuttons[k_name] = RadioButtons(name=k_name, options=v[1], disabled=False, indent=False) elif MetaPropertiesType.COMPOUND.value == v[0].value: # checkbox self.checkboxes[k_name] = [Checkbox(False, indent=False, name=k_name, description=prop_name) for prop_name in v[1]] elif MetaPropertiesType.CONTINUE.value == v[0].value: self.bounded_text[k_name] = BoundedFloatText(value=v[1][0], min=v[1][0], max=v[1][1]) elif MetaPropertiesType.TEXT.value == v[0].value: self.box_text[k_name] = Textarea(disabled=False) return labels def set_check_radio_boxes_layout(self, labels): output_layout = [] self.check_radio_boxes_layout = {} for rb_k, rb_v in self.radiobuttons.items(): rb_v.layout.width = '180px' rb_v.observe(self.checkbox_changed) rb_v.add_class(rb_k) html_title = HTML(value="<b>" + labels[rb_k] + "</b>") self.check_radio_boxes_layout[rb_k] = VBox([rb_v]) output_layout.append(VBox([html_title, self.check_radio_boxes_layout[rb_k]])) for cb_k, cb_i in self.checkboxes.items(): for cb in cb_i: cb.layout.width = '180px' cb.observe(self.checkbox_changed) cb.add_class(cb_k) html_title = HTML(value="<b>" + labels[cb_k] + "</b>") self.check_radio_boxes_layout[cb_k] = VBox(children=[cb for cb in cb_i]) output_layout.append(VBox([html_title, self.check_radio_boxes_layout[cb_k]])) for bf_k, bf in self.bounded_text.items(): bf.layout.width = '80px' bf.layout.height = '35px' bf.observe(self.checkbox_changed) bf.add_class(bf_k) html_title = HTML(value="<b>" + labels[bf_k] + "</b>") self.check_radio_boxes_layout[bf_k] = VBox([bf]) output_layout.append(VBox([html_title, self.check_radio_boxes_layout[bf_k]])) for tb_k, tb_i in self.box_text.items(): tb_i.layout.width = '500px' tb_i.observe(self.checkbox_changed) tb_i.add_class(tb_k) html_title = HTML(value="<b>" + labels[tb_k] + "</b>") self.check_radio_boxes_layout[tb_k] = VBox([tb_i]) output_layout.append(VBox([html_title, self.check_radio_boxes_layout[tb_k]])) return output_layout def load_js(self): ## loading js library to perform html screenshots j_code = """ require.config({ paths: { html2canvas: "https://html2canvas.hertzen.com/dist/html2canvas.min" } }); """ display(Javascript(j_code)) def change_check_radio_boxes_value(self, current_ann): for m_k, m_v in self.properties_and_values.items(): if m_v[0].value == MetaPropertiesType.UNIQUE.value: # radiobutton self.radiobuttons[m_k].unobserve(self.checkbox_changed) self.radiobuttons[m_k].value = current_ann[m_k] if m_k in current_ann.keys() else None self.radiobuttons[m_k].observe(self.checkbox_changed) elif m_v[0].value == MetaPropertiesType.COMPOUND.value: # checkbox for cb_i, cb_v in enumerate(self.checkboxes[m_k]): cb_v.unobserve(self.checkbox_changed) if m_k in current_ann.keys(): if cb_v.description in current_ann[m_k].keys(): cb_v.value = current_ann[m_k][cb_v.description] else: cb_v.value = False else: cb_v.value = False cb_v.observe(self.checkbox_changed) elif m_v[0].value == MetaPropertiesType.CONTINUE.value: # textbound self.bounded_text[m_k].unobserve(self.checkbox_changed) self.bounded_text[m_k].value = float(current_ann[m_k]) if m_k in current_ann.keys() else \ self.bounded_text[m_k].min self.bounded_text[m_k].observe(self.checkbox_changed) elif m_v[0].value == MetaPropertiesType.TEXT.value: # text self.box_text[m_k].unobserve(self.checkbox_changed) self.box_text[m_k].value = current_ann[m_k] if m_k in current_ann.keys() else "" self.box_text[m_k].observe(self.checkbox_changed) def create_results_dict(self, file_path): mapping = {} mapping["annotated_ids"] = set() # key: object_id from dataset, values=[(annotations done)] mapping["categories_counter"] = dict.fromkeys([c for c in self.dataset_orig.get_categories_names()], 0) self.mapping = mapping if not os.path.exists(file_path): # it does exist __ANNOTATED in the output directory with open(self.dataset_orig.dataset_root_param, 'r') as input_json_file: dataset_annotated = json.load(input_json_file) input_json_file.close() # take the same metaproperties already in file if it's not empty (like a new file) meta_prop = dataset_annotated['meta_properties'] if 'meta_properties' in dataset_annotated.keys() else [] # adds the new annotations categories to dataset if it doesn't exist for k_name, v in self.properties_and_values.items(): new_mp_to_append = { "name": k_name, "type": v[0].value, } if len(v) > 1: new_mp_to_append["values"] = sorted([p for p in v[1]]) names_prop_in_file = {m_p['name']: m_p for m_i, m_p in enumerate(dataset_annotated[ 'meta_properties'])} if 'meta_properties' in dataset_annotated.keys() else None if 'meta_properties' not in dataset_annotated.keys(): # it is a new file meta_prop.append(new_mp_to_append) dataset_annotated['meta_properties'] = [] elif names_prop_in_file is not None and k_name not in names_prop_in_file.keys(): # if there is a property with the same in meta_properties, it must be the same structure as the one proposed meta_prop.append(new_mp_to_append) self.update_annotation_counter_and_current_pos(dataset_annotated) elif names_prop_in_file is not None and k_name in names_prop_in_file.keys() and \ names_prop_in_file[k_name] == new_mp_to_append: # we don't append because it's already there self.update_annotation_counter_and_current_pos(dataset_annotated) else: raise NameError("An annotation with the same name {} " "already exist in dataset {}, and it has different structure. Check properties.".format( k_name, self.dataset_orig.dataset_root_param)) # if k_name is in name_props_in_file and it's the same structure. No update is done. dataset_annotated['meta_properties'] = dataset_annotated['meta_properties'] + meta_prop else: with open(file_path, 'r') as classification_file: dataset_annotated = json.load(classification_file) classification_file.close() self.update_annotation_counter_and_current_pos(dataset_annotated) return mapping, dataset_annotated @abc.abstractmethod def add_annotation_to_mapping(self, ann): pass @abc.abstractmethod def update_mapping_from_whole_dataset(self): pass @abc.abstractmethod def update_annotation_counter_and_current_pos(self, dataset_annotated): pass def execute_validation(self, ann): if self.validate: if self.validate_function(ann): self.validation_show.value = labels_str.srt_validation_not_ok else: self.validation_show.value = labels_str.srt_validation_ok @abc.abstractmethod def show_name_func(self, image_record, path_img): pass @abc.abstractmethod def checkbox_changed(self, b): pass def create_button(self, description, disabled, function): button = Button(description=description) button.disabled = disabled button.on_click(function) return button @abc.abstractmethod def show_image(self, image_record, ann_key): pass @abc.abstractmethod def save_state(self): pass def save_function(self, image_path): img_name = os.path.basename(image_path).split('.')[0] j_code = """ require(["html2canvas"], function(html2canvas) { var element = $(".p-Widget.jupyter-widgets-output-area.output_wrapper.$it_name$")[0]; console.log(element); html2canvas(element).then(function (canvas) { var myImage = canvas.toDataURL(); var a = document.createElement("a"); a.href = myImage; a.download = "$img_name$.png"; a.click(); a.remove(); }); }); """ j_code = j_code.replace('$it_name$', "my_canvas_class") j_code = j_code.replace('$img_name$', img_name) tmp_out = Output() with tmp_out: display(Javascript(j_code)) tmp_out.clear_output() @abc.abstractmethod def perform_action(self): pass @abc.abstractmethod def get_image_record(self): pass @abc.abstractmethod def on_reset_clicked(self, b): pass def on_previous_clicked(self, b): self.save_state() self.current_pos -= 1 self.perform_action() def on_next_clicked(self, b): self.save_state() self.current_pos += 1 self.perform_action() @abc.abstractmethod def on_save_clicked(self, b): pass def selected_index(self, t): if t['owner'].value is None or t['name'] != 'value': return self.current_pos = t['new'] - 1 self.perform_action() def start_annotation(self): if self.max_pos < self.current_pos: print(labels_str.info_no_more_images) return display(self.all_widgets) self.perform_action() @abc.abstractmethod def print_statistics(self): pass @abc.abstractmethod def print_results(self): pass
def __init__(self): self.output_dir = '.' # self.output_dir = 'tmpdir' # self.fig = plt.figure(figsize=(7.2,6)) # this strange figsize results in a ~square contour plot self.use_defaults = True self.svg_xmin = 0 self.svg_xrange = 2000 self.xmin = -1000. self.xmax = 1000. self.ymin = -1000. self.ymax = 1000. self.x_range = 2000. self.y_range = 2000. self.show_nucleus = 0 self.show_edge = False # initial value self.field_index = 4 # self.field_index = self.mcds_field.value + 4 # define dummy size of mesh (set in the tool's primary module) self.numx = 0 self.numy = 0 tab_height = '600px' tab_height = '500px' constWidth = '180px' constWidth2 = '150px' tab_layout = Layout( width='900px', # border='2px solid black', height=tab_height, ) #overflow_y='scroll') max_frames = 1 # self.mcds_plot = interactive(self.plot_substrate, frame=(0, max_frames), continuous_update=False) self.mcds_plot = interactive(self.plot_plots, frame=(0, max_frames), continuous_update=False) # "plot_size" controls the size of the tab height, not the plot (rf. figsize for that) # NOTE: the Substrates Plot tab has an extra row of widgets at the top of it (cf. Cell Plots tab) svg_plot_size = '700px' svg_plot_size = '600px' svg_plot_size = '700px' svg_plot_size = '900px' self.mcds_plot.layout.width = svg_plot_size self.mcds_plot.layout.height = svg_plot_size self.fontsize = 20 self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='Max', layout=Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) self.field_min_max = {'dummy': [0., 1.]} # hacky I know, but make a dict that's got (key,value) reversed from the dict in the Dropdown below self.field_dict = {0: 'dummy'} self.mcds_field = Dropdown( options={'dummy': 0}, value=0, # description='Field', layout=Layout(width=constWidth)) # print("substrate __init__: self.mcds_field.value=",self.mcds_field.value) # self.mcds_field.observe(self.mcds_field_cb) self.mcds_field.observe(self.mcds_field_changed_cb) # self.field_cmap = Text( # value='viridis', # description='Colormap', # disabled=True, # layout=Layout(width=constWidth), # ) self.field_cmap = Dropdown( options=['viridis', 'jet', 'YlOrRd'], value='YlOrRd', # description='Field', layout=Layout(width=constWidth)) #self.field_cmap.observe(self.plot_substrate) # self.field_cmap.observe(self.plot_substrate) self.field_cmap.observe(self.mcds_field_cb) self.cmap_fixed = Checkbox( description='Fix', disabled=False, # layout=Layout(width=constWidth2), ) self.save_min_max = Button( description='Save', #style={'description_width': 'initial'}, button_style= 'success', # 'success', 'info', 'warning', 'danger' or '' tooltip='Save min/max for this substrate', disabled=True, layout=Layout(width='90px')) def save_min_max_cb(b): # field_name = self.mcds_field.options[] # field_name = next(key for key, value in self.mcds_field.options.items() if value == self.mcds_field.value) field_name = self.field_dict[self.mcds_field.value] # print(field_name) # self.field_min_max = {'oxygen': [0., 30.], 'glucose': [0., 1.], 'H+ ions': [0., 1.], 'ECM': [0., 1.], 'NP1': [0., 1.], 'NP2': [0., 1.]} self.field_min_max[field_name][0] = self.cmap_min.value self.field_min_max[field_name][1] = self.cmap_max.value # print(self.field_min_max) self.save_min_max.on_click(save_min_max_cb) self.cmap_min = FloatText( description='Min', value=0, step=0.1, disabled=True, layout=Layout(width=constWidth2), ) self.cmap_min.observe(self.mcds_field_cb) self.cmap_max = FloatText( description='Max', value=38, step=0.1, disabled=True, layout=Layout(width=constWidth2), ) self.cmap_max.observe(self.mcds_field_cb) def cmap_fixed_cb(b): if (self.cmap_fixed.value): self.cmap_min.disabled = False self.cmap_max.disabled = False self.save_min_max.disabled = False else: self.cmap_min.disabled = True self.cmap_max.disabled = True self.save_min_max.disabled = True # self.mcds_field_cb() self.cmap_fixed.observe(cmap_fixed_cb) field_cmap_row2 = HBox([self.field_cmap, self.cmap_fixed]) # field_cmap_row3 = HBox([self.save_min_max, self.cmap_min, self.cmap_max]) items_auto = [ self.save_min_max, #layout=Layout(flex='3 1 auto', width='auto'), self.cmap_min, self.cmap_max, ] box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='80%') field_cmap_row3 = Box(children=items_auto, layout=box_layout) #--------------------- self.cell_edges_toggle = Checkbox( description='edges', disabled=False, value=False, # layout=Layout(width=constWidth2), ) def cell_edges_toggle_cb(b): # self.update() if (self.cell_edges_toggle.value): self.show_edge = True else: self.show_edge = False self.mcds_plot.update() self.cell_edges_toggle.observe(cell_edges_toggle_cb) self.cells_toggle = Checkbox( description='Cells', disabled=False, value=True, # layout=Layout(width=constWidth2), ) def cells_toggle_cb(b): # self.update() self.mcds_plot.update() if (self.cells_toggle.value): self.cell_edges_toggle.disabled = False else: self.cell_edges_toggle.disabled = True self.cells_toggle.observe(cells_toggle_cb) #--------------------- self.substrates_toggle = Checkbox( description='Substrates', disabled=False, value=True, # layout=Layout(width=constWidth2), ) def substrates_toggle_cb(b): if (self.substrates_toggle.value): # seems bass-ackwards self.cmap_fixed.disabled = False self.cmap_min.disabled = False self.cmap_max.disabled = False self.mcds_field.disabled = False self.field_cmap.disabled = False else: self.cmap_fixed.disabled = True self.cmap_min.disabled = True self.cmap_max.disabled = True self.mcds_field.disabled = True self.field_cmap.disabled = True self.substrates_toggle.observe(substrates_toggle_cb) self.grid_toggle = Checkbox( description='grid', disabled=False, value=True, # layout=Layout(width=constWidth2), ) def grid_toggle_cb(b): # self.update() self.mcds_plot.update() self.grid_toggle.observe(grid_toggle_cb) # field_cmap_row3 = Box([self.save_min_max, self.cmap_min, self.cmap_max]) # mcds_tab = widgets.VBox([mcds_dir, mcds_plot, mcds_play], layout=tab_layout) # mcds_params = VBox([self.mcds_field, field_cmap_row2, field_cmap_row3, self.max_frames]) # mcds_dir # mcds_params = VBox([self.mcds_field, field_cmap_row2, field_cmap_row3,]) # mcds_dir # self.tab = HBox([mcds_params, self.mcds_plot], layout=tab_layout) # self.tab = HBox([mcds_params, self.mcds_plot]) help_label = Label('select slider: drag or left/right arrows') # row1 = Box([help_label, Box( [self.max_frames, self.mcds_field, self.field_cmap], layout=Layout(border='0px solid black', row1a = Box([self.max_frames, self.mcds_field, self.field_cmap], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) row1b = Box([self.cells_toggle, self.cell_edges_toggle], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) row1 = HBox([row1a, Label('.....'), row1b]) row2a = Box([self.cmap_fixed, self.cmap_min, self.cmap_max], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) # row2b = Box( [self.substrates_toggle, self.grid_toggle], layout=Layout(border='1px solid black', row2b = Box([ self.substrates_toggle, ], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) # row2 = HBox( [row2a, self.substrates_toggle, self.grid_toggle]) row2 = HBox([row2a, Label('.....'), row2b]) if (hublib_flag): self.download_button = Download('mcds.zip', style='warning', icon='cloud-download', tooltip='Download data', cb=self.download_cb) self.download_svg_button = Download( 'svg.zip', style='warning', icon='cloud-download', tooltip='You need to allow pop-ups in your browser', cb=self.download_svg_cb) download_row = HBox([ self.download_button.w, self.download_svg_button.w, Label("Download all cell plots (browser must allow pop-ups).") ]) # self.tab = VBox([row1, row2, self.mcds_plot]) # self.tab = VBox([row1, row2, self.mcds_plot, download_row]) # box_layout = Layout(border='0px solid') controls_box = VBox([row1, row2]) # ,width='50%', layout=box_layout) self.tab = VBox([controls_box, self.mcds_plot, download_row]) else: # self.tab = VBox([row1, row2]) self.tab = VBox([row1, row2, self.mcds_plot])
class Iterator: def __init__(self, images, name="iterator", show_name=True, show_axis=False, show_random=True, fig_size=(10, 10), buttons_vertical=False, image_display_function=None): if len(images) == 0: raise Exception("No images provided") self.show_axis = show_axis self.name = name self.show_name = show_name self.show_random = show_random self.images = images self.max_pos = len(self.images) - 1 self.pos = 0 self.fig_size = fig_size self.buttons_vertical = buttons_vertical if image_display_function is None: self.image_display_function = self.__show_image else: self.image_display_function = image_display_function self.previous_button = self.__create_button("Previous", (self.pos == 0), self.__on_previous_clicked) self.next_button = self.__create_button("Next", (self.pos == self.max_pos), self.__on_next_clicked) self.save_button = self.__create_button("Save", False, self.__on_save_clicked) self.save_function = self.__save_function # save_function buttons = [self.previous_button, self.next_button] if self.show_random: self.random_button = self.__create_button("Random", False, self.__on_random_clicked) buttons.append(self.random_button) buttons.append(self.save_button) label_total = Label(value='/ {}'.format(len(self.images))) self.text_index = BoundedIntText(value=1, min=1, max=len(self.images)) self.text_index.layout.width = '80px' self.text_index.layout.height = '35px' self.text_index.observe(self.__selected_index) self.out = Output() self.out.add_class(name) if self.buttons_vertical: self.all_widgets = HBox(children=[ VBox(children=[HBox([self.text_index, label_total])] + buttons), self.out ]) else: self.all_widgets = VBox(children=[ HBox([self.text_index, label_total]), HBox(children=buttons), self.out ]) ## loading js library to perform html screenshots j_code = """ require.config({ paths: { html2canvas: "https://html2canvas.hertzen.com/dist/html2canvas.min" } }); """ display(Javascript(j_code)) def __create_button(self, description, disabled, function): button = Button(description=description) button.disabled = disabled button.on_click(function) return button def __show_image(self, image_path, index): img = Image.open(image_path) if self.show_name: print(os.path.basename(image_path)) plt.figure(figsize=self.fig_size) if not self.show_axis: plt.axis('off') plt.imshow(img) plt.show() def __save_function(self, image_path, index): img_name = os.path.basename(image_path).split('.')[0] j_code = """ require(["html2canvas"], function(html2canvas) { var element = $(".p-Widget.jupyter-widgets-output-area.output_wrapper.$it_name$")[0]; console.log(element); html2canvas(element).then(function (canvas) { var myImage = canvas.toDataURL(); var a = document.createElement("a"); a.href = myImage; a.download = "$img_name$.png"; a.click(); a.remove(); }); }); """ j_code = j_code.replace('$it_name$', self.name) j_code = j_code.replace('$img_name$', img_name) tmp_out = Output() with tmp_out: display(Javascript(j_code)) tmp_out.clear_output() def __on_next_clicked(self, b): self.pos += 1 self.__perform_action(self.pos, self.max_pos) def __on_save_clicked(self, b): self.save_function(self.images[self.pos], self.pos) def __perform_action(self, index, max_pos): self.next_button.disabled = (index == max_pos) self.previous_button.disabled = (index == 0) with self.out: self.out.clear_output() with self.out: self.image_display_function(self.images[index], index) self.text_index.unobserve(self.__selected_index) self.text_index.value = index + 1 self.text_index.observe(self.__selected_index) def __on_previous_clicked(self, b): self.pos -= 1 self.__perform_action(self.pos, self.max_pos) def __on_random_clicked(self, b): self.pos = random.randint(0, self.max_pos) self.__perform_action(self.pos, self.max_pos) def __selected_index(self, t): if t['owner'].value is None or t['name'] != 'value': return self.pos = t['new'] - 1 self.__perform_action(self.pos, self.max_pos) def start_iteration(self): if self.max_pos < self.pos: print("No available images") return display(self.all_widgets) self.__perform_action(self.pos, self.max_pos)
def __init__(self): tab_height = '520px' tab_layout = Layout( width='800px', # border='2px solid black', height=tab_height, overflow_y='scroll') self.output_dir = '.' max_frames = 505 # first time + 30240 / 60 self.svg_plot = interactive(self.plot_svg, frame=(0, max_frames), continuous_update=False) svg_plot_size = '500px' self.svg_plot.layout.width = svg_plot_size self.svg_plot.layout.height = svg_plot_size self.use_defaults = True self.show_nucleus = 0 # 0->False, 1->True in Checkbox! self.show_edge = 1 # 0->False, 1->True in Checkbox! self.scale_radius = 1.0 self.axes_min = 0.0 self.axes_max = 2000 # hmm, this can change (TODO?) # self.tab = HBox([svg_plot], layout=tab_layout) self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='Max', layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) self.show_nucleus_checkbox = Checkbox( description='nucleus', value=False, disabled=False, layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.show_nucleus_checkbox.observe(self.show_nucleus_cb) self.show_edge_checkbox = Checkbox( description='edge', value=True, disabled=False, layout=Layout(flex='1 1 auto', width='auto'), #Layout(width='160px'), ) self.show_edge_checkbox.observe(self.show_edge_cb) # row1 = HBox([Label('(select slider: drag or left/right arrows)'), # self.max_frames, VBox([self.show_nucleus_checkbox, self.show_edge_checkbox])]) # self.max_frames, self.show_nucleus_checkbox], layout=Layout(width='500px')) # self.tab = VBox([row1,self.svg_plot], layout=tab_layout) items_auto = [ Label('(select slider: drag or left/right arrows)'), self.max_frames, self.show_nucleus_checkbox, self.show_edge_checkbox, ] #row1 = HBox([Label('(select slider: drag or left/right arrows)'), # max_frames, show_nucleus_checkbox, show_edge_checkbox], # layout=Layout(width='800px')) box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='90%') row1 = Box(children=items_auto, layout=box_layout) self.tab = VBox([row1, self.svg_plot], layout=tab_layout)
def __init__(self, images, name="iterator", show_name=True, show_axis=False, show_random=True, fig_size=(10, 10), buttons_vertical=False, image_display_function=None): if len(images) == 0: raise Exception("No images provided") self.show_axis = show_axis self.name = name self.show_name = show_name self.show_random = show_random self.images = images self.max_pos = len(self.images) - 1 self.pos = 0 self.fig_size = fig_size self.buttons_vertical = buttons_vertical if image_display_function is None: self.image_display_function = self.__show_image else: self.image_display_function = image_display_function self.previous_button = self.__create_button("Previous", (self.pos == 0), self.__on_previous_clicked) self.next_button = self.__create_button("Next", (self.pos == self.max_pos), self.__on_next_clicked) self.save_button = self.__create_button("Save", False, self.__on_save_clicked) self.save_function = self.__save_function # save_function buttons = [self.previous_button, self.next_button] if self.show_random: self.random_button = self.__create_button("Random", False, self.__on_random_clicked) buttons.append(self.random_button) buttons.append(self.save_button) label_total = Label(value='/ {}'.format(len(self.images))) self.text_index = BoundedIntText(value=1, min=1, max=len(self.images)) self.text_index.layout.width = '80px' self.text_index.layout.height = '35px' self.text_index.observe(self.__selected_index) self.out = Output() self.out.add_class(name) if self.buttons_vertical: self.all_widgets = HBox(children=[ VBox(children=[HBox([self.text_index, label_total])] + buttons), self.out ]) else: self.all_widgets = VBox(children=[ HBox([self.text_index, label_total]), HBox(children=buttons), self.out ]) ## loading js library to perform html screenshots j_code = """ require.config({ paths: { html2canvas: "https://html2canvas.hertzen.com/dist/html2canvas.min" } }); """ display(Javascript(j_code))
class ConfigTab(object): def __init__(self): # micron_units = HTMLMath(value=r"$\mu M$") micron_units = Label( 'micron') # use "option m" (Mac, for micro symbol) # micron_units = Label('microns') # use "option m" (Mac, for micro symbol) constWidth = '180px' # tab_height = '400px' tab_height = '500px' # tab_layout = Layout(width='900px', # border='2px solid black', # tab_layout = Layout(width='850px', # border='2px solid black', # height=tab_height, overflow_y='scroll',) # np_tab_layout = Layout(width='800px', # border='2px solid black', # height='350px', overflow_y='scroll',) # my_domain = [0,0,-10, 2000,2000,10, 20,20,20] # [x,y,zmin, x,y,zmax, x,y,zdelta] # label_domain = Label('Domain ($\mu M$):') label_domain = Label('Domain (micron):') stepsize = 10 disable_domain = False self.xmin = FloatText( step=stepsize, # description='$X_{min}$', description='Xmin', disabled=disable_domain, layout=Layout(width=constWidth), ) self.ymin = FloatText( step=stepsize, description='Ymin', disabled=disable_domain, layout=Layout(width=constWidth), ) self.zmin = FloatText( step=stepsize, description='Zmin', disabled=disable_domain, layout=Layout(width=constWidth), ) self.xmax = FloatText( step=stepsize, description='Xmax', disabled=disable_domain, layout=Layout(width=constWidth), ) self.ymax = FloatText( step=stepsize, description='Ymax', disabled=disable_domain, layout=Layout(width=constWidth), ) self.zmax = FloatText( step=stepsize, description='Zmax', disabled=disable_domain, layout=Layout(width=constWidth), ) # description='$Time_{max}$', self.tmax = BoundedFloatText( min=0., max=100000000, step=stepsize, description='Max Time', layout=Layout(width=constWidth), ) self.xdelta = BoundedFloatText( min=1., description='dx', # '∆x', # Mac: opt-j for delta disabled=disable_domain, layout=Layout(width=constWidth), ) self.ydelta = BoundedFloatText( min=1., description='dy', disabled=True, layout=Layout(width=constWidth), ) self.zdelta = BoundedFloatText( min=1., description='dz', disabled=disable_domain, layout=Layout(width=constWidth), ) def xdelta_cb(b): self.ydelta.value = self.xdelta.value self.zdelta.value = 0.5 * (self.xdelta.value + self.ydelta.value) self.zmin.value = -0.5 * self.zdelta.value self.zmax.value = 0.5 * self.zdelta.value self.xdelta.observe(xdelta_cb) """ self.tdelta = BoundedFloatText( min=0.01, description='$Time_{delta}$', layout=Layout(width=constWidth), ) """ """ self.toggle2D = Checkbox( description='2-D', layout=Layout(width=constWidth), ) def toggle2D_cb(b): if (self.toggle2D.value): #zmin.disabled = zmax.disabled = zdelta.disabled = True zmin.disabled = True zmax.disabled = True zdelta.disabled = True else: zmin.disabled = False zmax.disabled = False zdelta.disabled = False self.toggle2D.observe(toggle2D_cb) """ x_row = HBox([self.xmin, self.xmax, self.xdelta]) y_row = HBox([self.ymin, self.ymax, self.ydelta]) z_row = HBox([self.zmin, self.zmax, self.zdelta]) self.omp_threads = BoundedIntText( min=1, max=4, description='# threads', layout=Layout(width=constWidth), ) # self.toggle_prng = Checkbox( # description='Seed PRNG', style={'description_width': 'initial'}, # e.g. 'initial' '120px' # layout=Layout(width=constWidth), # ) # self.prng_seed = BoundedIntText( # min = 1, # description='Seed', # disabled=True, # layout=Layout(width=constWidth), # ) # def toggle_prng_cb(b): # if (toggle_prng.value): # self.prng_seed.disabled = False # else: # self.prng_seed.disabled = True # self.toggle_prng.observe(toggle_prng_cb) #prng_row = HBox([toggle_prng, prng_seed]) self.toggle_svg = Checkbox( description='Cells', # SVG layout=Layout(width='150px')) # constWidth = '180px' # self.svg_t0 = BoundedFloatText ( # min=0, # description='$T_0$', # layout=Layout(width=constWidth), # ) self.svg_interval = BoundedIntText( min=1, max= 99999999, # TODO: set max on all Bounded to avoid unwanted default description='every', layout=Layout(width='160px'), ) self.mcds_interval = BoundedIntText( min=1, max=99999999, description='every', # disabled=True, layout=Layout(width='160px'), ) # don't let this be > mcds interval def svg_interval_cb(b): if (self.svg_interval.value > self.mcds_interval.value): self.svg_interval.value = self.mcds_interval.value self.svg_interval.observe( svg_interval_cb) # BEWARE: when fill_gui, this sets value = 1 ! # don't let this be < svg interval def mcds_interval_cb(b): if (self.mcds_interval.value < self.svg_interval.value): self.mcds_interval.value = self.svg_interval.value self.mcds_interval.observe( mcds_interval_cb) # BEWARE: see warning above def toggle_svg_cb(b): if (self.toggle_svg.value): # self.svg_t0.disabled = False self.svg_interval.disabled = False else: # self.svg_t0.disabled = True self.svg_interval.disabled = True self.toggle_svg.observe(toggle_svg_cb) self.toggle_mcds = Checkbox( # value=False, description='Subtrates', # Full layout=Layout(width='180px'), ) # self.mcds_t0 = FloatText( # description='$T_0$', # disabled=True, # layout=Layout(width=constWidth), # ) def toggle_mcds_cb(b): if (self.toggle_mcds.value): # self.mcds_t0.disabled = False #False self.mcds_interval.disabled = False else: # self.mcds_t0.disabled = True self.mcds_interval.disabled = True self.toggle_mcds.observe(toggle_mcds_cb) svg_mat_output_row = HBox([ Label('Plots:'), self.toggle_svg, HBox([self.svg_interval, Label('min')]), self.toggle_mcds, HBox([self.mcds_interval, Label('min')]) ]) # to sync, do this # svg_mat_output_row = HBox( [Label('Plots:'), self.svg_interval, Label('min')]) #write_config_row = HBox([write_config_button, write_config_file]) #run_sim_row = HBox([run_button, run_command_str, kill_button]) # run_sim_row = HBox([run_button, run_command_str]) # run_sim_row = HBox([run_button.w]) # need ".w" for the custom RunCommand widget label_blankline = Label('') # toggle_2D_seed_row = HBox([toggle_prng, prng_seed]) # toggle2D box_layout = Layout(border='1px solid') # domain_box = VBox([label_domain,x_row,y_row,z_row], layout=box_layout) domain_box = VBox([label_domain, x_row, y_row], layout=box_layout) self.tab = VBox([ domain_box, # label_blankline, HBox([self.tmax, Label('min')]), self.omp_threads, svg_mat_output_row, # HBox([self.substrate[3], self.diffusion_coef[3], self.decay_rate[3] ]), ]) # output_dir, toggle_2D_seed_ # ], layout=tab_layout) # output_dir, toggle_2D_seed_ # Populate the GUI widgets with values from the XML def fill_gui(self, xml_root): self.xmin.value = float(xml_root.find(".//x_min").text) self.xmax.value = float(xml_root.find(".//x_max").text) self.xdelta.value = float(xml_root.find(".//dx").text) self.ymin.value = float(xml_root.find(".//y_min").text) self.ymax.value = float(xml_root.find(".//y_max").text) self.ydelta.value = float(xml_root.find(".//dy").text) self.zmin.value = float(xml_root.find(".//z_min").text) self.zmax.value = float(xml_root.find(".//z_max").text) self.zdelta.value = float(xml_root.find(".//dz").text) self.tmax.value = float(xml_root.find(".//max_time").text) self.omp_threads.value = int(xml_root.find(".//omp_num_threads").text) if xml_root.find(".//full_data//enable").text.lower() == 'true': self.toggle_mcds.value = True else: self.toggle_mcds.value = False self.mcds_interval.value = int( xml_root.find(".//full_data//interval").text) # NOTE: do this *after* filling the mcds_interval, directly above, due to the callback/constraints on them if xml_root.find(".//SVG//enable").text.lower() == 'true': self.toggle_svg.value = True else: self.toggle_svg.value = False self.svg_interval.value = int(xml_root.find(".//SVG//interval").text) # Read values from the GUI widgets and generate/write a new XML def fill_xml(self, xml_root): # print('config.py fill_xml() !!!!!') # TODO: verify template .xml file exists! # TODO: verify valid type (numeric) and range? xml_root.find(".//x_min").text = str(self.xmin.value) xml_root.find(".//x_max").text = str(self.xmax.value) xml_root.find(".//dx").text = str(self.xdelta.value) xml_root.find(".//y_min").text = str(self.ymin.value) xml_root.find(".//y_max").text = str(self.ymax.value) xml_root.find(".//dy").text = str(self.ydelta.value) xml_root.find(".//z_min").text = str(self.zmin.value) xml_root.find(".//z_max").text = str(self.zmax.value) xml_root.find(".//dz").text = str(self.zdelta.value) xml_root.find(".//max_time").text = str(self.tmax.value) xml_root.find(".//omp_num_threads").text = str(self.omp_threads.value) xml_root.find(".//SVG").find(".//enable").text = str( self.toggle_svg.value) xml_root.find(".//SVG").find(".//interval").text = str( self.svg_interval.value) xml_root.find(".//full_data").find(".//enable").text = str( self.toggle_mcds.value) xml_root.find(".//full_data").find(".//interval").text = str( self.mcds_interval.value) # user_details = ET.SubElement(root, "user_details") # ET.SubElement(user_details, "PhysiCell_settings", name="version").text = "devel-version" # ET.SubElement(user_details, "domain") # ET.SubElement(user_details, "xmin").text = "-100" # tree = ET.ElementTree(root) # tree.write(write_config_file.value) # tree.write("test.xml") # TODO: verify can write to this filename # tree.write(write_config_file.value) def get_num_svg_frames(self): if (self.toggle_svg.value): return int(self.tmax.value / self.svg_interval.value) else: return 0 def get_num_substrate_frames(self): if (self.toggle_mcds.value): return int(self.tmax.value / self.mcds_interval.value) else: return 0
def build_options(self): grid = GridspecLayout(4, 2) options_map = {} style = {'description_width': '60%'} # plot_type plot_type = Dropdown( description='Plot:', options=['force', 'decision', 'both'], description_tooltip='Which plot to draw decision, force or both', style=style) options_map['plot_type'] = plot_type # background_data background_data = Dropdown( description='Background data:', options={ 'KMeans': 'kmeans', 'Custom variable': 'custom' }, value='kmeans', description_tooltip= 'What background data will be used to sample from, when simulating "missing" feature\n' ' - KMeans: use KMeans to sample from provided dataset\n' ' - Custom variable: provide variable with instances to use', style=style) options_map['background_data'] = background_data # kmeans_count (only show when KMeans is chosen) kmeans_count = BoundedIntText( value=100, min=1, max=len(self.X_train), description='Count of KMeans centers:', description_tooltip= 'Number of means to use when creating background data', style=style) options_map['kmeans_count'] = kmeans_count # data (only show when Custom variable is chosen) data = UpdatingCombobox( options_keys=self.globals_options, description='Background data variable:', options=list(self.globals_options), description_tooltip= 'Variable with background data from which the "missing" features will be sampled', style=style) options_map['data'] = data # set up swap of options def swap_kmeans(change): if change['new'] == 'kmeans': data.lookup_in_kernel = False grid[1, 1] = kmeans_count else: data.lookup_in_kernel = True grid[1, 1] = data background_data.observe(swap_kmeans, names=['value']) # link link = Dropdown( description='Link:', options=['identity', 'logit'], value='identity', description_tooltip= 'A generalized linear model link to connect the feature importance values ' 'to the model output.\n' 'Since the feature importance values, phi, sum up to the model output, ' 'it often makes sense to connect them to the ouput with a link function ' 'where link(outout) = sum(phi).\n ' 'If the model output is a probability then the LogitLink link function makes ' 'the feature importance values have log-odds units.', style=style) options_map['link'] = link # nsamples nsamples = BoundedIntText( min=1, max=999999, value=2048, disabled=True, description='Model sample size:', description_tooltip= 'Number of times to re-evaluate the model when explaining each prediction.\n' 'More samples lead to lower variance estimates of the SHAP values.\n' 'The "auto" setting uses nsamples = 2 * X.shape[1] + 2048.', style=style) options_map['nsamples'] = nsamples # auto_nsamples auto_nsamples = Checkbox(description='Auto choose model sample size', value=True, style={'description_width': 'auto'}) options_map['auto_nsamples'] = auto_nsamples def disable_nsamples(change): nsamples.disabled = change['new'] auto_nsamples.observe(disable_nsamples, names=['value']) # l1_reg l1_reg = Combobox( description='L1 regularization:', options=['auto', 'aic', 'bic'], value='auto', description_tooltip= 'The l1 regularization to use for feature selection ' '(the estimation procedure is based on a debiased lasso).\n' ' - The auto option currently uses "aic" when less that 20% ' 'of the possible sample space is enumerated, otherwise it uses no regularization.\n' ' - The "aic" and "bic" options use the AIC and BIC rules for regularization.\n' ' - Integer selects a fix number of top features.\n' ' - float directly sets the "alpha" parameter of the sklearn.linear_model.Lasso model ' 'used for feature selection', style=style) options_map['l1_reg'] = l1_reg # class_to_explain (only if classification) if self.is_classification: class_to_explain = Dropdown( description='Class to plot:', options={val: e for e, val in enumerate(self.class_names)}, description_tooltip= 'For classification select a class for which the prediction will be explained', style=style) options_map['class_to_explain'] = class_to_explain grid[3, 1] = class_to_explain grid[0, 0] = plot_type grid[1, 0] = background_data grid[1, 1] = kmeans_count grid[0, 1] = link grid[2, 0] = nsamples grid[2, 1] = auto_nsamples grid[3, 0] = l1_reg return options_map, grid
class SubstrateTab(object): def __init__(self): self.output_dir = '.' # self.output_dir = 'tmpdir' self.figsize_width_substrate = 15.0 # allow extra for colormap self.figsize_height_substrate = 12.5 self.figsize_width_svg = 12.0 self.figsize_height_svg = 12.0 # self.fig = plt.figure(figsize=(7.2,6)) # this strange figsize results in a ~square contour plot self.first_time = True self.modulo = 1 self.use_defaults = True self.svg_delta_t = 1 self.substrate_delta_t = 1 self.svg_frame = 1 self.substrate_frame = 1 self.customized_output_freq = False self.therapy_activation_time = 1000000 self.max_svg_frame_pre_therapy = 1000000 self.max_substrate_frame_pre_therapy = 1000000 self.svg_xmin = 0 # Probably don't want to hardwire these if we allow changing the domain size # self.svg_xrange = 2000 # self.xmin = -1000. # self.xmax = 1000. # self.ymin = -1000. # self.ymax = 1000. # self.x_range = 2000. # self.y_range = 2000. self.show_nucleus = False self.show_edge = True # initial value self.field_index = 4 # self.field_index = self.mcds_field.value + 4 self.skip_cb = False # define dummy size of mesh (set in the tool's primary module) self.numx = 0 self.numy = 0 self.title_str = '' tab_height = '600px' tab_height = '500px' constWidth = '180px' constWidth2 = '150px' tab_layout = Layout(width='900px', # border='2px solid black', height=tab_height, ) #overflow_y='scroll') max_frames = 1 # self.mcds_plot = interactive(self.plot_substrate, frame=(0, max_frames), continuous_update=False) # self.i_plot = interactive(self.plot_plots, frame=(0, max_frames), continuous_update=False) self.i_plot = interactive(self.plot_substrate, frame=(0, max_frames), continuous_update=False) # "plot_size" controls the size of the tab height, not the plot (rf. figsize for that) # NOTE: the Substrates Plot tab has an extra row of widgets at the top of it (cf. Cell Plots tab) svg_plot_size = '700px' svg_plot_size = '600px' svg_plot_size = '700px' svg_plot_size = '900px' self.i_plot.layout.width = svg_plot_size self.i_plot.layout.height = svg_plot_size self.fontsize = 20 # description='# cell frames', self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='# frames', layout=Layout(width='160px'), ) self.max_frames.observe(self.update_max_frames) # self.field_min_max = {'dummy': [0., 1., False]} # NOTE: manually setting these for now (vs. parsing them out of data/initial.xml) self.field_min_max = {'director signal':[0.,1.,False], 'cargo signal':[0.,1.,False] } # hacky I know, but make a dict that's got (key,value) reversed from the dict in the Dropdown below # self.field_dict = {0:'dummy'} self.field_dict = {0:'director signal', 1:'cargo signal'} self.mcds_field = Dropdown( options={'director signal': 0, 'cargo signal':1}, value=0, # description='Field', layout=Layout(width=constWidth) ) # print("substrate __init__: self.mcds_field.value=",self.mcds_field.value) # self.mcds_field.observe(self.mcds_field_cb) self.mcds_field.observe(self.mcds_field_changed_cb) self.field_cmap = Dropdown( options=['viridis', 'jet', 'YlOrRd'], value='YlOrRd', # description='Field', layout=Layout(width=constWidth) ) # self.field_cmap.observe(self.plot_substrate) self.field_cmap.observe(self.mcds_field_cb) self.cmap_fixed_toggle = Checkbox( description='Fix', disabled=False, # layout=Layout(width=constWidth2), ) self.cmap_fixed_toggle.observe(self.mcds_field_cb) # def cmap_fixed_toggle_cb(b): # # self.update() # # self.field_min_max = {'oxygen': [0., 30.,True], 'glucose': [0., 1.,False]} # field_name = self.field_dict[self.mcds_field.value] # if (self.cmap_fixed_toggle.value): # self.field_min_max[field_name][0] = self.cmap_min.value # self.field_min_max[field_name][1] = self.cmap_max.value # self.field_min_max[field_name][2] = True # else: # # self.field_min_max[field_name][0] = self.cmap_min.value # # self.field_min_max[field_name][1] = self.cmap_max.value # self.field_min_max[field_name][2] = False # self.i_plot.update() # self.cmap_fixed_toggle.observe(cmap_fixed_toggle_cb) # self.save_min_max= Button( # description='Save', #style={'description_width': 'initial'}, # button_style='success', # 'success', 'info', 'warning', 'danger' or '' # tooltip='Save min/max for this substrate', # disabled=True, # layout=Layout(width='90px') # ) # def save_min_max_cb(b): # # field_name = self.mcds_field.options[] # # field_name = next(key for key, value in self.mcds_field.options.items() if value == self.mcds_field.value) # field_name = self.field_dict[self.mcds_field.value] # # print(field_name) # # self.field_min_max = {'oxygen': [0., 30.], 'glucose': [0., 1.], 'H+ ions': [0., 1.], 'ECM': [0., 1.], 'NP1': [0., 1.], 'NP2': [0., 1.]} # self.field_min_max[field_name][0] = self.cmap_min.value # self.field_min_max[field_name][1] = self.cmap_max.value # # print(self.field_min_max) # self.save_min_max.on_click(save_min_max_cb) self.cmap_min = FloatText( description='Min', value=0, step = 0.1, disabled=True, layout=Layout(width=constWidth2), ) self.cmap_min.observe(self.mcds_field_cb) self.cmap_max = FloatText( description='Max', value=38, step = 0.1, disabled=True, layout=Layout(width=constWidth2), ) self.cmap_max.observe(self.mcds_field_cb) def cmap_fixed_toggle_cb(b): field_name = self.field_dict[self.mcds_field.value] # print(self.cmap_fixed_toggle.value) if (self.cmap_fixed_toggle.value): # toggle on fixed range self.cmap_min.disabled = False self.cmap_max.disabled = False self.field_min_max[field_name][0] = self.cmap_min.value self.field_min_max[field_name][1] = self.cmap_max.value self.field_min_max[field_name][2] = True # self.save_min_max.disabled = False else: # toggle off fixed range self.cmap_min.disabled = True self.cmap_max.disabled = True self.field_min_max[field_name][2] = False # self.save_min_max.disabled = True # self.mcds_field_cb() self.i_plot.update() self.cmap_fixed_toggle.observe(cmap_fixed_toggle_cb) field_cmap_row2 = HBox([self.field_cmap, self.cmap_fixed_toggle]) # field_cmap_row3 = HBox([self.save_min_max, self.cmap_min, self.cmap_max]) items_auto = [ # self.save_min_max, #layout=Layout(flex='3 1 auto', width='auto'), self.cmap_min, self.cmap_max, ] box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='80%') field_cmap_row3 = Box(children=items_auto, layout=box_layout) # self.debug_str = Text( # value='debug info', # description='Debug:', # disabled=True, # layout=Layout(width='600px'), #constWidth = '180px' # ) #--------------------- self.cell_nucleus_toggle = Checkbox( description='nuclei', disabled=False, value = self.show_nucleus, # layout=Layout(width=constWidth2), ) def cell_nucleus_toggle_cb(b): # self.update() if (self.cell_nucleus_toggle.value): self.show_nucleus = True else: self.show_nucleus = False self.i_plot.update() self.cell_nucleus_toggle.observe(cell_nucleus_toggle_cb) #---- self.cell_edges_toggle = Checkbox( description='edges', disabled=False, value=self.show_edge, # layout=Layout(width=constWidth2), ) def cell_edges_toggle_cb(b): # self.update() if (self.cell_edges_toggle.value): self.show_edge = True else: self.show_edge = False self.i_plot.update() self.cell_edges_toggle.observe(cell_edges_toggle_cb) self.cells_toggle = Checkbox( description='Cells', disabled=False, value=True, # layout=Layout(width=constWidth2), ) def cells_toggle_cb(b): # self.update() self.i_plot.update() if (self.cells_toggle.value): self.cell_edges_toggle.disabled = False self.cell_nucleus_toggle.disabled = False else: self.cell_edges_toggle.disabled = True self.cell_nucleus_toggle.disabled = True self.cells_toggle.observe(cells_toggle_cb) #--------------------- self.substrates_toggle = Checkbox( description='Substrates', disabled=False, value=True, # layout=Layout(width=constWidth2), ) def substrates_toggle_cb(b): if (self.substrates_toggle.value): # seems bass-ackwards self.cmap_fixed_toggle.disabled = False self.cmap_min.disabled = False self.cmap_max.disabled = False self.mcds_field.disabled = False self.field_cmap.disabled = False else: self.cmap_fixed_toggle.disabled = True self.cmap_min.disabled = True self.cmap_max.disabled = True self.mcds_field.disabled = True self.field_cmap.disabled = True self.substrates_toggle.observe(substrates_toggle_cb) self.grid_toggle = Checkbox( description='grid', disabled=False, value=True, # layout=Layout(width=constWidth2), ) def grid_toggle_cb(b): # self.update() self.i_plot.update() self.grid_toggle.observe(grid_toggle_cb) # field_cmap_row3 = Box([self.save_min_max, self.cmap_min, self.cmap_max]) # mcds_tab = widgets.VBox([mcds_dir, mcds_plot, mcds_play], layout=tab_layout) # mcds_params = VBox([self.mcds_field, field_cmap_row2, field_cmap_row3, self.max_frames]) # mcds_dir # mcds_params = VBox([self.mcds_field, field_cmap_row2, field_cmap_row3,]) # mcds_dir # self.tab = HBox([mcds_params, self.mcds_plot], layout=tab_layout) help_label = Label('select slider: drag or left/right arrows') # row1 = Box([help_label, Box( [self.max_frames, self.mcds_field, self.field_cmap], layout=Layout(border='0px solid black', row1a = Box( [self.max_frames, self.mcds_field, self.field_cmap], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) row1b = Box( [self.cells_toggle, self.cell_nucleus_toggle, self.cell_edges_toggle], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) row1 = HBox( [row1a, Label('.....'), row1b]) row2a = Box([self.cmap_fixed_toggle, self.cmap_min, self.cmap_max], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) # row2b = Box( [self.substrates_toggle, self.grid_toggle], layout=Layout(border='1px solid black', row2b = Box( [self.substrates_toggle, ], layout=Layout(border='1px solid black', width='50%', height='', align_items='stretch', flex_direction='row', display='flex')) # row2 = HBox( [row2a, self.substrates_toggle, self.grid_toggle]) row2 = HBox( [row2a, Label('.....'), row2b]) if (hublib_flag): self.download_button = Download('mcds.zip', style='warning', icon='cloud-download', tooltip='Download data', cb=self.download_cb) self.download_svg_button = Download('svg.zip', style='warning', icon='cloud-download', tooltip='You need to allow pop-ups in your browser', cb=self.download_svg_cb) download_row = HBox([self.download_button.w, self.download_svg_button.w, Label("Download all cell plots (browser must allow pop-ups).")]) # box_layout = Layout(border='0px solid') controls_box = VBox([row1, row2]) # ,width='50%', layout=box_layout) self.tab = VBox([controls_box, self.i_plot, download_row]) # self.tab = VBox([controls_box, self.debug_str, self.i_plot, download_row]) else: # self.tab = VBox([row1, row2]) self.tab = VBox([row1, row2, self.i_plot]) #--------------------------------------------------- def update_dropdown_fields(self, data_dir): # print('update_dropdown_fields called --------') self.output_dir = data_dir tree = None try: fname = os.path.join(self.output_dir, "initial.xml") tree = ET.parse(fname) xml_root = tree.getroot() except: print("Cannot open ",fname," to read info, e.g., names of substrate fields.") return xml_root = tree.getroot() self.field_min_max = {} self.field_dict = {} dropdown_options = {} uep = xml_root.find('.//variables') comment_str = "" field_idx = 0 if (uep): for elm in uep.findall('variable'): # print("-----> ",elm.attrib['name']) field_name = elm.attrib['name'] self.field_min_max[field_name] = [0., 1., False] self.field_dict[field_idx] = field_name dropdown_options[field_name] = field_idx self.field_min_max[field_name][0] = 0 self.field_min_max[field_name][1] = 1 # self.field_min_max[field_name][0] = field_idx #rwh: helps debug # self.field_min_max[field_name][1] = field_idx+1 self.field_min_max[field_name][2] = False field_idx += 1 # constWidth = '180px' # print('options=',dropdown_options) # print(self.field_min_max) # debug self.mcds_field.value = 0 self.mcds_field.options = dropdown_options # self.mcds_field = Dropdown( # # options={'oxygen': 0, 'glucose': 1}, # options=dropdown_options, # value=0, # # description='Field', # layout=Layout(width=constWidth) # ) # def update_max_frames_expected(self, value): # called when beginning an interactive Run # self.max_frames.value = value # assumes naming scheme: "snapshot%08d.svg" # self.mcds_plot.children[0].max = self.max_frames.value #------------------------------------------------------------------------------ def update_params(self, config_tab, user_params_tab): # xml_root.find(".//x_min").text = str(self.xmin.value) # xml_root.find(".//x_max").text = str(self.xmax.value) # xml_root.find(".//dx").text = str(self.xdelta.value) # xml_root.find(".//y_min").text = str(self.ymin.value) # xml_root.find(".//y_max").text = str(self.ymax.value) # xml_root.find(".//dy").text = str(self.ydelta.value) # xml_root.find(".//z_min").text = str(self.zmin.value) # xml_root.find(".//z_max").text = str(self.zmax.value) # xml_root.find(".//dz").text = str(self.zdelta.value) self.xmin = config_tab.xmin.value self.xmax = config_tab.xmax.value self.x_range = self.xmax - self.xmin self.svg_xrange = self.xmax - self.xmin self.ymin = config_tab.ymin.value self.ymax = config_tab.ymax.value self.y_range = self.ymax - self.ymin self.numx = math.ceil( (self.xmax - self.xmin) / config_tab.xdelta.value) self.numy = math.ceil( (self.ymax - self.ymin) / config_tab.ydelta.value) if (self.x_range > self.y_range): ratio = self.y_range / self.x_range self.figsize_width_substrate = 15.0 # allow extra for colormap self.figsize_height_substrate = 12.5 * ratio self.figsize_width_svg = 12.0 self.figsize_height_svg = 12.0 * ratio else: # x < y ratio = self.x_range / self.y_range self.figsize_width_substrate = 15.0 * ratio self.figsize_height_substrate = 12.5 self.figsize_width_svg = 12.0 * ratio self.figsize_height_svg = 12.0 self.svg_flag = config_tab.toggle_svg.value self.substrates_flag = config_tab.toggle_mcds.value # print("substrates: update_params(): svg_flag, toggle=",self.svg_flag,config_tab.toggle_svg.value) # print("substrates: update_params(): self.substrates_flag = ",self.substrates_flag) self.svg_delta_t = config_tab.svg_interval.value self.substrate_delta_t = config_tab.mcds_interval.value self.modulo = int(self.substrate_delta_t / self.svg_delta_t) # print("substrates: update_params(): modulo=",self.modulo) if self.customized_output_freq: # self.therapy_activation_time = user_params_tab.therapy_activation_time.value # NOTE: edit for user param name # print("substrates: update_params(): therapy_activation_time=",self.therapy_activation_time) self.max_svg_frame_pre_therapy = int(self.therapy_activation_time/self.svg_delta_t) self.max_substrate_frame_pre_therapy = int(self.therapy_activation_time/self.substrate_delta_t) #------------------------------------------------------------------------------ # def update(self, rdir): # Called from driver module (e.g., pc4*.py) (among other places?) def update(self, rdir=''): # with debug_view: # print("substrates: update rdir=", rdir) # print("substrates: update rdir=", rdir) if rdir: self.output_dir = rdir # print('update(): self.output_dir = ', self.output_dir) if self.first_time: # if True: self.first_time = False full_xml_filename = Path(os.path.join(self.output_dir, 'config.xml')) # print("substrates: update(), config.xml = ",full_xml_filename) # self.num_svgs = len(glob.glob(os.path.join(self.output_dir, 'snap*.svg'))) # self.num_substrates = len(glob.glob(os.path.join(self.output_dir, 'output*.xml'))) # print("substrates: num_svgs,num_substrates =",self.num_svgs,self.num_substrates) # argh - no! If no files created, then denom = -1 # self.modulo = int((self.num_svgs - 1) / (self.num_substrates - 1)) # print("substrates: update(): modulo=",self.modulo) if full_xml_filename.is_file(): tree = ET.parse(full_xml_filename) # this file cannot be overwritten; part of tool distro xml_root = tree.getroot() self.svg_delta_t = int(xml_root.find(".//SVG//interval").text) self.substrate_delta_t = int(xml_root.find(".//full_data//interval").text) # print("substrates: svg,substrate delta_t values=",self.svg_delta_t,self.substrate_delta_t) self.modulo = int(self.substrate_delta_t / self.svg_delta_t) # print("substrates: update(): modulo=",self.modulo) # all_files = sorted(glob.glob(os.path.join(self.output_dir, 'output*.xml'))) # if the substrates/MCDS all_files = sorted(glob.glob(os.path.join(self.output_dir, 'snap*.svg'))) # if .svg if len(all_files) > 0: last_file = all_files[-1] self.max_frames.value = int(last_file[-12:-4]) # assumes naming scheme: "snapshot%08d.svg" else: substrate_files = sorted(glob.glob(os.path.join(self.output_dir, 'output*.xml'))) if len(substrate_files) > 0: last_file = substrate_files[-1] self.max_frames.value = int(last_file[-12:-4]) def download_svg_cb(self): file_str = os.path.join(self.output_dir, '*.svg') # print('zip up all ',file_str) with zipfile.ZipFile('svg.zip', 'w') as myzip: for f in glob.glob(file_str): myzip.write(f, os.path.basename(f)) # 2nd arg avoids full filename path in the archive def download_cb(self): file_xml = os.path.join(self.output_dir, '*.xml') file_mat = os.path.join(self.output_dir, '*.mat') # print('zip up all ',file_str) with zipfile.ZipFile('mcds.zip', 'w') as myzip: for f in glob.glob(file_xml): myzip.write(f, os.path.basename(f)) # 2nd arg avoids full filename path in the archive for f in glob.glob(file_mat): myzip.write(f, os.path.basename(f)) def update_max_frames(self,_b): self.i_plot.children[0].max = self.max_frames.value def dummy_cb(self, b): return # called if user selected different substrate in dropdown def mcds_field_changed_cb(self, b): # print("mcds_field_changed_cb: self.mcds_field.value=",self.mcds_field.value) if (self.mcds_field.value == None): return self.field_index = self.mcds_field.value + 4 field_name = self.field_dict[self.mcds_field.value] # print('mcds_field_changed_cb: field_name='+ field_name) # print(self.field_min_max[field_name]) # self.debug_str.value = 'mcds_field_changed_cb: '+ field_name + str(self.field_min_max[field_name]) # self.debug_str.value = 'cb1: '+ str(self.field_min_max) # BEWARE of these triggering the mcds_field_cb() callback! Hence, the "skip_cb" self.skip_cb = True self.cmap_min.value = self.field_min_max[field_name][0] self.cmap_max.value = self.field_min_max[field_name][1] self.cmap_fixed_toggle.value = bool(self.field_min_max[field_name][2]) self.skip_cb = False self.i_plot.update() # called if user provided different min/max values for colormap, or a different colormap def mcds_field_cb(self, b): if self.skip_cb: return self.field_index = self.mcds_field.value + 4 field_name = self.field_dict[self.mcds_field.value] # print('mcds_field_cb: field_name='+ field_name) # print('mcds_field_cb: '+ field_name) self.field_min_max[field_name][0] = self.cmap_min.value self.field_min_max[field_name][1] = self.cmap_max.value self.field_min_max[field_name][2] = self.cmap_fixed_toggle.value # print(self.field_min_max[field_name]) # self.debug_str.value = 'mcds_field_cb: ' + field_name + str(self.field_min_max[field_name]) # self.debug_str.value = 'cb2: '+ str(self.field_min_max) # print('--- cb2: '+ str(self.field_min_max)) #rwh2 # self.cmap_fixed_toggle.value = self.field_min_max[field_name][2] # field_name = self.mcds_field.options[self.mcds_field.value] # self.cmap_min.value = self.field_min_max[field_name][0] # oxygen, etc # self.cmap_max.value = self.field_min_max[field_name][1] # oxygen, etc # self.field_index = self.mcds_field.value + 4 # print('field_index=',self.field_index) self.i_plot.update() #--------------------------------------------------------------------------- def circles(self, x, y, s, c='b', vmin=None, vmax=None, **kwargs): """ See https://gist.github.com/syrte/592a062c562cd2a98a83 Make a scatter plot of circles. Similar to plt.scatter, but the size of circles are in data scale. Parameters ---------- x, y : scalar or array_like, shape (n, ) Input data s : scalar or array_like, shape (n, ) Radius of circles. c : color or sequence of color, optional, default : 'b' `c` can be a single color format string, or a sequence of color specifications of length `N`, or a sequence of `N` numbers to be mapped to colors using the `cmap` and `norm` specified via kwargs. Note that `c` should not be a single numeric RGB or RGBA sequence because that is indistinguishable from an array of values to be colormapped. (If you insist, use `color` instead.) `c` can be a 2-D array in which the rows are RGB or RGBA, however. vmin, vmax : scalar, optional, default: None `vmin` and `vmax` are used in conjunction with `norm` to normalize luminance data. If either are `None`, the min and max of the color array is used. kwargs : `~matplotlib.collections.Collection` properties Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls), norm, cmap, transform, etc. Returns ------- paths : `~matplotlib.collections.PathCollection` Examples -------- a = np.arange(11) circles(a, a, s=a*0.2, c=a, alpha=0.5, ec='none') plt.colorbar() License -------- This code is under [The BSD 3-Clause License] (http://opensource.org/licenses/BSD-3-Clause) """ if np.isscalar(c): kwargs.setdefault('color', c) c = None if 'fc' in kwargs: kwargs.setdefault('facecolor', kwargs.pop('fc')) if 'ec' in kwargs: kwargs.setdefault('edgecolor', kwargs.pop('ec')) if 'ls' in kwargs: kwargs.setdefault('linestyle', kwargs.pop('ls')) if 'lw' in kwargs: kwargs.setdefault('linewidth', kwargs.pop('lw')) # You can set `facecolor` with an array for each patch, # while you can only set `facecolors` with a value for all. zipped = np.broadcast(x, y, s) patches = [Circle((x_, y_), s_) for x_, y_, s_ in zipped] collection = PatchCollection(patches, **kwargs) if c is not None: c = np.broadcast_to(c, zipped.shape).ravel() collection.set_array(c) collection.set_clim(vmin, vmax) ax = plt.gca() ax.add_collection(collection) ax.autoscale_view() # plt.draw_if_interactive() if c is not None: plt.sci(collection) # return collection #------------------------------------------------------------ # def plot_svg(self, frame, rdel=''): def plot_svg(self, frame): # global current_idx, axes_max global current_frame current_frame = frame fname = "snapshot%08d.svg" % frame full_fname = os.path.join(self.output_dir, fname) # with debug_view: # print("plot_svg:", full_fname) # print("-- plot_svg:", full_fname) if not os.path.isfile(full_fname): print("Once output files are generated, click the slider.") return xlist = deque() ylist = deque() rlist = deque() rgb_list = deque() # print('\n---- ' + fname + ':') # tree = ET.parse(fname) tree = ET.parse(full_fname) root = tree.getroot() # print('--- root.tag ---') # print(root.tag) # print('--- root.attrib ---') # print(root.attrib) # print('--- child.tag, child.attrib ---') numChildren = 0 for child in root: # print(child.tag, child.attrib) # print("keys=",child.attrib.keys()) if self.use_defaults and ('width' in child.attrib.keys()): self.axes_max = float(child.attrib['width']) # print("debug> found width --> axes_max =", axes_max) if child.text and "Current time" in child.text: svals = child.text.split() # remove the ".00" on minutes self.title_str += " cells: " + svals[2] + "d, " + svals[4] + "h, " + svals[7][:-3] + "m" # self.cell_time_mins = int(svals[2])*1440 + int(svals[4])*60 + int(svals[7][:-3]) # self.title_str += " cells: " + str(self.cell_time_mins) + "m" # rwh # print("width ",child.attrib['width']) # print('attrib=',child.attrib) # if (child.attrib['id'] == 'tissue'): if ('id' in child.attrib.keys()): # print('-------- found tissue!!') tissue_parent = child break # print('------ search tissue') cells_parent = None for child in tissue_parent: # print('attrib=',child.attrib) if (child.attrib['id'] == 'cells'): # print('-------- found cells, setting cells_parent') cells_parent = child break numChildren += 1 num_cells = 0 # print('------ search cells') for child in cells_parent: # print(child.tag, child.attrib) # print('attrib=',child.attrib) for circle in child: # two circles in each child: outer + nucleus # circle.attrib={'cx': '1085.59','cy': '1225.24','fill': 'rgb(159,159,96)','r': '6.67717','stroke': 'rgb(159,159,96)','stroke-width': '0.5'} # print(' --- cx,cy=',circle.attrib['cx'],circle.attrib['cy']) xval = float(circle.attrib['cx']) # map SVG coords into comp domain # xval = (xval-self.svg_xmin)/self.svg_xrange * self.x_range + self.xmin xval = xval/self.x_range * self.x_range + self.xmin s = circle.attrib['fill'] # print("s=",s) # print("type(s)=",type(s)) if (s[0:3] == "rgb"): # if an rgb string, e.g. "rgb(175,175,80)" rgb = list(map(int, s[4:-1].split(","))) rgb[:] = [x / 255. for x in rgb] else: # otherwise, must be a color name rgb_tuple = mplc.to_rgb(mplc.cnames[s]) # a tuple rgb = [x for x in rgb_tuple] # test for bogus x,y locations (rwh TODO: use max of domain?) too_large_val = 10000. if (np.fabs(xval) > too_large_val): print("bogus xval=", xval) break yval = float(circle.attrib['cy']) # yval = (yval - self.svg_xmin)/self.svg_xrange * self.y_range + self.ymin yval = yval/self.y_range * self.y_range + self.ymin if (np.fabs(yval) > too_large_val): print("bogus xval=", xval) break rval = float(circle.attrib['r']) # if (rgb[0] > rgb[1]): # print(num_cells,rgb, rval) xlist.append(xval) ylist.append(yval) rlist.append(rval) rgb_list.append(rgb) # For .svg files with cells that *have* a nucleus, there will be a 2nd if (not self.show_nucleus): #if (not self.show_nucleus): break num_cells += 1 # if num_cells > 3: # for debugging # print(fname,': num_cells= ',num_cells," --- debug exit.") # sys.exit(1) # break # print(fname,': num_cells= ',num_cells) xvals = np.array(xlist) yvals = np.array(ylist) rvals = np.array(rlist) rgbs = np.array(rgb_list) # print("xvals[0:5]=",xvals[0:5]) # print("rvals[0:5]=",rvals[0:5]) # print("rvals.min, max=",rvals.min(),rvals.max()) # rwh - is this where I change size of render window?? (YES - yipeee!) # plt.figure(figsize=(6, 6)) # plt.cla() # if (self.substrates_toggle.value): self.title_str += " (" + str(num_cells) + " agents)" # title_str = " (" + str(num_cells) + " agents)" # else: # mins= round(int(float(root.find(".//current_time").text))) # TODO: check units = mins # hrs = int(mins/60) # days = int(hrs/24) # title_str = '%dd, %dh, %dm' % (int(days),(hrs%24), mins - (hrs*60)) plt.title(self.title_str) plt.xlim(self.xmin, self.xmax) plt.ylim(self.ymin, self.ymax) # plt.xlim(axes_min,axes_max) # plt.ylim(axes_min,axes_max) # plt.scatter(xvals,yvals, s=rvals*scale_radius, c=rgbs) # TODO: make figsize a function of plot_size? What about non-square plots? # self.fig = plt.figure(figsize=(9, 9)) # axx = plt.axes([0, 0.05, 0.9, 0.9]) # left, bottom, width, height # axx = fig.gca() # print('fig.dpi=',fig.dpi) # = 72 # im = ax.imshow(f.reshape(100,100), interpolation='nearest', cmap=cmap, extent=[0,20, 0,20]) # ax.xlim(axes_min,axes_max) # ax.ylim(axes_min,axes_max) # convert radii to radii in pixels # ax2 = self.fig.gca() # N = len(xvals) # rr_pix = (ax2.transData.transform(np.vstack([rvals, rvals]).T) - # ax2.transData.transform(np.vstack([np.zeros(N), np.zeros(N)]).T)) # rpix, _ = rr_pix.T # markers_size = (144. * rpix / self.fig.dpi)**2 # = (2*rpix / fig.dpi * 72)**2 # markers_size = markers_size/4000000. # print('max=',markers_size.max()) #rwh - temp fix - Ah, error only occurs when "edges" is toggled on if (self.show_edge): try: # plt.scatter(xvals,yvals, s=markers_size, c=rgbs, edgecolor='black', linewidth=0.5) self.circles(xvals,yvals, s=rvals, color=rgbs, edgecolor='black', linewidth=0.5) # cell_circles = self.circles(xvals,yvals, s=rvals, color=rgbs, edgecolor='black', linewidth=0.5) # plt.sci(cell_circles) except (ValueError): pass else: # plt.scatter(xvals,yvals, s=markers_size, c=rgbs) self.circles(xvals,yvals, s=rvals, color=rgbs) # if (self.show_tracks): # for key in self.trackd.keys(): # xtracks = self.trackd[key][:,0] # ytracks = self.trackd[key][:,1] # plt.plot(xtracks[0:frame],ytracks[0:frame], linewidth=5) # plt.xlim(self.axes_min, self.axes_max) # plt.ylim(self.axes_min, self.axes_max) # ax.grid(False) # axx.set_title(title_str) # plt.title(title_str) #--------------------------------------------------------------------------- # assume "frame" is cell frame #, unless Cells is togggled off, then it's the substrate frame # # def plot_substrate(self, frame, grid): def plot_substrate(self, frame): # global current_idx, axes_max, gFileId, field_index # print("plot_substrate(): frame*self.substrate_delta_t = ",frame*self.substrate_delta_t) # print("plot_substrate(): frame*self.svg_delta_t = ",frame*self.svg_delta_t) self.title_str = '' # Recall: # self.svg_delta_t = config_tab.svg_interval.value # self.substrate_delta_t = config_tab.mcds_interval.value # self.modulo = int(self.substrate_delta_t / self.svg_delta_t) # self.therapy_activation_time = user_params_tab.therapy_activation_time.value # print("plot_substrate(): pre_therapy: max svg, substrate frames = ",max_svg_frame_pre_therapy, max_substrate_frame_pre_therapy) # Assume: # .svg files >= # substrate files # if (self.cells_toggle.value): # if (self.substrates_toggle.value and frame*self.substrate_delta_t <= self.svg_frame*self.svg_delta_t): # if (self.substrates_toggle.value and (frame % self.modulo == 0)): if (self.substrates_toggle.value): # self.fig = plt.figure(figsize=(14, 15.6)) # self.fig = plt.figure(figsize=(15.0, 12.5)) self.fig = plt.figure(figsize=(self.figsize_width_substrate, self.figsize_height_substrate)) # rwh - funky way to figure out substrate frame for pc4cancerbots (due to user-defined "save_interval*") # self.cell_time_mins # self.substrate_frame = int(frame / self.modulo) if (self.customized_output_freq and (frame > self.max_svg_frame_pre_therapy)): # max_svg_frame_pre_therapy = int(self.therapy_activation_time/self.svg_delta_t) # max_substrate_frame_pre_therapy = int(self.therapy_activation_time/self.substrate_delta_t) self.substrate_frame = self.max_substrate_frame_pre_therapy + (frame - self.max_svg_frame_pre_therapy) else: self.substrate_frame = int(frame / self.modulo) # print("plot_substrate(): self.substrate_frame=",self.substrate_frame) # if (self.substrate_frame > (self.num_substrates-1)): # self.substrate_frame = self.num_substrates-1 # print('self.substrate_frame = ',self.substrate_frame) # if (self.cells_toggle.value): # self.modulo = int((self.num_svgs - 1) / (self.num_substrates - 1)) # self.substrate_frame = frame % self.modulo # else: # self.substrate_frame = frame fname = "output%08d_microenvironment0.mat" % self.substrate_frame xml_fname = "output%08d.xml" % self.substrate_frame # fullname = output_dir_str + fname # fullname = fname full_fname = os.path.join(self.output_dir, fname) # print("--- plot_substrate(): full_fname=",full_fname) full_xml_fname = os.path.join(self.output_dir, xml_fname) # self.output_dir = '.' # if not os.path.isfile(fullname): if not os.path.isfile(full_fname): print("Once output files are generated, click the slider.") # No: output00000000_microenvironment0.mat return # tree = ET.parse(xml_fname) tree = ET.parse(full_xml_fname) xml_root = tree.getroot() mins = round(int(float(xml_root.find(".//current_time").text))) # TODO: check units = mins self.substrate_mins= round(int(float(xml_root.find(".//current_time").text))) # TODO: check units = mins hrs = int(mins/60) days = int(hrs/24) self.title_str = 'substrate: %dd, %dh, %dm' % (int(days),(hrs%24), mins - (hrs*60)) # self.title_str = 'substrate: %dm' % (mins ) # rwh info_dict = {} # scipy.io.loadmat(fullname, info_dict) scipy.io.loadmat(full_fname, info_dict) M = info_dict['multiscale_microenvironment'] # global_field_index = int(mcds_field.value) # print('plot_substrate: field_index =',field_index) f = M[self.field_index, :] # 4=tumor cells field, 5=blood vessel density, 6=growth substrate # plt.clf() # my_plot = plt.imshow(f.reshape(400,400), cmap='jet', extent=[0,20, 0,20]) # self.fig = plt.figure(figsize=(18.0,15)) # this strange figsize results in a ~square contour plot # plt.subplot(grid[0:1, 0:1]) # main_ax = self.fig.add_subplot(grid[0:1, 0:1]) # works, but tiny upper-left region #main_ax = self.fig.add_subplot(grid[0:2, 0:2]) # main_ax = self.fig.add_subplot(grid[0:, 0:2]) #main_ax = self.fig.add_subplot(grid[:-1, 0:]) # nrows, ncols #main_ax = self.fig.add_subplot(grid[0:, 0:]) # nrows, ncols #main_ax = self.fig.add_subplot(grid[0:4, 0:]) # nrows, ncols # main_ax = self.fig.add_subplot(grid[0:3, 0:]) # nrows, ncols # main_ax = self.fig.add_subplot(111) # nrows, ncols # plt.rc('font', size=10) # TODO: does this affect the Cell plots fonts too? YES. Not what we want. # fig.set_tight_layout(True) # ax = plt.axes([0, 0.05, 0.9, 0.9 ]) #left, bottom, width, height # ax = plt.axes([0, 0.0, 1, 1 ]) # cmap = plt.cm.viridis # Blues, YlOrBr, ... # im = ax.imshow(f.reshape(100,100), interpolation='nearest', cmap=cmap, extent=[0,20, 0,20]) # ax.grid(False) # print("substrates.py: ------- numx, numy = ", self.numx, self.numy ) # if (self.numx == 0): # need to parse vals from the config.xml # # print("--- plot_substrate(): full_fname=",full_fname) # fname = os.path.join(self.output_dir, "config.xml") # tree = ET.parse(fname) # xml_root = tree.getroot() # self.xmin = float(xml_root.find(".//x_min").text) # self.xmax = float(xml_root.find(".//x_max").text) # dx = float(xml_root.find(".//dx").text) # self.ymin = float(xml_root.find(".//y_min").text) # self.ymax = float(xml_root.find(".//y_max").text) # dy = float(xml_root.find(".//dy").text) # self.numx = math.ceil( (self.xmax - self.xmin) / dx) # self.numy = math.ceil( (self.ymax - self.ymin) / dy) try: xgrid = M[0, :].reshape(self.numy, self.numx) ygrid = M[1, :].reshape(self.numy, self.numx) except: print("substrates.py: mismatched mesh size for reshape: numx,numy=",self.numx, self.numy) pass # xgrid = M[0, :].reshape(self.numy, self.numx) # ygrid = M[1, :].reshape(self.numy, self.numx) num_contours = 15 levels = MaxNLocator(nbins=num_contours).tick_values(self.cmap_min.value, self.cmap_max.value) contour_ok = True if (self.cmap_fixed_toggle.value): try: # substrate_plot = main_ax.contourf(xgrid, ygrid, M[self.field_index, :].reshape(self.numy, self.numx), levels=levels, extend='both', cmap=self.field_cmap.value, fontsize=self.fontsize) substrate_plot = plt.contourf(xgrid, ygrid, M[self.field_index, :].reshape(self.numy, self.numx), levels=levels, extend='both', cmap=self.field_cmap.value, fontsize=self.fontsize) except: contour_ok = False # print('got error on contourf 1.') else: try: # substrate_plot = main_ax.contourf(xgrid, ygrid, M[self.field_index, :].reshape(self.numy,self.numx), num_contours, cmap=self.field_cmap.value) substrate_plot = plt.contourf(xgrid, ygrid, M[self.field_index, :].reshape(self.numy,self.numx), num_contours, cmap=self.field_cmap.value) except: contour_ok = False # print('got error on contourf 2.') if (contour_ok): # main_ax.set_title(self.title_str, fontsize=self.fontsize) plt.title(self.title_str, fontsize=self.fontsize) # main_ax.tick_params(labelsize=self.fontsize) # cbar = plt.colorbar(my_plot) # cbar = self.fig.colorbar(substrate_plot, ax=main_ax) cbar = self.fig.colorbar(substrate_plot) cbar.ax.tick_params(labelsize=self.fontsize) # cbar = main_ax.colorbar(my_plot) # cbar.ax.tick_params(labelsize=self.fontsize) # axes_min = 0 # axes_max = 2000 # main_ax.set_xlim([self.xmin, self.xmax]) # main_ax.set_ylim([self.ymin, self.ymax]) plt.xlim(self.xmin, self.xmax) plt.ylim(self.ymin, self.ymax) # if (frame == 0): # maybe allow substrate grid display later # xs = np.linspace(self.xmin,self.xmax,self.numx) # ys = np.linspace(self.ymin,self.ymax,self.numy) # hlines = np.column_stack(np.broadcast_arrays(xs[0], ys, xs[-1], ys)) # vlines = np.column_stack(np.broadcast_arrays(xs, ys[0], xs, ys[-1])) # grid_lines = np.concatenate([hlines, vlines]).reshape(-1, 2, 2) # line_collection = LineCollection(grid_lines, color="gray", linewidths=0.5) # # ax = main_ax.gca() # main_ax.add_collection(line_collection) # # ax.set_xlim(xs[0], xs[-1]) # # ax.set_ylim(ys[0], ys[-1]) # Now plot the cells (possibly on top of the substrate) if (self.cells_toggle.value): if (not self.substrates_toggle.value): # self.fig = plt.figure(figsize=(12, 12)) self.fig = plt.figure(figsize=(self.figsize_width_svg, self.figsize_height_svg)) # self.plot_svg(frame) self.svg_frame = frame # print('plot_svg with frame=',self.svg_frame) self.plot_svg(self.svg_frame)
def __init__(self, nb_rows, limit=50, *args, **kwargs): """ Parameters ---------- nb_rows: int total number of rows in the result set. limit: int number of rows to display in a page. """ super().__init__(*args, **kwargs) self.__nb_rows = nb_rows if nb_rows else 1 self.page = 1 self.limit = (limit if limit and limit > 0 and limit < PaginationWidget.MAX_LIMIT else PaginationWidget.DEFAULT_LIMIT) self.layout.width = "400px" if nb_rows <= limit: self.layout.visibility = "hidden" else: self.layout.visibility = "visible" nb_pages = self._get_nb_pages(self.limit) # widget to set page number self.__page_widget = BoundedIntText( value=self.page, min=1, max=nb_pages, step=1, continuous_update=True, description="page", description_tooltip="Current page", disabled=False, style={"description_width": "30px"}, layout=Layout(width="90px", max_width="90px"), ) # widget to display total number of pages. self.__label_slash = Label(value=f"/ {nb_pages}", layout=Layout(width="60px")) # widget to set limit self.__limit_widget = BoundedIntText( value=self.limit, min=1, max=PaginationWidget.MAX_LIMIT, step=1, continuous_update=True, description="rows", description_tooltip= f"Number of rows per page. Max. possible: {PaginationWidget.MAX_LIMIT}", disabled=False, style={"description_width": "30px"}, layout=Layout(width="90px", max_width="90px"), ) self.__page_widget.observe(self._page_widget_changed, names="value") self.__limit_widget.observe(self._limit_widget_changed, names="value") self.children = [ self.__page_widget, self.__label_slash, self.__limit_widget, ]