def show_indexed_timeseries_plotly(timeseries: TimeSeries, istart=None, istop=None, fig: go.FigureWidget = None, col=None, row=None, zero_start=False, xlabel='time (s)', ylabel=None, title=None, neurodata_vis_spec=None, **kwargs): if ylabel is None and timeseries.unit: ylabel = timeseries.unit tt = get_timeseries_tt(timeseries, istart=istart, istop=istop) if zero_start: tt = tt - tt[0] data, unit = get_timeseries_in_units(timeseries, istart=istart, istop=istop) trace_kwargs = dict() if col is not None or row is not None: trace_kwargs.update(row=row, col=col) fig.add_trace(x=tt, y=data, **trace_kwargs, **kwargs) layout_kwargs = dict(xaxis_title=xlabel) if ylabel is not None: layout_kwargs.update(yaxis_title=ylabel) if title is not None: layout_kwargs.update(title=title) fig.update_layout(**layout_kwargs)
def show_indexed_timeseries_plotly( timeseries: TimeSeries, istart: int = 0, istop: int = None, time_window: list = None, trace_range: list = None, offsets=None, fig: go.FigureWidget = None, col=None, row=None, zero_start=False, scatter_kwargs: dict = None, figure_kwargs: dict = None, ): if istart != 0 or istop is not None: if time_window is not None: raise ValueError( "input either time window or istart/stop but not both") if not (0 <= istart < timeseries.data.shape[0] and (istop is None or 0 < istop <= timeseries.data.shape[0])): raise ValueError("enter correct istart/stop values") t_istart = istart t_istop = istop elif time_window is not None: t_istart = timeseries_time_to_ind(timeseries, time_window[0]) t_istop = timeseries_time_to_ind(timeseries, time_window[1]) else: t_istart = istart t_istop = istop tt = get_timeseries_tt(timeseries, istart=t_istart, istop=t_istop) data, unit = get_timeseries_in_units(timeseries, istart=t_istart, istop=t_istop) if len(data.shape) == 1: data = data[:, np.newaxis] if trace_range is not None: if not (0 <= trace_range[0] < data.shape[1] and 0 < trace_range[1] <= data.shape[1]): raise ValueError("enter correct trace range") trace_istart = trace_range[0] trace_istop = trace_range[1] else: trace_istart = 0 trace_istop = data.shape[1] if offsets is None: offsets = np.zeros(trace_istop - trace_istart) if zero_start: tt = tt - tt[0] scatter_kwargs = dict() if scatter_kwargs is None else scatter_kwargs if fig is None: fig = go.FigureWidget(make_subplots(rows=1, cols=1)) row = 1 if row is None else row col = 1 if col is None else col for i, trace_id in enumerate(range(trace_istart, trace_istop)): fig.add_trace( go.Scattergl(x=tt, y=data[:, trace_id] + offsets[i], mode="lines", **scatter_kwargs), row=row, col=col, ) input_figure_kwargs = dict( xaxis=dict(title_text="time (s)", range=[tt[0], tt[-1]]), yaxis=dict(title_text=unit if unit is not None else None), title=timeseries.name, ) if figure_kwargs is None: figure_kwargs = dict() input_figure_kwargs.update(figure_kwargs) fig.update_xaxes(input_figure_kwargs.pop("xaxis"), row=row, col=col) fig.update_yaxes(input_figure_kwargs.pop("yaxis"), row=row, col=col) fig.update_layout(**input_figure_kwargs) return fig
class PapayaConfigWidget(VBox): """A widget that displays widgets to adjust NLPapayaViewer image parameters.""" lut_options = [ "Grayscale", "Red Overlay", "Green Overlay", "Blue Overlay", "Gold", "Spectrum", "Overlay (Positives)", "Overlay (Negatives)", ] def __init__(self, viewer, *args, **kwargs): """ Parameters ---------- viewer: NlPapayaViewer associated viewer. """ super().__init__(*args, **kwargs) self._viewer = viewer self._init_widgets() self.children = [ VBox([ VBox( [self._hist], layout=Layout( height="auto", margin="0px 0px 0px 0px", padding="5px 5px 5px 5px", ), ), VBox( [ self._alpha, self._lut, self._nlut, self._min, self._minp, self._max, self._maxp, self._sym, ], layout=Layout(width="230px"), ), ]) ] def _init_widgets(self): """Initializes all configuration widgets. Possible image config parameters are:""" layout = Layout(width="200px", max_width="200px") self._alpha = FloatSlider( value=1, min=0, max=1.0, step=0.1, description="alpha:", description_tooltip="Overlay image alpha level (0 to 1).", disabled=False, continuous_update=True, orientation="horizontal", readout=True, readout_format=".1f", layout=layout, ) self._lut = Dropdown( options=PapayaConfigWidget.lut_options, value="Red Overlay", description="lut:", description_tooltip="The color table name.", layout=layout, ) self._nlut = Dropdown( options=PapayaConfigWidget.lut_options, value="Red Overlay", description="negative-lut:", description_tooltip= "The color table name used by the negative side of the parametric pair.", layout=layout, ) self._min = FloatText( value=None, description="min:", description_tooltip="The display range minimum.", step=0.01, continuous_update=True, disabled=False, layout=layout, ) self._minp = BoundedFloatText( value=None, min=0, max=100, step=1, continuous_update=True, description="min %:", description_tooltip= "The display range minimum as a percentage of image max.", disabled=False, layout=layout, ) self._max = FloatText( value=None, description="max:", description_tooltip="The display range maximum.", step=0.01, continuous_update=True, disabled=False, layout=layout, ) self._maxp = BoundedFloatText( value=None, min=0, max=100, step=1, continuous_update=True, description="max %:", description_tooltip= "The display range minimum as a percentage of image max.", disabled=False, layout=layout, ) self._sym = Checkbox( value=False, description="symmetric", description_tooltip= "When selected, sets the negative range of a parametric pair to the same size as the positive range.", disabled=False, layout=layout, ) # figure to display histogram of image data fig = Figure() fig.update_layout( height=300, margin=dict(l=15, t=15, b=15, r=15, pad=4), showlegend=True, legend_orientation="h", ) self._hist = FigureWidget(fig) self._hist.add_trace( Histogram(x=[], name="All image data", visible="legendonly")) self._hist.add_trace(Histogram(x=[], name="Image data without 0s")) self._handlers = defaultdict() def _set_values(self, config, range, data): """Sets config values from the specified `config` and creates histogram for `data`. Parameters ---------- config : dict configuration parameters for the image. Possible keywords are: alpha : int the overlay image alpha level (0 to 1). lut : str the color table name. negative_lut : str the color table name used by the negative side of the parametric pair. max : int the display range maximum. maxPercent : int the display range maximum as a percentage of image max. min : int the display range minimum. minPercent : int the display range minimum as a percentage of image min. symmetric : bool if true, sets the negative range of a parametric pair to the same size as the positive range. range: float range of image values. data: [] flattened image data. """ self._alpha.value = config.get("alpha", 1) self._lut.value = config.get("lut", PapayaConfigWidget.lut_options[1]) self._nlut.value = config.get("negative_lut", PapayaConfigWidget.lut_options[1]) self._min.value = config.get("min", 0) self._minp.value = self._get_per_from_value(range, config.get("min", 0)) self._max.value = config.get("max", 0.1) self._maxp.value = self._get_per_from_value(range, config.get("max", 0.1)) self._sym.value = config.get("symmetric", "false") == "true" # set histogram data self._hist.data[0].x = data # leave out 0 values self._hist.data[1].x = [] if (data == [] or data is None) else data[data != 0] def _add_handlers(self, image): """Add config widget event handlers to change the config values for the specified `image`. Parameters ---------- image: neurolang_ipywidgets.PapayaImage image whose config values will be viewed/modified using this config widget. """ # Dropdown does not support resetting event handlers after Dropdown.unobserve_all is called # So handlers are stored to be removed individually # github issue https://github.com/jupyter-widgets/ipywidgets/issues/1868 self._handlers["alpha"] = partial(self._config_changed, image=image, name="alpha") self._handlers["lut"] = partial(self._config_changed, image=image, name="lut") self._handlers["nlut"] = partial(self._config_changed, image=image, name="negative_lut") self._handlers["min"] = partial(self._config_changed, image=image, name="min") self._handlers["minp"] = partial(self._set_min_max, image=image, name="minPercent") self._handlers["max"] = partial(self._config_changed, image=image, name="max") self._handlers["maxp"] = partial(self._set_min_max, image=image, name="maxPercent") self._handlers["sym"] = partial(self._config_bool_changed, image=image, name="symmetric") self._alpha.observe(self._handlers["alpha"], names="value") self._lut.observe(self._handlers["lut"], names="value") self._nlut.observe(self._handlers["nlut"], names="value") self._min.observe(self._handlers["min"], names="value") self._minp.observe(self._handlers["minp"], names="value") self._max.observe(self._handlers["max"], names="value") self._maxp.observe(self._handlers["maxp"], names="value") self._sym.observe(self._handlers["sym"], names="value") def _remove_handlers(self): """Removes all event handlers set for the config widgets.""" if len(self._handlers): self._alpha.unobserve(self._handlers["alpha"], names="value") self._lut.unobserve(self._handlers["lut"], names="value") self._nlut.unobserve(self._handlers["nlut"], names="value") self._min.unobserve(self._handlers["min"], names="value") self._minp.unobserve(self._handlers["minp"], names="value") self._max.unobserve(self._handlers["max"], names="value") self._maxp.unobserve(self._handlers["maxp"], names="value") self._sym.unobserve(self._handlers["sym"], names="value") self._handlers = defaultdict() @debounce(0.5) def _config_changed(self, change, image, name): if name == "min": self._minp.unobserve(self._handlers["minp"], names="value") self._minp.value = self._get_per_from_value( image.range, change.new) self._minp.observe(self._handlers["minp"], names="value") elif name == "max": self._maxp.unobserve(self._handlers["maxp"], names="value") self._maxp.value = self._get_per_from_value( image.range, change.new) self._maxp.observe(self._handlers["maxp"], names="value") self._set_config(image, name, change.new) @debounce(0.5) def _set_min_max(self, change, image, name): if name == "minPercent": self._min.unobserve(self._handlers["min"], names="value") self._min.value = self._get_value_from_per(image.range, change.new) self._set_config(image, "min", self._min.value) self._min.observe(self._handlers["min"], names="value") elif name == "maxPercent": self._max.unobserve(self._handlers["max"], names="value") self._max.value = self._get_value_from_per(image.range, change.new) self._set_config(image, "max", self._max.value) self._max.observe(self._handlers["max"], names="value") def _config_bool_changed(self, change, image, name): value = "false" if change.new: value = "true" self._set_config(image, name, value) def _set_config(self, image, key, value): image.config[key] = value self._viewer.set_images() def _get_per_from_value(self, range, value): return round(value * 100 / range, 0) def _get_value_from_per(self, range, per): return round(per * range / 100, 2) def set_image(self, image): """Sets the image whose config values will be viewed/modified using this config widget. If image is `None`, all config values are reset. Parameters ---------- image: neurolang_ipywidgets.PapayaImage image whose config values will be viewed/modified using this config widget. """ if image: self._remove_handlers() self._set_values(image.config, image.range, image.image.get_fdata().flatten()) self._add_handlers(image) else: self.reset() def reset(self): """Resets values for all config widgets.""" self._remove_handlers() self._set_values({}, 100, []) self.layout.visibility = "hidden"