Source code for nwbwidgets.dynamictablesummary

from ipywidgets import widgets, Layout
import plotly.express as px

from pynwb.misc import DynamicTable

from .utils.dynamictable import infer_columns_to_plot
from .utils.widgets import interactive_output


field_lay = widgets.Layout(
        max_height="40px", max_width="500px", min_height="30px", min_width="180px"
    )


[docs]class DynamicTableSummaryWidget(widgets.VBox): def __init__(self, table: DynamicTable): super().__init__() self.dynamic_table = table self.col_names, self.categorical_cols = infer_columns_to_plot(self.dynamic_table) num_entries = len(self.dynamic_table) num_columns = len(self.dynamic_table.colnames) num_columns_to_plot = len(self.col_names) num_categorical = len(self.categorical_cols) self.name_text = widgets.Label(f"Table name: {self.dynamic_table.name}\n", layout=field_lay) self.entries_text = widgets.Label(f"Number of entries: {num_entries}\n", layout=field_lay) self.col_text = widgets.Label(f"Number of columns: {num_columns} - real (r): {num_columns - num_categorical}, " f"categorical (c): {num_categorical}", layout=field_lay) self.col_plot_text = widgets.Label(f"Number of inspectable columns: {num_columns_to_plot}") self.summary_text = widgets.VBox( [self.name_text, self.entries_text, self.col_text, self.col_plot_text]) self.col_names_display = {} for col in self.col_names: if col in self.categorical_cols: self.col_names_display[f"(c) {col}"] = col else: self.col_names_display[f"(r) {col}"] = col self.column_dropdown = widgets.SelectMultiple( options=list(self.col_names_display), description="Inspect columns", layout=Layout(max_width="400px"), style={"description_width": "initial"}, disabled=False, tooltip="Select columns to inspect. You can select at most 1 categorical and 3 real columns." ) self.column_dropdown.observe(self.max_selection) self.nbins = widgets.IntText( 10, min=0, description="# bins", layout=Layout(max_width="400px") ) self.nbins.layout.visibility = "hidden" self.show_labels = widgets.Checkbox(value=True, description="show labels") self.plot_controls = widgets.HBox( [self.column_dropdown, self.nbins, self.show_labels]) self.controls = dict( col_names_display=self.column_dropdown, nbins=self.nbins, show_labels=self.show_labels) out_fig = interactive_output(self.plot_hist_bar, self.controls) bottom_panel = widgets.VBox([self.plot_controls, out_fig]) self.children = [self.summary_text, bottom_panel]
[docs] def max_selection(self, change): if change['type'] == 'change' and change['name'] == 'value': if len(self.column_dropdown.value) > 4: print("Maximum number of selected items reached! " "You can select at most 4 items (1 categorical and 3 real)") self.column_dropdown.value = ()
[docs] def reset_dropdown(self): self.column_dropdown.value = ()
[docs] def plot_hist_bar(self, col_names_display, nbins, show_labels): fig = None df = self.dynamic_table.to_dataframe() # remove 's' from dynamic table name if show_labels: entry_names = [f"{self.dynamic_table.name[:-1]} {index}" for index in df.index.values] else: entry_names = None if len(col_names_display) > 0: if len(col_names_display) == 1: # display either 1d histogram (r) or barplot (c) col_name_display = col_names_display[0] col_name = self.col_names_display[col_name_display] if col_name in self.categorical_cols: self.nbins.layout.visibility = "hidden" fig = px.histogram(df, x=col_name, histfunc='count') else: self.nbins.layout.visibility = "visible" fig = px.histogram( df, x=col_name, marginal="violin", nbins=nbins) fig.show() elif len(col_names_display) == 2: # display either scatterplot (2x r) or multiple histograms (1r + 1c) real_cols = [r for r in col_names_display if "(r)" in r] num_real = len(real_cols) if num_real == 2: self.nbins.layout.visibility = "hidden" col_name_0 = col_name = self.col_names_display[col_names_display[0]] col_name_1 = col_name = self.col_names_display[col_names_display[1]] fig = px.scatter(df, x=col_name_0, y=col_name_1, marginal_x="violin", marginal_y="violin", text=entry_names) fig.show() elif num_real == 1: self.nbins.layout.visibility = "visible" col_real = self.col_names_display[real_cols[0]] col_cat_name = [c for c in col_names_display if c not in real_cols][0] col_cat = self.col_names_display[col_cat_name] fig = px.histogram( df, x=col_real, color=col_cat, marginal="violin", nbins=nbins) fig.show() else: print("Select at least one real variable") self.reset_dropdown() elif len(col_names_display) == 3: # display either 3d scatterplot (3x r) or colored 2d scatterplot (2r + 1c) real_cols = [r for r in col_names_display if "(r)" in r] num_real = len(real_cols) if num_real == 3: self.nbins.layout.visibility = "hidden" col_name_0 = col_name = self.col_names_display[col_names_display[0]] col_name_1 = col_name = self.col_names_display[col_names_display[1]] col_name_2 = col_name = self.col_names_display[col_names_display[2]] fig = px.scatter_3d( df, x=col_name_0, y=col_name_1, z=col_name_2, text=entry_names) fig.show() elif num_real == 2: self.nbins.layout.visibility = "hidden" col_real_0 = col_name = self.col_names_display[real_cols[0]] col_real_1 = col_name = self.col_names_display[real_cols[1]] col_cat_name = [c for c in col_names_display if c not in real_cols][0] col_cat = self.col_names_display[col_cat_name] df[col_cat] = df[col_cat].astype("str") fig = px.scatter(df, x=col_real_0, y=col_real_1, color=col_cat, text=entry_names) fig.show() else: print("Select at most one categorical variable") self.reset_dropdown() elif len(col_names_display) == 4: real_cols = [r for r in col_names_display if "(r)" in r] num_real = len(real_cols) if num_real == 3: self.nbins.layout.visibility = "hidden" col_name_0 = col_name = self.col_names_display[real_cols[0]] col_name_1 = col_name = self.col_names_display[real_cols[1]] col_name_2 = col_name = self.col_names_display[real_cols[2]] col_cat_name = [c for c in col_names_display if c not in real_cols][0] col_cat = self.col_names_display[col_cat_name] df[col_cat] = df[col_cat].astype("str") fig = px.scatter_3d(df, x=col_name_0, y=col_name_1, z=col_name_2, color=col_cat, text=entry_names) fig.show() else: print("Select 3 real and one categorical variables") self.reset_dropdown() return fig