def class_area_histogram_with_select(record_stats_list, class_map=None, width=500, height=500):
    """Creates histograms for areas from a list of record_stats."""
    # gui
    # remove the first entry from the class_map, because the background class is not explicit part of the annotaitons
    unique_labels = sorted(pd.unique(record_stats_list[0]["label"]))
    for record_stats in record_stats_list[1:]:
        if not all(pd.unique(sorted(record_stats["label"])) == unique_labels):
            raise ValueError("All dataframes in the records_stats_list need to have the same set of unique values.")
    options = pd.unique(record_stats_list[0]["label"])
    options.sort()
    if class_map is not None:
        options = np.vectorize(class_map.get_id)(options)
    class_dropdown = pnw.Select(options=options.tolist())
    bins_slider = pnw.IntSlider(name="Bins", start=10, end=100, step=5)
    checkbox_normalized = pnw.Checkbox(name="Normalized", value=False)

    @pn.depends(class_dropdown.param.value, bins_slider.param.value, checkbox_normalized.param.value)
    def _draw_histogram(class_label, bins, normalized):
        nonlocal class_map
        nonlocal width
        nonlocal height
        nonlocal record_stats_list
        class_label = class_label if class_map is None else class_map.get_name(class_label)
        return pn.Row(*[draw_area_histogram(record_stats, class_label, class_map, bins, normalized, width, height) for record_stats in record_stats_list])

    return pn.Column(class_dropdown, pn.Row(bins_slider, checkbox_normalized), _draw_histogram)
Beispiel #2
0
class PanelWithEbandsRobot(BaseRobotPanel):  #, metaclass=abc.ABCMeta):
    """
    Mixin class for panels with a robot that owns a list of of |ElectronBands|
    """

    # Widgets to plot ebands.
    ebands_plotter_mode = pnw.Select(
        name="Plot Mode",
        value="gridplot",
        options=["gridplot", "combiplot", "boxplot",
                 "combiboxplot"])  # "animate",
    ebands_plotter_btn = pnw.Button(name="Plot", button_type='primary')
    ebands_df_checkbox = pnw.Checkbox(name='With Ebands DataFrame',
                                      value=False)

    # Widgets to plot edos.
    edos_plotter_mode = pnw.Select(name="Plot Mode",
                                   value="gridplot",
                                   options=["gridplot", "combiplot"])
    edos_plotter_btn = pnw.Button(name="Plot", button_type='primary')

    def get_ebands_plotter_widgets(self):
        return pn.Column(self.ebands_plotter_mode, self.ebands_df_checkbox,
                         self.ebands_plotter_btn)

    @param.depends("ebands_plotter_btn.clicks")
    def on_ebands_plotter_btn(self):
        if self.ebands_plotter_btn.clicks == 0: return
        ebands_plotter = self.robot.get_ebands_plotter()
        plot_mode = self.ebands_plotter_mode.value
        plotfunc = getattr(ebands_plotter, plot_mode, None)
        if plotfunc is None:
            raise ValueError("Don't know how to handle plot_mode: %s" %
                             plot_mode)

        fig = plotfunc(**self.fig_kwargs)
        col = pn.Column(self._mp(fig), sizing_mode='scale_width')
        if self.ebands_df_checkbox.value:
            df = ebands_plotter.get_ebands_frame(with_spglib=True)
            col.append(self._df(df))

        return pn.Row(col, sizing_mode='scale_width')

    def get_edos_plotter_widgets(self):
        return pn.Column(self.edos_plotter_mode, self.edos_plotter_btn)

    @param.depends("edos_plotter_btn.clicks")
    def on_edos_plotter_btn(self):
        if self.edos_plotter_btn.clicks == 0: return
        edos_plotter = self.robot.get_edos_plotter()
        plot_mode = self.edos_plotter_mode.value
        plotfunc = getattr(edos_plotter, plot_mode, None)
        if plotfunc is None:
            raise ValueError("Don't know how to handle plot_mode: %s" %
                             plot_mode)

        fig = plotfunc(**self.fig_kwargs)
        return pn.Row(pn.Column(self._mp(fig)), sizing_mode='scale_width')
Beispiel #3
0
    def _generate_annotations_tab(self):
        plot_size = min(floor(self.width / len(self.datasets)),
                        floor(self.height / 2))
        link_plots_checkbox = pnw.Checkbox(name="Link plot axis", value=False)

        @pn.depends(link_plots_checkbox.param.value)
        def _mixing_plots(link_plots):
            # mixing of classes
            mixing_matrix_classes_in_images = [
                utils.calculate_mixing_matrix(dataset,
                                              self.IMAGE_IDENTIFIER_COL,
                                              self.ANNOTATON_LABEL_COL)
                for dataset in self._get_descriptor_for_all_datasets(
                    self.DESCRIPTOR_DATA)
            ]
            class_mixing_matrix_plot = pn.Row(
                "<b>Class mixing</b>",
                *heatmap(mixing_matrix_classes_in_images,
                         "row_name",
                         "col_name",
                         "values",
                         link_plots=link_plots,
                         width=plot_size,
                         height=plot_size))
            # number of object per image, stacked hist
            classes_for_objects_per_image_stacked_hist = pn.Row(
                "<b>Objects per Image</b>",
                *stacked_hist(self._get_descriptor_for_all_datasets(
                    self.DESCRIPTOR_DATA),
                              self.OBJECTS_PER_IMAGE_COL,
                              self.ANNOTATON_LABEL_COL,
                              "Objects per Image",
                              link_plots=link_plots,
                              width=plot_size,
                              height=plot_size))
            return pn.Column(link_plots_checkbox, class_mixing_matrix_plot,
                             classes_for_objects_per_image_stacked_hist)

        # categorical overview
        self.categorical_2d_histogram = categorical_2d_histogram_with_gui(
            self._get_descriptor_for_all_datasets(self.DESCRIPTOR_DATA),
            category_cols=["label", "num_annotations", "width", "height"],
            hist_cols=[
                "num_annotations", "area", "area_normalized",
                "area_square_root", "area_square_root_normalized",
                "bbox_ratio", "bbox_xmin", "bbox_xmax", "bbox_ymin",
                "bbox_ymax", "bbox_width", "bbox_height", "width", "height"
            ],
            height=floor(plot_size * 1.5),
            width=floor(plot_size * 1.5))
        return pn.Column(_mixing_plots,
                         self.categorical_2d_histogram,
                         align="center")
