Esempio n. 1
0
class _SliderBase(Widget):

    bar_color = param.Color(default="#e6e6e6", doc="""
        Color of the slider bar as a hexidecimal RGB value.""")

    callback_policy = param.ObjectSelector(
        default='continuous', objects=['continuous', 'throttle', 'mouseup'], doc="""
        Policy to determine when slider events are triggered:

        * "continuous": the callback will be executed immediately for each movement of the slider
        * "throttle": the callback will be executed at most every ``callback_throttle`` milliseconds.
        * "mouseup": the callback will be executed only once when the slider is released.
        """)

    callback_throttle = param.Integer(default=200, doc="""
        Number of milliseconds to pause between callback calls as the slider is moved.""")

    direction = param.ObjectSelector(default='ltr', objects=['ltr', 'rtl'],
                                     doc="""
        Whether the slider should go from left-to-right ('ltr') or right-to-left ('rtl')""")

    orientation = param.ObjectSelector(default='horizontal',
                                       objects=['horizontal', 'vertical'], doc="""
        Whether the slider should be oriented horizontally or vertically.""")

    show_value = param.Boolean(default=True, doc="""
        Whether to show the widget value""")

    tooltips = param.Boolean(default=True, doc="""
        Whether the slider handle should display tooltips""")

    _widget_type = _BkSlider

    __abstract = True
Esempio n. 2
0
class CurveExample(hv.streams.Stream):

    color = param.Color(default='#000000', precedence=0)

    element = param.ObjectSelector(default=hv.Curve,
                                   objects=[hv.Curve, hv.Scatter, hv.Area],
                                   precedence=0)

    amplitude = param.Number(default=2, bounds=(2, 5))

    frequency = param.Number(default=2, bounds=(1, 10))

    output = parambokeh.view.Plot()

    def view(self, *args, **kwargs):
        return self.element(
            self.amplitude * np.sin(np.linspace(0, np.pi * self.frequency)),
            vdims=[hv.Dimension('y',
                                range=(-5, 5))])(style=dict(color=self.color))

    def event(self, **kwargs):
        if not self.output or any(k in kwargs for k in ['color', 'element']):
            self.output = hv.DynamicMap(self.view, streams=[self])
        else:
            super(CurveExample, self).event(**kwargs)
Esempio n. 3
0
class _SliderBase(Widget):

    bar_color = param.Color(default="#e6e6e6",
                            doc="""
        Color of the slider bar as a hexidecimal RGB value.""")

    direction = param.ObjectSelector(default='ltr',
                                     objects=['ltr', 'rtl'],
                                     doc="""
        Whether the slider should go from left-to-right ('ltr') or
        right-to-left ('rtl')""")

    orientation = param.ObjectSelector(default='horizontal',
                                       objects=['horizontal', 'vertical'],
                                       doc="""
        Whether the slider should be oriented horizontally or
        vertically.""")

    show_value = param.Boolean(default=True,
                               doc="""
        Whether to show the widget value.""")

    tooltips = param.Boolean(default=True,
                             doc="""
        Whether the slider handle should display tooltips.""")

    _widget_type = _BkSlider

    __abstract = True

    def __init__(self, **params):
        if 'value' in params and 'value_throttled' in self.param:
            params['value_throttled'] = params['value']
        super(_SliderBase, self).__init__(**params)
Esempio n. 4
0
class _SliderBase(Widget):

    bar_color = param.Color(default="#e6e6e6",
                            doc="""
        Color of the slider bar as a hexidecimal RGB value.""")

    direction = param.ObjectSelector(default='ltr',
                                     objects=['ltr', 'rtl'],
                                     doc="""
        Whether the slider should go from left-to-right ('ltr') or right-to-left ('rtl')"""
                                     )

    orientation = param.ObjectSelector(default='horizontal',
                                       objects=['horizontal', 'vertical'],
                                       doc="""
        Whether the slider should be oriented horizontally or vertically.""")

    show_value = param.Boolean(default=True,
                               doc="""
        Whether to show the widget value""")

    tooltips = param.Boolean(default=True,
                             doc="""
        Whether the slider handle should display tooltips""")

    _widget_type = _BkSlider

    __abstract = True
Esempio n. 5
0
class ColorPicker(Widget):

    value = param.Color(default=None, doc="""
        The selected color""")

    _widget_type = _BkColorPicker

    _rename = {'value': 'color', 'name': 'title'}
Esempio n. 6
0
class _SliderBase(Widget):

    bar_color = param.Color(default="#e6e6e6",
                            doc="""
        Color of the slider bar as a hexidecimal RGB value.""")

    direction = param.ObjectSelector(default='ltr',
                                     objects=['ltr', 'rtl'],
                                     doc="""
        Whether the slider should go from left-to-right ('ltr') or
        right-to-left ('rtl').""")

    name = param.String(default=None,
                        doc="""
        The name of the widget. Also used as the label of the widget. If not set,
        the widget has no label.""")

    orientation = param.ObjectSelector(default='horizontal',
                                       objects=['horizontal', 'vertical'],
                                       doc="""
        Whether the slider should be oriented horizontally or
        vertically.""")

    show_value = param.Boolean(default=True,
                               doc="""
        Whether to show the widget value as a label or not.""")

    tooltips = param.Boolean(default=True,
                             doc="""
        Whether the slider handle should display tooltips.""")

    _widget_type = _BkSlider

    __abstract = True

    def __init__(self, **params):
        if 'value' in params and 'value_throttled' in self.param:
            params['value_throttled'] = params['value']
        super().__init__(**params)

    def __repr__(self, depth=0):
        return '{cls}({params})'.format(
            cls=type(self).__name__,
            params=', '.join(param_reprs(self, ['value_throttled'])))

    def _process_property_change(self, msg):
        if config.throttled:
            if "value" in msg:
                del msg["value"]
            if "value_throttled" in msg:
                msg["value"] = msg["value_throttled"]
        return super()._process_property_change(msg)

    def _update_model(self, events, msg, root, model, doc, comm):
        if 'value_throttled' in msg:
            del msg['value_throttled']

        return super()._update_model(events, msg, root, model, doc, comm)
 class _BigDumbParams(param.Parameterized):
     action = param.Action(default_action, allow_None=True)
     array = param.Array(np.array([1.0, 2.0]))
     boolean = param.Boolean(True, allow_None=True)
     callable = param.Callable(default_action, allow_None=True)
     class_selector = param.ClassSelector(int, is_instance=False, allow_None=True)
     color = param.Color("#FFFFFF", allow_None=True)
     composite = param.Composite(["action", "array"], allow_None=True)
     try:
         data_frame = param.DataFrame(
             pd.DataFrame({"A": 1.0, "B": np.arange(5)}), allow_None=True
         )
     except TypeError:
         data_frame = param.DataFrame(pd.DataFrame({"A": 1.0, "B": np.arange(5)}))
     date = param.Date(datetime.now(), allow_None=True)
     date_range = param.DateRange((datetime.min, datetime.max), allow_None=True)
     dict_ = param.Dict({"foo": "bar"}, allow_None=True, doc="dict means dictionary")
     dynamic = param.Dynamic(default=default_action, allow_None=True)
     file_selector = param.FileSelector(
         os.path.join(FILE_DIR_DIR, "LICENSE"),
         path=os.path.join(FILE_DIR_DIR, "*"),
         allow_None=True,
     )
     filename = param.Filename(
         os.path.join(FILE_DIR_DIR, "LICENSE"), allow_None=True
     )
     foldername = param.Foldername(os.path.join(FILE_DIR_DIR), allow_None=True)
     hook_list = param.HookList(
         [CallableObject(), CallableObject()], class_=CallableObject, allow_None=True
     )
     integer = param.Integer(10, allow_None=True)
     list_ = param.List([1, 2, 3], allow_None=True, class_=int)
     list_selector = param.ListSelector([2, 2], objects=[1, 2, 3], allow_None=True)
     magnitude = param.Magnitude(0.5, allow_None=True)
     multi_file_selector = param.MultiFileSelector(
         [],
         path=os.path.join(FILE_DIR_DIR, "*"),
         allow_None=True,
         check_on_set=True,
     )
     number = param.Number(-10.0, allow_None=True, doc="here is a number")
     numeric_tuple = param.NumericTuple((5.0, 10.0), allow_None=True)
     object_selector = param.ObjectSelector(
         False, objects={"False": False, "True": 1}, allow_None=True
     )
     path = param.Path(os.path.join(FILE_DIR_DIR, "LICENSE"), allow_None=True)
     range_ = param.Range((-1.0, 2.0), allow_None=True)
     series = param.Series(pd.Series(range(5)), allow_None=True)
     string = param.String("foo", allow_None=True, doc="this is a string")
     tuple_ = param.Tuple((3, 4, "fi"), allow_None=True)
     x_y_coordinates = param.XYCoordinates((1.0, 2.0), allow_None=True)
Esempio n. 8
0
class StyleApp(param.Parameterized):
    color = param.Color(default="#000000")
    view = param.Parameter()

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

        self._html_pane = pn.pane.HTML(height=100, width=100)
        self.view = pn.Column(self._html_pane, self.param.color)
        self._update_style()

    @param.depends("color", watch=True)
    def _update_style(self, *events):
        self._html_pane.style = {"background-color": self.color}
Esempio n. 9
0
class ColorPicker(Widget):
    """
    The `ColorPicker` widget allows selecting a hexidecimal RGB color value
    using the browser’s color-picking widget.
    
    Reference: https://panel.holoviz.org/reference/widgets/ColorPicker.html

    :Example:

    >>> ColorPicker(name='Color', value='#99ef78')
    """

    value = param.Color(default=None, doc="""
        The selected color""")

    _widget_type = _BkColorPicker

    _rename = {'value': 'color', 'name': 'title'}
Esempio n. 10
0
    class Example(BaseClass):
        """An example Parameterized class"""

        timestamps = []

        boolean = param.Boolean(True, doc="A sample Boolean parameter")
        color = param.Color(default="#FFFFFF")
        date = param.Date(dt.date(2017, 1, 1), bounds=wired.DATE_BOUNDS)
        dataframe = param.DataFrame(pd.util.testing.makeDataFrame().iloc[:3])
        select_string = param.ObjectSelector(default="yellow", objects=["red", "yellow", "green"])
        select_fn = param.ObjectSelector(default=list, objects=[list, set, dict])
        int_list = param.ListSelector(default=[3, 5], objects=[1, 3, 5, 7, 9], precedence=0.5)
        single_file = param.FileSelector(path="../../*/*.py*", precedence=0.5)
        multiple_files = param.MultiFileSelector(path="../../*/*.py?", precedence=0.5)
        record_timestamp = param.Action(
            lambda x: x.timestamps.append(dt.datetime.utcnow()),
            doc="""Record timestamp.""",
            precedence=0.7,
        )
Esempio n. 11
0
class Notification(param.Parameterized):

    background = param.Color(default=None)

    duration = param.Integer(default=3000, constant=True)

    icon = param.String(default=None)

    message = param.String(default='', constant=True)

    notification_area = param.Parameter(constant=True, precedence=-1)

    notification_type = param.String(default=None, constant=True, label='type')

    _destroyed = param.Boolean(default=False)

    def destroy(self):
        from .notebook import push_on_root
        self._destroyed = True
        for ref in self.notification_area._models:
            push_on_root(ref)
Esempio n. 12
0
    class MyParameterized(param.Parameterized):
        enable = param.Boolean(True,
                               doc="A sample Boolean parameter",
                               allow_None=True)
        what_proportion = param.Magnitude(default=0.9)
        age = param.Number(49,
                           bounds=(0, 100),
                           doc="Any Number between 0 to 100")
        how_many = param.Integer()
        favorite_quote = param.String(default="Hello, world!")

        choose_file_or_folder = param.Path(search_paths='./')
        choose_folder = param.Foldername(search_paths="./")
        choose_file = param.Filename(search_paths="./")
        select_a_file = param.FileSelector(path='./*')
        select_multiple_files = param.MultiFileSelector(path='./*')

        favorite_color = param.ObjectSelector(
            default="green", objects=["red", "yellow", "green"])
        favorite_fruit = param.Selector(default="Apple",
                                        objects=["Orange", "Apple", "Mango"])
        select_multiple = param.ListSelector(default=[3, 5],
                                             objects=[1, 2, 3, 4, 5])

        birthday = param.CalendarDate(dt.date(2017, 1, 1),
                                      bounds=(dt.date(2017, 1,
                                                      1), dt.date(2017, 2, 1)))
        appointment = param.Date(dt.datetime(2017, 1, 1),
                                 bounds=(dt.datetime(2017, 1, 1),
                                         dt.datetime(2017, 2, 1)))
        least_favorite_color = param.Color(default='#FF0000')
        dataset = param.DataFrame(pd.util.testing.makeDataFrame().iloc[:3])

        this_strange_thing = param.Tuple(default=(False, ), allow_None=True)
        some_numbers = param.NumericTuple(default=(1, 2, 3.0, 4.0))
        home_city = param.XYCoordinates(default=(-111.65, 40.23))
        bounds = param.Range(default=(-10, 10))
