Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow gaps between histogram bars and fix axis labels #72

Merged
merged 5 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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