Beispiel #4
0
    def __init__(
        self,
        df,
        *,
        feature_aliases=None,
        describe=True,
        x_label="timestamp",
        port=5006,
        websocket_origin=49179,
        sample_rate=1.0,
        plot_width=600,
        plot_height=400,
        **params,
    ):

        BasePanel.__init__(
            self,
            df,
            feature_aliases=feature_aliases,
            port=port,
            websocket_origin=websocket_origin,
            sample_rate=sample_rate,
        )
        self.plot_width = plot_width
        self.plot_height = plot_height
        self.describe = describe
        self.x_label = x_label

        tags = sorted(list(df.columns))
        tag = tags[0]
        bounds = self.tag_bounds[tag]

        # widget objects
        self.feature = pnw.Select(value=tag, options=tags, name="Ticker")
        self.description = pnw.Select(
            value=self.feature_aliases[tag],
            options=sorted(list(self.feature_aliases.values())),
            name="Company",
        )
        self.tag_range = pnw.RangeSlider(start=bounds[0],
                                         end=bounds[1],
                                         value=bounds,
                                         name="Feature Range")
        self.log_scale = pnw.Checkbox(
            name="Log scale",
            value=False,
        )

        pm.Parameterized.__init__(self, **params)
Beispiel #5
0
def plot_all(data, alp=True, var='h_li'):
    """
    Scatter plot with x=lon, y=lat.
    Interactivity for missing data and color.
    
    """

    # Static plot
    def scatter(data=data, alp=alp, var=var):
        clean = data[data.loc[:, var] < 1e+38].hvplot.scatter(x='longitude',
                                                              y='latitude',
                                                              c=var,
                                                              s=1,
                                                              alpha=0.2,
                                                              cmap='viridis',
                                                              hover=False)
        missing = data[data.loc[:, var] > 1e+38].hvplot.scatter(
            x='longitude',
            y='latitude',
            c='red',
            s=1,
            alpha=0.2 if alp == True else 0,
            hover=False)
        return (clean * missing)

    # Widgets
    var = pnw.Select(name='Color', value='h_li', options=list(data.columns))
    alp = pnw.Checkbox(value=True, name='Missing data (red)')
    text = "<br>\n# All ATL06 data for the selected area\nSelect a color variable and whether to show missing data"

    # Interactive plot
    @pn.depends(var, alp)
    def reactive(var, alp):
        return (scatter(data, alp, var))

    # Layout
    widgets = pn.Column(text, var, alp)
    image = pn.Row(reactive, widgets)
    return (image)
Beispiel #6
0
def categorical_2d_histogram_with_gui(data: pd.DataFrame, category_cols=None, hist_cols=None, width=500, height=500):
    """Creates a categorical_2d_histogram for a dataframe, where each option (except width, height and color_mapper) of the categorical_2d_histogram can be set with gui elements.
    If the input is a list all dataframes need to have the same cols as the first dataframe in the list"""
    if category_cols is None and isinstance(data, pd.DataFrame):
        category_cols = data.columns.tolist()
    elif category_cols is None and isinstance(data, list):
        category_cols = data[0].columns.tolist()
    if hist_cols is None and isinstance(data, pd.DataFrame):
        hist_cols = [col_name for col_name in data.columns if is_numeric_dtype(data[col_name])]
    elif hist_cols is None and isinstance(data, list):
        hist_cols = [col_name for col_name in data[0].columns if is_numeric_dtype(data[0][col_name])]
    x_select = pnw.Select(name="X-Axis", options=hist_cols)
    y_select = pnw.Select(name="Y-Axis", options=category_cols)

    axis_selector = pn.Row(x_select, y_select, width=width)

    x_is_categorical = pnw.Checkbox(name="X is categorical", value=False)
    x_bins = pnw.IntInput(name="Bins", start=1, end=500, value=10, disabled=False)
    if isinstance(data, pd.DataFrame):
        x_range_start=data[x_select.value].min()
        x_range_end=data[x_select.value].max()
        x_range_end=x_range_end if x_range_end > x_range_start else x_range_end*1.1
        x_range_step=(x_range_end - x_range_start) / 50
    elif isinstance(data, list):
        x_range_start=min(df[x_select.value].min() for df in data)
        x_range_end=max(df[x_select.value].max() for df in data)
        x_range_end=x_range_end if x_range_end > x_range_start else x_range_end*1.1
        x_range_step=(x_range_end - x_range_start) / 50
    x_range = pnw.RangeSlider(name="X-Axis Range", start=x_range_start, end=x_range_end, step=x_range_step, disabled=False)

    x_axis_configuration = pn.Row(x_range, x_bins, width=width)

    normalize_rows = pnw.Checkbox(name="Normalize rows", value=False)
    x_precision = pnw.IntInput(name="Precision", start=0, end=10, value=2, disabled=False)

    additional_parameters = pn.Row(x_is_categorical, normalize_rows, x_precision, width=width)

    config_gui = pn.Column(axis_selector, additional_parameters, x_axis_configuration, align="center")

    @pn.depends(y_select.param.value, x_select.param.value, x_bins.param.value_throttled, x_range.param.value_throttled, x_is_categorical.param.value, normalize_rows.param.value, x_precision.param.value)
    def _plot(category_col, hist_col, bins, range, x_is_categorical, normalize_rows, precision):
        if x_is_categorical:
            x_range.disabled = True
            x_precision.disabled = True
            x_bins.disabled = True
        else:
            x_range.disabled = False
            x_precision.disabled = False
            x_bins.disabled = False

        if isinstance(data, pd.DataFrame):
            if data[hist_col].min() != x_range.start or data[hist_col].max() != x_range.end:
                x_range.start = data[hist_col].min()
                x_range.end = data[hist_col].max() if data[hist_col].max() > x_range.start else data[hist_col].max()*1.1
                x_range.value = (x_range.start, x_range.end)
                x_range.step = (x_range.end-x_range.start)/50
        elif isinstance(data, list):
            if min(df[hist_col].min() for df in data) != x_range.start or max(df[hist_col].max() for df in data) != x_range.end:
                x_range.start = min(df[hist_col].min() for df in data)
                x_range.end = max(df[hist_col].max() for df in data) if max(df[hist_col].max() for df in data) > x_range.start else max(df[hist_col].max() for df in data)*1.1
                x_range.value = (x_range.start, x_range.end)
                x_range.step = (x_range.end-x_range.start)/50
        range = x_range.value

        if isinstance(data, list):
            plot = pn.Row(*categorical_2d_histogram(data, category_col, hist_col, bins, range, normalize_rows, precision, color_mapper=None, hist_col_is_categorical=x_is_categorical, width=width, height=height))
        elif isinstance(data, pd.DataFrame):
            plot = pn.Row(categorical_2d_histogram(data, category_col, hist_col, bins, range, normalize_rows, precision, color_mapper=None, hist_col_is_categorical=x_is_categorical, width=width, height=height))
        return plot

    return pn.Column(config_gui, _plot)