Esempio n. 13
0
class link_selections(_base_link_selections):
    """
    Operation which automatically links selections between elements
    in the supplied HoloViews object. Can be used a single time or
    be used as an instance to apply the linked selections across
    multiple objects.
    """

    cross_filter_mode = param.Selector(['overwrite', 'intersect'],
                                       default='intersect',
                                       doc="""
        Determines how to combine selections across different
        elements.""")

    index_cols = param.List(default=None,
                            doc="""
        If provided, selection switches to index mode where all queries
        are expressed solely in terms of discrete values along the
        index_cols.  All Elements given to link_selections must define the index_cols, either as explicit dimensions or by sharing an underlying Dataset that defines them."""
                            )

    selection_expr = param.Parameter(default=None,
                                     doc="""
        dim expression of the current selection or None to indicate
        that everything is selected.""")

    selected_color = param.Color(default=None,
                                 allow_None=True,
                                 doc="""
        Color of selected data, or None to use the original color of
        each element.""")

    selection_mode = param.Selector(
        ['overwrite', 'intersect', 'union', 'inverse'],
        default='overwrite',
        doc="""
        Determines how to combine successive selections on the same
        element.""")

    unselected_alpha = param.Magnitude(default=0.1,
                                       doc="""
        Alpha of unselected data.""")

    unselected_color = param.Color(default=None,
                                   doc="""
        Color of unselected data.""")

    @bothmethod
    def instance(self_or_cls, **params):
        inst = super(link_selections, self_or_cls).instance(**params)

        # Initialize private properties
        inst._obj_selections = {}
        inst._obj_regions = {}
        inst._reset_regions = True

        # _datasets caches
        inst._datasets = []
        inst._cache = {}

        self_or_cls._install_param_callbacks(inst)

        return inst

    @param.depends('selection_expr', watch=True)
    def _update_pipes(self):
        sel_expr = self.selection_expr
        for pipe, ds, raw in self._datasets:
            ref = ds._plot_id
            self._cache[ref] = ds_cache = self._cache.get(ref, {})
            if sel_expr in ds_cache:
                data = ds_cache[sel_expr]
                return pipe.event(data=data.data)
            else:
                ds_cache.clear()
            sel_ds = SelectionDisplay._select(ds, sel_expr, self._cache)
            ds_cache[sel_expr] = sel_ds
            pipe.event(data=sel_ds.data if raw else sel_ds)

    def selection_param(self, data):
        """
        Returns a parameter which reflects the current selection
        when applied to the supplied data, making it easy to create
        a callback which depends on the current selection.

        Args:
            data: A Dataset type or data which can be cast to a Dataset

        Returns:
            A parameter which reflects the current selection
        """
        raw = False
        if not isinstance(data, Dataset):
            raw = True
            data = Dataset(data)
        pipe = Pipe(data=data.data)
        self._datasets.append((pipe, data, raw))
        return pipe.param.data

    @bothmethod
    def _install_param_callbacks(self_or_cls, inst):
        def update_selection_mode(*_):
            # Reset selection state of streams
            for stream in inst._selection_expr_streams.values():
                stream.reset()
                stream.mode = inst.selection_mode

        inst.param.watch(update_selection_mode, ['selection_mode'])

        def update_cross_filter_mode(*_):
            inst._cross_filter_stream.reset()
            inst._cross_filter_stream.mode = inst.cross_filter_mode

        inst.param.watch(update_cross_filter_mode, ['cross_filter_mode'])

        def update_show_region(*_):
            for stream in inst._selection_expr_streams.values():
                stream.include_region = inst.show_regions
                stream.event()

        inst.param.watch(update_show_region, ['show_regions'])

        def update_selection_expr(*_):
            new_selection_expr = inst.selection_expr
            current_selection_expr = inst._cross_filter_stream.selection_expr
            if repr(new_selection_expr) != repr(current_selection_expr):
                # Disable regions if setting selection_expr directly
                if inst.show_regions:
                    inst.show_regions = False
                inst._selection_override.event(
                    selection_expr=new_selection_expr)

        inst.param.watch(update_selection_expr, ['selection_expr'])

        def selection_expr_changed(*_):
            new_selection_expr = inst._cross_filter_stream.selection_expr
            if repr(inst.selection_expr) != repr(new_selection_expr):
                inst.selection_expr = new_selection_expr

        inst._cross_filter_stream.param.watch(selection_expr_changed,
                                              ['selection_expr'])

        # Clear selection expr sequence history on plot reset
        for stream in inst._selection_expr_streams.values():

            def clear_stream_history(resetting, stream=stream):
                if resetting:
                    stream.clear_history()

            print("registering reset for ", stream)
            stream.plot_reset_stream.param.watch(clear_stream_history,
                                                 ['resetting'])

    @classmethod
    def _build_selection_streams(cls, inst):
        # Colors stream
        style_stream = _Styles(
            colors=[inst.unselected_color, inst.selected_color],
            alpha=inst.unselected_alpha)

        # Cmap streams
        cmap_streams = [
            _Cmap(cmap=inst.unselected_cmap),
            _Cmap(cmap=inst.selected_cmap),
        ]

        def update_colors(*_):
            colors = [inst.unselected_color, inst.selected_color]
            style_stream.event(colors=colors, alpha=inst.unselected_alpha)
            cmap_streams[0].event(cmap=inst.unselected_cmap)
            if cmap_streams[1] is not None:
                cmap_streams[1].event(cmap=inst.selected_cmap)

        inst.param.watch(
            update_colors,
            ['unselected_color', 'selected_color', 'unselected_alpha'])

        # Exprs stream
        exprs_stream = _SelectionExprLayers(inst._selection_override,
                                            inst._cross_filter_stream)

        return _SelectionStreams(
            style_stream=style_stream,
            exprs_stream=exprs_stream,
            cmap_streams=cmap_streams,
        )

    @property
    def unselected_cmap(self):
        """
        The datashader colormap for unselected data
        """
        if self.unselected_color is None:
            return None
        return _color_to_cmap(self.unselected_color)

    @property
    def selected_cmap(self):
        """
        The datashader colormap for selected data
        """
        return None if self.selected_color is None else _color_to_cmap(
            self.selected_color)
Esempio n. 14
0
File: pane.py Progetto: Jhsmit/PyHDX
class PDBeMolStar(ReactiveHTML):
    """PDBe MolStar structure viewer.

    Set one of `molecule_id`, `custom_data` and `ligand_view`.

    For more information:

    - https://github.com/PDBeurope/pdbe-molstar/wiki
    - https://molstar.org/


    The implementation is based on the JS Plugin. See
    - https://github.com/PDBeurope/pdbe-molstar/wiki/1.-PDBe-Molstar-as-JS-plugin
    For documentation on the helper methods:
    - https://github.com/molstar/pdbe-molstar/wiki/3.-Helper-Methods

    """

    molecule_id = param.String(default=None,
                               doc="PDB id to load. Example: '1qyn' or '1cbs'")

    custom_data = param.Dict(
        doc="""Load data from a specific data source. Example: 
        { "url": "https://www.ebi.ac.uk/pdbe/coordinates/1cbs/chains?entityId=1&asymId=A&encoding=bcif", "format": "cif", "binary": True }
        """)

    ligand_view = param.Dict(
        doc=
        """This option can be used to display the PDBe ligand page 3D view like https://www.ebi.ac.uk/pdbe/entry/pdb/1cbs/bound/REA.
        Example: {"label_comp_id": "REA"}
        """)

    alphafold_view = param.Boolean(
        default=False,
        doc=
        "Applies AlphaFold confidence score colouring theme for alphafold model"
    )

    assembly_id = param.String(doc="Specify assembly")

    # Todo: figure out if `background` could/ should be used
    bg_color = param.Color(
        "#F7F7F7",
        doc=
        "Color of the background. If `None`, colors default is chosen depending on the color theme",
    )

    highlight_color = param.Color(default="#ff6699",
                                  doc="Color for mouseover highlighting")

    select_color = param.Color(default="#0c0d11", doc="Color for selections")

    visual_style = param.Selector(default=None,
                                  objects=[None, *REPRESENTATIONS],
                                  doc="Visual styling")

    # Todo: Determine if it should be default or light theme
    theme = param.Selector(default="default",
                           objects=["default", "dark"],
                           doc="CSS theme to use")

    hide_polymer = param.Boolean(default=False, doc="Hide polymer")

    hide_water = param.Boolean(default=False, doc="Hide water")

    hide_heteroatoms = param.Boolean(default=False, doc="Hide het")

    hide_carbs = param.Boolean(default=False, doc="Hide carbs")

    hide_non_standard = param.Boolean(default=False, doc="Hide non standard")

    hide_coarse = param.Boolean(default=False, doc="Hide coarse")

    hide_controls_icon = param.Boolean(default=False,
                                       doc="Hide the control menu")

    hide_expand_icon = param.Boolean(default=False, doc="Hide the expand icon")

    hide_settings_icon = param.Boolean(default=False,
                                       doc="Hide the settings menu")

    hide_selection_icon = param.Boolean(
        default=False,
        doc="Hide the selection icon"  # Default False, set False/True for True
    )

    # Todo requires testing with a trajectory file
    hide_animation_icon = param.Boolean(default=False,
                                        doc="Hide the animation icon")

    pdbe_url = param.String(
        default=None,
        constant=True,
        doc="Url for PDB data. Mostly used for internal testing")

    load_maps = param.Boolean(
        default=False,
        doc="Load electron density maps from the pdb volume server")

    validation_annotation = param.Boolean(
        default=False, doc="Adds 'annotation' control in the menu")

    domain_annotation = param.Boolean(
        default=False, doc="Adds 'annotation' control in the menu")

    low_precision_coords = param.Boolean(
        default=False,
        doc="Load low precision coordinates from the model server")

    hide_controls = param.Boolean(default=True, doc="Hide the control menu")

    expanded = param.Boolean(default=False,
                             doc="""Display full-screen by default on load""")

    landscape = param.Boolean(
        default=
        True,  # Changed to True because it works best with Panel currently
        doc=
        """Set landscape view. The controls will similar to the full-screen view""",
    )

    select_interaction = param.Boolean(
        default=True,
        doc="Switch on or off the default selection interaction behaviour")

    lighting = param.Selector(
        default="matte",
        objects=["flat", "matte", "glossy", "metallic", "plastic"],
        doc="Set the lighting",
    )

    default_preset = param.Selector(
        default="default",
        objects=["default", "unitcell", "all-models", "supercell"],
        doc="Set the preset view",
    )

    pdbe_link = param.Boolean(
        default=True,
        doc="Show the PDBe entry link at in the top right corner")

    spin = param.Boolean(default=False, doc="Toggle spin")

    _clear_highlight = param.Boolean(
        doc="Event to trigger clearing of highlights")

    _select = param.Dict(
        doc="Dictionary used for selections and coloring these selections")

    _clear_selection = param.Boolean(doc="Clear selection event trigger")

    _highlight = param.Dict(
        doc="Dictionary used for selections and coloring these selections")

    _reset = param.Boolean(doc="Reset event trigger")

    _args = param.Dict(doc="Dictionary with function call arguments")

    test = param.Boolean(default=False)

    _template = """
<link id="molstarTheme" rel="stylesheet" type="text/css" href="https://www.ebi.ac.uk/pdbe/pdb-component-library/css/pdbe-molstar-1.2.1.css"/>
<div id="container" style="width:100%; height: 100%;"><div id="pdbeViewer"></div></div>
"""
    __javascript__ = [
        "https://www.ebi.ac.uk/pdbe/pdb-component-library/js/pdbe-molstar-plugin-1.2.1.js",
    ]

    _scripts = {
        "render": """
        function standardize_color(str){
            var ctx = document.createElement("canvas").getContext("2d");
            ctx.fillStyle = str;
            return ctx.fillStyle;
        }
        function toRgb(color) {
          var hex = standardize_color(color)
          var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
          return result ? {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16)
          } : null;
        }
        state.toRgb = toRgb

        function getHideStructure(){
            var hideStructure = [];

            if (data.hide_polymer){
                hideStructure.push("polymer")
            }
            if (data.hide_water){
                hideStructure.push("water")
            }
            if (data.hide_heteroatoms){
                hideStructure.push("het")
            }
            if (data.hide_carbs){
                hideStructure.push("carbs")
            }
            if (data.hide_non_standard){
                hideStructure.push("nonStandard")
            }
            if (data.hide_coarse){
                hideStructure.push("coarse")
            }

            return hideStructure
        }

        function getHideCanvasControls(){
            var hideCanvasControls = [];
            if (data.hide_controls_icon){
                hideCanvasControls.push("controlToggle")
            }
            if (data.hide_expand_icon){
                hideCanvasControls.push("expand")
            }
            if (data.hide_settings_icon){
                hideCanvasControls.push("controlInfo")
            }
            if (data.hide_selection_icon){
                hideCanvasControls.push('selection')
            }
            if (data.hide_animation_icon){
                hideCanvasControls.push("animation")
            }

            return hideCanvasControls
        }

        state.getHideCanvasControls = getHideCanvasControls

        function getOptions(){
            var options = {
                moleculeId: data.molecule_id,
                customData: data.custom_data,
                ligandView: data.ligand_view,
                alphafoldView: data.alphafold_view,
                assemblyId: data.assembly_id,
                bgColor: toRgb(data.bg_color),
                highlightColor: toRgb(data.highlight_color),
                selectColor: toRgb(data.select_color),
                hideStructure: getHideStructure(),
                hideCanvasControls: getHideCanvasControls(),
                loadMaps: data.load_maps,
                validationAnnotation: data.validation_annotation,
                domainAnnotation: data.domain_annotation,
                lowPrecisionCoords: data.low_precision_coords,
                expanded: data.expanded,
                hideControls: data.hide_controls,
                landscape: data.landscape,
                selectInteraction: data.select_interaction,
                lighting: data.lighting,
                defaultPreset: data.default_preset,
                pdbeLink: data.pdbe_link,
            }
            if (data.visual_style!==null){
                options["visualStyle"]=data.visual_style
            }
            if (data.pdbe_url!==null){
                options["pdbeUrl"]=data.pdbe_url
            }
            return options
        }
        state.getOptions=getOptions
        self.theme()

        state.viewerInstance = new PDBeMolstarPlugin();
        state.viewerInstance.render(pdbeViewer, state.getOptions());

        """,
        "rerender": """
        state.viewerInstance.visual.update(state.getOptions(), fullLoad=true)
        """,
        "molecule_id": """self.rerender()""",
        "custom_data": """self.rerender()""",
        "ligand_view": """self.rerender()""",
        "alphafold_view": """self.rerender()""",
        "assembly_id": """self.rerender()""",
        "visual_style": """self.rerender()""",
        "bg_color":
        "state.viewerInstance.canvas.setBgColor(state.toRgb(data.bg_color))",
        "highlight_color": """
        state.viewerInstance.visual.setColor({highlight: state.toRgb(data.highlight_color)})""",
        "select_color": """
        state.viewerInstance.visual.setColor({select: state.toRgb(data.select_color)})""",
        "theme": """
        if (data.theme==="dark"){
            molstarTheme.href="https://www.ebi.ac.uk/pdbe/pdb-component-library/css/pdbe-molstar-1.2.1.css"
        } else {
            molstarTheme.href="https://www.ebi.ac.uk/pdbe/pdb-component-library/css/pdbe-molstar-light-1.2.1.css"
        }
        """,
        "hide_polymer":
        "state.viewerInstance.visual.visibility({polymer:!data.hide_polymer})",
        "hide_water":
        "state.viewerInstance.visual.visibility({water:!data.hide_water})",
        "hide_heteroatoms":
        "state.viewerInstance.visual.visibility({het:!data.hide_heteroatoms})",
        "hide_carbs":
        "state.viewerInstance.visual.visibility({carbs:!data.hide_carbs})",
        "hide_non_standard":
        "state.viewerInstance.visual.visibility({nonStandard:!data.hide_non_standard})",
        "hide_coarse":
        "state.viewerInstance.visual.visibility({coarse:!data.hide_coarse})",
        "hide_controls_icon": """self.rerender()""",
        "hide_expand_icon": """self.rerender()""",
        "hide_settings_icon": """self.rerender()""",
        "hide_selection_icon": """self.rerender()""",
        "hide_animation_icon": """self.rerender()""",
        "load_maps": "self.rerender()",
        "validation_annotation": """self.rerender()""",
        "domain_annotation": """self.rerender()""",
        "low_precision_coords": """self.rerender()""",
        "expanded":
        "state.viewerInstance.canvas.toggleExpanded(data.expanded)",
        "landscape": """self.rerender()""",
        "select_interaction": """self.rerender()""",
        "lighting": """self.rerender()""",
        "default_preset": """self.rerender()""",
        "pdbe_link": """self.rerender()""",
        "hide_controls":
        "state.viewerInstance.canvas.toggleControls(!data.hide_controls);",
        "spin": """state.viewerInstance.visual.toggleSpin(data.spin);""",
        "_select": """
        console.log(data._select);
        if(data._select) {
        state.viewerInstance.visual.select(data._select);
        }
        """,
        "_clear_selection": """
        state.viewerInstance.visual.clearSelection(data._args['number']);
        """,
        "_highlight": """
        if(data._highlight) {
            state.viewerInstance.visual.highlight(data._highlight);
        };           
        """,
        "_clear_highlight": """
        state.viewerInstance.visual.clearHighlight();
        """,
        "_reset": """
        state.viewerInstance.visual.reset(data._args['data'])""",
        "resize": "state.viewerInstance.canvas.handleResize()",
    }

    def color(self, data, non_selected_color=None):
        """
        Alias for PDBE Molstar's `select` method.

        See https://github.com/molstar/pdbe-molstar/wiki/3.-Helper-Methods for parameter
        details

        :param data: List of dicts
        :param non_selected_color: Dict of color example: {'r':255, 'g':215, 'b': 0}
        :return: None
        """

        self._select = {"data": data, "nonSelectedColor": non_selected_color}
        self._select = None

    def clear_selection(self, structure_number=None):
        """
        Clear selection

        See https://github.com/molstar/pdbe-molstar/wiki/3.-Helper-Methods for parameter
        details.

        :param structure_number: Optional integer to specify structure number
        :return:
        """

        self._args = {"number": structure_number}
        self._clear_selection = not self._clear_selection

    def highlight(self, data):
        """
        Trigger highlight

        See https://github.com/molstar/pdbe-molstar/wiki/3.-Helper-Methods for parameter
        details.

        :param data: List of dicts
        :return: None
        """

        self._highlight = {"data": data}
        self._highlight = None

    def clear_highlight(self):
        """Clears the current highlight"""
        self._clear_highlight = not self._clear_highlight

    def reset(self, data):
        """
        Reset to defaults

        See https://github.com/molstar/pdbe-molstar/wiki/3.-Helper-Methods for parameter
        details.

        :param data: Dictionary of options to reset to defaults
        :return:
        """

        self._args = {"data": data}
        self._reset = not self._reset

    def _load_complete(self, event):
        print('aww yeah')
