Skip to content

Commit

Permalink
Merge pull request #4153 from stephenpardy/handle_spacing_with_spec
Browse files Browse the repository at this point in the history
Adding some rounding and error messaging for subplots
  • Loading branch information
alexcjohnson authored May 5, 2023
2 parents 5b65329 + bf7f6de commit 59ffd90
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Fixed
- Fixed another compatibility issue with Pandas 2.0, just affecting `px.*(line_close=True)` [[#4190](https://github.com/plotly/plotly.py/pull/4190)]
- Added some rounding to the `make_subplots` function to handle situations where the user-input specs cause the domain to exceed 1 by small amounts https://github.com/plotly/plotly.py/pull/4153

## [5.14.1] - 2023-04-05

Expand Down
47 changes: 40 additions & 7 deletions packages/python/plotly/plotly/_subplots.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,6 @@ def _check_hv_spacing(dimsize, spacing, name, dimvarname, dimname):
# Loop through specs -- (r, c) <-> (row, col)
for r, spec_row in enumerate(specs):
for c, spec in enumerate(spec_row):

if spec is None: # skip over None cells
continue

Expand Down Expand Up @@ -702,6 +701,46 @@ def _check_hv_spacing(dimsize, spacing, name, dimvarname, dimname):
else:
y_s = grid[r_spanned][c][1] + spec["b"]
y_e = grid[r][c][1] + heights[-1 - r] - spec["t"]

if y_s < 0.0:
# round for values very close to one
# handles some floating point errors
if y_s > -0.01:
y_s = 0.0
else:
raise Exception(
"A combination of the 'b' values, heights, and "
"number of subplots too large for this subplot grid."
)
if y_s > 1.0:
# round for values very close to one
# handles some floating point errors
if y_s < 1.01:
y_s = 1.0
else:
raise Exception(
"A combination of the 'b' values, heights, and "
"number of subplots too large for this subplot grid."
)

if y_e < 0.0:
if y_e > -0.01:
y_e = 0.0
else:
raise Exception(
"A combination of the 't' values, heights, and "
"number of subplots too large for this subplot grid."
)

if y_e > 1.0:
if y_e < 1.01:
y_e = 1.0
else:
raise Exception(
"A combination of the 't' values, heights, and "
"number of subplots too large for this subplot grid."
)

y_domain = [y_s, y_e]

list_of_domains.append(x_domain)
Expand All @@ -726,7 +765,6 @@ def _check_hv_spacing(dimsize, spacing, name, dimvarname, dimname):
insets_ref = [None for inset in range(len(insets))] if insets else None
if insets:
for i_inset, inset in enumerate(insets):

r = inset["cell"][0] - 1
c = inset["cell"][1] - 1

Expand Down Expand Up @@ -1052,7 +1090,6 @@ def _subplot_type_for_trace_type(trace_type):


def _validate_coerce_subplot_type(subplot_type):

# Lowercase subplot_type
orig_subplot_type = subplot_type
subplot_type = subplot_type.lower()
Expand Down Expand Up @@ -1200,7 +1237,6 @@ def _build_subplot_title_annotations(


def _build_grid_str(specs, grid_ref, insets, insets_ref, row_seq):

# Compute rows and columns
rows = len(specs)
cols = len(specs[0])
Expand Down Expand Up @@ -1257,7 +1293,6 @@ def _pad(s, cell_len=cell_len):
# Loop through specs, fill in _tmp
for r, spec_row in enumerate(specs):
for c, spec in enumerate(spec_row):

ref = grid_ref[r][c]
if ref is None:
if _tmp[r][c] == "":
Expand Down Expand Up @@ -1339,7 +1374,6 @@ def _pad(s, cell_len=cell_len):


def _set_trace_grid_reference(trace, layout, grid_ref, row, col, secondary_y=False):

if row <= 0:
raise Exception(
"Row value is out of range. " "Note: the starting cell is (1, 1)"
Expand Down Expand Up @@ -1461,7 +1495,6 @@ def _get_grid_subplot(fig, row, col, secondary_y=False):


def _get_subplot_ref_for_trace(trace):

if "domain" in trace:
return SubplotRef(
subplot_type="domain",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,22 @@ def test_specs_padding(self):
)
self.assertEqual(fig.to_plotly_json(), expected.to_plotly_json())

def test_specs_rounding_rounds_down(self):
n_subplots = 8
padding_size = 0.2

specs = []
for _ in range(n_subplots):
specs.append([{"b": padding_size / 2.0, "t": padding_size / 2.0}])

fig = subplots.make_subplots(rows=n_subplots, specs=specs)
self.assertTrue(
all(
fig.layout[f"yaxis{i if i > 1 else ''}"]["domain"][0] <= 1.0
for i in range(1, n_subplots + 1)
)
)

def test_specs_padding_bottom_left(self):
expected = Figure(
data=Data(),
Expand Down Expand Up @@ -1592,7 +1608,6 @@ def test_large_columns_no_errors(self):
)

def test_row_width_and_column_width(self):

expected = Figure(
{
"data": [],
Expand Down Expand Up @@ -1680,7 +1695,6 @@ def test_row_width_and_column_width(self):
self.assertEqual(fig.to_plotly_json(), expected.to_plotly_json())

def test_row_width_and_shared_yaxes(self):

expected = Figure(
{
"data": [],
Expand Down

0 comments on commit 59ffd90

Please sign in to comment.