Beispiel #7
0
def map_dash():
    """Map dashboard"""
    # Create the map
    map_pane = pn.pane.plot.Folium(sizing_mode="scale_both", min_width=800)

    # Initialize map at Joshua Tree in July
    unit = 'JOTR'
    month = 7
    coords = get_coords(unit, parks)
    bnds = get_bounds(unit, boundaries)
    traffic = get_traffic(unit, traffic_data)
    visitors = get_visitors(unit, month, publicUse)
    map_pane.object = makeMap(unit, month, coords, bnds, visitors, traffic)

    # Create the dropdown menus for month and visitors
    month_buttons = pnw.RadioButtonGroup(name='Month',
                                         options=list(month_dict.keys()),
                                         button_type='primary',
                                         value='July')
    traffic_checkbox = pnw.Checkbox(name='Display traffic counters',
                                    value=True)
    park_select = pnw.Select(name='Where do you want to go?',
                             options=list(park_dict.keys()),
                             value='Joshua Tree NP')

    # Trigger map updates
    def update_map(event):
        month = month_dict[month_buttons.value]
        unit = park_dict[park_select.value]
        coords = get_coords(unit, parks)
        bnds = get_bounds(unit, boundaries)
        traffic = get_traffic(unit, traffic_data)
        visitors = get_visitors(unit, month, publicUse)
        map_pane.object = makeMap(unit,
                                  month,
                                  coords,
                                  bnds,
                                  visitors,
                                  traffic,
                                  useTraffic=traffic_checkbox.value)
        return

    # Updates
    month_buttons.param.watch(update_map, 'value')
    month_buttons.param.trigger('value')
    park_select.param.watch(update_map, 'value')
    park_select.param.trigger('value')
    traffic_checkbox.param.watch(update_map, 'value')
    traffic_checkbox.param.trigger('value')

    # Fully return the map
    app = pn.Column(month_buttons,
                    traffic_checkbox,
                    park_select,
                    map_pane,
                    width_policy='fit')
    return app


#pn.extension()

#app = map_dash()
#app.servable()
#server = app.show(threaded=True)
Beispiel #8
0
    def __init__(self, plot, tabs):  # pylint: disable=redefined-outer-name
        """Initialize form.

        :param plot: IsothermPlot instance for validation of results.
        :param tabs: Panel tabs instance for triggering tab switching.
        """
        self.plot = plot
        self.tabs = tabs

        # isotherm metadata
        self.inp_doi = pw.TextInput(name='Article DOI',
                                    placeholder='10.1021/jacs.9b01891')
        self.inp_doi.param.watch(self.on_change_doi, 'value')
        self.inp_temperature = pw.TextInput(name='Temperature',
                                            placeholder='303')
        self.inp_adsorbent = pw.AutocompleteInput(
            name='Adsorbent Material',
            options=QUANTITIES['adsorbents']['names'],
            placeholder='Zeolite 5A',
            case_sensitive=False,
            **restrict_kwargs)
        self.inp_isotherm_type = pw.Select(
            name='Isotherm type',
            options=['Select'] + QUANTITIES['isotherm_type']['names'])
        self.inp_measurement_type = pw.Select(
            name='Measurement type',
            options=['Select'] + QUANTITIES['measurement_type']['names'])
        self.inp_pressure_scale = pw.Checkbox(
            name='Logarithmic pressure scale')
        self.inp_isotherm_data = pw.TextAreaInput(
            name='Isotherm Data',
            height=200,
            placeholder=config.SINGLE_COMPONENT_EXAMPLE)
        self.inp_figure_image = pw.FileInput(name='Figure snapshot')

        # units metadata
        self.inp_pressure_units = pw.Select(
            name='Pressure units',
            options=['Select'] + QUANTITIES['pressure_units']['names'])
        self.inp_pressure_units.param.watch(self.on_change_pressure_units,
                                            'value')
        self.inp_saturation_pressure = pw.TextInput(
            name='Saturation pressure [bar]', disabled=True)
        self.inp_adsorption_units = pw.AutocompleteInput(
            name='Adsorption Units',
            options=QUANTITIES['adsorption_units']['names'],
            placeholder='mmol/g',
            case_sensitive=False,
            **restrict_kwargs)

        # digitizer info
        self.inp_source_type = pw.TextInput(name='Source description',
                                            placeholder='Figure 1a')
        self.inp_tabular = pw.Checkbox(
            name='Tabular Data (i.e., not digitized from a graphical source)')
        self.inp_digitizer = pw.TextInput(name='Digitized by',
                                          placeholder='Your full name')

        # fill form from JSON upload
        self.inp_json = pw.FileInput(name='Upload JSON Isotherm')

        # buttons
        self.btn_prefill = pn.widgets.Button(
            name='Prefill (default or from JSON)', button_type='primary')
        self.btn_prefill.on_click(self.on_click_prefill)
        self.out_info = bw.PreText(
            text='Press "Plot" in order to download json.')
        self.inp_adsorbates = Adsorbates(show_controls=False, )
        self.btn_plot = pn.widgets.Button(name='Plot', button_type='primary')
        self.btn_plot.on_click(self.on_click_plot)

        for inp in self.required_inputs:
            inp.css_classes = ['required']

        # create layout
        self.layout = pn.Column(
            pn.pane.HTML('<h2>Isotherm Digitizer</h2>'),
            self.inp_digitizer,
            self.inp_doi,
            pn.pane.HTML('<hr>'),
            self.inp_source_type,
            pn.Row(pn.pane.HTML("""Attach Figure Graphics"""),
                   self.inp_figure_image),
            self.inp_measurement_type,
            self.inp_adsorbent,
            self.inp_adsorbates.column,
            self.inp_temperature,
            self.inp_isotherm_type,
            pn.Row(self.inp_pressure_units, self.inp_saturation_pressure),
            self.inp_pressure_scale,
            self.inp_adsorption_units,
            pn.pane.HTML("""We recommend the
                <b><a href='https://apps.automeris.io/wpd/' target="_blank">WebPlotDigitizer</a></b>
                for data extraction."""),
            self.inp_isotherm_data,
            self.inp_tabular,
            pn.Row(self.btn_plot, self.btn_prefill, self.inp_json),
            self.out_info,
        )
Beispiel #9
0
import panel.widgets as pnw
import datetime
import pandas as pd

import us.states as uss

pn.extension()
pn.config.sizing_mode = "stretch_width"

stats_w = pnw.DataFrame(pd.DataFrame(), name='stats')
counties_w = pnw.DataFrame(pd.DataFrame(), name='counties')