class Stylesheet(pn.pane.HTML):
    """The Material `Stylesheet` can be included in your app
if you want to have customized styles for your widgets and panes.

The styles are based on [Material Design](https://material.io/design) and the
[MWC](https://github.com/material-components/material-components-web-components) implementation.

As an example you can set the `primary_color` and this corresponds to the `--mdc-theme-primary`
css value.

The Stylesheet `.editor` parameter provides an interactive stylesheet editor.
"""

    primary_color = param.Color(default="#4caf50")
    primary_on_color = param.Color(default="#000000")

    secondary_color = param.Color(default="#9c27b0")
    secondary_on_color = param.Color(default="#ffffff")

    error_color = param.Color(default="#f44336")
    error_on_color = param.Color(default="#000000")

    reset_to_defaults = param.Action()

    editor = param.Parameter(doc="An interactive style editor component")

    # Needed for inheritance to work
    priority = 0
    _rename = {**pn.pane.HTML._rename, **_STYLEPANE_RENAME}

    def __init__(self, **params):
        params["height"] = 0
        params["width"] = 0
        params["sizing_mode"] = "fixed"
        params["margin"] = 0
        super().__init__(**params)

        self.editor = pn.WidgetBox(pn.Param(
            self,
            parameters=(_SETTINGS_PARAMETERS),
        ),
                                   name="Material StyleSheet Editor")
        self.reset_to_defaults = self._reset_to_defaults

        self._handle_style_parameter_change()

    # Don't name the function
    # `_update`, `_update_object_from_parameters`, `_update_model` or `_update_pane`
    # as this will override a function in the parent class.
    @param.depends(*_STYLE_PARAMETERS, watch=True)
    def _handle_style_parameter_change(self, *_):
        self.object = f"""
<style>
:root {{
  --mdc-theme-primary: {self.primary_color};
  --mdc-theme-on-primary: {self.primary_on_color};
  --mdc-theme-secondary: {self.secondary_color};
  --mdc-theme-on-secondary: {self.secondary_on_color};
  --mdc-theme-error: {self.error_color};
  --mdc-theme-on-error: {self.error_on_color};

  --mdc-typography-button-font-size: 1.33rem;
}}
body {{
    font-family: roboto;
    font-size: 14px;
}}
mwc-circular-progress {{
    margin-left: auto;
    margin-right: auto;
    display: block;
}}

mwc-button.secondary,
mwc-linear-progress.secondary,
mwc-circular-progress.secondary
{{
    --mdc-theme-primary: {self.secondary_color};
    --mdc-theme-on-primary: {self.secondary_on_color};
}}
mwc-button.warning, mwc-button.danger,
mwc-linear-progress.warning, mwc-linear-progress.danger,
mwc-circular-progress.warning, mwc-circular-progress.danger
{{
    --mdc-theme-primary: {self.error_color};
    --mdc-theme-on-primary: {self.error_on_color};
}}
mwc-button.light,
mwc-linear-progress.light,
mwc-circular-progress.light
{{
    --mdc-theme-primary: #fafafa;
    --mdc-theme-on-primary: black;
}}
mwc-button.dark,
mwc-linear-progress.dark,
mwc-circular-progress.dark
{{
    --mdc-theme-primary: #212121;
    --mdc-theme-on-primary: white;
}}
</style>
"""

    def _reset_to_defaults(self, *_):
        defaults = {p: self.param[p].default for p in _STYLE_PARAMETERS}
        self.param.set_param(**defaults)

    # Needed to avoid infinite recursion
    def __str__(self):
        return "Stylesheet()"

    def __repr__(self, depth=0):  # pylint: disable=unused-argument
        return "Stylesheet()"
Esempio n. 16
0
class link_selections(_base_link_selections):
    selection_expr = param.Parameter(default=None)
    unselected_color = param.Color(default="#99a6b2")  # LightSlateGray - 65%
    selected_color = param.Color(default="#DC143C")  # Crimson

    @classmethod
    def _build_selection_streams(cls, inst):
        # Colors stream
        colors_stream = _Colors(
            colors=[inst.unselected_color, inst.selected_color])

        # Cmap streams
        cmap_streams = [
            _Cmap(cmap=inst.unselected_cmap),
            _Cmap(cmap=inst.selected_cmap),
        ]

        def update_colors(*_):
            colors_stream.event(
                colors=[inst.unselected_color, inst.selected_color])
            cmap_streams[0].event(cmap=inst.unselected_cmap)
            cmap_streams[1].event(cmap=inst.selected_cmap)

        inst.param.watch(
            update_colors,
            parameter_names=['unselected_color', 'selected_color'])

        # Exprs stream
        exprs_stream = _Exprs(exprs=[True, None])

        def update_exprs(*_):
            exprs_stream.event(exprs=[True, inst.selection_expr])

        inst.param.watch(update_exprs, parameter_names=['selection_expr'])

        # Alpha streams
        alpha_streams = [
            _Alpha(alpha=255),
            _Alpha(alpha=inst._selected_alpha),
        ]

        def update_alphas(*_):
            alpha_streams[1].event(alpha=inst._selected_alpha)

        inst.param.watch(update_alphas, parameter_names=['selection_expr'])

        return _SelectionStreams(
            colors_stream=colors_stream,
            exprs_stream=exprs_stream,
            alpha_streams=alpha_streams,
            cmap_streams=cmap_streams,
        )

    @property
    def unselected_cmap(self):
        """
        The datashader colormap for unselected data
        """
        return _color_to_cmap(self.unselected_color)

    @property
    def selected_cmap(self):
        """
        The datashader colormap for selected data
        """
        return _color_to_cmap(self.selected_color)

    @property
    def _selected_alpha(self):
        if self.selection_expr:
            return 255
        else:
            return 0

    def _expr_stream_updated(self, hvobj, selection_expr, bbox):
        if selection_expr:
            self.selection_expr = selection_expr
