Skip to content

Commit

Permalink
Merge pull request #72 from Carifio24/histogram-viewer-gaps
Browse files Browse the repository at this point in the history
Histogram viewer gaps and axis label fix
  • Loading branch information
Carifio24 authored Jun 24, 2024
2 parents b9fc9f0 + 03c8eb6 commit 62385f3
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 4 deletions.
19 changes: 19 additions & 0 deletions doc/PlotlyViewerExample.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,25 @@
"# viewer = app.new_data_viewer(PlotlyHistogramView, data=data)"
]
},
{
"cell_type": "markdown",
"id": "26be6106-c61a-4d84-82e3-136ccfcee588",
"metadata": {},
"source": [
"You can adjust whether there are gaps between the bars and, if so, what fraction of the plot they occupy"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "821b6397-80e2-443c-b6c3-50bf954abbf2",
"metadata": {},
"outputs": [],
"source": [
"histogram_viewer.state.gaps = True\n",
"histogram_viewer.state.gap_fraction = 0.15"
]
},
{
"cell_type": "markdown",
"id": "588347a7-8f4d-4f47-9838-a4a2e4106b02",
Expand Down
4 changes: 2 additions & 2 deletions glue_plotly/viewers/common/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ def axis_y(self):
return self.figure.layout.yaxis

def update_x_axislabel(self, label):
self.axis_x['title'] = label
self.axis_x['title'].update(text=label)

def update_y_axislabel(self, label):
self.axis_y['title'] = label
self.axis_y['title'].update(text=label)

def _update_selection_layer_bounds(self):
x0 = 0.5 * (self.state.x_min + self.state.x_max)
Expand Down
17 changes: 17 additions & 0 deletions glue_plotly/viewers/histogram/state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from glue.viewers.histogram.state import DDCProperty, HistogramViewerState


__all__ = ["PlotlyHistogramViewerState"]


class PlotlyHistogramViewerState(HistogramViewerState):

gaps = DDCProperty(False, docstring='Whether to include gaps between histogram bars')
gap_fraction = DDCProperty(0.15,
docstring='The gap fraction if using gaps. For example, '
'0 means that no gap between bars, 0.5 means '
'that the bars and gaps are evenly sized, and 1 '
'means that the entire bar mark is gap.')

def __init__(self, **kwargs):
super().__init__(**kwargs)
Empty file.
77 changes: 77 additions & 0 deletions glue_plotly/viewers/histogram/tests/test_viewer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from glue.core import Data
from glue_jupyter import JupyterApplication
from plotly.graph_objects import Bar

from glue_plotly.common import DEFAULT_FONT
from glue_plotly.viewers.histogram import PlotlyHistogramView


class TestHistogramViewer:

def setup_method(self, method):
self.data = Data(label="histogram", x=[1, 1, 1, 2, 2, 3, 3, 3, 4, 6, 6])
self.app = JupyterApplication()
self.app.session.data_collection.append(self.data)
self.viewer = self.app.new_data_viewer(PlotlyHistogramView)
self.viewer.add_data(self.data)

viewer_state = self.viewer.state
viewer_state.x_min = 0.5
viewer_state.hist_x_min = 0.5
viewer_state.x_max = 6.5
viewer_state.hist_x_max = 6.5
viewer_state.hist_n_bin = 6
viewer_state.y_min = 0
viewer_state.y_max = 5
viewer_state.x_axislabel = 'X Axis'
viewer_state.y_axislabel = 'Y Axis'
viewer_state.normalize = False

self.layer = self.viewer.layers[0]
self.layer.state.color = "#abcdef"
self.layer.state.alpha = 0.75

def teardown_method(self, method):
self.viewer = None
self.app = None

def test_basic(self):
assert len(self.viewer.layers) == 1
traces = list(self.layer.traces())
assert len(traces) == 1
bars = traces[0]
assert isinstance(bars, Bar)
assert bars.marker.color == "#abcdef"
assert bars.marker.opacity == 0.75
assert bars.x == tuple(range(1, 7))
expected_y = [3, 2, 3, 1, 0, 2]
assert all(a == b for a, b in zip(bars.y, expected_y))

def test_axes(self):
x_axis = self.viewer.figure.layout.xaxis
y_axis = self.viewer.figure.layout.yaxis

assert x_axis.title.text == 'X Axis'
assert y_axis.title.text == 'Y Axis'
assert x_axis.type == 'linear'
assert y_axis.type == 'linear'

assert x_axis.range == (0.5, 6.5)
assert y_axis.range == (0, 5)

assert all(f.family == DEFAULT_FONT for f in
(x_axis.title.font, x_axis.tickfont, y_axis.title.font, y_axis.tickfont))

common_items = dict(showgrid=False, showline=False, mirror=True, rangemode='normal',
zeroline=False, showspikes=False, showticklabels=True)
for axis in x_axis, y_axis:
assert all(axis[key] == value for key, value in common_items.items())

def test_gaps(self):
assert self.viewer.figure.layout.bargap == 0
self.viewer.state.gaps = True
assert self.viewer.figure.layout.bargap == 0.15
self.viewer.state.gap_fraction = 0.36
assert self.viewer.figure.layout.bargap == 0.36
self.viewer.state.gaps = False
assert self.viewer.figure.layout.bargap == 0
10 changes: 8 additions & 2 deletions glue_plotly/viewers/histogram/viewer.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from glue.core.subset import XRangeROI, roi_to_subset_state
from glue.viewers.histogram.state import HistogramViewerState
from glue_plotly.common import base_layout_config, base_rectilinear_axis
from glue_plotly.viewers import PlotlyBaseView
from glue_plotly.viewers.histogram.layer_artist import PlotlyHistogramLayerArtist

from glue_jupyter.registries import viewer_registry
from glue_jupyter.common.state_widgets.layer_histogram import HistogramLayerStateWidget
from glue_jupyter.common.state_widgets.viewer_histogram import HistogramViewerStateWidget
from glue_plotly.viewers.histogram.state import PlotlyHistogramViewerState


__all__ = ["PlotlyHistogramView"]
Expand All @@ -22,7 +22,7 @@ class PlotlyHistogramView(PlotlyBaseView):
allow_duplicate_data = False
allow_duplicate_subset = False

_state_cls = HistogramViewerState
_state_cls = PlotlyHistogramViewerState
_options_cls = HistogramViewerStateWidget
_data_artist_cls = PlotlyHistogramLayerArtist
_subset_artist_cls = PlotlyHistogramLayerArtist
Expand All @@ -32,6 +32,8 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.state.add_callback('x_att', self._update_axes)
self.state.add_callback('normalize', self._update_axes)
self.state.add_callback('gaps', self._gaps_changed)
self.state.add_callback('gap_fraction', self._gaps_changed)
self._update_axes()

def _create_layout_config(self):
Expand All @@ -54,6 +56,10 @@ def _update_axes(self, *args):
else:
self.state.y_axislabel = 'Number'

def _gaps_changed(self, *args):
gap = self.state.gap_fraction if self.state.gaps else 0
self.figure.layout.update(bargap=gap)

def _roi_to_subset_state(self, roi):
return roi_to_subset_state(roi, x_att=self.state.x_att)

Expand Down

0 comments on commit 62385f3

Please sign in to comment.