sort_cols = [
    'Confirmed', 'Deaths', 'Active', 'county', 'pop2019', 'fraction_confirmed',
    'death_rate'
]
state_w = pnw.Select(name='state',
                     options=uss.states(),
                     value='Alabama',
                     disabled=False)

sortby_w = pnw.Select(name='sort on column',
                      options=sort_cols,
                      value='fraction_confirmed',
                      disabled=False)

ascending_w = pnw.Checkbox(name='Sort Ascending', value=False, disabled=False)

date_w = pnw.DatePicker(name='date',
                        value=datetime.date.today() - datetime.timedelta(1),
                        disabled=False)
Beispiel #10
0
def bam_viewer(bam_file, ref_file, gff_file=None, width=1000, height=200, color='gray'):
    """Bam viewer widget.
    
    Args:
        bam_file: sorted bam file
        ref_file: reference sequence in fasta format
        gff_file: optional genomic features file
    """
    slider = pnw.IntSlider(name='location',start=1,end=10000,value=500,step=500,width=300)
    main_pane = pn.pane.Bokeh(height=100)
    cov_pane = pn.pane.Bokeh(height=60)
    loc_pane = pn.pane.Str(50,width=250,style={'margin': '4pt'})
    feat_pane = pn.pane.Bokeh(height=60)
    ref_pane = pn.pane.Bokeh(height=60)
    xzoom_slider = pnw.IntSlider(name='x zoom',start=50,end=8000,value=1000,step=10,width=100)
    yzoom_slider = pnw.IntSlider(name='y zoom',start=10,end=100,value=20,step=5,width=100)#,orientation='vertical')
    panleft_btn = pnw.Button(name='<',width=50,button_type='primary')
    panright_btn = pnw.Button(name='>',width=50,button_type='primary')
    chroms_select = pnw.Select(name='Chromosome', options=[], width=250)
    colorby = pnw.Select(name='Color by', options=['quality','pair orientation','read strand'], width=180)
    search_pane = pnw.TextInput(name='search',width=200)
    trans_option = pnw.Checkbox(name='show translation')
    debug_pane = pn.pane.Markdown()
    
    def pan_right(event):
        plot = main_pane.object
        plot.x_range
        start = slider.value 
        loc = slider.value+100    
        slider.value=loc
        update(event)
        return

    def pan_left(event):
        loc = slider.value-100
        if loc<1:
            return
        slider.value=loc
        update(event)
        return

    def update_features():
        """Load features"""

        if gff_file is None:
            return        
        ext = os.path.splitext(gff_file)[1]        
        if ext in ['.gff','.gff3']:
            feats = utils.gff_to_features(gff_file)
        elif ext in ['.gb','.gbff']:
            feats = utils.genbank_to_features(gff_file)
        p = feat_pane.object = plotters.plot_features(feats, 
                                                  plot_width=width, plot_height=100)
        return p

    def search_features(event):
        """Find a feature"""
        
        term = search_pane.value        
        feats = utils.gff_to_features(gff_file)
        df = utils.features_to_dataframe(feats)    
        df['gene'] = df.gene.fillna('')
        f = df[df.gene.str.contains(term)].iloc[0]
        debug_pane.object = str(f.start)
        slider.value = int(f.start)
        update(event)
        return
    
    def update_ref(filename, start, end):
        """Update reference sequence"""

        if filename == None:
            return
        seqlen = utils.get_fasta_length(filename)
        slider.end = seqlen
        refseq = Fasta(filename)
        chroms = list(refseq.keys())
        chroms_select.options = chroms
        key = chroms[0]
        seq = refseq[key][int(start):int(end)].seq
        ref_pane.object = plotters.plot_sequence(seq, plot_height=50,fontsize='9pt',xaxis=False)
        return
    
    def update(event):
        """Update viewers on widget change"""

        xzoom = xzoom_slider.value
        yzoom = yzoom_slider.value
        start = slider.value     
        N = xzoom/2
        end = start+N
        chrom = utils.get_chrom(bam_file)
        loc_pane.object = '%s:%s-%s' %(chrom,start,int(end))
        cov = utils.get_coverage(bam_file,chrom,start,end)
        cov_pane.object = plotters.plot_coverage(cov,plot_width=width)
        main_pane.object = plotters.plot_bam_alignment(bam_file,chrom,start,end,height=yzoom,plot_width=width,plot_height=height)        
        update_ref(ref_file, start, end)
        if feature_plot:
            feature_plot.x_range.start = start
            feature_plot.x_range.end = end
        debug_pane.object = ''
        return

    slider.param.watch(update, 'value')
    xzoom_slider.param.watch(update, 'value')
    yzoom_slider.param.watch(update, 'value')
    panright_btn.param.watch(pan_right, 'clicks')
    panleft_btn.param.watch(pan_left, 'clicks')
    search_pane.param.watch(search_features, 'value')
    feature_plot = update_features()
    
    #initialise slider
    slider.param.trigger('value')
    
    #menus = pn.Row(bam_input, ref_input, gff_input)
    top = pn.Row(slider,xzoom_slider,yzoom_slider,panleft_btn,panright_btn,loc_pane)
    bottom = pn.Row(chroms_select, search_pane,colorby,trans_option)
    app = pn.Column(top,cov_pane,main_pane,ref_pane,feat_pane,bottom,debug_pane)
    return app