Esempio n. 17
0
class _config(_base_config):
    """
    Holds global configuration options for Panel. The options can be
    set directly on the global config instance, via keyword arguments
    in the extension or via environment variables. For example to set
    the embed option the following approaches can be used:

        pn.config.embed = True

        pn.extension(embed=True)

        os.environ['PANEL_EMBED'] = 'True'
    """

    apply_signatures = param.Boolean(default=True,
                                     doc="""
        Whether to set custom Signature which allows tab-completion
        in some IDEs and environments.""")

    autoreload = param.Boolean(default=False,
                               doc="""
        Whether to autoreload server when script changes.""")

    loading_spinner = param.Selector(
        default='arcs',
        objects=['arc', 'arcs', 'bar', 'dots', 'petal'],
        doc="""
        Loading indicator to use when component loading parameter is set.""")

    loading_color = param.Color(default='#c3c3c3',
                                doc="""
        Color of the loading indicator.""")

    loading_max_height = param.Integer(default=400,
                                       doc="""
        Maximum height of the loading indicator.""")

    notifications = param.Boolean(default=False,
                                  doc="""
        Whether to enable notifications functionality.""")

    profiler = param.Selector(default=None,
                              allow_None=True,
                              objects=['pyinstrument', 'snakeviz'],
                              doc="""
        The profiler engine to enable.""")

    safe_embed = param.Boolean(default=False,
                               doc="""
        Ensure all bokeh property changes trigger events which are
        embedded. Useful when only partial updates are made in an
        app, e.g. when working with HoloViews.""")

    session_history = param.Integer(default=0,
                                    bounds=(-1, None),
                                    doc="""
        If set to a non-negative value this determines the maximum length
        of the pn.state.session_info dictionary, which tracks
        information about user sessions. A value of -1 indicates an
        unlimited history.""")

    sizing_mode = param.ObjectSelector(default=None,
                                       objects=[
                                           'fixed', 'stretch_width',
                                           'stretch_height', 'stretch_both',
                                           'scale_width', 'scale_height',
                                           'scale_both', None
                                       ],
                                       doc="""
        Specify the default sizing mode behavior of panels.""")

    template = param.ObjectSelector(default=None,
                                    doc="""
        The default template to render served applications into.""")

    theme = param.ObjectSelector(default='default',
                                 objects=['default', 'dark'],
                                 doc="""
        The theme to apply to the selected global template.""")

    throttled = param.Boolean(default=False,
                              doc="""
        If sliders and inputs should be throttled until release of mouse.""")

    _admin = param.Boolean(default=False,
                           doc="Whether the admin panel was enabled.")

    _comms = param.ObjectSelector(
        default='default',
        objects=['default', 'ipywidgets', 'vscode', 'colab'],
        doc="""
        Whether to render output in Jupyter with the default Jupyter
        extension or use the jupyter_bokeh ipywidget model.""")

    _console_output = param.ObjectSelector(
        default='accumulate',
        allow_None=True,
        objects=['accumulate', 'replace', 'disable', False],
        doc="""
        How to log errors and stdout output triggered by callbacks
        from Javascript in the notebook.""")

    _cookie_secret = param.String(default=None,
                                  doc="""
        Configure to enable getting/setting secure cookies.""")

    _embed = param.Boolean(default=False,
                           allow_None=True,
                           doc="""
        Whether plot data will be embedded.""")

    _embed_json = param.Boolean(default=False,
                                doc="""
        Whether to save embedded state to json files.""")

    _embed_json_prefix = param.String(default='',
                                      doc="""
        Prefix for randomly generated json directories.""")

    _embed_load_path = param.String(default=None,
                                    doc="""
        Where to load json files for embedded state.""")

    _embed_save_path = param.String(default='./',
                                    doc="""
        Where to save json files for embedded state.""")

    _log_level = param.Selector(
        default='WARNING',
        objects=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
        doc="Log level of Panel loggers")

    _nthreads = param.Integer(default=None,
                              doc="""
        When set to a non-None value a thread pool will be started.
        Whenever an event arrives from the frontend it will be
        dispatched to the thread pool to be processed.""")

    _oauth_provider = param.ObjectSelector(default=None,
                                           allow_None=True,
                                           objects=[],
                                           doc="""
        Select between a list of authentification providers.""")

    _oauth_expiry = param.Number(default=1,
                                 bounds=(0, None),
                                 doc="""
        Expiry of the OAuth cookie in number of days.""")

    _oauth_key = param.String(default=None,
                              doc="""
        A client key to provide to the OAuth provider.""")

    _oauth_secret = param.String(default=None,
                                 doc="""
        A client secret to provide to the OAuth provider.""")

    _oauth_jwt_user = param.String(default=None,
                                   doc="""
        The key in the ID JWT token to consider the user.""")

    _oauth_redirect_uri = param.String(default=None,
                                       doc="""
        A redirect URI to provide to the OAuth provider.""")

    _oauth_encryption_key = param.ClassSelector(default=None,
                                                class_=bytes,
                                                doc="""
        A random string used to encode OAuth related user information.""")

    _oauth_extra_params = param.Dict(default={},
                                     doc="""
        Additional parameters required for OAuth provider.""")

    _inline = param.Boolean(default=_LOCAL_DEV_VERSION,
                            allow_None=True,
                            doc="""
        Whether to inline JS and CSS resources. If disabled, resources
        are loaded from CDN if one is available.""")

    _globals = [
        'autoreload', 'comms', 'cookie_secret', 'nthreads', 'oauth_provider',
        'oauth_expiry', 'oauth_key', 'oauth_secret', 'oauth_jwt_user',
        'oauth_redirect_uri', 'oauth_encryption_key', 'oauth_extra_params'
    ]

    _truthy = ['True', 'true', '1', True, 1]

    _session_config = WeakKeyDictionary()

    def __init__(self, **params):
        super().__init__(**params)
        self._validating = False
        for p in self.param:
            if p.startswith('_') and p[1:] not in self._globals:
                setattr(self, p + '_', None)
        if self.log_level:
            panel_log_handler.setLevel(self.log_level)

    @param.depends('_nthreads', watch=True, on_init=True)
    def _set_thread_pool(self):
        from .io.state import state
        if self.nthreads is None:
            if state._thread_pool is not None:
                state._thread_pool.shutdown(wait=False)
            state._thread_pool = None
            return
        if state._thread_pool:
            raise RuntimeError("Thread pool already running")
        threads = self.nthreads if self.nthreads else None
        state._thread_pool = ThreadPoolExecutor(max_workers=threads)

    @param.depends('notifications', watch=True)
    def _enable_notifications(self):
        from .io.notifications import NotificationArea
        from .io.state import state
        if not state.curdoc:
            state._notification = NotificationArea()

    @contextmanager
    def set(self, **kwargs):
        values = [(k, v) for k, v in self.param.values().items()
                  if k != 'name']
        overrides = [(k, getattr(self, k + '_')) for k in self.param
                     if k.startswith('_') and k[1:] not in self._globals]
        for k, v in kwargs.items():
            setattr(self, k, v)
        try:
            yield
        finally:
            self.param.update(**dict(values))
            for k, v in overrides:
                setattr(self, k + '_', v)

    def __setattr__(self, attr, value):
        from .io.state import state
        if not getattr(self, 'initialized', False) or (
                attr.startswith('_')
                and attr.endswith('_')) or attr == '_validating':
            return super().__setattr__(attr, value)
        value = getattr(self, f'_{attr}_hook', lambda x: x)(value)
        if attr in self._globals:
            super().__setattr__(attr if attr in self.param else f'_{attr}',
                                value)
        elif state.curdoc is not None:
            if attr in self.param:
                validate_config(self, attr, value)
            elif f'_{attr}' in self.param:
                validate_config(self, f'_{attr}', value)
            else:
                raise AttributeError(
                    f'{attr!r} is not a valid config parameter.')
            if state.curdoc not in self._session_config:
                self._session_config[state.curdoc] = {}
            self._session_config[state.curdoc][attr] = value
        elif f'_{attr}' in self.param and hasattr(self, f'_{attr}_'):
            validate_config(self, f'_{attr}', value)
            super().__setattr__(f'_{attr}_', value)
        else:
            super().__setattr__(attr, value)

    @param.depends('_log_level', watch=True)
    def _update_log_level(self):
        panel_log_handler.setLevel(self._log_level)

    def __getattribute__(self, attr):
        from .io.state import state
        init = super().__getattribute__('initialized')
        global_params = super().__getattribute__('_globals')
        if init and not attr.startswith('__'):
            params = super().__getattribute__('param')
        else:
            params = []
        session_config = super().__getattribute__('_session_config')
        if state.curdoc and state.curdoc not in session_config:
            session_config[state.curdoc] = {}
        if (attr in ('raw_css', 'css_files', 'js_files', 'js_modules')
                and state.curdoc and attr not in session_config[state.curdoc]):
            new_obj = copy.copy(super().__getattribute__(attr))
            setattr(self, attr, new_obj)
        if attr in global_params:
            return super().__getattribute__(attr)
        elif state.curdoc and state.curdoc in session_config and attr in session_config[
                state.curdoc]:
            return session_config[state.curdoc][attr]
        elif f'_{attr}' in params and getattr(self, f'_{attr}_') is not None:
            return super().__getattribute__(f'_{attr}_')
        return super().__getattribute__(attr)

    def _console_output_hook(self, value):
        return value if value else 'disable'

    def _template_hook(self, value):
        if isinstance(value, str):
            return self.param.template.names[value]
        return value

    @property
    def _doc_build(self):
        return os.environ.get('PANEL_DOC_BUILD')

    @property
    def console_output(self):
        if self._doc_build:
            return 'disable'
        else:
            return os.environ.get('PANEL_CONSOLE_OUTPUT',
                                  _config._console_output)

    @property
    def embed(self):
        return os.environ.get('PANEL_EMBED', _config._embed) in self._truthy

    @property
    def comms(self):
        return os.environ.get('PANEL_COMMS', self._comms)

    @property
    def embed_json(self):
        return os.environ.get('PANEL_EMBED_JSON',
                              _config._embed_json) in self._truthy

    @property
    def embed_json_prefix(self):
        return os.environ.get('PANEL_EMBED_JSON_PREFIX',
                              _config._embed_json_prefix)

    @property
    def embed_save_path(self):
        return os.environ.get('PANEL_EMBED_SAVE_PATH',
                              _config._embed_save_path)

    @property
    def embed_load_path(self):
        return os.environ.get('PANEL_EMBED_LOAD_PATH',
                              _config._embed_load_path)

    @property
    def inline(self):
        return os.environ.get('PANEL_INLINE', _config._inline) in self._truthy

    @property
    def log_level(self):
        log_level = os.environ.get('PANEL_LOG_LEVEL', self._log_level)
        return log_level.upper() if log_level else None

    @property
    def nthreads(self):
        nthreads = os.environ.get('PANEL_NUM_THREADS', self._nthreads)
        return None if nthreads is None else int(nthreads)

    @property
    def oauth_provider(self):
        provider = os.environ.get('PANEL_OAUTH_PROVIDER', self._oauth_provider)
        return provider.lower() if provider else None

    @property
    def oauth_expiry(self):
        provider = os.environ.get('PANEL_OAUTH_EXPIRY', self._oauth_expiry)
        return float(provider)

    @property
    def oauth_key(self):
        return os.environ.get('PANEL_OAUTH_KEY', self._oauth_key)

    @property
    def cookie_secret(self):
        return os.environ.get(
            'PANEL_COOKIE_SECRET',
            os.environ.get('BOKEH_COOKIE_SECRET', self._cookie_secret))

    @property
    def oauth_secret(self):
        return os.environ.get('PANEL_OAUTH_SECRET', self._oauth_secret)

    @property
    def oauth_redirect_uri(self):
        return os.environ.get('PANEL_OAUTH_REDIRECT_URI',
                              self._oauth_redirect_uri)

    @property
    def oauth_jwt_user(self):
        return os.environ.get('PANEL_OAUTH_JWT_USER', self._oauth_jwt_user)

    @property
    def oauth_encryption_key(self):
        return os.environ.get('PANEL_OAUTH_ENCRYPTION',
                              self._oauth_encryption_key)

    @property
    def oauth_extra_params(self):
        if 'PANEL_OAUTH_EXTRA_PARAMS' in os.environ:
            return ast.literal_eval(os.environ['PANEL_OAUTH_EXTRA_PARAMS'])
        else:
            return self._oauth_extra_params
Esempio n. 18
0
class DataSource(param.Parameterized):
    tags = param.List(
        doc='List of tags to specify the type of data in the dataobject.')
    source = param.ClassSelector(
        ColumnDataSource,
        doc='ColumnDataSource object which is used for graphical display')
    renderer = param.String(default='line')
    default_color = param.Color(
        default='#0611d4')  # todo get default color from css?

    def __init__(self, input_data, **params):
        #update to lumen / pandas dataframes
        self.render_kwargs = {
            k: params.pop(k)
            for k in list(params.keys()) if k not in self.param
        }
        #todo currently this override colors in dic
        super(DataSource, self).__init__(**params)
        dic = self.get_dic(input_data)
        default_color = 'color' if 'color' in dic else self.default_color
        self.render_kwargs['color'] = self.render_kwargs.get(
            'color', default_color)

        self.source = ColumnDataSource(dic, name=self.name)

    def __getitem__(self, item):
        return self.source.data.__getitem__(item)

    @property  #cached property?
    def df(self):
        df = pd.DataFrame(self.source.data)
        return df

    @property
    def export_df(self):
        df = pd.DataFrame({
            k: v
            for k, v in self.source.data.items() if not k.startswith('__')
        })
        return df

    def get_dic(self, input_data):
        #todo allow dataframes
        if isinstance(input_data, np.ndarray):
            dic = {name: input_data[name] for name in input_data.dtype.names}
            #self.array = input_data  #
        elif isinstance(input_data, dict):
            if 'image' in self.tags:  # Images requires lists of arrays rather than arrays
                dic = {k: v for k, v in input_data.items()}
            else:
                dic = {k: np.array(v) for k, v in input_data.items()}
        elif isinstance(input_data, Protein):
            dic = {
                k: np.array(v)
                for k, v in input_data.to_dict('list').items()
            }
            dic['r_number'] = np.array(input_data.index)
        else:
            raise TypeError("Invalid input data type")

        #todo this does not apply to all data sets? (it does not, for example images)
        if 'color' not in dic.keys() and 'image' not in self.tags:
            column = next(iter(dic.values()))
            color = np.full_like(column,
                                 fill_value=self.default_color,
                                 dtype='<U7')
            dic['color'] = color
        return dic

    def to_numpy(self):
        raise NotImplementedError(
            'Converting to numpy rec array not implemented')

    @property
    def scalar_fields(self):
        """Returns a list of names of fields with scalar dtype"""
        return [
            name for name, data in self.source.data.items()
            if np.issubdtype(data.dtype, np.number)
        ]

    @property
    def y(self):
        """:class:`~numpy.ndarray`: Array of y values"""
        if 'y' in self.render_kwargs:
            try:
                return self.source.data[self.render_kwargs['y']]
            except TypeError:
                return None  #  'y' might be a list of y values
        elif 'y' in self.source.data:
            return self.source.data['y']
        else:
            return None

    @property
    def x(self):
        """:class:`~numpy.ndarray`: Array of x values"""
        if 'x' in self.render_kwargs:
            return self.source.data[self.render_kwargs['x']]
        elif 'x' in self.source.data:
            return self.source.data['x']
        else:
            return None

    def update(self, data_source_obj):
        """
        Update the data and source object

        Parameters
        ----------
        data_source

        Returns
        -------


        """

        self.source.data.update(**data_source_obj.source.data)

    def resolve_tags(self, tags):
        # format ['tag1', ('tag2a', 'tag2b') ] = tag1 OR (tag2a AND tag2b)

        for tag in tags:
            if isinstance(tag, str):
                bool = tag in self.tags
                # if tag in self.tags:
                #     return True
            else:
                bool = all(sub_tag in self.tags for sub_tag in tag)
            if bool:
                return True
        return False
Esempio n. 19
0
class link_selections(_base_link_selections):
    """
    Operation which automatically links selections between elements
    in the supplied HoloViews object. Can be used a single time or
    be used as an instance to apply the linked selections across
    multiple objects.
    """

    cross_filter_mode = param.Selector(['overwrite', 'intersect'],
                                       default='intersect',
                                       doc="""
        Determines how to combine selections across different
        elements.""")

    index_cols = param.List(default=None,
                            doc="""
        If provided, selection switches to index mode where all queries
        are expressed solely in terms of discrete values along the
        index_cols.  All Elements given to link_selections must define the index_cols, either as explicit dimensions or by sharing an underlying Dataset that defines them."""
                            )

    selection_expr = param.Parameter(default=None,
                                     doc="""
        dim expression of the current selection or None to indicate
        that everything is selected.""")

    selected_color = param.Color(default=None,
                                 allow_None=True,
                                 doc="""
        Color of selected data, or None to use the original color of
        each element.""")

    selection_mode = param.Selector(
        ['overwrite', 'intersect', 'union', 'inverse'],
        default='overwrite',
        doc="""
        Determines how to combine successive selections on the same
        element.""")

    show_regions = param.Boolean(default=True,
                                 doc="""
        Whether to highlight the selected regions.""")

    unselected_alpha = param.Magnitude(default=0.1,
                                       doc="""
        Alpha of unselected data.""")

    unselected_color = param.Color(default=None,
                                   doc="""
        Color of unselected data.""")

    @bothmethod
    def instance(self_or_cls, **params):
        inst = super(link_selections, self_or_cls).instance(**params)

        # Initialize private properties
        inst._obj_selections = {}
        inst._obj_regions = {}
        inst._reset_regions = True

        return inst

    @classmethod
    def _build_selection_streams(cls, inst):
        # Colors stream
        style_stream = _Styles(
            colors=[inst.unselected_color, inst.selected_color],
            alpha=inst.unselected_alpha)

        # Cmap streams
        cmap_streams = [
            _Cmap(cmap=inst.unselected_cmap),
            _Cmap(cmap=inst.selected_cmap),
        ]

        def update_colors(*_):
            colors = [inst.unselected_color, inst.selected_color]
            style_stream.event(colors=colors, alpha=inst.unselected_alpha)
            cmap_streams[0].event(cmap=inst.unselected_cmap)
            if cmap_streams[1] is not None:
                cmap_streams[1].event(cmap=inst.selected_cmap)

        inst.param.watch(
            update_colors,
            ['unselected_color', 'selected_color', 'unselected_alpha'])

        # Exprs stream
        exprs_stream = _Exprs(exprs=[True, None])

        def update_exprs(*_):
            exprs_stream.event(exprs=[True, inst.selection_expr])
            # Reset regions
            if inst._reset_regions:
                for k, v in inst._region_streams.items():
                    inst._region_streams[k].event(region_element=None)
                inst._obj_selections.clear()
                inst._obj_regions.clear()

        inst.param.watch(update_exprs, ['selection_expr'])

        return _SelectionStreams(
            style_stream=style_stream,
            exprs_stream=exprs_stream,
            cmap_streams=cmap_streams,
        )

    @property
    def unselected_cmap(self):
        """
        The datashader colormap for unselected data
        """
        if self.unselected_color is None:
            return None
        return _color_to_cmap(self.unselected_color)

    @property
    def selected_cmap(self):
        """
        The datashader colormap for selected data
        """
        return None if self.selected_color is None else _color_to_cmap(
            self.selected_color)

    def _expr_stream_updated(self, hvobj, selection_expr, bbox, region_element,
                             **kwargs):
        if selection_expr:
            if self.cross_filter_mode == "overwrite":
                # clear other regions and selections
                for k, v in self._region_streams.items():
                    if k is not hvobj:
                        self._region_streams[k].event(region_element=None)
                        self._obj_regions.pop(k, None)
                        self._obj_selections.pop(k, None)

            # Update selection expression
            if hvobj not in self._obj_selections or self.selection_mode == "overwrite":
                if self.selection_mode == "inverse":
                    self._obj_selections[hvobj] = ~selection_expr
                else:
                    self._obj_selections[hvobj] = selection_expr
            else:
                if self.selection_mode == "intersect":
                    self._obj_selections[hvobj] &= selection_expr
                elif self.selection_mode == "union":
                    self._obj_selections[hvobj] |= selection_expr
                else:  # inverse
                    self._obj_selections[hvobj] &= ~selection_expr

            # Update region
            if self.show_regions:
                if isinstance(hvobj, DynamicMap):
                    el_type = hvobj.type
                else:
                    el_type = hvobj

                region_element = el_type._merge_regions(
                    self._obj_regions.get(hvobj, None), region_element,
                    self.selection_mode)
                self._obj_regions[hvobj] = region_element
            else:
                region_element = None

            # build combined selection
            selection_exprs = list(self._obj_selections.values())
            if self.index_cols:
                if len(selection_exprs) > 1:
                    vals = set.intersection(*(set(expr.ops[2]['args'][0])
                                              for expr in selection_exprs))
                    old = selection_exprs[0]
                    selection_expr = dim('new')
                    selection_expr.dimension = old.dimension
                    selection_expr.ops = list(old.ops)
                    selection_expr.ops[2] = dict(selection_expr.ops[2],
                                                 args=(list(vals), ))
            else:
                selection_expr = selection_exprs[0]
                for expr in selection_exprs[1:]:
                    selection_expr = selection_expr & expr

            # Set _reset_regions to False so that plot regions aren't automatically
            # cleared when self.selection_expr is set.
            self._reset_regions = False
            self.selection_expr = selection_expr
            self._reset_regions = True

            # update this region stream
            if self._region_streams.get(hvobj, None) is not None:
                self._region_streams[hvobj].event(
                    region_element=region_element)
