def _field_folder(self, fields, **kwargs): folder = super(UniverseWidget, self)._field_folder(**kwargs) folder.deactivate('nx', 'ny', 'nz') fopts = Dropdown(options=fields) def _fopts(c): for scn in self.active(): scn.field_idx = c.new fopts.observe(_fopts, names='value') folder['fopts'] = fopts return folder
def _field_folder(self, **kwargs): """Folder that houses field GUI controls.""" folder = super(DemoContainer, self)._field_folder(**kwargs) fopts = Dropdown(options=['null', 'Sphere', 'Torus', 'Ellipsoid']) fopts.active = True fopts.disabled = False def _field(c): for scn in self.active(): scn.field = c.new fopts.observe(_field, names='value') folder.insert(1, 'options', fopts) return folder
def _make_repr_name_choices(self, component_slider, repr_slider): repr_choices = Dropdown(options=[" ",]) def on_chose(change): repr_name = change['new'] repr_index = repr_choices.options.index(repr_name) repr_slider.value = repr_index repr_choices.observe(on_chose, names='value') repr_choices.layout.width = default.DEFAULT_TEXT_WIDTH self.widget_repr_choices = repr_choices return self.widget_repr_choices
class NGLDisplay: """Structure display class Provides basic structure/trajectory display in the notebook and optional gui which can be used to enhance its usability. It is also possible to extend the functionality of the particular instance of the viewer by adding further widgets manipulating the structure. """ def __init__(self, atoms, xsize=500, ysize=500): import nglview from ipywidgets import Dropdown, FloatSlider, IntSlider, HBox, VBox self.atoms = atoms if isinstance(atoms[0], Atoms): # Assume this is a trajectory or struct list self.view = nglview.show_asetraj(atoms) self.frm = IntSlider(value=0, min=0, max=len(atoms) - 1) self.frm.observe(self._update_frame) self.struct = atoms[0] else: # Assume this is just a single structure self.view = nglview.show_ase(atoms) self.struct = atoms self.frm = None self.colors = {} self.view._remote_call('setSize', target='Widget', args=['%dpx' % (xsize,), '%dpx' % (ysize,)]) self.view.add_unitcell() self.view.add_spacefill() self.view.camera = 'orthographic' self.view.update_spacefill(radiusType='covalent', scale=0.7) self.view.center() self.asel = Dropdown(options=['All'] + list(set(self.struct.get_chemical_symbols())), value='All', description='Show') self.rad = FloatSlider(value=0.8, min=0.0, max=1.5, step=0.01, description='Ball size') self.asel.observe(self._select_atom) self.rad.observe(self._update_repr) wdg = [self.asel, self.rad] if self.frm: wdg.append(self.frm) self.gui = HBox([self.view, VBox(wdg)]) # Make useful shortcuts for the user of the class self.gui.view = self.view self.gui.control_box = self.gui.children[1] self.gui.custom_colors = self.custom_colors def _update_repr(self, chg=None): self.view.update_spacefill(radiusType='covalent', scale=self.rad.value) def _update_frame(self, chg=None): self.view.frame = self.frm.value return def _select_atom(self, chg=None): sel = self.asel.value self.view.remove_spacefill() for e in set(self.struct.get_chemical_symbols()): if (sel == 'All' or e == sel): if e in self.colors: self.view.add_spacefill(selection='#' + e, color=self.colors[e]) else: self.view.add_spacefill(selection='#' + e) self._update_repr() def custom_colors(self, clr=None): """ Define custom colors for some atoms. Pass a dictionary of the form {'Fe':'red', 'Au':'yellow'} to the function. To reset the map to default call the method without parameters. """ if clr: self.colors = clr else: self.colors = {} self._select_atom()
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.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 # define dummy size of mesh (set in the tool's primary module) self.numx = 0 self.numy = 0 tab_height = '500px' tab_height = '700px' 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 = '900px' svg_plot_size = '600px' svg_plot_size = '500px' 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='90%') 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, self.max_frames], layout=tab_layout) # 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')) if (hublib_flag): 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]) else: # self.tab = VBox([row1, row2]) self.tab = VBox([row1, row2, self.mcds_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']) 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("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) # print("substrates.py: ------- numx, numy = ", self.numx, self.numy ) if (self.numx == 0): # need to parse vals from the config.xml fname = os.path.join(self.output_dir, "config.xml") tree = ET.parse(fname) xml_root = tree.getroot() xmin = float(xml_root.find(".//x_min").text) xmax = float(xml_root.find(".//x_max").text) dx = float(xml_root.find(".//dx").text) ymin = float(xml_root.find(".//y_min").text) ymax = float(xml_root.find(".//y_max").text) dy = float(xml_root.find(".//dy").text) self.numx = math.ceil( (xmax - xmin) / dx) self.numy = math.ceil( (ymax - ymin) / dy) 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.value): try: my_plot = plt.contourf(xgrid, ygrid, M[self.field_index, :].reshape(self.numy, self.numx), levels=levels, extend='both', cmap=self.field_cmap.value) except: contour_ok = False # print('got error on contourf 1.') else: try: my_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): plt.title(title_str) plt.colorbar(my_plot) axes_min = 0 axes_max = 2000
class MLSection: def __init__(self): self.data = pickle.load(open('all_data.pkl', 'rb')) self.setup_widgets() self.refresh_plot() def setup_widgets(self): amine_list = sorted(list(self.data.keys())) self.select_amine = Dropdown( options=amine_list, description='Amine: ', disabled=False, ) self.select_metric = Dropdown( options=['Accuracy', 'Precision', 'Recall', 'F1'], description='Metric: ', disabled=False, ) self.figure = go.FigureWidget() self.select_amine.observe(self.select_amine_callback, 'value') self.select_metric.observe(self.select_amine_callback, 'value') self.full_widget = VBox( [self.figure, HBox([self.select_amine, self.select_metric])]) def select_amine_callback(self, state): self.refresh_plot() def refresh_plot(self): color_list = [ 'rgba(31, 118, 180, 1)', 'rgba(255, 127, 14, 1)', 'rgba(44, 160, 44, 1)', 'rgba(214, 39, 39, 1)', 'rgba(147, 103, 189, 1)', 'rgba(140, 86, 75, 1)', 'rgba(227, 119, 195, 1)', 'rgba(127, 127, 127, 1)', 'rgba(189, 189, 34, 1)', 'rgba(23, 189, 207, 1)' ] amine = self.select_amine.value metric = self.select_metric.value x_values = self.data[amine]['learn_rate'] # y_values = self.data[amine] layout = go.Layout( hovermode='closest', showlegend=True, xaxis=go.layout.XAxis(title=go.layout.xaxis.Title( text="Number of training experiments", ), ), yaxis=go.layout.YAxis(title=go.layout.yaxis.Title(text=metric, )), ) trace_list = [] for i, model in enumerate(sorted(self.data[amine]['model'].keys())): y_mean = [ np.mean(y_data.flatten()) for y_data in self.data[amine]['model'][model][metric.lower()] ] x = x_values trace = go.Scatter( name=model, x=x, y=y_mean, marker=dict( size=5, color=color_list[i % len(color_list)], ), opacity=1.0, ) trace_list.append(trace) y_std_dev = [ np.std(y_data.flatten()) for y_data in self.data[amine]['model'][model][metric.lower()] ] y_upper = np.array(y_mean) + np.array(y_std_dev) y_lower = np.array(y_mean) - np.array(y_std_dev) trace2 = go.Scatter( x=x + x[::-1], y=list(y_upper) + list(reversed(y_lower)), fill='tozerox', fillcolor=self.change_alpha(color_list[i % len(color_list)], 0.3), line=dict(color='rgba(255,255,255,0)'), name=model, showlegend=False, ) trace_list.append(trace2) """ if std_dev[model]: x_rev = x[::-1] y_upper = np.array(data[model]) + np.array(std_dev[model]) y_lower = np.array(data[model]) - np.array(std_dev[model]) trace2 = go.Scatter( x=x+x_rev, y=list(y_upper)+list(y_lower)[::-1], fill='tozerox', fillcolor=self.change_alpha( color_list[i % len(color_list)], 0.3), line=dict(color='rgba(255,255,255,0)'), name=model, showlegend=False, ) trace_list.append(trace2) """ # self.figure = go.FigureWidget(data=trace_list, layout=layout) with self.figure.batch_update(): self.figure.data = [] # for trace in trace_list: self.figure.add_traces(trace_list) self.figure.layout = layout def change_alpha(self, color, alpha): color = color.split(',') color[-1] = '{})'.format(alpha) return ','.join(color) @property def plot(self): return self.full_widget
class WikipediaPageRow(Document): def __init__(self, name=None): self.editable = name is None self.checkbox = Checkbox(value=True, layout=_checkbox_layout, indent=False) self.true_name = self.summary = self.last_textfield = None if self.editable: self.text_field = Text(layout=_label_layout) else: self.text_field = Label(value=name, layout=_label_layout) self.remove_button = Button( description='Remove', disabled=False, button_style= 'danger', # 'success', 'info', 'warning', 'danger' or '' layout=_remove_layout, ) self.additional_info = Label("", layout=_additional_info_layout) self.ambiguity_dropdown = None def __iter__(self): yield self.checkbox yield self.text_field yield self.remove_button if self.ambiguity_dropdown is None: yield self.additional_info else: yield self.ambiguity_dropdown def _search(self): if self.last_textfield != self.text_field_value: try: self.last_textfield = self.text_field_value self.true_name = _get_wikipedia_search( name=self.text_field_value)[0] self.summary = _get_wikipedia_summary(self.true_name) self.ambiguity_dropdown = None except (wikipedia.DisambiguationError, IndexError) as e: if isinstance(e, wikipedia.DisambiguationError): options = [ val for val in e.options if not "All pages" in val ] self.ambiguity_dropdown = Dropdown( options=options, value=options[0], description='-> Ambiguity:', disabled=False, layout=_additional_info_layout) self.ambiguity_dropdown.observe( self._true_name_from_dropdown) self._true_name_from_dropdown() else: self.last_textfield = "" self.true_name = "" self.summary = None self.ambiguity_dropdown = None def _true_name_from_dropdown(self, _=None): self.true_name = self.ambiguity_dropdown.value self.summary = _get_wikipedia_summary(self.true_name) @property def text_field_value(self): return self.text_field.value @property def name(self): self._search() return self.true_name @property def text(self): self._search() return self.summary @property def on(self): return self.checkbox.value and self.text_field_value @staticmethod def make_header(): return HBox( (Label("Use", layout=_checkbox_layout), Label("Page Search Name", layout=_label_layout), Label("Remove", layout=_remove_layout), Label("Search Result", layout=_additional_info_layout)))
def _create_controls( self, time: Union[pd.DatetimeIndex, pd.TimedeltaIndex, List[pd.Timestamp]], reference_system: str, show_data_labels: bool, show_labels: bool, show_origins: bool, show_traces: bool, show_vectors: bool, show_wireframe: bool, ): """Create the control panel. Parameters ---------- time : pandas.DatetimeIndex, pandas.TimedeltaIndex, List[pandas.Timestamp], or \ LocalCoordinateSystem The time steps that should be plotted initially reference_system : str Name of the initial reference system. If `None` is provided, the root system of the `CoordinateSystemManager` instance will be used show_data_labels : bool If `True`, the data labels will be shown initially show_labels : bool If `True`, the coordinate system labels will be shown initially show_origins : bool If `True`, the coordinate systems' origins will be shown initially show_traces : bool If `True`, the coordinate systems' traces will be shown initially show_vectors : bool If `True`, the coordinate systems' axis vectors will be shown initially show_wireframe : bool If `True`, spatial data containing mesh data will be drawn as wireframe """ num_times = 1 disable_time_widgets = True lo = Layout(width="200px") # create widgets if time is not None: num_times = len(time) disable_time_widgets = False play = Play( min=0, max=num_times - 1, value=self._current_time_index, step=1, ) time_slider = IntSlider( min=0, max=num_times - 1, value=self._current_time_index, description="Time:", ) reference_dropdown = Dropdown( options=self._csm.coordinate_system_names, value=reference_system, description="Reference:", disabled=False, ) data_dropdown = Dropdown( options=SpatialDataVisualizer.visualization_methods, value="auto", description="data repr.:", disabled=False, layout=lo, ) lo = Layout(width="200px") vectors_cb = Checkbox(value=show_vectors, description="show vectors", layout=lo) origin_cb = Checkbox(value=show_origins, description="show origins", layout=lo) traces_cb = Checkbox(value=show_traces, description="show traces", layout=lo) labels_cb = Checkbox(value=show_labels, description="show labels", layout=lo) wf_cb = Checkbox(value=show_wireframe, description="show wireframe", layout=lo) data_labels_cb = Checkbox(value=show_data_labels, description="show data labels", layout=lo) jslink((play, "value"), (time_slider, "value")) play.disabled = disable_time_widgets time_slider.disabled = disable_time_widgets # callback functions def _reference_callback(change): self.update_reference_system(change["new"]) def _time_callback(change): self.update_time_index(change["new"]) def _vectors_callback(change): self.show_vectors(change["new"]) def _origins_callback(change): self.show_origins(change["new"]) def _traces_callback(change): self.show_traces(change["new"]) def _labels_callback(change): self.show_labels(change["new"]) def _data_callback(change): self.set_data_visualization_method(change["new"]) def _data_labels_callback(change): self.show_data_labels(change["new"]) def _wireframe_callback(change): self.show_wireframes(change["new"]) # register callbacks time_slider.observe(_time_callback, names="value") reference_dropdown.observe(_reference_callback, names="value") vectors_cb.observe(_vectors_callback, names="value") origin_cb.observe(_origins_callback, names="value") traces_cb.observe(_traces_callback, names="value") labels_cb.observe(_labels_callback, names="value") data_dropdown.observe(_data_callback, names="value") data_labels_cb.observe(_data_labels_callback, names="value") wf_cb.observe(_wireframe_callback, names="value") # create control panel row_1 = HBox([time_slider, play, reference_dropdown]) row_2 = HBox([vectors_cb, origin_cb, traces_cb, labels_cb]) if len(self._data_vis) > 0: row_3 = HBox([data_dropdown, wf_cb, data_labels_cb]) return VBox([row_1, row_2, row_3]) return VBox([row_1, row_2])
class TimeSeriesSmoothing(): """ Class to plot a single time step and per-pixel time series """ debug_view = widgets.Output(layout={'border': '1px solid black'}) def __init__(self, fname, band=1, isNotebook=True): """ :param ts: TATSSI qa_analytics object """ # Clear cell clear_output() # Time series object self.ts = Analysis(fname=fname) self.isNotebook = isNotebook if self.isNotebook is True: # Smoothing methods # set in __fill_smoothing_method self.smoothing_methods = None # Display controls self.__display_controls() # Create plot objects self.__create_plot_objects() # Create plot self.__plot(band) # Disable RasterIO logging, just show ERRORS log = rio_logging.getLogger() log.setLevel(rio_logging.ERROR) def __create_plot_objects(self): """ Create plot objects """ self.fig = plt.figure(figsize=(10.0, 3.0)) # Image plot self.img_p = plt.subplot2grid((1, 4), (0, 0), colspan=1) # Time series plot self.ts_p = plt.subplot2grid((1, 4), (0, 1), colspan=3) def __display_controls(self): """ Display widgets in an horizontal box """ self.__fill_data_variables() self.__fill_smoothing_method() self.__fill_smooth_factor() left_box = VBox([self.data_vars]) center_box = VBox([self.smoothing_methods]) right_box = VBox([self.smooth_factor]) #_HBox = HBox([left_box, center_box, right_box], _HBox = HBox([left_box, center_box, right_box], layout={'height': '80px', 'width' : '99%'} ) display(_HBox) def __fill_smooth_factor(self): """ Fill smooth factor bounded float text """ self.smooth_factor = widgets.BoundedFloatText( value=0.75, min=0.1, max=10.0, step=0.05, description='Smooth factor:', disabled=False, style = {'description_width': 'initial'}, layout={'width': '150px'} ) def __fill_data_variables(self): """ Fill the data variables dropdown list """ data_vars = [] for data_var in self.ts.data.data_vars: data_vars.append(data_var) self.data_vars = Dropdown( options=data_vars, value=data_vars[0], description='Data variables:', disabled=False, style = {'description_width': 'initial'}, layout={'width': '400px'}, ) self.data_vars.observe(self.on_data_vars_change) def on_data_vars_change(self, change): """ Handles a change in the data variable to display """ if change['type'] == 'change' and change['name'] == 'value': self.left_ds = getattr(self.ts.data, change['new']) if self.mask is None: self.right_ds = self.left_ds.copy(deep=True) else: self.right_ds = self.left_ds * self.mask self.left_imshow.set_data(self.left_ds.data[0]) self.right_imshow.set_data(self.right_ds.data[0]) def __fill_smoothing_method(self): """ Fill smooth methods """ smoothing_methods = ['smoothn', 'ExponentialSmoothing', 'SimpleExpSmoothing', 'Holt'] self.smoothing_methods = SelectMultiple( options=tuple(smoothing_methods), value=tuple([smoothing_methods[0]]), rows=len(smoothing_methods), description='Smoothing methods', disabled=False, style = {'description_width': 'initial'}, layout={'width': '330px'}, ) def __plot(self, band, is_qa=False): """ Plot a variable and time series """ self.img_ds = getattr(self.ts.data, self.data_vars.value) # Create plot self.img_imshow = self.img_ds[band].plot.imshow(cmap='Greys_r', ax=self.img_p, add_colorbar=False) # Turn off axis self.img_p.axis('off') self.img_p.set_aspect('equal') self.fig.canvas.draw_idle() # Connect the canvas with the event cid = self.fig.canvas.mpl_connect('button_press_event', self.on_click) # Plot the centroid _layers, _rows, _cols = self.img_ds.shape # Get y-axis max and min #y_min, y_max = self.ds.data.min(), self.ds.data.max() plot_sd = self.img_ds[:, int(_cols / 2), int(_rows / 2)] plot_sd.plot(ax = self.ts_p, color='black', linestyle = '-', linewidth=1, label='Original data') plt.margins(tight=True) plt.tight_layout() # Legend self.ts_p.legend(loc='best', fontsize='small', fancybox=True, framealpha=0.5) # Grid self.ts_p.grid(axis='both', alpha=.3) plt.show() @debug_view.capture(clear_output=True) def on_click(self, event): """ Event handler """ # Event does not apply for time series plot # Check if the click was in a if event.inaxes in [self.ts_p]: return # Clear subplot self.ts_p.clear() # Delete last reference point if len(self.img_p.lines) > 0: del self.img_p.lines[0] # Draw a point as a reference self.img_p.plot(event.xdata, event.ydata, marker='o', color='red', markersize=7, alpha=0.7) # Interpolated data to smooth img_plot_sd = self.img_ds.sel(longitude=event.xdata, latitude=event.ydata, method='nearest') if img_plot_sd.chunks is not None: img_plot_sd = img_plot_sd.compute() # Plots img_plot_sd.plot(ax=self.ts_p, color='black', linestyle = '-', linewidth=1, label='Original data') # For every smoothing method selected by the user for method in self.smoothing_methods.value: y = img_plot_sd.data s = float(self.smooth_factor.value) if method is 'smoothn': # Smoothing fittedvalues = smoothn(y, isrobust=True, s=s, TolZ=1e-6, axis=0)[0] else: _method = getattr(tsa, method) # Smoothing #fit = _method(y).fit(smoothing_level=s, optimized=False) fit = _method(y.astype(float)).fit(smoothing_level=s) # Re-cast to original data type fittedvalues = np.zeros_like(fit.fittedvalues) fittedvalues[0:-1] = fit.fittedvalues[1::] fittedvalues[-1] = y[-1] # Plot tmp_ds = img_plot_sd.copy(deep=True, data=fittedvalues) tmp_ds.plot(ax = self.ts_p, label=method, linewidth=2) # Change ylimits max_val = img_plot_sd.data.max() min_val = img_plot_sd.data.min() data_range = max_val - min_val max_val = max_val + (data_range * 0.2) min_val = min_val - (data_range * 0.2) self.ts_p.set_ylim([min_val, max_val]) # Legend self.ts_p.legend(loc='best', fontsize='small', fancybox=True, framealpha=0.5) # Grid self.ts_p.grid(axis='both', alpha=.3) # Redraw plot plt.draw() @staticmethod def __enhance(data): # Histogram _histogram = np.histogram(data)[1] # Change ylimits max_val = _histogram[-3] min_val = _histogram[2] return min_val, max_val
class TrajectoryPlayer(DOMWidget): # should set default values here different from desired defaults # so `observe` can be triggered step = Int(0).tag(sync=True) sync_frame = Bool(True).tag(sync=True) interpolate = Bool(False).tag(sync=False) delay = Float(0.0).tag(sync=True) parameters = Dict().tag(sync=True) iparams = Dict().tag(sync=False) _interpolation_t = Float().tag(sync=False) _iterpolation_type = CaselessStrEnum(['linear', 'spline']).tag(sync=False) spin = Bool(False).tag(sync=False) _spin_x = Int(1).tag(sync=False) _spin_y = Int(0).tag(sync=False) _spin_z = Int(0).tag(sync=False) _spin_speed = Float(0.005).tag(sync=False) camera = CaselessStrEnum(['perspective', 'orthographic'], default_value='perspective').tag(sync=False) _render_params = Dict().tag(sync=False) _real_time_update = Bool(False).tag(sync=False) widget_tab = Any(None).tag(sync=False) widget_repr = Any(None).tag(sync=False) widget_repr_parameters = Any(None).tag(sync=False) widget_quick_repr = Any(None).tag(sync=False) widget_general = Any(None).tag(sync=False) widget_picked = Any(None).tag(sync=False) widget_preference = Any(None).tag(sync=False) widget_extra = Any(None).tag(sync=False) widget_theme = Any(None).tag(sync=False) widget_help = Any(None).tag(sync=False) widget_export_image = Any(None).tag(sync=False) widget_component_slider = Any(None).tag(sync=False) widget_repr_slider = Any(None).tag(sync=False) widget_repr_choices = Any(None).tag(sync=False) widget_repr_control_buttons = Any(None).tag(sync=False) widget_repr_add = Any(None).tag(sync=False) widget_accordion_repr_parameters = Any(None).tag(sync=False) widget_repr_parameters_dialog = Any(None).tag(sync=False) widget_repr_name = Any(None).tag(sync=False) widget_component_dropdown = Any(None).tag(sync=False) widget_drag = Any(None).tag(sync=False) def __init__(self, view, step=1, delay=100, sync_frame=False, min_delay=40): self._view = view self.step = step self.sync_frame = sync_frame self.delay = delay self.min_delay = min_delay self._interpolation_t = 0.5 self._iterpolation_type = 'linear' self.iparams = dict( t=self._interpolation_t, step=1, type=self._iterpolation_type) self._render_params = dict(factor=4, antialias=True, trim=False, transparent=False) self._widget_names = [w for w in dir(self) if w.startswith('wiget_')] self.observe(self._on_widget_built, names=['widget_repr_parameters', 'widget_repr', 'widget_preference']) self._movie_maker = None def _on_widget_built(self, change): widget = change['new'] if widget is not None: widget.layout.padding = '5%' def _update_padding(self, padding=default.DEFAULT_PADDING): widget_collection = [ self.widget_general, self.widget_repr, self.widget_preference, self.widget_repr_parameters, self.widget_help, self.widget_extra, self.widget_picked ] for widget in widget_collection: if widget is not None: widget.layout.padding = padding def _create_all_widgets(self): if self.widget_tab is None: self.widget_tab = self._display() old_index = self.widget_tab.selected_index for index, _ in enumerate(self.widget_tab.children): self.widget_tab.selected_index = index self.widget_tab.selected_index = old_index def smooth(self): self.interpolate = True @observe('camera') def on_camera_changed(self, change): camera_type = change['new'] self._view._remote_call("setParameters", target='Stage', kwargs=dict(cameraType=camera_type)) @property def frame(self): return self._view.frame @frame.setter def frame(self, value): self._view.frame = value @property def count(self): return self._view.count @observe('sync_frame') def update_sync_frame(self, change): value = change['new'] if value: self._view._set_sync_frame() else: self._view._set_unsync_frame() @observe("delay") def update_delay(self, change): delay = change['new'] self._view._set_delay(delay) @observe('parameters') def update_parameters(self, change): params = change['new'] self.sync_frame = params.get("sync_frame", self.sync_frame) self.delay = params.get("delay", self.delay) self.step = params.get("step", self.step) @observe('_interpolation_t') def _interpolation_t_changed(self, change): self.iparams['t'] = change['new'] @observe('spin') def on_spin_changed(self, change): self.spin = change['new'] if self.spin: self._view._set_spin([self._spin_x, self._spin_y, self._spin_z], self._spin_speed) else: # stop self._view._set_spin(None, None) @observe('_spin_x') def on_spin_x_changed(self, change): self._spin_x = change['new'] if self.spin: self._view._set_spin([self._spin_x, self._spin_y, self._spin_z], self._spin_speed) @observe('_spin_y') def on_spin_y_changed(self, change): self._spin_y = change['new'] if self.spin: self._view._set_spin([self._spin_x, self._spin_y, self._spin_z], self._spin_speed) @observe('_spin_z') def on_spin_z_changed(self, change): self._spin_z = change['new'] if self.spin: self._view._set_spin([self._spin_x, self._spin_y, self._spin_z], self._spin_speed) @observe('_spin_speed') def on_spin_speed_changed(self, change): self._spin_speed = change['new'] if self.spin: self._view._set_spin([self._spin_x, self._spin_y, self._spin_z], self._spin_speed) def _display(self): box_factory = [(self._make_general_box, 'General'), (self._make_widget_repr, 'Representation'), (self._make_widget_preference, 'Preference'), (self._make_theme_box, 'Theme'), (self._make_extra_box, 'Extra'), (self._show_website, 'Help')] tab = _make_delay_tab(box_factory, selected_index=-1) # tab = _make_autofit(tab) tab.layout.align_self = 'center' tab.layout.align_items = 'stretch' self.widget_tab = tab return self.widget_tab def _make_widget_tab(self): return self._display() def _make_button_center(self): button = Button(description=' Center', icon='fa-bullseye') @button.on_click def on_click(button): self._view.center() return button def _make_button_theme(self): button = Button(description='Oceans16') @button.on_click def on_click(button): from nglview import theme display(theme.oceans16()) self._view._remote_call('cleanOutput', target='Widget') return button def _make_button_reset_theme(self, hide_toolbar=False): from nglview import theme if hide_toolbar: button = Button(description='Simplified Default') @button.on_click def on_click(button): theme.reset(hide_toolbar=True) else: button = Button(description='Default') @button.on_click def on_click(button): theme.reset() return button def _make_button_clean_error_output(self): button = Button(description='Clear Error') @button.on_click def on_click(_): js_utils.clean_error_output() return button def _make_widget_preference(self, width='100%'): def make_func(): parameters = self._view._full_stage_parameters def func(pan_speed=parameters.get('panSpeed', 0.8), rotate_speed=parameters.get('rotateSpeed', 2), zoom_speed=parameters.get('zoomSpeed', 1.2), clip_dist=parameters.get('clipDist', 10), camera_fov=parameters.get('cameraFov', 40), clip_far=parameters.get('clipFar', 100), clip_near=parameters.get('clipNear', 0), fog_far=parameters.get('fogFar', 100), fog_near=parameters.get('fogNear', 50), impostor=parameters.get('impostor', True), light_intensity=parameters.get('lightIntensity', 1), quality=parameters.get('quality', 'medium'), sample_level=parameters.get('sampleLevel', 1)): self._view.parameters = dict( panSpeed=pan_speed, rotateSpeed=rotate_speed, zoomSpeed=zoom_speed, clipDist=clip_dist, clipFar=clip_far, clipNear=clip_near, cameraFov=camera_fov, fogFar=fog_far, fogNear=fog_near, impostor=impostor, lightIntensity=light_intensity, quality=quality, sampleLevel=sample_level) return func def make_widget_box(): widget_sliders = interactive(make_func(), pan_speed=(0, 10, 0.1), rotate_speed=(0, 10, 1), zoom_speed=(0, 10, 1), clip_dist=(0, 200, 5), clip_far=(0, 100, 1), clip_near=(0, 100, 1), camera_fov=(15, 120, 1), fog_far=(0, 100, 1), fog_near=(0, 100, 1), light_intensity=(0, 10, 0.02), quality=['low', 'medium', 'high'], sample_level=(-1, 5, 1)) for child in widget_sliders.children: if isinstance(child, (IntSlider, FloatSlider)): child.layout.width = default.DEFAULT_SLIDER_WIDTH return widget_sliders if self.widget_preference is None: widget_sliders = make_widget_box() reset_button = Button(description='Reset') widget_sliders.children = [reset_button,] + list(widget_sliders.children) @reset_button.on_click def on_click(reset_button): self._view.parameters = self._view._original_stage_parameters self._view._full_stage_parameters = self._view._original_stage_parameters widget_sliders.children = [reset_button,] + list(make_widget_box().children) self.widget_preference = _relayout_master(widget_sliders, width=width) return self.widget_preference def _show_download_image(self): # "interactive" does not work for True/False in ipywidgets 4 yet. button = Button(description=' Screenshot', icon='fa-camera') @button.on_click def on_click(button): self._view.download_image() return button def _make_button_url(self, url, description): button = Button(description=description) @button.on_click def on_click(button): display(Javascript(js_utils.open_url_template.format(url=url))) return button def _show_website(self, ngl_base_url=default.NGL_BASE_URL): buttons = [self._make_button_url(url.format(ngl_base_url), description) for url, description in [("'http://arose.github.io/nglview/latest/'", "nglview"), ("'{}/index.html'", "NGL"), ("'{}/tutorial-selection-language.html'", "Selection"), ("'{}/tutorial-molecular-representations.html'", "Representation")] ] self.widget_help = _make_autofit(HBox(buttons)) return self.widget_help def _make_button_qtconsole(self): from nglview import js_utils button = Button(description='qtconsole', tooltip='pop up qtconsole') @button.on_click def on_click(button): js_utils.launch_qtconsole() return button def _make_text_picked(self): ta = Textarea(value=json.dumps(self._view.picked), description='Picked atom') ta.layout.width = '300px' return ta def _refresh(self, component_slider, repr_slider): """update representation and component information """ self._view._request_repr_parameters(component=component_slider.value, repr_index=repr_slider.value) self._view._remote_call('requestReprInfo', target='Widget') self._view._handle_repr_dict_changed(change=dict(new=self._view._repr_dict)) def _make_button_repr_control(self, component_slider, repr_slider, repr_selection): button_refresh = Button(description=' Refresh', tooltip='Get representation info', icon='fa-refresh') button_center_selection = Button(description=' Center', tooltip='center selected atoms', icon='fa-bullseye') button_center_selection._ngl_name = 'button_center_selection' button_hide = Button(description=' Hide', icon='fa-eye-slash', tooltip='Hide/Show current representation') button_remove = Button(description=' Remove', icon='fa-trash', tooltip='Remove current representation') button_repr_parameter_dialog = Button(description=' Dialog', tooltip='Pop up representation parameters control dialog') @button_refresh.on_click def on_click_refresh(button): self._refresh(component_slider, repr_slider) @button_center_selection.on_click def on_click_center(center_selection): self._view.center_view(selection=repr_selection.value, component=component_slider.value) @button_hide.on_click def on_click_hide(button_hide): component=component_slider.value repr_index=repr_slider.value if button_hide.description == 'Hide': hide = True button_hide.description = 'Show' else: hide = False button_hide.description = 'Hide' self._view._remote_call('setVisibilityForRepr', target='Widget', args=[component, repr_index, not hide]) @button_remove.on_click def on_click_remove(button_remove): self._view._remove_representation(component=component_slider.value, repr_index=repr_slider.value) self._view._request_repr_parameters(component=component_slider.value, repr_index=repr_slider.value) @button_repr_parameter_dialog.on_click def on_click_repr_dialog(_): from nglview.widget_box import DraggableBox if self.widget_repr_parameters is not None and self.widget_repr_choices: self.widget_repr_parameters_dialog = DraggableBox([self.widget_repr_choices, self.widget_repr_parameters]) self.widget_repr_parameters_dialog._ipython_display_() self.widget_repr_parameters_dialog._dialog = 'on' bbox = _make_autofit(HBox([button_refresh, button_center_selection, button_hide, button_remove, button_repr_parameter_dialog])) return bbox def _make_widget_repr(self): self.widget_repr_name = Text(value='', description='representation') self.widget_repr_name._ngl_name = 'repr_name_text' repr_selection = Text(value=' ', description='selection') repr_selection._ngl_name = 'repr_selection' repr_selection.width = self.widget_repr_name.width = default.DEFAULT_TEXT_WIDTH max_n_components = max(self._view.n_components-1, 0) self.widget_component_slider = IntSlider(value=0, max=max_n_components, min=0, description='component') self.widget_component_slider._ngl_name = 'component_slider' cvalue = ' ' self.widget_component_dropdown = Dropdown(value=cvalue, options=[cvalue,], description='component') self.widget_component_dropdown._ngl_name = 'component_dropdown' self.widget_repr_slider = IntSlider(value=0, description='representation', width=default.DEFAULT_SLIDER_WIDTH) self.widget_repr_slider._ngl_name = 'repr_slider' self.widget_repr_slider.visible = True self.widget_component_slider.layout.width = default.DEFAULT_SLIDER_WIDTH self.widget_repr_slider.layout.width = default.DEFAULT_SLIDER_WIDTH self.widget_component_dropdown.layout.width = self.widget_component_dropdown.max_width = default.DEFAULT_TEXT_WIDTH # turn off for now self.widget_component_dropdown.layout.display = 'none' self.widget_component_dropdown.description = '' # self.widget_accordion_repr_parameters = Accordion() self.widget_accordion_repr_parameters = Tab() self.widget_repr_parameters = self._make_widget_repr_parameters(self.widget_component_slider, self.widget_repr_slider, self.widget_repr_name) self.widget_accordion_repr_parameters.children = [self.widget_repr_parameters, Box()] self.widget_accordion_repr_parameters.set_title(0, 'Parameters') self.widget_accordion_repr_parameters.set_title(1, 'Hide') self.widget_accordion_repr_parameters.selected_index = 1 checkbox_reprlist = Checkbox(value=False, description='reprlist') checkbox_reprlist._ngl_name = 'checkbox_reprlist' self.widget_repr_choices = self._make_repr_name_choices(self.widget_component_slider, self.widget_repr_slider) self.widget_repr_choices._ngl_name = 'reprlist_choices' self.widget_repr_add = self._make_add_widget_repr(self.widget_component_slider) def on_update_checkbox_reprlist(change): self.widget_repr_choices.visible= change['new'] checkbox_reprlist.observe(on_update_checkbox_reprlist, names='value') def on_repr_name_text_value_changed(change): name = change['new'].strip() old = change['old'].strip() should_update = (self._real_time_update and old and name and name in REPRESENTATION_NAMES and name != change['old'].strip()) if should_update: component=self.widget_component_slider.value repr_index=self.widget_repr_slider.value self._view._remote_call('setRepresentation', target='Widget', args=[change['new'], {}, component, repr_index]) self._view._request_repr_parameters(component, repr_index) def on_component_or_repr_slider_value_changed(change): self._view._request_repr_parameters(component=self.widget_component_slider.value, repr_index=self.widget_repr_slider.value) self.widget_component_dropdown.options = tuple(self._view._ngl_component_names) if self.widget_accordion_repr_parameters.selected_index >= 0: self.widget_repr_parameters.name = self.widget_repr_name.value self.widget_repr_parameters.repr_index = self.widget_repr_slider.value self.widget_repr_parameters.component_index = self.widget_component_slider.value def on_repr_selection_value_changed(change): if self._real_time_update: component = self.widget_component_slider.value repr_index = self.widget_repr_slider.value self._view._set_selection(change['new'], component=component, repr_index=repr_index) def on_change_component_dropdown(change): choice = change['new'] if choice: self.widget_component_slider.value = self._view._ngl_component_names.index(choice) self.widget_component_dropdown.observe(on_change_component_dropdown, names='value') self.widget_repr_slider.observe(on_component_or_repr_slider_value_changed, names='value') self.widget_component_slider.observe(on_component_or_repr_slider_value_changed, names='value') self.widget_repr_name.observe(on_repr_name_text_value_changed, names='value') repr_selection.observe(on_repr_selection_value_changed, names='value') self.widget_repr_control_buttons = self._make_button_repr_control(self.widget_component_slider, self.widget_repr_slider, repr_selection) blank_box = Box([Label("")]) all_kids = [self.widget_repr_control_buttons, blank_box, self.widget_repr_add, self.widget_component_dropdown, self.widget_repr_name, repr_selection, self.widget_component_slider, self.widget_repr_slider, self.widget_repr_choices, self.widget_accordion_repr_parameters ] vbox = VBox(all_kids) self._view._request_repr_parameters(component=self.widget_component_slider.value, repr_index=self.widget_repr_slider.value) self.widget_repr = _relayout_master(vbox, width='100%') self._refresh(self.widget_component_slider, self.widget_repr_slider) setattr(self.widget_repr, "_saved_widgets", []) for _box in self.widget_repr.children: if hasattr(_box, 'children'): for kid in _box.children: self.widget_repr._saved_widgets.append(kid) return self.widget_repr def _make_widget_repr_parameters(self, component_slider, repr_slider, repr_name_text=None): name = repr_name_text.value if repr_name_text is not None else ' ' widget = self._view._display_repr(component=component_slider.value, repr_index=repr_slider.value, name=name) widget._ngl_name = 'repr_parameters_box' return widget def _make_button_export_image(self): slider_factor = IntSlider(value=4, min=1, max=10, description='scale') checkbox_antialias = Checkbox(value=True, description='antialias') checkbox_trim = Checkbox(value=False, description='trim') checkbox_transparent = Checkbox(value=False, description='transparent') filename_text = Text(value='Screenshot', description='Filename') delay_text = FloatText(value=1, description='delay (s)', tooltip='hello') start_text, stop_text, step_text = (IntText(value=0, description='start'), IntText(value=self._view.count, description='stop'), IntText(value=1, description='step')) start_text.layout.max_width = stop_text.layout.max_width = step_text.layout.max_width \ = filename_text.layout.max_width = delay_text.layout.max_width = default.DEFAULT_TEXT_WIDTH button_movie_images = Button(description='Export Images') def download_image(filename): self._view.download_image(factor=slider_factor.value, antialias=checkbox_antialias.value, trim=checkbox_trim.value, transparent=checkbox_transparent.value, filename=filename) @button_movie_images.on_click def on_click_images(button_movie_images): for i in range(start_text.value, stop_text.value, step_text.value): self._view.frame = i time.sleep(delay_text.value) download_image(filename=filename_text.value + str(i)) time.sleep(delay_text.value) vbox = VBox([ button_movie_images, start_text, stop_text, step_text, delay_text, filename_text, slider_factor, checkbox_antialias, checkbox_trim, checkbox_transparent, ]) form_items = _relayout(vbox, make_form_item_layout()) form = Box(form_items, layout=_make_box_layout()) # form = _relayout_master(vbox) return form def _make_resize_notebook_slider(self): resize_notebook_slider = IntSlider(min=300, max=2000, description='resize notebook') def on_resize_notebook(change): width = change['new'] self._view._remote_call('resizeNotebook', target='Widget', args=[width,]) resize_notebook_slider.observe(on_resize_notebook, names='value') return resize_notebook_slider def _make_add_widget_repr(self, component_slider): dropdown_repr_name = Dropdown(options=REPRESENTATION_NAMES, value='cartoon') repr_selection = Text(value='*', description='') repr_button = Button(description='Add', tooltip="""Add representation. You can also hit Enter in selection box""") repr_button.layout = Layout(width='auto', flex='1 1 auto') dropdown_repr_name.layout.width = repr_selection.layout.width = default.DEFAULT_TEXT_WIDTH def on_click_or_submit(button_or_text_area): self._view.add_representation(selection=repr_selection.value.strip(), repr_type=dropdown_repr_name.value, component=component_slider.value) repr_button.on_click(on_click_or_submit) repr_selection.on_submit(on_click_or_submit) add_repr_box = HBox([repr_button, dropdown_repr_name, repr_selection]) add_repr_box._ngl_name = 'add_repr_box' return add_repr_box def _make_repr_playground(self): vbox = VBox() children = [] rep_names = REPRESENTATION_NAMES[:] excluded_names = ['ball+stick', 'distance'] for name in excluded_names: rep_names.remove(name) repr_selection = Text(value='*') repr_selection.layout.width = default.DEFAULT_TEXT_WIDTH repr_selection_box = HBox([Label('selection'), repr_selection]) setattr(repr_selection_box, 'value', repr_selection.value) for index, name in enumerate(rep_names): button = ToggleButton(description=name) def make_func(): def on_toggle_button_value_change(change, button=button): selection = repr_selection.value new = change['new'] # True/False if new: self._view.add_representation(button.description, selection=selection) else: self._view._remove_representations_by_name(button.description) return on_toggle_button_value_change button.observe(make_func(), names='value') children.append(button) button_clear = Button(description='clear', button_style='info', icon='fa-eraser') @button_clear.on_click def on_clear(button_clear): self._view.clear() for kid in children: # unselect kid.value = False vbox.children = children + [repr_selection, button_clear] _make_autofit(vbox) self.widget_quick_repr = vbox return self.widget_quick_repr def _make_repr_name_choices(self, component_slider, repr_slider): repr_choices = Dropdown(options=[" ",]) def on_chose(change): repr_name = change['new'] repr_index = repr_choices.options.index(repr_name) repr_slider.value = repr_index repr_choices.observe(on_chose, names='value') repr_choices.layout.width = default.DEFAULT_TEXT_WIDTH self.widget_repr_choices = repr_choices return self.widget_repr_choices def _make_drag_widget(self): button_drag = Button(description='widget drag: off', tooltip='dangerous') drag_nb = Button(description='notebook drag: off', tooltip='dangerous') button_reset_notebook = Button(description='notebook: reset', tooltip='reset?') button_dialog = Button(description='dialog', tooltip='make a dialog') button_split_half = Button(description='split screen', tooltip='try best to make a good layout') @button_drag.on_click def on_drag(button_drag): if button_drag.description == 'widget drag: off': self._view._set_draggable(True) button_drag.description = 'widget drag: on' else: self._view._set_draggable(False) button_drag.description = 'widget drag: off' @drag_nb.on_click def on_drag_nb(button_drag): if drag_nb.description == 'notebook drag: off': js_utils._set_notebook_draggable(True) drag_nb.description = 'notebook drag: on' else: js_utils._set_notebook_draggable(False) drag_nb.description = 'notebook drag: off' @button_reset_notebook.on_click def on_reset(button_reset_notebook): js_utils._reset_notebook() @button_dialog.on_click def on_dialog(button_dialog): self._view._remote_call('setDialog', target='Widget') @button_split_half.on_click def on_split_half(button_dialog): from nglview import js_utils import time js_utils._move_notebook_to_the_left() js_utils._set_notebook_width('5%') time.sleep(0.1) self._view._remote_call('setDialog', target='Widget') drag_box = HBox([button_drag, drag_nb, button_reset_notebook, button_dialog, button_split_half]) drag_box = _make_autofit(drag_box) self.widget_drag = drag_box return drag_box def _make_spin_box(self): checkbox_spin = Checkbox(self.spin, description='spin') spin_x_slide = IntSlider( self._spin_x, min=-1, max=1, description='spin_x') spin_y_slide = IntSlider( self._spin_y, min=-1, max=1, description='spin_y') spin_z_slide = IntSlider( self._spin_z, min=-1, max=1, description='spin_z') spin_speed_slide = FloatSlider( self._spin_speed, min=0, max=0.2, step=0.001, description='spin speed') # spin link((checkbox_spin, 'value'), (self, 'spin')) link((spin_x_slide, 'value'), (self, '_spin_x')) link((spin_y_slide, 'value'), (self, '_spin_y')) link((spin_z_slide, 'value'), (self, '_spin_z')) link((spin_speed_slide, 'value'), (self, '_spin_speed')) spin_box= VBox([checkbox_spin, spin_x_slide, spin_y_slide, spin_z_slide, spin_speed_slide]) spin_box = _relayout_master(spin_box, width='75%') return spin_box def _make_widget_picked(self): self.widget_picked = self._make_text_picked() picked_box = HBox([self.widget_picked,]) return _relayout_master(picked_box, width='75%') def _make_export_image_widget(self): if self.widget_export_image is None: self.widget_export_image = HBox([self._make_button_export_image()]) return self.widget_export_image def _make_extra_box(self): if self.widget_extra is None: extra_list = [(self._make_drag_widget, 'Drag'), (self._make_spin_box, 'Spin'), (self._make_widget_picked, 'Picked'), (self._make_repr_playground, 'Quick'), (self._make_export_image_widget, 'Image'), (self._make_command_box, 'Command')] extra_box = _make_delay_tab(extra_list, selected_index=0) self.widget_extra = extra_box return self.widget_extra def _make_theme_box(self): if self.widget_theme is None: self.widget_theme = Box([self._make_button_theme(), self._make_button_reset_theme(hide_toolbar=False), self._make_button_reset_theme(hide_toolbar=True), self._make_button_clean_error_output()]) return self.widget_theme def _make_general_box(self): if self.widget_general is None: step_slide = IntSlider( value=self.step, min=-100, max=100, description='step') delay_text = IntSlider( value=self.delay, min=10, max=1000, description='delay') toggle_button_interpolate = ToggleButton(self.interpolate, description='Smoothing', tooltip='smoothing trajectory') link((toggle_button_interpolate, 'value'), (self, 'interpolate')) background_color_picker = ColorPicker(value='white', description='background') camera_type = Dropdown(value=self.camera, options=['perspective', 'orthographic'], description='camera') link((step_slide, 'value'), (self, 'step')) link((delay_text, 'value'), (self, 'delay')) link((toggle_button_interpolate, 'value'), (self, 'interpolate')) link((camera_type, 'value'), (self, 'camera')) link((background_color_picker, 'value'), (self._view, 'background')) center_button = self._make_button_center() render_button = self._show_download_image() qtconsole_button = self._make_button_qtconsole() center_render_hbox = _make_autofit(HBox([toggle_button_interpolate, center_button, render_button, qtconsole_button])) v0_left = VBox([step_slide, delay_text, background_color_picker, camera_type, center_render_hbox, ]) v0_left = _relayout_master(v0_left, width='100%') self.widget_general = v0_left return self.widget_general def _make_command_box(self): widget_text_command = Text() @widget_text_command.on_submit def _on_submit_command(_): command = widget_text_command.value js_utils.execute(command) widget_text_command.value = '' return widget_text_command def _create_all_tabs(self): tab = self._display() for index, _ in enumerate(tab.children): # trigger ceating widgets tab.selected_index = index self.widget_extra = self._make_extra_box() for index, _ in enumerate(self.widget_extra.children): self.widget_extra.selected_index = index def _simplify_repr_control(self): for widget in self.widget_repr._saved_widgets: if not isinstance(widget, Tab): widget.layout.display = 'none' self.widget_repr_choices.layout.display = 'flex' self.widget_accordion_repr_parameters.selected_index = 0
class ExplorerReports(ExplorerPane): def __init__(self, es: ExplorerThresholds, parent_widget=None): super().__init__(parent_widget=parent_widget) self.selector = es self.report_picker = Dropdown( options=[ ' ', _report_picker_current_selection, _report_picker_build_nobuild, 'Other Report' ], value=' ', description='Choose:', disabled=False, ) self.report_picker.observe(self.report_picker_action) self.second_picker = Dropdown( options=(" ", ), value=' ', description=" ", disabled=False, ) self.second_picker.layout.visibility = 'hidden' self.report_pane = Output(layout=Layout(width='7.5in', ), ) self.make_stack( self.report_picker, self.second_picker, self.report_pane, ) self.next_button.disabled = True def redraw_with_no_second_picker(self): self.second_picker.layout.visibility = 'hidden' def redraw_with_bnb_picker(self, second_options=(' ', ), label="Choose:"): # self.second_picker = Dropdown( # options=second_options, # description=label, # disabled=True, # ) # self.second_picker.layout.visibility = 'visible' self.second_picker.options = (' ', ) + tuple(second_options) self.second_picker.description = "Strategy:" # # self.stack = VBox([ # self.report_picker, # self.second_picker, # self.report_pane, # ]) self.second_picker.observe(self.bnb_picker_action) def report_picker_action(self, action_content): if 'name' in action_content and action_content['name'] == 'value': if 'new' in action_content: if action_content['new'] == _report_picker_current_selection: self.redraw_with_no_second_picker() self.report_pane.clear_output(wait=True) single_report(self.selector, output_to=self.report_pane) elif action_content['new'] == _report_picker_build_nobuild: # self.report_pane.clear_output(wait=True) # build_no_build_report(self.selector, output_to=self.report_pane) self.redraw_with_bnb_picker( second_options=self.selector.data.strategy_names) else: self.report_pane.clear_output(wait=True) with self.report_pane: print( f"{action_content['new']} is not implemented in this version of Explorer" ) def bnb_picker_action(self, action_content): if 'name' in action_content and action_content['name'] == 'value': if 'new' in action_content: if action_content['new'] == " ": self.report_pane.clear_output() else: self.report_pane.clear_output(wait=True) build_no_build_report(self.selector, bnb=action_content['new'], output_to=self.report_pane)
datetime.now(), kwargs['coordinates'], random.randint( -20, 20), random.randint(0, 100)) out.value = add_log(msg) m.on_interaction(handle_interaction) def on_map_selected(change): m.layers = [ basemap_to_tiles(maps[basemap_selector.value]), weather_maps[heatmap_selector.value] ] basemap_selector.observe(on_map_selected, names='value') heatmap_selector.observe(on_map_selected, names='value') # In[18]: temp = TileLayer( min_zoom=1, max_zoom=18, url='https://tile.openweathermap.org/map/temp_new/{z}/{x}/{y}.png?appid=' + OWM_API_KEY, name='owm', attribute='me') precipitation = TileLayer( min_zoom=1, max_zoom=18, url=
def time_series_widget(aoi, year, pid): path = normpath( join(config.get_value(['paths', 'temp']), aoi, str(year), str(pid))) # confvalues = config.read() # inst = confvalues['set']['institution'] file_info = normpath(join(path, 'info.json')) with open(file_info, 'r') as f: info_data = json.loads(f.read()) pid = info_data['pid'][0] ts_cloud = Checkbox(value=True, description='Cloud free', disabled=False, indent=False) ts_files = glob.glob(normpath(join(path, '*time_series*.csv'))) ts_file_types = [b.split('_')[-1].split('.')[0] for b in ts_files] if 's2' in ts_file_types: ts_file_types.append('ndvi') ts_types = [t for t in data_options.pts_tstype() if t[1] in ts_file_types] ts_type = Dropdown( options=ts_types, description='Select type:', disabled=False, ) btn_ts = Button(value=False, description='Plot TS', disabled=False, button_style='info', tooltip='Refresh output', icon='') ts_out = Output() @btn_ts.on_click def btn_ts_on_click(b): btn_ts.description = 'Refresh' btn_ts.icon = 'refresh' with ts_out: ts_out.clear_output() if ts_type.value == 's2': time_series.s2(aoi, str(year), str(pid), bands=['B4', 'B8']) elif ts_type.value == 'ndvi': time_series.ndvi(aoi, str(year), str(pid)) elif ts_type.value == 'bs': time_series.s1(aoi, str(year), str(pid), 'bs') elif ts_type.value == 'c6': time_series.s1(aoi, str(year), str(pid), 'c6') def on_ts_type_change(change): if ts_type.value == 's2': wbox_ts.children = [btn_ts, ts_type] else: wbox_ts.children = [btn_ts, ts_type] ts_type.observe(on_ts_type_change, 'value') wbox_ts = HBox([btn_ts, ts_type, ts_cloud]) wbox = VBox([wbox_ts, ts_out]) return wbox
class TrafficWidget(object): # -- Constructor -- def __init__(self, traffic: Traffic, projection=EuroPP()) -> None: ipython = get_ipython() ipython.magic("matplotlib ipympl") from ipympl.backend_nbagg import FigureCanvasNbAgg, FigureManagerNbAgg self.fig_map = Figure(figsize=(6, 6)) self.fig_time = Figure(figsize=(6, 4)) self.canvas_map = FigureCanvasNbAgg(self.fig_map) self.canvas_time = FigureCanvasNbAgg(self.fig_time) self.manager_map = FigureManagerNbAgg(self.canvas_map, 0) self.manager_time = FigureManagerNbAgg(self.canvas_time, 0) layout = {"width": "590px", "height": "800px", "border": "none"} self.output = Output(layout=layout) self._traffic = traffic self.t_view = traffic.sort_values("timestamp") self.trajectories: Dict[str, List[Artist]] = defaultdict(list) self.create_map(projection) self.projection = Dropdown(options=["EuroPP", "Lambert93", "Mercator"]) self.projection.observe(self.on_projection_change) self.identifier_input = Text(description="Callsign/ID") self.identifier_input.observe(self.on_id_input) self.identifier_select = SelectMultiple( options=sorted(self._traffic.callsigns), # type: ignore value=[], rows=20, ) self.identifier_select.observe(self.on_id_change) self.area_input = Text(description="Area") self.area_input.observe(self.on_area_input) self.extent_button = Button(description="Extent") self.extent_button.on_click(self.on_extent_button) self.plot_button = Button(description="Plot") self.plot_button.on_click(self.on_plot_button) self.clear_button = Button(description="Reset") self.clear_button.on_click(self.on_clear_button) self.plot_airport = Button(description="Airport") self.plot_airport.on_click(self.on_plot_airport) self.area_select = SelectMultiple(options=[], value=[], rows=3, disabled=False) self.area_select.observe(self.on_area_click) self.altitude_select = SelectionRangeSlider( options=[0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000], index=(0, 8), description="Altitude", disabled=False, continuous_update=False, ) self.altitude_select.observe(self.on_altitude_select) self.time_slider = SelectionRangeSlider( options=list(range(100)), index=(0, 99), description="Date", continuous_update=False, ) self.lock_time_change = False self.set_time_range() self.time_slider.observe(self.on_time_select) self.canvas_map.observe(self.on_axmap_change, ["_button", "_png_is_old"]) self.canvas_time.observe(self.on_axtime_change, ["_png_is_old"]) col_options = [] for column, dtype in self._traffic.data.dtypes.items(): if column not in ("latitude", "longitude"): if dtype in ["float64", "int64"]: col_options.append(column) self.y_selector = SelectMultiple(options=col_options, value=[], rows=5, disabled=False) self.y_selector.observe(self.on_id_change) self.sec_y_selector = SelectMultiple(options=col_options, value=[], rows=5, disabled=False) self.sec_y_selector.observe(self.on_id_change) self.time_tab = VBox( [HBox([self.y_selector, self.sec_y_selector]), self.canvas_time]) self.tabs = Tab() self.tabs.children = [self.canvas_map, self.time_tab] self.tabs.set_title(0, "Map") self.tabs.set_title(1, "Plots") self._main_elt = HBox([ self.tabs, VBox([ self.projection, HBox([self.extent_button, self.plot_button]), HBox([self.plot_airport, self.clear_button]), self.area_input, self.area_select, self.time_slider, self.altitude_select, self.identifier_input, self.identifier_select, ]), ]) @property def traffic(self) -> Traffic: return self._traffic def _ipython_display_(self) -> None: clear_output() self.canvas_map.draw_idle() self._main_elt._ipython_display_() def debug(self) -> None: if self.tabs.children[-1] != self.output: self.tabs.children = list(self.tabs.children) + [self.output] def set_time_range(self) -> None: with self.output: tz_now = datetime.now().astimezone().tzinfo start_time = cast(pd.Timestamp, self._traffic.start_time) end_time = cast(pd.Timestamp, self._traffic.end_time) self.dates = [ start_time + i * (end_time - start_time) / 99 for i in range(100) ] if cast(pd.Timestamp, self._traffic.start_time).tzinfo is not None: options = [ t.tz_convert("utc").strftime("%H:%M") for t in self.dates ] else: options = [ t.tz_localize(tz_now).tz_convert("utc").strftime("%H:%M") for t in self.dates ] self.lock_time_change = True self.time_slider.options = options self.time_slider.index = (0, 99) self.lock_time_change = False def create_map(self, projection: Union[str, Projection] = "EuroPP()") -> None: with self.output: if isinstance(projection, str): if not projection.endswith("()"): projection = projection + "()" projection = eval(projection) self.projection = projection with plt.style.context("traffic"): self.fig_map.clear() self.trajectories.clear() self.ax_map = self.fig_map.add_subplot( 111, projection=self.projection) self.ax_map.add_feature(countries()) if projection.__class__.__name__.split(".")[-1] in [ "Lambert93" ]: self.ax_map.add_feature(rivers()) self.fig_map.set_tight_layout(True) self.ax_map.background_patch.set_visible(False) self.ax_map.outline_patch.set_visible(False) self.ax_map.format_coord = lambda x, y: "" self.ax_map.set_global() self.default_plot() self.canvas_map.draw_idle() def default_plot(self) -> None: with self.output: # clear all trajectory pieces for key, value in self.trajectories.items(): for elt in value: elt.remove() self.trajectories.clear() self.ax_map.set_prop_cycle(None) lon_min, lon_max, lat_min, lat_max = self.ax_map.get_extent( PlateCarree()) cur_flights = list( f.at() for f in self.t_view if lat_min <= getattr(f.at(), "latitude", -90) <= lat_max and lon_min <= getattr(f.at(), "longitude", -180) <= lon_max) def params(at): if len(cur_flights) < 10: return dict(s=8, text_kw=dict(s=at.callsign)) else: return dict(s=8, text_kw=dict(s="")) for at in cur_flights: if at is not None: self.trajectories[at.callsign] += at.plot( self.ax_map, **params(at)) self.canvas_map.draw_idle() def create_timeplot(self) -> None: with plt.style.context("traffic"): self.fig_time.clear() self.ax_time = self.fig_time.add_subplot(111) self.fig_time.set_tight_layout(True) # -- Callbacks -- def on_projection_change(self, change: Dict[str, Any]) -> None: with self.output: if change["name"] == "value": self.create_map(change["new"]) def on_clear_button(self, elt: Dict[str, Any]) -> None: with self.output: self.t_view = self.traffic.sort_values("timestamp") self.create_map(self.projection) self.create_timeplot() def on_area_input(self, elt: Dict[str, Any]) -> None: with self.output: if elt["name"] != "value": return search_text = elt["new"] if len(search_text) == 0: self.area_select.options = list() else: from ..data import nm_airspaces self.area_select.options = list( x.name for x in nm_airspaces.parse(search_text)) def on_area_click(self, elt: Dict[str, Any]) -> None: with self.output: if elt["name"] != "value": return from ..data import nm_airspaces self.ax_map.set_extent(nm_airspaces[elt["new"][0]]) self.canvas_map.draw_idle() def on_extent_button(self, elt: Dict[str, Any]) -> None: with self.output: if len(self.area_select.value) == 0: if len(self.area_input.value) == 0: self.ax_map.set_global() else: self.ax_map.set_extent(location(self.area_input.value)) else: from ..data import nm_airspaces self.ax_map.set_extent(nm_airspaces[self.area_select.value[0]]) t1, t2 = self.time_slider.index low, up = self.altitude_select.value self.on_filter(low, up, t1, t2) self.canvas_map.draw_idle() def on_axtime_change(self, change: Dict[str, Any]) -> None: with self.output: if change["name"] == "_png_is_old": # go away!! return self.canvas_map.set_window_title("") def on_axmap_change(self, change: Dict[str, Any]) -> None: with self.output: if change["name"] == "_png_is_old": # go away!! return self.canvas_map.set_window_title("") if change["new"] is None: t1, t2 = self.time_slider.index low, up = self.altitude_select.value self.on_filter(low, up, t1, t2) def on_id_input(self, elt: Dict[str, Any]) -> None: with self.output: # typing issue because of the lru_cache_wrappen callsigns = cast(Set[str], self.t_view.callsigns) # low, up = alt.value self.identifier_select.options = sorted( callsign for callsign in callsigns if re.match( elt["new"]["value"], callsign, flags=re.IGNORECASE)) def on_plot_button(self, elt: Dict[str, Any]) -> None: with self.output: if len(self.area_select.value) == 0: if len(self.area_input.value) == 0: return self.default_plot() location(self.area_input.value).plot(self.ax_map, color="grey", linestyle="dashed") else: from ..data import nm_airspaces airspace = nm_airspaces[self.area_select.value[0]] if airspace is not None: airspace.plot(self.ax_map) self.canvas_map.draw_idle() def on_plot_airport(self, elt: Dict[str, Any]) -> None: with self.output: if len(self.area_input.value) == 0: from cartotools.osm import request, tags west, east, south, north = self.ax_map.get_extent( crs=PlateCarree()) if abs(east - west) > 1 or abs(north - south) > 1: # that would be a too big request return request((west, south, east, north), **tags.airport).plot(self.ax_map) else: from ..data import airports airport_handle = airports[self.area_input.value] assert airport_handle is not None airport_handle.plot(self.ax_map) self.canvas_map.draw_idle() def on_id_change(self, change: Dict[str, Any]) -> None: with self.output: if change["name"] != "value": return y = self.y_selector.value + self.sec_y_selector.value secondary_y = self.sec_y_selector.value callsigns = self.identifier_select.value if len(y) == 0: y = ["altitude"] extra_dict = dict() if len(y) > 1: # just to avoid confusion... callsigns = callsigns[:1] # clear all trajectory pieces self.create_timeplot() for key, value in self.trajectories.items(): for elt in value: elt.remove() self.trajectories.clear() for callsign in callsigns: flight = self.t_view[callsign] if len(y) == 1: extra_dict["label"] = callsign if flight is not None: try: self.trajectories[callsign] += flight.plot(self.ax_map) at = flight.at() if at is not None: self.trajectories[callsign] += at.plot( self.ax_map, s=8, text_kw=dict(s=callsign)) except Exception: # NoneType object is not iterable pass try: flight.plot_time( self.ax_time, y=y, secondary_y=secondary_y, **extra_dict, ) except Exception: # no numeric data to plot pass if len(callsigns) == 0: self.default_plot() else: self.ax_time.legend() # non conformal with traffic style for elt in self.ax_time.get_xticklabels(): elt.set_size(12) for elt in self.ax_time.get_yticklabels(): elt.set_size(12) self.ax_time.set_xlabel("") self.canvas_map.draw_idle() self.canvas_time.draw_idle() if len(callsigns) != 0: low, up = self.ax_time.get_ylim() if (up - low) / up < 0.05: self.ax_time.set_ylim(up - 0.05 * up, up + 0.05 * up) self.canvas_time.draw_idle() def on_filter(self, low, up, t1, t2) -> None: with self.output: west, east, south, north = self.ax_map.get_extent( crs=PlateCarree()) self.t_view = (self.traffic.between( self.dates[t1], self.dates[t2]).query( f"{low} <= altitude <= {up} or altitude != altitude" ).query( f"{west} <= longitude <= {east} and " f"{south} <= latitude <= {north}").sort_values("timestamp") ) self.identifier_select.options = sorted( flight.callsign for flight in self.t_view if flight is not None and re.match( self.identifier_input.value, flight.callsign, flags=re.IGNORECASE, )) return self.default_plot() def on_altitude_select(self, change: Dict[str, Any]) -> None: with self.output: if change["name"] != "value": return low, up = change["new"] t1, t2 = self.time_slider.index self.on_filter(low, up, t1, t2) def on_time_select(self, change: Dict[str, Any]) -> None: with self.output: if self.lock_time_change: return if change["name"] != "index": return t1, t2 = change["new"] low, up = self.altitude_select.value self.on_filter(low, up, t1, t2)
def time_series(path): import matplotlib.pyplot as plt import matplotlib.dates as mdates from datetime import timedelta import pandas as pd import json import glob confvalues = config.read() inst = confvalues['set']['institution'] file_info = glob.glob(f"{path}*_information.json")[0] with open(file_info, 'r') as f: info_data = json.loads(f.read()) pid = info_data['ogc_fid'][0] crop_name = info_data['cropname'][0] area = info_data['area'][0] figure_dpi = 50 def plot_ts_s2(cloud): file_ts = glob.glob(f"{path}*_time_series_s2.csv")[0] df = pd.read_csv(file_ts, index_col=0) df['date'] = pd.to_datetime(df['date_part'], unit='s') start_date = df.iloc[0]['date'].date() end_date = df.iloc[-1]['date'].date() print(f"From '{start_date}' to '{end_date}'.") pd.set_option('max_colwidth', 200) pd.set_option('display.max_columns', 20) # Plot settings are confirm IJRS graphics instructions plt.rcParams['axes.titlesize'] = 16 plt.rcParams['axes.labelsize'] = 14 plt.rcParams['xtick.labelsize'] = 12 plt.rcParams['ytick.labelsize'] = 12 plt.rcParams['legend.fontsize'] = 14 df.set_index(['date'], inplace=True) dfB4 = df[df.band == 'B4'].copy() dfB8 = df[df.band == 'B8'].copy() datesFmt = mdates.DateFormatter('%-d %b %Y') if cloud is False: # Plot NDVI fig = plt.figure(figsize=(16.0, 10.0)) axb = fig.add_subplot(1, 1, 1) axb.set_title( f"Parcel {pid} (crop: {crop_name}, area: {area:.2f} ha)") axb.set_xlabel("Date") axb.xaxis.set_major_formatter(datesFmt) axb.set_ylabel(r'DN') axb.plot(dfB4.index, dfB4['mean'], linestyle=' ', marker='s', markersize=10, color='DarkBlue', fillstyle='none', label='B4') axb.plot(dfB8.index, dfB8['mean'], linestyle=' ', marker='o', markersize=10, color='Red', fillstyle='none', label='B8') axb.set_xlim(start_date, end_date + timedelta(1)) axb.set_ylim(0, 10000) axb.legend(frameon=False) # loc=2) return plt.show() else: # Plot Cloud free NDVI. dfSC = df[df.band == 'SC'].copy() dfNDVI = (dfB8['mean'] - dfB4['mean']) / \ (dfB8['mean'] + dfB4['mean']) cloudfree = ((dfSC['mean'] >= 4) & (dfSC['mean'] < 6)) fig = plt.figure(figsize=(16.0, 10.0)) axb = fig.add_subplot(1, 1, 1) axb.set_title( f"{inst}\nParcel {pid} (crop: {crop_name}, area: {area:.2f} sqm)" ) axb.set_xlabel("Date") axb.xaxis.set_major_formatter(datesFmt) axb.set_ylabel(r'NDVI') axb.plot(dfNDVI.index, dfNDVI, linestyle=' ', marker='s', markersize=10, color='DarkBlue', fillstyle='none', label='NDVI') axb.plot(dfNDVI[cloudfree].index, dfNDVI[cloudfree], linestyle=' ', marker='P', markersize=10, color='Red', fillstyle='none', label='Cloud free NDVI') axb.set_xlim(start_date, end_date + timedelta(1)) axb.set_ylim(0, 1.0) axb.legend(frameon=False) # loc=2) return plt.show() def plot_ts_bs(): import numpy as np file_ts = glob.glob(f"{path}*_time_series_bs.csv")[0] df = pd.read_csv(file_ts, index_col=0) df['date'] = pd.to_datetime(df['date_part'], unit='s') start_date = df.iloc[0]['date'].date() end_date = df.iloc[-1]['date'].date() print(f"From '{start_date}' to '{end_date}'.") pd.set_option('max_colwidth', 200) pd.set_option('display.max_columns', 20) # Plot settings are confirm IJRS graphics instructions plt.rcParams['axes.titlesize'] = 16 plt.rcParams['axes.labelsize'] = 14 plt.rcParams['xtick.labelsize'] = 12 plt.rcParams['ytick.labelsize'] = 12 plt.rcParams['legend.fontsize'] = 14 df.set_index(['date'], inplace=True) datesFmt = mdates.DateFormatter('%-d %b %Y') # Plot Backscattering coefficient datesFmt = mdates.DateFormatter('%-d %b %Y') df = df[df['mean'] >= 0] # to remove negative values dfVV = df[df.band == 'VV'].copy() dfVH = df[df.band == 'VH'].copy() fig = plt.figure(figsize=(16.0, 10.0)) axb = fig.add_subplot(1, 1, 1) dfVV['mean'] = dfVV['mean'].map(lambda s: 10.0 * np.log10(s)) dfVH['mean'] = dfVH['mean'].map(lambda s: 10.0 * np.log10(s)) axb.set_title( f"{inst}\nParcel {pid} (crop: {crop_name}, area: {area:.2f} sqm)") axb.set_xlabel("Date") axb.xaxis.set_major_formatter(datesFmt) axb.set_ylabel(r'Backscattering coefficient, $\gamma\degree$ (dB)') axb.plot(dfVH.index, dfVH['mean'], linestyle=' ', marker='s', markersize=10, color='DarkBlue', fillstyle='none', label='VH') axb.plot(dfVV.index, dfVV['mean'], linestyle=' ', marker='o', markersize=10, color='Red', fillstyle='none', label='VV') axb.set_xlim(start_date, end_date + timedelta(1)) axb.set_ylim(-25, 0) axb.legend(frameon=False) # loc=2) return plt.show() def plot_ts_c6(): file_ts = glob.glob(f"{path}*_time_series_c6.csv")[0] df = pd.read_csv(file_ts, index_col=0) df['date'] = pd.to_datetime(df['date_part'], unit='s') start_date = df.iloc[0]['date'].date() end_date = df.iloc[-1]['date'].date() print(f"From '{start_date}' to '{end_date}'.") pd.set_option('max_colwidth', 200) pd.set_option('display.max_columns', 20) datesFmt = mdates.DateFormatter('%-d %b %Y') # Plot settings are confirm IJRS graphics instructions plt.rcParams['axes.titlesize'] = 16 plt.rcParams['axes.labelsize'] = 14 plt.rcParams['xtick.labelsize'] = 12 plt.rcParams['ytick.labelsize'] = 12 plt.rcParams['legend.fontsize'] = 14 df.set_index(['date'], inplace=True) # Plot Coherence dfVV = df[df.band == 'VV'].copy() dfVH = df[df.band == 'VH'].copy() fig = plt.figure(figsize=(16.0, 10.0)) axb = fig.add_subplot(1, 1, 1) axb.set_title( f"{inst}\nParcel {pid} (crop: {crop_name}, area: {area:.2f} sqm)") axb.set_xlabel("Date") axb.xaxis.set_major_formatter(datesFmt) axb.set_ylabel(r'Coherence') axb.plot(dfVH.index, dfVH['mean'], linestyle=' ', marker='s', markersize=10, color='DarkBlue', fillstyle='none', label='VH') axb.plot(dfVV.index, dfVV['mean'], linestyle=' ', marker='o', markersize=10, color='Red', fillstyle='none', label='VV') axb.set_xlim(start_date, end_date + timedelta(1)) axb.set_ylim(0, 1) axb.legend(frameon=False) # loc=2) return plt.show() ts_cloud = Checkbox(value=True, description='Cloud free', disabled=False, indent=False) ts_files = glob.glob(f"{path}*time_series*.csv") ts_file_types = [b.split('_')[-1].split('.')[0] for b in ts_files] ts_types = [t for t in data_options.pts_tstype() if t[1] in ts_file_types] ts_type = Dropdown( options=ts_types, description='Select type:', disabled=False, ) btn_ts = Button(value=False, description='Plot TS', disabled=False, button_style='info', tooltip='Refresh output', icon='') ts_out = Output() @btn_ts.on_click def btn_ts_on_click(b): btn_ts.description = 'Refresh' btn_ts.icon = 'refresh' with ts_out: ts_out.clear_output() if ts_type.value == 's2': plot_ts_s2(ts_cloud.value) elif ts_type.value == 'bs': plot_ts_bs() elif ts_type.value == 'c6': plot_ts_c6() def on_ts_type_change(change): if ts_type.value == 's2': wbox_ts.children = [btn_ts, ts_type, ts_cloud] else: wbox_ts.children = [btn_ts, ts_type] ts_type.observe(on_ts_type_change, 'value') wbox_ts = HBox([btn_ts, ts_type, ts_cloud]) wbox = VBox([wbox_ts, ts_out]) return wbox
def _tensor_folder(self): alo = Layout(width='70px') rlo = Layout(width='220px') scale = FloatSlider(max=10.0, step=0.001, readout=True, value=1.0) xs = [Text(layout=alo,disabled=True), Text(layout=alo,disabled=True), Text(layout=alo,disabled=True)] ys = [Text(layout=alo,disabled=True), Text(layout=alo,disabled=True), Text(layout=alo,disabled=True)] zs = [Text(layout=alo,disabled=True), Text(layout=alo,disabled=True), Text(layout=alo,disabled=True)] cs = [Text(layout=alo,disabled=True), Text(layout=alo,disabled=True), Text(layout=alo,disabled=True)] cidx = HBox([Text(disabled=True,description='Atom Index',layout=rlo)]) xbox = HBox(xs, layout=rlo) ybox = HBox(ys, layout=rlo) zbox = HBox(zs, layout=rlo) cbox = HBox(cs, layout=rlo) tens = Button(description=' Tensor', icon='bank') tensor_cont = VBox([xbox,ybox,zbox]) tensorIndex = Dropdown(options=[0],value=0,description='Tensor') # sceneIndex = Dropdown(options=[0],value=0,description='Scene') ten_label = Label(value="Change selected tensor:") sel_label = Label(value="Selected tensor in gray frame") cod_label = Label(value="Center of selected tensor: (x,y,z)") tensor = [] self.coords = [] def _changeTensor(tensor, tdx): carts = ['x','y','z'] for i,bra in enumerate(carts): for j,ket in enumerate(carts): tensor_cont.children[i].children[j].disabled=False tensor_cont.children[i].children[j].value = \ str(tensor[0][tdx][bra+ket]) tensor_cont.children[i].children[j].disabled=True adx = tensor[0][tdx]['atom'] cidx.children[0].value = str(adx) cbox.children[0].value = str(self.coords[0][int(adx)]) cbox.children[1].value = str(self.coords[1][int(adx)]) cbox.children[2].value = str(self.coords[2][int(adx)]) # scale.value = tensor[0][tdx]['scale'] def _tens(c): for scn in self.active(): scn.tens = not scn.tens self.coords = self._filter_coords() # sceneIndex.options = [x for x in range(len(self.active()))] # sceneIndex.value = sceneIndex.options[0] tensor = self.active()[0].tensor_d tensorIndex.options = [x for x in range(len(tensor[0]))] tensorIndex.value = tensorIndex.options[0] tdx = tensorIndex.value _changeTensor(tensor, tdx) def _scale(c): for scn in self.active(): scn.scale = c.new # tdx = tensorIndex.value # tensor = self.active()[0].tensor_d # tensor[0][tdx]['scale'] = c.new def _idx(c): for scn in self.active(): scn.tidx = c.new tensor = self.active()[0].tensor_d tdx = c.new _changeTensor(tensor, tdx) # def _sdx(c): # tensor = self.active()[sceneIndex.value].tensor_d # tensorIndex.options = [x for x in range(len(tensor[0]))] # tensorIndex.value = tensorIndex.options[0] # tdx = tensorIndex.value # _changeTensor(tensor, tdx) tens.on_click(_tens) scale.observe(_scale, names='value') tensorIndex.observe(_idx, names='value') # sceneIndex.observe(_sdx, names='value') content = _ListDict([ ('scale', scale), ('ten', ten_label), # ('sdx', sceneIndex), ('tdx', tensorIndex), ('tensor', tensor_cont), ('sel', sel_label), ('cidx', cidx), ('center', cod_label), ('coord', cbox)]) return Folder(tens, content)
class Figure1: def __init__(self, csv_file_path, base_path='', inchi_key='XFYICZOIWSBQSK-UHFFFAOYSA-N', cluster=None): self.selected_plate = None self.old_plate = None self.base_path = base_path self.clustering = cluster self.full_perovskite_data = pd.read_csv( csv_file_path, low_memory=False, skiprows=4) self.full_perovskite_data = self.full_perovskite_data[ self.full_perovskite_data['_raw_ExpVer'] >= 1.1] self.organic_inchis = pd.read_csv( './perovskitedata/organic_inchikey.csv', sep='\t') self.solvent_inchis = json.load(open('./perovskitedata/solvents.json')) # Filtering inchis that exist in full_perovskite_data self.state_spaces = pd.read_csv('./perovskitedata/state_spaces.csv') self.ss_dict = {} for row in self.state_spaces.iterrows(): row = list(row[1]) # app.logger.info(row) points = [ast.literal_eval(pt) for pt in row[1:-1]] chemical_abbrev = ast.literal_eval(row[-1])[1] inchi_row = self.organic_inchis[self.organic_inchis['Chemical Abbreviation'] == chemical_abbrev] if not inchi_row.empty: row = inchi_row.iloc[0] self.ss_dict[row['InChI Key (ID)']] = points self.generate_plot(inchi_key, '') self.setup_widgets() def generate_plot(self, inchi_key, solvent_inchi): if inchi_key in self.ss_dict: self.setup_hull(hull_points=self.ss_dict[inchi_key]) else: self.setup_hull(hull_points=[[0, 0, 0]]) self.gen_amine_traces(inchi_key, solvent=solvent_inchi) self.setup_plot() def setup_hull(self, hull_points=[[0., 0., 0.], [0., 2.3, 0.], [1.86, 1.86, 0.], [0., 0., 9.5], [1.19339, 1.19339, 9.5], [0., 1.4757, 9.5]]): xp, yp, zp = zip(*hull_points) self.hull_mesh = go.Mesh3d(x=xp, y=yp, z=zp, color='green', opacity=0.50, alphahull=0) def gen_amine_traces(self, inchi_key, amine_short_name='Me2NH2I', solvent=None): amine_data = self.full_perovskite_data.loc[self.full_perovskite_data['_rxn_organic-inchikey'] == inchi_key] if solvent: amine_data = amine_data[amine_data['_raw_reagent_0_chemicals_0_InChIKey'] == solvent] print(f'Total points: {len(amine_data)}') self.max_inorg = amine_data['_rxn_M_inorganic'].max() self.max_org = amine_data['_rxn_M_organic'].max() self.max_acid = amine_data['_rxn_M_acid'].max() # Splitting by crystal scores. Assuming crystal scores from 1-4 self.amine_crystal_dfs = [] for i in range(1, 5): self.amine_crystal_dfs.append( amine_data.loc[amine_data['_out_crystalscore'] == i]) self.amine_crystal_traces = [] self.trace_colors = ['rgba(65, 118, 244, 1.0)', 'rgba(92, 244, 65, 1.0)', 'rgba(244, 238, 66, 1.0)', 'rgba(244, 66, 66, 1.0)'] for i, df in enumerate(self.amine_crystal_dfs): trace = go.Scatter3d( x=df['_rxn_M_inorganic'], y=df['_rxn_M_organic'], z=df['_rxn_M_acid'], mode='markers', name='Score {}'.format(i+1), text=['<b>PbI3</b>: {:.3f} <br><b>Amine</b>: {:.3f} <br><b>FAH</b>: {:.3f}'.format( row['_rxn_M_inorganic'], row['_rxn_M_organic'], row['_rxn_M_acid']) for idx, row in df.iterrows()], hoverinfo='text', marker=dict( size=4, color=self.trace_colors[i], line=dict( width=0.2 ), opacity=1.0 ) ) self.amine_crystal_traces.append(trace) if i == 3: # normed = preprocessing.minmax_scale( # [df['_rxn_M_inorganic'], df['_rxn_M_organic'], df['_rxn_M_acid']], axis=1) # normed_success_points = np.dstack( # (normed[0], normed[1], normed[2]))[0] success_points = np.dstack( (df['_rxn_M_inorganic'], df['_rxn_M_organic'], df['_rxn_M_acid']))[0] ones_hull = None if self.clustering is not None: self.clustering.fit(success_points) # print(self.clustering.labels_) one_labels = success_points[[ True if i == 0 else False for i in self.clustering.labels_]] ones_hull = ConvexHull(one_labels) success_hull = None if len(success_points): success_hull = ConvexHull(success_points) self.data = self.amine_crystal_traces if ones_hull is not None: xp, yp, zp = zip(*one_labels[ones_hull.vertices]) self.ones_hull_plot = go.Mesh3d(x=xp, y=yp, z=zp, color='yellow', opacity=0.50, alphahull=0) x_mean = np.mean(xp) y_mean = np.mean(yp) z_mean = np.mean(zp) # print('Cluster Hull centroid wrt points: ({}, {}, {})'.format( # x_mean, y_mean, z_mean)) # print('Cluster Hull centroid wrt sides: ({}, {}, {})'.format( # *self.com_edges(xp, yp, zp))) self.data += [self.ones_hull_plot] if success_hull: xp, yp, zp = zip(*success_points[success_hull.vertices]) self.success_hull_plot = go.Mesh3d(x=xp, y=yp, z=zp, color='red', opacity=0.50, alphahull=0) x_mean = np.mean(xp) y_mean = np.mean(yp) z_mean = np.mean(zp) # print('Success Hull centroid wrt points: ({}, {}, {})'.format( # x_mean, y_mean, z_mean)) # print('Success Hull centroid wrt sides: ({}, {}, {})'.format( # *self.com_edges(xp, yp, zp))) self.data += [self.success_hull_plot] if self.hull_mesh: self.data += [self.hull_mesh] def com_edges(self, px, py, pz): sx = sy = sz = slen = 0 x1 = px[-1] y1 = py[-1] z1 = pz[-1] for i in range(len(px)): x2 = px[i] y2 = py[i] z2 = pz[i] dx = x2 - x1 dy = y2 - y1 dz = z2 - z1 length = math.sqrt(dx*dx + dy*dy + dz*dz) sx = sx + (x1 + x2)/2*length sy = sy + (y1 + y2)/2*length sz = sz + (z1 + z2)/2*length slen = slen + length x1 = x2 y1 = y2 z1 = z2 cx = sx/slen cy = sy/slen cz = sz/slen return cx, cy, cz def setup_plot(self, xaxis_label='Lead Iodide [PbI3] (M)', yaxis_label='Dimethylammonium Iodide<br>[Me2NH2I] (M)', zaxis_label='Formic Acid [FAH] (M)'): self.layout = go.Layout( scene=dict( xaxis=dict( title=xaxis_label, tickmode='linear', dtick=0.5, range=[0, self.max_inorg], ), yaxis=dict( title=yaxis_label, tickmode='linear', dtick=0.5, range=[0, self.max_org], ), zaxis=dict( title=zaxis_label, tickmode='linear', dtick=1.0, range=[0, self.max_acid], ), ), legend=go.layout.Legend( x=0, y=1, traceorder="normal", font=dict( family="sans-serif", size=12, color="black" ), bgcolor="LightSteelBlue", bordercolor="Black", borderwidth=2 ), width=975, height=700, margin=go.layout.Margin( l=20, r=20, b=20, t=20, pad=2 ), ) try: with self.fig.batch_update(): for i, trace in enumerate(self.data): self.fig.data[i].x = trace.x self.fig.data[i].y = trace.y self.fig.data[i].z = trace.z self.fig.layout.update(self.layout) except: self.fig = go.FigureWidget(data=self.data, layout=self.layout) for trace in self.fig.data[:-1]: trace.on_click(self.show_data_3d_callback) def setup_widgets(self, image_folder='images'): image_folder = self.base_path + '/' + image_folder self.image_list = os.listdir(image_folder) # Data Filter Setup download_robot_file = Button( description='Download Robot File', disabled=False, button_style='', tooltip='Click to download robot file of the current plate', ) download_prep_file = Button( description='Download Reagent Prep', disabled=False, button_style='', tooltip='Click to download reagent preperation file for the current plate', ) reset_plot = Button( description='Reset', disabled=False, tooltip='Reset the colors of the plot' ) xy_check = Button( description='Show X-Y axes', disabled=False, button_style='', tooltip='Click to show X-Y axes' ) show_hull_check = ToggleButton( value=True, description='Show State Space', disabled=False, button_style='', tooltip='Toggle to show/hide state space', icon='check' ) show_success_hull = ToggleButton( value=True, description='Show sucess hull', disabled=False, button_style='', tooltip='Toggle to show/hide success hull', icon='check' ) self.select_amine = Dropdown( options=[row[1]['Chemical Name'] for row in self.organic_inchis.iterrows( ) if len(self.full_perovskite_data.loc[self.full_perovskite_data['_rxn_organic-inchikey'] == row[1]['InChI Key (ID)']]) > 0], description='Amine:', disabled=False, ) self.select_solvent = Dropdown( options=[None], description='Solvent:', disabled=False, ) download_robot_file.on_click(self.download_robot_callback) download_prep_file.on_click(self.download_prep_callback) reset_plot.on_click(self.reset_plot_callback) xy_check.on_click(self.set_xy_camera) show_hull_check.observe(self.toggle_mesh, 'value') show_success_hull.observe(self.toggle_success_mesh, 'value') self.select_amine.observe(self.select_amine_callback, 'value') self.select_solvent.observe(self.select_solvent_callback, 'value') # Experiment data tab setup self.experiment_table = HTML() self.experiment_table.value = "Please click on a point to explore experiment details" self.image_data = {} for img_filename in os.listdir(image_folder): with open("{}/{}".format(image_folder, img_filename), "rb") as f: b = f.read() self.image_data[img_filename] = b self.image_widget = Image( value=self.image_data['not_found.png'], layout=Layout(height='400px', width='650px') ) experiment_view_vbox = VBox( [HBox([self.experiment_table, self.image_widget])]) plot_tabs = Tab([VBox([self.fig, HBox([self.select_amine, self.select_solvent]), HBox([xy_check, show_hull_check, show_success_hull, reset_plot])]), ]) plot_tabs.set_title(0, 'Chemical Space') self.full_widget = VBox([plot_tabs, experiment_view_vbox]) self.full_widget.layout.align_items = 'center' def select_amine_callback(self, state): new_amine_name = state['new'] new_amine_inchi = self.organic_inchis[self.organic_inchis['Chemical Name'] == new_amine_name].iloc[0]['InChI Key (ID)'] amine_data = self.full_perovskite_data[self.full_perovskite_data['_rxn_organic-inchikey'] == new_amine_inchi] solvents = [ inchi for inchi in amine_data['_raw_reagent_0_chemicals_0_InChIKey'].unique()] self.select_solvent.options = ['All'] + [ key for key, value in self.solvent_inchis.items() if value in solvents] solvent_inchi = "" self.generate_plot(new_amine_inchi, solvent_inchi) def select_solvent_callback(self, state): new_solvent_inchi = self.solvent_inchis[state['new']] amine = self.select_amine.value amine_inchi = self.organic_inchis[self.organic_inchis['Chemical Name'] == amine].iloc[0]['InChI Key (ID)'] self.generate_plot(amine_inchi, new_solvent_inchi) def get_plate_options(self): plates = set() for df in self.amine_crystal_dfs: for i, row in df.iterrows(): name = str(row['name']) plate_name = '_'.join(name.split('_')[:-1]) plates.add(plate_name) plate_options = [] for i, plate in enumerate(plates): plate_options.append(plate) return plate_options def generate_table(self, row, columns, column_names): table_html = """ <table border="1" style="width:100%;"> <tbody>""" for i, column in enumerate(columns): if isinstance(row[column], str): value = row[column].split('_')[-1] else: value = np.round(row[column], decimals=3) table_html += """ <tr> <td style="padding: 8px;">{}</td> <td style="padding: 8px;">{}</td> </tr> """.format(column_names[i], value) table_html += """ </tbody> </table> """ return table_html def toggle_mesh(self, state): with self.fig.batch_update(): self.fig.data[-1].visible = state.new def toggle_success_mesh(self, state): with self.fig.batch_update(): self.fig.data[-2].visible = state.new def set_xy_camera(self, state): camera = dict( up=dict(x=0, y=0, z=1), center=dict(x=0, y=0, z=0), eye=dict(x=0.0, y=0.0, z=2.5) ) self.fig['layout'].update( scene=dict(camera=camera), ) def download_robot_callback(self, b): if self.selected_plate: js_string = """ var base_uri = utils.get_body_data("baseUrl"); var file_location = utils.encode_uri_components('{}_RobotInput.xls'); // var final_url = utils.url_path_join(base_uri, 'files', file_location) var final_url = 'files/' + file_location console.log(final_url) window.open(final_url, IPython._target); """.format(self.selected_plate) display(Javascript(js_string)) def download_prep_callback(self, b): if self.selected_plate: js_string = """ var base_uri = utils.get_body_data("baseUrl"); var file_location = utils.encode_uri_components('{}_ExpDataEntry.xlsx'); // var final_url = utils.url_path_join(base_uri, 'files', file_location) var final_url = 'files/' + file_location console.log(final_url) window.open(final_url, IPython._target); """.format(self.selected_plate) display(Javascript(js_string)) def reset_plot_callback(self, b): with self.fig.batch_update(): for i in range(len(self.fig.data[:4])): self.fig.data[i].marker.color = self.trace_colors[i] self.fig.data[i].marker.size = 4 def show_data_3d_callback(self, trace, point, selector): if point.point_inds and point.trace_index < 4: selected_experiment = self.amine_crystal_dfs[point.trace_index].iloc[point.point_inds[0]] with self.fig.batch_update(): for i in range(len(self.fig.data[:4])): color = self.trace_colors[i].split(',') color[-1] = '0.5)' color = ','.join(color) if i == point.trace_index: marker_colors = [color for x in range(len(trace['x']))] marker_colors[point.point_inds[0] ] = self.trace_colors[i] self.fig.data[i].marker.color = marker_colors self.fig.data[i].marker.size = 6 else: self.fig.data[i].marker.color = color self.fig.data[i].marker.size = 4 self.populate_data(selected_experiment) def populate_data(self, selected_experiment): name = selected_experiment['name'] if name+'.jpg' in self.image_list: self.image_widget.value = self.image_data[name+'.jpg'] else: self.image_widget.value = self.image_data['not_found.png'] columns = ['name', '_rxn_M_acid', '_rxn_M_inorganic', '_rxn_M_organic', '_rxn_mixingtime1S', '_rxn_mixingtime2S', '_rxn_reactiontimeS', '_rxn_stirrateRPM', '_rxn_temperatureC_actual_bulk'] column_names = ['Well ID', 'Formic Acid [FAH]', 'Lead Iodide [PbI2]', 'Dimethylammonium Iodide [Me2NH2I]', 'Mixing Time Stage 1 (s)', 'Mixing Time Stage 2 (s)', 'Reaction Time (s)', 'Stir Rate (RPM)', 'Temperature (C)'] prefix = '_'.join(name.split('_')[:-1]) self.selected_plate = prefix self.experiment_table.value = '<p>Plate ID:<br> {}</p>'.format(prefix) + self.generate_table( selected_experiment.loc[columns], columns, column_names) @property def plot(self): return self.full_widget
def hyperExplore(df,initial_axis,initial_surface_axis,legend_group,hover_items): data = df.assign(x=df[initial_axis[0]],y=df[initial_axis[1]])\ .sort_values(legend_group)\ .reset_index(drop=True) group_ops = data[legend_group].sort_values().unique() num_groups = len(group_ops) axis_ops = data.columns.values lenSlide = '500px' fig = px.scatter(data, x="x", y="y", color=legend_group,hover_data=hover_items, log_x=True, title='Hyperparameter Exploration',height=600) fig.update_layout( legend=dict( orientation="v", yanchor="top", y=1.02, xanchor="left", x=1), xaxis=dict(title=initial_axis[0], titlefont=dict(size=14)), yaxis=dict(title=initial_axis[1], titlefont=dict(size=14)) ) fig.update_traces(marker=dict(size=20,line=dict(width=1.5, color='DarkSlateGrey')), selector=dict(mode='markers')) fig.update_layout(plot_bgcolor='rgba(0,0,0,0)') fig.update_xaxes(showgrid=True, gridwidth=.1, gridcolor='lightgrey') fig.update_yaxes(showgrid=True, gridwidth=.1, gridcolor='lightgrey') param_drop1 = Dropdown( value='None', options=np.insert(axis_ops,0,'None'), description='Parameter 1:' ) slider1 = widgets.SelectionSlider( options=['Select Parameter'], value='Select Parameter', layout=Layout(width=lenSlide), continuous_update=True ) size_drop = Dropdown( value='None', options=np.insert(axis_ops,0,'None'), description='Size:' ) size_slider = widgets.IntSlider( value=20, min=10, max=50, step=1, disabled=False, continuous_update=True, orientation='horizontal', layout=Layout(width=lenSlide), readout=True, readout_format='d' ) slider_group1 = widgets.HBox([param_drop1, slider1]) slider_group2 = widgets.HBox([size_drop, size_slider]) xaxis = Dropdown( value=initial_axis[0], options=axis_ops, description='X-axis:' ) yaxis = Dropdown( value=initial_axis[1], options=axis_ops, description='Y-axis:' ) container = widgets.VBox(children=[slider_group1,slider_group2,xaxis,yaxis]) g = go.FigureWidget(data=fig, layout=go.Layout( title=dict( text='Hyperparameter Exploration' ) )) x_surface = Dropdown( value=initial_surface_axis[0], options=axis_ops, description='X-axis' ) y_surface = Dropdown( value=initial_surface_axis[1], options=axis_ops, description='Y-axis' ) z_surface = Dropdown( value=initial_surface_axis[2], options=axis_ops, description='Z-axis' ) surface_buttons = widgets.RadioButtons( options=group_ops, value=group_ops[0], # Defaults to 'pineapple' description=legend_group+":", disabled=False ) z_vals = data.query('{} == "{}"'\ .format(legend_group,surface_buttons.value))[[x_surface.value,y_surface.value,z_surface.value]]\ .groupby([x_surface.value,y_surface.value])\ .median().reset_index()\ .pivot(index=x_surface.value,columns=y_surface.value,values=z_surface.value) fig2 = go.Figure(data=[go.Surface(z=z_vals)]) fig2.update_layout(title='Hyperparameter Surface: '+surface_buttons.value, autosize=False, margin=dict(l=65, r=50, b=65, t=90), height=600) layout = go.Layout( scene = dict( xaxis = dict( title = initial_surface_axis[0]), yaxis = dict( title = initial_surface_axis[1]), zaxis = dict( title = initial_surface_axis[2]), )) fig2.update_layout(layout) container2 = widgets.HBox(children=[surface_buttons,x_surface,y_surface,z_surface]) g2 = go.FigureWidget(data=fig2, layout=go.Layout( title=dict( text='Hyperparameter Surface: '+surface_buttons.value ) )) def axis_response(change): with g.batch_update(): #Gets the widget that was altered modified = change.owner.description if modified == xaxis.description: for i in range(num_groups): #Get data for legend group filtered_data = data.query("{} == '{}'".format(legend_group,g.data[i].name)) #Query filtered data for slider specs query_filt(filtered_data,i) g.layout.xaxis.title = xaxis.value elif modified == yaxis.description: for i in range(num_groups): #Get data for legend group filtered_data = data.query("{} == '{}'".format(legend_group,g.data[i].name)) #Query filtered data for slider specs query_filt(filtered_data,i) g.layout.yaxis.title = yaxis.value def slider1_response(change): with g.batch_update(): for i in range(num_groups): #Get data for legend group filtered_data = data.query("{} == '{}'".format(legend_group,g.data[i].name))#make key var that iters #Query filtered data for slider specs query_filt(filtered_data,i) def query_filt(filtered_data,i): #Query filtered data for slider specs # filt_bool = (filtered_data.learning_rate == lr_slider.value)#make learning_rate var if param_drop1.value == 'None': #Assign data to graph g.data[i].x = filtered_data[xaxis.value] g.data[i].y = filtered_data[yaxis.value] else: filt_bool = (filtered_data[param_drop1.value] == slider1.value)#make learning_rate var #Filter out data xfilt = [v if b else None for v,b in zip(filtered_data[xaxis.value],filt_bool)] yfilt = [v if b else None for v,b in zip(filtered_data[yaxis.value],filt_bool)] #Assign data to graph g.data[i].x = xfilt g.data[i].y = yfilt def create_slider_options(drop_value): if drop_value == 'None': slide_ops = ['Select Parameter'] else: slide_ops = data[drop_value].sort_values().unique() return slide_ops def param_update(change): #everytime we change param, update the slider options and current value slider1.options = create_slider_options(param_drop1.value) slider1.value = slider1.options[0] def size_response(change): with g.batch_update(): if size_drop.value == 'None': g.update_traces(marker=dict(size=size_slider.value)) else: sizeFig = px.scatter(data, x="x", y="y", color="model", size=size_drop.value, size_max=size_slider.value) traceSizes = [x.marker.size for x in sizeFig.data] for i in range(num_groups): g.data[i].marker.size = traceSizes[i] g.data[i].marker.sizeref = sizeFig.data[0].marker.sizeref g.data[i].marker.sizemode = sizeFig.data[0].marker.sizemode g.data[i].marker.sizemin = 4 def surface_response(change): with g.batch_update(): z_vals = data.query('{} == "{}"'\ .format(legend_group,surface_buttons.value))[[x_surface.value,y_surface.value,z_surface.value]]\ .groupby([x_surface.value,y_surface.value])\ .median().reset_index()\ .pivot(index=x_surface.value,columns=y_surface.value,values=z_surface.value) g2.data[0].z = z_vals.values layout = go.Layout( scene = dict( xaxis = dict( title = x_surface.value), yaxis = dict( title = y_surface.value), zaxis = dict( title = z_surface.value), ), title=dict( text='Hyperparameter Surface: '+surface_buttons.value )) g2.update_layout(layout) surface_buttons.observe(surface_response,"value") x_surface.observe(surface_response,"value") y_surface.observe(surface_response,"value") z_surface.observe(surface_response,"value") size_drop.observe(size_response,"value") size_slider.observe(size_response, "value") slider1.observe(slider1_response, names="value") xaxis.observe(axis_response, names="value") yaxis.observe(axis_response, names="value") param_drop1.observe(param_update, names="value") scatterTab = widgets.VBox([container,g]) surfaceTab = widgets.VBox([container2,g2]) tab = widgets.Tab([scatterTab,surfaceTab]) tab.set_title(0,'Scatter') tab.set_title(1,'Surface') return tab
class NasaGibsViewer(PanelObject): def __init__(self,ptype='time',*args,**kwargs): self.title = 'NASA GIBS Image Viewer' PanelObject.__init__(self,*args, **kwargs) self.url = 'https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/wmts.cgi' self.plat = 24.42 self.plon = 54.43 self.height = 1.0 self.width = 1.0 def getCP(self): self.setLabel() self.imgDate = datetime.now() self.selectVar ='MODIS_Terra_SurfaceReflectance_Bands143' self.dateSW = DatePicker(description='Date', layout=Layout(width='220px'), value = self.imgDate, disabled=False) self.vardict = {'TerraRGB':'MODIS_Terra_SurfaceReflectance_Bands143', 'AquaRGB' :'MODIS_Aqua_SurfaceReflectance_Bands143', 'AquaLST Day':'MODIS_Aqua_Land_Surface_Temp_Day'} self.varSW = Dropdown(options=['TerraRGB','AquaRGB','AquaLST Day'], value='TerraRGB', layout=Layout(width='220px'), description='Var:', disabled=False ) self.latSW = Text(description='Lat:',disabled=False,value='24.42',layout=Layout(width='220px')) self.lonSW = Text(description='Lon:',disabled=False,value='54.43',layout=Layout(width='220px')) self.plotPB =Button(description='Plot',disabled=False,layout={'width':'auto','border':'3px outset'}) self.latRS = FloatSlider( value=5, min=2.0, max=15, step=0.2, description='Width', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.1f', ) self.lonRS = FloatSlider( value=5.0, min=2.0, max=15.0, step=0.2, description='Height:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='.1f' ) self.inpUSR.children+= (HBox([ VBox([self.plotPB]), VBox([self.dateSW,self.latSW,self.lonSW]), VBox([self.latRS,self.lonRS,self.varSW ]) ], layout={'overflow':'visible'} ),) self.dateSW.observe(self.dateSWCB) self.varSW.observe(self.varSWCB,names='value') self.latSW.observe(self.latSWCB,names='value') self.lonSW.observe(self.lonSWCB,names='value') self.latRS.observe(self.latRSCB,names='value') self.lonRS.observe(self.lonRSCB,names='value') self.plotPB.on_click(self.plotGIBS) return self.cp def dateSWCB(self,change): if change['type'] == 'change': self.imgDate = self.dateSW.value def varSWCB(self,b): self.selectVar = self.vardict[self.varSW.value] def latSWCB(self,change): self.plat = float(self.latSW.value) def lonSWCB(self,change): self.plon = float(self.lonSW.value) def latRSCB(self,change): self.height = self.latRS.value*0.5 def lonRSCB(self,change): self.width = self.lonRS.value*0.5 def plotGIBS(self,b): self.lat1 = self.plat - self.height self.lat2 = self.plat + self.height self.lon1 = self.plon - self.width self.lon2 = self.plon + self.width with self.out_cp: plt.ioff() layer = self.selectVar date_str = '{}-{}-{}'.format(self.imgDate.strftime('%Y'), self.imgDate.strftime('%m'), self.imgDate.strftime('%d') ) print(layer,date_str) fig = plt.figure(figsize=(8, 8)) ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree()) ax.add_wmts(self.url, layer,wmts_kwargs={'time': date_str}) self.out_cp.clear_output() ax.set_extent([self.lon1, self.lon2, self.lat1, self.lat2], crs=ccrs.PlateCarree()) ax.coastlines(resolution='50m', color='yellow') plt.plot(self.plon, self.plat, marker='o', color='red', markersize=15, alpha=1.0) plt.show()
value_1 = A_1.value * np.sin(w_1.value * t) value_2 = A_2.value * np.cos(w_2.value * t) else: value_1 = A_1.value * np.sin(2 * math.pi * f_1.value*t - Phi_1.value * np.pi/180) value_2 = A_2.value * np.cos(2 * math.pi * f_2.value*t - Phi_2.value * np.pi/180) return value_1, value_2 # parameters t = np.arange(0.0, 10.0, 0.001) y_1, y_2 = calculate() # figure data = [go.Scatter(y = y_1, x = t, opacity = 0.75, name = 'Trace 1'), go.Scatter(y = y_2, x = t, opacity = 0.75, name = 'Trace 2')] layout = {'yaxis': {'range': [-2, 2], 'title': "CALCULATED VALUE"}, 'xaxis': {'range': [0, 10], 'title': "TIME"}} fig = go.FigureWidget(data, layout) def recalculate(value): global fig fig.data[0].y, fig.data[1].y = calculate() A_1.observe(recalculate, 'value') A_2.observe(recalculate, 'value') f_1.observe(recalculate, 'value') f_2.observe(recalculate, 'value') w_1.observe(recalculate, 'value') w_2.observe(recalculate, 'value') Phi_1.observe(recalculate, 'value') Phi_2.observe(recalculate, 'value') use.observe(recalculate, 'value') fig
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 Figure1: def __init__(self, csv_file_path, base_path='', inchi_key='JMXLWMIFDJCGBV-UHFFFAOYSA-N'): self.selected_plate = None self.old_plate = None self.base_path = base_path self.full_perovskite_data = pd.read_csv( csv_file_path, low_memory=False, skiprows=4) self.setup_hull() self.gen_amine_traces(inchi_key) self.setup_plot() self.generate_xrd() self.setup_widgets() def setup_hull(self, hull_points=[[0., 0., 0.], [0., 2.3, 0.], [1.86, 1.86, 0.], [0., 0., 9.5], [1.19339, 1.19339, 9.5], [0., 1.4757, 9.5]]): xp, yp, zp = zip(*hull_points) self.hull_mesh = go.Mesh3d(x=xp, y=yp, z=zp, color='#FFB6C1', opacity=0.50, alphahull=0) def gen_amine_traces(self, inchi_key, amine_short_name='Me2NH2I'): amine_data = self.full_perovskite_data.loc[self.full_perovskite_data['_rxn_organic-inchikey'] == inchi_key] # Splitting by crystal scores. Assuming crystal scores from 1-4 self.amine_crystal_dfs = [] for i in range(1, 5): self.amine_crystal_dfs.append( amine_data.loc[amine_data['_out_crystalscore'] == i]) self.amine_crystal_traces = [] self.trace_colors = ['rgba(65, 118, 244, 1.0)', 'rgba(92, 244, 65, 1.0)', 'rgba(244, 238, 66, 1.0)', 'rgba(244, 66, 66, 1.0)'] for i, df in enumerate(self.amine_crystal_dfs): trace = go.Scatter3d( x=df['_rxn_M_inorganic'], y=df['_rxn_M_organic'], z=df['_rxn_M_acid'], mode='markers', name='Score {}'.format(i+1), text=['<b>PbI3</b>: {:.3f} <br><b>Amine</b>: {:.3f} <br><b>FAH</b>: {:.3f}'.format( row['_rxn_M_inorganic'], row['_rxn_M_organic'], row['_rxn_M_acid']) for idx, row in df.iterrows()], hoverinfo='text', marker=dict( size=4, color=self.trace_colors[i], line=dict( width=0.2 ), opacity=1.0 ) ) self.amine_crystal_traces.append(trace) self.data = self.amine_crystal_traces if self.hull_mesh: self.data += [self.hull_mesh] def setup_plot(self, xaxis_label='Lead Iodide [PbI3] (M)', yaxis_label='Dimethylammonium Iodide<br>[Me2NH2I] (M)', zaxis_label='Formic Acid [FAH] (M)'): self.layout = go.Layout( scene=dict( xaxis=dict( title=xaxis_label, tickmode='linear', dtick=0.5, range=[0, 2.0], ), yaxis=dict( title=yaxis_label, tickmode='linear', dtick=0.5, range=[0, 2.5], ), zaxis=dict( title=zaxis_label, tickmode='linear', dtick=1.0, range=[0, 9.5], ), ), legend=go.layout.Legend( x=0, y=1, traceorder="normal", font=dict( family="sans-serif", size=12, color="black" ), bgcolor="LightSteelBlue", bordercolor="Black", borderwidth=2 ), width=975, height=700, margin=go.layout.Margin( l=20, r=20, b=20, t=20, pad=2 ), ) self.fig = go.FigureWidget(data=self.data, layout=self.layout) for trace in self.fig.data[:-1]: trace.on_click(self.show_data_3d_callback) def setup_widgets(self, image_folder='images'): image_folder = self.base_path + '/' + image_folder self.image_list = os.listdir(image_folder) # Data Filter Setup download_robot_file = Button( description='Download Robot File', disabled=False, button_style='', tooltip='Click to download robot file of the current plate', ) download_prep_file = Button( description='Download Reagent Prep', disabled=False, button_style='', tooltip='Click to download reagent preperation file for the current plate', ) reset_plot = Button( description='Reset', disabled=False, tooltip='Reset the colors of the plot' ) xy_check = Button( description='Show X-Y axes', disabled=False, button_style='', tooltip='Click to show X-Y axes' ) show_hull_check = ToggleButton( value=True, description='Show Convex Hull', disabled=False, button_style='', tooltip='Toggle to show/hide convex hull', icon='check' ) download_robot_file.on_click(self.download_robot_callback) download_prep_file.on_click(self.download_prep_callback) reset_plot.on_click(self.reset_plot_callback) xy_check.on_click(self.set_xy_camera) show_hull_check.observe(self.toggle_mesh, 'value') # Experiment data tab setup self.experiment_table = HTML() self.experiment_table.value = "Please click on a point to explore experiment details" self.image_data = {} for img_filename in os.listdir(image_folder): with open("{}/{}".format(image_folder, img_filename), "rb") as f: b = f.read() self.image_data[img_filename] = b self.image_widget = Image( value=self.image_data['not_found.png'], layout=Layout(height='400px', width='650px') ) experiment_view_vbox = VBox( [HBox([self.experiment_table, self.image_widget])]) self.thermal_plot = self.init_thermal_plot() plate_options = self.get_plate_options() self.selected_plate = plate_options[0] self.generate_thermal(self.selected_plate) self.plate_dropdown = Dropdown(options=plate_options, description='Plate:', ) self.plate_dropdown.observe(self.change_plates, 'value') #tab = Tab() #tab.children = [experiment_view_vbox] #tab.set_title(0, 'Experiment Details') #tab.set_title(1, 'XRD data') plot_tabs = Tab([VBox([self.fig, HBox([xy_check, show_hull_check, reset_plot])]), VBox([self.thermal_plot, HBox([self.plate_dropdown, download_robot_file, download_prep_file])]), ]) plot_tabs.set_title(0, 'Chemical Space') plot_tabs.set_title(1, 'Plate') self.full_widget = VBox([plot_tabs, experiment_view_vbox]) self.full_widget.layout.align_items = 'center' def get_plate_options(self): plates = set() for df in self.amine_crystal_dfs: for i, row in df.iterrows(): name = str(row['name']) plate_name = '_'.join(name.split('_')[:-1]) plates.add(plate_name) plate_options = [] for i, plate in enumerate(plates): plate_options.append(plate) return plate_options def change_plates(self, state): self.selected_plate = state.new self.generate_thermal(self.selected_plate) def init_thermal_plot(self): import plotly.graph_objs as go #base_url = list(notebookapp.list_running_servers())[0]['base_url'] #data_url = base_url + 'files/sd2e-community/perovskite-data/data_connected_pub' full_url = 'images/not_found.png' layout = go.Layout( hovermode='closest', xaxis=dict( title='Column', showgrid=False, ticktext=[i+1 for i in range(12)], tickvals=[i*1.0+0.5 for i in range(12)], ), yaxis=dict( title='Row', showgrid=False, ticktext=list('ABCDEFGH'), tickvals=[i*1.0+0.5 for i in range(8)], ), images=[ go.layout.Image( source=full_url, xref="x", yref="y", x=0, y=8, sizex=12, sizey=8, sizing="stretch", opacity=0.8, layer="below") ], width=950, height=700, ) from itertools import product xy = list(product([i*1.0+0.5 for i in range(12)], [i*1.0+0.5 for i in range(8)])) x, y = list(zip(*xy)) self.vial_labels = list(product([i+1 for i in range(12)], list('ABCDEFGH'))) trace1 = go.Scatter( x=x, y=y, mode='markers', marker=dict(size=45, color='rgba(66, 245, 87, 0.1)', line=dict(width=3, color='rgb(0, 0, 0)')), opacity=1.0, ) fig = go.FigureWidget(data=[trace1], layout=layout) fig.data[0].on_click(self.show_data_thermal_callback) return fig def generate_xrd(self): import pandas as pd dat = pd.read_csv(self.base_path + '/2019-02-21T16_54_38.714239+00_00_LBL_1.xy', skiprows=1, delimiter=' ') dat.columns = ['x', 'y'] trace = go.Scatter( x=dat['x'], y=dat['y'], ) data = [trace] layout = go.Layout( autosize=False, width=1000, height=600, margin=go.layout.Margin( l=50, r=50, b=100, t=100, pad=4 ), ) self.xrd_plot = go.FigureWidget(data=data, layout=layout) def generate_table(self, row, columns, column_names): table_html = """ <table border="1" style="width:100%;"> <tbody>""" for i, column in enumerate(columns): if isinstance(row[column], str): value = row[column].split('_')[-1] else: value = np.round(row[column], decimals=3) table_html += """ <tr> <td style="padding: 8px;">{}</td> <td style="padding: 8px;">{}</td> </tr> """.format(column_names[i], value) table_html += """ </tbody> </table> """ return table_html def toggle_mesh(self, state): with self.fig.batch_update(): self.fig.data[-1].visible = state.new def set_xy_camera(self, state): camera = dict( up=dict(x=0, y=0, z=1), center=dict(x=0, y=0, z=0), eye=dict(x=0.0, y=0.0, z=2.5) ) self.fig['layout'].update( scene=dict(camera=camera), ) def download_robot_callback(self, b): if self.selected_plate: js_string = """ var base_uri = utils.get_body_data("baseUrl"); var file_location = utils.encode_uri_components('{}_RobotInput.xls'); // var final_url = utils.url_path_join(base_uri, 'files', file_location) var final_url = 'files/' + file_location console.log(final_url) window.open(final_url, IPython._target); """.format(self.selected_plate) display(Javascript(js_string)) def download_prep_callback(self, b): if self.selected_plate: js_string = """ var base_uri = utils.get_body_data("baseUrl"); var file_location = utils.encode_uri_components('{}_ExpDataEntry.xlsx'); // var final_url = utils.url_path_join(base_uri, 'files', file_location) var final_url = 'files/' + file_location console.log(final_url) window.open(final_url, IPython._target); """.format(self.selected_plate) display(Javascript(js_string)) def reset_plot_callback(self, b): with self.fig.batch_update(): for i in range(len(self.fig.data[:-1])): self.fig.data[i].marker.color = self.trace_colors[i] self.fig.data[i].marker.size = 4 def generate_thermal(self, new_plate): if new_plate != self.old_plate: self.old_plate = new_plate with self.thermal_plot.batch_update(): # base_url = list(notebookapp.list_running_servers())[ # 0]['base_url'] #data_url = base_url + 'files/sd2e-community/perovskite-data/data_connected_pub' full_url = 'images/{}_thermal.PNG'.format(new_plate) self.thermal_plot.layout.images = [go.layout.Image( source=full_url, xref="x", yref="y", x=0, y=8, sizex=12, sizey=8, sizing="stretch", opacity=0.8, layer="below")] def show_data_3d_callback(self, trace, point, selector): if point.point_inds: selected_experiment = self.amine_crystal_dfs[point.trace_index].iloc[point.point_inds[0]] with self.fig.batch_update(): for i in range(len(self.fig.data[:-1])): color = self.trace_colors[i].split(',') color[-1] = '0.5)' color = ','.join(color) if i == point.trace_index: marker_colors = [color for x in range(len(trace['x']))] marker_colors[point.point_inds[0] ] = self.trace_colors[i] self.fig.data[i].marker.color = marker_colors self.fig.data[i].marker.size = 6 else: self.fig.data[i].marker.color = color self.fig.data[i].marker.size = 4 self.populate_data(selected_experiment) # Code to update thermal image self.generate_thermal(self.selected_plate) def show_data_thermal_callback(self, trace, point, selector): pt_idx = point.point_inds[0] vial_name = self.vial_labels[pt_idx][1] + \ str(self.vial_labels[pt_idx][0]) experiment_name = self.selected_plate+'_'+vial_name #self.amine_crystal_dfs['preTestScore'].where(df['postTestScore'] > 50) selected_experiment = None for df in self.amine_crystal_dfs: if not df.loc[df['name'] == experiment_name].empty: selected_experiment = df.loc[df['name'] == experiment_name].iloc[0] # print(selected_experiment['name']) self.populate_data(selected_experiment) break marker_colors = [ 'rgba(66, 245, 87, 0.1)' for i in range(len(trace['x']))] score = int(selected_experiment['_out_crystalscore'] - 1) marker_colors[pt_idx] = self.trace_colors[score] with self.thermal_plot.batch_update(): self.thermal_plot.data[0].marker.color = marker_colors def populate_data(self, selected_experiment): name = selected_experiment['name'] if name+'.jpg' in self.image_list: self.image_widget.value = self.image_data[name+'.jpg'] else: self.image_widget.value = self.image_data['not_found.png'] columns = ['name', '_rxn_M_acid', '_rxn_M_inorganic', '_rxn_M_organic', '_rxn_mixingtime1S', '_rxn_mixingtime2S', '_rxn_reactiontimeS', '_rxn_stirrateRPM', '_rxn_temperatureC_actual_bulk'] column_names = ['Well ID', 'Formic Acid [FAH]', 'Lead Iodide [PbI2]', 'Dimethylammonium Iodide [Me2NH2I]', 'Mixing Time Stage 1 (s)', 'Mixing Time Stage 2 (s)', 'Reaction Time (s)', 'Stir Rate (RPM)', 'Temperature (C)'] prefix = '_'.join(name.split('_')[:-1]) self.selected_plate = prefix self.experiment_table.value = '<p>Plate ID:<br> {}</p>'.format(prefix) + self.generate_table( selected_experiment.loc[columns], columns, column_names) @property def plot(self): return self.full_widget
class FileChooser(VBox): _LBL_TEMPLATE = '<span style="margin-left:10px; color:{1};">{0}</span>' _LBL_NOFILE = 'No file selected' def __init__(self, path=os.getcwd(), filename='', show_hidden=False, **kwargs): self._default_path = path.rstrip(os.path.sep) self._default_filename = filename self._selected_path = '' self._selected_filename = '' self._show_hidden = show_hidden # Widgets self._pathlist = Dropdown(description="", layout=Layout(width='auto', grid_area='pathlist')) self._filename = Text(placeholder='output filename', layout=Layout(width='auto', grid_area='filename')) self._dircontent = Select(rows=8, layout=Layout(width='auto', grid_area='dircontent')) self._cancel = Button( description='Cancel', button_style= 'warning', # 'success', 'info', 'warning', 'danger' or '' layout=Layout(width='auto', display='none')) self._select = Button( description='Select', button_style= 'success', # 'success', 'info', 'warning', 'danger' or '' layout=Layout(width='auto')) # Widget observe handlers self._pathlist.observe(self._on_pathlist_select, names='value') self._dircontent.observe(self._on_dircontent_select, names='value') self._filename.observe(self._on_filename_change, names='value') self._select.on_click(self._on_select_click) self._cancel.on_click(self._on_cancel_click) # Selected file label self._label = HTML(value=self._LBL_TEMPLATE.format( self._LBL_NOFILE, 'black'), placeholder='', description='') # Layout self._gb = GridBox( children=[self._pathlist, self._filename, self._dircontent], layout=Layout(display='none', width='500px', grid_gap='0px 0px', grid_template_rows='auto auto', grid_template_columns='60% 40%', grid_template_areas=''' 'pathlist filename' 'dircontent dircontent' ''')) buttonbar = HBox(children=[self._select, self._cancel, self._label], layout=Layout(width='auto')) # Call setter to set initial form values self._set_form_values(self._default_path, self._default_filename) # Call VBox super class __init__ super().__init__(children=[ self._gb, buttonbar, ], layout=Layout(width='auto'), **kwargs) def _set_form_values(self, path, filename): '''Set the form values''' # Disable triggers to prevent selecting an entry in the Select # box from automatically triggering a new event. self._pathlist.unobserve(self._on_pathlist_select, names='value') self._dircontent.unobserve(self._on_dircontent_select, names='value') self._filename.unobserve(self._on_filename_change, names='value') # Set form values self._pathlist.options = get_subpaths(path) self._pathlist.value = path self._filename.value = filename self._dircontent.options = get_dir_contents(path, hidden=self._show_hidden) # If the value in the filename Text box equals a value in the # Select box and the entry is a file then select the entry. if ((filename in self._dircontent.options) and os.path.isfile(os.path.join(path, filename))): self._dircontent.value = filename else: self._dircontent.value = None # Reenable triggers again self._pathlist.observe(self._on_pathlist_select, names='value') self._dircontent.observe(self._on_dircontent_select, names='value') self._filename.observe(self._on_filename_change, names='value') # Set the state of the select Button if self._gb.layout.display is None: selected = os.path.join(self._selected_path, self._selected_filename) # filename value is empty or equals the selected value if (filename == '') or (os.path.join(path, filename) == selected): self._select.disabled = True else: self._select.disabled = False def _on_pathlist_select(self, change): '''Handler for when a new path is selected''' self._set_form_values(change['new'], self._filename.value) def _on_dircontent_select(self, change): '''Handler for when a folder entry is selected''' new_path = update_path(self._pathlist.value, change['new']) # Check if folder or file if os.path.isdir(new_path): path = new_path filename = self._filename.value elif os.path.isfile(new_path): path = self._pathlist.value filename = change['new'] self._set_form_values(path, filename) def _on_filename_change(self, change): '''Handler for when the filename field changes''' self._set_form_values(self._pathlist.value, change['new']) def _on_select_click(self, b): '''Handler for when the select button is clicked''' if self._gb.layout.display is 'none': self._gb.layout.display = None self._cancel.layout.display = None # Show the form with the correct path and filename if self._selected_path and self._selected_filename: path = self._selected_path filename = self._selected_filename else: path = self._default_path filename = self._default_filename self._set_form_values(path, filename) else: self._gb.layout.display = 'none' self._cancel.layout.display = 'none' self._select.description = 'Change' self._selected_path = self._pathlist.value self._selected_filename = self._filename.value # self._default_path = self._selected_path # self._default_filename = self._selected_filename selected = os.path.join(self._selected_path, self._selected_filename) if os.path.isfile(selected): self._label.value = self._LBL_TEMPLATE.format( selected, 'orange') else: self._label.value = self._LBL_TEMPLATE.format( selected, 'green') def _on_cancel_click(self, b): '''Handler for when the cancel button is clicked''' self._gb.layout.display = 'none' self._cancel.layout.display = 'none' self._select.disabled = False def reset(self, path=None, filename=None): '''Reset the form to the default path and filename''' self._selected_path = '' self._selected_filename = '' self._label.value = self._LBL_TEMPLATE.format(self._LBL_NOFILE, 'black') if path is not None: self._default_path = path.rstrip(os.path.sep) if filename is not None: self._default_filename = filename self._set_form_values(self._default_path, self._default_filename) def refresh(self): '''Re-render the form''' self._set_form_values(self._pathlist.value, self._filename.value) @property def show_hidden(self): '''Get current number of rows''' return self._show_hidden @show_hidden.setter def show_hidden(self, hidden): '''Set number of rows''' self._show_hidden = hidden self.refresh() @property def rows(self): '''Get current number of rows''' return self._dircontent.rows @rows.setter def rows(self, rows): '''Set number of rows''' self._dircontent.rows = rows @property def default(self): '''Get the default value''' return os.path.join(self._default_path, self._default_filename) @property def default_path(self): '''Get the default_path value''' return self._default_path @default_path.setter def default_path(self, path): '''Set the default_path''' self._default_path = path.rstrip(os.path.sep) self._default = os.path.join(self._default_path, self._filename.value) self._set_form_values(self._default_path, self._filename.value) @property def default_filename(self): '''Get the default_filename value''' return self._default_filename @default_filename.setter def default_filename(self, filename): '''Set the default_filename''' self._default_filename = filename self._default = os.path.join(self._pathlist.value, self._default_filename) self._set_form_values(self._pathlist.value, self._default_filename) @property def selected(self): '''Get selected value''' return os.path.join(self._selected_path, self._selected_filename) @property def selected_path(self): '''Get selected_path value''' return self._selected_path @property def selected_filename(self): '''Get the selected_filename''' return self._selected_filename @property def nmrname(self): # added by MAD return os.path.join( os.path.basename(os.path.dirname(self._selected_path)), os.path.basename(self._selected_path)) def __repr__(self): str_ = ("FileChooser(" "path='{0}', " "filename='{1}', " "show_hidden='{2}')").format(self._default_path, self._default_filename, self._show_hidden) return str_
class NGLDisplay: """Structure display class Provides basic structure/trajectory display in the notebook and optional gui which can be used to enhance its usability. It is also possible to extend the functionality of the particular instance of the viewer by adding further widgets manipulating the structure. """ def __init__(self, atoms, xsize=500, ysize=500): import nglview import nglview.color from ipywidgets import Dropdown, FloatSlider, IntSlider, HBox, VBox self.atoms = atoms if isinstance(atoms[0], Atoms): # Assume this is a trajectory or struct list self.view = nglview.show_asetraj(atoms, default=False) self.frm = IntSlider(value=0, min=0, max=len(atoms) - 1) self.frm.observe(self._update_frame) self.struct = atoms[0] else: # Assume this is just a single structure self.view = nglview.show_ase(atoms, default=False) self.struct = atoms self.frm = None self.colors = {} self.view._remote_call('setSize', target='Widget', args=['%dpx' % (xsize,), '%dpx' % (ysize,)]) self.view.add_unitcell() self.view.add_spacefill() self.view.camera = 'orthographic' self.view.parameters = { "clipDist": 0 } self.view.center() self.asel = Dropdown(options=['All'] + list(set(self.struct.get_chemical_symbols())), value='All', description='Show') self.csel = Dropdown(options=nglview.color.COLOR_SCHEMES, value='element', description='Color scheme') self.rad = FloatSlider(value=0.5, min=0.0, max=1.5, step=0.01, description='Ball size') self.asel.observe(self._select_atom) self.csel.observe(self._update_repr) self.rad.observe(self._update_repr) self.view.update_spacefill(radiusType='covalent', radiusScale=0.5, color_scheme=self.csel.value, color_scale='rainbow') wdg = [self.asel, self.csel, self.rad] if self.frm: wdg.append(self.frm) self.gui = HBox([self.view, VBox(wdg)]) # Make useful shortcuts for the user of the class self.gui.view = self.view self.gui.control_box = self.gui.children[1] self.gui.custom_colors = self.custom_colors def _update_repr(self, chg=None): self.view.update_spacefill(radiusType='covalent', radiusScale=self.rad.value, color_scheme=self.csel.value, color_scale='rainbow') def _update_frame(self, chg=None): self.view.frame = self.frm.value return def _select_atom(self, chg=None): sel = self.asel.value self.view.remove_spacefill() for e in set(self.struct.get_chemical_symbols()): if (sel == 'All' or e == sel): if e in self.colors: self.view.add_spacefill(selection='#' + e, color=self.colors[e]) else: self.view.add_spacefill(selection='#' + e) self._update_repr() def custom_colors(self, clr=None): """ Define custom colors for some atoms. Pass a dictionary of the form {'Fe':'red', 'Au':'yellow'} to the function. To reset the map to default call the method without parameters. """ if clr: self.colors = clr else: self.colors = {} self._select_atom()
class CellDefTab(object): def __init__(self): micron_units = Label('micron') # use "option m" (Mac, for micro symbol) constWidth = '180px' tab_height = '500px' stepsize = 10 #style = {'description_width': '250px'} style = {'description_width': '25%'} layout = {'width': '400px'} name_button_layout={'width':'25%'} widget_layout = {'width': '15%'} units_button_layout ={'width':'15%'} desc_button_layout={'width':'45%'} # divider_button_layout={'width':'40%', 'align_items':'left'} divider_button_layout={'width':'40%'} self.cell_parent_dict = {'lung epithelium':'default', 'immune':'default', 'CD8 Tcell':'immune'} self.cell_type = Dropdown(description='Cell:', options={'default':'default', 'lung epithelium':'lung epithelium', 'immune':'immune', 'CD8 Tcell':'CD8 Tcell'}) self.cell_type.style = {'description_width': '%sch' % str(len(self.cell_type.description) + 1)} self.cell_type.observe(self.cell_type_cb) self.parent_name = Text(value='None',placeholder='Type something',description='Parent:',disabled=True) menv_var1 = Button(description='director_signal', disabled=True, layout=name_button_layout) menv_var1.style.button_color = 'tan' param_name1 = Button(description='cycle trans rate', disabled=True, layout=name_button_layout) self.cycle_trans_rate = FloatText(value=1000, step=100,style=style, layout=widget_layout) param_name2 = Button(description='decay_rate', disabled=True, layout=name_button_layout) self.director_signal_decay_rate = FloatText(value=.1, step=0.01,style=style, layout=widget_layout) param_name3 = Button(description='initial_condition', disabled=True, layout=name_button_layout) self.director_signal_initial_condition = FloatText(value=0,style=style, layout=widget_layout) param_name4 = Button(description='Dirichlet_boundary_condition', disabled=True, layout=name_button_layout) self.director_signal_Dirichlet_boundary_condition = FloatText(value=1,style=style, layout=widget_layout) self.director_signal_Dirichlet_boundary_condition_toggle = Checkbox(description='on/off', disabled=False,style=style, layout=widget_layout) menv_var2 = Button(description='cargo_signal', disabled=True, layout=name_button_layout) menv_var2.style.button_color = 'lightgreen' param_name5 = Button(description='diffusion_coefficient', disabled=True, layout=name_button_layout) self.cargo_signal_diffusion_coefficient = FloatText(value=1000, step=100,style=style, layout=widget_layout) param_name6 = Button(description='decay_rate', disabled=True, layout=name_button_layout) self.cargo_signal_decay_rate = FloatText(value=.4, step=0.1,style=style, layout=widget_layout) param_name7 = Button(description='initial_condition', disabled=True, layout=name_button_layout) self.cargo_signal_initial_condition = FloatText(value=0,style=style, layout=widget_layout) param_name8 = Button(description='Dirichlet_boundary_condition', disabled=True, layout=name_button_layout) self.cargo_signal_Dirichlet_boundary_condition = FloatText(value=1,style=style, layout=widget_layout) self.cargo_signal_Dirichlet_boundary_condition_toggle = Checkbox(description='on/off', disabled=False,style=style, layout=widget_layout) self.calculate_gradient = Checkbox(description='calculate_gradients', disabled=False, layout=desc_button_layout) self.track_internal = Checkbox(description='track_in_agents', disabled=False, layout=desc_button_layout) row_director_signal = [menv_var1, ] box_layout = Layout(display='flex', flex_flow='row', align_items='stretch', width='100%') """ box_director_signal = Box(children=row_director_signal, layout=box_layout) box1 = Box(children=row1, layout=box_layout) box_cargo_signal = Box(children=row_cargo_signal, layout=box_layout) box5 = Box(children=row5, layout=box_layout) """ #-------------------------- div_cycle = Button(description='Phenotype:cycle', disabled=True, layout=divider_button_layout) param_name1 = Button(description='transition rate: 0->1', disabled=True, layout=name_button_layout) param_name1.style.button_color = 'tan' param_name1_units = Button(description='1/min', disabled=True, layout=units_button_layout) param_name1_units.style.button_color = 'tan' self.cycle_trans_rate1 = FloatText( value=0.0001, step=0.00001, style=style, layout=widget_layout) row1 = [param_name1, self.cycle_trans_rate1, param_name1_units] box1 = Box(children=row1, layout=box_layout) param_name2 = Button(description='transition rate: 1->2', disabled=True, layout=name_button_layout) param_name2.style.button_color = 'lightgreen' param_name2_units = Button(description='1/min', disabled=True, layout=units_button_layout) param_name2_units.style.button_color = 'lightgreen' self.cycle_trans_rate2 = FloatText( value=0.0002, step=0.00001, style=style, layout=widget_layout) row2 = [param_name2, self.cycle_trans_rate2, param_name2_units] box2 = Box(children=row2, layout=box_layout) #-------------------------- div_death = Button(description='Phenotype:death', disabled=True, layout=divider_button_layout) #-------------------------- div_volume = Button(description='Phenotype:volume', disabled=True, layout=divider_button_layout) param_name9 = Button(description='volume', disabled=True, layout=name_button_layout) param_name9.style.button_color = 'tan' param_name9_units = Button(description='micron^3', disabled=True, layout=units_button_layout) param_name9_units.style.button_color = 'tan' self.volume = FloatText( value=2.15e3, step=100, style=style, layout=widget_layout) row9 = [param_name9, self.volume, param_name9_units] box9 = Box(children=row9, layout=box_layout) #-------------------------- #-------------------------- div_mechanics = Button(description='Phenotype:mechanics', disabled=True, layout=divider_button_layout) #-------------------------- div_motility = Button(description='Phenotype:motility', disabled=True, layout=divider_button_layout) #-------------------------- div_secretion = Button(description='Phenotype:secretion', disabled=True, layout=divider_button_layout) #-------------------------- div_intracellular = Button(description='Phenotype:intracellular', disabled=True, layout=divider_button_layout) #-------------------------- div_custom_data = Button(description='Custom data', disabled=True, layout=divider_button_layout) # <elastic_coefficient length=”1” units=”1/min”>1.0</elastic_coefficient> # <attachment_point length=”3” units=”micron”>-12.8,13.9,0.0</attachment_point> param_name31 = Button(description='elastic_coefficient', disabled=True, layout=name_button_layout) param_name31.style.button_color = 'tan' param_name31_units = Button(description='1/min', disabled=True, layout=units_button_layout) param_name31_units.style.button_color = 'tan' self.custom_elastic_coef = FloatText( value=1.0, step=0.1, style=style, layout=widget_layout) row31 = [param_name31, self.custom_elastic_coef, param_name31_units] box31 = Box(children=row31, layout=box_layout) param_name32 = Button(description='attachment_point', disabled=True, layout=name_button_layout) param_name32.style.button_color = 'lightgreen' param_name32_units = Button(description='micron', disabled=True, layout=units_button_layout) param_name32_units.style.button_color = 'lightgreen' self.custom_attachment_point = Text( value="-12.8,13.9,0.0", style=style, layout=widget_layout) row32 = [param_name32, self.custom_attachment_point, param_name32_units] box32 = Box(children=row32, layout=box_layout) #-------------------------- self.vbox1 = VBox([ div_cycle, box1, box2, div_death, div_volume, box9, div_mechanics, div_motility, div_secretion, div_intracellular, div_custom_data, box31, box32, ]) self.vbox2 = VBox([ box1, ]) self.cell_stuff = self.vbox1 self.tab = VBox([ HBox([self.cell_type, self.parent_name]), self.vbox1, self.vbox2 ]) #------------------------------ def cell_type_cb(self, change): if change['type'] == 'change' and change['name'] == 'value': print("changed to %s" % change['new']) # self.vbox1.layout.visibility = 'hidden' # vs. visible # self.vbox1.layout.visibility = None self.vbox1.layout.display = 'none' # self.tab[1] = self.vbox2 # self.cell_stuff = self.vbox2 # self.tab.children[1] = self.vbox2 # print("self.tab.children[1] = ",self.tab.children[1]) # print('update_parent_cb') #-------------------------- # Populate the GUI widgets with values from the XML def fill_gui(self, xml_root): return # Read values from the GUI widgets to enable editing XML def fill_xml(self, xml_root): uep = xml_root.find('.//microenvironment_setup') # find unique entry point vp = [] # pointers to <variable> nodes if uep: for var in uep.findall('variable'): vp.append(var) uep = xml_root.find('.//microenvironment_setup') # find unique entry point vp[0].find('.//diffusion_coefficient').text = str(self.director_signal_diffusion_coefficient.value) vp[0].find('.//decay_rate').text = str(self.director_signal_decay_rate.value) vp[0].find('.//initial_condition').text = str(self.director_signal_initial_condition.value) vp[0].find('.//Dirichlet_boundary_condition').text = str(self.director_signal_Dirichlet_boundary_condition.value) vp[0].find('.//Dirichlet_boundary_condition').attrib['enabled'] = str(self.director_signal_Dirichlet_boundary_condition_toggle.value).lower() vp[1].find('.//diffusion_coefficient').text = str(self.cargo_signal_diffusion_coefficient.value) vp[1].find('.//decay_rate').text = str(self.cargo_signal_decay_rate.value) vp[1].find('.//initial_condition').text = str(self.cargo_signal_initial_condition.value) vp[1].find('.//Dirichlet_boundary_condition').text = str(self.cargo_signal_Dirichlet_boundary_condition.value) vp[1].find('.//Dirichlet_boundary_condition').attrib['enabled'] = str(self.cargo_signal_Dirichlet_boundary_condition_toggle.value).lower() uep.find('.//options//calculate_gradients').text = str(self.calculate_gradient.value) uep.find('.//options//track_internalized_substrates_in_each_agent').text = str(self.track_internal.value)
class JupyterRenderer: def __init__( self, size=(640, 480), compute_normals_mode=NORMAL.SERVER_SIDE, default_shape_color=format_color(166, 166, 166), # light grey default_edge_color=format_color(32, 32, 32), # dark grey default_vertex_color=format_color(8, 8, 8), # darker grey pick_color=format_color(232, 176, 36), # orange background_color='white'): """ Creates a jupyter renderer. size: a tuple (width, height). Must be a square, or shapes will look like deformed compute_normals_mode: optional, set to SERVER_SIDE by default. This flag lets you choose the way normals are computed. If SERVER_SIDE is selected (default value), then normals will be computed by the Tesselator, packed as a python tuple, and send as a json structure to the client. If, on the other hand, CLIENT_SIDE is chose, then the computer only compute vertex indices, and let the normals be computed by the client (the web js machine embedded in the webrowser). * SERVER_SIDE: higher server load, loading time increased, lower client load. Poor performance client will choose this option (mobile terminals for instance) * CLIENT_SIDE: lower server load, loading time decreased, higher client load. Higher performance clients will choose this option (laptops, desktop machines). * default_shape_color * default_e1dge_color: * default_pick_color: * background_color: """ self._default_shape_color = default_shape_color self._default_edge_color = default_edge_color self._default_vertex_color = default_vertex_color self._pick_color = pick_color self._background = background_color self._background_opacity = 1 self._size = size self._compute_normals_mode = compute_normals_mode self._bb = None # the bounding box, necessary to compute camera position # the default camera object self._camera_target = [0., 0., 0.] # the point to look at self._camera_position = [0, 0., 100.] # the camera initial position self._camera = None self._camera_distance_factor = 6 self._camera_initial_zoom = 2.5 # a dictionnary of all the shapes belonging to the renderer # each element is a key 'mesh_id:shape' self._shapes = {} # we save the renderer so that is can be accessed self._renderer = None # the group of 3d and 2d objects to render self._displayed_pickable_objects = Group() # the group of other objects (grid, trihedron etc.) that can't be selected self._displayed_non_pickable_objects = Group() # event manager/selection manager self._picker = None self._current_shape_selection = None self._current_mesh_selection = None self._savestate = None self._selection_color = format_color(232, 176, 36) self._select_callbacks = [ ] # a list of all functions called after an object is selected # UI self.layout = Layout(width='auto', height='auto') self._toggle_shp_visibility_button = self.create_button( "Hide/Show", "Toggle Shape Visibility", True, self.toggle_shape_visibility) self._shp_properties_button = Dropdown(options=[ 'Compute', 'Inertia', 'Recognize Face', 'Aligned BBox', 'Oriented BBox' ], value='Compute', description='', layout=self.layout, disabled=True) self._shp_properties_button.observe(self.on_compute_change) self._remove_shp_button = self.create_button( "Remove", "Permanently remove the shape from the Scene", True, self.remove_shape) self._controls = [ self.create_checkbox("axes", "Axes", True, self.toggle_axes_visibility), self.create_checkbox("grid", "Grid", True, self.toggle_grid_visibility), self.create_button("Reset View", "Restore default view", False, self._reset), self._shp_properties_button, self._toggle_shp_visibility_button, self._remove_shp_button ] self.html = HTML("") def create_button(self, description, tooltip, disabled, handler): button = Button(disabled=disabled, tooltip=tooltip, description=description, layout=self.layout) button.on_click(handler) return button def create_checkbox(self, kind, description, value, handler): checkbox = Checkbox(value=value, description=description, layout=self.layout) checkbox.observe(handler, "value") checkbox.add_class("view_%s" % kind) return checkbox def remove_shape(self, *kargs): self.clicked_obj.visible = not self.clicked_obj.visible # remove shape fro mthe mapping dict cur_id = self.clicked_obj.name del self._shapes[cur_id] self._remove_shp_button.disabled = True def on_compute_change(self, change): if change['type'] == 'change' and change['name'] == 'value': selection = change['new'] output = "" if 'Inertia' in selection: cog, mass, mass_property = measure_shape_mass_center_of_gravity( self._current_shape_selection) # display this point (type gp_Pnt) self.DisplayShape([cog]) output += "<u><b>Center of Gravity</b></u>:<br><b>Xcog=</b>%.3f<br><b>Ycog=</b>%.3f<br><b>Zcog=</b>%.3f<br>" % ( cog.X(), cog.Y(), cog.Z()) output += "<u><b>%s=</b></u>:<b>%.3f</b><br>" % (mass_property, mass) elif 'Oriented' in selection: center, dim, oobb_shp = get_oriented_boundingbox( self._current_shape_selection) self.DisplayShape(oobb_shp, render_edges=True, transparency=True, opacity=0.2, selectable=False) output += "<u><b>OOBB center</b></u>:<br><b>X=</b>%.3f<br><b>Y=</b>%.3f<br><b>Z=</b>%.3f<br>" % ( center.X(), center.Y(), center.Z()) output += "<u><b>OOBB dimensions</b></u>:<br><b>dX=</b>%.3f<br><b>dY=</b>%.3f<br><b>dZ=</b>%.3f<br>" % ( dim[0], dim[1], dim[2]) output += "<u><b>OOBB volume</b></u>:<br><b>V=</b>%.3f<br>" % ( dim[0] * dim[1] * dim[2]) elif 'Aligned' in selection: center, dim, albb_shp = get_aligned_boundingbox( self._current_shape_selection) self.DisplayShape(albb_shp, render_edges=True, transparency=True, opacity=0.2, selectable=False) output += "<u><b>ABB center</b></u>:<br><b>X=</b>%.3f<br><b>Y=</b>%.3f<br><b>Z=</b>%.3f<br>" % ( center.X(), center.Y(), center.Z()) output += "<u><b>ABB dimensions</b></u>:<br><b>dX=</b>%.3f<br><b>dY=</b>%.3f<br><b>dZ=</b>%.3f<br>" % ( dim[0], dim[1], dim[2]) output += "<u><b>ABB volume</b></u>:<br><b>V=</b>%.3f<br>" % ( dim[0] * dim[1] * dim[2]) elif 'Recognize' in selection: # try featrue recognition kind, pnt, vec = recognize_face(self._current_shape_selection) output += "<u><b>Type</b></u>: %s<br>" % kind if kind == "Plane": self.DisplayShape([pnt]) output += "<u><b>Properties</b></u>:<br>" output += "<u><b>Point</b></u>:<br><b>X=</b>%.3f<br><b>Y=</b>%.3f<br><b>Z=</b>%.3f<br>" % ( pnt.X(), pnt.Y(), pnt.Z()) output += "<u><b>Normal</b></u>:<br><b>u=</b>%.3f<br><b>v=</b>%.3f<br><b>w=</b>%.3f<br>" % ( vec.X(), vec.Y(), vec.Z()) elif kind == "Cylinder": self.DisplayShape([pnt]) output += "<u><b>Properties</b></u>:<br>" output += "<u><b>Axis point</b></u>:<br><b>X=</b>%.3f<br><b>Y=</b>%.3f<br><b>Z=</b>%.3f<br>" % ( pnt.X(), pnt.Y(), pnt.Z()) output += "<u><b>Axis direction</b></u>:<br><b>u=</b>%.3f<br><b>v=</b>%.3f<br><b>w=</b>%.3f<br>" % ( vec.X(), vec.Y(), vec.Z()) self.html.value = output def toggle_shape_visibility(self, *kargs): self.clicked_obj.visible = not self.clicked_obj.visible def toggle_axes_visibility(self, change): self.axes.set_visibility(_bool_or_new(change)) def toggle_grid_visibility(self, change): self.horizontal_grid.set_visibility(_bool_or_new(change)) self.vertical_grid.set_visibility(_bool_or_new(change)) def click(self, value): """ called whenever a shape or edge is clicked """ obj = value.owner.object self.clicked_obj = obj if self._current_mesh_selection != obj: if self._current_mesh_selection is not None: self._current_mesh_selection.material.color = self._current_selection_material_color self._current_mesh_selection.material.transparent = False self._current_mesh_selection = None self._current_selection_material_color = None self._shp_properties_button.value = "Compute" self._shp_properties_button.disabled = True self._toggle_shp_visibility_button.disabled = True self._remove_shp_button.disabled = True self._current_shape_selection = None if obj is not None: self._shp_properties_button.disabled = False self._toggle_shp_visibility_button.disabled = False self._remove_shp_button.disabled = False id_clicked = obj.name # the mesh id clicked self._current_mesh_selection = obj self._current_selection_material_color = obj.material.color obj.material.color = self._selection_color # selected part becomes transparent obj.material.transparent = True obj.material.opacity = 0.5 # get the shape from this mesh id selected_shape = self._shapes[id_clicked] html_value = "<b>Shape type:</b> %s<br>" % get_type_as_string( selected_shape) html_value += "<b>Shape id:</b> %s<br>" % id_clicked self.html.value = html_value self._current_shape_selection = selected_shape else: self.html.value = "<b>Shape type:</b> None<br><b>Shape id:</b> None" # then execute calbacks for callback in self._select_callbacks: callback(self._current_shape_selection) def register_select_callback(self, callback): """ Adds a callback that will be called each time a shape is selected """ if not callable(callback): raise AssertionError( "You must provide a callable to register the callback") else: self._select_callbacks.append(callback) def unregister_callback(self, callback): """ Remove a callback from the callback list """ if callback not in self._select_callbacks: raise AssertionError("This callback is not registered") else: self._select_callbacks.remove(callback) def GetSelectedShape(self): """ Returns the selected shape """ return self._current_shape_selection def DisplayShapeAsSVG(self, shp, export_hidden_edges=True, location=gp_Pnt(0, 0, 0), direction=gp_Dir(1, 1, 1), color="black", line_width=0.5): svg_string = export_shape_to_svg( shp, export_hidden_edges=export_hidden_edges, location=location, direction=direction, color=color, line_width=line_width, margin_left=0, margin_top=0) svg = SVG(data=svg_string) display(svg) def DisplayShape(self, shp, shape_color=None, render_edges=False, edge_color=None, edge_deflection=0.05, vertex_color=None, quality=1.0, transparency=False, opacity=1., topo_level='default', update=False, selectable=True): """ Displays a topods_shape in the renderer instance. shp: the TopoDS_Shape to render shape_color: the shape color, in html corm, eg '#abe000' render_edges: optional, False by default. If True, compute and dislay all edges as a linear interpolation of segments. edge_color: optional, black by default. The color used for edge rendering, in html form eg '#ff00ee' edge_deflection: optional, 0.05 by default vertex_color: optional quality: optional, 1.0 by default. If set to something lower than 1.0, mesh will be more precise. If set to something higher than 1.0, mesh will be less precise, i.e. lower numer of triangles. transparency: optional, False by default (opaque). opacity: optional, float, by default to 1 (opaque). if transparency is set to True, 0. is fully opaque, 1. is fully transparent. topo_level: "default" by default. The value should be either "compound", "shape", "vertex". update: optional, False by default. If True, render all the shapes. selectable: if True, can be doubleclicked from the 3d window """ if edge_color is None: edge_color = self._default_edge_color if shape_color is None: shape_color = self._default_shape_color if vertex_color is None: vertex_color = self._default_vertex_color output = [] # a list of all geometries created from the shape # is it list of gp_Pnt ? if isinstance(shp, list) and isinstance(shp[0], gp_Pnt): result = self.AddVerticesToScene(shp, vertex_color) output.append(result) # or a 1d element such as edge or wire ? elif is_wire(shp) or is_edge(shp): result = self.AddCurveToScene(shp, edge_color, edge_deflection) output.append(result) elif topo_level != "default": t = TopologyExplorer(shp) map_type_and_methods = { "Solid": t.solids, "Face": t.faces, "Shell": t.shells, "Compound": t.compounds, "Compsolid": t.comp_solids } for subshape in map_type_and_methods[topo_level](): result = self.AddShapeToScene(subshape, shape_color, render_edges, edge_color, vertex_color, quality, transparency, opacity) output.append(result) else: result = self.AddShapeToScene(shp, shape_color, render_edges, edge_color, vertex_color, quality, transparency, opacity) output.append(result) if selectable: # Add geometries to pickable or non pickable objects for elem in output: self._displayed_pickable_objects.add(elem) if update: self.Display() def AddVerticesToScene(self, pnt_list, vertex_color, vertex_width=5): """ shp is a list of gp_Pnt """ vertices_list = [] # will be passed to pythreejs BB = BRep_Builder() compound = TopoDS_Compound() BB.MakeCompound(compound) for vertex in pnt_list: vertex_to_add = BRepBuilderAPI_MakeVertex(vertex).Shape() BB.Add(compound, vertex_to_add) vertices_list.append([vertex.X(), vertex.Y(), vertex.Z()]) # map the Points and the AIS_PointCloud # and to the dict of shapes, to have a mapping between meshes and shapes point_cloud_id = "%s" % uuid.uuid4().hex self._shapes[point_cloud_id] = compound vertices_list = np.array(vertices_list, dtype=np.float32) attributes = { "position": BufferAttribute(vertices_list, normalized=False) } mat = PointsMaterial(color=vertex_color, sizeAttenuation=True, size=vertex_width) geom = BufferGeometry(attributes=attributes) points = Points(geometry=geom, material=mat, name=point_cloud_id) return points def AddCurveToScene(self, shp, edge_color, deflection): """ shp is either a TopoDS_Wire or a TopodS_Edge. """ if is_edge(shp): pnts = discretize_edge(shp, deflection) elif is_wire(shp): pnts = discretize_wire(shp, deflection) np_edge_vertices = np.array(pnts, dtype=np.float32) np_edge_indices = np.arange(np_edge_vertices.shape[0], dtype=np.uint32) edge_geometry = BufferGeometry( attributes={ 'position': BufferAttribute(np_edge_vertices), 'index': BufferAttribute(np_edge_indices) }) edge_material = LineBasicMaterial(color=edge_color, linewidth=1) # and to the dict of shapes, to have a mapping between meshes and shapes edge_id = "%s" % uuid.uuid4().hex self._shapes[edge_id] = shp edge_line = Line(geometry=edge_geometry, material=edge_material, name=edge_id) # and to the dict of shapes, to have a mapping between meshes and shapes edge_id = "%s" % uuid.uuid4().hex self._shapes[edge_id] = shp return edge_line def AddShapeToScene( self, shp, shape_color=None, # the default render_edges=False, edge_color=None, vertex_color=None, quality=1.0, transparency=False, opacity=1.): # first, compute the tesselation tess = ShapeTesselator(shp) tess.Compute(compute_edges=render_edges, mesh_quality=quality, parallel=True) # get vertices and normals vertices_position = tess.GetVerticesPositionAsTuple() number_of_triangles = tess.ObjGetTriangleCount() number_of_vertices = len(vertices_position) # number of vertices should be a multiple of 3 if number_of_vertices % 3 != 0: raise AssertionError("Wrong number of vertices") if number_of_triangles * 9 != number_of_vertices: raise AssertionError("Wrong number of triangles") # then we build the vertex and faces collections as numpy ndarrays np_vertices = np.array(vertices_position, dtype='float32').reshape( int(number_of_vertices / 3), 3) # Note: np_faces is just [0, 1, 2, 3, 4, 5, ...], thus arange is used np_faces = np.arange(np_vertices.shape[0], dtype='uint32') # set geometry properties buffer_geometry_properties = { 'position': BufferAttribute(np_vertices), 'index': BufferAttribute(np_faces) } if self._compute_normals_mode == NORMAL.SERVER_SIDE: # get the normal list, converts to a numpy ndarray. This should not raise # any issue, since normals have been computed by the server, and are available # as a list of floats np_normals = np.array(tess.GetNormalsAsTuple(), dtype='float32').reshape(-1, 3) # quick check if np_normals.shape != np_vertices.shape: raise AssertionError("Wrong number of normals/shapes") buffer_geometry_properties['normal'] = BufferAttribute(np_normals) # build a BufferGeometry instance shape_geometry = BufferGeometry(attributes=buffer_geometry_properties) # if the client has to render normals, add the related js instructions if self._compute_normals_mode == NORMAL.CLIENT_SIDE: shape_geometry.exec_three_obj_method('computeVertexNormals') # then a default material shp_material = self._material(shape_color, transparent=transparency, opacity=opacity) # and to the dict of shapes, to have a mapping between meshes and shapes mesh_id = "%s" % uuid.uuid4().hex self._shapes[mesh_id] = shp # finally create the mesh shape_mesh = Mesh(geometry=shape_geometry, material=shp_material, name=mesh_id) # edge rendering, if set to True if render_edges: edges = list( map( lambda i_edge: [ tess.GetEdgeVertex(i_edge, i_vert) for i_vert in range(tess.ObjEdgeGetVertexCount(i_edge)) ], range(tess.ObjGetEdgeCount()))) edge_list = _flatten(list(map(_explode, edges))) lines = LineSegmentsGeometry(positions=edge_list) mat = LineMaterial(linewidth=1, color=edge_color) edge_lines = LineSegments2(lines, mat) self._displayed_non_pickable_objects.add(edge_lines) return shape_mesh def _scale(self, vec): r = self._bb._max_dist_from_center() * self._camera_distance_factor n = np.linalg.norm(vec) new_vec = [v / n * r for v in vec] return new_vec def _material(self, color, transparent=False, opacity=1.0): #material = MeshPhongMaterial() material = CustomMaterial("standard") material.color = color material.clipping = True material.side = "DoubleSide" material.polygonOffset = True material.polygonOffsetFactor = 1 material.polygonOffsetUnits = 1 material.transparent = transparent material.opacity = opacity material.update("metalness", 0.3) material.update("roughness", 0.8) return material def EraseAll(self): self._shapes = {} self._displayed_pickable_objects = Group() self._current_shape_selection = None self._current_mesh_selection = None self._current_selection_material = None self._renderer.scene = Scene(children=[]) def Display(self, position=None, rotation=None): # Get the overall bounding box if self._shapes: self._bb = BoundingBox([self._shapes.values()]) else: # if nothing registered yet, create a fake bb self._bb = BoundingBox([[BRepPrimAPI_MakeSphere(5.).Shape()]]) bb_max = self._bb.max orbit_radius = 1.5 * self._bb._max_dist_from_center() # Set up camera camera_target = self._bb.center camera_position = _add( self._bb.center, self._scale( [1, 1, 1] if position is None else self._scale(position))) camera_zoom = self._camera_initial_zoom self._camera = CombinedCamera(position=camera_position, width=self._size[0], height=self._size[1]) self._camera.up = (0.0, 0.0, 1.0) self._camera.mode = 'orthographic' self._camera_target = camera_target self._camera.position = camera_position if rotation is not None: self._camera.rotation = rotation # Set up lights in every of the 8 corners of the global bounding box positions = list( itertools.product(*[(-orbit_radius, orbit_radius)] * 3)) key_lights = [ DirectionalLight(color='white', position=pos, intensity=0.5) for pos in positions ] ambient_light = AmbientLight(intensity=0.1) # Set up Helpers self.axes = Axes(bb_center=self._bb.center, length=bb_max * 1.1) self.horizontal_grid = Grid(bb_center=self._bb.center, maximum=bb_max, colorCenterLine='#aaa', colorGrid='#ddd') self.vertical_grid = Grid(bb_center=self._bb.center, maximum=bb_max, colorCenterLine='#aaa', colorGrid='#ddd') # Set up scene environment = self.axes.axes + key_lights + [ ambient_light, self.horizontal_grid.grid, self.vertical_grid.grid, self._camera ] scene_shp = Scene(children=[ self._displayed_pickable_objects, self._displayed_non_pickable_objects ] + environment) # Set up Controllers self._controller = OrbitControls(controlling=self._camera, target=camera_target, target0=camera_target) # Update controller to instantiate camera position self._camera.zoom = camera_zoom self._update() # setup Picker self._picker = Picker(controlling=self._displayed_pickable_objects, event='dblclick') self._picker.observe(self.click) self._renderer = Renderer(camera=self._camera, background=self._background, background_opacity=self._background_opacity, scene=scene_shp, controls=[self._controller, self._picker], width=self._size[0], height=self._size[1], antialias=True) # set rotation and position for each grid self.horizontal_grid.set_position((0, 0, 0)) self.horizontal_grid.set_rotation((math.pi / 2.0, 0, 0, "XYZ")) self.vertical_grid.set_position((0, -bb_max, 0)) self._savestate = (self._camera.rotation, self._controller.target) # then display both 3d widgets and webui display(HBox([VBox([HBox(self._controls), self._renderer]), self.html])) def ExportToHTML(self, filename): embed.embed_minimal_html(filename, views=self._renderer, title='pythonocc') def _reset(self, *kargs): self._camera.rotation, self._controller.target = self._savestate self._camera.position = _add(self._bb.center, self._scale((1, 1, 1))) self._camera.zoom = self._camera_initial_zoom self._update() def _update(self): self._controller.exec_three_obj_method('update') def __repr__(self): self.Display() return ""
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 self.first_time = True self.modulo = 1 self.use_defaults = True self.svg_delta_t = 0 self.substrate_delta_t = 0 self.svg_frame = 1 self.substrate_frame = 1 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 = 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 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 self.max_frames = BoundedIntText( min=0, max=99999, value=max_frames, description='# cell 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_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.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 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.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_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).") ]) # 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]) 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']) 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): # Called from pc4biorobots.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" 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 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.i_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.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" # 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 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 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() # 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 = '' # 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.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 hrs = int(mins / 60) days = int(hrs / 24) self.title_str = 'substrate: %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=(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() xmin = float(xml_root.find(".//x_min").text) xmax = float(xml_root.find(".//x_max").text) dx = float(xml_root.find(".//dx").text) ymin = float(xml_root.find(".//y_min").text) ymax = float(xml_root.find(".//y_max").text) dy = float(xml_root.find(".//dy").text) self.numx = math.ceil((xmax - xmin) / dx) self.numy = math.ceil((ymax - ymin) / dy) 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.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.plot_svg(frame) self.svg_frame = frame # print('plot_svg with frame=',self.svg_frame) self.plot_svg(self.svg_frame) # plt.subplot(grid[2, 0]) # oxy_ax = self.fig.add_subplot(grid[2:, 0:1]) #oxy_ax = self.fig.add_subplot(grid[:2, 2:]) #oxy_ax = self.fig.add_subplot(grid[:-1, 0:2]) # nrows, ncols #oxy_ax = self.fig.add_subplot(grid[2:3, 0:1]) # nrows, ncols # oxy_ax = self.fig.add_subplot(grid[4:4, 0:1]) # invalid # main_ax = self.fig.add_subplot(grid[0:1, 0:1]) # experiment with small plot of oxygen (or whatever) # oxy_ax = self.fig.add_subplot(grid[3:4, 0:1]) # nrows, ncols # x = np.linspace(0, 500) # oxy_ax.plot(x, 300*np.sin(x)) #--------------------------------------------------------------------------- def plot_plots(self, frame): # if (self.first_time): # self.svg_delta_t = 1 # self.substrate_delta_t = 1 # self.first_time = False if (self.substrates_toggle.value): self.fig = plt.figure(figsize=(14, 15.6)) else: # only cells being displayed (maybe) self.fig = plt.figure(figsize=(12, 12)) # grid = plt.GridSpec(4, 3, wspace=0.10, hspace=0.2) # (nrows, ncols) # self.plot_substrate(frame, grid) self.plot_substrate(frame)
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 log_explorer(run_manager) -> VBox: # noqa: C901 def _update_fname_dropdown( run_manager, fname_dropdown, only_running_checkbox, only_failed_checkbox, sort_by_dropdown, contains_text, ): def on_click(_): current_value = fname_dropdown.value fnames = _get_fnames(run_manager, only_running_checkbox.value) if only_failed_checkbox.value: fnames = _failed_job_logs(fnames, run_manager, only_running_checkbox.value) if contains_text.value.strip() != "": fnames = _files_that_contain(fnames, contains_text.value.strip()) fnames = _sort_fnames(sort_by_dropdown.value, run_manager, fnames) fname_dropdown.options = fnames with suppress(Exception): fname_dropdown.value = current_value fname_dropdown.disabled = not fnames return on_click def _last_editted(fname: Path) -> float: try: return fname.stat().st_mtime except FileNotFoundError: return -1.0 async def _tail_log(fname: Path, textarea: Textarea) -> None: T = -2.0 # to make sure the update always triggers while True: await asyncio.sleep(2) try: T_new = _last_editted(fname) if T_new > T: textarea.value = _read_file(fname) T = T_new except asyncio.CancelledError: return except Exception: pass def _tail( dropdown, tail_button, textarea, update_button, only_running_checkbox, only_failed_checkbox, ): tail_task = None ioloop = asyncio.get_running_loop() def on_click(_): nonlocal tail_task if tail_task is None: fname = dropdown.options[dropdown.index] tail_task = ioloop.create_task(_tail_log(fname, textarea)) tail_button.description = "cancel tail log" tail_button.button_style = "danger" tail_button.icon = "window-close" dropdown.disabled = True update_button.disabled = True only_running_checkbox.disabled = True only_failed_checkbox.disabled = True else: tail_button.description = "tail log" tail_button.button_style = "info" tail_button.icon = "refresh" dropdown.disabled = False only_running_checkbox.disabled = False only_failed_checkbox.disabled = False update_button.disabled = False tail_task.cancel() tail_task = None return on_click def _on_dropdown_change(textarea): def on_change(change): if (change["type"] == "change" and change["name"] == "value" and change["new"] is not None): textarea.value = _read_file(change["new"]) return on_change def _click_button_on_change(button): def on_change(change): if change["type"] == "change" and change["name"] == "value": button.click() return on_change fnames = _get_fnames(run_manager, only_running=False) # no need to sort `fnames` because the default sort_by option is alphabetical text = _read_file(fnames[0]) if fnames else "" textarea = Textarea(text, layout=dict(width="auto"), rows=20) sort_by_dropdown = Dropdown( description="Sort by", options=[ "Alphabetical", "CPU %", "Mem %", "Last editted", "Loss", "npoints" ], ) contains_text = Text(description="Has string") fname_dropdown = Dropdown(description="File name", options=fnames) fname_dropdown.observe(_on_dropdown_change(textarea)) only_running_checkbox = Checkbox(description="Only files of running jobs", indent=False) only_failed_checkbox = Checkbox( description="Only files of failed jobs (might include false positives)", indent=False, ) update_button = Button(description="update file list", button_style="info", icon="refresh") update_button.on_click( _update_fname_dropdown( run_manager, fname_dropdown, only_running_checkbox, only_failed_checkbox, sort_by_dropdown, contains_text, )) sort_by_dropdown.observe(_click_button_on_change(update_button)) only_running_checkbox.observe(_click_button_on_change(update_button)) only_failed_checkbox.observe(_click_button_on_change(update_button)) tail_button = Button(description="tail log", button_style="info", icon="refresh") tail_button.on_click( _tail( fname_dropdown, tail_button, textarea, update_button, only_running_checkbox, only_failed_checkbox, )) title = HTML("<h2><tt>adaptive_scheduler.widgets.log_explorer</tt></h2>") return VBox( [ title, only_running_checkbox, only_failed_checkbox, update_button, sort_by_dropdown, contains_text, fname_dropdown, tail_button, textarea, ], layout=Layout(border="solid 2px gray"), )
<style> .output { display: flex; align-items: center; text-align: right; } </style> """), arg) EMPTY = '--' def dropdown_eventhandler(change): if (change.new == EMPTY): clear_output(wait=True) _display(dropdown) else: clear_output(wait=True) _display(dropdown) _display(Markdown(f'ros_{change.new}.md')) dropdown = Dropdown(options=['--', '1', '2', '3', '4'], value='--', description='Пункт ↑:', disabled=False) dropdown.observe(dropdown_eventhandler, names='value') _display(dropdown)
def widget_box(path): map_view_box = Output() file_info = glob.glob(f"{path}*_information.json")[0] with open(file_info, 'r') as f: info_data = json.loads(f.read()) pid = info_data['ogc_fid'][0] crop_name = info_data['cropname'][0] area = info_data['area'][0] ci_path = f"{path}{pid}_chip_images/" csv_lists = glob.glob(f"{ci_path}{pid}_images_list.*.csv") bands_list = [i.split('.')[-2] for i in csv_lists] ci_band = Dropdown(options=view_images.available_options( path, pid, False, False), disabled=False, layout=Layout(width='140px')) ci_cloud = Checkbox(value=False, description='Cloud free', disabled=True, indent=False, layout=Layout(width='140px')) def ci_band_changed(b): # m.substitute_layer() map_view_box.clear_output() # m.clear_layers() # m.clear_controls() with map_view_box: display(show_m()) ci_band.observe(ci_band_changed) parcel_info = Label( f"Crop ID: {pid} Crop type: {crop_name}, Area: {area:.2f} sqm") display(HBox([parcel_info, ci_band])) # if os.path.exists(ci_path): def show_m(): multipoly = [] multycent = [] geom = view_spatial.trasform_geometry(info_data) poly = geom['coordinates'][0][0] # poly = view_spatial.swap_xy(geom['coordinates'][0])[0] multipoly.append(poly) cent = view_spatial.centroid(poly) multycent.append(cent) cent = view_spatial.centroid(multycent) m = Map(center=cent, zoom=16, basemap=basemaps.OpenStreetMap.Mapnik) polygon = Polygon(locations=multipoly, name='Parcel polygon', color="yellow", fill_color=None) m.add_layer(polygon) basemap2 = basemap_to_tiles(basemaps.Esri.WorldImagery) poly_text = HTML() poly_text.value = f"""Parcel ID: {pid}<br> Crop name: {crop_name}<br> Area: {area:.2f} sqm<br> Coordinates: {cent} """ poly_text.placeholder = "HTML" poly_text.description = "" # Popup with a given location on the map: poly_popup = Popup(child=poly_text, close_button=False, auto_close=False, close_on_escape_key=False) m.add_layer(poly_popup) # Popup associated to a layer polygon.popup = poly_popup # Layers control show_poly = Checkbox(value=True, description='Polygon', disabled=False, indent=False, layout=Layout(width='140px')) show_sat = Checkbox(value=False, description='High res basemap', disabled=False, indent=False, layout=Layout(width='140px')) def polygon_changed(b): try: if show_poly.value is True: m.add_layer(polygon) else: m.remove_layer(polygon) except Exception: pass show_poly.observe(polygon_changed) def show_sat_changed(b): try: if show_sat.value is True: m.add_layer(basemap2) else: m.remove_layer(basemap2) except Exception: pass show_sat.observe(show_sat_changed) try: csv_list = f"{ci_path}{pid}_images_list.{ci_band.value[0]}.csv" df = view_images.create_df(ci_path, pid, ci_band.value) geotiff = f"{ci_path}{df['imgs'][0]}.{ci_band.value[0]}.tif" bounds = view_spatial.bounds(geotiff) images = {} for i, row in df.iterrows(): str_date = str(row['date'].date()).replace('-', '') workdir = os.getcwd().split('/')[-1] img_tc = f"{ci_path}{('').join(ci_band.value)}_{str_date}.png" # Create false color image if it does not exist # Merge bands (images path, export image path, bands list) if not os.path.isfile(img_tc): imgs_path = f"{ci_path}{row['imgs']}" view_images.merge_bands(imgs_path, img_tc, ci_band.value) values = config.read() # Set the current environment if eval(values['set']['jupyterlab']) is True: image_path = f'files/{workdir}/{img_tc}' else: image_path = img_tc images[i] = ImageOverlay(url=image_path, name=str_date, bounds=(bounds)) # Time slider slider = IntSlider(value=1, min=1, max=len(images), step=1, description=str(df['date'][0].date()), disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d') show_chip = Checkbox(value=True, description='Chip image', disabled=False, indent=False, layout=Layout(width='140px')) def on_ci_band_change(change): pass ci_band.observe(on_ci_band_change, 'value') def show_chip_changed(b): try: if show_chip.value is True: m.add_layer(images[slider.value - 1]) else: m.remove_layer(images[slider.value - 1]) except Exception: pass show_chip.observe(show_chip_changed) # Slider control play = Play(value=1, min=1, max=len(images), step=1, interval=1000, description="Press play", disabled=False) def slider_changed(b): if show_chip.value is True: try: m.substitute_layer(images[b['old'] - 1], images[b['new'] - 1]) except Exception: pass slider.description = str(df['date'][slider.value - 1].date()) slider.observe(slider_changed) jslink((play, 'value'), (slider, 'value')) time_box = HBox([slider, play]) time_control = WidgetControl(widget=time_box, position='bottomleft') m.add_control(time_control) m.add_layer(images[0]) map_options = VBox([show_poly, show_chip, show_sat]) except Exception as err: map_options = VBox([show_poly, show_sat]) print(err) layers_control = WidgetControl(widget=map_options, position='topright', max_width=150) m.add_control(layers_control) return m with map_view_box: display(show_m()) return map_view_box
def _field_folder(self, **kwargs): """Folder that houses field GUI controls.""" folder = super(DemoUniverse, self)._field_folder(**kwargs) uni_field_lists = _ListDict([ ('Hydrogenic', ['1s', '2s', '2px', '2py', '2pz', '3s', '3px', '3py', '3pz', '3d-2', '3d-1', '3d0', '3d+1', '3d+2']), ('Gaussian', ['s', 'px', 'py', 'pz', 'd200', 'd110', 'd101', 'd020', 'd011', 'd002', 'f300', 'f210', 'f201', 'f120', 'f111', 'f102', 'f030', 'f021', 'f012', 'f003']), ('SolidHarmonic', [str(i) for i in range(8)])]) kind_widgets = _ListDict([ (key, Dropdown(options=vals)) for key, vals in uni_field_lists.items()]) ml_widgets = _ListDict([ (str(l), Dropdown(options=[str(i) for i in range(-l, l+1)])) for l in range(8)]) fopts = list(uni_field_lists.keys()) folder.update(kind_widgets, relayout=True) folder.update(ml_widgets, relayout=True) def _field(c): fk = uni_field_lists[c.new][0] for scn in self.active(): scn.field = c.new scn.field_kind = fk folder.deactivate(c.old) folder[c.new].value = fk folder.activate(c.new, enable=True) if c.new == 'SolidHarmonic': folder.activate(fk, enable=True) else: aml = [key for key in folder._get(keys=True) if key.isnumeric()] if aml: folder.deactivate(*aml) folder._set_gui() def _field_kind(c): for scn in self.active(): scn.field_kind = c.new if scn.field == 'SolidHarmonic': scn.field_ml = folder[c.new].options[0] folder.activate(c.new, enable=True) folder.deactivate(c.old) if scn.field_ml != '0': folder.deactivate('0') else: aml = [i for i in folder._get(keys=True) if i.isnumeric()] if aml: folder.deactivate(*aml) folder._set_gui() def _field_ml(c): for scn in self.active(): scn.field_ml = c.new for key, obj in kind_widgets.items(): folder.deactivate(key) obj.observe(_field_kind, names='value') for key, obj in ml_widgets.items(): folder.deactivate(key) obj.observe(_field_ml, names='value') fopts = Dropdown(options=fopts) fopts.observe(_field, names='value') folder.insert(1, 'fopts', fopts) folder.activate('Hydrogenic', enable=True, update=True) folder.move_to_end('alpha', 'iso', 'nx', 'ny', 'nz') return folder
class TrajectoryPlayer(DOMWidget): # should set default values here different from desired defaults # so `observe` can be triggered step = Int(0).tag(sync=True) sync_frame = Bool(True).tag(sync=True) interpolate = Bool(False).tag(sync=False) delay = Float(0.0).tag(sync=True) parameters = Dict().tag(sync=True) iparams = Dict().tag(sync=False) _interpolation_t = Float().tag(sync=False) _iterpolation_type = CaselessStrEnum(['linear', 'spline']).tag(sync=False) spin = Bool(False).tag(sync=False) _spin_x = Int(1).tag(sync=False) _spin_y = Int(0).tag(sync=False) _spin_z = Int(0).tag(sync=False) _spin_speed = Float(0.005).tag(sync=False) camera = CaselessStrEnum(['perspective', 'orthographic'], default_value='perspective').tag(sync=False) _render_params = Dict().tag(sync=False) _real_time_update = Bool(False).tag(sync=False) widget_tab = Any(None).tag(sync=False) widget_repr = Any(None).tag(sync=False) widget_repr_parameters = Any(None).tag(sync=False) widget_quick_repr = Any(None).tag(sync=False) widget_general = Any(None).tag(sync=False) widget_picked = Any(None).tag(sync=False) widget_preference = Any(None).tag(sync=False) widget_extra = Any(None).tag(sync=False) widget_theme = Any(None).tag(sync=False) widget_help = Any(None).tag(sync=False) widget_export_image = Any(None).tag(sync=False) widget_component_slider = Any(None).tag(sync=False) widget_repr_slider = Any(None).tag(sync=False) widget_repr_choices = Any(None).tag(sync=False) widget_repr_control_buttons = Any(None).tag(sync=False) widget_repr_add = Any(None).tag(sync=False) widget_accordion_repr_parameters = Any(None).tag(sync=False) widget_repr_parameters_dialog = Any(None).tag(sync=False) widget_repr_name = Any(None).tag(sync=False) widget_component_dropdown = Any(None).tag(sync=False) widget_drag = Any(None).tag(sync=False) def __init__(self, view, step=1, delay=100, sync_frame=False, min_delay=40): self._view = view self.step = step self.sync_frame = sync_frame self.delay = delay self.min_delay = min_delay self._interpolation_t = 0.5 self._iterpolation_type = 'linear' self.iparams = dict(t=self._interpolation_t, step=1, type=self._iterpolation_type) self._render_params = dict(factor=4, antialias=True, trim=False, transparent=False) self._widget_names = [w for w in dir(self) if w.startswith('wiget_')] self.observe(self._on_widget_built, names=[ 'widget_repr_parameters', 'widget_repr', 'widget_preference' ]) def _on_widget_built(self, change): widget = change['new'] if widget is not None: widget.layout.padding = '5%' def _update_padding(self, padding=default.DEFAULT_PADDING): widget_collection = [ self.widget_general, self.widget_repr, self.widget_preference, self.widget_repr_parameters, self.widget_help, self.widget_extra, self.widget_picked ] for widget in widget_collection: if widget is not None: widget.layout.padding = padding def _create_all_widgets(self): if self.widget_tab is None: self.widget_tab = self._display() old_index = self.widget_tab.selected_index for index, _ in enumerate(self.widget_tab.children): self.widget_tab.selected_index = index self.widget_tab.selected_index = old_index def smooth(self): self.interpolate = True @observe('camera') def on_camera_changed(self, change): camera_type = change['new'] self._view._remote_call("setParameters", target='Stage', kwargs=dict(cameraType=camera_type)) @property def frame(self): return self._view.frame @frame.setter def frame(self, value): self._view.frame = value @property def count(self): return self._view.count @observe('sync_frame') def update_sync_frame(self, change): value = change['new'] if value: self._view._set_sync_frame() else: self._view._set_unsync_frame() @observe("delay") def update_delay(self, change): delay = change['new'] self._view._set_delay(delay) @observe('parameters') def update_parameters(self, change): params = change['new'] self.sync_frame = params.get("sync_frame", self.sync_frame) self.delay = params.get("delay", self.delay) self.step = params.get("step", self.step) @observe('_interpolation_t') def _interpolation_t_changed(self, change): self.iparams['t'] = change['new'] @observe('spin') def on_spin_changed(self, change): self.spin = change['new'] if self.spin: self._view._set_spin([self._spin_x, self._spin_y, self._spin_z], self._spin_speed) else: # stop self._view._set_spin(None, None) @observe('_spin_x') def on_spin_x_changed(self, change): self._spin_x = change['new'] if self.spin: self._view._set_spin([self._spin_x, self._spin_y, self._spin_z], self._spin_speed) @observe('_spin_y') def on_spin_y_changed(self, change): self._spin_y = change['new'] if self.spin: self._view._set_spin([self._spin_x, self._spin_y, self._spin_z], self._spin_speed) @observe('_spin_z') def on_spin_z_changed(self, change): self._spin_z = change['new'] if self.spin: self._view._set_spin([self._spin_x, self._spin_y, self._spin_z], self._spin_speed) @observe('_spin_speed') def on_spin_speed_changed(self, change): self._spin_speed = change['new'] if self.spin: self._view._set_spin([self._spin_x, self._spin_y, self._spin_z], self._spin_speed) def _display(self): box_factory = [(self._make_general_box, 'General'), (self._make_widget_repr, 'Representation'), (self._make_widget_preference, 'Preference'), (self._make_theme_box, 'Theme'), (self._make_extra_box, 'Extra'), (Box, 'Hide'), (self._show_website, 'Help')] tab = _make_delay_tab(box_factory, selected_index=-1) # tab = _make_autofit(tab) tab.layout.align_self = 'center' tab.layout.align_items = 'stretch' self.widget_tab = tab return self.widget_tab def _make_button_center(self): button = Button(description=' Center', icon='fa-bullseye') @button.on_click def on_click(button): self._view.center() return button def _make_button_theme(self): button = Button(description='Oceans16') @button.on_click def on_click(button): from nglview import theme display(theme.oceans16()) self._view._remote_call('cleanOutput', target='Widget') return button def _make_button_reset_theme(self, hide_toolbar=False): from nglview import theme if hide_toolbar: button = Button(description='Simplified Default') @button.on_click def on_click(button): theme.reset(hide_toolbar=True) else: button = Button(description='Default') @button.on_click def on_click(button): theme.reset() return button def _make_widget_preference(self, width='100%'): def make_func(): parameters = self._view._full_stage_parameters def func(pan_speed=parameters.get('panSpeed', 0.8), rotate_speed=parameters.get('rotateSpeed', 2), zoom_speed=parameters.get('zoomSpeed', 1.2), clip_dist=parameters.get('clipDist', 10), camera_fov=parameters.get('cameraFov', 40), clip_far=parameters.get('clipFar', 100), clip_near=parameters.get('clipNear', 0), fog_far=parameters.get('fogFar', 100), fog_near=parameters.get('fogNear', 50), impostor=parameters.get('impostor', True), light_intensity=parameters.get('lightIntensity', 1), quality=parameters.get('quality', 'medium'), sample_level=parameters.get('sampleLevel', 1)): self._view.parameters = dict(panSpeed=pan_speed, rotateSpeed=rotate_speed, zoomSpeed=zoom_speed, clipDist=clip_dist, clipFar=clip_far, clipNear=clip_near, cameraFov=camera_fov, fogFar=fog_far, fogNear=fog_near, impostor=impostor, lightIntensity=light_intensity, quality=quality, sampleLevel=sample_level) return func def make_widget_box(): widget_sliders = interactive(make_func(), pan_speed=(0, 10, 0.1), rotate_speed=(0, 10, 1), zoom_speed=(0, 10, 1), clip_dist=(0, 200, 5), clip_far=(0, 100, 1), clip_near=(0, 100, 1), camera_fov=(15, 120, 1), fog_far=(0, 100, 1), fog_near=(0, 100, 1), light_intensity=(0, 10, 0.02), quality=['low', 'medium', 'high'], sample_level=(-1, 5, 1)) for child in widget_sliders.children: if isinstance(child, (IntSlider, FloatSlider)): child.layout.width = default.DEFAULT_SLIDER_WIDTH return widget_sliders if self.widget_preference is None: widget_sliders = make_widget_box() reset_button = Button(description='Reset') widget_sliders.children = [ reset_button, ] + list(widget_sliders.children) @reset_button.on_click def on_click(reset_button): self._view.parameters = self._view._original_stage_parameters self._view._full_stage_parameters = self._view._original_stage_parameters widget_sliders.children = [ reset_button, ] + list(make_widget_box().children) self.widget_preference = _relayout_master(widget_sliders, width=width) return self.widget_preference def _show_download_image(self): # "interactive" does not work for True/False in ipywidgets 4 yet. button = Button(description=' Screenshot', icon='fa-camera') @button.on_click def on_click(button): self._view.download_image() return button def _make_button_url(self, url, description): button = Button(description=description) @button.on_click def on_click(button): display(Javascript(js_utils.open_url_template.format(url=url))) return button def _show_website(self, ngl_base_url=default.NGL_BASE_URL): buttons = [ self._make_button_url(url.format(ngl_base_url), description) for url, description in [("'http://arose.github.io/nglview/latest/'", "nglview"), ( "'{}/index.html'", "NGL"), ("'{}/tutorial-selection-language.html'", "Selection"), ("'{}/tutorial-molecular-representations.html'", "Representation")] ] self.widget_help = _make_autofit(HBox(buttons)) return self.widget_help def _make_button_qtconsole(self): from nglview import js_utils button = Button(description='qtconsole', tooltip='pop up qtconsole') @button.on_click def on_click(button): js_utils.launch_qtconsole() return button def _make_text_picked(self): ta = Textarea(value=json.dumps(self._view.picked), description='Picked atom') ta.layout.width = '300px' return ta def _refresh(self, component_slider, repr_slider): """update representation and component information """ self._view._request_repr_parameters(component=component_slider.value, repr_index=repr_slider.value) self._view._remote_call('requestReprInfo', target='Widget') self._view._handle_repr_dict_changed(change=dict( new=self._view._repr_dict)) def _make_button_repr_control(self, component_slider, repr_slider, repr_selection): button_refresh = Button(description=' Refresh', tooltip='Get representation info', icon='fa-refresh') button_center_selection = Button(description=' Center', tooltip='center selected atoms', icon='fa-bullseye') button_center_selection._ngl_name = 'button_center_selection' button_hide = Button(description=' Hide', icon='fa-eye-slash', tooltip='Hide/Show current representation') button_remove = Button(description=' Remove', icon='fa-trash', tooltip='Remove current representation') button_repr_parameter_dialog = Button( description=' Dialog', tooltip='Pop up representation parameters control dialog') @button_refresh.on_click def on_click_refresh(button): self._refresh(component_slider, repr_slider) @button_center_selection.on_click def on_click_center(center_selection): self._view.center_view(selection=repr_selection.value, component=component_slider.value) @button_hide.on_click def on_click_hide(button_hide): component = component_slider.value repr_index = repr_slider.value if button_hide.description == 'Hide': hide = True button_hide.description = 'Show' else: hide = False button_hide.description = 'Hide' self._view._remote_call('setVisibilityForRepr', target='Widget', args=[component, repr_index, not hide]) @button_remove.on_click def on_click_remove(button_remove): self._view._remove_representation(component=component_slider.value, repr_index=repr_slider.value) self._view._request_repr_parameters( component=component_slider.value, repr_index=repr_slider.value) @button_repr_parameter_dialog.on_click def on_click_repr_dialog(_): from nglview.widget_box import DraggableBox if self.widget_repr_parameters is not None and self.widget_repr_choices: self.widget_repr_parameters_dialog = DraggableBox( [self.widget_repr_choices, self.widget_repr_parameters]) self.widget_repr_parameters_dialog._ipython_display_() self.widget_repr_parameters_dialog._dialog = 'on' bbox = _make_autofit( HBox([ button_refresh, button_center_selection, button_hide, button_remove, button_repr_parameter_dialog ])) return bbox def _make_widget_repr(self): # TODO: class? if self.widget_repr is None: self.widget_repr_name = Text(value='', description='representation') self.widget_repr_name._ngl_name = 'repr_name_text' repr_selection = Text(value=' ', description='selection') repr_selection._ngl_name = 'repr_selection' repr_selection.width = self.widget_repr_name.width = default.DEFAULT_TEXT_WIDTH max_n_components = max(self._view.n_components - 1, 0) self.widget_component_slider = IntSlider(value=0, max=max_n_components, min=0, description='component') self.widget_component_slider._ngl_name = 'component_slider' cvalue = ' ' self.widget_component_dropdown = Dropdown(value=cvalue, options=[ cvalue, ], description='component') self.widget_component_dropdown._ngl_name = 'component_dropdown' self.widget_repr_slider = IntSlider( value=0, description='representation', width=default.DEFAULT_SLIDER_WIDTH) self.widget_repr_slider._ngl_name = 'repr_slider' self.widget_repr_slider.visible = True self.widget_component_slider.layout.width = default.DEFAULT_SLIDER_WIDTH self.widget_repr_slider.layout.width = default.DEFAULT_SLIDER_WIDTH self.widget_component_dropdown.layout.width = self.widget_component_dropdown.max_width = default.DEFAULT_TEXT_WIDTH # turn off for now self.widget_component_dropdown.layout.display = 'none' self.widget_component_dropdown.description = '' # self.widget_accordion_repr_parameters = Accordion() self.widget_accordion_repr_parameters = Tab() self.widget_repr_parameters = self._make_widget_repr_parameters( self.widget_component_slider, self.widget_repr_slider, self.widget_repr_name) self.widget_accordion_repr_parameters.children = [ self.widget_repr_parameters, Box() ] self.widget_accordion_repr_parameters.set_title(0, 'Parameters') self.widget_accordion_repr_parameters.set_title(1, 'Hide') self.widget_accordion_repr_parameters.selected_index = 1 checkbox_reprlist = Checkbox(value=False, description='reprlist') checkbox_reprlist._ngl_name = 'checkbox_reprlist' self.widget_repr_choices = self._make_repr_name_choices( self.widget_component_slider, self.widget_repr_slider) self.widget_repr_choices._ngl_name = 'reprlist_choices' self.widget_repr_add = self._make_add_widget_repr( self.widget_component_slider) def on_update_checkbox_reprlist(change): self.widget_repr_choices.visible = change['new'] checkbox_reprlist.observe(on_update_checkbox_reprlist, names='value') def on_repr_name_text_value_changed(change): name = change['new'].strip() old = change['old'].strip() should_update = (self._real_time_update and old and name and name in REPRESENTATION_NAMES and name != change['old'].strip()) if should_update: component = component_slider.value repr_index = repr_slider.value self._view._remote_call( 'setRepresentation', target='Widget', args=[change['new'], {}, component, repr_index]) self._view._request_repr_parameters(component, repr_index) def on_component_or_repr_slider_value_changed(change): self._view._request_repr_parameters( component=self.widget_component_slider.value, repr_index=self.widget_repr_slider.value) self.widget_component_dropdown.options = tuple( self._view._ngl_component_names) if self.widget_accordion_repr_parameters.selected_index >= 0: self.widget_repr_parameters.name = self.widget_repr_name.value self.widget_repr_parameters.repr_index = self.widget_repr_slider.value self.widget_repr_parameters.component_index = self.widget_component_slider.value def on_repr_selection_value_changed(change): if self._real_time_update: component = self.widget_component_slider.value repr_index = self.widget_repr_slider.value self._view._set_selection(change['new'], component=component, repr_index=repr_index) def on_change_component_dropdown(change): choice = change['new'] if choice: self.widget_component_slider.value = self._view._ngl_component_names.index( choice) self.widget_component_dropdown.observe( on_change_component_dropdown, names='value') self.widget_repr_slider.observe( on_component_or_repr_slider_value_changed, names='value') self.widget_component_slider.observe( on_component_or_repr_slider_value_changed, names='value') self.widget_repr_name.observe(on_repr_name_text_value_changed, names='value') repr_selection.observe(on_repr_selection_value_changed, names='value') self.widget_repr_control_buttons = self._make_button_repr_control( self.widget_component_slider, self.widget_repr_slider, repr_selection) blank_box = Box([Label("")]) all_kids = [ self.widget_repr_control_buttons, blank_box, self.widget_repr_add, self.widget_component_dropdown, self.widget_repr_name, repr_selection, self.widget_component_slider, self.widget_repr_slider, self.widget_repr_choices, self.widget_accordion_repr_parameters ] vbox = VBox(all_kids) self._view._request_repr_parameters( component=self.widget_component_slider.value, repr_index=self.widget_repr_slider.value) self.widget_repr = _relayout_master(vbox, width='100%') self._refresh(self.widget_component_slider, self.widget_repr_slider) setattr(self.widget_repr, "_saved_widgets", []) for _box in self.widget_repr.children: if hasattr(_box, 'children'): for kid in _box.children: self.widget_repr._saved_widgets.append(kid) return self.widget_repr def _make_widget_repr_parameters(self, component_slider, repr_slider, repr_name_text=None): name = repr_name_text.value if repr_name_text is not None else ' ' widget = self._view._display_repr(component=component_slider.value, repr_index=repr_slider.value, name=name) widget._ngl_name = 'repr_parameters_box' return widget def _make_button_export_image(self): slider_factor = IntSlider(value=4, min=1, max=10, description='scale') checkbox_antialias = Checkbox(value=True, description='antialias') checkbox_trim = Checkbox(value=False, description='trim') checkbox_transparent = Checkbox(value=False, description='transparent') filename_text = Text(value='Screenshot', description='Filename') delay_text = FloatText(value=1, description='delay (s)', tooltip='hello') start_text, stop_text, step_text = (IntText(value=0, description='start'), IntText(value=self._view.count, description='stop'), IntText(value=1, description='step')) start_text.layout.max_width = stop_text.layout.max_width = step_text.layout.max_width \ = filename_text.layout.max_width = delay_text.layout.max_width = default.DEFAULT_TEXT_WIDTH button_movie_images = Button(description='Export Images') def download_image(filename): self._view.download_image(factor=slider_factor.value, antialias=checkbox_antialias.value, trim=checkbox_trim.value, transparent=checkbox_transparent.value, filename=filename) @button_movie_images.on_click def on_click_images(button_movie_images): for i in range(start_text.value, stop_text.value, step_text.value): self._view.frame = i time.sleep(delay_text.value) download_image(filename=filename_text.value + str(i)) time.sleep(delay_text.value) vbox = VBox([ button_movie_images, start_text, stop_text, step_text, delay_text, filename_text, slider_factor, checkbox_antialias, checkbox_trim, checkbox_transparent, ]) form_items = _relayout(vbox, form_item_layout) form = Box(form_items, layout=_make_box_layout()) # form = _relayout_master(vbox) return form def _make_resize_notebook_slider(self): resize_notebook_slider = IntSlider(min=300, max=2000, description='resize notebook') def on_resize_notebook(change): width = change['new'] self._view._remote_call('resizeNotebook', target='Widget', args=[ width, ]) resize_notebook_slider.observe(on_resize_notebook, names='value') return resize_notebook_slider def _make_add_widget_repr(self, component_slider): dropdown_repr_name = Dropdown(options=REPRESENTATION_NAMES, value='cartoon') repr_selection = Text(value='*', description='') repr_button = Button(description='Add', tooltip="""Add representation. You can also hit Enter in selection box""") repr_button.layout = Layout(width='auto', flex='1 1 auto') dropdown_repr_name.layout.width = repr_selection.layout.width = default.DEFAULT_TEXT_WIDTH def on_click_or_submit(button_or_text_area): self._view.add_representation( selection=repr_selection.value.strip(), repr_type=dropdown_repr_name.value, component=component_slider.value) repr_button.on_click(on_click_or_submit) repr_selection.on_submit(on_click_or_submit) add_repr_box = HBox([repr_button, dropdown_repr_name, repr_selection]) add_repr_box._ngl_name = 'add_repr_box' return add_repr_box def _make_repr_playground(self): vbox = VBox() children = [] rep_names = REPRESENTATION_NAMES[:] excluded_names = ['ball+stick', 'distance'] for name in excluded_names: rep_names.remove(name) repr_selection = Text(value='*') repr_selection.layout.width = default.DEFAULT_TEXT_WIDTH repr_selection_box = HBox([Label('selection'), repr_selection]) setattr(repr_selection_box, 'value', repr_selection.value) for index, name in enumerate(rep_names): button = ToggleButton(description=name) def make_func(): def on_toggle_button_value_change(change, button=button): selection = repr_selection.value new = change['new'] # True/False if new: self._view.add_representation(button.description, selection=selection) else: self._view._remove_representations_by_name( button.description) return on_toggle_button_value_change button.observe(make_func(), names='value') children.append(button) button_clear = Button(description='clear', button_style='info', icon='fa-eraser') @button_clear.on_click def on_clear(button_clear): self._view.clear() for kid in children: # unselect kid.value = False vbox.children = children + [repr_selection, button_clear] _make_autofit(vbox) self.widget_quick_repr = vbox return self.widget_quick_repr def _make_repr_name_choices(self, component_slider, repr_slider): repr_choices = Dropdown() def on_chose(change): repr_name = change['new'] repr_index = repr_choices.options.index(repr_name) repr_slider.value = repr_index repr_choices.observe(on_chose, names='value') repr_choices.layout.width = default.DEFAULT_TEXT_WIDTH self.widget_repr_choices = repr_choices return self.widget_repr_choices def _make_drag_widget(self): button_drag = Button(description='widget drag: off', tooltip='dangerous') drag_nb = Button(description='notebook drag: off', tooltip='dangerous') button_reset_notebook = Button(description='notebook: reset', tooltip='reset?') button_dialog = Button(description='dialog', tooltip='make a dialog') button_split_half = Button(description='split screen', tooltip='try best to make a good layout') @button_drag.on_click def on_drag(button_drag): if button_drag.description == 'widget drag: off': self._view._set_draggable(True) button_drag.description = 'widget drag: on' else: self._view._set_draggable(False) button_drag.description = 'widget drag: off' @drag_nb.on_click def on_drag_nb(button_drag): if drag_nb.description == 'notebook drag: off': js_utils._set_notebook_draggable(True) drag_nb.description = 'notebook drag: on' else: js_utils._set_notebook_draggable(False) drag_nb.description = 'notebook drag: off' @button_reset_notebook.on_click def on_reset(button_reset_notebook): js_utils._reset_notebook() @button_dialog.on_click def on_dialog(button_dialog): self._view._remote_call('setDialog', target='Widget') @button_split_half.on_click def on_split_half(button_dialog): from nglview import js_utils import time js_utils._move_notebook_to_the_left() js_utils._set_notebook_width('5%') time.sleep(0.1) self._view._remote_call('setDialog', target='Widget') drag_box = HBox([ button_drag, drag_nb, button_reset_notebook, button_dialog, button_split_half ]) drag_box = _make_autofit(drag_box) self.widget_drag = drag_box return drag_box def _make_spin_box(self): checkbox_spin = Checkbox(self.spin, description='spin') spin_x_slide = IntSlider(self._spin_x, min=-1, max=1, description='spin_x') spin_y_slide = IntSlider(self._spin_y, min=-1, max=1, description='spin_y') spin_z_slide = IntSlider(self._spin_z, min=-1, max=1, description='spin_z') spin_speed_slide = FloatSlider(self._spin_speed, min=0, max=0.2, step=0.001, description='spin speed') # spin link((checkbox_spin, 'value'), (self, 'spin')) link((spin_x_slide, 'value'), (self, '_spin_x')) link((spin_y_slide, 'value'), (self, '_spin_y')) link((spin_z_slide, 'value'), (self, '_spin_z')) link((spin_speed_slide, 'value'), (self, '_spin_speed')) spin_box = VBox([ checkbox_spin, spin_x_slide, spin_y_slide, spin_z_slide, spin_speed_slide ]) spin_box = _relayout_master(spin_box, width='75%') return spin_box def _make_widget_picked(self): self.widget_picked = self._make_text_picked() picked_box = HBox([ self.widget_picked, ]) return _relayout_master(picked_box, width='75%') def _make_export_image_widget(self): if self.widget_export_image is None: self.widget_export_image = HBox([self._make_button_export_image()]) return self.widget_export_image def _make_extra_box(self): if self.widget_extra is None: extra_list = [(self._make_drag_widget, 'Drag'), (self._make_spin_box, 'Spin'), (self._make_widget_picked, 'Picked'), (self._make_repr_playground, 'Quick'), (self._make_export_image_widget, 'Image')] extra_box = _make_delay_tab(extra_list, selected_index=0) self.widget_extra = extra_box return self.widget_extra def _make_theme_box(self): if self.widget_theme is None: self.widget_theme = Box([ self._make_button_theme(), self._make_button_reset_theme(hide_toolbar=False), self._make_button_reset_theme(hide_toolbar=True) ]) return self.widget_theme def _make_general_box(self): if self.widget_general is None: step_slide = IntSlider(value=self.step, min=-100, max=100, description='step') delay_text = IntSlider(value=self.delay, min=10, max=1000, description='delay') toggle_button_interpolate = ToggleButton( self.interpolate, description='Smoothing', tooltip='smoothing trajectory') link((toggle_button_interpolate, 'value'), (self, 'interpolate')) background_color_picker = ColorPicker(value='white', description='background') camera_type = Dropdown(value=self.camera, options=['perspective', 'orthographic'], description='camera') link((step_slide, 'value'), (self, 'step')) link((delay_text, 'value'), (self, 'delay')) link((toggle_button_interpolate, 'value'), (self, 'interpolate')) link((camera_type, 'value'), (self, 'camera')) link((background_color_picker, 'value'), (self._view, 'background')) center_button = self._make_button_center() render_button = self._show_download_image() qtconsole_button = self._make_button_qtconsole() center_render_hbox = _make_autofit( HBox([ toggle_button_interpolate, center_button, render_button, qtconsole_button ])) v0_left = VBox([ step_slide, delay_text, background_color_picker, camera_type, center_render_hbox, ]) v0_left = _relayout_master(v0_left, width='100%') self.widget_general = v0_left return self.widget_general def _create_all_tabs(self): tab = self._display() for index, _ in enumerate(tab.children): # trigger ceating widgets tab.selected_index = index def _simplify_repr_control(self): for widget in self.widget_repr._saved_widgets: if not isinstance(widget, Tab): widget.layout.display = 'none' self.widget_repr_choices.layout.display = 'flex' self.widget_accordion_repr_parameters.selected_index = 0
class RADashBoard: def __init__(self): self.out_cp = Output() display(self.out_cp) self.objDict = {} self.objinfoDict = {} self.title = 'Research & Applications Dashboard' self.nx = 1 self.ny = 1 self.panelWidth = [250,500] self.panelHeight = [250,500] #self.ob = OpenAQGui().createCP() self.ob = QueryOpenAq().getCP() self.state = 0 self.gridGap = 15 self.gridPad = 15 self.panelBorder = 3 self.dbBorder =5 self.cpView = 0 self.pwdDict= {} self.createMainCP = True self.accList =['NASA Earth Data'] def addAccount(accname): self.accList.append(accname) def addObject(self,obj,short_name, desc): self.objDict[short_name] = obj self.objinfoDict[short_name] = desc def displayCP(self): self.rowSW = Dropdown(options=[1,2,3,4],value=1,description='Rows:', disabled=False,layout={'width':'150px'} ) self.colSW = Dropdown(options=[1,2,3,4],value=1,description='Columns:', disabled=False,layout={'width':'150px'} ) self.row = Dropdown(options=[1,2,3,4],value=1, description='# of row:',disabled=True) self.col = Dropdown(options=[1,2,3,4],value=1, description='# of col:',disabled=True) self.obj = Dropdown(options=[],value=None, description='Object:',disabled=True) self.conDB = Button(description='Configure Dashboard',disabled=False, layout={'width':'150px','border':'3px outset'} ) self.topLabel = HTML(disabled=False,layout={'width': 'auto'}) self.topLabel.value = ( '<div style="background-color: #C0C0C0 ;'+ 'padding: 1em 0em 0em 0em;border-bottom-style:groove;border-width:4px">'+ '<b><font size="4"><center><h2>'+self.title+'</h2></center></font></b></div>') self.rule = HTML(disabled=True,layout=Layout(width='auto',padding='0px')) self.rule.value = ( '<div >'+'<hr></div>') self.cpMain = VBox([ HBox([self.topLabel],layout={'justify_content':'center','flex_flow':'column'}), HBox([ HBox([self.rowSW],layout={'justify_content':'flex-start'}), HBox([self.colSW],layout={'justify_content':'flex-end'}) ],layout={'padding':'15px'} ), HBox([self.conDB],layout={'justify_content':'center','padding':'15px'}) ],layout={'border':'3px groove','width': '400px'} ) self.rowSW.observe(self.rowSWCB,names='value') self.colSW.observe(self.colSWCB,names='value') self.conDB.on_click(self.configDBCB) with self.out_cp: display(self.cpMain) def rowSWCB(self,change): if change['type'] == 'change': # set the city to the new user selected value given # by the "value" attribute in the city selection widget. self.ny = int(self.rowSW.value) def colSWCB(self,change): if change['type'] == 'change': # set the city to the new user selected value given # by the "value" attribute in the city selection widget. self.nx = int(self.colSW.value) def rowSWCB(self,change): if change['type'] == 'change': # set the city to the new user selected value given # by the "value" attribute in the city selection widget. self.ny = int(self.rowSW.value) def colSWCB(self,change): if change['type'] == 'change': # set the city to the new user selected value given # by the "value" attribute in the city selection widget. self.nx = int(self.colSW.value) def configDBCB(self,b): self.out_cp.clear_output() self.objList = [*(self.objDict)] pw = self.panelWidth[0] lw = (pw*self.nx)+((self.nx-1)*self.gridGap)+(self.gridPad*2) gw = lw + (2*self.dbBorder) lw1 = lw-2 self.topLabel.layout = {'width': str(lw-2)+'px'} gap = str(self.gridGap)+'px' pd = str(self.gridPad) pad = pd+'px '+pd+'px '+pd+'px '+pd+'px' self.gridDB1 = GridspecLayout(self.ny,self.nx, layout={ 'scroll':'False', 'grid_gap':gap, 'padding':pad } ) self.objSW = [ ([0] * self.nx) for y in range(self.ny) ] self.objinfoTW = [ ([0] * self.nx) for y in range(self.ny) ] self.pwTW = [ ([0] * self.nx) for y in range(self.ny) ] self.phTW = [ ([0] * self.nx) for y in range(self.ny) ] txw = str(int(0.96*float(self.panelWidth[0])))+'px' pw = str(self.panelWidth[0])+'px' ph = str(self.panelHeight[0])+'px' pb = str(self.panelBorder)+'px groove' for i in range(0,self.ny): for j in range(0,self.nx): desc = 'Panel('+str(i+1)+','+str(j+1)+'):' self.objSW[i][j] = Dropdown(options=self.objList,value=self.objList[0], description=desc,disabled=False, layout={'width':txw}) objinfo = self.objinfoDict[self.objList[0]] self.objinfoTW[i][j] = Textarea(value=objinfo,placeholder='',description='', disabled=False,layout={'width':txw,'border':'2px inset'}) self.pwTW[i][j] = Text(value=str(self.panelWidth[1]),placeholder='',description='Panel Width:', disabled=False,layout={'width':txw,'border':'2px inset'}) self.phTW[i][j] = Text(value=str(self.panelHeight[1]),placeholder='',description='Panel Height', disabled=False,layout={'width':txw,'border':'2px inset'}) self.gridDB1[i,j] = VBox([self.objSW[i][j],self.pwTW[i][j],self.phTW[i][j],self.objinfoTW[i][j]],layout={'border':'2px solid black'}) self.objSW[i][j].observe(functools.partial(self.objSWCB, irow_=i, jcol_=j),names='value') self.phTW[i][j].observe(functools.partial(self.phTWCB, irow_=i, jcol_=j),names='value') gp = str(self.gridPad)+'px' dbb = str(self.dbBorder)+'px groove' dbw = str(gw)+'px' self.pmLabel = HTML(disabled=False,layout={'width': 'auto','flex_flow':'column'}) self.pmLabel.value = ( '<div style="background-color: #C0C0C0 ;'+ 'border-top-style:groove;border-width:3px' 'padding: 1em 0em 0em 0em;border-bottom-style:groove;border-width:3px">'+ '<b><font size="4"><center><h3>Password Manager</h3></center></font></b></div>') self.accSW = Dropdown(options=self.accList,value=self.accList[0], description='Account:',disabled=False, layout={'width':txw}) self.usrTW = Text(value='',placeholder='',description='Username:'******'width':txw}) self.pwdPW = Password(value='',placeholder='',description='Password:'******'width':txw}) self.addPWD = Button(description='Add Account',disabled=False, layout={'width':'150px','border':'3px outset'} ) self.createDB = Button(description='Create Dashboard',disabled=False, layout={'width':'150px','border':'3px outset'} ) self.addPWD.on_click(self.addPWDCB) self.createDB.on_click(self.createDBCB) self.reconfigDB = Button(description='Reconfigure Dashboard',disabled=False, layout={'width':'180px','border':'3px outset'} ) self.reconfigDB.on_click(self.reconfigDBCB) self.cp = VBox([ HBox([self.topLabel],layout={'flex_flow':'column'}), HBox([self.gridDB1]), HBox([self.pmLabel],layout={'flex_flow':'column'}), VBox([self.accSW,self.usrTW,self.pwdPW]), HBox([self.addPWD],layout={'justify_content':'center'}), self.rule, HBox([self.reconfigDB,self.createDB],layout={'justify_content':'center','padding':gp}) ],layout={'border':dbb,'width':dbw} ) with self.out_cp: self.out_cp.clear_output() display(self.cp) def objSWCB(self,change,irow_,jcol_): self.objinfoTW[irow_][jcol_].value =self.objinfoDict[self.objSW[irow_][jcol_].value] def phTWCB(self,change,irow_,jcol_): self.objinfoTW[irow_][jcol_].value =('Hint: Set the same height of all the panels in'+ ' a row for optimal panel layout') def addPWDCB(self,b): self.pwdDict[self.accSW.value]={'user':self.usrTW.value,'password':self.pwdPW.value} def createDBCB(self,b): self.out_cp.clear_output() wd = [0]*self.ny for i in range(self.ny): for j in range(self.nx): wd[i] += int(self.pwTW[i][j].value) tpw = max(wd) lw = tpw+((self.nx-1)*self.gridGap)+(self.gridPad*2) self.topLabel.layout = {'width': 'auto'} gw = lw + (2*self.dbBorder) gap = str(self.gridGap)+'px' pd = str(self.gridPad) pad = pd+'px '+pd+'px '+pd+'px '+pd+'px' self.gridDB2 = GridspecLayout(self.ny,self.nx, layout={ 'scroll':'True', 'grid_gap':gap, 'padding':pad } ) ph = str(self.panelHeight[1])+'px' pb = str(self.panelBorder)+'px groove' for i in range(0,self.ny): for j in range(0,self.nx): pw = self.pwTW[i][j].value+'px' ph = self.phTW[i][j].value+'px' obj = self.objDict[self.objSW[i][j].value]() obj.pwdDict = self.pwdDict obj.spacer.layout={'width':pw} obj = obj.getCP() obj.layout={'overflow_x':'visible','overflow_y':'visible'} self.gridDB2[i,j] = HBox([obj],layout={'height': ph,'width': pw,'border':pb}) gp = str(self.gridPad)+'px' dbb = str(self.dbBorder)+'px groove' dbw = str(gw)+'px' self.cp = VBox([ VBox([self.topLabel,self.gridDB2],layout={'flex_flow':'column'}), HBox([self.reconfigDB],layout={'justify_content':'center','padding':gp}) ],layout={'border':dbb,'width':dbw} ) with self.out_cp: self.out_cp.clear_output() display(self.cp) def reconfigDBCB(self,b): with self.out_cp: self.out_cp.clear_output() self.topLabel.layout={'flex_flow':'column'} display(self.cpMain)
class Accesses(): def __init__(self, model, update_selection): self.model = model self.update_selection = update_selection self.colormap = np.copy(newc) self.colorpickers = {} self.custom_layer_preset = None self.all_tags = self.model.curr_trace.tags # includes spacetime and thread self.layer_options = [ ('None', [0]), ('accesses-read', [READ_HIT, READ_MISS, COMP_R_MISS]), ('accesses-write', [WRITE_HIT, WRITE_MISS, COMP_W_MISS]), ('hits-all', [WRITE_HIT, READ_HIT]), ('hits-read', [READ_HIT]), ('hits-write', [WRITE_HIT]), ('misses-all', [READ_MISS, WRITE_MISS, COMP_R_MISS, COMP_W_MISS]), ('misses-reads', [READ_MISS, COMP_R_MISS]), ('misses-writes', [WRITE_MISS, COMP_W_MISS]), ('misses-capacity-all', [WRITE_MISS, READ_MISS]), ('misses-capacity-reads', [READ_MISS]), ('misses-capacity-writes', [WRITE_MISS]), ('misses-compulsory-all', [WRITE_MISS, READ_MISS]), ('misses-compulsory-reads', [COMP_R_MISS]), ('misses-compulsory-writes', [COMP_W_MISS]) ] i_val = 9 for tag in self.all_tags: i_layer = (tag.display_name(), tag) i_val += 1 self.layer_options.append(i_layer) self.widgets = self.init_widgets() def init_widgets(self): ####################################################################### ''' Helper functions to help with wrapping widgets in layouts and initializing UI elements ''' def clr_picker(enum_color, cache=False, miss_acc=False): ''' ''' def handle_color_picker(change): print(enum_color, change) self.colormap[enum_color] = to_rgba(change.new, 1) self.model.plot.colormap = ListedColormap(self.colormap) self.model.plot.backend.plot.update_image() if cache: clr_picker = ColorPicker(concise=True, value=to_hex(self.colormap[enum_color][0:3]), disabled=False, layout=Layout(width="30px")) else: clr_picker = ColorPicker(concise=True, value=to_hex(self.colormap[enum_color][0:3]), disabled=False, layout=Layout(width="25px", margin="0 4px 0 4px")) clr_picker.observe(handle_color_picker, names='value') self.colorpickers[enum_color] = clr_picker clr_picker.observing = True return clr_picker def ParentBox(parent_widgets): # Create wrapper to combine clrpicker checkbox and dropdown return HBox([clr_picker(enum_color=parent_widgets.enum_color), parent_widgets.check_widget , parent_widgets.dropdown_widget], layout=Layout(align_items="center", overflow="hidden", justify_content="flex-start")) ####################################################################### # drop down menue for color view selection self.dropdown = Dropdown(options=C_VIEW_OPTIONS, value='None', disabled=False, layout={'width': 'min-content'} ) self.dropdown.observe(self.update_presets, names='value') self.dropdown.observing = True dropdown_row = HBox([GridBox([Label(value='Layer Preset:'), self.dropdown], layout=Layout(grid_template_rows="30px", grid_template_columns="120px 200px"))], layout=Layout( padding="0px 0px 14px 100px")) ####################################################################### # Primary layers self.layer1_widgets = ParentWidgets(label='1', tooltip="Layer1", enum_color=9, clr=6.1, init_layer_val=[0], layer_options=self.layer_options, compute=self.compute_layers) self.layer2_widgets = ParentWidgets(label='2', tooltip="Layer2", enum_color=8, clr=5.5, init_layer_val=[0], layer_options=self.layer_options, compute=self.compute_layers) self.layer3_widgets = ParentWidgets(label='3', tooltip="Layer3", enum_color=7, clr=5.1, init_layer_val=[0], layer_options=self.layer_options, compute=self.compute_layers) self.layer4_widgets = ParentWidgets(label='4', tooltip="Layer4", enum_color=6, clr=4.4, init_layer_val=[0], layer_options=self.layer_options, compute=self.compute_layers) self.layer5_widgets = ParentWidgets(label='5', tooltip="Layer5", enum_color=5, clr=3.5, init_layer_val=[0], layer_options=self.layer_options, compute=self.compute_layers) self.layer6_widgets = ParentWidgets(label='6', tooltip="Layer6", enum_color=4, clr=3.1, init_layer_val=[0], layer_options=self.layer_options, compute=self.compute_layers) self.layer7_widgets = ParentWidgets(label='7', tooltip="Layer7", enum_color=3, clr=2.4, init_layer_val=[0], layer_options=self.layer_options, compute=self.compute_layers) self.layer8_widgets = ParentWidgets(label='8', tooltip="Layer8", enum_color=2, clr=1.4, init_layer_val=[0], layer_options=self.layer_options, compute=self.compute_layers) self.layers = [self.layer1_widgets, self.layer2_widgets, self.layer3_widgets, self.layer4_widgets, self.layer5_widgets, self.layer6_widgets, self.layer7_widgets, self.layer8_widgets] # Wrap parent widgets in a layout with a color picker layer1 = ParentBox(self.layer1_widgets) layer2 = ParentBox(self.layer2_widgets) layer3 = ParentBox(self.layer3_widgets) layer4 = ParentBox(self.layer4_widgets) layer5 = ParentBox(self.layer5_widgets) layer6 = ParentBox(self.layer6_widgets) layer7 = ParentBox(self.layer7_widgets) layer8 = ParentBox(self.layer8_widgets) grid_elements = [layer1, vdiv, layer2, Whdiv, hdiv, Whdiv, layer3, vdiv, layer4, Whdiv, hdiv, Whdiv, layer5, vdiv, layer6, Whdiv, hdiv, Whdiv, layer7, vdiv, layer8, Whdiv, hdiv, Whdiv, ] row_template = "50px 2px 50px 2px 50px 2px 50px 2px 50px 2px" column_template = "180px 2px 180px" # Add pseudo grid and wrap primary boxes in ipywidget gridbox = HBox([GridBox(grid_elements, layout=Layout(grid_template_rows=row_template, grid_template_columns=column_template))], layout=Layout( padding="0 0 0 14px")) # cache_icon = v.Icon(children=['fa-database'], v_on='tooltip.on') # cache_icon_tp = v.Tooltip(bottom=True, v_slots=[{'name': 'activator', 'variable': 'tooltip', 'children': cache_icon}], children=["Cache"]) # cache_clrpkr = clr_picker(3, cache=True) # reset_clrs = v.Btn(v_on='tooltip.on', icon=True, children=[v.Icon(children=['refresh'])]) # reset_clrs.on_event('click', self.reset_colormap) # reset_clrs_tp = v.Tooltip(bottom=True, v_slots=[{'name': 'activator', 'variable': 'tooltip', 'children': reset_clrs}], children=["Reset all colors"]) # cache_row = HBox([cache_icon_tp, cache_clrpkr, reset_clrs_tp], # layout=Layout(padding="0 20px 20px 20px", align_items="center", justify_content="space-between")) ## , cache_row return VBox([dropdown_row, gridbox]) # @debounced(0.2) def compute_layers(self, change): # reset the layer value of old selections # tags threads and accesses use seperate queries if type(change['old']) is SpaceTimeTag : addr_low = float(change['old'].address[0]) addr_high = float(change['old'].address[1]) + 1 indx_low = float(change['old'].access[0]) indx_high = float(change['old'].access[1]) + 1 # !See Explantion Below self.model.curr_trace.df.Temp1 = self.model.curr_trace.df.func.where( (addr_low <= self.model.curr_trace.df.Address), 1.0 , 2.0) self.model.curr_trace.df.Temp2 = self.model.curr_trace.df.func.where( (addr_high >= self.model.curr_trace.df.Address), 1.0 , 3.0) self.model.curr_trace.df.TempA = self.model.curr_trace.df.func.where( (self.model.curr_trace.df.Temp1 == self.model.curr_trace.df.Temp2), 1.0 , 6.0) self.model.curr_trace.df.Temp3 = self.model.curr_trace.df.func.where( ( indx_low <= self.model.curr_trace.df.index ), 1.0 , 4.0) self.model.curr_trace.df.Temp4 = self.model.curr_trace.df.func.where( ( indx_high >= self.model.curr_trace.df.index ), 1.0, 5.0) self.model.curr_trace.df.TempB = self.model.curr_trace.df.func.where( (self.model.curr_trace.df.Temp3 == self.model.curr_trace.df.Temp4), 1.0 , 7.0) self.model.curr_trace.df[LAYER] = self.model.curr_trace.df.func.where( (self.model.curr_trace.df.TempA == self.model.curr_trace.df.TempB), 0.4 , self.model.curr_trace.df.Layer) elif type(change['old']) is ThreadTag: t_id = change['old'].thread_id self.model.curr_trace.df[LAYER] = self.model.curr_trace.df.func.where(self.model.curr_trace.df.ThreadID == t_id, 1, self.model.curr_trace.df.Layer) else: for atype in change['old']: self.model.curr_trace.df[LAYER] = self.model.curr_trace.df.func.where(self.model.curr_trace.df.Access == atype, 1 , self.model.curr_trace.df.Layer) for layer in reversed(self.layers): # check if the layer checkbox is enabled first if layer.check.v_model == True: # do not update none layers and layer.dropdown_widget.value == change['new'] if layer.dropdown_widget.value != [0] : # tags threads and accesses use seperate queries if type(layer.dropdown_widget.value) is SpaceTimeTag : addr_low = float(layer.dropdown_widget.value.address[0]) addr_high = float(layer.dropdown_widget.value.address[1]) + 1 indx_low = float(layer.dropdown_widget.value.access[0]) indx_high = float(layer.dropdown_widget.value.access[1]) + 1 # df.func.where has a bug where it can only evaluate single boolean value expressions # EX. self.model.curr_trace.df.Address >= addr_low and self.model.curr_trace.df.Address <= addr_high # results in only the first comparison being evaluated. # Thus we must seperate the upper and lower bound calculations, this is not efficient but has minimal # impact on perfomance. # create temp layer to find which accesses belong to tag. self.model.curr_trace.df.Temp1 = self.model.curr_trace.df.func.where( (addr_low <= self.model.curr_trace.df.Address), 1.0 , 2.0) self.model.curr_trace.df.Temp2 = self.model.curr_trace.df.func.where( (addr_high >= self.model.curr_trace.df.Address), 1.0 , 3.0) self.model.curr_trace.df.TempA = self.model.curr_trace.df.func.where( (self.model.curr_trace.df.Temp1 == self.model.curr_trace.df.Temp2), 1.0 , 6.0) self.model.curr_trace.df.Temp3 = self.model.curr_trace.df.func.where( ( indx_low <= self.model.curr_trace.df.index ), 1.0 , 4.0) self.model.curr_trace.df.Temp4 = self.model.curr_trace.df.func.where( ( indx_high >= self.model.curr_trace.df.index ), 1.0, 5.0) self.model.curr_trace.df.TempB = self.model.curr_trace.df.func.where( (self.model.curr_trace.df.Temp3 == self.model.curr_trace.df.Temp4), 1.0 , 7.0) self.model.curr_trace.df[LAYER] = self.model.curr_trace.df.func.where( self.model.curr_trace.df.TempA == self.model.curr_trace.df.TempB, layer.clr , self.model.curr_trace.df.Layer) elif type(layer.dropdown_widget.value) is ThreadTag: t_id = layer.dropdown_widget.value.thread_id self.model.curr_trace.df[LAYER] = self.model.curr_trace.df.func.where( self.model.curr_trace.df.ThreadID == t_id, layer.clr , self.model.curr_trace.df.Layer) else: for atype in layer.dropdown_widget.value: self.model.curr_trace.df[LAYER] = self.model.curr_trace.df.func.where( self.model.curr_trace.df.Access == atype, layer.clr , self.model.curr_trace.df.Layer) else: for atype in layer.dropdown_widget.value: self.model.curr_trace.df[LAYER] = self.model.curr_trace.df.func.where( self.model.curr_trace.df.Access == atype, 1, self.model.curr_trace.df.Layer) self.model.plot.colormap = ListedColormap(self.colormap) self.model.plot.backend.plot.update_grid() def update_presets(self, change): new_preset = change.new if new_preset == 'None': for layer in self.layers: layer.update_selection([0]) elif new_preset == 'AccessType': self.layers[0].update_selection([COMP_W_MISS]) self.layers[1].update_selection([WRITE_MISS]) self.layers[2].update_selection([COMP_R_MISS]) self.layers[3].update_selection([COMP_R_MISS]) self.layers[4].update_selection([WRITE_HIT]) self.layers[5].update_selection([READ_HIT]) elif new_preset == 'TAG': layer_index = 0 for layer_option in reversed(self.layer_options): if type(layer_option[1]) is SpaceTimeTag and layer_index < len(self.layers): if layer_option[0] != 'Stack' and layer_option[0] != 'Heap': self.layers[layer_index].update_selection(layer_option[1]) layer_index += 1 elif new_preset == 'THREAD': layer_index = 0 for layer_option in reversed(self.layer_options): if type(layer_option[1]) is ThreadTag and layer_index < len(self.layers): self.layers[layer_index].update_selection(layer_option[1]) layer_index += 1 elif new_preset == 'Custom': if self.custom_layer_preset is not None: for (index, layer_option) in enumerate(self.custom_layer_preset): for option in self.layer_options: if option[0] == layer_option: self.layers[index].update_selection(option[1]) def set_custom_presets(self, layer_preset): self.custom_layer_preset = layer_preset self.dropdown.value = 'Custom' def reset_colormap(self, *_): self.colormap = np.copy(newc) for clr, clr_picker in self.colorpickers.items(): if clr < TOP_READ: clr_picker.observing = False clr_picker.value = to_hex(self.colormap[enum_color][0:3]) clr_picker.observing = True self.model.plot.colormap = ListedColormap(self.colormap) self.model.plot.backend.plot._update_image()
def _init_gui(self, **kwargs): """Initialize generic GUI controls and observe callbacks.""" mainopts = super(TensorContainer, self)._init_gui(**kwargs) scn = self.scenes[0] alo = Layout(width='74px') rlo = Layout(width='235px') if self._df is not None: scn.txx = self._df.loc[0,'xx'] scn.txy = self._df.loc[0,'xy'] scn.txz = self._df.loc[0,'xz'] scn.tyx = self._df.loc[0,'yx'] scn.tyy = self._df.loc[0,'yy'] scn.tyz = self._df.loc[0,'yz'] scn.tzx = self._df.loc[0,'zx'] scn.tzy = self._df.loc[0,'zy'] scn.tzz = self._df.loc[0,'zz'] xs = [FloatText(value=scn.txx , layout=alo), FloatText(value=scn.txy , layout=alo), FloatText(value=scn.txz , layout=alo)] ys = [FloatText(value=scn.tyx , layout=alo), FloatText(value=scn.tyy , layout=alo), FloatText(value=scn.tyz , layout=alo)] zs = [FloatText(value=scn.tzx , layout=alo), FloatText(value=scn.tzy , layout=alo), FloatText(value=scn.tzz , layout=alo)] #scale = FloatSlider(max=10.0, step=0.01, readout=True, value=1.0) opt = [0] if self._df is None else [int(x) for x in self._df.index.values] tensorIndex = Dropdown(options=opt, value=opt[0], layout=rlo) tdxlabel = Label(value='Select the tensor index:') def _x0(c): for scn in self.active(): scn.txx = c.new def _x1(c): for scn in self.active(): scn.txy = c.new def _x2(c): for scn in self.active(): scn.txz = c.new def _y0(c): for scn in self.active(): scn.tyx = c.new def _y1(c): for scn in self.active(): scn.tyy = c.new def _y2(c): for scn in self.active(): scn.tyz = c.new def _z0(c): for scn in self.active(): scn.tzx = c.new def _z1(c): for scn in self.active(): scn.tzy = c.new def _z2(c): for scn in self.active(): scn.tzz = c.new xs[0].observe(_x0, names='value') xs[1].observe(_x1, names='value') xs[2].observe(_x2, names='value') ys[0].observe(_y0, names='value') ys[1].observe(_y1, names='value') ys[2].observe(_y2, names='value') zs[0].observe(_z0, names='value') zs[1].observe(_z1, names='value') zs[2].observe(_z2, names='value') rlo = Layout(width='234px') xbox = HBox(xs, layout=rlo) ybox = HBox(ys, layout=rlo) zbox = HBox(zs, layout=rlo) geom = Button(icon='cubes', description=' Geometry', layout=_wlo) def _change_tensor(tdx=0): carts = ['x','y','z'] for i, bra in enumerate(carts): for j, ket in enumerate(carts): if i == 0: xs[j].value = self._df.loc[tdx,bra+ket] elif i == 1: ys[j].value = self._df.loc[tdx,bra+ket] elif i == 2: zs[j].value = self._df.loc[tdx,bra+ket] def _geom(b): for scn in self.active(): scn.geom = not scn.geom def _tdx(c): for scn in self.active(): scn.tdx = c.new _change_tensor(c.new) geom.on_click(_geom) tensorIndex.observe(_tdx, names="value") mainopts.update([('geom', geom), ('tlbl', tdxlabel), ('tidx', tensorIndex), ('xbox', xbox), ('ybox', ybox), ('zbox', zbox)]) return mainopts
class MyRenderer(JupyterRenderer): """ An inherited class of the PythonOCC JupyterRenderer with only slight modifications :param size: :param compute_normals_mode: :param default_shape_color: :param default_edge_color: :param default_vertex_color: :param pick_color: :param background_color: """ def __init__( self, size=(640, 480), compute_normals_mode=NORMAL.SERVER_SIDE, default_shape_color=format_color(166, 166, 166), # light grey default_edge_color=format_color(32, 32, 32), # dark grey default_vertex_color=format_color(8, 8, 8), # darker grey pick_color=format_color(232, 176, 36), # orange background_color="white", ): super().__init__( size, compute_normals_mode, default_shape_color, default_edge_color, default_vertex_color, pick_color, background_color, ) from ipywidgets import Dropdown self._toggle_geom_visibility_button = self.create_button( "Geom", "Toggle Geom Visibility", False, self.toggle_all_geom_visibility) self._toggle_mesh_visibility_button = self.create_button( "Mesh", "Toggle Mesh Visibility", False, self.toggle_mesh_visibility) self._controls.pop(0) self._controls.pop(0) fem_sets = ["None"] self._fem_sets_opts = Dropdown(options=fem_sets, value=fem_sets[0], tooltip="Select a set", disabled=False) self._fem_sets_opts.observe(self._on_changed_fem_set, "value") self._controls.insert(0, self._toggle_geom_visibility_button) self._controls.insert(1, self._toggle_mesh_visibility_button) self._controls.pop(-1) self._controls.pop(-1) self._controls.append(self._fem_sets_opts) # self._controls.append(p1) # self._controls.append(p2) self._refs = dict() self._fem_refs = dict() def visible_check(self, obj, obj_type="geom"): from ada import Beam, Part, Plate if obj.name not in self._refs.keys(): raise ValueError(f'object "{obj.name}" not found') adaobj = self._refs[obj.name] if obj_type == "geom" and type(adaobj) in (Beam, Plate): obj.visible = not obj.visible if obj_type == "mesh" and issubclass(type(adaobj), Part) is True: obj.visible = not obj.visible def toggle_all_geom_visibility(self, *kargs): for c in self._displayed_non_pickable_objects.children: self.visible_check(c) for c in self._displayed_pickable_objects.children: self.visible_check(c) def toggle_mesh_visibility(self, *kargs): for c in self._displayed_non_pickable_objects.children: self.visible_check(c, "mesh") for c in self._displayed_pickable_objects.children: self.visible_check(c, "mesh") def DisplayMesh(self, part, edge_color=None, vertex_color=None, vertex_width=2): """ :param part: :param edge_color: :param vertex_color: :param vertex_width: :type part: ada.Part """ from OCC.Core.BRep import BRep_Builder from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeVertex from OCC.Core.gp import gp_Pnt from OCC.Core.TopoDS import TopoDS_Compound # edge_color = format_color(*part.colour) if edge_color is None else edge_color rgb = randint(0, 255), randint(0, 255), randint(0, 255) edge_color = format_color(*rgb) if edge_color is None else edge_color vertex_color = self._default_vertex_color if vertex_color is None else vertex_color pmesh_id = "%s" % uuid.uuid4().hex BB = BRep_Builder() compound = TopoDS_Compound() BB.MakeCompound(compound) vertices_list = [] def togp(n_): return gp_Pnt(float(n_[0]), float(n_[1]), float(n_[2])) for vertex in map(togp, part.fem.nodes): vertex_to_add = BRepBuilderAPI_MakeVertex(vertex).Shape() BB.Add(compound, vertex_to_add) vertices_list.append([vertex.X(), vertex.Y(), vertex.Z()]) attributes = { "position": BufferAttribute(vertices_list, normalized=False) } mat = PointsMaterial(color=vertex_color, sizeAttenuation=False, size=vertex_width) geom = BufferGeometry(attributes=attributes) points_geom = Points(geometry=geom, material=mat, name=pmesh_id) lmesh_id = "%s" % uuid.uuid4().hex edges_nodes = list( chain.from_iterable( filter(None, [grab_nodes(el, part.fem) for el in part.fem.elements]))) np_edge_vertices = np.array(edges_nodes, dtype=np.float32) np_edge_indices = np.arange(np_edge_vertices.shape[0], dtype=np.uint32) vertex_col = tuple([x / 255 for x in rgb]) edge_geometry = BufferGeometry( attributes={ "position": BufferAttribute(np_edge_vertices), "index": BufferAttribute(np_edge_indices), "color": BufferAttribute( [vertex_col for n in np_edge_vertices]), }) edge_material = LineBasicMaterial(vertexColors="VertexColors", linewidth=5) edge_geom = LineSegments( geometry=edge_geometry, material=edge_material, type="LinePieces", name=lmesh_id, ) output = [points_geom, edge_geom] for elem in output: self._shapes[elem.name] = compound self._refs[elem.name] = part self._displayed_pickable_objects.add(elem) self._fem_sets_opts.options = ["None"] + [ f"{part.fem.name}.{s.name}" for s in filter( lambda x: "internal" not in x.metadata.keys(), part.fem.sets) ] self._fem_refs[part.fem.name] = (part.fem, edge_geometry) def DisplayAdaShape(self, shp): """ :param shp: :type shp: ada.Shape :return: """ res = self.DisplayShape( shp.geom, transparency=shp.transparent, opacity=shp.opacity, shape_color=shp.colour, render_edges=False, ) for r in res: self._refs[r.name] = shp def DisplayBeam(self, beam): """ :param beam: :type beam: ada.Beam """ try: if "ifc_file" in beam.metadata.keys(): from ada.core.ifc_utils import get_representation a = beam.parent.get_assembly() ifc_f = a.get_ifc_source_by_name(beam.metadata["ifc_file"]) ifc_elem = ifc_f.by_guid(beam.guid) geom, color, alpha = get_representation( ifc_elem, a.ifc_settings) else: geom = beam.solid res = self.DisplayShape(geom, shape_color=beam.colour, render_edges=True) except BaseException as e: logging.debug( f'Unable to create solid for "{beam.name}" due to {e}') return None for r in res: self._refs[r.name] = beam def DisplayPlate(self, plate): """ :param plate: :type plate: ada.Plate """ geom = self._ifc_geom_to_shape( plate._ifc_geom) if plate._ifc_geom is not None else plate.solid # self.AddShapeToScene(geom) try: res = self.DisplayShape(geom, shape_color=plate.colour_webgl, opacity=0.5) except BaseException as e: logging.error(e) return None for r in res: self._refs[r.name] = plate def DisplayPipe(self, pipe): """ :param pipe: :type pipe: ada.Pipe """ # self.AddShapeToScene(geom) res = [] for i, geom in enumerate(pipe.geometries): try: res += self.DisplayShape(geom, shape_color=pipe.colour_webgl, opacity=0.5) except BaseException as e: logging.error(e) continue for r in res: self._refs[r.name] = pipe def DisplayWall(self, wall): """ :param wall: :type wall: ada.Wall """ try: res = self.DisplayShape(wall.solid, shape_color=wall.colour, opacity=0.5) except BaseException as e: logging.error(e) return None for r in res: self._refs[r.name] = wall def DisplayAdaPart(self, part): """ :return: :type part: ada.Part """ all_shapes = [ shp for p in part.get_all_subparts() for shp in p.shapes ] + part.shapes all_beams = [bm for p in part.get_all_subparts() for bm in p.beams] + [bm for bm in part.beams] all_plates = [pl for p in part.get_all_subparts() for pl in p.plates] + [pl for pl in part.plates] all_pipes = [ pipe for p in part.get_all_subparts() for pipe in p.pipes ] + [pipe for pipe in part.pipes] all_walls = [ wall for p in part.get_all_subparts() for wall in p.walls ] + [wall for wall in part.walls] for wall in all_walls: for insert in wall._inserts: all_shapes.append(insert.shapes[0]) list(map(self.DisplayAdaShape, all_shapes)) list(filter(None, map(self.DisplayBeam, all_beams))) list(filter(None, map(self.DisplayPlate, all_plates))) list(filter(None, map(self.DisplayPipe, all_pipes))) list(filter(None, map(self.DisplayWall, all_walls))) list( map( self.DisplayMesh, filter( lambda x: len(x.fem.elements) != 0, part.get_all_parts_in_assembly(include_self=True), ), )) def DisplayObj(self, obj): from ada import Beam, Part, Pipe, Plate, Shape if issubclass(type(obj), Part) is True: self.DisplayAdaPart(obj) elif type(obj) is Beam: self.DisplayBeam(obj) elif type(obj) is Plate: self.DisplayPlate(obj) elif type(obj) is Pipe: self.DisplayPipe(obj) elif issubclass(type(obj), Shape): self.DisplayAdaShape(obj) else: raise ValueError(f'type "{type(obj)}" Not Recognized') def _ifc_geom_to_shape(self, ifc_geom): from OCC.Core import BRepTools from OCC.Core.TopoDS import TopoDS_Compound if type(ifc_geom) is TopoDS_Compound: geom = ifc_geom elif type(ifc_geom.solid) is not TopoDS_Compound: brep_data = ifc_geom.solid.brep_data ss = BRepTools.BRepTools_ShapeSet() ss.ReadFromString(brep_data) nb_shapes = ss.NbShapes() geom = ss.Shape(nb_shapes) else: geom = ifc_geom.solid return geom # Override and modify parent methods def DisplayShape( self, shp, shape_color=None, render_edges=False, edge_color=None, edge_deflection=0.05, vertex_color=None, quality=1.0, transparency=False, opacity=1.0, topo_level="default", update=False, selectable=True, ): """ Displays a topods_shape in the renderer instance. :param shp: the TopoDS_Shape to render :param shape_color: the shape color, in html corm, eg '#abe000' :param render_edges: optional, False by default. If True, compute and dislay all edges as a linear interpolation of segments. :param edge_color: optional, black by default. The color used for edge rendering, in html form eg '#ff00ee' :param edge_deflection: optional, 0.05 by default :param vertex_color: optional :param quality: optional, 1.0 by default. If set to something lower than 1.0, mesh will be more precise. If set to something higher than 1.0, mesh will be less precise, i.e. lower numer of triangles. :param transparency: optional, False by default (opaque). :param opacity: optional, float, by default to 1 (opaque). if transparency is set to True, 0. is fully opaque, 1. is fully transparent. :param topo_level: "default" by default. The value should be either "compound", "shape", "vertex". :param update: optional, False by default. If True, render all the shapes. :param selectable: if True, can be doubleclicked from the 3d window """ if edge_color is None: edge_color = self._default_edge_color if shape_color is None: shape_color = self._default_shape_color if vertex_color is None: vertex_color = self._default_vertex_color output = [] # a list of all geometries created from the shape # is it list of gp_Pnt ? from OCC.Core.gp import gp_Pnt from OCC.Extend.TopologyUtils import is_edge, is_wire if isinstance(shp, list) and isinstance(shp[0], gp_Pnt): result = self.AddVerticesToScene(shp, vertex_color) output.append(result) # or a 1d element such as edge or wire ? elif is_wire(shp) or is_edge(shp): result = self.AddCurveToScene(shp, edge_color, edge_deflection) output.append(result) elif topo_level != "default": from OCC.Extend.TopologyUtils import TopologyExplorer t = TopologyExplorer(shp) map_type_and_methods = { "Solid": t.solids, "Face": t.faces, "Shell": t.shells, "Compound": t.compounds, "Compsolid": t.comp_solids, } for subshape in map_type_and_methods[topo_level](): result = self.AddShapeToScene( subshape, shape_color, render_edges, edge_color, vertex_color, quality, transparency, opacity, ) output.append(result) else: result = self.AddShapeToScene( shp, shape_color, render_edges, edge_color, vertex_color, quality, transparency, opacity, ) output.append(result) if selectable: # Add geometries to pickable or non pickable objects for elem in output: self._displayed_pickable_objects.add(elem) if update: self.Display() return output def AddShapeToScene( self, shp, shape_color=None, # the default render_edges=False, edge_color=None, vertex_color=None, quality=1.0, transparency=False, opacity=1.0, ): # first, compute the tesselation tess = ShapeTesselator(shp) tess.Compute(compute_edges=render_edges, mesh_quality=quality, parallel=True) # get vertices and normals vertices_position = tess.GetVerticesPositionAsTuple() number_of_triangles = tess.ObjGetTriangleCount() number_of_vertices = len(vertices_position) # number of vertices should be a multiple of 3 if number_of_vertices % 3 != 0: raise AssertionError("Wrong number of vertices") if number_of_triangles * 9 != number_of_vertices: raise AssertionError("Wrong number of triangles") # then we build the vertex and faces collections as numpy ndarrays np_vertices = np.array(vertices_position, dtype="float32").reshape( int(number_of_vertices / 3), 3) # Note: np_faces is just [0, 1, 2, 3, 4, 5, ...], thus arange is used np_faces = np.arange(np_vertices.shape[0], dtype="uint32") # set geometry properties buffer_geometry_properties = { "position": BufferAttribute(np_vertices), "index": BufferAttribute(np_faces), } if self._compute_normals_mode == NORMAL.SERVER_SIDE: # get the normal list, converts to a numpy ndarray. This should not raise # any issue, since normals have been computed by the server, and are available # as a list of floats np_normals = np.array(tess.GetNormalsAsTuple(), dtype="float32").reshape(-1, 3) # quick check if np_normals.shape != np_vertices.shape: raise AssertionError("Wrong number of normals/shapes") buffer_geometry_properties["normal"] = BufferAttribute(np_normals) # build a BufferGeometry instance shape_geometry = BufferGeometry(attributes=buffer_geometry_properties) # if the client has to render normals, add the related js instructions if self._compute_normals_mode == NORMAL.CLIENT_SIDE: shape_geometry.exec_three_obj_method("computeVertexNormals") # then a default material shp_material = self._material(shape_color, transparent=transparency, opacity=opacity) # and to the dict of shapes, to have a mapping between meshes and shapes mesh_id = "%s" % uuid.uuid4().hex self._shapes[mesh_id] = shp # finally create the mesh shape_mesh = Mesh(geometry=shape_geometry, material=shp_material, name=mesh_id) # edge rendering, if set to True if render_edges: edges = list( map( lambda i_edge: [ tess.GetEdgeVertex(i_edge, i_vert) for i_vert in range(tess.ObjEdgeGetVertexCount(i_edge)) ], range(tess.ObjGetEdgeCount()), )) edge_list = _flatten(list(map(_explode, edges))) lines = LineSegmentsGeometry(positions=edge_list) mat = LineMaterial(linewidth=1, color=edge_color) edge_lines = LineSegments2(lines, mat, name=mesh_id) self._displayed_non_pickable_objects.add(edge_lines) return shape_mesh def build_display(self, position=None, rotation=None, camera_type="orthographic"): """ :param position: Camera Position :param rotation: Camera Rotation :param camera_type: Camera Type "orthographic" or "perspective" """ import itertools import math from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeSphere from OCC.Display.WebGl.jupyter_renderer import Axes, Grid, _add from pythreejs import ( AmbientLight, CombinedCamera, DirectionalLight, OrbitControls, Picker, Renderer, Scene, ) # Get the overall bounding box if self._shapes: self._bb = BoundingBox([self._shapes.values()]) else: # if nothing registered yet, create a fake bb self._bb = BoundingBox([[BRepPrimAPI_MakeSphere(5.0).Shape()]]) bb_max = self._bb.max orbit_radius = 1.5 * self._bb._max_dist_from_center() # Set up camera camera_target = self._bb.center camera_position = _add( self._bb.center, self._scale( [1, 1, 1] if position is None else self._scale(position))) camera_zoom = self._camera_initial_zoom self._camera = CombinedCamera(position=camera_position, width=self._size[0], height=self._size[1]) self._camera.up = (0.0, 0.0, 1.0) self._camera.mode = camera_type self._camera_target = camera_target self._camera.position = camera_position if rotation is not None: self._camera.rotation = rotation # Set up lights in every of the 8 corners of the global bounding box positions = list( itertools.product(*[(-orbit_radius, orbit_radius)] * 3)) key_lights = [ DirectionalLight(color="white", position=pos, intensity=0.5) for pos in positions ] ambient_light = AmbientLight(intensity=0.1) # Set up Helpers self.axes = Axes(bb_center=self._bb.center, length=bb_max * 1.1) self.horizontal_grid = Grid(bb_center=self._bb.center, maximum=bb_max, colorCenterLine="#aaa", colorGrid="#ddd") self.vertical_grid = Grid(bb_center=self._bb.center, maximum=bb_max, colorCenterLine="#aaa", colorGrid="#ddd") # Set up scene temp_elems = [ ambient_light, self.horizontal_grid.grid, self.vertical_grid.grid, self._camera ] environment = self.axes.axes + key_lights + temp_elems scene_shp = Scene(children=[ self._displayed_pickable_objects, self._displayed_non_pickable_objects ] + environment) # Set up Controllers self._controller = OrbitControls(controlling=self._camera, target=camera_target, target0=camera_target) # Update controller to instantiate camera position self._camera.zoom = camera_zoom self._update() # setup Picker self._picker = Picker(controlling=self._displayed_pickable_objects, event="dblclick") self._picker.observe(self.click) self._renderer = Renderer( camera=self._camera, background=self._background, background_opacity=self._background_opacity, scene=scene_shp, controls=[self._controller, self._picker], width=self._size[0], height=self._size[1], antialias=True, ) # set rotation and position for each grid self.horizontal_grid.set_position((0, 0, 0)) self.horizontal_grid.set_rotation((math.pi / 2.0, 0, 0, "XYZ")) self.vertical_grid.set_position((0, -bb_max, 0)) self._savestate = (self._camera.rotation, self._controller.target) def click(self, value): """called whenever a shape or edge is clicked""" obj = value.owner.object self.clicked_obj = obj if self._current_mesh_selection != obj: if self._current_mesh_selection is not None: self._current_mesh_selection.material.color = self._current_selection_material_color self._current_mesh_selection.material.transparent = False self._current_mesh_selection = None self._current_selection_material_color = None self._shp_properties_button.value = "Compute" self._shp_properties_button.disabled = True self._toggle_shp_visibility_button.disabled = True self._remove_shp_button.disabled = True self._current_shape_selection = None if obj is not None: self._shp_properties_button.disabled = False self._toggle_shp_visibility_button.disabled = False self._remove_shp_button.disabled = False id_clicked = obj.name # the mesh id clicked self._current_mesh_selection = obj self._current_selection_material_color = obj.material.color obj.material.color = self._selection_color # selected part becomes transparent obj.material.transparent = True obj.material.opacity = 0.5 # get the shape from this mesh id selected_shape = self._shapes[id_clicked] try: html_value = self._click_ada_to_html(obj) except BaseException as e: html_value = f'An error occured: "{str(e)}"' self.html.value = f'<div style="margin: 0 auto; width:300px;">{html_value}</div>' self._current_shape_selection = selected_shape else: self.html.value = "<b>Shape type:</b> None<br><b>Shape id:</b> None" # then execute calbacks for callback in self._select_callbacks: callback(self._current_shape_selection) def _click_ada_to_html(self, obj): """ :param obj: :return: """ from ada import Beam, Part, Pipe, Plate, Shape, Wall from ada.fem.utils import get_eldata def write_metadata_to_html(met_d): table_str = "" for subkey, val in met_d.items(): if type(val) is dict: table_str += f"<tr></tr><td><b>{subkey}:</b></td></tr></tr>" table_str += write_metadata_to_html(val) else: table_str += f"<tr><td>{subkey}</td><td>{val}</td></tr>" return table_str part_name = self._refs[ obj.name].name if obj.name in self._refs.keys() else obj.name selected_part = self._refs[ obj.name] if obj.name in self._refs.keys() else None html_value = "<b>Name:</b> {part_name}".format(part_name=part_name) if issubclass(type(selected_part), Part): assert isinstance(selected_part, Part) html_value += ", <b>Type:</b> FEM Mesh<br><br>" html_value += "<b>Mesh Info</b> <br>" fem_data = get_eldata(selected_part.fem) html_value += "{fem_data}<br>".format(fem_data=", ".join( [f"(<b>{x}</b>: {y})" for x, y in fem_data.items()])) vol_cog_str = ", ".join( [f"{x:.3f}" for x in selected_part.fem.nodes.vol_cog]) cog = selected_part.fem.elements.calc_cog() cog_str = ", ".join([f"{x:.3f}" for x in cog.p]) html_value += f"<b>Vol:</b> {cog.tot_vol:.3f} <b>COG:</b> ({vol_cog_str}) <br>" html_value += f"<b>Mass:</b> {cog.tot_mass:.1f} <b>COG:</b> ({cog_str}) <br>" html_value += f"<b>Beam mass:</b> {cog.bm_mass:.1f}<br>" html_value += f"<b>Shell mass:</b> {cog.sh_mass:.1f}<br>" html_value += f"<b>Node mass:</b> {cog.no_mass:.1f}<br>" html_value += ( "<br><br>Note! Mass calculations are calculated based on <br>beam offsets " "(which is not shown in the viewer yet).") elif type(selected_part) is Beam: assert isinstance(selected_part, Beam) html_value += ", <b>Type:</b> Beam<br>" bm = selected_part html_value += f"<b>Nodes:</b> <b>n1:</b> {bm.n1.p}, <b>n2:</b> {bm.n2.p}<br>" html_value += f"<b>Ori:</b> <b>xv:</b> {bm.xvec}, <b>yv:</b> {bm.yvec}, <b>up:</b> {bm.up}<br>" html_value += f"<b>Angle:</b> {bm._angle} degrees<br>" html_value += f"<b>Section:</b> {bm.section.name}, <b>type:</b> {bm.section.type}<br>" html_value += f"<b>Material:</b> {bm.material.name}<br>" elif type(selected_part) is Plate: html_value += ", <b>Type:</b> Plate<br>" elif type(selected_part) is Shape: assert isinstance(selected_part, Shape) html_value += ", <b>Type:</b> Shape<br>" table_str = f'<div style="height:{self._size[1]}px;overflow:auto;line-height:1.0">' table_str += '<font size="2px" face="Arial" >' table_str += '<table style="width:100%;border: 1px solid black;"><tr><th>Key</th><th>Value</th></tr>' table_str += write_metadata_to_html(selected_part.metadata) table_str += "</table></font></div>" html_value += table_str elif type(selected_part) is Pipe: html_value += ", <b>Type:</b> Pipe<br>" elif type(selected_part) is Wall: html_value += ", <b>Type:</b> Wall<br>" else: html_value += f'<b>Type:</b> Object type "{type(selected_part)}" not recognized by ADA<br>' return html_value def _on_changed_fem_set(self, p): indata = p["new"] tmp_data = indata.split(".") pref = tmp_data[0] setref = tmp_data[1] fem = self._fem_refs[pref][0] edge_geom = self._fem_refs[pref][1] edges_nodes = list( chain.from_iterable( filter(None, [grab_nodes(el, fem, True) for el in fem.elements]))) dark_grey = (0.66, 0.66, 0.66) color_array = np.array( [dark_grey for x in edge_geom.attributes["color"].array], dtype="float32") color = (1, 0, 0) if setref in fem.elsets.keys(): fem_set = fem.elsets[setref] set_edges_nodes = list( chain.from_iterable( filter( None, [grab_nodes(el, fem, True) for el in fem_set.members]))) res1 = [locate(edges_nodes, i) for i in set_edges_nodes] set_edges_indices = chain.from_iterable(res1) for i in set_edges_indices: color_array[i] = color elif setref in fem.nsets.keys(): print(f'Set "{setref}" is a node set (which is not yet supported)') else: logging.error( f'Unrecognized set "{setref}". Not belonging to node or elements' ) edge_geom.attributes["color"].array = color_array def highlight_elem(self, elem_id, fem_name): """ :param elem_id: Can be int or list of ints :param fem_name: :return: """ fem = self._fem_refs[fem_name][0] edge_geom = self._fem_refs[fem_name][1] if type(elem_id) is int: el = fem.elements.from_id(elem_id) elem_nodes = grab_nodes(el, fem, True) elif type(elem_id) in (tuple, list): elem_nodes = list( chain.from_iterable( filter(None, [ grab_nodes(fem.elements.from_id(el), fem, True) for el in elem_id ]))) else: raise ValueError(f'Unrecognized type "{type(elem_id)}"') edges_nodes = list( chain.from_iterable( filter(None, [grab_nodes(el, fem, True) for el in fem.elements]))) res1 = [locate(edges_nodes, i) for i in elem_nodes] set_edges_indices = chain.from_iterable(res1) dark_grey = (0.66, 0.66, 0.66) color_array = np.array( [dark_grey for x in edge_geom.attributes["color"].array], dtype="float32") color = (1, 0, 0) for i in set_edges_indices: color_array[i] = color edge_geom.attributes["color"].array = color_array