Beispiel #11
0
    def _update_widgets_panel(self):
        self._default_component[self.component_type] = self.component

        component = None
        controls = None
        if self.component is pn.pane.HoloViews:
            component = pn.pane.HoloViews(_create_hvplot())
        if self.component is pn.pane.ECharts:
            # Issue https://github.com/holoviz/panel/issues/1817
            component = pn.pane.ECharts(_create_echarts_plot(),
                                        min_height=400,
                                        min_width=200,
                                        sizing_mode="stretch_both")
        if self.component is pnw.Ace:
            py_code = inspect.getsource(_create_hvplot)
            component = pnw.Ace(
                value=py_code,
                sizing_mode="stretch_width",
                language="python",
                height=400,
                theme=self._ace_theme,
            )
        elif self.component is pnw.AutocompleteInput:
            component = pnw.AutocompleteInput(
                name="Autocomplete Input",
                options=["Biology", "Chemistry", "Physics"],
                placeholder="Write something here",
            )
        elif self.component is pnw.Button:
            component = pnw.Button(name="Click me", button_type="primary")
        elif self.component is pnw.CheckBoxGroup:
            component = pnw.CheckBoxGroup(
                name="Checkbox Group",
                value=["Apple", "Pear"],
                options=["Apple", "Banana", "Pear", "Strawberry"],
                inline=True,
            )
        elif self.component is pnw.CheckButtonGroup:
            component = pnw.CheckButtonGroup(
                name="Check Button Group",
                value=["Apple", "Pear"],
                options=["Apple", "Banana", "Pear", "Strawberry"],
                button_type="success",
            )
        elif self.component is pnw.Checkbox:
            component = pnw.Checkbox(name="Checkbox")
        elif self.component is pnw.ColorPicker:
            component = pnw.ColorPicker(name="Color Picker", value="#DF3874")
        elif self.component is pnw.CrossSelector:
            component = pnw.CrossSelector(
                name="Fruits",
                value=["Apple", "Pear"],
                options=["Apple", "Banana", "Pear", "Strawberry"],
                height=300,
            )
        elif self.component is pnw.DataFrame:
            component = self.component(name="Hello")
            component.value = get_dataframe()
            component.formatters = get_default_formatters(component.value)
            controls = pn.Spacer()
        elif self.component is pnw.DatePicker:
            component = pnw.DatePicker(name="Date Picker")
            # Issue: https://github.com/holoviz/panel/issues/1810
            # component.start = date(2020, 1, 20)
            # component.end = date(2020, 2, 20)
            # component.value = date(2020, 2, 18)
        elif self.component is pnw.DateRangeSlider:
            component = self.component(name="Hello")
            component.start = date(2020, 1, 20)
            component.end = date(2020, 2, 20)
            component.value = (date(2020, 2, 18), date(2020, 2, 20))
        elif self.component is pnw.DateSlider:
            component = self.component(name="Hello")
            component.start = date(2020, 1, 20)
            component.end = date(2020, 2, 20)
            component.value = date(2020, 2, 18)
        elif self.component is pnw.DatetimeInput:
            component = self.component(name="Hello")
            component.value = datetime(2020, 2, 18, 1, 2, 3)
        elif self.component is pnw.DatetimeRangeInput:
            component = self.component(
                name="Hello",
                start=datetime(2020, 1, 20),
                end=datetime(2020, 2, 20),
                value=(datetime(2020, 2, 18), datetime(2020, 2, 20)),
            )
        elif self.component is pnw.DiscretePlayer:
            component = pnw.DiscretePlayer(
                name="Discrete Player",
                options=[2, 4, 8, 16, 32, 64, 128],
                value=32,
                loop_policy="loop",
            )
        elif self.component is pnw.DiscreteSlider:
            component = pnw.DiscreteSlider(name="Discrete Slider",
                                           options=[2, 4, 8, 16, 32, 64, 128],
                                           value=32)
        elif self.component is pnw.FileDownload:
            component = pnw.FileDownload(file="README.md",
                                         filename="README.md")
        elif self.component is pnw.FileInput:
            component = pnw.FileInput(accept=".csv,.json")
        elif self.component is pnw.FileSelector:
            component = pnw.FileSelector(name="Hello", max_height=400)
        elif self.component is pnw.FloatInput:
            component = pnw.FloatInput(name="FloatInput",
                                       value=5.0,
                                       step=1e-1,
                                       start=0,
                                       end=1000)
        elif self.component is pnw.FloatSlider:
            component = pnw.FloatSlider(name="Float Slider",
                                        start=0,
                                        end=3.141,
                                        step=0.01,
                                        value=1.57)
        elif self.component is pnw.IntInput:
            component = pnw.IntInput(name="IntInput",
                                     value=5,
                                     step=2,
                                     start=0,
                                     end=1000)
        elif self.component is pnw.IntRangeSlider:
            component = pnw.IntRangeSlider(name="Integer Range Slider",
                                           start=0,
                                           end=100,
                                           value=(8, 40),
                                           step=2)
        elif self.component is pnw.IntSlider:
            component = pnw.IntSlider(name="Integer Slider",
                                      start=0,
                                      end=20,
                                      step=2,
                                      value=4)
        elif self.component is pnw.LiteralInput:
            component = pnw.LiteralInput(name="Literal Input (dict)",
                                         value={"key": [1, 2, 3]},
                                         type=dict)
        elif self.component is pnw.MenuButton:
            menu_items = [
                ("Option A", "a"),
                ("Option B", "b"),
                ("Option C", "c"),
                None,
                ("Help", "help"),
            ]
            component = pnw.MenuButton(name="Dropdown",
                                       items=menu_items,
                                       button_type="primary")
        elif self.component is pnw.MultiChoice:
            component = pnw.MultiChoice(
                name="MultiSelect",
                value=["Apple", "Pear"],
                options=["Apple", "Banana", "Pear", "Strawberry"],
            )
        elif self.component is pnw.MultiSelect:
            component = pnw.MultiSelect(
                name="MultiSelect",
                value=["Apple", "Pear"],
                options=["Apple", "Banana", "Pear", "Strawberry"],
                size=8,
            )
        elif self.component is pnw.PasswordInput:
            component = pnw.PasswordInput(name="Password Input",
                                          placeholder="Enter a string here...")
        elif self.component is pnw.Player:
            component = pnw.Player(name="Player",
                                   start=0,
                                   end=100,
                                   value=32,
                                   loop_policy="loop")
        elif self.component is pnw.Progress:
            component = pnw.Progress(name="Progress", value=20, width=200)
        elif self.component is pnw.RadioBoxGroup:
            component = pnw.RadioBoxGroup(
                name="RadioBoxGroup",
                options=["Biology", "Chemistry", "Physics"],
                inline=True)
        elif self.component is pnw.RadioButtonGroup:
            component = pnw.RadioButtonGroup(
                name="Radio Button Group",
                options=["Biology", "Chemistry", "Physics"],
                button_type="success",
            )
        elif self.component is pnw.RangeSlider:
            component = pnw.RangeSlider(
                name="Range Slider",
                start=0,
                end=math.pi,
                value=(math.pi / 4.0, math.pi / 2.0),
                step=0.01,
            )
        elif self.component is pnw.Select:
            component = pnw.Select(name="Select",
                                   options=["Biology", "Chemistry", "Physics"])
        elif self.component is pnw.StaticText:
            component = pnw.StaticText(name="Static Text", value="A string")
        elif self.component is pnw.TextAreaInput:
            component = pnw.input.TextAreaInput(
                name="Text Area Input", placeholder="Enter a string here...")
        elif self.component is pnw.TextInput:
            component = pnw.TextInput(name="Text Input",
                                      placeholder="Enter a string here...")
        elif self.component == pnw.Toggle:
            component = pnw.Toggle(name="Toggle", button_type="success")
        elif self.component == pnw.VideoStream:
            component = pnw.VideoStream(name="Video Stream",
                                        sizing_mode="stretch_width",
                                        height=300)
        if not component:
            component = self.component(name="Hello")
        if not controls:
            controls = component.controls()
        controls.margin = 0
        self._component_panel[:] = [
            pn.pane.Markdown("## " + component.__class__.name + " " +
                             self.component_type),
            component,
            pn.layout.Divider(),
            pn.pane.Markdown("## Parameters"),
            controls,
        ]