Esempio n. 20
0
class _config(_base_config):
    """
    Holds global configuration options for Panel. The options can be
    set directly on the global config instance, via keyword arguments
    in the extension or via environment variables. For example to set
    the embed option the following approaches can be used:

        pn.config.embed = True

        pn.extension(embed=True)

        os.environ['PANEL_EMBED'] = 'True'
    """

    apply_signatures = param.Boolean(default=True,
                                     doc="""
        Whether to set custom Signature which allows tab-completion
        in some IDEs and environments.""")

    autoreload = param.Boolean(default=False,
                               doc="""
        Whether to autoreload server when script changes.""")

    loading_spinner = param.Selector(
        default='arcs',
        objects=['arc', 'arcs', 'bar', 'dots', 'petal'],
        doc="""
        Loading indicator to use when component loading parameter is set.""")

    loading_color = param.Color(default='#c3c3c3',
                                doc="""
        Color of the loading indicator.""")

    safe_embed = param.Boolean(default=False,
                               doc="""
        Ensure all bokeh property changes trigger events which are
        embedded. Useful when only partial updates are made in an
        app, e.g. when working with HoloViews.""")

    session_history = param.Integer(default=0,
                                    bounds=(-1, None),
                                    doc="""
        If set to a non-negative value this determines the maximum length
        of the pn.state.session_info dictionary, which tracks
        information about user sessions. A value of -1 indicates an
        unlimited history.""")

    sizing_mode = param.ObjectSelector(default=None,
                                       objects=[
                                           'fixed', 'stretch_width',
                                           'stretch_height', 'stretch_both',
                                           'scale_width', 'scale_height',
                                           'scale_both', None
                                       ],
                                       doc="""
        Specify the default sizing mode behavior of panels.""")

    throttled = param.Boolean(default=False,
                              doc="""
        If sliders and inputs should be throttled until release of mouse.""")

    _comms = param.ObjectSelector(
        default='default',
        objects=['default', 'ipywidgets', 'vscode', 'colab'],
        doc="""
        Whether to render output in Jupyter with the default Jupyter
        extension or use the jupyter_bokeh ipywidget model.""")

    _console_output = param.ObjectSelector(
        default='accumulate',
        allow_None=True,
        objects=['accumulate', 'replace', 'disable', False],
        doc="""
        How to log errors and stdout output triggered by callbacks
        from Javascript in the notebook.""")

    _cookie_secret = param.String(default=None,
                                  doc="""
        Configure to enable getting/setting secure cookies.""")

    _embed = param.Boolean(default=False,
                           allow_None=True,
                           doc="""
        Whether plot data will be embedded.""")

    _embed_json = param.Boolean(default=False,
                                doc="""
        Whether to save embedded state to json files.""")

    _embed_json_prefix = param.String(default='',
                                      doc="""
        Prefix for randomly generated json directories.""")

    _embed_load_path = param.String(default=None,
                                    doc="""
        Where to load json files for embedded state.""")

    _embed_save_path = param.String(default='./',
                                    doc="""
        Where to save json files for embedded state.""")

    _log_level = param.Selector(
        default=None,
        objects=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
        doc="Log level of Panel loggers")

    _oauth_provider = param.ObjectSelector(default=None,
                                           allow_None=True,
                                           objects=[],
                                           doc="""
        Select between a list of authentification providers.""")

    _oauth_key = param.String(default=None,
                              doc="""
        A client key to provide to the OAuth provider.""")

    _oauth_secret = param.String(default=None,
                                 doc="""
        A client secret to provide to the OAuth provider.""")

    _oauth_jwt_user = param.String(default=None,
                                   doc="""
        The key in the ID JWT token to consider the user.""")

    _oauth_redirect_uri = param.String(default=None,
                                       doc="""
        A redirect URI to provide to the OAuth provider.""")

    _oauth_encryption_key = param.ClassSelector(default=None,
                                                class_=bytes,
                                                doc="""
        A random string used to encode OAuth related user information.""")

    _oauth_extra_params = param.Dict(default={},
                                     doc="""
        Additional parameters required for OAuth provider.""")

    _inline = param.Boolean(default=_LOCAL_DEV_VERSION,
                            allow_None=True,
                            doc="""
        Whether to inline JS and CSS resources. If disabled, resources
        are loaded from CDN if one is available.""")

    _truthy = ['True', 'true', '1', True, 1]

    def __init__(self, **params):
        super().__init__(**params)
        for p in self.param:
            if p.startswith('_'):
                setattr(self, p + '_', None)

    @contextmanager
    def set(self, **kwargs):
        values = [(k, v) for k, v in self.param.get_param_values()
                  if k != 'name']
        overrides = [(k, getattr(self, k + '_')) for k in self.param
                     if k.startswith('_')]
        for k, v in kwargs.items():
            setattr(self, k, v)
        try:
            yield
        finally:
            self.param.set_param(**dict(values))
            for k, v in overrides:
                setattr(self, k + '_', v)

    @property
    def _doc_build(self):
        return os.environ.get('PANEL_DOC_BUILD')

    @property
    def console_output(self):
        if self._console_output_ is not None:
            return 'disable' if not self._console_output_ else self._console_output_
        elif self._doc_build:
            return 'disable'
        else:
            return os.environ.get('PANEL_CONSOLE_OUTPUT',
                                  _config._console_output)

    @console_output.setter
    def console_output(self, value):
        validate_config(self, '_console_output', value)
        self._console_output_ = value

    @property
    def embed(self):
        if self._embed_ is not None:
            return self._embed_
        else:
            return os.environ.get('PANEL_EMBED',
                                  _config._embed) in self._truthy

    @embed.setter
    def embed(self, value):
        validate_config(self, '_embed', value)
        self._embed_ = value

    @property
    def comms(self):
        if self._comms_ is not None:
            return self._comms_
        else:
            return os.environ.get('PANEL_COMMS', _config._comms)

    @comms.setter
    def comms(self, value):
        validate_config(self, '_comms', value)
        self._comms_ = value

    @property
    def embed_json(self):
        if self._embed_json_ is not None:
            return self._embed_json_
        else:
            return os.environ.get('PANEL_EMBED_JSON',
                                  _config._embed_json) in self._truthy

    @embed_json.setter
    def embed_json(self, value):
        validate_config(self, '_embed_json', value)
        self._embed_json_ = value

    @property
    def embed_json_prefix(self):
        if self._embed_json_prefix_ is not None:
            return self._embed_json_prefix_
        else:
            return os.environ.get('PANEL_EMBED_JSON_PREFIX',
                                  _config._embed_json_prefix)

    @embed_json_prefix.setter
    def embed_json_prefix(self, value):
        validate_config(self, '_embed_json_prefix', value)
        self._embed_json_prefix_ = value

    @property
    def embed_save_path(self):
        if self._embed_save_path_ is not None:
            return self._embed_save_path_
        else:
            return os.environ.get('PANEL_EMBED_SAVE_PATH',
                                  _config._embed_save_path)

    @embed_save_path.setter
    def embed_save_path(self, value):
        validate_config(self, '_embed_save_path', value)
        self._embed_save_path_ = value

    @property
    def embed_load_path(self):
        if self._embed_load_path_ is not None:
            return self._embed_load_path_
        else:
            return os.environ.get('PANEL_EMBED_LOAD_PATH',
                                  _config._embed_load_path)

    @embed_load_path.setter
    def embed_load_path(self, value):
        validate_config(self, '_embed_load_path', value)
        self._embed_load_path_ = value

    @property
    def inline(self):
        if self._inline_ is not None:
            return self._inline_
        else:
            return os.environ.get('PANEL_INLINE',
                                  _config._inline) in self._truthy

    @inline.setter
    def inline(self, value):
        validate_config(self, '_inline', value)
        self._inline_ = value

    @property
    def log_level(self):
        if self._log_level_ is not None:
            return self._log_level_
        elif 'PANEL_LOG_LEVEL' in os.environ:
            return os.environ['PANEL_LOG_LEVEL'].upper()
        else:
            return self._log_level

    @log_level.setter
    def log_level(self, value):
        validate_config(self, '_log_level', value)
        self._log_level_ = value

    @property
    def oauth_provider(self):
        if self._oauth_provider_ is not None:
            return self._oauth_provider_
        else:
            provider = os.environ.get('PANEL_OAUTH_PROVIDER',
                                      _config._oauth_provider)
            return provider.lower() if provider else None

    @oauth_provider.setter
    def oauth_provider(self, value):
        validate_config(self, '_oauth_provider', value.lower())
        self._oauth_provider_ = value.lower()

    @property
    def oauth_key(self):
        if self._oauth_key_ is not None:
            return self._oauth_key_
        else:
            return os.environ.get('PANEL_OAUTH_KEY', _config._oauth_key)

    @oauth_key.setter
    def oauth_key(self, value):
        validate_config(self, '_oauth_key', value)
        self._oauth_key_ = value

    @property
    def cookie_secret(self):
        if self._cookie_secret_ is not None:
            return self._cookie_secret_
        else:
            return os.environ.get(
                'PANEL_COOKIE_SECRET',
                os.environ.get('BOKEH_COOKIE_SECRET', _config._cookie_secret))

    @cookie_secret.setter
    def cookie_secret(self, value):
        validate_config(self, '_cookie_secret', value)
        self._cookie_secret_ = value

    @property
    def oauth_secret(self):
        if self._oauth_secret_ is not None:
            return self._oauth_secret_
        else:
            return os.environ.get('PANEL_OAUTH_SECRET', _config._oauth_secret)

    @oauth_secret.setter
    def oauth_secret(self, value):
        validate_config(self, '_oauth_secret', value)
        self._oauth_secret_ = value

    @property
    def oauth_redirect_uri(self):
        if self._oauth_redirect_uri_ is not None:
            return self._oauth_redirect_uri_
        else:
            return os.environ.get('PANEL_OAUTH_REDIRECT_URI',
                                  _config._oauth_redirect_uri)

    @oauth_redirect_uri.setter
    def oauth_redirect_uri(self, value):
        validate_config(self, '_oauth_redirect_uri', value)
        self._oauth_redirect_uri_ = value

    @property
    def oauth_jwt_user(self):
        if self._oauth_jwt_user_ is not None:
            return self._oauth_jwt_user_
        else:
            return os.environ.get('PANEL_OAUTH_JWT_USER',
                                  _config._oauth_jwt_user)

    @oauth_jwt_user.setter
    def oauth_jwt_user(self, value):
        validate_config(self, '_oauth_jwt_user', value)
        self._oauth_jwt_user_ = value

    @property
    def oauth_encryption_key(self):
        if self._oauth_encryption_key_ is not None:
            return self._oauth_encryption_key_
        else:
            return os.environ.get('PANEL_OAUTH_ENCRYPTION',
                                  _config._oauth_encryption_key)

    @oauth_encryption_key.setter
    def oauth_encryption_key(self, value):
        validate_config(self, '_oauth_encryption_key', value)
        self._oauth_encryption_key_ = value

    @property
    def oauth_extra_params(self):
        if self._oauth_extra_params_ is not None:
            return self._oauth_extra_params_
        else:
            if 'PANEL_OAUTH_EXTRA_PARAMS' in os.environ:
                return ast.literal_eval(os.environ['PANEL_OAUTH_EXTRA_PARAMS'])
            else:
                return _config._oauth_extra_params

    @oauth_extra_params.setter
    def oauth_extra_params(self, value):
        validate_config(self, '_oauth_extra_params', value)
        self._oauth_extra_params_ = value
