Skip to content

Commit 8e663af

Browse files
authored
Merge branch 'main' into doc-prod-to-main
2 parents c1a1958 + 389158a commit 8e663af

File tree

6 files changed

+115
-8
lines changed

6 files changed

+115
-8
lines changed

CHANGELOG.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5-
## Unreleased
5+
## [6.2.0] - 2025-06-26
66

7+
### Added
8+
- Add SRI (Subresource Integrity) hash support for CDN script tags when using `include_plotlyjs='cdn'`. This enhances security by ensuring browser verification of CDN-served plotly.js files [[#5165](https://github.com/plotly/plotly.py/pull/5165)] (with thanks to @ddworken)
9+
10+
### Fixed
11+
- Allow setting Plotly.js path via `pio.defaults` [[#5207](https://github.com/plotly/plotly.py/pull/5207)]
12+
13+
### Changed
14+
- Refactor validation code to reduce bundle size [[#5214](https://github.com/plotly/plotly.py/pull/5214)] (with thanks to @bmaranville)
715
- Add deprecation warnings when using Kaleido v0 or deprecated image export features [[#5177](https://github.com/plotly/plotly.py/pull/5236)]
816

917
## [6.1.2] - 2025-05-27
@@ -24,9 +32,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
2432
- Add support for Kaleido>=v1.0.0 for image generation [[#5062](https://github.com/plotly/plotly.py/pull/5062), [#5177](https://github.com/plotly/plotly.py/pull/5177)]
2533
- Reduce package bundle size by 18-24% via changes to code generation [[#4978](https://github.com/plotly/plotly.py/pull/4978)]
2634

27-
### Added
28-
- Add SRI (Subresource Integrity) hash support for CDN script tags when using `include_plotlyjs='cdn'`. This enhances security by ensuring browser verification of CDN-served plotly.js files [[#PENDING](https://github.com/plotly/plotly.py/pull/PENDING)]
29-
3035
### Fixed
3136
- Fix third-party widget display issues in v6 [[#5102](https://github.com/plotly/plotly.py/pull/5102)]
3237
- Add handling for case where `jupyterlab` or `notebook` is not installed [[#5104](https://github.com/plotly/plotly.py/pull/5104/files)]

doc/python/bar-charts.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,108 @@ fig.update_layout(
589589
)
590590
```
591591

592+
### Using a scatterplot to wrap long bars into multiple columns
593+
594+
This bar-style pictogram allows readers to focus on the relative sizes of smaller entities by wrapping the bar for largest entries into multiple columns. You could make it even more of a pictogram by using fontawesome to replace the square markers we use below with icons like mortar boards for students.
595+
596+
```python
597+
import plotly.graph_objects as go
598+
import pandas as pd
599+
def pictogram_bar(data, title, icon_size, max_icons_per_column=10, units_per_icon=1, unit_description="", inter_group_spacing=.8,icon_vertical_spacing=0.005):
600+
601+
fig = go.Figure()
602+
x_start = 1
603+
tick_locations = []
604+
#loop through each group and create a trace with its icons
605+
for i, (category, value) in enumerate(data.items()):
606+
# compute the number of icons to use to represent this category. Depending on your use case, you might replace round with floor or ceiling.
607+
icon_count = round(value / units_per_icon)
608+
# compute the number of columns in which to arrange the icons for this category
609+
# using a double negative sign to convert a floor(division) operation into a ceiling(division) operation
610+
num_columns = -(-icon_count // max_icons_per_column)
611+
612+
#create and populate lists of icon coordinates
613+
x_coordinates, y_coordinates = [], []
614+
for col in range(num_columns):
615+
# the number of icons in this column is the lesser of the column height or
616+
# the number of icons remaining to place
617+
column_icons = min(max_icons_per_column, icon_count - col * max_icons_per_column)
618+
619+
# Create a one item list containing the x-coordinate of this column.
620+
# Then add column_icons copies of that coordinate to the list of icon x coordinates using list multiplication.
621+
# Normalizing the width of each within-category column to 1 simplifies the code.
622+
# We can adjust the visible space between columns by adjusting the total width below.
623+
x_coordinates.extend([x_start + col] * column_icons)
624+
# Create a list of sequentially increasing y-coordinates for icons.
625+
y_coordinates.extend([y + icon_vertical_spacing * y for y in range(1, column_icons + 1)])
626+
# Add scatter plot for the category
627+
fig.add_trace(go.Scatter(
628+
x=x_coordinates,
629+
y=y_coordinates,
630+
mode='markers',
631+
marker=dict(size=icon_size, symbol="square", color= i),
632+
name=category,
633+
# Suppress the x and y coordinates in the hover text, since they are irrelevant implementation details.
634+
hoverinfo="text",
635+
text=[f"{category}: {value}" for _ in range(len(x_coordinates))]
636+
))
637+
638+
# Add an annotation above the center of each category showing its value
639+
fig.add_trace(go.Scatter(
640+
x=[x_start + (num_columns - 1) / 2], # Compute the location of the center
641+
y=[max_icons_per_column* (1+icon_vertical_spacing) + 1.15],
642+
mode="text",
643+
text=[f"{value}"],
644+
textfont=dict(size=14, color="black"),
645+
showlegend=False
646+
))
647+
# Track locations where we will put the text labeling each category
648+
tick_locations.append(x_start + (num_columns - 1) / 2)
649+
#compute the left edge of the next category
650+
x_start += num_columns + inter_group_spacing
651+
652+
fig.update_layout(
653+
title=title,
654+
xaxis=dict(
655+
tickvals=tick_locations,
656+
# Label ecah category
657+
ticktext=list(data.keys()),
658+
tickangle=-45,
659+
showgrid=False,
660+
title="Categories"
661+
),
662+
yaxis=dict(
663+
title=f"Each icon represents {units_per_icon:,g} {unit_description}",
664+
# The y-axis goes above the top icon to make room for the annotations.
665+
# We set tick values so the axis labeling does not go above the top icon.
666+
# If you choose a value of max_icons_per_column that is not a multiple of 5, consider changing this.
667+
tickvals=list(range(0,max_icons_per_column+1,5)),
668+
showgrid=False,
669+
zeroline=False,
670+
),
671+
# We have already got all the labeling we need so we suppress the legend.
672+
showlegend=False,
673+
height=700,
674+
# The x-coordinates scale to fill available space, so adjusting the width of the image is a good way to adjust spacing between columns.
675+
width=(len(data) * 150 + 50)
676+
)
677+
fig.show()
678+
679+
df = pd.DataFrame({
680+
'School': ["Haverford College", "University of Mary Washington", "Brown University", "Arizona State University"],
681+
'Enrollment': [1421, 3611, 7226, 65174]
682+
})
683+
684+
pictogram_bar(
685+
data={row['School']: row['Enrollment'] for _, row in df.iterrows()},
686+
title="Undergraduate Enrollment at Participating Schools",
687+
units_per_icon=1000,
688+
unit_description = "students",
689+
icon_size=27,
690+
icon_vertical_spacing=0.05
691+
)
692+
```
693+
592694
### Customizing Individual Bar Base
593695

594696
```python

doc/what_about_dash.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ app.layout = html.Div([
2222
dcc.Graph(figure=fig)
2323
])
2424

25-
app.run_server(debug=True, use_reloader=False) # Turn off reloader if inside Jupyter
25+
app.run(debug=True, use_reloader=False) # Turn off reloader if inside Jupyter
2626
```
2727
<!-- #endregion -->

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ classifiers = [
3232
]
3333
requires-python = ">=3.8"
3434
license = {file="LICENSE.txt"}
35-
version = "6.1.2"
35+
version = "6.2.0"
3636
dependencies = [
3737
"narwhals>=1.15.1",
3838
"packaging"

tests/test_io/test_to_from_plotly_json.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def numpy_unicode_array(request):
109109
params=[
110110
datetime.datetime(2003, 7, 12, 8, 34, 22),
111111
datetime.datetime.now(),
112-
np.datetime64(datetime.datetime.utcnow()),
112+
np.datetime64(datetime.datetime.now(datetime.timezone.utc)),
113113
pd.Timestamp(datetime.datetime.now()),
114114
eastern.localize(datetime.datetime(2003, 7, 12, 8, 34, 22)),
115115
eastern.localize(datetime.datetime.now()),

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)