Beispiel #12
0
class FlowPanel(AbipyParameterized):
    """
    """
    verbose = pn.widgets.IntSlider(start=0, end=10, step=1, value=0)

    engine = pn.widgets.Select(value="fdp",
                               options=[
                                   'dot', 'neato', 'twopi', 'circo', 'fdp',
                                   'sfdp', 'patchwork', 'osage'
                               ])
    dirtree = pn.widgets.Checkbox(name='Dirtree', value=False)
    graphviz_btn = pn.widgets.Button(name="Show graph", button_type='primary')

    status_btn = pn.widgets.Button(name="Show status", button_type='primary')
    history_btn = pn.widgets.Button(name="Show history", button_type='primary')
    debug_btn = pn.widgets.Button(name="Debug", button_type='primary')
    events_btn = pn.widgets.Button(name="Events", button_type='primary')
    corrections_btn = pn.widgets.Button(name="Corrections",
                                        button_type='primary')
    handlers_btn = pn.widgets.Button(name="Handlers", button_type='primary')

    vars_text = pn.widgets.TextInput(
        name='Abivars',
        placeholder='Enter list of variables separated by comma')
    vars_btn = pn.widgets.Button(name="Show Variables", button_type='primary')

    dims_btn = pn.widgets.Button(name="Show Dimensions", button_type='primary')

    structures_btn = pn.widgets.Button(name="Show Structures",
                                       button_type='primary')
    structures_io_checkbox = pn.widgets.CheckBoxGroup(
        name='Input/Output Structure',
        value=['output'],
        options=['input', 'output'],
        inline=True)

    # Widgets to plot ebands.
    ebands_btn = pn.widgets.Button(name="Show Ebands", button_type='primary')
    ebands_plotter_mode = pnw.Select(
        name="Plot Mode",
        value="gridplot",
        options=["gridplot", "combiplot", "boxplot",
                 "combiboxplot"])  # "animate",
    ebands_plotter_btn = pnw.Button(name="Plot", button_type='primary')
    ebands_df_checkbox = pnw.Checkbox(name='With Ebands DataFrame',
                                      value=False)
    ebands_ksamp_checkbox = pn.widgets.CheckBoxGroup(
        name='Input/Output Structure',
        value=["with_path", "with_ibz"],
        options=['with_path', 'with_ibz'],
        inline=True)

    #TODO: Implement widget for selected_nids(flow, options),
    #radio_group = pn.widgets.RadioButtonGroup(
    #   name='Radio Button Group', options=['Biology', 'Chemistry', 'Physics'], button_type='success')

    def __init__(self, flow, **params):
        super().__init__(**params)
        self.flow = flow

    @param.depends('status_btn.clicks')
    def on_status_btn(self):
        if self.status_btn.clicks == 0: return
        stream = StringIO()
        self.flow.show_status(stream=stream, verbose=self.verbose.value)
        return pn.Row(bkw.PreText(text=stream.getvalue()))

    @param.depends('history_btn.clicks')
    def on_history_btn(self):
        if self.history_btn.clicks == 0: return
        stream = StringIO()
        #flow.show_history(status=options.task_status, nids=selected_nids(flow, options),
        #                  full_history=options.full_history, metadata=options.metadata)
        self.flow.show_history(stream=stream)
        return pn.Row(bkw.PreText(text=stream.getvalue()))

    @param.depends('graphviz_btn.clicks')
    def on_graphviz_btn(self):
        """
        """
        if self.graphviz_btn.clicks == 0: return
        node = self.flow
        if self.dirtree.value:
            graph = node.get_graphviz_dirtree(engine=self.engine.value)
        else:
            graph = node.get_graphviz(engine=self.engine.value)
        return pn.Column(graph)

    @param.depends('debug_btn.clicks')
    def on_debug_btn(self):
        if self.debug_btn.clicks == 0: return
        #TODO https://github.com/ralphbean/ansi2html ?
        stream = StringIO()
        #flow.debug(status=options.task_status, nids=selected_nids(flow, options))
        self.flow.debug(stream=stream)
        return pn.Row(bkw.PreText(text=stream.getvalue()))

    @param.depends('events_btn.clicks')
    def on_events_btn(self):
        if self.events_btn.clicks == 0: return
        stream = StringIO()
        self.flow.show_events(stream=stream)
        #flow.show_events(status=options.task_status, nids=selected_nids(flow, options))
        return pn.Row(bkw.PreText(text=stream.getvalue()))

    @param.depends('corrections_btn.clicks')
    def on_corrections_btn(self):
        if self.corrections_btn.clicks == 0: return
        stream = StringIO()
        self.flow.show_corrections(stream=stream)
        #flow.show_corrections(status=options.task_status, nids=selected_nids(flow, options))
        return pn.Row(bkw.PreText(text=stream.getvalue()))

    @param.depends('handlers_btn.clicks')
    def on_handlers_btn(self):
        #if self.handlers_btn.clicks == 0: return
        stream = StringIO()
        #if options.doc:
        #    flowtk.autodoc_event_handlers()
        #else:
        #show_events(self, status=None, nids=None, stream=sys.stdout):
        self.flow.show_event_handlers(verbose=self.verbose.value,
                                      stream=stream)
        return pn.Row(bkw.PreText(text=stream.getvalue()))

    @param.depends('vars_btn.clicks')
    def on_vars_btn(self):
        if self.vars_btn.clicks == 0: return
        if not self.vars_text.value: return
        varnames = [s.strip() for s in self.vars_text.value.split(",")]
        df = self.flow.compare_abivars(
            varnames=varnames,  # nids=selected_nids(flow, options),
            printout=False,
            with_colors=False)
        return pn.Row(self._df(df))

    @param.depends('dims_btn.clicks')
    def on_dims_btn(self):
        if self.dims_btn.clicks == 0: return
        df = self.flow.get_dims_dataframe(  # nids=selected_nids(flow, options),
            printout=False,
            with_colors=False)
        return pn.Row(self._df(df), sizing_mode="scale_width")

    @param.depends('structures_btn.clicks')
    def on_structures_btn(self):
        if self.structures_btn.clicks == 0: return
        what = ""
        if "input" in self.structures_io_checkbox.value: what += "i"
        if "output" in self.structures_io_checkbox.value: what += "o"
        dfs = self.flow.compare_structures(
            nids=None,  # select_nids(flow, options),
            what=what,
            verbose=self.verbose.value,
            with_spglib=False,
            printout=False,
            with_colors=False)

        return pn.Row(self._df(dfs.lattice), sizing_mode="scale_width")

    @param.depends('ebands_plotter_btn.clicks')
    def on_ebands_btn(self):
        if self.ebands_plotter_btn.clicks == 0: return

        df, ebands_plotter = self.flow.compare_ebands(
            nids=None,  # select_nids(flow, options),
            with_path="with_path" in self.ebands_ksamp_checkbox.value,
            with_ibz="with_ibz" in self.ebands_ksamp_checkbox.value,
            verbose=self.verbose.value,
            with_spglib=False)

        if ebands_plotter is None:
            return

        plot_mode = self.ebands_plotter_mode.value
        plotfunc = getattr(ebands_plotter, plot_mode, None)
        if plotfunc is None:
            raise ValueError("Don't know how to handle plot_mode: %s" %
                             plot_mode)

        fig = plotfunc(**self.fig_kwargs)
        col = pn.Column(self._mp(fig))
        if self.ebands_df_checkbox.value:
            col.append(self._df(df))

        return pn.Row(col)  #, sizing_mode='scale_width')

    def get_panel(self):
        """Return tabs with widgets to interact with the flow."""
        tabs = pn.Tabs()
        app = tabs.append
        #row = pn.Row(bkw.PreText(text=self.ddb.to_string(verbose=self.verbose.value), sizing_mode="scale_both"))
        app(("Status", pn.Row(self.status_btn, self.on_status_btn)))
        app(("History", pn.Row(self.history_btn, self.on_history_btn)))
        app(("Events", pn.Row(self.events_btn, self.on_events_btn)))
        app(("Corrections",
             pn.Row(self.corrections_btn, self.on_corrections_btn)))
        app(("Handlers", pn.Row(self.handlers_btn, self.on_handlers_btn)))
        app(("Structures",
             pn.Row(
                 pn.Column(self.structures_io_checkbox, self.structures_btn),
                 self.on_structures_btn)))
        ws = pn.Column(self.ebands_plotter_mode, self.ebands_ksamp_checkbox,
                       self.ebands_df_checkbox, self.ebands_plotter_btn)
        app(("Ebands", pn.Row(ws, self.on_ebands_btn)))
        app(("Abivars",
             pn.Row(pn.Column(self.vars_text, self.vars_btn),
                    self.on_vars_btn)))
        app(("Dims", pn.Row(pn.Column(self.dims_btn), self.on_dims_btn)))
        app(("Debug", pn.Row(self.debug_btn, self.on_debug_btn)))
        app(("Graphviz",
             pn.Row(pn.Column(self.engine, self.dirtree, self.graphviz_btn),
                    self.on_graphviz_btn)))
        return tabs