Esempio n. 21
0
class VTKVolume(AbstractVTK):
    """
    The `VTKVolume` pane renders 3d volumetric data defined on regular grids.
    It may be constructed from a 3D NumPy array or a vtkVolume.
    
    The pane provides a number of interactive control which can be set either
    through callbacks from Python or Javascript callbacks.

    Reference: https://panel.holoviz.org/reference/panes/VTKVolume.html

    :Example:

    >>> pn.extension('vtk')
    >>> VTKVolume(
    ...    data_matrix, spacing=(3,2,1), interpolation='nearest',
    ...    edge_gradient=0, sampling=0,
    ...    sizing_mode='stretch_width', height=400,
    ... )
    """

    ambient = param.Number(default=0.2,
                           step=1e-2,
                           doc="""
        Value to control the ambient lighting. It is the light an
        object gives even in the absence of strong light. It is
        constant in all directions.""")

    controller_expanded = param.Boolean(default=True,
                                        doc="""
        If True the volume controller panel options is expanded in the view""")

    colormap = param.Selector(default='erdc_rainbow_bright',
                              objects=PRESET_CMAPS,
                              doc="""
        Name of the colormap used to transform pixel value in color.""")

    diffuse = param.Number(default=0.7,
                           step=1e-2,
                           doc="""
        Value to control the diffuse Lighting. It relies on both the
        light direction and the object surface normal.""")

    display_volume = param.Boolean(default=True,
                                   doc="""
        If set to True, the 3D respresentation of the volume is
        displayed using ray casting.""")

    display_slices = param.Boolean(default=False,
                                   doc="""
        If set to true, the orthgonal slices in the three (X, Y, Z)
        directions are displayed. Position of each slice can be
        controlled using slice_(i,j,k) parameters.""")

    edge_gradient = param.Number(default=0.4,
                                 bounds=(0, 1),
                                 step=1e-2,
                                 doc="""
        Parameter to adjust the opacity of the volume based on the
        gradient between voxels.""")

    interpolation = param.Selector(
        default='fast_linear',
        objects=['fast_linear', 'linear', 'nearest'],
        doc="""
        interpolation type for sampling a volume. `nearest`
        interpolation will snap to the closest voxel, `linear` will
        perform trilinear interpolation to compute a scalar value from
        surrounding voxels.  `fast_linear` under WebGL 1 will perform
        bilinear interpolation on X and Y but use nearest for Z. This
        is slightly faster than full linear at the cost of no Z axis
        linear interpolation.""")

    mapper = param.Dict(doc="Lookup Table in format {low, high, palette}")

    max_data_size = param.Number(default=(256**3) * 2 / 1e6,
                                 doc="""
        Maximum data size transfert allowed without subsampling""")

    nan_opacity = param.Number(default=1.,
                               bounds=(0., 1.),
                               doc="""
        Opacity applied to nan values in slices""")

    origin = param.Tuple(default=None, length=3, allow_None=True)

    render_background = param.Color(default='#52576e',
                                    doc="""
        Allows to specify the background color of the 3D rendering.
        The value must be specified as an hexadecimal color string.""")

    rescale = param.Boolean(default=False,
                            doc="""
        If set to True the colormap is rescaled beween min and max
        value of the non-transparent pixel, otherwise  the full range
        of the pixel values are used.""")

    shadow = param.Boolean(default=True,
                           doc="""
        If set to False, then the mapper for the volume will not
        perform shading computations, it is the same as setting
        ambient=1, diffuse=0, specular=0.""")

    sampling = param.Number(default=0.4,
                            bounds=(0, 1),
                            step=1e-2,
                            doc="""
        Parameter to adjust the distance between samples used for
        rendering. The lower the value is the more precise is the
        representation but it is more computationally intensive.""")

    spacing = param.Tuple(default=(1, 1, 1),
                          length=3,
                          doc="""
        Distance between voxel in each direction""")

    specular = param.Number(default=0.3,
                            step=1e-2,
                            doc="""
        Value to control specular lighting. It is the light reflects
        back toward the camera when hitting the object.""")

    specular_power = param.Number(default=8.,
                                  doc="""
        Specular power refers to how much light is reflected in a
        mirror like fashion, rather than scattered randomly in a
        diffuse manner.""")

    slice_i = param.Integer(per_instance=True,
                            doc="""
        Integer parameter to control the position of the slice normal
        to the X direction.""")

    slice_j = param.Integer(per_instance=True,
                            doc="""
        Integer parameter to control the position of the slice normal
        to the Y direction.""")

    slice_k = param.Integer(per_instance=True,
                            doc="""
        Integer parameter to control the position of the slice normal
        to the Z direction.""")

    _serializers = {}

    _rename = {'max_data_size': None, 'spacing': None, 'origin': None}

    _updates = True

    def __init__(self, object=None, **params):
        super().__init__(object, **params)
        self._sub_spacing = self.spacing
        self._update()

    @classmethod
    def applies(cls, obj):
        if ((isinstance(obj, np.ndarray) and obj.ndim == 3)
                or any([isinstance(obj, k) for k in cls._serializers.keys()])):
            return True
        elif 'vtk' not in sys.modules and 'vtkmodules' not in sys.modules:
            return False
        else:
            import vtk
            return isinstance(obj, vtk.vtkImageData)

    def _get_model(self, doc, root=None, parent=None, comm=None):
        VTKVolumePlot = lazy_load('panel.models.vtk', 'VTKVolumePlot',
                                  isinstance(comm, JupyterComm), root)
        props = self._process_param_change(self._init_params())
        if self._volume_data is not None:
            props['data'] = self._volume_data

        model = VTKVolumePlot(**props)
        if root is None:
            root = model
        self._link_props(model, [
            'colormap', 'orientation_widget', 'camera', 'mapper',
            'controller_expanded', 'nan_opacity'
        ], doc, root, comm)
        self._models[root.ref['id']] = (model, parent)
        return model

    def _update_object(self, ref, doc, root, parent, comm):
        self._legend = None
        super()._update_object(ref, doc, root, parent, comm)

    def _get_object_dimensions(self):
        if isinstance(self.object, np.ndarray):
            return self.object.shape
        else:
            return self.object.GetDimensions()

    def _process_param_change(self, msg):
        msg = super()._process_param_change(msg)
        if self.object is not None:
            slice_params = {'slice_i': 0, 'slice_j': 1, 'slice_k': 2}
            for k, v in msg.items():
                sub_dim = self._subsample_dimensions
                ori_dim = self._orginal_dimensions
                if k in slice_params:
                    index = slice_params[k]
                    msg[k] = int(np.round(v * sub_dim[index] / ori_dim[index]))
        return msg

    def _process_property_change(self, msg):
        msg = super()._process_property_change(msg)
        if self.object is not None:
            slice_params = {'slice_i': 0, 'slice_j': 1, 'slice_k': 2}
            for k, v in msg.items():
                sub_dim = self._subsample_dimensions
                ori_dim = self._orginal_dimensions
                if k in slice_params:
                    index = slice_params[k]
                    msg[k] = int(np.round(v * ori_dim[index] / sub_dim[index]))
        return msg

    def _update(self, ref=None, model=None):
        self._volume_data = self._get_volume_data()
        if self._volume_data is not None:
            self._orginal_dimensions = self._get_object_dimensions()
            self._subsample_dimensions = self._volume_data['dims']
            self.param.slice_i.bounds = (0, self._orginal_dimensions[0] - 1)
            self.slice_i = (self._orginal_dimensions[0] - 1) // 2
            self.param.slice_j.bounds = (0, self._orginal_dimensions[1] - 1)
            self.slice_j = (self._orginal_dimensions[1] - 1) // 2
            self.param.slice_k.bounds = (0, self._orginal_dimensions[2] - 1)
            self.slice_k = (self._orginal_dimensions[2] - 1) // 2
        if model is not None:
            model.data = self._volume_data

    @classmethod
    def register_serializer(cls, class_type, serializer):
        """
        Register a seriliazer for a given type of class.
        A serializer is a function which take an instance of `class_type`
        (like a vtk.vtkImageData) as input and return a numpy array of the data
        """
        cls._serializers.update({class_type: serializer})

    def _volume_from_array(self, sub_array):
        return dict(buffer=base64encode(sub_array.ravel(order='F')),
                    dims=sub_array.shape,
                    spacing=self._sub_spacing,
                    origin=self.origin,
                    data_range=(np.nanmin(sub_array), np.nanmax(sub_array)),
                    dtype=sub_array.dtype.name)

    def _get_volume_data(self):
        if self.object is None:
            return None
        elif isinstance(self.object, np.ndarray):
            return self._volume_from_array(self._subsample_array(self.object))
        else:
            available_serializer = [
                v for k, v in VTKVolume._serializers.items()
                if isinstance(self.object, k)
            ]
            if not available_serializer:
                import vtk
                from vtk.util import numpy_support

                def volume_serializer(inst):
                    imageData = inst.object
                    array = numpy_support.vtk_to_numpy(
                        imageData.GetPointData().GetScalars())
                    dims = imageData.GetDimensions()
                    inst.spacing = imageData.GetSpacing()
                    inst.origin = imageData.GetOrigin()
                    return inst._volume_from_array(
                        inst._subsample_array(array.reshape(dims, order='F')))

                VTKVolume.register_serializer(vtk.vtkImageData,
                                              volume_serializer)
                serializer = volume_serializer
            else:
                serializer = available_serializer[0]
            return serializer(self)

    def _subsample_array(self, array):
        original_shape = array.shape
        spacing = self.spacing
        extent = tuple(
            (o_s - 1) * s for o_s, s in zip(original_shape, spacing))
        dim_ratio = np.cbrt((array.nbytes / 1e6) / self.max_data_size)
        max_shape = tuple(int(o_s / dim_ratio) for o_s in original_shape)
        dowsnscale_factor = [
            max(o_s, m_s) / m_s for m_s, o_s in zip(max_shape, original_shape)
        ]

        if any([d_f > 1 for d_f in dowsnscale_factor]):
            try:
                import scipy.ndimage as nd
                sub_array = nd.interpolation.zoom(
                    array,
                    zoom=[1 / d_f for d_f in dowsnscale_factor],
                    order=0,
                    mode="nearest")
            except ImportError:
                sub_array = array[::int(np.ceil(dowsnscale_factor[0])), ::int(
                    np.ceil(dowsnscale_factor[1])
                ), ::int(np.ceil(dowsnscale_factor[2]))]
            self._sub_spacing = tuple(e / (s - 1)
                                      for e, s in zip(extent, sub_array.shape))
        else:
            sub_array = array
            self._sub_spacing = self.spacing
        return sub_array
class ArcProgressIndicator(pn.reactive.ReactiveHTML):

    progress = param.Number(default=0, bounds=(0, 100))

    transition_duration = param.Number(default=0.5, bounds=(0, None))

    format_options = param.Dict(
        default={
            "locale": "en-US",
            "style": "percent",
            "minimumIntegerDigits": "1",
            "maximumIntegerDigits": "3",
            "minimumFractionDigits": "1",
            "maximumFractionDigits": "1"
        })

    text_style = param.Dict(default={
        "font-size": 4.5,
        "text-anchor": "middle",
        "letter-spacing": -0.2,
    })

    empty_color = param.Color(default="#e8f6fd")

    fill_color = param.Color(default="#2a87d8")

    use_gradient = param.Boolean(default=False)

    gradient = param.Parameter(default=[{
        "stop": 0,
        "color": "green"
    }, {
        "stop": 1,
        "color": "red"
    }])

    annotations = param.Parameter(default=[])

    viewbox = param.List(default=[0, -1, 20, 10], constant=True)

    _template = """
    <div id="arcprog">
        <svg height="100%" width="100%" viewBox="0 -1 20 10" style="display: block;">
          <defs>
              <linearGradient id="grad">
                <stop offset="0" style="stop-color:black" />
                <stop offset="1" style="stop-color:magenta" />
              </linearGradient>
          </defs>
        </svg>
    </div>
    """

    _scripts = {
        "render":
        """
            state.initialized = false
            state.GradientReader = function(colorStops) {

                const canvas = document.createElement('canvas');   // create canvas element
                const ctx = canvas.getContext('2d');               // get context
                const gr = ctx.createLinearGradient(0, 0, 101, 0); // create a gradient

                canvas.width = 101;                                // 101 pixels incl.
                canvas.height = 1;                                 // as the gradient

                for (const { stop, color } of colorStops) {               // add color stops
                    gr.addColorStop(stop, color);
                }

                ctx.fillStyle = gr;                                // set as fill style
                ctx.fillRect(0, 0, 101, 1);                        // draw a single line

                // method to get color of gradient at % position [0, 100]
                return {
                    getColor: (pst) => {
                        const color_array = ctx.getImageData(pst|0, 0, 1, 1).data
                        return `rgb(${color_array[0]}, ${color_array[1]}, ${color_array[2]})`
                    }
                };
            }
            state.container = document.getElementById(`arcprog-${data.id}`)
            const svg = state.container.querySelector("svg")

            const empty_path = document.createElementNS("http://www.w3.org/2000/svg", "path")
            empty_path.setAttribute("d", "M1 9 A 8 8 0 1 1 19 9")
            empty_path.setAttribute("fill", "none")
            empty_path.setAttribute("stroke-width", "1.5")
            state.empty_path = empty_path

            const fill_path = empty_path.cloneNode()
            state.fill_path = fill_path

            text = document.createElementNS("http://www.w3.org/2000/svg", "text")
            text.setAttribute("y","8.9")
            text.setAttribute("x","10")
            self.text_style()
            state.text = text

            //path used to
            const external_path = document.createElementNS("http://www.w3.org/2000/svg", "path")
            external_path.setAttribute("d", "M0.25 9 A 8.75 8.75 0 1 1 19.75 9")
            state.external_path = external_path

            svg.appendChild(empty_path)
            svg.appendChild(fill_path)
            svg.appendChild(text)

            self.viewbox()
            self.transition_duration()
            self.empty_color()
            self.fill_color()
            self.format_options()
            self.gradient()
            self.progress()
            self.annotations()
            state.initialized = true
        """,
        "annotations":
        """
            const path_len = state.empty_path.getTotalLength()
            const tot_len = state.external_path.getTotalLength()
            const svg = state.container.querySelector("svg")
            svg.querySelectorAll(".ArcProgressIndicator_annotation").forEach((node) => node.remove())
            const annotations = data.annotations
            annotations.forEach((annotation) => {
                const {progress, text, tick_width, text_size} = annotation
                const annotation_position = state.external_path.getPointAtLength(tot_len * progress/100);

                const annot_tick = state.empty_path.cloneNode()
                annot_tick.setAttribute("class", "ArcProgressIndicator_annotation")
                annot_tick.setAttribute("stroke-dasharray", `${tick_width} ${path_len}`)
                annot_tick.setAttribute("stroke-dashoffset", `${-(path_len * progress/100 - tick_width/2)}`)
                annot_tick.setAttribute("stroke", "black")

                const annot_text = document.createElementNS("http://www.w3.org/2000/svg", "text")
                annot_text.setAttribute("class", "ArcProgressIndicator_annotation")
                annot_text.setAttribute("x",annotation_position.x)
                annot_text.setAttribute("y",annotation_position.y)
                annot_text.setAttribute("style",`font-size:${text_size};text-anchor:${progress>50 ? "start" : "end"}`)

                const textNode = document.createTextNode(text)
                annot_text.appendChild(textNode)

                svg.appendChild(annot_tick)
                svg.appendChild(annot_text)
            })


        """,
        "progress":
        """
            const textNode = document.createTextNode(`${state.formatter.format(data.progress / (state.formatter.resolvedOptions().style=="percent" ? 100 : 1))}`)

            if(state.text.firstChild)
                state.text.firstChild.replaceWith(textNode)
            else
                text.appendChild(textNode)
            const path_len = state.empty_path.getTotalLength()
            state.fill_path.setAttribute("stroke-dasharray", `${path_len * data.progress/100} ${path_len}`)
            const current_color = data.use_gradient ? state.gr.getColor(data.progress) : data.fill_color

            if(!state.text_style || !("fill" in state.text_style))
                state.text.setAttribute("fill", current_color)
        """,
        "transition_duration":
        """
            state.fill_path.setAttribute("style", `transition: stroke-dasharray ${data.transition_duration}s`)
        """,
        "format_options":
        """
            state.formatter = new Intl.NumberFormat(data.format_options.locale, data.format_options)
            if (state.initialized)
                self.progress()
        """,
        "text_style":
        """
                text.setAttribute("style", Object.entries(data.text_style).map(([k, v]) => `${k}:${v}`).join(';'))
            """,
        "empty_color":
        """
            state.empty_path.setAttribute("stroke", data.empty_color)
        """,
        "fill_color":
        """
            if (data.use_gradient)
                state.fill_path.setAttribute("stroke", `url(#grad-${data.id}`)
            else
                state.fill_path.setAttribute("stroke", data.fill_color)
        """,
        "use_gradient":
        """
            self.fill_color()
            if (state.initialized)
                self.progress()
        """,
        "gradient":
        """
            const gradientNode = state.container.querySelector("linearGradient")
            gradientNode.querySelectorAll("stop").forEach((stop) => gradientNode.removeChild(stop))
            const list_gradient_values = data.gradient
            list_gradient_values.forEach((elem) => {
                const stopNode = document.createElementNS("http://www.w3.org/2000/svg", "stop")
                stopNode.setAttribute("offset", `${elem.stop}`)
                stopNode.setAttribute("stop-color", `${elem.color}`)
                gradientNode.appendChild(stopNode)
            })
            state.gr = new state.GradientReader(data.gradient)
            if (state.initialized)
                self.progress()
        """,
        "viewbox":
        """
            const svg = state.container.querySelector("svg")
            svg.setAttribute("viewBox", data.viewbox.join(" "))
        """
    }

    def __init__(self, **params):
        if "text_style" in params:
            default_text_style = dict(self.param.text_style.default)
            default_text_style.update(params.get("text_style"))
            params["text_style"] = default_text_style
        if "format_options" in params:
            default_format_options = dict(self.param.format_options.default)
            default_format_options.update(params.get("format_options"))
            params["format_options"] = default_format_options

        super().__init__(**params)
        self._on_use_gradient_change()

    @pn.depends("use_gradient", watch=True)
    def _on_use_gradient_change(self):
        if self.use_gradient:
            self.param.fill_color.precedence = -1
            self.param.gradient.precedence = 1
        else:
            self.param.fill_color.precedence = 1
            self.param.gradient.precedence = -1