Beispiel #13
0
def predictions_dashboard(path):
    """Dashboard for viewing results from epitopepredict runs."""

    #folder_input = pn.widgets.TextInput(name='path', value='../zaire_test', width=400,width_policy='fit')
    #reload_btn = pn.widgets.Button(name='reload',width=100,button_type='primary')

    names = web.get_file_lists(path)
    if names is None:
        return
    preds = web.get_predictors(path, name=names[0])
    print(preds)
    seqname = pnw.Select(name='name', value=names[0], options=names)
    cutoff_slider = pnw.FloatSlider(name='cutoff',
                                    value=.95,
                                    start=.75,
                                    end=.99,
                                    step=0.01)
    cutoff_method = pnw.Select(name='cutoff method',
                               value='default',
                               options=['default', 'rank'])
    n_select = pnw.FloatSlider(name='n', value=1, start=1, end=8, step=1)
    plot_select = pnw.Select(name='plot view',
                             value='tracks',
                             options=['tracks', 'sequence'])
    table_select = pnw.Select(name='table view',
                              value='promiscuous',
                              options=['promiscuous', 'binders'])
    colorseq_box = pnw.Checkbox(name='color sequences', value=False)

    header = pn.pane.Markdown('__total sequences: %s__' % len(names),
                              css_classes=['main'])
    tables = pn.Tabs(width=900)
    plot = pn.pane.Bokeh(width=800)
    debug = pn.pane.Markdown('test',
                             style={
                                 'font-size': '10pt',
                                 'background-color': 'yellow'
                             })
    summary_plot = pn.pane.Bokeh()
    summary_table_tabs = pn.Tabs()
    recalc_button = pnw.Button(name='recalculate', width=200)

    def update_banner():
        """Update the banner"""

        fullpath = os.path.abspath(path)
        banner = pn.Row(
            pn.pane.Markdown(
                '<h4>epitopepredict: %s</h4> [help](%s) version %s' %
                (fullpath, helppage, __version__),
                css_classes=['divheader'],
                sizing_mode='stretch_width'))
        return banner

    def update_header(target, event):
        names = web.get_file_lists(event.new)
        target.object = "_total sequences: %s_" % str(len(names))
        return

    def callback_getpath(event):
        path = os.path.getcwd()
        folder.value = path

    def update_plot(preds, name, cutoff, n, kind):
        """Plot data view"""

        if kind == 'tracks':
            p = plotting.bokeh_plot_tracks(preds,
                                           name=name,
                                           cutoff=cutoff,
                                           n=n,
                                           width=1000,
                                           title=name)
            plot.object = p
        elif kind == 'sequence':
            p = plotting.bokeh_plot_sequence(preds,
                                             name=name,
                                             cutoff=cutoff,
                                             n=n,
                                             width=1000,
                                             title=name,
                                             color_sequence=colorseq_box.value)
            plot.object = p
        return p

    def update_tables(preds, name, n):
        """Tabular views of results"""

        P = preds[0]
        view = table_select.value
        tables.clear()
        for P in preds:
            if view == 'promiscuous':
                df = P.promiscuous_binders(n=n, name=name)
            else:
                df = P.get_binders(name=name)
            res = df.to_html(classes="tinytable sortable")
            div = '<div class="scrollingArea">%s</div>' % res
            tables.append((P.name, div))
            #tables.append((P.name,pn.pane.HTML('<p>hddsadsadsasda</p>',width=700)))
        return

    def update(event):
        """Update all elements"""

        name = seqname.value
        n = n_select.value
        cutoff = cutoff_slider.value
        kind = plot_select.value
        debug.object = name
        preds = web.get_predictors(path, name=name)
        update_plot(preds, name=name, cutoff=cutoff, n=n, kind=kind)
        update_tables(preds, name, n)
        return

    def update_summary(path):
        """Summary info for folder"""

        data = web.get_summary_tables(path)
        df = pd.concat(data, sort=True).reset_index()
        #plot = plotting.bokeh_summary_plot(df)
        #summary_plot.object = plot
        summary_table_tabs.clear()
        a = web.aggregate_summary(data)
        div = web.get_scrollable_table(a)
        summary_table_tabs.append(('all', div))
        names = list(data.keys())
        for n in names:
            df = data[n]
            res = df.to_html(classes="tinytable sortable")
            div = '<div class="scrollingArea">%s</div>' % res
            summary_table_tabs.append((n, div))
        return

    @pn.depends(seqname.param.value, n_select.param.value)
    def download_link(name, n):
        if preds is None:
            return
        df = preds[0].promiscuous_binders(n=n, name=name)
        df.to_csv()
        return pn.Pane(HTML('<a>download</a>'), width=700)

    info = pn.pane.Markdown(web.get_readme())
    banner = update_banner()
    update_summary(path)
    #reload_btn.param.watch(load_predictors, 'clicks')
    #reload_btn.param.trigger()
    seqname.param.watch(update, 'value')
    cutoff_slider.param.watch(update, 'value')
    n_select.param.watch(update, 'value')
    table_select.param.watch(update, 'value')
    plot_select.param.watch(update, 'value')
    seqname.param.trigger('options', 'value')

    top = pn.Row(header)  #,download_link)
    left = pn.Column(plot, tables, margin=10, sizing_mode='stretch_width')
    right = pn.Column(seqname,
                      cutoff_slider,
                      cutoff_method,
                      n_select,
                      plot_select,
                      table_select,
                      colorseq_box,
                      css_classes=['widget-box'],
                      width=200)
    center = pn.Row(left, right)
    #bottom = pn.Row(table)
    main = pn.Column(top, center)
    summarypane = pn.Column(recalc_button, (pn.Row(summary_table_tabs)))
    tabs = pn.Tabs(('summary', summarypane), ('sequence', main),
                   ('about', info))
    #tabs.append()
    app = pn.Column(banner, tabs, sizing_mode='stretch_width')
    return app
Beispiel #14
0
class PanelWithElectronBands(AbipyParameterized):  #, metaclass=abc.ABCMeta):

    # Bands plot
    with_gaps = pnw.Checkbox(name='Show gaps')
    #ebands_ylims
    #ebands_e0
    # e0: Option used to define the zero of energy in the band structure plot. Possible values:
    #     - `fermie`: shift all eigenvalues to have zero energy at the Fermi energy (`self.fermie`).
    #     -  Number e.g e0=0.5: shift all eigenvalues to have zero energy at 0.5 eV
    #     -  None: Don't shift energies, equivalent to e0=0
    set_fermie_to_vbm = pnw.Checkbox(name="Set Fermie to VBM")

    plot_ebands_btn = pnw.Button(name="Plot e-bands", button_type='primary')

    # DOS plot.
    edos_method = pnw.Select(name="e-DOS method",
                             options=["gaussian", "tetra"])
    edos_step = pnw.Spinner(name='e-DOS step (eV)',
                            value=0.1,
                            step=0.05,
                            start=1e-6,
                            end=None)
    edos_width = pnw.Spinner(name='e-DOS Gaussian broadening (eV)',
                             value=0.2,
                             step=0.05,
                             start=1e-6,
                             end=None)
    plot_edos_btn = pnw.Button(name="Plot e-DOS", button_type='primary')

    # Fermi surface plot.
    fs_viewer = pnw.Select(name="FS viewer",
                           options=["matplotlib", "xcrysden"])
    plot_fermi_surface_btn = pnw.Button(name="Plot Fermi surface",
                                        button_type='primary')

    #@abc.abstractproperty
    #def ebands(self):
    #    """Returns the |ElectronBands| object."""

    def get_plot_ebands_widgets(self):
        """Widgets to plot ebands."""
        return pn.Column(self.with_gaps, self.set_fermie_to_vbm,
                         self.plot_ebands_btn)

    @param.depends('plot_ebands_btn.clicks')
    def on_plot_ebands_btn(self):
        """Button triggering ebands plot."""
        if self.plot_ebands_btn.clicks == 0: return
        if self.set_fermie_to_vbm.value:
            self.ebands.set_fermie_to_vbm()

        fig1 = self.ebands.plot(e0="fermie",
                                ylims=None,
                                with_gaps=self.with_gaps.value,
                                max_phfreq=None,
                                fontsize=8,
                                **self.fig_kwargs)

        fig2 = self.ebands.kpoints.plot(**self.fig_kwargs)
        row = pn.Row(self._mp(fig1),
                     self._mp(fig2))  #, sizing_mode='scale_width')
        text = bkw.PreText(text=self.ebands.to_string(verbose=self.verbose))
        return pn.Column(row, text, sizing_mode='scale_width')

    def get_plot_edos_widgets(self):
        """Widgets to compute e-DOS."""
        return pn.Column(self.edos_method, self.edos_step, self.edos_width,
                         self.plot_edos_btn)

    @param.depends('plot_edos_btn.clicks')
    def on_plot_edos_btn(self):
        """Button triggering edos plot."""
        if self.plot_edos_btn.clicks == 0: return
        edos = self.ebands.get_edos(method=self.edos_method.value,
                                    step=self.edos_step.value,
                                    width=self.edos_width.value)
        fig = edos.plot(**self.fig_kwargs)
        return pn.Row(self._mp(fig), sizing_mode='scale_width')

    def get_plot_fermi_surface_widgets(self):
        """Widgets to compute e-DOS."""
        return pn.Column(self.fs_viewer, self.plot_fermi_surface_btn)

    @param.depends('plot_fermi_surface_btn.clicks')
    def on_plot_fermi_surface_btn(self):
        if self.plot_fermi_surface_btn.clicks == 0: return

        # Cache eb3d
        if hasattr(self, "_eb3d"):
            eb3d = self._eb3d
        else:
            # Build ebands in full BZ.
            eb3d = self._eb3d = self.ebands.get_ebands3d()

        if self.fs_viewer.value == "matplotlib":
            # Use matplotlib to plot isosurfaces corresponding to the Fermi level (default)
            # Warning: requires skimage package, rendering could be slow.
            fig = eb3d.plot_isosurfaces(e0="fermie",
                                        cmap=None,
                                        **self.fig_kwargs)
            return pn.Row(self._mp(fig), sizing_mode='scale_width')

        else:
            raise ValueError("Invalid choice: %s" % self.fs_viewer.value)