Esempio n. 23
0
class NGL(ReactiveHTML):
    """
    The [NGL Viewer](https://github.com/nglviewer/ngl) can be used
    to show and analyse pdb molecule structures

    See also panel-chemistry for bokeh implementation:
    https://github.com/MarcSkovMadsen/panel-chemistry



    """

    object = param.String()

    extension = param.Selector(
        default="pdb",
        objects=EXTENSIONS,
    )

    background_color = param.Color(default="#F7F7F7",
                                   doc="Color to use for the background")

    representation = param.Selector(
        default="ball+stick",
        objects=REPRESENTATIONS,
        doc="""
         A display representation. Default is 'ball+stick'. See
         http://nglviewer.org/ngl/api/manual/coloring.html#representations
         """,
    )

    color_scheme = param.Selector(default="chainid", objects=COLOR_SCHEMES)

    custom_color_scheme = param.List(
        default=[["#258fdb", "*"]],
        doc="""
        A custom color scheme. See
        http://nglviewer.org/ngl/api/manual/coloring.html#custom-coloring.""",
    )

    effect = param.Selector(default=None,
                            objects=[None, "spin", "rock"],
                            allow_None=True)

    _template = """
    <div id="ngl_stage" style="width:100%; height:100%;"></div>
    """
    _scripts = {
        "render":
        """
            var stage = new NGL.Stage(ngl_stage)        
            state._stage = stage
            state._stage.setParameters({ backgroundColor: data.background_color})
            stage.handleResize();
            self.updateStage()
        """,
        "object":
        """
            self.updateStage()
            """,
        "color_scheme":
        """
            self.setParameters()
            """,
        "custom_color_scheme":
        """
            self.setParameters()
        """,
        "background_color":
        """
        state._stage.setParameters({ backgroundColor: data.background_color})
        """,
        "setParameters":
        """
            if (state._stage.compList.length !== 0) {
                const parameters = self.getParameters();
                state._stage.compList[0].reprList[0].setParameters( parameters );
            }
            """,
        "getParameters":
        """
            if (data.color_scheme==="custom"){
                var scheme = NGL.ColormakerRegistry.addSelectionScheme( data.custom_color_scheme, "new scheme")
                var parameters = {color: scheme}
            }
            else {
                var parameters = {colorScheme: data.color_scheme}
            }
            parameters["sele"] = 'protein'

            return parameters
        """,
        "representation":
        """
            const parameters = self.getParameters();
            const component = state._stage.compList[0];
            component.removeAllRepresentations();
            component.addRepresentation(data.representation, parameters);
            """,
        "effect":
        """
            if (data.effect==="spin"){
                state._stage.setSpin(true);
            } else if (data.effect==="rock"){
                state._stage.setRock(true);
            } else {
                state._stage.setSpin(false);
                state._stage.setRock(false);
            }
            """,
        "updateStage":
        """
            parameters = self.getParameters();
            state._stage.removeAllComponents()
            state._stage.loadFile(new Blob([data.object], {type: 'text/plain'}), { ext: data.extension}).then(function (component) {
              component.addRepresentation(data.representation, parameters);
              component.autoView();
            });
            """,
        "after_layout":
        """
            state._stage.handleResize();
            """,
    }

    __javascript__ = [
        "https://unpkg.com/[email protected]/dist/ngl.js",
    ]
Esempio n. 24
0
class LoadingStyler(param.Parameterized):
    """A utility that can be used to select and style the loading spinner"""

    spinner = param.ObjectSelector(default=DEFAULT_URL,
                                   objects=config.SPINNERS,
                                   doc="The loading spinner to use")
    spinner_height = param.Integer(50, bounds=(1, 100))
    background_rgb = param.Tuple((255, 255, 255))
    background_alpha = param.Number(0.5,
                                    bounds=(0.0, 1.0),
                                    step=0.01,
                                    doc="The background alpha")
    color = param.Color(config.DEFAULT_COLOR)
    style = param.String("",
                         doc="The CSS Style applied to the loading spinner")

    settings_panel = param.Parameter(
        doc="A panel containing the settings of the LoadingStyler")
    style_panel = param.Parameter(
        doc="An 'invisible' HTML pane containing the css style")

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

        self.settings_panel = pn.Param(
            self,
            parameters=[
                "spinner",
                "spinner_height",
                "background_alpha",
                "color",
                "style",
            ],
            widgets={
                "style": {
                    "type": pn.widgets.TextAreaInput,
                    "sizing_mode": "stretch_both",
                    "disabled": True,
                }
            },
        )

        self.style_panel = pn.pane.HTML(sizing_mode="fixed",
                                        width=0,
                                        height=0,
                                        margin=0)
        self._toggle_color()
        self._update_style()

    @property
    def _spinner_url(self):
        spinner = self.spinner
        if callable(spinner):
            return spinner(self.color)  # pylint: disable=not-callable
        return spinner

    @param.depends("spinner", watch=True)
    def _toggle_color(self):
        color_picker: pn.widgets.ColorPicker = [
            widget for widget in self.settings_panel
            if isinstance(widget, pn.widgets.ColorPicker)
        ][0]
        color_picker.disabled = not callable(self.spinner)

    @param.depends("spinner",
                   "spinner_height",
                   "color",
                   "background_rgb",
                   "background_alpha",
                   watch=True)
    def _update_style(self):
        self.style = f"""
.bk.pn-loading:before {{
background-image: url('{self._spinner_url}');
background-size: auto {self.spinner_height}%;
background-color: rgb({self.background_rgb[0]},{self.background_rgb[1]},{self.background_rgb[2]},{self.background_alpha});
}}"""

    @param.depends("style", watch=True)
    def _update_loading_spinner_css(self):
        self.style_panel.object = f"""<style>{self.style}</style>"""
Esempio n. 25
0
 class Q(param.Parameterized):
     q = param.Color('red', allow_named=False)
Esempio n. 26
0
class FastStyle(param.Parameterized):
    """
    The FastStyle class provides the different colors and icons used
    to style the Fast Templates.
    """

    accent_fill_active = param.Color(default="#E45A8C")
    accent_fill_hover = param.Color(default="#DF3874")
    accent_fill_rest = param.Color(default="#A01346")
    accent_foreground_active = param.Color(default="#BA1651")
    accent_foreground_cut = param.Color(default="#000000")
    accent_foreground_hover = param.Color(default="#7A0F35")
    accent_foreground_rest = param.Color(default="#A01346")

    neutral_outline_active = param.Color(default="#D6D6D6")
    neutral_outline_hover = param.Color(default="#979797")
    neutral_outline_rest = param.Color(default="#BEBEBE")

    accent_base_color = param.Color(default="#A01346")
    background_color = param.Color(default="#ffffff")
    collapsed_icon = param.String(default=COLLAPSED_SVG_ICON)
    expanded_icon = param.String(default=EXPANDED_SVG_ICON)
    color = param.Color(default="#00aa41")
    neutral_fill_card_rest = param.Color(default="#F7F7F7")
    neutral_focus = param.Color(default="#888888")
    neutral_foreground_rest = param.Color(default="#2B2B2B")

    header_background = param.Color(default="#00aa41")
    header_color = param.Color(default="#ffffff")
    font = param.String(default="Open Sans, sans-serif")
    font_url = param.String(default=FONT_URL)

    def create_bokeh_theme(self):
        """Returns a custom bokeh theme based on the style parameters

        Returns:
            Dict: A Bokeh Theme
        """

        return {
            "attrs": {
                "Figure": {
                    "background_fill_color": self.background_color,
                    "border_fill_color": self.neutral_fill_card_rest,
                    "border_fill_alpha": 0,
                    "outline_line_color": self.neutral_focus,
                    "outline_line_alpha": 0.5,
                    "outline_line_width": 1,
                },
                "Grid": {
                    "grid_line_color": self.neutral_focus,
                    "grid_line_alpha": 0.25
                },
                "Axis": {
                    "major_tick_line_alpha": 0,
                    "major_tick_line_color": self.neutral_foreground_rest,
                    "minor_tick_line_alpha": 0,
                    "minor_tick_line_color": self.neutral_foreground_rest,
                    "axis_line_alpha": 0,
                    "axis_line_color": self.neutral_foreground_rest,
                    "major_label_text_color": self.neutral_foreground_rest,
                    "major_label_text_font": self.font,
                    "major_label_text_font_size": "1.025em",
                    "axis_label_standoff": 10,
                    "axis_label_text_color": self.neutral_foreground_rest,
                    "axis_label_text_font": self.font,
                    "axis_label_text_font_size": "1.25em",
                    "axis_label_text_font_style": "normal",
                },
                "Legend": {
                    "spacing": 8,
                    "glyph_width": 15,
                    "label_standoff": 8,
                    "label_text_color": self.neutral_foreground_rest,
                    "label_text_font": self.font,
                    "label_text_font_size": "1.025em",
                    "border_line_alpha": 0.5,
                    "border_line_color": self.neutral_focus,
                    "background_fill_alpha": 0.25,
                    "background_fill_color": self.neutral_fill_card_rest,
                },
                "ColorBar": {
                    "title_text_color": self.neutral_foreground_rest,
                    "title_text_font": self.font,
                    "title_text_font_size": "1.025em",
                    "title_text_font_style": "normal",
                    "major_label_text_color": self.neutral_foreground_rest,
                    "major_label_text_font": self.font,
                    "major_label_text_font_size": "1.025em",
                    # "background_fill_color": FAST_DARK_75,
                    "major_tick_line_alpha": 0,
                    "bar_line_alpha": 0,
                },
                "Title": {
                    "text_color": self.neutral_foreground_rest,
                    "text_font": self.font,
                    "text_font_size": "1.15em",
                },
            }
        }
Esempio n. 27
0
 class Q(param.Parameterized):
     q = param.Color()
class ColorPalette(param.Parameterized):  # pylint: disable=too-many-instance-attributes
    """A Material Design Color Palette """

    color_50 = param.Color(default="#f3e5f6", precedence=0.0)
    color_100 = param.Color(default="#e1bee7", precedence=0.1)
    color_200 = param.Color(default="#ce93d8", precedence=0.2)
    color_300 = param.Color(default="#ba68c8", precedence=0.3)
    color_400 = param.Color(default="#ab47bc", precedence=0.4)
    color_500 = param.Color(default="#9c27b0", precedence=0.5)
    color_600 = param.Color(default="#9423a9", precedence=0.6)
    color_700 = param.Color(default="#8a1da0", precedence=0.7)
    color_800 = param.Color(default="#801797", precedence=0.8)
    color_900 = param.Color(default="#6e0e87", precedence=0.9)
    color_a100 = param.Color(default="#efb8ff", precedence=1.1)
    color_a200 = param.Color(default="#e485ff", precedence=1.2)
    color_a400 = param.Color(default="#d852ff", precedence=1.4)
    color_a700 = param.Color(default="#d238ff", precedence=1.7)

    contrast_50 = param.ObjectSelector(default=color.DARK_PRIMARY_TEXT,
                                       objects=color.PRIMARY_TEXTS,
                                       precedence=0.0)
    contrast_100 = param.ObjectSelector(default=color.DARK_PRIMARY_TEXT,
                                        objects=color.PRIMARY_TEXTS,
                                        precedence=0.1)
    contrast_200 = param.ObjectSelector(default=color.DARK_PRIMARY_TEXT,
                                        objects=color.PRIMARY_TEXTS,
                                        precedence=0.2)
    contrast_300 = param.ObjectSelector(default=color.DARK_PRIMARY_TEXT,
                                        objects=color.PRIMARY_TEXTS,
                                        precedence=0.3)
    contrast_400 = param.ObjectSelector(default=color.LIGHT_PRIMARY_TEXT,
                                        objects=color.PRIMARY_TEXTS,
                                        precedence=0.4)
    contrast_500 = param.ObjectSelector(default=color.LIGHT_PRIMARY_TEXT,
                                        objects=color.PRIMARY_TEXTS,
                                        precedence=0.5)
    contrast_600 = param.ObjectSelector(default=color.LIGHT_PRIMARY_TEXT,
                                        objects=color.PRIMARY_TEXTS,
                                        precedence=0.6)
    contrast_700 = param.ObjectSelector(default=color.LIGHT_PRIMARY_TEXT,
                                        objects=color.PRIMARY_TEXTS,
                                        precedence=0.7)
    contrast_800 = param.ObjectSelector(default=color.LIGHT_PRIMARY_TEXT,
                                        objects=color.PRIMARY_TEXTS,
                                        precedence=0.8)
    contrast_900 = param.ObjectSelector(default=color.LIGHT_PRIMARY_TEXT,
                                        objects=color.PRIMARY_TEXTS,
                                        precedence=0.9)
    contrast_a100 = param.ObjectSelector(default=color.DARK_PRIMARY_TEXT,
                                         objects=color.PRIMARY_TEXTS,
                                         precedence=1.1)
    contrast_a200 = param.ObjectSelector(default=color.DARK_PRIMARY_TEXT,
                                         objects=color.PRIMARY_TEXTS,
                                         precedence=1.2)
    contrast_a400 = param.ObjectSelector(default=color.DARK_PRIMARY_TEXT,
                                         objects=color.PRIMARY_TEXTS,
                                         precedence=1.4)
    contrast_a700 = param.ObjectSelector(default=color.LIGHT_PRIMARY_TEXT,
                                         objects=color.PRIMARY_TEXTS,
                                         precedence=1.7)

    @param.depends("color_500", watch=True)
    def _update_colors_from_color_500(self):
        colors = compute_colors(self.color_500)

        self.color_50 = colors["50"]
        self.color_100 = colors["100"]
        self.color_200 = colors["200"]
        self.color_300 = colors["300"]
        self.color_400 = colors["400"]
        # self.color_500 = colors["500"]
        self.color_600 = colors["600"]
        self.color_700 = colors["700"]
        self.color_800 = colors["800"]
        self.color_900 = colors["900"]
        self.color_a100 = colors["A100"]
        self.color_a200 = colors["A200"]
        self.color_a400 = colors["A400"]
        self.color_a700 = colors["A700"]

        self.contrast_50 = (color.LIGHT_PRIMARY_TEXT if is_dark(self.color_50)
                            else color.DARK_PRIMARY_TEXT)
        self.contrast_100 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_100) else color.DARK_PRIMARY_TEXT)
        self.contrast_200 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_200) else color.DARK_PRIMARY_TEXT)
        self.contrast_300 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_300) else color.DARK_PRIMARY_TEXT)
        self.contrast_400 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_400) else color.DARK_PRIMARY_TEXT)
        self.contrast_500 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_500) else color.DARK_PRIMARY_TEXT)
        self.contrast_600 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_600) else color.DARK_PRIMARY_TEXT)
        self.contrast_700 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_700) else color.DARK_PRIMARY_TEXT)
        self.contrast_800 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_800) else color.DARK_PRIMARY_TEXT)
        self.contrast_900 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_900) else color.DARK_PRIMARY_TEXT)
        self.contrast_a100 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_a100) else color.DARK_PRIMARY_TEXT)
        self.contrast_a200 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_a200) else color.DARK_PRIMARY_TEXT)
        self.contrast_a400 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_a400) else color.DARK_PRIMARY_TEXT)
        self.contrast_a700 = (color.LIGHT_PRIMARY_TEXT if is_dark(
            self.color_a700) else color.DARK_PRIMARY_TEXT)

    def editor(self) -> pn.Column:
        """Returns an editor from that enables the user to edit the Color Palette.

        Returns:
            [pn.Column]: An Color Palette Editor
        """
        return pn.Column(
            "## Color Palette Editor",
            pn.Param(
                self,
                show_name=False,
                parameters=COLOR_PARAMETERS,
            ),
        )

    def color_500_editor(self) -> pn.Column:
        """Returns an editor that enables the user to edit the Color 500.

        Returns:
            pn.Column: [description]
        """
        return pn.Column(
            "## Color Palette Editor",
            self.param.color_500,
            self.readonly_view(),
        )

    def to_html_table(self) -> str:
        """Returns a HTML string that shows the color palette"""
        return f"""\
<table style="width:100%;text-align:center"><tbody>
<tr style="background-color:{self.color_50};color:{self.contrast_50}"><td>50: </td><td>{self.color_50}</td></tr>
<tr style="background-color:{self.color_100};color:{self.contrast_100}"><td>100: </td><td>{self.color_100}</td></tr>
<tr style="background-color:{self.color_200};color:{self.contrast_200}"><td>200: </td><td>{self.color_200}</td></tr>
<tr style="background-color:{self.color_300};color:{self.contrast_300}"><td>300: </td><td>{self.color_300}</td></tr>
<tr style="background-color:{self.color_400};color:{self.contrast_400}"><td>400: </td><td>{self.color_400}</td></tr>
<tr style="background-color:{self.color_500};color:{self.contrast_500}"><td>500: </td><td>{self.color_500}</td></tr>
<tr style="background-color:{self.color_600};color:{self.contrast_600}"><td>600: </td><td>{self.color_600}</td></tr>
<tr style="background-color:{self.color_700};color:{self.contrast_700}"><td>700: </td><td>{self.color_700}</td></tr>
<tr style="background-color:{self.color_800};color:{self.contrast_800}"><td>800: </td><td>{self.color_800}</td></tr>
<tr style="background-color:{self.color_900};color:{self.contrast_900}"><td>900: </td><td>{self.color_900}</td></tr>
<tr style="background-color:{self.color_a100};color:{self.contrast_a100}"><td>A100: </td><td>{self.color_a100}</td></tr>
<tr style="background-color:{self.color_a200};color:{self.contrast_a200}"><td>A200: </td><td>{self.color_a200}</td></tr>
<tr style="background-color:{self.color_a400};color:{self.contrast_a400}"><td>A400: </td><td>{self.color_a400}</td></tr>
<tr style="background-color:{self.color_a700};color:{self.contrast_a700}"><td>A700: </td><td>{self.color_a700}</td></tr>
</tbody></table>"""

    def readonly_view(self) -> pn.Column:
        """Returns a read only view of the Color Palette

        Returns:
            pn.Column: A read only view
        """
        return pn.Column("## Color Palette",
                         pn.pane.HTML(self.to_html_table()))

    def __eq__(self, other):
        return self.name == other.name
Esempio n. 29
0
class VTKVolume(PaneBase):

    max_data_size = param.Number(default=(256**3) * 2 / 1e6,
                                 doc="""
        Maximum data size transfert allowed without subsampling""")

    origin = param.Tuple(default=None, length=3, allow_None=True)

    spacing = param.Tuple(default=(1, 1, 1),
                          length=3,
                          doc="""
        Distance between voxel in each direction""")

    render_background = param.Color(default='#52576e',
                                    doc="""
        Allows to specify the background color of the 3D rendering. The value must be specified
        as an hexadecimal color string
    """)

    colormap = param.Selector(default='erdc_rainbow_bright',
                              objects=PRESET_CMAPS,
                              doc="""
        Name of the colormap used to transform pixel value in color
    """)

    rescale = param.Boolean(default=False,
                            doc="""
        If set to True the colormap is rescale beween min and max value of the non transparent pixels
        Else the full range of the pixel values are used
    """)

    shadow = param.Boolean(default=True,
                           doc="""
        If set to False, then the mapper for the volume will not perform shading
        computations, it is the same as setting ambient=1, diffuse=0, specular=0
    """)

    sampling = param.Number(default=0.4,
                            bounds=(0, 1),
                            step=1e-2,
                            doc="""
        Parameter to adjust the distance between samples used for rendering. The lower the value is
        the more precise is the representation but it is more computationnaly intensive
    """)

    edge_gradient = param.Number(default=0.4,
                                 bounds=(0, 1),
                                 step=1e-2,
                                 doc="""
        Parameter to adjust the opacity of the volume based on the gradient between voxels
    """)

    interpolation = param.Selector(
        default='fast_linear',
        objects=['fast_linear', 'linear', 'nearest'],
        doc="""
        interpolation type for sampling a volume. `nearest` interpolation will snap to the closest voxel,
        `linear` will perform trilinear interpolation to compute a scalar value from surrounding voxels.
        `fast_linear` under WebGL 1 will perform bilinear interpolation on X and Y but use nearest
        for Z. This is slightly faster than full linear at the cost of no Z axis linear interpolation.
    """)

    ambient = param.Number(default=0.2,
                           step=1e-2,
                           doc="""
        Value to control the ambient lighting. It is the light an object gives even in the absence
        of strong light. It is constant in all directions.
    """)

    diffuse = param.Number(default=0.7,
                           step=1e-2,
                           doc="""
        Value to control the diffuse Lighting. It relies on both the light direction and the
        object surface normal.
    """)

    specular = param.Number(default=0.3,
                            step=1e-2,
                            doc="""
        Value to control specular lighting. It is the light reflects back toward the camera when hitting the
        object
    """)

    specular_power = param.Number(default=8.,
                                  doc="""
        Specular power refers to how much light is reflected in a mirror like fashion,
        rather than scattered randomly in a diffuse manner
    """)

    slice_i = param.Integer(per_instance=True,
                            doc="""
        Integer parameter to control the position of the slice normal to the X direction
    """)

    slice_j = param.Integer(per_instance=True,
                            doc="""
        Integer parameter to control the position of the slice normal to the Y direction
    """)

    slice_k = param.Integer(per_instance=True,
                            doc="""
        Integer parameter to control the position of the slice normal to the Z direction
    """)

    display_volume = param.Boolean(default=True,
                                   doc="""
        If set to True, the 3D respresentation of the volume is displayed using ray casting
    """)

    display_slices = param.Boolean(default=False,
                                   doc="""
        If set to true, the orthgonal slices in the three (X, Y, Z) directions are displayed.
        Postition of each slice can be controlled using slice_(i,j,k) parameters
    """)

    _serializers = {}

    _rename = {'max_data_size': None, 'spacing': None, 'origin': None}

    _updates = True

    def __init__(self, object=None, **params):
        super(VTKVolume, self).__init__(object, **params)
        self._sub_spacing = self.spacing
        self._volume_data = self._get_volume_data()
        if self._volume_data:
            self.param.slice_i.bounds = (0, self._volume_data['dims'][0] - 1)
            self.slice_i = (self._volume_data['dims'][0] - 1) // 2
            self.param.slice_j.bounds = (0, self._volume_data['dims'][1] - 1)
            self.slice_j = (self._volume_data['dims'][1] - 1) // 2
            self.param.slice_k.bounds = (0, self._volume_data['dims'][2] - 1)
            self.slice_k = (self._volume_data['dims'][2] - 1) // 2

    @classmethod
    def applies(cls, obj):
        if ((isinstance(obj, np.ndarray) and obj.ndim == 3)
                or any([isinstance(obj, k) for k in cls._serializers.keys()])):
            return True
        elif 'vtk' not in sys.modules:
            return False
        else:
            import vtk
            return isinstance(obj, vtk.vtkImageData)

    def _get_model(self, doc, root=None, parent=None, comm=None):
        """
        Should return the bokeh model to be rendered.
        """
        if 'panel.models.vtk' not in sys.modules:
            if isinstance(comm, JupyterComm):
                self.param.warning(
                    'VTKVolumePlot was not imported on instantiation '
                    'and may not render in a notebook. Restart '
                    'the notebook kernel and ensure you load '
                    'it as part of the extension using:'
                    '\n\npn.extension(\'vtk\')\n')
            from ...models.vtk import VTKVolumePlot
        else:
            VTKVolumePlot = getattr(sys.modules['panel.models.vtk'],
                                    'VTKVolumePlot')

        props = self._process_param_change(self._init_properties())
        volume_data = self._volume_data

        model = VTKVolumePlot(data=volume_data, **props)
        if root is None:
            root = model
        self._link_props(model, ['colormap'], doc, root, comm)
        self._models[root.ref['id']] = (model, parent)
        return model

    def _update_object(self, ref, doc, root, parent, comm):
        self._legend = None
        super(VTKVolume, self)._update_object(ref, doc, root, parent, comm)

    def _init_properties(self):
        return {
            k: v
            for k, v in self.param.get_param_values()
            if v is not None and k not in
            ['default_layout', 'object', 'max_data_size', 'spacing', 'origin']
        }

    def _update(self, model):
        self._volume_data = self._get_volume_data()
        if self._volume_data:
            self.param.slice_i.bounds = (0, self._volume_data['dims'][0] - 1)
            self.slice_i = (self._volume_data['dims'][0] - 1) // 2
            self.param.slice_j.bounds = (0, self._volume_data['dims'][1] - 1)
            self.slice_j = (self._volume_data['dims'][1] - 1) // 2
            self.param.slice_k.bounds = (0, self._volume_data['dims'][2] - 1)
            self.slice_k = (self._volume_data['dims'][2] - 1) // 2
        model.data = self._volume_data

    @classmethod
    def register_serializer(cls, class_type, serializer):
        """
        Register a seriliazer for a given type of class.
        A serializer is a function which take an instance of `class_type`
        (like a vtk.vtkImageData) as input and return a numpy array of the data
        """
        cls._serializers.update({class_type: serializer})

    def _volume_from_array(self, sub_array):
        return dict(
            buffer=base64encode(
                sub_array.ravel(
                    order='F' if sub_array.flags['F_CONTIGUOUS'] else 'C')),
            dims=sub_array.shape
            if sub_array.flags['F_CONTIGUOUS'] else sub_array.shape[::-1],
            spacing=self._sub_spacing
            if sub_array.flags['F_CONTIGUOUS'] else self._sub_spacing[::-1],
            origin=self.origin,
            data_range=(sub_array.min(), sub_array.max()),
            dtype=sub_array.dtype.name)

    def _get_volume_data(self):
        if self.object is None:
            return None
        elif isinstance(self.object, np.ndarray):
            return self._volume_from_array(self._subsample_array(self.object))
        else:
            available_serializer = [
                v for k, v in self._serializers.items()
                if isinstance(self.object, k)
            ]
            if not available_serializer:
                import vtk
                from vtk.util import numpy_support

                def volume_serializer(imageData):
                    array = numpy_support.vtk_to_numpy(
                        imageData.GetPointData().GetScalars())
                    dims = imageData.GetDimensions()[::-1]
                    self.spacing = imageData.GetSpacing()[::-1]
                    self.origin = imageData.GetOrigin()
                    return self._volume_from_array(
                        self._subsample_array(array.reshape(dims, order='C')))

                self.register_serializer(vtk.vtkImageData, volume_serializer)
                serializer = volume_serializer
            else:
                serializer = available_serializer[0]
            return serializer(self.object)

    def _subsample_array(self, array):
        original_shape = array.shape
        spacing = self.spacing
        extent = tuple(
            (o_s - 1) * s for o_s, s in zip(original_shape, spacing))
        dim_ratio = np.cbrt(
            (np.prod(original_shape) / 1e6) / self.max_data_size)
        max_shape = tuple(int(o_s / dim_ratio) for o_s in original_shape)
        dowsnscale_factor = [
            max(o_s, m_s) / m_s for m_s, o_s in zip(max_shape, original_shape)
        ]

        if any([d_f > 1 for d_f in dowsnscale_factor]):
            try:
                import scipy.ndimage as nd
                sub_array = nd.interpolation.zoom(
                    array,
                    zoom=[1 / d_f for d_f in dowsnscale_factor],
                    order=0)
            except ImportError:
                sub_array = array[::int(np.ceil(dowsnscale_factor[0])), ::int(
                    np.ceil(dowsnscale_factor[1])
                ), ::int(np.ceil(dowsnscale_factor[2]))]
            self._sub_spacing = tuple(e / (s - 1)
                                      for e, s in zip(extent, sub_array.shape))
        else:
            sub_array = array
            self._sub_spacing = self.spacing
        return sub_array
Esempio n. 30
0
 class Q(param.Parameterized):
     q = param.Color(allow_named=True)